diff options
Diffstat (limited to 'trunk/src/emu/cpu/se3208/se3208.c')
-rw-r--r-- | trunk/src/emu/cpu/se3208/se3208.c | 1941 |
1 files changed, 1941 insertions, 0 deletions
diff --git a/trunk/src/emu/cpu/se3208/se3208.c b/trunk/src/emu/cpu/se3208/se3208.c new file mode 100644 index 00000000000..6add121d646 --- /dev/null +++ b/trunk/src/emu/cpu/se3208/se3208.c @@ -0,0 +1,1941 @@ +#include "emu.h" +#include "debugger.h" +#include "se3208.h" + +/* + SE3208 CPU Emulator by ElSemi + + For information about this CPU: + www.adc.co.kr + +*/ + +typedef struct _se3208_state_t se3208_state_t; +struct _se3208_state_t +{ + //GPR + UINT32 R[8]; + //SPR + UINT32 PC; + UINT32 SR; + UINT32 SP; + UINT32 ER; + UINT32 PPC; + + device_irq_callback irq_callback; + legacy_cpu_device *device; + address_space *program; + direct_read_data *direct; + UINT8 IRQ; + UINT8 NMI; + + int icount; +}; + +#define FLAG_C 0x0080 +#define FLAG_V 0x0010 +#define FLAG_S 0x0020 +#define FLAG_Z 0x0040 + +#define FLAG_M 0x0200 +#define FLAG_E 0x0800 +#define FLAG_AUT 0x1000 +#define FLAG_ENI 0x2000 +#define FLAG_NMI 0x4000 + +#define CLRFLAG(f) se3208_state->SR&=~(f); +#define SETFLAG(f) se3208_state->SR|=(f); +#define TESTFLAG(f) (se3208_state->SR&(f)) + +#define EXTRACT(val,sbit,ebit) (((val)>>sbit)&((1<<((ebit-sbit)+1))-1)) +#define SEX8(val) ((val&0x80)?(val|0xFFFFFF00):(val&0xFF)) +#define SEX16(val) ((val&0x8000)?(val|0xFFFF0000):(val&0xFFFF)) +#define ZEX8(val) ((val)&0xFF) +#define ZEX16(val) ((val)&0xFFFF) +#define SEX(bits,val) ((val)&(1<<(bits-1))?((val)|(~((1<<bits)-1))):(val&((1<<bits)-1))) + +//Precompute the instruction decoding in a big table +typedef void (*_OP)(se3208_state_t *se3208_state, UINT16 Opcode); +#define INST(a) static void a(se3208_state_t *se3208_state, UINT16 Opcode) +static _OP *OpTable=NULL; + +INLINE se3208_state_t *get_safe_token(device_t *device) +{ + assert(device != NULL); + assert(device->type() == SE3208); + return (se3208_state_t *)downcast<legacy_cpu_device *>(device)->token(); +} + +INLINE UINT32 read_dword_unaligned(address_space *space, UINT32 address) +{ + if (address & 3) + return space->read_byte(address) | space->read_byte(address+1)<<8 | space->read_byte(address+2)<<16 | space->read_byte(address+3)<<24; + else + return space->read_dword(address); +} + +INLINE UINT16 read_word_unaligned(address_space *space, UINT32 address) +{ + if (address & 1) + return space->read_byte(address) | space->read_byte(address+1)<<8; + else + return space->read_word(address); +} + +INLINE void write_dword_unaligned(address_space *space, UINT32 address, UINT32 data) +{ + if (address & 3) + { + space->write_byte(address, data & 0xff); + space->write_byte(address+1, (data>>8)&0xff); + space->write_byte(address+2, (data>>16)&0xff); + space->write_byte(address+3, (data>>24)&0xff); + } + else + { + space->write_dword(address, data); + } +} + +INLINE void write_word_unaligned(address_space *space, UINT32 address, UINT16 data) +{ + if (address & 1) + { + space->write_byte(address, data & 0xff); + space->write_byte(address+1, (data>>8)&0xff); + } + else + { + space->write_word(address, data); + } +} + + +INLINE UINT8 SE3208_Read8(se3208_state_t *se3208_state, UINT32 addr) +{ + return se3208_state->program->read_byte(addr); +} + +INLINE UINT16 SE3208_Read16(se3208_state_t *se3208_state, UINT32 addr) +{ + return read_word_unaligned(se3208_state->program,addr); +} + +INLINE UINT32 SE3208_Read32(se3208_state_t *se3208_state, UINT32 addr) +{ + return read_dword_unaligned(se3208_state->program,addr); +} + +INLINE void SE3208_Write8(se3208_state_t *se3208_state, UINT32 addr,UINT8 val) +{ + se3208_state->program->write_byte(addr,val); +} + +INLINE void SE3208_Write16(se3208_state_t *se3208_state, UINT32 addr,UINT16 val) +{ + write_word_unaligned(se3208_state->program,addr,val); +} + +INLINE void SE3208_Write32(se3208_state_t *se3208_state, UINT32 addr,UINT32 val) +{ + write_dword_unaligned(se3208_state->program,addr,val); +} + + + +INLINE UINT32 AddWithFlags(se3208_state_t *se3208_state, UINT32 a,UINT32 b) +{ + UINT32 r=a+b; + CLRFLAG(FLAG_Z|FLAG_C|FLAG_V|FLAG_S); + if(!r) + SETFLAG(FLAG_Z); + if(r&0x80000000) + SETFLAG(FLAG_S); + if(((((a&b)|(~r&(a|b)))>>31))&1) + SETFLAG(FLAG_C); + if(((((a^r)&(b^r))>>31))&1) + SETFLAG(FLAG_V); + return r; +} + +INLINE UINT32 SubWithFlags(se3208_state_t *se3208_state, UINT32 a,UINT32 b) //a-b +{ + UINT32 r=a-b; + CLRFLAG(FLAG_Z|FLAG_C|FLAG_V|FLAG_S); + if(!r) + SETFLAG(FLAG_Z); + if(r&0x80000000) + SETFLAG(FLAG_S); + if((((b&r)|(~a&(b|r)))>>31)&1) + SETFLAG(FLAG_C); + if((((b^a)&(r^a))>>31)&1) + SETFLAG(FLAG_V); + return r; +} + +INLINE UINT32 AdcWithFlags(se3208_state_t *se3208_state,UINT32 a,UINT32 b) +{ + UINT32 C=(se3208_state->SR&FLAG_C)?1:0; + UINT32 r=a+b+C; + CLRFLAG(FLAG_Z|FLAG_C|FLAG_V|FLAG_S); + if(!r) + SETFLAG(FLAG_Z); + if(r&0x80000000) + SETFLAG(FLAG_S); + if(((((a&b)|(~r&(a|b)))>>31))&1) + SETFLAG(FLAG_C); + if(((((a^r)&(b^r))>>31))&1) + SETFLAG(FLAG_V); + return r; + +} + +INLINE UINT32 SbcWithFlags(se3208_state_t *se3208_state,UINT32 a,UINT32 b) +{ + UINT32 C=(se3208_state->SR&FLAG_C)?1:0; + UINT32 r=a-b-C; + CLRFLAG(FLAG_Z|FLAG_C|FLAG_V|FLAG_S); + if(!r) + SETFLAG(FLAG_Z); + if(r&0x80000000) + SETFLAG(FLAG_S); + if((((b&r)|(~a&(b|r)))>>31)&1) + SETFLAG(FLAG_C); + if((((b^a)&(r^a))>>31)&1) + SETFLAG(FLAG_V); + return r; +} + +INLINE UINT32 MulWithFlags(se3208_state_t *se3208_state,UINT32 a,UINT32 b) +{ + INT64 r=(INT64) a*(INT64) b; + CLRFLAG(FLAG_V); + if(r>>32) + SETFLAG(FLAG_V); + return (UINT32) (r&0xffffffff); +} + +INLINE UINT32 NegWithFlags(se3208_state_t *se3208_state,UINT32 a) +{ + return SubWithFlags(se3208_state,0,a); +} + +INLINE UINT32 AsrWithFlags(se3208_state_t *se3208_state,UINT32 Val, UINT8 By) +{ + signed int v=(signed int) Val; + v>>=By; + CLRFLAG(FLAG_Z|FLAG_C|FLAG_V|FLAG_S); + if(!v) + SETFLAG(FLAG_Z); + if(v&0x80000000) + SETFLAG(FLAG_S); + if(Val&(1<<(By-1))) + SETFLAG(FLAG_C); + return (UINT32) v; +} + +INLINE UINT32 LsrWithFlags(se3208_state_t *se3208_state,UINT32 Val, UINT8 By) +{ + UINT32 v=Val; + v>>=By; + CLRFLAG(FLAG_Z|FLAG_C|FLAG_V|FLAG_S); + if(!v) + SETFLAG(FLAG_Z); + if(v&0x80000000) + SETFLAG(FLAG_S); + if(Val&(1<<(By-1))) + SETFLAG(FLAG_C); + return v; +} + +INLINE UINT32 AslWithFlags(se3208_state_t *se3208_state,UINT32 Val, UINT8 By) +{ + UINT32 v=Val; + v<<=By; + CLRFLAG(FLAG_Z|FLAG_C|FLAG_V|FLAG_S); + if(!v) + SETFLAG(FLAG_Z); + if(v&0x80000000) + SETFLAG(FLAG_S); + if(Val&(1<<(32-By))) + SETFLAG(FLAG_C); + return v; +} + + +INST(INVALIDOP) +{ + //assert(false); +} + +INST(LDB) +{ + UINT32 Offset=EXTRACT(Opcode,0,4); + UINT32 Index=EXTRACT(Opcode,5,7); + UINT32 SrcDst=EXTRACT(Opcode,8,10); + UINT32 Val; + + if(Index) + Index=se3208_state->R[Index]; + else + Index=0; + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf); + + Val=SE3208_Read8(se3208_state, Index+Offset); + se3208_state->R[SrcDst]=SEX8(Val); + + CLRFLAG(FLAG_E); +} + +INST(STB) +{ + UINT32 Offset=EXTRACT(Opcode,0,4); + UINT32 Index=EXTRACT(Opcode,5,7); + UINT32 SrcDst=EXTRACT(Opcode,8,10); + + if(Index) + Index=se3208_state->R[Index]; + else + Index=0; + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf); + + SE3208_Write8(se3208_state, Index+Offset,ZEX8(se3208_state->R[SrcDst])); + + CLRFLAG(FLAG_E); +} + +INST(LDS) +{ + UINT32 Offset=EXTRACT(Opcode,0,4); + UINT32 Index=EXTRACT(Opcode,5,7); + UINT32 SrcDst=EXTRACT(Opcode,8,10); + UINT32 Val; + + Offset<<=1; + + if(Index) + Index=se3208_state->R[Index]; + else + Index=0; + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf); + + Val=SE3208_Read16(se3208_state, Index+Offset); + se3208_state->R[SrcDst]=SEX16(Val); + + CLRFLAG(FLAG_E); +} + +INST(STS) +{ + UINT32 Offset=EXTRACT(Opcode,0,4); + UINT32 Index=EXTRACT(Opcode,5,7); + UINT32 SrcDst=EXTRACT(Opcode,8,10); + + Offset<<=1; + + if(Index) + Index=se3208_state->R[Index]; + else + Index=0; + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf); + + SE3208_Write16(se3208_state, Index+Offset,ZEX16(se3208_state->R[SrcDst])); + + CLRFLAG(FLAG_E); +} + +INST(LD) +{ + UINT32 Offset=EXTRACT(Opcode,0,4); + UINT32 Index=EXTRACT(Opcode,5,7); + UINT32 SrcDst=EXTRACT(Opcode,8,10); + + Offset<<=2; + + if(Index) + Index=se3208_state->R[Index]; + else + Index=0; + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf); + + se3208_state->R[SrcDst]=SE3208_Read32(se3208_state, Index+Offset); + + CLRFLAG(FLAG_E); +} + +INST(ST) +{ + UINT32 Offset=EXTRACT(Opcode,0,4); + UINT32 Index=EXTRACT(Opcode,5,7); + UINT32 SrcDst=EXTRACT(Opcode,8,10); + + Offset<<=2; + + if(Index) + Index=se3208_state->R[Index]; + else + Index=0; + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf); + + SE3208_Write32(se3208_state, Index+Offset,se3208_state->R[SrcDst]); + + CLRFLAG(FLAG_E); +} + +INST(LDBU) +{ + UINT32 Offset=EXTRACT(Opcode,0,4); + UINT32 Index=EXTRACT(Opcode,5,7); + UINT32 SrcDst=EXTRACT(Opcode,8,10); + UINT32 Val; + + if(Index) + Index=se3208_state->R[Index]; + else + Index=0; + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf); + + Val=SE3208_Read8(se3208_state, Index+Offset); + se3208_state->R[SrcDst]=ZEX8(Val); + + CLRFLAG(FLAG_E); +} + +INST(LDSU) +{ + UINT32 Offset=EXTRACT(Opcode,0,4); + UINT32 Index=EXTRACT(Opcode,5,7); + UINT32 SrcDst=EXTRACT(Opcode,8,10); + UINT32 Val; + + Offset<<=1; + + if(Index) + Index=se3208_state->R[Index]; + else + Index=0; + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf); + + Val=SE3208_Read16(se3208_state, Index+Offset); + se3208_state->R[SrcDst]=ZEX16(Val); + + CLRFLAG(FLAG_E); +} + + +INST(LERI) +{ + UINT32 Imm=EXTRACT(Opcode,0,13); + if(TESTFLAG(FLAG_E)) + se3208_state->ER=(EXTRACT(se3208_state->ER,0,17)<<14)|Imm; + else + se3208_state->ER=SEX(14,Imm); + + + SETFLAG(FLAG_E); +} + +INST(LDSP) +{ + UINT32 Offset=EXTRACT(Opcode,0,7); + UINT32 Index=se3208_state->SP; + UINT32 SrcDst=EXTRACT(Opcode,8,10); + + Offset<<=2; + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf); + + se3208_state->R[SrcDst]=SE3208_Read32(se3208_state, Index+Offset); + + CLRFLAG(FLAG_E); +} + +INST(STSP) +{ + UINT32 Offset=EXTRACT(Opcode,0,7); + UINT32 Index=se3208_state->SP; + UINT32 SrcDst=EXTRACT(Opcode,8,10); + + Offset<<=2; + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf); + + SE3208_Write32(se3208_state, Index+Offset,se3208_state->R[SrcDst]); + + CLRFLAG(FLAG_E); +} + +static void PushVal(se3208_state_t *se3208_state, UINT32 Val) +{ + se3208_state->SP-=4; + SE3208_Write32(se3208_state, se3208_state->SP,Val); +} + +static UINT32 PopVal(se3208_state_t *se3208_state) +{ + UINT32 Val=SE3208_Read32(se3208_state, se3208_state->SP); + se3208_state->SP+=4; + return Val; +} + +INST(PUSH) +{ + UINT32 Set=EXTRACT(Opcode,0,10); + if(Set&(1<<10)) + PushVal(se3208_state,se3208_state->PC); + if(Set&(1<<9)) + PushVal(se3208_state,se3208_state->SR); + if(Set&(1<<8)) + PushVal(se3208_state,se3208_state->ER); + if(Set&(1<<7)) + PushVal(se3208_state,se3208_state->R[7]); + if(Set&(1<<6)) + PushVal(se3208_state,se3208_state->R[6]); + if(Set&(1<<5)) + PushVal(se3208_state,se3208_state->R[5]); + if(Set&(1<<4)) + PushVal(se3208_state,se3208_state->R[4]); + if(Set&(1<<3)) + PushVal(se3208_state,se3208_state->R[3]); + if(Set&(1<<2)) + PushVal(se3208_state,se3208_state->R[2]); + if(Set&(1<<1)) + PushVal(se3208_state,se3208_state->R[1]); + if(Set&(1<<0)) + PushVal(se3208_state,se3208_state->R[0]); +} + +INST(POP) +{ + UINT32 Set=EXTRACT(Opcode,0,10); + if(Set&(1<<0)) + se3208_state->R[0]=PopVal(se3208_state); + if(Set&(1<<1)) + se3208_state->R[1]=PopVal(se3208_state); + if(Set&(1<<2)) + se3208_state->R[2]=PopVal(se3208_state); + if(Set&(1<<3)) + se3208_state->R[3]=PopVal(se3208_state); + if(Set&(1<<4)) + se3208_state->R[4]=PopVal(se3208_state); + if(Set&(1<<5)) + se3208_state->R[5]=PopVal(se3208_state); + if(Set&(1<<6)) + se3208_state->R[6]=PopVal(se3208_state); + if(Set&(1<<7)) + se3208_state->R[7]=PopVal(se3208_state); + if(Set&(1<<8)) + se3208_state->ER=PopVal(se3208_state); + if(Set&(1<<9)) + se3208_state->SR=PopVal(se3208_state); + if(Set&(1<<10)) + { + se3208_state->PC=PopVal(se3208_state)-2; //PC automatically incresases by 2 + } +} + +INST(LEATOSP) +{ + UINT32 Offset=EXTRACT(Opcode,9,12); + UINT32 Index=EXTRACT(Opcode,3,5); + + if(Index) + Index=se3208_state->R[Index]; + else + Index=0; + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf); + else + Offset=SEX(4,Offset); + + se3208_state->SP=Index+Offset; + + CLRFLAG(FLAG_E); +} + +INST(LEAFROMSP) +{ + UINT32 Offset=EXTRACT(Opcode,9,12); + UINT32 Index=EXTRACT(Opcode,3,5); + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf); + else + Offset=SEX(4,Offset); + + se3208_state->R[Index]=se3208_state->SP+Offset; + + CLRFLAG(FLAG_E); +} + +INST(LEASPTOSP) +{ + UINT32 Offset=EXTRACT(Opcode,0,7); + + Offset<<=2; + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,23)<<8)|(Offset&0xff); + else + Offset=SEX(10,Offset); + + se3208_state->SP=se3208_state->SP+Offset; + + CLRFLAG(FLAG_E); +} + +INST(MOV) +{ + UINT32 Src=EXTRACT(Opcode,3,5); + UINT32 Dst=EXTRACT(Opcode,9,11); + + se3208_state->R[Dst]=se3208_state->R[Src]; +} + +INST(LDI) +{ + UINT32 Dst=EXTRACT(Opcode,8,10); + UINT32 Imm=EXTRACT(Opcode,0,7); + + if(TESTFLAG(FLAG_E)) + Imm=(EXTRACT(se3208_state->ER,0,27)<<4)|(Imm&0xf); + else + Imm=SEX8(Imm); + + se3208_state->R[Dst]=Imm; + + CLRFLAG(FLAG_E); +} + +INST(LDBSP) +{ + UINT32 Offset=EXTRACT(Opcode,0,3); + UINT32 Index=se3208_state->SP; + UINT32 SrcDst=EXTRACT(Opcode,4,6); + UINT32 Val; + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf); + + Val=SE3208_Read8(se3208_state, Index+Offset); + se3208_state->R[SrcDst]=SEX8(Val); + + CLRFLAG(FLAG_E); +} + +INST(STBSP) +{ + UINT32 Offset=EXTRACT(Opcode,0,3); + UINT32 Index=se3208_state->SP; + UINT32 SrcDst=EXTRACT(Opcode,4,6); + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf); + + SE3208_Write8(se3208_state, Index+Offset,ZEX8(se3208_state->R[SrcDst])); + + CLRFLAG(FLAG_E); +} + +INST(LDSSP) +{ + UINT32 Offset=EXTRACT(Opcode,0,3); + UINT32 Index=se3208_state->SP; + UINT32 SrcDst=EXTRACT(Opcode,4,6); + UINT32 Val; + + Offset<<=1; + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf); + + Val=SE3208_Read16(se3208_state, Index+Offset); + se3208_state->R[SrcDst]=SEX16(Val); + + CLRFLAG(FLAG_E); +} + +INST(STSSP) +{ + UINT32 Offset=EXTRACT(Opcode,0,3); + UINT32 Index=se3208_state->SP; + UINT32 SrcDst=EXTRACT(Opcode,4,6); + + Offset<<=1; + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf); + + SE3208_Write16(se3208_state, Index+Offset,ZEX16(se3208_state->R[SrcDst])); + + CLRFLAG(FLAG_E); +} + +INST(LDBUSP) +{ + UINT32 Offset=EXTRACT(Opcode,0,3); + UINT32 Index=se3208_state->SP; + UINT32 SrcDst=EXTRACT(Opcode,4,6); + UINT32 Val; + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf); + + Val=SE3208_Read8(se3208_state, Index+Offset); + se3208_state->R[SrcDst]=ZEX8(Val); + + CLRFLAG(FLAG_E); +} + +INST(LDSUSP) +{ + UINT32 Offset=EXTRACT(Opcode,0,3); + UINT32 Index=se3208_state->SP; + UINT32 SrcDst=EXTRACT(Opcode,4,6); + UINT32 Val; + + Offset<<=1; + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,27)<<4)|(Offset&0xf); + + Val=SE3208_Read16(se3208_state, Index+Offset); + se3208_state->R[SrcDst]=ZEX16(Val); + + CLRFLAG(FLAG_E); +} + +INST(ADDI) +{ + UINT32 Imm=EXTRACT(Opcode,9,12); + UINT32 Src=EXTRACT(Opcode,3,5); + UINT32 Dst=EXTRACT(Opcode,0,2); + + if(TESTFLAG(FLAG_E)) + Imm=(EXTRACT(se3208_state->ER,0,27)<<4)|(Imm&0xf); + else + Imm=SEX(4,Imm); + + se3208_state->R[Dst]=AddWithFlags(se3208_state,se3208_state->R[Src],Imm); + + CLRFLAG(FLAG_E); +} + +INST(SUBI) +{ + UINT32 Imm=EXTRACT(Opcode,9,12); + UINT32 Src=EXTRACT(Opcode,3,5); + UINT32 Dst=EXTRACT(Opcode,0,2); + + if(TESTFLAG(FLAG_E)) + Imm=(EXTRACT(se3208_state->ER,0,27)<<4)|(Imm&0xf); + else + Imm=SEX(4,Imm); + + se3208_state->R[Dst]=SubWithFlags(se3208_state,se3208_state->R[Src],Imm); + + CLRFLAG(FLAG_E); +} + +INST(ADCI) +{ + UINT32 Imm=EXTRACT(Opcode,9,12); + UINT32 Src=EXTRACT(Opcode,3,5); + UINT32 Dst=EXTRACT(Opcode,0,2); + + if(TESTFLAG(FLAG_E)) + Imm=(EXTRACT(se3208_state->ER,0,27)<<4)|(Imm&0xf); + else + Imm=SEX(4,Imm); + + se3208_state->R[Dst]=AdcWithFlags(se3208_state,se3208_state->R[Src],Imm); + + CLRFLAG(FLAG_E); +} + +INST(SBCI) +{ + UINT32 Imm=EXTRACT(Opcode,9,12); + UINT32 Src=EXTRACT(Opcode,3,5); + UINT32 Dst=EXTRACT(Opcode,0,2); + + if(TESTFLAG(FLAG_E)) + Imm=(EXTRACT(se3208_state->ER,0,27)<<4)|(Imm&0xf); + else + Imm=SEX(4,Imm); + + se3208_state->R[Dst]=SbcWithFlags(se3208_state,se3208_state->R[Src],Imm); + + CLRFLAG(FLAG_E); +} + +INST(ANDI) +{ + UINT32 Imm=EXTRACT(Opcode,9,12); + UINT32 Src=EXTRACT(Opcode,3,5); + UINT32 Dst=EXTRACT(Opcode,0,2); + + if(TESTFLAG(FLAG_E)) + Imm=(EXTRACT(se3208_state->ER,0,27)<<4)|(Imm&0xf); + else + Imm=SEX(4,Imm); + + se3208_state->R[Dst]=se3208_state->R[Src]&Imm; + + CLRFLAG(FLAG_S|FLAG_Z|FLAG_E); + if(!se3208_state->R[Dst]) + SETFLAG(FLAG_Z); + if(se3208_state->R[Dst]&0x80000000) + SETFLAG(FLAG_S); +} + +INST(ORI) +{ + UINT32 Imm=EXTRACT(Opcode,9,12); + UINT32 Src=EXTRACT(Opcode,3,5); + UINT32 Dst=EXTRACT(Opcode,0,2); + + if(TESTFLAG(FLAG_E)) + Imm=(EXTRACT(se3208_state->ER,0,27)<<4)|(Imm&0xf); + else + Imm=SEX(4,Imm); + + se3208_state->R[Dst]=se3208_state->R[Src]|Imm; + + CLRFLAG(FLAG_S|FLAG_Z|FLAG_E); + if(!se3208_state->R[Dst]) + SETFLAG(FLAG_Z); + if(se3208_state->R[Dst]&0x80000000) + SETFLAG(FLAG_S); +} + +INST(XORI) +{ + UINT32 Imm=EXTRACT(Opcode,9,12); + UINT32 Src=EXTRACT(Opcode,3,5); + UINT32 Dst=EXTRACT(Opcode,0,2); + + if(TESTFLAG(FLAG_E)) + Imm=(EXTRACT(se3208_state->ER,0,27)<<4)|(Imm&0xf); + else + Imm=SEX(4,Imm); + + se3208_state->R[Dst]=se3208_state->R[Src]^Imm; + + CLRFLAG(FLAG_S|FLAG_Z|FLAG_E); + if(!se3208_state->R[Dst]) + SETFLAG(FLAG_Z); + if(se3208_state->R[Dst]&0x80000000) + SETFLAG(FLAG_S); +} + +INST(CMPI) +{ + UINT32 Imm=EXTRACT(Opcode,9,12); + UINT32 Src=EXTRACT(Opcode,3,5); + + if(TESTFLAG(FLAG_E)) + Imm=(EXTRACT(se3208_state->ER,0,27)<<4)|(Imm&0xf); + else + Imm=SEX(4,Imm); + + SubWithFlags(se3208_state,se3208_state->R[Src],Imm); + + CLRFLAG(FLAG_E); +} + +INST(TSTI) +{ + UINT32 Imm=EXTRACT(Opcode,9,12); + UINT32 Src=EXTRACT(Opcode,3,5); + UINT32 Dst; + + if(TESTFLAG(FLAG_E)) + Imm=(EXTRACT(se3208_state->ER,0,27)<<4)|(Imm&0xf); + else + Imm=SEX(4,Imm); + + Dst=se3208_state->R[Src]&Imm; + + CLRFLAG(FLAG_S|FLAG_Z|FLAG_E); + if(!Dst) + SETFLAG(FLAG_Z); + if(Dst&0x80000000) + SETFLAG(FLAG_S); +} + +INST(ADD) +{ + UINT32 Src2=EXTRACT(Opcode,9,11); + UINT32 Src1=EXTRACT(Opcode,3,5); + UINT32 Dst=EXTRACT(Opcode,0,2); + + se3208_state->R[Dst]=AddWithFlags(se3208_state,se3208_state->R[Src1],se3208_state->R[Src2]); +} + +INST(SUB) +{ + UINT32 Src2=EXTRACT(Opcode,9,11); + UINT32 Src1=EXTRACT(Opcode,3,5); + UINT32 Dst=EXTRACT(Opcode,0,2); + + se3208_state->R[Dst]=SubWithFlags(se3208_state,se3208_state->R[Src1],se3208_state->R[Src2]); +} + +INST(ADC) +{ + UINT32 Src2=EXTRACT(Opcode,9,11); + UINT32 Src1=EXTRACT(Opcode,3,5); + UINT32 Dst=EXTRACT(Opcode,0,2); + + se3208_state->R[Dst]=AdcWithFlags(se3208_state,se3208_state->R[Src1],se3208_state->R[Src2]); +} + +INST(SBC) +{ + UINT32 Src2=EXTRACT(Opcode,9,11); + UINT32 Src1=EXTRACT(Opcode,3,5); + UINT32 Dst=EXTRACT(Opcode,0,2); + + se3208_state->R[Dst]=SbcWithFlags(se3208_state,se3208_state->R[Src1],se3208_state->R[Src2]); +} + +INST(AND) +{ + UINT32 Src2=EXTRACT(Opcode,9,11); + UINT32 Src1=EXTRACT(Opcode,3,5); + UINT32 Dst=EXTRACT(Opcode,0,2); + + se3208_state->R[Dst]=se3208_state->R[Src1]&se3208_state->R[Src2]; + + CLRFLAG(FLAG_S|FLAG_Z); + if(!se3208_state->R[Dst]) + SETFLAG(FLAG_Z); + if(se3208_state->R[Dst]&0x80000000) + SETFLAG(FLAG_S); +} + +INST(OR) +{ + UINT32 Src2=EXTRACT(Opcode,9,11); + UINT32 Src1=EXTRACT(Opcode,3,5); + UINT32 Dst=EXTRACT(Opcode,0,2); + + se3208_state->R[Dst]=se3208_state->R[Src1]|se3208_state->R[Src2]; + + CLRFLAG(FLAG_S|FLAG_Z); + if(!se3208_state->R[Dst]) + SETFLAG(FLAG_Z); + if(se3208_state->R[Dst]&0x80000000) + SETFLAG(FLAG_S); + +} + +INST(XOR) +{ + UINT32 Src2=EXTRACT(Opcode,9,11); + UINT32 Src1=EXTRACT(Opcode,3,5); + UINT32 Dst=EXTRACT(Opcode,0,2); + + se3208_state->R[Dst]=se3208_state->R[Src1]^se3208_state->R[Src2]; + + CLRFLAG(FLAG_S|FLAG_Z); + if(!se3208_state->R[Dst]) + SETFLAG(FLAG_Z); + if(se3208_state->R[Dst]&0x80000000) + SETFLAG(FLAG_S); + +} + +INST(CMP) +{ + UINT32 Src2=EXTRACT(Opcode,9,11); + UINT32 Src1=EXTRACT(Opcode,3,5); + + SubWithFlags(se3208_state,se3208_state->R[Src1],se3208_state->R[Src2]); +} + +INST(TST) +{ + UINT32 Src2=EXTRACT(Opcode,9,11); + UINT32 Src1=EXTRACT(Opcode,3,5); + UINT32 Dst; + + Dst=se3208_state->R[Src1]&se3208_state->R[Src2]; + + CLRFLAG(FLAG_S|FLAG_Z); + if(!Dst) + SETFLAG(FLAG_Z); + if(Dst&0x80000000) + SETFLAG(FLAG_S); +} + +INST(MULS) +{ + UINT32 Src2=EXTRACT(Opcode,6,8); + UINT32 Src1=EXTRACT(Opcode,3,5); + UINT32 Dst=EXTRACT(Opcode,0,2); + + se3208_state->R[Dst]=MulWithFlags(se3208_state,se3208_state->R[Src1],se3208_state->R[Src2]); + + CLRFLAG(FLAG_E); +} + +INST(NEG) +{ + UINT32 Dst=EXTRACT(Opcode,9,11); + UINT32 Src=EXTRACT(Opcode,3,5); + + se3208_state->R[Dst]=NegWithFlags(se3208_state,se3208_state->R[Src]); +} + +INST(CALL) +{ + UINT32 Offset=EXTRACT(Opcode,0,7); + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset; + else + Offset=SEX(8,Offset); + Offset<<=1; + PushVal(se3208_state,se3208_state->PC+2); + se3208_state->PC=se3208_state->PC+Offset; + + CLRFLAG(FLAG_E); +} + +INST(JV) +{ + UINT32 Offset=EXTRACT(Opcode,0,7); + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset; + else + Offset=SEX(8,Offset); + Offset<<=1; + + if(TESTFLAG(FLAG_V)) + { + se3208_state->PC=se3208_state->PC+Offset; + } + + CLRFLAG(FLAG_E); + +} + +INST(JNV) +{ + UINT32 Offset=EXTRACT(Opcode,0,7); + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset; + else + Offset=SEX(8,Offset); + Offset<<=1; + + if(!TESTFLAG(FLAG_V)) + { + se3208_state->PC=se3208_state->PC+Offset; + } + + CLRFLAG(FLAG_E); +} + +INST(JC) +{ + UINT32 Offset=EXTRACT(Opcode,0,7); + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset; + else + Offset=SEX(8,Offset); + Offset<<=1; + + if(TESTFLAG(FLAG_C)) + { + se3208_state->PC=se3208_state->PC+Offset; + } + + CLRFLAG(FLAG_E); +} + +INST(JNC) +{ + UINT32 Offset=EXTRACT(Opcode,0,7); + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset; + else + Offset=SEX(8,Offset); + Offset<<=1; + + if(!TESTFLAG(FLAG_C)) + { + se3208_state->PC=se3208_state->PC+Offset; + } + + CLRFLAG(FLAG_E); +} + +INST(JP) +{ + UINT32 Offset=EXTRACT(Opcode,0,7); + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset; + else + Offset=SEX(8,Offset); + Offset<<=1; + + if(!TESTFLAG(FLAG_S)) + { + se3208_state->PC=se3208_state->PC+Offset; + } + + CLRFLAG(FLAG_E); +} + +INST(JM) +{ + UINT32 Offset=EXTRACT(Opcode,0,7); + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset; + else + Offset=SEX(8,Offset); + Offset<<=1; + + if(TESTFLAG(FLAG_S)) + { + se3208_state->PC=se3208_state->PC+Offset; + } + + CLRFLAG(FLAG_E); +} + +INST(JNZ) +{ + UINT32 Offset=EXTRACT(Opcode,0,7); + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset; + else + Offset=SEX(8,Offset); + Offset<<=1; + + if(!TESTFLAG(FLAG_Z)) + { + se3208_state->PC=se3208_state->PC+Offset; + } + + CLRFLAG(FLAG_E); +} + +INST(JZ) +{ + UINT32 Offset=EXTRACT(Opcode,0,7); + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset; + else + Offset=SEX(8,Offset); + Offset<<=1; + + if(TESTFLAG(FLAG_Z)) + { + se3208_state->PC=se3208_state->PC+Offset; + } + + CLRFLAG(FLAG_E); +} + +INST(JGE) +{ + UINT32 Offset=EXTRACT(Opcode,0,7); + UINT32 S=TESTFLAG(FLAG_S)?1:0; + UINT32 V=TESTFLAG(FLAG_V)?1:0; + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset; + else + Offset=SEX(8,Offset); + Offset<<=1; + + if(!(S^V)) + { + se3208_state->PC=se3208_state->PC+Offset; + } + + CLRFLAG(FLAG_E); +} + +INST(JLE) +{ + UINT32 Offset=EXTRACT(Opcode,0,7); + UINT32 S=TESTFLAG(FLAG_S)?1:0; + UINT32 V=TESTFLAG(FLAG_V)?1:0; + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset; + else + Offset=SEX(8,Offset); + Offset<<=1; + + if(TESTFLAG(FLAG_Z) || (S^V)) + { + se3208_state->PC=se3208_state->PC+Offset; + } + CLRFLAG(FLAG_E); +} + +INST(JHI) +{ + UINT32 Offset=EXTRACT(Opcode,0,7); + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset; + else + Offset=SEX(8,Offset); + Offset<<=1; + + if(!(TESTFLAG(FLAG_Z) || TESTFLAG(FLAG_C))) + { + se3208_state->PC=se3208_state->PC+Offset; + } + + CLRFLAG(FLAG_E); +} + +INST(JLS) +{ + UINT32 Offset=EXTRACT(Opcode,0,7); + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset; + else + Offset=SEX(8,Offset); + Offset<<=1; + + if(TESTFLAG(FLAG_Z) || TESTFLAG(FLAG_C)) + { + se3208_state->PC=se3208_state->PC+Offset; + } + + CLRFLAG(FLAG_E); +} + +INST(JGT) +{ + UINT32 Offset=EXTRACT(Opcode,0,7); + UINT32 S=TESTFLAG(FLAG_S)?1:0; + UINT32 V=TESTFLAG(FLAG_V)?1:0; + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset; + else + Offset=SEX(8,Offset); + Offset<<=1; + + if(!(TESTFLAG(FLAG_Z) || (S^V))) + { + se3208_state->PC=se3208_state->PC+Offset; + } + + CLRFLAG(FLAG_E); +} + +INST(JLT) +{ + UINT32 Offset=EXTRACT(Opcode,0,7); + UINT32 S=TESTFLAG(FLAG_S)?1:0; + UINT32 V=TESTFLAG(FLAG_V)?1:0; + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset; + else + Offset=SEX(8,Offset); + Offset<<=1; + + if(S^V) + { + se3208_state->PC=se3208_state->PC+Offset; + } + + CLRFLAG(FLAG_E); +} + + + +INST(JMP) +{ + UINT32 Offset=EXTRACT(Opcode,0,7); + + if(TESTFLAG(FLAG_E)) + Offset=(EXTRACT(se3208_state->ER,0,22)<<8)|Offset; + else + Offset=SEX(8,Offset); + + Offset<<=1; + + se3208_state->PC=se3208_state->PC+Offset; + + CLRFLAG(FLAG_E); +} + +INST(JR) +{ + UINT32 Src=EXTRACT(Opcode,0,3); + + se3208_state->PC=se3208_state->R[Src]-2; + + CLRFLAG(FLAG_E); +} + +INST(CALLR) +{ + UINT32 Src=EXTRACT(Opcode,0,3); + PushVal(se3208_state,se3208_state->PC+2); + se3208_state->PC=se3208_state->R[Src]-2; + + CLRFLAG(FLAG_E); +} + +INST(ASR) +{ + UINT32 CS=Opcode&(1<<10); + UINT32 Dst=EXTRACT(Opcode,0,2); + UINT32 Imm=EXTRACT(Opcode,5,9); + UINT32 Cnt=EXTRACT(Opcode,5,7); + + if(CS) + se3208_state->R[Dst]=AsrWithFlags(se3208_state,se3208_state->R[Dst],se3208_state->R[Cnt]&0x1f); + else + se3208_state->R[Dst]=AsrWithFlags(se3208_state,se3208_state->R[Dst],Imm&0x1f); + + CLRFLAG(FLAG_E); +} + +INST(LSR) +{ + UINT32 CS=Opcode&(1<<10); + UINT32 Dst=EXTRACT(Opcode,0,2); + UINT32 Imm=EXTRACT(Opcode,5,9); + UINT32 Cnt=EXTRACT(Opcode,5,7); + + if(CS) + se3208_state->R[Dst]=LsrWithFlags(se3208_state,se3208_state->R[Dst],se3208_state->R[Cnt]&0x1f); + else + se3208_state->R[Dst]=LsrWithFlags(se3208_state,se3208_state->R[Dst],Imm&0x1f); + + CLRFLAG(FLAG_E); +} + +INST(ASL) +{ + UINT32 CS=Opcode&(1<<10); + UINT32 Dst=EXTRACT(Opcode,0,2); + UINT32 Imm=EXTRACT(Opcode,5,9); + UINT32 Cnt=EXTRACT(Opcode,5,7); + + if(CS) + se3208_state->R[Dst]=AslWithFlags(se3208_state,se3208_state->R[Dst],se3208_state->R[Cnt]&0x1f); + else + se3208_state->R[Dst]=AslWithFlags(se3208_state,se3208_state->R[Dst],Imm&0x1f); + + CLRFLAG(FLAG_E); +} + +INST(EXTB) +{ + UINT32 Dst=EXTRACT(Opcode,0,3); + UINT32 Val=se3208_state->R[Dst]; + + se3208_state->R[Dst]=SEX8(Val); + + CLRFLAG(FLAG_S|FLAG_Z|FLAG_E); + if(!se3208_state->R[Dst]) + SETFLAG(FLAG_Z); + if(se3208_state->R[Dst]&0x80000000) + SETFLAG(FLAG_S); + +} + +INST(EXTS) +{ + UINT32 Dst=EXTRACT(Opcode,0,3); + UINT32 Val=se3208_state->R[Dst]; + + se3208_state->R[Dst]=SEX16(Val); + + CLRFLAG(FLAG_S|FLAG_Z|FLAG_E); + if(!se3208_state->R[Dst]) + SETFLAG(FLAG_Z); + if(se3208_state->R[Dst]&0x80000000) + SETFLAG(FLAG_S); +} + +INST(SET) +{ + UINT32 Imm=EXTRACT(Opcode,0,3); + + se3208_state->SR|=(1<<Imm); +} + +INST(CLR) +{ + UINT32 Imm=EXTRACT(Opcode,0,3); + + se3208_state->SR&=~(1<<Imm); +} + +INST(SWI) +{ + UINT32 Imm=EXTRACT(Opcode,0,3); + + if(!TESTFLAG(FLAG_ENI)) + return; + PushVal(se3208_state,se3208_state->PC); + PushVal(se3208_state,se3208_state->SR); + + CLRFLAG(FLAG_ENI|FLAG_E|FLAG_M); + + se3208_state->PC=SE3208_Read32(se3208_state, 4*Imm+0x40)-2; +} + +INST(HALT) +{ +// UINT32 Imm=EXTRACT(Opcode,0,3); + +// DEBUGMESSAGE("HALT\t0x%x",Imm); +} + +INST(MVTC) +{ +// UINT32 Imm=EXTRACT(Opcode,0,3); + +// DEBUGMESSAGE("MVTC\t%%R0,%%CR%d",Imm); +} + +INST(MVFC) +{ +// UINT32 Imm=EXTRACT(Opcode,0,3); + +// DEBUGMESSAGE("MVFC\t%%CR0%d,%%R0",Imm); +} + + +static _OP DecodeOp(UINT16 Opcode) +{ + switch(EXTRACT(Opcode,14,15)) + { + case 0x0: + { + UINT8 Op=EXTRACT(Opcode,11,13); + switch(Op) + { + case 0x0: + return LDB; + case 0x1: + return LDS; + case 0x2: + return LD; + case 0x3: + return LDBU; + case 0x4: + return STB; + case 0x5: + return STS; + case 0x6: + return ST; + case 0x7: + return LDSU; + } + } + break; + case 0x1: + return LERI; + case 0x2: + { + switch(EXTRACT(Opcode,11,13)) + { + case 0: + return LDSP; + case 1: + return STSP; + case 2: + return PUSH; + case 3: + return POP; + case 4: + case 5: + case 6: + case 7: + case 8: //arith + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + switch(EXTRACT(Opcode,6,8)) + { + case 0: + return ADDI; + case 1: + return ADCI; + case 2: + return SUBI; + case 3: + return SBCI; + case 4: + return ANDI; + case 5: + return ORI; + case 6: + return XORI; + case 7: + switch(EXTRACT(Opcode,0,2)) + { + case 0: + return CMPI; + case 1: + return TSTI; + case 2: + return LEATOSP; + case 3: + return LEAFROMSP; + } + break; + } + break; + } + } + break; + case 3: + switch(EXTRACT(Opcode,12,13)) + { + case 0: + switch(EXTRACT(Opcode,6,8)) + { + case 0: + return ADD; + case 1: + return ADC; + case 2: + return SUB; + case 3: + return SBC; + case 4: + return AND; + case 5: + return OR; + case 6: + return XOR; + case 7: + switch(EXTRACT(Opcode,0,2)) + { + case 0: + return CMP; + case 1: + return TST; + case 2: + return MOV; + case 3: + return NEG; + } + break; + } + break; + case 1: //Jumps + switch(EXTRACT(Opcode,8,11)) + { + case 0x0: + return JNV; + case 0x1: + return JV; + case 0x2: + return JP; + case 0x3: + return JM; + case 0x4: + return JNZ; + case 0x5: + return JZ; + case 0x6: + return JNC; + case 0x7: + return JC; + case 0x8: + return JGT; + case 0x9: + return JLT; + case 0xa: + return JGE; + case 0xb: + return JLE; + case 0xc: + return JHI; + case 0xd: + return JLS; + case 0xe: + return JMP; + case 0xf: + return CALL; + } + break; + case 2: + if(Opcode&(1<<11)) + return LDI; + else //SP Ops + { + if(Opcode&(1<<10)) + { + switch(EXTRACT(Opcode,7,9)) + { + case 0: + return LDBSP; + case 1: + return LDSSP; + case 3: + return LDBUSP; + case 4: + return STBSP; + case 5: + return STSSP; + case 7: + return LDSUSP; + } + } + else + { + if(Opcode&(1<<9)) + { + return LEASPTOSP; + } + else + { + if(Opcode&(1<<8)) + { + + } + else + { + switch(EXTRACT(Opcode,4,7)) + { + case 0: + return EXTB; + case 1: + return EXTS; + case 8: + return JR; + case 9: + return CALLR; + case 10: + return SET; + case 11: + return CLR; + case 12: + return SWI; + case 13: + return HALT; + } + } + } + } + } + break; + case 3: + switch(EXTRACT(Opcode,9,11)) + { + case 0: + case 1: + case 2: + case 3: + switch(EXTRACT(Opcode,3,4)) + { + case 0: + return ASR; + case 1: + return LSR; + case 2: + return ASL; + //case 3: + // return LSL; + } + break; + case 4: + return MULS; + case 6: + if(Opcode&(1<<3)) + return MVFC; + else + return MVTC; + break; + } + break; + } + break; + + } + return INVALIDOP; +} + + +static void BuildTable(void) +{ + int i; + if(!OpTable) + OpTable=global_alloc_array(_OP, 0x10000); + for(i=0;i<0x10000;++i) + OpTable[i]=DecodeOp(i); +} + +static CPU_RESET( se3208 ) +{ + se3208_state_t *se3208_state = get_safe_token(device); + + device_irq_callback save_irqcallback = se3208_state->irq_callback; + memset(se3208_state,0,sizeof(se3208_state_t)); + se3208_state->irq_callback = save_irqcallback; + se3208_state->device = device; + se3208_state->program = device->space(AS_PROGRAM); + se3208_state->direct = &se3208_state->program->direct(); + se3208_state->PC=SE3208_Read32(se3208_state, 0); + se3208_state->SR=0; + se3208_state->IRQ=CLEAR_LINE; + se3208_state->NMI=CLEAR_LINE; +} + +static void SE3208_NMI(se3208_state_t *se3208_state) +{ + PushVal(se3208_state,se3208_state->PC); + PushVal(se3208_state,se3208_state->SR); + + CLRFLAG(FLAG_NMI|FLAG_ENI|FLAG_E|FLAG_M); + + se3208_state->PC=SE3208_Read32(se3208_state, 4); +} + +static void SE3208_Interrupt(se3208_state_t *se3208_state) +{ + if(!TESTFLAG(FLAG_ENI)) + return; + + PushVal(se3208_state,se3208_state->PC); + PushVal(se3208_state,se3208_state->SR); + + CLRFLAG(FLAG_ENI|FLAG_E|FLAG_M); + + + if(!(TESTFLAG(FLAG_AUT))) + se3208_state->PC=SE3208_Read32(se3208_state, 8); + else + se3208_state->PC=SE3208_Read32(se3208_state, 4*se3208_state->irq_callback(se3208_state->device, 0)); +} + + +static CPU_EXECUTE( se3208 ) +{ + se3208_state_t *se3208_state = get_safe_token(device); + + do + { + UINT16 Opcode=se3208_state->direct->read_decrypted_word(se3208_state->PC, WORD_XOR_LE(0)); + + debugger_instruction_hook(device, se3208_state->PC); + + OpTable[Opcode](se3208_state, Opcode); + se3208_state->PPC=se3208_state->PC; + se3208_state->PC+=2; + //Check interrupts + if(se3208_state->NMI==ASSERT_LINE) + { + SE3208_NMI(se3208_state); + se3208_state->NMI=CLEAR_LINE; + } + else if(se3208_state->IRQ==ASSERT_LINE && TESTFLAG(FLAG_ENI)) + { + SE3208_Interrupt(se3208_state); + } + --(se3208_state->icount); + } while(se3208_state->icount>0); +} + +static CPU_INIT( se3208 ) +{ + se3208_state_t *se3208_state = get_safe_token(device); + + BuildTable(); + + se3208_state->irq_callback = irqcallback; + se3208_state->device = device; + se3208_state->program = device->space(AS_PROGRAM); + se3208_state->direct = &se3208_state->program->direct(); +} + +static CPU_EXIT( se3208 ) +{ + if(OpTable) { + global_free(OpTable); + OpTable = NULL; + } +} + + +static void set_irq_line(se3208_state_t *se3208_state, int line,int state) +{ + if(line==INPUT_LINE_NMI) //NMI + se3208_state->NMI=state; + else + se3208_state->IRQ=state; +} + + +static CPU_SET_INFO( se3208 ) +{ + se3208_state_t *se3208_state = get_safe_token(device); + + switch (state) + { + /* --- the following bits of info are set as 64-bit signed integers --- */ + case CPUINFO_INT_INPUT_STATE + SE3208_INT: set_irq_line(se3208_state, 0, info->i); break; + case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: set_irq_line(se3208_state, INPUT_LINE_NMI, info->i); break; + + case CPUINFO_INT_REGISTER + SE3208_PC: + case CPUINFO_INT_PC: se3208_state->PC = info->i; break; + case CPUINFO_INT_REGISTER + SE3208_SP: + case CPUINFO_INT_SP: se3208_state->SP = info->i; break; + case CPUINFO_INT_REGISTER + SE3208_ER: se3208_state->ER = info->i; break; + case CPUINFO_INT_REGISTER + SE3208_SR: se3208_state->SR = info->i; break; + case CPUINFO_INT_REGISTER + SE3208_R0: se3208_state->R[ 0] = info->i; break; + case CPUINFO_INT_REGISTER + SE3208_R1: se3208_state->R[ 1] = info->i; break; + case CPUINFO_INT_REGISTER + SE3208_R2: se3208_state->R[ 2] = info->i; break; + case CPUINFO_INT_REGISTER + SE3208_R3: se3208_state->R[ 3] = info->i; break; + case CPUINFO_INT_REGISTER + SE3208_R4: se3208_state->R[ 4] = info->i; break; + case CPUINFO_INT_REGISTER + SE3208_R5: se3208_state->R[ 5] = info->i; break; + case CPUINFO_INT_REGISTER + SE3208_R6: se3208_state->R[ 6] = info->i; break; + case CPUINFO_INT_REGISTER + SE3208_R7: se3208_state->R[ 7] = info->i; break; + } +} + + +CPU_GET_INFO( se3208 ) +{ + se3208_state_t *se3208_state = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL; + + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(se3208_state_t); break; + case CPUINFO_INT_INPUT_LINES: info->i = 1; break; + case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break; + case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break; + case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break; + case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break; + case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 2; break; + case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 2; break; + case CPUINFO_INT_MIN_CYCLES: info->i = 1; break; + case CPUINFO_INT_MAX_CYCLES: info->i = 1; break; + + case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break; + case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 32; break; + case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break; + case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break; + case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break; + case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break; + case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break; + case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break; + case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break; + + case CPUINFO_INT_INPUT_STATE + SE3208_INT: info->i = se3208_state->IRQ; break; + case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = se3208_state->NMI; break; + + case CPUINFO_INT_PREVIOUSPC: info->i = se3208_state->PPC; break; + + case CPUINFO_INT_PC: + case CPUINFO_INT_REGISTER + SE3208_PC: info->i = se3208_state->PC; break; + case CPUINFO_INT_REGISTER + SE3208_SP: + case CPUINFO_INT_SP: info->i = se3208_state->SP; break; + case CPUINFO_INT_REGISTER + SE3208_SR: info->i = se3208_state->SR; break; + case CPUINFO_INT_REGISTER + SE3208_ER: info->i = se3208_state->ER; break; + case CPUINFO_INT_REGISTER + SE3208_R0: info->i = se3208_state->R[ 0]; break; + case CPUINFO_INT_REGISTER + SE3208_R1: info->i = se3208_state->R[ 1]; break; + case CPUINFO_INT_REGISTER + SE3208_R2: info->i = se3208_state->R[ 2]; break; + case CPUINFO_INT_REGISTER + SE3208_R3: info->i = se3208_state->R[ 3]; break; + case CPUINFO_INT_REGISTER + SE3208_R4: info->i = se3208_state->R[ 4]; break; + case CPUINFO_INT_REGISTER + SE3208_R5: info->i = se3208_state->R[ 5]; break; + case CPUINFO_INT_REGISTER + SE3208_R6: info->i = se3208_state->R[ 6]; break; + case CPUINFO_INT_REGISTER + SE3208_R7: info->i = se3208_state->R[ 7]; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(se3208); break; + case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(se3208); break; + case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(se3208); break; + case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(se3208); break; + case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(se3208);break; + case CPUINFO_FCT_BURN: info->burn = NULL; break; + case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(se3208); break; + case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &se3208_state->icount; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "SE3208"); break; + case DEVINFO_STR_FAMILY: strcpy(info->s, "Advanced Digital Chips Inc."); break; + case DEVINFO_STR_VERSION: strcpy(info->s, "1.00"); break; + case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; + case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Miguel Angel Horna, all rights reserved."); break; + + case CPUINFO_STR_FLAGS: + sprintf(info->s, "%c%c%c%c %c%c%c%c%c", + se3208_state->SR&FLAG_C?'C':'.', + se3208_state->SR&FLAG_V?'V':'.', + se3208_state->SR&FLAG_S?'S':'.', + se3208_state->SR&FLAG_Z?'Z':'.', + + se3208_state->SR&FLAG_M?'M':'.', + se3208_state->SR&FLAG_E?'E':'.', + se3208_state->SR&FLAG_AUT?'A':'.', + se3208_state->SR&FLAG_ENI?'I':'.', + se3208_state->SR&FLAG_NMI?'N':'.' + + ); + + break; + + case CPUINFO_STR_REGISTER + SE3208_PC: sprintf(info->s, "PC :%08X", se3208_state->PC); break; + case CPUINFO_STR_REGISTER + SE3208_SR: sprintf(info->s, "SR :%08X", se3208_state->SR); break; + case CPUINFO_STR_REGISTER + SE3208_ER: sprintf(info->s, "ER :%08X", se3208_state->ER); break; + case CPUINFO_STR_REGISTER + SE3208_SP: sprintf(info->s, "SP :%08X", se3208_state->SP); break; + case CPUINFO_STR_REGISTER + SE3208_R0: sprintf(info->s, "R0 :%08X", se3208_state->R[ 0]); break; + case CPUINFO_STR_REGISTER + SE3208_R1: sprintf(info->s, "R1 :%08X", se3208_state->R[ 1]); break; + case CPUINFO_STR_REGISTER + SE3208_R2: sprintf(info->s, "R2 :%08X", se3208_state->R[ 2]); break; + case CPUINFO_STR_REGISTER + SE3208_R3: sprintf(info->s, "R3 :%08X", se3208_state->R[ 3]); break; + case CPUINFO_STR_REGISTER + SE3208_R4: sprintf(info->s, "R4 :%08X", se3208_state->R[ 4]); break; + case CPUINFO_STR_REGISTER + SE3208_R5: sprintf(info->s, "R5 :%08X", se3208_state->R[ 5]); break; + case CPUINFO_STR_REGISTER + SE3208_R6: sprintf(info->s, "R6 :%08X", se3208_state->R[ 6]); break; + case CPUINFO_STR_REGISTER + SE3208_R7: sprintf(info->s, "R7 :%08X", se3208_state->R[ 7]); break; + case CPUINFO_STR_REGISTER + SE3208_PPC: sprintf(info->s, "PPC :%08X", se3208_state->PPC); break; + } +} + + +DEFINE_LEGACY_CPU_DEVICE(SE3208, se3208); |