3 #include "../debugger.h"
5 #include "./i386_real.h"
6 #define FAULT(fault,error) {cpustate->ext = 1; i386_trap_with_error(fault,0,0,error); return;}
7 #define FAULT_EXP(fault,error) {cpustate->ext = 1; i386_trap_with_error(fault,0,trap_level+1,error); return;}
9 #include "../libcpu_softfloat/softfloat.h"
12 int I386_OPS::cpu_translate_i386(void *cpudevice, address_spacenum space, int intention, offs_t *address)
14 i386_state *cpu_state = (i386_state *)cpudevice;
16 if(space == AS_PROGRAM)
17 ret = i386_translate_address(intention, address, NULL);
18 *address &= cpu_state->a20_mask;
22 i386_state *I386_OPS::i386_common_init(int tlbsize)
25 static const int regs8[8] = {AL,CL,DL,BL,AH,CH,DH,BH};
26 static const int regs16[8] = {AX,CX,DX,BX,SP,BP,SI,DI};
27 static const int regs32[8] = {EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI};
28 cpustate = &__cpustate;
29 //cpustate = (i386_state *)malloc(sizeof(i386_state));
30 //x86_cycle_table = _x86_cycle_table_real;
32 assert((sizeof(XMM_REG)/sizeof(double)) == 2);
36 for( i=0; i < 256; i++ ) {
38 for( j=0; j < 8; j++ ) {
42 i386_parity_table[i] = ~(c & 0x1) & 0x1;
45 for( i=0; i < 256; i++ ) {
46 i386_MODRM_table[i].reg.b = regs8[(i >> 3) & 0x7];
47 i386_MODRM_table[i].reg.w = regs16[(i >> 3) & 0x7];
48 i386_MODRM_table[i].reg.d = regs32[(i >> 3) & 0x7];
50 i386_MODRM_table[i].rm.b = regs8[i & 0x7];
51 i386_MODRM_table[i].rm.w = regs16[i & 0x7];
52 i386_MODRM_table[i].rm.d = regs32[i & 0x7];
55 cpustate->vtlb = vtlb_alloc((void *)cpustate, AS_PROGRAM, 0, tlbsize);
56 cpustate->smi = false;
57 cpustate->lock = false;
59 // i386_interface *intf = (i386_interface *) device->static_config();
62 // cpustate->smiact.resolve(intf->smiact, *device);
64 // memset(&cpustate->smiact, 0, sizeof(cpustate->smiact));
67 cpustate->program = d_mem;
69 cpustate->pic = d_pic;
70 #ifdef I386_PSEUDO_BIOS
71 cpustate->bios = d_bios;
73 #ifdef SINGLE_MODE_DMA
74 cpustate->dma = d_dma;
79 void I386_OPS::i386_decode_opcode()
81 cpustate->opcode = FETCH();
83 if(cpustate->lock && !cpustate->lock_table[0][cpustate->opcode])
84 return I386OP(invalid)();
86 if( cpustate->operand_size )
87 (this->*cpustate->opcode_table1_32[cpustate->opcode])();
89 (this->*cpustate->opcode_table1_16[cpustate->opcode])();
93 int I386_OPS::cpu_execute_i386(int cycles)
95 CHANGE_PC(cpustate->eip);
97 if (cpustate->halted || cpustate->busreq)
99 #ifdef SINGLE_MODE_DMA
100 if(cpustate->dma != NULL) {
101 cpustate->dma->do_dma();
105 int passed_cycles = max(1, cpustate->extra_cycles);
106 // this is main cpu, cpustate->cycles is not used
107 /*cpustate->cycles = */cpustate->extra_cycles = 0;
108 cpustate->tsc += passed_cycles;
109 return passed_cycles;
111 cpustate->cycles += cycles;
112 cpustate->base_cycles = cpustate->cycles;
114 /* adjust for any interrupts that came in */
115 cpustate->cycles -= cpustate->extra_cycles;
116 cpustate->extra_cycles = 0;
118 /* if busreq is raised, spin cpu while remained clock */
119 if (cpustate->cycles > 0) {
120 cpustate->cycles = 0;
122 int passed_cycles = cpustate->base_cycles - cpustate->cycles;
123 cpustate->tsc += passed_cycles;
124 return passed_cycles;
129 cpustate->cycles = 1;
131 cpustate->cycles += cycles;
133 cpustate->base_cycles = cpustate->cycles;
135 /* adjust for any interrupts that came in */
136 cpustate->cycles -= cpustate->extra_cycles;
137 cpustate->extra_cycles = 0;
139 while( cpustate->cycles > 0 && !cpustate->busreq )
142 bool now_debugging = cpustate->debugger->now_debugging;
144 cpustate->debugger->check_break_points(cpustate->pc);
145 if(cpustate->debugger->now_suspended) {
146 cpustate->emu->mute_sound();
147 cpustate->debugger->now_waiting = true;
148 while(cpustate->debugger->now_debugging && cpustate->debugger->now_suspended) {
149 cpustate->emu->sleep(10);
151 cpustate->debugger->now_waiting = false;
153 if(cpustate->debugger->now_debugging) {
154 cpustate->program = cpustate->io = cpustate->debugger;
156 now_debugging = false;
158 i386_check_irq_line();
159 cpustate->operand_size = cpustate->sreg[CS].d;
160 cpustate->xmm_operand_size = 0;
161 cpustate->address_size = cpustate->sreg[CS].d;
162 cpustate->operand_prefix = 0;
163 cpustate->address_prefix = 0;
166 int old_tf = cpustate->TF;
168 cpustate->segment_prefix = 0;
169 cpustate->prev_eip = cpustate->eip;
170 cpustate->prev_pc = cpustate->pc;
172 if(cpustate->delayed_interrupt_enable != 0)
175 cpustate->delayed_interrupt_enable = 0;
177 #ifdef DEBUG_MISSING_OPCODE
178 cpustate->opcode_bytes_length = 0;
179 cpustate->opcode_pc = cpustate->pc;
183 i386_decode_opcode();
184 if(cpustate->TF && old_tf)
186 cpustate->prev_eip = cpustate->eip;
190 if(cpustate->lock && (cpustate->opcode != 0xf0))
191 cpustate->lock = false;
196 i386_trap_with_error(e&0xffffffff,0,0,e>>32);
198 #ifdef SINGLE_MODE_DMA
199 if(cpustate->dma != NULL) {
200 cpustate->dma->do_dma();
203 /* adjust for any interrupts that came in */
204 cpustate->cycles -= cpustate->extra_cycles;
205 cpustate->extra_cycles = 0;
208 if(!cpustate->debugger->now_going) {
209 cpustate->debugger->now_suspended = true;
211 cpustate->program = cpustate->program_stored;
212 cpustate->io = cpustate->io_stored;
216 i386_check_irq_line();
218 cpustate->operand_size = cpustate->sreg[CS].d;
219 cpustate->xmm_operand_size = 0;
220 cpustate->address_size = cpustate->sreg[CS].d;
221 cpustate->operand_prefix = 0;
222 cpustate->address_prefix = 0;
225 int old_tf = cpustate->TF;
227 cpustate->segment_prefix = 0;
228 cpustate->prev_eip = cpustate->eip;
229 cpustate->prev_pc = cpustate->pc;
231 if(cpustate->delayed_interrupt_enable != 0)
234 cpustate->delayed_interrupt_enable = 0;
236 #ifdef DEBUG_MISSING_OPCODE
237 cpustate->opcode_bytes_length = 0;
238 cpustate->opcode_pc = cpustate->pc;
242 i386_decode_opcode();
243 if(cpustate->TF && old_tf)
245 cpustate->prev_eip = cpustate->eip;
249 if(cpustate->lock && (cpustate->opcode != 0xf0))
250 cpustate->lock = false;
255 i386_trap_with_error(e&0xffffffff,0,0,e>>32);
257 #ifdef SINGLE_MODE_DMA
258 if(cpustate->dma != NULL) {
259 cpustate->dma->do_dma();
262 /* adjust for any interrupts that came in */
263 cpustate->cycles -= cpustate->extra_cycles;
264 cpustate->extra_cycles = 0;
270 /* if busreq is raised, spin cpu while remained clock */
271 if (cpustate->cycles > 0 && cpustate->busreq) {
272 cpustate->cycles = 0;
274 int passed_cycles = cpustate->base_cycles - cpustate->cycles;
275 cpustate->tsc += passed_cycles;
276 return passed_cycles;
279 void I386_OPS::i386_trap(int irq, int irq_gate, int trap_level)
281 /* I386 Interrupts/Traps/Faults:
283 * 0x00 Divide by zero
284 * 0x01 Debug exception
288 * 0x05 Array bounds check
289 * 0x06 Illegal Opcode
290 * 0x07 FPU not available
292 * 0x09 Coprocessor segment overrun
293 * 0x0a Invalid task state
294 * 0x0b Segment not present
295 * 0x0c Stack exception
296 * 0x0d General Protection Fault
299 * 0x10 Coprocessor error
302 UINT32 offset, oldflags = get_flags();
304 int entry = irq * (PROTECTED_MODE ? 8 : 4);
306 cpustate->lock = false;
308 if( !(PROTECTED_MODE) )
311 PUSH16(oldflags & 0xffff );
312 PUSH16(cpustate->sreg[CS].selector );
313 if(irq == 3 || irq == 4 || irq == 9 || irq_gate == 1)
314 PUSH16(cpustate->eip );
316 PUSH16(cpustate->prev_eip );
318 cpustate->sreg[CS].selector = READ16(cpustate->idtr.base + entry + 2 );
319 cpustate->eip = READ16(cpustate->idtr.base + entry );
329 UINT8 CPL = cpustate->CPL, DPL = 0; //, RPL = 0;
332 v1 = READ32PL0(cpustate->idtr.base + entry );
333 v2 = READ32PL0(cpustate->idtr.base + entry + 4 );
334 offset = (v2 & 0xffff0000) | (v1 & 0xffff);
335 segment = (v1 >> 16) & 0xffff;
336 type = (v2>>8) & 0x1F;
337 flags = (v2>>8) & 0xf0ff;
341 logerror("IRQ: Double fault.\n");
342 FAULT_EXP(FAULT_DF,0);
346 logerror("IRQ: Triple fault. CPU reset.\n");
347 #if defined(HAS_I386)
349 #elif defined(HAS_I486)
351 #elif defined(HAS_PENTIUM)
353 #elif defined(HAS_MEDIAGX)
355 #elif defined(HAS_PENTIUM_PRO)
356 cpu_reset_pentium_pro();
357 #elif defined(HAS_PENTIUM_MMX)
358 cpu_reset_pentium_mmx();
359 #elif defined(HAS_PENTIUM2)
360 cpu_reset_pentium2();
361 #elif defined(HAS_PENTIUM3)
362 cpu_reset_pentium3();
363 #elif defined(HAS_PENTIUM4)
364 cpu_reset_pentium4();
367 cpustate->shutdown = 1;
371 /* segment privilege checks */
372 if(entry >= cpustate->idtr.limit)
374 logerror("IRQ (%08x): Vector %02xh is past IDT limit.\n",cpustate->pc,entry);
375 FAULT_EXP(FAULT_GP,entry+2)
377 /* segment must be interrupt gate, trap gate, or task gate */
378 if(type != 0x05 && type != 0x06 && type != 0x07 && type != 0x0e && type != 0x0f)
380 logerror("IRQ#%02x (%08x): Vector segment %04x is not an interrupt, trap or task gate.\n",irq,cpustate->pc,segment);
381 FAULT_EXP(FAULT_GP,entry+2)
384 if(cpustate->ext == 0) // if software interrupt (caused by INT/INTO/INT3)
386 if(((flags >> 5) & 0x03) < CPL)
388 logerror("IRQ (%08x): Software IRQ - gate DPL is less than CPL.\n",cpustate->pc);
389 FAULT_EXP(FAULT_GP,entry+2)
393 if((!cpustate->IOP1 || !cpustate->IOP2) && (cpustate->opcode != 0xcc))
395 logerror("IRQ (%08x): Is in Virtual 8086 mode and IOPL != 3.\n",cpustate->pc);
402 if((flags & 0x0080) == 0)
404 logerror("IRQ: Vector segment is not present.\n");
405 FAULT_EXP(FAULT_NP,entry+2)
411 memset(&desc, 0, sizeof(desc));
412 desc.selector = segment;
413 i386_load_protected_mode_segment(&desc,NULL);
416 logerror("IRQ: Task gate: TSS is not in the GDT.\n");
417 FAULT_EXP(FAULT_TS,segment & ~0x03);
421 if(segment > cpustate->gdtr.limit)
423 logerror("IRQ: Task gate: TSS is past GDT limit.\n");
424 FAULT_EXP(FAULT_TS,segment & ~0x03);
427 if((desc.flags & 0x000f) != 0x09 && (desc.flags & 0x000f) != 0x01)
429 logerror("IRQ: Task gate: TSS is not an available TSS.\n");
430 FAULT_EXP(FAULT_TS,segment & ~0x03);
432 if((desc.flags & 0x0080) == 0)
434 logerror("IRQ: Task gate: TSS is not present.\n");
435 FAULT_EXP(FAULT_NP,segment & ~0x03);
437 if(!(irq == 3 || irq == 4 || irq == 9 || irq_gate == 1))
438 cpustate->eip = cpustate->prev_eip;
439 if(desc.flags & 0x08)
440 i386_task_switch(desc.selector,1);
442 i286_task_switch(desc.selector,1);
447 /* Interrupt or Trap gate */
448 memset(&desc, 0, sizeof(desc));
449 desc.selector = segment;
450 i386_load_protected_mode_segment(&desc,NULL);
451 CPL = cpustate->CPL; // current privilege level
452 DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level
453 // RPL = segment & 0x03; // requested privilege level
455 if((segment & ~0x03) == 0)
457 logerror("IRQ: Gate segment is null.\n");
458 FAULT_EXP(FAULT_GP,cpustate->ext)
462 if((segment & ~0x07) > cpustate->ldtr.limit)
464 logerror("IRQ: Gate segment is past LDT limit.\n");
465 FAULT_EXP(FAULT_GP,(segment & 0x03)+cpustate->ext)
470 if((segment & ~0x07) > cpustate->gdtr.limit)
472 logerror("IRQ: Gate segment is past GDT limit.\n");
473 FAULT_EXP(FAULT_GP,(segment & 0x03)+cpustate->ext)
476 if((desc.flags & 0x0018) != 0x18)
478 logerror("IRQ: Gate descriptor is not a code segment.\n");
479 FAULT_EXP(FAULT_GP,(segment & 0x03)+cpustate->ext)
481 if((desc.flags & 0x0080) == 0)
483 logerror("IRQ: Gate segment is not present.\n");
484 FAULT_EXP(FAULT_NP,(segment & 0x03)+cpustate->ext)
486 if((desc.flags & 0x0004) == 0 && (DPL < CPL))
488 /* IRQ to inner privilege */
490 UINT32 newESP,oldSS,oldESP;
492 if(V8086_MODE && DPL)
494 logerror("IRQ: Gate to CPL>0 from VM86 mode.\n");
495 FAULT_EXP(FAULT_GP,segment & ~0x03);
497 /* Check new stack segment in TSS */
498 memset(&stack, 0, sizeof(stack));
499 stack.selector = i386_get_stack_segment(DPL);
500 i386_load_protected_mode_segment(&stack,NULL);
501 oldSS = cpustate->sreg[SS].selector;
506 if((stack.selector & ~0x03) == 0)
508 logerror("IRQ: New stack selector is null.\n");
509 FAULT_EXP(FAULT_GP,cpustate->ext)
511 if(stack.selector & 0x04)
513 if((stack.selector & ~0x07) > cpustate->ldtr.base)
515 logerror("IRQ: New stack selector is past LDT limit.\n");
516 FAULT_EXP(FAULT_TS,(stack.selector & ~0x03)+cpustate->ext)
521 if((stack.selector & ~0x07) > cpustate->gdtr.base)
523 logerror("IRQ: New stack selector is past GDT limit.\n");
524 FAULT_EXP(FAULT_TS,(stack.selector & ~0x03)+cpustate->ext)
527 if((stack.selector & 0x03) != DPL)
529 logerror("IRQ: New stack selector RPL is not equal to code segment DPL.\n");
530 FAULT_EXP(FAULT_TS,(stack.selector & ~0x03)+cpustate->ext)
532 if(((stack.flags >> 5) & 0x03) != DPL)
534 logerror("IRQ: New stack segment DPL is not equal to code segment DPL.\n");
535 FAULT_EXP(FAULT_TS,(stack.selector & ~0x03)+cpustate->ext)
537 if(((stack.flags & 0x0018) != 0x10) && (stack.flags & 0x0002) != 0)
539 logerror("IRQ: New stack segment is not a writable data segment.\n");
540 FAULT_EXP(FAULT_TS,(stack.selector & ~0x03)+cpustate->ext) // #TS(stack selector + EXT)
542 if((stack.flags & 0x0080) == 0)
544 logerror("IRQ: New stack segment is not present.\n");
545 FAULT_EXP(FAULT_SS,(stack.selector & ~0x03)+cpustate->ext) // #TS(stack selector + EXT)
547 newESP = i386_get_stack_ptr(DPL);
548 if(type & 0x08) // 32-bit gate
550 if(((newESP < (V8086_MODE?36:20)) && !(stack.flags & 0x4)) || ((~stack.limit < (~(newESP - 1) + (V8086_MODE?36:20))) && (stack.flags & 0x4)))
552 logerror("IRQ: New stack has no space for return addresses.\n");
553 FAULT_EXP(FAULT_SS,0)
559 if(((newESP < (V8086_MODE?18:10)) && !(stack.flags & 0x4)) || ((~stack.limit < (~(newESP - 1) + (V8086_MODE?18:10))) && (stack.flags & 0x4)))
561 logerror("IRQ: New stack has no space for return addresses.\n");
562 FAULT_EXP(FAULT_SS,0)
565 if(offset > desc.limit)
567 logerror("IRQ: New EIP is past code segment limit.\n");
568 FAULT_EXP(FAULT_GP,0)
570 /* change CPL before accessing the stack */
572 /* check for page fault at new stack TODO: check if stack frame crosses page boundary */
573 WRITE_TEST(stack.base+newESP-1);
574 /* Load new stack segment descriptor */
575 cpustate->sreg[SS].selector = stack.selector;
576 i386_load_protected_mode_segment(&cpustate->sreg[SS],NULL);
577 i386_set_descriptor_accessed(stack.selector);
581 //logerror("IRQ (%08x): Interrupt during V8086 task\n",cpustate->pc);
584 PUSH32(cpustate->sreg[GS].selector & 0xffff);
585 PUSH32(cpustate->sreg[FS].selector & 0xffff);
586 PUSH32(cpustate->sreg[DS].selector & 0xffff);
587 PUSH32(cpustate->sreg[ES].selector & 0xffff);
591 PUSH16(cpustate->sreg[GS].selector);
592 PUSH16(cpustate->sreg[FS].selector);
593 PUSH16(cpustate->sreg[DS].selector);
594 PUSH16(cpustate->sreg[ES].selector);
596 cpustate->sreg[GS].selector = 0;
597 cpustate->sreg[FS].selector = 0;
598 cpustate->sreg[DS].selector = 0;
599 cpustate->sreg[ES].selector = 0;
601 i386_load_segment_descriptor(GS);
602 i386_load_segment_descriptor(FS);
603 i386_load_segment_descriptor(DS);
604 i386_load_segment_descriptor(ES);
623 if((desc.flags & 0x0004) || (DPL == CPL))
625 /* IRQ to same privilege */
626 if(V8086_MODE && !cpustate->ext)
628 logerror("IRQ: Gate to same privilege from VM86 mode.\n");
629 FAULT_EXP(FAULT_GP,segment & ~0x03);
631 if(type == 0x0e || type == 0x0f) // 32-bit gate
635 // TODO: Add check for error code (2 extra bytes)
636 if(REG32(ESP) < stack_limit)
638 logerror("IRQ: Stack has no space left (needs %i bytes).\n",stack_limit);
639 FAULT_EXP(FAULT_SS,0)
641 if(offset > desc.limit)
643 logerror("IRQ: Gate segment offset is past segment limit.\n");
644 FAULT_EXP(FAULT_GP,0)
650 logerror("IRQ: Gate descriptor is non-conforming, and DPL does not equal CPL.\n");
651 FAULT_EXP(FAULT_GP,segment)
655 UINT32 tempSP = REG32(ESP);
658 // this is ugly but the alternative is worse
659 if(type != 0x0e && type != 0x0f) // if not 386 interrupt or trap gate
661 PUSH16(oldflags & 0xffff );
662 PUSH16(cpustate->sreg[CS].selector );
663 if(irq == 3 || irq == 4 || irq == 9 || irq_gate == 1)
664 PUSH16(cpustate->eip );
666 PUSH16(cpustate->prev_eip );
670 PUSH32(oldflags & 0x00ffffff );
671 PUSH32(cpustate->sreg[CS].selector );
672 if(irq == 3 || irq == 4 || irq == 9 || irq_gate == 1)
673 PUSH32(cpustate->eip );
675 PUSH32(cpustate->prev_eip );
684 segment = (segment & ~0x03) | cpustate->CPL;
685 cpustate->sreg[CS].selector = segment;
686 cpustate->eip = offset;
688 if(type == 0x0e || type == 0x06)
694 i386_load_segment_descriptor(CS);
695 CHANGE_PC(cpustate->eip);
699 void I386_OPS::i386_trap_with_error(int irq, int irq_gate, int trap_level, UINT32 error)
701 i386_trap(irq,irq_gate,trap_level);
702 if(irq == 8 || irq == 10 || irq == 11 || irq == 12 || irq == 13 || irq == 14)
704 // for these exceptions, an error code is pushed onto the stack by the processor.
705 // no error code is pushed for software interrupts, either.
708 UINT32 entry = irq * 8;
710 v2 = READ32PL0(cpustate->idtr.base + entry + 4 );
711 type = (v2>>8) & 0x1F;
714 v2 = READ32PL0(cpustate->idtr.base + entry);
715 v2 = READ32PL0(cpustate->gdtr.base + ((v2 >> 16) & 0xfff8) + 4);
716 type = (v2>>8) & 0x1F;
728 bool I386_OPS::write_debug_reg(const _TCHAR *reg, uint32_t data)
730 #if defined(USE_DEBUGGER)
731 if(_tcsicmp(reg, _T("IP")) == 0) {
732 cpustate->eip = data & 0xffff;
733 CHANGE_PC(cpustate->eip);
734 } else if(_tcsicmp(reg, _T("AX")) == 0) {
736 } else if(_tcsicmp(reg, _T("BX")) == 0) {
738 } else if(_tcsicmp(reg, _T("CX")) == 0) {
740 } else if(_tcsicmp(reg, _T("DX")) == 0) {
742 } else if(_tcsicmp(reg, _T("SP")) == 0) {
744 } else if(_tcsicmp(reg, _T("BP")) == 0) {
746 } else if(_tcsicmp(reg, _T("SI")) == 0) {
748 } else if(_tcsicmp(reg, _T("DI")) == 0) {
750 } else if(_tcsicmp(reg, _T("AL")) == 0) {
752 } else if(_tcsicmp(reg, _T("AH")) == 0) {
754 } else if(_tcsicmp(reg, _T("BL")) == 0) {
756 } else if(_tcsicmp(reg, _T("BH")) == 0) {
758 } else if(_tcsicmp(reg, _T("CL")) == 0) {
760 } else if(_tcsicmp(reg, _T("CH")) == 0) {
762 } else if(_tcsicmp(reg, _T("DL")) == 0) {
764 } else if(_tcsicmp(reg, _T("DH")) == 0) {
773 uint32_t I386_OPS::read_debug_reg(const _TCHAR *reg)
775 #if defined(USE_DEBUGGER)
776 if(_tcsicmp(reg, _T("IP")) == 0) {
777 return cpustate->eip;
778 } else if(_tcsicmp(reg, _T("AX")) == 0) {
780 } else if(_tcsicmp(reg, _T("BX")) == 0) {
782 } else if(_tcsicmp(reg, _T("CX")) == 0) {
784 } else if(_tcsicmp(reg, _T("DX")) == 0) {
786 } else if(_tcsicmp(reg, _T("SP")) == 0) {
788 } else if(_tcsicmp(reg, _T("BP")) == 0) {
790 } else if(_tcsicmp(reg, _T("SI")) == 0) {
792 } else if(_tcsicmp(reg, _T("DI")) == 0) {
794 } else if(_tcsicmp(reg, _T("AL")) == 0) {
796 } else if(_tcsicmp(reg, _T("AH")) == 0) {
798 } else if(_tcsicmp(reg, _T("BL")) == 0) {
800 } else if(_tcsicmp(reg, _T("BH")) == 0) {
802 } else if(_tcsicmp(reg, _T("CL")) == 0) {
804 } else if(_tcsicmp(reg, _T("CH")) == 0) {
806 } else if(_tcsicmp(reg, _T("DL")) == 0) {
808 } else if(_tcsicmp(reg, _T("DH")) == 0) {
815 int I386_OPS::debug_dasm(uint32_t pc, _TCHAR *buffer, size_t buffer_len)
817 #if defined(USE_DEBUGGER)
818 //UINT64 eip = cpustate->eip;
819 UINT64 eip = pc - cpustate->sreg[CS].base;
821 for(int i = 0; i < 16; i++) {
823 ops[i] = d_mem->read_data8w(pc + i, &wait);
827 if(cpustate->operand_size) {
828 return CPU_DISASSEMBLE_CALL(x86_32) & DASMFLAG_LENGTHMASK;
830 return CPU_DISASSEMBLE_CALL(x86_16) & DASMFLAG_LENGTHMASK;