570 |
}; |
}; |
571 |
|
|
572 |
static GenOpFunc *gen_op_lds_T0_A0[3 * 3] = { |
static GenOpFunc *gen_op_lds_T0_A0[3 * 3] = { |
573 |
gen_op_ldsb_T0_A0, |
gen_op_ldsb_raw_T0_A0, |
574 |
gen_op_ldsw_T0_A0, |
gen_op_ldsw_raw_T0_A0, |
575 |
NULL, |
NULL, |
576 |
|
#ifndef CONFIG_USER_ONLY |
577 |
gen_op_ldsb_kernel_T0_A0, |
gen_op_ldsb_kernel_T0_A0, |
578 |
gen_op_ldsw_kernel_T0_A0, |
gen_op_ldsw_kernel_T0_A0, |
579 |
NULL, |
NULL, |
581 |
gen_op_ldsb_user_T0_A0, |
gen_op_ldsb_user_T0_A0, |
582 |
gen_op_ldsw_user_T0_A0, |
gen_op_ldsw_user_T0_A0, |
583 |
NULL, |
NULL, |
584 |
|
#endif |
585 |
}; |
}; |
586 |
|
|
587 |
static GenOpFunc *gen_op_ldu_T0_A0[3 * 3] = { |
static GenOpFunc *gen_op_ldu_T0_A0[3 * 3] = { |
588 |
gen_op_ldub_T0_A0, |
gen_op_ldub_raw_T0_A0, |
589 |
gen_op_lduw_T0_A0, |
gen_op_lduw_raw_T0_A0, |
590 |
NULL, |
NULL, |
591 |
|
|
592 |
|
#ifndef CONFIG_USER_ONLY |
593 |
gen_op_ldub_kernel_T0_A0, |
gen_op_ldub_kernel_T0_A0, |
594 |
gen_op_lduw_kernel_T0_A0, |
gen_op_lduw_kernel_T0_A0, |
595 |
NULL, |
NULL, |
597 |
gen_op_ldub_user_T0_A0, |
gen_op_ldub_user_T0_A0, |
598 |
gen_op_lduw_user_T0_A0, |
gen_op_lduw_user_T0_A0, |
599 |
NULL, |
NULL, |
600 |
|
#endif |
601 |
}; |
}; |
602 |
|
|
603 |
/* sign does not matter, except for lidt/lgdt call (TODO: fix it) */ |
/* sign does not matter, except for lidt/lgdt call (TODO: fix it) */ |
604 |
static GenOpFunc *gen_op_ld_T0_A0[3 * 3] = { |
static GenOpFunc *gen_op_ld_T0_A0[3 * 3] = { |
605 |
gen_op_ldub_T0_A0, |
gen_op_ldub_raw_T0_A0, |
606 |
gen_op_lduw_T0_A0, |
gen_op_lduw_raw_T0_A0, |
607 |
gen_op_ldl_T0_A0, |
gen_op_ldl_raw_T0_A0, |
608 |
|
|
609 |
|
#ifndef CONFIG_USER_ONLY |
610 |
gen_op_ldub_kernel_T0_A0, |
gen_op_ldub_kernel_T0_A0, |
611 |
gen_op_lduw_kernel_T0_A0, |
gen_op_lduw_kernel_T0_A0, |
612 |
gen_op_ldl_kernel_T0_A0, |
gen_op_ldl_kernel_T0_A0, |
614 |
gen_op_ldub_user_T0_A0, |
gen_op_ldub_user_T0_A0, |
615 |
gen_op_lduw_user_T0_A0, |
gen_op_lduw_user_T0_A0, |
616 |
gen_op_ldl_user_T0_A0, |
gen_op_ldl_user_T0_A0, |
617 |
|
#endif |
618 |
}; |
}; |
619 |
|
|
620 |
static GenOpFunc *gen_op_ld_T1_A0[3 * 3] = { |
static GenOpFunc *gen_op_ld_T1_A0[3 * 3] = { |
621 |
gen_op_ldub_T1_A0, |
gen_op_ldub_raw_T1_A0, |
622 |
gen_op_lduw_T1_A0, |
gen_op_lduw_raw_T1_A0, |
623 |
gen_op_ldl_T1_A0, |
gen_op_ldl_raw_T1_A0, |
624 |
|
|
625 |
|
#ifndef CONFIG_USER_ONLY |
626 |
gen_op_ldub_kernel_T1_A0, |
gen_op_ldub_kernel_T1_A0, |
627 |
gen_op_lduw_kernel_T1_A0, |
gen_op_lduw_kernel_T1_A0, |
628 |
gen_op_ldl_kernel_T1_A0, |
gen_op_ldl_kernel_T1_A0, |
630 |
gen_op_ldub_user_T1_A0, |
gen_op_ldub_user_T1_A0, |
631 |
gen_op_lduw_user_T1_A0, |
gen_op_lduw_user_T1_A0, |
632 |
gen_op_ldl_user_T1_A0, |
gen_op_ldl_user_T1_A0, |
633 |
|
#endif |
634 |
}; |
}; |
635 |
|
|
636 |
static GenOpFunc *gen_op_st_T0_A0[3 * 3] = { |
static GenOpFunc *gen_op_st_T0_A0[3 * 3] = { |
637 |
gen_op_stb_T0_A0, |
gen_op_stb_raw_T0_A0, |
638 |
gen_op_stw_T0_A0, |
gen_op_stw_raw_T0_A0, |
639 |
gen_op_stl_T0_A0, |
gen_op_stl_raw_T0_A0, |
640 |
|
|
641 |
|
#ifndef CONFIG_USER_ONLY |
642 |
gen_op_stb_kernel_T0_A0, |
gen_op_stb_kernel_T0_A0, |
643 |
gen_op_stw_kernel_T0_A0, |
gen_op_stw_kernel_T0_A0, |
644 |
gen_op_stl_kernel_T0_A0, |
gen_op_stl_kernel_T0_A0, |
646 |
gen_op_stb_user_T0_A0, |
gen_op_stb_user_T0_A0, |
647 |
gen_op_stw_user_T0_A0, |
gen_op_stw_user_T0_A0, |
648 |
gen_op_stl_user_T0_A0, |
gen_op_stl_user_T0_A0, |
649 |
|
#endif |
650 |
}; |
}; |
651 |
|
|
652 |
static inline void gen_string_movl_A0_ESI(DisasContext *s) |
static inline void gen_string_movl_A0_ESI(DisasContext *s) |
1185 |
|
|
1186 |
if (base == 4) { |
if (base == 4) { |
1187 |
havesib = 1; |
havesib = 1; |
1188 |
code = ldub(s->pc++); |
code = ldub_code(s->pc++); |
1189 |
scale = (code >> 6) & 3; |
scale = (code >> 6) & 3; |
1190 |
index = (code >> 3) & 7; |
index = (code >> 3) & 7; |
1191 |
base = code & 7; |
base = code & 7; |
1195 |
case 0: |
case 0: |
1196 |
if (base == 5) { |
if (base == 5) { |
1197 |
base = -1; |
base = -1; |
1198 |
disp = ldl(s->pc); |
disp = ldl_code(s->pc); |
1199 |
s->pc += 4; |
s->pc += 4; |
1200 |
} else { |
} else { |
1201 |
disp = 0; |
disp = 0; |
1202 |
} |
} |
1203 |
break; |
break; |
1204 |
case 1: |
case 1: |
1205 |
disp = (int8_t)ldub(s->pc++); |
disp = (int8_t)ldub_code(s->pc++); |
1206 |
break; |
break; |
1207 |
default: |
default: |
1208 |
case 2: |
case 2: |
1209 |
disp = ldl(s->pc); |
disp = ldl_code(s->pc); |
1210 |
s->pc += 4; |
s->pc += 4; |
1211 |
break; |
break; |
1212 |
} |
} |
1238 |
switch (mod) { |
switch (mod) { |
1239 |
case 0: |
case 0: |
1240 |
if (rm == 6) { |
if (rm == 6) { |
1241 |
disp = lduw(s->pc); |
disp = lduw_code(s->pc); |
1242 |
s->pc += 2; |
s->pc += 2; |
1243 |
gen_op_movl_A0_im(disp); |
gen_op_movl_A0_im(disp); |
1244 |
rm = 0; /* avoid SS override */ |
rm = 0; /* avoid SS override */ |
1248 |
} |
} |
1249 |
break; |
break; |
1250 |
case 1: |
case 1: |
1251 |
disp = (int8_t)ldub(s->pc++); |
disp = (int8_t)ldub_code(s->pc++); |
1252 |
break; |
break; |
1253 |
default: |
default: |
1254 |
case 2: |
case 2: |
1255 |
disp = lduw(s->pc); |
disp = lduw_code(s->pc); |
1256 |
s->pc += 2; |
s->pc += 2; |
1257 |
break; |
break; |
1258 |
} |
} |
1346 |
|
|
1347 |
switch(ot) { |
switch(ot) { |
1348 |
case OT_BYTE: |
case OT_BYTE: |
1349 |
ret = ldub(s->pc); |
ret = ldub_code(s->pc); |
1350 |
s->pc++; |
s->pc++; |
1351 |
break; |
break; |
1352 |
case OT_WORD: |
case OT_WORD: |
1353 |
ret = lduw(s->pc); |
ret = lduw_code(s->pc); |
1354 |
s->pc += 2; |
s->pc += 2; |
1355 |
break; |
break; |
1356 |
default: |
default: |
1357 |
case OT_LONG: |
case OT_LONG: |
1358 |
ret = ldl(s->pc); |
ret = ldl_code(s->pc); |
1359 |
s->pc += 4; |
s->pc += 4; |
1360 |
break; |
break; |
1361 |
} |
} |
1765 |
dflag = s->code32; |
dflag = s->code32; |
1766 |
s->override = -1; |
s->override = -1; |
1767 |
next_byte: |
next_byte: |
1768 |
b = ldub(s->pc); |
b = ldub_code(s->pc); |
1769 |
s->pc++; |
s->pc++; |
1770 |
/* check prefixes */ |
/* check prefixes */ |
1771 |
switch (b) { |
switch (b) { |
1823 |
case 0x0f: |
case 0x0f: |
1824 |
/**************************/ |
/**************************/ |
1825 |
/* extended op code */ |
/* extended op code */ |
1826 |
b = ldub(s->pc++) | 0x100; |
b = ldub_code(s->pc++) | 0x100; |
1827 |
goto reswitch; |
goto reswitch; |
1828 |
|
|
1829 |
/**************************/ |
/**************************/ |
1848 |
|
|
1849 |
switch(f) { |
switch(f) { |
1850 |
case 0: /* OP Ev, Gv */ |
case 0: /* OP Ev, Gv */ |
1851 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
1852 |
reg = ((modrm >> 3) & 7); |
reg = ((modrm >> 3) & 7); |
1853 |
mod = (modrm >> 6) & 3; |
mod = (modrm >> 6) & 3; |
1854 |
rm = modrm & 7; |
rm = modrm & 7; |
1870 |
gen_op(s, op, ot, opreg); |
gen_op(s, op, ot, opreg); |
1871 |
break; |
break; |
1872 |
case 1: /* OP Gv, Ev */ |
case 1: /* OP Gv, Ev */ |
1873 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
1874 |
mod = (modrm >> 6) & 3; |
mod = (modrm >> 6) & 3; |
1875 |
reg = ((modrm >> 3) & 7); |
reg = ((modrm >> 3) & 7); |
1876 |
rm = modrm & 7; |
rm = modrm & 7; |
1904 |
else |
else |
1905 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
1906 |
|
|
1907 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
1908 |
mod = (modrm >> 6) & 3; |
mod = (modrm >> 6) & 3; |
1909 |
rm = modrm & 7; |
rm = modrm & 7; |
1910 |
op = (modrm >> 3) & 7; |
op = (modrm >> 3) & 7; |
1948 |
else |
else |
1949 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
1950 |
|
|
1951 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
1952 |
mod = (modrm >> 6) & 3; |
mod = (modrm >> 6) & 3; |
1953 |
rm = modrm & 7; |
rm = modrm & 7; |
1954 |
op = (modrm >> 3) & 7; |
op = (modrm >> 3) & 7; |
2054 |
else |
else |
2055 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
2056 |
|
|
2057 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
2058 |
mod = (modrm >> 6) & 3; |
mod = (modrm >> 6) & 3; |
2059 |
rm = modrm & 7; |
rm = modrm & 7; |
2060 |
op = (modrm >> 3) & 7; |
op = (modrm >> 3) & 7; |
2094 |
gen_push_T0(s); |
gen_push_T0(s); |
2095 |
gen_eob(s); |
gen_eob(s); |
2096 |
break; |
break; |
2097 |
case 3: /*< lcall Ev */ |
case 3: /* lcall Ev */ |
2098 |
gen_op_ld_T1_A0[ot + s->mem_index](); |
gen_op_ld_T1_A0[ot + s->mem_index](); |
2099 |
gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); |
gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); |
2100 |
gen_op_ld_T0_A0[OT_WORD + s->mem_index](); |
gen_op_ldu_T0_A0[OT_WORD + s->mem_index](); |
2101 |
do_lcall: |
do_lcall: |
2102 |
if (s->pe && !s->vm86) { |
if (s->pe && !s->vm86) { |
2103 |
if (s->cc_op != CC_OP_DYNAMIC) |
if (s->cc_op != CC_OP_DYNAMIC) |
2118 |
case 5: /* ljmp Ev */ |
case 5: /* ljmp Ev */ |
2119 |
gen_op_ld_T1_A0[ot + s->mem_index](); |
gen_op_ld_T1_A0[ot + s->mem_index](); |
2120 |
gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); |
gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); |
2121 |
gen_op_lduw_T0_A0(); |
gen_op_ldu_T0_A0[OT_WORD + s->mem_index](); |
2122 |
do_ljmp: |
do_ljmp: |
2123 |
if (s->pe && !s->vm86) { |
if (s->pe && !s->vm86) { |
2124 |
if (s->cc_op != CC_OP_DYNAMIC) |
if (s->cc_op != CC_OP_DYNAMIC) |
2147 |
else |
else |
2148 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
2149 |
|
|
2150 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
2151 |
mod = (modrm >> 6) & 3; |
mod = (modrm >> 6) & 3; |
2152 |
rm = modrm & 7; |
rm = modrm & 7; |
2153 |
reg = (modrm >> 3) & 7; |
reg = (modrm >> 3) & 7; |
2188 |
case 0x69: /* imul Gv, Ev, I */ |
case 0x69: /* imul Gv, Ev, I */ |
2189 |
case 0x6b: |
case 0x6b: |
2190 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
2191 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
2192 |
reg = ((modrm >> 3) & 7) + OR_EAX; |
reg = ((modrm >> 3) & 7) + OR_EAX; |
2193 |
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); |
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); |
2194 |
if (b == 0x69) { |
if (b == 0x69) { |
2215 |
ot = OT_BYTE; |
ot = OT_BYTE; |
2216 |
else |
else |
2217 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
2218 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
2219 |
reg = (modrm >> 3) & 7; |
reg = (modrm >> 3) & 7; |
2220 |
mod = (modrm >> 6) & 3; |
mod = (modrm >> 6) & 3; |
2221 |
if (mod == 3) { |
if (mod == 3) { |
2242 |
ot = OT_BYTE; |
ot = OT_BYTE; |
2243 |
else |
else |
2244 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
2245 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
2246 |
reg = (modrm >> 3) & 7; |
reg = (modrm >> 3) & 7; |
2247 |
mod = (modrm >> 6) & 3; |
mod = (modrm >> 6) & 3; |
2248 |
gen_op_mov_TN_reg[ot][1][reg](); |
gen_op_mov_TN_reg[ot][1][reg](); |
2259 |
s->cc_op = CC_OP_SUBB + ot; |
s->cc_op = CC_OP_SUBB + ot; |
2260 |
break; |
break; |
2261 |
case 0x1c7: /* cmpxchg8b */ |
case 0x1c7: /* cmpxchg8b */ |
2262 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
2263 |
mod = (modrm >> 6) & 3; |
mod = (modrm >> 6) & 3; |
2264 |
if (mod == 3) |
if (mod == 3) |
2265 |
goto illegal_op; |
goto illegal_op; |
2300 |
break; |
break; |
2301 |
case 0x8f: /* pop Ev */ |
case 0x8f: /* pop Ev */ |
2302 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
2303 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
2304 |
gen_pop_T0(s); |
gen_pop_T0(s); |
2305 |
s->popl_esp_hack = 2 << dflag; |
s->popl_esp_hack = 2 << dflag; |
2306 |
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); |
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); |
2310 |
case 0xc8: /* enter */ |
case 0xc8: /* enter */ |
2311 |
{ |
{ |
2312 |
int level; |
int level; |
2313 |
val = lduw(s->pc); |
val = lduw_code(s->pc); |
2314 |
s->pc += 2; |
s->pc += 2; |
2315 |
level = ldub(s->pc++); |
level = ldub_code(s->pc++); |
2316 |
gen_enter(s, val, level); |
gen_enter(s, val, level); |
2317 |
} |
} |
2318 |
break; |
break; |
2378 |
ot = OT_BYTE; |
ot = OT_BYTE; |
2379 |
else |
else |
2380 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
2381 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
2382 |
reg = (modrm >> 3) & 7; |
reg = (modrm >> 3) & 7; |
2383 |
|
|
2384 |
/* generate a generic store */ |
/* generate a generic store */ |
2390 |
ot = OT_BYTE; |
ot = OT_BYTE; |
2391 |
else |
else |
2392 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
2393 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
2394 |
mod = (modrm >> 6) & 3; |
mod = (modrm >> 6) & 3; |
2395 |
if (mod != 3) |
if (mod != 3) |
2396 |
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
2407 |
ot = OT_BYTE; |
ot = OT_BYTE; |
2408 |
else |
else |
2409 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
2410 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
2411 |
reg = (modrm >> 3) & 7; |
reg = (modrm >> 3) & 7; |
2412 |
|
|
2413 |
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); |
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); |
2414 |
gen_op_mov_reg_T0[ot][reg](); |
gen_op_mov_reg_T0[ot][reg](); |
2415 |
break; |
break; |
2416 |
case 0x8e: /* mov seg, Gv */ |
case 0x8e: /* mov seg, Gv */ |
2417 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
2418 |
reg = (modrm >> 3) & 7; |
reg = (modrm >> 3) & 7; |
2419 |
if (reg >= 6 || reg == R_CS) |
if (reg >= 6 || reg == R_CS) |
2420 |
goto illegal_op; |
goto illegal_op; |
2431 |
} |
} |
2432 |
break; |
break; |
2433 |
case 0x8c: /* mov Gv, seg */ |
case 0x8c: /* mov Gv, seg */ |
2434 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
2435 |
reg = (modrm >> 3) & 7; |
reg = (modrm >> 3) & 7; |
2436 |
mod = (modrm >> 6) & 3; |
mod = (modrm >> 6) & 3; |
2437 |
if (reg >= 6) |
if (reg >= 6) |
2453 |
d_ot = dflag + OT_WORD; |
d_ot = dflag + OT_WORD; |
2454 |
/* ot is the size of source */ |
/* ot is the size of source */ |
2455 |
ot = (b & 1) + OT_BYTE; |
ot = (b & 1) + OT_BYTE; |
2456 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
2457 |
reg = ((modrm >> 3) & 7) + OR_EAX; |
reg = ((modrm >> 3) & 7) + OR_EAX; |
2458 |
mod = (modrm >> 6) & 3; |
mod = (modrm >> 6) & 3; |
2459 |
rm = modrm & 7; |
rm = modrm & 7; |
2490 |
|
|
2491 |
case 0x8d: /* lea */ |
case 0x8d: /* lea */ |
2492 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
2493 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
2494 |
reg = (modrm >> 3) & 7; |
reg = (modrm >> 3) & 7; |
2495 |
/* we must ensure that no segment is added */ |
/* we must ensure that no segment is added */ |
2496 |
s->override = -1; |
s->override = -1; |
2583 |
ot = OT_BYTE; |
ot = OT_BYTE; |
2584 |
else |
else |
2585 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
2586 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
2587 |
reg = (modrm >> 3) & 7; |
reg = (modrm >> 3) & 7; |
2588 |
mod = (modrm >> 6) & 3; |
mod = (modrm >> 6) & 3; |
2589 |
if (mod == 3) { |
if (mod == 3) { |
2622 |
op = R_GS; |
op = R_GS; |
2623 |
do_lxx: |
do_lxx: |
2624 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
2625 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
2626 |
reg = (modrm >> 3) & 7; |
reg = (modrm >> 3) & 7; |
2627 |
mod = (modrm >> 6) & 3; |
mod = (modrm >> 6) & 3; |
2628 |
if (mod == 3) |
if (mod == 3) |
2631 |
gen_op_ld_T1_A0[ot + s->mem_index](); |
gen_op_ld_T1_A0[ot + s->mem_index](); |
2632 |
gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); |
gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); |
2633 |
/* load the segment first to handle exceptions properly */ |
/* load the segment first to handle exceptions properly */ |
2634 |
gen_op_lduw_T0_A0(); |
gen_op_ldu_T0_A0[OT_WORD + s->mem_index](); |
2635 |
gen_movl_seg_T0(s, op, pc_start - s->cs_base); |
gen_movl_seg_T0(s, op, pc_start - s->cs_base); |
2636 |
/* then put the data */ |
/* then put the data */ |
2637 |
gen_op_mov_reg_T1[ot][reg](); |
gen_op_mov_reg_T1[ot][reg](); |
2654 |
else |
else |
2655 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
2656 |
|
|
2657 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
2658 |
mod = (modrm >> 6) & 3; |
mod = (modrm >> 6) & 3; |
2659 |
rm = modrm & 7; |
rm = modrm & 7; |
2660 |
op = (modrm >> 3) & 7; |
op = (modrm >> 3) & 7; |
2671 |
gen_shift(s, op, ot, opreg, OR_ECX); |
gen_shift(s, op, ot, opreg, OR_ECX); |
2672 |
} else { |
} else { |
2673 |
if (shift == 2) { |
if (shift == 2) { |
2674 |
shift = ldub(s->pc++); |
shift = ldub_code(s->pc++); |
2675 |
} |
} |
2676 |
gen_shifti(s, op, ot, opreg, shift); |
gen_shifti(s, op, ot, opreg, shift); |
2677 |
} |
} |
2705 |
shift = 0; |
shift = 0; |
2706 |
do_shiftd: |
do_shiftd: |
2707 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
2708 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
2709 |
mod = (modrm >> 6) & 3; |
mod = (modrm >> 6) & 3; |
2710 |
rm = modrm & 7; |
rm = modrm & 7; |
2711 |
reg = (modrm >> 3) & 7; |
reg = (modrm >> 3) & 7; |
2719 |
gen_op_mov_TN_reg[ot][1][reg](); |
gen_op_mov_TN_reg[ot][1][reg](); |
2720 |
|
|
2721 |
if (shift) { |
if (shift) { |
2722 |
val = ldub(s->pc++); |
val = ldub_code(s->pc++); |
2723 |
val &= 0x1f; |
val &= 0x1f; |
2724 |
if (val) { |
if (val) { |
2725 |
if (mod == 3) |
if (mod == 3) |
2748 |
/************************/ |
/************************/ |
2749 |
/* floats */ |
/* floats */ |
2750 |
case 0xd8 ... 0xdf: |
case 0xd8 ... 0xdf: |
2751 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
2752 |
mod = (modrm >> 6) & 3; |
mod = (modrm >> 6) & 3; |
2753 |
rm = modrm & 7; |
rm = modrm & 7; |
2754 |
op = ((b & 7) << 3) | ((modrm >> 3) & 7); |
op = ((b & 7) << 3) | ((modrm >> 3) & 7); |
3265 |
ot = OT_BYTE; |
ot = OT_BYTE; |
3266 |
else |
else |
3267 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
3268 |
val = ldub(s->pc++); |
val = ldub_code(s->pc++); |
3269 |
gen_op_movl_T0_im(val); |
gen_op_movl_T0_im(val); |
3270 |
gen_op_in[ot](); |
gen_op_in[ot](); |
3271 |
gen_op_mov_reg_T1[ot][R_EAX](); |
gen_op_mov_reg_T1[ot][R_EAX](); |
3280 |
ot = OT_BYTE; |
ot = OT_BYTE; |
3281 |
else |
else |
3282 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
3283 |
val = ldub(s->pc++); |
val = ldub_code(s->pc++); |
3284 |
gen_op_movl_T0_im(val); |
gen_op_movl_T0_im(val); |
3285 |
gen_op_mov_TN_reg[ot][1][R_EAX](); |
gen_op_mov_TN_reg[ot][1][R_EAX](); |
3286 |
gen_op_out[ot](); |
gen_op_out[ot](); |
3318 |
/************************/ |
/************************/ |
3319 |
/* control */ |
/* control */ |
3320 |
case 0xc2: /* ret im */ |
case 0xc2: /* ret im */ |
3321 |
val = ldsw(s->pc); |
val = ldsw_code(s->pc); |
3322 |
s->pc += 2; |
s->pc += 2; |
3323 |
gen_pop_T0(s); |
gen_pop_T0(s); |
3324 |
gen_stack_update(s, val + (2 << s->dflag)); |
gen_stack_update(s, val + (2 << s->dflag)); |
3336 |
gen_eob(s); |
gen_eob(s); |
3337 |
break; |
break; |
3338 |
case 0xca: /* lret im */ |
case 0xca: /* lret im */ |
3339 |
val = ldsw(s->pc); |
val = ldsw_code(s->pc); |
3340 |
s->pc += 2; |
s->pc += 2; |
3341 |
do_lret: |
do_lret: |
3342 |
if (s->pe && !s->vm86) { |
if (s->pe && !s->vm86) { |
3452 |
break; |
break; |
3453 |
|
|
3454 |
case 0x190 ... 0x19f: /* setcc Gv */ |
case 0x190 ... 0x19f: /* setcc Gv */ |
3455 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
3456 |
gen_setcc(s, b); |
gen_setcc(s, b); |
3457 |
gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1); |
gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1); |
3458 |
break; |
break; |
3459 |
case 0x140 ... 0x14f: /* cmov Gv, Ev */ |
case 0x140 ... 0x14f: /* cmov Gv, Ev */ |
3460 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
3461 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
3462 |
reg = (modrm >> 3) & 7; |
reg = (modrm >> 3) & 7; |
3463 |
mod = (modrm >> 6) & 3; |
mod = (modrm >> 6) & 3; |
3464 |
gen_setcc(s, b); |
gen_setcc(s, b); |
3551 |
/* bit operations */ |
/* bit operations */ |
3552 |
case 0x1ba: /* bt/bts/btr/btc Gv, im */ |
case 0x1ba: /* bt/bts/btr/btc Gv, im */ |
3553 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
3554 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
3555 |
op = (modrm >> 3) & 7; |
op = (modrm >> 3) & 7; |
3556 |
mod = (modrm >> 6) & 3; |
mod = (modrm >> 6) & 3; |
3557 |
rm = modrm & 7; |
rm = modrm & 7; |
3562 |
gen_op_mov_TN_reg[ot][0][rm](); |
gen_op_mov_TN_reg[ot][0][rm](); |
3563 |
} |
} |
3564 |
/* load shift */ |
/* load shift */ |
3565 |
val = ldub(s->pc++); |
val = ldub_code(s->pc++); |
3566 |
gen_op_movl_T1_im(val); |
gen_op_movl_T1_im(val); |
3567 |
if (op < 4) |
if (op < 4) |
3568 |
goto illegal_op; |
goto illegal_op; |
3590 |
op = 3; |
op = 3; |
3591 |
do_btx: |
do_btx: |
3592 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
3593 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
3594 |
reg = (modrm >> 3) & 7; |
reg = (modrm >> 3) & 7; |
3595 |
mod = (modrm >> 6) & 3; |
mod = (modrm >> 6) & 3; |
3596 |
rm = modrm & 7; |
rm = modrm & 7; |
3619 |
case 0x1bc: /* bsf */ |
case 0x1bc: /* bsf */ |
3620 |
case 0x1bd: /* bsr */ |
case 0x1bd: /* bsr */ |
3621 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
3622 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
3623 |
reg = (modrm >> 3) & 7; |
reg = (modrm >> 3) & 7; |
3624 |
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); |
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); |
3625 |
gen_op_bsx_T0_cc[ot - OT_WORD][b & 1](); |
gen_op_bsx_T0_cc[ot - OT_WORD][b & 1](); |
3655 |
s->cc_op = CC_OP_EFLAGS; |
s->cc_op = CC_OP_EFLAGS; |
3656 |
break; |
break; |
3657 |
case 0xd4: /* aam */ |
case 0xd4: /* aam */ |
3658 |
val = ldub(s->pc++); |
val = ldub_code(s->pc++); |
3659 |
gen_op_aam(val); |
gen_op_aam(val); |
3660 |
s->cc_op = CC_OP_LOGICB; |
s->cc_op = CC_OP_LOGICB; |
3661 |
break; |
break; |
3662 |
case 0xd5: /* aad */ |
case 0xd5: /* aad */ |
3663 |
val = ldub(s->pc++); |
val = ldub_code(s->pc++); |
3664 |
gen_op_aad(val); |
gen_op_aad(val); |
3665 |
s->cc_op = CC_OP_LOGICB; |
s->cc_op = CC_OP_LOGICB; |
3666 |
break; |
break; |
3674 |
gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base); |
gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base); |
3675 |
break; |
break; |
3676 |
case 0xcd: /* int N */ |
case 0xcd: /* int N */ |
3677 |
val = ldub(s->pc++); |
val = ldub_code(s->pc++); |
3678 |
/* XXX: add error code for vm86 GPF */ |
/* XXX: add error code for vm86 GPF */ |
3679 |
if (!s->vm86) |
if (!s->vm86) |
3680 |
gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base); |
gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base); |
3727 |
break; |
break; |
3728 |
case 0x62: /* bound */ |
case 0x62: /* bound */ |
3729 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
3730 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
3731 |
reg = (modrm >> 3) & 7; |
reg = (modrm >> 3) & 7; |
3732 |
mod = (modrm >> 6) & 3; |
mod = (modrm >> 6) & 3; |
3733 |
if (mod == 3) |
if (mod == 3) |
3794 |
} |
} |
3795 |
break; |
break; |
3796 |
case 0x100: |
case 0x100: |
3797 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
3798 |
mod = (modrm >> 6) & 3; |
mod = (modrm >> 6) & 3; |
3799 |
op = (modrm >> 3) & 7; |
op = (modrm >> 3) & 7; |
3800 |
switch(op) { |
switch(op) { |
3837 |
} |
} |
3838 |
break; |
break; |
3839 |
case 0x101: |
case 0x101: |
3840 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
3841 |
mod = (modrm >> 6) & 3; |
mod = (modrm >> 6) & 3; |
3842 |
op = (modrm >> 3) & 7; |
op = (modrm >> 3) & 7; |
3843 |
switch(op) { |
switch(op) { |
3913 |
if (!s->pe || s->vm86) |
if (!s->pe || s->vm86) |
3914 |
goto illegal_op; |
goto illegal_op; |
3915 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
3916 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
3917 |
reg = (modrm >> 3) & 7; |
reg = (modrm >> 3) & 7; |
3918 |
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); |
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); |
3919 |
gen_op_mov_TN_reg[ot][1][reg](); |
gen_op_mov_TN_reg[ot][1][reg](); |
3927 |
gen_op_mov_reg_T1[ot][reg](); |
gen_op_mov_reg_T1[ot][reg](); |
3928 |
break; |
break; |
3929 |
case 0x118: |
case 0x118: |
3930 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
3931 |
mod = (modrm >> 6) & 3; |
mod = (modrm >> 6) & 3; |
3932 |
op = (modrm >> 3) & 7; |
op = (modrm >> 3) & 7; |
3933 |
switch(op) { |
switch(op) { |
3949 |
if (s->cpl != 0) { |
if (s->cpl != 0) { |
3950 |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3951 |
} else { |
} else { |
3952 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
3953 |
if ((modrm & 0xc0) != 0xc0) |
if ((modrm & 0xc0) != 0xc0) |
3954 |
goto illegal_op; |
goto illegal_op; |
3955 |
rm = modrm & 7; |
rm = modrm & 7; |
3979 |
if (s->cpl != 0) { |
if (s->cpl != 0) { |
3980 |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3981 |
} else { |
} else { |
3982 |
modrm = ldub(s->pc++); |
modrm = ldub_code(s->pc++); |
3983 |
if ((modrm & 0xc0) != 0xc0) |
if ((modrm & 0xc0) != 0xc0) |
3984 |
goto illegal_op; |
goto illegal_op; |
3985 |
rm = modrm & 7; |
rm = modrm & 7; |