Path: vanilla!asbach!hugis!noris.net!xlink.net!howland.reston.ans.net!news.sprintlink.net!newsserver.pixel.kodak.com!bloom-beacon.mit.edu!eru.mt.luth.se!news.kth.se!xbyse.nada.kth.se!d88-bli From: d88-bli@xbyse.nada.kth.se (Bo Lindbergh) Newsgroups: comp.sys.sinclair Subject: Re: DAA (Decimal Adjust Accumalator) Date: 26 Sep 1995 22:40:10 GMT Organization: Royal Institute of Technology, Stockholm, Sweden Lines: 53 Message-ID: <449vga$lk6@news.kth.se> References: <446amq$din@griffin.ccc.nottingham.ac.uk> NNTP-Posting-Host: xbyse.nada.kth.se Mime-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit In article <446amq$din@griffin.ccc.nottingham.ac.uk> pcxigw@vaxb.nott.ac.uk writes: > Hi, > Does anyone have a description of how DAA works, particularly > how does one calculate the value to add to the accumalator? Here's some actual (well, almost...) code from my emulator that reproduces the behaviour of a physical Z80 exactly. You probably need to grok full adders to understand it. /* assume these declarations at appropriate locations */ extern unsigned char parity[256]; int res,cy; unsigned char op8,reg_a,reg_f,flag_z,flag_h,flag_pv,flag_n,flag_c; /* first adjust the C and H flags by checking if the high or low nibbles of the accumulator exceed 9 */ cy = (reg_a+0x66) ^ reg_a; /* add bias and extract carry bits */ flag_c |= (cy>>8) & 1; /* carry into bit 8 => set C flag */ flag_h |= (cy>>4) & 1; /* carry into bit 4 => set H flag */ /* then compute the correction value: if the C flag is set, set the high nibble to 6, else to 0. if the H flag is set, set the low nibble to 6, else to 0. */ op8 = (0x88 - ((flag_c<<4) | flag_h)) & 0x66; /* but if the last operation was a subtraction, negate it */ if (flag_n) op8 = -op8; /* apply the correction */ res = reg_a+op8; /* set the H flag according to the correction addition */ cy = reg_a ^ res; flag_h = (cy>>4) & 1; /* save the result */ reg_a = res; /* set the Z flag accordingly */ flag_z = (0x100-reg_a) >> 8; /* set the S flag and the two unused bits accordingly */ reg_f = reg_a; /* set the P/V flag according to the parity */ flag_pv = parity[reg_a]; Eliminating the one conditional jump is left as an exercise for the reader. :-) /Bo Lindbergh