[Simh] DAA Emulation

Peter Schorn peter.schorn at acm.org
Sat Dec 11 18:18:54 EST 2010


Please note:

1. altair_cpu.c is for an 8080 CPU and contains the code listed below in
the most recent version of SIMH. No "code cleanup".

2. i86op_daa (from i86_ops.c) is for an 8086 CPU and I'd be interested
in any evidence that this is not correct 8086 CPU behavior resp. why
this should behave exactly the same as for an 8080.

Peter
---
peter.schorn at acm.org


On 11.12.10 23:11, Timothe Litt wrote:
> I was not defending the simh code, and agree that it does not conform. 
>  
> Interestingly, a version of altair_cpu.c c.a. 2003 seems to be more
> correct, so it appears that some "code cleanup" introduced this form of
> the bug at a later date.  The old code still wasn't correct, as it
> didn't clear AC if the add is NOT done...
>  
> Obviously this needs a regression test!
> 
> case 047: { /* DAA */
> 
> DAR = A & 0x0F;
> 
> if (DAR > 9 || AC > 0) {
> 
> DAR += 6;
> 
> A &= 0xF0;
> 
> A |= DAR & 0x0F;
> 
> if (DAR & 0x10)
> 
> AC = 0200000;
> 
> else
> 
> AC = 0;
> 
> }
> 
> DAR = (A >> 4) & 0x0F;
> 
> if (DAR > 9 || AC > 0) {
> 
> DAR += 6;
> 
> if (AC) DAR++;
> 
> A &= 0x0F;
> 
> A |= (DAR << 4);
> 
> }
> 
> if ((DAR << 4) & 0x100)
> 
> C = 0200000;
> 
> else
> 
> C = 0;
> 
> if (A & 0x80) {
> 
> S = 0200000;
> 
> } else {
> 
> S = 0;
> 
> }
> 
> if ((A & 0xff) == 0)
> 
> Z = 0200000;
> 
> else
> 
> Z = 0;
> 
> parity(A);
> 
> A = A & 0xFF;
> 
> break;
> 
> }
> 
> 
> ---------------------------------------------------------
> This communication may not represent my employer's views,
> if any, on the matters discussed.
>  
> 
>  
> 
> ------------------------------------------------------------------------
> *From:* Al Williams [mailto:al.williams at awce.com]
> *Sent:* Saturday, December 11, 2010 12:08
> *To:* Timothe Litt
> *Cc:* Richard Cini; simh at trailing-edge.com; Vince Briel
> *Subject:* Re: [Simh] DAA Emulation
> 
> I agree with your interpretation and by that interpretation the code in
> both emulators is currently busted. In the case of SIMH adding 6 does
> not always result in a half carry. 
> 
> Granted if LSD is >9 it will cause AC to set. But in the case when AC is
> already set this isn't always the case. Assuming the last add was BCD
> you could have X9+Y9 = [X+Y+1]2.
> 
> So the LSD is 2 and AC is set. Adding 6 gives you 8 and no half carry.
> So setting the flag every time you add 6 is incorrect.
> 
> 
> On Sat, Dec 11, 2010 at 10:51 AM, Timothe Litt <litt at ieee.org
> <mailto:litt at ieee.org>> wrote:
> 
>     According to the Sep 75 Intel 8080 Microcomputer Systems manual:
>      
>     P 4-3: Auxiliary Carry: If the instruction caused a carry out of bit
>     3 and into bit 4 of the resulting value, the auxiliary carry is set;
>     otherwise it is reset.  This flag is affected by single precision
>     additions, subtractions, increments, decrements, comparisons and
>     logical operations, but is principally used with additions and
>     increments preceding a DAA (Decimal Adjust Accumulator) instruction.
>      
>     P 4-8: DAA description has the text previously cited, plus
>         NOTE: All flags are affected
>         Cycles: 1
>         States: 4
>         Flags: Z,S,P,CY,AC
>      
>     I read this as AC should be set if the first add 6 (to the LSB of A)
>     happened and caused a carry and should be cleared otherwise.  (Only
>     this add can cause a carry from bit 3 to bit 4.)
>      
> 
>     ---------------------------------------------------------
>     This communication may not represent my employer's views,
>     if any, on the matters discussed.
>      
> 
>      
> 
>     ------------------------------------------------------------------------
>     *From:* simh-bounces at trailing-edge.com
>     <mailto:simh-bounces at trailing-edge.com>
>     [mailto:simh-bounces at trailing-edge.com
>     <mailto:simh-bounces at trailing-edge.com>] *On Behalf Of *Al Williams
>     *Sent:* Saturday, December 11, 2010 10:30
>     *To:* Richard Cini
>     *Cc:* simh at trailing-edge.com <mailto:simh at trailing-edge.com>; Vince
>     Briel
>     *Subject:* Re: [Simh] DAA Emulation
> 
>     Yeah I've read the docs, but even what you pasted in doesn't
>     directly answer the question: What is the state of the AC flag after
>     a DAA? So I think the code correctly implements the additions you
>     mentioned. But I think we all 3 disagree on the AC flag code. Notice
>     I didn't copy the whole function in either case, so the handling of
>     the MSD is "not shown".
> 
> 
> 
> 
>     On Sat, Dec 11, 2010 at 8:16 AM, Richard Cini <rich.cini at verizon.net
>     <mailto:rich.cini at verizon.net>> wrote:
> 
>         Al --
> 
>             Thanks a lot for the email. I’m sure you looked at this, but
>         I pulled the Intel 8080 Users Manual and under DAA, it says the
>         following (snipping a bit):
> 
>             The 8-bit number in the accumulator is adjusted to form two
>         4-bit [BCD] digits by the following process:
> 
>                 (1) If the value of the least significant 4 bits is
>         greater than 9 *or *if the AC flag is set, 6 is added to the
>         accumulator.
>                 (2) if the value of the most significant 4 bits is *now
>         *greater than 9 *or *if the CY flag is set, 6 is added to the
>         most significant 4 bits of the accumulator.
> 
>             Based on this, I would say that the second part of the test
>         in the Altair32 code is wrong. Further, it looks like the SIMH
>         code may be wrong as well because it doesn’t test the CY flag in
>         the second test.
> 
>             As far as the register display, I’ll make that change —
>         oddly no one has ever reported it.
> 
>             Thanks again for locating this bug.
> 
>         Rich
> 
>         --
>         Rich Cini
>         Collector of Classic Computers
>         Build Master and lead engineer, Altair32 Emulator
>         http://www.altair32.com
>         http://www.classiccmp.org/cini
> 
> 
> 
> 
>         On 12/11/10 1:32 AM, "Al Williams" <al.williams at awce.com
>         <http://al.williams@awce.com>> wrote:
> 
>             Hi Rich and Bob,
> 
>             I've been doing some work on Vince Briel's excellent AVR
>             emulation of the 8080 and while rewriting DAA I came across
>             what I think to be a harmless bug but thought you might want
>             to comment on it.
> 
>             >From what I can glean DAA effects all flags including half
>             carry. And I _think_ that half carry occurs from the +6 (if
>             it happens at all). So if you don't adjust the LSD you get
>             AC=0. If you add 6 then if adding the 6 gives you a carry
>             out of Bit 3 you get AC set. Note that the carry might
>             ripple so that's NOT to say Bit 4 is necessarily 1.
> 
>             Here's part of Altair32's code:
> 
>             static void daa ( OP_ARG_U ) 
>             {
>             // Decimal Adjust Accumulator
>             // DAA:: A=BCD format
>             // Flags: SZAPC
>             // *****
> 
>             register /* FJS */ word tmp = ACCUM;
> 
>             if ( (( tmp & 0x0f ) > 0x09 ) || ( FLAGS & AC_FLAG ))
>             tmp += 0x06;
> 
>             if (tmp > 0x0f)
>             FLAGS |= AC_FLAG; // if adjusted LSB > 0xf, set AC
>             else
>             FLAGS &= ~AC_FLAG; // else clear SC
> 
> 
>             So since tmp is not masked off, any value >0xF gets AC set
>             even if no carry or add occurred! In other words, pretend
>             the value of ACCUM is 90 (and thus temp is 90) with AC=0.
>             The first if does not fire. The second if does and AC gets
>             set. That's got to be wrong. Granted, who checks AC after
>             DAA? But still.... 
> 
> 
>             So why copy Bob? Well... I think SIMH has a similar but
>             different problem. Here's a snip from the DAA code:
> 
>             /*opcode=0x27*/
>             static void i86op_daa(PC_ENV *m)
>             {
>                uint16 dbyte;
>                dbyte = m->R_AL;
>                if (ACCESS_FLAG(m,F_AF)|| (dbyte&0xf) > 9)
>                  {
>                 dbyte += 6;
>                 if (dbyte&0x100)
>                   SET_FLAG(m, F_CF);
>                 SET_FLAG(m, F_AF);
>                  }
>                else
> 
> 
>             Here we add 6 to dbyte and then AC is always set. If no +6
>             then AC is cleared. This COULD be correct behavior, but I
>             can't find any reference material that says it is. In any
>             event, SIMH and Altair32 are doing something different here,
>             so they both can't be right. Meanwhile I have my own version
>             of DAA in AVR assembler that I will spare you unless you
>             ask. The only real silicon I have even close to operational
>             at the moment is a Z80 and not only is it not operational,
>             the DAA is one place where it is a lot different so I don't
>             trust the result there.
> 
>             Oh. One other note about Altair32. In the debugger, the A
>             and FLAGS display is swapped in the debug console window.
>             The Register display up top left is ok though. I bet you've
>             heard that one before.
> 
>             If either of you can show documentation on the AC flag after
>             DAA or point to a real piece of silicon's behavior I'd like
>             to know so I can fix the DAA code in the Briel emulator to
>             match. Otherwise, I thought you'd like to know about this
>             bug even though it is pretty innocuous as far as I can tell.
> 
> 
>             Al Williams
>             http://www.ddj.com/embedded (among others)
> 
> 
> 
> 
> 
> 
> 
> 
> _______________________________________________
> Simh mailing list
> Simh at trailing-edge.com
> http://mailman.trailing-edge.com/mailman/listinfo/simh



More information about the Simh mailing list