Omnimaga

Calculator Community => TI Calculators => ASM => Topic started by: harold on November 24, 2011, 11:33:41 am

Title: BIT n,(HL) flags
Post by: harold 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?
Title: Re: BIT n,(HL) flags
Post by: calc84maniac 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.
Title: Re: BIT n,(HL) flags
Post by: harold 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?
Title: Re: BIT n,(HL) flags
Post by: ralphdspam 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.
Title: Re: BIT n,(HL) flags
Post by: thepenguin77 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 (http://clrhome.tk/resources/table/). Any instruction in red won't work, (remember though that some gray instructions are duplicates of real instructions)
Title: Re: BIT n,(HL) flags
Post by: harold 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.
Title: Re: BIT n,(HL) flags
Post by: FloppusMaximus 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 (http://tilem.svn.sourceforge.net/viewvc/tilem/trunk/emu/z80cmds.h?revision=HEAD&view=markup), z80main.h (http://tilem.svn.sourceforge.net/viewvc/tilem/trunk/emu/z80main.h?revision=HEAD&view=markup), z80cb.h (http://tilem.svn.sourceforge.net/viewvc/tilem/trunk/emu/z80cb.h?revision=HEAD&view=markup), z80ed.h (http://tilem.svn.sourceforge.net/viewvc/tilem/trunk/emu/z80ed.h?revision=HEAD&view=markup), z80ddfd.h (http://tilem.svn.sourceforge.net/viewvc/tilem/trunk/emu/z80ddfd.h?revision=HEAD&view=markup).
Title: Re: BIT n,(HL) flags
Post by: harold 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

Title: Re: BIT n,(HL) flags
Post by: FloppusMaximus 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.