- update sector count before calling write completion function (SF patch #2144692)
[bochs-mirror.git] / cpu / stack16.cc
blob7eb7a4228377ebfee1acff373a4b4e6c8986caa9
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: stack16.cc,v 1.43 2008/08/27 21:57:40 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::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;
78 Bit16u ds = pop_16();
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;
89 Bit16u es = pop_16();
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)
160 push_16(i->Iw());
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);
169 push_16(op1_16);
172 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSHAD16(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_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);
187 ESP -= 16;
189 else
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);
199 SP -= 16;
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));
218 ESP += 16;
220 else
222 Bit16u temp_SP = SP;
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));
231 SP += 16;
234 DI = di;
235 SI = si;
236 BP = bp;
237 BX = bx;
238 DX = dx;
239 CX = cx;
240 AX = ax;
243 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ENTER16_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_16(BP);
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.
258 if (level > 0) {
259 /* do level-1 times */
260 while (--level) {
261 ebp -= 2;
262 Bit16u temp16 = read_virtual_word_32(BX_SEG_REG_SS, ebp);
263 push_16(temp16);
266 /* push(frame pointer) */
267 push_16(frame_ptr16);
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_word(BX_SEG_REG_SS, ESP);
277 BP = frame_ptr16;
279 else {
280 Bit16u bp = BP;
282 if (level > 0) {
283 /* do level-1 times */
284 while (--level) {
285 bp -= 2;
286 Bit16u temp16 = read_virtual_word_32(BX_SEG_REG_SS, bp);
287 push_16(temp16);
290 /* push(frame pointer) */
291 push_16(frame_ptr16);
294 SP -= imm16;
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);
302 BP = frame_ptr16;
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);
311 Bit16u value16;
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);
315 ESP = EBP + 2;
317 else {
318 value16 = read_virtual_word_32(BX_SEG_REG_SS, BP);
319 SP = BP + 2;
322 BP = value16;