diff --git a/include/prim_ops.h b/include/prim_ops.h index 3690603..95b5d94 100644 --- a/include/prim_ops.h +++ b/include/prim_ops.h @@ -130,6 +130,7 @@ void ins (x86emu_t *emu, int size); void outs (x86emu_t *emu, int size); void push_word (x86emu_t *emu, u16 w); void push_long (x86emu_t *emu, u32 w); +void push_halflong (x86emu_t *emu, u16 w); u16 pop_word (x86emu_t *emu); u32 pop_long (x86emu_t *emu); int eval_condition(x86emu_t *emu, unsigned type); diff --git a/ops.c b/ops.c index c4ae3d4..2f3883d 100644 --- a/ops.c +++ b/ops.c @@ -437,7 +437,7 @@ static void x86emuOp_push_ES(x86emu_t *emu, u8 op1) OP_DECODE("push es"); if(MODE_DATA32) { - push_long(emu, emu->x86.R_ES); + push_halflong(emu, emu->x86.R_ES); } else { push_word(emu, emu->x86.R_ES); @@ -464,7 +464,7 @@ static void x86emuOp_push_CS(x86emu_t *emu, u8 op1) { OP_DECODE("push cs"); if(MODE_DATA32) { - push_long(emu, emu->x86.R_CS); + push_halflong(emu, emu->x86.R_CS); } else { push_word(emu, emu->x86.R_CS); @@ -493,7 +493,7 @@ static void x86emuOp_push_SS(x86emu_t *emu, u8 op1) OP_DECODE("push ss"); if(MODE_DATA32) { - push_long(emu, emu->x86.R_SS); + push_halflong(emu, emu->x86.R_SS); } else { push_word(emu, emu->x86.R_SS); @@ -521,7 +521,7 @@ static void x86emuOp_push_DS(x86emu_t *emu, u8 op1) OP_DECODE("push ds"); if(MODE_DATA32) { - push_long(emu, emu->x86.R_DS); + push_halflong(emu, emu->x86.R_DS); } else { push_word(emu, emu->x86.R_DS); diff --git a/prim_ops.c b/prim_ops.c index e9e81f6..cd0d92e 100644 --- a/prim_ops.c +++ b/prim_ops.c @@ -1262,6 +1262,7 @@ u8 shl_byte(x86emu_t *emu, u8 d, u8 s) CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); CONDITIONAL_SET_FLAG(res & 0x80, F_SF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + CLEAR_FLAG(F_AF); } else { res = (u8) d; } @@ -1281,6 +1282,7 @@ u8 shl_byte(x86emu_t *emu, u8 d, u8 s) CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80, F_CF); CLEAR_FLAG(F_OF); CLEAR_FLAG(F_SF); + CLEAR_FLAG(F_AF); SET_FLAG(F_PF); SET_FLAG(F_ZF); } @@ -1304,6 +1306,7 @@ u16 shl_word(x86emu_t *emu, u16 d, u8 s) CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + CLEAR_FLAG(F_AF); } else { res = (u16) d; } @@ -1321,6 +1324,7 @@ u16 shl_word(x86emu_t *emu, u16 d, u8 s) CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF); CLEAR_FLAG(F_OF); CLEAR_FLAG(F_SF); + CLEAR_FLAG(F_AF); SET_FLAG(F_PF); SET_FLAG(F_ZF); } @@ -1344,6 +1348,7 @@ u32 shl_long(x86emu_t *emu, u32 d, u8 s) CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + CLEAR_FLAG(F_AF); } else { res = d; } @@ -1358,6 +1363,7 @@ u32 shl_long(x86emu_t *emu, u32 d, u8 s) CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF); CLEAR_FLAG(F_OF); CLEAR_FLAG(F_SF); + CLEAR_FLAG(F_AF); SET_FLAG(F_PF); SET_FLAG(F_ZF); } @@ -2515,6 +2521,22 @@ void push_long(x86emu_t *emu, u32 w) } } +/**************************************************************************** +REMARKS: +Pushes a 16-bit (segment) register onto the 32-bit data stack. +****************************************************************************/ +void push_halflong(x86emu_t *emu, u16 w) +{ + if(MODE_STACK32) { + emu->x86.R_ESP -= 4; + store_data_word_abs(emu, emu->x86.seg + R_SS_INDEX, emu->x86.R_ESP, w); + } + else { + emu->x86.R_SP -= 4; + store_data_word_abs(emu, emu->x86.seg + R_SS_INDEX, emu->x86.R_SP, w); + } +} + /**************************************************************************** REMARKS: Pops a word from the stack. diff --git a/test/0034_ret_far_32.done b/test/0034_ret_far_32.done index d8212fa..574b2b4 100644 --- a/test/0034_ret_far_32.done +++ b/test/0034_ret_far_32.done @@ -2,7 +2,7 @@ ; 0 1 2 3 4 5 6 7 8 9 a b c d e f 00001000: 68 aa aa aa aa 0e e8 06 00 00 00 68 bb bb bb bb 00001010: f4 ca 04 00 90 90 f4 -fffffff0: 0b 00 00 00 00 01 00 00 bb bb bb bb +fffffff0: 0b 00 00 00 00 01 * * bb bb bb bb ; - - registers msr[0010] 0000000000000006 ; tsc diff --git a/test/0039_shl.done b/test/0039_shl.done new file mode 100644 index 0000000..dde8886 --- /dev/null +++ b/test/0039_shl.done @@ -0,0 +1,27 @@ +; - - memory +; 0 1 2 3 4 5 6 7 8 9 a b c d e f +00001000: 9c 66 c1 e1 00 9c 66 d1 e1 9c f4 +0000fff0: 83 00 12 00 12 00 + +; - - registers +msr[0010] 0000000000000006 ; tsc + +cr0=00000000 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 +dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 + +gdt.base=00000000 gdt.limit=ffff +idt.base=00000000 idt.limit=ffff +tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 +ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 + +cs=0100 cs.base=00001000 cs.limit=0000ffff cs.acc=009b +ss=0000 ss.base=00000000 ss.limit=0000ffff ss.acc=0093 +ds=0000 ds.base=00000000 ds.limit=0000ffff ds.acc=0093 +es=0000 es.base=00000000 es.limit=0000ffff es.acc=0093 +fs=0000 fs.base=00000000 fs.limit=0000ffff fs.acc=0093 +gs=0000 gs.base=00000000 gs.limit=0000ffff gs.acc=0093 + +eax=00000000 ebx=00000000 ecx=fffffffe edx=00000000 +esi=00000000 edi=00000000 ebp=00000000 esp=0000fffa +eip=0000000b eflags=00000081 ; sf cf + diff --git a/test/0039_shl.tst b/test/0039_shl.tst new file mode 100644 index 0000000..2cef0d0 --- /dev/null +++ b/test/0039_shl.tst @@ -0,0 +1,11 @@ +[init] + +ecx=0xffffffff eflags=0x00000010 + +[code start=0x100:0x0] + + pushf + shl ecx,0 + pushf + shl ecx,1 + pushf diff --git a/test/0040_pushseg.done b/test/0040_pushseg.done new file mode 100644 index 0000000..559808d --- /dev/null +++ b/test/0040_pushseg.done @@ -0,0 +1,29 @@ +; - - memory +; 0 1 2 3 4 5 6 7 8 9 a b c d e f +00001000: 68 78 56 34 12 58 16 1f 1e 58 f4 +00002000: 00 00 00 00 00 00 00 00 ff ff 00 10 00 93 40 00 +00002010: ff ff 00 00 00 93 cf 00 +fffffff0: 10 00 34 12 + +; - - registers +msr[0010] 0000000000000007 ; tsc + +cr0=00000001 cr1=00000000 cr2=00000000 cr3=00000000 cr4=00000000 +dr0=00000000 dr1=00000000 dr2=00000000 dr3=00000000 dr6=00000000 dr7=00000000 + +gdt.base=00002000 gdt.limit=ffff +idt.base=00000000 idt.limit=ffff +tr=0000 tr.base=00000000 tr.limit=00000000 tr.acc=0000 +ldt=0000 ldt.base=00000000 ldt.limit=00000000 ldt.acc=0000 + +cs=0008 cs.base=00001000 cs.limit=0000ffff cs.acc=0493 +ss=0010 ss.base=00000000 ss.limit=ffffffff ss.acc=0c93 +ds=0010 ds.base=00000000 ds.limit=ffffffff ds.acc=0c93 +es=0000 es.base=00000000 es.limit=00000000 es.acc=0000 +fs=0000 fs.base=00000000 fs.limit=00000000 fs.acc=0000 +gs=0000 gs.base=00000000 gs.limit=00000000 gs.acc=0000 + +eax=12340010 ebx=00000000 ecx=00000000 edx=00000000 +esi=00000000 edi=00000000 ebp=00000000 esp=00000000 +eip=0000000b eflags=00000002 + diff --git a/test/0040_pushseg.tst b/test/0040_pushseg.tst new file mode 100644 index 0000000..7256ce7 --- /dev/null +++ b/test/0040_pushseg.tst @@ -0,0 +1,17 @@ +[init mode=protected] + +gdt.base=0x2000 +gdt[0x00]=0 +gdt[0x08]=descr(base=0x1000,limit=0xffff,acc=0x493) +gdt[0x10]=descr(base=0,limit=0xffffffff,acc=0xc93) + +ss=0x10 + +[code start=8:0 bits=32] + + push 0x12345678 + pop eax + push ss + pop ds + push ds + pop eax