- compilation fixes for MSVC toolkit 2003
[bochs-mirror.git] / cpu / ctrl_xfer32.cc
blob26024eab56727a7798781ae2e1f86e11ac591d54
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: ctrl_xfer32.cc,v 1.80 2008/10/06 20:41:28 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 #define RIP EIP
37 #endif
39 #if BX_CPU_LEVEL >= 3
41 BX_CPP_INLINE void BX_CPP_AttrRegparmN(1) BX_CPU_C::branch_near32(Bit32u new_EIP)
43 BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
45 // check always, not only in protected mode
46 if (new_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
48 BX_ERROR(("branch_near32: offset outside of CS limits"));
49 exception(BX_GP_EXCEPTION, 0, 0);
52 EIP = new_EIP;
54 #if BX_SUPPORT_TRACE_CACHE && !defined(BX_TRACE_CACHE_NO_SPECULATIVE_TRACING)
55 // assert magic async_event to stop trace execution
56 BX_CPU_THIS_PTR async_event |= BX_ASYNC_EVENT_STOP_TRACE;
57 #endif
60 void BX_CPP_AttrRegparmN(1) BX_CPU_C::RETnear32_Iw(bxInstruction_c *i)
62 BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
64 #if BX_DEBUGGER
65 BX_CPU_THIS_PTR show_flag |= Flag_ret;
66 #endif
68 BX_CPU_THIS_PTR speculative_rsp = 1;
69 BX_CPU_THIS_PTR prev_rsp = ESP;
71 Bit16u imm16 = i->Iw();
72 Bit32u return_EIP = pop_32();
73 if (return_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
75 BX_ERROR(("RETnear32_Iw: offset outside of CS limits"));
76 exception(BX_GP_EXCEPTION, 0, 0);
78 EIP = return_EIP;
80 if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b)
81 ESP += imm16;
82 else
83 SP += imm16;
85 BX_CPU_THIS_PTR speculative_rsp = 0;
87 BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET, EIP);
90 void BX_CPP_AttrRegparmN(1) BX_CPU_C::RETnear32(bxInstruction_c *i)
92 BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
94 #if BX_DEBUGGER
95 BX_CPU_THIS_PTR show_flag |= Flag_ret;
96 #endif
98 BX_CPU_THIS_PTR speculative_rsp = 1;
99 BX_CPU_THIS_PTR prev_rsp = ESP;
101 Bit32u return_EIP = pop_32();
102 if (return_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
104 BX_ERROR(("RETnear32: offset outside of CS limits"));
105 exception(BX_GP_EXCEPTION, 0, 0);
107 EIP = return_EIP;
109 BX_CPU_THIS_PTR speculative_rsp = 0;
111 BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET, EIP);
114 void BX_CPP_AttrRegparmN(1) BX_CPU_C::RETfar32_Iw(bxInstruction_c *i)
116 invalidate_prefetch_q();
118 #if BX_DEBUGGER
119 BX_CPU_THIS_PTR show_flag |= Flag_ret;
120 #endif
122 Bit16u imm16 = i->Iw();
123 Bit16u cs_raw;
124 Bit32u eip;
126 BX_CPU_THIS_PTR speculative_rsp = 1;
127 BX_CPU_THIS_PTR prev_rsp = RSP;
129 if (protected_mode()) {
130 BX_CPU_THIS_PTR return_protected(i, imm16);
131 goto done;
134 eip = pop_32();
135 cs_raw = (Bit16u) pop_32(); /* 32bit pop, MSW discarded */
137 // CS.LIMIT can't change when in real/v8086 mode
138 if (eip > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) {
139 BX_ERROR(("RETfar32_Iw: instruction pointer not within code segment limits"));
140 exception(BX_GP_EXCEPTION, 0, 0);
143 load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
144 EIP = eip;
146 if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b)
147 ESP += imm16;
148 else
149 SP += imm16;
151 done:
152 BX_CPU_THIS_PTR speculative_rsp = 0;
154 BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET,
155 BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
158 void BX_CPP_AttrRegparmN(1) BX_CPU_C::RETfar32(bxInstruction_c *i)
160 Bit32u eip;
161 Bit16u cs_raw;
163 invalidate_prefetch_q();
165 #if BX_DEBUGGER
166 BX_CPU_THIS_PTR show_flag |= Flag_ret;
167 #endif
169 BX_CPU_THIS_PTR speculative_rsp = 1;
170 BX_CPU_THIS_PTR prev_rsp = RSP;
172 if (protected_mode()) {
173 BX_CPU_THIS_PTR return_protected(i, 0);
174 goto done;
177 eip = pop_32();
179 // CS.LIMIT can't change when in real/v8086 mode
180 if (eip > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) {
181 BX_ERROR(("RETfar32: instruction pointer not within code segment limits"));
182 exception(BX_GP_EXCEPTION, 0, 0);
185 cs_raw = (Bit16u) pop_32(); /* 32bit pop, MSW discarded */
187 load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
188 EIP = eip;
190 done:
191 BX_CPU_THIS_PTR speculative_rsp = 0;
193 BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET,
194 BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
197 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CALL_Jd(bxInstruction_c *i)
199 #if BX_DEBUGGER
200 BX_CPU_THIS_PTR show_flag |= Flag_call;
201 #endif
203 Bit32u new_EIP = EIP + i->Id();
205 BX_CPU_THIS_PTR speculative_rsp = 1;
206 BX_CPU_THIS_PTR prev_rsp = ESP;
208 /* push 32 bit EA of next instruction */
209 push_32(EIP);
211 branch_near32(new_EIP);
213 BX_CPU_THIS_PTR speculative_rsp = 0;
215 BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL, EIP);
218 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CALL32_Ap(bxInstruction_c *i)
220 BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
222 Bit16u cs_raw;
223 Bit32u disp32;
225 invalidate_prefetch_q();
227 #if BX_DEBUGGER
228 BX_CPU_THIS_PTR show_flag |= Flag_call;
229 #endif
231 disp32 = i->Id();
232 cs_raw = i->Iw2();
234 BX_CPU_THIS_PTR speculative_rsp = 1;
235 BX_CPU_THIS_PTR prev_rsp = ESP;
237 if (protected_mode()) {
238 BX_CPU_THIS_PTR call_protected(i, cs_raw, disp32);
239 goto done;
242 // CS.LIMIT can't change when in real/v8086 mode
243 if (disp32 > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) {
244 BX_ERROR(("CALL32_Ap: instruction pointer not within code segment limits"));
245 exception(BX_GP_EXCEPTION, 0, 0);
248 push_32(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value);
249 push_32(EIP);
251 load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
252 EIP = disp32;
254 done:
255 BX_CPU_THIS_PTR speculative_rsp = 0;
257 BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL,
258 BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
261 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CALL_EdR(bxInstruction_c *i)
263 #if BX_DEBUGGER
264 BX_CPU_THIS_PTR show_flag |= Flag_call;
265 #endif
267 Bit32u new_EIP = BX_READ_32BIT_REG(i->rm());
269 BX_CPU_THIS_PTR speculative_rsp = 1;
270 BX_CPU_THIS_PTR prev_rsp = ESP;
272 /* push 32 bit EA of next instruction */
273 push_32(EIP);
275 branch_near32(new_EIP);
277 BX_CPU_THIS_PTR speculative_rsp = 0;
279 BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL, EIP);
282 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CALL32_Ep(bxInstruction_c *i)
284 Bit16u cs_raw;
285 Bit32u op1_32;
287 invalidate_prefetch_q();
289 #if BX_DEBUGGER
290 BX_CPU_THIS_PTR show_flag |= Flag_call;
291 #endif
293 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
295 /* pointer, segment address pair */
296 op1_32 = read_virtual_dword(i->seg(), eaddr);
297 cs_raw = read_virtual_word (i->seg(), eaddr+4);
299 BX_CPU_THIS_PTR speculative_rsp = 1;
300 BX_CPU_THIS_PTR prev_rsp = RSP;
302 if (protected_mode()) {
303 BX_CPU_THIS_PTR call_protected(i, cs_raw, op1_32);
304 goto done;
307 // CS.LIMIT can't change when in real/v8086 mode
308 if (op1_32 > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) {
309 BX_ERROR(("CALL32_Ep: instruction pointer not within code segment limits"));
310 exception(BX_GP_EXCEPTION, 0, 0);
313 push_32(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value);
314 push_32(EIP);
316 load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
317 EIP = op1_32;
319 done:
320 BX_CPU_THIS_PTR speculative_rsp = 0;
322 BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL,
323 BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
326 void BX_CPP_AttrRegparmN(1) BX_CPU_C::JMP_Jd(bxInstruction_c *i)
328 Bit32u new_EIP = EIP + (Bit32s) i->Id();
329 branch_near32(new_EIP);
330 BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP, new_EIP);
333 void BX_CPP_AttrRegparmN(1) BX_CPU_C::JO_Jd(bxInstruction_c *i)
335 if (get_OF()) {
336 Bit32u new_EIP = EIP + (Bit32s) i->Id();
337 branch_near32(new_EIP);
338 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
340 #if BX_INSTRUMENTATION
341 else {
342 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
344 #endif
347 void BX_CPP_AttrRegparmN(1) BX_CPU_C::JNO_Jd(bxInstruction_c *i)
349 if (! get_OF()) {
350 Bit32u new_EIP = EIP + (Bit32s) i->Id();
351 branch_near32(new_EIP);
352 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
354 #if BX_INSTRUMENTATION
355 else {
356 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
358 #endif
361 void BX_CPP_AttrRegparmN(1) BX_CPU_C::JB_Jd(bxInstruction_c *i)
363 if (get_CF()) {
364 Bit32u new_EIP = EIP + (Bit32s) i->Id();
365 branch_near32(new_EIP);
366 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
368 #if BX_INSTRUMENTATION
369 else {
370 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
372 #endif
375 void BX_CPP_AttrRegparmN(1) BX_CPU_C::JNB_Jd(bxInstruction_c *i)
377 if (! get_CF()) {
378 Bit32u new_EIP = EIP + (Bit32s) i->Id();
379 branch_near32(new_EIP);
380 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
382 #if BX_INSTRUMENTATION
383 else {
384 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
386 #endif
389 void BX_CPP_AttrRegparmN(1) BX_CPU_C::JZ_Jd(bxInstruction_c *i)
391 if (get_ZF()) {
392 Bit32u new_EIP = EIP + (Bit32s) i->Id();
393 branch_near32(new_EIP);
394 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
396 #if BX_INSTRUMENTATION
397 else {
398 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
400 #endif
403 void BX_CPP_AttrRegparmN(1) BX_CPU_C::JNZ_Jd(bxInstruction_c *i)
405 if (! get_ZF()) {
406 Bit32u new_EIP = EIP + (Bit32s) i->Id();
407 branch_near32(new_EIP);
408 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
410 #if BX_INSTRUMENTATION
411 else {
412 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
414 #endif
417 void BX_CPP_AttrRegparmN(1) BX_CPU_C::JBE_Jd(bxInstruction_c *i)
419 if (get_CF() || get_ZF()) {
420 Bit32u new_EIP = EIP + (Bit32s) i->Id();
421 branch_near32(new_EIP);
422 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
424 #if BX_INSTRUMENTATION
425 else {
426 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
428 #endif
431 void BX_CPP_AttrRegparmN(1) BX_CPU_C::JNBE_Jd(bxInstruction_c *i)
433 if (! (get_CF() || get_ZF())) {
434 Bit32u new_EIP = EIP + (Bit32s) i->Id();
435 branch_near32(new_EIP);
436 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
438 #if BX_INSTRUMENTATION
439 else {
440 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
442 #endif
445 void BX_CPP_AttrRegparmN(1) BX_CPU_C::JS_Jd(bxInstruction_c *i)
447 if (get_SF()) {
448 Bit32u new_EIP = EIP + (Bit32s) i->Id();
449 branch_near32(new_EIP);
450 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
452 #if BX_INSTRUMENTATION
453 else {
454 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
456 #endif
459 void BX_CPP_AttrRegparmN(1) BX_CPU_C::JNS_Jd(bxInstruction_c *i)
461 if (! get_SF()) {
462 Bit32u new_EIP = EIP + (Bit32s) i->Id();
463 branch_near32(new_EIP);
464 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
466 #if BX_INSTRUMENTATION
467 else {
468 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
470 #endif
473 void BX_CPP_AttrRegparmN(1) BX_CPU_C::JP_Jd(bxInstruction_c *i)
475 if (get_PF()) {
476 Bit32u new_EIP = EIP + (Bit32s) i->Id();
477 branch_near32(new_EIP);
478 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
480 #if BX_INSTRUMENTATION
481 else {
482 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
484 #endif
487 void BX_CPP_AttrRegparmN(1) BX_CPU_C::JNP_Jd(bxInstruction_c *i)
489 if (! get_PF()) {
490 Bit32u new_EIP = EIP + (Bit32s) i->Id();
491 branch_near32(new_EIP);
492 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
494 #if BX_INSTRUMENTATION
495 else {
496 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
498 #endif
501 void BX_CPP_AttrRegparmN(1) BX_CPU_C::JL_Jd(bxInstruction_c *i)
503 if (getB_SF() != getB_OF()) {
504 Bit32u new_EIP = EIP + (Bit32s) i->Id();
505 branch_near32(new_EIP);
506 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
508 #if BX_INSTRUMENTATION
509 else {
510 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
512 #endif
515 void BX_CPP_AttrRegparmN(1) BX_CPU_C::JNL_Jd(bxInstruction_c *i)
517 if (getB_SF() == getB_OF()) {
518 Bit32u new_EIP = EIP + (Bit32s) i->Id();
519 branch_near32(new_EIP);
520 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
522 #if BX_INSTRUMENTATION
523 else {
524 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
526 #endif
529 void BX_CPP_AttrRegparmN(1) BX_CPU_C::JLE_Jd(bxInstruction_c *i)
531 if (get_ZF() || (getB_SF() != getB_OF())) {
532 Bit32u new_EIP = EIP + (Bit32s) i->Id();
533 branch_near32(new_EIP);
534 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
536 #if BX_INSTRUMENTATION
537 else {
538 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
540 #endif
543 void BX_CPP_AttrRegparmN(1) BX_CPU_C::JNLE_Jd(bxInstruction_c *i)
545 if (! get_ZF() && (getB_SF() == getB_OF())) {
546 Bit32u new_EIP = EIP + (Bit32s) i->Id();
547 branch_near32(new_EIP);
548 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
550 #if BX_INSTRUMENTATION
551 else {
552 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
554 #endif
557 void BX_CPP_AttrRegparmN(1) BX_CPU_C::JMP_Ap(bxInstruction_c *i)
559 BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
561 Bit32u disp32;
562 Bit16u cs_raw;
564 invalidate_prefetch_q();
566 if (i->os32L()) {
567 disp32 = i->Id();
569 else {
570 disp32 = i->Iw();
572 cs_raw = i->Iw2();
574 // jump_protected doesn't affect ESP so it is ESP safe
575 if (protected_mode()) {
576 BX_CPU_THIS_PTR jump_protected(i, cs_raw, disp32);
577 goto done;
580 // CS.LIMIT can't change when in real/v8086 mode
581 if (disp32 > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) {
582 BX_ERROR(("JMP_Ap: instruction pointer not within code segment limits"));
583 exception(BX_GP_EXCEPTION, 0, 0);
586 load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
587 EIP = disp32;
589 done:
590 BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP,
591 BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
594 void BX_CPP_AttrRegparmN(1) BX_CPU_C::JMP_EdR(bxInstruction_c *i)
596 Bit32u new_EIP = BX_READ_32BIT_REG(i->rm());
597 branch_near32(new_EIP);
598 BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP, new_EIP);
601 /* Far indirect jump */
602 void BX_CPP_AttrRegparmN(1) BX_CPU_C::JMP32_Ep(bxInstruction_c *i)
604 Bit16u cs_raw;
605 Bit32u op1_32;
607 invalidate_prefetch_q();
609 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
611 /* pointer, segment address pair */
612 op1_32 = read_virtual_dword(i->seg(), eaddr);
613 cs_raw = read_virtual_word (i->seg(), eaddr+4);
615 // jump_protected doesn't affect RSP so it is RSP safe
616 if (protected_mode()) {
617 BX_CPU_THIS_PTR jump_protected(i, cs_raw, op1_32);
618 goto done;
621 // CS.LIMIT can't change when in real/v8086 mode
622 if (op1_32 > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) {
623 BX_ERROR(("JMP32_Ep: instruction pointer not within code segment limits"));
624 exception(BX_GP_EXCEPTION, 0, 0);
627 load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
628 EIP = op1_32;
630 done:
631 BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP,
632 BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
635 void BX_CPP_AttrRegparmN(1) BX_CPU_C::IRET32(bxInstruction_c *i)
637 BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
639 Bit32u eip, eflags32;
640 Bit16u cs_raw;
642 invalidate_prefetch_q();
644 #if BX_DEBUGGER
645 BX_CPU_THIS_PTR show_flag |= Flag_iret;
646 #endif
648 BX_CPU_THIS_PTR nmi_disable = 0;
650 BX_CPU_THIS_PTR speculative_rsp = 1;
651 BX_CPU_THIS_PTR prev_rsp = ESP;
653 if (v8086_mode()) {
654 // IOPL check in stack_return_from_v86()
655 iret32_stack_return_from_v86(i);
656 goto done;
659 if (protected_mode()) {
660 iret_protected(i);
661 goto done;
664 eip = pop_32();
665 cs_raw = (Bit16u) pop_32(); // #SS has higher priority
666 eflags32 = pop_32();
668 // CS.LIMIT can't change when in real/v8086 mode
669 if (eip > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) {
670 BX_ERROR(("IRET32: instruction pointer not within code segment limits"));
671 exception(BX_GP_EXCEPTION, 0, 0);
674 load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
675 EIP = eip;
676 writeEFlags(eflags32, 0x00257fd5); // VIF, VIP, VM unchanged
678 done:
679 BX_CPU_THIS_PTR speculative_rsp = 0;
681 BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_IRET,
682 BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
685 void BX_CPP_AttrRegparmN(1) BX_CPU_C::JECXZ_Jb(bxInstruction_c *i)
687 // it is impossible to get this instruction in long mode
688 BX_ASSERT(i->as64L() == 0);
690 Bit32u temp_ECX;
692 if (i->as32L())
693 temp_ECX = ECX;
694 else
695 temp_ECX = CX;
697 if (temp_ECX == 0) {
698 Bit32u new_EIP = EIP + (Bit32s) i->Id();
699 branch_near32(new_EIP);
700 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
702 #if BX_INSTRUMENTATION
703 else {
704 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
706 #endif
710 // There is some weirdness in LOOP instructions definition. If an exception
711 // was generated during the instruction execution (for example #GP fault
712 // because EIP was beyond CS segment limits) CPU state should restore the
713 // state prior to instruction execution.
715 // The final point that we are not allowed to decrement ECX register before
716 // it is known that no exceptions can happen.
719 void BX_CPP_AttrRegparmN(1) BX_CPU_C::LOOPNE32_Jb(bxInstruction_c *i)
721 // it is impossible to get this instruction in long mode
722 BX_ASSERT(i->as64L() == 0);
724 if (i->as32L()) {
725 Bit32u count = ECX;
727 count--;
728 if (count != 0 && (get_ZF()==0)) {
729 Bit32u new_EIP = EIP + (Bit32s) i->Id();
730 branch_near32(new_EIP);
731 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
733 #if BX_INSTRUMENTATION
734 else {
735 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
737 #endif
739 ECX = count;
741 else {
742 Bit16u count = CX;
744 count--;
745 if (count != 0 && (get_ZF()==0)) {
746 Bit32u new_EIP = EIP + (Bit32s) i->Id();
747 branch_near32(new_EIP);
748 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
750 #if BX_INSTRUMENTATION
751 else {
752 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
754 #endif
756 CX = count;
760 void BX_CPP_AttrRegparmN(1) BX_CPU_C::LOOPE32_Jb(bxInstruction_c *i)
762 // it is impossible to get this instruction in long mode
763 BX_ASSERT(i->as64L() == 0);
765 if (i->as32L()) {
766 Bit32u count = ECX;
768 count--;
769 if (count != 0 && get_ZF()) {
770 Bit32u new_EIP = EIP + (Bit32s) i->Id();
771 branch_near32(new_EIP);
772 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
774 #if BX_INSTRUMENTATION
775 else {
776 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
778 #endif
780 ECX = count;
782 else {
783 Bit16u count = CX;
785 count--;
786 if (count != 0 && get_ZF()) {
787 Bit32u new_EIP = EIP + (Bit32s) i->Id();
788 branch_near32(new_EIP);
789 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
791 #if BX_INSTRUMENTATION
792 else {
793 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
795 #endif
797 CX = count;
801 void BX_CPP_AttrRegparmN(1) BX_CPU_C::LOOP32_Jb(bxInstruction_c *i)
803 // it is impossible to get this instruction in long mode
804 BX_ASSERT(i->as64L() == 0);
806 if (i->as32L()) {
807 Bit32u count = ECX;
809 count--;
810 if (count != 0) {
811 Bit32u new_EIP = EIP + (Bit32s) i->Id();
812 branch_near32(new_EIP);
813 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
815 #if BX_INSTRUMENTATION
816 else {
817 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
819 #endif
821 ECX = count;
823 else {
824 Bit16u count = CX;
826 count--;
827 if (count != 0) {
828 Bit32u new_EIP = EIP + (Bit32s) i->Id();
829 branch_near32(new_EIP);
830 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_EIP);
832 #if BX_INSTRUMENTATION
833 else {
834 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
836 #endif
838 CX = count;
842 #endif