- added instructions how to update the online documentation
[bochs-mirror.git] / cpu / stack32.cc
blobc49253f448cdfeaa26d5eefe53a9fb1471a3bd8f
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: stack32.cc,v 1.57 2008/09/19 19:18:57 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (C) 2001 MandrakeSoft S.A.
6 //
7 // MandrakeSoft S.A.
8 // 43, rue d'Aboukir
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
29 #include "bochs.h"
30 #include "cpu.h"
31 #define LOG_THIS BX_CPU_THIS_PTR
33 // Make code more tidy with a few macros.
34 #if BX_SUPPORT_X86_64==0
35 #define RSP ESP
36 #endif
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)
160 push_32(i->Id());
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);
169 push_32(op1_32);
172 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSHAD32(bxInstruction_c *i)
174 Bit32u temp_ESP = ESP;
175 Bit16u temp_SP = SP;
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);
187 ESP -= 32;
189 else
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);
199 SP -= 32;
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));
218 ESP += 32;
220 else
222 Bit16u temp_SP = SP;
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));
231 SP += 32;
234 EDI = edi;
235 ESI = esi;
236 EBP = ebp;
237 EBX = ebx;
238 EDX = edx;
239 ECX = ecx;
240 EAX = eax;
243 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ENTER32_IwIb(bxInstruction_c *i)
245 Bit16u imm16 = i->Iw();
246 Bit8u level = i->Ib2();
247 level &= 0x1F;
249 BX_CPU_THIS_PTR speculative_rsp = 1;
250 BX_CPU_THIS_PTR prev_rsp = RSP;
252 push_32(EBP);
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.
258 if (level > 0) {
259 /* do level-1 times */
260 while (--level) {
261 ebp -= 4;
262 Bit32u temp32 = read_virtual_dword_32(BX_SEG_REG_SS, ebp);
263 push_32(temp32);
266 /* push(frame pointer) */
267 push_32(frame_ptr32);
270 ESP -= imm16;
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);
277 else {
278 Bit16u bp = BP;
280 if (level > 0) {
281 /* do level-1 times */
282 while (--level) {
283 bp -= 4;
284 Bit32u temp32 = read_virtual_dword_32(BX_SEG_REG_SS, bp);
285 push_32(temp32);
288 /* push(frame pointer) */
289 push_32(frame_ptr32);
292 SP -= imm16;
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);
300 EBP = frame_ptr32;
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);
309 Bit32u value32;
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);
313 ESP = EBP + 4;
315 else {
316 value32 = read_virtual_dword_32(BX_SEG_REG_SS, BP);
317 SP = BP + 4;
320 EBP = value32;