| 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; |