1 /////////////////////////////////////////////////////////////////////////
2 // $Id: stack32.cc,v 1.57 2008/09/19 19:18:57 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
5 // Copyright (C) 2001 MandrakeSoft S.A.
9 // 75002 Paris - France
10 // http://www.linux-mandrake.com/
11 // http://www.mandrakesoft.com/
13 // This library is free software; you can redistribute it and/or
14 // modify it under the terms of the GNU Lesser General Public
15 // License as published by the Free Software Foundation; either
16 // version 2 of the License, or (at your option) any later version.
18 // This library is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 // Lesser General Public License for more details.
23 // You should have received a copy of the GNU Lesser General Public
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
26 /////////////////////////////////////////////////////////////////////////
28 #define NEED_CPU_REG_SHORTCUTS 1
31 #define LOG_THIS BX_CPU_THIS_PTR
33 // Make code more tidy with a few macros.
34 #if BX_SUPPORT_X86_64==0
38 void BX_CPP_AttrRegparmN(1) BX_CPU_C::POP_EdM(bxInstruction_c
*i
)
40 BX_CPU_THIS_PTR speculative_rsp
= 1;
41 BX_CPU_THIS_PTR prev_rsp
= RSP
;
43 Bit32u val32
= pop_32();
45 // Note: there is one little weirdism here. It is possible to use
46 // ESP in the modrm addressing. If used, the value of ESP after the
47 // pop is used to calculate the address.
48 bx_address eaddr
= BX_CPU_CALL_METHODR(i
->ResolveModrm
, (i
));
50 write_virtual_dword(i
->seg(), eaddr
, val32
);
52 BX_CPU_THIS_PTR speculative_rsp
= 0;
55 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSH_ERX(bxInstruction_c
*i
)
57 push_32(BX_READ_32BIT_REG(i
->opcodeReg()));
60 void BX_CPP_AttrRegparmN(1) BX_CPU_C::POP_ERX(bxInstruction_c
*i
)
62 BX_WRITE_32BIT_REGZ(i
->opcodeReg(), pop_32());
65 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSH32_CS(bxInstruction_c
*i
)
67 push_32(BX_CPU_THIS_PTR sregs
[BX_SEG_REG_CS
].selector
.value
);
70 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSH32_DS(bxInstruction_c
*i
)
72 push_32(BX_CPU_THIS_PTR sregs
[BX_SEG_REG_DS
].selector
.value
);
75 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSH32_ES(bxInstruction_c
*i
)
77 push_32(BX_CPU_THIS_PTR sregs
[BX_SEG_REG_ES
].selector
.value
);
80 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSH32_FS(bxInstruction_c
*i
)
82 push_32(BX_CPU_THIS_PTR sregs
[BX_SEG_REG_FS
].selector
.value
);
85 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSH32_GS(bxInstruction_c
*i
)
87 push_32(BX_CPU_THIS_PTR sregs
[BX_SEG_REG_GS
].selector
.value
);
90 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSH32_SS(bxInstruction_c
*i
)
92 push_32(BX_CPU_THIS_PTR sregs
[BX_SEG_REG_SS
].selector
.value
);
95 void BX_CPP_AttrRegparmN(1) BX_CPU_C::POP32_DS(bxInstruction_c
*i
)
97 BX_CPU_THIS_PTR speculative_rsp
= 1;
98 BX_CPU_THIS_PTR prev_rsp
= RSP
;
100 Bit32u ds
= pop_32();
101 load_seg_reg(&BX_CPU_THIS_PTR sregs
[BX_SEG_REG_DS
], (Bit16u
) ds
);
103 BX_CPU_THIS_PTR speculative_rsp
= 0;
106 void BX_CPP_AttrRegparmN(1) BX_CPU_C::POP32_ES(bxInstruction_c
*i
)
108 BX_CPU_THIS_PTR speculative_rsp
= 1;
109 BX_CPU_THIS_PTR prev_rsp
= RSP
;
111 Bit32u es
= pop_32();
112 load_seg_reg(&BX_CPU_THIS_PTR sregs
[BX_SEG_REG_ES
], (Bit16u
) es
);
114 BX_CPU_THIS_PTR speculative_rsp
= 0;
117 void BX_CPP_AttrRegparmN(1) BX_CPU_C::POP32_FS(bxInstruction_c
*i
)
119 BX_CPU_THIS_PTR speculative_rsp
= 1;
120 BX_CPU_THIS_PTR prev_rsp
= RSP
;
122 Bit32u fs
= pop_32();
123 load_seg_reg(&BX_CPU_THIS_PTR sregs
[BX_SEG_REG_FS
], (Bit16u
) fs
);
125 BX_CPU_THIS_PTR speculative_rsp
= 0;
128 void BX_CPP_AttrRegparmN(1) BX_CPU_C::POP32_GS(bxInstruction_c
*i
)
130 BX_CPU_THIS_PTR speculative_rsp
= 1;
131 BX_CPU_THIS_PTR prev_rsp
= RSP
;
133 Bit32u gs
= pop_32();
134 load_seg_reg(&BX_CPU_THIS_PTR sregs
[BX_SEG_REG_GS
], (Bit16u
) gs
);
136 BX_CPU_THIS_PTR speculative_rsp
= 0;
139 void BX_CPP_AttrRegparmN(1) BX_CPU_C::POP32_SS(bxInstruction_c
*i
)
141 BX_CPU_THIS_PTR speculative_rsp
= 1;
142 BX_CPU_THIS_PTR prev_rsp
= RSP
;
144 Bit32u ss
= pop_32();
145 load_seg_reg(&BX_CPU_THIS_PTR sregs
[BX_SEG_REG_SS
], (Bit16u
) ss
);
147 BX_CPU_THIS_PTR speculative_rsp
= 0;
149 // POP SS inhibits interrupts, debug exceptions and single-step
150 // trap exceptions until the execution boundary following the
151 // next instruction is reached.
152 // Same code as MOV_SwEw()
153 BX_CPU_THIS_PTR inhibit_mask
|=
154 BX_INHIBIT_INTERRUPTS
| BX_INHIBIT_DEBUG
;
155 BX_CPU_THIS_PTR async_event
= 1;
158 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSH_Id(bxInstruction_c
*i
)
163 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSH_EdM(bxInstruction_c
*i
)
165 bx_address eaddr
= BX_CPU_CALL_METHODR(i
->ResolveModrm
, (i
));
167 Bit32u op1_32
= read_virtual_dword_32(i
->seg(), eaddr
);
172 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSHAD32(bxInstruction_c
*i
)
174 Bit32u temp_ESP
= ESP
;
177 if (BX_CPU_THIS_PTR sregs
[BX_SEG_REG_SS
].cache
.u
.segment
.d_b
)
179 write_virtual_dword_32(BX_SEG_REG_SS
, (Bit32u
) (temp_ESP
- 4), EAX
);
180 write_virtual_dword_32(BX_SEG_REG_SS
, (Bit32u
) (temp_ESP
- 8), ECX
);
181 write_virtual_dword_32(BX_SEG_REG_SS
, (Bit32u
) (temp_ESP
- 12), EDX
);
182 write_virtual_dword_32(BX_SEG_REG_SS
, (Bit32u
) (temp_ESP
- 16), EBX
);
183 write_virtual_dword_32(BX_SEG_REG_SS
, (Bit32u
) (temp_ESP
- 20), temp_ESP
);
184 write_virtual_dword_32(BX_SEG_REG_SS
, (Bit32u
) (temp_ESP
- 24), EBP
);
185 write_virtual_dword_32(BX_SEG_REG_SS
, (Bit32u
) (temp_ESP
- 28), ESI
);
186 write_virtual_dword_32(BX_SEG_REG_SS
, (Bit32u
) (temp_ESP
- 32), EDI
);
191 write_virtual_dword_32(BX_SEG_REG_SS
, (Bit16u
) (temp_SP
- 4), EAX
);
192 write_virtual_dword_32(BX_SEG_REG_SS
, (Bit16u
) (temp_SP
- 8), ECX
);
193 write_virtual_dword_32(BX_SEG_REG_SS
, (Bit16u
) (temp_SP
- 12), EDX
);
194 write_virtual_dword_32(BX_SEG_REG_SS
, (Bit16u
) (temp_SP
- 16), EBX
);
195 write_virtual_dword_32(BX_SEG_REG_SS
, (Bit16u
) (temp_SP
- 20), temp_ESP
);
196 write_virtual_dword_32(BX_SEG_REG_SS
, (Bit16u
) (temp_SP
- 24), EBP
);
197 write_virtual_dword_32(BX_SEG_REG_SS
, (Bit16u
) (temp_SP
- 28), ESI
);
198 write_virtual_dword_32(BX_SEG_REG_SS
, (Bit16u
) (temp_SP
- 32), EDI
);
203 void BX_CPP_AttrRegparmN(1) BX_CPU_C::POPAD32(bxInstruction_c
*i
)
205 Bit32u edi
, esi
, ebp
, ebx
, edx
, ecx
, eax
, dummy
;
207 if (BX_CPU_THIS_PTR sregs
[BX_SEG_REG_SS
].cache
.u
.segment
.d_b
)
209 Bit32u temp_ESP
= ESP
;
210 edi
= read_virtual_dword_32(BX_SEG_REG_SS
, (Bit32u
) (temp_ESP
+ 0));
211 esi
= read_virtual_dword_32(BX_SEG_REG_SS
, (Bit32u
) (temp_ESP
+ 4));
212 ebp
= read_virtual_dword_32(BX_SEG_REG_SS
, (Bit32u
) (temp_ESP
+ 8));
213 dummy
= read_virtual_dword_32(BX_SEG_REG_SS
, (Bit32u
) (temp_ESP
+ 12));
214 ebx
= read_virtual_dword_32(BX_SEG_REG_SS
, (Bit32u
) (temp_ESP
+ 16));
215 edx
= read_virtual_dword_32(BX_SEG_REG_SS
, (Bit32u
) (temp_ESP
+ 20));
216 ecx
= read_virtual_dword_32(BX_SEG_REG_SS
, (Bit32u
) (temp_ESP
+ 24));
217 eax
= read_virtual_dword_32(BX_SEG_REG_SS
, (Bit32u
) (temp_ESP
+ 28));
223 edi
= read_virtual_dword_32(BX_SEG_REG_SS
, (Bit16u
) (temp_SP
+ 0));
224 esi
= read_virtual_dword_32(BX_SEG_REG_SS
, (Bit16u
) (temp_SP
+ 4));
225 ebp
= read_virtual_dword_32(BX_SEG_REG_SS
, (Bit16u
) (temp_SP
+ 8));
226 dummy
= read_virtual_dword_32(BX_SEG_REG_SS
, (Bit16u
) (temp_SP
+ 12));
227 ebx
= read_virtual_dword_32(BX_SEG_REG_SS
, (Bit16u
) (temp_SP
+ 16));
228 edx
= read_virtual_dword_32(BX_SEG_REG_SS
, (Bit16u
) (temp_SP
+ 20));
229 ecx
= read_virtual_dword_32(BX_SEG_REG_SS
, (Bit16u
) (temp_SP
+ 24));
230 eax
= read_virtual_dword_32(BX_SEG_REG_SS
, (Bit16u
) (temp_SP
+ 28));
243 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ENTER32_IwIb(bxInstruction_c
*i
)
245 Bit16u imm16
= i
->Iw();
246 Bit8u level
= i
->Ib2();
249 BX_CPU_THIS_PTR speculative_rsp
= 1;
250 BX_CPU_THIS_PTR prev_rsp
= RSP
;
253 Bit32u frame_ptr32
= ESP
;
255 if (BX_CPU_THIS_PTR sregs
[BX_SEG_REG_SS
].cache
.u
.segment
.d_b
) {
256 Bit32u ebp
= EBP
; // Use temp copy for case of exception.
259 /* do level-1 times */
262 Bit32u temp32
= read_virtual_dword_32(BX_SEG_REG_SS
, ebp
);
266 /* push(frame pointer) */
267 push_32(frame_ptr32
);
272 // ENTER finishes with memory write check on the final stack pointer
273 // the memory is touched but no write actually occurs
274 // emulate it by doing RMW read access from SS:ESP
275 read_RMW_virtual_dword(BX_SEG_REG_SS
, ESP
);
281 /* do level-1 times */
284 Bit32u temp32
= read_virtual_dword_32(BX_SEG_REG_SS
, bp
);
288 /* push(frame pointer) */
289 push_32(frame_ptr32
);
294 // ENTER finishes with memory write check on the final stack pointer
295 // the memory is touched but no write actually occurs
296 // emulate it by doing RMW read access from SS:SP
297 read_RMW_virtual_dword_32(BX_SEG_REG_SS
, SP
);
302 BX_CPU_THIS_PTR speculative_rsp
= 0;
305 void BX_CPP_AttrRegparmN(1) BX_CPU_C::LEAVE32(bxInstruction_c
*i
)
307 BX_ASSERT(BX_CPU_THIS_PTR cpu_mode
!= BX_MODE_LONG_64
);
311 if (BX_CPU_THIS_PTR sregs
[BX_SEG_REG_SS
].cache
.u
.segment
.d_b
) {
312 value32
= read_virtual_dword_32(BX_SEG_REG_SS
, EBP
);
316 value32
= read_virtual_dword_32(BX_SEG_REG_SS
, BP
);