DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/cpu/core_dynrec/decoder.h
00001 /*
00002  *  Copyright (C) 2002-2020  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 along
00015  *  with this program; if not, write to the Free Software Foundation, Inc.,
00016  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 
00020 
00021 #include "decoder_basic.h"
00022 #include "operators.h"
00023 #include "decoder_opcodes.h"
00024 
00025 #include "dyn_fpu.h"
00026 
00027 /*
00028         The function CreateCacheBlock translates the instruction stream
00029         until either an unhandled instruction is found, the maximum
00030         number of translated instructions is reached or some critical
00031         instruction is encountered.
00032 */
00033 
00034 static CacheBlockDynRec * CreateCacheBlock(CodePageHandlerDynRec * codepage,PhysPt start,Bitu max_opcodes) {
00035         // initialize a load of variables
00036         decode.code_start=start;
00037         decode.code=start;
00038         decode.page.code=codepage;
00039         decode.page.index=start&4095;
00040         decode.page.wmap=codepage->write_map;
00041         decode.page.invmap=codepage->invalidation_map;
00042         decode.page.first=start >> 12;
00043         decode.active_block=decode.block=cache_openblock();
00044         decode.block->page.start=(Bit16u)decode.page.index;
00045         codepage->AddCacheBlock(decode.block);
00046 
00047         InitFlagsOptimization();
00048 
00049         // every codeblock that is run sets cache.block.running to itself
00050         // so the block linking knows the last executed block
00051         gen_mov_direct_ptr(&cache.block.running,(DRC_PTR_SIZE_IM)decode.block);
00052 
00053         // start with the cycles check
00054         gen_mov_word_to_reg(FC_RETOP,&CPU_Cycles,true);
00055         save_info_dynrec[used_save_info_dynrec].branch_pos=gen_create_branch_long_leqzero(FC_RETOP);
00056         save_info_dynrec[used_save_info_dynrec].type=cycle_check;
00057         used_save_info_dynrec++;
00058 
00059         decode.cycles=0;
00060         while (max_opcodes--) {
00061                 // Init prefixes
00062                 decode.big_addr=cpu.code.big;
00063                 decode.big_op=cpu.code.big;
00064                 decode.seg_prefix=0;
00065                 decode.seg_prefix_used=false;
00066                 decode.rep=REP_NONE;
00067                 decode.cycles++;
00068                 decode.op_start=decode.code;
00069 restart_prefix:
00070                 Bitu opcode;
00071                 if (!decode.page.invmap) opcode=decode_fetchb();
00072                 else {
00073                         // some entries in the invalidation map, see if the next
00074                         // instruction is known to be modified a lot
00075                         if (decode.page.index<4096) {
00076                                 if (GCC_UNLIKELY(decode.page.invmap[decode.page.index]>=4)) goto illegalopcode;
00077                                 opcode=decode_fetchb();
00078                         } else {
00079                                 // switch to the next page
00080                                 opcode=decode_fetchb();
00081                                 if (GCC_UNLIKELY(decode.page.invmap && 
00082                                         (decode.page.invmap[decode.page.index-1]>=4))) goto illegalopcode;
00083                         }
00084                 }
00085                 switch (opcode) {
00086                 // instructions 'op reg8,reg8' and 'op [],reg8'
00087                 case 0x00:dyn_dop_ebgb(DOP_ADD);break;
00088                 case 0x08:dyn_dop_ebgb(DOP_OR);break;
00089                 case 0x10:dyn_dop_ebgb(DOP_ADC);break;
00090                 case 0x18:dyn_dop_ebgb(DOP_SBB);break;
00091                 case 0x20:dyn_dop_ebgb(DOP_AND);break;
00092                 case 0x28:dyn_dop_ebgb(DOP_SUB);break;
00093                 case 0x30:dyn_dop_ebgb(DOP_XOR);break;
00094                 case 0x38:dyn_dop_ebgb(DOP_CMP);break;
00095 
00096                 // instructions 'op reg8,reg8' and 'op reg8,[]'
00097                 case 0x02:dyn_dop_gbeb(DOP_ADD);break;
00098                 case 0x0a:dyn_dop_gbeb(DOP_OR);break;
00099                 case 0x12:dyn_dop_gbeb(DOP_ADC);break;
00100                 case 0x1a:dyn_dop_gbeb(DOP_SBB);break;
00101                 case 0x22:dyn_dop_gbeb(DOP_AND);break;
00102                 case 0x2a:dyn_dop_gbeb(DOP_SUB);break;
00103                 case 0x32:dyn_dop_gbeb(DOP_XOR);break;
00104                 case 0x3a:dyn_dop_gbeb(DOP_CMP);break;
00105 
00106                 // instructions 'op reg16/32,reg16/32' and 'op [],reg16/32'
00107                 case 0x01:dyn_dop_evgv(DOP_ADD);break;
00108                 case 0x09:dyn_dop_evgv(DOP_OR);break;
00109                 case 0x11:dyn_dop_evgv(DOP_ADC);break;
00110                 case 0x19:dyn_dop_evgv(DOP_SBB);break;
00111                 case 0x21:dyn_dop_evgv(DOP_AND);break;
00112                 case 0x29:dyn_dop_evgv(DOP_SUB);break;
00113                 case 0x31:dyn_dop_evgv(DOP_XOR);break;
00114                 case 0x39:dyn_dop_evgv(DOP_CMP);break;
00115 
00116                 // instructions 'op reg16/32,reg16/32' and 'op reg16/32,[]'
00117                 case 0x03:dyn_dop_gvev(DOP_ADD);break;
00118                 case 0x0b:dyn_dop_gvev(DOP_OR);break;
00119                 case 0x13:dyn_dop_gvev(DOP_ADC);break;
00120                 case 0x1b:dyn_dop_gvev(DOP_SBB);break;
00121                 case 0x23:dyn_dop_gvev(DOP_AND);break;
00122                 case 0x2b:dyn_dop_gvev(DOP_SUB);break;
00123                 case 0x33:dyn_dop_gvev(DOP_XOR);break;
00124                 case 0x3b:dyn_dop_gvev(DOP_CMP);break;
00125 
00126                 // instructions 'op reg8,imm8'
00127                 case 0x04:dyn_dop_byte_imm(DOP_ADD,DRC_REG_EAX,0);break;
00128                 case 0x0c:dyn_dop_byte_imm(DOP_OR,DRC_REG_EAX,0);break;
00129                 case 0x14:dyn_dop_byte_imm(DOP_ADC,DRC_REG_EAX,0);break;
00130                 case 0x1c:dyn_dop_byte_imm(DOP_SBB,DRC_REG_EAX,0);break;
00131                 case 0x24:dyn_dop_byte_imm(DOP_AND,DRC_REG_EAX,0);break;
00132                 case 0x2c:dyn_dop_byte_imm(DOP_SUB,DRC_REG_EAX,0);break;
00133                 case 0x34:dyn_dop_byte_imm(DOP_XOR,DRC_REG_EAX,0);break;
00134                 case 0x3c:dyn_dop_byte_imm(DOP_CMP,DRC_REG_EAX,0);break;
00135 
00136                 // instructions 'op reg16/32,imm16/32'
00137                 case 0x05:dyn_dop_word_imm(DOP_ADD,DRC_REG_EAX);break;
00138                 case 0x0d:dyn_dop_word_imm_old(DOP_OR,DRC_REG_EAX,decode.big_op ? decode_fetchd() :  decode_fetchw());break;
00139                 case 0x15:dyn_dop_word_imm_old(DOP_ADC,DRC_REG_EAX,decode.big_op ? decode_fetchd() :  decode_fetchw());break;
00140                 case 0x1d:dyn_dop_word_imm_old(DOP_SBB,DRC_REG_EAX,decode.big_op ? decode_fetchd() :  decode_fetchw());break;
00141                 case 0x25:dyn_dop_word_imm(DOP_AND,DRC_REG_EAX);break;
00142                 case 0x2d:dyn_dop_word_imm_old(DOP_SUB,DRC_REG_EAX,decode.big_op ? decode_fetchd() :  decode_fetchw());break;
00143                 case 0x35:dyn_dop_word_imm_old(DOP_XOR,DRC_REG_EAX,decode.big_op ? decode_fetchd() :  decode_fetchw());break;
00144                 case 0x3d:dyn_dop_word_imm_old(DOP_CMP,DRC_REG_EAX,decode.big_op ? decode_fetchd() :  decode_fetchw());break;
00145 
00146                 // push segment register onto stack
00147                 case 0x06:dyn_push_seg(DRC_SEG_ES);break;
00148                 case 0x0e:dyn_push_seg(DRC_SEG_CS);break;
00149                 case 0x16:dyn_push_seg(DRC_SEG_SS);break;
00150                 case 0x1e:dyn_push_seg(DRC_SEG_DS);break;
00151 
00152                 // pop segment register from stack
00153                 case 0x07:dyn_pop_seg(DRC_SEG_ES);break;
00154                 case 0x17:dyn_pop_seg(DRC_SEG_SS);break;
00155                 case 0x1f:dyn_pop_seg(DRC_SEG_DS);break;
00156 
00157                 // segment prefixes
00158                 case 0x26:dyn_segprefix(DRC_SEG_ES);goto restart_prefix;
00159                 case 0x2e:dyn_segprefix(DRC_SEG_CS);goto restart_prefix;
00160                 case 0x36:dyn_segprefix(DRC_SEG_SS);goto restart_prefix;
00161                 case 0x3e:dyn_segprefix(DRC_SEG_DS);goto restart_prefix;
00162                 case 0x64:dyn_segprefix(DRC_SEG_FS);goto restart_prefix;
00163                 case 0x65:dyn_segprefix(DRC_SEG_GS);goto restart_prefix;
00164 
00165 //              case 0x27: DAA missing
00166 //              case 0x2f: DAS missing
00167 //              case 0x37: AAA missing
00168 //              case 0x3f: AAS missing
00169 
00170                 // dual opcodes
00171                 case 0x0f:
00172                 {
00173                         Bitu dual_code=decode_fetchb();
00174                         switch (dual_code) {
00175                                 case 0x00:
00176                                         if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegalopcode;
00177                                         dyn_grp6();
00178                                         break;
00179                                 case 0x01:
00180                                         if (dyn_grp7()) goto finish_block;
00181                                         break;
00182 /*                              case 0x02:
00183                                         if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegalopcode;
00184                                         dyn_larlsl(true);
00185                                         break;
00186                                 case 0x03:
00187                                         if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegalopcode;
00188                                         dyn_larlsl(false);
00189                                         break; */
00190 
00191                                 case 0x20:dyn_mov_from_crx();break;
00192                                 case 0x22:dyn_mov_to_crx();goto finish_block;
00193 
00194                                 // short conditional jumps
00195                                 case 0x80:case 0x81:case 0x82:case 0x83:case 0x84:case 0x85:case 0x86:case 0x87:        
00196                                 case 0x88:case 0x89:case 0x8a:case 0x8b:case 0x8c:case 0x8d:case 0x8e:case 0x8f:        
00197                                         dyn_branched_exit((BranchTypes)(dual_code&0xf),
00198                                                 decode.big_op ? (Bit32s)decode_fetchd() : (Bit16s)decode_fetchw());
00199                                         goto finish_block;
00200 
00201                                 // conditional byte set instructions
00202 /*                              case 0x90:case 0x91:case 0x92:case 0x93:case 0x94:case 0x95:case 0x96:case 0x97:        
00203                                 case 0x98:case 0x99:case 0x9a:case 0x9b:case 0x9c:case 0x9d:case 0x9e:case 0x9f:        
00204                                         dyn_set_byte_on_condition((BranchTypes)(dual_code&0xf));
00205                                         AcquireFlags(FMASK_TEST);
00206                                         break; */
00207 
00208                                 // push/pop segment registers
00209                                 case 0xa0:dyn_push_seg(DRC_SEG_FS);break;
00210                                 case 0xa1:dyn_pop_seg(DRC_SEG_FS);break;
00211                                 case 0xa8:dyn_push_seg(DRC_SEG_GS);break;
00212                                 case 0xa9:dyn_pop_seg(DRC_SEG_GS);break;
00213 
00214                                 // double shift instructions
00215                                 case 0xa4:dyn_dshift_ev_gv(true,true);break;
00216                                 case 0xa5:dyn_dshift_ev_gv(true,false);break;
00217                                 case 0xac:dyn_dshift_ev_gv(false,true);break;
00218                                 case 0xad:dyn_dshift_ev_gv(false,false);break;
00219 
00220                                 case 0xaf:dyn_imul_gvev(0);break;
00221 
00222                                 // lfs
00223                                 case 0xb4:
00224                                         dyn_get_modrm();
00225                                         if (GCC_UNLIKELY(decode.modrm.mod==3)) goto illegalopcode;
00226                                         dyn_load_seg_off_ea(DRC_SEG_FS);
00227                                         break;
00228                                 // lgs
00229                                 case 0xb5:
00230                                         dyn_get_modrm();
00231                                         if (GCC_UNLIKELY(decode.modrm.mod==3)) goto illegalopcode;
00232                                         dyn_load_seg_off_ea(DRC_SEG_GS);
00233                                         break;
00234 
00235                                 // zero-extending moves
00236                                 case 0xb6:dyn_movx_ev_gb(false);break;
00237                                 case 0xb7:dyn_movx_ev_gw(false);break;
00238 
00239                                 // sign-extending moves
00240                                 case 0xbe:dyn_movx_ev_gb(true);break;
00241                                 case 0xbf:dyn_movx_ev_gw(true);break;
00242 
00243                                 default:
00244 #if DYN_LOG
00245 //                                      LOG_MSG("Unhandled dual opcode 0F%02X",dual_code);
00246 #endif
00247                                         goto illegalopcode;
00248                         }
00249                         break;
00250                 }
00251 
00252                 // 'inc/dec reg16/32'
00253                 case 0x40:case 0x41:case 0x42:case 0x43:case 0x44:case 0x45:case 0x46:case 0x47:        
00254                         dyn_sop_word(SOP_INC,opcode&7);
00255                         break;
00256                 case 0x48:case 0x49:case 0x4a:case 0x4b:case 0x4c:case 0x4d:case 0x4e:case 0x4f:        
00257                         dyn_sop_word(SOP_DEC,opcode&7);
00258                         break;
00259 
00260                 // 'push/pop reg16/32'
00261                 case 0x50:case 0x51:case 0x52:case 0x53:case 0x54:case 0x55:case 0x56:case 0x57:        
00262                         dyn_push_reg(opcode&7);
00263                         break;
00264                 case 0x58:case 0x59:case 0x5a:case 0x5b:case 0x5c:case 0x5d:case 0x5e:case 0x5f:        
00265                         dyn_pop_reg(opcode&7);
00266                         break;
00267 
00268                 case 0x60:
00269                         if (decode.big_op) gen_call_function_raw(dynrec_pusha_dword);
00270                         else gen_call_function_raw(dynrec_pusha_word);
00271                         break;
00272                 case 0x61:
00273                         if (decode.big_op) gen_call_function_raw(dynrec_popa_dword);
00274                         else gen_call_function_raw(dynrec_popa_word);
00275                         break;
00276 
00277 //              case 0x62: BOUND missing
00278 //              case 0x61: ARPL missing
00279 
00280                 case 0x66:decode.big_op=!cpu.code.big;goto restart_prefix;
00281                 case 0x67:decode.big_addr=!cpu.code.big;goto restart_prefix;
00282 
00283                 // 'push imm8/16/32'
00284                 case 0x68:
00285                         dyn_push_word_imm(decode.big_op ? decode_fetchd() :  decode_fetchw());
00286                         break;
00287                 case 0x6a:
00288                         dyn_push_byte_imm((Bit8s)decode_fetchb());
00289                         break;
00290 
00291                 // signed multiplication
00292                 case 0x69:dyn_imul_gvev(decode.big_op ? 4 : 2);break;
00293                 case 0x6b:dyn_imul_gvev(1);break;
00294 
00295 //              case 0x6c to 0x6f missing (ins/outs)
00296 
00297                 // short conditional jumps
00298                 case 0x70:case 0x71:case 0x72:case 0x73:case 0x74:case 0x75:case 0x76:case 0x77:        
00299                 case 0x78:case 0x79:case 0x7a:case 0x7b:case 0x7c:case 0x7d:case 0x7e:case 0x7f:        
00300                         dyn_branched_exit((BranchTypes)(opcode&0xf),(Bit8s)decode_fetchb());    
00301                         goto finish_block;
00302 
00303                 // 'op []/reg8,imm8'
00304                 case 0x80:
00305                 case 0x82:dyn_grp1_eb_ib();break;
00306 
00307                 // 'op []/reg16/32,imm16/32'
00308                 case 0x81:dyn_grp1_ev_iv(false);break;
00309                 case 0x83:dyn_grp1_ev_iv(true);break;
00310 
00311                 // 'test []/reg8/16/32,reg8/16/32'
00312                 case 0x84:dyn_dop_gbeb(DOP_TEST);break;
00313                 case 0x85:dyn_dop_gvev(DOP_TEST);break;
00314 
00315                 // 'xchg reg8/16/32,[]/reg8/16/32'
00316                 case 0x86:dyn_dop_ebgb_xchg();break;
00317                 case 0x87:dyn_dop_evgv_xchg();break;
00318 
00319                 // 'mov []/reg8/16/32,reg8/16/32'
00320                 case 0x88:dyn_dop_ebgb_mov();break;
00321                 case 0x89:dyn_dop_evgv_mov();break;
00322                 // 'mov reg8/16/32,[]/reg8/16/32'
00323                 case 0x8a:dyn_dop_gbeb_mov();break;
00324                 case 0x8b:dyn_dop_gvev_mov();break;
00325 
00326                 // move segment register into memory or a 16bit register
00327                 case 0x8c:dyn_mov_ev_seg();break;
00328 
00329                 // load effective address
00330                 case 0x8d:dyn_lea();break;
00331 
00332                 // move a value from memory or a 16bit register into a segment register
00333                 case 0x8e:dyn_mov_seg_ev();break;
00334 
00335                 // 'pop []'
00336                 case 0x8f:dyn_pop_ev();break;
00337 
00338                 case 0x90:      // nop
00339                 case 0x9b:      // wait
00340                 case 0xf0:      // lock
00341                         break;
00342 
00343                 case 0x91:case 0x92:case 0x93:case 0x94:case 0x95:case 0x96:case 0x97:
00344                         dyn_xchg_ax(opcode&7);
00345                         break;
00346 
00347                 // sign-extend al into ax/sign-extend ax into eax
00348                 case 0x98:dyn_cbw();break;
00349                 // sign-extend ax into dx:ax/sign-extend eax into edx:eax
00350                 case 0x99:dyn_cwd();break;
00351 
00352                 case 0x9a:dyn_call_far_imm();goto finish_block;
00353 
00354                 case 0x9c:      // pushf
00355                         AcquireFlags(FMASK_TEST);
00356                         gen_call_function_I(CPU_PUSHF,decode.big_op);
00357                         dyn_check_exception(FC_RETOP);
00358                         break;
00359                 case 0x9d:      // popf
00360                         gen_call_function_I(CPU_POPF,decode.big_op);
00361                         dyn_check_exception(FC_RETOP);
00362                         InvalidateFlags();
00363                         break;
00364 
00365                 case 0x9e:dyn_sahf();break;
00366 //              case 0x9f: LAHF missing
00367 
00368                 // 'mov al/ax,[]'
00369                 case 0xa0:
00370                         dyn_mov_byte_al_direct(decode.big_addr ? decode_fetchd() : decode_fetchw());
00371                         break;
00372                 case 0xa1:
00373                         dyn_mov_byte_ax_direct(decode.big_addr ? decode_fetchd() : decode_fetchw());
00374                         break;
00375                 // 'mov [],al/ax'
00376                 case 0xa2:
00377                         dyn_mov_byte_direct_al();
00378                         break;
00379                 case 0xa3:
00380                         dyn_mov_byte_direct_ax(decode.big_addr ? decode_fetchd() : decode_fetchw());
00381                         break;
00382 
00383 
00384 //              case 0xa6 to 0xaf string operations, some missing
00385 
00386                 // movsb/w/d
00387                 case 0xa4:dyn_string(STR_MOVSB);break;
00388                 case 0xa5:dyn_string(decode.big_op ? STR_MOVSD : STR_MOVSW);break;
00389 
00390                 // stosb/w/d
00391                 case 0xaa:dyn_string(STR_STOSB);break;
00392                 case 0xab:dyn_string(decode.big_op ? STR_STOSD : STR_STOSW);break;
00393 
00394                 // lodsb/w/d
00395                 case 0xac:dyn_string(STR_LODSB);break;
00396                 case 0xad:dyn_string(decode.big_op ? STR_LODSD : STR_LODSW);break;
00397 
00398 
00399                 // 'test reg8/16/32,imm8/16/32'
00400                 case 0xa8:dyn_dop_byte_imm(DOP_TEST,DRC_REG_EAX,0);break;
00401                 case 0xa9:dyn_dop_word_imm_old(DOP_TEST,DRC_REG_EAX,decode.big_op ? decode_fetchd() :  decode_fetchw());break;
00402 
00403                 // 'mov reg8/16/32,imm8/16/32'
00404                 case 0xb0:case 0xb1:case 0xb2:case 0xb3:case 0xb4:case 0xb5:case 0xb6:case 0xb7:        
00405                         dyn_mov_byte_imm(opcode&3,(opcode>>2)&1,decode_fetchb());
00406                         break;
00407                 case 0xb8:case 0xb9:case 0xba:case 0xbb:case 0xbc:case 0xbd:case 0xbe:case 0xbf:        
00408                         dyn_mov_word_imm(opcode&7);
00409                         break;
00410 
00411                 // 'shiftop []/reg8,imm8/1/cl'
00412                 case 0xc0:dyn_grp2_eb(grp2_imm);break;
00413                 case 0xd0:dyn_grp2_eb(grp2_1);break;
00414                 case 0xd2:dyn_grp2_eb(grp2_cl);break;
00415 
00416                 // 'shiftop []/reg16/32,imm8/1/cl'
00417                 case 0xc1:dyn_grp2_ev(grp2_imm);break;
00418                 case 0xd1:dyn_grp2_ev(grp2_1);break;
00419                 case 0xd3:dyn_grp2_ev(grp2_cl);break;
00420 
00421                 // retn [param]
00422                 case 0xc2:dyn_ret_near(decode_fetchw());goto finish_block;
00423                 case 0xc3:dyn_ret_near(0);goto finish_block;
00424 
00425                 // les
00426                 case 0xc4:
00427                         dyn_get_modrm();
00428                         if (GCC_UNLIKELY(decode.modrm.mod==3)) goto illegalopcode;
00429                         dyn_load_seg_off_ea(DRC_SEG_ES);
00430                         break;
00431                 // lds
00432                 case 0xc5:
00433                         dyn_get_modrm();
00434                         if (GCC_UNLIKELY(decode.modrm.mod==3)) goto illegalopcode;
00435                         dyn_load_seg_off_ea(DRC_SEG_DS);break;
00436 
00437                 // 'mov []/reg8/16/32,imm8/16/32'
00438                 case 0xc6:dyn_dop_ebib_mov();break;
00439                 case 0xc7:dyn_dop_eviv_mov();break;
00440 
00441                 case 0xc8:dyn_enter();break;
00442                 case 0xc9:dyn_leave();break;
00443 
00444                 // retf [param]
00445                 case 0xca:dyn_ret_far(decode_fetchw());goto finish_block;
00446                 case 0xcb:dyn_ret_far(0);goto finish_block;
00447 
00448                 // int/iret
00449 #if !(C_DEBUG)
00450                 case 0xcd:dyn_interrupt(decode_fetchb());goto finish_block;
00451 #endif
00452                 case 0xcf:dyn_iret();goto finish_block;
00453 
00454 //              case 0xd4: AAM missing
00455 //              case 0xd5: AAD missing
00456 
00457 //              case 0xd6: SALC missing
00458 //              case 0xd7: XLAT missing
00459 
00460 
00461 #ifdef CPU_FPU
00462                 // floating point instructions
00463                 case 0xd8:
00464                         dyn_fpu_esc0();
00465                         break;
00466                 case 0xd9:
00467                         dyn_fpu_esc1();
00468                         break;
00469                 case 0xda:
00470                         dyn_fpu_esc2();
00471                         break;
00472                 case 0xdb:
00473                         dyn_fpu_esc3();
00474                         break;
00475                 case 0xdc:
00476                         dyn_fpu_esc4();
00477                         break;
00478                 case 0xdd:
00479                         dyn_fpu_esc5();
00480                         break;
00481                 case 0xde:
00482                         dyn_fpu_esc6();
00483                         break;
00484                 case 0xdf:
00485                         dyn_fpu_esc7();
00486                         break;
00487 #endif
00488 
00489 
00490                 // loop instructions
00491                 case 0xe0:dyn_loop(LOOP_NE);goto finish_block;
00492                 case 0xe1:dyn_loop(LOOP_E);goto finish_block;
00493                 case 0xe2:dyn_loop(LOOP_NONE);goto finish_block;
00494                 case 0xe3:dyn_loop(LOOP_JCXZ);goto finish_block;
00495 
00496 
00497                 // 'in al/ax/eax,port_imm'
00498                 case 0xe4:dyn_read_port_byte_direct(decode_fetchb());break;
00499                 case 0xe5:dyn_read_port_word_direct(decode_fetchb());break;
00500                 // 'out port_imm,al/ax/eax'
00501                 case 0xe6:dyn_write_port_byte_direct(decode_fetchb());break;
00502                 case 0xe7:dyn_write_port_word_direct(decode_fetchb());break;
00503 
00504                 // 'in al/ax/eax,port_dx'
00505                 case 0xec:dyn_read_port_byte();break;
00506                 case 0xed:dyn_read_port_word();break;
00507                 // 'out port_dx,al/ax/eax'
00508                 case 0xee:dyn_write_port_byte();break;
00509                 case 0xef:dyn_write_port_word();break;
00510 
00511 
00512                 // 'call near imm16/32'
00513                 case 0xe8:
00514                         dyn_call_near_imm();
00515                         goto finish_block;
00516                 // 'jmp near imm16/32'
00517                 case 0xe9:
00518                         dyn_exit_link(decode.big_op ? (Bit32s)decode_fetchd() : (Bit16s)decode_fetchw());
00519                         goto finish_block;
00520                 // 'jmp far'
00521                 case 0xea:
00522                         dyn_jmp_far_imm();
00523                         goto finish_block;
00524                 // 'jmp short imm8'
00525                 case 0xeb:
00526                         dyn_exit_link((Bit8s)decode_fetchb());
00527                         goto finish_block;
00528 
00529 
00530                 // repeat prefixes
00531                 case 0xf2:
00532                         decode.rep=REP_NZ;
00533                         goto restart_prefix;
00534                 case 0xf3:
00535                         decode.rep=REP_Z;
00536                         goto restart_prefix;
00537 
00538                 case 0xf5:              //CMC
00539                         gen_call_function_raw(dynrec_cmc);
00540                         break;
00541                 case 0xf8:              //CLC
00542                         gen_call_function_raw(dynrec_clc);
00543                         break;
00544                 case 0xf9:              //STC
00545                         gen_call_function_raw(dynrec_stc);
00546                         break;
00547 
00548                 case 0xf6:dyn_grp3_eb();break;
00549                 case 0xf7:dyn_grp3_ev();break;
00550 
00551                 case 0xfa:              //CLI
00552                         gen_call_function_raw(CPU_CLI);
00553                         dyn_check_exception(FC_RETOP);
00554                         break;
00555                 case 0xfb:              //STI
00556                         gen_call_function_raw(CPU_STI);
00557                         dyn_check_exception(FC_RETOP);
00558                         if (max_opcodes==0) max_opcodes=1;              //Allow 1 extra opcode
00559                         break;
00560 
00561                 case 0xfc:              //CLD
00562                         gen_call_function_raw(dynrec_cld);
00563                         break;
00564                 case 0xfd:              //STD
00565                         gen_call_function_raw(dynrec_std);
00566                         break;
00567 
00568                 case 0xfe:
00569                         if (dyn_grp4_eb()) goto finish_block;
00570                         break;
00571                 case 0xff:
00572                         switch (dyn_grp4_ev()) {
00573                         case 0:
00574                                 break;
00575                         case 1:
00576                                 goto core_close_block;
00577                         case 2:
00578                                 goto illegalopcode;
00579                         default:
00580                                 break;
00581                         }
00582                         break;
00583 
00584                 default:
00585 #if DYN_LOG
00586 //                      LOG_MSG("Dynrec unhandled opcode %X",opcode);
00587 #endif
00588                         goto illegalopcode;
00589                 }
00590         }
00591         // link to next block because the maximum number of opcodes has been reached
00592         dyn_set_eip_end();
00593         dyn_reduce_cycles();
00594         gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlockDynRec,cache.start));
00595         dyn_closeblock();
00596     goto finish_block;
00597 core_close_block:
00598         dyn_reduce_cycles();
00599         dyn_return(BR_Normal);
00600         dyn_closeblock();
00601         goto finish_block;
00602 illegalopcode:
00603         // some unhandled opcode has been encountered
00604         dyn_set_eip_last();
00605         dyn_reduce_cycles();
00606         dyn_return(BR_Opcode);  // tell the core what happened
00607         dyn_closeblock();
00608         goto finish_block;
00609 finish_block:
00610 
00611         // setup the correct end-address
00612         decode.page.index--;
00613         decode.active_block->page.end=(Bit16u)decode.page.index;
00614 //      LOG_MSG("Created block size %d start %d end %d",decode.block->cache.size,decode.block->page.start,decode.block->page.end);
00615 
00616         return decode.block;
00617 }