DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/cpu/core_dynrec/decoder_opcodes.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 /*
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*)(&reg_eip):(void*)(&reg_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*)(&reg_eip):(void*)(&reg_ip),decode.big_op);
00861                 return 1;
00862         case 0x4:       // JMP Ev
00863                 gen_mov_word_from_reg(FC_OP1,decode.big_op?(void*)(&reg_eip):(void*)(&reg_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(&reg_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(&reg_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(&reg_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(&reg_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(&reg_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*)(&reg_eip):(void*)(&reg_ip),true);
01198 
01199         if (bytes) gen_add_direct_word(&reg_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*)(&reg_eip):(void*)(&reg_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 }