#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <arch/cache.h>
#include "sh2core.h"
#include "sh2rec.h"
#include "sh2rec_htab.h"
#include "sh2int.h"
#define R0 0
#define R1 1
#define R2 2
#define R3 3
#define R4 4
#define R5 5
#define R6 6
#define R7 7
#define R8 8
#define R9 9
#define R10 10
#define R11 11
#define R12 12
#define R13 13
#define R14 14
#define R15 15
#define R_SR 0
#define R_GBR 1
#define R_VBR 2
#define R_MACH 0
#define R_MACL 1
#define R_PR 2
#define OP_ADD 0x300C
#define OP_ADDC 0x300E
#define OP_AND 0x2009
#define OP_EXTSB 0x600E
#define OP_EXTSW 0x600F
#define OP_EXTUB 0x600C
#define OP_EXTUW 0x600D
#define OP_NEG 0x600B
#define OP_NEGC 0x600A
#define OP_NOT 0x6007
#define OP_OR 0x200B
#define OP_SUB 0x3008
#define OP_SUBC 0x300A
#define OP_SWAPB 0x6008
#define OP_SWAPW 0x6009
#define OP_XOR 0x200A
#define OP_XTRCT 0x200D
#define OP_ROTCL 0x4024
#define OP_ROTCR 0x4025
#define OP_ROTL 0x4004
#define OP_ROTR 0x4005
#define OP_SHAL 0x4020
#define OP_SHAR 0x4021
#define OP_SHLL 0x4000
#define OP_SHLR 0x4001
#define OP_CMPEQ 0x3000
#define OP_CMPGE 0x3003
#define OP_CMPGT 0x3007
#define OP_CMPHI 0x3006
#define OP_CMPHS 0x3002
#define OP_CMPSTR 0x200C
#define OP_TST 0x2008
#define OP_DMULS 0x300D
#define OP_DMULU 0x3005
#define OP_MULL 0x0007
#define OP_MULS 0x200F
#define OP_MULU 0x200E
#ifdef SH2REC__DEBUG
#define EMIT_INST {\
printf("%s\n", __PRETTY_FUNCTION__); \
printf("Emitting %04x at %p\n", inst, (void *)b->ptr); \
*b->ptr++ = inst; \
}
#else
#define EMIT_INST *b->ptr++ = inst
#endif
#ifdef SH2REC__DEBUG
#define EMIT_32 {\
uint32_t *__ptr = (uint32_t *)b->ptr; \
printf("%s\n", __PRETTY_FUNCTION__); \
printf("Emitting %08x at %p\n", (unsigned int)v, (void *)__ptr); \
*__ptr = v; \
b->ptr += 2; \
}
#else
#define EMIT_32 uint32_t *__ptr = (uint32_t *)b->ptr; *__ptr = v; b->ptr += 2
#endif
static inline void emit16(sh2rec_block_t *b, uint16_t inst) {
EMIT_INST;
}
static inline void emit32(sh2rec_block_t *b, uint32_t v) {
EMIT_32;
}
static inline void emitMOV(sh2rec_block_t *b, int m, int n) {
uint16_t inst = 0x6003 | (n << 8) | (m << 4);
EMIT_INST;
}
static inline void emitMOVWI(sh2rec_block_t *b, int d, int n) {
uint16_t inst = 0x9000 | (n << 8) | (d);
EMIT_INST;
}
static inline void emitMOVLI(sh2rec_block_t *b, int d, int n) {
uint16_t inst = 0xD000 | (n << 8) | (d);
EMIT_INST;
}
static inline void emitMOVLS(sh2rec_block_t *b, int m, int n) {
uint16_t inst = 0x2002 | (n << 8) | (m << 4);
EMIT_INST;
}
static inline void emitMOVLL(sh2rec_block_t *b, int m, int n) {
uint16_t inst = 0x6002 | (n << 8) | (m << 4);
EMIT_INST;
}
static inline void emitMOVWM(sh2rec_block_t *b, int m, int n) {
uint16_t inst = 0x2005 | (n << 8) | (m << 4);
EMIT_INST;
}
static inline void emitMOVLM(sh2rec_block_t *b, int m, int n) {
uint16_t inst = 0x2006 | (n << 8) | (m << 4);
EMIT_INST;
}
static inline void emitMOVLP(sh2rec_block_t *b, int m, int n) {
uint16_t inst = 0x6006 | (n << 8) | (m << 4);
EMIT_INST;
}
static inline void emitMOVI(sh2rec_block_t *b, int imm, int n) {
uint16_t inst = 0xE000 | (n << 8) | (imm & 0xFF);
EMIT_INST;
}
static inline void emitMOVLL4(sh2rec_block_t *b, int m, int d, int n) {
uint16_t inst = 0x5000 | (n << 8) | (m << 4) | (d);
EMIT_INST;
}
static inline void emitMOVLS4(sh2rec_block_t *b, int m, int d, int n) {
uint16_t inst = 0x1000 | (n << 8) | (m << 4) | (d);
EMIT_INST;
}
static inline void emitMOVLLG(sh2rec_block_t *b, int imm) {
uint16_t inst = 0xC600 | (imm & 0xFF);
EMIT_INST;
}
static inline void emitMOVLSG(sh2rec_block_t *b, int imm) {
uint16_t inst = 0xC200 | (imm & 0xFF);
EMIT_INST;
}
static inline void emitMOVT(sh2rec_block_t *b, int n) {
uint16_t inst = 0x0029 | (n << 8);
EMIT_INST;
}
static inline void emitALU(sh2rec_block_t *b, int m, int n, uint16_t op) {
uint16_t inst = (n << 8) | (m << 4) | op;
EMIT_INST;
}
static inline void emitSHIFT(sh2rec_block_t *b, int n, uint16_t op) {
uint16_t inst = (n << 8) | op;
EMIT_INST;
}
static inline void emitADDI(sh2rec_block_t *b, int imm, int n) {
uint16_t inst = 0x7000 | (n << 8) | (imm & 0xFF);
EMIT_INST;
}
static inline void emitANDI(sh2rec_block_t *b, int imm) {
uint16_t inst = 0xC900 | (imm & 0xFF);
EMIT_INST;
}
static inline void emitORI(sh2rec_block_t *b, int imm) {
uint16_t inst = 0xCB00 | (imm & 0xFF);
EMIT_INST;
}
static inline void emitXORI(sh2rec_block_t *b, int imm) {
uint16_t inst = 0xCA00 | (imm & 0xFF);
EMIT_INST;
}
static inline void emitSHLL2(sh2rec_block_t *b, int n) {
uint16_t inst = 0x4008 | (n << 8);
EMIT_INST;
}
static inline void emitSHLL8(sh2rec_block_t *b, int n) {
uint16_t inst = 0x4018 | (n << 8);
EMIT_INST;
}
static inline void emitSHLL16(sh2rec_block_t *b, int n) {
uint16_t inst = 0x4028 | (n << 8);
EMIT_INST;
}
static inline void emitSHLR2(sh2rec_block_t *b, int n) {
uint16_t inst = 0x4009 | (n << 8);
EMIT_INST;
}
static inline void emitSHLR8(sh2rec_block_t *b, int n) {
uint16_t inst = 0x4019 | (n << 8);
EMIT_INST;
}
static inline void emitSHLR16(sh2rec_block_t *b, int n) {
uint16_t inst = 0x4029 | (n << 8);
EMIT_INST;
}
static inline void emitCMPIM(sh2rec_block_t *b, int imm) {
uint16_t inst = 0x8800 | (imm & 0xFF);
EMIT_INST;
}
static inline void emitCMPPL(sh2rec_block_t *b, int n) {
uint16_t inst = 0x4015 | (n << 8);
EMIT_INST;
}
static inline void emitCMPPZ(sh2rec_block_t *b, int n) {
uint16_t inst = 0x4011 | (n << 8);
EMIT_INST;
}
static inline void emitADDV(sh2rec_block_t *b, int m, int n) {
uint16_t inst = 0x300F | (n << 8) | (m << 4);
EMIT_INST;
}
static inline void emitSUBV(sh2rec_block_t *b, int m, int n) {
uint16_t inst = 0x300B | (n << 8) | (m << 4);
EMIT_INST;
}
static inline void emitLDS(sh2rec_block_t *b, int m, int sr) {
uint16_t inst = 0x400A | (m << 8) | (sr << 4);
EMIT_INST;
}
static inline void emitSTS(sh2rec_block_t *b, int sr, int n) {
uint16_t inst = 0x000A | (n << 8) | (sr << 4);
EMIT_INST;
}
static inline void emitLDC(sh2rec_block_t *b, int m, int sr) {
uint16_t inst = 0x400E | (m << 8) | (sr << 4);
EMIT_INST;
}
static inline void emitSTC(sh2rec_block_t *b, int sr, int n) {
uint16_t inst = 0x0002 | (n << 8) | (sr << 4);
EMIT_INST;
}
static inline void emitDT(sh2rec_block_t *b, int n) {
uint16_t inst = 0x4010 | (n << 8);
EMIT_INST;
}
static inline void emitTSTI(sh2rec_block_t *b, int imm) {
uint16_t inst = 0xC800 | (imm & 0xFF);
EMIT_INST;
}
static inline void emitBRA(sh2rec_block_t *b, int d) {
uint16_t inst = 0xA000 | (d);
EMIT_INST;
}
static inline void emitDIV0S(sh2rec_block_t *b, int m, int n) {
uint16_t inst = 0x2007 | (n << 8) | (m << 4);
EMIT_INST;
}
static inline void emitDIV1(sh2rec_block_t *b, int m, int n) {
uint16_t inst = 0x3004 | (n << 8) | (m << 4);
EMIT_INST;
}
static inline void emitRTS(sh2rec_block_t *b) {
uint16_t inst = 0x000B;
EMIT_INST;
}
static inline void emitNOP(sh2rec_block_t *b) {
uint16_t inst = 0x0009;
EMIT_INST;
}
static inline void emitJSR(sh2rec_block_t *b, int m) {
uint16_t inst = 0x400B | (m << 8);
EMIT_INST;
}
static inline void emitMACL(sh2rec_block_t *b, int m, int n) {
uint16_t inst = 0x000F | (n << 8) | (m << 4);
EMIT_INST;
}
static inline void emitMACW(sh2rec_block_t *b, int m, int n) {
uint16_t inst = 0x400F | (n << 8) | (m << 4);
EMIT_INST;
}
static inline void emitCLRMAC(sh2rec_block_t *b) {
uint16_t inst = 0x0028;
EMIT_INST;
}
static inline void emitBF(sh2rec_block_t *b, int disp) {
uint16_t inst = 0x8B00 | (disp & 0xFF);
EMIT_INST;
}
static inline void emitBT(sh2rec_block_t *b, int disp) {
uint16_t inst = 0x8900 | (disp & 0xFF);
EMIT_INST;
}
static inline void generateALUOP(uint16_t inst, sh2rec_block_t *b, int op) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitMOVLL4(b, R8, regn, R2);
emitMOVLL4(b, R8, regm, R3);
emitALU(b, R3, R2, op);
emitMOVLS4(b, R2, regn, R8);
++b->cycles;
}
static inline void generateSHIFT(uint16_t inst, sh2rec_block_t *b, int op) {
int regn = INSTRUCTION_B(inst);
emitMOVLLG(b, 16);
emitMOVLL4(b, R8, regn, R2);
emitSHIFT(b, R0, OP_ROTCR);
emitSHIFT(b, R2, op);
emitSHIFT(b, R0, OP_ROTCL);
emitMOVLS4(b, R2, regn, R8);
emitMOVLSG(b, 16);
++b->cycles;
}
static inline void generateCOMP(uint16_t inst, sh2rec_block_t *b, int op) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitMOVLLG(b, 16);
emitMOVLL4(b, R8, regn, R2);
emitMOVLL4(b, R8, regm, R3);
emitSHIFT(b, R0, OP_ROTCR);
emitALU(b, R3, R2, op);
emitSHIFT(b, R0, OP_ROTCL);
emitMOVLSG(b, 16);
++b->cycles;
}
static void generateADD(uint16_t inst, sh2rec_block_t *b) {
generateALUOP(inst, b, OP_ADD);
b->pc += 2;
}
static void generateADDI(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int imm = INSTRUCTION_CD(inst);
emitMOVLL4(b, R8, regn, R2);
emitADDI(b, imm, R2);
emitMOVLS4(b, R2, regn, R8);
++b->cycles;
b->pc += 2;
}
static void generateADDC(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitMOVLLG(b, 16);
emitMOVLL4(b, R8, regn, R2);
emitMOVLL4(b, R8, regm, R3);
emitSHIFT(b, R0, OP_ROTCR);
emitALU(b, R3, R2, OP_ADDC);
emitSHIFT(b, R0, OP_ROTCL);
emitMOVLS4(b, R2, regn, R8);
emitMOVLSG(b, 16);
++b->cycles;
b->pc += 2;
}
static void generateADDV(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitMOVLLG(b, 16);
emitMOVLL4(b, R8, regn, R2);
emitMOVLL4(b, R8, regm, R3);
emitSHIFT(b, R0, OP_ROTCR);
emitADDV(b, R3, R2);
emitSHIFT(b, R0, OP_ROTCL);
emitMOVLS4(b, R2, regn, R8);
emitMOVLSG(b, 16);
++b->cycles;
b->pc += 2;
}
static void generateAND(uint16_t inst, sh2rec_block_t *b) {
generateALUOP(inst, b, OP_AND);
b->pc += 2;
}
static void generateANDI(uint16_t inst, sh2rec_block_t *b) {
int imm = INSTRUCTION_CD(inst);
emitMOVLL4(b, R8, 0, R0);
emitANDI(b, imm);
emitMOVLS4(b, R0, 0, R8);
++b->cycles;
b->pc += 2;
}
static void generateANDM(uint16_t inst, sh2rec_block_t *b) {
int imm = INSTRUCTION_CD(inst);
emitSTS(b, R_PR, R10);
emitMOVLLG(b, 17);
emitMOVLL4(b, R8, 0, R4);
emitMOVLL4(b, R9, 0, R1);
emitALU(b, R0, R4, OP_ADD);
emitJSR(b, R1);
emitMOVLM(b, R4, R15);
emitMOVLL4(b, R9, 3, R1);
emitANDI(b, imm);
emitMOVLP(b, R15, R4);
emitJSR(b, R1);
emitMOV(b, R0, R5);
emitLDS(b, R10, R_PR);
b->cycles += 3;
b->pc += 2;
}
static void generateBF(uint16_t inst, sh2rec_block_t *b) {
int disp = INSTRUCTION_CD(inst);
uint32_t val = b->pc + 2;
emitMOVLLG(b, 16);
emitMOVLI(b, 4, R2);
emitSHIFT(b, R0, OP_ROTCR);
emitMOVI(b, 0, R0);
emitBT(b, 2);
emitMOVI(b, disp, R0);
emitSHIFT(b, R0, OP_SHLL);
emitADDI(b, 2, R0);
emitRTS(b);
emitALU(b, R2, R0, OP_ADD);
if(((uint32_t)b->ptr) & 0x03)
emit16(b, 0);
emit32(b, val);
b->cycles += 2;
}
static void generateBFS(uint16_t inst, sh2rec_block_t *b) {
int disp = INSTRUCTION_CD(inst);
uint32_t val = b->pc + 4;
int n = (((uint32_t)b->ptr) & 0x03) ? 3 : 4;
emitMOVLLG(b, 16);
emitMOVLI(b, n, R2);
emitSHIFT(b, R0, OP_ROTCR);
emitMOVI(b, 0, R0);
emitBT(b, 1);
emitMOVI(b, disp, R0);
emitSHIFT(b, R0, OP_SHLL);
if(((uint32_t)b->ptr) & 0x03) {
emitBRA(b, 3);
emitALU(b, R2, R0, OP_ADD);
emit16(b, 0);
}
else {
emitBRA(b, 2);
emitALU(b, R2, R0, OP_ADD);
}
emit32(b, val);
emitMOVLM(b, R0, R15);
b->pc += 2;
sh2rec_rec_inst(b, 1);
emitRTS(b);
emitMOVLP(b, R15, R0);
++b->cycles;
}
static void generateBRA(uint16_t inst, sh2rec_block_t *b) {
int disp = INSTRUCTION_BCD(inst);
int32_t val;
if(disp & 0x00000800) {
disp |= 0xFFFFF000;
}
val = b->pc + 4 + (disp << 1);
emitMOVLI(b, 1, R2);
if(((uint32_t)b->ptr) & 0x03) {
emitBRA(b, 3);
emitMOVLM(b, R2, R15);
emit16(b, 0);
}
else {
emitBRA(b, 2);
emitMOVLM(b, R2, R15);
}
emit32(b, (uint32_t )val);
b->pc += 2;
sh2rec_rec_inst(b, 1);
emitRTS(b);
emitMOVLP(b, R15, R0);
b->cycles += 2;
}
static void generateBRAF(uint16_t inst, sh2rec_block_t *b) {
int regm = INSTRUCTION_B(inst);
uint32_t val = b->pc + 4;
if(((uint32_t)b->ptr) & 0x03) {
emitMOVLI(b, 2, R0);
emitMOVLL4(b, R8, regm, R2);
emitBRA(b, 3);
emitALU(b, R0, R2, OP_ADD);
emit16(b, 0);
}
else {
emitMOVLI(b, 1, R0);
emitMOVLL4(b, R8, regm, R2);
emitBRA(b, 2);
emitALU(b, R0, R2, OP_ADD);
}
emit32(b, val);
emitMOVLM(b, R2, R15);
b->pc += 2;
sh2rec_rec_inst(b, 1);
emitRTS(b);
emitMOVLP(b, R15, R0);
b->cycles += 2;
}
static void generateBSR(uint16_t inst, sh2rec_block_t *b) {
int disp = INSTRUCTION_BCD(inst);
int32_t val;
int32_t val2 = b->pc + 4;
if(disp & 0x00000800) {
disp |= 0xFFFFF000;
}
val = b->pc + 4 + (disp << 1);
if(((uint32_t)b->ptr) & 0x03) {
emitMOVLI(b, 2, R2);
emitMOVLI(b, 2, R0);
emitBRA(b, 5);
emitMOVLM(b, R2, R15);
emit16(b, 0);
}
else {
emitMOVLI(b, 1, R2);
emitMOVLI(b, 2, R0);
emitBRA(b, 4);
emitMOVLM(b, R2, R15);
}
emit32(b, (uint32_t)val);
emit32(b, (uint32_t)val2);
emitMOVLSG(b, 21);
b->pc += 2;
sh2rec_rec_inst(b, 1);
emitRTS(b);
emitMOVLP(b, R15, R0);
b->cycles += 2;
}
static void generateBSRF(uint16_t inst, sh2rec_block_t *b) {
int regm = INSTRUCTION_B(inst);
uint32_t val = b->pc + 4;
emitMOVLI(b, 1, R0);
if(((uint32_t)b->ptr) & 0x03) {
emitBRA(b, 3);
emitMOVLL4(b, R8, regm, R2);
emit16(b, 0);
}
else {
emitBRA(b, 2);
emitMOVLL4(b, R8, regm, R2);
}
emit32(b, val);
emitALU(b, R0, R2, OP_ADD);
emitMOVLSG(b, 21);
emitMOVLM(b, R2, R15);
b->pc += 2;
sh2rec_rec_inst(b, 1);
emitRTS(b);
emitMOVLP(b, R15, R0);
b->cycles += 2;
}
static void generateBT(uint16_t inst, sh2rec_block_t *b) {
int disp = INSTRUCTION_CD(inst);
uint32_t val = b->pc + 2;
emitMOVLLG(b, 16);
emitMOVLI(b, 4, R2);
emitSHIFT(b, R0, OP_ROTCR);
emitMOVI(b, 0, R0);
emitBF(b, 2);
emitMOVI(b, disp, R0);
emitSHIFT(b, R0, OP_SHLL);
emitADDI(b, 2, R0);
emitRTS(b);
emitALU(b, R2, R0, OP_ADD);
if(((uint32_t)b->ptr) & 0x03)
emit16(b, 0);
emit32(b, val);
b->cycles += 2;
}
static void generateBTS(uint16_t inst, sh2rec_block_t *b) {
int disp = INSTRUCTION_CD(inst);
uint32_t val = b->pc + 4;
int n = (((uint32_t)b->ptr) & 0x03) ? 3 : 4;
emitMOVLLG(b, 16);
emitMOVLI(b, n, R2);
emitSHIFT(b, R0, OP_ROTCR);
emitMOVI(b, 0, R0);
emitBF(b, 1);
emitMOVI(b, disp, R0);
emitSHIFT(b, R0, OP_SHLL);
if(((uint32_t)b->ptr) & 0x03) {
emitBRA(b, 3);
emitALU(b, R2, R0, OP_ADD);
emit16(b, 0);
}
else {
emitBRA(b, 2);
emitALU(b, R2, R0, OP_ADD);
}
emit32(b, val);
emitMOVLM(b, R0, R15);
b->pc += 2;
sh2rec_rec_inst(b, 1);
emitRTS(b);
emitMOVLP(b, R15, R0);
++b->cycles;
}
static void generateCLRMAC(uint16_t inst, sh2rec_block_t *b) {
emitCLRMAC(b);
++b->cycles;
b->pc += 2;
}
static void generateCLRT(uint16_t inst, sh2rec_block_t *b) {
emitMOVLLG(b, 16);
emitMOVI(b, 0xFE, R1);
emitALU(b, R3, R0, OP_AND);
emitMOVLSG(b, 16);
++b->cycles;
b->pc += 2;
}
static void generateCMPEQ(uint16_t inst, sh2rec_block_t *b) {
generateCOMP(inst, b, OP_CMPEQ);
b->pc += 2;
}
static void generateCMPGE(uint16_t inst, sh2rec_block_t *b) {
generateCOMP(inst, b, OP_CMPGE);
b->pc += 2;
}
static void generateCMPGT(uint16_t inst, sh2rec_block_t *b) {
generateCOMP(inst, b, OP_CMPGT);
b->pc += 2;
}
static void generateCMPHI(uint16_t inst, sh2rec_block_t *b) {
generateCOMP(inst, b, OP_CMPHI);
b->pc += 2;
}
static void generateCMPHS(uint16_t inst, sh2rec_block_t *b) {
generateCOMP(inst, b, OP_CMPHS);
b->pc += 2;
}
static void generateCMPSTR(uint16_t inst, sh2rec_block_t *b) {
generateCOMP(inst, b, OP_CMPSTR);
b->pc += 2;
}
static void generateCMPPL(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
emitMOVLLG(b, 16);
emitMOVLL4(b, R8, regn, R2);
emitSHIFT(b, R0, OP_ROTCR);
emitCMPPL(b, R2);
emitSHIFT(b, R0, OP_ROTCL);
emitMOVLSG(b, 16);
++b->cycles;
b->pc += 2;
}
static void generateCMPPZ(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
emitMOVLLG(b, 16);
emitMOVLL4(b, R8, regn, R2);
emitSHIFT(b, R0, OP_ROTCR);
emitCMPPZ(b, R2);
emitSHIFT(b, R0, OP_ROTCL);
emitMOVLSG(b, 16);
++b->cycles;
b->pc += 2;
}
static void generateCMPIM(uint16_t inst, sh2rec_block_t *b) {
int imm = INSTRUCTION_CD(inst);
emitMOVLLG(b, 16);
emitMOV(b, R0, R2);
emitMOVLL4(b, R8, 0, R0);
emitSHIFT(b, R2, OP_ROTCR);
emitCMPIM(b, imm);
emitSHIFT(b, R2, OP_ROTCL);
emitMOV(b, R2, R0);
emitMOVLSG(b, 16);
++b->cycles;
b->pc += 2;
}
static void generateDIV0S(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitMOVLLG(b, 16);
emitMOVLL4(b, R8, regn, R2);
emitMOVI(b, 0x03, R4);
emitANDI(b, 0xF2);
emitMOVLL4(b, R8, regm, R3);
emitSHLL8(b, R4);
emitSHIFT(b, R0, OP_SHLR);
emitDIV0S(b, R3, R2);
emitSTC(b, R_SR, R5);
emitALU(b, R4, R5, OP_AND);
emitSHIFT(b, R0, OP_ROTCL);
emitALU(b, R5, R0, OP_OR);
emitMOVLSG(b, 16);
++b->cycles;
b->pc += 2;
}
static void generateDIV0U(uint16_t inst, sh2rec_block_t *b) {
emitMOVLLG(b, 16);
emitANDI(b, 0xF2);
emitMOVLSG(b, 16);
++b->cycles;
b->pc += 2;
}
static void generateDIV1(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitMOVLLG(b, 16);
emitMOVLL4(b, R8, regn, R2);
emitMOVI(b, 0x03, R4);
emitSHLL8(b, R4);
emitMOVLL4(b, R8, regm, R3);
emitMOV(b, R4, R6);
emitALU(b, R0, R6, OP_AND);
emitSHIFT(b, R0, OP_ROTCR);
emitSTC(b, R_SR, R5);
emitALU(b, R4, R7, OP_NOT);
emitALU(b, R7, R5, OP_AND);
emitALU(b, R6, R5, OP_OR);
emitLDC(b, R5, R_SR);
emitDIV1(b, R3, R2);
emitSTC(b, R_SR, R5);
emitALU(b, R4, R5, OP_AND);
emitSHIFT(b, R0, OP_ROTCL);
emitMOVLS4(b, R2, regn, R8);
emitANDI(b, 0xF3);
emitALU(b, R5, R0, OP_OR);
emitMOVLSG(b, 16);
++b->cycles;
b->pc += 2;
}
static void generateDMULS(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitMOVLL4(b, R8, regn, R2);
emitMOVLL4(b, R8, regm, R3);
emitALU(b, R3, R2, OP_DMULS);
b->cycles += 2;
b->pc += 2;
}
static void generateDMULU(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitMOVLL4(b, R8, regn, R2);
emitMOVLL4(b, R8, regm, R3);
emitALU(b, R3, R2, OP_DMULU);
b->cycles += 2;
b->pc += 2;
}
static void generateDT(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
emitMOVLLG(b, 16);
emitMOVLL4(b, R8, regn, R2);
emitSHIFT(b, R0, OP_ROTCR);
emitDT(b, R2);
emitSHIFT(b, R0, OP_ROTCL);
emitMOVLS4(b, R2, regn, R8);
emitMOVLSG(b, 16);
++b->cycles;
b->pc += 2;
}
static void generateEXTSB(uint16_t inst, sh2rec_block_t *b) {
generateALUOP(inst, b, OP_EXTSB);
b->pc += 2;
}
static void generateEXTSW(uint16_t inst, sh2rec_block_t *b) {
generateALUOP(inst, b, OP_EXTSW);
b->pc += 2;
}
static void generateEXTUB(uint16_t inst, sh2rec_block_t *b) {
generateALUOP(inst, b, OP_EXTUB);
b->pc += 2;
}
static void generateEXTUW(uint16_t inst, sh2rec_block_t *b) {
generateALUOP(inst, b, OP_EXTUW);
b->pc += 2;
}
static void generateJMP(uint16_t inst, sh2rec_block_t *b) {
int regm = INSTRUCTION_B(inst);
emitMOVLL4(b, R8, regm, R0);
emitMOVLM(b, R0, R15);
b->pc += 2;
sh2rec_rec_inst(b, 1);
emitRTS(b);
emitMOVLP(b, R15, R0);
b->cycles += 2;
}
static void generateJSR(uint16_t inst, sh2rec_block_t *b) {
int regm = INSTRUCTION_B(inst);
uint32_t val = b->pc + 4;
emitMOVLI(b, 1, R0);
if(((uint32_t)b->ptr) & 0x03) {
emitBRA(b, 3);
emitMOVLL4(b, R8, regm, R2);
emit16(b, 0);
}
else {
emitBRA(b, 2);
emitMOVLL4(b, R8, regm, R2);
}
emit32(b, val);
emitMOVLM(b, R2, R15);
emitMOVLSG(b, 21);
b->pc += 2;
sh2rec_rec_inst(b, 1);
emitRTS(b);
emitMOVLP(b, R15, R0);
b->cycles += 2;
}
static void generateLDCSR(uint16_t inst, sh2rec_block_t *b) {
int regm = INSTRUCTION_B(inst);
emitMOVWI(b, 2, R2);
emitMOVLL4(b, R8, regm, R0);
emitBRA(b, 1);
emitALU(b, R2, R0, OP_AND);
emit16(b, 0x03F3);
emitMOVLSG(b, 16);
++b->cycles;
b->pc += 2;
}
static void generateLDCGBR(uint16_t inst, sh2rec_block_t *b) {
int regm = INSTRUCTION_B(inst);
emitMOVLL4(b, R8, regm, R0);
emitMOVLSG(b, 17);
++b->cycles;
b->pc += 2;
}
static void generateLDCVBR(uint16_t inst, sh2rec_block_t *b) {
int regm = INSTRUCTION_B(inst);
emitMOVLL4(b, R8, regm, R0);
emitMOVLSG(b, 18);
++b->cycles;
b->pc += 2;
}
static void generateLDCMSR(uint16_t inst, sh2rec_block_t *b) {
int regm = INSTRUCTION_B(inst);
emitMOVLL4(b, R9, 2, R0);
emitSTS(b, R_PR, R10);
emitMOVLL4(b, R8, regm, R4);
emitMOVI(b, 4, R1);
emitALU(b, R4, R1, OP_ADD);
emitJSR(b, R0);
emitMOVLS4(b, R1, regm, R8);
emitLDS(b, R10, R_PR);
emitMOVWI(b, 2, R2);
emitBRA(b, 1);
emitALU(b, R2, R0, OP_AND);
emit16(b, 0x03F3);
emitMOVLSG(b, 16);
b->cycles += 3;
b->pc += 2;
}
static void generateLDCMGBR(uint16_t inst, sh2rec_block_t *b) {
int regm = INSTRUCTION_B(inst);
emitMOVLL4(b, R9, 2, R0);
emitSTS(b, R_PR, R10);
emitMOVLL4(b, R8, regm, R4);
emitMOVI(b, 4, R1);
emitALU(b, R4, R1, OP_ADD);
emitJSR(b, R0);
emitMOVLS4(b, R1, regm, R8);
emitLDS(b, R10, R_PR);
emitMOVLSG(b, 17);
b->cycles += 3;
b->pc += 2;
}
static void generateLDCMVBR(uint16_t inst, sh2rec_block_t *b) {
int regm = INSTRUCTION_B(inst);
emitMOVLL4(b, R9, 2, R0);
emitSTS(b, R_PR, R10);
emitMOVLL4(b, R8, regm, R4);
emitMOVI(b, 4, R1);
emitALU(b, R4, R1, OP_ADD);
emitJSR(b, R0);
emitMOVLS4(b, R1, regm, R8);
emitLDS(b, R10, R_PR);
emitMOVLSG(b, 18);
b->cycles += 3;
b->pc += 2;
}
static void generateLDSMACH(uint16_t inst, sh2rec_block_t *b) {
int regm = INSTRUCTION_B(inst);
emitMOVLL4(b, R8, regm, R0);
emitLDS(b, R0, R_MACH);
++b->cycles;
b->pc += 2;
}
static void generateLDSMACL(uint16_t inst, sh2rec_block_t *b) {
int regm = INSTRUCTION_B(inst);
emitMOVLL4(b, R8, regm, R0);
emitLDS(b, R0, R_MACL);
++b->cycles;
b->pc += 2;
}
static void generateLDSPR(uint16_t inst, sh2rec_block_t *b) {
int regm = INSTRUCTION_B(inst);
emitMOVLL4(b, R8, regm, R0);
emitMOVLSG(b, 21);
++b->cycles;
b->pc += 2;
}
static void generateLDSMMACH(uint16_t inst, sh2rec_block_t *b) {
int regm = INSTRUCTION_B(inst);
emitMOVLL4(b, R9, 2, R0);
emitSTS(b, R_PR, R10);
emitMOVLL4(b, R8, regm, R4);
emitMOVI(b, 4, R1);
emitALU(b, R4, R1, OP_ADD);
emitJSR(b, R0);
emitMOVLS4(b, R1, regm, R8);
emitLDS(b, R10, R_PR);
emitLDS(b, R0, R_MACH);
++b->cycles;
b->pc += 2;
}
static void generateLDSMMACL(uint16_t inst, sh2rec_block_t *b) {
int regm = INSTRUCTION_B(inst);
emitMOVLL4(b, R9, 2, R0);
emitSTS(b, R_PR, R10);
emitMOVLL4(b, R8, regm, R4);
emitMOVI(b, 4, R1);
emitALU(b, R4, R1, OP_ADD);
emitJSR(b, R0);
emitMOVLS4(b, R1, regm, R8);
emitLDS(b, R10, R_PR);
emitLDS(b, R0, R_MACL);
++b->cycles;
b->pc += 2;
}
static void generateLDSMPR(uint16_t inst, sh2rec_block_t *b) {
int regm = INSTRUCTION_B(inst);
emitMOVLL4(b, R9, 2, R0);
emitSTS(b, R_PR, R10);
emitMOVLL4(b, R8, regm, R4);
emitMOVI(b, 4, R1);
emitALU(b, R4, R1, OP_ADD);
emitJSR(b, R0);
emitMOVLS4(b, R1, regm, R8);
emitLDS(b, R10, R_PR);
emitMOVLSG(b, 21);
++b->cycles;
b->pc += 2;
}
static void generateMACL(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitSTS(b, R_PR, R10);
emitMOVLL4(b, R8, regm, R4);
emitMOVLL4(b, R9, 2, R0);
emitADDI(b, 4, R4);
emitMOVLS4(b, R4, regm, R8);
emitJSR(b, R0);
emitADDI(b, -4, R4);
emitMOVLM(b, R0, R15);
emitMOVLL4(b, R8, regn, R4);
emitMOVLL4(b, R9, 2, R0);
emitADDI(b, 4, R4);
emitMOVLS4(b, R4, regn, R8);
emitJSR(b, R0);
emitADDI(b, -4, R4);
emitSTC(b, R_SR, R2);
emitMOVI(b, 0xFD, R3);
emitMOVLM(b, R0, R15);
emitMOVLLG(b, 16);
emitALU(b, R2, R3, OP_AND);
emitANDI(b, 0x02);
emitALU(b, R0, R3, OP_OR);
emitLDC(b, R3, R_SR);
emitMACL(b, R15, R15);
emitLDC(b, R2, R_SR);
emitLDS(b, R10, R_PR);
b->cycles += 3;
b->pc += 2;
}
static void generateMACW(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitSTS(b, R_PR, R10);
emitMOVLL4(b, R8, regm, R4);
emitMOVLL4(b, R9, 1, R0);
emitADDI(b, 2, R4);
emitMOVLS4(b, R4, regm, R8);
emitJSR(b, R0);
emitADDI(b, -2, R4);
emitMOVWM(b, R0, R15);
emitMOVLL4(b, R8, regn, R4);
emitMOVLL4(b, R9, 1, R0);
emitADDI(b, 2, R4);
emitMOVLS4(b, R4, regn, R8);
emitJSR(b, R0);
emitADDI(b, -2, R4);
emitMOVWM(b, R0, R15);
emitSTC(b, R_SR, R2);
emitMOVI(b, 0xFD, R3);
emitMOVLM(b, R0, R15);
emitMOVLLG(b, 16);
emitALU(b, R2, R3, OP_AND);
emitANDI(b, 0x02);
emitALU(b, R0, R3, OP_OR);
emitLDC(b, R3, R_SR);
emitMACW(b, R15, R15);
emitLDC(b, R2, R_SR);
emitLDS(b, R10, R_PR);
b->cycles += 3;
b->pc += 2;
}
static void generateMOV(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitMOVLL4(b, R8, regm, R2);
emitMOVLS4(b, R2, regn, R8);
++b->cycles;
b->pc += 2;
}
static void generateMOVBS(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitMOVLL4(b, R9, 3, R0);
emitMOVLL4(b, R8, regm, R5);
emitSTS(b, R_PR, R10);
emitJSR(b, R0);
emitMOVLL4(b, R8, regn, R4);
emitLDS(b, R10, R_PR);
++b->cycles;
b->pc += 2;
}
static void generateMOVWS(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitMOVLL4(b, R9, 4, R0);
emitMOVLL4(b, R8, regm, R5);
emitSTS(b, R_PR, R10);
emitJSR(b, R0);
emitMOVLL4(b, R8, regn, R4);
emitLDS(b, R10, R_PR);
++b->cycles;
b->pc += 2;
}
static void generateMOVLS(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitMOVLL4(b, R9, 5, R0);
emitMOVLL4(b, R8, regm, R5);
emitSTS(b, R_PR, R10);
emitJSR(b, R0);
emitMOVLL4(b, R8, regn, R4);
emitLDS(b, R10, R_PR);
++b->cycles;
b->pc += 2;
}
static void generateMOVBL(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitMOVLL4(b, R9, 0, R0);
emitSTS(b, R_PR, R10);
emitJSR(b, R0);
emitMOVLL4(b, R8, regm, R4);
emitALU(b, R0, R0, OP_EXTSB);
emitLDS(b, R10, R_PR);
emitMOVLS4(b, R0, regn, R8);
++b->cycles;
b->pc += 2;
}
static void generateMOVWL(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitMOVLL4(b, R9, 1, R0);
emitSTS(b, R_PR, R10);
emitJSR(b, R0);
emitMOVLL4(b, R8, regm, R4);
emitALU(b, R0, R0, OP_EXTSW);
emitLDS(b, R10, R_PR);
emitMOVLS4(b, R0, regn, R8);
++b->cycles;
b->pc += 2;
}
static void generateMOVLL(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitMOVLL4(b, R9, 2, R0);
emitSTS(b, R_PR, R10);
emitJSR(b, R0);
emitMOVLL4(b, R8, regm, R4);
emitLDS(b, R10, R_PR);
emitMOVLS4(b, R0, regn, R8);
++b->cycles;
b->pc += 2;
}
static void generateMOVBM(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitMOVLL4(b, R8, regm, R5);
emitMOVLL4(b, R9, 3, R0);
emitMOVLL4(b, R8, regn, R4);
emitSTS(b, R_PR, R10);
emitADDI(b, -1, R4);
emitJSR(b, R0);
emitMOVLS4(b, R4, regn, R8);
emitLDS(b, R10, R_PR);
++b->cycles;
b->pc += 2;
}
static void generateMOVWM(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitMOVLL4(b, R8, regm, R5);
emitMOVLL4(b, R9, 4, R0);
emitMOVLL4(b, R8, regn, R4);
emitSTS(b, R_PR, R10);
emitADDI(b, -2, R4);
emitJSR(b, R0);
emitMOVLS4(b, R4, regn, R8);
emitLDS(b, R10, R_PR);
++b->cycles;
b->pc += 2;
}
static void generateMOVLM(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitMOVLL4(b, R8, regm, R5);
emitMOVLL4(b, R9, 5, R0);
emitMOVLL4(b, R8, regn, R4);
emitSTS(b, R_PR, R10);
emitADDI(b, -4, R4);
emitJSR(b, R0);
emitMOVLS4(b, R4, regn, R8);
emitLDS(b, R10, R_PR);
++b->cycles;
b->pc += 2;
}
static void generateMOVBP(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitSTS(b, R_PR, R10);
emitMOVLL4(b, R9, 0, R0);
emitMOVLL4(b, R8, regm, R4);
emitMOVI(b, 1, R1);
emitALU(b, R4, R1, OP_ADD);
emitJSR(b, R0);
emitMOVLS4(b, R1, regm, R8);
emitALU(b, R0, R0, OP_EXTSB);
emitLDS(b, R10, R_PR);
emitMOVLS4(b, R0, regn, R8);
++b->cycles;
b->pc += 2;
}
static void generateMOVWP(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitSTS(b, R_PR, R10);
emitMOVLL4(b, R9, 1, R0);
emitMOVLL4(b, R8, regm, R4);
emitMOVI(b, 2, R1);
emitALU(b, R4, R1, OP_ADD);
emitJSR(b, R0);
emitMOVLS4(b, R1, regm, R8);
emitALU(b, R0, R0, OP_EXTSW);
emitLDS(b, R10, R_PR);
emitMOVLS4(b, R0, regn, R8);
++b->cycles;
b->pc += 2;
}
static void generateMOVLP(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitSTS(b, R_PR, R10);
emitMOVLL4(b, R9, 2, R0);
emitMOVLL4(b, R8, regm, R4);
emitMOVI(b, 4, R1);
emitALU(b, R4, R1, OP_ADD);
emitJSR(b, R0);
emitMOVLS4(b, R1, regm, R8);
emitLDS(b, R10, R_PR);
emitMOVLS4(b, R0, regn, R8);
++b->cycles;
b->pc += 2;
}
static void generateMOVBS0(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitMOVLL4(b, R8, regm, R5);
emitMOVLL4(b, R8, 0, R1);
emitMOVLL4(b, R9, 3, R0);
emitSTS(b, R_PR, R10);
emitMOVLL4(b, R8, regn, R4);
emitJSR(b, R0);
emitALU(b, R1, R4, OP_ADD);
emitLDS(b, R10, R_PR);
++b->cycles;
b->pc += 2;
}
static void generateMOVWS0(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitMOVLL4(b, R8, regm, R5);
emitMOVLL4(b, R8, 0, R1);
emitMOVLL4(b, R9, 4, R0);
emitSTS(b, R_PR, R10);
emitMOVLL4(b, R8, regn, R4);
emitJSR(b, R0);
emitALU(b, R1, R4, OP_ADD);
emitLDS(b, R10, R_PR);
++b->cycles;
b->pc += 2;
}
static void generateMOVLS0(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitMOVLL4(b, R8, regm, R5);
emitMOVLL4(b, R8, 0, R1);
emitMOVLL4(b, R9, 5, R0);
emitSTS(b, R_PR, R10);
emitMOVLL4(b, R8, regn, R4);
emitJSR(b, R0);
emitALU(b, R1, R4, OP_ADD);
emitLDS(b, R10, R_PR);
++b->cycles;
b->pc += 2;
}
static void generateMOVBL0(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitSTS(b, R_PR, R10);
emitMOVLL4(b, R9, 0, R0);
emitMOVLL4(b, R8, regm, R4);
emitMOVLL4(b, R8, 0, R1);
emitJSR(b, R0);
emitALU(b, R1, R4, OP_ADD);
emitALU(b, R0, R0, OP_EXTSB);
emitLDS(b, R10, R_PR);
emitMOVLS4(b, R0, regn, R8);
++b->cycles;
b->pc += 2;
}
static void generateMOVWL0(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitSTS(b, R_PR, R10);
emitMOVLL4(b, R9, 1, R0);
emitMOVLL4(b, R8, regm, R4);
emitMOVLL4(b, R8, 0, R1);
emitJSR(b, R0);
emitALU(b, R1, R4, OP_ADD);
emitALU(b, R0, R0, OP_EXTSW);
emitLDS(b, R10, R_PR);
emitMOVLS4(b, R0, regn, R8);
++b->cycles;
b->pc += 2;
}
static void generateMOVLL0(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitSTS(b, R_PR, R10);
emitMOVLL4(b, R9, 2, R0);
emitMOVLL4(b, R8, regm, R4);
emitMOVLL4(b, R8, 0, R1);
emitJSR(b, R0);
emitALU(b, R1, R4, OP_ADD);
emitLDS(b, R10, R_PR);
emitMOVLS4(b, R0, regn, R8);
++b->cycles;
b->pc += 2;
}
static void generateMOVI(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int imm = INSTRUCTION_CD(inst);
emitMOVI(b, imm, R2);
emitMOVLS4(b, R2, regn, R8);
++b->cycles;
b->pc += 2;
}
static void generateMOVWI(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int imm = INSTRUCTION_CD(inst);
uint32_t addr = b->pc + 4 + (imm << 1);
if(((uint32_t)b->ptr) & 0x03) {
emitMOVLI(b, 1, R4);
emitBRA(b, 2);
emitMOVLL4(b, R9, 1, R0);
emit32(b, addr);
}
else {
emitMOVLI(b, 1, R4);
emitBRA(b, 3);
emitMOVLL4(b, R9, 1, R0);
emit16(b, 0);
emit32(b, addr);
}
emitSTS(b, R_PR, R10);
emitJSR(b, R0);
emitNOP(b);
emitALU(b, R0, R0, OP_EXTSW);
emitLDS(b, R10, R_PR);
emitMOVLS4(b, R0, regn, R8);
++b->cycles;
b->pc += 2;
}
static void generateMOVLI(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int imm = INSTRUCTION_CD(inst);
uint32_t addr = ((b->pc + 4) & 0xFFFFFFFC) + (imm << 2);
if(((uint32_t)b->ptr) & 0x03) {
emitMOVLI(b, 1, R4);
emitBRA(b, 2);
emitMOVLL4(b, R9, 2, R0);
emit32(b, addr);
}
else {
emitMOVLI(b, 1, R4);
emitBRA(b, 3);
emitMOVLL4(b, R9, 2, R0);
emit16(b, 0);
emit32(b, addr);
}
emitSTS(b, R_PR, R10);
emitJSR(b, R0);
emitNOP(b);
emitLDS(b, R10, R_PR);
emitMOVLS4(b, R0, regn, R8);
++b->cycles;
b->pc += 2;
}
static void generateMOVBLG(uint16_t inst, sh2rec_block_t *b) {
int imm = INSTRUCTION_CD(inst);
emitSTS(b, R_PR, R10);
emitMOVLL4(b, R9, 0, R1);
emitMOVI(b, imm, R4);
emitMOVLLG(b, 17);
emitALU(b, R4, R4, OP_EXTUB);
emitJSR(b, R1);
emitALU(b, R0, R4, OP_ADD);
emitALU(b, R0, R0, OP_EXTSB);
emitLDS(b, R10, R_PR);
emitMOVLS4(b, R0, 0, R8);
++b->cycles;
b->pc += 2;
}
static void generateMOVWLG(uint16_t inst, sh2rec_block_t *b) {
int imm = INSTRUCTION_CD(inst);
emitSTS(b, R_PR, R10);
emitMOVI(b, imm, R4);
emitMOVLL4(b, R9, 1, R1);
emitALU(b, R4, R4, OP_EXTUB);
emitMOVLLG(b, 17);
emitSHIFT(b, R4, OP_SHLL);
emitJSR(b, R1);
emitALU(b, R0, R4, OP_ADD);
emitALU(b, R0, R0, OP_EXTSW);
emitLDS(b, R10, R_PR);
emitMOVLS4(b, R0, 0, R8);
++b->cycles;
b->pc += 2;
}
static void generateMOVLLG(uint16_t inst, sh2rec_block_t *b) {
int imm = INSTRUCTION_CD(inst);
emitSTS(b, R_PR, R10);
emitMOVI(b, imm, R4);
emitMOVLL4(b, R9, 2, R1);
emitALU(b, R4, R4, OP_EXTUB);
emitMOVLLG(b, 17);
emitSHLL2(b, R4);
emitJSR(b, R1);
emitALU(b, R0, R4, OP_ADD);
emitLDS(b, R10, R_PR);
emitMOVLS4(b, R0, 0, R8);
++b->cycles;
b->pc += 2;
}
static void generateMOVBSG(uint16_t inst, sh2rec_block_t *b) {
int imm = INSTRUCTION_CD(inst);
emitMOVLL4(b, R8, 0, R5);
emitMOVLLG(b, 17);
emitSTS(b, R_PR, R10);
emitMOVLL4(b, R9, 3, R1);
emitMOVI(b, imm, R4);
emitALU(b, R4, R4, OP_EXTUB);
emitJSR(b, R1);
emitALU(b, R0, R4, OP_ADD);
emitLDS(b, R10, R_PR);
++b->cycles;
b->pc += 2;
}
static void generateMOVWSG(uint16_t inst, sh2rec_block_t *b) {
int imm = INSTRUCTION_CD(inst);
emitMOVLL4(b, R8, 0, R5);
emitMOVI(b, imm, R4);
emitMOVLLG(b, 17);
emitALU(b, R4, R4, OP_EXTUB);
emitMOVLL4(b, R9, 4, R1);
emitSTS(b, R_PR, R10);
emitSHIFT(b, R4, OP_SHLL);
emitJSR(b, R1);
emitALU(b, R0, R4, OP_ADD);
emitLDS(b, R10, R_PR);
++b->cycles;
b->pc += 2;
}
static void generateMOVLSG(uint16_t inst, sh2rec_block_t *b) {
int imm = INSTRUCTION_CD(inst);
emitMOVLL4(b, R8, 0, R5);
emitMOVI(b, imm, R4);
emitMOVLLG(b, 17);
emitALU(b, R4, R4, OP_EXTUB);
emitMOVLL4(b, R9, 5, R1);
emitSTS(b, R_PR, R10);
emitSHLL2(b, R4);
emitJSR(b, R1);
emitALU(b, R0, R4, OP_ADD);
emitLDS(b, R10, R_PR);
++b->cycles;
b->pc += 2;
}
static void generateMOVBS4(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_C(inst);
int imm = INSTRUCTION_D(inst);
emitMOVLL4(b, R8, 0, R5);
emitMOVLL4(b, R9, 3, R1);
emitMOVLL4(b, R8, regn, R4);
emitSTS(b, R_PR, R10);
emitJSR(b, R1);
emitADDI(b, imm, R4);
emitLDS(b, R10, R_PR);
++b->cycles;
b->pc += 2;
}
static void generateMOVWS4(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_C(inst);
int imm = INSTRUCTION_D(inst) << 1;
emitMOVLL4(b, R8, 0, R5);
emitMOVLL4(b, R9, 4, R1);
emitMOVLL4(b, R8, regn, R4);
emitSTS(b, R_PR, R10);
emitJSR(b, R1);
emitADDI(b, imm, R4);
emitLDS(b, R10, R_PR);
++b->cycles;
b->pc += 2;
}
static void generateMOVLS4(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
int imm = INSTRUCTION_D(inst) << 2;
emitMOVLL4(b, R8, regm, R5);
emitMOVLL4(b, R9, 5, R1);
emitMOVLL4(b, R8, regn, R4);
emitSTS(b, R_PR, R10);
emitJSR(b, R1);
emitADDI(b, imm, R4);
emitLDS(b, R10, R_PR);
++b->cycles;
b->pc += 2;
}
static void generateMOVBL4(uint16_t inst, sh2rec_block_t *b) {
int regm = INSTRUCTION_C(inst);
int imm = INSTRUCTION_D(inst);
emitMOVLL4(b, R8, regm, R4);
emitMOVLL4(b, R9, 0, R1);
emitSTS(b, R_PR, R10);
emitJSR(b, R1);
emitADDI(b, imm, R4);
emitALU(b, R0, R0, OP_EXTSB);
emitLDS(b, R10, R_PR);
emitMOVLS4(b, R0, 0, R8);
++b->cycles;
b->pc += 2;
}
static void generateMOVWL4(uint16_t inst, sh2rec_block_t *b) {
int regm = INSTRUCTION_C(inst);
int imm = INSTRUCTION_D(inst) << 1;
emitMOVLL4(b, R8, regm, R4);
emitMOVLL4(b, R9, 1, R1);
emitSTS(b, R_PR, R10);
emitJSR(b, R1);
emitADDI(b, imm, R4);
emitALU(b, R0, R0, OP_EXTSW);
emitLDS(b, R10, R_PR);
emitMOVLS4(b, R0, 0, R8);
++b->cycles;
b->pc += 2;
}
static void generateMOVLL4(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
int imm = INSTRUCTION_D(inst) << 2;
emitMOVLL4(b, R8, regm, R4);
emitMOVLL4(b, R9, 2, R1);
emitSTS(b, R_PR, R10);
emitJSR(b, R1);
emitADDI(b, imm, R4);
emitLDS(b, R10, R_PR);
emitMOVLS4(b, R0, regn, R8);
++b->cycles;
b->pc += 2;
}
static void generateMOVA(uint16_t inst, sh2rec_block_t *b) {
int imm = INSTRUCTION_CD(inst);
uint32_t addr = ((b->pc + 4) & 0xFFFFFFFC) + (imm << 2);
if(((uint32_t)b->ptr) & 0x03) {
emitMOVLI(b, 1, R2);
emitBRA(b, 2);
emitMOVLS4(b, R2, 0, R8);
emit32(b, addr);
}
else {
emitMOVLI(b, 1, R2);
emitBRA(b, 3);
emitMOVLS4(b, R2, 0, R8);
emit16(b, 0);
emit32(b, addr);
}
++b->cycles;
b->pc += 2;
}
static void generateMOVT(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
emitMOVLLG(b, 16);
emitANDI(b, 0x01);
emitMOVLS4(b, R0, regn, R8);
++b->cycles;
b->pc += 2;
}
static void generateMULL(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitMOVLL4(b, R8, regn, R2);
emitMOVLL4(b, R8, regm, R3);
emitALU(b, R3, R2, OP_MULL);
b->cycles += 2;
b->pc += 2;
}
static void generateMULS(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitMOVLL4(b, R8, regn, R2);
emitMOVLL4(b, R8, regm, R3);
emitALU(b, R3, R2, OP_MULS);
++b->cycles;
b->pc += 2;
}
static void generateMULU(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitMOVLL4(b, R8, regn, R2);
emitMOVLL4(b, R8, regm, R3);
emitALU(b, R3, R2, OP_MULU);
++b->cycles;
b->pc += 2;
}
static void generateNEG(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitMOVLL4(b, R8, regm, R3);
emitALU(b, R3, R2, OP_NEG);
emitMOVLS4(b, R2, regn, R8);
++b->cycles;
b->pc += 2;
}
static void generateNEGC(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitMOVLLG(b, 16);
emitMOVLL4(b, R8, regm, R3);
emitSHIFT(b, R0, OP_ROTCR);
emitALU(b, R3, R2, OP_NEGC);
emitSHIFT(b, R0, OP_ROTCL);
emitMOVLS4(b, R2, regn, R8);
emitMOVLSG(b, 16);
++b->cycles;
b->pc += 2;
}
static void generateNOP(uint16_t inst, sh2rec_block_t *b) {
++b->cycles;
b->pc += 2;
}
static void generateNOT(uint16_t inst, sh2rec_block_t *b) {
generateALUOP(inst, b, OP_NOT);
b->pc += 2;
}
static void generateOR(uint16_t inst, sh2rec_block_t *b) {
generateALUOP(inst, b, OP_OR);
b->pc += 2;
}
static void generateORI(uint16_t inst, sh2rec_block_t *b) {
int imm = INSTRUCTION_CD(inst);
emitMOVLL4(b, R8, 0, R0);
emitORI(b, imm);
emitMOVLS4(b, R0, 0, R8);
++b->cycles;
b->pc += 2;
}
static void generateORM(uint16_t inst, sh2rec_block_t *b) {
int imm = INSTRUCTION_CD(inst);
emitSTS(b, R_PR, R10);
emitMOVLLG(b, 17);
emitMOVLL4(b, R8, 0, R4);
emitMOVLL4(b, R9, 0, R1);
emitALU(b, R0, R4, OP_ADD);
emitJSR(b, R1);
emitMOVLM(b, R4, R15);
emitMOVLL4(b, R9, 3, R1);
emitORI(b, imm);
emitMOVLP(b, R15, R4);
emitJSR(b, R1);
emitMOV(b, R0, R5);
emitLDS(b, R10, R_PR);
b->cycles += 3;
b->pc += 2;
}
static void generateROTCL(uint16_t inst, sh2rec_block_t *b) {
generateSHIFT(inst, b, OP_ROTCL);
b->pc += 2;
}
static void generateROTCR(uint16_t inst, sh2rec_block_t *b) {
generateSHIFT(inst, b, OP_ROTCR);
b->pc += 2;
}
static void generateROTL(uint16_t inst, sh2rec_block_t *b) {
generateSHIFT(inst, b, OP_ROTL);
b->pc += 2;
}
static void generateROTR(uint16_t inst, sh2rec_block_t *b) {
generateSHIFT(inst, b, OP_ROTR);
b->pc += 2;
}
static void generateRTE(uint16_t inst, sh2rec_block_t *b) {
emitMOVLL4(b, R9, 2, R0);
emitSTS(b, R_PR, R10);
emitJSR(b, R0);
emitMOVLL4(b, R8, 15, R4);
emitMOVLL4(b, R9, 2, R1);
emitMOVLL4(b, R8, 15, R4);
emitMOVI(b, 4, R2);
emitALU(b, R2, R4, OP_ADD);
emitMOVLM(b, R0, R15);
emitALU(b, R4, R2, OP_ADD);
emitJSR(b, R1);
emitMOVLS4(b, R2, 15, R8);
emitMOVWI(b, 1, R1);
emitBRA(b, 1);
emitALU(b, R1, R0, OP_AND);
emit16(b, 0x03F3);
emitLDS(b, R10, R_PR);
emitMOVLSG(b, 16);
b->pc += 2;
sh2rec_rec_inst(b, 1);
emitRTS(b);
emitMOVLP(b, R15, R0);
b->cycles += 4;
}
static void generateRTS(uint16_t inst, sh2rec_block_t *b) {
emitMOVLLG(b, 21);
emitMOVLM(b, R0, R15);
b->pc += 2;
sh2rec_rec_inst(b, 1);
emitRTS(b);
emitMOVLP(b, R15, R0);
b->cycles += 2;
}
static void generateSETT(uint16_t inst, sh2rec_block_t *b) {
emitMOVLLG(b, 16);
emitORI(b, 0x01);
emitMOVLSG(b, 16);
++b->cycles;
b->pc += 2;
}
static void generateSHAL(uint16_t inst, sh2rec_block_t *b) {
generateSHIFT(inst, b, OP_SHAL);
b->pc += 2;
}
static void generateSHAR(uint16_t inst, sh2rec_block_t *b) {
generateSHIFT(inst, b, OP_SHAR);
b->pc += 2;
}
static void generateSHLL(uint16_t inst, sh2rec_block_t *b) {
generateSHIFT(inst, b, OP_SHLL);
b->pc += 2;
}
static void generateSHLL2(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
emitMOVLL4(b, R8, regn, R2);
emitSHLL2(b, R2);
emitMOVLS4(b, R2, regn, R8);
++b->cycles;
b->pc += 2;
}
static void generateSHLL8(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
emitMOVLL4(b, R8, regn, R2);
emitSHLL8(b, R2);
emitMOVLS4(b, R2, regn, R8);
++b->cycles;
b->pc += 2;
}
static void generateSHLL16(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
emitMOVLL4(b, R8, regn, R2);
emitSHLL16(b, R2);
emitMOVLS4(b, R2, regn, R8);
++b->cycles;
b->pc += 2;
}
static void generateSHLR(uint16_t inst, sh2rec_block_t *b) {
generateSHIFT(inst, b, OP_SHLR);
b->pc += 2;
}
static void generateSHLR2(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
emitMOVLL4(b, R8, regn, R2);
emitSHLR2(b, R2);
emitMOVLS4(b, R2, regn, R8);
++b->cycles;
b->pc += 2;
}
static void generateSHLR8(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
emitMOVLL4(b, R8, regn, R2);
emitSHLR8(b, R2);
emitMOVLS4(b, R2, regn, R8);
++b->cycles;
b->pc += 2;
}
static void generateSHLR16(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
emitMOVLL4(b, R8, regn, R2);
emitSHLR16(b, R2);
emitMOVLS4(b, R2, regn, R8);
++b->cycles;
b->pc += 2;
}
static void generateSLEEP(uint16_t inst, sh2rec_block_t *b) {
b->cycles += 3;
b->pc += 2;
}
static void generateSTCSR(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
emitMOVLLG(b, 16);
emitMOVLS4(b, R0, regn, R8);
++b->cycles;
b->pc += 2;
}
static void generateSTCGBR(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
emitMOVLLG(b, 17);
emitMOVLS4(b, R0, regn, R8);
++b->cycles;
b->pc += 2;
}
static void generateSTCVBR(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
emitMOVLLG(b, 18);
emitMOVLS4(b, R0, regn, R8);
++b->cycles;
b->pc += 2;
}
static void generateSTCMSR(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
emitMOVLLG(b, 16);
emitMOVLL4(b, R9, 5, R1);
emitMOVLL4(b, R8, regn, R4);
emitSTS(b, R_PR, R10);
emitADDI(b, -4, R4);
emitMOV(b, R0, R5);
emitJSR(b, R1);
emitMOVLS4(b, R4, regn, R8);
emitLDS(b, R10, R_PR);
b->cycles += 2;
b->pc += 2;
}
static void generateSTCMGBR(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
emitMOVLLG(b, 17);
emitMOVLL4(b, R9, 5, R1);
emitMOVLL4(b, R8, regn, R4);
emitSTS(b, R_PR, R10);
emitADDI(b, -4, R4);
emitMOV(b, R0, R5);
emitJSR(b, R1);
emitMOVLS4(b, R4, regn, R8);
emitLDS(b, R10, R_PR);
b->cycles += 2;
b->pc += 2;
}
static void generateSTCMVBR(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
emitMOVLLG(b, 18);
emitMOVLL4(b, R9, 5, R1);
emitMOVLL4(b, R8, regn, R4);
emitSTS(b, R_PR, R10);
emitADDI(b, -4, R4);
emitMOV(b, R0, R5);
emitJSR(b, R1);
emitMOVLS4(b, R4, regn, R8);
emitLDS(b, R10, R_PR);
b->cycles += 2;
b->pc += 2;
}
static void generateSTSMACH(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
emitSTS(b, R_MACH, R0);
emitMOVLS4(b, R0, regn, R8);
++b->cycles;
b->pc += 2;
}
static void generateSTSMACL(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
emitSTS(b, R_MACL, R0);
emitMOVLS4(b, R0, regn, R8);
++b->cycles;
b->pc += 2;
}
static void generateSTSPR(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
emitMOVLLG(b, 21);
emitMOVLS4(b, R0, regn, R8);
++b->cycles;
b->pc += 2;
}
static void generateSTSMMACH(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
emitSTS(b, R_MACH, R5);
emitMOVLL4(b, R9, 5, R1);
emitMOVLL4(b, R8, regn, R4);
emitSTS(b, R_PR, R10);
emitADDI(b, -4, R4);
emitJSR(b, R1);
emitMOVLS4(b, R4, regn, R8);
emitLDS(b, R10, R_PR);
++b->cycles;
b->pc += 2;
}
static void generateSTSMMACL(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
emitSTS(b, R_MACL, R5);
emitMOVLL4(b, R9, 5, R1);
emitMOVLL4(b, R8, regn, R4);
emitSTS(b, R_PR, R10);
emitADDI(b, -4, R4);
emitJSR(b, R1);
emitMOVLS4(b, R4, regn, R8);
emitLDS(b, R10, R_PR);
++b->cycles;
b->pc += 2;
}
static void generateSTSMPR(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
emitMOVLLG(b, 21);
emitMOVLL4(b, R9, 5, R1);
emitMOVLL4(b, R8, regn, R4);
emitSTS(b, R_PR, R10);
emitADDI(b, -4, R4);
emitMOV(b, R0, R5);
emitJSR(b, R1);
emitMOVLS4(b, R4, regn, R8);
emitLDS(b, R10, R_PR);
++b->cycles;
b->pc += 2;
}
static void generateSUB(uint16_t inst, sh2rec_block_t *b) {
generateALUOP(inst, b, OP_SUB);
b->pc += 2;
}
static void generateSUBC(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitMOVLLG(b, 16);
emitMOVLL4(b, R8, regn, R2);
emitMOVLL4(b, R8, regm, R3);
emitSHIFT(b, R0, OP_ROTCR);
emitALU(b, R3, R2, OP_SUBC);
emitSHIFT(b, R0, OP_ROTCL);
emitMOVLS4(b, R2, regn, R8);
emitMOVLSG(b, 16);
++b->cycles;
b->pc += 2;
}
static void generateSUBV(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
int regm = INSTRUCTION_C(inst);
emitMOVLLG(b, 16);
emitMOVLL4(b, R8, regn, R2);
emitMOVLL4(b, R8, regm, R3);
emitSHIFT(b, R0, OP_ROTCR);
emitSUBV(b, R3, R2);
emitSHIFT(b, R0, OP_ROTCL);
emitMOVLSG(b, 16);
++b->cycles;
b->pc += 2;
}
static void generateSWAPB(uint16_t inst, sh2rec_block_t *b) {
generateALUOP(inst, b, OP_SWAPB);
b->pc += 2;
}
static void generateSWAPW(uint16_t inst, sh2rec_block_t *b) {
generateALUOP(inst, b, OP_SWAPW);
b->pc += 2;
}
static void generateTAS(uint16_t inst, sh2rec_block_t *b) {
int regn = INSTRUCTION_B(inst);
emitMOVLL4(b, R9, 0, R0);
emitSTS(b, R_PR, R10);
emitJSR(b, R0);
emitMOVLL4(b, R8, regn, R4);
emitMOV(b, R0, R5);
emitMOVLLG(b, 16);
emitMOVI(b, 0x80, R2);
emitMOVLL4(b, R8, regn, R4);
emitSHIFT(b, R0, OP_ROTCR);
emitALU(b, R5, R5, OP_TST);
emitSHIFT(b, R0, OP_ROTCL);
emitMOVLL4(b, R9, 3, R1);
emitMOVLSG(b, 16);
emitJSR(b, R1);
emitALU(b, R2, R5, OP_OR);
emitLDS(b, R10, R_PR);
b->cycles += 4;
b->pc += 2;
}
static void generateTRAPA(uint16_t inst, sh2rec_block_t *b) {
int imm = INSTRUCTION_CD(inst);
int disp = (((uint32_t)(b->ptr)) & 0x03) ? 5 : 6;
uint32_t val = b->pc + 2;
emitSTS(b, R_PR, R10);
emitMOVLL4(b, R8, 15, R4);
emitMOVLL4(b, R9, 5, R1);
emitMOVLLG(b, 16);
emitADDI(b, -4, R4);
emitJSR(b, R1);
emitMOV(b, R0, R5);
emitMOVLL4(b, R8, 15, R4);
emitMOVLL4(b, R9, 5, R1);
emitADDI(b, -8, R4);
emitMOVLI(b, disp, R5);
emitJSR(b, R1);
emitMOVLS4(b, R4, 15, R8);
emitMOVI(b, imm, R4);
emitALU(b, R4, R4, OP_EXTUB);
emitMOVLL4(b, R9, 2, R1);
emitMOVLLG(b, 18);
emitSHLL2(b, R4);
emitJSR(b, R1);
emitALU(b, R0, R4, OP_ADD);
emitLDS(b, R10, R_PR);
emitRTS(b);
emitNOP(b);
if(((uint32_t)b->ptr) & 0x03)
emit16(b, 0);
emit32(b, val);
b->cycles += 8;
}
static void generateTST(uint16_t inst, sh2rec_block_t *b) {
generateCOMP(inst, b, OP_TST);
b->pc += 2;
}
static void generateTSTI(uint16_t inst, sh2rec_block_t *b) {
int imm = INSTRUCTION_CD(inst);
emitMOVLLG(b, 16);
emitMOV(b, R0, R2);
emitMOVLL4(b, R8, 0, R0);
emitSHIFT(b, R2, OP_ROTCR);
emitTSTI(b, imm);
emitSHIFT(b, R2, OP_ROTCL);
emitMOV(b, R2, R0);
emitMOVLSG(b, 16);
++b->cycles;
b->pc += 2;
}
static void generateTSTM(uint16_t inst, sh2rec_block_t *b) {
int imm = INSTRUCTION_CD(inst);
emitSTS(b, R_PR, R10);
emitMOVLL4(b, R9, 0, R1);
emitMOVLLG(b, 17);
emitMOVLL4(b, R8, 0, R4);
emitJSR(b, R1);
emitALU(b, R0, R4, OP_ADD);
emitMOV(b, R0, R5);
emitMOVI(b, imm, R3);
emitMOVLLG(b, 16);
emitSHIFT(b, R0, OP_ROTCR);
emitALU(b, R3, R5, OP_TST);
emitSHIFT(b, R0, OP_ROTCL);
emitMOVLSG(b, 16);
emitLDS(b, R10, R_PR);
b->cycles += 3;
b->pc += 2;
}
static void generateXOR(uint16_t inst, sh2rec_block_t *b) {
generateALUOP(inst, b, OP_XOR);
b->pc += 2;
}
static void generateXORI(uint16_t inst, sh2rec_block_t *b) {
int imm = INSTRUCTION_CD(inst);
emitMOVLL4(b, R8, 0, R0);
emitXORI(b, imm);
emitMOVLS4(b, R0, 0, R8);
++b->cycles;
b->pc += 2;
}
static void generateXORM(uint16_t inst, sh2rec_block_t *b) {
int imm = INSTRUCTION_CD(inst);
emitSTS(b, R_PR, R10);
emitMOVLLG(b, 17);
emitMOVLL4(b, R8, 0, R4);
emitMOVLL4(b, R9, 0, R1);
emitALU(b, R0, R4, OP_ADD);
emitJSR(b, R1);
emitMOVLM(b, R4, R15);
emitMOVLL4(b, R9, 3, R1);
emitXORI(b, imm);
emitMOVLP(b, R15, R4);
emitJSR(b, R1);
emitMOV(b, R0, R5);
emitLDS(b, R10, R_PR);
b->cycles += 3;
b->pc += 2;
}
static void generateXTRCT(uint16_t inst, sh2rec_block_t *b) {
generateALUOP(inst, b, OP_XTRCT);
b->pc += 2;
}
int sh2rec_rec_inst(sh2rec_block_t *b, int isdelay) {
uint16_t inst = MappedMemoryReadWord(b->pc);
int done = 0;
switch(INSTRUCTION_A(inst)) {
case 0:
switch(INSTRUCTION_D(inst)) {
case 2:
switch(INSTRUCTION_C(inst)) {
case 0: generateSTCSR(inst, b); break;
case 1: generateSTCGBR(inst, b); break;
case 2: generateSTCVBR(inst, b); break;
default: return -1;
}
break;
case 3:
switch(INSTRUCTION_C(inst)) {
case 0: generateBSRF(inst, b); done = 1; break;
case 2: generateBRAF(inst, b); done = 1; break;
default: return -1;
}
break;
case 4: generateMOVBS0(inst, b); break;
case 5: generateMOVWS0(inst, b); break;
case 6: generateMOVLS0(inst, b); break;
case 7: generateMULL(inst, b); break;
case 8:
switch(INSTRUCTION_C(inst)) {
case 0: generateCLRT(inst, b); break;
case 1: generateSETT(inst, b); break;
case 2: generateCLRMAC(inst, b); break;
default: return -1;
}
break;
case 9:
switch(INSTRUCTION_C(inst)) {
case 0: generateNOP(inst, b); break;
case 1: generateDIV0U(inst, b); break;
case 2: generateMOVT(inst, b); break;
default: return -1;
}
break;
case 10:
switch(INSTRUCTION_C(inst)) {
case 0: generateSTSMACH(inst, b); break;
case 1: generateSTSMACL(inst, b); break;
case 2: generateSTSPR(inst, b); break;
default: return -1;
}
break;
case 11:
switch(INSTRUCTION_C(inst)) {
case 0: generateRTS(inst, b); done = 1; break;
case 1: generateSLEEP(inst, b); break;
case 2: generateRTE(inst, b); done = 1; break;
default: return -1;
}
break;
case 12: generateMOVBL0(inst, b); break;
case 13: generateMOVWL0(inst, b); break;
case 14: generateMOVLL0(inst, b); break;
case 15: generateMACL(inst, b); break;
default: return -1;
}
break;
case 1: generateMOVLS4(inst, b); break;
case 2:
switch(INSTRUCTION_D(inst)) {
case 0: generateMOVBS(inst, b); break;
case 1: generateMOVWS(inst, b); break;
case 2: generateMOVLS(inst, b); break;
case 4: generateMOVBM(inst, b); break;
case 5: generateMOVWM(inst, b); break;
case 6: generateMOVLM(inst, b); break;
case 7: generateDIV0S(inst, b); break;
case 8: generateTST(inst, b); break;
case 9: generateAND(inst, b); break;
case 10: generateXOR(inst, b); break;
case 11: generateOR(inst, b); break;
case 12: generateCMPSTR(inst, b); break;
case 13: generateXTRCT(inst, b); break;
case 14: generateMULU(inst, b); break;
case 15: generateMULS(inst, b); break;
default: return -1;
}
break;
case 3:
switch(INSTRUCTION_D(inst)) {
case 0: generateCMPEQ(inst, b); break;
case 2: generateCMPHS(inst, b); break;
case 3: generateCMPGE(inst, b); break;
case 4: generateDIV1(inst, b); break;
case 5: generateDMULU(inst, b); break;
case 6: generateCMPHI(inst, b); break;
case 7: generateCMPGT(inst, b); break;
case 8: generateSUB(inst, b); break;
case 10: generateSUBC(inst, b); break;
case 11: generateSUBV(inst, b); break;
case 12: generateADD(inst, b); break;
case 13: generateDMULS(inst, b); break;
case 14: generateADDC(inst, b); break;
case 15: generateADDV(inst, b); break;
default: return -1;
}
break;
case 4:
switch(INSTRUCTION_D(inst)) {
case 0:
switch(INSTRUCTION_C(inst)) {
case 0: generateSHLL(inst, b); break;
case 1: generateDT(inst, b); break;
case 2: generateSHAL(inst, b); break;
default: return -1;
}
break;
case 1:
switch(INSTRUCTION_C(inst)) {
case 0: generateSHLR(inst, b); break;
case 1: generateCMPPZ(inst, b); break;
case 2: generateSHAR(inst, b); break;
default: return -1;
}
break;
case 2:
switch(INSTRUCTION_C(inst)) {
case 0: generateSTSMMACH(inst, b); break;
case 1: generateSTSMMACL(inst, b); break;
case 2: generateSTSMPR(inst, b); break;
default: return -1;
}
break;
case 3:
switch(INSTRUCTION_C(inst)) {
case 0: generateSTCMSR(inst, b); break;
case 1: generateSTCMGBR(inst, b); break;
case 2: generateSTCMVBR(inst, b); break;
default: return -1;
}
break;
case 4:
switch(INSTRUCTION_C(inst)) {
case 0: generateROTL(inst, b); break;
case 2: generateROTCL(inst, b); break;
default: return -1;
}
break;
case 5:
switch(INSTRUCTION_C(inst)) {
case 0: generateROTR(inst, b); break;
case 1: generateCMPPL(inst, b); break;
case 2: generateROTCR(inst, b); break;
default: return -1;
}
break;
case 6:
switch(INSTRUCTION_C(inst)) {
case 0: generateLDSMMACH(inst, b); break;
case 1: generateLDSMMACL(inst, b); break;
case 2: generateLDSMPR(inst, b); break;
default: return -1;
}
break;
case 7:
switch(INSTRUCTION_C(inst)) {
case 0: generateLDCMSR(inst, b); break;
case 1: generateLDCMGBR(inst, b); break;
case 2: generateLDCMVBR(inst, b); break;
default: return -1;
}
break;
case 8:
switch(INSTRUCTION_C(inst)) {
case 0: generateSHLL2(inst, b); break;
case 1: generateSHLL8(inst, b); break;
case 2: generateSHLL16(inst, b); break;
default: return -1;
}
break;
case 9:
switch(INSTRUCTION_C(inst)) {
case 0: generateSHLR2(inst, b); break;
case 1: generateSHLR8(inst, b); break;
case 2: generateSHLR16(inst, b); break;
default: return -1;
}
break;
case 10:
switch(INSTRUCTION_C(inst)) {
case 0: generateLDSMACH(inst, b); break;
case 1: generateLDSMACL(inst, b); break;
case 2: generateLDSPR(inst, b); break;
default: return -1;
}
break;
case 11:
switch(INSTRUCTION_C(inst)) {
case 0: generateJSR(inst, b); done = 1; break;
case 1: generateTAS(inst, b); break;
case 2: generateJMP(inst, b); done = 1; break;
default: return -1;
}
break;
case 14:
switch(INSTRUCTION_C(inst)) {
case 0: generateLDCSR(inst, b); break;
case 1: generateLDCGBR(inst, b); break;
case 2: generateLDCVBR(inst, b); break;
default: return -1;
}
break;
case 15: generateMACW(inst, b); break;
default: return -1;
}
break;
case 5: generateMOVLL4(inst, b); break;
case 6:
switch(INSTRUCTION_D(inst)) {
case 0: generateMOVBL(inst, b); break;
case 1: generateMOVWL(inst, b); break;
case 2: generateMOVLL(inst, b); break;
case 3: generateMOV(inst, b); break;
case 4: generateMOVBP(inst, b); break;
case 5: generateMOVWP(inst, b); break;
case 6: generateMOVLP(inst, b); break;
case 7: generateNOT(inst, b); break;
case 8: generateSWAPB(inst, b); break;
case 9: generateSWAPW(inst, b); break;
case 10: generateNEGC(inst, b); break;
case 11: generateNEG(inst, b); break;
case 12: generateEXTUB(inst, b); break;
case 13: generateEXTUW(inst, b); break;
case 14: generateEXTSB(inst, b); break;
case 15: generateEXTSW(inst, b); break;
}
break;
case 7: generateADDI(inst, b); break;
case 8:
switch(INSTRUCTION_B(inst)) {
case 0: generateMOVBS4(inst, b); break;
case 1: generateMOVWS4(inst, b); break;
case 4: generateMOVBL4(inst, b); break;
case 5: generateMOVWL4(inst, b); break;
case 8: generateCMPIM(inst, b); break;
case 9: generateBT(inst, b); done = 1; break;
case 11: generateBF(inst, b); done = 1; break;
case 13: generateBTS(inst, b); done = 1; break;
case 15: generateBFS(inst, b); done = 1; break;
default: return -1;
}
break;
case 9: generateMOVWI(inst, b); break;
case 10: generateBRA(inst, b); done = 1; break;
case 11: generateBSR(inst, b); done = 1; break;
case 12:
switch(INSTRUCTION_B(inst)) {
case 0: generateMOVBSG(inst, b); break;
case 1: generateMOVWSG(inst, b); break;
case 2: generateMOVLSG(inst, b); break;
case 3: generateTRAPA(inst, b); done = 1; break;
case 4: generateMOVBLG(inst, b); break;
case 5: generateMOVWLG(inst, b); break;
case 6: generateMOVLLG(inst, b); break;
case 7: generateMOVA(inst, b); break;
case 8: generateTSTI(inst, b); break;
case 9: generateANDI(inst, b); break;
case 10: generateXORI(inst, b); break;
case 11: generateORI(inst, b); break;
case 12: generateTSTM(inst, b); break;
case 13: generateANDM(inst, b); break;
case 14: generateXORM(inst, b); break;
case 15: generateORM(inst, b); break;
}
break;
case 13: generateMOVLI(inst, b); break;
case 14: generateMOVI(inst, b); break;
default: return -1;
}
return done;
}
int sh2rec_rec_block(sh2rec_block_t *b) {
int done = 0;
while(!done) {
done = sh2rec_rec_inst(b, 0);
}
icache_flush_range((uint32)b->block, ((u32)b->ptr) - ((u32)b->block));
return 0;
}
extern void sh2rec_exec(SH2_struct *cxt, u32 cycles);
static int sh2rec_init(void) {
sh2rec_htab_init();
return 0;
}
static void sh2rec_deinit(void) {
sh2rec_htab_reset();
}
static void sh2rec_reset(void) {
sh2rec_htab_reset();
}
void sh2rec_check_interrupts(SH2_struct *c) {
if(c->NumberOfInterrupts != 0) {
if(c->interrupts[c->NumberOfInterrupts-1].level > c->regs.SR.part.I) {
c->regs.R[15] -= 4;
MappedMemoryWriteLong(c->regs.R[15], c->regs.SR.all);
c->regs.R[15] -= 4;
MappedMemoryWriteLong(c->regs.R[15], c->regs.PC);
c->regs.SR.part.I = c->interrupts[c->NumberOfInterrupts - 1].level;
c->regs.PC = MappedMemoryReadLong(c->regs.VBR + (c->interrupts[c->NumberOfInterrupts-1].vector << 2));
c->NumberOfInterrupts--;
c->isSleeping = 0;
}
}
}
sh2rec_block_t *sh2rec_find_block(u32 pc) {
sh2rec_block_t *b = sh2rec_htab_lookup(pc);
if(!b) {
b = sh2rec_htab_block_create(pc, 4096);
sh2rec_rec_block(b);
}
return b;
}
SH2Interface_struct SH2Dynarec = {
SH2CORE_DYNAREC,
"SH2 -> SH4 Dynarec",
sh2rec_init,
sh2rec_deinit,
sh2rec_reset,
sh2rec_exec,
SH2InterpreterGetRegisters,
SH2InterpreterGetGPR,
SH2InterpreterGetSR,
SH2InterpreterGetGBR,
SH2InterpreterGetVBR,
SH2InterpreterGetMACH,
SH2InterpreterGetMACL,
SH2InterpreterGetPR,
SH2InterpreterGetPC,
SH2InterpreterSetRegisters,
SH2InterpreterSetGPR,
SH2InterpreterSetSR,
SH2InterpreterSetGBR,
SH2InterpreterSetVBR,
SH2InterpreterSetMACH,
SH2InterpreterSetMACL,
SH2InterpreterSetPR,
SH2InterpreterSetPC,
SH2InterpreterSendInterrupt,
SH2InterpreterGetInterrupts,
SH2InterpreterSetInterrupts,
NULL
};