DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/cpu/core_full/load.h
00001 /*
00002  *  Copyright (C) 2002-2019  The DOSBox Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA.
00017  */
00018 
00019 switch (inst.code.load) {
00020 /* General loading */
00021         case L_POPwRM:
00022                 inst_op1_w = Pop_16();
00023                 goto case_L_MODRM;
00024         case L_POPdRM:
00025                 inst_op1_d = Pop_32();
00026                 goto case_L_MODRM;
00027         case L_MODRM_NVM:
00028                 if ((reg_flags & FLAG_VM) || !cpu.pmode) goto illegalopcode;
00029                 goto case_L_MODRM;
00030 case_L_MODRM:
00031         case L_MODRM:
00032                 inst.rm=Fetchb();
00033                 inst.rm_index=(inst.rm >> 3) & 7;
00034                 inst.rm_eai=inst.rm&07;
00035                 inst.rm_mod=inst.rm>>6;
00036                 /* Decode address of mod/rm if needed */
00037                 if (inst.rm<0xc0) {
00038                         if (!(inst.prefix & PREFIX_ADDR))
00039                         #include "ea_lookup.h"
00040                 }
00041 l_MODRMswitch:
00042                 switch (inst.code.extra) {      
00043 /* Byte */
00044                 case M_Ib:
00045                         inst_op1_d=Fetchb();
00046                         break;
00047                 case M_Ebx:
00048                         if (inst.rm<0xc0) inst_op1_ds=(Bit8s)LoadMb(inst.rm_eaa);
00049                         else inst_op1_ds=(Bit8s)reg_8(inst.rm_eai);
00050                         break;
00051                 case M_EbIb:
00052                         inst_op2_d=Fetchb();
00053                 case M_Eb:
00054                         if (inst.rm<0xc0) inst_op1_d=LoadMb(inst.rm_eaa);
00055                         else inst_op1_d=reg_8(inst.rm_eai);
00056                         break;
00057                 case M_EbGb:
00058                         if (inst.rm<0xc0) inst_op1_d=LoadMb(inst.rm_eaa);
00059                         else inst_op1_d=reg_8(inst.rm_eai);
00060                         inst_op2_d=reg_8(inst.rm_index);
00061                         break;
00062                 case M_GbEb:
00063                         if (inst.rm<0xc0) inst_op2_d=LoadMb(inst.rm_eaa);
00064                         else inst_op2_d=reg_8(inst.rm_eai);
00065                 case M_Gb:
00066                         inst_op1_d=reg_8(inst.rm_index);;
00067                         break;
00068 /* Word */
00069                 case M_Iw:
00070                         inst_op1_d=Fetchw();
00071                         break;
00072                 case M_EwxGwx:
00073                         inst_op2_ds=(Bit16s)reg_16(inst.rm_index);
00074                         goto l_M_Ewx;
00075                 case M_EwxIbx:
00076                         inst_op2_ds=Fetchbs();
00077                         goto l_M_Ewx;
00078                 case M_EwxIwx:
00079                         inst_op2_ds=Fetchws();
00080 l_M_Ewx:                
00081                 case M_Ewx:
00082                         if (inst.rm<0xc0) inst_op1_ds=(Bit16s)LoadMw(inst.rm_eaa);
00083                         else inst_op1_ds=(Bit16s)reg_16(inst.rm_eai);
00084                         break;
00085                 case M_EwIb:
00086                         inst_op2_d=Fetchb();
00087                         goto l_M_Ew;
00088                 case M_EwIbx:
00089                         inst_op2_ds=Fetchbs();
00090                         goto l_M_Ew;            
00091                 case M_EwIw:
00092                         inst_op2_d=Fetchw();
00093                         goto l_M_Ew;
00094                 case M_EwGwCL:
00095                         inst_imm_d=reg_cl;
00096                         goto l_M_EwGw;
00097                 case M_EwGwIb:
00098                         inst_imm_d=Fetchb();
00099                         goto l_M_EwGw;
00100                 case M_EwGwt:
00101                         inst_op2_d=reg_16(inst.rm_index);
00102                         inst.rm_eaa+=(Bitu)(((Bit16s)inst_op2_d >> 4) * 2);
00103                         goto l_M_Ew;
00104 l_M_EwGw:                       
00105                 case M_EwGw:
00106                         inst_op2_d=reg_16(inst.rm_index);
00107 l_M_Ew:
00108                 case M_Ew:
00109                         if (inst.rm<0xc0) inst_op1_d=LoadMw(inst.rm_eaa);
00110                         else inst_op1_d=reg_16(inst.rm_eai);
00111                         break;
00112                 case M_GwEw:
00113                         if (inst.rm<0xc0) inst_op2_d=LoadMw(inst.rm_eaa);
00114                         else inst_op2_d=reg_16(inst.rm_eai);
00115                 case M_Gw:
00116                         inst_op1_d=reg_16(inst.rm_index);;
00117                         break;
00118 /* DWord */
00119                 case M_Id:
00120                         inst_op1_d=Fetchd();
00121                         break;
00122                 case M_EdxGdx:
00123                         inst_op2_ds=(Bit32s)reg_32(inst.rm_index);
00124                 case M_Edx:
00125                         if (inst.rm<0xc0) inst_op1_d=(Bit32u)((Bit32s)LoadMd(inst.rm_eaa));
00126                         else inst_op1_d=(Bit32u)((Bit32s)reg_32(inst.rm_eai));
00127                         break;
00128                 case M_EdIb:
00129                         inst_op2_d=Fetchb();
00130                         goto l_M_Ed;
00131                 case M_EdIbx:
00132                         inst_op2_ds=Fetchbs();
00133                         goto l_M_Ed;
00134                 case M_EdId:
00135                         inst_op2_d=Fetchd();
00136                         goto l_M_Ed;                    
00137                 case M_EdGdCL:
00138                         inst_imm_d=reg_cl;
00139                         goto l_M_EdGd;
00140                 case M_EdGdt:
00141                         inst_op2_d=reg_32(inst.rm_index);
00142                         inst.rm_eaa+=(Bit32u)(((Bit32s)inst_op2_d >> 5) * 4);
00143                         goto l_M_Ed;
00144                 case M_EdGdIb:
00145                         inst_imm_d=Fetchb();
00146                         goto l_M_EdGd;
00147 l_M_EdGd:
00148                 case M_EdGd:
00149                         inst_op2_d=reg_32(inst.rm_index);
00150 l_M_Ed:
00151                 case M_Ed:
00152                         if (inst.rm<0xc0) inst_op1_d=LoadMd(inst.rm_eaa);
00153                         else inst_op1_d=reg_32(inst.rm_eai);
00154                         break;
00155                 case M_GdEd:
00156                         if (inst.rm<0xc0) inst_op2_d=LoadMd(inst.rm_eaa);
00157                         else inst_op2_d=reg_32(inst.rm_eai);
00158                 case M_Gd:
00159                         inst_op1_d=reg_32(inst.rm_index);
00160                         break;
00161 /* Others */            
00162 
00163                 case M_SEG:
00164                         //TODO Check for limit
00165                         inst_op1_d=SegValue((SegNames)inst.rm_index);
00166                         break;
00167                 case M_Efw:
00168                         if (inst.rm>=0xc0) goto illegalopcode;
00169                         inst_op1_d=LoadMw(inst.rm_eaa);
00170                         inst_op2_d=LoadMw(inst.rm_eaa+2);
00171                         break;
00172                 case M_Efd:
00173                         if (inst.rm>=0xc0) goto illegalopcode;
00174                         inst_op1_d=LoadMd(inst.rm_eaa);
00175                         inst_op2_d=LoadMw(inst.rm_eaa+4);
00176                         break;
00177                 case M_EA:
00178                         inst_op1_d=inst.rm_off;
00179                         break;
00180                 case M_POPw:
00181                         inst_op1_d = Pop_16();
00182                         break;
00183                 case M_POPd:
00184                         inst_op1_d = Pop_32();
00185                         break;
00186                 case M_GRP:
00187                         inst.code=Groups[inst.code.op][inst.rm_index];
00188                         goto l_MODRMswitch;
00189                 case M_SHIFT_Ib:
00190                         inst_op2_d = Fetchb() & 0x1f;
00191                         if (!inst_op2_d)
00192                                 break;
00193                         inst.code=Groups[inst.code.op][inst.rm_index];
00194                         goto l_MODRMswitch;
00195                 case M_SHIFT_CL:
00196                         inst_op2_d = reg_cl & 0x1f;
00197                         if (!inst_op2_d)
00198                                 break;
00199                         inst.code=Groups[inst.code.op][inst.rm_index];
00200                         goto l_MODRMswitch;
00201                 case M_SHIFT_1:
00202                         inst_op2_d=1;
00203                         inst.code=Groups[inst.code.op][inst.rm_index];
00204                         goto l_MODRMswitch;
00205                 case 0:
00206                         break;
00207                 default:
00208                         LOG(LOG_CPU,LOG_ERROR)("MODRM:Unhandled load %d entry %lx",inst.code.extra,(unsigned long)inst.entry);
00209                         break;
00210                 }
00211                 break;
00212         case L_POPw:
00213                 inst_op1_d = Pop_16();
00214                 break;
00215         case L_POPd:
00216                 inst_op1_d = Pop_32();
00217                 break;
00218         case L_POPfw:
00219                 inst_op1_d = Pop_16();
00220                 inst_op2_d = Pop_16();
00221                 break;
00222         case L_POPfd:
00223                 inst_op1_d = Pop_32();
00224                 inst_op2_d = Pop_16();
00225                 break;
00226         case L_Ib:
00227                 inst_op1_d=Fetchb();
00228                 break;
00229         case L_Ibx:
00230                 inst_op1_ds=Fetchbs();
00231                 break;
00232         case L_Iw:
00233                 inst_op1_d=Fetchw();
00234                 break;
00235         case L_Iwx:
00236                 inst_op1_ds=Fetchws();
00237                 break;
00238         case L_Idx:
00239         case L_Id:
00240                 inst_op1_d=Fetchd();
00241                 break;
00242         case L_Ifw:
00243                 inst_op1_d=Fetchw();
00244                 inst_op2_d=Fetchw();
00245                 break;
00246         case L_Ifd:
00247                 inst_op1_d=Fetchd();
00248                 inst_op2_d=Fetchw();
00249                 break;
00250 /* Direct load of registers */
00251         case L_REGbIb:
00252                 inst_op2_d=Fetchb();
00253         case L_REGb:
00254                 inst_op1_d=reg_8(inst.code.extra);
00255                 break;
00256         case L_REGwIw:
00257                 inst_op2_d=Fetchw();
00258         case L_REGw:
00259                 inst_op1_d=reg_16(inst.code.extra);
00260                 break;
00261         case L_REGdId:
00262                 inst_op2_d=Fetchd();
00263         case L_REGd:
00264                 inst_op1_d=reg_32(inst.code.extra);
00265                 break;
00266         case L_SEG:
00267                 inst_op1_d=SegValue((SegNames)inst.code.extra);
00268                 break;
00269 /* Depending on addressize */
00270         case L_OP:
00271                 if (inst.prefix & PREFIX_ADDR) {
00272                         inst.rm_eaa=Fetchd();
00273                 } else {
00274                         inst.rm_eaa=Fetchw();
00275                 }
00276                 if (inst.prefix & PREFIX_SEG) {
00277                         inst.rm_eaa+=inst.seg.base;
00278                 } else {
00279                         inst.rm_eaa+=SegBase(ds);
00280                 }
00281                 break;
00282         /* Special cases */
00283         case L_DOUBLE:
00284                 inst.entry|=0x100;
00285                 goto restartopcode;
00286         case L_PRESEG:
00287                 inst.prefix|=PREFIX_SEG;
00288                 inst.seg.base=SegBase((SegNames)inst.code.extra);
00289                 goto restartopcode;
00290         case L_PREREPNE:
00291                 inst.prefix|=PREFIX_REP;
00292                 inst.repz=false;
00293                 goto restartopcode;
00294         case L_PREREP:
00295                 inst.prefix|=PREFIX_REP;
00296                 inst.repz=true;
00297                 goto restartopcode;
00298         case L_PREOP:
00299                 inst.entry=(cpu.code.big ^ 1u) * 0x200u;
00300                 goto restartopcode;
00301         case L_PREADD:
00302                 inst.prefix=(inst.prefix & ~1u) | (cpu.code.big ^ 1u);
00303                 goto restartopcode;
00304         case L_VAL:
00305                 inst_op1_d=inst.code.extra;
00306                 break;
00307         case L_INTO:
00308                 if (!get_OF()) goto nextopcode;
00309                 inst_op1_d=4;
00310                 break;
00311         case D_IRETw:
00312                 CPU_IRET(false,GetIP());
00313                 if (GETFLAG(IF) && PIC_IRQCheck) {
00314                         return CBRET_NONE;
00315                 }
00316                 continue;
00317         case D_IRETd:
00318                 CPU_IRET(true,GetIP());
00319                 if (GETFLAG(IF) && PIC_IRQCheck) 
00320                         return CBRET_NONE;
00321                 continue;
00322         case D_RETFwIw:
00323                 {
00324                         Bitu words=Fetchw();
00325                         FillFlags();    
00326                         CPU_RET(false,words,GetIP());
00327                         continue;
00328                 }
00329         case D_RETFw:
00330                 FillFlags();
00331                 CPU_RET(false,0,GetIP());
00332                 continue;
00333         case D_RETFdIw:
00334                 {
00335                         Bitu words=Fetchw();
00336                         FillFlags();    
00337                         CPU_RET(true,words,GetIP());
00338                         continue;
00339                 }
00340         case D_RETFd:
00341                 FillFlags();
00342                 CPU_RET(true,0,GetIP());
00343                 continue;
00344 /* Direct operations */
00345         case L_STRING:
00346                 #include "string.h"
00347                 goto nextopcode;
00348         case D_PUSHAw:
00349                 if (CPU_ArchitectureType<CPU_ARCHTYPE_80186) goto illegalopcode;
00350                 {
00351                         Bit32u old_esp = reg_esp;
00352                         try {
00353                                 Bit16u old_sp = (CPU_ArchitectureType >= CPU_ARCHTYPE_286 ? reg_sp : (reg_sp-10));
00354                                 Push_16(reg_ax);Push_16(reg_cx);Push_16(reg_dx);Push_16(reg_bx);
00355                                 Push_16(old_sp);Push_16(reg_bp);Push_16(reg_si);Push_16(reg_di);
00356                         }
00357                         catch (GuestPageFaultException &pf) {
00358                                 (void)pf;
00359                                 LOG_MSG("PUSHA interrupted by page fault");
00360                                 reg_esp = old_esp;
00361                                 throw;
00362                         }
00363                 } goto nextopcode;
00364         case D_PUSHAd:
00365                 {
00366                         Bit32u old_esp = reg_esp;
00367                         try {
00368                                 Bit32u tmpesp = reg_esp;
00369                                 Push_32(reg_eax);Push_32(reg_ecx);Push_32(reg_edx);Push_32(reg_ebx);
00370                                 Push_32(tmpesp);Push_32(reg_ebp);Push_32(reg_esi);Push_32(reg_edi);
00371                         }
00372                         catch (GuestPageFaultException &pf) {
00373                                 (void)pf;
00374                                 LOG_MSG("PUSHAD interrupted by page fault");
00375                                 reg_esp = old_esp;
00376                                 throw;
00377                         }
00378                 } goto nextopcode;
00379         case D_POPAw:
00380                 if (CPU_ArchitectureType<CPU_ARCHTYPE_80186) goto illegalopcode;
00381                 {
00382                         Bit32u old_esp = reg_esp;
00383                         try {
00384                                 reg_di=Pop_16();reg_si=Pop_16();reg_bp=Pop_16();Pop_16();//Don't save SP
00385                                 reg_bx=Pop_16();reg_dx=Pop_16();reg_cx=Pop_16();reg_ax=Pop_16();
00386                         }
00387                         catch (GuestPageFaultException &pf) {
00388                                 (void)pf;
00389                                 LOG_MSG("POPA interrupted by page fault");
00390                                 reg_esp = old_esp;
00391                                 throw;
00392                         }
00393                 } goto nextopcode;
00394         case D_POPAd:
00395                 {
00396                         Bit32u old_esp = reg_esp;
00397                         try {
00398                                 reg_edi=Pop_32();reg_esi=Pop_32();reg_ebp=Pop_32();Pop_32();//Don't save ESP
00399                                 reg_ebx=Pop_32();reg_edx=Pop_32();reg_ecx=Pop_32();reg_eax=Pop_32();
00400                         }
00401                         catch (GuestPageFaultException &pf) {
00402                                 (void)pf;
00403                                 LOG_MSG("POPAD interrupted by page fault");
00404                                 reg_esp = old_esp;
00405                                 throw;
00406                         }
00407                 } goto nextopcode;
00408         case D_POPSEGw:
00409                 if (CPU_PopSeg((SegNames)inst.code.extra,false)) RunException();
00410                 goto nextopcode;
00411         case D_POPSEGd:
00412                 if (CPU_PopSeg((SegNames)inst.code.extra,true)) RunException();
00413                 goto nextopcode;
00414         case D_SETALC:
00415                 reg_al = get_CF() ? 0xFF : 0;
00416                 goto nextopcode;
00417         case D_XLAT:
00418                 if (inst.prefix & PREFIX_SEG) {
00419                         if (inst.prefix & PREFIX_ADDR) {
00420                                 reg_al=LoadMb(inst.seg.base+(Bit32u)(reg_ebx+reg_al));
00421                         } else {
00422                                 reg_al=LoadMb(inst.seg.base+(Bit16u)(reg_bx+reg_al));
00423                         }
00424                 } else {
00425                         if (inst.prefix & PREFIX_ADDR) {
00426                                 reg_al=LoadMb(SegBase(ds)+(Bit32u)(reg_ebx+reg_al));
00427                         } else {
00428                                 reg_al=LoadMb(SegBase(ds)+(Bit16u)(reg_bx+reg_al));
00429                         }
00430                 }
00431                 goto nextopcode;
00432         case D_CBW:
00433                 reg_ax=(Bit16u)((Bit8s)reg_al);
00434                 goto nextopcode;
00435         case D_CWDE:
00436                 reg_eax=(Bit32u)((Bit16s)reg_ax);
00437                 goto nextopcode;
00438         case D_CWD:
00439                 if (reg_ax & 0x8000) reg_dx=0xffff;
00440                 else reg_dx=0;
00441                 goto nextopcode;
00442         case D_CDQ:
00443                 if (reg_eax & 0x80000000) reg_edx=0xffffffff;
00444                 else reg_edx=0;
00445                 goto nextopcode;
00446         case D_CLI:
00447                 if (CPU_CLI()) RunException();
00448                 goto nextopcode;
00449         case D_STI:
00450                 if (CPU_STI()) RunException();
00451                 goto nextopcode;
00452         case D_STC:
00453                 FillFlags();SETFLAGBIT(CF,true);
00454                 goto nextopcode;
00455         case D_CLC:
00456                 FillFlags();SETFLAGBIT(CF,false);
00457                 goto nextopcode;
00458         case D_CMC:
00459                 FillFlags();
00460                 SETFLAGBIT(CF,!(reg_flags & FLAG_CF));
00461                 goto nextopcode;
00462         case D_CLD:
00463                 SETFLAGBIT(DF,false);
00464                 cpu.direction=1;
00465                 goto nextopcode;
00466         case D_STD:
00467                 SETFLAGBIT(DF,true);
00468                 cpu.direction=-1;
00469                 goto nextopcode;
00470         case D_PUSHF:
00471                 if (CPU_PUSHF(inst.code.extra)) RunException();
00472                 goto nextopcode;
00473         case D_POPF:
00474                 if (CPU_POPF(inst.code.extra)) RunException();
00475                 if (GETFLAG(IF) && PIC_IRQCheck) {
00476                         SaveIP();
00477                         return CBRET_NONE;
00478                 }
00479                 goto nextopcode;
00480         case D_SAHF:
00481                 SETFLAGSb(reg_ah);
00482                 goto nextopcode;
00483         case D_LAHF:
00484                 FillFlags();
00485                 reg_ah=reg_flags&0xff;
00486                 goto nextopcode;
00487         case D_WAIT:
00488         case D_NOP:
00489                 goto nextopcode;
00490         case D_LOCK: /* FIXME: according to intel, LOCK should raise an exception if it's not followed by one of a small set of instructions;
00491                         probably doesn't matter for our purposes as it is a pentium prefix anyhow */
00492 // todo: make an option to show this
00493 //              LOG(LOG_CPU,LOG_NORMAL)("CPU:LOCK");
00494                 goto nextopcode;
00495         case D_ENTERw:
00496                 {
00497                         Bitu bytes=Fetchw();
00498                         Bitu level=Fetchb();
00499                         CPU_ENTER(false,bytes,level);
00500                         goto nextopcode;
00501                 }
00502         case D_ENTERd:
00503                 {
00504                         Bitu bytes=Fetchw();
00505                         Bitu level=Fetchb();
00506                         CPU_ENTER(true,bytes,level);
00507                         goto nextopcode;
00508                 }
00509         case D_LEAVEw:
00510                 {
00511                         Bit32u old_esp = reg_esp;
00512 
00513                         reg_esp &= cpu.stack.notmask;
00514                         reg_esp |= reg_ebp&cpu.stack.mask;
00515                         try {
00516                                 reg_bp = Pop_16();
00517                         }
00518                         catch (GuestPageFaultException &pf) {
00519                                 (void)pf;
00520                                 reg_esp = old_esp;
00521                                 throw;
00522                         }
00523                 } goto nextopcode;
00524         case D_LEAVEd:
00525                 {
00526                         Bit32u old_esp = reg_esp;
00527 
00528                         reg_esp &= cpu.stack.notmask;
00529                         reg_esp |= reg_ebp&cpu.stack.mask;
00530                         try {
00531                                 reg_ebp = Pop_32();
00532                         }
00533                         catch (GuestPageFaultException &pf) {
00534                                 (void)pf;
00535                                 reg_esp = old_esp;
00536                                 throw;
00537                         }
00538                 } goto nextopcode;
00539         case D_DAA:
00540                 DAA();
00541                 goto nextopcode;
00542         case D_DAS:
00543                 DAS();
00544                 goto nextopcode;
00545         case D_AAA:
00546                 AAA();
00547                 goto nextopcode;
00548         case D_AAS:
00549                 AAS();
00550                 goto nextopcode;
00551         case D_CPUID:
00552                 if (!CPU_CPUID()) goto illegalopcode;
00553                 goto nextopcode;
00554         case D_HLT:
00555                 if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP);
00556                 FillFlags();
00557                 CPU_HLT(GetIP());
00558                 return CBRET_NONE;
00559         case D_CLTS:
00560                 if (cpu.pmode && cpu.cpl) goto illegalopcode;
00561                 cpu.cr0&=(~CR0_TASKSWITCH);
00562                 goto nextopcode;
00563         case D_ICEBP:
00564                 CPU_SW_Interrupt_NoIOPLCheck(1,GetIP());
00565                 continue;
00566         case D_RDTSC: {
00567                 if (CPU_ArchitectureType<CPU_ARCHTYPE_PENTIUM) goto illegalopcode;
00568                 Bit64s tsc=(Bit64s)(PIC_FullIndex()*(double)(CPU_CycleAutoAdjust?70000:CPU_CycleMax));
00569                 reg_edx=(Bit32u)(tsc>>32);
00570                 reg_eax=(Bit32u)(tsc&0xffffffff);
00571                 break;
00572                 }
00573         default:
00574                 LOG(LOG_CPU,LOG_ERROR)("LOAD:Unhandled code %d opcode %lx",inst.code.load,(unsigned long)inst.entry);
00575                 goto illegalopcode;
00576 }
00577