2020-02-29 19:12:23 +01:00
|
|
|
#ifdef USE_NEW_DYNAREC
|
2022-11-19 10:40:32 -05:00
|
|
|
# define CPU_SET_OXPC
|
2020-02-29 19:12:23 +01:00
|
|
|
#else
|
2022-11-19 10:40:32 -05:00
|
|
|
# define CPU_SET_OXPC oxpc = cpu_state.pc;
|
2020-02-29 19:12:23 +01:00
|
|
|
#endif
|
|
|
|
|
|
2022-11-19 10:40:32 -05:00
|
|
|
#define RETF_a16(stack_offset) \
|
|
|
|
|
if ((msw & 1) && !(cpu_state.eflags & VM_FLAG)) { \
|
|
|
|
|
pmoderetf(0, stack_offset); \
|
|
|
|
|
return 1; \
|
|
|
|
|
} \
|
|
|
|
|
CPU_SET_OXPC \
|
|
|
|
|
if (stack32) { \
|
|
|
|
|
cpu_state.pc = readmemw(ss, ESP); \
|
|
|
|
|
loadcs(readmemw(ss, ESP + 2)); \
|
|
|
|
|
} else { \
|
|
|
|
|
cpu_state.pc = readmemw(ss, SP); \
|
|
|
|
|
loadcs(readmemw(ss, SP + 2)); \
|
|
|
|
|
} \
|
|
|
|
|
if (cpu_state.abrt) \
|
|
|
|
|
return 1; \
|
|
|
|
|
if (stack32) \
|
|
|
|
|
ESP += 4 + stack_offset; \
|
|
|
|
|
else \
|
|
|
|
|
SP += 4 + stack_offset; \
|
|
|
|
|
cycles -= timing_retf_rm;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2022-11-19 10:40:32 -05:00
|
|
|
#define RETF_a32(stack_offset) \
|
|
|
|
|
if ((msw & 1) && !(cpu_state.eflags & VM_FLAG)) { \
|
|
|
|
|
pmoderetf(1, stack_offset); \
|
|
|
|
|
return 1; \
|
|
|
|
|
} \
|
|
|
|
|
CPU_SET_OXPC \
|
|
|
|
|
if (stack32) { \
|
|
|
|
|
cpu_state.pc = readmeml(ss, ESP); \
|
|
|
|
|
loadcs(readmeml(ss, ESP + 4) & 0xffff); \
|
|
|
|
|
} else { \
|
|
|
|
|
cpu_state.pc = readmeml(ss, SP); \
|
|
|
|
|
loadcs(readmeml(ss, SP + 4) & 0xffff); \
|
|
|
|
|
} \
|
|
|
|
|
if (cpu_state.abrt) \
|
|
|
|
|
return 1; \
|
|
|
|
|
if (stack32) \
|
|
|
|
|
ESP += 8 + stack_offset; \
|
|
|
|
|
else \
|
|
|
|
|
SP += 8 + stack_offset; \
|
|
|
|
|
cycles -= timing_retf_rm;
|
2016-06-26 00:34:39 +02:00
|
|
|
|
2022-11-19 10:40:32 -05:00
|
|
|
static int
|
|
|
|
|
opRETF_a16(uint32_t fetchdat)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2022-11-19 10:40:32 -05:00
|
|
|
int cycles_old = cycles;
|
|
|
|
|
UN_USED(cycles_old);
|
2022-02-20 02:26:27 -05:00
|
|
|
|
2022-11-19 10:40:32 -05:00
|
|
|
CPU_BLOCK_END();
|
|
|
|
|
RETF_a16(0);
|
2022-02-20 02:26:27 -05:00
|
|
|
|
2022-11-19 10:40:32 -05:00
|
|
|
PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0);
|
|
|
|
|
PREFETCH_FLUSH();
|
|
|
|
|
return 0;
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
2022-11-19 10:40:32 -05:00
|
|
|
static int
|
|
|
|
|
opRETF_a32(uint32_t fetchdat)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2022-11-19 10:40:32 -05:00
|
|
|
int cycles_old = cycles;
|
|
|
|
|
UN_USED(cycles_old);
|
2022-02-20 02:26:27 -05:00
|
|
|
|
2022-11-19 10:40:32 -05:00
|
|
|
CPU_BLOCK_END();
|
|
|
|
|
RETF_a32(0);
|
2016-12-23 03:16:24 +01:00
|
|
|
|
2022-11-19 10:40:32 -05:00
|
|
|
PREFETCH_RUN(cycles_old - cycles, 1, -1, 0, 2, 0, 0, 1);
|
|
|
|
|
PREFETCH_FLUSH();
|
|
|
|
|
return 0;
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2022-11-19 10:40:32 -05:00
|
|
|
static int
|
|
|
|
|
opRETF_a16_imm(uint32_t fetchdat)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2022-11-19 10:40:32 -05:00
|
|
|
uint16_t offset = getwordf();
|
|
|
|
|
int cycles_old = cycles;
|
|
|
|
|
UN_USED(cycles_old);
|
2016-12-23 03:16:24 +01:00
|
|
|
|
2022-11-19 10:40:32 -05:00
|
|
|
CPU_BLOCK_END();
|
|
|
|
|
RETF_a16(offset);
|
2016-12-23 03:16:24 +01:00
|
|
|
|
2022-11-19 10:40:32 -05:00
|
|
|
PREFETCH_RUN(cycles_old - cycles, 3, -1, 2, 0, 0, 0, 0);
|
|
|
|
|
PREFETCH_FLUSH();
|
|
|
|
|
return 0;
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
2022-11-19 10:40:32 -05:00
|
|
|
static int
|
|
|
|
|
opRETF_a32_imm(uint32_t fetchdat)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2022-11-19 10:40:32 -05:00
|
|
|
uint16_t offset = getwordf();
|
|
|
|
|
int cycles_old = cycles;
|
|
|
|
|
UN_USED(cycles_old);
|
2016-12-23 03:16:24 +01:00
|
|
|
|
2022-11-19 10:40:32 -05:00
|
|
|
CPU_BLOCK_END();
|
|
|
|
|
RETF_a32(offset);
|
2016-12-23 03:16:24 +01:00
|
|
|
|
2022-11-19 10:40:32 -05:00
|
|
|
PREFETCH_RUN(cycles_old - cycles, 3, -1, 0, 2, 0, 0, 1);
|
|
|
|
|
PREFETCH_FLUSH();
|
|
|
|
|
return 0;
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2022-11-19 10:40:32 -05:00
|
|
|
static int
|
|
|
|
|
opIRET_186(uint32_t fetchdat)
|
2022-09-04 16:02:52 -04:00
|
|
|
{
|
2022-11-19 10:40:32 -05:00
|
|
|
int cycles_old = cycles;
|
|
|
|
|
UN_USED(cycles_old);
|
2022-09-04 16:02:52 -04:00
|
|
|
|
2022-11-19 10:40:32 -05:00
|
|
|
if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) {
|
|
|
|
|
x86gpf(NULL, 0);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
if (msw & 1) {
|
|
|
|
|
optype = IRET;
|
|
|
|
|
pmodeiret(0);
|
|
|
|
|
optype = 0;
|
|
|
|
|
} else {
|
|
|
|
|
uint16_t new_cs;
|
|
|
|
|
CPU_SET_OXPC
|
|
|
|
|
if (stack32) {
|
|
|
|
|
cpu_state.pc = readmemw(ss, ESP);
|
|
|
|
|
new_cs = readmemw(ss, ESP + 2);
|
|
|
|
|
cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ESP + 4) & 0xffd5) | 2;
|
|
|
|
|
ESP += 6;
|
|
|
|
|
} else {
|
|
|
|
|
cpu_state.pc = readmemw(ss, SP);
|
|
|
|
|
new_cs = readmemw(ss, ((SP + 2) & 0xffff));
|
|
|
|
|
cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ((SP + 4) & 0xffff)) & 0x0fd5) | 2;
|
|
|
|
|
SP += 6;
|
2022-09-04 16:02:52 -04:00
|
|
|
}
|
2022-11-19 10:40:32 -05:00
|
|
|
loadcs(new_cs);
|
|
|
|
|
cycles -= timing_iret_rm;
|
|
|
|
|
}
|
|
|
|
|
flags_extract();
|
|
|
|
|
nmi_enable = 1;
|
|
|
|
|
CPU_BLOCK_END();
|
2022-09-04 16:02:52 -04:00
|
|
|
|
2022-11-19 10:40:32 -05:00
|
|
|
PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0);
|
|
|
|
|
PREFETCH_FLUSH();
|
|
|
|
|
return cpu_state.abrt;
|
2022-09-04 16:02:52 -04:00
|
|
|
}
|
|
|
|
|
|
2022-11-19 10:40:32 -05:00
|
|
|
static int
|
|
|
|
|
opIRET_286(uint32_t fetchdat)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2022-11-19 10:40:32 -05:00
|
|
|
int cycles_old = cycles;
|
|
|
|
|
UN_USED(cycles_old);
|
2022-02-20 02:26:27 -05:00
|
|
|
|
2022-11-19 10:40:32 -05:00
|
|
|
if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) {
|
|
|
|
|
x86gpf(NULL, 0);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
if (msw & 1) {
|
|
|
|
|
optype = IRET;
|
|
|
|
|
pmodeiret(0);
|
|
|
|
|
optype = 0;
|
|
|
|
|
} else {
|
|
|
|
|
uint16_t new_cs;
|
|
|
|
|
CPU_SET_OXPC
|
|
|
|
|
if (stack32) {
|
|
|
|
|
cpu_state.pc = readmemw(ss, ESP);
|
|
|
|
|
new_cs = readmemw(ss, ESP + 2);
|
|
|
|
|
cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ESP + 4) & 0xffd5) | 2;
|
|
|
|
|
ESP += 6;
|
|
|
|
|
} else {
|
|
|
|
|
cpu_state.pc = readmemw(ss, SP);
|
|
|
|
|
new_cs = readmemw(ss, ((SP + 2) & 0xffff));
|
|
|
|
|
cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ((SP + 4) & 0xffff)) & 0x0fd5) | 2;
|
|
|
|
|
SP += 6;
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
2022-11-19 10:40:32 -05:00
|
|
|
loadcs(new_cs);
|
|
|
|
|
cycles -= timing_iret_rm;
|
|
|
|
|
}
|
|
|
|
|
flags_extract();
|
|
|
|
|
nmi_enable = 1;
|
|
|
|
|
CPU_BLOCK_END();
|
2016-12-23 03:16:24 +01:00
|
|
|
|
2022-11-19 10:40:32 -05:00
|
|
|
PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0);
|
|
|
|
|
PREFETCH_FLUSH();
|
|
|
|
|
return cpu_state.abrt;
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2022-11-19 10:40:32 -05:00
|
|
|
static int
|
|
|
|
|
opIRET(uint32_t fetchdat)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2022-11-19 10:40:32 -05:00
|
|
|
int cycles_old = cycles;
|
|
|
|
|
UN_USED(cycles_old);
|
2022-02-20 02:26:27 -05:00
|
|
|
|
2022-11-19 10:40:32 -05:00
|
|
|
if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) {
|
|
|
|
|
if (cr4 & CR4_VME) {
|
2023-08-10 15:43:16 -04:00
|
|
|
uint16_t new_pc;
|
|
|
|
|
uint16_t new_cs;
|
|
|
|
|
uint16_t new_flags;
|
2017-07-15 12:46:44 +02:00
|
|
|
|
2022-11-19 10:40:32 -05:00
|
|
|
new_pc = readmemw(ss, SP);
|
|
|
|
|
new_cs = readmemw(ss, ((SP + 2) & 0xffff));
|
|
|
|
|
new_flags = readmemw(ss, ((SP + 4) & 0xffff));
|
|
|
|
|
if (cpu_state.abrt)
|
|
|
|
|
return 1;
|
2017-07-15 12:46:44 +02:00
|
|
|
|
2022-11-19 10:40:32 -05:00
|
|
|
if ((new_flags & T_FLAG) || ((new_flags & I_FLAG) && (cpu_state.eflags & VIP_FLAG))) {
|
|
|
|
|
x86gpf(NULL, 0);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
SP += 6;
|
|
|
|
|
if (new_flags & I_FLAG)
|
|
|
|
|
cpu_state.eflags |= VIF_FLAG;
|
|
|
|
|
else
|
|
|
|
|
cpu_state.eflags &= ~VIF_FLAG;
|
|
|
|
|
cpu_state.flags = (cpu_state.flags & 0x3300) | (new_flags & 0x4cd5) | 2;
|
|
|
|
|
loadcs(new_cs);
|
|
|
|
|
cpu_state.pc = new_pc;
|
2017-07-15 12:46:44 +02:00
|
|
|
|
2022-11-19 10:40:32 -05:00
|
|
|
cycles -= timing_iret_rm;
|
|
|
|
|
} else {
|
|
|
|
|
x86gpf_expected(NULL, 0);
|
|
|
|
|
return 1;
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
2022-11-19 10:40:32 -05:00
|
|
|
} else {
|
|
|
|
|
if (msw & 1) {
|
|
|
|
|
optype = IRET;
|
|
|
|
|
pmodeiret(0);
|
|
|
|
|
optype = 0;
|
|
|
|
|
} else {
|
|
|
|
|
uint16_t new_cs;
|
|
|
|
|
CPU_SET_OXPC
|
|
|
|
|
if (stack32) {
|
|
|
|
|
cpu_state.pc = readmemw(ss, ESP);
|
|
|
|
|
new_cs = readmemw(ss, ESP + 2);
|
|
|
|
|
cpu_state.flags = (readmemw(ss, ESP + 4) & 0xffd5) | 2;
|
|
|
|
|
ESP += 6;
|
|
|
|
|
} else {
|
|
|
|
|
cpu_state.pc = readmemw(ss, SP);
|
|
|
|
|
new_cs = readmemw(ss, ((SP + 2) & 0xffff));
|
|
|
|
|
cpu_state.flags = (readmemw(ss, ((SP + 4) & 0xffff)) & 0xffd5) | 2;
|
|
|
|
|
SP += 6;
|
|
|
|
|
}
|
|
|
|
|
loadcs(new_cs);
|
|
|
|
|
cycles -= timing_iret_rm;
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
2022-11-19 10:40:32 -05:00
|
|
|
}
|
|
|
|
|
flags_extract();
|
|
|
|
|
nmi_enable = 1;
|
|
|
|
|
CPU_BLOCK_END();
|
2016-12-23 03:16:24 +01:00
|
|
|
|
2022-11-19 10:40:32 -05:00
|
|
|
PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0);
|
|
|
|
|
PREFETCH_FLUSH();
|
|
|
|
|
return cpu_state.abrt;
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
|
|
|
|
|
2022-11-19 10:40:32 -05:00
|
|
|
static int
|
|
|
|
|
opIRETD(uint32_t fetchdat)
|
2016-06-26 00:34:39 +02:00
|
|
|
{
|
2022-11-19 10:40:32 -05:00
|
|
|
int cycles_old = cycles;
|
|
|
|
|
UN_USED(cycles_old);
|
2022-02-20 02:26:27 -05:00
|
|
|
|
2022-11-19 10:40:32 -05:00
|
|
|
if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) {
|
|
|
|
|
x86gpf_expected(NULL, 0);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
if (msw & 1) {
|
|
|
|
|
optype = IRET;
|
|
|
|
|
pmodeiret(1);
|
|
|
|
|
optype = 0;
|
|
|
|
|
} else {
|
|
|
|
|
uint16_t new_cs;
|
|
|
|
|
CPU_SET_OXPC
|
|
|
|
|
if (stack32) {
|
|
|
|
|
cpu_state.pc = readmeml(ss, ESP);
|
|
|
|
|
new_cs = readmemw(ss, ESP + 4);
|
|
|
|
|
cpu_state.flags = (readmemw(ss, ESP + 8) & 0xffd5) | 2;
|
|
|
|
|
cpu_state.eflags = readmemw(ss, ESP + 10);
|
|
|
|
|
ESP += 12;
|
|
|
|
|
} else {
|
|
|
|
|
cpu_state.pc = readmeml(ss, SP);
|
|
|
|
|
new_cs = readmemw(ss, ((SP + 4) & 0xffff));
|
|
|
|
|
cpu_state.flags = (readmemw(ss, (SP + 8) & 0xffff) & 0xffd5) | 2;
|
|
|
|
|
cpu_state.eflags = readmemw(ss, (SP + 10) & 0xffff);
|
|
|
|
|
SP += 12;
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|
2022-11-19 10:40:32 -05:00
|
|
|
loadcs(new_cs);
|
|
|
|
|
cycles -= timing_iret_rm;
|
|
|
|
|
}
|
|
|
|
|
flags_extract();
|
|
|
|
|
nmi_enable = 1;
|
|
|
|
|
CPU_BLOCK_END();
|
2016-12-23 03:16:24 +01:00
|
|
|
|
2022-11-19 10:40:32 -05:00
|
|
|
PREFETCH_RUN(cycles_old - cycles, 1, -1, 0, 2, 0, 0, 1);
|
|
|
|
|
PREFETCH_FLUSH();
|
|
|
|
|
return cpu_state.abrt;
|
2016-06-26 00:34:39 +02:00
|
|
|
}
|