1 /******************************************************************************
2 * Copyright (c) 2004, 2008 IBM Corporation
3 * Copyright (c) 2008, 2009 Pattrick Hueper <phueper@hueper.net>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
11 * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
14 * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer
16 * in the documentation and/or other materials provided with the
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * IBM Corporation - initial implementation
33 *****************************************************************************/
36 #include "compat/rtas.h"
43 #include "interrupt.h"
45 #include <x86emu/x86emu.h>
46 #include "../x86emu/prim_ops.h"
48 #include <device/pci.h>
49 #include <device/pci_ops.h>
51 //setup to run the code at the address, that the Interrupt Vector points to...
55 DEBUG_PRINTF_INTR("%s(%x): executing interrupt handler @%08x\n",
56 __func__
, intNum
, my_rdl(intNum
* 4));
57 // push current R_FLG... will be popped by IRET
58 push_word((u16
) M
.x86
.R_FLG
);
61 // push current CS:IP to the stack, will be popped by IRET
62 push_word(M
.x86
.R_CS
);
63 push_word(M
.x86
.R_IP
);
64 // set CS:IP to the interrupt handler address... so the next executed instruction will
65 // be the interrupt handler
66 M
.x86
.R_CS
= my_rdw(intNum
* 4 + 2);
67 M
.x86
.R_IP
= my_rdw(intNum
* 4);
70 // handle int10 (VGA BIOS Interrupt)
74 // the data for INT10 is stored in BDA (0000:0400h) offset 49h-66h
75 // function number in AH
76 //DEBUG_PRINTF_CS_IP("%s:\n", __func__);
77 //x86emu_dump_xregs();
78 //if ((M.x86.R_IP == 0x32c2) && (M.x86.R_SI == 0x1ce2)){
80 //M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F;
85 // BDA offset 49h is current video mode
86 my_wrb(0x449, M
.x86
.R_AL
);
89 else if (M
.x86
.R_AL
== 6)
99 // set cursor position
100 // BH: pagenumber, DX: cursor_pos (DH:row, DL:col)
101 // BDA offset 50h-60h are 8 cursor position words for
102 // eight possible video pages
103 my_wrw(0x450 + (M
.x86
.R_BH
* 2), M
.x86
.R_DX
);
106 //get cursor position
108 // BDA offset 50h-60h are 8 cursor position words for
109 // eight possible video pages
111 M
.x86
.R_CH
= 0; // start scan line ???
112 M
.x86
.R_CL
= 0; // end scan line ???
113 M
.x86
.R_DX
= my_rdw(0x450 + (M
.x86
.R_BH
* 2));
117 // BDA offset 62h is current page number
118 my_wrb(0x462, M
.x86
.R_AL
);
124 //scroll down windows
127 //read character and attribute at position
128 M
.x86
.R_AH
= 0x07; // white-on-black
129 M
.x86
.R_AL
= 0x20; // a space...
132 // write character and attribute
133 //AL: char, BH: page number, BL: attribute, CX: number of times to write
134 //BDA offset 62h is current page number
135 CHECK_DBG(DEBUG_PRINT_INT10
) {
137 if (M
.x86
.R_BH
== my_rdb(0x462)) {
138 for (i
= 0; i
< M
.x86
.R_CX
; i
++)
139 printf("%c", M
.x86
.R_AL
);
145 //AL: char, BH: page number, BL: attribute, CX: number of times to write
146 //BDA offset 62h is current page number
147 CHECK_DBG(DEBUG_PRINT_INT10
) {
149 if (M
.x86
.R_BH
== my_rdb(0x462)) {
150 for (i
= 0; i
< M
.x86
.R_CX
; i
++)
151 printf("%c", M
.x86
.R_AL
);
156 // teletype output: write character and advance cursor...
157 //AL: char, BH: page number, BL: attribute
158 //BDA offset 62h is current page number
159 CHECK_DBG(DEBUG_PRINT_INT10
) {
160 // we ignore the pagenumber on this call...
161 //if (M.x86.R_BH == my_rdb(0x462))
163 printf("%c", M
.x86
.R_AL
);
164 // for debugging, to read all lines
165 //if (M.x86.R_AL == 0xd) // carriage return
172 // BDA offset 49h is current video mode
173 // BDA offset 62h is current page number
174 // BDA offset 4ah is columns on screen
175 M
.x86
.R_AH
= 80; //number of character columns... we hardcode it to 80
176 M
.x86
.R_AL
= my_rdb(0x449);
177 M
.x86
.R_BH
= my_rdb(0x462);
180 printf("%s(): unknown function (%x) for int10 handler.\n",
181 __func__
, M
.x86
.R_AH
);
182 DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n",
183 M
.x86
.R_AX
, M
.x86
.R_BX
, M
.x86
.R_CX
,
190 // this table translates ASCII chars into their XT scan codes:
191 static u8 keycode_table
[256] = {
192 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0 - 7
193 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 8 - 15
194 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 16 - 23
195 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 24 - 31
196 0x39, 0x02, 0x28, 0x04, 0x05, 0x06, 0x08, 0x28, // 32 - 39
197 0x0a, 0x0b, 0x09, 0x2b, 0x33, 0x0d, 0x34, 0x35, // 40 - 47
198 0x0b, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // 48 - 55
199 0x09, 0x0a, 0x27, 0x27, 0x33, 0x2b, 0x34, 0x35, // 56 - 63
200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 64 - 71
201 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 72 - 79
202 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 80 - 87
203 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 88 - 95
204 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 96 - 103
205 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 104 - 111
206 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 112 - 119
207 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 120 - 127
208 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ...
209 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
210 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
211 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
212 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
213 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
214 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
215 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
216 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
217 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
218 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
220 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
221 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
222 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
223 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
229 translate_keycode(u64
* keycode
)
233 if (*keycode
< 256) {
234 scan_code
= keycode_table
[*keycode
];
235 char_code
= (u8
) * keycode
& 0xff;
244 printf("%s(): unknown multibyte keycode: %llx\n",
249 //assemble scan/char code in keycode
250 *keycode
= (u64
) ((((u16
) scan_code
) << 8) | char_code
);
253 // handle int16 (Keyboard BIOS Interrupt)
257 // keyboard buffer is in BIOS Memory Area:
258 // offset 0x1a (WORD) pointer to next char in keybuffer
259 // offset 0x1c (WORD) pointer to next insert slot in keybuffer
260 // offset 0x1e-0x3e: 16 WORD Ring Buffer
261 // since we currently always read the char from the FW buffer,
262 // we misuse the ring buffer, we use it as pointer to a u64 that stores
263 // multi-byte keys (e.g. special keys in VT100 terminal)
264 // and as long as a key is available (not 0) we don't read further keys
265 u64
*keycode
= (u64
*) (M
.mem_base
+ 0x41e);
267 // function number in AH
268 DEBUG_PRINTF_INTR("%s(): Keyboard Interrupt: function: %x.\n",
269 __func__
, M
.x86
.R_AH
);
270 DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n", M
.x86
.R_AX
,
271 M
.x86
.R_BX
, M
.x86
.R_CX
, M
.x86
.R_DX
);
272 switch (M
.x86
.R_AH
) {
276 M
.x86
.R_AX
= (u16
) * keycode
;
280 M
.x86
.R_AH
= 0x61; // scancode for space key
281 M
.x86
.R_AL
= 0x20; // a space
286 // ZF set = no keystroke
287 // read first byte of key code
289 // already read, but not yet taken
291 M
.x86
.R_AX
= (u16
) * keycode
;
293 /* TODO: we need getchar... */
301 // since after an ESC it may take a while to receive the next char,
302 // we send something that is not shown on the screen, and then try to get
304 // TODO: only after ESC?? what about other multibyte keys
305 printf("tt%c%c", 0x08, 0x08); // 0x08 == Backspace
307 /* TODO: we need getchar... */
308 while ((c
= -1 /*getchar()*/) != -1) {
309 *keycode
= (*keycode
<< 8) | c
;
310 DEBUG_PRINTF(" key read: %0llx\n",
313 translate_keycode(keycode
);
314 DEBUG_PRINTF(" translated key: %0llx\n",
321 M
.x86
.R_AX
= (u16
) * keycode
;
323 //M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F;
329 printf("%s(): unknown function (%x) for int16 handler.\n",
330 __func__
, M
.x86
.R_AH
);
331 DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n",
332 M
.x86
.R_AX
, M
.x86
.R_BX
, M
.x86
.R_CX
,
339 // handle int1a (PCI BIOS Interrupt)
343 // function number in AX
345 struct device
*dev
= NULL
;
347 switch (M
.x86
.R_AX
) {
349 // Installation check
350 CLEAR_FLAG(F_CF
); // clear CF
351 M
.x86
.R_EDX
= 0x20494350; // " ICP" endian swapped "PCI "
352 M
.x86
.R_AL
= 0x1; // Config Space Mechanism 1 supported
353 M
.x86
.R_BX
= 0x0210; // PCI Interface Level Version 2.10
354 M
.x86
.R_CL
= 0xff; // number of last PCI Bus in system TODO: check!
358 // device_id in CX, vendor_id in DX
359 // device index in SI (i.e. if multiple devices with same vendor/device id
360 // are connected). We currently only support device index 0
362 DEBUG_PRINTF_INTR("%s(): function: %x: PCI Find Device\n",
363 __func__
, M
.x86
.R_AX
);
365 /* FixME: support SI != 0 */
367 // only allow the device to find itself...
368 if ((M
.x86
.R_CX
== bios_device
.pci_device_id
)
369 && (M
.x86
.R_DX
== bios_device
.pci_vendor_id
)
370 // device index must be 0
371 && (M
.x86
.R_SI
== 0)) {
372 dev
= bios_device
.dev
;
373 M
.x86
.R_BH
= bios_device
.bus
;
374 M
.x86
.R_BL
= bios_device
.devfn
;
375 } else if (CONFIG(YABEL_PCI_ACCESS_OTHER_DEVICES
)) {
376 dev
= dev_find_device(M
.x86
.R_DX
, M
.x86
.R_CX
, 0);
378 M
.x86
.R_BH
= dev
->bus
->secondary
;
379 M
.x86
.R_BL
= dev
->path
.pci
.devfn
;
381 ("%s(): function %x: PCI Find Device --> 0x%04x\n",
382 __func__
, M
.x86
.R_AX
, M
.x86
.R_BX
);
387 ("%s(): function %x: invalid device/vendor/device index! (%04x/%04x/%02x expected: %04x/%04x/00)\n",
388 __func__
, M
.x86
.R_AX
, M
.x86
.R_CX
, M
.x86
.R_DX
,
389 M
.x86
.R_SI
, bios_device
.pci_device_id
,
390 bios_device
.pci_vendor_id
);
393 M
.x86
.R_AH
= 0x86; // return code: device not found
397 M
.x86
.R_AH
= 0x00; // return code: success
399 case 0xb108: //read configuration byte
400 case 0xb109: //read configuration word
401 case 0xb10a: //read configuration dword
405 DEBUG_PRINTF_INTR("%s(): function: %x: PCI Config Read from device: bus: %02x, devfn: %02x, offset: %02x\n",
406 __func__
, M
.x86
.R_AX
, bus
, devfn
, offs
);
408 if ((bus
== bios_device
.bus
) && (devfn
== bios_device
.devfn
)) {
409 dev
= bios_device
.dev
;
410 } else if (CONFIG(YABEL_PCI_ACCESS_OTHER_DEVICES
)) {
411 dev
= pcidev_path_on_bus(bus
, devfn
);
412 DEBUG_PRINTF_INTR("%s(): function: %x: pcidev_path_on_bus() returned: %s\n",
413 __func__
, M
.x86
.R_AX
, dev_path(dev
));
418 ("%s(): Config read access invalid device! bus: %02x (%02x), devfn: %02x (%02x), offs: %02x\n",
419 __func__
, bus
, bios_device
.bus
, devfn
,
420 bios_device
.devfn
, offs
);
422 M
.x86
.R_AH
= 0x87; //return code: bad pci register
427 switch (M
.x86
.R_AX
) {
430 #if CONFIG(PCI_OPTION_ROM_RUN_YABEL)
431 pci_read_config8(dev
, offs
);
433 (u8
) rtas_pci_config_read(bios_device
.puid
, 1,
438 ("%s(): function %x: PCI Config Read @%02x --> 0x%02x\n",
439 __func__
, M
.x86
.R_AX
, offs
,
444 #if CONFIG(PCI_OPTION_ROM_RUN_YABEL)
445 pci_read_config16(dev
, offs
);
447 (u16
) rtas_pci_config_read(bios_device
.puid
, 2,
452 ("%s(): function %x: PCI Config Read @%02x --> 0x%04x\n",
453 __func__
, M
.x86
.R_AX
, offs
,
458 #if CONFIG(PCI_OPTION_ROM_RUN_YABEL)
459 pci_read_config32(dev
, offs
);
461 (u32
) rtas_pci_config_read(bios_device
.puid
, 4,
466 ("%s(): function %x: PCI Config Read @%02x --> 0x%08x\n",
467 __func__
, M
.x86
.R_AX
, offs
,
472 M
.x86
.R_AH
= 0x0; // return code: success
474 case 0xb10b: //write configuration byte
475 case 0xb10c: //write configuration word
476 case 0xb10d: //write configuration dword
481 if ((bus
== bios_device
.bus
) && (devfn
== bios_device
.devfn
)) {
482 dev
= bios_device
.dev
;
487 ("%s(): Config read access invalid! bus: %x (%x), devfn: %x (%x), offs: %x\n",
488 __func__
, bus
, bios_device
.bus
, devfn
,
489 bios_device
.devfn
, offs
);
491 M
.x86
.R_AH
= 0x87; //return code: bad pci register
496 switch (M
.x86
.R_AX
) {
498 #if CONFIG(PCI_OPTION_ROM_RUN_YABEL)
499 pci_write_config8(dev
, offs
, M
.x86
.R_CL
);
501 rtas_pci_config_write(bios_device
.puid
, 1, bus
,
502 devfn
, offs
, M
.x86
.R_CL
);
505 ("%s(): function %x: PCI Config Write @%02x <-- 0x%02x\n",
506 __func__
, M
.x86
.R_AX
, offs
,
510 #if CONFIG(PCI_OPTION_ROM_RUN_YABEL)
511 pci_write_config16(dev
, offs
, M
.x86
.R_CX
);
513 rtas_pci_config_write(bios_device
.puid
, 2, bus
,
514 devfn
, offs
, M
.x86
.R_CX
);
517 ("%s(): function %x: PCI Config Write @%02x <-- 0x%04x\n",
518 __func__
, M
.x86
.R_AX
, offs
,
522 #if CONFIG(PCI_OPTION_ROM_RUN_YABEL)
523 pci_write_config32(dev
, offs
, M
.x86
.R_ECX
);
525 rtas_pci_config_write(bios_device
.puid
, 4, bus
,
526 devfn
, offs
, M
.x86
.R_ECX
);
529 ("%s(): function %x: PCI Config Write @%02x <-- 0x%08x\n",
530 __func__
, M
.x86
.R_AX
, offs
,
535 M
.x86
.R_AH
= 0x0; // return code: success
538 printf("%s(): unknown function (%x) for int1a handler.\n",
539 __func__
, M
.x86
.R_AX
);
540 DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n",
541 M
.x86
.R_AX
, M
.x86
.R_BX
, M
.x86
.R_CX
,
548 // main Interrupt Handler routine, should be registered as x86emu interrupt handler
550 handleInterrupt(int intNum
)
553 #ifndef DEBUG_PRINT_INT10
554 // this printf makes output by int 10 unreadable...
555 // so we only enable it, if int10 print is disabled
556 DEBUG_PRINTF_INTR("%s(%x)\n", __func__
, intNum
);
559 /* check whether this interrupt has a function pointer set in yabel_intFuncArray and run that */
560 if (yabel_intFuncArray
[intNum
]) {
561 DEBUG_PRINTF_INTR("%s(%x) intHandler overridden, calling it...\n", __func__
, intNum
);
562 int_handled
= (*yabel_intFuncArray
[intNum
])();
565 case 0x10: //BIOS video interrupt
566 case 0x42: // INT 10h relocated by EGA/VGA BIOS
567 case 0x6d: // INT 10h relocated by VGA BIOS
568 // get interrupt vector from IDT (4 bytes per Interrupt starting at address 0
569 if ((my_rdl(intNum
* 4) == 0xF000F065) || //F000:F065 is default BIOS interrupt handler address
570 (my_rdl(intNum
* 4) == 0xF4F4F4F4)) //invalid
573 // ignore interrupt...
575 ("%s(%x): invalid interrupt Vector (%08x) found, interrupt ignored...\n",
576 __func__
, intNum
, my_rdl(intNum
* 4));
577 DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n",
578 M
.x86
.R_AX
, M
.x86
.R_BX
, M
.x86
.R_CX
,
587 // Keyboard BIOS Interrupt
592 // PCI BIOS Interrupt
597 /* The self-defined PMM INT number, this is called by
598 * the code in PMM struct, and it is handled by
605 printf("Interrupt %#x (Vector: %x) not implemented\n", intNum
,
607 DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n",
608 M
.x86
.R_AX
, M
.x86
.R_BX
, M
.x86
.R_CX
,
615 // if we did not handle the interrupt, jump to the interrupt vector...
621 // prepare and execute Interrupt 10 (VGA Interrupt)
625 // Initialize stack and data segment
626 M
.x86
.R_SS
= STACK_SEGMENT
;
627 M
.x86
.R_DS
= DATA_SEGMENT
;
628 M
.x86
.R_SP
= STACK_START_OFFSET
;
630 // push a HLT instruction and a pointer to it onto the stack
631 // any return will pop the pointer and jump to the HLT, thus
632 // exiting (more or less) cleanly
633 push_word(0xf4f4); //F4=HLT
634 //push_word(M.x86.R_SS);
635 //push_word(M.x86.R_SP + 2);
637 // setupInt will push the current CS and IP to the stack to return to it,
638 // but we want to halt, so set CS:IP to the HLT instruction we just pushed
640 M
.x86
.R_CS
= M
.x86
.R_SS
;
641 M
.x86
.R_IP
= M
.x86
.R_SP
; // + 4;
643 CHECK_DBG(DEBUG_TRACE_X86EMU
) {
646 CHECK_DBG(DEBUG_JMP
) {
647 M
.x86
.debug
|= DEBUG_TRACEJMP_REGS_F
;
648 M
.x86
.debug
|= DEBUG_TRACEJMP_REGS_F
;
649 M
.x86
.debug
|= DEBUG_TRACECALL_F
;
650 M
.x86
.debug
|= DEBUG_TRACECALL_REGS_F
;
653 DEBUG_PRINTF_INTR("%s(): starting execution of INT10...\n",
656 DEBUG_PRINTF_INTR("%s(): execution finished\n", __func__
);
659 // prepare and execute Interrupt 13 (Disk Interrupt)
663 // Initialize stack and data segment
664 M
.x86
.R_SS
= STACK_SEGMENT
;
665 M
.x86
.R_DS
= DATA_SEGMENT
;
666 M
.x86
.R_SP
= STACK_START_OFFSET
;
668 // push a HLT instruction and a pointer to it onto the stack
669 // any return will pop the pointer and jump to the HLT, thus
670 // exiting (more or less) cleanly
671 push_word(0xf4f4); //F4=HLT
672 //push_word(M.x86.R_SS);
673 //push_word(M.x86.R_SP + 2);
675 // setupInt will push the current CS and IP to the stack to return to it,
676 // but we want to halt, so set CS:IP to the HLT instruction we just pushed
678 M
.x86
.R_CS
= M
.x86
.R_SS
;
679 M
.x86
.R_IP
= M
.x86
.R_SP
;
681 CHECK_DBG(DEBUG_TRACE_X86EMU
) {
684 CHECK_DBG(DEBUG_JMP
) {
685 M
.x86
.debug
|= DEBUG_TRACEJMP_REGS_F
;
686 M
.x86
.debug
|= DEBUG_TRACEJMP_REGS_F
;
687 M
.x86
.debug
|= DEBUG_TRACECALL_F
;
688 M
.x86
.debug
|= DEBUG_TRACECALL_REGS_F
;
692 DEBUG_PRINTF_INTR("%s(): starting execution of INT13...\n",
695 DEBUG_PRINTF_INTR("%s(): execution finished\n", __func__
);