- compare disk size with the size calculated from geometry to avoid image
[bochs-mirror.git] / cpu / protect_ctrl.cc
blobaed5beab43b98f3116f77de129d1cd5425322412
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: protect_ctrl.cc,v 1.58 2007/03/23 14:50:45 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
33 void BX_CPU_C::ARPL_EwGw(bxInstruction_c *i)
35 Bit16u op2_16, op1_16;
37 if (protected_mode()) {
38 /* op1_16 is a register or memory reference */
39 if (i->modC0()) {
40 op1_16 = BX_READ_16BIT_REG(i->rm());
42 else {
43 /* pointer, segment address pair */
44 read_RMW_virtual_word(i->seg(), RMAddr(i), &op1_16);
47 op2_16 = BX_READ_16BIT_REG(i->nnn());
49 if ((op1_16 & 0x03) < (op2_16 & 0x03)) {
50 op1_16 = (op1_16 & 0xfffc) | (op2_16 & 0x03);
51 /* now write back to destination */
52 if (i->modC0()) {
53 if (i->os32L()) {
54 // if 32bit opsize, then 0xff3f is or'd into
55 // upper 16bits of register
56 Bit32u op1_32 = BX_READ_32BIT_REG(i->rm());
57 op1_32 = (op1_32 & 0xffff0000) | op1_16;
58 op1_32 |= 0xff3f0000;
59 BX_WRITE_32BIT_REGZ(i->rm(), op1_32);
61 else {
62 BX_WRITE_16BIT_REG(i->rm(), op1_16);
65 else {
66 write_RMW_virtual_word(op1_16);
68 set_ZF(1);
70 else {
71 set_ZF(0);
74 else {
75 BX_DEBUG(("ARPL: not recognized in real or virtual-8086 mode"));
76 UndefinedOpcode(i);
80 void BX_CPU_C::LAR_GvEw(bxInstruction_c *i)
82 /* for 16 bit operand size mode */
83 Bit16u raw_selector;
84 bx_descriptor_t descriptor;
85 bx_selector_t selector;
86 Bit32u dword1, dword2;
88 if (real_mode() || v8086_mode()) {
89 BX_ERROR(("LAR: not recognized in real or virtual-8086 mode"));
90 UndefinedOpcode(i);
91 return;
94 if (i->modC0()) {
95 raw_selector = BX_READ_16BIT_REG(i->rm());
97 else {
98 /* pointer, segment address pair */
99 read_virtual_word(i->seg(), RMAddr(i), &raw_selector);
102 /* if selector null, clear ZF and done */
103 if ((raw_selector & 0xfffc) == 0) {
104 clear_ZF();
105 return;
108 parse_selector(raw_selector, &selector);
110 if (!fetch_raw_descriptor2(&selector, &dword1, &dword2)) {
111 /* not within descriptor table */
112 clear_ZF();
113 return;
116 parse_descriptor(dword1, dword2, &descriptor);
118 if (descriptor.valid==0) {
119 clear_ZF();
120 return;
123 /* if source selector is visible at CPL & RPL,
124 * within the descriptor table, and of type accepted by LAR instruction,
125 * then load register with segment limit and set ZF
128 if (descriptor.segment) { /* normal segment */
129 if (IS_CODE_SEGMENT(descriptor.type) && IS_CODE_SEGMENT_CONFORMING(descriptor.type)) {
130 /* ignore DPL for conforming segments */
132 else {
133 if ((descriptor.dpl<CPL) || (descriptor.dpl<selector.rpl)) {
134 clear_ZF();
135 return;
138 assert_ZF();
139 if (i->os32L()) {
140 /* masked by 00FxFF00, where x is undefined */
141 BX_WRITE_32BIT_REGZ(i->nnn(), dword2 & 0x00ffff00);
143 else {
144 BX_WRITE_16BIT_REG(i->nnn(), dword2 & 0xff00);
146 return;
148 else { /* system or gate segment */
149 switch (descriptor.type) {
150 case BX_SYS_SEGMENT_AVAIL_286_TSS:
151 case BX_SYS_SEGMENT_LDT:
152 case BX_SYS_SEGMENT_BUSY_286_TSS:
153 case BX_286_CALL_GATE:
154 case BX_TASK_GATE:
155 #if BX_CPU_LEVEL >= 3
156 case BX_SYS_SEGMENT_AVAIL_386_TSS:
157 case BX_SYS_SEGMENT_BUSY_386_TSS:
158 case BX_386_CALL_GATE:
159 #endif
160 break;
161 default: /* rest not accepted types to LAR */
162 BX_DEBUG(("lar(): not accepted type"));
163 clear_ZF();
164 return;
167 if ((descriptor.dpl<CPL) || (descriptor.dpl<selector.rpl)) {
168 clear_ZF();
169 return;
171 assert_ZF();
172 if (i->os32L()) {
173 /* masked by 00FxFF00, where x is undefined ? */
174 BX_WRITE_32BIT_REGZ(i->nnn(), dword2 & 0x00ffff00);
176 else {
177 BX_WRITE_16BIT_REG(i->nnn(), dword2 & 0xff00);
182 void BX_CPU_C::LSL_GvEw(bxInstruction_c *i)
184 /* for 16 bit operand size mode */
185 Bit16u raw_selector;
186 Bit32u limit32;
187 bx_selector_t selector;
188 Bit32u dword1, dword2;
189 Bit32u descriptor_dpl;
191 if (real_mode() || v8086_mode()) {
192 BX_ERROR(("LSL: not recognized in real or virtual-8086 mode"));
193 UndefinedOpcode(i);
196 if (i->modC0()) {
197 raw_selector = BX_READ_16BIT_REG(i->rm());
199 else {
200 /* pointer, segment address pair */
201 read_virtual_word(i->seg(), RMAddr(i), &raw_selector);
204 /* if selector null, clear ZF and done */
205 if ((raw_selector & 0xfffc) == 0) {
206 clear_ZF();
207 return;
210 parse_selector(raw_selector, &selector);
212 if (!fetch_raw_descriptor2(&selector, &dword1, &dword2)) {
213 /* not within descriptor table */
214 clear_ZF();
215 return;
218 descriptor_dpl = (dword2 >> 13) & 0x03;
220 if ((dword2 & 0x00001000) == 0) { // system segment
221 Bit32u type = (dword2 >> 8) & 0x0000000f;
222 switch (type) {
223 case BX_SYS_SEGMENT_AVAIL_286_TSS:
224 case BX_SYS_SEGMENT_BUSY_286_TSS:
225 case BX_SYS_SEGMENT_LDT:
226 case BX_SYS_SEGMENT_AVAIL_386_TSS:
227 case BX_SYS_SEGMENT_BUSY_386_TSS:
228 limit32 = (dword1 & 0x0000ffff) | (dword2 & 0x000f0000);
229 if (dword2 & 0x00800000)
230 limit32 = (limit32 << 12) | 0x00000fff;
231 if ((descriptor_dpl<CPL) || (descriptor_dpl<selector.rpl)) {
232 clear_ZF();
233 return;
235 goto lsl_ok;
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 // conforming code segment, no check done
247 goto lsl_ok;
250 if ((descriptor_dpl<CPL) || (descriptor_dpl<selector.rpl)) {
251 clear_ZF();
252 return;
254 goto lsl_ok;
257 lsl_ok:
258 /* all checks pass, limit32 is now byte granular, write to op1 */
259 assert_ZF();
261 if (i->os32L()) {
262 BX_WRITE_32BIT_REGZ(i->nnn(), limit32);
264 else {
265 // chop off upper 16 bits
266 BX_WRITE_16BIT_REG(i->nnn(), (Bit16u) limit32);
270 void BX_CPU_C::SLDT_Ew(bxInstruction_c *i)
272 if (real_mode() || v8086_mode()) {
273 BX_ERROR(("SLDT: not recognized in real or virtual-8086 mode"));
274 UndefinedOpcode(i);
277 Bit16u val16 = BX_CPU_THIS_PTR ldtr.selector.value;
278 if (i->modC0()) {
279 if (i->os32L()) {
280 BX_WRITE_32BIT_REGZ(i->rm(), val16);
282 else {
283 BX_WRITE_16BIT_REG(i->rm(), val16);
286 else {
287 write_virtual_word(i->seg(), RMAddr(i), &val16);
291 void BX_CPU_C::STR_Ew(bxInstruction_c *i)
293 if (real_mode() || v8086_mode()) {
294 BX_ERROR(("STR: not recognized in real or virtual-8086 mode"));
295 UndefinedOpcode(i);
298 Bit16u val16 = BX_CPU_THIS_PTR tr.selector.value;
299 if (i->modC0()) {
300 if (i->os32L()) {
301 BX_WRITE_32BIT_REGZ(i->rm(), val16);
303 else {
304 BX_WRITE_16BIT_REG(i->rm(), val16);
307 else {
308 write_virtual_word(i->seg(), RMAddr(i), &val16);
312 void 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;
320 if (real_mode() || v8086_mode()) {
321 BX_ERROR(("LLDT: not recognized in real or virtual-8086 mode"));
322 UndefinedOpcode(i);
325 /* #GP(0) if the current privilege level is not 0 */
326 if (CPL != 0) {
327 BX_ERROR(("LLDT: The current priveledge level is not 0"));
328 exception(BX_GP_EXCEPTION, 0, 0);
331 if (i->modC0()) {
332 raw_selector = BX_READ_16BIT_REG(i->rm());
334 else {
335 read_virtual_word(i->seg(), RMAddr(i), &raw_selector);
338 invalidate_prefetch_q();
340 /* if selector is NULL, invalidate and done */
341 if ((raw_selector & 0xfffc) == 0) {
342 BX_CPU_THIS_PTR ldtr.selector.value = raw_selector;
343 BX_CPU_THIS_PTR ldtr.cache.valid = 0;
344 return;
347 /* parse fields in selector */
348 parse_selector(raw_selector, &selector);
350 // #GP(selector) if the selector operand does not point into GDT
351 if (selector.ti != 0) {
352 BX_ERROR(("LLDT: selector.ti != 0"));
353 exception(BX_GP_EXCEPTION, raw_selector & 0xfffc, 0);
356 /* fetch 2 dwords of descriptor; call handles out of limits checks */
357 fetch_raw_descriptor(&selector, &dword1, &dword2, BX_GP_EXCEPTION);
358 parse_descriptor(dword1, dword2, &descriptor);
360 #if BX_SUPPORT_X86_64
361 if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) {
362 // set upper 32 bits of ldt base
363 Bit32u dword3;
364 access_linear(BX_CPU_THIS_PTR gdtr.base + selector.index*8 + 8, 4, 0, BX_READ, &dword3);
365 descriptor.u.system.base |= ((Bit64u)dword3 << 32);
366 BX_INFO(("64 bit LDT base = 0x%08x%08x",
367 GET32H(descriptor.u.system.base), GET32L(descriptor.u.system.base)));
369 #endif
371 /* if selector doesn't point to an LDT descriptor #GP(selector) */
372 if (descriptor.valid == 0 || descriptor.segment ||
373 descriptor.type != BX_SYS_SEGMENT_LDT)
375 BX_ERROR(("LLDT: doesn't point to an LDT descriptor!"));
376 exception(BX_GP_EXCEPTION, raw_selector & 0xfffc, 0);
379 /* #NP(selector) if LDT descriptor is not present */
380 if (! IS_PRESENT(descriptor)) {
381 BX_ERROR(("LLDT: LDT descriptor not present!"));
382 exception(BX_NP_EXCEPTION, raw_selector & 0xfffc, 0);
385 BX_CPU_THIS_PTR ldtr.selector = selector;
386 BX_CPU_THIS_PTR ldtr.cache = descriptor;
387 BX_CPU_THIS_PTR ldtr.cache.valid = 1;
390 void BX_CPU_C::LTR_Ew(bxInstruction_c *i)
392 bx_descriptor_t descriptor;
393 bx_selector_t selector;
394 Bit16u raw_selector;
395 Bit32u dword1, dword2;
397 if (real_mode() || v8086_mode()) {
398 BX_ERROR(("LTR: not recognized in real or virtual-8086 mode"));
399 UndefinedOpcode(i);
402 invalidate_prefetch_q();
404 /* #GP(0) if the current privilege level is not 0 */
405 if (CPL != 0) {
406 BX_ERROR(("LTR: The current priveledge level is not 0"));
407 exception(BX_GP_EXCEPTION, 0, 0);
410 if (i->modC0()) {
411 raw_selector = BX_READ_16BIT_REG(i->rm());
413 else {
414 read_virtual_word(i->seg(), RMAddr(i), &raw_selector);
417 /* if selector is NULL, invalidate and done */
418 if ((raw_selector & BX_SELECTOR_RPL_MASK) == 0) {
419 BX_ERROR(("LTR: loading with NULL selector!"));
420 exception(BX_GP_EXCEPTION, 0, 0);
423 /* parse fields in selector, then check for null selector */
424 parse_selector(raw_selector, &selector);
426 if (selector.ti) {
427 BX_ERROR(("LTR: selector.ti != 0"));
428 exception(BX_GP_EXCEPTION, raw_selector & 0xfffc, 0);
431 /* fetch 2 dwords of descriptor; call handles out of limits checks */
432 fetch_raw_descriptor(&selector, &dword1, &dword2, BX_GP_EXCEPTION);
433 parse_descriptor(dword1, dword2, &descriptor);
435 #if BX_SUPPORT_X86_64
436 if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) {
437 // set upper 32 bits of tss base
438 Bit32u dword3;
439 access_linear(BX_CPU_THIS_PTR gdtr.base + selector.index*8 + 8, 4, 0, BX_READ, &dword3);
440 descriptor.u.system.base |= ((Bit64u)dword3 << 32);
441 BX_DEBUG(("64 bit TSS base = 0x%08x%08x",
442 GET32H(descriptor.u.system.base), GET32L(descriptor.u.system.base)));
444 #endif
446 /* #GP(selector) if object is not a TSS or is already busy */
447 if (descriptor.valid==0 || descriptor.segment ||
448 (descriptor.type!=BX_SYS_SEGMENT_AVAIL_286_TSS &&
449 descriptor.type!=BX_SYS_SEGMENT_AVAIL_386_TSS))
451 BX_ERROR(("LTR: doesn't point to an available TSS descriptor!"));
452 exception(BX_GP_EXCEPTION, raw_selector & 0xfffc, 0);
455 /* #NP(selector) if TSS descriptor is not present */
456 if (! IS_PRESENT(descriptor)) {
457 BX_ERROR(("LTR: LDT descriptor not present!"));
458 exception(BX_NP_EXCEPTION, raw_selector & 0xfffc, 0);
461 BX_CPU_THIS_PTR tr.selector = selector;
462 BX_CPU_THIS_PTR tr.cache = descriptor;
463 BX_CPU_THIS_PTR tr.cache.valid = 1;
464 // tr.cache.type should not have busy bit, or it would not get
465 // through the conditions above.
466 BX_ASSERT((BX_CPU_THIS_PTR tr.cache.type & 2) == 0);
468 /* mark as busy */
469 dword2 |= 0x00000200; /* set busy bit */
470 access_linear(BX_CPU_THIS_PTR gdtr.base + selector.index*8 + 4, 4, 0,
471 BX_WRITE, &dword2);
474 void BX_CPU_C::VERR_Ew(bxInstruction_c *i)
476 /* for 16 bit operand size mode */
477 Bit16u raw_selector;
478 bx_descriptor_t descriptor;
479 bx_selector_t selector;
480 Bit32u dword1, dword2;
482 if (real_mode() || v8086_mode()) {
483 BX_ERROR(("VERR: not recognized in real or virtual-8086 mode"));
484 UndefinedOpcode(i);
487 if (i->modC0()) {
488 raw_selector = BX_READ_16BIT_REG(i->rm());
490 else {
491 /* pointer, segment address pair */
492 read_virtual_word(i->seg(), RMAddr(i), &raw_selector);
495 /* if selector null, clear ZF and done */
496 if ((raw_selector & 0xfffc) == 0) {
497 BX_DEBUG(("VERR: null selector"));
498 clear_ZF();
499 return;
502 /* if source selector is visible at CPL & RPL,
503 * within the descriptor table, and of type accepted by VERR instruction,
504 * then load register with segment limit and set ZF */
505 parse_selector(raw_selector, &selector);
507 if (!fetch_raw_descriptor2(&selector, &dword1, &dword2)) {
508 /* not within descriptor table */
509 BX_DEBUG(("VERR: not within descriptor table"));
510 clear_ZF();
511 return;
514 parse_descriptor(dword1, dword2, &descriptor);
516 if (descriptor.segment==0) { /* system or gate descriptor */
517 BX_DEBUG(("VERR: system descriptor"));
518 clear_ZF(); /* inaccessible */
519 return;
522 if (descriptor.valid==0) {
523 BX_DEBUG(("VERR: valid bit cleared"));
524 clear_ZF(); /* inaccessible */
525 return;
528 /* normal data/code segment */
529 if (IS_CODE_SEGMENT(descriptor.type)) { /* code segment */
530 /* ignore DPL for readable conforming segments */
531 if (IS_CODE_SEGMENT_CONFORMING(descriptor.type) &&
532 IS_CODE_SEGMENT_READABLE(descriptor.type))
534 BX_DEBUG(("VERR: conforming code, OK"));
535 assert_ZF(); /* accessible */
536 return;
538 if (!IS_CODE_SEGMENT_READABLE(descriptor.type)) {
539 BX_DEBUG(("VERR: code not readable"));
540 clear_ZF(); /* inaccessible */
541 return;
543 /* readable, non-conforming code segment */
544 if ((descriptor.dpl<CPL) || (descriptor.dpl<selector.rpl)) {
545 BX_DEBUG(("VERR: non-conforming code not withing priv level"));
546 clear_ZF(); /* inaccessible */
547 return;
550 assert_ZF(); /* accessible */
552 else { /* data segment */
553 if ((descriptor.dpl<CPL) || (descriptor.dpl<selector.rpl)) {
554 BX_DEBUG(("VERR: data seg not withing priv level"));
555 clear_ZF(); /* not accessible */
556 return;
558 assert_ZF(); /* accessible */
562 void BX_CPU_C::VERW_Ew(bxInstruction_c *i)
564 /* for 16 bit operand size mode */
565 Bit16u raw_selector;
566 bx_descriptor_t descriptor;
567 bx_selector_t selector;
568 Bit32u dword1, dword2;
570 if (real_mode() || v8086_mode()) {
571 BX_ERROR(("VERW: not recognized in real or virtual-8086 mode"));
572 UndefinedOpcode(i);
575 if (i->modC0()) {
576 raw_selector = BX_READ_16BIT_REG(i->rm());
578 else {
579 /* pointer, segment address pair */
580 read_virtual_word(i->seg(), RMAddr(i), &raw_selector);
583 /* if selector null, clear ZF and done */
584 if ((raw_selector & 0xfffc) == 0) {
585 BX_DEBUG(("VERW: null selector"));
586 clear_ZF();
587 return;
590 /* if source selector is visible at CPL & RPL,
591 * within the descriptor table, and of type accepted by VERW instruction,
592 * then load register with segment limit and set ZF */
593 parse_selector(raw_selector, &selector);
595 if (!fetch_raw_descriptor2(&selector, &dword1, &dword2)) {
596 /* not within descriptor table */
597 BX_DEBUG(("VERW: not within descriptor table"));
598 clear_ZF();
599 return;
602 parse_descriptor(dword1, dword2, &descriptor);
604 /* rule out system segments & code segments */
605 if (descriptor.segment==0 || IS_CODE_SEGMENT(descriptor.type)) {
606 BX_DEBUG(("VERW: system seg or code"));
607 clear_ZF();
608 return;
611 if (descriptor.valid==0) {
612 BX_DEBUG(("VERW: valid bit cleared"));
613 clear_ZF();
614 return;
617 /* data segment */
618 if (IS_DATA_SEGMENT_WRITEABLE(descriptor.type)) { /* writable */
619 if ((descriptor.dpl<CPL) || (descriptor.dpl<selector.rpl)) {
620 BX_DEBUG(("VERW: writable data seg not within priv level"));
621 clear_ZF(); /* not accessible */
622 return;
624 assert_ZF(); /* accessible */
625 return;
628 BX_DEBUG(("VERW: data seg not writable"));
629 clear_ZF(); /* not accessible */
632 void BX_CPU_C::SGDT_Ms(bxInstruction_c *i)
634 Bit16u limit_16 = BX_CPU_THIS_PTR gdtr.limit;
635 Bit32u base_32 = BX_CPU_THIS_PTR gdtr.base;
637 write_virtual_word(i->seg(), RMAddr(i), &limit_16);
638 write_virtual_dword(i->seg(), RMAddr(i)+2, &base_32);
641 void BX_CPU_C::SIDT_Ms(bxInstruction_c *i)
643 Bit16u limit_16 = BX_CPU_THIS_PTR idtr.limit;
644 Bit32u base_32 = BX_CPU_THIS_PTR idtr.base;
646 write_virtual_word(i->seg(), RMAddr(i), &limit_16);
647 write_virtual_dword(i->seg(), RMAddr(i)+2, &base_32);
650 void BX_CPU_C::LGDT_Ms(bxInstruction_c *i)
652 if (v8086_mode()) {
653 BX_ERROR(("LGDT: not recognized in virtual-8086 mode"));
654 exception(BX_GP_EXCEPTION, 0, 0);
657 if (!real_mode() && CPL!=0) {
658 BX_ERROR(("LGDT: CPL!=0 in protected mode"));
659 exception(BX_GP_EXCEPTION, 0, 0);
662 invalidate_prefetch_q();
664 #if BX_CPU_LEVEL >= 3
665 if (i->os32L()) {
666 Bit16u limit_16;
667 Bit32u base0_31;
669 read_virtual_word(i->seg(), RMAddr(i), &limit_16);
670 read_virtual_dword(i->seg(), RMAddr(i) + 2, &base0_31);
672 BX_CPU_THIS_PTR gdtr.limit = limit_16;
673 BX_CPU_THIS_PTR gdtr.base = base0_31;
675 else
676 #endif
678 Bit16u limit_16, base0_15;
679 Bit8u base16_23;
681 read_virtual_word(i->seg(), RMAddr(i), &limit_16);
682 read_virtual_word(i->seg(), RMAddr(i) + 2, &base0_15);
683 read_virtual_byte(i->seg(), RMAddr(i) + 4, &base16_23);
685 /* ignore high 8 bits */
686 BX_CPU_THIS_PTR gdtr.limit = limit_16;
687 BX_CPU_THIS_PTR gdtr.base = (base16_23 << 16) | base0_15;
691 void BX_CPU_C::LIDT_Ms(bxInstruction_c *i)
693 if (v8086_mode()) {
694 BX_ERROR(("LIDT: not recognized in virtual-8086 mode"));
695 exception(BX_GP_EXCEPTION, 0, 0);
698 if (!real_mode() && CPL!=0) {
699 BX_ERROR(("LIDT: CPL!=0 in protected mode"));
700 exception(BX_GP_EXCEPTION, 0, 0);
703 invalidate_prefetch_q();
705 Bit16u limit_16;
706 Bit32u base_32;
708 #if BX_CPU_LEVEL >= 3
709 if (i->os32L()) {
710 read_virtual_word(i->seg(), RMAddr(i), &limit_16);
711 read_virtual_dword(i->seg(), RMAddr(i) + 2, &base_32);
713 BX_CPU_THIS_PTR idtr.limit = limit_16;
714 BX_CPU_THIS_PTR idtr.base = base_32;
716 else
717 #endif
719 read_virtual_word(i->seg(), RMAddr(i), &limit_16);
720 read_virtual_dword(i->seg(), RMAddr(i) + 2, &base_32);
722 BX_CPU_THIS_PTR idtr.limit = limit_16;
723 BX_CPU_THIS_PTR idtr.base = base_32 & 0x00ffffff; /* ignore upper 8 bits */
727 #if BX_SUPPORT_X86_64
729 void BX_CPU_C::SGDT64_Ms(bxInstruction_c *i)
731 Bit16u limit_16 = BX_CPU_THIS_PTR gdtr.limit;
732 Bit64u base_64 = BX_CPU_THIS_PTR gdtr.base;
734 write_virtual_word (i->seg(), RMAddr(i), &limit_16);
735 write_virtual_qword(i->seg(), RMAddr(i)+2, &base_64);
738 void BX_CPU_C::SIDT64_Ms(bxInstruction_c *i)
740 Bit16u limit_16 = BX_CPU_THIS_PTR idtr.limit;
741 Bit64u base_64 = BX_CPU_THIS_PTR idtr.base;
743 write_virtual_word(i->seg(), RMAddr(i), &limit_16);
744 write_virtual_qword(i->seg(), RMAddr(i)+2, &base_64);
747 void BX_CPU_C::LGDT64_Ms(bxInstruction_c *i)
749 BX_ASSERT(protected_mode());
751 /* operand might be a register or memory reference */
752 if (i->modC0()) {
753 BX_ERROR(("LGDT64_Ms: must be memory reference"));
754 UndefinedOpcode(i);
757 if (CPL!=0) {
758 BX_ERROR(("LGDT64_Ms: CPL != 0 in long mode"));
759 exception(BX_GP_EXCEPTION, 0, 0);
762 invalidate_prefetch_q();
764 Bit16u limit_16;
765 Bit64u base_64;
767 read_virtual_word(i->seg(), RMAddr(i), &limit_16);
768 read_virtual_qword(i->seg(), RMAddr(i) + 2, &base_64);
770 BX_CPU_THIS_PTR gdtr.limit = limit_16;
771 BX_CPU_THIS_PTR gdtr.base = base_64;
774 void BX_CPU_C::LIDT64_Ms(bxInstruction_c *i)
776 BX_ASSERT(protected_mode());
778 if (CPL != 0) {
779 BX_ERROR(("LIDT64_Ms: CPL != 0 in long mode"));
780 exception(BX_GP_EXCEPTION, 0, 0);
783 invalidate_prefetch_q();
785 Bit16u limit_16;
786 Bit64u base_64;
788 read_virtual_word(i->seg(), RMAddr(i), &limit_16);
789 read_virtual_qword(i->seg(), RMAddr(i) + 2, &base_64);
791 BX_CPU_THIS_PTR idtr.limit = limit_16;
792 BX_CPU_THIS_PTR idtr.base = base_64;
795 #endif