- compare disk size with the size calculated from geometry to avoid image
[bochs-mirror.git] / cpu / ctrl_xfer16.cc
blobeb62076c06d3c02009a2cae542748f0618192ec5
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: ctrl_xfer16.cc,v 1.37 2007/07/09 15:16:11 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
28 #define NEED_CPU_REG_SHORTCUTS 1
29 #include "bochs.h"
30 #include "cpu.h"
31 #define LOG_THIS BX_CPU_THIS_PTR
34 void BX_CPU_C::RETnear16_Iw(bxInstruction_c *i)
36 Bit16u return_IP;
38 #if BX_DEBUGGER
39 BX_CPU_THIS_PTR show_flag |= Flag_ret;
40 #endif
42 pop_16(&return_IP);
44 if (return_IP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
46 BX_ERROR(("retnear_iw: IP > limit"));
47 exception(BX_GP_EXCEPTION, 0, 0);
50 EIP = return_IP;
52 Bit16u imm16 = i->Iw();
54 if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) /* 32bit stack */
55 ESP += imm16;
56 else
57 SP += imm16;
59 BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET, EIP);
62 void BX_CPU_C::RETnear16(bxInstruction_c *i)
64 Bit16u return_IP;
66 #if BX_DEBUGGER
67 BX_CPU_THIS_PTR show_flag |= Flag_ret;
68 #endif
70 pop_16(&return_IP);
72 if (return_IP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
74 BX_ERROR(("retnear: IP > limit"));
75 exception(BX_GP_EXCEPTION, 0, 0);
78 EIP = return_IP;
80 BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET, EIP);
83 void BX_CPU_C::RETfar16_Iw(bxInstruction_c *i)
85 Bit16s imm16;
86 Bit16u ip, cs_raw;
88 invalidate_prefetch_q();
90 #if BX_DEBUGGER
91 BX_CPU_THIS_PTR show_flag |= Flag_ret;
92 #endif
94 imm16 = i->Iw();
96 #if BX_CPU_LEVEL >= 2
97 if (protected_mode()) {
98 BX_CPU_THIS_PTR return_protected(i, imm16);
99 goto done;
101 #endif
103 pop_16(&ip);
104 pop_16(&cs_raw);
106 EIP = (Bit32u) ip;
107 load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
109 if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b)
110 ESP += imm16;
111 else
112 SP += imm16;
114 done:
115 BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET,
116 BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
119 void BX_CPU_C::RETfar16(bxInstruction_c *i)
121 Bit16u ip, cs_raw;
123 invalidate_prefetch_q();
125 #if BX_DEBUGGER
126 BX_CPU_THIS_PTR show_flag |= Flag_ret;
127 #endif
129 #if BX_CPU_LEVEL >= 2
130 if ( protected_mode() ) {
131 BX_CPU_THIS_PTR return_protected(i, 0);
132 goto done;
134 #endif
136 pop_16(&ip);
137 pop_16(&cs_raw);
138 EIP = (Bit32u) ip;
139 load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
141 done:
142 BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET,
143 BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
146 void BX_CPU_C::CALL_Aw(bxInstruction_c *i)
148 Bit32u new_EIP;
150 #if BX_DEBUGGER
151 BX_CPU_THIS_PTR show_flag |= Flag_call;
152 #endif
154 new_EIP = EIP + (Bit32s) i->Id();
155 new_EIP &= 0x0000ffff;
157 #if BX_CPU_LEVEL >= 2
158 if (new_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
160 BX_ERROR(("CALL_Aw: new_IP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].limit"));
161 exception(BX_GP_EXCEPTION, 0, 0);
163 #endif
165 /* push 16 bit EA of next instruction */
166 push_16(IP);
167 EIP = new_EIP;
169 BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL, EIP);
172 void BX_CPU_C::CALL16_Ap(bxInstruction_c *i)
174 Bit16u cs_raw;
175 Bit16u disp16;
177 invalidate_prefetch_q();
179 #if BX_DEBUGGER
180 BX_CPU_THIS_PTR show_flag |= Flag_call;
181 #endif
183 disp16 = i->Iw();
184 cs_raw = i->Iw2();
186 #if BX_CPU_LEVEL >= 2
187 if (protected_mode()) {
188 BX_CPU_THIS_PTR call_protected(i, cs_raw, disp16);
189 goto done;
191 #endif
193 push_16(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value);
194 push_16((Bit16u) EIP);
195 EIP = (Bit32u) disp16;
196 load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
198 done:
199 BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL,
200 BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
203 void BX_CPU_C::CALL_Ew(bxInstruction_c *i)
205 Bit16u op1_16;
207 #if BX_DEBUGGER
208 BX_CPU_THIS_PTR show_flag |= Flag_call;
209 #endif
211 if (i->modC0()) {
212 op1_16 = BX_READ_16BIT_REG(i->rm());
214 else {
215 read_virtual_word(i->seg(), RMAddr(i), &op1_16);
218 #if BX_CPU_LEVEL >= 2
219 if (op1_16 > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
221 BX_ERROR(("CALL_Ew: IP out of CS limits!"));
222 exception(BX_GP_EXCEPTION, 0, 0);
224 #endif
226 push_16(IP);
227 EIP = op1_16;
229 BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL, EIP);
232 void BX_CPU_C::CALL16_Ep(bxInstruction_c *i)
234 Bit16u cs_raw;
235 Bit16u op1_16;
237 invalidate_prefetch_q();
239 #if BX_DEBUGGER
240 BX_CPU_THIS_PTR show_flag |= Flag_call;
241 #endif
243 if (i->modC0()) {
244 BX_INFO(("CALL_Ep: op1 is a register"));
245 exception(BX_UD_EXCEPTION, 0, 0);
248 read_virtual_word(i->seg(), RMAddr(i), &op1_16);
249 read_virtual_word(i->seg(), RMAddr(i)+2, &cs_raw);
251 if ( protected_mode() ) {
252 BX_CPU_THIS_PTR call_protected(i, cs_raw, op1_16);
253 goto done;
256 push_16(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value);
257 push_16(IP);
259 EIP = op1_16;
260 load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
262 done:
263 BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL,
264 BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
267 void BX_CPU_C::JMP_Jw(bxInstruction_c *i)
269 Bit32u new_EIP = EIP + (Bit32s) i->Id();
270 new_EIP &= 0x0000ffff;
271 branch_near32(new_EIP);
272 BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP, new_EIP);
275 void BX_CPU_C::JCC_Jw(bxInstruction_c *i)
277 bx_bool condition;
279 switch (i->b1() & 0x0f) {
280 case 0x00: /* JO */ condition = get_OF(); break;
281 case 0x01: /* JNO */ condition = !get_OF(); break;
282 case 0x02: /* JB */ condition = get_CF(); break;
283 case 0x03: /* JNB */ condition = !get_CF(); break;
284 case 0x04: /* JZ */ condition = get_ZF(); break;
285 case 0x05: /* JNZ */ condition = !get_ZF(); break;
286 case 0x06: /* JBE */ condition = get_CF() || get_ZF(); break;
287 case 0x07: /* JNBE */ condition = !get_CF() && !get_ZF(); break;
288 case 0x08: /* JS */ condition = get_SF(); break;
289 case 0x09: /* JNS */ condition = !get_SF(); break;
290 case 0x0A: /* JP */ condition = get_PF(); break;
291 case 0x0B: /* JNP */ condition = !get_PF(); break;
292 case 0x0C: /* JL */ condition = getB_SF() != getB_OF(); break;
293 case 0x0D: /* JNL */ condition = getB_SF() == getB_OF(); break;
294 case 0x0E: /* JLE */ condition = get_ZF() || (getB_SF() != getB_OF()); break;
295 case 0x0F: /* JNLE */ condition = (getB_SF() == getB_OF()) && !get_ZF(); break;
296 default:
297 condition = 0; // For compiler...all targets should set condition.
298 break;
301 if (condition) {
302 Bit32u new_EIP = EIP + (Bit32s) i->Id();
303 new_EIP &= 0x0000ffff;
304 branch_near32(new_EIP);
305 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
307 #if BX_INSTRUMENTATION
308 else {
309 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
311 #endif
314 void BX_CPU_C::JZ_Jw(bxInstruction_c *i)
316 if (get_ZF()) {
317 Bit32u new_EIP = EIP + (Bit32s) i->Id();
318 new_EIP &= 0x0000ffff;
319 branch_near32(new_EIP);
320 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
322 #if BX_INSTRUMENTATION
323 else {
324 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
326 #endif
329 void BX_CPU_C::JNZ_Jw(bxInstruction_c *i)
331 if (!get_ZF()) {
332 Bit32u new_EIP = EIP + (Bit32s) i->Id();
333 new_EIP &= 0x0000ffff;
334 branch_near32(new_EIP);
335 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
337 #if BX_INSTRUMENTATION
338 else {
339 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
341 #endif
344 void BX_CPU_C::JMP_Ew(bxInstruction_c *i)
346 Bit16u op1_16;
348 if (i->modC0()) {
349 op1_16 = BX_READ_16BIT_REG(i->rm());
351 else {
352 read_virtual_word(i->seg(), RMAddr(i), &op1_16);
355 Bit32u new_EIP = op1_16;
356 branch_near32(new_EIP);
357 BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP, new_EIP);
360 /* Far indirect jump */
362 void BX_CPU_C::JMP16_Ep(bxInstruction_c *i)
364 Bit16u cs_raw;
365 Bit16u op1_16;
367 invalidate_prefetch_q();
369 if (i->modC0()) {
370 /* far indirect must specify a memory address */
371 BX_INFO(("JMP_Ep(): op1 is a register"));
372 exception(BX_UD_EXCEPTION, 0, 0);
375 read_virtual_word(i->seg(), RMAddr(i), &op1_16);
376 read_virtual_word(i->seg(), RMAddr(i)+2, &cs_raw);
378 #if BX_CPU_LEVEL >= 2
379 if ( protected_mode() ) {
380 BX_CPU_THIS_PTR jump_protected(i, cs_raw, op1_16);
381 goto done;
383 #endif
385 EIP = op1_16;
386 load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
388 done:
389 BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP,
390 BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
393 void BX_CPU_C::IRET16(bxInstruction_c *i)
395 Bit16u ip, cs_raw, flags;
397 invalidate_prefetch_q();
399 #if BX_DEBUGGER
400 BX_CPU_THIS_PTR show_flag |= Flag_iret;
401 #endif
403 BX_CPU_THIS_PTR nmi_disable = 0;
405 if (v8086_mode()) {
406 // IOPL check in stack_return_from_v86()
407 iret16_stack_return_from_v86(i);
408 goto done;
411 #if BX_CPU_LEVEL >= 2
412 if (BX_CPU_THIS_PTR cr0.get_PE()) {
413 iret_protected(i);
414 goto done;
416 #endif
418 if (! can_pop(6)) {
419 BX_ERROR(("IRET: top 6 bytes of stack not within stack limits"));
420 exception(BX_SS_EXCEPTION, 0, 0);
423 pop_16(&ip);
424 pop_16(&cs_raw);
425 pop_16(&flags);
427 load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
428 EIP = (Bit32u) ip;
429 write_flags(flags, /* change IOPL? */ 1, /* change IF? */ 1);
431 done:
432 BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_IRET,
433 BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);