Author Topic: BIT n,(HL) flags  (Read 4409 times)

0 Members and 1 Guest are viewing this topic.

Offline harold

  • LV5 Advanced (Next: 300)
  • *****
  • Posts: 226
  • Rating: +41/-3
    • View Profile
BIT n,(HL) flags
« on: November 24, 2011, 11:33:41 am »
BIT n,(HL) sets some nice flags, including of course flags 3 and 5.
It takes the values for 3 and 5 from an internal register, that among other things holds:
- the original H after ADD HL,xx
- the upper byte of PC after a JR
- the upper byte of IX+displacement after at least some instructions that use IX+displacement

My question is, does anyone have a more complete list?
Blog about bitmath: bitmath.blogspot.nl
Check the haroldbot thread for the supported commands and syntax.
You can use haroldbot from this website.

Offline calc84maniac

  • eZ80 Guru
  • Coder Of Tomorrow
  • LV11 Super Veteran (Next: 3000)
  • ***********
  • Posts: 2912
  • Rating: +471/-17
    • View Profile
    • TI-Boy CE
Re: BIT n,(HL) flags
« Reply #1 on: November 24, 2011, 12:26:21 pm »
The BIT instruction internally does an AND with a generated bitmask, and all affected flags are set by that result. So the Sign flag, for example, can be set only in the case of BIT 7. Keep in mind that the newer TI-Z80 models will always reset bits 3 and 5 of the F register, though.
"Most people ask, 'What does a thing do?' Hackers ask, 'What can I make it do?'" - Pablos Holman

Offline harold

  • LV5 Advanced (Next: 300)
  • *****
  • Posts: 226
  • Rating: +41/-3
    • View Profile
Re: BIT n,(HL) flags
« Reply #2 on: November 24, 2011, 12:44:06 pm »
That's for BIT n,reg8 at least, but my sources say BIT n,(HL/IX/IY) behave differently; BIT n,(IX+d) takes 5 and 3 from (IX+d)>>8 and BIT n,(HL) from .. weird places. Are those sources incorrect?
Blog about bitmath: bitmath.blogspot.nl
Check the haroldbot thread for the supported commands and syntax.
You can use haroldbot from this website.

Offline ralphdspam

  • LV8 Addict (Next: 1000)
  • ********
  • Posts: 841
  • Rating: +38/-1
  • My name is actually Matt.
    • View Profile
Re: BIT n,(HL) flags
« Reply #3 on: November 27, 2011, 11:44:54 pm »
Keep in mind that the newer TI-Z80 models will always reset bits 3 and 5 of the F register, though.
Which Z80s have that change, and are there any other changes made to undocumented opcodes?

That's for BIT n,reg8 at least, but my sources say BIT n,(HL/IX/IY) behave differently; BIT n,(IX+d) takes 5 and 3 from (IX+d)>>8 and BIT n,(HL) from .. weird places. Are those sources incorrect?
There are many different models of Z80, so I wouldn't be surprised if there are differences in undocumented flags.  Also, I would recommend staying away from IX and IY instructions if you want the programs to work on the Nspire with 84+ keypad.
ld a, 0
ld a, a

Offline thepenguin77

  • z80 Assembly Master
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1594
  • Rating: +823/-5
  • The game in my avatar is bit.ly/p0zPWu
    • View Profile
Re: BIT n,(HL) flags
« Reply #4 on: November 28, 2011, 11:18:29 am »
That's for BIT n,reg8 at least, but my sources say BIT n,(HL/IX/IY) behave differently; BIT n,(IX+d) takes 5 and 3 from (IX+d)>>8 and BIT n,(HL) from .. weird places. Are those sources incorrect?
There are many different models of Z80, so I wouldn't be surprised if there are differences in undocumented flags.  Also, I would recommend staying away from IX and IY instructions if you want the programs to work on the Nspire with 84+ keypad.

Actually, IX and IY work fine, it's only their undocumented half registers that don't. For instance, LD IX, $1337 works while, LD IXH, $13 \ LD IXL, $37 does not.

To see what instructions won't works, look here. Any instruction in red won't work, (remember though that some gray instructions are duplicates of real instructions)
« Last Edit: November 28, 2011, 11:19:13 am by thepenguin77 »
zStart v1.3.013 9-20-2013 
All of my utilities
TI-Connect Help
You can build a statue out of either 1'x1' blocks or 12'x12' blocks. The 1'x1' blocks will take a lot longer, but the final product is worth it.
       -Runer112

Offline harold

  • LV5 Advanced (Next: 300)
  • *****
  • Posts: 226
  • Rating: +41/-3
    • View Profile
Re: BIT n,(HL) flags
« Reply #5 on: November 28, 2011, 11:42:07 am »
Ok, well I'm interested in the precise behaviour of the z80 that's in the TI 83+ (black). For emulation, so it had better be exactly right, undocumented behaviour and all.
Later I might potentially do the SE/84 versions as well but this one isn't even near usable yet.
Blog about bitmath: bitmath.blogspot.nl
Check the haroldbot thread for the supported commands and syntax.
You can use haroldbot from this website.

Offline FloppusMaximus

  • LV5 Advanced (Next: 300)
  • *****
  • Posts: 290
  • Rating: +57/-5
    • View Profile
Re: BIT n,(HL) flags
« Reply #6 on: December 06, 2011, 07:49:28 pm »
The undocumented register you're referring to is called W.  It's half of a register pair called WZ; there's no way to access either W or Z directly, so the precise details aren't that important.  WZ has a shadow register WZ', which is enabled/disabled by the EXX instruction (I really have no idea why.)

You may have read Sean Young's "The Undocumented Z80 Documented" (if you haven't, you should).  As far as I know, nobody has written anything more about it than that, so I've had to reverse-engineer everything else myself.

(And of course, this is totally academic; it only matters for people like us who care about perfectly emulating every single bit.)

WZ is used for:
- addresses that are to be jumped to (to avoid having to read and write PC at the same time)
- temporary 16-bit additions, like the IX/IY instructions you mentioned (because there's nowhere else where the value can be stored)
- all input and output addresses (I don't really know why, but I guess it simplifies the internal logic somewhat)

And a few other things.  WZ is often incremented or decremented after it's used, which is the only reason the Z register matters at all.

The only instructions I never figured out are CPI(R) and CPD(R), which definitely use WZ in some way, but I never figured out the details.

The only real documentation I have is the TilEm 2 source: z80cmds.h, z80main.h, z80cb.h, z80ed.h, z80ddfd.h.

Offline harold

  • LV5 Advanced (Next: 300)
  • *****
  • Posts: 226
  • Rating: +41/-3
    • View Profile
Re: BIT n,(HL) flags
« Reply #7 on: December 07, 2011, 05:53:48 am »
Thanks, that will help.
I have read that, but there's not that much information about WZ in it.

edit: I found a document that contains some information about WZ, though they call it MEMPTR. It includes CPI/D(R) bahaviour.

Spoiler For Spoiler:
MEMPTR, esoteric register of the ZiLOG Z80 CPU.
by Boo-boo (first and draft English translation by Vladimir Kladov)

  As it is known, after the instruction BIT n,(HL) execution, bits 3 and 5 of the flag register become containing values that is not documented in the official documentation at all. Actually these bits are copied from the bits 11 and 13 of the internal register pair of Z80 CPU, which is used for 16-bit operations, and in most cases to handle addresses. This is usual practice for processors having 8-bits data bus working with 16-bits data.
  It is not known why and how these bits of the internal buffer register are copied to the flags register though. At least Sean Young in the "Undocumented Z80 Documented" refers to that phenomenon (http://www.myquest.nl/z80undocumented/) and a bit more info can be found in the Z80 description of another "nocash" project (http://www.work.de/nocash/zxdocs.htm) where such register pair is called as MEMPTR. Unfortunately until now attemts to crack the algorithm setting the value of the MEMPTR by different processor instructions on base of knowning only two bits of those 16-bits register were not successful.
  But miraculously in result of many experiments (based on the hyposesis that index addressing instructions initialize the MEMPTR always the same way) and also after the deep meditations under the results of these samples we have found that CPI instruction increments the MEMPTR by 1 whereas CPD instruction decrements it. Hence, decrementing the MEMPTR in the loop and monitoring borrow from the high bits having two known bits in the flag register, it is possible to determine unambigously 14 low bits of the MEMPTR and having these in our hands to say for sure on which rule MEMPTR is set after each instruction.
  A list of instructions changing the MEMPTR is follow, together with the formula for new MEMPTR value. Here "rp" means register pair (16 bits register BC, DE, HL or SP - ?), and "INDEX" means register pair IX or IY. Instructions not listed below do not affect MEMPTR as it is found. All the CPU chips tested give the same results except KP1858BM1 and T34BM1 slices noted as "BM1" in the text.
====================================================================================

LD A,(addr)
   MEMPTR = addr + 1

LD (addr),A
   MEMPTR_low = (addr + 1) & #FF,  MEMPTR_hi = A
   Note for *BM1: MEMPTR_low = (addr + 1) & #FF,  MEMPTR_hi = 0

LD A,(rp)  where rp -- BC or DE
   MEMPTR = rp + 1

LD (rp),A  where rp -- BC or DE
   MEMPTR_low = (rp + 1) & #FF,  MEMPTR_hi = A
   Note for *BM1: MEMPTR_low = (rp + 1) & #FF,  MEMPTR_hi = 0

LD (addr), rp
LD rp,(addr)
   MEMPTR = addr + 1

EX (SP),rp
   MEMPTR = rp value after the operation

ADD/ADC/SBC rp1,rp2
   MEMPTR = rp1_before_operation + 1

RLD/RRD
   MEMPTR = HL + 1

JR/DJNZ/RET/RETI/RST (jumping to addr)
   MEMPTR = addr

JP(except JP rp)/CALL addr (even in case of conditional call/jp, independantly on condition satisfied or not)
   MEMPTR = addr

IN A,(port)
   MEMPTR = (A_before_operation << 8) + port + 1

IN A,(C)
   MEMPTR = BC + 1

OUT (port),A
   MEMPTR_low = (port + 1) & #FF,  MEMPTR_hi = A
   Note for *BM1: MEMPTR_low = (port + 1) & #FF,  MEMPTR_hi = 0

OUT (C),A
   MEMPTR = BC + 1

LDIR/LDDR
   when BC == 1: MEMPTR is not changed
   when BC <> 1: MEMPTR = PC + 1, where PC = instruction address

CPI
   MEMPTR = MEMPTR + 1

CPD
   MEMPTR = MEMPTR - 1

CPIR
   when BC=1 or A=(HL): exactly as CPI
   In other cases MEMPTR = PC + 1 on each step, where PC = instruction address.
   Note* since at the last execution BC=1 or A=(HL), resulting MEMPTR = PC + 1 + 1
     (if there were not interrupts during the execution)

CPDR
   when BC=1 or A=(HL): exactly as CPD
   In other cases MEMPTR = PC + 1 on each step, where PC = instruction address.
   Note* since at the last execution BC=1 or A=(HL), resulting MEMPTR = PC + 1 - 1
     (if there were not interrupts during the execution)

INI
   MEMPTR = BC_before_decrementing_B + 1

IND
   MEMPTR = BC_before_decrementing_B - 1

INIR
   exactly as INI on each execution.
   I.e. resulting MEMPTR = ((1 << 8) + C) + 1

INDR
   exactly as IND on each execution.
   I.e. resulting MEMPTR = ((1 << 8) + C) - 1

OUTI
   MEMPTR = BC_after_decrementing_B + 1

OUTD
   MEMPTR = BC_after_decrementing_B - 1

OTIR
   exactly as OUTI on each execution. I.e. resulting MEMPTR = C + 1

OTDR
   exactly as OUTD on each execution. I.e. resulting MEMPTR = C - 1

Any instruction with (INDEX+d):
   MEMPTR = INDEX+d

Interrupt call to addr:
   As usual CALL. I.e. MEMPTR = addr

====================================================================================
  What is the profit of which secret knowledge? First of all, it is possible now to program Z80 emulators supporting _all_ the undocumented pecularities of the CPU. In the second place the fact that on some Z80 clones MEMPTR register behaves a bit another adds a method of model checking. Seems very enough!
(c)2006, zx.pk.ru
Theoretical part: boo_boo, Vladimir Kladov
Testing real Z80 chips: Wlodek, CHRV, icebear, molodcov_alex, goodboy

« Last Edit: December 07, 2011, 11:38:17 am by harold »
Blog about bitmath: bitmath.blogspot.nl
Check the haroldbot thread for the supported commands and syntax.
You can use haroldbot from this website.

Offline FloppusMaximus

  • LV5 Advanced (Next: 300)
  • *****
  • Posts: 290
  • Rating: +57/-5
    • View Profile
Re: BIT n,(HL) flags
« Reply #8 on: December 08, 2011, 03:12:47 am »
Ah, of course.  They don't actually use the register, they just increment it or decrement it for the heck of it.  (Now I wonder why LDI and LDD don't do the same.)

I was hoping the answer would shed some light on the extremely peculiar behavior of the flags following CPI/CPD.  Oh well.  Thanks for posting this.