#ifndef ARM_CPU
#define ARM_CPU
#include "types.h"
#include "bits.h"
#include "MMU.h"
#ifdef __cplusplus
extern "C" {
#endif
#define ARMCPU_ARM7 1
#define ARMCPU_ARM9 0
#define CODE(i) (((i)>>25)&0X7)
#define OPCODE(i) (((i)>>21)&0xF)
#define SIGNEBIT(i) BIT_N(i,20)
#define INSTRUCTION_INDEX(i) ((((i)>>16)&0xFF0)|(((i)>>4)&0xF))
#define ROR(i, j) ((((u32)(i))>>(j)) | (((u32)(i))<<(32-(j))))
#define UNSIGNED_OVERFLOW(a,b,c) ((BIT31(a)&BIT31(b)) | \
((BIT31(a)|BIT31(b))&BIT31(~c)))
#define UNSIGNED_UNDERFLOW(a,b,c) ((BIT31(~a)&BIT31(b)) | \
((BIT31(~a)|BIT31(b))&BIT31(c)))
#define SIGNED_OVERFLOW(a,b,c) ((BIT31(a)&BIT31(b)&BIT31(~c))|\
(BIT31(~a)&BIT31(~(b))&BIT31(c)))
#define SIGNED_UNDERFLOW(a,b,c) ((BIT31(a)&BIT31(~(b))&BIT31(~c))|\
(BIT31(~a)&BIT31(b)&BIT31(c)))
#define EQ 0x0
#define NE 0x1
#define CS 0x2
#define CC 0x3
#define MI 0x4
#define PL 0x5
#define VS 0x6
#define VC 0x7
#define HI 0x8
#define LS 0x9
#define GE 0xA
#define LT 0xB
#define GT 0xC
#define LE 0xD
#define AL 0xE
extern const unsigned char arm_cond_table[16*16];
#define TEST_COND(cond, inst, CPSR) ((arm_cond_table[((CPSR.val >> 24) & 0xf0)+(cond)] >> (inst)) & 1)
enum Mode
{
USR = 0x10,
FIQ = 0x11,
IRQ = 0x12,
SVC = 0x13,
ABT = 0x17,
UND = 0x1B,
SYS = 0x1F
};
#ifdef WORDS_BIGENDIAN
typedef union
{
struct
{
u32 N : 1,
Z : 1,
C : 1,
V : 1,
Q : 1,
RAZ : 19,
I : 1,
F : 1,
T : 1,
mode : 5;
} bits;
u32 val;
} Status_Reg;
#else
typedef union
{
struct
{
u32 mode : 5,
T : 1,
F : 1,
I : 1,
RAZ : 19,
Q : 1,
V : 1,
C : 1,
Z : 1,
N : 1;
} bits;
u32 val;
} Status_Reg;
#endif
struct armcpu_ctrl_iface {
void (*stall)( void *instance);
void (*unstall)( void *instance);
u32 (*read_reg)( void *instance, u32 reg_num);
void (*set_reg)( void *instance, u32 reg_num, u32 value);
void (*install_post_ex_fn)( void *instance,
void (*fn)( void *, u32 adr, int thumb),
void *fn_data);
void (*remove_post_ex_fn)( void *instance);
void *data;
};
typedef void* armcp_t;
typedef struct armcpu_t
{
u32 proc_ID;
u32 instruction; u32 instruct_adr; u32 next_instruction;
u32 R[16]; Status_Reg CPSR; Status_Reg SPSR;
u32 R13_usr, R14_usr;
u32 R13_svc, R14_svc;
u32 R13_abt, R14_abt;
u32 R13_und, R14_und;
u32 R13_irq, R14_irq;
u32 R8_fiq, R9_fiq, R10_fiq, R11_fiq, R12_fiq, R13_fiq, R14_fiq;
Status_Reg SPSR_svc, SPSR_abt, SPSR_und, SPSR_irq, SPSR_fiq;
armcp_t *coproc[16];
u32 intVector;
u8 LDTBit; BOOL waitIRQ;
BOOL wIRQ;
BOOL wirq;
u32 (* *swi_tab)(struct armcpu_t * cpu);
#ifdef GDB_STUB
int irq_flag;
void (*post_ex_fn)( void *, u32 adr, int thumb);
void *post_ex_fn_data;
int stalled;
struct armcpu_memory_iface *mem_if;
struct armcpu_ctrl_iface ctrl_iface;
#endif
} armcpu_t;
#ifdef GDB_STUB
int armcpu_new( armcpu_t *armcpu, u32 id, struct armcpu_memory_iface *mem_if,
struct armcpu_ctrl_iface **ctrl_iface_ret);
#else
int armcpu_new( armcpu_t *armcpu, u32 id);
#endif
void armcpu_init(armcpu_t *armcpu, u32 adr);
u32 armcpu_switchMode(armcpu_t *armcpu, u8 mode);
static u32 armcpu_prefetch(armcpu_t *armcpu);
u32 armcpu_exec(armcpu_t *armcpu);
BOOL armcpu_irqExeption(armcpu_t *armcpu);
BOOL
armcpu_flagIrq( armcpu_t *armcpu);
extern armcpu_t NDS_ARM7;
extern armcpu_t NDS_ARM9;
static INLINE void NDS_makeARM9Int(u32 num)
{
MMU.reg_IF[0] |= (1<<num);
if ((MMU.reg_IE[0] & (1 << num)) && MMU.reg_IME[0])
{
NDS_ARM9.wIRQ = TRUE;
NDS_ARM9.waitIRQ = FALSE;
}
}
static INLINE void NDS_makeARM7Int(u32 num)
{
MMU.reg_IF[1] |= (1<<num);
if ((MMU.reg_IE[1] & (1 << num)) && MMU.reg_IME[1])
{
NDS_ARM7.wIRQ = TRUE;
NDS_ARM7.waitIRQ = FALSE;
}
}
static INLINE void NDS_makeInt(u8 proc_ID,u32 num)
{
switch (proc_ID)
{
case 0:
NDS_makeARM9Int(num) ;
break ;
case 1:
NDS_makeARM7Int(num) ;
break ;
}
}
#ifdef __cplusplus
}
#endif
#endif