DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/cpu/core_full/load.h
00001 /*
00002  *  Copyright (C) 2002-2015  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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_GRP_Ib:
00190                         inst_op2_d=Fetchb();
00191                         inst.code=Groups[inst.code.op][inst.rm_index];
00192                         goto l_MODRMswitch;
00193                 case M_GRP_CL:
00194                         inst_op2_d=reg_cl;
00195                         inst.code=Groups[inst.code.op][inst.rm_index];
00196                         goto l_MODRMswitch;
00197                 case M_GRP_1:
00198                         inst_op2_d=1;
00199                         inst.code=Groups[inst.code.op][inst.rm_index];
00200                         goto l_MODRMswitch;
00201                 case 0:
00202                         break;
00203                 default:
00204                         LOG(LOG_CPU,LOG_ERROR)("MODRM:Unhandled load %d entry %lx",inst.code.extra,(unsigned long)inst.entry);
00205                         break;
00206                 }
00207                 break;
00208         case L_POPw:
00209                 inst_op1_d = Pop_16();
00210                 break;
00211         case L_POPd:
00212                 inst_op1_d = Pop_32();
00213                 break;
00214         case L_POPfw:
00215                 inst_op1_d = Pop_16();
00216                 inst_op2_d = Pop_16();
00217                 break;
00218         case L_POPfd:
00219                 inst_op1_d = Pop_32();
00220                 inst_op2_d = Pop_16();
00221                 break;
00222         case L_Ib:
00223                 inst_op1_d=Fetchb();
00224                 break;
00225         case L_Ibx:
00226                 inst_op1_ds=Fetchbs();
00227                 break;
00228         case L_Iw:
00229                 inst_op1_d=Fetchw();
00230                 break;
00231         case L_Iwx:
00232                 inst_op1_ds=Fetchws();
00233                 break;
00234         case L_Idx:
00235         case L_Id:
00236                 inst_op1_d=Fetchd();
00237                 break;
00238         case L_Ifw:
00239                 inst_op1_d=Fetchw();
00240                 inst_op2_d=Fetchw();
00241                 break;
00242         case L_Ifd:
00243                 inst_op1_d=Fetchd();
00244                 inst_op2_d=Fetchw();
00245                 break;
00246 /* Direct load of registers */
00247         case L_REGbIb:
00248                 inst_op2_d=Fetchb();
00249         case L_REGb:
00250                 inst_op1_d=reg_8(inst.code.extra);
00251                 break;
00252         case L_REGwIw:
00253                 inst_op2_d=Fetchw();
00254         case L_REGw:
00255                 inst_op1_d=reg_16(inst.code.extra);
00256                 break;
00257         case L_REGdId:
00258                 inst_op2_d=Fetchd();
00259         case L_REGd:
00260                 inst_op1_d=reg_32(inst.code.extra);
00261                 break;
00262         case L_SEG:
00263                 inst_op1_d=SegValue((SegNames)inst.code.extra);
00264                 break;
00265 /* Depending on addressize */
00266         case L_OP:
00267                 if (inst.prefix & PREFIX_ADDR) {
00268                         inst.rm_eaa=Fetchd();
00269                 } else {
00270                         inst.rm_eaa=Fetchw();
00271                 }
00272                 if (inst.prefix & PREFIX_SEG) {
00273                         inst.rm_eaa+=inst.seg.base;
00274                 } else {
00275                         inst.rm_eaa+=SegBase(ds);
00276                 }
00277                 break;
00278         /* Special cases */
00279         case L_DOUBLE:
00280                 inst.entry|=0x100;
00281                 goto restartopcode;
00282         case L_PRESEG:
00283                 inst.prefix|=PREFIX_SEG;
00284                 inst.seg.base=SegBase((SegNames)inst.code.extra);
00285                 goto restartopcode;
00286         case L_PREREPNE:
00287                 inst.prefix|=PREFIX_REP;
00288                 inst.repz=false;
00289                 goto restartopcode;
00290         case L_PREREP:
00291                 inst.prefix|=PREFIX_REP;
00292                 inst.repz=true;
00293                 goto restartopcode;
00294         case L_PREOP:
00295                 inst.entry=(cpu.code.big ^ 1u) * 0x200u;
00296                 goto restartopcode;
00297         case L_PREADD:
00298                 inst.prefix=(inst.prefix & ~1u) | (cpu.code.big ^ 1u);
00299                 goto restartopcode;
00300         case L_VAL:
00301                 inst_op1_d=inst.code.extra;
00302                 break;
00303         case L_INTO:
00304                 if (!get_OF()) goto nextopcode;
00305                 inst_op1_d=4;
00306                 break;
00307         case D_IRETw:
00308                 CPU_IRET(false,GetIP());
00309                 if (GETFLAG(IF) && PIC_IRQCheck) {
00310                         return CBRET_NONE;
00311                 }
00312                 continue;
00313         case D_IRETd:
00314                 CPU_IRET(true,GetIP());
00315                 if (GETFLAG(IF) && PIC_IRQCheck) 
00316                         return CBRET_NONE;
00317                 continue;
00318         case D_RETFwIw:
00319                 {
00320                         Bitu words=Fetchw();
00321                         FillFlags();    
00322                         CPU_RET(false,words,GetIP());
00323                         continue;
00324                 }
00325         case D_RETFw:
00326                 FillFlags();
00327                 CPU_RET(false,0,GetIP());
00328                 continue;
00329         case D_RETFdIw:
00330                 {
00331                         Bitu words=Fetchw();
00332                         FillFlags();    
00333                         CPU_RET(true,words,GetIP());
00334                         continue;
00335                 }
00336         case D_RETFd:
00337                 FillFlags();
00338                 CPU_RET(true,0,GetIP());
00339                 continue;
00340 /* Direct operations */
00341         case L_STRING:
00342                 #include "string.h"
00343                 goto nextopcode;
00344         case D_PUSHAw:
00345                 if (CPU_ArchitectureType<CPU_ARCHTYPE_80186) goto illegalopcode;
00346                 {
00347                         Bitu old_esp = reg_esp;
00348                         try {
00349                                 Bit16u old_sp = (CPU_ArchitectureType >= CPU_ARCHTYPE_286 ? reg_sp : (reg_sp-10));
00350                                 Push_16(reg_ax);Push_16(reg_cx);Push_16(reg_dx);Push_16(reg_bx);
00351                                 Push_16(old_sp);Push_16(reg_bp);Push_16(reg_si);Push_16(reg_di);
00352                         }
00353                         catch (GuestPageFaultException &pf) {
00354                                 (void)pf;
00355                                 LOG_MSG("PUSHA interrupted by page fault");
00356                                 reg_esp = old_esp;
00357                                 throw;
00358                         }
00359                 } goto nextopcode;
00360         case D_PUSHAd:
00361                 {
00362                         Bitu old_esp = reg_esp;
00363                         try {
00364                                 Bitu tmpesp = reg_esp;
00365                                 Push_32(reg_eax);Push_32(reg_ecx);Push_32(reg_edx);Push_32(reg_ebx);
00366                                 Push_32(tmpesp);Push_32(reg_ebp);Push_32(reg_esi);Push_32(reg_edi);
00367                         }
00368                         catch (GuestPageFaultException &pf) {
00369                                 (void)pf;
00370                                 LOG_MSG("PUSHAD interrupted by page fault");
00371                                 reg_esp = old_esp;
00372                                 throw;
00373                         }
00374                 } goto nextopcode;
00375         case D_POPAw:
00376                 if (CPU_ArchitectureType<CPU_ARCHTYPE_80186) goto illegalopcode;
00377                 {
00378                         Bitu old_esp = reg_esp;
00379                         try {
00380                                 reg_di=Pop_16();reg_si=Pop_16();reg_bp=Pop_16();Pop_16();//Don't save SP
00381                                 reg_bx=Pop_16();reg_dx=Pop_16();reg_cx=Pop_16();reg_ax=Pop_16();
00382                         }
00383                         catch (GuestPageFaultException &pf) {
00384                                 (void)pf;
00385                                 LOG_MSG("POPA interrupted by page fault");
00386                                 reg_esp = old_esp;
00387                                 throw;
00388                         }
00389                 } goto nextopcode;
00390         case D_POPAd:
00391                 {
00392                         Bitu old_esp = reg_esp;
00393                         try {
00394                                 reg_edi=Pop_32();reg_esi=Pop_32();reg_ebp=Pop_32();Pop_32();//Don't save ESP
00395                                 reg_ebx=Pop_32();reg_edx=Pop_32();reg_ecx=Pop_32();reg_eax=Pop_32();
00396                         }
00397                         catch (GuestPageFaultException &pf) {
00398                                 (void)pf;
00399                                 LOG_MSG("POPAD interrupted by page fault");
00400                                 reg_esp = old_esp;
00401                                 throw;
00402                         }
00403                 } goto nextopcode;
00404         case D_POPSEGw:
00405                 if (CPU_PopSeg((SegNames)inst.code.extra,false)) RunException();
00406                 goto nextopcode;
00407         case D_POPSEGd:
00408                 if (CPU_PopSeg((SegNames)inst.code.extra,true)) RunException();
00409                 goto nextopcode;
00410         case D_SETALC:
00411                 reg_al = get_CF() ? 0xFF : 0;
00412                 goto nextopcode;
00413         case D_XLAT:
00414                 if (inst.prefix & PREFIX_SEG) {
00415                         if (inst.prefix & PREFIX_ADDR) {
00416                                 reg_al=LoadMb(inst.seg.base+(Bit32u)(reg_ebx+reg_al));
00417                         } else {
00418                                 reg_al=LoadMb(inst.seg.base+(Bit16u)(reg_bx+reg_al));
00419                         }
00420                 } else {
00421                         if (inst.prefix & PREFIX_ADDR) {
00422                                 reg_al=LoadMb(SegBase(ds)+(Bit32u)(reg_ebx+reg_al));
00423                         } else {
00424                                 reg_al=LoadMb(SegBase(ds)+(Bit16u)(reg_bx+reg_al));
00425                         }
00426                 }
00427                 goto nextopcode;
00428         case D_CBW:
00429                 reg_ax=(Bit16u)((Bit8s)reg_al);
00430                 goto nextopcode;
00431         case D_CWDE:
00432                 reg_eax=(Bit32u)((Bit16s)reg_ax);
00433                 goto nextopcode;
00434         case D_CWD:
00435                 if (reg_ax & 0x8000) reg_dx=0xffff;
00436                 else reg_dx=0;
00437                 goto nextopcode;
00438         case D_CDQ:
00439                 if (reg_eax & 0x80000000) reg_edx=0xffffffff;
00440                 else reg_edx=0;
00441                 goto nextopcode;
00442         case D_CLI:
00443                 if (CPU_CLI()) RunException();
00444                 goto nextopcode;
00445         case D_STI:
00446                 if (CPU_STI()) RunException();
00447                 goto nextopcode;
00448         case D_STC:
00449                 FillFlags();SETFLAGBIT(CF,true);
00450                 goto nextopcode;
00451         case D_CLC:
00452                 FillFlags();SETFLAGBIT(CF,false);
00453                 goto nextopcode;
00454         case D_CMC:
00455                 FillFlags();
00456                 SETFLAGBIT(CF,!(reg_flags & FLAG_CF));
00457                 goto nextopcode;
00458         case D_CLD:
00459                 SETFLAGBIT(DF,false);
00460                 cpu.direction=1;
00461                 goto nextopcode;
00462         case D_STD:
00463                 SETFLAGBIT(DF,true);
00464                 cpu.direction=-1;
00465                 goto nextopcode;
00466         case D_PUSHF:
00467                 if (CPU_PUSHF(inst.code.extra)) RunException();
00468                 goto nextopcode;
00469         case D_POPF:
00470                 if (CPU_POPF(inst.code.extra)) RunException();
00471                 if (GETFLAG(IF) && PIC_IRQCheck) {
00472                         SaveIP();
00473                         return CBRET_NONE;
00474                 }
00475                 goto nextopcode;
00476         case D_SAHF:
00477                 SETFLAGSb(reg_ah);
00478                 goto nextopcode;
00479         case D_LAHF:
00480                 FillFlags();
00481                 reg_ah=reg_flags&0xff;
00482                 goto nextopcode;
00483         case D_WAIT:
00484         case D_NOP:
00485                 goto nextopcode;
00486         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;
00487                         probably doesn't matter for our purposes as it is a pentium prefix anyhow */
00488 // todo: make an option to show this
00489 //              LOG(LOG_CPU,LOG_NORMAL)("CPU:LOCK");
00490                 goto nextopcode;
00491         case D_ENTERw:
00492                 {
00493                         Bitu bytes=Fetchw();
00494                         Bitu level=Fetchb();
00495                         CPU_ENTER(false,bytes,level);
00496                         goto nextopcode;
00497                 }
00498         case D_ENTERd:
00499                 {
00500                         Bitu bytes=Fetchw();
00501                         Bitu level=Fetchb();
00502                         CPU_ENTER(true,bytes,level);
00503                         goto nextopcode;
00504                 }
00505         case D_LEAVEw:
00506                 {
00507                         Bit32u old_esp = reg_esp;
00508 
00509                         reg_esp &= cpu.stack.notmask;
00510                         reg_esp |= reg_ebp&cpu.stack.mask;
00511                         try {
00512                                 reg_bp = Pop_16();
00513                         }
00514                         catch (GuestPageFaultException &pf) {
00515                                 (void)pf;
00516                                 reg_esp = old_esp;
00517                                 throw;
00518                         }
00519                 } goto nextopcode;
00520         case D_LEAVEd:
00521                 {
00522                         Bit32u old_esp = reg_esp;
00523 
00524                         reg_esp &= cpu.stack.notmask;
00525                         reg_esp |= reg_ebp&cpu.stack.mask;
00526                         try {
00527                                 reg_ebp = Pop_32();
00528                         }
00529                         catch (GuestPageFaultException &pf) {
00530                                 (void)pf;
00531                                 reg_esp = old_esp;
00532                                 throw;
00533                         }
00534                 } goto nextopcode;
00535         case D_DAA:
00536                 DAA();
00537                 goto nextopcode;
00538         case D_DAS:
00539                 DAS();
00540                 goto nextopcode;
00541         case D_AAA:
00542                 AAA();
00543                 goto nextopcode;
00544         case D_AAS:
00545                 AAS();
00546                 goto nextopcode;
00547         case D_CPUID:
00548                 if (!CPU_CPUID()) goto illegalopcode;
00549                 goto nextopcode;
00550         case D_HLT:
00551                 if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP);
00552                 FillFlags();
00553                 CPU_HLT(GetIP());
00554                 return CBRET_NONE;
00555         case D_CLTS:
00556                 if (cpu.pmode && cpu.cpl) goto illegalopcode;
00557                 cpu.cr0&=(~CR0_TASKSWITCH);
00558                 goto nextopcode;
00559         case D_ICEBP:
00560                 CPU_SW_Interrupt_NoIOPLCheck(1,GetIP());
00561                 continue;
00562         case D_RDTSC: {
00563                 if (CPU_ArchitectureType<CPU_ARCHTYPE_PENTIUM) goto illegalopcode;
00564                 Bit64s tsc=(Bit64s)(PIC_FullIndex()*(double)(CPU_CycleAutoAdjust?70000:CPU_CycleMax));
00565                 reg_edx=(Bit32u)(tsc>>32);
00566                 reg_eax=(Bit32u)(tsc&0xffffffff);
00567                 break;
00568                 }
00569         default:
00570                 LOG(LOG_CPU,LOG_ERROR)("LOAD:Unhandled code %d opcode %lx",inst.code.load,(unsigned long)inst.entry);
00571                 goto illegalopcode;
00572 }
00573