| 19 |
*/ |
*/ |
| 20 |
#include "exec.h" |
#include "exec.h" |
| 21 |
|
|
| 22 |
|
//#define DEBUG_PCALL |
| 23 |
|
|
| 24 |
const uint8_t parity_table[256] = { |
const uint8_t parity_table[256] = { |
| 25 |
CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, |
CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, |
| 26 |
0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, |
0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, |
| 542 |
uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2, push_size; |
uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2, push_size; |
| 543 |
uint32_t old_cs, old_ss, old_esp, old_eip; |
uint32_t old_cs, old_ss, old_esp, old_eip; |
| 544 |
|
|
| 545 |
|
#ifdef DEBUG_PCALL |
| 546 |
|
if (loglevel) { |
| 547 |
|
static int count; |
| 548 |
|
fprintf(logfile, "%d: interrupt: vector=%02x error_code=%04x int=%d CS:IP=%04x:%08x CPL=%d\n", |
| 549 |
|
count, intno, error_code, is_int, env->segs[R_CS].selector, env->eip, env->hflags & 3); |
| 550 |
|
#if 0 |
| 551 |
|
{ |
| 552 |
|
int i; |
| 553 |
|
uint8_t *ptr; |
| 554 |
|
printf(" code="); |
| 555 |
|
ptr = env->segs[R_CS].base + env->eip; |
| 556 |
|
for(i = 0; i < 16; i++) { |
| 557 |
|
printf(" %02x", ldub(ptr + i)); |
| 558 |
|
} |
| 559 |
|
printf("\n"); |
| 560 |
|
} |
| 561 |
|
#endif |
| 562 |
|
count++; |
| 563 |
|
} |
| 564 |
|
#endif |
| 565 |
|
|
| 566 |
has_error_code = 0; |
has_error_code = 0; |
| 567 |
if (!is_int && !is_hw) { |
if (!is_int && !is_hw) { |
| 568 |
switch(intno) { |
switch(intno) { |
| 1283 |
|
|
| 1284 |
new_cs = T0; |
new_cs = T0; |
| 1285 |
new_eip = T1; |
new_eip = T1; |
| 1286 |
|
#ifdef DEBUG_PCALL |
| 1287 |
|
if (loglevel) { |
| 1288 |
|
fprintf(logfile, "lcall %04x:%08x\n", |
| 1289 |
|
new_cs, new_eip); |
| 1290 |
|
} |
| 1291 |
|
#endif |
| 1292 |
if ((new_cs & 0xfffc) == 0) |
if ((new_cs & 0xfffc) == 0) |
| 1293 |
raise_exception_err(EXCP0D_GPF, 0); |
raise_exception_err(EXCP0D_GPF, 0); |
| 1294 |
if (load_segment(&e1, &e2, new_cs) != 0) |
if (load_segment(&e1, &e2, new_cs) != 0) |
| 1295 |
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
| 1296 |
cpl = env->hflags & HF_CPL_MASK; |
cpl = env->hflags & HF_CPL_MASK; |
| 1297 |
|
#ifdef DEBUG_PCALL |
| 1298 |
|
if (loglevel) { |
| 1299 |
|
fprintf(logfile, "desc=%08x:%08x\n", e1, e2); |
| 1300 |
|
} |
| 1301 |
|
#endif |
| 1302 |
if (e2 & DESC_S_MASK) { |
if (e2 & DESC_S_MASK) { |
| 1303 |
if (!(e2 & DESC_CS_MASK)) |
if (!(e2 & DESC_CS_MASK)) |
| 1304 |
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
| 1375 |
raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc); |
raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc); |
| 1376 |
selector = e1 >> 16; |
selector = e1 >> 16; |
| 1377 |
offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff); |
offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff); |
| 1378 |
|
param_count = e2 & 0x1f; |
| 1379 |
if ((selector & 0xfffc) == 0) |
if ((selector & 0xfffc) == 0) |
| 1380 |
raise_exception_err(EXCP0D_GPF, 0); |
raise_exception_err(EXCP0D_GPF, 0); |
| 1381 |
|
|
| 1392 |
if (!(e2 & DESC_C_MASK) && dpl < cpl) { |
if (!(e2 & DESC_C_MASK) && dpl < cpl) { |
| 1393 |
/* to inner priviledge */ |
/* to inner priviledge */ |
| 1394 |
get_ss_esp_from_tss(&ss, &sp, dpl); |
get_ss_esp_from_tss(&ss, &sp, dpl); |
| 1395 |
|
#ifdef DEBUG_PCALL |
| 1396 |
|
if (loglevel) |
| 1397 |
|
fprintf(logfile, "ss=%04x sp=%04x param_count=%d ESP=%x\n", |
| 1398 |
|
ss, sp, param_count, ESP); |
| 1399 |
|
#endif |
| 1400 |
if ((ss & 0xfffc) == 0) |
if ((ss & 0xfffc) == 0) |
| 1401 |
raise_exception_err(EXCP0A_TSS, ss & 0xfffc); |
raise_exception_err(EXCP0A_TSS, ss & 0xfffc); |
| 1402 |
if ((ss & 3) != dpl) |
if ((ss & 3) != dpl) |
| 1413 |
if (!(ss_e2 & DESC_P_MASK)) |
if (!(ss_e2 & DESC_P_MASK)) |
| 1414 |
raise_exception_err(EXCP0A_TSS, ss & 0xfffc); |
raise_exception_err(EXCP0A_TSS, ss & 0xfffc); |
| 1415 |
|
|
|
param_count = e2 & 0x1f; |
|
| 1416 |
push_size = ((param_count * 2) + 8) << shift; |
push_size = ((param_count * 2) + 8) << shift; |
| 1417 |
|
|
| 1418 |
old_esp = ESP; |
old_esp = ESP; |
| 1428 |
get_seg_limit(ss_e1, ss_e2), |
get_seg_limit(ss_e1, ss_e2), |
| 1429 |
ss_e2); |
ss_e2); |
| 1430 |
|
|
| 1431 |
if (!(env->segs[R_SS].flags & DESC_B_MASK)) |
if (!(ss_e2 & DESC_B_MASK)) |
| 1432 |
sp &= 0xffff; |
sp &= 0xffff; |
| 1433 |
ssp = env->segs[R_SS].base + sp; |
ssp = env->segs[R_SS].base + sp; |
| 1434 |
if (shift) { |
if (shift) { |
| 1480 |
e2); |
e2); |
| 1481 |
cpu_x86_set_cpl(env, dpl); |
cpu_x86_set_cpl(env, dpl); |
| 1482 |
|
|
|
/* from this point, not restartable if same priviledge */ |
|
| 1483 |
if (!(env->segs[R_SS].flags & DESC_B_MASK)) |
if (!(env->segs[R_SS].flags & DESC_B_MASK)) |
| 1484 |
ESP = (ESP & 0xffff0000) | (sp & 0xffff); |
ESP = (ESP & 0xffff0000) | (sp & 0xffff); |
| 1485 |
else |
else |
| 1876 |
if (dpl < cpl || dpl < rpl) |
if (dpl < cpl || dpl < rpl) |
| 1877 |
return; |
return; |
| 1878 |
} |
} |
| 1879 |
/* ok */ |
CC_SRC |= CC_Z; |
| 1880 |
} |
} |
| 1881 |
|
|
| 1882 |
void helper_verw(void) |
void helper_verw(void) |
| 1904 |
if (!(e2 & DESC_W_MASK)) |
if (!(e2 & DESC_W_MASK)) |
| 1905 |
return; |
return; |
| 1906 |
} |
} |
| 1907 |
/* ok */ |
CC_SRC |= CC_Z; |
| 1908 |
} |
} |
| 1909 |
|
|
| 1910 |
/* FPU helpers */ |
/* FPU helpers */ |