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

Subversion Repositories ao486

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 alfik
/////////////////////////////////////////////////////////////////////////
2
// $Id: io.cc 11117 2012-03-28 21:11:19Z sshwarts $
3
/////////////////////////////////////////////////////////////////////////
4
//
5
//  Copyright (C) 2001-2011  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
 
23
#define NEED_CPU_REG_SHORTCUTS 1
24
#include "bochs.h"
25
#include "cpu.h"
26
#define LOG_THIS BX_CPU_THIS_PTR
27
 
28
#include "iodev/iodev.h"
29
 
30
//
31
// Repeat Speedups methods
32
//
33
 
34
#if BX_SUPPORT_REPEAT_SPEEDUPS
35
Bit32u BX_CPU_C::FastRepINSW(bxInstruction_c *i, bx_address dstOff, Bit16u port, Bit32u wordCount)
36
{
37
  Bit32u wordsFitDst;
38
  signed int pointerDelta;
39
  Bit8u *hostAddrDst;
40
  unsigned count;
41
 
42
  BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
43
 
44
  bx_segment_reg_t *dstSegPtr = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES];
45
  if (!(dstSegPtr->cache.valid & SegAccessWOK))
46
    return 0;
47
  if ((dstOff | 0xfff) > dstSegPtr->cache.u.segment.limit_scaled)
48
    return 0;
49
 
50
  bx_address laddrDst = get_laddr32(BX_SEG_REG_ES, dstOff);
51
  // check that the address is word aligned
52
  if (laddrDst & 1) return 0;
53
 
54
  hostAddrDst = v2h_write_byte(laddrDst, BX_CPU_THIS_PTR user_pl);
55
  // Check that native host access was not vetoed for that page
56
  if (!hostAddrDst) return 0;
57
 
58
  // See how many words can fit in the rest of this page.
59
  if (BX_CPU_THIS_PTR get_DF()) {
60
    // Counting downward
61
    // 1st word must cannot cross page boundary because it is word aligned
62
    wordsFitDst = (2 + (PAGE_OFFSET(laddrDst))) >> 1;
63
    pointerDelta = -2;
64
  }
65
  else {
66
    // Counting upward
67
    wordsFitDst = (0x1000 - PAGE_OFFSET(laddrDst)) >> 1;
68
    pointerDelta =  2;
69
  }
70
 
71
  // Restrict word count to the number that will fit in this page.
72
  if (wordCount > wordsFitDst)
73
      wordCount = wordsFitDst;
74
 
75
  // If after all the restrictions, there is anything left to do...
76
  if (wordCount) {
77
    for (count=0; count<wordCount; ) {
78
      bx_devices.bulkIOQuantumsTransferred = 0;
79
      if (BX_CPU_THIS_PTR get_DF()==0) { // Only do accel for DF=0
80
        bx_devices.bulkIOHostAddr = hostAddrDst;
81
        bx_devices.bulkIOQuantumsRequested = (wordCount - count);
82
      }
83
      else
84
        bx_devices.bulkIOQuantumsRequested = 0;
85
      Bit16u temp16 = BX_INP(port, 2);
86
      if (bx_devices.bulkIOQuantumsTransferred) {
87
        hostAddrDst = bx_devices.bulkIOHostAddr;
88
        count += bx_devices.bulkIOQuantumsTransferred;
89
      }
90
      else {
91
        WriteHostWordToLittleEndian(hostAddrDst, temp16);
92
        hostAddrDst += pointerDelta;
93
        count++;
94
      }
95
      // Terminate early if there was an event.
96
      if (BX_CPU_THIS_PTR async_event) break;
97
    }
98
 
99
    // Reset for next non-bulk IO
100
    bx_devices.bulkIOQuantumsRequested = 0;
101
 
102
    return count;
103
  }
104
 
105
  return 0;
106
}
107
 
108
Bit32u BX_CPU_C::FastRepOUTSW(bxInstruction_c *i, unsigned srcSeg, bx_address srcOff, Bit16u port, Bit32u wordCount)
109
{
110
  Bit32u wordsFitSrc;
111
  signed int pointerDelta;
112
  Bit8u *hostAddrSrc;
113
  unsigned count;
114
 
115
  BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
116
 
117
  bx_segment_reg_t *srcSegPtr = &BX_CPU_THIS_PTR sregs[srcSeg];
118
  if (!(srcSegPtr->cache.valid & SegAccessROK))
119
    return 0;
120
  if ((srcOff | 0xfff) > srcSegPtr->cache.u.segment.limit_scaled)
121
    return 0;
122
 
123
  bx_address laddrSrc = get_laddr32(srcSeg, srcOff);
124
  // check that the address is word aligned
125
  if (laddrSrc & 1) return 0;
126
 
127
  hostAddrSrc = v2h_read_byte(laddrSrc, BX_CPU_THIS_PTR user_pl);
128
 
129
  // Check that native host access was not vetoed for that page
130
  if (!hostAddrSrc) return 0;
131
 
132
  // See how many words can fit in the rest of this page.
133
  if (BX_CPU_THIS_PTR get_DF()) {
134
    // Counting downward
135
    // 1st word must cannot cross page boundary because it is word aligned
136
    wordsFitSrc = (2 + (PAGE_OFFSET(laddrSrc))) >> 1;
137
    pointerDelta = (unsigned) -2;
138
  }
139
  else {
140
    // Counting upward
141
    wordsFitSrc = (0x1000 - PAGE_OFFSET(laddrSrc)) >> 1;
142
    pointerDelta =  2;
143
  }
144
 
145
  // Restrict word count to the number that will fit in this page.
146
  if (wordCount > wordsFitSrc)
147
      wordCount = wordsFitSrc;
148
 
149
  // If after all the restrictions, there is anything left to do...
150
  if (wordCount) {
151
    for (count=0; count<wordCount; ) {
152
      bx_devices.bulkIOQuantumsTransferred = 0;
153
      if (BX_CPU_THIS_PTR get_DF()==0) { // Only do accel for DF=0
154
        bx_devices.bulkIOHostAddr = hostAddrSrc;
155
        bx_devices.bulkIOQuantumsRequested = (wordCount - count);
156
      }
157
      else
158
        bx_devices.bulkIOQuantumsRequested = 0;
159
      Bit16u temp16;
160
      ReadHostWordFromLittleEndian(hostAddrSrc, temp16);
161
      BX_OUTP(port, temp16, 2);
162
      if (bx_devices.bulkIOQuantumsTransferred) {
163
        hostAddrSrc = bx_devices.bulkIOHostAddr;
164
        count += bx_devices.bulkIOQuantumsTransferred;
165
      }
166
      else {
167
        hostAddrSrc += pointerDelta;
168
        count++;
169
      }
170
      // Terminate early if there was an event.
171
      if (BX_CPU_THIS_PTR async_event) break;
172
    }
173
 
174
    // Reset for next non-bulk IO
175
    bx_devices.bulkIOQuantumsRequested = 0;
176
 
177
    return count;
178
  }
179
 
180
  return 0;
181
}
182
 
183
#endif
184
 
185
//
186
// REP INS methods
187
//
188
 
189
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_INSB_YbDX(bxInstruction_c *i)
190
{
191
  if (! allow_io(i, DX, 1)) {
192
    BX_DEBUG(("INSB_YbDX: I/O access not allowed !"));
193
    exception(BX_GP_EXCEPTION, 0);
194
  }
195
 
196
#if BX_SUPPORT_X86_64
197
  if (i->as64L()) {
198
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSB64_YbDX);
199
  }
200
  else
201
#endif
202
  if (i->as32L()) {
203
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSB32_YbDX);
204
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI
205
  }
206
  else {
207
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSB16_YbDX);
208
  }
209
 
210
  BX_NEXT_INSTR(i);
211
}
212
 
213
// 16-bit address size
214
void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSB16_YbDX(bxInstruction_c *i)
215
{
216
  // trigger any segment or page faults before reading from IO port
217
  Bit8u value8 = read_RMW_virtual_byte_32(BX_SEG_REG_ES, DI);
218
 
219
  value8 = BX_INP(DX, 1);
220
 
221
  write_RMW_virtual_byte(value8);
222
 
223
  if (BX_CPU_THIS_PTR get_DF())
224
    DI--;
225
  else
226
    DI++;
227
}
228
 
229
// 32-bit address size
230
void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSB32_YbDX(bxInstruction_c *i)
231
{
232
  // trigger any segment or page faults before reading from IO port
233
  Bit8u value8 = read_RMW_virtual_byte(BX_SEG_REG_ES, EDI);
234
 
235
  value8 = BX_INP(DX, 1);
236
 
237
  /* no seg override possible */
238
  write_RMW_virtual_byte(value8);
239
 
240
  if (BX_CPU_THIS_PTR get_DF()) {
241
    RDI = EDI - 1;
242
  }
243
  else {
244
    RDI = EDI + 1;
245
  }
246
}
247
 
248
#if BX_SUPPORT_X86_64
249
 
250
// 64-bit address size
251
void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSB64_YbDX(bxInstruction_c *i)
252
{
253
  // trigger any segment or page faults before reading from IO port
254
  Bit8u value8 = read_RMW_virtual_byte_64(BX_SEG_REG_ES, RDI);
255
 
256
  value8 = BX_INP(DX, 1);
257
 
258
  write_RMW_virtual_byte(value8);
259
 
260
  if (BX_CPU_THIS_PTR get_DF())
261
    RDI--;
262
  else
263
    RDI++;
264
}
265
 
266
#endif
267
 
268
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_INSW_YwDX(bxInstruction_c *i)
269
{
270
  if (! allow_io(i, DX, 2)) {
271
    BX_DEBUG(("INSW_YwDX: I/O access not allowed !"));
272
    exception(BX_GP_EXCEPTION, 0);
273
  }
274
 
275
#if BX_SUPPORT_X86_64
276
  if (i->as64L()) {
277
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSW64_YwDX);
278
  }
279
  else
280
#endif
281
  if (i->as32L()) {
282
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSW32_YwDX);
283
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI
284
  }
285
  else {
286
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSW16_YwDX);
287
  }
288
 
289
  BX_NEXT_INSTR(i);
290
}
291
 
292
// 16-bit operand size, 16-bit address size
293
void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSW16_YwDX(bxInstruction_c *i)
294
{
295
  // trigger any segment or page faults before reading from IO port
296
  Bit16u value16 = read_RMW_virtual_word_32(BX_SEG_REG_ES, DI);
297
 
298
  value16 = BX_INP(DX, 2);
299
 
300
  write_RMW_virtual_word(value16);
301
 
302
  if (BX_CPU_THIS_PTR get_DF())
303
    DI -= 2;
304
  else
305
    DI += 2;
306
}
307
 
308
// 16-bit operand size, 32-bit address size
309
void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSW32_YwDX(bxInstruction_c *i)
310
{
311
  Bit16u value16=0;
312
  Bit32u edi = EDI;
313
  unsigned incr = 2;
314
 
315
#if (BX_SUPPORT_REPEAT_SPEEDUPS) && (BX_DEBUGGER == 0)
316
  /* If conditions are right, we can transfer IO to physical memory
317
   * in a batch, rather than one instruction at a time.
318
   */
319
  if (i->repUsedL() && !BX_CPU_THIS_PTR async_event)
320
  {
321
    Bit32u wordCount = ECX;
322
    BX_ASSERT(wordCount > 0);
323
    wordCount = FastRepINSW(i, edi, DX, wordCount);
324
    if (wordCount) {
325
      // Decrement the ticks count by the number of iterations, minus
326
      // one, since the main cpu loop will decrement one.  Also,
327
      // the count is predecremented before examined, so defintely
328
      // don't roll it under zero.
329
      BX_TICKN(wordCount-1);
330
      RCX = ECX - (wordCount-1);
331
      incr = wordCount << 1; // count * 2.
332
    }
333
    else {
334
      // trigger any segment or page faults before reading from IO port
335
      value16 = read_RMW_virtual_word(BX_SEG_REG_ES, edi);
336
 
337
      value16 = BX_INP(DX, 2);
338
 
339
      write_RMW_virtual_word(value16);
340
    }
341
  }
342
  else
343
#endif
344
  {
345
    // trigger any segment or page faults before reading from IO port
346
    value16 = read_RMW_virtual_word_32(BX_SEG_REG_ES, edi);
347
 
348
    value16 = BX_INP(DX, 2);
349
 
350
    write_RMW_virtual_word(value16);
351
  }
352
 
353
  if (BX_CPU_THIS_PTR get_DF())
354
    RDI = EDI - incr;
355
  else
356
    RDI = EDI + incr;
357
}
358
 
359
#if BX_SUPPORT_X86_64
360
 
361
// 16-bit operand size, 64-bit address size
362
void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSW64_YwDX(bxInstruction_c *i)
363
{
364
  // trigger any segment or page faults before reading from IO port
365
  Bit16u value16 = read_RMW_virtual_word_64(BX_SEG_REG_ES, RDI);
366
 
367
  value16 = BX_INP(DX, 2);
368
 
369
  write_RMW_virtual_word(value16);
370
 
371
  if (BX_CPU_THIS_PTR get_DF())
372
    RDI -= 2;
373
  else
374
    RDI += 2;
375
}
376
 
377
#endif
378
 
379
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_INSD_YdDX(bxInstruction_c *i)
380
{
381
  if (! allow_io(i, DX, 4)) {
382
    BX_DEBUG(("INSD_YdDX: I/O access not allowed !"));
383
    exception(BX_GP_EXCEPTION, 0);
384
  }
385
 
386
#if BX_SUPPORT_X86_64
387
  if (i->as64L()) {
388
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSD64_YdDX);
389
  }
390
  else
391
#endif
392
  if (i->as32L()) {
393
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSD32_YdDX);
394
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI
395
  }
396
  else {
397
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSD16_YdDX);
398
  }
399
 
400
  BX_NEXT_INSTR(i);
401
}
402
 
403
// 32-bit operand size, 16-bit address size
404
void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSD16_YdDX(bxInstruction_c *i)
405
{
406
  // trigger any segment or page faults before reading from IO port
407
  Bit32u value32 = read_RMW_virtual_dword_32(BX_SEG_REG_ES, DI);
408
 
409
  value32 = BX_INP(DX, 4);
410
 
411
  write_RMW_virtual_dword(value32);
412
 
413
  if (BX_CPU_THIS_PTR get_DF())
414
    DI -= 4;
415
  else
416
    DI += 4;
417
}
418
 
419
// 32-bit operand size, 32-bit address size
420
void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSD32_YdDX(bxInstruction_c *i)
421
{
422
  // trigger any segment or page faults before reading from IO port
423
  Bit32u value32 = read_RMW_virtual_dword(BX_SEG_REG_ES, EDI);
424
 
425
  value32 = BX_INP(DX, 4);
426
 
427
  write_RMW_virtual_dword(value32);
428
 
429
  if (BX_CPU_THIS_PTR get_DF())
430
    RDI = EDI - 4;
431
  else
432
    RDI = EDI + 4;
433
}
434
 
435
#if BX_SUPPORT_X86_64
436
 
437
// 32-bit operand size, 64-bit address size
438
void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSD64_YdDX(bxInstruction_c *i)
439
{
440
  // trigger any segment or page faults before reading from IO port
441
  Bit32u value32 = read_RMW_virtual_dword_64(BX_SEG_REG_ES, RDI);
442
 
443
  value32 = BX_INP(DX, 4);
444
 
445
  write_RMW_virtual_dword(value32);
446
 
447
  if (BX_CPU_THIS_PTR get_DF())
448
    RDI -= 4;
449
  else
450
    RDI += 4;
451
}
452
 
453
#endif
454
 
455
//
456
// REP OUTS methods
457
//
458
 
459
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_OUTSB_DXXb(bxInstruction_c *i)
460
{
461
  if (! allow_io(i, DX, 1)) {
462
    BX_DEBUG(("OUTSB_DXXb: I/O access not allowed !"));
463
    exception(BX_GP_EXCEPTION, 0);
464
  }
465
 
466
#if BX_SUPPORT_X86_64
467
  if (i->as64L()) {
468
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSB64_DXXb);
469
  }
470
  else
471
#endif
472
  if (i->as32L()) {
473
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSB32_DXXb);
474
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI
475
  }
476
  else {
477
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSB16_DXXb);
478
  }
479
 
480
  BX_NEXT_INSTR(i);
481
}
482
 
483
// 16-bit address size
484
void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSB16_DXXb(bxInstruction_c *i)
485
{
486
  Bit8u value8 = read_virtual_byte_32(i->seg(), SI);
487
  BX_OUTP(DX, value8, 1);
488
 
489
  if (BX_CPU_THIS_PTR get_DF())
490
    SI--;
491
  else
492
    SI++;
493
}
494
 
495
// 32-bit address size
496
void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSB32_DXXb(bxInstruction_c *i)
497
{
498
  Bit8u value8 = read_virtual_byte(i->seg(), ESI);
499
  BX_OUTP(DX, value8, 1);
500
 
501
  if (BX_CPU_THIS_PTR get_DF())
502
    RSI = ESI - 1;
503
  else
504
    RSI = ESI + 1;
505
}
506
 
507
#if BX_SUPPORT_X86_64
508
 
509
// 64-bit address size
510
void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSB64_DXXb(bxInstruction_c *i)
511
{
512
  Bit8u value8 = read_virtual_byte_64(i->seg(), RSI);
513
  BX_OUTP(DX, value8, 1);
514
 
515
  if (BX_CPU_THIS_PTR get_DF())
516
    RSI--;
517
  else
518
    RSI++;
519
}
520
 
521
#endif
522
 
523
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_OUTSW_DXXw(bxInstruction_c *i)
524
{
525
  if (! allow_io(i, DX, 2)) {
526
    BX_DEBUG(("OUTSW_DXXw: I/O access not allowed !"));
527
    exception(BX_GP_EXCEPTION, 0);
528
  }
529
 
530
#if BX_SUPPORT_X86_64
531
  if (i->as64L()) {
532
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSW64_DXXw);
533
  }
534
  else
535
#endif
536
  if (i->as32L()) {
537
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSW32_DXXw);
538
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI
539
  }
540
  else {
541
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSW16_DXXw);
542
  }
543
 
544
  BX_NEXT_INSTR(i);
545
}
546
 
547
// 16-bit operand size, 16-bit address size
548
void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSW16_DXXw(bxInstruction_c *i)
549
{
550
  Bit16u value16 = read_virtual_word_32(i->seg(), SI);
551
  BX_OUTP(DX, value16, 2);
552
 
553
  if (BX_CPU_THIS_PTR get_DF())
554
    SI -= 2;
555
  else
556
    SI += 2;
557
}
558
 
559
// 16-bit operand size, 32-bit address size
560
void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSW32_DXXw(bxInstruction_c *i)
561
{
562
  Bit16u value16;
563
  Bit32u esi = ESI;
564
  unsigned incr = 2;
565
 
566
#if (BX_SUPPORT_REPEAT_SPEEDUPS) && (BX_DEBUGGER == 0)
567
  /* If conditions are right, we can transfer IO to physical memory
568
   * in a batch, rather than one instruction at a time.
569
   */
570
  if (i->repUsedL() && !BX_CPU_THIS_PTR async_event) {
571
    Bit32u wordCount = ECX;
572
    wordCount = FastRepOUTSW(i, i->seg(), esi, DX, wordCount);
573
    if (wordCount) {
574
      // Decrement eCX.  Note, the main loop will decrement 1 also, so
575
      // decrement by one less than expected, like the case above.
576
      BX_TICKN(wordCount-1); // Main cpu loop also decrements one more.
577
      RCX = ECX - (wordCount-1);
578
      incr = wordCount << 1; // count * 2.
579
    }
580
    else {
581
      value16 = read_virtual_word(i->seg(), esi);
582
      BX_OUTP(DX, value16, 2);
583
    }
584
  }
585
  else
586
#endif
587
  {
588
    value16 = read_virtual_word(i->seg(), esi);
589
    BX_OUTP(DX, value16, 2);
590
  }
591
 
592
  if (BX_CPU_THIS_PTR get_DF())
593
    RSI = ESI - incr;
594
  else
595
    RSI = ESI + incr;
596
}
597
 
598
#if BX_SUPPORT_X86_64
599
 
600
// 16-bit operand size, 64-bit address size
601
void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSW64_DXXw(bxInstruction_c *i)
602
{
603
  Bit16u value16 = read_virtual_word_64(i->seg(), RSI);
604
  BX_OUTP(DX, value16, 2);
605
 
606
  if (BX_CPU_THIS_PTR get_DF())
607
    RSI -= 2;
608
  else
609
    RSI += 2;
610
}
611
 
612
#endif
613
 
614
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_OUTSD_DXXd(bxInstruction_c *i)
615
{
616
  if (! allow_io(i, DX, 4)) {
617
    BX_DEBUG(("OUTSD_DXXd: I/O access not allowed !"));
618
    exception(BX_GP_EXCEPTION, 0);
619
  }
620
 
621
#if BX_SUPPORT_X86_64
622
  if (i->as64L()) {
623
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSD64_DXXd);
624
  }
625
  else
626
#endif
627
  if (i->as32L()) {
628
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSD32_DXXd);
629
    BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI
630
  }
631
  else {
632
    BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSD16_DXXd);
633
  }
634
 
635
  BX_NEXT_INSTR(i);
636
}
637
 
638
// 32-bit operand size, 16-bit address size
639
void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSD16_DXXd(bxInstruction_c *i)
640
{
641
  Bit32u value32 = read_virtual_dword_32(i->seg(), SI);
642
  BX_OUTP(DX, value32, 4);
643
 
644
  if (BX_CPU_THIS_PTR get_DF())
645
    SI -= 4;
646
  else
647
    SI += 4;
648
}
649
 
650
// 32-bit operand size, 32-bit address size
651
void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSD32_DXXd(bxInstruction_c *i)
652
{
653
  Bit32u value32 = read_virtual_dword(i->seg(), ESI);
654
  BX_OUTP(DX, value32, 4);
655
 
656
  if (BX_CPU_THIS_PTR get_DF())
657
    RSI = ESI - 4;
658
  else
659
    RSI = ESI + 4;
660
}
661
 
662
#if BX_SUPPORT_X86_64
663
 
664
// 32-bit operand size, 64-bit address size
665
void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSD64_DXXd(bxInstruction_c *i)
666
{
667
  Bit32u value32 = read_virtual_dword_64(i->seg(), RSI);
668
  BX_OUTP(DX, value32, 4);
669
 
670
  if (BX_CPU_THIS_PTR get_DF())
671
    RSI -= 4;
672
  else
673
    RSI += 4;
674
}
675
 
676
#endif
677
 
678
//
679
// non repeatable IN/OUT methods
680
//
681
 
682
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IN_ALIb(bxInstruction_c *i)
683
{
684
  unsigned port = i->Ib();
685
 
686
  if (! allow_io(i, port, 1)) {
687
    BX_DEBUG(("IN_ALIb: I/O access not allowed !"));
688
    exception(BX_GP_EXCEPTION, 0);
689
  }
690
 
691
  AL = BX_INP(port, 1);
692
 
693
  BX_NEXT_INSTR(i);
694
}
695
 
696
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IN_AXIb(bxInstruction_c *i)
697
{
698
  unsigned port = i->Ib();
699
 
700
  if (! allow_io(i, port, 2)) {
701
    BX_DEBUG(("IN_AXIb: I/O access not allowed !"));
702
    exception(BX_GP_EXCEPTION, 0);
703
  }
704
 
705
  AX = BX_INP(port, 2);
706
 
707
  BX_NEXT_INSTR(i);
708
}
709
 
710
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IN_EAXIb(bxInstruction_c *i)
711
{
712
  unsigned port = i->Ib();
713
 
714
  if (! allow_io(i, port, 4)) {
715
    BX_DEBUG(("IN_EAXIb: I/O access not allowed !"));
716
    exception(BX_GP_EXCEPTION, 0);
717
  }
718
 
719
  RAX = BX_INP(port, 4);
720
 
721
  BX_NEXT_INSTR(i);
722
}
723
 
724
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OUT_IbAL(bxInstruction_c *i)
725
{
726
  unsigned port = i->Ib();
727
 
728
  if (! allow_io(i, port, 1)) {
729
    BX_DEBUG(("OUT_IbAL: I/O access not allowed !"));
730
    exception(BX_GP_EXCEPTION, 0);
731
  }
732
 
733
  BX_OUTP(port, AL, 1);
734
 
735
  BX_NEXT_INSTR(i);
736
}
737
 
738
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OUT_IbAX(bxInstruction_c *i)
739
{
740
  unsigned port = i->Ib();
741
 
742
  if (! allow_io(i, port, 2)) {
743
    BX_DEBUG(("OUT_IbAX: I/O access not allowed !"));
744
    exception(BX_GP_EXCEPTION, 0);
745
  }
746
 
747
  BX_OUTP(port, AX, 2);
748
 
749
  BX_NEXT_INSTR(i);
750
}
751
 
752
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OUT_IbEAX(bxInstruction_c *i)
753
{
754
  unsigned port = i->Ib();
755
 
756
  if (! allow_io(i, port, 4)) {
757
    BX_DEBUG(("OUT_IbEAX: I/O access not allowed !"));
758
    exception(BX_GP_EXCEPTION, 0);
759
  }
760
 
761
  BX_OUTP(port, EAX, 4);
762
 
763
  BX_NEXT_INSTR(i);
764
}
765
 
766
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IN_ALDX(bxInstruction_c *i)
767
{
768
  unsigned port = DX;
769
 
770
  if (! allow_io(i, port, 1)) {
771
    BX_DEBUG(("IN_ALDX: I/O access not allowed !"));
772
    exception(BX_GP_EXCEPTION, 0);
773
  }
774
 
775
  AL = BX_INP(port, 1);
776
 
777
  BX_NEXT_INSTR(i);
778
}
779
 
780
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IN_AXDX(bxInstruction_c *i)
781
{
782
  unsigned port = DX;
783
 
784
  if (! allow_io(i, port, 2)) {
785
    BX_DEBUG(("IN_AXDX: I/O access not allowed !"));
786
    exception(BX_GP_EXCEPTION, 0);
787
  }
788
 
789
  AX = BX_INP(port, 2);
790
 
791
  BX_NEXT_INSTR(i);
792
}
793
 
794
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IN_EAXDX(bxInstruction_c *i)
795
{
796
  unsigned port = DX;
797
 
798
  if (! allow_io(i, port, 4)) {
799
    BX_DEBUG(("IN_EAXDX: I/O access not allowed !"));
800
    exception(BX_GP_EXCEPTION, 0);
801
  }
802
 
803
  RAX = BX_INP(port, 4);
804
 
805
  BX_NEXT_INSTR(i);
806
}
807
 
808
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OUT_DXAL(bxInstruction_c *i)
809
{
810
  unsigned port = DX;
811
 
812
  if (! allow_io(i, port, 1)) {
813
    BX_DEBUG(("OUT_DXAL: I/O access not allowed !"));
814
    exception(BX_GP_EXCEPTION, 0);
815
  }
816
 
817
  BX_OUTP(port, AL, 1);
818
 
819
  BX_NEXT_INSTR(i);
820
}
821
 
822
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OUT_DXAX(bxInstruction_c *i)
823
{
824
  unsigned port = DX;
825
 
826
  if (! allow_io(i, port, 2)) {
827
    BX_DEBUG(("OUT_DXAX: I/O access not allowed !"));
828
    exception(BX_GP_EXCEPTION, 0);
829
  }
830
 
831
  BX_OUTP(port, AX, 2);
832
 
833
  BX_NEXT_INSTR(i);
834
}
835
 
836
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OUT_DXEAX(bxInstruction_c *i)
837
{
838
  unsigned port = DX;
839
 
840
  if (! allow_io(i, port, 4)) {
841
    BX_DEBUG(("OUT_DXEAX: I/O access not allowed !"));
842
    exception(BX_GP_EXCEPTION, 0);
843
  }
844
 
845
  BX_OUTP(port, EAX, 4);
846
 
847
  BX_NEXT_INSTR(i);
848
}
849
 
850
bx_bool BX_CPP_AttrRegparmN(3) BX_CPU_C::allow_io(bxInstruction_c *i, Bit16u port, unsigned len)
851
{
852
  /* If CPL <= IOPL, then all IO portesses are accessible.
853
   * Otherwise, must check the IO permission map on >286.
854
   * On the 286, there is no IO permissions map */
855
 
856
  if (BX_CPU_THIS_PTR cr0.get_PE() && (BX_CPU_THIS_PTR get_VM() || (CPL > BX_CPU_THIS_PTR get_IOPL())))
857
  {
858
    if (BX_CPU_THIS_PTR tr.cache.valid==0 ||
859
       (BX_CPU_THIS_PTR tr.cache.type != BX_SYS_SEGMENT_AVAIL_386_TSS &&
860
        BX_CPU_THIS_PTR tr.cache.type != BX_SYS_SEGMENT_BUSY_386_TSS))
861
    {
862
      BX_ERROR(("allow_io(): TR doesn't point to a valid 32bit TSS, TR.TYPE=%u", BX_CPU_THIS_PTR tr.cache.type));
863
      return(0);
864
    }
865
 
866
    if (BX_CPU_THIS_PTR tr.cache.u.segment.limit_scaled < 103) {
867
      BX_ERROR(("allow_io(): TR.limit < 103"));
868
      return(0);
869
    }
870
 
871
    Bit32u io_base = system_read_word(BX_CPU_THIS_PTR tr.cache.u.segment.base + 102);
872
 
873
    if ((io_base + port/8) >= BX_CPU_THIS_PTR tr.cache.u.segment.limit_scaled) {
874
      BX_DEBUG(("allow_io(): IO port %x (len %d) outside TSS IO permission map (base=%x, limit=%x) #GP(0)",
875
        port, len, io_base, BX_CPU_THIS_PTR tr.cache.u.segment.limit_scaled));
876
      return(0);
877
    }
878
 
879
    Bit16u permission16 = system_read_word(BX_CPU_THIS_PTR tr.cache.u.segment.base + io_base + port/8);
880
 
881
    unsigned bit_index = port & 0x7;
882
    unsigned mask = (1 << len) - 1;
883
    if ((permission16 >> bit_index) & mask)
884
      return(0);
885
  }
886
 
887
#if BX_SUPPORT_SVM
888
  if (BX_CPU_THIS_PTR in_svm_guest) {
889
    if (SVM_INTERCEPT(SVM_INTERCEPT0_IO)) SvmInterceptIO(i, port, len);
890
  }
891
#endif
892
 
893
#if BX_SUPPORT_VMX
894
  if (BX_CPU_THIS_PTR in_vmx_guest)
895
    VMexit_IO(i, port, len);
896
#endif
897
 
898
#if BX_X86_DEBUGGER && BX_CPU_LEVEL >= 5
899
  iobreakpoint_match(port, len);
900
#endif
901
 
902
  return(1);
903
}

powered by: WebSVN 2.1.0

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