mirror of
https://github.com/sarah-walker-pcem/pcem.git
synced 2025-07-23 03:33:02 +02:00
330 lines
9.1 KiB
C
330 lines
9.1 KiB
C
#ifndef _X86_H_
|
|
#define _X86_H_
|
|
|
|
#define EAX cpu_state.regs[0].l
|
|
#define ECX cpu_state.regs[1].l
|
|
#define EDX cpu_state.regs[2].l
|
|
#define EBX cpu_state.regs[3].l
|
|
#define ESP cpu_state.regs[4].l
|
|
#define EBP cpu_state.regs[5].l
|
|
#define ESI cpu_state.regs[6].l
|
|
#define EDI cpu_state.regs[7].l
|
|
#define AX cpu_state.regs[0].w
|
|
#define CX cpu_state.regs[1].w
|
|
#define DX cpu_state.regs[2].w
|
|
#define BX cpu_state.regs[3].w
|
|
#define SP cpu_state.regs[4].w
|
|
#define BP cpu_state.regs[5].w
|
|
#define SI cpu_state.regs[6].w
|
|
#define DI cpu_state.regs[7].w
|
|
#define AL cpu_state.regs[0].b.l
|
|
#define AH cpu_state.regs[0].b.h
|
|
#define CL cpu_state.regs[1].b.l
|
|
#define CH cpu_state.regs[1].b.h
|
|
#define DL cpu_state.regs[2].b.l
|
|
#define DH cpu_state.regs[2].b.h
|
|
#define BL cpu_state.regs[3].b.l
|
|
#define BH cpu_state.regs[3].b.h
|
|
|
|
typedef union {
|
|
uint32_t l;
|
|
uint16_t w;
|
|
struct {
|
|
uint8_t l, h;
|
|
} b;
|
|
} x86reg;
|
|
|
|
typedef struct {
|
|
uint32_t base;
|
|
uint32_t limit, limit_raw;
|
|
uint8_t access, access2;
|
|
uint16_t seg;
|
|
uint32_t limit_low, limit_high;
|
|
int checked; /*Non-zero if selector is known to be valid*/
|
|
} x86seg;
|
|
|
|
typedef union MMX_REG {
|
|
uint64_t q;
|
|
int64_t sq;
|
|
uint32_t l[2];
|
|
int32_t sl[2];
|
|
uint16_t w[4];
|
|
int16_t sw[4];
|
|
uint8_t b[8];
|
|
int8_t sb[8];
|
|
float f[2];
|
|
} MMX_REG;
|
|
|
|
struct {
|
|
x86reg regs[8];
|
|
|
|
uint8_t tag[8];
|
|
|
|
x86seg *ea_seg;
|
|
uint32_t eaaddr;
|
|
|
|
int flags_op;
|
|
uint32_t flags_res;
|
|
uint32_t flags_op1, flags_op2;
|
|
|
|
uint32_t pc;
|
|
uint32_t oldpc;
|
|
uint32_t op32;
|
|
|
|
int TOP;
|
|
|
|
union {
|
|
struct {
|
|
int8_t rm, mod, reg;
|
|
} rm_mod_reg;
|
|
uint32_t rm_mod_reg_data;
|
|
} rm_data;
|
|
|
|
int8_t ssegs;
|
|
int8_t ismmx;
|
|
int8_t abrt;
|
|
int8_t smi_pending;
|
|
|
|
int _cycles;
|
|
int cpu_recomp_ins;
|
|
|
|
uint16_t npxs, npxc;
|
|
|
|
double ST[8];
|
|
|
|
uint16_t MM_w4[8];
|
|
|
|
MMX_REG MM[8];
|
|
|
|
uint32_t old_fp_control, new_fp_control;
|
|
#if defined i386 || defined __i386 || defined __i386__ || defined _X86_
|
|
uint16_t old_fp_control2, new_fp_control2;
|
|
#endif
|
|
#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined __amd64__
|
|
uint32_t trunc_fp_control;
|
|
#endif
|
|
x86seg seg_cs, seg_ds, seg_es, seg_ss, seg_fs, seg_gs;
|
|
|
|
union {
|
|
uint32_t l;
|
|
uint16_t w;
|
|
} CR0;
|
|
|
|
uint16_t flags, eflags;
|
|
|
|
uint32_t smbase;
|
|
} cpu_state;
|
|
|
|
#define cpu_state_offset(MEMBER) ((uintptr_t)&cpu_state.MEMBER - (uintptr_t)&cpu_state - 128)
|
|
|
|
#define cycles cpu_state._cycles
|
|
extern int cycles_main;
|
|
|
|
#define cr0 cpu_state.CR0.l
|
|
#define msw cpu_state.CR0.w
|
|
|
|
/*Segments -
|
|
_cs,_ds,_es,_ss are the segment structures
|
|
CS,DS,ES,SS is the 16-bit data
|
|
cs,ds,es,ss are defines to the bases*/
|
|
#define CS cpu_state.seg_cs.seg
|
|
#define DS cpu_state.seg_ds.seg
|
|
#define ES cpu_state.seg_es.seg
|
|
#define SS cpu_state.seg_ss.seg
|
|
#define FS cpu_state.seg_fs.seg
|
|
#define GS cpu_state.seg_gs.seg
|
|
#define cs cpu_state.seg_cs.base
|
|
#define ds cpu_state.seg_ds.base
|
|
#define es cpu_state.seg_es.base
|
|
#define ss cpu_state.seg_ss.base
|
|
//#define seg_fs _fs.base
|
|
#define gs cpu_state.seg_gs.base
|
|
|
|
#define CPL ((cpu_state.seg_cs.access >> 5) & 3)
|
|
|
|
#define C_FLAG 0x0001
|
|
#define P_FLAG 0x0004
|
|
#define A_FLAG 0x0010
|
|
#define Z_FLAG 0x0040
|
|
#define N_FLAG 0x0080
|
|
#define T_FLAG 0x0100
|
|
#define I_FLAG 0x0200
|
|
#define D_FLAG 0x0400
|
|
#define V_FLAG 0x0800
|
|
#define NT_FLAG 0x4000
|
|
#define VM_FLAG 0x0002 /*In EFLAGS*/
|
|
#define VIF_FLAG 0x0008 /*In EFLAGS*/
|
|
#define VIP_FLAG 0x0010 /*In EFLAGS*/
|
|
|
|
#define WP_FLAG 0x10000 /*In CR0*/
|
|
|
|
#define CR4_VME (1 << 0)
|
|
#define CR4_PVI (1 << 1)
|
|
#define CR4_PSE (1 << 4)
|
|
|
|
#define IOPL ((cpu_state.flags >> 12) & 3)
|
|
|
|
#define IOPLp ((!(msw & 1)) || (CPL <= IOPL))
|
|
|
|
extern x86seg gdt, ldt, idt, tr;
|
|
|
|
extern uint32_t cr2, cr3, cr4;
|
|
extern uint32_t dr[8];
|
|
|
|
extern uint16_t sysenter_cs;
|
|
extern uint32_t sysenter_eip, sysenter_esp;
|
|
|
|
extern uint16_t cpu_cur_status;
|
|
|
|
/*The flags below must match in both cpu_cur_status and block->status for a block
|
|
to be valid*/
|
|
#define CPU_STATUS_USE32 (1 << 0)
|
|
#define CPU_STATUS_STACK32 (1 << 1)
|
|
#define CPU_STATUS_PMODE (1 << 2)
|
|
#define CPU_STATUS_V86 (1 << 3)
|
|
#define CPU_STATUS_SMM (1 << 4)
|
|
#define CPU_STATUS_FLAGS 0xff
|
|
|
|
/*If the flags below are set in cpu_cur_status, they must be set in block->status.
|
|
Otherwise they are ignored*/
|
|
#define CPU_STATUS_NOTFLATDS (1 << 8)
|
|
#define CPU_STATUS_NOTFLATSS (1 << 9)
|
|
#define CPU_STATUS_MASK 0xff00
|
|
|
|
extern uint32_t rmdat;
|
|
#define fetchdat rmdat
|
|
|
|
extern uint32_t easeg;
|
|
extern uint32_t *eal_r, *eal_w;
|
|
|
|
extern int oldcpl;
|
|
extern uint32_t oldss;
|
|
|
|
extern int nmi_enable;
|
|
|
|
extern int trap;
|
|
|
|
extern uint32_t use32;
|
|
extern int stack32;
|
|
|
|
extern uint8_t znptable8[256];
|
|
extern uint16_t *mod1add[2][8];
|
|
extern uint32_t *mod1seg[8];
|
|
|
|
extern int cgate16, cgate32;
|
|
extern int cpl_override;
|
|
|
|
extern int x86_was_reset;
|
|
|
|
extern int insc;
|
|
extern int fpucount;
|
|
extern float mips, flops;
|
|
|
|
#define setznp168 setznp16
|
|
|
|
#define getr8(r) ((r & 4) ? cpu_state.regs[r & 3].b.h : cpu_state.regs[r & 3].b.l)
|
|
#define getr16(r) cpu_state.regs[r].w
|
|
#define getr32(r) cpu_state.regs[r].l
|
|
|
|
#define setr8(r, v) \
|
|
if (r & 4) \
|
|
cpu_state.regs[r & 3].b.h = v; \
|
|
else \
|
|
cpu_state.regs[r & 3].b.l = v;
|
|
#define setr16(r, v) cpu_state.regs[r].w = v
|
|
#define setr32(r, v) cpu_state.regs[r].l = v
|
|
|
|
#define fetchea() \
|
|
{ \
|
|
rmdat = readmemb(cs + pc); \
|
|
pc++; \
|
|
reg = (rmdat >> 3) & 7; \
|
|
mod = (rmdat >> 6) & 3; \
|
|
rm = rmdat & 7; \
|
|
if (mod != 3) \
|
|
fetcheal(); \
|
|
}
|
|
|
|
extern int optype;
|
|
#define JMP 1
|
|
#define CALL 2
|
|
#define IRET 3
|
|
#define OPTYPE_INT 4
|
|
|
|
enum { ABRT_NONE = 0, ABRT_GEN, ABRT_TS = 0xA, ABRT_NP = 0xB, ABRT_SS = 0xC, ABRT_GPF = 0xD, ABRT_PF = 0xE };
|
|
|
|
#define ABRT_MASK 0x7f
|
|
/*An 'expected' exception is one that would be expected to occur on every execution
|
|
of this code path; eg a GPF due to being in v86 mode. An 'unexpected' exception is
|
|
one that would be unlikely to occur on the next exception, eg a page fault may be
|
|
fixed up by the exception handler and the next execution would not hit it.
|
|
|
|
This distinction is used by the dynarec; a block that hits an 'expected' exception
|
|
would be compiled, a block that hits an 'unexpected' exception would be rejected so
|
|
that we don't end up with an unnecessarily short block*/
|
|
#define ABRT_EXPECTED 0x80
|
|
extern uint32_t abrt_error;
|
|
|
|
void x86_doabrt(int x86_abrt);
|
|
|
|
extern int codegen_flat_ds;
|
|
extern int codegen_flat_ss;
|
|
|
|
extern uint32_t pccache;
|
|
extern uint8_t *pccache2;
|
|
|
|
void x86illegal();
|
|
|
|
void x86seg_reset();
|
|
void x86gpf(char *s, uint16_t error);
|
|
void x86gpf_expected(char *s, uint16_t error);
|
|
|
|
void resetx86();
|
|
void softresetx86();
|
|
void refreshread();
|
|
void dumpregs();
|
|
|
|
void execx86(int cycs);
|
|
void exec386(int cycs);
|
|
void exec386_dynarec(int cycs);
|
|
|
|
void pmodeint(int num, int soft);
|
|
int loadseg(uint16_t seg, x86seg *s);
|
|
void loadcs(uint16_t seg);
|
|
void loadcscall(uint16_t seg, uint32_t old_pc);
|
|
void loadcsjmp(uint16_t seg, uint32_t old_pc);
|
|
void pmoderetf(int is32, uint16_t off);
|
|
void pmodeiret(int is32);
|
|
|
|
void x86_int(int num);
|
|
void x86_int_sw(int num);
|
|
int x86_int_sw_rm(int num);
|
|
|
|
void sysenter(void);
|
|
void sysexit(void);
|
|
|
|
int divl(uint32_t val);
|
|
int idivl(int32_t val);
|
|
|
|
extern int cpu_end_block_after_ins;
|
|
|
|
void x86_smi_trigger(void);
|
|
void x86_smi_enter(void);
|
|
void x86_smi_leave(void);
|
|
|
|
void cyrix_load_seg_descriptor(uint32_t addr, x86seg *seg);
|
|
void cyrix_write_seg_descriptor(uint32_t addr, x86seg *seg);
|
|
|
|
#define SMHR_VALID (1 << 0)
|
|
#define SMHR_ADDR_MASK (0xfffffffc)
|
|
|
|
struct {
|
|
struct {
|
|
uint32_t base;
|
|
uint64_t size;
|
|
} arr[8];
|
|
uint32_t smhr;
|
|
} cyrix;
|
|
|
|
#endif /* _X86_H_ */
|