OpenCores
URL https://opencores.org/ocsvn/ao486/ao486/trunk

Subversion Repositories ao486

[/] [ao486/] [trunk/] [bochs486/] [cpu/] [segment_ctrl_pro.cc] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 alfik
/////////////////////////////////////////////////////////////////////////
2
// $Id: segment_ctrl_pro.cc 11107 2012-03-25 19:07:17Z sshwarts $
3
/////////////////////////////////////////////////////////////////////////
4
//
5
//  Copyright (C) 2001-2012  The Bochs Project
6
//
7
//  This library is free software; you can redistribute it and/or
8
//  modify it under the terms of the GNU Lesser General Public
9
//  License as published by the Free Software Foundation; either
10
//  version 2 of the License, or (at your option) any later version.
11
//
12
//  This library is distributed in the hope that it will be useful,
13
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
//  Lesser General Public License for more details.
16
//
17
//  You should have received a copy of the GNU Lesser General Public
18
//  License along with this library; if not, write to the Free Software
19
//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
20
/////////////////////////////////////////////////////////////////////////
21
 
22
#define NEED_CPU_REG_SHORTCUTS 1
23
#include "bochs.h"
24
#include "cpu.h"
25
#define LOG_THIS BX_CPU_THIS_PTR
26
 
27
  void BX_CPP_AttrRegparmN(2)
28
BX_CPU_C::load_seg_reg(bx_segment_reg_t *seg, Bit16u new_value)
29
{
30
  if (protected_mode())
31
  {
32
    if (seg == &BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS])
33
    {
34
      bx_selector_t ss_selector;
35
      bx_descriptor_t descriptor;
36
      Bit32u dword1, dword2;
37
 
38
      parse_selector(new_value, &ss_selector);
39
 
40
      if ((new_value & 0xfffc) == 0) { /* null selector */
41
#if BX_SUPPORT_X86_64
42
        // allow SS = 0 in 64 bit mode only with cpl != 3 and rpl=cpl
43
        if (long64_mode() && CPL != 3 && ss_selector.rpl == CPL) {
44
          load_null_selector(seg, new_value);
45
          return;
46
        }
47
#endif
48
        BX_ERROR(("load_seg_reg(SS): loading null selector"));
49
        exception(BX_GP_EXCEPTION, new_value & 0xfffc);
50
      }
51
 
52
      fetch_raw_descriptor(&ss_selector, &dword1, &dword2, BX_GP_EXCEPTION);
53
 
54
      /* selector's RPL must = CPL, else #GP(selector) */
55
      if (ss_selector.rpl != CPL) {
56
        BX_ERROR(("load_seg_reg(SS): rpl != CPL"));
57
        exception(BX_GP_EXCEPTION, new_value & 0xfffc);
58
      }
59
 
60
      parse_descriptor(dword1, dword2, &descriptor);
61
 
62
      if (descriptor.valid==0) {
63
        BX_ERROR(("load_seg_reg(SS): valid bit cleared"));
64
        exception(BX_GP_EXCEPTION, new_value & 0xfffc);
65
      }
66
 
67
      /* AR byte must indicate a writable data segment else #GP(selector) */
68
      if (descriptor.segment==0 || IS_CODE_SEGMENT(descriptor.type) ||
69
          IS_DATA_SEGMENT_WRITEABLE(descriptor.type) == 0)
70
      {
71
        BX_ERROR(("load_seg_reg(SS): not writable data segment"));
72
        exception(BX_GP_EXCEPTION, new_value & 0xfffc);
73
      }
74
 
75
      /* DPL in the AR byte must equal CPL else #GP(selector) */
76
      if (descriptor.dpl != CPL) {
77
        BX_ERROR(("load_seg_reg(SS): dpl != CPL"));
78
        exception(BX_GP_EXCEPTION, new_value & 0xfffc);
79
      }
80
 
81
      /* segment must be marked PRESENT else #SS(selector) */
82
      if (! IS_PRESENT(descriptor)) {
83
        BX_ERROR(("load_seg_reg(SS): not present"));
84
        exception(BX_SS_EXCEPTION, new_value & 0xfffc);
85
      }
86
 
87
      touch_segment(&ss_selector, &descriptor);
88
 
89
      /* load SS with selector, load SS cache with descriptor */
90
      BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector    = ss_selector;
91
      BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache       = descriptor;
92
      BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.valid = 1;
93
 
94
      invalidate_stack_cache();
95
 
96
      return;
97
    }
98
    else if ((seg==&BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS]) ||
99
             (seg==&BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES]) ||
100
             (seg==&BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS]) ||
101
             (seg==&BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS])
102
            )
103
    {
104
      bx_descriptor_t descriptor;
105
      bx_selector_t selector;
106
      Bit32u dword1, dword2;
107
 
108
      if ((new_value & 0xfffc) == 0) { /* null selector */
109
        load_null_selector(seg, new_value);
110
        return;
111
      }
112
 
113
      parse_selector(new_value, &selector);
114
      fetch_raw_descriptor(&selector, &dword1, &dword2, BX_GP_EXCEPTION);
115
      parse_descriptor(dword1, dword2, &descriptor);
116
 
117
      if (descriptor.valid==0) {
118
        BX_ERROR(("load_seg_reg(%s, 0x%04x): invalid segment", strseg(seg), new_value));
119
        exception(BX_GP_EXCEPTION, new_value & 0xfffc);
120
      }
121
 
122
      /* AR byte must indicate data or readable code segment else #GP(selector) */
123
      if (descriptor.segment==0 || (IS_CODE_SEGMENT(descriptor.type) &&
124
          IS_CODE_SEGMENT_READABLE(descriptor.type) == 0))
125
      {
126
        BX_ERROR(("load_seg_reg(%s, 0x%04x): not data or readable code", strseg(seg), new_value));
127
        exception(BX_GP_EXCEPTION, new_value & 0xfffc);
128
      }
129
 
130
      /* If data or non-conforming code, then both the RPL and the CPL
131
       * must be less than or equal to DPL in AR byte else #GP(selector) */
132
      if (IS_DATA_SEGMENT(descriptor.type) ||
133
          IS_CODE_SEGMENT_NON_CONFORMING(descriptor.type))
134
      {
135
        if ((selector.rpl > descriptor.dpl) || (CPL > descriptor.dpl)) {
136
          BX_ERROR(("load_seg_reg(%s, 0x%04x): RPL & CPL must be <= DPL", strseg(seg), new_value));
137
          exception(BX_GP_EXCEPTION, new_value & 0xfffc);
138
        }
139
      }
140
 
141
      /* segment must be marked PRESENT else #NP(selector) */
142
      if (! IS_PRESENT(descriptor)) {
143
        BX_ERROR(("load_seg_reg(%s, 0x%04x): segment not present", strseg(seg), new_value));
144
        exception(BX_NP_EXCEPTION, new_value & 0xfffc);
145
      }
146
 
147
      touch_segment(&selector, &descriptor);
148
 
149
      /* load segment register with selector */
150
      /* load segment register-cache with descriptor */
151
      seg->selector    = selector;
152
      seg->cache       = descriptor;
153
      seg->cache.valid = 1;
154
 
155
      return;
156
    }
157
    else {
158
      BX_PANIC(("load_seg_reg(): invalid segment register passed!"));
159
      return;
160
    }
161
  }
162
 
163
  /* real or v8086 mode */
164
 
165
  /* www.x86.org:
166
    According  to  Intel, each time any segment register is loaded in real
167
    mode,  the  base  address is calculated as 16 times the segment value,
168
    while  the  access  rights  and size limit attributes are given fixed,
169
    "real-mode  compatible" values. This is not true. In fact, only the CS
170
    descriptor  caches  for  the  286,  386, and 486 get loaded with fixed
171
    values  each  time  the segment register is loaded. Loading CS, or any
172
    other segment register in real mode, on later Intel processors doesn't
173
    change  the  access rights or the segment size limit attributes stored
174
    in  the  descriptor  cache  registers.  For these segments, the access
175
    rights and segment size limit attributes from any previous setting are
176
    honored. */
177
 
178
  seg->selector.value = new_value;
179
  seg->selector.rpl = real_mode() ? 0 : 3;
180
  seg->cache.valid = 1;
181
  seg->cache.u.segment.base = new_value << 4;
182
  seg->cache.segment = 1; /* regular segment */
183
  seg->cache.p = 1; /* present */
184
 
185
  /* Do not modify segment limit and AR bytes when in real mode */
186
  /* Support for big real mode */
187
  if (!real_mode()) {
188
    seg->cache.type = BX_DATA_READ_WRITE_ACCESSED;
189
    seg->cache.dpl = 3; /* we are in v8086 mode */
190
    seg->cache.u.segment.limit_scaled = 0xffff;
191
    seg->cache.u.segment.g     = 0; /* byte granular */
192
    seg->cache.u.segment.d_b   = 0; /* default 16bit size */
193
#if BX_SUPPORT_X86_64
194
    seg->cache.u.segment.l     = 0; /* default 16bit size */
195
#endif
196
    seg->cache.u.segment.avl   = 0;
197
  }
198
 
199
  if (seg == &BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS]) {
200
    invalidate_prefetch_q();
201
    updateFetchModeMask(/* CS reloaded */);
202
#if BX_CPU_LEVEL >= 4
203
    handleAlignmentCheck(/* CPL change */);
204
#endif
205
  }
206
 
207
  if (seg == &BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS])
208
    invalidate_stack_cache();
209
}
210
 
211
  void BX_CPP_AttrRegparmN(2)
212
BX_CPU_C::load_null_selector(bx_segment_reg_t *seg, unsigned value)
213
{
214
  BX_ASSERT((value & 0xfffc) == 0);
215
 
216
  seg->selector.index = 0;
217
  seg->selector.ti    = 0;
218
  seg->selector.rpl   = BX_SELECTOR_RPL(value);
219
  seg->selector.value = value;
220
 
221
  seg->cache.valid    = 0; /* invalidate null selector */
222
  seg->cache.p        = 0;
223
  seg->cache.dpl      = 0;
224
  seg->cache.segment  = 1; /* data/code segment */
225
  seg->cache.type     = 0;
226
 
227
  seg->cache.u.segment.base         = 0;
228
  seg->cache.u.segment.limit_scaled = 0;
229
  seg->cache.u.segment.g            = 0;
230
  seg->cache.u.segment.d_b          = 0;
231
  seg->cache.u.segment.avl          = 0;
232
#if BX_SUPPORT_X86_64
233
  seg->cache.u.segment.l            = 0;
234
#endif
235
 
236
  invalidate_stack_cache();
237
}
238
 
239
BX_CPP_INLINE void BX_CPU_C::validate_seg_reg(unsigned seg)
240
{
241
  /*
242
     FOR (seg = ES, DS, FS, GS)
243
     DO
244
       IF ((seg.attr.dpl < CPL) && ((seg.attr.type = 'data')
245
                || (seg.attr.type = 'non-conforming-code')))
246
       {
247
          seg = NULL // can't use lower dpl data segment at higher cpl
248
       }
249
     END
250
  */
251
 
252
  bx_segment_reg_t *segment = &BX_CPU_THIS_PTR sregs[seg];
253
 
254
  if (segment->cache.dpl < CPL)
255
  {
256
    // invalidate if data or non-conforming code segment
257
    if (segment->cache.valid==0 || segment->cache.segment==0 ||
258
        IS_DATA_SEGMENT(segment->cache.type) ||
259
        IS_CODE_SEGMENT_NON_CONFORMING(segment->cache.type))
260
    {
261
      segment->selector.value = 0;
262
      segment->cache.valid = 0;
263
    }
264
  }
265
}
266
 
267
void BX_CPU_C::validate_seg_regs(void)
268
{
269
  validate_seg_reg(BX_SEG_REG_ES);
270
  validate_seg_reg(BX_SEG_REG_DS);
271
  validate_seg_reg(BX_SEG_REG_FS);
272
  validate_seg_reg(BX_SEG_REG_GS);
273
}
274
 
275
void parse_selector(Bit16u raw_selector, bx_selector_t *selector)
276
{
277
  selector->value = raw_selector;
278
  selector->index = raw_selector >> 3;
279
  selector->ti    = (raw_selector >> 2) & 0x01;
280
  selector->rpl   = raw_selector & 0x03;
281
}
282
 
283
Bit8u get_ar_byte(const bx_descriptor_t *d)
284
{
285
  return (d->type) |
286
         (d->segment << 4) |
287
         (d->dpl << 5) |
288
         (d->p << 7);
289
}
290
 
291
void set_ar_byte(bx_descriptor_t *d, Bit8u ar_byte)
292
{
293
  d->p        = (ar_byte >> 7) & 0x01;
294
  d->dpl      = (ar_byte >> 5) & 0x03;
295
  d->segment  = (ar_byte >> 4) & 0x01;
296
  d->type     = (ar_byte & 0x0f);
297
}
298
 
299
  Bit32u BX_CPP_AttrRegparmN(1)
300
BX_CPU_C::get_descriptor_l(const bx_descriptor_t *d)
301
{
302
  Bit32u limit = d->u.segment.limit_scaled;
303
  if (d->u.segment.g)
304
    limit >>= 12;
305
 
306
  Bit32u val = ((d->u.segment.base & 0xffff) << 16) | (limit & 0xffff);
307
 
308
  if (d->segment || !d->valid) {
309
    return(val);
310
  }
311
  else {
312
    switch (d->type) {
313
      case BX_SYS_SEGMENT_LDT:
314
      case BX_SYS_SEGMENT_AVAIL_286_TSS:
315
      case BX_SYS_SEGMENT_BUSY_286_TSS:
316
      case BX_SYS_SEGMENT_AVAIL_386_TSS:
317
      case BX_SYS_SEGMENT_BUSY_386_TSS:
318
        return(val);
319
 
320
      default:
321
        BX_ERROR(("#get_descriptor_l(): type %d not finished", d->type));
322
        return(0);
323
    }
324
  }
325
}
326
 
327
  Bit32u BX_CPP_AttrRegparmN(1)
328
BX_CPU_C::get_descriptor_h(const bx_descriptor_t *d)
329
{
330
  Bit32u val;
331
 
332
  Bit32u limit = d->u.segment.limit_scaled;
333
  if (d->u.segment.g)
334
    limit >>= 12;
335
 
336
  if (d->segment || !d->valid) {
337
    val = (d->u.segment.base & 0xff000000) |
338
          ((d->u.segment.base >> 16) & 0x000000ff) |
339
          (d->type << 8) |
340
          (d->segment << 12) |
341
          (d->dpl << 13) |
342
          (d->p << 15) | (limit & 0xf0000) |
343
          (d->u.segment.avl << 20) |
344
#if BX_SUPPORT_X86_64
345
          (d->u.segment.l << 21) |
346
#endif
347
          (d->u.segment.d_b << 22) |
348
          (d->u.segment.g << 23);
349
    return(val);
350
  }
351
  else {
352
    switch (d->type) {
353
      case BX_SYS_SEGMENT_AVAIL_286_TSS:
354
      case BX_SYS_SEGMENT_BUSY_286_TSS:
355
      case BX_SYS_SEGMENT_LDT:
356
      case BX_SYS_SEGMENT_AVAIL_386_TSS:
357
      case BX_SYS_SEGMENT_BUSY_386_TSS:
358
        val = ((d->u.segment.base >> 16) & 0xff) |
359
              (d->type << 8) |
360
              (d->dpl << 13) |
361
              (d->p << 15) | (limit & 0xf0000) |
362
              (d->u.segment.avl << 20) |
363
              (d->u.segment.d_b << 22) |
364
              (d->u.segment.g << 23) |
365
              (d->u.segment.base & 0xff000000);
366
        return(val);
367
 
368
      default:
369
        BX_ERROR(("#get_descriptor_h(): type %d not finished", d->type));
370
        return(0);
371
    }
372
  }
373
}
374
 
375
bx_bool BX_CPU_C::set_segment_ar_data(bx_segment_reg_t *seg, bx_bool valid,
376
            Bit16u raw_selector, bx_address base, Bit32u limit_scaled, Bit16u ar_data)
377
{
378
  parse_selector(raw_selector, &seg->selector);
379
 
380
  bx_descriptor_t *d = &seg->cache;
381
 
382
  d->p        = (ar_data >> 7) & 0x1;
383
  d->dpl      = (ar_data >> 5) & 0x3;
384
  d->segment  = (ar_data >> 4) & 0x1;
385
  d->type     = (ar_data & 0x0f);
386
 
387
  d->valid    = valid;
388
 
389
  if (d->segment || !valid) { /* data/code segment descriptors */
390
    d->u.segment.g     = (ar_data >> 15) & 0x1;
391
    d->u.segment.d_b   = (ar_data >> 14) & 0x1;
392
#if BX_SUPPORT_X86_64
393
    d->u.segment.l     = (ar_data >> 13) & 0x1;
394
#endif
395
    d->u.segment.avl   = (ar_data >> 12) & 0x1;
396
 
397
    d->u.segment.base  = base;
398
    d->u.segment.limit_scaled = limit_scaled;
399
  }
400
  else {
401
    switch(d->type) {
402
      case BX_SYS_SEGMENT_LDT:
403
      case BX_SYS_SEGMENT_AVAIL_286_TSS:
404
      case BX_SYS_SEGMENT_BUSY_286_TSS:
405
      case BX_SYS_SEGMENT_AVAIL_386_TSS:
406
      case BX_SYS_SEGMENT_BUSY_386_TSS:
407
        d->u.segment.avl   = (ar_data >> 12) & 0x1;
408
        d->u.segment.d_b   = (ar_data >> 14) & 0x1;
409
        d->u.segment.g     = (ar_data >> 15) & 0x1;
410
        d->u.segment.base  = base;
411
        d->u.segment.limit_scaled = limit_scaled;
412
        break;
413
 
414
      default:
415
        BX_ERROR(("set_segment_ar_data(): case %u unsupported, valid=%d", (unsigned) d->type, d->valid));
416
    }
417
  }
418
 
419
  return d->valid;
420
}
421
 
422
void parse_descriptor(Bit32u dword1, Bit32u dword2, bx_descriptor_t *temp)
423
{
424
  Bit8u AR_byte;
425
  Bit32u limit;
426
 
427
  AR_byte        = dword2 >> 8;
428
  temp->p        = (AR_byte >> 7) & 0x1;
429
  temp->dpl      = (AR_byte >> 5) & 0x3;
430
  temp->segment  = (AR_byte >> 4) & 0x1;
431
  temp->type     = (AR_byte & 0xf);
432
  temp->valid    = 0; /* start out invalid */
433
 
434
  if (temp->segment) { /* data/code segment descriptors */
435
    limit = (dword1 & 0xffff) | (dword2 & 0x000F0000);
436
 
437
    temp->u.segment.base       = (dword1 >> 16) | ((dword2 & 0xFF) << 16);
438
    temp->u.segment.g          = (dword2 & 0x00800000) > 0;
439
    temp->u.segment.d_b        = (dword2 & 0x00400000) > 0;
440
#if BX_SUPPORT_X86_64
441
    temp->u.segment.l          = (dword2 & 0x00200000) > 0;
442
#endif
443
    temp->u.segment.avl        = (dword2 & 0x00100000) > 0;
444
    temp->u.segment.base      |= (dword2 & 0xFF000000);
445
 
446
    if (temp->u.segment.g)
447
      temp->u.segment.limit_scaled = (limit << 12) | 0xfff;
448
    else
449
      temp->u.segment.limit_scaled =  limit;
450
 
451
    temp->valid    = 1;
452
  }
453
  else { // system & gate segment descriptors
454
    switch (temp->type) {
455
      case BX_286_CALL_GATE:
456
      case BX_286_INTERRUPT_GATE:
457
      case BX_286_TRAP_GATE:
458
        // param count only used for call gate
459
        temp->u.gate.param_count   = dword2 & 0x1f;
460
        temp->u.gate.dest_selector = dword1 >> 16;
461
        temp->u.gate.dest_offset   = dword1 & 0xffff;
462
        temp->valid = 1;
463
        break;
464
 
465
      case BX_386_CALL_GATE:
466
      case BX_386_INTERRUPT_GATE:
467
      case BX_386_TRAP_GATE:
468
        // param count only used for call gate
469
        temp->u.gate.param_count   = dword2 & 0x1f;
470
        temp->u.gate.dest_selector = dword1 >> 16;
471
        temp->u.gate.dest_offset   = (dword2 & 0xffff0000) |
472
                                     (dword1 & 0x0000ffff);
473
        temp->valid = 1;
474
        break;
475
 
476
      case BX_TASK_GATE:
477
        temp->u.taskgate.tss_selector = dword1 >> 16;
478
        temp->valid = 1;
479
        break;
480
 
481
      case BX_SYS_SEGMENT_LDT:
482
      case BX_SYS_SEGMENT_AVAIL_286_TSS:
483
      case BX_SYS_SEGMENT_BUSY_286_TSS:
484
      case BX_SYS_SEGMENT_AVAIL_386_TSS:
485
      case BX_SYS_SEGMENT_BUSY_386_TSS:
486
        limit = (dword1 & 0xffff) | (dword2 & 0x000F0000);
487
        temp->u.segment.base  = (dword1 >> 16) |
488
                               ((dword2 & 0xff) << 16) | (dword2 & 0xff000000);
489
        temp->u.segment.g     = (dword2 & 0x00800000) > 0;
490
        temp->u.segment.d_b   = (dword2 & 0x00400000) > 0;
491
        temp->u.segment.avl   = (dword2 & 0x00100000) > 0;
492
        if (temp->u.segment.g)
493
          temp->u.segment.limit_scaled = (limit << 12) | 0xfff;
494
        else
495
          temp->u.segment.limit_scaled =  limit;
496
        temp->valid = 1;
497
        break;
498
 
499
      default: // reserved
500
        temp->valid    = 0;
501
        break;
502
    }
503
  }
504
}
505
 
506
  void BX_CPP_AttrRegparmN(2)
507
BX_CPU_C::touch_segment(bx_selector_t *selector, bx_descriptor_t *descriptor)
508
{
509
  if (! IS_SEGMENT_ACCESSED(descriptor->type)) {
510
    Bit8u AR_byte = get_ar_byte(descriptor);
511
    AR_byte |= 1;
512
    descriptor->type |= 1;
513
 
514
    if (selector->ti == 0) { /* GDT */
515
       access_write_linear(BX_CPU_THIS_PTR gdtr.base + selector->index*8 + 5, 1, 0, &AR_byte);
516
    }
517
    else { /* LDT */
518
       access_write_linear(BX_CPU_THIS_PTR ldtr.cache.u.segment.base + selector->index*8 + 5, 1, 0, &AR_byte);
519
    }
520
  }
521
}
522
 
523
  void BX_CPP_AttrRegparmN(3)
524
BX_CPU_C::load_ss(bx_selector_t *selector, bx_descriptor_t *descriptor, Bit8u cpl)
525
{
526
  // Add cpl to the selector value.
527
  selector->value = (BX_SELECTOR_RPL_MASK & selector->value) | cpl;
528
 
529
  if ((selector->value & BX_SELECTOR_RPL_MASK) != 0)
530
    touch_segment(selector, descriptor);
531
 
532
  BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector = *selector;
533
  BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache = *descriptor;
534
  BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.rpl = cpl;
535
  BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.valid = 1;
536
 
537
  invalidate_stack_cache();
538
}
539
 
540
void BX_CPU_C::fetch_raw_descriptor(const bx_selector_t *selector,
541
                        Bit32u *dword1, Bit32u *dword2, unsigned exception_no)
542
{
543
  Bit32u index = selector->index;
544
  bx_address offset;
545
  Bit64u raw_descriptor;
546
 
547
  if (selector->ti == 0) { /* GDT */
548
    if ((index*8 + 7) > BX_CPU_THIS_PTR gdtr.limit) {
549
      BX_ERROR(("fetch_raw_descriptor: GDT: index (%x) %x > limit (%x)",
550
         index*8 + 7, index, BX_CPU_THIS_PTR gdtr.limit));
551
      exception(exception_no, selector->value & 0xfffc);
552
    }
553
    offset = BX_CPU_THIS_PTR gdtr.base + index*8;
554
  }
555
  else { /* LDT */
556
    if (BX_CPU_THIS_PTR ldtr.cache.valid==0) {
557
      BX_ERROR(("fetch_raw_descriptor: LDTR.valid=0"));
558
      exception(exception_no, selector->value & 0xfffc);
559
    }
560
    if ((index*8 + 7) > BX_CPU_THIS_PTR ldtr.cache.u.segment.limit_scaled) {
561
      BX_ERROR(("fetch_raw_descriptor: LDT: index (%x) %x > limit (%x)",
562
         index*8 + 7, index, BX_CPU_THIS_PTR ldtr.cache.u.segment.limit_scaled));
563
      exception(exception_no, selector->value & 0xfffc);
564
    }
565
    offset = BX_CPU_THIS_PTR ldtr.cache.u.segment.base + index*8;
566
  }
567
 
568
  raw_descriptor = system_read_qword(offset);
569
 
570
  *dword1 = GET32L(raw_descriptor);
571
  *dword2 = GET32H(raw_descriptor);
572
}
573
 
574
  bx_bool BX_CPP_AttrRegparmN(3)
575
BX_CPU_C::fetch_raw_descriptor2(const bx_selector_t *selector, Bit32u *dword1, Bit32u *dword2)
576
{
577
  Bit32u index = selector->index;
578
  bx_address offset;
579
  Bit64u raw_descriptor;
580
 
581
  if (selector->ti == 0) { /* GDT */
582
    if ((index*8 + 7) > BX_CPU_THIS_PTR gdtr.limit)
583
      return 0;
584
    offset = BX_CPU_THIS_PTR gdtr.base + index*8;
585
  }
586
  else { /* LDT */
587
    if (BX_CPU_THIS_PTR ldtr.cache.valid==0) {
588
      BX_ERROR(("fetch_raw_descriptor2: LDTR.valid=0"));
589
      return 0;
590
    }
591
    if ((index*8 + 7) > BX_CPU_THIS_PTR ldtr.cache.u.segment.limit_scaled)
592
      return 0;
593
    offset = BX_CPU_THIS_PTR ldtr.cache.u.segment.base + index*8;
594
  }
595
 
596
  raw_descriptor = system_read_qword(offset);
597
 
598
  *dword1 = GET32L(raw_descriptor);
599
  *dword2 = GET32H(raw_descriptor);
600
 
601
  return 1;
602
}
603
 
604
#if BX_SUPPORT_X86_64
605
void BX_CPU_C::fetch_raw_descriptor_64(const bx_selector_t *selector,
606
           Bit32u *dword1, Bit32u *dword2, Bit32u *dword3, unsigned exception_no)
607
{
608
  Bit32u index = selector->index;
609
  bx_address offset;
610
  Bit64u raw_descriptor1, raw_descriptor2;
611
 
612
  if (selector->ti == 0) { /* GDT */
613
    if ((index*8 + 15) > BX_CPU_THIS_PTR gdtr.limit) {
614
      BX_ERROR(("fetch_raw_descriptor64: GDT: index (%x) %x > limit (%x)",
615
         index*8 + 15, index, BX_CPU_THIS_PTR gdtr.limit));
616
      exception(exception_no, selector->value & 0xfffc);
617
    }
618
    offset = BX_CPU_THIS_PTR gdtr.base + index*8;
619
  }
620
  else { /* LDT */
621
    if (BX_CPU_THIS_PTR ldtr.cache.valid==0) {
622
      BX_ERROR(("fetch_raw_descriptor64: LDTR.valid=0"));
623
      exception(exception_no, selector->value & 0xfffc);
624
    }
625
    if ((index*8 + 15) > BX_CPU_THIS_PTR ldtr.cache.u.segment.limit_scaled) {
626
      BX_ERROR(("fetch_raw_descriptor64: LDT: index (%x) %x > limit (%x)",
627
         index*8 + 15, index, BX_CPU_THIS_PTR ldtr.cache.u.segment.limit_scaled));
628
      exception(exception_no, selector->value & 0xfffc);
629
    }
630
    offset = BX_CPU_THIS_PTR ldtr.cache.u.segment.base + index*8;
631
  }
632
 
633
  raw_descriptor1 = system_read_qword(offset);
634
  raw_descriptor2 = system_read_qword(offset + 8);
635
 
636
  if (raw_descriptor2 & BX_CONST64(0x00001F0000000000)) {
637
    BX_ERROR(("fetch_raw_descriptor64: extended attributes DWORD4 TYPE != 0"));
638
    exception(BX_GP_EXCEPTION, selector->value & 0xfffc);
639
  }
640
 
641
  *dword1 = GET32L(raw_descriptor1);
642
  *dword2 = GET32H(raw_descriptor1);
643
  *dword3 = GET32L(raw_descriptor2);
644
}
645
 
646
bx_bool BX_CPU_C::fetch_raw_descriptor2_64(const bx_selector_t *selector,
647
           Bit32u *dword1, Bit32u *dword2, Bit32u *dword3)
648
{
649
  Bit32u index = selector->index;
650
  bx_address offset;
651
  Bit64u raw_descriptor1, raw_descriptor2;
652
 
653
  if (selector->ti == 0) { /* GDT */
654
    if ((index*8 + 15) > BX_CPU_THIS_PTR gdtr.limit) {
655
      BX_ERROR(("fetch_raw_descriptor2_64: GDT: index (%x) %x > limit (%x)",
656
         index*8 + 15, index, BX_CPU_THIS_PTR gdtr.limit));
657
      return 0;
658
    }
659
    offset = BX_CPU_THIS_PTR gdtr.base + index*8;
660
  }
661
  else { /* LDT */
662
    if (BX_CPU_THIS_PTR ldtr.cache.valid==0) {
663
      BX_ERROR(("fetch_raw_descriptor2_64: LDTR.valid=0"));
664
      return 0;
665
    }
666
    if ((index*8 + 15) > BX_CPU_THIS_PTR ldtr.cache.u.segment.limit_scaled) {
667
      BX_ERROR(("fetch_raw_descriptor2_64: LDT: index (%x) %x > limit (%x)",
668
         index*8 + 15, index, BX_CPU_THIS_PTR ldtr.cache.u.segment.limit_scaled));
669
      return 0;
670
    }
671
    offset = BX_CPU_THIS_PTR ldtr.cache.u.segment.base + index*8;
672
  }
673
 
674
  raw_descriptor1 = system_read_qword(offset);
675
  raw_descriptor2 = system_read_qword(offset + 8);
676
 
677
  if (raw_descriptor2 & BX_CONST64(0x00001F0000000000)) {
678
    BX_ERROR(("fetch_raw_descriptor2_64: extended attributes DWORD4 TYPE != 0"));
679
    return 0;
680
  }
681
 
682
  *dword1 = GET32L(raw_descriptor1);
683
  *dword2 = GET32H(raw_descriptor1);
684
  *dword3 = GET32L(raw_descriptor2);
685
 
686
  return 1;
687
}
688
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.