DOSBox-X
|
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 }