I\'ve ported my library x86Lib to mbed. It fully emulates the 8086 processor, but a few things I\'m still working on. Notable missing things are interrupts. Previously I used exceptions for interrupts, but exceptions aren\'t supported with the mbed compiler. It is also quite slow

Dependents:   x86Lib_Tester

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers maths.cpp Source File

maths.cpp

00001 /**
00002 Copyright (c) 2007 - 2009 Jordan "Earlz/hckr83" Earls  <http://www.Earlz.biz.tm>
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without
00006 modification, are permitted provided that the following conditions
00007 are met:
00008 
00009 1. Redistributions of source code must retain the above copyright
00010    notice, this list of conditions and the following disclaimer.
00011 2. Redistributions in binary form must reproduce the above copyright
00012    notice, this list of conditions and the following disclaimer in the
00013    documentation and/or other materials provided with the distribution.
00014 3. The name of the author may not be used to endorse or promote products
00015    derived from this software without specific prior written permission.
00016    
00017 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
00018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
00019 AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
00020 THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00021 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00022 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
00023 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00024 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00025 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
00026 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027 
00028 This file is part of the x86Lib project.
00029 **/
00030 #define X86LIB_BUILD
00031 #include <x86Lib.h>
00032 namespace x86Lib{
00033 using namespace std;
00034 
00035 
00036 
00037 
00038 // TODO (Jordan#4#): Get AF stuff working in this!!
00039 uint8_t x86CPU::Sub8(uint8_t base,uint8_t subt){
00040     int8_t result;
00041     if(subt>base){freg.cf=1;}else{freg.cf=0;}
00042     if((int16_t)base-subt>127 || (int16_t)base-subt<-127){
00043             freg.of=1;
00044         }else{
00045             freg.of=0;
00046         }
00047     result=base-subt;
00048     if(result==0){freg.zf=1;}else{freg.zf=0;}
00049     CalculatePF8(result); //do pf
00050     CalculateSF8(result); //do sf
00051     base&=0xF;
00052     subt&=0xF; 
00053     freg.af = (((base-subt) & ~0xf) != 0); //thank you http://stackoverflow.com/questions/4513746/explain-how-the-af-flag-works-in-an-x86-instructions
00054     return result;
00055 }
00056 
00057 uint16_t x86CPU::Sub16(uint16_t base,uint16_t subt){
00058     int16_t result;
00059     uint16_t mirror;
00060     if(subt>base){freg.cf=1;}else{freg.cf=0;}
00061     if((int32_t)base-subt>32767 || (int32_t)base-subt<-32767){
00062             freg.of=1;
00063         }else{
00064             freg.of=0;
00065         }
00066     mirror=base-subt;
00067     result=mirror;
00068     if(result==0){freg.zf=1;}else{freg.zf=0;}
00069     CalculatePF16(result); //do pf
00070     CalculateSF16(result); //do sf
00071     base&=0xF;
00072     subt&=0xF; 
00073     freg.af = (((base-subt) & ~0xf) != 0); 
00074     return mirror;
00075 }
00076 
00077 uint8_t x86CPU::Add8(uint8_t base,uint8_t adder){
00078     int8_t result;
00079     if(adder+base>255){freg.cf=1;}else{freg.cf=0;}
00080     if((int16_t)base+adder>127 || (int16_t)base+adder<-127){
00081             freg.of=1;
00082         }else{
00083             freg.of=0;
00084         }
00085     result=base+adder;
00086     if(result==0){freg.zf=1;}else{freg.zf=0;}
00087     CalculatePF8(result); //do pf
00088     CalculateSF8(result); //do sf
00089     base&=0x0F;
00090     adder&=0x0F;
00091     freg.af = ((int16_t)base+adder > 15);
00092     return result;
00093 }
00094 
00095 uint16_t x86CPU::Add16(uint16_t base,uint16_t adder){
00096     int16_t result;
00097     if((uint32_t)adder+base>(uint32_t)65535){freg.cf=1;}else{freg.cf=0;}
00098     if((int32_t)base+adder>32767 || (int32_t)base+adder<-32767){
00099             freg.of=1;
00100         }else{
00101             freg.of=0;
00102         }
00103     result=base+adder;
00104     if(result==0){freg.zf=1;}else{freg.zf=0;}
00105     CalculatePF16(result); //do pf
00106     CalculateSF16(result); //do sf
00107     base&=0x0F;
00108     adder&=0x0F;
00109     freg.af = ((int16_t)base+adder > 15);
00110     return result;
00111 }
00112 
00113 
00114 
00115 
00116 uint8_t x86CPU::And8(uint8_t base,uint8_t mask){
00117     freg.of=0;
00118     freg.cf=0;
00119     base=base&mask;
00120     CalculatePF8(base);
00121     CalculateSF8(base);
00122     if(base==0){
00123         freg.zf=1;
00124     }else{
00125         freg.zf=0;
00126     }
00127     return base;
00128 }
00129 
00130 uint16_t x86CPU::And16(uint16_t base,uint16_t mask){
00131     freg.of=0;
00132     freg.cf=0;
00133     base=base&mask;
00134     CalculatePF16(base);
00135     CalculateSF16(base);
00136     if(base==0){
00137         freg.zf=1;
00138     }else{
00139         freg.zf=0;
00140     }
00141     return base;
00142 }
00143 
00144 //Not affects no flags, so just use ~
00145 
00146 
00147 uint8_t x86CPU::Or8(uint8_t base,uint8_t mask){
00148     freg.of=0;
00149     freg.cf=0;
00150     base=base|mask;
00151     CalculatePF8(base);
00152     CalculateSF8(base);
00153     if(base==0){
00154         freg.zf=1;
00155     }else{
00156         freg.zf=0;
00157     }
00158     return base;
00159 }
00160 
00161 uint16_t x86CPU::Or16(uint16_t base,uint16_t mask){
00162     freg.of=0;
00163     freg.cf=0;
00164     base=base|mask;
00165     CalculatePF16(base);
00166     CalculateSF16(base);
00167     if(base==0){
00168         freg.zf=1;
00169     }else{
00170         freg.zf=0;
00171     }
00172     return base;
00173 }
00174 
00175 uint8_t x86CPU::Xor8(uint8_t base,uint8_t mask){
00176     freg.of=0;
00177     freg.cf=0;
00178     base=base^mask;
00179     CalculatePF8(base);
00180     CalculateSF8(base);
00181     if(base==0){
00182         freg.zf=1;
00183     }else{
00184         freg.zf=0;
00185     }
00186     return base;
00187 }
00188 
00189 uint16_t x86CPU::Xor16(uint16_t base,uint16_t mask){
00190     freg.of=0;
00191     freg.cf=0;
00192     base=base^mask;
00193     CalculatePF16(base);
00194     CalculateSF16(base);
00195     if(base==0){
00196         freg.zf=1;
00197     }else{
00198         freg.zf=0;
00199     }
00200     return base;
00201 }
00202 
00203 uint8_t x86CPU::ShiftLogicalRight8(uint8_t base,uint8_t count){
00204     count&=0x1F; //only use bottom 5 bits
00205     if(count==0){
00206         CalculatePF8(base);
00207         CalculateSF8(base);
00208         freg.zf=1;
00209         return base;
00210     }
00211     freg.of=(base&0x80)>>7;
00212     freg.cf=(base>>(count-1))&1;
00213     base=base>>count;
00214     freg.of=freg.of^((base&0x80)>>7); //if the sign bit changed, then set it to 1
00215     CalculatePF8(base);
00216     CalculateSF8(base);
00217     if(base==0){
00218         freg.zf=1;
00219     }else{
00220         freg.zf=0;
00221     }
00222     freg.of=0;
00223     return base;
00224 }
00225 
00226 uint16_t x86CPU::ShiftLogicalRight16(uint16_t base,uint8_t count){
00227     count&=0x1F; //only use bottom 5 bits
00228     if(count==0){
00229         CalculatePF16(base);
00230         CalculateSF16(base);
00231         freg.zf=1;
00232         return base;
00233     }
00234     freg.of=(base&0x8000)>>15;
00235     freg.cf=(base>>(count-1))&1;
00236     base=base>>count;
00237     freg.of=freg.of^((base&0x8000)>>15); //if the sign bit changed, then set it to 1
00238     CalculatePF16(base);
00239     CalculateSF16(base);
00240     if(base==0){
00241         freg.zf=1;
00242     }else{
00243         freg.zf=0;
00244     }
00245     freg.of=0;
00246     return base;
00247 }
00248 uint8_t x86CPU::ShiftArithmeticRight8(uint8_t base,uint8_t count){
00249     count&=0x1F; //only use bottom 5 bits
00250     if(count==0){
00251         CalculatePF8(base);
00252         CalculateSF8(base);
00253         freg.zf=1;
00254         return base;
00255     }
00256     freg.cf=(base>>(count-1))&1;
00257     if((base&0x80)!=0){
00258         base=(base>>count)|(~(0xFF>>count)); //this replaces displaced zero bits with the sign bit
00259     }else{
00260         base=(base>>count);
00261     }
00262     freg.of=0;
00263     CalculatePF8(base);
00264     CalculateSF8(base);
00265     if(base==0){
00266         freg.zf=1;
00267     }else{
00268         freg.zf=0;
00269     }
00270     freg.of=0;
00271     return base;
00272 }
00273 uint16_t x86CPU::ShiftArithmeticRight16(uint16_t base,uint8_t count){
00274     count&=0x1F; //only use bottom 5 bits
00275     if(count==0){
00276         CalculatePF16(base);
00277         CalculateSF16(base);
00278         freg.zf=1;
00279         return base;
00280     }
00281     freg.cf=(base>>(count-1))&1;
00282     if((base&0x8000)!=0){
00283         base=(base>>count)|(~(0xFFFF>>count)); //this replaces displaced zero bits with the sign bit
00284     }else{
00285         base=(base>>count);
00286     }
00287     freg.of=0;
00288     CalculatePF16(base);
00289     CalculateSF16(base);
00290     if(base==0){
00291         freg.zf=1;
00292     }else{
00293         freg.zf=0;
00294     }
00295     freg.of=0;
00296     return base;
00297 }
00298 
00299 uint8_t x86CPU::ShiftLogicalLeft8(uint8_t base,uint8_t count){
00300     count&=0x1F; //only use bottom 5 bits
00301     if(count==0){
00302         CalculatePF8(base);
00303         CalculateSF8(base);
00304         freg.zf=1;
00305         return base;
00306     }
00307     freg.of=(base&0x80)>>7;
00308     freg.cf=((base<<(count-1))&0x80)>>7;
00309     base=base<<count;
00310     freg.of=freg.of^((base&0x80)>>7); //if the sign bit changed, then set it to 1
00311     CalculatePF8(base);
00312     CalculateSF8(base);
00313     if(base==0){
00314         freg.zf=1;
00315     }else{
00316         freg.zf=0;
00317     }
00318     freg.of=0;
00319     return base;
00320 }
00321 
00322 uint16_t x86CPU::ShiftLogicalLeft16(uint16_t base,uint8_t count){
00323     count&=0x1F; //only use bottom 5 bits
00324     if(count==0){
00325         CalculatePF16(base);
00326         CalculateSF16(base);
00327         freg.zf=1;
00328         return base;
00329     }
00330     freg.of=(base&0x8000)>>15;
00331     freg.cf=((base<<(count-1))&0x8000)>>15;
00332     base=base<<count;
00333     freg.of=freg.of^((base&0x8000)>>15); //if the sign bit changed, then set it to 1
00334     CalculatePF16(base);
00335     CalculateSF16(base);
00336     if(base==0){
00337         freg.zf=1;
00338     }else{
00339         freg.zf=0;
00340     }
00341     return base;
00342 }
00343 
00344 /**ToDo: Possibly adapt BOCHS source so that we avoid this loop crap...**/
00345 uint8_t x86CPU::RotateRight8(uint8_t base,uint8_t count){
00346     freg.of=(base&0x80)>>7;
00347     while(count>0){
00348         freg.cf=(base&0x01);
00349         base=(freg.cf<<7)|(base>>1);
00350         count--;
00351     }
00352     freg.of=freg.of^((base&0x80)>>7);
00353     return base;
00354 }
00355 
00356 uint16_t x86CPU::RotateRight16(uint16_t base,uint8_t count){
00357     freg.of=(base&0x8000)>>15;
00358     while(count>0){
00359         freg.cf=(base&0x01);
00360         base=(freg.cf<<15)|(base>>1);
00361         count--;
00362     }
00363     freg.of=freg.of^((base&0x80)>>15);
00364     return base;
00365 }
00366 
00367 uint8_t x86CPU::RotateLeft8(uint8_t base,uint8_t count){
00368     freg.of=(base&0x80)>>7;
00369     while(count>0){
00370         freg.cf=(base&0x80)>>7;
00371         base=(freg.cf)|(base<<1);
00372         count--;
00373     }
00374     freg.of=freg.of^((base&0x80)>>7);
00375     return base;
00376 }
00377 
00378 uint16_t x86CPU::RotateLeft16(uint16_t base,uint8_t count){
00379     freg.of=(base&0x8000)>>15;
00380     while(count>0){
00381         freg.cf=(base&0x8000)>>15;
00382         base=(freg.cf)|(base<<1);
00383         count--;
00384     }
00385     freg.of=freg.of^((base&0x8000)>>15);
00386     return base;
00387 }
00388 
00389 uint8_t x86CPU::RotateCarryLeft8(uint8_t base,uint8_t count){
00390    freg.of=(base&0x80)>>7;
00391    while(count>0){
00392       freg.r0=freg.cf; //reserved bit as a temp variable...
00393       freg.cf=(base&0x80)>>7;
00394       base=(base<<1);
00395       base|=freg.r0; //puts (old)CF in it's place
00396       count--;
00397    }
00398    freg.of=freg.of^((base&0x80)>>7);
00399    return base;
00400 }
00401 
00402 uint16_t x86CPU::RotateCarryLeft16(uint16_t base,uint8_t count){
00403     freg.of=(base&0x8000)>>15;
00404     while(count>0){
00405         freg.r0=freg.cf; //reserved bit as a temp variable...
00406         freg.cf=(base&0x8000)>>15;
00407         base=(base<<1);
00408         base=(base&0xFFFE)|freg.r0; //zeros the 0 bit and puts (old)CF in it's place
00409         count--;
00410     }
00411     freg.of=freg.of^((base&0x8000)>>15);
00412     return base;
00413 }
00414 
00415 uint8_t x86CPU::RotateCarryRight8(uint8_t base,uint8_t count){
00416     freg.of=(base&0x80)>>7;
00417     while(count>0){
00418         freg.r0=freg.cf;
00419         freg.cf=(base&0x01);
00420         base=(freg.r0<<7)|(base>>1);
00421         count--;
00422     }
00423     freg.of=freg.of^((base&0x80)>>7);
00424     return base;
00425 }
00426 
00427 uint16_t x86CPU::RotateCarryRight16(uint16_t base,uint8_t count){
00428     freg.of=(base&0x8000)>>15;
00429     while(count>0){
00430         freg.r0=freg.cf;
00431         freg.cf=(base&0x01);
00432         base=(freg.r0<<15)|(base>>1);
00433         count--;
00434     }
00435     freg.of=freg.of^((base&0x8000)>>15);
00436     return base;
00437 }
00438 
00439 
00440 
00441 
00442 
00443 
00444 
00445 
00446 
00447 void x86CPU::op16_sub_al_imm8(){ //0x2C
00448     *regs8[AL]=Sub8(*regs8[AL],op_cache[1]);
00449     eip++;
00450 }
00451 
00452 void x86CPU::op16_sub_ax_imm16(){ //0x2D..yay! 2D and not 3!
00453     *regs16[AX]=Sub16(*regs16[AX],*(uint16_t*)&op_cache[1]);
00454     eip+=2;
00455 }
00456 
00457 void x86CPU::op16_sub_rm8_r8(){
00458     eip++;
00459     ModRM16 rm8(this);
00460     rm8.WriteByter(Sub8(rm8.ReadByter(),*regs8[rm8.GetExtra()]));
00461     //finally learning the power of deconstructors!
00462 }
00463 
00464 void x86CPU::op16_sub_rm16_r16(){
00465     eip++;
00466     ModRM16 rm16(this);
00467     rm16.WriteWordr(Sub16(rm16.ReadWordr(),*regs16[rm16.GetExtra()]));
00468 }
00469 void x86CPU::op16_sub_r8_rm8(){
00470     eip++;
00471     ModRM16 rm8(this);
00472     *regs8[rm8.GetExtra()]=Sub8(*regs8[rm8.GetExtra()],rm8.ReadByter());
00473 }
00474 
00475 void x86CPU::op16_sub_r16_rm16(){
00476     eip++;
00477     ModRM16 rm16(this);
00478     *regs16[rm16.GetExtra()]=Sub16(*regs16[rm16.GetExtra()],rm16.ReadWordr());
00479 }
00480 
00481 void x86CPU::op16_sub_rm8_imm8(ModRM16 &rm8){ //group 0x80 /5
00482     rm8.WriteByter(Sub8(rm8.ReadByter(),ReadByte(cCS,eip+rm8.GetLength())));
00483 }
00484 
00485 void x86CPU::op16_sub_rm16_imm16(ModRM16 &rm){ //Group 0x81 /5
00486     rm.WriteWordr(Sub16(rm.ReadWordr(),ReadWord(cCS,eip+rm.GetLength())));
00487 }
00488 
00489 void x86CPU::op16_sub_rm16_imm8(ModRM16 &rm){ //group 0x83 /5
00490     rm.WriteWordr(Sub16(rm.ReadWordr(),SignExtend8(ReadByte(cCS,eip+rm.GetLength()))));
00491 }
00492 
00493 /****/
00494 void x86CPU::op16_sbb_al_imm8(){
00495     *regs8[AL]=Sub8(*regs8[AL],op_cache[1]-freg.cf);
00496     eip++;
00497 }
00498 
00499 void x86CPU::op16_sbb_ax_imm16(){
00500     *regs16[AX]=Sub16(*regs16[AX],*(uint16_t*)&op_cache[1]-freg.cf);
00501     eip++;
00502     eip++;
00503 }
00504 
00505 void x86CPU::op16_sbb_rm8_r8(){
00506     eip++;
00507     ModRM16 rm8(this);
00508     rm8.WriteByter(Sub8(rm8.ReadByter(),*regs8[rm8.GetExtra()]-freg.cf));
00509 }
00510 
00511 void x86CPU::op16_sbb_rm16_r16(){
00512     eip++;
00513     ModRM16 rm16(this);
00514     rm16.WriteWordr(Sub16(rm16.ReadWordr(),*regs16[rm16.GetExtra()]-freg.cf));
00515 }
00516 void x86CPU::op16_sbb_r8_rm8(){
00517     eip++;
00518     ModRM16 rm8(this);
00519     *regs8[rm8.GetExtra()]=Sub8(*regs8[rm8.GetExtra()],rm8.ReadByter()-freg.cf);
00520 }
00521 
00522 void x86CPU::op16_sbb_r16_rm16(){
00523     eip++;
00524     ModRM16 rm16(this);
00525     *regs16[rm16.GetExtra()]=Sub16(*regs16[rm16.GetExtra()],rm16.ReadWordr()-freg.cf);
00526 }
00527 
00528 void x86CPU::op16_sbb_rm8_imm8(ModRM16 &rm8){ //group 0x80
00529     rm8.WriteByter(Sub8(rm8.ReadByter(),ReadByte(cCS,eip+rm8.GetLength())-freg.cf));
00530 }
00531 
00532 void x86CPU::op16_sbb_rm16_imm16(ModRM16 &rm){ //Group 0x81
00533     rm.WriteWordr(Sub16(rm.ReadWordr(),ReadWord(cCS,eip+rm.GetLength())-freg.cf));
00534 }
00535 
00536 void x86CPU::op16_sbb_rm16_imm8(ModRM16 &rm){ //group 0x83
00537     rm.WriteWordr(Sub16(rm.ReadWordr(),SignExtend8(ReadByte(cCS,eip+rm.GetLength())-freg.cf)));
00538 }
00539 
00540 
00541 void x86CPU::op16_dec_r16(){ //0x48+r
00542     freg.r0=freg.cf;
00543     *regs16[(op_cache[0]-0x48)]=Sub16(*regs16[(op_cache[0]-0x48)],1);
00544     freg.cf=freg.r0;
00545 }
00546 
00547 void x86CPU::op16_dec_rm8(ModRM16& rm){
00548     freg.r0=freg.cf;
00549     rm.WriteByter(Sub8(rm.ReadByter(),1));
00550     freg.cf=freg.r0;
00551 }
00552 
00553 void x86CPU::op16_dec_rm16(ModRM16& rm){
00554     freg.r0=freg.cf;
00555     rm.WriteWordr(Sub16(rm.ReadWordr(),1));
00556     freg.cf=freg.r0;
00557 }
00558 
00559 
00560 
00561 
00562 
00563 
00564 //cmp and sub are so similar, that they are both going in here...
00565 void x86CPU::op16_cmp_al_imm8(){
00566     Sub8(*regs8[AL],op_cache[1]);
00567     eip++;
00568 }
00569 
00570 void x86CPU::op16_cmp_ax_imm16(){
00571     Sub16(*regs16[AX],*(uint16_t*)&op_cache[1]);
00572     eip+=2;
00573 }
00574 
00575 void x86CPU::op16_cmp_rm8_r8(){
00576     eip++;
00577     ModRM16 rm(this);
00578     Sub8(rm.ReadByter(),*regs8[rm.GetExtra()]);
00579 }
00580 
00581 void x86CPU::op16_cmp_rm16_r16(){
00582     eip++;
00583     ModRM16 rm(this);
00584     Sub16(rm.ReadWordr(),*regs16[rm.GetExtra()]);
00585 }
00586 
00587 void x86CPU::op16_cmp_r8_rm8(){
00588     eip++;
00589     ModRM16 rm(this);
00590     Sub8(*regs16[rm.GetExtra()],rm.ReadByter());
00591 }
00592 
00593 void x86CPU::op16_cmp_r16_rm16(){
00594     eip++;
00595     ModRM16 rm(this);
00596     Sub16(*regs16[rm.GetExtra()],rm.ReadWordr());
00597 }
00598 
00599 void x86CPU::op16_cmp_rm8_imm8(ModRM16 &rm){ //group 80 /7
00600     Sub8(rm.ReadByter(),ReadByte(cCS,eip+rm.GetLength()));
00601 }
00602 
00603 void x86CPU::op16_cmp_rm16_imm16(ModRM16 &rm){ //group 81 /7
00604     Sub16(rm.ReadWordr(),ReadWord(cCS,eip+rm.GetLength()));
00605 }
00606 
00607 void x86CPU::op16_cmp_rm16_imm8(ModRM16 &rm){ //group 83 /7
00608     Sub16(rm.ReadWordr(),SignExtend8(ReadByte(cCS,eip+rm.GetLength())));
00609 }
00610 
00611 
00612 
00613 
00614 
00615 
00616 void x86CPU::op16_add_al_imm8(){
00617     *regs8[AL]=Add8(*regs8[AL],op_cache[1]);
00618     eip++;
00619 }
00620 
00621 void x86CPU::op16_add_ax_imm8(){
00622     *regs16[AX]=Add16(*regs16[AX],*(uint16_t*)&op_cache[1]);
00623     eip++;
00624     eip++;
00625 }
00626 
00627 void x86CPU::op16_add_rm8_r8(){
00628     eip++;
00629     ModRM16 rm8(this);
00630     rm8.WriteByter(Add8(rm8.ReadByter(),*regs8[rm8.GetExtra()]));
00631 }
00632 
00633 void x86CPU::op16_add_rm16_r16(){
00634     eip++;
00635     ModRM16 rm16(this);
00636     rm16.WriteWordr(Add16(rm16.ReadWordr(),*regs16[rm16.GetExtra()]));
00637 }
00638 
00639 void x86CPU::op16_add_r8_rm8(){
00640     eip++;
00641     ModRM16 rm(this);
00642     *regs8[rm.GetExtra()]=Add8(*regs8[rm.GetExtra()],rm.ReadByter());
00643 }
00644 
00645 void x86CPU::op16_add_r16_rm16(){
00646     eip++;
00647     ModRM16 rm(this);
00648     *regs16[rm.GetExtra()]=Add16(*regs16[rm.GetExtra()],rm.ReadWordr());
00649 }
00650 
00651 void x86CPU::op16_add_rm8_imm8(ModRM16 &rm){ //Group 0x80 /0
00652     rm.WriteByter(Add8(rm.ReadWordr(),ReadByte(cCS,eip+rm.GetLength())));
00653 }
00654 
00655 void x86CPU::op16_add_rm16_imm16(ModRM16 &rm){ //Group 0x81 /0
00656     rm.WriteWordr(Add16(rm.ReadWordr(),ReadWord(cCS,eip+rm.GetLength())));
00657 }
00658 
00659 void x86CPU::op16_add_rm16_imm8(ModRM16 &rm){ //group 0x83 /0
00660     rm.WriteWordr(Add16(rm.ReadWordr(),SignExtend8(ReadByte(cCS,eip+rm.GetLength()))));
00661 }
00662 
00663 
00664 /****/
00665 void x86CPU::op16_adc_al_imm8(){
00666     *regs8[AL]=Add8(*regs8[AL],op_cache[1]+freg.cf);
00667     eip++;
00668 }
00669 
00670 void x86CPU::op16_adc_ax_imm8(){
00671     *regs16[AX]=Add16(*regs16[AX],*(uint16_t*)&op_cache[1]+freg.cf);
00672     eip++;
00673     eip++;
00674 }
00675 
00676 void x86CPU::op16_adc_rm8_r8(){
00677     eip++;
00678     ModRM16 rm8(this);
00679     rm8.WriteByter(Add8(rm8.ReadByter(),*regs8[rm8.GetExtra()]+freg.cf));
00680 }
00681 
00682 void x86CPU::op16_adc_rm16_r16(){
00683     eip++;
00684     ModRM16 rm16(this);
00685     rm16.WriteWordr(Add16(rm16.ReadWordr(),*regs16[rm16.GetExtra()]+freg.cf));
00686 }
00687 
00688 void x86CPU::op16_adc_r8_rm8(){
00689     eip++;
00690     ModRM16 rm(this);
00691     *regs8[rm.GetExtra()]=Add8(*regs8[rm.GetExtra()],rm.ReadByter()+freg.cf);
00692 }
00693 
00694 void x86CPU::op16_adc_r16_rm16(){
00695     eip++;
00696     ModRM16 rm(this);
00697     *regs16[rm.GetExtra()]=Add16(*regs16[rm.GetExtra()],rm.ReadWordr()+freg.cf);
00698 }
00699 
00700 void x86CPU::op16_adc_rm8_imm8(ModRM16 &rm){ //Group 0x80 /2
00701     rm.WriteByter(Add8(rm.ReadWordr(),ReadByte(cCS,eip+rm.GetLength())+freg.cf));
00702 }
00703 
00704 void x86CPU::op16_adc_rm16_imm16(ModRM16 &rm){ //Group 0x81 /2
00705     rm.WriteWordr(Add16(rm.ReadWordr(),ReadWord(cCS,eip+rm.GetLength())+freg.cf));
00706 }
00707 
00708 void x86CPU::op16_adc_rm16_imm8(ModRM16 &rm){ //group 0x83 /2
00709     rm.WriteWordr(Add16(rm.ReadWordr(),SignExtend8(ReadByte(cCS,eip+rm.GetLength()))+freg.cf));
00710 }
00711 
00712 
00713 
00714 void x86CPU::op16_inc_r16(){ //0x40+r
00715     freg.r0=freg.cf;
00716     *regs16[(op_cache[0]-0x40)]=Add16(*regs16[(op_cache[0]-0x40)],1);
00717     freg.cf=freg.r0;
00718 }
00719 
00720 void x86CPU::op16_inc_rm8(ModRM16 &rm){
00721     freg.r0=freg.cf; //yay for reserved flags!
00722     rm.WriteByter(Add8(rm.ReadByter(),1));
00723     freg.cf=freg.r0;
00724 }
00725 
00726 void x86CPU::op16_inc_rm16(ModRM16 &rm){
00727     freg.r0=freg.cf;
00728     rm.WriteWordr(Add16(rm.ReadWordr(),1));
00729     freg.cf=freg.r0;
00730 }
00731 
00732 void x86CPU::op16_neg_rm8(ModRM16 &rm){
00733     uint8_t tmp=rm.ReadByter();
00734     if(tmp==0xFF){
00735         freg.of=1;
00736         return;
00737     }
00738     rm.WriteByter(Sub8(0,tmp));
00739     if(tmp==0){
00740         freg.cf=0;
00741     }else{
00742         freg.cf=1;
00743     }
00744 }
00745 void x86CPU::op16_neg_rm16(ModRM16 &rm){
00746     uint16_t tmp=rm.ReadWordr();
00747     if(tmp==0xFFFF){
00748         freg.of=1;
00749         return;
00750     }
00751     rm.WriteWordr(Sub16(0,tmp));
00752     if(tmp==0){
00753         freg.cf=0;
00754     }else{
00755         freg.cf=1;
00756     }
00757 }
00758 
00759 
00760 
00761 void x86CPU::op16_div_rm8(ModRM16 &rm){
00762     if(rm.ReadByter()==0){
00763         Onx86LibError();
00764         //throw CpuInt_excp(DIV0_IEXCP);
00765     }
00766     if(((*regs16[AX])/rm.ReadByter())>0xFF){
00767         Onx86LibError();
00768         //throw CpuInt_excp(DIV0_IEXCP); 
00769     }
00770     *regs8[AL]=(*regs16[AX])/rm.ReadByter();
00771     *regs8[AH]=(*regs16[AX])%rm.ReadByter();
00772 }
00773 
00774 void x86CPU::op16_div_rm16(ModRM16 &rm){
00775     if(rm.ReadWordr()==0){
00776         Onx86LibError();
00777         //throw CpuInt_excp(DIV0_IEXCP);
00778     }
00779     if((((*regs16[DX]<<16)|(*regs16[AX]))/rm.ReadWordr())>0xFFFF){
00780         Onx86LibError();
00781         //throw CpuInt_excp(DIV0_IEXCP);
00782     }
00783     *regs8[AX]=((*regs16[DX]<<16)|(*regs16[AX]))/rm.ReadWordr();
00784     *regs8[DX]=((*regs16[DX]<<16)|(*regs16[AX]))%rm.ReadWordr();
00785 }
00786 
00787 
00788 void x86CPU::op16_idiv_rm8(ModRM16 &rm){ //This WORKS! both signed, and unsigned!
00789     //grrr...who the crap does signed division anyway!?
00790     if(rm.ReadByter()==0){
00791         Onx86LibError();
00792         //throw CpuInt_excp(DIV0_IEXCP);
00793     }
00794     uint8_t tmp=rm.ReadByter();
00795     bool store1,store2;
00796 
00797     tmp=Unsign8(tmp,store1);
00798     *regs16[AX]=Unsign16(*regs16[AX],store2);
00799     if(((*regs16[AX])/tmp)>0xFF){
00800         Onx86LibError();
00801         //throw CpuInt_excp(DIV0_IEXCP);
00802     }
00803 
00804     *regs8[AL]=(*regs16[AX])/tmp;
00805     *regs8[AH]=(*regs16[AX])%tmp;
00806 
00807     *regs8[AL]=Resign8(*regs8[AL],store1^store2);
00808 }
00809 
00810 void x86CPU::op16_idiv_rm16(ModRM16 &rm){
00811     if(rm.ReadWordr()==0){
00812         Onx86LibError();
00813         //throw CpuInt_excp(DIV0_IEXCP);
00814     }
00815     uint16_t tmp=rm.ReadWordr();
00816     bool store1,store2;
00817     tmp=Unsign16(tmp,store1);
00818     static uint32_t tmp2=Unsign32(((*regs16[DX])<<16)|(*regs16[AX]),store2);
00819 
00820     if((tmp2/tmp)>0xFFFF){
00821         Onx86LibError();
00822         //throw CpuInt_excp(DIV0_IEXCP);
00823     }
00824     *regs16[AX]=tmp2/tmp;
00825     *regs16[DX]=tmp2%tmp;
00826 
00827     *regs16[AX]=Resign16(*regs16[AX],store1^store2);
00828 }
00829 
00830 
00831 
00832 void x86CPU::op16_mul_rm8(ModRM16 &rm){
00833     *regs16[AX]=(*regs8[AL])*rm.ReadByter();
00834     if((*regs8[AH])>0){ //if tophalf of result has anything in it
00835         freg.cf=1;
00836         freg.of=1;
00837     }else{
00838         freg.cf=0;
00839         freg.of=0;
00840     }
00841 }
00842 
00843 
00844 void x86CPU::op16_mul_rm16(ModRM16 &rm){
00845     uint32_t result;
00846     result=(*regs16[AX])*rm.ReadWordr();
00847     *regs16[AX]=result&0x0000FFFF;
00848     *regs16[DX]=(result&0xFFFF0000)>>16;
00849     if((*regs16[DX])>0){ //if tophalf of result has anything in it
00850         freg.cf=1;
00851         freg.of=1;
00852     }else{
00853         freg.cf=0;
00854         freg.of=0;
00855     }
00856 }
00857 
00858 void x86CPU::op16_imul_rm8(ModRM16 &rm){
00859     bool store1,store2;
00860     *regs16[AX]=Unsign8(*regs8[AL],store1)*Unsign8(rm.ReadByter(),store2);
00861     if(*regs8[AX]>0){
00862         freg.of=1;
00863         freg.cf=1;
00864     }else{
00865         freg.of=0;
00866         freg.cf=0;
00867     }
00868     *regs16[AX]=Resign16(*regs16[AX],store1^store2);
00869 }
00870 
00871 void x86CPU::op16_imul_rm16(ModRM16 &rm){
00872     bool store1,store2;
00873     uint32_t result=Unsign16(*regs16[AX],store1)*Unsign16(rm.ReadWordr(),store2);
00874     if((result&0xFFFF0000)>0){
00875         freg.of=1;
00876         freg.cf=1;
00877     }else{
00878         freg.of=0;
00879         freg.cf=0;
00880     }
00881     result=Resign32(result,store1^store2);
00882     *regs16[DX]=(result&0xFFFF0000)>>16;
00883     *regs16[AX]=(result&0xFFFF);
00884 }
00885 
00886 
00887 
00888 void x86CPU::op16_and_rm8_r8(){
00889     eip++;
00890     ModRM16 rm(this);
00891     rm.WriteByter(And8(rm.ReadByter(),*regs8[rm.GetExtra()]));
00892 }
00893 
00894 void x86CPU::op16_and_rm16_r16(){
00895     eip++;
00896     ModRM16 rm(this);
00897     rm.WriteWordr(And16(rm.ReadWordr(),*regs16[rm.GetExtra()]));
00898 }
00899 
00900 void x86CPU::op16_and_r8_rm8(){
00901     eip++;
00902     ModRM16 rm(this);
00903     *regs8[rm.GetExtra()]=And8(*regs8[rm.GetExtra()],rm.ReadByter());
00904 }
00905 
00906 void x86CPU::op16_and_r16_rm16(){
00907     eip++;
00908     ModRM16 rm(this);
00909     *regs16[rm.GetExtra()]=And16(*regs16[rm.GetExtra()],rm.ReadWordr());
00910 }
00911 
00912 void x86CPU::op16_and_al_imm8(){
00913     eip++;
00914     *regs8[AL]=And8(*regs8[AL],op_cache[1]);
00915 }
00916 
00917 void x86CPU::op16_and_ax_imm16(){
00918     eip++;
00919     eip++;
00920     *regs16[AX]=And16(*regs16[AX],*(uint16_t*)&op_cache[1]);
00921 }
00922 
00923 void x86CPU::op16_and_rm8_imm8(ModRM16& rm){
00924     rm.WriteByter(And8(rm.ReadByter(),ReadByte(cCS,eip+rm.GetLength())));
00925 }
00926 
00927 void x86CPU::op16_and_rm16_imm16(ModRM16& rm){
00928     rm.WriteWordr(And16(rm.ReadWordr(),ReadWord(cCS,eip+rm.GetLength())));
00929 }
00930 
00931 void x86CPU::op16_and_rm16_imm8(ModRM16& rm){
00932     rm.WriteWordr(And16(rm.ReadWordr(),SignExtend8(ReadByte(cCS,eip+rm.GetLength()))));
00933     //gotta love parentheses...
00934 }
00935 
00936 void x86CPU::op16_or_rm8_r8(){
00937     eip++;
00938     ModRM16 rm(this);
00939     rm.WriteByter(Or8(rm.ReadByter(),*regs8[rm.GetExtra()]));
00940 }
00941 
00942 void x86CPU::op16_or_rm16_r16(){
00943     eip++;
00944     ModRM16 rm(this);
00945     rm.WriteWordr(Or16(rm.ReadWordr(),*regs16[rm.GetExtra()]));
00946 }
00947 
00948 void x86CPU::op16_or_r8_rm8(){
00949     eip++;
00950     ModRM16 rm(this);
00951     *regs8[rm.GetExtra()]=Or8(*regs8[rm.GetExtra()],rm.ReadByter());
00952 }
00953 
00954 void x86CPU::op16_or_r16_rm16(){
00955     eip++;
00956     ModRM16 rm(this);
00957     *regs16[rm.GetExtra()]=Or16(*regs16[rm.GetExtra()],rm.ReadWordr());
00958 }
00959 
00960 void x86CPU::op16_or_al_imm8(){
00961     eip++;
00962     *regs8[AL]=Or8(*regs8[AL],op_cache[1]);
00963 }
00964 
00965 void x86CPU::op16_or_ax_imm16(){
00966     eip++;
00967     eip++;
00968     *regs16[AX]=Or16(*regs16[AX],*(uint16_t*)&op_cache[1]);
00969 }
00970 
00971 void x86CPU::op16_or_rm8_imm8(ModRM16& rm){
00972     rm.WriteByter(Or8(rm.ReadByter(),ReadByte(cCS,eip+rm.GetLength())));
00973 }
00974 
00975 void x86CPU::op16_or_rm16_imm16(ModRM16& rm){
00976     rm.WriteWordr(Or16(rm.ReadWordr(),ReadWord(cCS,eip+rm.GetLength())));
00977 }
00978 
00979 void x86CPU::op16_or_rm16_imm8(ModRM16& rm){
00980     rm.WriteWordr(Or16(rm.ReadWordr(),SignExtend8(ReadByte(cCS,eip+rm.GetLength()))));
00981     //gotta love parentheses...
00982 }
00983 
00984 
00985 
00986 void x86CPU::op16_xor_rm8_r8(){
00987     eip++;
00988     ModRM16 rm(this);
00989     rm.WriteByter(Xor8(rm.ReadByter(),*regs8[rm.GetExtra()]));
00990 }
00991 
00992 void x86CPU::op16_xor_rm16_r16(){
00993     eip++;
00994     ModRM16 rm(this);
00995     rm.WriteWordr(Xor16(rm.ReadWordr(),*regs16[rm.GetExtra()]));
00996 }
00997 
00998 void x86CPU::op16_xor_r8_rm8(){
00999     eip++;
01000     ModRM16 rm(this);
01001     *regs8[rm.GetExtra()]=Xor8(*regs8[rm.GetExtra()],rm.ReadByter());
01002 }
01003 
01004 void x86CPU::op16_xor_r16_rm16(){
01005     eip++;
01006     ModRM16 rm(this);
01007     *regs16[rm.GetExtra()]=Xor16(*regs16[rm.GetExtra()],rm.ReadWordr());
01008 }
01009 
01010 void x86CPU::op16_xor_al_imm8(){
01011     eip++;
01012     *regs8[AL]=Xor8(*regs8[AL],op_cache[1]);
01013 }
01014 
01015 void x86CPU::op16_xor_ax_imm16(){
01016     eip++;
01017     eip++;
01018     *regs16[AX]=Xor16(*regs16[AX],*(uint16_t*)&op_cache[1]);
01019 }
01020 
01021 void x86CPU::op16_xor_rm8_imm8(ModRM16& rm){
01022     rm.WriteByter(Xor8(rm.ReadByter(),ReadByte(cCS,eip+rm.GetLength())));
01023 }
01024 
01025 void x86CPU::op16_xor_rm16_imm16(ModRM16& rm){
01026     rm.WriteWordr(Xor16(rm.ReadWordr(),ReadWord(cCS,eip+rm.GetLength())));
01027 }
01028 
01029 void x86CPU::op16_xor_rm16_imm8(ModRM16& rm){
01030     rm.WriteWordr(Xor16(rm.ReadWordr(),SignExtend8(ReadByte(cCS,eip+rm.GetLength()))));
01031     //gotta love parentheses...
01032 }
01033 
01034 void x86CPU::op16_test_rm8_r8(){
01035     eip++;
01036     ModRM16 rm(this);
01037     And8(rm.ReadByter(),*regs8[rm.GetExtra()]);
01038 }
01039 
01040 void x86CPU::op16_test_rm16_r16(){
01041     eip++;
01042     ModRM16 rm(this);
01043     And16(rm.ReadWordr(),*regs16[rm.GetExtra()]);
01044 }
01045 void x86CPU::op16_test_al_imm8(){
01046     eip++;
01047     And8(*regs8[AL],op_cache[1]);
01048 }
01049 void x86CPU::op16_test_ax_imm16(){
01050     eip++;
01051     eip++;
01052     And16(*regs16[AX],*(uint16_t*)&op_cache[1]);
01053 }
01054 
01055 void x86CPU::op16_test_rm8_imm8(ModRM16& rm){
01056     And8(rm.ReadByter(),ReadByte(cCS,eip+rm.GetLength()));
01057 }
01058 
01059 void x86CPU::op16_test_rm16_imm16(ModRM16& rm){
01060     And16(rm.ReadWordr(),ReadWord(cCS,eip+rm.GetLength()));
01061 }
01062 
01063 void x86CPU::op16_test_rm16_imm8(ModRM16& rm){
01064     And16(rm.ReadWordr(),SignExtend8(ReadByte(cCS,eip+rm.GetLength())));
01065     //gotta love parentheses...
01066 }
01067 
01068 
01069 void x86CPU::op16_shr_rm8_cl(ModRM16 &rm){
01070     rm.WriteByter(ShiftLogicalRight8(rm.ReadByter(),*regs8[CL]));
01071 }
01072 void x86CPU::op16_shr_rm16_cl(ModRM16 &rm){
01073     rm.WriteWordr(ShiftLogicalRight16(rm.ReadWordr(),*regs8[CL]));
01074 }
01075 
01076 void x86CPU::op16_shl_rm8_cl(ModRM16 &rm){
01077     rm.WriteByter(ShiftLogicalLeft8(rm.ReadByter(),*regs8[CL]));
01078 }
01079 void x86CPU::op16_shl_rm16_cl(ModRM16 &rm){
01080     rm.WriteWordr(ShiftLogicalLeft16(rm.ReadWordr(),*regs8[CL]));
01081 }
01082 
01083 void x86CPU::op16_sar_rm8_cl(ModRM16 &rm){
01084     rm.WriteByter(ShiftArithmeticRight8(rm.ReadByter(),*regs8[CL]));
01085 }
01086 void x86CPU::op16_sar_rm16_cl(ModRM16 &rm){
01087     rm.WriteWordr(ShiftArithmeticRight16(rm.ReadWordr(),*regs8[CL]));
01088 }
01089 
01090 void x86CPU::op16_rol_rm8_cl(ModRM16 &rm){
01091     rm.WriteByter(RotateLeft8(rm.ReadByter(),*regs8[CL]));
01092 }
01093 void x86CPU::op16_rol_rm16_cl(ModRM16 &rm){
01094     rm.WriteWordr(RotateLeft16(rm.ReadWordr(),*regs8[CL]));
01095 }
01096 
01097 void x86CPU::op16_ror_rm8_cl(ModRM16 &rm){
01098     rm.WriteByter(RotateRight8(rm.ReadByter(),*regs8[CL]));
01099 }
01100 void x86CPU::op16_ror_rm16_cl(ModRM16 &rm){
01101     rm.WriteWordr(RotateRight16(rm.ReadWordr(),*regs8[CL]));
01102 }
01103 
01104 
01105 void x86CPU::op16_rcl_rm8_cl(ModRM16 &rm){
01106     rm.WriteByter(RotateCarryLeft8(rm.ReadByter(),*regs8[CL]));
01107 }
01108 void x86CPU::op16_rcl_rm16_cl(ModRM16 &rm){
01109     rm.WriteWordr(RotateCarryLeft16(rm.ReadWordr(),*regs8[CL]));
01110 }
01111 
01112 void x86CPU::op16_rcr_rm8_cl(ModRM16 &rm){
01113     rm.WriteByter(RotateCarryRight8(rm.ReadByter(),*regs8[CL]));
01114 }
01115 void x86CPU::op16_rcr_rm16_cl(ModRM16 &rm){
01116     rm.WriteWordr(RotateCarryRight16(rm.ReadWordr(),*regs8[CL]));
01117 }
01118 
01119 
01120 /****/
01121 void x86CPU::op16_shr_rm8_1(ModRM16 &rm){
01122     rm.WriteByter(ShiftLogicalRight8(rm.ReadByter(),1));
01123 }
01124 void x86CPU::op16_shr_rm16_1(ModRM16 &rm){
01125     rm.WriteWordr(ShiftLogicalRight16(rm.ReadWordr(),1));
01126 }
01127 
01128 void x86CPU::op16_shl_rm8_1(ModRM16 &rm){
01129     rm.WriteByter(ShiftLogicalLeft8(rm.ReadByter(),1));
01130 }
01131 void x86CPU::op16_shl_rm16_1(ModRM16 &rm){
01132     rm.WriteWordr(ShiftLogicalLeft16(rm.ReadWordr(),1));
01133 }
01134 
01135 void x86CPU::op16_sar_rm8_1(ModRM16 &rm){
01136     rm.WriteByter(ShiftArithmeticRight8(rm.ReadByter(),1));
01137 }
01138 void x86CPU::op16_sar_rm16_1(ModRM16 &rm){
01139     rm.WriteWordr(ShiftArithmeticRight16(rm.ReadWordr(),1));
01140 }
01141 
01142 void x86CPU::op16_rol_rm8_1(ModRM16 &rm){
01143     rm.WriteByter(RotateLeft8(rm.ReadByter(),1));
01144 }
01145 void x86CPU::op16_rol_rm16_1(ModRM16 &rm){
01146     rm.WriteWordr(RotateLeft16(rm.ReadWordr(),1));
01147 }
01148 
01149 void x86CPU::op16_ror_rm8_1(ModRM16 &rm){
01150     rm.WriteByter(RotateRight8(rm.ReadByter(),1));
01151 }
01152 void x86CPU::op16_ror_rm16_1(ModRM16 &rm){
01153     rm.WriteWordr(RotateRight16(rm.ReadWordr(),1));
01154 }
01155 
01156 
01157 void x86CPU::op16_rcl_rm8_1(ModRM16 &rm){
01158     rm.WriteByter(RotateCarryLeft8(rm.ReadByter(),1));
01159 }
01160 void x86CPU::op16_rcl_rm16_1(ModRM16 &rm){
01161     rm.WriteWordr(RotateCarryLeft16(rm.ReadWordr(),1));
01162 }
01163 
01164 void x86CPU::op16_rcr_rm8_1(ModRM16 &rm){
01165     rm.WriteByter(RotateCarryRight8(rm.ReadByter(),1));
01166 }
01167 void x86CPU::op16_rcr_rm16_1(ModRM16 &rm){
01168     rm.WriteWordr(RotateCarryRight16(rm.ReadWordr(),1));
01169 }
01170 
01171 void x86CPU::op16_not_rm8(ModRM16 &rm){
01172     rm.WriteByter(~(rm.ReadByter()));
01173 }
01174 
01175 void x86CPU::op16_not_rm16(ModRM16 &rm){
01176     rm.WriteWordr(~(rm.ReadWordr()));
01177 }
01178 
01179 
01180 
01181 
01182 /**
01183 BCD Opcodes for Open86
01184 By: Alboin, 3-16-07
01185 Modified to work with x86Lib by Jordan(hckr83)
01186 **/
01187 
01188 
01189 /* Opcode: 0x37 */
01190 void x86CPU::op16_aaa() {
01191     if((*regs8[AL] & 0x0f) > 9 || freg.af == 1) {
01192         *regs8[AL] += 6;
01193         *regs8[AH]++;
01194         freg.af = 1;
01195         freg.cf = 1;
01196     }
01197     else {
01198         freg.af = 0;
01199         freg.cf = 0;
01200     }
01201     *regs8[AL] = *regs8[AL] & 0x0f;
01202 }
01203 
01204 
01205 /* Opcode: 0x27 */
01206 void x86CPU::op16_daa() {
01207     if((*regs8[AL] & 0x0f) > 9 || freg.af == 1) {
01208         *regs8[AL] += 6;
01209         *regs8[AH]++;
01210     }
01211     else
01212         freg.af = 0;
01213 
01214     if(*regs8[AL] > 0x9f || freg.cf == 1) {
01215             *regs8[AL] = *regs8[AL] + 0x60;
01216             freg.cf = 1;
01217     }
01218     else
01219         freg.cf = 0;
01220 }
01221 
01222 /* Opcode: 0x2F */
01223 void x86CPU::op16_das() {
01224     if((*regs8[AL] & 0x0f) > 9 || freg.af == 1) {
01225         *regs8[AL] -= 6;
01226         freg.af = 1;
01227     }
01228     else
01229         freg.af = 0;
01230 
01231     if(*regs8[AL] > 0x9f || freg.cf == 1) {
01232             *regs8[AL] -= 0x60;
01233             freg.cf = 1;
01234     }
01235     else
01236         freg.cf = 0;
01237 }
01238 
01239 /* Opcode: 0x3F */
01240 void x86CPU::op16_aas() {
01241     if((*regs8[AL] & 0x0f) > 9 || freg.af == 1) {
01242         *regs8[AL] -= 6;
01243         *regs8[AH]--;
01244         freg.af = 1;
01245         freg.cf = 1;
01246     }
01247     else {
01248         freg.af = 0;
01249         freg.cf = 0;
01250     }
01251     *regs8[AL] = *regs8[AL] & 0x0f;
01252 }
01253 
01254 
01255 
01256 void x86CPU::op16_aad(){
01257     //AAD is a weird opcode because it is two bytes
01258     //for "apparently" no reason. But really, it is just
01259     //undocumented... the 0x0A in the second byte is for
01260     //multiplecation...but it can be changed...
01261     *regs8[AL]=(*regs8[AH])*(op_cache[1])+*regs8[AL];
01262     *regs8[AH]=0;
01263 }
01264 
01265 void x86CPU::op16_aam(){
01266     //same wiht the 0x0A operand as above..
01267     if(op_cache[1]==0){
01268         Onx86LibError();
01269         //throw CpuInt_excp(DIV0_IEXCP);
01270     }
01271     *regs8[AH]=(*regs8[AL])/op_cache[1];
01272     *regs8[AL]=(*regs8[AL])%op_cache[1];
01273 }
01274 
01275 
01276 
01277 
01278 
01279 
01280 
01281 
01282 
01283 
01284 };
01285 
01286 
01287