- update sector count before calling write completion function (SF patch #2144692)
[bochs-mirror.git] / cpu / protect_ctrl.cc
blob1a4e66ba0d6a5a0dd2597f24adbfcc569a005989
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: protect_ctrl.cc,v 1.91 2008/08/08 09:22:48 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 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ARPL_EwGw(bxInstruction_c *i)
35 Bit16u op2_16, op1_16;
37 if (real_mode() || v8086_mode()) {
38 BX_DEBUG(("ARPL: not recognized in real or virtual-8086 mode"));
39 exception(BX_UD_EXCEPTION, 0, 0);
42 /* op1_16 is a register or memory reference */
43 if (i->modC0()) {
44 op1_16 = BX_READ_16BIT_REG(i->rm());
46 else {
47 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
48 /* pointer, segment address pair */
49 op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
52 op2_16 = BX_READ_16BIT_REG(i->nnn());
54 if ((op1_16 & 0x03) < (op2_16 & 0x03)) {
55 op1_16 = (op1_16 & 0xfffc) | (op2_16 & 0x03);
56 /* now write back to destination */
57 if (i->modC0()) {
58 BX_WRITE_16BIT_REG(i->rm(), op1_16);
60 else {
61 write_RMW_virtual_word(op1_16);
63 assert_ZF();
65 else {
66 clear_ZF();
70 void BX_CPP_AttrRegparmN(1) BX_CPU_C::LAR_GvEw(bxInstruction_c *i)
72 /* for 16 bit operand size mode */
73 Bit16u raw_selector;
74 bx_descriptor_t descriptor;
75 bx_selector_t selector;
76 Bit32u dword1, dword2;
78 if (real_mode() || v8086_mode()) {
79 BX_ERROR(("LAR: not recognized in real or virtual-8086 mode"));
80 exception(BX_UD_EXCEPTION, 0, 0);
83 if (i->modC0()) {
84 raw_selector = BX_READ_16BIT_REG(i->rm());
86 else {
87 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
88 /* pointer, segment address pair */
89 raw_selector = read_virtual_word(i->seg(), eaddr);
92 /* if selector null, clear ZF and done */
93 if ((raw_selector & 0xfffc) == 0) {
94 clear_ZF();
95 return;
98 parse_selector(raw_selector, &selector);
100 if (!fetch_raw_descriptor2(&selector, &dword1, &dword2)) {
101 BX_DEBUG(("LAR: failed to fetch descriptor"));
102 clear_ZF();
103 return;
106 parse_descriptor(dword1, dword2, &descriptor);
108 if (descriptor.valid==0) {
109 BX_DEBUG(("LAR: descriptor not valid"));
110 clear_ZF();
111 return;
114 /* if source selector is visible at CPL & RPL,
115 * within the descriptor table, and of type accepted by LAR instruction,
116 * then load register with segment limit and set ZF
119 if (descriptor.segment) { /* normal segment */
120 if (IS_CODE_SEGMENT(descriptor.type) && IS_CODE_SEGMENT_CONFORMING(descriptor.type)) {
121 /* ignore DPL for conforming segments */
123 else {
124 if ((descriptor.dpl<CPL) || (descriptor.dpl<selector.rpl)) {
125 clear_ZF();
126 return;
129 assert_ZF();
130 if (i->os32L()) {
131 /* masked by 00FxFF00, where x is undefined */
132 BX_WRITE_32BIT_REGZ(i->nnn(), dword2 & 0x00ffff00);
134 else {
135 BX_WRITE_16BIT_REG(i->nnn(), dword2 & 0xff00);
138 else { /* system or gate segment */
139 switch (descriptor.type) {
140 case BX_SYS_SEGMENT_AVAIL_286_TSS:
141 case BX_SYS_SEGMENT_BUSY_286_TSS:
142 case BX_286_CALL_GATE:
143 case BX_TASK_GATE:
144 if (long_mode()) {
145 BX_DEBUG(("LAR: descriptor type in not accepted in long mode"));
146 clear_ZF();
147 return;
149 /* fall through */
150 case BX_SYS_SEGMENT_LDT:
151 #if BX_CPU_LEVEL >= 3
152 case BX_SYS_SEGMENT_AVAIL_386_TSS:
153 case BX_SYS_SEGMENT_BUSY_386_TSS:
154 case BX_386_CALL_GATE:
155 #endif
156 break;
157 default: /* rest not accepted types to LAR */
158 BX_DEBUG(("LAR: not accepted descriptor type"));
159 clear_ZF();
160 return;
163 if ((descriptor.dpl<CPL) || (descriptor.dpl<selector.rpl)) {
164 clear_ZF();
165 return;
167 assert_ZF();
168 if (i->os32L()) {
169 /* masked by 00FxFF00, where x is undefined ? */
170 BX_WRITE_32BIT_REGZ(i->nnn(), dword2 & 0x00ffff00);
172 else {
173 BX_WRITE_16BIT_REG(i->nnn(), dword2 & 0xff00);
178 void BX_CPP_AttrRegparmN(1) BX_CPU_C::LSL_GvEw(bxInstruction_c *i)
180 /* for 16 bit operand size mode */
181 Bit16u raw_selector;
182 Bit32u limit32;
183 bx_selector_t selector;
184 Bit32u dword1, dword2;
186 if (real_mode() || v8086_mode()) {
187 BX_ERROR(("LSL: not recognized in real or virtual-8086 mode"));
188 exception(BX_UD_EXCEPTION, 0, 0);
191 if (i->modC0()) {
192 raw_selector = BX_READ_16BIT_REG(i->rm());
194 else {
195 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
196 /* pointer, segment address pair */
197 raw_selector = read_virtual_word(i->seg(), eaddr);
200 /* if selector null, clear ZF and done */
201 if ((raw_selector & 0xfffc) == 0) {
202 clear_ZF();
203 return;
206 parse_selector(raw_selector, &selector);
208 if (!fetch_raw_descriptor2(&selector, &dword1, &dword2)) {
209 clear_ZF();
210 return;
213 Bit32u descriptor_dpl = (dword2 >> 13) & 0x03;
215 if ((dword2 & 0x00001000) == 0) { // system segment
216 Bit32u type = (dword2 >> 8) & 0x0000000f;
217 switch (type) {
218 case BX_SYS_SEGMENT_AVAIL_286_TSS:
219 case BX_SYS_SEGMENT_BUSY_286_TSS:
220 if (long_mode()) {
221 clear_ZF();
222 return;
224 /* fall through */
225 case BX_SYS_SEGMENT_LDT:
226 case BX_SYS_SEGMENT_AVAIL_386_TSS:
227 case BX_SYS_SEGMENT_BUSY_386_TSS:
228 if ((descriptor_dpl<CPL) || (descriptor_dpl<selector.rpl)) {
229 clear_ZF();
230 return;
232 limit32 = (dword1 & 0x0000ffff) | (dword2 & 0x000f0000);
233 if (dword2 & 0x00800000)
234 limit32 = (limit32 << 12) | 0x00000fff;
235 break;
236 default:
237 clear_ZF();
238 return;
241 else { // data & code segment
242 limit32 = (dword1 & 0x0000ffff) | (dword2 & 0x000f0000);
243 if (dword2 & 0x00800000)
244 limit32 = (limit32 << 12) | 0x00000fff;
245 if ((dword2 & 0x00000c00) != 0x00000c00) {
246 // non-conforming code segment
247 if ((descriptor_dpl<CPL) || (descriptor_dpl<selector.rpl)) {
248 clear_ZF();
249 return;
254 /* all checks pass, limit32 is now byte granular, write to op1 */
255 assert_ZF();
257 if (i->os32L()) {
258 BX_WRITE_32BIT_REGZ(i->nnn(), limit32);
260 else {
261 // chop off upper 16 bits
262 BX_WRITE_16BIT_REG(i->nnn(), (Bit16u) limit32);
266 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SLDT_Ew(bxInstruction_c *i)
268 if (real_mode() || v8086_mode()) {
269 BX_ERROR(("SLDT: not recognized in real or virtual-8086 mode"));
270 exception(BX_UD_EXCEPTION, 0, 0);
273 Bit16u val16 = BX_CPU_THIS_PTR ldtr.selector.value;
274 if (i->modC0()) {
275 if (i->os32L()) {
276 BX_WRITE_32BIT_REGZ(i->rm(), val16);
278 else {
279 BX_WRITE_16BIT_REG(i->rm(), val16);
282 else {
283 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
284 /* pointer, segment address pair */
285 write_virtual_word(i->seg(), eaddr, val16);
289 void BX_CPP_AttrRegparmN(1) BX_CPU_C::STR_Ew(bxInstruction_c *i)
291 if (real_mode() || v8086_mode()) {
292 BX_ERROR(("STR: not recognized in real or virtual-8086 mode"));
293 exception(BX_UD_EXCEPTION, 0, 0);
296 Bit16u val16 = BX_CPU_THIS_PTR tr.selector.value;
297 if (i->modC0()) {
298 if (i->os32L()) {
299 BX_WRITE_32BIT_REGZ(i->rm(), val16);
301 else {
302 BX_WRITE_16BIT_REG(i->rm(), val16);
305 else {
306 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
307 /* pointer, segment address pair */
308 write_virtual_word(i->seg(), eaddr, val16);
312 void BX_CPP_AttrRegparmN(1) BX_CPU_C::LLDT_Ew(bxInstruction_c *i)
314 /* protected mode */
315 bx_descriptor_t descriptor;
316 bx_selector_t selector;
317 Bit16u raw_selector;
318 Bit32u dword1, dword2;
319 #if BX_SUPPORT_X86_64
320 Bit32u dword3 = 0;
321 #endif
323 if (real_mode() || v8086_mode()) {
324 BX_ERROR(("LLDT: not recognized in real or virtual-8086 mode"));
325 exception(BX_UD_EXCEPTION, 0, 0);
328 if (CPL != 0) {
329 BX_ERROR(("LLDT: The current priveledge level is not 0"));
330 exception(BX_GP_EXCEPTION, 0, 0);
333 if (i->modC0()) {
334 raw_selector = BX_READ_16BIT_REG(i->rm());
336 else {
337 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
338 /* pointer, segment address pair */
339 raw_selector = read_virtual_word(i->seg(), eaddr);
342 invalidate_prefetch_q();
344 /* if selector is NULL, invalidate and done */
345 if ((raw_selector & 0xfffc) == 0) {
346 BX_CPU_THIS_PTR ldtr.selector.value = raw_selector;
347 BX_CPU_THIS_PTR ldtr.cache.valid = 0;
348 return;
351 /* parse fields in selector */
352 parse_selector(raw_selector, &selector);
354 // #GP(selector) if the selector operand does not point into GDT
355 if (selector.ti != 0) {
356 BX_ERROR(("LLDT: selector.ti != 0"));
357 exception(BX_GP_EXCEPTION, raw_selector & 0xfffc, 0);
360 /* fetch descriptor; call handles out of limits checks */
361 #if BX_SUPPORT_X86_64
362 if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) {
363 fetch_raw_descriptor_64(&selector, &dword1, &dword2, &dword3, BX_GP_EXCEPTION);
365 else
366 #endif
368 fetch_raw_descriptor(&selector, &dword1, &dword2, BX_GP_EXCEPTION);
371 parse_descriptor(dword1, dword2, &descriptor);
373 /* if selector doesn't point to an LDT descriptor #GP(selector) */
374 if (descriptor.valid == 0 || descriptor.segment ||
375 descriptor.type != BX_SYS_SEGMENT_LDT)
377 BX_ERROR(("LLDT: doesn't point to an LDT descriptor!"));
378 exception(BX_GP_EXCEPTION, raw_selector & 0xfffc, 0);
381 /* #NP(selector) if LDT descriptor is not present */
382 if (! IS_PRESENT(descriptor)) {
383 BX_ERROR(("LLDT: LDT descriptor not present!"));
384 exception(BX_NP_EXCEPTION, raw_selector & 0xfffc, 0);
387 #if BX_SUPPORT_X86_64
388 descriptor.u.system.base |= ((Bit64u)(dword3) << 32);
389 BX_DEBUG(("64 bit LDT base = 0x%08x%08x",
390 GET32H(descriptor.u.system.base), GET32L(descriptor.u.system.base)));
391 if (!IsCanonical(descriptor.u.system.base)) {
392 BX_ERROR(("LLDT: non-canonical LDT descriptor base!"));
393 exception(BX_GP_EXCEPTION, raw_selector & 0xfffc, 0);
395 #endif
397 BX_CPU_THIS_PTR ldtr.selector = selector;
398 BX_CPU_THIS_PTR ldtr.cache = descriptor;
399 BX_CPU_THIS_PTR ldtr.cache.valid = 1;
402 void BX_CPP_AttrRegparmN(1) BX_CPU_C::LTR_Ew(bxInstruction_c *i)
404 bx_descriptor_t descriptor;
405 bx_selector_t selector;
406 Bit16u raw_selector;
407 Bit32u dword1, dword2;
408 #if BX_SUPPORT_X86_64
409 Bit32u dword3 = 0;
410 #endif
412 if (real_mode() || v8086_mode()) {
413 BX_ERROR(("LTR: not recognized in real or virtual-8086 mode"));
414 exception(BX_UD_EXCEPTION, 0, 0);
417 if (CPL != 0) {
418 BX_ERROR(("LTR: The current priveledge level is not 0"));
419 exception(BX_GP_EXCEPTION, 0, 0);
422 if (i->modC0()) {
423 raw_selector = BX_READ_16BIT_REG(i->rm());
425 else {
426 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
427 /* pointer, segment address pair */
428 raw_selector = read_virtual_word(i->seg(), eaddr);
431 invalidate_prefetch_q();
433 /* if selector is NULL, invalidate and done */
434 if ((raw_selector & BX_SELECTOR_RPL_MASK) == 0) {
435 BX_ERROR(("LTR: loading with NULL selector!"));
436 exception(BX_GP_EXCEPTION, 0, 0);
439 /* parse fields in selector, then check for null selector */
440 parse_selector(raw_selector, &selector);
442 if (selector.ti) {
443 BX_ERROR(("LTR: selector.ti != 0"));
444 exception(BX_GP_EXCEPTION, raw_selector & 0xfffc, 0);
447 /* fetch descriptor; call handles out of limits checks */
448 #if BX_SUPPORT_X86_64
449 if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) {
450 fetch_raw_descriptor_64(&selector, &dword1, &dword2, &dword3, BX_GP_EXCEPTION);
452 else
453 #endif
455 fetch_raw_descriptor(&selector, &dword1, &dword2, BX_GP_EXCEPTION);
458 parse_descriptor(dword1, dword2, &descriptor);
460 /* #GP(selector) if object is not a TSS or is already busy */
461 if (descriptor.valid==0 || descriptor.segment ||
462 (descriptor.type!=BX_SYS_SEGMENT_AVAIL_286_TSS &&
463 descriptor.type!=BX_SYS_SEGMENT_AVAIL_386_TSS))
465 BX_ERROR(("LTR: doesn't point to an available TSS descriptor!"));
466 exception(BX_GP_EXCEPTION, raw_selector & 0xfffc, 0);
469 #if BX_SUPPORT_X86_64
470 if (long_mode() && descriptor.type!=BX_SYS_SEGMENT_AVAIL_386_TSS) {
471 BX_ERROR(("LTR: doesn't point to an available TSS386 descriptor in long mode!"));
472 exception(BX_GP_EXCEPTION, raw_selector & 0xfffc, 0);
474 #endif
476 /* #NP(selector) if TSS descriptor is not present */
477 if (! IS_PRESENT(descriptor)) {
478 BX_ERROR(("LTR: TSS descriptor not present!"));
479 exception(BX_NP_EXCEPTION, raw_selector & 0xfffc, 0);
482 #if BX_SUPPORT_X86_64
483 descriptor.u.system.base |= ((Bit64u)(dword3) << 32);
484 BX_DEBUG(("64 bit TSS base = 0x%08x%08x",
485 GET32H(descriptor.u.system.base), GET32L(descriptor.u.system.base)));
486 if (!IsCanonical(descriptor.u.system.base)) {
487 BX_ERROR(("LTR: non-canonical TSS descriptor base!"));
488 exception(BX_GP_EXCEPTION, raw_selector & 0xfffc, 0);
490 #endif
492 BX_CPU_THIS_PTR tr.selector = selector;
493 BX_CPU_THIS_PTR tr.cache = descriptor;
494 BX_CPU_THIS_PTR tr.cache.valid = 1;
495 // tr.cache.type should not have busy bit, or it would not get
496 // through the conditions above.
497 BX_ASSERT((BX_CPU_THIS_PTR tr.cache.type & 2) == 0);
498 BX_CPU_THIS_PTR tr.cache.type |= 2; // mark as busy
500 /* mark as busy */
501 if (!(dword2 & 0x0200)) {
502 dword2 |= 0x0200; /* set busy bit */
503 access_write_linear(BX_CPU_THIS_PTR gdtr.base + selector.index*8 + 4, 4, 0, &dword2);
507 void BX_CPP_AttrRegparmN(1) BX_CPU_C::VERR_Ew(bxInstruction_c *i)
509 /* for 16 bit operand size mode */
510 Bit16u raw_selector;
511 bx_descriptor_t descriptor;
512 bx_selector_t selector;
513 Bit32u dword1, dword2;
515 if (real_mode() || v8086_mode()) {
516 BX_ERROR(("VERR: not recognized in real or virtual-8086 mode"));
517 exception(BX_UD_EXCEPTION, 0, 0);
520 if (i->modC0()) {
521 raw_selector = BX_READ_16BIT_REG(i->rm());
523 else {
524 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
525 /* pointer, segment address pair */
526 raw_selector = read_virtual_word(i->seg(), eaddr);
529 /* if selector null, clear ZF and done */
530 if ((raw_selector & 0xfffc) == 0) {
531 BX_DEBUG(("VERR: null selector"));
532 clear_ZF();
533 return;
536 /* if source selector is visible at CPL & RPL,
537 * within the descriptor table, and of type accepted by VERR instruction,
538 * then load register with segment limit and set ZF */
539 parse_selector(raw_selector, &selector);
541 if (!fetch_raw_descriptor2(&selector, &dword1, &dword2)) {
542 /* not within descriptor table */
543 BX_DEBUG(("VERR: not within descriptor table"));
544 clear_ZF();
545 return;
548 parse_descriptor(dword1, dword2, &descriptor);
550 if (descriptor.segment==0) { /* system or gate descriptor */
551 BX_DEBUG(("VERR: system descriptor"));
552 clear_ZF(); /* inaccessible */
553 return;
556 if (descriptor.valid==0) {
557 BX_DEBUG(("VERR: valid bit cleared"));
558 clear_ZF(); /* inaccessible */
559 return;
562 /* normal data/code segment */
563 if (IS_CODE_SEGMENT(descriptor.type)) { /* code segment */
564 /* ignore DPL for readable conforming segments */
565 if (IS_CODE_SEGMENT_CONFORMING(descriptor.type) &&
566 IS_CODE_SEGMENT_READABLE(descriptor.type))
568 BX_DEBUG(("VERR: conforming code, OK"));
569 assert_ZF(); /* accessible */
570 return;
572 if (!IS_CODE_SEGMENT_READABLE(descriptor.type)) {
573 BX_DEBUG(("VERR: code not readable"));
574 clear_ZF(); /* inaccessible */
575 return;
577 /* readable, non-conforming code segment */
578 if ((descriptor.dpl<CPL) || (descriptor.dpl<selector.rpl)) {
579 BX_DEBUG(("VERR: non-conforming code not withing priv level"));
580 clear_ZF(); /* inaccessible */
582 else {
583 assert_ZF(); /* accessible */
586 else { /* data segment */
587 if ((descriptor.dpl<CPL) || (descriptor.dpl<selector.rpl)) {
588 BX_DEBUG(("VERR: data seg not withing priv level"));
589 clear_ZF(); /* not accessible */
591 else {
592 assert_ZF(); /* accessible */
597 void BX_CPP_AttrRegparmN(1) BX_CPU_C::VERW_Ew(bxInstruction_c *i)
599 /* for 16 bit operand size mode */
600 Bit16u raw_selector;
601 bx_descriptor_t descriptor;
602 bx_selector_t selector;
603 Bit32u dword1, dword2;
605 if (real_mode() || v8086_mode()) {
606 BX_ERROR(("VERW: not recognized in real or virtual-8086 mode"));
607 exception(BX_UD_EXCEPTION, 0, 0);
610 if (i->modC0()) {
611 raw_selector = BX_READ_16BIT_REG(i->rm());
613 else {
614 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
615 /* pointer, segment address pair */
616 raw_selector = read_virtual_word(i->seg(), eaddr);
619 /* if selector null, clear ZF and done */
620 if ((raw_selector & 0xfffc) == 0) {
621 BX_DEBUG(("VERW: null selector"));
622 clear_ZF();
623 return;
626 /* if source selector is visible at CPL & RPL,
627 * within the descriptor table, and of type accepted by VERW instruction,
628 * then load register with segment limit and set ZF */
629 parse_selector(raw_selector, &selector);
631 if (!fetch_raw_descriptor2(&selector, &dword1, &dword2)) {
632 /* not within descriptor table */
633 BX_DEBUG(("VERW: not within descriptor table"));
634 clear_ZF();
635 return;
638 parse_descriptor(dword1, dword2, &descriptor);
640 /* rule out system segments & code segments */
641 if (descriptor.segment==0 || IS_CODE_SEGMENT(descriptor.type)) {
642 BX_DEBUG(("VERW: system seg or code"));
643 clear_ZF();
644 return;
647 if (descriptor.valid==0) {
648 BX_DEBUG(("VERW: valid bit cleared"));
649 clear_ZF();
650 return;
653 /* data segment */
654 if (IS_DATA_SEGMENT_WRITEABLE(descriptor.type)) { /* writable */
655 if ((descriptor.dpl<CPL) || (descriptor.dpl<selector.rpl)) {
656 BX_DEBUG(("VERW: writable data seg not within priv level"));
657 clear_ZF(); /* not accessible */
659 else {
660 assert_ZF(); /* accessible */
663 else {
664 BX_DEBUG(("VERW: data seg not writable"));
665 clear_ZF(); /* not accessible */
669 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SGDT_Ms(bxInstruction_c *i)
671 Bit16u limit_16 = BX_CPU_THIS_PTR gdtr.limit;
672 Bit32u base_32 = (Bit32u) BX_CPU_THIS_PTR gdtr.base;
674 Bit32u eaddr = (Bit32u) BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
676 write_virtual_word_32(i->seg(), eaddr, limit_16);
677 write_virtual_dword_32(i->seg(), eaddr+2, base_32);
680 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SIDT_Ms(bxInstruction_c *i)
682 Bit16u limit_16 = BX_CPU_THIS_PTR idtr.limit;
683 Bit32u base_32 = (Bit32u) BX_CPU_THIS_PTR idtr.base;
685 Bit32u eaddr = (Bit32u) BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
687 write_virtual_word_32(i->seg(), eaddr, limit_16);
688 write_virtual_dword_32(i->seg(), eaddr+2, base_32);
691 void BX_CPP_AttrRegparmN(1) BX_CPU_C::LGDT_Ms(bxInstruction_c *i)
693 if (v8086_mode()) {
694 BX_ERROR(("LGDT: not recognized in virtual-8086 mode"));
695 exception(BX_GP_EXCEPTION, 0, 0);
698 if (!real_mode() && CPL!=0) {
699 BX_ERROR(("LGDT: CPL!=0 in protected mode"));
700 exception(BX_GP_EXCEPTION, 0, 0);
703 invalidate_prefetch_q();
705 Bit32u eaddr = (Bit32u) BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
707 Bit16u limit_16 = read_virtual_word_32(i->seg(), eaddr);
708 Bit32u base_32 = read_virtual_dword_32(i->seg(), eaddr + 2);
710 if (i->os32L() == 0) base_32 &= 0x00ffffff; /* ignore upper 8 bits */
712 BX_CPU_THIS_PTR gdtr.limit = limit_16;
713 BX_CPU_THIS_PTR gdtr.base = base_32;
716 void BX_CPP_AttrRegparmN(1) BX_CPU_C::LIDT_Ms(bxInstruction_c *i)
718 if (v8086_mode()) {
719 BX_ERROR(("LIDT: not recognized in virtual-8086 mode"));
720 exception(BX_GP_EXCEPTION, 0, 0);
723 if (!real_mode() && CPL!=0) {
724 BX_ERROR(("LIDT: CPL!=0 in protected mode"));
725 exception(BX_GP_EXCEPTION, 0, 0);
728 invalidate_prefetch_q();
730 Bit32u eaddr = (Bit32u) BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
732 Bit32u base_32 = read_virtual_dword_32(i->seg(), eaddr + 2);
733 Bit16u limit_16 = read_virtual_word_32(i->seg(), eaddr);
735 if (i->os32L() == 0) base_32 &= 0x00ffffff; /* ignore upper 8 bits */
737 BX_CPU_THIS_PTR idtr.limit = limit_16;
738 BX_CPU_THIS_PTR idtr.base = base_32;
741 #if BX_SUPPORT_X86_64
743 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SGDT64_Ms(bxInstruction_c *i)
745 Bit16u limit_16 = BX_CPU_THIS_PTR gdtr.limit;
746 Bit64u base_64 = BX_CPU_THIS_PTR gdtr.base;
748 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
750 write_virtual_word_64(i->seg(), eaddr, limit_16);
751 write_virtual_qword_64(i->seg(), eaddr+2, base_64);
754 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SIDT64_Ms(bxInstruction_c *i)
756 Bit16u limit_16 = BX_CPU_THIS_PTR idtr.limit;
757 Bit64u base_64 = BX_CPU_THIS_PTR idtr.base;
759 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
761 write_virtual_word_64(i->seg(), eaddr, limit_16);
762 write_virtual_qword_64(i->seg(), eaddr+2, base_64);
765 void BX_CPP_AttrRegparmN(1) BX_CPU_C::LGDT64_Ms(bxInstruction_c *i)
767 if (CPL!=0) {
768 BX_ERROR(("LGDT64_Ms: CPL != 0 in long mode"));
769 exception(BX_GP_EXCEPTION, 0, 0);
772 invalidate_prefetch_q();
774 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
776 Bit64u base_64 = read_virtual_qword_64(i->seg(), eaddr + 2);
777 if (! IsCanonical(base_64)) {
778 BX_ERROR(("LGDT64_Ms: loaded base64 address is not in canonical form!"));
779 exception(BX_GP_EXCEPTION, 0, 0);
781 Bit16u limit_16 = read_virtual_word_64(i->seg(), eaddr);
783 BX_CPU_THIS_PTR gdtr.limit = limit_16;
784 BX_CPU_THIS_PTR gdtr.base = base_64;
787 void BX_CPP_AttrRegparmN(1) BX_CPU_C::LIDT64_Ms(bxInstruction_c *i)
789 if (CPL != 0) {
790 BX_ERROR(("LIDT64_Ms: CPL != 0 in long mode"));
791 exception(BX_GP_EXCEPTION, 0, 0);
794 invalidate_prefetch_q();
796 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
798 Bit64u base_64 = read_virtual_qword_64(i->seg(), eaddr + 2);
799 if (! IsCanonical(base_64)) {
800 BX_ERROR(("LIDT64_Ms: loaded base64 address is not in canonical form!"));
801 exception(BX_GP_EXCEPTION, 0, 0);
803 Bit16u limit_16 = read_virtual_word_64(i->seg(), eaddr);
805 BX_CPU_THIS_PTR idtr.limit = limit_16;
806 BX_CPU_THIS_PTR idtr.base = base_64;
809 #endif