1 // license:BSD-3-Clause
2 // copyright-holders:Ville Linde, Barry Rodewald, Carl, Phil Bennett
9 #include "../../../lib/softfloat/milieu.h"
10 #include "../../../lib/softfloat/softfloat.h"
13 #if !defined(_MSC_VER)
16 //#define DEBUG_MISSING_OPCODE
18 #define I386OP(XX) i386_##XX
19 #define I486OP(XX) i486_##XX
20 #define PENTIUMOP(XX) pentium_##XX
21 #define MMXOP(XX) mmx_##XX
22 #define SSEOP(XX) sse_##XX
24 extern int i386_dasm_one(_TCHAR *buffer, UINT32 pc, const UINT8 *oprom, int mode);
26 enum SREGS { ES, CS, SS, DS, FS, GS };
30 AL = NATIVE_ENDIAN_VALUE_LE_BE(0,3),
31 AH = NATIVE_ENDIAN_VALUE_LE_BE(1,2),
32 CL = NATIVE_ENDIAN_VALUE_LE_BE(4,7),
33 CH = NATIVE_ENDIAN_VALUE_LE_BE(5,6),
34 DL = NATIVE_ENDIAN_VALUE_LE_BE(8,11),
35 DH = NATIVE_ENDIAN_VALUE_LE_BE(9,10),
36 BL = NATIVE_ENDIAN_VALUE_LE_BE(12,15),
37 BH = NATIVE_ENDIAN_VALUE_LE_BE(13,14)
42 AX = NATIVE_ENDIAN_VALUE_LE_BE(0,1),
43 CX = NATIVE_ENDIAN_VALUE_LE_BE(2,3),
44 DX = NATIVE_ENDIAN_VALUE_LE_BE(4,5),
45 BX = NATIVE_ENDIAN_VALUE_LE_BE(6,7),
46 SP = NATIVE_ENDIAN_VALUE_LE_BE(8,9),
47 BP = NATIVE_ENDIAN_VALUE_LE_BE(10,11),
48 SI = NATIVE_ENDIAN_VALUE_LE_BE(12,13),
49 DI = NATIVE_ENDIAN_VALUE_LE_BE(14,15)
52 enum DREGS { EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI };
68 /* 16-bit registers */
79 /* 32-bit registers */
90 /* segment registers */
176 /* mmx registers aliased to x87 ones */
191 SMRAM_IORSRT = 0x100,
216 SMRAM_EFLAGS = 0x1F4,
223 SMRAM_IP5_IOEIP = 0x110,
224 SMRAM_IP5_CR4 = 0x128,
225 SMRAM_IP5_ESLIM = 0x130,
226 SMRAM_IP5_ESBASE = 0x134,
227 SMRAM_IP5_ESACC = 0x138,
228 SMRAM_IP5_CSLIM = 0x13C,
229 SMRAM_IP5_CSBASE = 0x140,
230 SMRAM_IP5_CSACC = 0x144,
231 SMRAM_IP5_SSLIM = 0x148,
232 SMRAM_IP5_SSBASE = 0x14C,
233 SMRAM_IP5_SSACC = 0x150,
234 SMRAM_IP5_DSLIM = 0x154,
235 SMRAM_IP5_DSBASE = 0x158,
236 SMRAM_IP5_DSACC = 0x15C,
237 SMRAM_IP5_FSLIM = 0x160,
238 SMRAM_IP5_FSBASE = 0x164,
239 SMRAM_IP5_FSACC = 0x168,
240 SMRAM_IP5_GSLIM = 0x16C,
241 SMRAM_IP5_GSBASE = 0x170,
242 SMRAM_IP5_GSACC = 0x174,
243 SMRAM_IP5_LDTLIM = 0x178,
244 SMRAM_IP5_LDTBASE = 0x17C,
245 SMRAM_IP5_LDTACC = 0x180,
246 SMRAM_IP5_GDTLIM = 0x184,
247 SMRAM_IP5_GDTBASE = 0x188,
248 SMRAM_IP5_GDTACC = 0x18C,
249 SMRAM_IP5_IDTLIM = 0x190,
250 SMRAM_IP5_IDTBASE = 0x194,
251 SMRAM_IP5_IDTACC = 0x198,
252 SMRAM_IP5_TRLIM = 0x19C,
253 SMRAM_IP5_TRBASE = 0x1A0,
254 SMRAM_IP5_TRACC = 0x1A4,
257 /* Protected mode exceptions */
258 #define FAULT_UD 6 // Invalid Opcode
259 #define FAULT_NM 7 // Coprocessor not available
260 #define FAULT_DF 8 // Double Fault
261 #define FAULT_TS 10 // Invalid TSS
262 #define FAULT_NP 11 // Segment or Gate not present
263 #define FAULT_SS 12 // Stack fault
264 #define FAULT_GP 13 // General Protection Fault
265 #define FAULT_PF 14 // Page Fault
266 #define FAULT_MF 16 // Match (Coprocessor) Fault
268 /* MXCSR Control and Status Register */
269 #define MXCSR_IE (1<<0) // Invalid Operation Flag
270 #define MXCSR_DE (1<<1) // Denormal Flag
271 #define MXCSR_ZE (1<<2) // Divide-by-Zero Flag
272 #define MXCSR_OE (1<<3) // Overflow Flag
273 #define MXCSR_UE (1<<4) // Underflow Flag
274 #define MXCSR_PE (1<<5) // Precision Flag
275 #define MXCSR_DAZ (1<<6) // Denormals Are Zeros
276 #define MXCSR_IM (1<<7) // Invalid Operation Mask
277 #define MXCSR_DM (1<<8) // Denormal Operation Mask
278 #define MXCSR_ZM (1<<9) // Divide-by-Zero Mask
279 #define MXCSR_OM (1<<10) // Overflow Mask
280 #define MXCSR_UM (1<<11) // Underflow Mask
281 #define MXCSR_PM (1<<12) // Precision Mask
282 #define MXCSR_RC (3<<13) // Rounding Control
283 #define MXCSR_FZ (1<<15) // Flush to Zero
290 int d; // Operand size
294 struct I386_CALL_GATE
299 UINT8 ar; // access rights
305 struct I386_SYS_TABLE {
310 struct I386_SEG_DESC {
377 UINT8 CPL; // current privilege level
379 UINT8 performed_intersegment_jump;
380 UINT8 delayed_interrupt_enable;
382 UINT32 cr[5]; // Control registers
383 UINT32 dr[8]; // Debug registers
384 UINT32 tr[8]; // Test registers
386 I386_SYS_TABLE gdtr; // Global Descriptor Table Register
387 I386_SYS_TABLE idtr; // Interrupt Descriptor Table Register
388 I386_SEG_DESC task; // Task register
389 I386_SEG_DESC ldtr; // Local Descriptor Table Register
391 UINT8 ext; // external interrupt
398 int xmm_operand_size;
404 int segment_override;
415 #ifdef I386_PSEUDO_BIOS
418 #ifdef SINGLE_MODE_DMA
424 DEVICE *program_stored;
429 int cpuid_max_input_value_eax;
430 UINT32 cpuid_id0, cpuid_id1, cpuid_id2;
432 UINT32 feature_flags;
446 void (*opcode_table_x87_d8[256])(i386_state *cpustate, UINT8 modrm);
447 void (*opcode_table_x87_d9[256])(i386_state *cpustate, UINT8 modrm);
448 void (*opcode_table_x87_da[256])(i386_state *cpustate, UINT8 modrm);
449 void (*opcode_table_x87_db[256])(i386_state *cpustate, UINT8 modrm);
450 void (*opcode_table_x87_dc[256])(i386_state *cpustate, UINT8 modrm);
451 void (*opcode_table_x87_dd[256])(i386_state *cpustate, UINT8 modrm);
452 void (*opcode_table_x87_de[256])(i386_state *cpustate, UINT8 modrm);
453 void (*opcode_table_x87_df[256])(i386_state *cpustate, UINT8 modrm);
459 void (*opcode_table1_16[256])(i386_state *cpustate);
460 void (*opcode_table1_32[256])(i386_state *cpustate);
461 void (*opcode_table2_16[256])(i386_state *cpustate);
462 void (*opcode_table2_32[256])(i386_state *cpustate);
463 void (*opcode_table338_16[256])(i386_state *cpustate);
464 void (*opcode_table338_32[256])(i386_state *cpustate);
465 void (*opcode_table33a_16[256])(i386_state *cpustate);
466 void (*opcode_table33a_32[256])(i386_state *cpustate);
467 void (*opcode_table366_16[256])(i386_state *cpustate);
468 void (*opcode_table366_32[256])(i386_state *cpustate);
469 void (*opcode_table3f2_16[256])(i386_state *cpustate);
470 void (*opcode_table3f2_32[256])(i386_state *cpustate);
471 void (*opcode_table3f3_16[256])(i386_state *cpustate);
472 void (*opcode_table3f3_32[256])(i386_state *cpustate);
473 void (*opcode_table46638_16[256])(i386_state *cpustate);
474 void (*opcode_table46638_32[256])(i386_state *cpustate);
475 void (*opcode_table4f238_16[256])(i386_state *cpustate);
476 void (*opcode_table4f238_32[256])(i386_state *cpustate);
477 void (*opcode_table4f338_16[256])(i386_state *cpustate);
478 void (*opcode_table4f338_32[256])(i386_state *cpustate);
479 void (*opcode_table4663a_16[256])(i386_state *cpustate);
480 void (*opcode_table4663a_32[256])(i386_state *cpustate);
481 void (*opcode_table4f23a_16[256])(i386_state *cpustate);
482 void (*opcode_table4f23a_32[256])(i386_state *cpustate);
484 bool lock_table[2][256];
486 UINT8 *cycle_table_pm;
487 UINT8 *cycle_table_rm;
497 // devcb_resolved_write_line smiact;
500 // bytes in current opcode, debug only
501 #ifdef DEBUG_MISSING_OPCODE
502 UINT8 opcode_bytes[16];
504 int opcode_bytes_length;
508 extern int i386_parity_table[256];
509 static int i386_limit_check(i386_state *cpustate, int seg, UINT32 offset);
511 #define FAULT_THROW(fault,error) { throw (UINT64)(fault | (UINT64)error << 32); }
512 #define PF_THROW(error) { cpustate->cr[2] = address; FAULT_THROW(FAULT_PF,error); }
514 #define PROTECTED_MODE (cpustate->cr[0] & 0x1)
515 #define STACK_32BIT (cpustate->sreg[SS].d)
516 #define V8086_MODE (cpustate->VM)
517 #define NESTED_TASK (cpustate->NT)
518 #define WP (cpustate->cr[0] & 0x10000)
520 #define SetOF_Add32(r,s,d) (cpustate->OF = (((r) ^ (s)) & ((r) ^ (d)) & 0x80000000) ? 1: 0)
521 #define SetOF_Add16(r,s,d) (cpustate->OF = (((r) ^ (s)) & ((r) ^ (d)) & 0x8000) ? 1 : 0)
522 #define SetOF_Add8(r,s,d) (cpustate->OF = (((r) ^ (s)) & ((r) ^ (d)) & 0x80) ? 1 : 0)
524 #define SetOF_Sub32(r,s,d) (cpustate->OF = (((d) ^ (s)) & ((d) ^ (r)) & 0x80000000) ? 1 : 0)
525 #define SetOF_Sub16(r,s,d) (cpustate->OF = (((d) ^ (s)) & ((d) ^ (r)) & 0x8000) ? 1 : 0)
526 #define SetOF_Sub8(r,s,d) (cpustate->OF = (((d) ^ (s)) & ((d) ^ (r)) & 0x80) ? 1 : 0)
528 #define SetCF8(x) {cpustate->CF = ((x) & 0x100) ? 1 : 0; }
529 #define SetCF16(x) {cpustate->CF = ((x) & 0x10000) ? 1 : 0; }
530 #define SetCF32(x) {cpustate->CF = ((x) & (((UINT64)1) << 32)) ? 1 : 0; }
532 #define SetSF(x) (cpustate->SF = (x))
533 #define SetZF(x) (cpustate->ZF = (x))
534 #define SetAF(x,y,z) (cpustate->AF = (((x) ^ ((y) ^ (z))) & 0x10) ? 1 : 0)
535 #define SetPF(x) (cpustate->PF = i386_parity_table[(x) & 0xFF])
537 #define SetSZPF8(x) {cpustate->ZF = ((UINT8)(x)==0); cpustate->SF = ((x)&0x80) ? 1 : 0; cpustate->PF = i386_parity_table[x & 0xFF]; }
538 #define SetSZPF16(x) {cpustate->ZF = ((UINT16)(x)==0); cpustate->SF = ((x)&0x8000) ? 1 : 0; cpustate->PF = i386_parity_table[x & 0xFF]; }
539 #define SetSZPF32(x) {cpustate->ZF = ((UINT32)(x)==0); cpustate->SF = ((x)&0x80000000) ? 1 : 0; cpustate->PF = i386_parity_table[x & 0xFF]; }
541 #define MMX(n) (*((MMX_REG *)(&cpustate->x87_reg[(n)].low)))
542 #define XMM(n) cpustate->sse_reg[(n)]
544 /***********************************************************************************/
559 extern MODRM_TABLE i386_MODRM_table[256];
561 #define REG8(x) (cpustate->reg.b[x])
562 #define REG16(x) (cpustate->reg.w[x])
563 #define REG32(x) (cpustate->reg.d[x])
565 #define LOAD_REG8(x) (REG8(i386_MODRM_table[x].reg.b))
566 #define LOAD_REG16(x) (REG16(i386_MODRM_table[x].reg.w))
567 #define LOAD_REG32(x) (REG32(i386_MODRM_table[x].reg.d))
568 #define LOAD_RM8(x) (REG8(i386_MODRM_table[x].rm.b))
569 #define LOAD_RM16(x) (REG16(i386_MODRM_table[x].rm.w))
570 #define LOAD_RM32(x) (REG32(i386_MODRM_table[x].rm.d))
572 #define STORE_REG8(x, value) (REG8(i386_MODRM_table[x].reg.b) = value)
573 #define STORE_REG16(x, value) (REG16(i386_MODRM_table[x].reg.w) = value)
574 #define STORE_REG32(x, value) (REG32(i386_MODRM_table[x].reg.d) = value)
575 #define STORE_RM8(x, value) (REG8(i386_MODRM_table[x].rm.b) = value)
576 #define STORE_RM16(x, value) (REG16(i386_MODRM_table[x].rm.w) = value)
577 #define STORE_RM32(x, value) (REG32(i386_MODRM_table[x].rm.d) = value)
579 #define SWITCH_ENDIAN_32(x) (((((x) << 24) & (0xff << 24)) | (((x) << 8) & (0xff << 16)) | (((x) >> 8) & (0xff << 8)) | (((x) >> 24) & (0xff << 0))))
581 /***********************************************************************************/
583 INLINE UINT32 i386_translate(i386_state *cpustate, int segment, UINT32 ip, int rwn)
585 // TODO: segment limit access size, execution permission, handle exception thrown from exception handler
586 if(PROTECTED_MODE && !V8086_MODE && (rwn != -1))
588 if(!(cpustate->sreg[segment].valid))
589 FAULT_THROW((segment==SS)?FAULT_SS:FAULT_GP, 0);
590 if(i386_limit_check(cpustate, segment, ip))
591 FAULT_THROW((segment==SS)?FAULT_SS:FAULT_GP, 0);
592 if((rwn == 0) && ((cpustate->sreg[segment].flags & 8) && !(cpustate->sreg[segment].flags & 2)))
593 FAULT_THROW(FAULT_GP, 0);
594 if((rwn == 1) && ((cpustate->sreg[segment].flags & 8) || !(cpustate->sreg[segment].flags & 2)))
595 FAULT_THROW(FAULT_GP, 0);
597 return cpustate->sreg[segment].base + ip;
600 #define VTLB_FLAG_DIRTY 0x100
602 INLINE vtlb_entry get_permissions(UINT32 pte, int wp)
604 vtlb_entry ret = VTLB_READ_ALLOWED | ((pte & 4) ? VTLB_USER_READ_ALLOWED : 0);
606 ret |= VTLB_WRITE_ALLOWED;
608 ret |= VTLB_WRITE_ALLOWED | ((pte & 4) ? VTLB_USER_WRITE_ALLOWED : 0);
612 static int i386_translate_address(i386_state *cpustate, int intention, offs_t *address, vtlb_entry *entry)
615 UINT32 pdbr = cpustate->cr[3] & 0xfffff000;
616 UINT32 directory = (a >> 22) & 0x3ff;
617 UINT32 table = (a >> 12) & 0x3ff;
620 bool user = (intention & TRANSLATE_USER_MASK) ? true : false;
621 bool write = (intention & TRANSLATE_WRITE) ? true : false;
622 bool debug = (intention & TRANSLATE_DEBUG_MASK) ? true : false;
624 if(!(cpustate->cr[0] & 0x80000000))
631 UINT32 page_dir = cpustate->program->read_data32(pdbr + directory * 4);
634 if ((page_dir & 0x80) && (cpustate->cr[4] & 0x10))
636 a = (page_dir & 0xffc00000) | (a & 0x003fffff);
642 perm = get_permissions(page_dir, WP);
643 if(write && (!(perm & VTLB_WRITE_ALLOWED) || (user && !(perm & VTLB_USER_WRITE_ALLOWED))))
645 else if(user && !(perm & VTLB_USER_READ_ALLOWED))
650 perm |= VTLB_FLAG_DIRTY;
651 if(!(page_dir & 0x40) && write)
652 cpustate->program->write_data32(pdbr + directory * 4, page_dir | 0x60);
653 else if(!(page_dir & 0x20))
654 cpustate->program->write_data32(pdbr + directory * 4, page_dir | 0x20);
660 UINT32 page_entry = cpustate->program->read_data32((page_dir & 0xfffff000) + (table * 4));
661 if(!(page_entry & 1))
665 a = (page_entry & 0xfffff000) | (a & 0xfff);
671 perm = get_permissions(page_entry, WP);
672 if(write && (!(perm & VTLB_WRITE_ALLOWED) || (user && !(perm & VTLB_USER_WRITE_ALLOWED))))
674 else if(user && !(perm & VTLB_USER_READ_ALLOWED))
679 perm |= VTLB_FLAG_DIRTY;
680 if(!(page_dir & 0x20))
681 cpustate->program->write_data32(pdbr + directory * 4, page_dir | 0x20);
682 if(!(page_entry & 0x40) && write)
683 cpustate->program->write_data32((page_dir & 0xfffff000) + (table * 4), page_entry | 0x60);
684 else if(!(page_entry & 0x20))
685 cpustate->program->write_data32((page_dir & 0xfffff000) + (table * 4), page_entry | 0x20);
702 INLINE int translate_address(i386_state *cpustate, int pl, int type, UINT32 *address, UINT32 *error)
704 if(!(cpustate->cr[0] & 0x80000000)) // Some (very few) old OS's won't work with this
707 const vtlb_entry *table = vtlb_table(cpustate->vtlb);
708 UINT32 index = *address >> 12;
709 vtlb_entry entry = table[index];
710 if(type == TRANSLATE_FETCH)
711 type = TRANSLATE_READ;
713 type |= TRANSLATE_USER_MASK;
715 UINT32 test_addr = *address;
718 if(!(entry & VTLB_FLAG_VALID) || ((type & TRANSLATE_WRITE) && !(entry & VTLB_FLAG_DIRTY)))
720 if(!i386_translate_address(cpustate, type, address, &entry))
722 *error = ((type & TRANSLATE_WRITE) ? 2 : 0) | ((cpustate->CPL == 3) ? 4 : 0);
727 vtlb_dynload(cpustate->vtlb, index, *address, entry);
730 if(!(entry & (1 << type)))
732 *error = ((type & TRANSLATE_WRITE) ? 2 : 0) | ((cpustate->CPL == 3) ? 4 : 0) | 1;
735 *address = (entry & 0xfffff000) | (*address & 0xfff);
737 int test_ret = i386_translate_address(cpustate, type | TRANSLATE_DEBUG_MASK, &test_addr, NULL);
738 if(!test_ret || (test_addr != *address))
739 logerror("TLB-PTE mismatch! %06X %06X %06x\n", *address, test_addr, cpustate->pc);
744 INLINE void CHANGE_PC(i386_state *cpustate, UINT32 pc)
746 cpustate->pc = i386_translate(cpustate, CS, pc, -1 );
749 INLINE void NEAR_BRANCH(i386_state *cpustate, INT32 offs)
752 cpustate->eip += offs;
753 cpustate->pc += offs;
756 INLINE UINT8 FETCH(i386_state *cpustate)
759 UINT32 address = cpustate->pc, error;
761 if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_FETCH,&address,&error))
764 value = cpustate->program->read_data8(address & cpustate->a20_mask);
765 #ifdef DEBUG_MISSING_OPCODE
766 cpustate->opcode_bytes[cpustate->opcode_bytes_length] = value;
767 cpustate->opcode_bytes_length = (cpustate->opcode_bytes_length + 1) & 15;
773 INLINE UINT16 FETCH16(i386_state *cpustate)
776 UINT32 address = cpustate->pc, error;
778 if( address & 0x1 ) { /* Unaligned read */
779 value = (FETCH(cpustate) << 0);
780 value |= (FETCH(cpustate) << 8);
782 if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_FETCH,&address,&error))
784 address &= cpustate->a20_mask;
785 value = cpustate->program->read_data16(address);
791 INLINE UINT32 FETCH32(i386_state *cpustate)
794 UINT32 address = cpustate->pc, error;
796 if( cpustate->pc & 0x3 ) { /* Unaligned read */
797 value = (FETCH(cpustate) << 0);
798 value |= (FETCH(cpustate) << 8);
799 value |= (FETCH(cpustate) << 16);
800 value |= (FETCH(cpustate) << 24);
802 if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_FETCH,&address,&error))
805 address &= cpustate->a20_mask;
806 value = cpustate->program->read_data32(address);
813 INLINE UINT8 READ8(i386_state *cpustate,UINT32 ea)
815 UINT32 address = ea, error;
817 if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_READ,&address, &error))
820 address &= cpustate->a20_mask;
821 return cpustate->program->read_data8(address);
823 INLINE UINT16 READ16(i386_state *cpustate,UINT32 ea)
826 UINT32 address = ea, error;
828 if( ea & 0x1 ) { /* Unaligned read */
829 value = (READ8( cpustate, address+0 ) << 0);
830 value |= (READ8( cpustate, address+1 ) << 8);
832 if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_READ,&address,&error))
835 address &= cpustate->a20_mask;
836 value = cpustate->program->read_data16( address );
840 INLINE UINT32 READ32(i386_state *cpustate,UINT32 ea)
843 UINT32 address = ea, error;
845 if( ea & 0x3 ) { /* Unaligned read */
846 value = (READ8( cpustate, address+0 ) << 0);
847 value |= (READ8( cpustate, address+1 ) << 8);
848 value |= (READ8( cpustate, address+2 ) << 16),
849 value |= (READ8( cpustate, address+3 ) << 24);
851 if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_READ,&address,&error))
854 address &= cpustate->a20_mask;
855 value = cpustate->program->read_data32( address );
860 INLINE UINT64 READ64(i386_state *cpustate,UINT32 ea)
863 UINT32 address = ea, error;
865 if( ea & 0x7 ) { /* Unaligned read */
866 value = (((UINT64) READ8( cpustate, address+0 )) << 0);
867 value |= (((UINT64) READ8( cpustate, address+1 )) << 8);
868 value |= (((UINT64) READ8( cpustate, address+2 )) << 16);
869 value |= (((UINT64) READ8( cpustate, address+3 )) << 24);
870 value |= (((UINT64) READ8( cpustate, address+4 )) << 32);
871 value |= (((UINT64) READ8( cpustate, address+5 )) << 40);
872 value |= (((UINT64) READ8( cpustate, address+6 )) << 48);
873 value |= (((UINT64) READ8( cpustate, address+7 )) << 56);
875 if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_READ,&address,&error))
878 address &= cpustate->a20_mask;
879 value = (((UINT64) cpustate->program->read_data32( address+0 )) << 0);
880 value |= (((UINT64) cpustate->program->read_data32( address+4 )) << 32);
884 INLINE UINT8 READ8PL0(i386_state *cpustate,UINT32 ea)
886 UINT32 address = ea, error;
888 if(!translate_address(cpustate,0,TRANSLATE_READ,&address,&error))
891 address &= cpustate->a20_mask;
892 return cpustate->program->read_data8(address);
894 INLINE UINT16 READ16PL0(i386_state *cpustate,UINT32 ea)
897 UINT32 address = ea, error;
899 if( ea & 0x1 ) { /* Unaligned read */
900 value = (READ8PL0( cpustate, address+0 ) << 0);
901 value |= (READ8PL0( cpustate, address+1 ) << 8);
903 if(!translate_address(cpustate,0,TRANSLATE_READ,&address,&error))
906 address &= cpustate->a20_mask;
907 value = cpustate->program->read_data16( address );
912 INLINE UINT32 READ32PL0(i386_state *cpustate,UINT32 ea)
915 UINT32 address = ea, error;
917 if( ea & 0x3 ) { /* Unaligned read */
918 value = (READ8PL0( cpustate, address+0 ) << 0);
919 value |= (READ8PL0( cpustate, address+1 ) << 8);
920 value |= (READ8PL0( cpustate, address+2 ) << 16);
921 value |= (READ8PL0( cpustate, address+3 ) << 24);
923 if(!translate_address(cpustate,0,TRANSLATE_READ,&address,&error))
926 address &= cpustate->a20_mask;
927 value = cpustate->program->read_data32( address );
932 INLINE void WRITE_TEST(i386_state *cpustate,UINT32 ea)
934 UINT32 address = ea, error;
935 if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_WRITE,&address,&error))
939 INLINE void WRITE8(i386_state *cpustate,UINT32 ea, UINT8 value)
941 UINT32 address = ea, error;
943 if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_WRITE,&address,&error))
946 address &= cpustate->a20_mask;
947 cpustate->program->write_data8(address, value);
949 INLINE void WRITE16(i386_state *cpustate,UINT32 ea, UINT16 value)
951 UINT32 address = ea, error;
953 if( ea & 0x1 ) { /* Unaligned write */
954 WRITE8( cpustate, address+0, value & 0xff );
955 WRITE8( cpustate, address+1, (value >> 8) & 0xff );
957 if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_WRITE,&address,&error))
960 address &= cpustate->a20_mask;
961 cpustate->program->write_data16(address, value);
964 INLINE void WRITE32(i386_state *cpustate,UINT32 ea, UINT32 value)
966 UINT32 address = ea, error;
968 if( ea & 0x3 ) { /* Unaligned write */
969 WRITE8( cpustate, address+0, value & 0xff );
970 WRITE8( cpustate, address+1, (value >> 8) & 0xff );
971 WRITE8( cpustate, address+2, (value >> 16) & 0xff );
972 WRITE8( cpustate, address+3, (value >> 24) & 0xff );
974 if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_WRITE,&address,&error))
977 ea &= cpustate->a20_mask;
978 cpustate->program->write_data32(address, value);
982 INLINE void WRITE64(i386_state *cpustate,UINT32 ea, UINT64 value)
984 UINT32 address = ea, error;
986 if( ea & 0x7 ) { /* Unaligned write */
987 WRITE8( cpustate, address+0, value & 0xff );
988 WRITE8( cpustate, address+1, (value >> 8) & 0xff );
989 WRITE8( cpustate, address+2, (value >> 16) & 0xff );
990 WRITE8( cpustate, address+3, (value >> 24) & 0xff );
991 WRITE8( cpustate, address+4, (value >> 32) & 0xff );
992 WRITE8( cpustate, address+5, (value >> 40) & 0xff );
993 WRITE8( cpustate, address+6, (value >> 48) & 0xff );
994 WRITE8( cpustate, address+7, (value >> 56) & 0xff );
996 if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_WRITE,&address,&error))
999 ea &= cpustate->a20_mask;
1000 cpustate->program->write_data32(address+0, value & 0xffffffff);
1001 cpustate->program->write_data32(address+4, (value >> 32) & 0xffffffff);
1005 /***********************************************************************************/
1007 INLINE UINT8 OR8(i386_state *cpustate,UINT8 dst, UINT8 src)
1009 UINT8 res = dst | src;
1010 cpustate->CF = cpustate->OF = 0;
1014 INLINE UINT16 OR16(i386_state *cpustate,UINT16 dst, UINT16 src)
1016 UINT16 res = dst | src;
1017 cpustate->CF = cpustate->OF = 0;
1021 INLINE UINT32 OR32(i386_state *cpustate,UINT32 dst, UINT32 src)
1023 UINT32 res = dst | src;
1024 cpustate->CF = cpustate->OF = 0;
1029 INLINE UINT8 AND8(i386_state *cpustate,UINT8 dst, UINT8 src)
1031 UINT8 res = dst & src;
1032 cpustate->CF = cpustate->OF = 0;
1036 INLINE UINT16 AND16(i386_state *cpustate,UINT16 dst, UINT16 src)
1038 UINT16 res = dst & src;
1039 cpustate->CF = cpustate->OF = 0;
1043 INLINE UINT32 AND32(i386_state *cpustate,UINT32 dst, UINT32 src)
1045 UINT32 res = dst & src;
1046 cpustate->CF = cpustate->OF = 0;
1051 INLINE UINT8 XOR8(i386_state *cpustate,UINT8 dst, UINT8 src)
1053 UINT8 res = dst ^ src;
1054 cpustate->CF = cpustate->OF = 0;
1058 INLINE UINT16 XOR16(i386_state *cpustate,UINT16 dst, UINT16 src)
1060 UINT16 res = dst ^ src;
1061 cpustate->CF = cpustate->OF = 0;
1065 INLINE UINT32 XOR32(i386_state *cpustate,UINT32 dst, UINT32 src)
1067 UINT32 res = dst ^ src;
1068 cpustate->CF = cpustate->OF = 0;
1073 #define SUB8(cpu, dst, src) SBB8(cpu, dst, src, 0)
1074 INLINE UINT8 SBB8(i386_state *cpustate,UINT8 dst, UINT8 src, UINT8 b)
1076 UINT16 res = (UINT16)dst - (UINT16)src - (UINT8)b;
1078 SetOF_Sub8(res,src,dst);
1084 #define SUB16(cpu, dst, src) SBB16(cpu, dst, src, 0)
1085 INLINE UINT16 SBB16(i386_state *cpustate,UINT16 dst, UINT16 src, UINT16 b)
1087 UINT32 res = (UINT32)dst - (UINT32)src - (UINT32)b;
1089 SetOF_Sub16(res,src,dst);
1095 #define SUB32(cpu, dst, src) SBB32(cpu, dst, src, 0)
1096 INLINE UINT32 SBB32(i386_state *cpustate,UINT32 dst, UINT32 src, UINT32 b)
1098 UINT64 res = (UINT64)dst - (UINT64)src - (UINT64) b;
1100 SetOF_Sub32(res,src,dst);
1106 #define ADD8(cpu, dst, src) ADC8(cpu, dst, src, 0)
1107 INLINE UINT8 ADC8(i386_state *cpustate,UINT8 dst, UINT8 src, UINT8 c)
1109 UINT16 res = (UINT16)dst + (UINT16)src + (UINT16)c;
1111 SetOF_Add8(res,src,dst);
1117 #define ADD16(cpu, dst, src) ADC16(cpu, dst, src, 0)
1118 INLINE UINT16 ADC16(i386_state *cpustate,UINT16 dst, UINT16 src, UINT8 c)
1120 UINT32 res = (UINT32)dst + (UINT32)src + (UINT32)c;
1122 SetOF_Add16(res,src,dst);
1128 #define ADD32(cpu, dst, src) ADC32(cpu, dst, src, 0)
1129 INLINE UINT32 ADC32(i386_state *cpustate,UINT32 dst, UINT32 src, UINT32 c)
1131 UINT64 res = (UINT64)dst + (UINT64)src + (UINT64) c;
1133 SetOF_Add32(res,src,dst);
1139 INLINE UINT8 INC8(i386_state *cpustate,UINT8 dst)
1141 UINT16 res = (UINT16)dst + 1;
1142 SetOF_Add8(res,1,dst);
1147 INLINE UINT16 INC16(i386_state *cpustate,UINT16 dst)
1149 UINT32 res = (UINT32)dst + 1;
1150 SetOF_Add16(res,1,dst);
1155 INLINE UINT32 INC32(i386_state *cpustate,UINT32 dst)
1157 UINT64 res = (UINT64)dst + 1;
1158 SetOF_Add32(res,1,dst);
1164 INLINE UINT8 DEC8(i386_state *cpustate,UINT8 dst)
1166 UINT16 res = (UINT16)dst - 1;
1167 SetOF_Sub8(res,1,dst);
1172 INLINE UINT16 DEC16(i386_state *cpustate,UINT16 dst)
1174 UINT32 res = (UINT32)dst - 1;
1175 SetOF_Sub16(res,1,dst);
1180 INLINE UINT32 DEC32(i386_state *cpustate,UINT32 dst)
1182 UINT64 res = (UINT64)dst - 1;
1183 SetOF_Sub32(res,1,dst);
1191 INLINE void PUSH16(i386_state *cpustate,UINT16 value)
1195 new_esp = REG32(ESP) - 2;
1196 ea = i386_translate(cpustate, SS, new_esp, 1);
1197 WRITE16(cpustate, ea, value );
1198 REG32(ESP) = new_esp;
1200 new_esp = (REG16(SP) - 2) & 0xffff;
1201 ea = i386_translate(cpustate, SS, new_esp, 1);
1202 WRITE16(cpustate, ea, value );
1203 REG16(SP) = new_esp;
1206 INLINE void PUSH32(i386_state *cpustate,UINT32 value)
1210 new_esp = REG32(ESP) - 4;
1211 ea = i386_translate(cpustate, SS, new_esp, 1);
1212 WRITE32(cpustate, ea, value );
1213 REG32(ESP) = new_esp;
1215 new_esp = (REG16(SP) - 4) & 0xffff;
1216 ea = i386_translate(cpustate, SS, new_esp, 1);
1217 WRITE32(cpustate, ea, value );
1218 REG16(SP) = new_esp;
1221 INLINE void PUSH8(i386_state *cpustate,UINT8 value)
1223 if( cpustate->operand_size ) {
1224 PUSH32(cpustate,(INT32)(INT8)value);
1226 PUSH16(cpustate,(INT16)(INT8)value);
1230 INLINE UINT8 POP8(i386_state *cpustate)
1235 new_esp = REG32(ESP) + 1;
1236 ea = i386_translate(cpustate, SS, new_esp - 1, 0);
1237 value = READ8(cpustate, ea );
1238 REG32(ESP) = new_esp;
1240 new_esp = REG16(SP) + 1;
1241 ea = i386_translate(cpustate, SS, (new_esp - 1) & 0xffff, 0);
1242 value = READ8(cpustate, ea );
1243 REG16(SP) = new_esp;
1247 INLINE UINT16 POP16(i386_state *cpustate)
1252 new_esp = REG32(ESP) + 2;
1253 ea = i386_translate(cpustate, SS, new_esp - 2, 0);
1254 value = READ16(cpustate, ea );
1255 REG32(ESP) = new_esp;
1257 new_esp = REG16(SP) + 2;
1258 ea = i386_translate(cpustate, SS, (new_esp - 2) & 0xffff, 0);
1259 value = READ16(cpustate, ea );
1260 REG16(SP) = new_esp;
1264 INLINE UINT32 POP32(i386_state *cpustate)
1269 new_esp = REG32(ESP) + 4;
1270 ea = i386_translate(cpustate, SS, new_esp - 4, 0);
1271 value = READ32(cpustate, ea );
1272 REG32(ESP) = new_esp;
1274 new_esp = REG16(SP) + 4;
1275 ea = i386_translate(cpustate, SS, (new_esp - 4) & 0xffff, 0);
1276 value = READ32(cpustate, ea );
1277 REG16(SP) = new_esp;
1282 INLINE void BUMP_SI(i386_state *cpustate,int adjustment)
1284 if ( cpustate->address_size )
1285 REG32(ESI) += ((cpustate->DF) ? -adjustment : +adjustment);
1287 REG16(SI) += ((cpustate->DF) ? -adjustment : +adjustment);
1290 INLINE void BUMP_DI(i386_state *cpustate,int adjustment)
1292 if ( cpustate->address_size )
1293 REG32(EDI) += ((cpustate->DF) ? -adjustment : +adjustment);
1295 REG16(DI) += ((cpustate->DF) ? -adjustment : +adjustment);
1300 /***********************************************************************************
1302 ***********************************************************************************/
1304 INLINE void check_ioperm(i386_state *cpustate, offs_t port, UINT8 mask)
1313 IOPL = cpustate->IOP1 | (cpustate->IOP2 << 1);
1314 if(!V8086_MODE && (cpustate->CPL <= IOPL))
1317 if((cpustate->task.limit < 0x67) || ((cpustate->task.flags & 0xd) != 9))
1318 FAULT_THROW(FAULT_GP,0);
1320 address = cpustate->task.base;
1321 IOPB = READ16PL0(cpustate, address+0x66);
1322 if((IOPB+(port/8)) > cpustate->task.limit)
1323 FAULT_THROW(FAULT_GP,0);
1325 map = READ8PL0(cpustate, address+IOPB+(port/8));
1328 FAULT_THROW(FAULT_GP,0);
1331 INLINE UINT8 READPORT8(i386_state *cpustate, offs_t port)
1333 check_ioperm(cpustate, port, 1);
1334 return cpustate->io->read_io8(port);
1337 INLINE void WRITEPORT8(i386_state *cpustate, offs_t port, UINT8 value)
1339 check_ioperm(cpustate, port, 1);
1340 cpustate->io->write_io8(port, value);
1343 INLINE UINT16 READPORT16(i386_state *cpustate, offs_t port)
1347 UINT16 value = READPORT8(cpustate, port);
1348 value |= (READPORT8(cpustate, port + 1) << 8);
1353 check_ioperm(cpustate, port, 3);
1354 return cpustate->io->read_io16(port);
1358 INLINE void WRITEPORT16(i386_state *cpustate, offs_t port, UINT16 value)
1362 WRITEPORT8(cpustate, port, value & 0xff);
1363 WRITEPORT8(cpustate, port + 1, (value >> 8) & 0xff);
1367 check_ioperm(cpustate, port, 3);
1368 cpustate->io->write_io16(port, value);
1372 INLINE UINT32 READPORT32(i386_state *cpustate, offs_t port)
1376 UINT32 value = READPORT8(cpustate, port);
1377 value |= (READPORT8(cpustate, port + 1) << 8);
1378 value |= (READPORT8(cpustate, port + 2) << 16);
1379 value |= (READPORT8(cpustate, port + 3) << 24);
1384 check_ioperm(cpustate, port, 0xf);
1385 return cpustate->io->read_io32(port);
1389 INLINE void WRITEPORT32(i386_state *cpustate, offs_t port, UINT32 value)
1393 WRITEPORT8(cpustate, port, value & 0xff);
1394 WRITEPORT8(cpustate, port + 1, (value >> 8) & 0xff);
1395 WRITEPORT8(cpustate, port + 2, (value >> 16) & 0xff);
1396 WRITEPORT8(cpustate, port + 3, (value >> 24) & 0xff);
1400 check_ioperm(cpustate, port, 0xf);
1401 cpustate->io->write_io32(port, value);
1405 /***********************************************************************************
1407 ***********************************************************************************/
1409 // Pentium MSR handling
1410 UINT64 pentium_msr_read(i386_state *cpustate, UINT32 offset,UINT8 *valid_msr)
1414 // Machine Check Exception (TODO)
1417 popmessage("RDMSR: Reading P5_MC_ADDR");
1421 popmessage("RDMSR: Reading P5_MC_TYPE");
1423 // Time Stamp Counter
1426 popmessage("RDMSR: Reading TSC");
1427 return cpustate->tsc;
1428 // Event Counters (TODO)
1431 popmessage("RDMSR: Reading CESR");
1435 return cpustate->perfctr[0];
1438 return cpustate->perfctr[1];
1440 if(!(offset & ~0xf)) // 2-f are test registers
1443 logerror("RDMSR: Reading test MSR %x", offset);
1446 logerror("RDMSR: invalid P5 MSR read %08x at %08x\n",offset,cpustate->pc-2);
1453 void pentium_msr_write(i386_state *cpustate, UINT32 offset, UINT64 data, UINT8 *valid_msr)
1457 // Machine Check Exception (TODO)
1459 popmessage("WRMSR: Writing P5_MC_ADDR");
1463 popmessage("WRMSR: Writing P5_MC_TYPE");
1466 // Time Stamp Counter
1468 cpustate->tsc = data;
1469 popmessage("WRMSR: Writing to TSC");
1472 // Event Counters (TODO)
1474 popmessage("WRMSR: Writing to CESR");
1478 cpustate->perfctr[0] = data;
1482 cpustate->perfctr[1] = data;
1486 if(!(offset & ~0xf)) // 2-f are test registers
1489 logerror("WRMSR: Writing test MSR %x", offset);
1492 logerror("WRMSR: invalid MSR write %08x (%08x%08x) at %08x\n",offset,(UINT32)(data >> 32),(UINT32)data,cpustate->pc-2);
1498 // P6 (Pentium Pro, Pentium II, Pentium III) MSR handling
1499 UINT64 p6_msr_read(i386_state *cpustate, UINT32 offset,UINT8 *valid_msr)
1503 // Machine Check Exception (TODO)
1506 popmessage("RDMSR: Reading P5_MC_ADDR");
1510 popmessage("RDMSR: Reading P5_MC_TYPE");
1512 // Time Stamp Counter
1515 popmessage("RDMSR: Reading TSC");
1516 return cpustate->tsc;
1517 // Performance Counters (TODO)
1518 case 0xc1: // PerfCtr0
1520 return cpustate->perfctr[0];
1521 case 0xc2: // PerfCtr1
1523 return cpustate->perfctr[1];
1525 logerror("RDMSR: unimplemented register called %08x at %08x\n",offset,cpustate->pc-2);
1532 void p6_msr_write(i386_state *cpustate, UINT32 offset, UINT64 data, UINT8 *valid_msr)
1536 // Time Stamp Counter
1538 cpustate->tsc = data;
1539 popmessage("WRMSR: Writing to TSC");
1542 // Performance Counters (TODO)
1543 case 0xc1: // PerfCtr0
1544 cpustate->perfctr[0] = data;
1547 case 0xc2: // PerfCtr1
1548 cpustate->perfctr[1] = data;
1552 logerror("WRMSR: unimplemented register called %08x (%08x%08x) at %08x\n",offset,(UINT32)(data >> 32),(UINT32)data,cpustate->pc-2);
1559 UINT64 piv_msr_read(i386_state *cpustate, UINT32 offset,UINT8 *valid_msr)
1564 logerror("RDMSR: unimplemented register called %08x at %08x\n",offset,cpustate->pc-2);
1571 void piv_msr_write(i386_state *cpustate, UINT32 offset, UINT64 data, UINT8 *valid_msr)
1576 logerror("WRMSR: unimplemented register called %08x (%08x%08x) at %08x\n",offset,(UINT32)(data >> 32),(UINT32)data,cpustate->pc-2);
1582 INLINE UINT64 MSR_READ(i386_state *cpustate, UINT32 offset,UINT8 *valid_msr)
1585 UINT8 cpu_type = (cpustate->cpu_version >> 8) & 0x0f;
1592 res = pentium_msr_read(cpustate,offset,valid_msr);
1594 case 6: // Pentium Pro, Pentium II, Pentium III
1595 res = p6_msr_read(cpustate,offset,valid_msr);
1597 case 15: // Pentium 4+
1598 res = piv_msr_read(cpustate,offset,valid_msr);
1608 INLINE void MSR_WRITE(i386_state *cpustate, UINT32 offset, UINT64 data, UINT8 *valid_msr)
1611 UINT8 cpu_type = (cpustate->cpu_version >> 8) & 0x0f;
1616 pentium_msr_write(cpustate,offset,data,valid_msr);
1618 case 6: // Pentium Pro, Pentium II, Pentium III
1619 p6_msr_write(cpustate,offset,data,valid_msr);
1621 case 15: // Pentium 4+
1622 piv_msr_write(cpustate,offset,data,valid_msr);
1627 #endif /* __I386_H__ */