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 /* 00022 The functions in this file are called almost exclusively by decoder.h, 00023 they translate an (or a set of) instruction(s) into hostspecific code 00024 and use the lower-level functions from decoder_basic.h and generating 00025 functions from risc_?.h 00026 Some complex instructions as well as most instructions that can modify 00027 the condition flags are translated by generating a call to a C-function 00028 (see operators.h). Parameter loading and result writeback is done 00029 according to the instruction. 00030 */ 00031 00032 static void dyn_dop_ebgb(DualOps op) { 00033 dyn_get_modrm(); 00034 if (decode.modrm.mod<3) { 00035 dyn_fill_ea(FC_ADDR); 00036 gen_protect_addr_reg(); 00037 dyn_read_byte_canuseword(FC_ADDR,FC_OP1); 00038 MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP2,decode.modrm.reg&3,((decode.modrm.reg>>2)&1)); 00039 dyn_dop_byte_gencall(op); 00040 00041 if ((op!=DOP_CMP) && (op!=DOP_TEST)) { 00042 gen_restore_addr_reg(); 00043 dyn_write_byte(FC_ADDR,FC_RETOP); 00044 } 00045 } else { 00046 MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,decode.modrm.rm&3,((decode.modrm.rm>>2)&1)); 00047 MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP2,decode.modrm.reg&3,((decode.modrm.reg>>2)&1)); 00048 dyn_dop_byte_gencall(op); 00049 if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,decode.modrm.rm&3,((decode.modrm.rm>>2)&1)); 00050 } 00051 } 00052 00053 static void dyn_dop_ebgb_mov(void) { 00054 dyn_get_modrm(); 00055 if (decode.modrm.mod<3) { 00056 dyn_fill_ea(FC_ADDR); 00057 MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.reg&3,((decode.modrm.reg>>2)&1)); 00058 dyn_write_byte(FC_ADDR,FC_TMP_BA1); 00059 } else { 00060 MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.reg&3,((decode.modrm.reg>>2)&1)); 00061 MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.rm&3,((decode.modrm.rm>>2)&1)); 00062 } 00063 } 00064 00065 static void dyn_dop_ebib_mov(void) { 00066 dyn_get_modrm(); 00067 if (decode.modrm.mod<3) { 00068 dyn_fill_ea(FC_ADDR); 00069 gen_mov_byte_to_reg_low_imm(FC_TMP_BA1,decode_fetchb()); 00070 dyn_write_byte(FC_ADDR,FC_TMP_BA1); 00071 } else { 00072 gen_mov_byte_to_reg_low_imm(FC_TMP_BA1,decode_fetchb()); 00073 MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.rm&3,((decode.modrm.rm>>2)&1)); 00074 } 00075 } 00076 00077 static void dyn_dop_ebgb_xchg(void) { 00078 dyn_get_modrm(); 00079 if (decode.modrm.mod<3) { 00080 dyn_fill_ea(FC_ADDR); 00081 gen_protect_addr_reg(); 00082 dyn_read_byte(FC_ADDR,FC_TMP_BA1); 00083 MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA2,decode.modrm.reg&3,((decode.modrm.reg>>2)&1)); 00084 00085 MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.reg&3,((decode.modrm.reg>>2)&1)); 00086 gen_restore_addr_reg(); 00087 dyn_write_byte(FC_ADDR,FC_TMP_BA2); 00088 } else { 00089 MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.rm&3,((decode.modrm.rm>>2)&1)); 00090 MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA2,decode.modrm.reg&3,((decode.modrm.reg>>2)&1)); 00091 MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.reg&3,((decode.modrm.reg>>2)&1)); 00092 MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA2,decode.modrm.rm&3,((decode.modrm.rm>>2)&1)); 00093 } 00094 } 00095 00096 static void dyn_dop_gbeb(DualOps op) { 00097 dyn_get_modrm(); 00098 if (decode.modrm.mod<3) { 00099 dyn_fill_ea(FC_ADDR); 00100 dyn_read_byte_canuseword(FC_ADDR,FC_OP2); 00101 MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,decode.modrm.reg&3,((decode.modrm.reg>>2)&1)); 00102 dyn_dop_byte_gencall(op); 00103 if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,decode.modrm.reg&3,((decode.modrm.reg>>2)&1)); 00104 } else { 00105 MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP2,decode.modrm.rm&3,((decode.modrm.rm>>2)&1)); 00106 MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,decode.modrm.reg&3,((decode.modrm.reg>>2)&1)); 00107 dyn_dop_byte_gencall(op); 00108 if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,decode.modrm.reg&3,((decode.modrm.reg>>2)&1)); 00109 } 00110 } 00111 00112 static void dyn_dop_gbeb_mov(void) { 00113 dyn_get_modrm(); 00114 if (decode.modrm.mod<3) { 00115 dyn_fill_ea(FC_ADDR); 00116 dyn_read_byte(FC_ADDR,FC_TMP_BA1); 00117 MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.reg&3,((decode.modrm.reg>>2)&1)); 00118 } else { 00119 MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.rm&3,((decode.modrm.rm>>2)&1)); 00120 MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.reg&3,((decode.modrm.reg>>2)&1)); 00121 } 00122 } 00123 00124 static void dyn_dop_evgv(DualOps op) { 00125 dyn_get_modrm(); 00126 if (decode.modrm.mod<3) { 00127 dyn_fill_ea(FC_ADDR); 00128 dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); 00129 gen_protect_addr_reg(); 00130 MOV_REG_WORD_TO_HOST_REG(FC_OP2,decode.modrm.reg,decode.big_op); 00131 dyn_dop_word_gencall(op,decode.big_op); 00132 if ((op!=DOP_CMP) && (op!=DOP_TEST)) { 00133 gen_restore_addr_reg(); 00134 dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op); 00135 } 00136 } else { 00137 MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); 00138 MOV_REG_WORD_TO_HOST_REG(FC_OP2,decode.modrm.reg,decode.big_op); 00139 dyn_dop_word_gencall(op,decode.big_op); 00140 if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.rm,decode.big_op); 00141 } 00142 } 00143 00144 static void dyn_dop_evgv_mov(void) { 00145 dyn_get_modrm(); 00146 if (decode.modrm.mod<3) { 00147 dyn_fill_ea(FC_ADDR); 00148 MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); 00149 dyn_write_word(FC_ADDR,FC_OP1,decode.big_op); 00150 } else { 00151 MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); 00152 MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); 00153 } 00154 } 00155 00156 static void dyn_dop_eviv_mov(void) { 00157 dyn_get_modrm(); 00158 if (decode.modrm.mod<3) { 00159 dyn_fill_ea(FC_ADDR); 00160 if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP1,decode_fetchd()); 00161 else gen_mov_word_to_reg_imm(FC_OP1,decode_fetchw()); 00162 dyn_write_word(FC_ADDR,FC_OP1,decode.big_op); 00163 } else { 00164 if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP1,decode_fetchd()); 00165 else gen_mov_word_to_reg_imm(FC_OP1,decode_fetchw()); 00166 MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); 00167 } 00168 } 00169 00170 static void dyn_dop_evgv_xchg(void) { 00171 dyn_get_modrm(); 00172 if (decode.modrm.mod<3) { 00173 dyn_fill_ea(FC_ADDR); 00174 gen_protect_addr_reg(); 00175 dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); 00176 MOV_REG_WORD_TO_HOST_REG(FC_OP2,decode.modrm.reg,decode.big_op); 00177 00178 gen_protect_reg(FC_OP1); 00179 gen_restore_addr_reg(); 00180 dyn_write_word(FC_ADDR,FC_OP2,decode.big_op); 00181 gen_restore_reg(FC_OP1); 00182 MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); 00183 } else { 00184 MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); 00185 MOV_REG_WORD_TO_HOST_REG(FC_OP2,decode.modrm.reg,decode.big_op); 00186 MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); 00187 MOV_REG_WORD_FROM_HOST_REG(FC_OP2,decode.modrm.rm,decode.big_op); 00188 } 00189 } 00190 00191 static void dyn_xchg_ax(Bit8u reg) { 00192 MOV_REG_WORD_TO_HOST_REG(FC_OP1,DRC_REG_EAX,decode.big_op); 00193 MOV_REG_WORD_TO_HOST_REG(FC_OP2,reg,decode.big_op); 00194 MOV_REG_WORD_FROM_HOST_REG(FC_OP1,reg,decode.big_op); 00195 MOV_REG_WORD_FROM_HOST_REG(FC_OP2,DRC_REG_EAX,decode.big_op); 00196 } 00197 00198 static void dyn_dop_gvev(DualOps op) { 00199 dyn_get_modrm(); 00200 if (decode.modrm.mod<3) { 00201 dyn_fill_ea(FC_ADDR); 00202 gen_protect_addr_reg(); 00203 dyn_read_word(FC_ADDR,FC_OP2,decode.big_op); 00204 MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); 00205 dyn_dop_word_gencall(op,decode.big_op); 00206 if ((op!=DOP_CMP) && (op!=DOP_TEST)) { 00207 gen_restore_addr_reg(); 00208 MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.reg,decode.big_op); 00209 } 00210 } else { 00211 MOV_REG_WORD_TO_HOST_REG(FC_OP2,decode.modrm.rm,decode.big_op); 00212 MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); 00213 dyn_dop_word_gencall(op,decode.big_op); 00214 if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.reg,decode.big_op); 00215 } 00216 } 00217 00218 static void dyn_dop_gvev_mov(void) { 00219 dyn_get_modrm(); 00220 if (decode.modrm.mod<3) { 00221 dyn_fill_ea(FC_ADDR); 00222 dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); 00223 MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); 00224 } else { 00225 MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); 00226 MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); 00227 } 00228 } 00229 00230 static void dyn_dop_byte_imm(DualOps op,Bit8u reg,Bit8u idx) { 00231 MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,reg,idx); 00232 gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,decode_fetchb()); 00233 dyn_dop_byte_gencall(op); 00234 if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,reg,idx); 00235 } 00236 00237 static void dyn_dop_byte_imm_mem(DualOps op,Bit8u reg,Bit8u idx) { 00238 MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,reg,idx); 00239 Bitu val; 00240 if (decode_fetchb_imm(val)) { 00241 gen_mov_byte_to_reg_low_canuseword(FC_OP2,(void*)val); 00242 } else { 00243 gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,(Bit8u)val); 00244 } 00245 dyn_dop_byte_gencall(op); 00246 if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,reg,idx); 00247 } 00248 00249 static void dyn_prep_word_imm(Bit8u reg) { 00250 (void)reg; 00251 00252 Bitu val; 00253 if (decode.big_op) { 00254 if (decode_fetchd_imm(val)) { 00255 gen_mov_word_to_reg(FC_OP2,(void*)val,true); 00256 return; 00257 } 00258 } else { 00259 if (decode_fetchw_imm(val)) { 00260 gen_mov_word_to_reg(FC_OP2,(void*)val,false); 00261 return; 00262 } 00263 } 00264 if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,(Bit32u)val); 00265 else gen_mov_word_to_reg_imm(FC_OP2,(Bit16u)val); 00266 } 00267 00268 static void dyn_dop_word_imm(DualOps op,Bit8u reg) { 00269 MOV_REG_WORD_TO_HOST_REG(FC_OP1,reg,decode.big_op); 00270 dyn_prep_word_imm(reg); 00271 dyn_dop_word_gencall(op,decode.big_op); 00272 if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,reg,decode.big_op); 00273 } 00274 00275 static void dyn_dop_word_imm_old(DualOps op,Bit8u reg,Bitu imm) { 00276 MOV_REG_WORD_TO_HOST_REG(FC_OP1,reg,decode.big_op); 00277 if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,(Bit32u)imm); 00278 else gen_mov_word_to_reg_imm(FC_OP2,(Bit16u)imm); 00279 dyn_dop_word_gencall(op,decode.big_op); 00280 if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,reg,decode.big_op); 00281 } 00282 00283 static void dyn_mov_byte_imm(Bit8u reg,Bit8u idx,Bit8u imm) { 00284 gen_mov_byte_to_reg_low_imm(FC_TMP_BA1,imm); 00285 MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,reg,idx); 00286 } 00287 00288 static void dyn_mov_word_imm(Bit8u reg) { 00289 Bitu val; 00290 if (decode.big_op) { 00291 if (decode_fetchd_imm(val)) { 00292 gen_mov_word_to_reg(FC_OP1,(void*)val,true); 00293 MOV_REG_WORD32_FROM_HOST_REG(FC_OP1,reg); 00294 return; 00295 } 00296 } else { 00297 if (decode_fetchw_imm(val)) { 00298 gen_mov_word_to_reg(FC_OP1,(void*)val,false); 00299 MOV_REG_WORD16_FROM_HOST_REG(FC_OP1,reg); 00300 return; 00301 } 00302 } 00303 if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP1,(Bit32u)val); 00304 else gen_mov_word_to_reg_imm(FC_OP1,(Bit16u)val); 00305 MOV_REG_WORD_FROM_HOST_REG(FC_OP1,reg,decode.big_op); 00306 } 00307 00308 00309 static void dyn_sop_word(SingleOps op,Bit8u reg) { 00310 MOV_REG_WORD_TO_HOST_REG(FC_OP1,reg,decode.big_op); 00311 dyn_sop_word_gencall(op,decode.big_op); 00312 MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,reg,decode.big_op); 00313 } 00314 00315 00316 static void dyn_mov_byte_al_direct(Bit32u imm) { 00317 MOV_SEG_PHYS_TO_HOST_REG(FC_ADDR,(decode.seg_prefix_used ? decode.seg_prefix : DRC_SEG_DS)); 00318 gen_add_imm(FC_ADDR,imm); 00319 dyn_read_byte(FC_ADDR,FC_TMP_BA1); 00320 MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,DRC_REG_EAX,0); 00321 } 00322 00323 static void dyn_mov_byte_ax_direct(Bit32u imm) { 00324 MOV_SEG_PHYS_TO_HOST_REG(FC_ADDR,(decode.seg_prefix_used ? decode.seg_prefix : DRC_SEG_DS)); 00325 gen_add_imm(FC_ADDR,imm); 00326 dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); 00327 MOV_REG_WORD_FROM_HOST_REG(FC_OP1,DRC_REG_EAX,decode.big_op); 00328 } 00329 00330 static void dyn_mov_byte_direct_al() { 00331 MOV_SEG_PHYS_TO_HOST_REG(FC_ADDR,(decode.seg_prefix_used ? decode.seg_prefix : DRC_SEG_DS)); 00332 if (decode.big_addr) { 00333 Bitu val; 00334 if (decode_fetchd_imm(val)) { 00335 gen_add(FC_ADDR,(void*)val); 00336 } else { 00337 gen_add_imm(FC_ADDR,(Bit32u)val); 00338 } 00339 } else { 00340 gen_add_imm(FC_ADDR,decode_fetchw()); 00341 } 00342 MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA1,DRC_REG_EAX,0); 00343 dyn_write_byte(FC_ADDR,FC_TMP_BA1); 00344 } 00345 00346 static void dyn_mov_byte_direct_ax(Bit32u imm) { 00347 MOV_SEG_PHYS_TO_HOST_REG(FC_ADDR,(decode.seg_prefix_used ? decode.seg_prefix : DRC_SEG_DS)); 00348 gen_add_imm(FC_ADDR,imm); 00349 MOV_REG_WORD_TO_HOST_REG(FC_OP1,DRC_REG_EAX,decode.big_op); 00350 dyn_write_word(FC_ADDR,FC_OP1,decode.big_op); 00351 } 00352 00353 00354 static void dyn_movx_ev_gb(bool sign) { 00355 dyn_get_modrm(); 00356 if (decode.modrm.mod<3) { 00357 dyn_fill_ea(FC_ADDR); 00358 dyn_read_byte(FC_ADDR,FC_TMP_BA1); 00359 gen_extend_byte(sign,FC_TMP_BA1); 00360 MOV_REG_WORD_FROM_HOST_REG(FC_TMP_BA1,decode.modrm.reg,decode.big_op); 00361 } else { 00362 MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.rm&3,((decode.modrm.rm>>2)&1)); 00363 gen_extend_byte(sign,FC_TMP_BA1); 00364 MOV_REG_WORD_FROM_HOST_REG(FC_TMP_BA1,decode.modrm.reg,decode.big_op); 00365 } 00366 } 00367 00368 static void dyn_movx_ev_gw(bool sign) { 00369 dyn_get_modrm(); 00370 if (decode.modrm.mod<3) { 00371 dyn_fill_ea(FC_ADDR); 00372 dyn_read_word(FC_ADDR,FC_OP1,false); 00373 gen_extend_word(sign,FC_OP1); 00374 MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); 00375 } else { 00376 MOV_REG_WORD16_TO_HOST_REG(FC_OP1,decode.modrm.rm); 00377 gen_extend_word(sign,FC_OP1); 00378 MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); 00379 } 00380 } 00381 00382 00383 static void dyn_mov_ev_seg(void) { 00384 dyn_get_modrm(); 00385 MOV_SEG_VAL_TO_HOST_REG(FC_OP1,decode.modrm.reg); 00386 if (decode.modrm.mod<3) { 00387 dyn_fill_ea(FC_ADDR); 00388 dyn_write_word(FC_ADDR,FC_OP1,false); 00389 } else { 00390 if (decode.big_op) gen_extend_word(false,FC_OP1); 00391 MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); 00392 } 00393 } 00394 00395 00396 static void dyn_lea(void) { 00397 dyn_get_modrm(); 00398 dyn_fill_ea(FC_ADDR,false); 00399 MOV_REG_WORD_FROM_HOST_REG(FC_ADDR,decode.modrm.reg,decode.big_op); 00400 } 00401 00402 00403 static void dyn_push_seg(Bit8u seg) { 00404 MOV_SEG_VAL_TO_HOST_REG(FC_OP1,seg); 00405 if (decode.big_op) { 00406 gen_extend_word(false,FC_OP1); 00407 gen_call_function_raw(dynrec_push_dword); 00408 } else { 00409 gen_call_function_raw(dynrec_push_word); 00410 } 00411 } 00412 00413 static void dyn_pop_seg(Bit8u seg) { 00414 gen_call_function_II(CPU_PopSeg,seg,decode.big_op); 00415 dyn_check_exception(FC_RETOP); 00416 } 00417 00418 static void dyn_push_reg(Bit8u reg) { 00419 MOV_REG_WORD_TO_HOST_REG(FC_OP1,reg,decode.big_op); 00420 if (decode.big_op) gen_call_function_raw(dynrec_push_dword); 00421 else gen_call_function_raw(dynrec_push_word); 00422 } 00423 00424 static void dyn_pop_reg(Bit8u reg) { 00425 if (decode.big_op) gen_call_function_raw(dynrec_pop_dword); 00426 else gen_call_function_raw(dynrec_pop_word); 00427 MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,reg,decode.big_op); 00428 } 00429 00430 static void dyn_push_byte_imm(Bit8s imm) { 00431 gen_mov_dword_to_reg_imm(FC_OP1,(Bit32u)imm); 00432 if (decode.big_op) gen_call_function_raw(dynrec_push_dword); 00433 else gen_call_function_raw(dynrec_push_word); 00434 } 00435 00436 static void dyn_push_word_imm(Bit32u imm) { 00437 if (decode.big_op) { 00438 gen_mov_dword_to_reg_imm(FC_OP1,imm); 00439 gen_call_function_raw(dynrec_push_dword); 00440 } else { 00441 gen_mov_word_to_reg_imm(FC_OP1,(Bit16u)imm); 00442 gen_call_function_raw(dynrec_push_word); 00443 } 00444 } 00445 00446 static void dyn_pop_ev(void) { 00447 dyn_get_modrm(); 00448 if (decode.modrm.mod<3) { 00449 // save original ESP 00450 MOV_REG_WORD32_TO_HOST_REG(FC_OP2,DRC_REG_ESP); 00451 gen_protect_reg(FC_OP2); 00452 if (decode.big_op) gen_call_function_raw(dynrec_pop_dword); 00453 else gen_call_function_raw(dynrec_pop_word); 00454 dyn_fill_ea(FC_ADDR); 00455 gen_mov_regs(FC_OP2,FC_RETOP); 00456 gen_mov_regs(FC_OP1,FC_ADDR); 00457 if (decode.big_op) gen_call_function_raw(mem_writed_checked_drc); 00458 else gen_call_function_raw(mem_writew_checked_drc); 00459 gen_extend_byte(false,FC_RETOP); // bool -> dword 00460 DRC_PTR_SIZE_IM no_fault = gen_create_branch_on_zero(FC_RETOP, true); 00461 // restore original ESP 00462 gen_restore_reg(FC_OP2); 00463 MOV_REG_WORD32_FROM_HOST_REG(FC_OP2,DRC_REG_ESP); 00464 dyn_check_exception(FC_RETOP); 00465 gen_fill_branch(no_fault); 00466 } else { 00467 if (decode.big_op) gen_call_function_raw(dynrec_pop_dword); 00468 else gen_call_function_raw(dynrec_pop_word); 00469 MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.rm,decode.big_op); 00470 } 00471 } 00472 00473 00474 static void dyn_segprefix(Bit8u seg) { 00475 // if (GCC_UNLIKELY(decode.seg_prefix_used)) IllegalOptionDynrec("dyn_segprefix"); 00476 decode.seg_prefix=seg; 00477 decode.seg_prefix_used=true; 00478 } 00479 00480 static void dyn_mov_seg_ev(void) { 00481 dyn_get_modrm(); 00482 if (GCC_UNLIKELY(decode.modrm.reg==DRC_SEG_CS)) IllegalOptionDynrec("dyn_mov_seg_ev"); 00483 if (decode.modrm.mod<3) { 00484 dyn_fill_ea(FC_ADDR); 00485 dyn_read_word(FC_ADDR,FC_RETOP,false); 00486 } else { 00487 MOV_REG_WORD16_TO_HOST_REG(FC_RETOP,decode.modrm.rm); 00488 } 00489 gen_call_function_IR(CPU_SetSegGeneral,decode.modrm.reg,FC_RETOP); 00490 dyn_check_exception(FC_RETOP); 00491 } 00492 00493 static void dyn_load_seg_off_ea(Bit8u seg) { 00494 if (decode.modrm.mod<3) { 00495 dyn_fill_ea(FC_ADDR); 00496 gen_protect_addr_reg(); 00497 dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); 00498 gen_protect_reg(FC_OP1); 00499 00500 gen_restore_addr_reg(); 00501 gen_add_imm(FC_ADDR,decode.big_op ? 4:2); 00502 dyn_read_word(FC_ADDR,FC_RETOP,false); 00503 00504 gen_call_function_IR(CPU_SetSegGeneral,seg,FC_RETOP); 00505 dyn_check_exception(FC_RETOP); 00506 00507 gen_restore_reg(FC_OP1); 00508 MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op); 00509 } else { 00510 IllegalOptionDynrec("dyn_load_seg_off_ea"); 00511 } 00512 } 00513 00514 00515 00516 static void dyn_imul_gvev(Bitu immsize) { 00517 dyn_get_modrm(); 00518 if (decode.modrm.mod<3) { 00519 dyn_fill_ea(FC_ADDR); 00520 dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); 00521 } else { 00522 MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); 00523 } 00524 00525 switch (immsize) { 00526 case 0: 00527 MOV_REG_WORD_TO_HOST_REG(FC_OP2,decode.modrm.reg,decode.big_op); 00528 break; 00529 case 1: 00530 if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,(Bit8s)decode_fetchb()); 00531 else gen_mov_word_to_reg_imm(FC_OP2,(Bit8s)decode_fetchb()); 00532 break; 00533 case 2: 00534 if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,(Bit16s)decode_fetchw()); 00535 else gen_mov_word_to_reg_imm(FC_OP2,(Bit16s)decode_fetchw()); 00536 break; 00537 case 4: 00538 if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,(Bit32s)decode_fetchd()); 00539 else gen_mov_word_to_reg_imm(FC_OP2,(Bit16u)((Bit32s)decode_fetchd())); 00540 break; 00541 } 00542 00543 if (decode.big_op) gen_call_function_raw(dynrec_dimul_dword); 00544 else gen_call_function_raw(dynrec_dimul_word); 00545 00546 MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.reg,decode.big_op); 00547 } 00548 00549 static void dyn_dshift_ev_gv(bool left,bool immediate) { 00550 dyn_get_modrm(); 00551 if (decode.modrm.mod<3) { 00552 dyn_fill_ea(FC_ADDR); 00553 gen_protect_addr_reg(); 00554 dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); 00555 } else { 00556 MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); 00557 } 00558 MOV_REG_WORD_TO_HOST_REG(FC_OP2,decode.modrm.reg,decode.big_op); 00559 if (immediate) gen_mov_byte_to_reg_low_imm(FC_OP3,decode_fetchb()); 00560 else MOV_REG_BYTE_TO_HOST_REG_LOW(FC_OP3,DRC_REG_ECX,0); 00561 if (decode.big_op) dyn_dpshift_dword_gencall(left); 00562 else dyn_dpshift_word_gencall(left); 00563 00564 if (decode.modrm.mod<3) { 00565 gen_restore_addr_reg(); 00566 dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op); 00567 } else { 00568 MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.rm,decode.big_op); 00569 } 00570 } 00571 00572 00573 static void dyn_grp1_eb_ib(void) { 00574 dyn_get_modrm(); 00575 DualOps op=grp1_table[decode.modrm.reg]; 00576 if (decode.modrm.mod<3) { 00577 dyn_fill_ea(FC_ADDR); 00578 gen_protect_addr_reg(); 00579 dyn_read_byte_canuseword(FC_ADDR,FC_OP1); 00580 gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,decode_fetchb()); 00581 dyn_dop_byte_gencall(op); 00582 00583 if ((op!=DOP_CMP) && (op!=DOP_TEST)) { 00584 gen_restore_addr_reg(); 00585 dyn_write_byte(FC_ADDR,FC_RETOP); 00586 } 00587 } else { 00588 dyn_dop_byte_imm_mem(op,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); 00589 } 00590 } 00591 00592 static void dyn_grp1_ev_iv(bool withbyte) { 00593 dyn_get_modrm(); 00594 DualOps op=grp1_table[decode.modrm.reg]; 00595 if (decode.modrm.mod<3) { 00596 dyn_fill_ea(FC_ADDR); 00597 gen_protect_addr_reg(); 00598 dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); 00599 00600 if (!withbyte) { 00601 dyn_prep_word_imm(FC_OP2); 00602 } else { 00603 Bits imm=(Bit8s)decode_fetchb(); 00604 if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,(Bit32u)imm); 00605 else gen_mov_word_to_reg_imm(FC_OP2,(Bit16u)imm); 00606 } 00607 00608 dyn_dop_word_gencall(op,decode.big_op); 00609 00610 if ((op!=DOP_CMP) && (op!=DOP_TEST)) { 00611 gen_restore_addr_reg(); 00612 dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op); 00613 } 00614 } else { 00615 if (!withbyte) { 00616 dyn_dop_word_imm(op,decode.modrm.rm); 00617 } else { 00618 Bits imm=withbyte ? (Bit8s)decode_fetchb() : (decode.big_op ? decode_fetchd(): decode_fetchw()); 00619 dyn_dop_word_imm_old(op,decode.modrm.rm,imm); 00620 } 00621 } 00622 } 00623 00624 00625 static void dyn_grp2_eb(grp2_types type) { 00626 dyn_get_modrm(); 00627 if (decode.modrm.mod<3) { 00628 dyn_fill_ea(FC_ADDR); 00629 gen_protect_addr_reg(); 00630 dyn_read_byte_canuseword(FC_ADDR,FC_OP1); 00631 } else { 00632 MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,decode.modrm.rm&3,((decode.modrm.rm>>2)&1)); 00633 } 00634 switch (type) { 00635 case grp2_1: 00636 gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,1); 00637 dyn_shift_byte_gencall((ShiftOps)decode.modrm.reg); 00638 break; 00639 case grp2_imm: { 00640 Bit8u imm=decode_fetchb(); 00641 if (imm) { 00642 gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,imm&0x1f); 00643 dyn_shift_byte_gencall((ShiftOps)decode.modrm.reg); 00644 } else return; 00645 } 00646 break; 00647 case grp2_cl: 00648 MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP2,DRC_REG_ECX,0); 00649 gen_and_imm(FC_OP2,0x1f); 00650 dyn_shift_byte_gencall((ShiftOps)decode.modrm.reg); 00651 break; 00652 } 00653 if (decode.modrm.mod<3) { 00654 gen_restore_addr_reg(); 00655 dyn_write_byte(FC_ADDR,FC_RETOP); 00656 } else { 00657 MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,decode.modrm.rm&3,((decode.modrm.rm>>2)&1)); 00658 } 00659 } 00660 00661 static void dyn_grp2_ev(grp2_types type) { 00662 dyn_get_modrm(); 00663 if (decode.modrm.mod<3) { 00664 dyn_fill_ea(FC_ADDR); 00665 gen_protect_addr_reg(); 00666 dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); 00667 } else { 00668 MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); 00669 } 00670 switch (type) { 00671 case grp2_1: 00672 gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,1); 00673 dyn_shift_word_gencall((ShiftOps)decode.modrm.reg,decode.big_op); 00674 break; 00675 case grp2_imm: { 00676 Bitu val; 00677 if (decode_fetchb_imm(val)) { 00678 gen_mov_byte_to_reg_low_canuseword(FC_OP2,(void*)val); 00679 gen_and_imm(FC_OP2,0x1f); 00680 dyn_shift_word_gencall((ShiftOps)decode.modrm.reg,decode.big_op); 00681 break; 00682 } 00683 Bit8u imm=(Bit8u)val; 00684 if (imm) { 00685 gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,imm&0x1f); 00686 dyn_shift_word_gencall((ShiftOps)decode.modrm.reg,decode.big_op); 00687 } else return; 00688 } 00689 break; 00690 case grp2_cl: 00691 MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP2,DRC_REG_ECX,0); 00692 gen_and_imm(FC_OP2,0x1f); 00693 dyn_shift_word_gencall((ShiftOps)decode.modrm.reg,decode.big_op); 00694 break; 00695 } 00696 if (decode.modrm.mod<3) { 00697 gen_restore_addr_reg(); 00698 dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op); 00699 } else { 00700 MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.rm,decode.big_op); 00701 } 00702 } 00703 00704 00705 static void dyn_grp3_eb(void) { 00706 dyn_get_modrm(); 00707 if (decode.modrm.mod<3) { 00708 dyn_fill_ea(FC_ADDR); 00709 if ((decode.modrm.reg==2) || (decode.modrm.reg==3)) gen_protect_addr_reg(); 00710 dyn_read_byte_canuseword(FC_ADDR,FC_OP1); 00711 } else { 00712 MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,decode.modrm.rm&3,((decode.modrm.rm>>2)&1)); 00713 } 00714 switch (decode.modrm.reg) { 00715 case 0x0: // test eb,ib 00716 gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,decode_fetchb()); 00717 dyn_dop_byte_gencall(DOP_TEST); 00718 return; 00719 case 0x2: // NOT Eb 00720 dyn_sop_byte_gencall(SOP_NOT); 00721 break; 00722 case 0x3: // NEG Eb 00723 dyn_sop_byte_gencall(SOP_NEG); 00724 break; 00725 case 0x4: // mul Eb 00726 gen_call_function_raw(dynrec_mul_byte); 00727 return; 00728 case 0x5: // imul Eb 00729 gen_call_function_raw(dynrec_imul_byte); 00730 return; 00731 case 0x6: // div Eb 00732 gen_call_function_raw(dynrec_div_byte); 00733 dyn_check_exception(FC_RETOP); 00734 return; 00735 case 0x7: // idiv Eb 00736 gen_call_function_raw(dynrec_idiv_byte); 00737 dyn_check_exception(FC_RETOP); 00738 return; 00739 } 00740 // Save the result if memory op 00741 if (decode.modrm.mod<3) { 00742 gen_restore_addr_reg(); 00743 dyn_write_byte(FC_ADDR,FC_RETOP); 00744 } else { 00745 MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,decode.modrm.rm&3,((decode.modrm.rm>>2)&1)); 00746 } 00747 } 00748 00749 static void dyn_grp3_ev(void) { 00750 dyn_get_modrm(); 00751 if (decode.modrm.mod<3) { 00752 dyn_fill_ea(FC_ADDR); 00753 if ((decode.modrm.reg==2) || (decode.modrm.reg==3)) gen_protect_addr_reg(); 00754 dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); 00755 } else { 00756 MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); 00757 } 00758 switch (decode.modrm.reg) { 00759 case 0x0: // test ev,iv 00760 if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,decode_fetchd()); 00761 else gen_mov_word_to_reg_imm(FC_OP2,decode_fetchw()); 00762 dyn_dop_word_gencall(DOP_TEST,decode.big_op); 00763 return; 00764 case 0x2: // NOT Ev 00765 dyn_sop_word_gencall(SOP_NOT,decode.big_op); 00766 break; 00767 case 0x3: // NEG Eb 00768 dyn_sop_word_gencall(SOP_NEG,decode.big_op); 00769 break; 00770 case 0x4: // mul Eb 00771 if (decode.big_op) gen_call_function_raw(dynrec_mul_dword); 00772 else gen_call_function_raw(dynrec_mul_word); 00773 return; 00774 case 0x5: // imul Eb 00775 if (decode.big_op) gen_call_function_raw(dynrec_imul_dword); 00776 else gen_call_function_raw(dynrec_imul_word); 00777 return; 00778 case 0x6: // div Eb 00779 if (decode.big_op) gen_call_function_raw(dynrec_div_dword); 00780 else gen_call_function_raw(dynrec_div_word); 00781 dyn_check_exception(FC_RETOP); 00782 return; 00783 case 0x7: // idiv Eb 00784 if (decode.big_op) gen_call_function_raw(dynrec_idiv_dword); 00785 else gen_call_function_raw(dynrec_idiv_word); 00786 dyn_check_exception(FC_RETOP); 00787 return; 00788 } 00789 // Save the result if memory op 00790 if (decode.modrm.mod<3) { 00791 gen_restore_addr_reg(); 00792 dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op); 00793 } else { 00794 MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.rm,decode.big_op); 00795 } 00796 } 00797 00798 00799 static bool dyn_grp4_eb(void) { 00800 dyn_get_modrm(); 00801 switch (decode.modrm.reg) { 00802 case 0x0://INC Eb 00803 case 0x1://DEC Eb 00804 if (decode.modrm.mod<3) { 00805 dyn_fill_ea(FC_ADDR); 00806 gen_protect_addr_reg(); 00807 dyn_read_byte_canuseword(FC_ADDR,FC_OP1); 00808 dyn_sop_byte_gencall(decode.modrm.reg==0 ? SOP_INC : SOP_DEC); 00809 gen_restore_addr_reg(); 00810 dyn_write_byte(FC_ADDR,FC_RETOP); 00811 } else { 00812 MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,decode.modrm.rm&3,((decode.modrm.rm>>2)&1)); 00813 dyn_sop_byte_gencall(decode.modrm.reg==0 ? SOP_INC : SOP_DEC); 00814 MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,decode.modrm.rm&3,((decode.modrm.rm>>2)&1)); 00815 } 00816 break; 00817 case 0x7: //CALBACK Iw 00818 gen_mov_direct_dword(&core_dynrec.callback,decode_fetchw()); 00819 dyn_set_eip_end(); 00820 dyn_reduce_cycles(); 00821 dyn_return(BR_CallBack); 00822 dyn_closeblock(); 00823 return true; 00824 default: 00825 IllegalOptionDynrec("dyn_grp4_eb"); 00826 break; 00827 } 00828 return false; 00829 } 00830 00831 static Bitu dyn_grp4_ev(void) { 00832 dyn_get_modrm(); 00833 if (decode.modrm.mod<3) { 00834 dyn_fill_ea(FC_ADDR); 00835 if ((decode.modrm.reg<2) || (decode.modrm.reg==3) || (decode.modrm.reg==5)) gen_protect_addr_reg(); 00836 dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); 00837 } else { 00838 MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op); 00839 } 00840 switch (decode.modrm.reg) { 00841 case 0x0://INC Ev 00842 case 0x1://DEC Ev 00843 dyn_sop_word_gencall(decode.modrm.reg==0 ? SOP_INC : SOP_DEC,decode.big_op); 00844 if (decode.modrm.mod<3) { 00845 gen_restore_addr_reg(); 00846 dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op); 00847 } else { 00848 MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.rm,decode.big_op); 00849 } 00850 break; 00851 case 0x2: // CALL Ev 00852 gen_mov_regs(FC_ADDR,FC_OP1); 00853 gen_protect_addr_reg(); 00854 gen_mov_word_to_reg(FC_OP1,decode.big_op?(void*)(®_eip):(void*)(®_ip),decode.big_op); 00855 gen_add_imm(FC_OP1,(Bit32u)(decode.code-decode.code_start)); 00856 if (decode.big_op) gen_call_function_raw(dynrec_push_dword); 00857 else gen_call_function_raw(dynrec_push_word); 00858 00859 gen_restore_addr_reg(); 00860 gen_mov_word_from_reg(FC_ADDR,decode.big_op?(void*)(®_eip):(void*)(®_ip),decode.big_op); 00861 return 1; 00862 case 0x4: // JMP Ev 00863 gen_mov_word_from_reg(FC_OP1,decode.big_op?(void*)(®_eip):(void*)(®_ip),decode.big_op); 00864 return 1; 00865 case 0x3: // CALL Ep 00866 case 0x5: // JMP Ep 00867 if (!decode.big_op) gen_extend_word(false,FC_OP1); 00868 if (decode.modrm.mod<3) gen_restore_addr_reg(); 00869 gen_protect_reg(FC_OP1); 00870 gen_add_imm(FC_ADDR,decode.big_op?4:2); 00871 dyn_read_word(FC_ADDR,FC_OP2,decode.big_op); 00872 gen_extend_word(false,FC_OP2); 00873 00874 dyn_set_eip_last_end(FC_RETOP); 00875 gen_restore_reg(FC_OP1,FC_ADDR); 00876 gen_call_function_IRRR(decode.modrm.reg == 3 ? CPU_CALL : CPU_JMP, 00877 decode.big_op,FC_OP2,FC_ADDR,FC_RETOP); 00878 return 1; 00879 case 0x6: // PUSH Ev 00880 if (decode.big_op) gen_call_function_raw(dynrec_push_dword); 00881 else gen_call_function_raw(dynrec_push_word); 00882 break; 00883 default: 00884 // IllegalOptionDynrec("dyn_grp4_ev"); 00885 return 2; 00886 } 00887 return 0; 00888 } 00889 00890 00891 static bool dyn_grp6(void) { 00892 dyn_get_modrm(); 00893 switch (decode.modrm.reg) { 00894 case 0x00: // SLDT 00895 case 0x01: // STR 00896 if (decode.modrm.reg==0) gen_call_function_raw(CPU_SLDT); 00897 else gen_call_function_raw(CPU_STR); 00898 if (decode.modrm.mod<3) { 00899 dyn_fill_ea(FC_ADDR); 00900 dyn_write_word(FC_ADDR,FC_RETOP,false); 00901 } else { 00902 MOV_REG_WORD16_FROM_HOST_REG(FC_RETOP,decode.modrm.rm); 00903 } 00904 break; 00905 case 0x02: // LLDT 00906 case 0x03: // LTR 00907 case 0x04: // VERR 00908 case 0x05: // VERW 00909 if (decode.modrm.mod<3) { 00910 dyn_fill_ea(FC_ADDR); 00911 dyn_read_word(FC_ADDR,FC_RETOP,false); 00912 } else { 00913 MOV_REG_WORD16_TO_HOST_REG(FC_RETOP,decode.modrm.rm); 00914 } 00915 gen_extend_word(false,FC_RETOP); 00916 switch (decode.modrm.reg) { 00917 case 0x02: // LLDT 00918 // if (cpu.cpl) return CPU_PrepareException(EXCEPTION_GP,0); 00919 if (cpu.cpl) E_Exit("lldt cpl>0"); 00920 gen_call_function_R(CPU_LLDT,FC_RETOP); 00921 dyn_check_exception(FC_RETOP); 00922 break; 00923 case 0x03: // LTR 00924 // if (cpu.cpl) return CPU_PrepareException(EXCEPTION_GP,0); 00925 if (cpu.cpl) E_Exit("ltr cpl>0"); 00926 gen_call_function_R(CPU_LTR,FC_RETOP); 00927 dyn_check_exception(FC_RETOP); 00928 break; 00929 case 0x04: // VERR 00930 gen_call_function_R(CPU_VERR,FC_RETOP); 00931 break; 00932 case 0x05: // VERW 00933 gen_call_function_R(CPU_VERW,FC_RETOP); 00934 break; 00935 } 00936 break; 00937 default: IllegalOptionDynrec("dyn_grp6"); 00938 } 00939 return false; 00940 } 00941 00942 static bool dyn_grp7(void) { 00943 dyn_get_modrm(); 00944 if (decode.modrm.mod<3) { 00945 switch (decode.modrm.reg) { 00946 case 0x00: // SGDT 00947 gen_call_function_raw(CPU_SGDT_limit); 00948 dyn_fill_ea(FC_ADDR); 00949 gen_protect_addr_reg(); 00950 dyn_write_word(FC_ADDR,FC_RETOP,false); 00951 gen_call_function_raw(CPU_SGDT_base); 00952 gen_restore_addr_reg(); 00953 gen_add_imm(FC_ADDR,2); 00954 dyn_write_word(FC_ADDR,FC_RETOP,true); 00955 break; 00956 case 0x01: // SIDT 00957 gen_call_function_raw(CPU_SIDT_limit); 00958 dyn_fill_ea(FC_ADDR); 00959 gen_protect_addr_reg(); 00960 dyn_write_word(FC_ADDR,FC_RETOP,false); 00961 gen_call_function_raw(CPU_SIDT_base); 00962 gen_restore_addr_reg(); 00963 gen_add_imm(FC_ADDR,2); 00964 dyn_write_word(FC_ADDR,FC_RETOP,true); 00965 break; 00966 case 0x02: // LGDT 00967 case 0x03: // LIDT 00968 // if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); 00969 if (cpu.pmode && cpu.cpl) IllegalOptionDynrec("lgdt nonpriviledged"); 00970 dyn_fill_ea(FC_ADDR); 00971 gen_protect_addr_reg(); 00972 dyn_read_word(FC_ADDR,FC_OP1,false); 00973 gen_extend_word(false,FC_OP1); 00974 gen_protect_reg(FC_OP1); 00975 00976 gen_restore_addr_reg(); 00977 gen_add_imm(FC_ADDR,2); 00978 dyn_read_word(FC_ADDR,FC_OP2,true); 00979 if (!decode.big_op) gen_and_imm(FC_OP2,0xffffff); 00980 00981 gen_restore_reg(FC_OP1); 00982 if (decode.modrm.reg==2) gen_call_function_RR(CPU_LGDT,FC_OP1,FC_OP2); 00983 else gen_call_function_RR(CPU_LIDT,FC_OP1,FC_OP2); 00984 break; 00985 case 0x04: // SMSW 00986 gen_call_function_raw(CPU_SMSW); 00987 dyn_fill_ea(FC_ADDR); 00988 dyn_write_word(FC_ADDR,FC_RETOP,false); 00989 break; 00990 case 0x06: // LMSW 00991 dyn_fill_ea(FC_ADDR); 00992 dyn_read_word(FC_ADDR,FC_RETOP,false); 00993 gen_call_function_R(CPU_LMSW,FC_RETOP); 00994 dyn_check_exception(FC_RETOP); 00995 dyn_set_eip_end(); 00996 dyn_reduce_cycles(); 00997 dyn_return(BR_Normal); 00998 dyn_closeblock(); 00999 return true; 01000 case 0x07: // INVLPG 01001 // if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); 01002 if (cpu.pmode && cpu.cpl) IllegalOptionDynrec("invlpg nonpriviledged"); 01003 gen_call_function_raw(PAGING_ClearTLB); 01004 break; 01005 default: IllegalOptionDynrec("dyn_grp7_1"); 01006 } 01007 } else { 01008 switch (decode.modrm.reg) { 01009 case 0x04: // SMSW 01010 gen_call_function_raw(CPU_SMSW); 01011 MOV_REG_WORD16_FROM_HOST_REG(FC_RETOP,decode.modrm.rm); 01012 break; 01013 case 0x06: // LMSW 01014 MOV_REG_WORD16_TO_HOST_REG(FC_RETOP,decode.modrm.rm); 01015 gen_call_function_R(CPU_LMSW,FC_RETOP); 01016 dyn_check_exception(FC_RETOP); 01017 dyn_set_eip_end(); 01018 dyn_reduce_cycles(); 01019 dyn_return(BR_Normal); 01020 dyn_closeblock(); 01021 return true; 01022 default: IllegalOptionDynrec("dyn_grp7_2"); 01023 } 01024 } 01025 return false; 01026 } 01027 01028 01029 /* 01030 static void dyn_larlsl(bool is_lar) { 01031 dyn_get_modrm(); 01032 if (decode.modrm.mod<3) { 01033 dyn_fill_ea(FC_ADDR); 01034 dyn_read_word(FC_ADDR,FC_RETOP,false); 01035 } else { 01036 MOV_REG_WORD16_TO_HOST_REG(FC_RETOP,decode.modrm.rm); 01037 } 01038 gen_extend_word(false,FC_RETOP); 01039 if (is_lar) gen_call_function((void*)CPU_LAR,"%R%A",FC_RETOP,(DRC_PTR_SIZE_IM)&core_dynrec.readdata); 01040 else gen_call_function((void*)CPU_LSL,"%R%A",FC_RETOP,(DRC_PTR_SIZE_IM)&core_dynrec.readdata); 01041 DRC_PTR_SIZE_IM brnz=gen_create_branch_on_nonzero(FC_RETOP,true); 01042 gen_mov_word_to_reg(FC_OP2,&core_dynrec.readdata,true); 01043 MOV_REG_WORD_FROM_HOST_REG(FC_OP2,decode.modrm.reg,decode.big_op); 01044 gen_fill_branch(brnz); 01045 } 01046 */ 01047 01048 01049 static void dyn_mov_from_crx(void) { 01050 dyn_get_modrm(); 01051 gen_call_function_IA(CPU_READ_CRX,decode.modrm.reg,(DRC_PTR_SIZE_IM)&core_dynrec.readdata); 01052 dyn_check_exception(FC_RETOP); 01053 gen_mov_word_to_reg(FC_OP2,&core_dynrec.readdata,true); 01054 MOV_REG_WORD32_FROM_HOST_REG(FC_OP2,decode.modrm.rm); 01055 } 01056 01057 static void dyn_mov_to_crx(void) { 01058 dyn_get_modrm(); 01059 MOV_REG_WORD32_TO_HOST_REG(FC_RETOP,decode.modrm.rm); 01060 gen_call_function_IR(CPU_WRITE_CRX,decode.modrm.reg,FC_RETOP); 01061 dyn_check_exception(FC_RETOP); 01062 dyn_set_eip_end(); 01063 dyn_reduce_cycles(); 01064 dyn_return(BR_Normal); 01065 dyn_closeblock(); 01066 } 01067 01068 01069 static void dyn_cbw(void) { 01070 if (decode.big_op) { 01071 MOV_REG_WORD16_TO_HOST_REG(FC_OP1,DRC_REG_EAX); 01072 gen_call_function_raw(dynrec_cwde); 01073 MOV_REG_WORD32_FROM_HOST_REG(FC_RETOP,DRC_REG_EAX); 01074 } else { 01075 MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,DRC_REG_EAX,0); 01076 gen_call_function_raw(dynrec_cbw); 01077 MOV_REG_WORD16_FROM_HOST_REG(FC_RETOP,DRC_REG_EAX); 01078 } 01079 } 01080 01081 static void dyn_cwd(void) { 01082 MOV_REG_WORD_TO_HOST_REG(FC_OP1,DRC_REG_EAX,decode.big_op); 01083 if (decode.big_op) { 01084 gen_call_function_raw(dynrec_cdq); 01085 MOV_REG_WORD32_FROM_HOST_REG(FC_RETOP,DRC_REG_EDX); 01086 } else { 01087 gen_call_function_raw(dynrec_cwd); 01088 MOV_REG_WORD16_FROM_HOST_REG(FC_RETOP,DRC_REG_EDX); 01089 } 01090 } 01091 01092 static void dyn_sahf(void) { 01093 MOV_REG_WORD16_TO_HOST_REG(FC_OP1,DRC_REG_EAX); 01094 gen_call_function_raw(dynrec_sahf); 01095 InvalidateFlags(); 01096 } 01097 01098 01099 static void dyn_exit_link(Bit32s eip_change) { 01100 gen_add_direct_word(®_eip,(decode.code-decode.code_start)+eip_change,decode.big_op); 01101 dyn_reduce_cycles(); 01102 gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlockDynRec,cache.start)); 01103 dyn_closeblock(); 01104 } 01105 01106 01107 static void dyn_branched_exit(BranchTypes btype,Bit32s eip_add) { 01108 Bit32u eip_base=decode.code-decode.code_start; 01109 dyn_reduce_cycles(); 01110 01111 dyn_branchflag_to_reg(btype); 01112 DRC_PTR_SIZE_IM data=gen_create_branch_on_nonzero(FC_RETOP,true); 01113 01114 // Branch not taken 01115 gen_add_direct_word(®_eip,eip_base,decode.big_op); 01116 gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlockDynRec,cache.start)); 01117 gen_fill_branch(data); 01118 01119 // Branch taken 01120 gen_add_direct_word(®_eip,eip_base+eip_add,decode.big_op); 01121 gen_jmp_ptr(&decode.block->link[1].to,offsetof(CacheBlockDynRec,cache.start)); 01122 dyn_closeblock(); 01123 } 01124 01125 /* 01126 static void dyn_set_byte_on_condition(BranchTypes btype) { 01127 dyn_get_modrm(); 01128 dyn_branchflag_to_reg(btype); 01129 gen_and_imm(FC_RETOP,1); 01130 if (decode.modrm.mod<3) { 01131 dyn_fill_ea(FC_ADDR); 01132 dyn_write_byte(FC_ADDR,FC_RETOP); 01133 } else { 01134 MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); 01135 } 01136 } 01137 */ 01138 01139 static void dyn_loop(LoopTypes type) { 01140 dyn_reduce_cycles(); 01141 Bit8s eip_add=(Bit8s)decode_fetchb(); 01142 Bit32u eip_base=decode.code-decode.code_start; 01143 DRC_PTR_SIZE_IM branch1=0; 01144 DRC_PTR_SIZE_IM branch2=0; 01145 switch (type) { 01146 case LOOP_E: 01147 dyn_branchflag_to_reg(BR_NZ); 01148 branch1=gen_create_branch_on_nonzero(FC_RETOP,true); 01149 break; 01150 case LOOP_NE: 01151 dyn_branchflag_to_reg(BR_Z); 01152 branch1=gen_create_branch_on_nonzero(FC_RETOP,true); 01153 break; 01154 default: 01155 break; 01156 } 01157 switch (type) { 01158 case LOOP_E: 01159 case LOOP_NE: 01160 case LOOP_NONE: 01161 MOV_REG_WORD_TO_HOST_REG(FC_OP1,DRC_REG_ECX,decode.big_addr); 01162 gen_add_imm(FC_OP1,(Bit32u)(-1)); 01163 MOV_REG_WORD_FROM_HOST_REG(FC_OP1,DRC_REG_ECX,decode.big_addr); 01164 branch2=gen_create_branch_on_zero(FC_OP1,decode.big_addr); 01165 break; 01166 case LOOP_JCXZ: 01167 MOV_REG_WORD_TO_HOST_REG(FC_OP1,DRC_REG_ECX,decode.big_addr); 01168 branch2=gen_create_branch_on_nonzero(FC_OP1,decode.big_addr); 01169 break; 01170 default: 01171 break; 01172 } 01173 gen_add_direct_word(®_eip,eip_base+eip_add,true); 01174 gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlockDynRec,cache.start)); 01175 if (branch1) { 01176 gen_fill_branch(branch1); 01177 MOV_REG_WORD_TO_HOST_REG(FC_OP1,DRC_REG_ECX,decode.big_addr); 01178 gen_add_imm(FC_OP1,(Bit32u)(-1)); 01179 MOV_REG_WORD_FROM_HOST_REG(FC_OP1,DRC_REG_ECX,decode.big_addr); 01180 } 01181 // Branch taken 01182 gen_fill_branch(branch2); 01183 gen_add_direct_word(®_eip,eip_base,decode.big_op); 01184 gen_jmp_ptr(&decode.block->link[1].to,offsetof(CacheBlockDynRec,cache.start)); 01185 dyn_closeblock(); 01186 } 01187 01188 01189 static void dyn_ret_near(Bit16u bytes) { 01190 dyn_reduce_cycles(); 01191 01192 if (decode.big_op) gen_call_function_raw(dynrec_pop_dword); 01193 else { 01194 gen_call_function_raw(dynrec_pop_word); 01195 gen_extend_word(false,FC_RETOP); 01196 } 01197 gen_mov_word_from_reg(FC_RETOP,decode.big_op?(void*)(®_eip):(void*)(®_ip),true); 01198 01199 if (bytes) gen_add_direct_word(®_esp,bytes,true); 01200 dyn_return(BR_Normal); 01201 dyn_closeblock(); 01202 } 01203 01204 static void dyn_call_near_imm(void) { 01205 Bit32s imm; 01206 if (decode.big_op) imm=(Bit32s)decode_fetchd(); 01207 else imm=(Bit16s)decode_fetchw(); 01208 dyn_set_eip_end(FC_OP1); 01209 if (decode.big_op) gen_call_function_raw(dynrec_push_dword); 01210 else gen_call_function_raw(dynrec_push_word); 01211 01212 dyn_set_eip_end(FC_OP1,imm); 01213 gen_mov_word_from_reg(FC_OP1,decode.big_op?(void*)(®_eip):(void*)(®_ip),decode.big_op); 01214 01215 dyn_reduce_cycles(); 01216 gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlockDynRec,cache.start)); 01217 dyn_closeblock(); 01218 } 01219 01220 static void dyn_ret_far(Bitu bytes) { 01221 dyn_reduce_cycles(); 01222 dyn_set_eip_last_end(FC_RETOP); 01223 gen_call_function_IIR(CPU_RET,decode.big_op,bytes,FC_RETOP); 01224 dyn_return(BR_Normal); 01225 dyn_closeblock(); 01226 } 01227 01228 static void dyn_call_far_imm(void) { 01229 Bitu sel,off; 01230 off=decode.big_op ? decode_fetchd() : decode_fetchw(); 01231 sel=decode_fetchw(); 01232 dyn_reduce_cycles(); 01233 dyn_set_eip_last_end(FC_RETOP); 01234 gen_call_function_IIIR(CPU_CALL,decode.big_op,sel,off,FC_RETOP); 01235 dyn_return(BR_Normal); 01236 dyn_closeblock(); 01237 } 01238 01239 static void dyn_jmp_far_imm(void) { 01240 Bit16u sel; 01241 Bit32u off; 01242 off=decode.big_op ? decode_fetchd() : decode_fetchw(); 01243 sel=decode_fetchw(); 01244 dyn_reduce_cycles(); 01245 dyn_set_eip_last_end(FC_RETOP); 01246 gen_call_function_IIIR(CPU_JMP,decode.big_op,sel,off,FC_RETOP); 01247 dyn_return(BR_Normal); 01248 dyn_closeblock(); 01249 } 01250 01251 static void dyn_iret(void) { 01252 dyn_reduce_cycles(); 01253 dyn_set_eip_last_end(FC_RETOP); 01254 gen_call_function_IR(CPU_IRET,decode.big_op,FC_RETOP); 01255 dyn_return(BR_Iret); 01256 dyn_closeblock(); 01257 } 01258 01259 #if !(C_DEBUG) 01260 static void dyn_interrupt(Bit8u num) { 01261 dyn_reduce_cycles(); 01262 dyn_set_eip_last_end(FC_RETOP); 01263 gen_call_function_IIR(CPU_Interrupt,num,CPU_INT_SOFTWARE,FC_RETOP); 01264 dyn_return(BR_Normal); 01265 dyn_closeblock(); 01266 } 01267 #endif 01268 01269 01270 static void dyn_string(StringOps op) { 01271 if (decode.rep) MOV_REG_WORD_TO_HOST_REG(FC_OP1,DRC_REG_ECX,decode.big_addr); 01272 else gen_mov_dword_to_reg_imm(FC_OP1,1); 01273 gen_mov_word_to_reg(FC_OP2,&cpu.direction,true); 01274 Bit8u di_base_addr=decode.seg_prefix_used ? decode.seg_prefix : DRC_SEG_DS; 01275 switch (op) { 01276 case STR_MOVSB: 01277 if (decode.big_addr) gen_call_function_mm(dynrec_movsb_dword,(Bitu)DRCD_SEG_PHYS(di_base_addr),(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); 01278 else gen_call_function_mm(dynrec_movsb_word,(Bitu)DRCD_SEG_PHYS(di_base_addr),(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); 01279 break; 01280 case STR_MOVSW: 01281 if (decode.big_addr) gen_call_function_mm(dynrec_movsw_dword,(Bitu)DRCD_SEG_PHYS(di_base_addr),(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); 01282 else gen_call_function_mm(dynrec_movsw_word,(Bitu)DRCD_SEG_PHYS(di_base_addr),(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); 01283 break; 01284 case STR_MOVSD: 01285 if (decode.big_addr) gen_call_function_mm(dynrec_movsd_dword,(Bitu)DRCD_SEG_PHYS(di_base_addr),(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); 01286 else gen_call_function_mm(dynrec_movsd_word,(Bitu)DRCD_SEG_PHYS(di_base_addr),(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); 01287 break; 01288 01289 case STR_LODSB: 01290 if (decode.big_addr) gen_call_function_m(dynrec_lodsb_dword,(Bitu)DRCD_SEG_PHYS(di_base_addr)); 01291 else gen_call_function_m(dynrec_lodsb_word,(Bitu)DRCD_SEG_PHYS(di_base_addr)); 01292 break; 01293 case STR_LODSW: 01294 if (decode.big_addr) gen_call_function_m(dynrec_lodsw_dword,(Bitu)DRCD_SEG_PHYS(di_base_addr)); 01295 else gen_call_function_m(dynrec_lodsw_word,(Bitu)DRCD_SEG_PHYS(di_base_addr)); 01296 break; 01297 case STR_LODSD: 01298 if (decode.big_addr) gen_call_function_m(dynrec_lodsd_dword,(Bitu)DRCD_SEG_PHYS(di_base_addr)); 01299 else gen_call_function_m(dynrec_lodsd_word,(Bitu)DRCD_SEG_PHYS(di_base_addr)); 01300 break; 01301 01302 case STR_STOSB: 01303 if (decode.big_addr) gen_call_function_m(dynrec_stosb_dword,(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); 01304 else gen_call_function_m(dynrec_stosb_word,(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); 01305 break; 01306 case STR_STOSW: 01307 if (decode.big_addr) gen_call_function_m(dynrec_stosw_dword,(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); 01308 else gen_call_function_m(dynrec_stosw_word,(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); 01309 break; 01310 case STR_STOSD: 01311 if (decode.big_addr) gen_call_function_m(dynrec_stosd_dword,(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); 01312 else gen_call_function_m(dynrec_stosd_word,(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); 01313 break; 01314 default: IllegalOptionDynrec("dyn_string"); 01315 } 01316 if (decode.rep) MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,DRC_REG_ECX,decode.big_addr); 01317 01318 if (op<STR_SCASB) { 01319 // those string operations are allowed for premature termination 01320 // when not enough cycles left 01321 if (!decode.big_addr) gen_extend_word(false,FC_RETOP); 01322 save_info_dynrec[used_save_info_dynrec].branch_pos=gen_create_branch_long_nonzero(FC_RETOP,true); 01323 save_info_dynrec[used_save_info_dynrec].eip_change=decode.op_start-decode.code_start; 01324 save_info_dynrec[used_save_info_dynrec].type=string_break; 01325 used_save_info_dynrec++; 01326 } 01327 } 01328 01329 01330 static void dyn_read_port_byte_direct(Bit8u port) { 01331 dyn_add_iocheck_var(port,1); 01332 gen_call_function_I(IO_ReadB,port); 01333 MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,DRC_REG_EAX,0); 01334 } 01335 01336 static void dyn_read_port_word_direct(Bit8u port) { 01337 dyn_add_iocheck_var(port,decode.big_op?4:2); 01338 if (decode.big_op) 01339 gen_call_function_I(IO_ReadD,port); 01340 else 01341 gen_call_function_I(IO_ReadW,port); 01342 MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,DRC_REG_EAX,decode.big_op); 01343 } 01344 01345 static void dyn_write_port_byte_direct(Bit8u port) { 01346 dyn_add_iocheck_var(port,1); 01347 MOV_REG_BYTE_TO_HOST_REG_LOW(FC_RETOP,DRC_REG_EAX,0); 01348 gen_extend_byte(false,FC_RETOP); 01349 gen_call_function_IR(IO_WriteB,port,FC_RETOP); 01350 } 01351 01352 static void dyn_write_port_word_direct(Bit8u port) { 01353 dyn_add_iocheck_var(port,decode.big_op?4:2); 01354 MOV_REG_WORD_TO_HOST_REG(FC_RETOP,DRC_REG_EAX,decode.big_op); 01355 if (!decode.big_op) gen_extend_word(false,FC_RETOP); 01356 if (decode.big_op) 01357 gen_call_function_IR(IO_WriteD,port,FC_RETOP); 01358 else 01359 gen_call_function_IR(IO_WriteW,port,FC_RETOP); 01360 } 01361 01362 01363 static void dyn_read_port_byte(void) { 01364 MOV_REG_WORD16_TO_HOST_REG(FC_ADDR,DRC_REG_EDX); 01365 gen_extend_word(false,FC_ADDR); 01366 gen_protect_addr_reg(); 01367 dyn_add_iocheck(FC_ADDR,1); 01368 gen_restore_addr_reg(); 01369 gen_call_function_R(IO_ReadB,FC_ADDR); 01370 MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,DRC_REG_EAX,0); 01371 } 01372 01373 static void dyn_read_port_word(void) { 01374 MOV_REG_WORD16_TO_HOST_REG(FC_ADDR,DRC_REG_EDX); 01375 gen_extend_word(false,FC_ADDR); 01376 gen_protect_addr_reg(); 01377 dyn_add_iocheck(FC_ADDR,decode.big_op?4:2); 01378 gen_restore_addr_reg(); 01379 if (decode.big_op) 01380 gen_call_function_R(IO_ReadD,FC_ADDR); 01381 else 01382 gen_call_function_R(IO_ReadW,FC_ADDR); 01383 MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,DRC_REG_EAX,decode.big_op); 01384 } 01385 01386 static void dyn_write_port_byte(void) { 01387 MOV_REG_WORD16_TO_HOST_REG(FC_ADDR,DRC_REG_EDX); 01388 gen_extend_word(false,FC_ADDR); 01389 gen_protect_addr_reg(); 01390 dyn_add_iocheck(FC_ADDR,1); 01391 MOV_REG_BYTE_TO_HOST_REG_LOW(FC_RETOP,DRC_REG_EAX,0); 01392 gen_extend_byte(false,FC_RETOP); 01393 gen_restore_addr_reg(); 01394 gen_call_function_RR(IO_WriteB,FC_ADDR,FC_RETOP); 01395 } 01396 01397 static void dyn_write_port_word(void) { 01398 MOV_REG_WORD16_TO_HOST_REG(FC_ADDR,DRC_REG_EDX); 01399 gen_extend_word(false,FC_ADDR); 01400 gen_protect_addr_reg(); 01401 dyn_add_iocheck(FC_ADDR,decode.big_op?4:2); 01402 MOV_REG_WORD_TO_HOST_REG(FC_RETOP,DRC_REG_EAX,decode.big_op); 01403 if (!decode.big_op) gen_extend_word(false,FC_RETOP); 01404 gen_restore_addr_reg(); 01405 if (decode.big_op) 01406 gen_call_function_RR(IO_WriteD,FC_ADDR,FC_RETOP); 01407 else 01408 gen_call_function_RR(IO_WriteW,FC_ADDR,FC_RETOP); 01409 } 01410 01411 01412 static void dyn_enter(void) { 01413 Bitu bytes=decode_fetchw(); 01414 Bitu level=decode_fetchb(); 01415 gen_call_function_III(CPU_ENTER,decode.big_op,bytes,level); 01416 } 01417 01418 static void dynrec_leave_word(void) { 01419 reg_esp&=cpu.stack.notmask; 01420 reg_esp|=(reg_ebp&cpu.stack.mask); 01421 reg_bp=CPU_Pop16(); 01422 } 01423 01424 static void dynrec_leave_dword(void) { 01425 reg_esp&=cpu.stack.notmask; 01426 reg_esp|=(reg_ebp&cpu.stack.mask); 01427 reg_ebp=CPU_Pop32(); 01428 } 01429 01430 static void dyn_leave(void) { 01431 if (decode.big_op) gen_call_function_raw(dynrec_leave_dword); 01432 else gen_call_function_raw(dynrec_leave_word); 01433 } 01434 01435 01436 static void dynrec_pusha_word(void) { 01437 Bit16u old_sp=reg_sp; 01438 CPU_Push16(reg_ax);CPU_Push16(reg_cx);CPU_Push16(reg_dx);CPU_Push16(reg_bx); 01439 CPU_Push16(old_sp);CPU_Push16(reg_bp);CPU_Push16(reg_si);CPU_Push16(reg_di); 01440 } 01441 01442 static void dynrec_pusha_dword(void) { 01443 Bit32u tmpesp = reg_esp; 01444 CPU_Push32(reg_eax);CPU_Push32(reg_ecx);CPU_Push32(reg_edx);CPU_Push32(reg_ebx); 01445 CPU_Push32(tmpesp);CPU_Push32(reg_ebp);CPU_Push32(reg_esi);CPU_Push32(reg_edi); 01446 } 01447 01448 static void dynrec_popa_word(void) { 01449 reg_di=CPU_Pop16();reg_si=CPU_Pop16(); 01450 reg_bp=CPU_Pop16();CPU_Pop16(); //Don't save SP 01451 reg_bx=CPU_Pop16();reg_dx=CPU_Pop16(); 01452 reg_cx=CPU_Pop16();reg_ax=CPU_Pop16(); 01453 } 01454 01455 static void dynrec_popa_dword(void) { 01456 reg_edi=CPU_Pop32();reg_esi=CPU_Pop32();reg_ebp=CPU_Pop32();CPU_Pop32(); //Don't save ESP 01457 reg_ebx=CPU_Pop32();reg_edx=CPU_Pop32();reg_ecx=CPU_Pop32();reg_eax=CPU_Pop32(); 01458 }