Skeetendo

’Cause all games were better on the GBC

You are not logged in.

  • Index
  • → Help/Question
  • → GB-Z80: Clarifications about flags affected by "rotate" instructions

#1 2012-07-14 14:27:13

Sawakita
Administrator
Registered: 2010-10-16
Post 284/364

GB-Z80: Clarifications about flags affected by "rotate" instructions

I have good reasons for doubting about the exactness regarding rotate instructions the way they're explained in the Game Boy Official Programming Manual. I've been reading through it these days and keep finding typos and contradictions.
Because there are other documents, around the web, about the instruction-set specifics, I tried comparing them and couldn't come to a solution of this inconsistency.

But let's explain the facts. The instruction RLCA (literally "rotate left carry a") is described as follows:

OFFICIAL Manual v1.0 wrote:

RLCA:

Flags:
| CY | H | N | Z |
| A7 | 0 | 0 | 0 |    (A7 means the value contained in bit 7 of register A)

Rotates the contents of register A to the left.
That is, the contents of bit 0 are copied to bit 1 and the previous contents of bit 1 (the contents before the copy operation) are copied to bit 2. The same operation is repeated in sequence for the rest of the register. The contents of bit 7 are placed in both CY and bit 0 of register A.

Example: When A = 0x85 and CY = 0,
         RLCA ; A← 0x0A, CY ← 1, Z ← 0, H ← 0, N ← 0

There are two things I find wrong, or at least unclear, here.
1) When you rotate-left 0x85 and put the value of bit 7 in bit 0 you get 0xB, not 0xA. So, here, either the description is wrong or the example is. By looking at the next instruction description in the manual, that is RLA, I tend to conjecture that they mixed RLCA and RLA unawares:

OFFICIAL Manual v1.0 wrote:

RLA:

Flags:
| CY | H | N | Z |
| A7 | 0 | 0 | 0 |

Rotates the contents of register A to the left.

Example: When A = 0x95 and CY = 1,
         RLCA ; A← 0x2B, CY ← 1, Z ← 0, H ← 0, N ← 0

As you can see RLA's example fits RLCA's description. Now it's a matter of figuring out whether RLCA's description belongs to RLA or RLA's example belongs to RLCA.

2) According to the Official Manual, the ZERO flag is always reset, no matter what A's value is. But RLC (rotate generic register) is said, in that same manual, to affect the ZERO flag according to the register's final value (set if register is zero, reset otherwise), so I'm rather surprised that the same operation done on the accumulator instead of another 8-bit register has a different behaviour on the ZERO flag.
Concerning the RLCA instruction itself: other not-so-official documents (Marc Rawer's manual and devrs') claim that ZERO flag is indeed SET when A == 0.
The Cribsheet agrees with the Official Manual (the ZERO flag is reset, unconditionally)

I doubt about the validity of a "GB-z80 vs Zilog-z80" comparison can be, but just for the record here is the Zilog z80 manual description of RLCA:

Zilog Z80 wrote:

The contents of the Accumulator (register A) are rotated left 1-bit position.
The sign bit (bit 7) is copied to the Carry flag and also to bit 0. Bit 0 is the
least-significant bit.

Condition Bits Affected:
S is not affected
Z is not affected
H is reset
P/V is not affected
N is reset
C is data from bit 7 of Accumulator

Example:
If the contents of the Accumulator are

7 6 5 4 3 2 1 0
1 0 0 0 1 0 0 0

at execution of RLCA the contents of the Accumulator and Carry flag are

C 7 6 5 4 3 2 1 0
1 0 0 0 1 0 0 0 1

TL;DR: What is the exact behaviour of RLCA (and, consequently, of RLA) and how are flags affected?

I'm curious to know your stance on this topic.

Last edited by Sawakita (2012-07-14 14:36:58)

Offline

#2 2012-07-14 14:41:35

486/701

Re: GB-Z80: Clarifications about flags affected by "rotate" instructions

I’ve encountered documentation inconsistencies in this area as well. This is the kind of data that I would pull from an existing emulator’s source code, like Gambatte’s.

#3 2012-07-14 14:55:43

Sawakita
Administrator
Registered: 2010-10-16
Post 285/364

Re: GB-Z80: Clarifications about flags affected by "rotate" instructions

Indeed, I used it as a reference sometimes. GìThe following is Gambatte's implementation:

//rlca (4 cycles):
//Rotate 8-bit register A left, store old bit7 in CF. Reset SF, HCF, ZF:
CF = A << 1;
A = (CF | CF >> 8) & 0xFF;
HF2 = 0;
ZF = 1;

I was initially fooled by the contradiction between Reset ... ZF and "ZF = 1;, but a quick look to the macro FROM_F() (they implemented flags as distinct values so when there's a direct write/read to/from register F they need to update the whole stuff) reveals that ZF correspond to a complemented actual ZERO flag (maybe because it didn't make sense for Gambatte's developers to have a 1 in ZF when the instruction returned ZERO :P):

ZF = ~from_f_var & 0x80;

So, as far as we can see here, Gambatte follows RLCA's description (and RLA's example, NOT RLCA's example). I guess I'll go with that solution, although I wonder what did Gambatte's developers used as a reference.

Offline

#4 2012-07-17 09:19:49

Danny-E 33
Administrator
Registered: 2012-06-09
Post 63/1,031

Re: GB-Z80: Clarifications about flags affected by "rotate" instructions

I came up with a few simple experiments to test your two questions:

Sawakita wrote:

1) When you rotate-left 0x85 and put the value of bit 7 in bit 0 you get 0xB, not 0xA. So, here, either the description is wrong or the example is.

For this, I took the simple routine at $1633 that determines the bank for each sprite before it is decompressed. I first moved Bulbasaur's frontsprite to bank 0B. And I changed the routine at $1633 to this:

ld a, $85
RLCA
jp [$24FD]

So when RLCA is performed on $85, the result should be $0B according to the description and it should be $0A according to the example. But this code successfully displayed the Bublasaur frontsprite in BGB so the description should be correct and the example is false, since RLC $85 successfully loaded bank 0B.

Sawakita wrote:

2) According to the Official Manual, the ZERO flag is always reset, no matter what A's value is. But RLC (rotate generic register) is said, in that same manual, to affect the ZERO flag according to the register's final value (set if register is zero, reset otherwise), so I'm rather surprised that the same operation done on the accumulator instead of another 8-bit register has a different behaviour on the ZERO flag.

Here, I kept Bulbasaur's frontsprite in bank 0B and also modified the routine for determining the bank at $1633. This time I changed to code to:

ld a, $00
RLCA
ld a, $0B
jr z, 02
ld a, $0A
jp $24FD

So this time, when RLCA is performed on $00 and results in $00, the z flag should either be: 1. Set becuase the result was zero 2. Unset because it is unset unconditionally. Then it loads $0B into a and jumps ahead only if the z flag is set. Otherwise, it loads $0A into a before it continues. The game did not load the Bulbasaur frontsprite from bank 0B. So the z flag must have been unset. So it does not matter if RLCA results in 00; the z flag is unset unconditionally.

However, this issue seems kinda silly to worry about, since $00 is the only value that will result in $00 using RLC or RLCA. Also, $80 and $00 are the only values that will result in $00 when using RL or RLA as long as the c flag is unset.
Although, I do understand your drive to be absolutely certain.

But doesn't this only prove how BGB is programmed? If I wanted to find out for sure, I would have to do these same tests on a real Gameboy, right?

(I did these tests partly to add to the conversation, but mostly because I saw a chance to practice what I've learned. I feel like every little thing I do is making me more and more comftorble with asm, so I'm glad I took the time to do this)


Red Hack: Pokémon Prototype

Total number of registered users: 8000+
Total number of active users: ~12

Offline

#5 2012-07-17 16:21:35

Tauwasser
Member
Registered: 2010-10-16
Post 294/448

Re: GB-Z80: Clarifications about flags affected by "rotate" instructions

Sawakita wrote:

2) According to the Official Manual, the ZERO flag is always reset, no matter what A's value is. But RLC (rotate generic register) is said, in that same manual, to affect the ZERO flag according to the register's final value (set if register is zero, reset otherwise), so I'm rather surprised that the same operation done on the accumulator instead of another 8-bit register has a different behaviour on the ZERO flag.

It's not the same opcode, just the same operation. What are you surprised about? RLCA is the original opcode -- which would only work on the accumulator -- while RLC r is a CB-prefixed opcode, which was added later in the instruction set life. Notice other prefixes are not supported by the z80gb CPU, but are present in real z80 CPUs.

Also, the Pan Docs and devr's actually support the official manual. Marc Rawer got it wrong, most likely because the original opcode summary he worked with did not include RLCA and he thus assumed that RLCA == RLC A.

The official example is indeed wrong. However, that's probably not surprising here. The quality of that leaked document is generally poor and also questionable.

Danny-E 33 wrote:

But doesn't this only prove how BGB is programmed? If I wanted to find out for sure, I would have to do these same tests on a real Gameboy, right?

Indeed, one would have to execute code on the original CPU (and possibly later revisions, although that's silly) to be 100% certain. However, using emulator source code from an emulator that can emulate all games to near 100% is proving the point. Any emulator that got any of the opcodes wrong would not have that coverage. Much less if one of the most-used opcodes -- such as the ALU operations and the rotate and shift group -- were wrong.

cYa,

Tauwasser

Last edited by Tauwasser (2012-07-18 19:13:09)

Offline

#6 2012-07-17 16:45:32

Danny-E 33
Administrator
Registered: 2012-06-09
Post 64/1,031

Re: GB-Z80: Clarifications about flags affected by "rotate" instructions

Tauwasser wrote:

Indeed, one would have to execute code on the original CPU (and possibly later revisions, although that's silly) to be 100% certain. However, using emulator source code from an emulator that can emulate all games to near 100% is proving the point. Any emulator that got any of the opcodes wrong would not have that coverage. Muss less if one of the most-used opcodes -- such as the ALU operations and the rotate and shift group -- were wrong.

So my tests weren't entirely meaningless?? Well now I feel kinda useful :) Even though I'm sure any of you could have done that just as easily :P


Red Hack: Pokémon Prototype

Total number of registered users: 8000+
Total number of active users: ~12

Offline

#7 2012-07-20 15:20:43

Sawakita
Administrator
Registered: 2010-10-16
Post 289/364

Re: GB-Z80: Clarifications about flags affected by "rotate" instructions

Tauwasser wrote:

have to execute code on the original CPU (and possibly later revisions, although that's silly) to be 100% certain. However, using emulator source code from an emulator that can emulate all games to near 100% is proving the point. Any emulator that got any of the opcodes wrong would not have that coverage. Much less if one of the most-used opcodes -- such as the ALU operations and the rotate and shift group -- were wrong.

Indeed, that's a valid point.
I've change my mindset, since believing more in something (no matter if unofficial) that works makes much more sense than following some (even if official) documentation that often hasn't means to prove its correctness.

Offline

#8 2012-07-21 04:21:18

492/701

Re: GB-Z80: Clarifications about flags affected by "rotate" instructions

On a related note, Gambatte has over 1000 regression tests, based on real hardware behavior, that can be run automatically: the testrunner runs the programs, dumps memory, and compares that to a predefined output. This is a huge point in favor of Gambatte, because any new emulation bugs introduced (that are covered by the tests) will be noticed the next time the tests are run. I’ll trust regression tests over official docs any day.

#9 2012-08-04 14:46:52

Danny-E 33
Administrator
Registered: 2012-06-09
Post 71/1,031

Re: GB-Z80: Clarifications about flags affected by "rotate" instructions

Danny-E 33 wrote:

However, this issue seems kinda silly to worry about, since $00 is the only value that will result in $00 using RLC or RLCA. Also, $80 and $00 are the only values that will result in $00 when using RL or RLA as long as the c flag is unset.

And just to test my asm knowledge, I was correct with what I said here, right?


Red Hack: Pokémon Prototype

Total number of registered users: 8000+
Total number of active users: ~12

Offline

  • Index
  • → Help/Question
  • → GB-Z80: Clarifications about flags affected by "rotate" instructions

Board footer

Powered by FluxBB