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 */ |