- added instructions how to update the online documentation
[bochs-mirror.git] / cpu / ctrl_xfer16.cc
blobe69cc6ddc5ddbc2b007a63e278ca34954d17a114
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: ctrl_xfer16.cc,v 1.64 2008/12/01 19:06:14 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 BX_CPP_INLINE void BX_CPP_AttrRegparmN(1) BX_CPU_C::branch_near16(Bit16u new_IP)
41 BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
43 // check always, not only in protected mode
44 if (new_IP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
46 BX_ERROR(("branch_near16: offset outside of CS limits"));
47 exception(BX_GP_EXCEPTION, 0, 0);
50 EIP = new_IP;
52 #if BX_SUPPORT_TRACE_CACHE && !defined(BX_TRACE_CACHE_NO_SPECULATIVE_TRACING)
53 // assert magic async_event to stop trace execution
54 BX_CPU_THIS_PTR async_event |= BX_ASYNC_EVENT_STOP_TRACE;
55 #endif
58 void BX_CPP_AttrRegparmN(1) BX_CPU_C::RETnear16_Iw(bxInstruction_c *i)
60 BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
62 #if BX_DEBUGGER
63 BX_CPU_THIS_PTR show_flag |= Flag_ret;
64 #endif
66 BX_CPU_THIS_PTR speculative_rsp = 1;
67 BX_CPU_THIS_PTR prev_rsp = ESP;
69 Bit16u return_IP = pop_16();
71 if (return_IP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
73 BX_ERROR(("RETnear16_Iw: IP > limit"));
74 exception(BX_GP_EXCEPTION, 0, 0);
77 EIP = return_IP;
79 Bit16u imm16 = i->Iw();
81 if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) /* 32bit stack */
82 ESP += imm16;
83 else
84 SP += imm16;
86 BX_CPU_THIS_PTR speculative_rsp = 0;
88 BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET, EIP);
91 void BX_CPP_AttrRegparmN(1) BX_CPU_C::RETnear16(bxInstruction_c *i)
93 BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
95 #if BX_DEBUGGER
96 BX_CPU_THIS_PTR show_flag |= Flag_ret;
97 #endif
99 BX_CPU_THIS_PTR speculative_rsp = 1;
100 BX_CPU_THIS_PTR prev_rsp = ESP;
102 Bit16u return_IP = pop_16();
104 if (return_IP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled)
106 BX_ERROR(("RETnear16: IP > limit"));
107 exception(BX_GP_EXCEPTION, 0, 0);
110 EIP = return_IP;
112 BX_CPU_THIS_PTR speculative_rsp = 0;
114 BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET, EIP);
117 void BX_CPP_AttrRegparmN(1) BX_CPU_C::RETfar16_Iw(bxInstruction_c *i)
119 Bit16u ip, cs_raw;
121 invalidate_prefetch_q();
123 #if BX_DEBUGGER
124 BX_CPU_THIS_PTR show_flag |= Flag_ret;
125 #endif
127 Bit16s imm16 = (Bit16s) i->Iw();
129 BX_CPU_THIS_PTR speculative_rsp = 1;
130 BX_CPU_THIS_PTR prev_rsp = RSP;
132 if (protected_mode()) {
133 BX_CPU_THIS_PTR return_protected(i, imm16);
134 goto done;
137 ip = pop_16();
138 cs_raw = pop_16();
140 // CS.LIMIT can't change when in real/v8086 mode
141 if (ip > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) {
142 BX_ERROR(("RETfar16_Iw: instruction pointer not within code segment limits"));
143 exception(BX_GP_EXCEPTION, 0, 0);
146 load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
147 RIP = (Bit32u) ip;
149 if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b)
150 ESP += imm16;
151 else
152 SP += imm16;
154 done:
156 BX_CPU_THIS_PTR speculative_rsp = 0;
158 BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET,
159 BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
162 void BX_CPP_AttrRegparmN(1) BX_CPU_C::RETfar16(bxInstruction_c *i)
164 Bit16u ip, cs_raw;
166 invalidate_prefetch_q();
168 #if BX_DEBUGGER
169 BX_CPU_THIS_PTR show_flag |= Flag_ret;
170 #endif
172 BX_CPU_THIS_PTR speculative_rsp = 1;
173 BX_CPU_THIS_PTR prev_rsp = RSP;
175 if (protected_mode()) {
176 BX_CPU_THIS_PTR return_protected(i, 0);
177 goto done;
180 ip = pop_16();
181 cs_raw = pop_16();
183 // CS.LIMIT can't change when in real/v8086 mode
184 if (ip > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) {
185 BX_ERROR(("RETfar16: instruction pointer not within code segment limits"));
186 exception(BX_GP_EXCEPTION, 0, 0);
189 load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
190 EIP = (Bit32u) ip;
192 done:
194 BX_CPU_THIS_PTR speculative_rsp = 0;
196 BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET,
197 BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
200 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CALL_Jw(bxInstruction_c *i)
202 #if BX_DEBUGGER
203 BX_CPU_THIS_PTR show_flag |= Flag_call;
204 #endif
206 BX_CPU_THIS_PTR speculative_rsp = 1;
207 BX_CPU_THIS_PTR prev_rsp = RSP;
209 /* push 16 bit EA of next instruction */
210 push_16(IP);
212 Bit16u new_IP = IP + i->Iw();
213 branch_near16(new_IP);
215 BX_CPU_THIS_PTR speculative_rsp = 0;
217 BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL, EIP);
220 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CALL16_Ap(bxInstruction_c *i)
222 BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
224 invalidate_prefetch_q();
226 #if BX_DEBUGGER
227 BX_CPU_THIS_PTR show_flag |= Flag_call;
228 #endif
230 Bit16u disp16 = i->Iw();
231 Bit16u cs_raw = i->Iw2();
233 BX_CPU_THIS_PTR speculative_rsp = 1;
234 BX_CPU_THIS_PTR prev_rsp = ESP;
236 if (protected_mode()) {
237 BX_CPU_THIS_PTR call_protected(i, cs_raw, disp16);
238 goto done;
241 push_16(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value);
242 push_16(IP);
244 // CS.LIMIT can't change when in real/v8086 mode
245 if (disp16 > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) {
246 BX_ERROR(("CALL16_Ap: instruction pointer not within code segment limits"));
247 exception(BX_GP_EXCEPTION, 0, 0);
250 load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
251 EIP = (Bit32u) disp16;
253 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_EwR(bxInstruction_c *i)
263 Bit16u new_IP = BX_READ_16BIT_REG(i->rm());
265 #if BX_DEBUGGER
266 BX_CPU_THIS_PTR show_flag |= Flag_call;
267 #endif
269 BX_CPU_THIS_PTR speculative_rsp = 1;
270 BX_CPU_THIS_PTR prev_rsp = ESP;
272 /* push 16 bit EA of next instruction */
273 push_16(IP);
275 branch_near16(new_IP);
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::CALL16_Ep(bxInstruction_c *i)
284 Bit16u cs_raw;
285 Bit16u op1_16;
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 op1_16 = read_virtual_word(i->seg(), eaddr);
296 cs_raw = read_virtual_word(i->seg(), eaddr+2);
298 BX_CPU_THIS_PTR speculative_rsp = 1;
299 BX_CPU_THIS_PTR prev_rsp = RSP;
301 if (protected_mode()) {
302 BX_CPU_THIS_PTR call_protected(i, cs_raw, op1_16);
303 goto done;
306 push_16(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value);
307 push_16(IP);
309 // CS.LIMIT can't change when in real/v8086 mode
310 if (op1_16 > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) {
311 BX_ERROR(("CALL16_Ep: instruction pointer not within code segment limits"));
312 exception(BX_GP_EXCEPTION, 0, 0);
315 load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
316 EIP = op1_16;
318 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_Jw(bxInstruction_c *i)
328 Bit16u new_IP = IP + i->Iw();
329 branch_near16(new_IP);
330 BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP, new_IP);
333 void BX_CPP_AttrRegparmN(1) BX_CPU_C::JO_Jw(bxInstruction_c *i)
335 if (get_OF()) {
336 Bit16u new_IP = IP + i->Iw();
337 branch_near16(new_IP);
338 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
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_Jw(bxInstruction_c *i)
349 if (! get_OF()) {
350 Bit16u new_IP = IP + i->Iw();
351 branch_near16(new_IP);
352 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
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_Jw(bxInstruction_c *i)
363 if (get_CF()) {
364 Bit16u new_IP = IP + i->Iw();
365 branch_near16(new_IP);
366 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
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_Jw(bxInstruction_c *i)
377 if (! get_CF()) {
378 Bit16u new_IP = IP + i->Iw();
379 branch_near16(new_IP);
380 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
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_Jw(bxInstruction_c *i)
391 if (get_ZF()) {
392 Bit16u new_IP = IP + i->Iw();
393 branch_near16(new_IP);
394 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
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_Jw(bxInstruction_c *i)
405 if (! get_ZF()) {
406 Bit16u new_IP = IP + i->Iw();
407 branch_near16(new_IP);
408 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
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_Jw(bxInstruction_c *i)
419 if (get_CF() || get_ZF()) {
420 Bit16u new_IP = IP + i->Iw();
421 branch_near16(new_IP);
422 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
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_Jw(bxInstruction_c *i)
433 if (! (get_CF() || get_ZF())) {
434 Bit16u new_IP = IP + i->Iw();
435 branch_near16(new_IP);
436 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
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_Jw(bxInstruction_c *i)
447 if (get_SF()) {
448 Bit16u new_IP = IP + i->Iw();
449 branch_near16(new_IP);
450 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
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_Jw(bxInstruction_c *i)
461 if (! get_SF()) {
462 Bit16u new_IP = IP + i->Iw();
463 branch_near16(new_IP);
464 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
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_Jw(bxInstruction_c *i)
475 if (get_PF()) {
476 Bit16u new_IP = IP + i->Iw();
477 branch_near16(new_IP);
478 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
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_Jw(bxInstruction_c *i)
489 if (! get_PF()) {
490 Bit16u new_IP = IP + i->Iw();
491 branch_near16(new_IP);
492 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
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_Jw(bxInstruction_c *i)
503 if (getB_SF() != getB_OF()) {
504 Bit16u new_IP = IP + i->Iw();
505 branch_near16(new_IP);
506 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
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_Jw(bxInstruction_c *i)
517 if (getB_SF() == getB_OF()) {
518 Bit16u new_IP = IP + i->Iw();
519 branch_near16(new_IP);
520 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
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_Jw(bxInstruction_c *i)
531 if (get_ZF() || (getB_SF() != getB_OF())) {
532 Bit16u new_IP = IP + i->Iw();
533 branch_near16(new_IP);
534 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
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_Jw(bxInstruction_c *i)
545 if (! get_ZF() && (getB_SF() == getB_OF())) {
546 Bit16u new_IP = IP + i->Iw();
547 branch_near16(new_IP);
548 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
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_EwR(bxInstruction_c *i)
559 Bit16u new_IP = BX_READ_16BIT_REG(i->rm());
560 branch_near16(new_IP);
561 BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP, new_IP);
564 /* Far indirect jump */
565 void BX_CPP_AttrRegparmN(1) BX_CPU_C::JMP16_Ep(bxInstruction_c *i)
567 Bit16u cs_raw;
568 Bit16u op1_16;
570 invalidate_prefetch_q();
572 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
574 op1_16 = read_virtual_word(i->seg(), eaddr);
575 cs_raw = read_virtual_word(i->seg(), eaddr+2);
577 // jump_protected doesn't affect RSP so it is RSP safe
578 if (protected_mode()) {
579 BX_CPU_THIS_PTR jump_protected(i, cs_raw, op1_16);
580 goto done;
583 // CS.LIMIT can't change when in real/v8086 mode
584 if (op1_16 > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) {
585 BX_ERROR(("JMP16_Ep: instruction pointer not within code segment limits"));
586 exception(BX_GP_EXCEPTION, 0, 0);
589 load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
590 EIP = op1_16;
592 done:
594 BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP,
595 BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
598 void BX_CPP_AttrRegparmN(1) BX_CPU_C::IRET16(bxInstruction_c *i)
600 Bit16u ip, cs_raw, flags;
602 invalidate_prefetch_q();
604 #if BX_DEBUGGER
605 BX_CPU_THIS_PTR show_flag |= Flag_iret;
606 #endif
608 BX_CPU_THIS_PTR disable_NMI = 0;
610 BX_CPU_THIS_PTR speculative_rsp = 1;
611 BX_CPU_THIS_PTR prev_rsp = RSP;
613 if (v8086_mode()) {
614 // IOPL check in stack_return_from_v86()
615 iret16_stack_return_from_v86(i);
616 goto done;
619 if (protected_mode()) {
620 iret_protected(i);
621 goto done;
624 ip = pop_16();
625 cs_raw = pop_16(); // #SS has higher priority
626 flags = pop_16();
628 // CS.LIMIT can't change when in real/v8086 mode
629 if(ip > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) {
630 BX_ERROR(("IRET16: instruction pointer not within code segment limits"));
631 exception(BX_GP_EXCEPTION, 0, 0);
634 load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw);
635 RIP = (Bit32u) ip;
636 write_flags(flags, /* change IOPL? */ 1, /* change IF? */ 1);
638 done:
639 BX_CPU_THIS_PTR speculative_rsp = 0;
641 BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_IRET,
642 BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP);
645 void BX_CPP_AttrRegparmN(1) BX_CPU_C::JCXZ_Jb(bxInstruction_c *i)
647 // it is impossible to get this instruction in long mode
648 BX_ASSERT(i->as64L() == 0);
650 Bit32u temp_ECX;
652 if (i->as32L())
653 temp_ECX = ECX;
654 else
655 temp_ECX = CX;
657 if (temp_ECX == 0) {
658 Bit16u new_IP = IP + i->Iw();
659 branch_near16(new_IP);
660 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
662 #if BX_INSTRUMENTATION
663 else {
664 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
666 #endif
670 // There is some weirdness in LOOP instructions definition. If an exception
671 // was generated during the instruction execution (for example #GP fault
672 // because EIP was beyond CS segment limits) CPU state should restore the
673 // state prior to instruction execution.
675 // The final point that we are not allowed to decrement ECX register before
676 // it is known that no exceptions can happen.
679 void BX_CPP_AttrRegparmN(1) BX_CPU_C::LOOPNE16_Jb(bxInstruction_c *i)
681 // it is impossible to get this instruction in long mode
682 BX_ASSERT(i->as64L() == 0);
684 if (i->as32L()) {
685 Bit32u count = ECX;
687 count--;
688 if (count != 0 && (get_ZF()==0)) {
689 Bit16u new_IP = IP + i->Iw();
690 branch_near16(new_IP);
691 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
693 #if BX_INSTRUMENTATION
694 else {
695 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
697 #endif
699 ECX = count;
701 else {
702 Bit16u count = CX;
704 count--;
705 if (count != 0 && (get_ZF()==0)) {
706 Bit16u new_IP = IP + i->Iw();
707 branch_near16(new_IP);
708 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
710 #if BX_INSTRUMENTATION
711 else {
712 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
714 #endif
716 CX = count;
720 void BX_CPP_AttrRegparmN(1) BX_CPU_C::LOOPE16_Jb(bxInstruction_c *i)
722 // it is impossible to get this instruction in long mode
723 BX_ASSERT(i->as64L() == 0);
725 if (i->as32L()) {
726 Bit32u count = ECX;
728 count--;
729 if (count != 0 && get_ZF()) {
730 Bit16u new_IP = IP + i->Iw();
731 branch_near16(new_IP);
732 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
734 #if BX_INSTRUMENTATION
735 else {
736 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
738 #endif
740 ECX = count;
742 else {
743 Bit16u count = CX;
745 count--;
746 if (count != 0 && get_ZF()) {
747 Bit16u new_IP = IP + i->Iw();
748 branch_near16(new_IP);
749 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
751 #if BX_INSTRUMENTATION
752 else {
753 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
755 #endif
757 CX = count;
761 void BX_CPP_AttrRegparmN(1) BX_CPU_C::LOOP16_Jb(bxInstruction_c *i)
763 // it is impossible to get this instruction in long mode
764 BX_ASSERT(i->as64L() == 0);
766 if (i->as32L()) {
767 Bit32u count = ECX;
769 count--;
770 if (count != 0) {
771 Bit16u new_IP = IP + i->Iw();
772 branch_near16(new_IP);
773 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
775 #if BX_INSTRUMENTATION
776 else {
777 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
779 #endif
781 ECX = count;
783 else {
784 Bit16u count = CX;
786 count--;
787 if (count != 0) {
788 Bit16u new_IP = IP + i->Iw();
789 branch_near16(new_IP);
790 BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, new_IP);
792 #if BX_INSTRUMENTATION
793 else {
794 BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID);
796 #endif
798 CX = count;