2054 lines
47 KiB
C
2054 lines
47 KiB
C
#include "../headers/instructions/instructions.h"
|
|
|
|
// Returns a pointer to the function that implements the corresponding instruction
|
|
void (*get_instruction_impl(uint16_t instruction))(cpu_t*, uint16_t) {
|
|
uint8_t high = (instruction >> 12) & 0x0F;
|
|
uint8_t high8 = instruction >> 8;
|
|
uint8_t low = instruction & 0x0F;
|
|
uint8_t low8 = instruction & 0xFF;
|
|
|
|
if (instruction == 0b0000000000101000) return CLRMAC;
|
|
if (instruction == 0b0000000001001000) return CLRS;
|
|
if (instruction == 0b0000000000001000) return CLRT;
|
|
if (instruction == 0b0000000000011001) return DIV0U;
|
|
if (instruction == 0b0000000000001001) return NOP;
|
|
if (instruction == 0b0000000000101011) return RTE;
|
|
if (instruction == 0b0000000000001011) return RTS;
|
|
if (instruction == 0b0000000001011000) return SETS;
|
|
if (instruction == 0b0000000000011000) return SETT;
|
|
if (high8 == 0b11001001) return ANDI;
|
|
if (high8 == 0b11001101) return ANDM;
|
|
if (high8 == 0b10001011) return BF;
|
|
if (high8 == 0b10001111) return BFS;
|
|
if (high8 == 0b10001001) return BT;
|
|
if (high8 == 0b10001101) return BTS;
|
|
if (high8 == 0b10001000) return CMPIM;
|
|
if (high8 == 0b11000100) return MOVBLG;
|
|
if (high8 == 0b11000101) return MOVWLG;
|
|
if (high8 == 0b11000110) return MOVLLG;
|
|
if (high8 == 0b11000000) return MOVBSG;
|
|
if (high8 == 0b11000001) return MOVWSG;
|
|
if (high8 == 0b11000010) return MOVLSG;
|
|
if (high8 == 0b10000000) return MOVBS4;
|
|
if (high8 == 0b10000001) return MOVWS4;
|
|
if (high8 == 0b10000100) return MOVBL4;
|
|
if (high8 == 0b10000101) return MOVWL4;
|
|
if (high8 == 0b11000111) return MOVA;
|
|
if (high8 == 0b11001011) return ORI;
|
|
if (high8 == 0b11001111) return ORM;
|
|
if (high8 == 0b11001000) return TSTI;
|
|
if (high8 == 0b11001100) return TSTM;
|
|
if (high8 == 0b11001010) return XORI;
|
|
if (high8 == 0b11001110) return XORM;
|
|
if (high == 0b0111) return ADDI;
|
|
if (high == 0b1010) return BRA;
|
|
if (high == 0b1110) return MOVI;
|
|
if (high == 0b1001) return MOVWI;
|
|
if (high == 0b1101) return MOVLI;
|
|
if (high == 0b0001) return MOVLS4;
|
|
if (high == 0b0101) return MOVLL4;
|
|
if (high == 0b1011) return BSR;
|
|
if (high == 0b0100) {
|
|
if (low8 == 0b00010101) return CMPPL;
|
|
if (low8 == 0b00010001) return CMPPZ;
|
|
if (low8 == 0b00010000) return DT;
|
|
if (low8 == 0b00101011) return JMP;
|
|
if (low8 == 0b00011110) return LDCGBR;
|
|
if (low8 == 0b00101110) return LDCVBR;
|
|
if (low8 == 0b00111010) return LDCSGR;
|
|
if (low8 == 0b00111110) return LDCSSR;
|
|
if (low8 == 0b01001110) return LDCSPC;
|
|
if (low8 == 0b11111010) return LDCDBR;
|
|
if (low8 == 0b00010111) return LDCMGBR;
|
|
if (low8 == 0b00100111) return LDCMVBR;
|
|
if (low8 == 0b00110110) return LDCMSGR;
|
|
if (low8 == 0b00110111) return LDCMSSR;
|
|
if (low8 == 0b01000111) return LDCMSPC;
|
|
if (low8 == 0b11110110) return LDCMDBR;
|
|
if (low8 == 0b00001010) return LDSMACH;
|
|
if (low8 == 0b00011010) return LDSMACL;
|
|
if (low8 == 0b00101010) return LDSPR;
|
|
if (low8 == 0b00000110) return LDSMMACH;
|
|
if (low8 == 0b00010110) return LDSMMACL;
|
|
if (low8 == 0b00100110) return LDSMPR;
|
|
if (low8 == 0b00100100) return ROTCL;
|
|
if (low8 == 0b00100101) return ROTCR;
|
|
if (low8 == 0b00000100) return ROTL;
|
|
if (low8 == 0b00000101) return ROTR;
|
|
if (low8 == 0b00100000) return SHAL;
|
|
if (low8 == 0b00100001) return SHAR;
|
|
if (low8 == 0b00000000) return SHLL;
|
|
if (low8 == 0b00001000) return SHLL2;
|
|
if (low8 == 0b00011000) return SHLL8;
|
|
if (low8 == 0b00101000) return SHLL16;
|
|
if (low8 == 0b00000001) return SHLR;
|
|
if (low8 == 0b00001001) return SHLR2;
|
|
if (low8 == 0b00011001) return SHLR8;
|
|
if (low8 == 0b00101001) return SHLR16;
|
|
if (low8 == 0b00010011) return STCMGBR;
|
|
if (low8 == 0b00100011) return STCMVBR;
|
|
if (low8 == 0b00110011) return STCMSSR;
|
|
if (low8 == 0b01000011) return STCMSPC;
|
|
if (low8 == 0b00110010) return STCMSGR;
|
|
if (low8 == 0b11110010) return STCMDBR;
|
|
if (low8 == 0b00000010) return STSMMACH;
|
|
if (low8 == 0b00010010) return STSMMACL;
|
|
if (low8 == 0b00100010) return STSMPR;
|
|
if (low8 == 0b00011011) return TAS;
|
|
if (low8 == 0b00001011) return JSR;
|
|
}
|
|
if (high == 0b0000) {
|
|
if (low8 == 0b00100011) return BRAF;
|
|
if (low8 == 0b00101001) return MOVT;
|
|
if (low8 == 0b10000011) return PREF;
|
|
if (low8 == 0b00010010) return STCGBR;
|
|
if (low8 == 0b00100010) return STCVBR;
|
|
if (low8 == 0b00110010) return STCSSR;
|
|
if (low8 == 0b01000010) return STCSPC;
|
|
if (low8 == 0b00111010) return STCSGR;
|
|
if (low8 == 0b11111010) return STCDBR;
|
|
if (low8 == 0b00001010) return STSMACH;
|
|
if (low8 == 0b00011010) return STSMACL;
|
|
if (low8 == 0b00101010) return STSPR;
|
|
if (low8 == 0b00000011) return BSRF;
|
|
}
|
|
if (high == 0b0110) {
|
|
if (low == 0b1110) return EXTSB;
|
|
if (low == 0b1111) return EXTSW;
|
|
if (low == 0b1100) return EXTUB;
|
|
if (low == 0b1101) return EXTUW;
|
|
if (low == 0b0011) return MOV;
|
|
if (low == 0b0000) return MOVBL;
|
|
if (low == 0b0001) return MOVWL;
|
|
if (low == 0b0010) return MOVLL;
|
|
if (low == 0b0100) return MOVBP;
|
|
if (low == 0b0101) return MOVWP;
|
|
if (low == 0b0110) return MOVLP;
|
|
if (low == 0b1011) return NEG;
|
|
if (low == 0b1010) return NEGC;
|
|
if (low == 0b0111) return NOT;
|
|
if (low == 0b1000) return SWAPB;
|
|
if (low == 0b1001) return SWAPW;
|
|
}
|
|
if (high == 0b0010) {
|
|
if (low == 0b1001) return AND;
|
|
if (low == 0b1100) return CMPSTR;
|
|
if (low == 0b0111) return DIV0S;
|
|
if (low == 0b0000) return MOVBS;
|
|
if (low == 0b0001) return MOVWS;
|
|
if (low == 0b0010) return MOVLS;
|
|
if (low == 0b0100) return MOVBM;
|
|
if (low == 0b0101) return MOVWM;
|
|
if (low == 0b0110) return MOVLM;
|
|
if (low == 0b1111) return MULS;
|
|
if (low == 0b1110) return MULU;
|
|
if (low == 0b1011) return OR;
|
|
if (low == 0b1000) return TST;
|
|
if (low == 0b1010) return XOR;
|
|
if (low == 0b1101) return XTRCT;
|
|
}
|
|
if (high == 0b0011) {
|
|
if (low == 0b1100) return ADD;
|
|
if (low == 0b1110) return ADDC;
|
|
if (low == 0b1111) return ADDV;
|
|
if (low == 0b0000) return CMPEQ;
|
|
if (low == 0b0011) return CMPGE;
|
|
if (low == 0b0111) return CMPGT;
|
|
if (low == 0b0110) return CMPHI;
|
|
if (low == 0b0010) return CMPHS;
|
|
if (low == 0b0100) return DIV1;
|
|
if (low == 0b1101) return DMULS;
|
|
if (low == 0b0101) return DMULU;
|
|
if (low == 0b1000) return SUB;
|
|
if (low == 0b1010) return SUBC;
|
|
if (low == 0b1011) return SUBV;
|
|
}
|
|
if (high == 0b0000) {
|
|
if (low == 0b1111) return MACL_;
|
|
if (low == 0b0100) return MOVBS0;
|
|
if (low == 0b0101) return MOVWS0;
|
|
if (low == 0b0110) return MOVLS0;
|
|
if (low == 0b1100) return MOVBL0;
|
|
if (low == 0b1101) return MOVWL0;
|
|
if (low == 0b1110) return MOVLL0;
|
|
if (low == 0b0111) return MULL;
|
|
}
|
|
if (high == 0b0100) {
|
|
if (low == 0b1111) return MACW;
|
|
if (low == 0b1100) return SHAD;
|
|
if (low == 0b1101) return SHLD;
|
|
}
|
|
|
|
print_binary(instruction, 16);
|
|
critical_error(" => Unknown instruction: 0x%04X\n", instruction);
|
|
}
|
|
|
|
struct SR0 {
|
|
unsigned long dummy0:22;
|
|
unsigned long M0:1;
|
|
unsigned long Q0:1;
|
|
unsigned long I0:4;
|
|
unsigned long dummy1:2;
|
|
unsigned long S0:1;
|
|
unsigned long T0:1;
|
|
};
|
|
|
|
#define M ((*(struct SR0 *)(&SR)).M0)
|
|
#define Q ((*(struct SR0 *)(&SR)).Q0)
|
|
#define S ((*(struct SR0 *)(&SR)).S0)
|
|
#define T ((*(struct SR0 *)(&SR)).T0)
|
|
|
|
#define SR cpu->sr
|
|
#define GBR cpu->gbr
|
|
#define SGR cpu->sgr
|
|
#define VBR cpu->vbr
|
|
#define SSR cpu->ssr
|
|
#define SPC cpu->spc
|
|
#define DBR cpu->dbr
|
|
|
|
#define PC cpu->pc
|
|
#define PR cpu->pr
|
|
#define R cpu->r
|
|
#define R0 cpu->r[0]
|
|
#define MACH cpu->mach
|
|
#define MACL cpu->macl
|
|
|
|
#define Read_Byte(addr) mem_read(cpu, addr, 1)
|
|
#define Read_Word(addr) mem_read(cpu, addr, 2)
|
|
#define Read_Long(addr) mem_read(cpu, addr, 4)
|
|
|
|
#define Write_Byte(addr, data) mem_write(cpu, addr, data, 1)
|
|
#define Write_Word(addr, data) mem_write(cpu, addr, data, 2)
|
|
#define Write_Long(addr, data) mem_write(cpu, addr, data, 4)
|
|
|
|
#define Delay_Slot(pc_next) \
|
|
uint32_t pc_save = cpu->pc; \
|
|
cpu->pc = pc_next; \
|
|
run_next_instruction(cpu); \
|
|
cpu->pc = pc_save;
|
|
|
|
#define is_32bit_instruction(addr) is_32bit_instruction_impl(cpu, addr)
|
|
|
|
int is_32bit_instruction_impl(cpu_t* cpu, int addr) {
|
|
// TODO
|
|
return 0;
|
|
}
|
|
|
|
// ADD / Rm,Rn - 0011nnnnmmmm1100
|
|
void ADD(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
R[n] += R[m];
|
|
PC += 2;
|
|
}
|
|
|
|
// ADDI / #imm,Rn - 0111nnnniiiiiiii
|
|
void ADDI(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long i = instruction & 0xFF;
|
|
|
|
if ((i&0x80)==0)
|
|
R[n] += (0x000000FF & (long)i);
|
|
else R[n] += (0xFFFFFF00 | (long)i);
|
|
PC += 2;
|
|
}
|
|
|
|
// ADDC / Rm,Rn - 0011nnnnmmmm1110
|
|
void ADDC(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
unsigned long tmp0,tmp1;
|
|
tmp1 = R[n] + R[m];
|
|
tmp0 = R[n];
|
|
R[n] = tmp1 + T;
|
|
if (tmp0>tmp1) T = 1;
|
|
else T = 0;
|
|
if (tmp1>R[n]) T = 1;
|
|
PC += 2;
|
|
}
|
|
|
|
// ADDV / Rm,Rn - 0011nnnnmmmm1111
|
|
void ADDV(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
long dest,src,ans;
|
|
if ((long)R[n]>=0) dest = 0;
|
|
else dest = 1;
|
|
if ((long)R[m]>=0) src = 0;
|
|
else src = 1;
|
|
src += dest;
|
|
R[n] += R[m];
|
|
if ((long)R[n]>=0) ans = 0;
|
|
else ans = 1;
|
|
ans += dest;
|
|
if (src==0 || src==2) {
|
|
if (ans==1) T = 1;
|
|
else T = 0;
|
|
}
|
|
else T = 0;
|
|
PC += 2;
|
|
}
|
|
|
|
// AND / Rm,Rn - 0010nnnnmmmm1001
|
|
void AND(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
R[n] &= R[m];
|
|
PC += 2;
|
|
}
|
|
|
|
// ANDI / #imm,R0 - 11001001iiiiiiii
|
|
void ANDI(cpu_t* cpu, uint16_t instruction) {
|
|
long i = instruction & 0xFF;
|
|
|
|
R[0] &= (0x000000FF & (long)i);
|
|
PC += 2;
|
|
}
|
|
|
|
// ANDM / #imm,@(R0,GBR) - 11001101iiiiiiii
|
|
void ANDM(cpu_t* cpu, uint16_t instruction) {
|
|
long i = instruction & 0xFF;
|
|
|
|
long temp;
|
|
temp = (long)Read_Byte(GBR+R[0]);
|
|
temp &= (0x000000FF & (long)i);
|
|
Write_Byte(GBR+R[0],temp);
|
|
PC += 2;
|
|
}
|
|
|
|
// BF / label - 10001011dddddddd
|
|
void BF(cpu_t* cpu, uint16_t instruction) {
|
|
int d = instruction & 0xFF;
|
|
|
|
int disp;
|
|
if ((d&0x80)==0)
|
|
disp = (0x000000FF & d);
|
|
else disp = (0xFFFFFF00 | d);
|
|
if (T==0)
|
|
PC = PC+4+(disp<<1);
|
|
else PC += 2;
|
|
}
|
|
|
|
// BFS / label - 10001111dddddddd
|
|
void BFS(cpu_t* cpu, uint16_t instruction) {
|
|
int d = instruction & 0xFF;
|
|
|
|
int disp;
|
|
unsigned int temp;
|
|
temp = PC;
|
|
if ((d&0x80)==0)
|
|
disp = (0x000000FF & d);
|
|
else disp = (0xFFFFFF00 | d);
|
|
if (T==0)
|
|
PC = PC + 4 + (disp<<1);
|
|
else PC += 4;
|
|
Delay_Slot(temp+2);
|
|
}
|
|
|
|
// BRA / label - 1010dddddddddddd
|
|
void BRA(cpu_t* cpu, uint16_t instruction) {
|
|
int d = instruction & 0xFFF;
|
|
|
|
int disp;
|
|
unsigned int temp;
|
|
temp = PC;
|
|
if ((d&0x800)==0)
|
|
disp = (0x00000FFF & d);
|
|
else disp = (0xFFFFF000 | d);
|
|
PC = PC + 4 + (disp<<1);
|
|
Delay_Slot(temp+2);
|
|
}
|
|
|
|
// BRAF / Rn - 0000nnnn00100011
|
|
void BRAF(cpu_t* cpu, uint16_t instruction) {
|
|
int n = (instruction >> 8) & 0xF;
|
|
|
|
unsigned int temp;
|
|
temp = PC;
|
|
PC = PC + 4 + R[n];
|
|
Delay_Slot(temp+2);
|
|
}
|
|
|
|
// BT / label - 10001001dddddddd
|
|
void BT(cpu_t* cpu, uint16_t instruction) {
|
|
int d = instruction & 0xFF;
|
|
|
|
int disp;
|
|
if ((d&0x80)==0)
|
|
disp = (0x000000FF & d);
|
|
else disp = (0xFFFFFF00 | d);
|
|
if (T==1)
|
|
PC = PC + 4 + (disp<<1);
|
|
else PC += 2;
|
|
}
|
|
|
|
// BTS / label - 10001101dddddddd
|
|
void BTS(cpu_t* cpu, uint16_t instruction) {
|
|
int d = instruction & 0xFF;
|
|
|
|
int disp;
|
|
unsigned temp;
|
|
temp = PC;
|
|
if ((d&0x80)==0)
|
|
disp = (0x000000FF & d);
|
|
else disp = (0xFFFFFF00 | d);
|
|
if (T==1)
|
|
PC = PC + 4 + (disp<<1);
|
|
else PC += 4;
|
|
Delay_Slot(temp+2);
|
|
}
|
|
|
|
// CLRMAC / 0 - 0000000000101000
|
|
void CLRMAC(cpu_t* cpu, uint16_t instruction) {
|
|
|
|
MACH = 0;
|
|
MACL = 0;
|
|
PC += 2;
|
|
}
|
|
|
|
// CLRS / 0 - 0000000001001000
|
|
void CLRS(cpu_t* cpu, uint16_t instruction) {
|
|
|
|
S = 0;
|
|
PC += 2;
|
|
}
|
|
|
|
// CLRT / 0 - 0000000000001000
|
|
void CLRT(cpu_t* cpu, uint16_t instruction) {
|
|
|
|
T = 0;
|
|
PC += 2;
|
|
}
|
|
|
|
// CMPEQ / Rm,Rn - 0011nnnnmmmm0000
|
|
void CMPEQ(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
if (R[n]==R[m]) T = 1;
|
|
else T = 0;
|
|
PC += 2;
|
|
}
|
|
|
|
// CMPGE / Rm,Rn - 0011nnnnmmmm0011
|
|
void CMPGE(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
if ((long)R[n]>=(long)R[m]) T = 1;
|
|
else T = 0;
|
|
PC += 2;
|
|
}
|
|
|
|
// CMPGT / Rm,Rn - 0011nnnnmmmm0111
|
|
void CMPGT(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
if ((long)R[n]>(long)R[m]) T = 1;
|
|
else T = 0;
|
|
PC += 2;
|
|
}
|
|
|
|
// CMPHI / Rm,Rn - 0011nnnnmmmm0110
|
|
void CMPHI(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
if ((unsigned long)R[n]>(unsigned long)R[m]) T = 1;
|
|
else T = 0;
|
|
PC += 2;
|
|
}
|
|
|
|
// CMPHS / Rm,Rn - 0011nnnnmmmm0010
|
|
void CMPHS(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
if ((unsigned long)R[n]>=(unsigned long)R[m]) T = 1;
|
|
else T = 0;
|
|
PC += 2;
|
|
}
|
|
|
|
// CMPPL / Rn - 0100nnnn00010101
|
|
void CMPPL(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
|
|
if ((long)R[n]>0) T = 1;
|
|
else T = 0;
|
|
PC += 2;
|
|
}
|
|
|
|
// CMPPZ / Rn - 0100nnnn00010001
|
|
void CMPPZ(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
|
|
if ((long)R[n]>=0) T = 1;
|
|
else T = 0;
|
|
PC += 2;
|
|
}
|
|
|
|
// CMPSTR / Rm,Rn - 0010nnnnmmmm1100
|
|
void CMPSTR(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
unsigned long temp;
|
|
long HH,HL,LH,LL;
|
|
temp=R[n]^R[m];
|
|
HH = (temp & 0xFF000000) >> 24;
|
|
HL = (temp & 0x00FF0000) >> 16;
|
|
LH = (temp & 0x0000FF00) >> 8;
|
|
LL = temp & 0x000000FF;
|
|
HH = HH && HL && LH && LL;
|
|
if (HH==0) T = 1;
|
|
else T = 0;
|
|
PC += 2;
|
|
}
|
|
|
|
// CMPIM / #imm,R0 - 10001000iiiiiiii
|
|
void CMPIM(cpu_t* cpu, uint16_t instruction) {
|
|
long i = instruction & 0xFF;
|
|
|
|
long imm;
|
|
if ((i&0x80)==0) imm=(0x000000FF & (long) i);
|
|
else imm=(0xFFFFFF00 | (long) i);
|
|
if (R[0]==imm) T = 1;
|
|
else T = 0;
|
|
PC += 2;
|
|
}
|
|
|
|
// DIV0S / Rm,Rn - 0010nnnnmmmm0111
|
|
void DIV0S(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
if ((R[n] & 0x80000000)==0) Q = 0;
|
|
else Q = 1;
|
|
if ((R[m] & 0x80000000)==0) M = 0;
|
|
else M = 1;
|
|
T = !(M==Q);
|
|
PC += 2;
|
|
}
|
|
|
|
// DIV0U / 0 - 0000000000011001
|
|
void DIV0U(cpu_t* cpu, uint16_t instruction) {
|
|
|
|
M = Q = T = 0;
|
|
PC += 2;
|
|
}
|
|
|
|
// DIV1 / Rm,Rn - 0011nnnnmmmm0100
|
|
void DIV1(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
unsigned long tmp0, tmp2;
|
|
unsigned char old_q, tmp1;
|
|
old_q = Q;
|
|
Q = (unsigned char)((0x80000000 & R[n])!=0);
|
|
tmp2 = R[m];
|
|
R[n] <<= 1;
|
|
R[n] |= (unsigned long)T;
|
|
switch(old_q){
|
|
case 0:switch(M){
|
|
case 0:tmp0 = R[n];
|
|
R[n] -= tmp2;
|
|
tmp1 = (R[n]>tmp0);
|
|
switch(Q){
|
|
case 0:Q = tmp1;
|
|
break;
|
|
case 1:Q = (unsigned char)(tmp1==0);
|
|
break;
|
|
}
|
|
break;
|
|
case 1:tmp0 = R[n];
|
|
R[n] += tmp2;
|
|
tmp1 = (R[n]<tmp0);
|
|
switch(Q){
|
|
case 0:Q = (unsigned char)(tmp1==0);
|
|
break;
|
|
case 1:Q = tmp1;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
case 1:switch(M){
|
|
case 0:tmp0 = R[n];
|
|
R[n] += tmp2;
|
|
tmp1 = (R[n]<tmp0);
|
|
switch(Q){
|
|
case 0:Q = tmp1;
|
|
break;
|
|
case 1:Q = (unsigned char)(tmp1==0);
|
|
break;
|
|
}
|
|
break;
|
|
case 1:tmp0 = R[n];
|
|
R[n] -= tmp2;
|
|
tmp1 = (R[n]>tmp0);
|
|
switch(Q){
|
|
case 0:Q = (unsigned char)(tmp1==0);
|
|
break;
|
|
case 1:Q = tmp1;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
T = (Q==M);
|
|
PC += 2;
|
|
}
|
|
|
|
// DMULS / Rm,Rn - 0011nnnnmmmm1101
|
|
void DMULS(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
unsigned long RnL,RnH,RmL,RmH,Res0,Res1,Res2;
|
|
unsigned long temp0,temp1,temp2,temp3;
|
|
long tempm,tempn,fnLmL;
|
|
tempn = (long)R[n];
|
|
tempm = (long)R[m];
|
|
if (tempn<0) tempn = 0 - tempn;
|
|
if (tempm<0) tempm = 0 - tempm;
|
|
if ((long)(R[n]^R[m])<0) fnLmL = -1;
|
|
else fnLmL = 0;
|
|
temp1 = (unsigned long)tempn;
|
|
temp2 = (unsigned long)tempm;
|
|
RnL = temp1&0x0000FFFF;
|
|
RnH = (temp1>>16)&0x0000FFFF;
|
|
RmL = temp2&0x0000FFFF;
|
|
RmH = (temp2>>16)&0x0000FFFF;
|
|
temp0 = RmL*RnL;
|
|
temp1 = RmH*RnL;
|
|
temp2 = RmL*RnH;
|
|
temp3 = RmH*RnH;
|
|
Res2 = 0;
|
|
Res1 = temp1+temp2;
|
|
if (Res1<temp1) Res2 += 0x00010000;
|
|
temp1 = (Res1<<16)&0xFFFF0000;
|
|
Res0 = temp0 + temp1;
|
|
if (Res0<temp0) Res2++;
|
|
Res2 = Res2 + ((Res1>>16)&0x0000FFFF) + temp3;
|
|
if (fnLmL<0) {
|
|
Res2 = ~
|
|
Res2;
|
|
if (Res0==0)
|
|
Res2++;
|
|
else
|
|
Res0 = (~
|
|
Res0) + 1;
|
|
}
|
|
MACH = Res2;
|
|
MACL = Res0;
|
|
PC +=2;
|
|
}
|
|
|
|
// DMULU / Rm,Rn - 0011nnnnmmmm0101
|
|
void DMULU(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
unsigned long RnL,RnH,RmL,RmH,Res0,Res1,Res2;
|
|
unsigned long temp0,temp1,temp2,temp3;
|
|
RnL = R[n] & 0x0000FFFF;
|
|
RnH = (R[n]>>16) & 0x0000FFFF;
|
|
RmL = R[m] & 0x0000FFFF;
|
|
RmH = (R[m]>>16) & 0x0000FFFF;
|
|
temp0 = RmL*RnL;
|
|
temp1 = RmH*RnL;
|
|
temp2 = RmL*RnH;
|
|
temp3 = RmH*RnH;
|
|
Res2 = 0;
|
|
Res1 = temp1 + temp2;
|
|
if (Res1<temp1) Res2 += 0x00010000;
|
|
temp1 = (Res1<<16) & 0xFFFF0000;
|
|
Res0 = temp0 + temp1;
|
|
if (Res0<temp0) Res2++;
|
|
Res2 = Res2 + ((Res1>>16)&0x0000FFFF) + temp3;
|
|
MACH = Res2;
|
|
MACL = Res0;
|
|
PC += 2;
|
|
}
|
|
|
|
// DT / Rn - 0100nnnn00010000
|
|
void DT(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
|
|
R[n]--;
|
|
if (R[n]==0) T = 1;
|
|
else T = 0;
|
|
PC += 2;
|
|
}
|
|
|
|
// EXTSB / Rm,Rn - 0110nnnnmmmm1110
|
|
void EXTSB(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
R[n] = R[m];
|
|
if ((R[m] & 0x00000080)==0) R[n] &=0x000000FF;
|
|
else R[n] |= 0xFFFFFF00;
|
|
PC += 2;
|
|
}
|
|
|
|
// EXTSW / Rm,Rn - 0110nnnnmmmm1111
|
|
void EXTSW(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
R[n] = R[m];
|
|
if ((R[m] & 0x00008000)==0) R[n] &=0x0000FFFF;
|
|
else R[n] |= 0xFFFF0000;
|
|
PC += 2;
|
|
}
|
|
|
|
// EXTUB / Rm,Rn - 0110nnnnmmmm1100
|
|
void EXTUB(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
R[n] = R[m];
|
|
R[n] &= 0x000000FF;
|
|
PC += 2;
|
|
}
|
|
|
|
// EXTUW / Rm,Rn - 0110nnnnmmmm1101
|
|
void EXTUW(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
R[n] = R[m];
|
|
R[n] &= 0x0000FFFF;
|
|
PC += 2;
|
|
}
|
|
|
|
// JMP / @Rn - 0100nnnn00101011
|
|
void JMP(cpu_t* cpu, uint16_t instruction) {
|
|
int n = (instruction >> 8) & 0xF;
|
|
|
|
unsigned int temp;
|
|
temp = PC;
|
|
PC = R[n];
|
|
Delay_Slot(temp+2);
|
|
}
|
|
|
|
// LDCGBR / Rm,GBR - 0100mmmm00011110
|
|
void LDCGBR(cpu_t* cpu, uint16_t instruction) {
|
|
int m = (instruction >> 8) & 0xF;
|
|
|
|
GBR = R[m];
|
|
PC += 2;
|
|
}
|
|
|
|
// LDCVBR / Rm,VBR - 0100mmmm00101110
|
|
void LDCVBR(cpu_t* cpu, uint16_t instruction) {
|
|
int m = (instruction >> 8) & 0xF;
|
|
|
|
VBR = R[m];
|
|
PC += 2;
|
|
}
|
|
|
|
// LDCSGR / Rm,SGR - 0100mmmm00111010
|
|
void LDCSGR(cpu_t* cpu, uint16_t instruction) {
|
|
int m = (instruction >> 8) & 0xF;
|
|
|
|
SGR = R[m];
|
|
PC += 2;
|
|
}
|
|
|
|
// LDCSSR / Rm,SSR - 0100mmmm00111110
|
|
void LDCSSR(cpu_t* cpu, uint16_t instruction) {
|
|
int m = (instruction >> 8) & 0xF;
|
|
|
|
SSR = R[m],
|
|
PC += 2;
|
|
}
|
|
|
|
// LDCSPC / Rm,SPC - 0100mmmm01001110
|
|
void LDCSPC(cpu_t* cpu, uint16_t instruction) {
|
|
int m = (instruction >> 8) & 0xF;
|
|
|
|
SPC = R[m];
|
|
PC += 2;
|
|
}
|
|
|
|
// LDCDBR / Rm,DBR - 0100mmmm11111010
|
|
void LDCDBR(cpu_t* cpu, uint16_t instruction) {
|
|
int m = (instruction >> 8) & 0xF;
|
|
|
|
DBR = R[m];
|
|
PC += 2;
|
|
}
|
|
|
|
// LDCMGBR / @Rm+,GBR - 0100mmmm00010111
|
|
void LDCMGBR(cpu_t* cpu, uint16_t instruction) {
|
|
int m = (instruction >> 8) & 0xF;
|
|
|
|
GBR=Read_Long(R[m]);
|
|
R[m] += 4;
|
|
PC += 2;
|
|
}
|
|
|
|
// LDCMVBR / @Rm+,VBR - 0100mmmm00100111
|
|
void LDCMVBR(cpu_t* cpu, uint16_t instruction) {
|
|
int m = (instruction >> 8) & 0xF;
|
|
|
|
VBR = Read_Long(R[m]);
|
|
R[m] += 4;
|
|
PC += 2;
|
|
}
|
|
|
|
// LDCMSGR / @Rm+,SGR - 0100mmmm00110110
|
|
void LDCMSGR(cpu_t* cpu, uint16_t instruction) {
|
|
int m = (instruction >> 8) & 0xF;
|
|
|
|
SGR = Read_Long(R[m]);
|
|
R[m] += 4;
|
|
PC += 2;
|
|
}
|
|
|
|
// LDCMSSR / @Rm+,SSR - 0100mmmm00110111
|
|
void LDCMSSR(cpu_t* cpu, uint16_t instruction) {
|
|
int m = (instruction >> 8) & 0xF;
|
|
|
|
SSR=Read_Long(R[m]);
|
|
R[m] += 4;
|
|
PC += 2;
|
|
}
|
|
|
|
// LDCMSPC / @Rm+,SPC - 0100mmmm01000111
|
|
void LDCMSPC(cpu_t* cpu, uint16_t instruction) {
|
|
int m = (instruction >> 8) & 0xF;
|
|
|
|
SPC = Read_Long(R[m]);
|
|
R[m] += 4;
|
|
PC += 2;
|
|
}
|
|
|
|
// LDCMDBR / @Rm+,DBR - 0100mmmm11110110
|
|
void LDCMDBR(cpu_t* cpu, uint16_t instruction) {
|
|
int m = (instruction >> 8) & 0xF;
|
|
|
|
DBR = Read_Long(R[m]);
|
|
R[m] += 4;
|
|
PC += 2;
|
|
}
|
|
|
|
// LDSMACH / Rm,MACH - 0100mmmm00001010
|
|
void LDSMACH(cpu_t* cpu, uint16_t instruction) {
|
|
long m = (instruction >> 8) & 0xF;
|
|
|
|
MACH = R[m];
|
|
PC += 2;
|
|
}
|
|
|
|
// LDSMACL / Rm,MACL - 0100mmmm00011010
|
|
void LDSMACL(cpu_t* cpu, uint16_t instruction) {
|
|
long m = (instruction >> 8) & 0xF;
|
|
|
|
MACL = R[m];
|
|
PC += 2;
|
|
}
|
|
|
|
// LDSPR / Rm,PR - 0100mmmm00101010
|
|
void LDSPR(cpu_t* cpu, uint16_t instruction) {
|
|
long m = (instruction >> 8) & 0xF;
|
|
|
|
PR = R[m];
|
|
PC += 2;
|
|
}
|
|
|
|
// LDSMMACH / @Rm+,MACH - 0100mmmm00000110
|
|
void LDSMMACH(cpu_t* cpu, uint16_t instruction) {
|
|
long m = (instruction >> 8) & 0xF;
|
|
|
|
MACH = Read_Long(R[m]);
|
|
R[m] += 4;
|
|
PC += 2;
|
|
}
|
|
|
|
// LDSMMACL / @Rm+,MACL - 0100mmmm00010110
|
|
void LDSMMACL(cpu_t* cpu, uint16_t instruction) {
|
|
long m = (instruction >> 8) & 0xF;
|
|
|
|
MACL = Read_Long(R[m]);
|
|
R[m] += 4;
|
|
PC += 2;
|
|
}
|
|
|
|
// LDSMPR / @Rm+,PR - 0100mmmm00100110
|
|
void LDSMPR(cpu_t* cpu, uint16_t instruction) {
|
|
long m = (instruction >> 8) & 0xF;
|
|
|
|
PR = Read_Long(R[m]);
|
|
R[m] += 4;
|
|
PC += 2;
|
|
}
|
|
|
|
// MACL_ / @Rm+,@Rn+ - 0000nnnnmmmm1111
|
|
void MACL_(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
unsigned long RnL,RnH,RmL,RmH,Res0,Res1,Res2;
|
|
unsigned long temp0,temp1,temp2,temp3;
|
|
long tempm,tempn,fnLmL;
|
|
tempn = (long)Read_Long(R[n]);
|
|
R[n] += 4;
|
|
tempm = (long)Read_Long(R[m]);
|
|
R[m] += 4;
|
|
if ((long)(tempn^tempm)<0) fnLmL = -1;
|
|
else fnLmL = 0;
|
|
if (tempn<0) tempn = 0-tempn;
|
|
if (tempm<0) tempm = 0-tempm;
|
|
temp1 = (unsigned long)tempn;
|
|
temp2 = (unsigned long)tempm;
|
|
RnL = temp1&0x0000FFFF;
|
|
RnH = (temp1>>16) & 0x0000FFFF;
|
|
RmL = temp2 & 0x0000FFFF;
|
|
RmH = (temp2>>16) & 0x0000FFFF;
|
|
temp0 = RmL*RnL;
|
|
temp1 = RmH*RnL;
|
|
temp2 = RmL*RnH;
|
|
temp3 = RmH*RnH;
|
|
Res2 = 0;
|
|
Res1 = temp1 + temp2;
|
|
if (Res1<temp1) Res2 += 0x00010000;
|
|
temp1 =(Res1<<16) & 0xFFFF0000;
|
|
Res0 = temp0 + temp1;
|
|
if (Res0<temp0) Res2++;
|
|
Res2 = Res2 + ((Res1>>16) & 0x0000FFFF) + temp3;
|
|
if(fnLmL<0){
|
|
Res2 = ~
|
|
Res2;
|
|
if (Res0==0) Res2++;
|
|
else Res0 = (~
|
|
Res0)+1;
|
|
}
|
|
if(S==1){
|
|
Res0 = MACL + Res0;
|
|
if (MACL>Res0) Res2++;
|
|
if (MACH & 0x00008000);
|
|
else Res2 += MACH|0xFFFF0000;
|
|
Res2 += MACH&0x00007FFF;
|
|
if(((long)Res2<0)&&(Res2 < 0xFFFF8000)){
|
|
Res2 = 0xFFFF8000;
|
|
Res0 = 0x00000000;
|
|
}
|
|
if(((long)Res2>0)&&(Res2 > 0x00007FFF)){
|
|
Res2 = 0x00007FFF;
|
|
Res0 = 0xFFFFFFFF;
|
|
};
|
|
MACH = (Res2 & 0x0000FFFF)|(MACH & 0xFFFF0000);
|
|
MACL = Res0;
|
|
}
|
|
else {
|
|
Res0 = MACL + Res0;
|
|
if (MACL>Res0) Res2++;
|
|
Res2 += MACH;
|
|
MACH = Res2;
|
|
MACL = Res0;
|
|
}
|
|
PC += 2;
|
|
}
|
|
|
|
// MACW / @Rm+,@Rn+ - 0100nnnnmmmm1111
|
|
void MACW(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
long tempm,tempn,dest,src,ans;
|
|
unsigned long templ;
|
|
tempn = (long)Read_Word(R[n]);
|
|
R[n] += 2;
|
|
tempm = (long)Read_Word(R[m]);
|
|
R[m] += 2;
|
|
templ = MACL;
|
|
tempm = ((long)(short)tempn*(long)(short)tempm);
|
|
if ((long)MACL>=0) dest = 0;
|
|
else dest = 1;
|
|
if ((long)tempm>=0) {
|
|
src = 0;
|
|
tempn = 0;
|
|
}
|
|
else {
|
|
src = 1;
|
|
tempn = 0xFFFFFFFF;
|
|
}
|
|
src += dest;
|
|
MACL += tempm;
|
|
if ((long)MACL>=0) ans = 0;
|
|
else ans = 1;
|
|
ans += dest;
|
|
if (S==1) {
|
|
if (ans==1) {
|
|
if (src==0) MACL = 0x7FFFFFFF;
|
|
if (src==2) MACL = 0x80000000;
|
|
}
|
|
}
|
|
else {
|
|
MACH += tempn;
|
|
if (templ>MACL) MACH += 1;
|
|
}
|
|
PC += 2;
|
|
}
|
|
|
|
// MOV / Rm,Rn - 0110nnnnmmmm0011
|
|
void MOV(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
R[n] = R[m];
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVBS / Rm,@Rn - 0010nnnnmmmm0000
|
|
void MOVBS(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
Write_Byte(R[n],R[m]);
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVWS / Rm,@Rn - 0010nnnnmmmm0001
|
|
void MOVWS(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
Write_Word(R[n],R[m]);
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVLS / Rm,@Rn - 0010nnnnmmmm0010
|
|
void MOVLS(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
Write_Long(R[n],R[m]);
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVBL / @Rm,Rn - 0110nnnnmmmm0000
|
|
void MOVBL(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
R[n] = (long)Read_Byte(R[m]);
|
|
if ((R[n]&0x80)==0) R[n] &= 0x000000FF;
|
|
else R[n] |= 0xFFFFFF00;
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVWL / @Rm,Rn - 0110nnnnmmmm0001
|
|
void MOVWL(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
R[n] = (long)Read_Word(R[m]);
|
|
if ((R[n]&0x8000)==0) R[n] &= 0x0000FFFF;
|
|
else R[n] |= 0xFFFF0000;
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVLL / @Rm,Rn - 0110nnnnmmmm0010
|
|
void MOVLL(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
R[n] = Read_Long(R[m]);
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVBM / Rm,@-Rn - 0010nnnnmmmm0100
|
|
void MOVBM(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
Write_Byte(R[n]-1,R[m]);
|
|
R[n] -= 1;
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVWM / Rm,@-Rn - 0010nnnnmmmm0101
|
|
void MOVWM(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
Write_Word(R[n]-2,R[m]);
|
|
R[n] -= 2;
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVLM / Rm,@-Rn - 0010nnnnmmmm0110
|
|
void MOVLM(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
Write_Long(R[n]-4,R[m]);
|
|
R[n] -= 4;
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVBP / @Rm+,Rn - 0110nnnnmmmm0100
|
|
void MOVBP(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
R[n] = (long)Read_Byte(R[m]);
|
|
if ((R[n]&0x80)==0) R[n] &= 0x000000FF;
|
|
else R[n] |= 0xFFFFFF00;
|
|
if (n!=m) R[m] += 1;
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVWP / @Rm+,Rn - 0110nnnnmmmm0101
|
|
void MOVWP(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
R[n] = (long)Read_Word(R[m]);
|
|
if ((R[n]&0x8000)==0) R[n] &= 0x0000FFFF;
|
|
else R[n] |= 0xFFFF0000;
|
|
if (n!=m) R[m] += 2;
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVLP / @Rm+,Rn - 0110nnnnmmmm0110
|
|
void MOVLP(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
R[n] = Read_Long(R[m]);
|
|
if (n!=m) R[m] += 4;
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVBS0 / Rm,@(R0,Rn) - 0000nnnnmmmm0100
|
|
void MOVBS0(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
Write_Byte(R[n]+R[0],R[m]);
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVWS0 / Rm,@(R0,Rn) - 0000nnnnmmmm0101
|
|
void MOVWS0(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
Write_Word(R[n]+R[0],R[m]);
|
|
PC+=2;
|
|
}
|
|
|
|
// MOVLS0 / Rm,@(R0,Rn) - 0000nnnnmmmm0110
|
|
void MOVLS0(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
Write_Long(R[n]+R[0],R[m]);
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVBL0 / @(R0,Rm),Rn - 0000nnnnmmmm1100
|
|
void MOVBL0(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
R[n] = (long)Read_Byte(R[m]+R[0]);
|
|
if ((R[n]&0x80)==0) R[n] &= 0x000000FF;
|
|
else R[n] |= 0xFFFFFF00;
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVWL0 / @(R0,Rm),Rn - 0000nnnnmmmm1101
|
|
void MOVWL0(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
R[n] = (long)Read_Word(R[m]+R[0]);
|
|
if ((R[n]&0x8000)==0) R[n] &= 0x0000FFFF;
|
|
else R[n] |= 0xFFFF0000;
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVLL0 / @(R0,Rm),Rn - 0000nnnnmmmm1110
|
|
void MOVLL0(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
R[n] = Read_Long(R[m]+R[0]);
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVI / #imm,Rn - 1110nnnniiiiiiii
|
|
void MOVI(cpu_t* cpu, uint16_t instruction) {
|
|
int n = (instruction >> 8) & 0xF;
|
|
int i = instruction & 0xFF;
|
|
|
|
if ((i&0x80)==0) R[n] = (0x000000FF & i);
|
|
else R[n] = (0xFFFFFF00 | i);
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVWI / @(disp*,PC),Rn - 1001nnnndddddddd
|
|
void MOVWI(cpu_t* cpu, uint16_t instruction) {
|
|
int n = (instruction >> 8) & 0xF;
|
|
int d = instruction & 0xFF;
|
|
|
|
unsigned int disp;
|
|
disp = (unsigned int)(0x000000FF & d);
|
|
R[n] = (int)Read_Word(PC+4+(disp<<1));
|
|
if ((R[n]&0x8000)==0) R[n] &= 0x0000FFFF;
|
|
else R[n] |= 0xFFFF0000;
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVLI / @(disp*,PC),Rn - 1101nnnndddddddd
|
|
void MOVLI(cpu_t* cpu, uint16_t instruction) {
|
|
int n = (instruction >> 8) & 0xF;
|
|
int d = instruction & 0xFF;
|
|
|
|
unsigned int disp;
|
|
disp = (unsigned int)(0x000000FF & (int)d);
|
|
R[n] = Read_Long((PC & 0xFFFFFFFC)+4+(disp<<2));
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVBLG / @(disp*,GBR),R0 - 11000100dddddddd
|
|
void MOVBLG(cpu_t* cpu, uint16_t instruction) {
|
|
int d = instruction & 0xFF;
|
|
|
|
unsigned int disp;
|
|
disp = (unsigned int)(0x000000FF & d);
|
|
R[0] = (int)Read_Byte(GBR+disp);
|
|
if ((R[0]&0x80)==0) R[0] &= 0x000000FF;
|
|
else R[0] |= 0xFFFFFF00;
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVWLG / @(disp*,GBR),R0 - 11000101dddddddd
|
|
void MOVWLG(cpu_t* cpu, uint16_t instruction) {
|
|
int d = instruction & 0xFF;
|
|
|
|
unsigned int disp;
|
|
disp = (unsigned int)(0x000000FF & d);
|
|
R[0] = (int)Read_Word(GBR+(disp<<1));
|
|
if ((R[0]&0x8000)==0) R[0] &= 0x0000FFFF;
|
|
else R[0] |= 0xFFFF0000;
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVLLG / @(disp*,GBR),R0 - 11000110dddddddd
|
|
void MOVLLG(cpu_t* cpu, uint16_t instruction) {
|
|
int d = instruction & 0xFF;
|
|
|
|
unsigned int disp;
|
|
disp = (unsigned int)(0x000000FF & d);
|
|
R[0] = Read_Long(GBR+(disp<<2));
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVBSG / R0,@(disp*,GBR) - 11000000dddddddd
|
|
void MOVBSG(cpu_t* cpu, uint16_t instruction) {
|
|
int d = instruction & 0xFF;
|
|
|
|
unsigned int disp;
|
|
disp = (unsigned int)(0x000000FF & d);
|
|
Write_Byte(GBR+disp,R[0]);
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVWSG / R0,@(disp*,GBR) - 11000001dddddddd
|
|
void MOVWSG(cpu_t* cpu, uint16_t instruction) {
|
|
int d = instruction & 0xFF;
|
|
|
|
unsigned int disp;
|
|
disp = (unsigned int)(0x000000FF & d);
|
|
Write_Word(GBR+(disp<<1),R[0]);
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVLSG / R0,@(disp*,GBR) - 11000010dddddddd
|
|
void MOVLSG(cpu_t* cpu, uint16_t instruction) {
|
|
int d = instruction & 0xFF;
|
|
|
|
unsigned int disp;
|
|
disp = (unsigned int)(0x000000FF & (long)d);
|
|
Write_Long(GBR+(disp<<2),R[0]);
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVBS4 / R0,@(disp*,Rn) - 10000000nnnndddd
|
|
void MOVBS4(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 4) & 0xF;
|
|
long d = instruction & 0xF;
|
|
|
|
long disp;
|
|
disp = (0x0000000F & (long)d);
|
|
Write_Byte(R[n]+disp,R[0]);
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVWS4 / R0,@(disp*,Rn) - 10000001nnnndddd
|
|
void MOVWS4(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 4) & 0xF;
|
|
long d = instruction & 0xF;
|
|
|
|
long disp;
|
|
disp = (0x0000000F & (long)d);
|
|
Write_Word(R[n]+(disp<<1),R[0]);
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVLS4 / Rm,@(disp*,Rn) - 0001nnnnmmmmdddd
|
|
void MOVLS4(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
long d = instruction & 0xF;
|
|
|
|
long disp;
|
|
disp = (0x0000000F & (long)d);
|
|
Write_Long(R[n]+(disp<<2),R[m]);
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVBL4 / @(disp*,Rm),R0 - 10000100mmmmdddd
|
|
void MOVBL4(cpu_t* cpu, uint16_t instruction) {
|
|
long m = (instruction >> 4) & 0xF;
|
|
long d = instruction & 0xF;
|
|
|
|
long disp;
|
|
disp = (0x0000000F & (long)d);
|
|
R[0] = Read_Byte(R[m]+disp);
|
|
if ((R[0]&0x80)==0) R[0] &= 0x000000FF;
|
|
else R[0] |= 0xFFFFFF00;
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVWL4 / @(disp*,Rm),R0 - 10000101mmmmdddd
|
|
void MOVWL4(cpu_t* cpu, uint16_t instruction) {
|
|
long m = (instruction >> 4) & 0xF;
|
|
long d = instruction & 0xF;
|
|
|
|
long disp;
|
|
disp = (0x0000000F & (long)d);
|
|
R[0] = Read_Word(R[m]+(disp<<1));
|
|
if ((R[0]&0x8000)==0) R[0] &= 0x0000FFFF;
|
|
else R[0] |= 0xFFFF0000;
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVLL4 / @(disp*,Rm),Rn - 0101nnnnmmmmdddd
|
|
void MOVLL4(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
long d = instruction & 0xF;
|
|
|
|
long disp;
|
|
disp = (0x0000000F & (long)d);
|
|
R[n] = Read_Long(R[m]+(disp<<2));
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVA / @(disp*,PC),R0 - 11000111dddddddd
|
|
void MOVA(cpu_t* cpu, uint16_t instruction) {
|
|
int d = instruction & 0xFF;
|
|
|
|
unsigned int disp;
|
|
disp = (unsigned int)(0x000000FF & d);
|
|
R[0] = (PC&0xFFFFFFFC) + 4 + (disp<<2);
|
|
PC += 2;
|
|
}
|
|
|
|
// MOVT / Rn - 0000nnnn00101001
|
|
void MOVT(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
|
|
R[n] = (0x00000001 & SR);
|
|
PC += 2;
|
|
}
|
|
|
|
// MULL / Rm,Rn - 0000nnnnmmmm0111
|
|
void MULL(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
MACL = R[n]*R[m];
|
|
PC += 2;
|
|
}
|
|
|
|
// MULS / Rm,Rn - 0010nnnnmmmm1111
|
|
void MULS(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
MACL = ((long)(short)R[n]*(long)(short)R[m]);
|
|
PC += 2;
|
|
}
|
|
|
|
// MULU / Rm,Rn - 0010nnnnmmmm1110
|
|
void MULU(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
MACL = (unsigned long)(unsigned short)R[n]*
|
|
(unsigned long)(unsigned short)R[m];
|
|
PC += 2;
|
|
}
|
|
|
|
// NEG / Rm,Rn - 0110nnnnmmmm1011
|
|
void NEG(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
R[n] = 0-R[m];
|
|
PC += 2;
|
|
}
|
|
|
|
// NEGC / Rm,Rn - 0110nnnnmmmm1010
|
|
void NEGC(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
unsigned long temp;
|
|
temp = 0-R[m];
|
|
R[n] = temp-T;
|
|
if (0<temp) T = 1;
|
|
else T = 0;
|
|
if (temp<R[n]) T = 1;
|
|
PC += 2;
|
|
}
|
|
|
|
// NOP / No - 0000000000001001
|
|
void NOP(cpu_t* cpu, uint16_t instruction) {
|
|
|
|
PC += 2;
|
|
}
|
|
|
|
// NOT / Rm,Rn - 0110nnnnmmmm0111
|
|
void NOT(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
R[n] = ~R[m];
|
|
PC += 2;
|
|
}
|
|
|
|
// OR / Rm,Rn - 0010nnnnmmmm1011
|
|
void OR(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
R[n] |= R[m];
|
|
PC += 2;
|
|
}
|
|
|
|
// ORI / #imm,R0 - 11001011iiiiiiii
|
|
void ORI(cpu_t* cpu, uint16_t instruction) {
|
|
long i = instruction & 0xFF;
|
|
|
|
R[0] |= (0x000000FF & (long)i);
|
|
PC += 2;
|
|
}
|
|
|
|
// ORM / #imm,@(R0,GBR) - 11001111iiiiiiii
|
|
void ORM(cpu_t* cpu, uint16_t instruction) {
|
|
long i = instruction & 0xFF;
|
|
|
|
long temp;
|
|
temp = (long)Read_Byte(GBR+R[0]);
|
|
temp |= (0x000000FF & (long)i);
|
|
Write_Byte(GBR+R[0],temp);
|
|
PC += 2;
|
|
}
|
|
|
|
// PREF / @Rn - 0000nnnn10000011
|
|
void PREF(cpu_t* cpu, uint16_t instruction) {
|
|
int n = (instruction >> 8) & 0xF;
|
|
|
|
PC += 2;
|
|
}
|
|
|
|
// ROTCL / Rn - 0100nnnn00100100
|
|
void ROTCL(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
|
|
long temp;
|
|
if ((R[n] & 0x80000000)==0) temp=0;
|
|
else temp = 1;
|
|
R[n] <<= 1;
|
|
if (T==1) R[n] |= 0x00000001;
|
|
else R[n] &= 0xFFFFFFFE;
|
|
if (temp==1) T = 1;
|
|
else T = 0;
|
|
PC += 2;
|
|
}
|
|
|
|
// ROTCR / Rn - 0100nnnn00100101
|
|
void ROTCR(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
|
|
long temp;
|
|
if ((R[n] & 0x00000001)==0) temp = 0;
|
|
else temp = 1;
|
|
R[n] >>= 1;
|
|
if (T==1) R[n] |= 0x80000000;
|
|
else R[n] &= 0x7FFFFFFF;
|
|
if (temp==1) T = 1;
|
|
else T = 0;
|
|
PC += 2;
|
|
}
|
|
|
|
// ROTL / Rn - 0100nnnn00000100
|
|
void ROTL(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
|
|
if ((R[n]&0x80000000)==0) T = 0;
|
|
else T = 1;
|
|
R[n] <<= 1;
|
|
if (T==1) R[n] |= 0x00000001;
|
|
else R[n] &= 0xFFFFFFFE;
|
|
PC += 2;
|
|
}
|
|
|
|
// ROTR / Rn - 0100nnnn00000101
|
|
void ROTR(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
|
|
if ((R[n] & 0x00000001)==0) T = 0;
|
|
else T = 1;
|
|
R[n] >>= 1;
|
|
if (T==1) R[n] |= 0x80000000;
|
|
else R[n] &= 0x7FFFFFFF;
|
|
PC += 2;
|
|
}
|
|
|
|
// RTE / SSR - 0000000000101011
|
|
void RTE(cpu_t* cpu, uint16_t instruction) {
|
|
|
|
unsigned int temp;
|
|
temp = PC;
|
|
SR = SSR;
|
|
PC = SPC;
|
|
Delay_Slot(temp+2);
|
|
}
|
|
|
|
// RTS / PR - 0000000000001011
|
|
void RTS(cpu_t* cpu, uint16_t instruction) {
|
|
|
|
unsigned int temp;
|
|
temp = PC;
|
|
PC = PR;
|
|
Delay_Slot(temp+2);
|
|
}
|
|
|
|
// SETS / 1 - 0000000001011000
|
|
void SETS(cpu_t* cpu, uint16_t instruction) {
|
|
|
|
S = 1;
|
|
PC += 2;
|
|
}
|
|
|
|
// SETT / 1 - 0000000000011000
|
|
void SETT(cpu_t* cpu, uint16_t instruction) {
|
|
|
|
T = 1;
|
|
PC += 2;
|
|
}
|
|
|
|
// SHAD / Rm,Rn - 0100nnnnmmmm1100
|
|
void SHAD(cpu_t* cpu, uint16_t instruction) {
|
|
int n = (instruction >> 8) & 0xF;
|
|
int m = (instruction >> 4) & 0xF;
|
|
|
|
int sgn = R[m] & 0x80000000;
|
|
if (sgn==0)
|
|
R[n] <<= (R[m] & 0x1F);
|
|
else if ((R[m] & 0x1F) == 0) {
|
|
if ((R[n] & 0x80000000) == 0)
|
|
R[n] = 0;
|
|
else
|
|
R[n] = 0xFFFFFFFF;
|
|
}
|
|
else
|
|
R[n] = (long)R[n] >> ((~R[m] & 0x1F)+1);
|
|
PC += 2;
|
|
}
|
|
|
|
// SHAL / Rn - 0100nnnn00100000
|
|
void SHAL(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
|
|
if ((R[n]&0x80000000)==0) T = 0;
|
|
else T = 1;
|
|
R[n] <<= 1;
|
|
PC += 2;
|
|
}
|
|
|
|
// SHAR / Rn - 0100nnnn00100001
|
|
void SHAR(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
|
|
long temp;
|
|
if ((R[n]&0x00000001)==0) T = 0;
|
|
else T = 1;
|
|
if ((R[n]&0x80000000)==0) temp = 0;
|
|
else temp = 1;
|
|
R[n] >>= 1;
|
|
if (temp==1) R[n] |= 0x80000000;
|
|
else R[n] &= 0x7FFFFFFF;
|
|
PC += 2;
|
|
}
|
|
|
|
// SHLD / Rm,Rn - 0100nnnnmmmm1101
|
|
void SHLD(cpu_t* cpu, uint16_t instruction) {
|
|
int n = (instruction >> 8) & 0xF;
|
|
int m = (instruction >> 4) & 0xF;
|
|
|
|
int sgn = R[m] & 0x80000000;
|
|
if (sgn == 0)
|
|
R[n] <<= (R[m] & 0x1F);
|
|
else if ((R[m] & 0x1F) == 0)
|
|
R[n] = 0;
|
|
else
|
|
R[n] = (unsigned)R[n] >> ((~R[m] & 0x1F)+1);
|
|
PC += 2;
|
|
}
|
|
|
|
// SHLL / Rn - 0100nnnn00000000
|
|
void SHLL(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
|
|
if ((R[n]&0x80000000)==0) T = 0;
|
|
else T = 1;
|
|
R[n] <<= 1;
|
|
PC += 2;
|
|
}
|
|
|
|
// SHLL2 / Rn - 0100nnnn00001000
|
|
void SHLL2(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
|
|
R[n] <<= 2;
|
|
PC += 2;
|
|
}
|
|
|
|
// SHLL8 / Rn - 0100nnnn00011000
|
|
void SHLL8(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
|
|
R[n] <<= 8;
|
|
PC += 2;
|
|
}
|
|
|
|
// SHLL16 / Rn - 0100nnnn00101000
|
|
void SHLL16(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
|
|
R[n] <<= 16;
|
|
PC += 2;
|
|
}
|
|
|
|
// SHLR / Rn - 0100nnnn00000001
|
|
void SHLR(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
|
|
if ((R[n] & 0x00000001)==0) T = 0;
|
|
else T = 1;
|
|
R[n] >>= 1;
|
|
R[n] &= 0x7FFFFFFF;
|
|
PC += 2;
|
|
}
|
|
|
|
// SHLR2 / Rn - 0100nnnn00001001
|
|
void SHLR2(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
|
|
R[n] >>= 2;
|
|
R[n] &= 0x3FFFFFFF;
|
|
PC += 2;
|
|
}
|
|
|
|
// SHLR8 / Rn - 0100nnnn00011001
|
|
void SHLR8(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
|
|
R[n] >>= 8;
|
|
R[n] &= 0x00FFFFFF;
|
|
PC += 2;
|
|
}
|
|
|
|
// SHLR16 / Rn - 0100nnnn00101001
|
|
void SHLR16(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
|
|
R[n] >>= 16;
|
|
R[n] &= 0x0000FFFF;
|
|
PC += 2;
|
|
}
|
|
|
|
// STCGBR / GBR,Rn - 0000nnnn00010010
|
|
void STCGBR(cpu_t* cpu, uint16_t instruction) {
|
|
int n = (instruction >> 8) & 0xF;
|
|
|
|
R[n] = GBR;
|
|
PC += 2;
|
|
}
|
|
|
|
// STCVBR / VBR,Rn - 0000nnnn00100010
|
|
void STCVBR(cpu_t* cpu, uint16_t instruction) {
|
|
int n = (instruction >> 8) & 0xF;
|
|
|
|
R[n] = VBR;
|
|
PC += 2;
|
|
}
|
|
|
|
// STCSSR / SSR,Rn - 0000nnnn00110010
|
|
void STCSSR(cpu_t* cpu, uint16_t instruction) {
|
|
int n = (instruction >> 8) & 0xF;
|
|
|
|
R[n] = SSR;
|
|
PC += 2;
|
|
}
|
|
|
|
// STCSPC / SPC,Rn - 0000nnnn01000010
|
|
void STCSPC(cpu_t* cpu, uint16_t instruction) {
|
|
int n = (instruction >> 8) & 0xF;
|
|
|
|
R[n] = SPC;
|
|
PC += 2;
|
|
}
|
|
|
|
// STCSGR / SGR,Rn - 0000nnnn00111010
|
|
void STCSGR(cpu_t* cpu, uint16_t instruction) {
|
|
int n = (instruction >> 8) & 0xF;
|
|
|
|
R[n] = SGR;
|
|
PC += 2;
|
|
}
|
|
|
|
// STCDBR / DBR,Rn - 0000nnnn11111010
|
|
void STCDBR(cpu_t* cpu, uint16_t instruction) {
|
|
int n = (instruction >> 8) & 0xF;
|
|
|
|
R[n] = DBR;
|
|
PC += 2;
|
|
}
|
|
|
|
// STCMGBR / GBR,@-Rn - 0100nnnn00010011
|
|
void STCMGBR(cpu_t* cpu, uint16_t instruction) {
|
|
int n = (instruction >> 8) & 0xF;
|
|
|
|
R[n] -= 4;
|
|
Write_Long(R[n],GBR);
|
|
PC += 2;
|
|
}
|
|
|
|
// STCMVBR / VBR,@-Rn - 0100nnnn00100011
|
|
void STCMVBR(cpu_t* cpu, uint16_t instruction) {
|
|
int n = (instruction >> 8) & 0xF;
|
|
|
|
R[n] -= 4;
|
|
Write_Long(R[n],VBR);
|
|
PC += 2;
|
|
}
|
|
|
|
// STCMSSR / SSR,@-Rn - 0100nnnn00110011
|
|
void STCMSSR(cpu_t* cpu, uint16_t instruction) {
|
|
int n = (instruction >> 8) & 0xF;
|
|
|
|
R[n] -= 4;
|
|
Write_Long(R[n],SSR);
|
|
PC += 2;
|
|
}
|
|
|
|
// STCMSPC / SPC,@-Rn - 0100nnnn01000011
|
|
void STCMSPC(cpu_t* cpu, uint16_t instruction) {
|
|
int n = (instruction >> 8) & 0xF;
|
|
|
|
R[n] -= 4;
|
|
Write_Long(R[n],SPC);
|
|
PC += 2;
|
|
}
|
|
|
|
// STCMSGR / SGR,@-Rn - 0100nnnn00110010
|
|
void STCMSGR(cpu_t* cpu, uint16_t instruction) {
|
|
int n = (instruction >> 8) & 0xF;
|
|
|
|
R[n] -= 4;
|
|
Write_Long(R[n],SGR);
|
|
PC += 2;
|
|
}
|
|
|
|
// STCMDBR / DBR,@-Rn - 0100nnnn11110010
|
|
void STCMDBR(cpu_t* cpu, uint16_t instruction) {
|
|
int n = (instruction >> 8) & 0xF;
|
|
|
|
R[n] -= 4;
|
|
Write_Long(R[n],DBR);
|
|
PC += 2;
|
|
}
|
|
|
|
// STSMACH / MACH,Rn - 0000nnnn00001010
|
|
void STSMACH(cpu_t* cpu, uint16_t instruction) {
|
|
int n = (instruction >> 8) & 0xF;
|
|
|
|
R[n] = MACH;
|
|
PC += 2;
|
|
}
|
|
|
|
// STSMACL / MACL,Rn - 0000nnnn00011010
|
|
void STSMACL(cpu_t* cpu, uint16_t instruction) {
|
|
int n = (instruction >> 8) & 0xF;
|
|
|
|
R[n] = MACL;
|
|
PC += 2;
|
|
}
|
|
|
|
// STSPR / PR,Rn - 0000nnnn00101010
|
|
void STSPR(cpu_t* cpu, uint16_t instruction) {
|
|
int n = (instruction >> 8) & 0xF;
|
|
|
|
R[n] = PR;
|
|
PC += 2;
|
|
}
|
|
|
|
// STSMMACH / MACH,@-Rn - 0100nnnn00000010
|
|
void STSMMACH(cpu_t* cpu, uint16_t instruction) {
|
|
int n = (instruction >> 8) & 0xF;
|
|
|
|
R[n] -= 4;
|
|
Write_Long(R[n],MACH);
|
|
PC += 2;
|
|
}
|
|
|
|
// STSMMACL / MACL,@-Rn - 0100nnnn00010010
|
|
void STSMMACL(cpu_t* cpu, uint16_t instruction) {
|
|
int n = (instruction >> 8) & 0xF;
|
|
|
|
R[n] -= 4;
|
|
Write_Long(R[n],MACL);
|
|
PC += 2;
|
|
}
|
|
|
|
// STSMPR / PR,@-Rn - 0100nnnn00100010
|
|
void STSMPR(cpu_t* cpu, uint16_t instruction) {
|
|
int n = (instruction >> 8) & 0xF;
|
|
|
|
R[n] -= 4;
|
|
Write_Long(R[n],PR);
|
|
PC += 2;
|
|
}
|
|
|
|
// SUB / Rm,Rn - 0011nnnnmmmm1000
|
|
void SUB(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
R[n] -= R[m];
|
|
PC += 2;
|
|
}
|
|
|
|
// SUBC / Rm,Rn - 0011nnnnmmmm1010
|
|
void SUBC(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
unsigned long tmp0,tmp1;
|
|
tmp1 = R[n] - R[m];
|
|
tmp0 = R[n];
|
|
R[n] = tmp1 - T;
|
|
if (tmp0<tmp1) T = 1;
|
|
else T = 0;
|
|
if (tmp1<R[n]) T = 1;
|
|
PC += 2;
|
|
}
|
|
|
|
// SUBV / Rm,Rn - 0011nnnnmmmm1011
|
|
void SUBV(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
long dest,src,ans;
|
|
if ((long)R[n]>=0) dest = 0;
|
|
else dest = 1;
|
|
if ((long)R[m]>=0) src = 0;
|
|
else src = 1;
|
|
src += dest;
|
|
R[n] -= R[m];
|
|
if ((long)R[n]>=0) ans = 0;
|
|
else ans = 1;
|
|
ans += dest;
|
|
if (src==1) {
|
|
if (ans==1) T = 1;
|
|
else T = 0;
|
|
}
|
|
else T = 0;
|
|
PC += 2;
|
|
}
|
|
|
|
// SWAPB / Rm,Rn - 0110nnnnmmmm1000
|
|
void SWAPB(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
unsigned long temp0,temp1;
|
|
temp0 = R[m] & 0xFFFF0000;
|
|
temp1 = (R[m] & 0x000000FF) << 8;
|
|
R[n] = (R[m] & 0x0000FF00) >> 8;
|
|
R[n] = R[n] | temp1 | temp0;
|
|
PC += 2;
|
|
}
|
|
|
|
// SWAPW / Rm,Rn - 0110nnnnmmmm1001
|
|
void SWAPW(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
unsigned long temp;
|
|
temp = (R[m]>>16)&0x0000FFFF;
|
|
R[n] = R[m]<<16;
|
|
R[n] |= temp;
|
|
PC += 2;
|
|
}
|
|
|
|
// TAS / @Rn - 0100nnnn00011011
|
|
void TAS(cpu_t* cpu, uint16_t instruction) {
|
|
int n = (instruction >> 8) & 0xF;
|
|
|
|
int temp;
|
|
temp = (int)Read_Byte(R[n]); /* Bus Lock */
|
|
if (temp==0) T = 1;
|
|
else T = 0;
|
|
temp |= 0x00000080;
|
|
Write_Byte(R[n],temp); /* Bus unlock */
|
|
PC += 2;
|
|
}
|
|
|
|
// TST / Rm,Rn - 0010nnnnmmmm1000
|
|
void TST(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
if ((R[n]&R[m])==0) T = 1;
|
|
else T = 0;
|
|
PC += 2;
|
|
}
|
|
|
|
// TSTI / #imm,R0 - 11001000iiiiiiii
|
|
void TSTI(cpu_t* cpu, uint16_t instruction) {
|
|
long i = instruction & 0xFF;
|
|
|
|
long temp;
|
|
temp = R[0]&(0x000000FF & (long)i);
|
|
if (temp==0) T = 1;
|
|
else T = 0;
|
|
PC += 2;
|
|
}
|
|
|
|
// TSTM / #imm,@(R0,GBR) - 11001100iiiiiiii
|
|
void TSTM(cpu_t* cpu, uint16_t instruction) {
|
|
long i = instruction & 0xFF;
|
|
|
|
long temp;
|
|
temp = (long)Read_Byte(GBR+R[0]);
|
|
temp &= (0x000000FF & (long)i);
|
|
if (temp==0) T = 1;
|
|
else T = 0;
|
|
PC += 2;
|
|
}
|
|
|
|
// XOR / Rm,Rn - 0010nnnnmmmm1010
|
|
void XOR(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
R[n] ^= R[m];
|
|
PC += 2;
|
|
}
|
|
|
|
// XORI / #imm,R0 - 11001010iiiiiiii
|
|
void XORI(cpu_t* cpu, uint16_t instruction) {
|
|
long i = instruction & 0xFF;
|
|
|
|
R[0] ^= (0x000000FF & (long)i);
|
|
PC += 2;
|
|
}
|
|
|
|
// XORM / #imm,@(R0,GBR) - 11001110iiiiiiii
|
|
void XORM(cpu_t* cpu, uint16_t instruction) {
|
|
long i = instruction & 0xFF;
|
|
|
|
int temp;
|
|
temp = (long)Read_Byte(GBR+R[0]);
|
|
temp ^= (0x000000FF &(long)i);
|
|
Write_Byte(GBR+R[0],temp);
|
|
PC += 2;
|
|
}
|
|
|
|
// XTRCT / Rm,Rn - 0010nnnnmmmm1101
|
|
void XTRCT(cpu_t* cpu, uint16_t instruction) {
|
|
long n = (instruction >> 8) & 0xF;
|
|
long m = (instruction >> 4) & 0xF;
|
|
|
|
unsigned long temp;
|
|
temp = (R[m]<<16) & 0xFFFF0000;
|
|
R[n] = (R[n]>>16) & 0x0000FFFF;
|
|
R[n] |= temp;
|
|
PC += 2;
|
|
}
|
|
|
|
// BSR / label - 1011dddddddddddd
|
|
void BSR(cpu_t* cpu, uint16_t instruction) {
|
|
int d = instruction & 0xFFF;
|
|
|
|
int disp;
|
|
unsigned int temp;
|
|
temp = PC;
|
|
if((d&0x800) == 0)
|
|
disp = (0x00000FFF & d);
|
|
else disp = (0xFFFFF000 | d);
|
|
if(is_32bit_instruction(temp+2))
|
|
PR = PC + 6;
|
|
else PR = PC + 4;
|
|
PC = PC + 4 + (disp << 1);
|
|
Delay_Slot(temp + 2);
|
|
}
|
|
|
|
// BSRF / Rn - 0000nnnn00000011
|
|
void BSRF(cpu_t* cpu, uint16_t instruction) {
|
|
int n = (instruction >> 8) & 0xF;
|
|
|
|
unsigned int temp;
|
|
temp = PC;
|
|
if(is_32bit_instruction(temp+2))
|
|
PR = PC +6;
|
|
else PR = PC + 4;
|
|
PC = PC + 4 + R[n];
|
|
Delay_Slot(temp+2);
|
|
}
|
|
|
|
// JSR / @Rn - 0100nnnn00001011
|
|
void JSR(cpu_t* cpu, uint16_t instruction) {
|
|
int n = (instruction >> 8) & 0xF;
|
|
|
|
unsigned int temp;
|
|
temp = PC;
|
|
if(is_32bit_instruction(temp+2))
|
|
PR = PC +6;
|
|
else PR = PC + 4;
|
|
PC = R[n];
|
|
Delay_Slot(temp+2);
|
|
}
|
|
|