23
23
// You should have received a copy of the GNU Lesser General Public
24
24
// License along with this library; if not, write to the Free Software
25
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
26
26
/////////////////////////////////////////////////////////////////////////
28
28
#define NEED_CPU_REG_SHORTCUTS 1
33
33
// Make code more tidy with a few macros.
34
34
#if BX_SUPPORT_X86_64==0
38
void BX_CPP_AttrRegparmN(1) BX_CPU_C::branch_near32(Bit32u new_EIP)
41
BX_CPP_INLINE void BX_CPP_AttrRegparmN(1) BX_CPU_C::branch_near32(Bit32u new_EIP)
43
BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
40
45
// check always, not only in protected mode
41
46
if (new_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
43
BX_ERROR(("branch_near: offset outside of CS limits"));
48
BX_ERROR(("branch_near32: offset outside of CS limits"));
44
49
exception(BX_GP_EXCEPTION, 0, 0);
47
54
#if BX_SUPPORT_TRACE_CACHE && !defined(BX_TRACE_CACHE_NO_SPECULATIVE_TRACING)
48
55
// assert magic async_event to stop trace execution
49
56
BX_CPU_THIS_PTR async_event |= BX_ASYNC_EVENT_STOP_TRACE;
57
60
void BX_CPP_AttrRegparmN(1) BX_CPU_C::RETnear32_Iw(bxInstruction_c *i)
62
BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
60
65
BX_CPU_THIS_PTR show_flag |= Flag_ret;
63
BX_CPU_THIS_PTR speculative_rsp = 1;
64
BX_CPU_THIS_PTR prev_rsp = RSP;
66
70
Bit16u imm16 = i->Iw();
67
71
Bit32u return_EIP = pop_32();
68
branch_near32(return_EIP);
72
if (return_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
74
BX_ERROR(("RETnear32_Iw: offset outside of CS limits"));
75
exception(BX_GP_EXCEPTION, 0, 0);
69
79
if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b)
74
BX_CPU_THIS_PTR speculative_rsp = 0;
76
86
BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET, EIP);
79
89
void BX_CPP_AttrRegparmN(1) BX_CPU_C::RETnear32(bxInstruction_c *i)
91
BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
82
94
BX_CPU_THIS_PTR show_flag |= Flag_ret;
85
BX_CPU_THIS_PTR speculative_rsp = 1;
86
BX_CPU_THIS_PTR prev_rsp = RSP;
88
99
Bit32u return_EIP = pop_32();
89
branch_near32(return_EIP);
100
if (return_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
102
BX_ERROR(("RETnear32: offset outside of CS limits"));
103
exception(BX_GP_EXCEPTION, 0, 0);
91
BX_CPU_THIS_PTR speculative_rsp = 0;
93
109
BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET, EIP);
108
BX_CPU_THIS_PTR speculative_rsp = 1;
109
BX_CPU_THIS_PTR prev_rsp = RSP;
111
126
if (protected_mode()) {
112
BX_CPU_THIS_PTR return_protected(i, imm16);
127
return_protected(i, imm16);
132
cs_raw = (Bit16u) pop_32(); /* 32bit pop, MSW discarded */
118
134
// CS.LIMIT can't change when in real/v8086 mode
119
135
if (eip > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) {
165
179
exception(BX_GP_EXCEPTION, 0, 0);
168
cs_raw = (Bit16u) pop_32(); /* 32bit pop, MSW discarded */
170
182
load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
174
BX_CPU_THIS_PTR speculative_rsp = 0;
176
188
BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET,
177
189
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
186
198
Bit32u new_EIP = EIP + i->Id();
188
if (new_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) {
189
BX_ERROR(("CALL_Jd: offset outside of CS limits"));
190
exception(BX_GP_EXCEPTION, 0, 0);
193
202
/* push 32 bit EA of next instruction */
205
branch_near32(new_EIP);
197
209
BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL, EIP);
200
212
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CALL32_Ap(bxInstruction_c *i)
214
BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
235
BX_CPU_THIS_PTR speculative_rsp = 0;
237
250
BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL,
238
251
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
241
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CALL_EdM(bxInstruction_c *i)
243
BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
246
BX_CPU_THIS_PTR show_flag |= Flag_call;
249
Bit32u op1_32 = read_virtual_dword(i->seg(), RMAddr(i));
251
if (op1_32 > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
253
BX_ERROR(("CALL_Ed: EIP out of CS limits!"));
254
exception(BX_GP_EXCEPTION, 0, 0);
260
BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL, EIP);
263
254
void BX_CPP_AttrRegparmN(1) BX_CPU_C::CALL_EdR(bxInstruction_c *i)
266
257
BX_CPU_THIS_PTR show_flag |= Flag_call;
269
Bit32u op1_32 = BX_READ_32BIT_REG(i->rm());
271
if (op1_32 > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
273
BX_ERROR(("CALL_Ed: EIP out of CS limits!"));
274
exception(BX_GP_EXCEPTION, 0, 0);
260
Bit32u new_EIP = BX_READ_32BIT_REG(i->rm());
264
/* push 32 bit EA of next instruction */
267
branch_near32(new_EIP);
280
271
BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL, EIP);
291
282
BX_CPU_THIS_PTR show_flag |= Flag_call;
294
BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
285
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
296
287
/* pointer, segment address pair */
297
op1_32 = read_virtual_dword(i->seg(), RMAddr(i));
298
cs_raw = read_virtual_word (i->seg(), RMAddr(i)+4);
288
op1_32 = read_virtual_dword(i->seg(), eaddr);
289
cs_raw = read_virtual_word (i->seg(), eaddr+4);
300
BX_CPU_THIS_PTR speculative_rsp = 1;
301
BX_CPU_THIS_PTR prev_rsp = RSP;
303
293
if (protected_mode()) {
304
BX_CPU_THIS_PTR call_protected(i, cs_raw, op1_32);
294
call_protected(i, cs_raw, op1_32);
568
582
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
571
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JMP_EdM(bxInstruction_c *i)
573
BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
575
/* pointer, segment address pair */
576
Bit32u new_EIP = read_virtual_dword(i->seg(), RMAddr(i));
578
if (new_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
580
BX_ERROR(("JMP_Ed: offset outside of CS limits"));
581
exception(BX_GP_EXCEPTION, 0, 0);
586
BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP, new_EIP);
589
585
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JMP_EdR(bxInstruction_c *i)
591
587
Bit32u new_EIP = BX_READ_32BIT_REG(i->rm());
593
if (new_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
595
BX_ERROR(("JMP_Ed: offset outside of CS limits"));
596
exception(BX_GP_EXCEPTION, 0, 0);
588
branch_near32(new_EIP);
601
589
BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP, new_EIP);
610
598
invalidate_prefetch_q();
612
BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
600
bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
614
602
/* pointer, segment address pair */
615
op1_32 = read_virtual_dword(i->seg(), RMAddr(i));
616
cs_raw = read_virtual_word (i->seg(), RMAddr(i)+4);
603
op1_32 = read_virtual_dword(i->seg(), eaddr);
604
cs_raw = read_virtual_word (i->seg(), eaddr+4);
618
606
// jump_protected doesn't affect RSP so it is RSP safe
619
607
if (protected_mode()) {
620
BX_CPU_THIS_PTR jump_protected(i, cs_raw, op1_32);
608
jump_protected(i, cs_raw, op1_32);
638
626
void BX_CPP_AttrRegparmN(1) BX_CPU_C::IRET32(bxInstruction_c *i)
628
BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
640
630
Bit32u eip, eflags32;
643
633
invalidate_prefetch_q();
636
if (!BX_CPU_THIS_PTR in_vmx_guest || !VMEXIT(VMX_VM_EXEC_CTRL1_NMI_VMEXIT))
638
BX_CPU_THIS_PTR disable_NMI = 0;
646
641
BX_CPU_THIS_PTR show_flag |= Flag_iret;
649
BX_CPU_THIS_PTR nmi_disable = 0;
651
BX_CPU_THIS_PTR speculative_rsp = 1;
652
BX_CPU_THIS_PTR prev_rsp = RSP;
654
646
if (v8086_mode()) {
655
647
// IOPL check in stack_return_from_v86()
670
664
exception(BX_GP_EXCEPTION, 0, 0);
673
cs_raw = (Bit16u) pop_32();
676
667
load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
678
669
writeEFlags(eflags32, 0x00257fd5); // VIF, VIP, VM unchanged
681
BX_CPU_THIS_PTR speculative_rsp = 0;
683
674
BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_IRET,
684
675
BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
678
void BX_CPP_AttrRegparmN(1) BX_CPU_C::JECXZ_Jb(bxInstruction_c *i)
680
// it is impossible to get this instruction in long mode
681
BX_ASSERT(i->as64L() == 0);
691
Bit32u new_EIP = EIP + (Bit32s) i->Id();
692
branch_near32(new_EIP);
693
BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
695
#if BX_INSTRUMENTATION
697
BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
703
// There is some weirdness in LOOP instructions definition. If an exception
704
// was generated during the instruction execution (for example #GP fault
705
// because EIP was beyond CS segment limits) CPU state should restore the
706
// state prior to instruction execution.
708
// The final point that we are not allowed to decrement ECX register before
709
// it is known that no exceptions can happen.
712
void BX_CPP_AttrRegparmN(1) BX_CPU_C::LOOPNE32_Jb(bxInstruction_c *i)
714
// it is impossible to get this instruction in long mode
715
BX_ASSERT(i->as64L() == 0);
721
if (count != 0 && (get_ZF()==0)) {
722
Bit32u new_EIP = EIP + (Bit32s) i->Id();
723
branch_near32(new_EIP);
724
BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
726
#if BX_INSTRUMENTATION
728
BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
738
if (count != 0 && (get_ZF()==0)) {
739
Bit32u new_EIP = EIP + (Bit32s) i->Id();
740
branch_near32(new_EIP);
741
BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
743
#if BX_INSTRUMENTATION
745
BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
753
void BX_CPP_AttrRegparmN(1) BX_CPU_C::LOOPE32_Jb(bxInstruction_c *i)
755
// it is impossible to get this instruction in long mode
756
BX_ASSERT(i->as64L() == 0);
762
if (count != 0 && get_ZF()) {
763
Bit32u new_EIP = EIP + (Bit32s) i->Id();
764
branch_near32(new_EIP);
765
BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
767
#if BX_INSTRUMENTATION
769
BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
779
if (count != 0 && get_ZF()) {
780
Bit32u new_EIP = EIP + (Bit32s) i->Id();
781
branch_near32(new_EIP);
782
BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
784
#if BX_INSTRUMENTATION
786
BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
794
void BX_CPP_AttrRegparmN(1) BX_CPU_C::LOOP32_Jb(bxInstruction_c *i)
796
// it is impossible to get this instruction in long mode
797
BX_ASSERT(i->as64L() == 0);
804
Bit32u new_EIP = EIP + (Bit32s) i->Id();
805
branch_near32(new_EIP);
806
BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
808
#if BX_INSTRUMENTATION
810
BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
821
Bit32u new_EIP = EIP + (Bit32s) i->Id();
822
branch_near32(new_EIP);
823
BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
825
#if BX_INSTRUMENTATION
827
BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);