- added instructions how to update the online documentation
[bochs-mirror.git] / cpu / io.cc
blob8763e2ba3d359b60078c1aa03a94286380072bad
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: io.cc,v 1.69 2008/12/11 21:19:38 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
27 /////////////////////////////////////////////////////////////////////////
29 #define NEED_CPU_REG_SHORTCUTS 1
30 #include "bochs.h"
31 #include "cpu.h"
32 #define LOG_THIS BX_CPU_THIS_PTR
34 #include "iodev/iodev.h"
36 #if BX_SUPPORT_X86_64==0
37 // Make life easier for merging cpu64 and cpu32 code.
38 #define RDI EDI
39 #define RSI ESI
40 #define RAX EAX
41 #define RCX ECX
42 #endif
45 // Repeat Speedups methods
48 #if BX_SupportRepeatSpeedups
49 Bit32u BX_CPU_C::FastRepINSW(bxInstruction_c *i, bx_address dstOff, Bit16u port, Bit32u wordCount)
51 Bit32u wordsFitDst;
52 signed int pointerDelta;
53 Bit8u *hostAddrDst;
54 unsigned count;
56 BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
58 bx_segment_reg_t *dstSegPtr = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES];
59 if (!(dstSegPtr->cache.valid & SegAccessWOK))
60 return 0;
61 if ((dstOff | 0xfff) > dstSegPtr->cache.u.segment.limit_scaled)
62 return 0;
64 bx_address laddrDst = BX_CPU_THIS_PTR get_laddr(BX_SEG_REG_ES, dstOff);
65 // check that the address is word aligned
66 if (laddrDst & 1) return 0;
68 hostAddrDst = v2h_write_byte(laddrDst, BX_CPU_THIS_PTR user_pl);
69 // Check that native host access was not vetoed for that page
70 if (!hostAddrDst) return 0;
72 // See how many words can fit in the rest of this page.
73 if (BX_CPU_THIS_PTR get_DF()) {
74 // Counting downward
75 // 1st word must cannot cross page boundary because it is word aligned
76 wordsFitDst = (2 + (PAGE_OFFSET(laddrDst))) >> 1;
77 pointerDelta = -2;
79 else {
80 // Counting upward
81 wordsFitDst = (0x1000 - PAGE_OFFSET(laddrDst)) >> 1;
82 pointerDelta = 2;
85 // Restrict word count to the number that will fit in this page.
86 if (wordCount > wordsFitDst)
87 wordCount = wordsFitDst;
89 // If after all the restrictions, there is anything left to do...
90 if (wordCount) {
91 for (count=0; count<wordCount; ) {
92 bx_devices.bulkIOQuantumsTransferred = 0;
93 if (BX_CPU_THIS_PTR get_DF()==0) { // Only do accel for DF=0
94 bx_devices.bulkIOHostAddr = hostAddrDst;
95 bx_devices.bulkIOQuantumsRequested = (wordCount - count);
97 else
98 bx_devices.bulkIOQuantumsRequested = 0;
99 Bit16u temp16 = BX_INP(port, 2);
100 if (bx_devices.bulkIOQuantumsTransferred) {
101 hostAddrDst = bx_devices.bulkIOHostAddr;
102 count += bx_devices.bulkIOQuantumsTransferred;
104 else {
105 WriteHostWordToLittleEndian(hostAddrDst, temp16);
106 hostAddrDst += pointerDelta;
107 count++;
109 // Terminate early if there was an event.
110 if (BX_CPU_THIS_PTR async_event) break;
113 // Reset for next non-bulk IO
114 bx_devices.bulkIOQuantumsRequested = 0;
116 return count;
119 return 0;
122 Bit32u BX_CPU_C::FastRepOUTSW(bxInstruction_c *i, unsigned srcSeg, bx_address srcOff, Bit16u port, Bit32u wordCount)
124 Bit32u wordsFitSrc;
125 signed int pointerDelta;
126 Bit8u *hostAddrSrc;
127 unsigned count;
129 BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64);
131 bx_segment_reg_t *srcSegPtr = &BX_CPU_THIS_PTR sregs[srcSeg];
132 if (!(srcSegPtr->cache.valid & SegAccessROK))
133 return 0;
134 if ((srcOff | 0xfff) > srcSegPtr->cache.u.segment.limit_scaled)
135 return 0;
137 bx_address laddrSrc = BX_CPU_THIS_PTR get_laddr(srcSeg, srcOff);
138 // check that the address is word aligned
139 if (laddrSrc & 1) return 0;
141 hostAddrSrc = v2h_read_byte(laddrSrc, BX_CPU_THIS_PTR user_pl);
143 // Check that native host access was not vetoed for that page
144 if (!hostAddrSrc) return 0;
146 // See how many words can fit in the rest of this page.
147 if (BX_CPU_THIS_PTR get_DF()) {
148 // Counting downward
149 // 1st word must cannot cross page boundary because it is word aligned
150 wordsFitSrc = (2 + (PAGE_OFFSET(laddrSrc))) >> 1;
151 pointerDelta = (unsigned) -2;
153 else {
154 // Counting upward
155 wordsFitSrc = (0x1000 - PAGE_OFFSET(laddrSrc)) >> 1;
156 pointerDelta = 2;
159 // Restrict word count to the number that will fit in this page.
160 if (wordCount > wordsFitSrc)
161 wordCount = wordsFitSrc;
163 // If after all the restrictions, there is anything left to do...
164 if (wordCount) {
165 for (count=0; count<wordCount; ) {
166 bx_devices.bulkIOQuantumsTransferred = 0;
167 if (BX_CPU_THIS_PTR get_DF()==0) { // Only do accel for DF=0
168 bx_devices.bulkIOHostAddr = hostAddrSrc;
169 bx_devices.bulkIOQuantumsRequested = (wordCount - count);
171 else
172 bx_devices.bulkIOQuantumsRequested = 0;
173 Bit16u temp16;
174 ReadHostWordFromLittleEndian(hostAddrSrc, temp16);
175 BX_OUTP(port, temp16, 2);
176 if (bx_devices.bulkIOQuantumsTransferred) {
177 hostAddrSrc = bx_devices.bulkIOHostAddr;
178 count += bx_devices.bulkIOQuantumsTransferred;
180 else {
181 hostAddrSrc += pointerDelta;
182 count++;
184 // Terminate early if there was an event.
185 if (BX_CPU_THIS_PTR async_event) break;
188 // Reset for next non-bulk IO
189 bx_devices.bulkIOQuantumsRequested = 0;
191 return count;
194 return 0;
197 #endif
200 // REP INS methods
203 void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_INSB_YbDX(bxInstruction_c *i)
205 #if BX_SUPPORT_X86_64
206 if (i->as64L()) {
207 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSB64_YbDX);
209 else
210 #endif
211 if (i->as32L()) {
212 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSB32_YbDX);
213 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI
215 else {
216 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSB16_YbDX);
220 // 16-bit address size
221 void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSB16_YbDX(bxInstruction_c *i)
223 if (! BX_CPU_THIS_PTR allow_io(DX, 1)) {
224 BX_DEBUG(("INSB_YbDX: I/O access not allowed !"));
225 exception(BX_GP_EXCEPTION, 0, 0);
228 // trigger any segment or page faults before reading from IO port
229 Bit8u value8 = read_RMW_virtual_byte_32(BX_SEG_REG_ES, DI);
231 value8 = BX_INP(DX, 1);
233 write_RMW_virtual_byte(value8);
235 if (BX_CPU_THIS_PTR get_DF())
236 DI--;
237 else
238 DI++;
241 // 32-bit address size
242 void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSB32_YbDX(bxInstruction_c *i)
244 if (! BX_CPU_THIS_PTR allow_io(DX, 1)) {
245 BX_DEBUG(("INSB_YbDX: I/O access not allowed !"));
246 exception(BX_GP_EXCEPTION, 0, 0);
249 // trigger any segment or page faults before reading from IO port
250 Bit8u value8 = read_RMW_virtual_byte_32(BX_SEG_REG_ES, EDI);
252 value8 = BX_INP(DX, 1);
254 /* no seg override possible */
255 write_RMW_virtual_byte(value8);
257 if (BX_CPU_THIS_PTR get_DF()) {
258 RDI = EDI - 1;
260 else {
261 RDI = EDI + 1;
265 #if BX_SUPPORT_X86_64
267 // 64-bit address size
268 void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSB64_YbDX(bxInstruction_c *i)
270 if (! BX_CPU_THIS_PTR allow_io(DX, 1)) {
271 BX_DEBUG(("INSB_YbDX: I/O access not allowed !"));
272 exception(BX_GP_EXCEPTION, 0, 0);
275 // trigger any segment or page faults before reading from IO port
276 Bit8u value8 = read_RMW_virtual_byte_64(BX_SEG_REG_ES, RDI);
278 value8 = BX_INP(DX, 1);
280 write_RMW_virtual_byte(value8);
282 if (BX_CPU_THIS_PTR get_DF())
283 RDI--;
284 else
285 RDI++;
288 #endif
290 void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_INSW_YwDX(bxInstruction_c *i)
292 #if BX_SUPPORT_X86_64
293 if (i->as64L()) {
294 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSW64_YwDX);
296 else
297 #endif
298 if (i->as32L()) {
299 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSW32_YwDX);
300 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI
302 else {
303 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSW16_YwDX);
307 // 16-bit operand size, 16-bit address size
308 void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSW16_YwDX(bxInstruction_c *i)
310 if (! BX_CPU_THIS_PTR allow_io(DX, 2)) {
311 BX_DEBUG(("INSW16_YwDX: I/O access not allowed !"));
312 exception(BX_GP_EXCEPTION, 0, 0);
315 // trigger any segment or page faults before reading from IO port
316 Bit16u value16 = read_RMW_virtual_word_32(BX_SEG_REG_ES, DI);
318 value16 = BX_INP(DX, 2);
320 write_RMW_virtual_word(value16);
322 if (BX_CPU_THIS_PTR get_DF())
323 DI -= 2;
324 else
325 DI += 2;
328 // 16-bit operand size, 32-bit address size
329 void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSW32_YwDX(bxInstruction_c *i)
331 Bit16u value16=0;
332 Bit32u edi = EDI;
333 unsigned incr = 2;
335 if (! BX_CPU_THIS_PTR allow_io(DX, 2)) {
336 BX_DEBUG(("INSW32_YwDX: I/O access not allowed !"));
337 exception(BX_GP_EXCEPTION, 0, 0);
340 #if (BX_SupportRepeatSpeedups) && (BX_DEBUGGER == 0)
341 /* If conditions are right, we can transfer IO to physical memory
342 * in a batch, rather than one instruction at a time.
344 if (i->repUsedL() && !BX_CPU_THIS_PTR async_event)
346 Bit32u wordCount = ECX;
347 BX_ASSERT(wordCount > 0);
348 wordCount = FastRepINSW(i, edi, DX, wordCount);
349 if (wordCount) {
350 // Decrement the ticks count by the number of iterations, minus
351 // one, since the main cpu loop will decrement one. Also,
352 // the count is predecremented before examined, so defintely
353 // don't roll it under zero.
354 BX_TICKN(wordCount-1);
355 RCX = ECX - (wordCount-1);
356 incr = wordCount << 1; // count * 2.
358 else {
359 // trigger any segment or page faults before reading from IO port
360 value16 = read_RMW_virtual_word_32(BX_SEG_REG_ES, edi);
362 value16 = BX_INP(DX, 2);
364 write_RMW_virtual_word(value16);
367 else
368 #endif
370 // trigger any segment or page faults before reading from IO port
371 value16 = read_RMW_virtual_word_32(BX_SEG_REG_ES, edi);
373 value16 = BX_INP(DX, 2);
375 write_RMW_virtual_word(value16);
378 if (BX_CPU_THIS_PTR get_DF())
379 RDI = EDI - incr;
380 else
381 RDI = EDI + incr;
384 #if BX_SUPPORT_X86_64
386 // 16-bit operand size, 64-bit address size
387 void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSW64_YwDX(bxInstruction_c *i)
389 if (! BX_CPU_THIS_PTR allow_io(DX, 2)) {
390 BX_DEBUG(("INSW64_YwDX: I/O access not allowed !"));
391 exception(BX_GP_EXCEPTION, 0, 0);
394 // trigger any segment or page faults before reading from IO port
395 Bit16u value16 = read_RMW_virtual_word_64(BX_SEG_REG_ES, RDI);
397 value16 = BX_INP(DX, 2);
399 write_RMW_virtual_word(value16);
401 if (BX_CPU_THIS_PTR get_DF())
402 RDI -= 2;
403 else
404 RDI += 2;
407 #endif
409 void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_INSD_YdDX(bxInstruction_c *i)
411 #if BX_SUPPORT_X86_64
412 if (i->as64L()) {
413 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSD64_YdDX);
415 else
416 #endif
417 if (i->as32L()) {
418 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSD32_YdDX);
419 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI
421 else {
422 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSD16_YdDX);
426 // 32-bit operand size, 16-bit address size
427 void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSD16_YdDX(bxInstruction_c *i)
429 if (! BX_CPU_THIS_PTR allow_io(DX, 4)) {
430 BX_DEBUG(("INSD16_YdDX: I/O access not allowed !"));
431 exception(BX_GP_EXCEPTION, 0, 0);
434 // trigger any segment or page faults before reading from IO port
435 Bit32u value32 = read_RMW_virtual_dword_32(BX_SEG_REG_ES, DI);
437 value32 = BX_INP(DX, 4);
439 write_RMW_virtual_dword(value32);
441 if (BX_CPU_THIS_PTR get_DF())
442 DI -= 4;
443 else
444 DI += 4;
447 // 32-bit operand size, 32-bit address size
448 void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSD32_YdDX(bxInstruction_c *i)
450 if (! BX_CPU_THIS_PTR allow_io(DX, 4)) {
451 BX_DEBUG(("INSD32_YdDX: I/O access not allowed !"));
452 exception(BX_GP_EXCEPTION, 0, 0);
455 // trigger any segment or page faults before reading from IO port
456 Bit32u value32 = read_RMW_virtual_dword_32(BX_SEG_REG_ES, EDI);
458 value32 = BX_INP(DX, 4);
460 write_RMW_virtual_dword(value32);
462 if (BX_CPU_THIS_PTR get_DF())
463 RDI = EDI - 4;
464 else
465 RDI = EDI + 4;
468 #if BX_SUPPORT_X86_64
470 // 32-bit operand size, 64-bit address size
471 void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSD64_YdDX(bxInstruction_c *i)
473 if (! BX_CPU_THIS_PTR allow_io(DX, 4)) {
474 BX_DEBUG(("INSD64_YdDX: I/O access not allowed !"));
475 exception(BX_GP_EXCEPTION, 0, 0);
478 // trigger any segment or page faults before reading from IO port
479 Bit32u value32 = read_RMW_virtual_dword_64(BX_SEG_REG_ES, RDI);
481 value32 = BX_INP(DX, 4);
483 write_RMW_virtual_dword(value32);
485 if (BX_CPU_THIS_PTR get_DF())
486 RDI -= 4;
487 else
488 RDI += 4;
491 #endif
494 // REP OUTS methods
497 void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_OUTSB_DXXb(bxInstruction_c *i)
499 #if BX_SUPPORT_X86_64
500 if (i->as64L()) {
501 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSB64_DXXb);
503 else
504 #endif
505 if (i->as32L()) {
506 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSB32_DXXb);
507 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI
509 else {
510 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSB16_DXXb);
514 // 16-bit address size
515 void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSB16_DXXb(bxInstruction_c *i)
517 if (! BX_CPU_THIS_PTR allow_io(DX, 1)) {
518 BX_DEBUG(("OUTSB16_DXXb: I/O access not allowed !"));
519 exception(BX_GP_EXCEPTION, 0, 0);
522 Bit8u value8 = read_virtual_byte_32(i->seg(), SI);
523 BX_OUTP(DX, value8, 1);
525 if (BX_CPU_THIS_PTR get_DF())
526 SI--;
527 else
528 SI++;
531 // 32-bit address size
532 void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSB32_DXXb(bxInstruction_c *i)
534 if (! BX_CPU_THIS_PTR allow_io(DX, 1)) {
535 BX_DEBUG(("OUTSB32_DXXb: I/O access not allowed !"));
536 exception(BX_GP_EXCEPTION, 0, 0);
539 Bit8u value8 = read_virtual_byte(i->seg(), ESI);
540 BX_OUTP(DX, value8, 1);
542 if (BX_CPU_THIS_PTR get_DF())
543 RSI = ESI - 1;
544 else
545 RSI = ESI + 1;
548 #if BX_SUPPORT_X86_64
550 // 64-bit address size
551 void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSB64_DXXb(bxInstruction_c *i)
553 if (! BX_CPU_THIS_PTR allow_io(DX, 1)) {
554 BX_DEBUG(("OUTSB64_DXXb: I/O access not allowed !"));
555 exception(BX_GP_EXCEPTION, 0, 0);
558 Bit8u value8 = read_virtual_byte_64(i->seg(), RSI);
559 BX_OUTP(DX, value8, 1);
561 if (BX_CPU_THIS_PTR get_DF())
562 RSI--;
563 else
564 RSI++;
567 #endif
569 void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_OUTSW_DXXw(bxInstruction_c *i)
571 #if BX_SUPPORT_X86_64
572 if (i->as64L()) {
573 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSW64_DXXw);
575 else
576 #endif
577 if (i->as32L()) {
578 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSW32_DXXw);
579 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI
581 else {
582 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSW16_DXXw);
586 // 16-bit operand size, 16-bit address size
587 void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSW16_DXXw(bxInstruction_c *i)
589 if (! BX_CPU_THIS_PTR allow_io(DX, 2)) {
590 BX_DEBUG(("OUTSW16_DXXw: I/O access not allowed !"));
591 exception(BX_GP_EXCEPTION, 0, 0);
594 Bit16u value16 = read_virtual_word_32(i->seg(), SI);
595 BX_OUTP(DX, value16, 2);
597 if (BX_CPU_THIS_PTR get_DF())
598 SI -= 2;
599 else
600 SI += 2;
603 // 16-bit operand size, 32-bit address size
604 void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSW32_DXXw(bxInstruction_c *i)
606 if (! BX_CPU_THIS_PTR allow_io(DX, 2)) {
607 BX_DEBUG(("OUTSW32_DXXw: I/O access not allowed !"));
608 exception(BX_GP_EXCEPTION, 0, 0);
611 Bit16u value16;
612 Bit32u esi = ESI;
613 unsigned incr = 2;
615 #if (BX_SupportRepeatSpeedups) && (BX_DEBUGGER == 0)
616 /* If conditions are right, we can transfer IO to physical memory
617 * in a batch, rather than one instruction at a time.
619 if (i->repUsedL() && !BX_CPU_THIS_PTR async_event) {
620 Bit32u wordCount = ECX;
621 wordCount = FastRepOUTSW(i, i->seg(), esi, DX, wordCount);
622 if (wordCount) {
623 // Decrement eCX. Note, the main loop will decrement 1 also, so
624 // decrement by one less than expected, like the case above.
625 BX_TICKN(wordCount-1); // Main cpu loop also decrements one more.
626 RCX = ECX - (wordCount-1);
627 incr = wordCount << 1; // count * 2.
629 else {
630 value16 = read_virtual_word(i->seg(), esi);
631 BX_OUTP(DX, value16, 2);
634 else
635 #endif
637 value16 = read_virtual_word(i->seg(), esi);
638 BX_OUTP(DX, value16, 2);
641 if (BX_CPU_THIS_PTR get_DF())
642 RSI = ESI - incr;
643 else
644 RSI = ESI + incr;
647 #if BX_SUPPORT_X86_64
649 // 16-bit operand size, 64-bit address size
650 void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSW64_DXXw(bxInstruction_c *i)
652 if (! BX_CPU_THIS_PTR allow_io(DX, 2)) {
653 BX_DEBUG(("OUTSW64_DXXw: I/O access not allowed !"));
654 exception(BX_GP_EXCEPTION, 0, 0);
657 Bit16u value16 = read_virtual_word_64(i->seg(), RSI);
658 BX_OUTP(DX, value16, 2);
660 if (BX_CPU_THIS_PTR get_DF())
661 RSI -= 2;
662 else
663 RSI += 2;
666 #endif
668 void BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_OUTSD_DXXd(bxInstruction_c *i)
670 #if BX_SUPPORT_X86_64
671 if (i->as64L()) {
672 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSD64_DXXd);
674 else
675 #endif
676 if (i->as32L()) {
677 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSD32_DXXd);
678 BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI
680 else {
681 BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSD16_DXXd);
685 // 32-bit operand size, 16-bit address size
686 void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSD16_DXXd(bxInstruction_c *i)
688 if (! BX_CPU_THIS_PTR allow_io(DX, 4)) {
689 BX_DEBUG(("OUTSD16_DXXd: I/O access not allowed !"));
690 exception(BX_GP_EXCEPTION, 0, 0);
693 Bit32u value32 = read_virtual_dword_32(i->seg(), SI);
694 BX_OUTP(DX, value32, 4);
696 if (BX_CPU_THIS_PTR get_DF())
697 SI -= 4;
698 else
699 SI += 4;
702 // 32-bit operand size, 32-bit address size
703 void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSD32_DXXd(bxInstruction_c *i)
705 if (! BX_CPU_THIS_PTR allow_io(DX, 4)) {
706 BX_DEBUG(("OUTSD32_DXXd: I/O access not allowed !"));
707 exception(BX_GP_EXCEPTION, 0, 0);
710 Bit32u value32 = read_virtual_dword(i->seg(), ESI);
711 BX_OUTP(DX, value32, 4);
713 if (BX_CPU_THIS_PTR get_DF())
714 RSI = ESI - 4;
715 else
716 RSI = ESI + 4;
719 #if BX_SUPPORT_X86_64
721 // 32-bit operand size, 64-bit address size
722 void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSD64_DXXd(bxInstruction_c *i)
724 if (! BX_CPU_THIS_PTR allow_io(DX, 4)) {
725 BX_DEBUG(("OUTSD64_DXXd: I/O access not allowed !"));
726 exception(BX_GP_EXCEPTION, 0, 0);
729 Bit32u value32 = read_virtual_dword_64(i->seg(), RSI);
730 BX_OUTP(DX, value32, 4);
732 if (BX_CPU_THIS_PTR get_DF())
733 RSI -= 4;
734 else
735 RSI += 4;
738 #endif
741 // non repeatable IN/OUT methods
744 void BX_CPP_AttrRegparmN(1) BX_CPU_C::IN_ALIb(bxInstruction_c *i)
746 AL = BX_CPU_THIS_PTR inp8(i->Ib());
749 void BX_CPP_AttrRegparmN(1) BX_CPU_C::IN_AXIb(bxInstruction_c *i)
751 AX = BX_CPU_THIS_PTR inp16(i->Ib());
754 void BX_CPP_AttrRegparmN(1) BX_CPU_C::IN_EAXIb(bxInstruction_c *i)
756 RAX = BX_CPU_THIS_PTR inp32(i->Ib());
759 void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUT_IbAL(bxInstruction_c *i)
761 BX_CPU_THIS_PTR outp8(i->Ib(), AL);
764 void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUT_IbAX(bxInstruction_c *i)
766 BX_CPU_THIS_PTR outp16(i->Ib(), AX);
769 void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUT_IbEAX(bxInstruction_c *i)
771 BX_CPU_THIS_PTR outp32(i->Ib(), EAX);
774 void BX_CPP_AttrRegparmN(1) BX_CPU_C::IN_ALDX(bxInstruction_c *i)
776 AL = BX_CPU_THIS_PTR inp8(DX);
779 void BX_CPP_AttrRegparmN(1) BX_CPU_C::IN_AXDX(bxInstruction_c *i)
781 AX = BX_CPU_THIS_PTR inp16(DX);
784 void BX_CPP_AttrRegparmN(1) BX_CPU_C::IN_EAXDX(bxInstruction_c *i)
786 RAX = BX_CPU_THIS_PTR inp32(DX);
789 void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUT_DXAL(bxInstruction_c *i)
791 BX_CPU_THIS_PTR outp8(DX, AL);
794 void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUT_DXAX(bxInstruction_c *i)
796 BX_CPU_THIS_PTR outp16(DX, AX);
799 void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUT_DXEAX(bxInstruction_c *i)
801 BX_CPU_THIS_PTR outp32(DX, EAX);