From: pfreire@lamparina.inesc.pt ( Pedro Jose' Freire ) Subject: Re: Z80 ADC/SBC emulation Reply-To: pfreire@inesc.pt Date: Thu, 15 Dec 1994 18:28:40 GMT In article <3chnj8$b4h@mimsy.cs.umd.edu> fms@highpower.cs.umd.edu (Marat Fayzullin) writes: From: fms@highpower.cs.umd.edu (Marat Fayzullin) Newsgroups: comp.emulators.misc,comp.sys.sinclair Date: 12 Dec 1994 14:43:52 GMT Organization: U of Maryland, Dept. of Computer Science, Coll. Pk., MD 20742 > A quick question: > > How do you emulate C, H and V signs in ADC/SBC instructions? > My solution was > > A^B^RESULT for RESULT=A +/- (B + CARRY) > > But it seems to be incorrect. > > Marat [ This is *one* answer. I have left a Spectrum emulator project in half because the ones "out there" were starting to give me all I wanted, so I never ended up testing it. ] The 8086 instruction set has two similar instrucions (ADC and SBB, respectivelly). Execute them. After that use a tiny little instruction used to allow bacward compatibility to the 8080 (where the Z80 was based). These are LAHF and SAHF (or something like that, I don't have my manual handy). They store the contents of the lower 8 bits of the FLAGS register into AH. From those you can use Z, C, S and V since they have the same meaning and are stored in the same bit as the original 8080. Now, as C (carry) is another name for the 9th bit of the result (17th for word operands), half carry (H) is another name for the 4th bit (and oddily the 12th bit of the result with word operands). Just pick up the right byte, AND a mask with it and the AH (FLAGS) register, and OR them together. Notice that the H flag shows up right in the 4th bit of F (Z80 flags). Handy. Now that you're at it, use a wider mask and insert the two adjacent bits of half carry (the 5th and 3rd bits) into AH (future F). Those are "undocumented" flags (I don't have a Z80 manual handy either, maybe they were other bits, but they *were* undocumented), and as far as I know, they simply follow the corresponding bits of the highest byte of the last result (i.e.: the byte that holds H). Somebody else might expand on this. Pedro Freire. -- Pedro Freire email: pfreire@inesc.pt ************************************************************************ From: fms@highpower.cs.umd.edu (Marat Fayzullin) Subject: Re: Z80 ADC/SBC emulation Date: 16 Dec 1994 20:44:29 GMT Marat Fayzullin (fms@highpower.cs.umd.edu) wrote: : A quick question: : How do you emulate C, H and V signs in ADC/SBC instructions? : My solution was : A^B^RESULT for RESULT=A +/- (B + CARRY) : But it seems to be incorrect. ******************** OK, here is update on flags emulation in 8-bit CPUs: Half-carry flag: FLAG = (A^B^RESULT)&0x10 for any operation Overflow flag: FLAG = ~(A^B)&(B^RESULT)&0x80 for addition [ADD/ADC] FLAG = (A^B)&(A^RESULT)&0x80 for subtraction [SUB/SBC] For INC/DEC, you can use following simplifications: INC: H_FLAG = (RESULT&0x0F)==0x00 V_FLAG = RESULT==0x80 DEC: H_FLAG = (RESULT&0x0F)==0x0F V_FLAG = RESULT==0x7F I would like to thank Jouko Valta for provided information. This post is made on behalf of those who are working on the same problem :) BTW, first PUBLIC RELEASE of Unix MSX emulator is at http://www.cs.umd.edu/users/fms/MSX/ Marat ******************************************************************** From: gerton@ciwi1.math.rug.nl () Subject: Re: Z80 ADC/SBC emulation Date: 16 Dec 1994 09:57:02 GMT In article : > From: fms@highpower.cs.umd.edu (Marat Fayzullin) > > How do you emulate C, H and V signs in ADC/SBC instructions? > > My solution was > > > > A^B^RESULT for RESULT=A +/- (B + CARRY) > > > > But it seems to be incorrect. [ [stuff deleted] > Now, as C (carry) is another name for the 9th bit of the result (17th for > word operands), half carry (H) is another name for the 4th bit (and oddily > the 12th bit of the result with word operands). Just pick up the right > byte, AND a mask with it and the AH (FLAGS) register, and OR them together. > Notice that the H flag shows up right in the 4th bit of F (Z80 flags). Handy. C is the 9th bit of the result (i.e. bit 8, if bits are counted from 0) if the arguments were genuine 8 bit bytes. Trivial remark for C, but not for H: H is only the fifth (!) bit (i.e. bit 4) of the result if bit 4 of the arguments were 0; otherwise it's different. For addition, bit 4 = arg1(bit 4)+arg2(bit 4)+carry(from bits 3) or Halfcarry = result(bit 4)-arg1(bit 4)-arg2(bit 4) which means that your solution seems to be correct. What is your reason for thinking it is incorrect? And indeed, if you're emulating the Z80 on a 8088+, you can simply use SAHF and LAHF for most of the bits (except undocumented ones, overflow and the add/substract flag used by (Z80) DAA) > Now that you're at it, use a wider mask and insert the two adjacent bits > of half carry (the 5th and 3rd bits) into AH (future F). Those are > "undocumented" flags (I don't have a Z80 manual handy either, maybe they > were other bits, but they *were* undocumented), and as far as I know, they > simply follow the corresponding bits of the highest byte of the last result > (i.e.: the byte that holds H). Correct as far as I know (except that bit 4, H, does not follow the high byte of the last result, see above, but 3 and 5 do.) The only exception I know is CP; after a CP the argument of CP is copied into the undocumented bits of F, not the result (of the subtraction). So CP #FF makes both undocumented bits 1, regardless of A. You might want to take a look at the documentation file of Z80-302.zip, where I tried to explain these things. Gerton Lunter.