x86 Carry and Auxiliary/Adjust flags?

Emulation of old PCs, PC hardware, or PC peripherals.

x86 Carry and Auxiliary/Adjust flags?

Postby superfury » 2017-8-10 @ 16:40

I'm trying to get the flags properly implemented in UniPCemu, but the 80186(or 80286, since it expects the high 4 bits to be zeroed?) testsuite says the carry and adjust flags are incorrect?

Code: Select all
//Addition Carry, Overflow, Adjust logic
//Tables based on http://teaching.idallen.com/dat2343/10f/notes/040_overflow.txt
//Index Bit0=sumsign, Bit1=num2sign(add or sub negated value), Bit2=num1sign(v1)
byte addoverflow[8] = {0,1,0,0,0,0,1,0};
byte suboverflow[8] = {0,0,0,1,1,0,0,0};

//Flags(Aux/Carry):
//ADD: ((op1)^(op2))^(((op1)^(result))&~((op1)^(op2)))^result
//SUB: ((op1)^(op2))^(((op1)^(result))&((op1)^(op2)))^result
//Auxiliary flag: ((op1^op2)^((op1^result)&(~(op1^op2))^result
//Auxiliary flag: ((op1)^(op2))^(((op1)^(result))&~((op1)^(op2)))^result
//borrow/carry bits
#define bcbitsa(v1,v2) (((v1)^(v2))^(((v1)^(dst))&~((v1)^(v2)))^dst)
#define bcbitss(v1,v2) (((v1)^(v2))^(((v1)^(dst))&((v1)^(v2)))^dst)

void flag_adcoa8(uint8_t v1, uint16_t add, uint16_t dst)
{
   FLAGW_CF((bcbitsa((uint16_t)v1,add)>>7)&1); //Carry?
   FLAGW_OF(addoverflow[((dst>>7)&1)|(((add>>6)&2))|((v1>>5)&4)]); //Overflow?
   FLAGW_AF((bcbitsa((uint16_t)v1,add)&0x8)>>3); //Adjust?
}

void flag_adcoa16(uint16_t v1, uint32_t add, uint32_t dst)
{
   FLAGW_CF((bcbitsa((uint32_t)v1,add)>>15)&1); //Carry?
   FLAGW_OF(addoverflow[((dst>>15)&1)|(((add>>14)&2))|((v1>>13)&4)]); //Overflow?
   FLAGW_AF((bcbitsa((uint32_t)v1,add)&0x8)>>3); //Adjust?
}

void flag_adcoa32(uint32_t v1, uint64_t add, uint64_t dst)
{
   FLAGW_CF((bcbitsa((uint64_t)v1,add)>>31)&1); //Carry?
   FLAGW_OF(addoverflow[((dst>>31)&1)|(((add>>30)&2))|((v1>>29)&4)]); //Overflow?
   FLAGW_AF((bcbitsa((uint32_t)v1,add)&0x8)>>3); //Adjust?
}

//Substract Carry, Overflow, Adjust logic
void flag_subcoa8(uint8_t v1, uint16_t sub, uint16_t dst)
{
   FLAGW_CF((bcbitss((uint16_t)v1,sub)>>7)&1); //Carry?
   FLAGW_OF(suboverflow[((dst>>7)&1)|((sub>>6)&2)|((v1>>5)&4)]); //Overflow?
   FLAGW_AF((bcbitss((uint16_t)v1,sub)&0x8)>>3); //Adjust?
}

void flag_subcoa16(uint16_t v1, uint32_t sub, uint32_t dst)
{
   FLAGW_CF((bcbitss((uint32_t)v1,sub)>>15)&1); //Carry?
   FLAGW_OF(suboverflow[((dst>>15)&1)|((sub>>14)&2)|((v1>>13)&4)]); //Overflow?
   FLAGW_AF((bcbitss((uint32_t)v1,sub)&0x8)>>3); //Adjust?
}

void flag_subcoa32(uint32_t v1, uint64_t sub, uint64_t dst)
{
   FLAGW_CF((bcbitss((uint64_t)v1,sub)>>31)&1); //Carry?
   FLAGW_OF(suboverflow[((dst>>31)&1)|((sub>>30)&2)|((v1>>29)&4)]); //Overflow?
   FLAGW_AF((bcbitss((uint64_t)v1,sub)&0x8)>>3); //Adjust?
}


Anyone knows what's going wrong? I've based it on http://www.emulators.com/docs/nx11_flags.htm and the code that's talked about(which is mentioned as well, at least the ADD instruction). For some reason, UniPCemu's doesn't match the dumped flags? The overflow flags now uses the tables from http://teaching.idallen.com/dat2343/10f ... erflow.txt
superfury
Oldbie
 
Posts: 1879
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: x86 Carry and Auxiliary/Adjust flags?

Postby peterferrie » 2017-8-11 @ 18:59

For carry, it's not bit 7 that matters in an 8-bit add, it's bit 8 after the adc (consider 0xff+0xff+carry set, or 0xff+0x00+carry clear, depending on the test case).
If the value after the add is less than the value of the left parameter, or if the result equals the left parameter and the right parameter is non-zero, then you have a carry.
There's an overflow if the top bit of the result is different from the top bit of both of the parameters.
There's an aux carry if both parameters had bit 3 set and the result does too, or if only one parameter had it set and the result doesn't.
peterferrie
Oldbie
 
Posts: 582
Joined: 2008-5-08 @ 21:54

Re: x86 Carry and Auxiliary/Adjust flags?

Postby superfury » 2017-8-11 @ 19:52

So the carry bit is set on toggling bit 8, while the aux bit does the same for bit 4? So it's quite litterally a half-carry(4-bits carry into bit 4 or borrow from bit 4)?

Edit: I've changed the bits to check from bits 3(auxiliary) and 7/15/31(carry) to bits 4(auxiliary) and 8/16/32. The test suite's SUBB/SUBW/SBBB/SBBW instructions still give errors on bit 4 of the flags(auxiliary carry)? It's bytes at address 0x70, 0x74, 0x84 and 0x90. It expects 0x97, 0x87, 0x87, 0x96 and gets 0x87, 0x97, 0x97, 0x96? So bit 0x10 in the flags is flipped? That's the auxiliary flag.

https://bitbucket.org/superfury/unipcem ... ?at=master

Edit: maybe a problem with the detection?
Code: Select all
#define bcbitsa(v1,v2) (((v1)^(v2))^(((v1)^(dst))&~((v1)^(v2)))^dst)
#define bcbitss(v1,v2) (((v1)^(v2))^(((v1)^(dst))&((v1)^(v2)))^dst)


bcbitsa is for adding, bcbitss is for substracting. Result bits is 1 for carry/borrow bits, 0 otherwise. Both v1 and v2 are the direct inputted values(unmodified, only carry added(+) with SBB/ADC as unsigned values).
superfury
Oldbie
 
Posts: 1879
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: x86 Carry and Auxiliary/Adjust flags?

Postby superfury » 2017-8-12 @ 15:06

I've tried making a simple truth table to use for calculating carry/adjust flags, based on the 7/15/31th bit of v1(the value being added/substracted to/from), v2(the value being added/substracted) and the result bit:

Code: Select all
ADD:
CARRY(7/15/31)/AUX(3):
   V1   V2   RES   FLAG
   0   0   0   0
   0   0   1   0
   0   1   0   1
   0   1   1   0
   1   0   0   1
   1   0   1   0
   1   1   0   0
   1   1   1   1

SUB:
CARRY(7/15/31)/AUX(3):
   V1   V2   RES   FLAG
   0   0   0   0
   0   0   1   1
   0   1   0   0
   0   1   1   1
   1   0   0   0
   1   0   1   0
   1   1   0   0
   1   1   1   1


For some reason, this doesn't match an actual CPU? The testsuite still fails.
superfury
Oldbie
 
Posts: 1879
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: x86 Carry and Auxiliary/Adjust flags?

Postby superfury » 2017-8-12 @ 18:53

After some checking and adjusting, the carry flag now seems to work correctly. But the adjust flag still isn't? It uses the same logic as the normal carry flag, but the effect of substracting 0x100 from 0xFF still doesn't set the Auxiliary carry flag, but does set the carry flag? The carry flag looks at the bit changed being 8/16/32, but the Auxiliary flag checks bit 3 instead? All cases work, except the substracting 0x100(0xFF immediate + Carry flag in SBB instruction) from 0xFF instruction? It's supposed to be cleared? (0xFF-0x100=0xFF, so the first case(both aren't set) doesn't apply, nor the second case(one parameter has bit 3 set(source parameter only) and the result doesn't have it set(being 0x1FF in 9-bit terms)) applies?

But somehow, the testsuite appears to expect the Auxiliary flag to be set with the substraction of 0xFF-0x100=0xFF?

Edit: Adding and modified according to Bochs lazy_flags.h's http://bochs.sourceforge.net/cgi-bin/lx ... zy_flags.h ADD_COUT_VEC and SUB_COUT_VEC makes the booting process run until loading CD-ROM device drivers, keyboard unresponsive. Test suites failing?

Edit: Restoring the old code makes it able to boot again, but it will still fail the testsuites on the ADC/D, SUB/SBB and CMP instructions?

Edit: Apparently, looking at the Bochs source code and comparing it to the original code of fake86, I notice something odd: all three handle the Carry flag in SBB/ADC instructions differently: Bochs(which seems to be correctly working) doesn't include the carry flag in the second operand flags, while fake86 does include it (incorrectly) in the second operand of the SBB instructions, while UniPCemu included it with sbb only(being based off fake86's flag operations originally). Now, fixing those flags using the Bochs way fixes the testsuite as well(sub and add tests work without problems now). The only part left is the mul ROM and rotate ROM giving errors.
superfury
Oldbie
 
Posts: 1879
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: x86 Carry and Auxiliary/Adjust flags?

Postby superfury » 2017-8-13 @ 15:32

The rotate ROM is acting odd: it expects the RCLW BX,CL instruction to set Overflow flag while CL=8? Since CL<>1, it shouldn't even change the overflow flag?

Also, there's still a problem with 80286+ AAA instruction?
superfury
Oldbie
 
Posts: 1879
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: x86 Carry and Auxiliary/Adjust flags?

Postby superfury » 2017-8-13 @ 18:47

This is the AAA instruction:
Code: Select all
byte CPU8086_internal_AAA()
{
   CPUPROT1
   if (EMULATED_CPU<CPU_80286) //Before new CPU?
   {
      if (((REG_AL&0xF)>9) || FLAG_AF)
      {
         REG_AL += 6;
         ++REG_AH;
         FLAGW_AF(1);
         FLAGW_CF(1);
      }
      else
      {
         FLAGW_AF(0);
         FLAGW_CF(0);
      }
      REG_AL &= 0xF;
   }
   else //Newer CPUs?
   {
      if (((REG_AL&0xF)>9) || FLAG_AF)
      {
         REG_AX += 0x0106;
         FLAGW_AF(1);
         FLAGW_CF(1);
      }
      else
      {
         FLAGW_AF(0);
         FLAGW_CF(0);
      }
      REG_AL &= 0xF;
   }
   //flag_szp8(REG_AL); //Basic flags!
   flag_p8(REG_AL); //Parity is affected!
   if (EMULATED_CPU<CPU_80286) //Before new CPU?
   {
      FLAGW_ZF((REG_AL==0)?1:0); //Zero is affected!
   }
   else
   {
      FLAGW_ZF((REG_AL==0)?1:0); //Zero is affected!
      FLAGW_SF(0); //Clear Sign!
   }
   //z=s=p=o=?
   CPUPROT2
   if (CPU_apply286cycles()==0) //No 80286+ cycles instead?
   {
      CPU[activeCPU].cycles_OP += 4; //Timings!
   }
   return 0;
}


And the rotate instructions:
Code: Select all
byte op_grp2_8(byte cnt, byte varshift) {
   //word d,
   INLINEREGISTER word s, shift, oldCF, msb;
   //word backup;
   //if (cnt>0x8) return(oper1b); //NEC V20/V30+ limits shift count
   s = oper1b;
   oldCF = FLAG_CF;
   if (EMULATED_CPU >= CPU_NECV30) cnt &= 0x1F; //Clear the upper 3 bits to become a NEC V20/V30+!
   switch (thereg) {
   case 0: //ROL r/m8
      for (shift = 1; shift <= cnt; shift++) {
         if (s & 0x80) FLAGW_CF(1); else FLAGW_CF(0);
         s = s << 1;
         s = s | FLAG_CF;
      }
      if (cnt==1) FLAGW_OF(((s >> 7) & 1)&FLAG_CF); else FLAGW_OF(0);
      break;

   case 1: //ROR r/m8
      for (shift = 1; shift <= cnt; shift++) {
         FLAGW_CF(s & 1);
         s = (s >> 1) | (FLAG_CF << 7);
      }
      if (cnt==1) FLAGW_OF((s >> 7) ^ ((s >> 6) & 1));
      break;

   case 2: //RCL r/m8
      for (shift = 1; shift <= cnt; shift++) {
         oldCF = FLAG_CF;
         if (s & 0x80) FLAGW_CF(1); else FLAGW_CF(0);
         s = s << 1;
         s = s | oldCF;
      }
      if (cnt==1) FLAGW_OF(FLAG_CF ^ ((s >> 7) & 1));
      break;

   case 3: //RCR r/m8
      for (shift = 1; shift <= cnt; shift++) {
         oldCF = FLAG_CF;
         FLAGW_CF(s & 1);
         s = (s >> 1) | (oldCF << 7);
      }
      if (cnt==1) FLAGW_OF((s >> 7) ^ ((s >> 6) & 1));
      break;

   case 4: case 6: //SHL r/m8
      //FLAGW_AF(0);
      for (shift = 1; shift <= cnt; shift++) {
         if (s & 0x80) FLAGW_CF(1); else FLAGW_CF(0);
         //if (s & 0x8) FLAGW_AF(1); //Auxiliary carry?
         s = (s << 1) & 0xFF;
      }
      if (cnt==1) { if (FLAG_CF==(s>>7)) FLAGW_OF(0); else FLAGW_OF(1); }
      flag_szp8((uint8_t)(s&0xFF)); break;

   case 5: //SHR r/m8
      if (cnt == 1) { if (s&0x80) FLAGW_OF(1); else FLAGW_OF(0); }
      //FLAGW_AF(0);
      for (shift = 1; shift <= cnt; shift++) {
         FLAGW_CF(s & 1);
         //backup = s; //Save backup!
         s = s >> 1;
         //if (((backup^s)&0x10)) FLAGW_AF(1); //Auxiliary carry?
      }
      flag_szp8((uint8_t)(s & 0xFF)); break;

   case 7: //SAR r/m8
      msb = s & 0x80;
      //FLAGW_AF(0);
      for (shift = 1; shift <= cnt; shift++) {
         FLAGW_CF(s & 1);
         //backup = s; //Save backup!
         s = (s >> 1) | msb;
         //if (((backup^s)&0x10)) FLAGW_AF(1); //Auxiliary carry?
      }
      byte tempSF;
      tempSF = FLAG_SF; //Save the SF!
      /*flag_szp8((uint8_t)(s & 0xFF));*/
      //http://www.electronics.dit.ie/staff/tscarff/8086_instruction_set/8086_instruction_set.html#SAR says only C and O flags!
      if (!cnt) //Nothing done?
      {
         FLAGW_SF(tempSF); //We don't update when nothing's done!
      }
      else if (cnt==1) //Overflow is cleared on all 1-bit shifts!
      {
         flag_s8(s); //Affect sign as well!
         FLAGW_OF(0); //Cleared!
      }
      else if (cnt) //Anything shifted at all?
      {
         flag_s8(s); //Affect sign as well!
      }
      if ((EMULATED_CPU>=CPU_NECV30) && cnt) //NECV20+ affected?
      {
         flag_p8(s); //Affect parity as well!
      }
      break;
   }
   op_grp2_cycles(cnt, varshift);
   return(s & 0xFF);
}

word op_grp2_16(byte cnt, byte varshift) {
   //uint32_t d,
   INLINEREGISTER uint_32 s, shift, oldCF, msb;
   //if (cnt>0x10) return(oper1); //NEC V20/V30+ limits shift count
   if (EMULATED_CPU >= CPU_NECV30) cnt &= 0x1F; //Clear the upper 3 bits to become a NEC V20/V30+!
   //word backup;
   s = oper1;
   oldCF = FLAG_CF;
   switch (thereg) {
   case 0: //ROL r/m16
      for (shift = 1; shift <= cnt; shift++) {
         if (s & 0x8000) FLAGW_CF(1); else FLAGW_CF(0);
         s = s << 1;
         s = s | FLAG_CF;
      }
      if (cnt==1) FLAGW_OF(FLAG_CF ^ ((s >> 15) & 1));
      break;

   case 1: //ROR r/m16
      for (shift = 1; shift <= cnt; shift++) {
         FLAGW_CF(s & 1);
         s = (s >> 1) | (FLAG_CF << 15);
      }
      if (cnt==1) FLAGW_OF((s >> 15) ^ ((s >> 14) & 1));
      break;

   case 2: //RCL r/m16
      for (shift = 1; shift <= cnt; shift++) {
         oldCF = FLAG_CF;
         if (s & 0x8000) FLAGW_CF(1); else FLAGW_CF(0);
         s = s << 1;
         s = s | oldCF;
         //oldCF = ((s&0x8000)>>15)&1; //Save FLAG_CF!
         //s = (s<<1)+FLAG_CF;
         //FLAG_CF = oldCF;
      }
      if (cnt==1) FLAGW_OF(FLAG_CF ^ ((s >> 15) & 1));
      break;

   case 3: //RCR r/m16
      for (shift = 1; shift <= cnt; shift++) {
         oldCF = FLAG_CF;
         FLAGW_CF(s & 1);
         s = (s >> 1) | (oldCF << 15);
         //oldCF = s&1;
         //s = (s<<1)+(FLAG_CF<<16);
         //FLAG_CF = oldCF;
      }
      if (cnt==1) FLAGW_OF((s >> 15) ^ ((s >> 14) & 1));
      break;

   case 4: case 6: //SHL r/m16
      //FLAGW_AF(0);
      for (shift = 1; shift <= cnt; shift++) {
         if (s & 0x8000) FLAGW_CF(1); else FLAGW_CF(0);
         //if (s & 0x8) FLAGW_AF(1); //Auxiliary carry?
         s = (s << 1) & 0xFFFF;
      }
      if (cnt==1) { if (FLAG_CF == (s >> 15)) FLAGW_OF(0); else FLAGW_OF(1); }
      flag_szp16(s); break;

   case 5: //SHR r/m16
      if (cnt==1) { if (s&0x8000) FLAGW_OF(1); else FLAGW_OF(0); }
      //FLAGW_AF(0);
      for (shift = 1; shift <= cnt; shift++) {
         FLAGW_CF(s & 1);
         //backup = s; //Save backup!
         s = s >> 1;
         //if (((backup^s)&0x10)) FLAGW_AF(1); //Auxiliary carry?
      }
      flag_szp16(s); break;

   case 7: //SAR r/m16
      msb = s & 0x8000; //Read the MSB!
      //FLAGW_AF(0);
      for (shift = 1; shift <= cnt; shift++) {
         FLAGW_CF(s & 1);
         //backup = s; //Save backup!
         s = (s >> 1) | msb;
         //if (((backup^s)&0x10)) FLAGW_AF(1); //Auxiliary carry?
      }
      byte tempSF;
      tempSF = FLAG_SF; //Save the SF!
      /*flag_szp16(s);*/
      //http://www.electronics.dit.ie/staff/tscarff/8086_instruction_set/8086_instruction_set.html#SAR says only C and O flags!
      if (!cnt) //Nothing done?
      {
         FLAGW_SF(tempSF); //We don't update when nothing's done!
      }
      else if (cnt==1) //Overflow is cleared on all 1-bit shifts!
      {
         flag_s16(s); //Affect sign as well!
         FLAGW_OF(0); //Cleared!
      }
      else if (cnt) //Anything shifted at all?
      {
         flag_s16(s); //Affect sign as well!
      }
      if ((EMULATED_CPU>=CPU_NECV30) && cnt) //NECV20+ affected?
      {
         flag_p16(s); //Affect parity as well!
         flag_s16(s); //Affect sign as well!
      }
      break;
   }
   op_grp2_cycles(cnt, varshift|4);
   return(s & 0xFFFF);
}


Can anyone see what's going wrong?
superfury
Oldbie
 
Posts: 1879
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: x86 Carry and Auxiliary/Adjust flags?

Postby vladstamate » 2017-8-14 @ 14:11

Where did you get the information that for 286+ AAA touches AX ? According to this MIT page for the 386 AAA instruction it should still touch only AH/AL just like 8086:

http://css.csail.mit.edu/6.858/2014/rea ... 86/AAA.htm

Also the AMD 186 instruction set here (http://ece425web.groups.et.byu.net/stab ... ionSet.pdf) describes it the same way.
User avatar
vladstamate
Oldbie
 
Posts: 615
Joined: 2015-8-23 @ 01:43

Re: x86 Carry and Auxiliary/Adjust flags?

Postby superfury » 2017-8-14 @ 17:32

I found that part of information here: http://www.hugi.scene.org/online/coding ... 0coaax.htm
superfury
Oldbie
 
Posts: 1879
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: x86 Carry and Auxiliary/Adjust flags?

Postby vladstamate » 2017-8-14 @ 22:35

According to this: https://stackoverflow.com/questions/189 ... uction-set you information is correct. So the MIT website is wrong... :(

But then when was the change introduced? It seems not 80186/188 as the AMD official docs still have the 8088/8086 behavior. It must have been 286. If I have some time I see about firing debug.exe on one of my machines and test it. I'll try a 386.
User avatar
vladstamate
Oldbie
 
Posts: 615
Joined: 2015-8-23 @ 01:43

Re: x86 Carry and Auxiliary/Adjust flags?

Postby vladstamate » 2017-8-14 @ 23:48

Ok, to confirm. I ran this code on my actual 386 computer (via debug.exe in DOS):

mov ax, 00f6
add al, 9
aaa

and the result was AX=0205

So your code is correct.
User avatar
vladstamate
Oldbie
 
Posts: 615
Joined: 2015-8-23 @ 01:43

Re: x86 Carry and Auxiliary/Adjust flags?

Postby superfury » 2017-8-15 @ 09:46

What about the 80286 and 80186? Do they have this new behaviour as well? Or do the 80186 or both still have the old 8086/88 behaviour?
superfury
Oldbie
 
Posts: 1879
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: x86 Carry and Auxiliary/Adjust flags?

Postby vladstamate » 2017-8-15 @ 12:00

I do not have an 186. Although I do have a 286 so I will try it in that. My guess though is that it will behave like a 386. We'll see.
User avatar
vladstamate
Oldbie
 
Posts: 615
Joined: 2015-8-23 @ 01:43

Re: x86 Carry and Auxiliary/Adjust flags?

Postby superfury » 2017-8-15 @ 12:12

With all current changes, I do notice a problem on the CPU emulation: when running Wolfenstein 3D's original program, it now hangs the CPU for some reason(it used to work previously). Also, both on current and the last release version of UniPCemu, for some reason, the cinematics of Megarace seem to hang and produce no sound? It seems to eventually continue on to the next screen(either a still video screen or a menu/gameplay). Gameplay seems to run somewhat, though. Any idea what might caused the cinematics to hang? It used to work previously.

Is there a way (besides the testsuite for 80486+ CPUs that's on another vogons thread(viewtopic.php?t=38447)) to test the 80386 emulation and find the offending instruction(s)? The smallest i386-nofpu program seems to hang in a little "returnpoint:cmp ax;jne xxx;(jumps to xxx);xxx:jmp returnpoint" neverending loop.
superfury
Oldbie
 
Posts: 1879
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: x86 Carry and Auxiliary/Adjust flags?

Postby peterferrie » 2017-8-15 @ 21:27

AAA had for a long time a documentation error: it's single 16-bit add, not two 8-bit adds, just as AAS is a 16-bit subtraction.
peterferrie
Oldbie
 
Posts: 582
Joined: 2008-5-08 @ 21:54

Re: x86 Carry and Auxiliary/Adjust flags?

Postby peterferrie » 2017-8-15 @ 21:32

superfury wrote:The rotate ROM is acting odd: it expects the RCLW BX,CL instruction to set Overflow flag while CL=8? Since CL<>1, it shouldn't even change the overflow flag?

Also, there's still a problem with 80286+ AAA instruction?


RCL would require CL=9 to rotate to the original value, otherwise it will shift the carry to the top bit, and that could well cause an overflow condition.
peterferrie
Oldbie
 
Posts: 582
Joined: 2008-5-08 @ 21:54

Re: x86 Carry and Auxiliary/Adjust flags?

Postby superfury » 2017-8-15 @ 22:14

But no flags should be affected when CL<>1, according to documentation? Or just carry flag?
superfury
Oldbie
 
Posts: 1879
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: x86 Carry and Auxiliary/Adjust flags?

Postby peterferrie » 2017-8-16 @ 20:49

All flags are affected as expected when CL < 9, when doing RCL or RCR.
peterferrie
Oldbie
 
Posts: 582
Joined: 2008-5-08 @ 21:54

Re: x86 Carry and Auxiliary/Adjust flags?

Postby superfury » 2017-8-17 @ 12:31

Managed to fix the code and the testsuite now runs fine again.

There's still a problem with the AAD instruction, it seems?

My current AAD instruction:
Code: Select all
OPTINLINE byte CPU8086_internal_AAD(byte data)
{
   CPUPROT1
   oper2b = REG_AL; //What to add!
   oper1b = (REG_AH*data); //AAD base to work on, we're adding to this!
   op_add8(); //Add, 8-bit, including flags!
   REG_AL = res8; //The result to load!
   REG_AH = 0; //AH is cleared!
   CPUPROT2
   if (CPU_apply286cycles()==0) //No 80286+ cycles instead?
   {
      CPU[activeCPU].cycles_OP += 60; //Timings!
   }
   return 0;
}


Can you see what's going wrong? The EPC 80186 testsuite doesn't match the AAD 39h(expecting flags to be 0082h, getting 0892h at address 88h) and AAD 12h(expecting flags to be 0086 and getting 0097 at address 8Ch). Can you see what's going wrong? The new instruction uses the new, improved version of the ADD flags(which is the same as Bochs). This is done, according to the alternative documentation at http://www.hugi.scene.org/online/coding ... 0coaax.htm . It says the flags are actually the result of the '+' operation, so essentially the (although incorrect in assembler) execution is: ADD (AH*imm),AL with the result being stored back into AL?
superfury
Oldbie
 
Posts: 1879
Joined: 2014-3-08 @ 11:25
Location: Netherlands

Re: x86 Carry and Auxiliary/Adjust flags?

Postby peterferrie » 2017-8-18 @ 19:50

Yes, the flags are the result of the add, but according to my documentation, it's a 16-bit add, not an 8-bit one.
i.e. ax = ((ah * imm8) + al) & 0xff
That might explain the difference in flags.
peterferrie
Oldbie
 
Posts: 582
Joined: 2008-5-08 @ 21:54


Return to PC Emulation

Who is online

Users browsing this forum: No registered users and 2 guests