/*********************************************************************************
 * C68K.H :
 *
 * C68K include file
 *
 ********************************************************************************/

#ifndef _C68K_H_
#define _C68K_H_

#ifdef __cplusplus
extern "C" {
#endif

// setting
///////////
//

#define NEOCD_HLE

//#define C68K_GEN
#define C68K_BYTE_SWAP_OPT
//#define C68K_BIG_ENDIAN
//#define C68K_DEBUG
#define C68K_TAS_CAN_SET_MEMORY
//#define C68K_CONST_JUMP_TABLE
//#define C68K_AUTOVECTOR_CALLBACK

#define C68K_FETCH_BITS 8   // [4-12]   default = 8

// Compiler dependant defines
///////////////////////////////

#ifndef u8
#define u8	unsigned char
#endif

#ifndef s8
#define s8	char
#endif

#ifndef u16
#define u16	unsigned short
#endif

#ifndef s16
#define s16	short
#endif

#ifndef u32
#define u32	unsigned int
#endif

#ifndef s32
#define s32	int
#endif

// 68K core types definitions
//////////////////////////////

#define C68K_ADR_BITS   24

#define C68K_FETCH_SFT  (C68K_ADR_BITS - C68K_FETCH_BITS)
#define C68K_FETCH_BANK (1 << C68K_FETCH_BITS)
#define C68K_FETCH_MASK (C68K_FETCH_BANK - 1)

#define C68K_SR_C_SFT   8
#define C68K_SR_V_SFT   7
#define C68K_SR_Z_SFT   0
#define C68K_SR_N_SFT   7
#define C68K_SR_X_SFT   8

#define C68K_SR_S_SFT   13

#define C68K_SR_C       (1 << C68K_SR_C_SFT)
#define C68K_SR_V       (1 << C68K_SR_V_SFT)
#define C68K_SR_Z       0
#define C68K_SR_N       (1 << C68K_SR_N_SFT)
#define C68K_SR_X       (1 << C68K_SR_X_SFT)

#define C68K_SR_S       (1 << C68K_SR_S_SFT)

#define C68K_CCR_MASK   0x1F
#define C68K_SR_MASK    (0x2700 | C68K_CCR_MASK)

// exception defines taken from musashi core
#define C68K_RESET_EX                   1
#define C68K_BUS_ERROR_EX               2
#define C68K_ADDRESS_ERROR_EX           3
#define C68K_ILLEGAL_INSTRUCTION_EX     4
#define C68K_ZERO_DIVIDE_EX             5
#define C68K_CHK_EX                     6
#define C68K_TRAPV_EX                   7
#define C68K_PRIVILEGE_VIOLATION_EX     8
#define C68K_TRACE_EX                   9
#define C68K_1010_EX                    10
#define C68K_1111_EX                    11
#define C68K_FORMAT_ERROR_EX            14
#define C68K_UNINITIALIZED_INTERRUPT_EX 15
#define C68K_SPURIOUS_INTERRUPT_EX      24
#define C68K_INTERRUPT_AUTOVECTOR_EX    24
#define C68K_TRAP_BASE_EX               32

#define C68K_INT_ACK_AUTOVECTOR         -1

#define C68K_RUNNING    0x01
#define C68K_HALTED     0x02
#define C68K_WAITING    0x04
#define C68K_DISABLE    0x10
#define C68K_FAULTED    0x40



typedef u32 C68K_READ(u32 adr);
typedef void C68K_WRITE(u32 adr, u32 data);

typedef s32  C68K_INT_CALLBACK(s32 level);
typedef void C68K_RESET_CALLBACK(void);

typedef struct {
    u32 D[8];       // 32 bytes aligned
    u32 A[8];       // 16 bytes aligned

    u32 flag_C;     // 32 bytes aligned
    u32 flag_V;
    u32 flag_notZ;
    u32 flag_N;

    u32 flag_X;     // 16 bytes aligned
    u32 flag_I;
    u32 flag_S;
    
    u32 USP;

    u32 PC;         // 32 bytes aligned
    u32 BasePC;
    u32 Status;
    s32 IRQLine;
    
    s32 CycleToDo;  // 16 bytes aligned
    s32 CycleIO;
    s32 CycleSup;
    u32 dirty1;
    
    C68K_READ *Read_Byte;                   // 32 bytes aligned
    C68K_READ *Read_Word;

    C68K_WRITE *Write_Byte;
    C68K_WRITE *Write_Word;

    C68K_INT_CALLBACK *Interrupt_CallBack;  // 16 bytes aligned
    C68K_RESET_CALLBACK *Reset_CallBack;

	u32 Fetch[C68K_FETCH_BANK];             // 32 bytes aligned
} c68k_struc;


// 68K core var declaration
////////////////////////////

extern  c68k_struc C68K;


// 68K core function declaration
/////////////////////////////////

void    C68k_Init(c68k_struc *cpu, C68K_INT_CALLBACK *int_cb);

s32     C68k_Reset(c68k_struc *cpu);

// if <  0 --> error (cpu state returned)
// if >= 0 --> number of extras cycles done
s32	    C68k_Exec(c68k_struc *cpu, s32 cycle);

void    C68k_Set_IRQ(c68k_struc *cpu, s32 level);

s32     C68k_Get_CycleToDo(c68k_struc *cpu);
s32     C68k_Get_CycleRemaining(c68k_struc *cpu);
s32     C68k_Get_CycleDone(c68k_struc *cpu);
void    C68k_Release_Cycle(c68k_struc *cpu);
void    C68k_Add_Cycle(c68k_struc *cpu, s32 cycle);

void    C68k_Set_Fetch(c68k_struc *cpu, u32 low_adr, u32 high_adr, u32 fetch_adr);

void    C68k_Set_ReadB(c68k_struc *cpu, C68K_READ *Func);
void    C68k_Set_ReadW(c68k_struc *cpu, C68K_READ *Func);
void    C68k_Set_WriteB(c68k_struc *cpu, C68K_WRITE *Func);
void    C68k_Set_WriteW(c68k_struc *cpu, C68K_WRITE *Func);

u32     C68k_Get_DReg(c68k_struc *cpu, u32 num);
u32     C68k_Get_AReg(c68k_struc *cpu, u32 num);
u32     C68k_Get_PC(c68k_struc *cpu);
u32     C68k_Get_SR(c68k_struc *cpu);
u32     C68k_Get_USP(c68k_struc *cpu);
u32     C68k_Get_MSP(c68k_struc *cpu);

void    C68k_Set_DReg(c68k_struc *cpu, u32 num, u32 val);
void    C68k_Set_AReg(c68k_struc *cpu, u32 num, u32 val);
void    C68k_Set_PC(c68k_struc *cpu, u32 val);
void    C68k_Set_SR(c68k_struc *cpu, u32 val);
void    C68k_Set_USP(c68k_struc *cpu, u32 val);
void    C68k_Set_MSP(c68k_struc *cpu, u32 val);

#ifdef __cplusplus
}
#endif

#endif  // _C68K_H_

