Files
pcem/includes/private/cpu/x86.h
2022-06-23 11:26:13 -07:00

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_ */