1 /////////////////////////////////////////////////////////////////////////
2 // $Id: stack16.cc,v 1.43 2008/08/27 21:57:40 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::PUSH_RX(bxInstruction_c
*i
)
40 push_16(BX_READ_16BIT_REG(i
->opcodeReg()));
43 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSH16_CS(bxInstruction_c
*i
)
45 push_16(BX_CPU_THIS_PTR sregs
[BX_SEG_REG_CS
].selector
.value
);
48 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSH16_DS(bxInstruction_c
*i
)
50 push_16(BX_CPU_THIS_PTR sregs
[BX_SEG_REG_DS
].selector
.value
);
53 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSH16_ES(bxInstruction_c
*i
)
55 push_16(BX_CPU_THIS_PTR sregs
[BX_SEG_REG_ES
].selector
.value
);
58 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSH16_FS(bxInstruction_c
*i
)
60 push_16(BX_CPU_THIS_PTR sregs
[BX_SEG_REG_FS
].selector
.value
);
63 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSH16_GS(bxInstruction_c
*i
)
65 push_16(BX_CPU_THIS_PTR sregs
[BX_SEG_REG_GS
].selector
.value
);
68 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSH16_SS(bxInstruction_c
*i
)
70 push_16(BX_CPU_THIS_PTR sregs
[BX_SEG_REG_SS
].selector
.value
);
73 void BX_CPP_AttrRegparmN(1) BX_CPU_C::POP16_DS(bxInstruction_c
*i
)
75 BX_CPU_THIS_PTR speculative_rsp
= 1;
76 BX_CPU_THIS_PTR prev_rsp
= RSP
;
79 load_seg_reg(&BX_CPU_THIS_PTR sregs
[BX_SEG_REG_DS
], ds
);
81 BX_CPU_THIS_PTR speculative_rsp
= 0;
84 void BX_CPP_AttrRegparmN(1) BX_CPU_C::POP16_ES(bxInstruction_c
*i
)
86 BX_CPU_THIS_PTR speculative_rsp
= 1;
87 BX_CPU_THIS_PTR prev_rsp
= RSP
;
90 load_seg_reg(&BX_CPU_THIS_PTR sregs
[BX_SEG_REG_ES
], es
);
92 BX_CPU_THIS_PTR speculative_rsp
= 0;
95 void BX_CPP_AttrRegparmN(1) BX_CPU_C::POP16_FS(bxInstruction_c
*i
)
97 BX_CPU_THIS_PTR speculative_rsp
= 1;
98 BX_CPU_THIS_PTR prev_rsp
= RSP
;
100 Bit16u fs
= pop_16();
101 load_seg_reg(&BX_CPU_THIS_PTR sregs
[BX_SEG_REG_FS
], fs
);
103 BX_CPU_THIS_PTR speculative_rsp
= 0;
106 void BX_CPP_AttrRegparmN(1) BX_CPU_C::POP16_GS(bxInstruction_c
*i
)
108 BX_CPU_THIS_PTR speculative_rsp
= 1;
109 BX_CPU_THIS_PTR prev_rsp
= RSP
;
111 Bit16u gs
= pop_16();
112 load_seg_reg(&BX_CPU_THIS_PTR sregs
[BX_SEG_REG_GS
], gs
);
114 BX_CPU_THIS_PTR speculative_rsp
= 0;
117 void BX_CPP_AttrRegparmN(1) BX_CPU_C::POP16_SS(bxInstruction_c
*i
)
119 BX_CPU_THIS_PTR speculative_rsp
= 1;
120 BX_CPU_THIS_PTR prev_rsp
= RSP
;
122 Bit16u ss
= pop_16();
123 load_seg_reg(&BX_CPU_THIS_PTR sregs
[BX_SEG_REG_SS
], ss
);
125 BX_CPU_THIS_PTR speculative_rsp
= 0;
127 // POP SS inhibits interrupts, debug exceptions and single-step
128 // trap exceptions until the execution boundary following the
129 // next instruction is reached.
130 // Same code as MOV_SwEw()
131 BX_CPU_THIS_PTR inhibit_mask
|=
132 BX_INHIBIT_INTERRUPTS
| BX_INHIBIT_DEBUG
;
133 BX_CPU_THIS_PTR async_event
= 1;
136 void BX_CPP_AttrRegparmN(1) BX_CPU_C::POP_RX(bxInstruction_c
*i
)
138 BX_WRITE_16BIT_REG(i
->opcodeReg(), pop_16());
141 void BX_CPP_AttrRegparmN(1) BX_CPU_C::POP_EwM(bxInstruction_c
*i
)
143 BX_CPU_THIS_PTR speculative_rsp
= 1;
144 BX_CPU_THIS_PTR prev_rsp
= RSP
;
146 Bit16u val16
= pop_16();
148 // Note: there is one little weirdism here. It is possible to use
149 // SP in the modrm addressing. If used, the value of SP after the
150 // pop is used to calculate the address.
151 bx_address eaddr
= BX_CPU_CALL_METHODR(i
->ResolveModrm
, (i
));
153 write_virtual_word(i
->seg(), eaddr
, val16
);
155 BX_CPU_THIS_PTR speculative_rsp
= 0;
158 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSH_Iw(bxInstruction_c
*i
)
163 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSH_EwM(bxInstruction_c
*i
)
165 bx_address eaddr
= BX_CPU_CALL_METHODR(i
->ResolveModrm
, (i
));
167 Bit16u op1_16
= read_virtual_word(i
->seg(), eaddr
);
172 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSHAD16(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_word_32(BX_SEG_REG_SS
, (Bit32u
)(temp_ESP
- 2), AX
);
180 write_virtual_word_32(BX_SEG_REG_SS
, (Bit32u
)(temp_ESP
- 4), CX
);
181 write_virtual_word_32(BX_SEG_REG_SS
, (Bit32u
)(temp_ESP
- 6), DX
);
182 write_virtual_word_32(BX_SEG_REG_SS
, (Bit32u
)(temp_ESP
- 8), BX
);
183 write_virtual_word_32(BX_SEG_REG_SS
, (Bit32u
)(temp_ESP
- 10), temp_SP
);
184 write_virtual_word_32(BX_SEG_REG_SS
, (Bit32u
)(temp_ESP
- 12), BP
);
185 write_virtual_word_32(BX_SEG_REG_SS
, (Bit32u
)(temp_ESP
- 14), SI
);
186 write_virtual_word_32(BX_SEG_REG_SS
, (Bit32u
)(temp_ESP
- 16), DI
);
191 write_virtual_word_32(BX_SEG_REG_SS
, (Bit16u
)(temp_SP
- 2), AX
);
192 write_virtual_word_32(BX_SEG_REG_SS
, (Bit16u
)(temp_SP
- 4), CX
);
193 write_virtual_word_32(BX_SEG_REG_SS
, (Bit16u
)(temp_SP
- 6), DX
);
194 write_virtual_word_32(BX_SEG_REG_SS
, (Bit16u
)(temp_SP
- 8), BX
);
195 write_virtual_word_32(BX_SEG_REG_SS
, (Bit16u
)(temp_SP
- 10), temp_SP
);
196 write_virtual_word_32(BX_SEG_REG_SS
, (Bit16u
)(temp_SP
- 12), BP
);
197 write_virtual_word_32(BX_SEG_REG_SS
, (Bit16u
)(temp_SP
- 14), SI
);
198 write_virtual_word_32(BX_SEG_REG_SS
, (Bit16u
)(temp_SP
- 16), DI
);
203 void BX_CPP_AttrRegparmN(1) BX_CPU_C::POPAD16(bxInstruction_c
*i
)
205 Bit16u di
, si
, bp
, bx
, dx
, cx
, ax
, dummy
;
207 if (BX_CPU_THIS_PTR sregs
[BX_SEG_REG_SS
].cache
.u
.segment
.d_b
)
209 Bit32u temp_ESP
= ESP
;
210 di
= read_virtual_word_32(BX_SEG_REG_SS
, (Bit32u
)(temp_ESP
+ 0));
211 si
= read_virtual_word_32(BX_SEG_REG_SS
, (Bit32u
)(temp_ESP
+ 2));
212 bp
= read_virtual_word_32(BX_SEG_REG_SS
, (Bit32u
)(temp_ESP
+ 4));
213 dummy
= read_virtual_word_32(BX_SEG_REG_SS
, (Bit32u
)(temp_ESP
+ 6));
214 bx
= read_virtual_word_32(BX_SEG_REG_SS
, (Bit32u
)(temp_ESP
+ 8));
215 dx
= read_virtual_word_32(BX_SEG_REG_SS
, (Bit32u
)(temp_ESP
+ 10));
216 cx
= read_virtual_word_32(BX_SEG_REG_SS
, (Bit32u
)(temp_ESP
+ 12));
217 ax
= read_virtual_word_32(BX_SEG_REG_SS
, (Bit32u
)(temp_ESP
+ 14));
223 di
= read_virtual_word_32(BX_SEG_REG_SS
, (Bit16u
)(temp_SP
+ 0));
224 si
= read_virtual_word_32(BX_SEG_REG_SS
, (Bit16u
)(temp_SP
+ 2));
225 bp
= read_virtual_word_32(BX_SEG_REG_SS
, (Bit16u
)(temp_SP
+ 4));
226 dummy
= read_virtual_word_32(BX_SEG_REG_SS
, (Bit16u
)(temp_SP
+ 6));
227 bx
= read_virtual_word_32(BX_SEG_REG_SS
, (Bit16u
)(temp_SP
+ 8));
228 dx
= read_virtual_word_32(BX_SEG_REG_SS
, (Bit16u
)(temp_SP
+ 10));
229 cx
= read_virtual_word_32(BX_SEG_REG_SS
, (Bit16u
)(temp_SP
+ 12));
230 ax
= read_virtual_word_32(BX_SEG_REG_SS
, (Bit16u
)(temp_SP
+ 14));
243 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ENTER16_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 Bit16u frame_ptr16
= SP
;
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 Bit16u temp16
= read_virtual_word_32(BX_SEG_REG_SS
, ebp
);
266 /* push(frame pointer) */
267 push_16(frame_ptr16
);
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_word(BX_SEG_REG_SS
, ESP
);
283 /* do level-1 times */
286 Bit16u temp16
= read_virtual_word_32(BX_SEG_REG_SS
, bp
);
290 /* push(frame pointer) */
291 push_16(frame_ptr16
);
296 // ENTER finishes with memory write check on the final stack pointer
297 // the memory is touched but no write actually occurs
298 // emulate it by doing RMW read access from SS:SP
299 read_RMW_virtual_word_32(BX_SEG_REG_SS
, SP
);
304 BX_CPU_THIS_PTR speculative_rsp
= 0;
307 void BX_CPP_AttrRegparmN(1) BX_CPU_C::LEAVE16(bxInstruction_c
*i
)
309 BX_ASSERT(BX_CPU_THIS_PTR cpu_mode
!= BX_MODE_LONG_64
);
313 if (BX_CPU_THIS_PTR sregs
[BX_SEG_REG_SS
].cache
.u
.segment
.d_b
) {
314 value16
= read_virtual_word_32(BX_SEG_REG_SS
, EBP
);
318 value16
= read_virtual_word_32(BX_SEG_REG_SS
, BP
);