rec-arm: fix immediate writem bug. clean up
get rid of unused and unstable opts div32p2 implementation (untested) Fixed canonical test mode
This commit is contained in:
parent
70ea7c4d76
commit
af2ba55bac
|
@ -591,6 +591,19 @@ ADD.SP.REG 0x008D0000
|
|||
EMIT_I;
|
||||
}
|
||||
|
||||
EAPI SBFX(eReg Rd, eReg Rm, u8 lsb, u8 width, ConditionCode CC=AL)
|
||||
{
|
||||
DECL_Id(0x07A00050);
|
||||
verify(lsb+width<=32);
|
||||
|
||||
SET_CC;
|
||||
I |= (Rd&15)<<12;
|
||||
I |= (Rm&15);
|
||||
I |= (lsb&31)<<7;
|
||||
I |= ((width-1)&31)<<16;
|
||||
EMIT_I;
|
||||
}
|
||||
|
||||
EAPI MOV(eReg Rd, eReg Rm, ConditionCode CC=AL)
|
||||
{
|
||||
DECL_Id(0x01A00000);
|
||||
|
@ -844,4 +857,4 @@ ADD.SP.REG 0x008D0000
|
|||
|
||||
|
||||
|
||||
};
|
||||
};
|
||||
|
|
|
@ -242,6 +242,8 @@ EAPI LDRH(eReg Rt, eReg Rn, s32 sImm8, ConditionCode CC=AL) { DECL_Id(0x005000B0
|
|||
EAPI STRH(eReg Rt, eReg Rn, s32 sImm8, ConditionCode CC=AL) { DECL_Id(0x004000B0); SET_CC; SET_Rtn; SET_P; SET_sImm8; EMIT_I; }
|
||||
EAPI LDRD(eReg Rt, eReg Rn, s32 sImm8, ConditionCode CC=AL) { DECL_Id(0x004000D0); SET_CC; SET_Rtn; SET_P; SET_sImm8; EMIT_I; }
|
||||
EAPI STRD(eReg Rt, eReg Rn, s32 sImm8, ConditionCode CC=AL) { DECL_Id(0x004000F0); SET_CC; SET_Rtn; SET_P; SET_sImm8; EMIT_I; }
|
||||
EAPI LDRSB(eReg Rt, eReg Rn, s32 sImm8 = 0, ConditionCode CC = AL) { DECL_Id(0x005000D0); SET_CC; SET_Rtn; SET_P; SET_sImm8; EMIT_I; }
|
||||
EAPI LDRSH(eReg Rt, eReg Rn, s32 sImm8 = 0, ConditionCode CC = AL) { DECL_Id(0x005000F0); SET_CC; SET_Rtn; SET_P; SET_sImm8; EMIT_I; }
|
||||
|
||||
EAPI LDRH(eReg Rt, eReg Rn, eReg Rm, bool Add=true,ConditionCode CC=AL) { DECL_Id(0x001000B0); SET_CC; SET_Rtnm; SET_P; if (Add) {SET_U;} EMIT_I; }
|
||||
EAPI STRH(eReg Rt, eReg Rn, eReg Rm, bool Add=true,ConditionCode CC=AL) { DECL_Id(0x000000B0); SET_CC; SET_Rtnm; SET_P; if (Add) {SET_U;} EMIT_I; }
|
||||
|
@ -307,4 +309,4 @@ EAPI POP(u32 RegList, ConditionCode CC=AL)
|
|||
|
||||
|
||||
|
||||
};
|
||||
};
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#define _DEVEL 1
|
||||
#include "arm_emitter/arm_emitter.h"
|
||||
|
||||
//#define CANONICALTEST
|
||||
|
||||
/*
|
||||
|
||||
ARM ABI
|
||||
|
@ -303,8 +305,12 @@ u32 DynaRBI::Relink()
|
|||
{
|
||||
//quick opt here:
|
||||
//peek into reg alloc, store actuall sr_T register to relink_data
|
||||
#ifndef CANONICALTEST
|
||||
bool last_op_sets_flags=!has_jcond && oplist.size() > 0 &&
|
||||
oplist[oplist.size()-1].rd._reg==reg_sr_T && ccmap.count(oplist[oplist.size()-1].op);
|
||||
#else
|
||||
bool last_op_sets_flags = false;
|
||||
#endif
|
||||
|
||||
ConditionCode CC=CC_EQ;
|
||||
|
||||
|
@ -636,33 +642,34 @@ void ngen_CC_Param(shil_opcode* op,shil_param* par,CanonicalParamType tp)
|
|||
}
|
||||
}
|
||||
|
||||
void ngen_CC_Call(shil_opcode* op,void* function)
|
||||
void ngen_CC_Call(shil_opcode* op, void* function)
|
||||
{
|
||||
u32 rd=r0;
|
||||
u32 fd=f0;
|
||||
u32 rd = r0;
|
||||
u32 fd = f0;
|
||||
|
||||
for (int i=CC_pars.size();i-->0;)
|
||||
for (int i = CC_pars.size(); i-- > 0; )
|
||||
{
|
||||
if (CC_pars[i].type==CPT_ptr)
|
||||
CC_PS& param = CC_pars[i];
|
||||
if (param.type == CPT_ptr)
|
||||
{
|
||||
MOV32((eReg)rd, (u32)CC_pars[i].par->reg_ptr());
|
||||
MOV32((eReg)rd, (u32)param.par->reg_ptr());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (CC_pars[i].par->is_reg())
|
||||
if (param.par->is_reg())
|
||||
{
|
||||
#ifdef ARM_HARDFP
|
||||
if (CC_pars[i].type == CPT_f32)
|
||||
if (param.type == CPT_f32)
|
||||
{
|
||||
if (reg.IsAllocg(*CC_pars[i].par))
|
||||
if (reg.IsAllocg(*param.par))
|
||||
{
|
||||
//printf("MOV((eReg)rd,reg.map(*CC_pars[i].par)); %d %d\n",rd,reg.map(*CC_pars[i].par));
|
||||
VMOV((eFSReg)fd,reg.mapg(*CC_pars[i].par));
|
||||
//printf("MOV((eReg)rd,reg.map(*param.par)); %d %d\n",rd,reg.map(*param.par));
|
||||
VMOV((eFSReg)fd, reg.mapg(*param.par));
|
||||
}
|
||||
else if (reg.IsAllocf(*CC_pars[i].par))
|
||||
else if (reg.IsAllocf(*param.par))
|
||||
{
|
||||
//printf("LoadSh4Reg_mem((eReg)rd, *CC_pars[i].par); %d\n",rd);
|
||||
VMOV((eFSReg)fd,reg.mapfs(*CC_pars[i].par));
|
||||
//printf("LoadSh4Reg_mem((eReg)rd, *param.par); %d\n",rd);
|
||||
VMOV((eFSReg)fd, reg.mapfs(*param.par));
|
||||
}
|
||||
else
|
||||
die("Must not happen!\n");
|
||||
|
@ -670,27 +677,28 @@ void ngen_CC_Call(shil_opcode* op,void* function)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (reg.IsAllocg(*CC_pars[i].par))
|
||||
if (reg.IsAllocg(*param.par))
|
||||
{
|
||||
//printf("MOV((eReg)rd,reg.map(*CC_pars[i].par)); %d %d\n",rd,reg.map(*CC_pars[i].par));
|
||||
MOV((eReg)rd,reg.mapg(*CC_pars[i].par));
|
||||
//printf("MOV((eReg)rd,reg.map(*param.par)); %d %d\n",rd,reg.map(*param.par));
|
||||
MOV((eReg)rd, reg.mapg(*param.par));
|
||||
}
|
||||
else if (reg.IsAllocf(*CC_pars[i].par))
|
||||
else if (reg.IsAllocf(*param.par))
|
||||
{
|
||||
//printf("LoadSh4Reg_mem((eReg)rd, *CC_pars[i].par); %d\n",rd);
|
||||
VMOV((eReg)rd,reg.mapfs(*CC_pars[i].par));
|
||||
//printf("LoadSh4Reg_mem((eReg)rd, *param.par); %d\n",rd);
|
||||
VMOV((eReg)rd, reg.mapfs(*param.par));
|
||||
}
|
||||
else
|
||||
die("Must not happen!\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
verify(CC_pars[i].type != CPT_f32);
|
||||
//printf("MOV32((eReg)rd, CC_pars[i].par->_imm); %d\n",rd);
|
||||
MOV32((eReg)rd, CC_pars[i].par->_imm);
|
||||
verify(param.par->is_imm());
|
||||
//printf("MOV32((eReg)rd, param.par->_imm); %d\n",rd);
|
||||
MOV32((eReg)rd, param.par->_imm);
|
||||
}
|
||||
}
|
||||
rd++;
|
||||
fd++;
|
||||
}
|
||||
//printf("used reg r0 to r%d, %d params, calling %08X\n",rd-1,CC_pars.size(),function);
|
||||
CALL((u32)function);
|
||||
|
@ -1020,9 +1028,14 @@ u32* ngen_readm_fail_v2(u32* ptrv,u32* regs,u32 fault_addr)
|
|||
return (u32*)ptr;
|
||||
}
|
||||
|
||||
EAPI NEG(eReg Rd,eReg Rs)
|
||||
EAPI NEG(eReg Rd, eReg Rs)
|
||||
{
|
||||
RSB(Rd,Rs,0);
|
||||
RSB(Rd, Rs, 0);
|
||||
}
|
||||
|
||||
EAPI NEG(eReg Rd, eReg Rs, ConditionCode CC)
|
||||
{
|
||||
RSB(Rd, Rs, 0, CC);
|
||||
}
|
||||
|
||||
eReg GenMemAddr(shil_opcode* op, eReg raddr = r0)
|
||||
|
@ -1072,92 +1085,48 @@ bool ngen_readm_immediate(RuntimeBlockInfo* block, shil_opcode* op, bool staging
|
|||
|
||||
if (isram)
|
||||
{
|
||||
MOV32(r0, (u32)ptr);
|
||||
switch(optp)
|
||||
{
|
||||
case SZ_8:
|
||||
{
|
||||
verify(false);
|
||||
MOV32(r0, (u32)ptr);
|
||||
LDRB(rd, r0);
|
||||
SXTB(rd, rd);
|
||||
}
|
||||
LDRSB(rd, r0);
|
||||
break;
|
||||
|
||||
case SZ_16:
|
||||
{
|
||||
LoadImmBase16(rd, (u32)ptr, true); // true for sx
|
||||
}
|
||||
LDRSH(rd, r0);
|
||||
break;
|
||||
|
||||
case SZ_32I:
|
||||
{
|
||||
verify(reg.IsAllocg(op->rd));
|
||||
{
|
||||
if (optimise && staging && !is_s8(*(u32*)ptr) && abs((int)op->rs1._imm - (int)block->addr) <= 1024)
|
||||
{
|
||||
op->flags |= 0x40000000;
|
||||
|
||||
MOV32(r0, (u32)ptr);
|
||||
LDR(rd, r0);
|
||||
MOV32(r1, *(u32*)ptr);
|
||||
CMP(rd, r1);
|
||||
//JUMP((unat)EMIT_GET_PTR() + 24, CC_EQ);
|
||||
MOV32(r1, (u32)&op->flags);
|
||||
MOV32(r2, ~0x40000000);
|
||||
LDR(r3, r1);
|
||||
AND(r3, r3, r2, CC_NE);
|
||||
STR(r3, r1);
|
||||
}
|
||||
else if (optimise && !staging && (op->flags & 0x40000000))
|
||||
{
|
||||
MOV32(rd, *(u32*)ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
MOV32(r0, (u32)ptr);
|
||||
LDR(rd, r0);
|
||||
}
|
||||
}
|
||||
}
|
||||
LDR(rd, r0);
|
||||
break;
|
||||
|
||||
case SZ_32F:
|
||||
{
|
||||
verify(reg.IsAllocf(op->rd));
|
||||
MOV32(r0, (u32)ptr);
|
||||
VLDR(reg.mapfs(op->rd), r0, 0);
|
||||
|
||||
}
|
||||
VLDR(reg.mapfs(op->rd), r0, 0);
|
||||
break;
|
||||
|
||||
case SZ_64F:
|
||||
{
|
||||
MOV32(r0, (u32)ptr);
|
||||
VLDR(d0, r0, 0);
|
||||
VSTR(d0, r8, op->rd.reg_nofs() / 4);
|
||||
}
|
||||
VLDR(d0, r0, 0);
|
||||
VSTR(d0, r8, op->rd.reg_nofs() / 4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MOV32(r0, op->rs1._imm);
|
||||
CALL((u32)ptr);
|
||||
|
||||
switch(optp)
|
||||
{
|
||||
case SZ_8:
|
||||
CALL((u32)ptr);
|
||||
SXTB(r0, r0);
|
||||
break;
|
||||
|
||||
case SZ_16:
|
||||
CALL((u32)ptr);
|
||||
SXTH(r0, r0);
|
||||
break;
|
||||
|
||||
case SZ_32I:
|
||||
case SZ_32F:
|
||||
CALL((u32)ptr);
|
||||
break;
|
||||
|
||||
case SZ_64F:
|
||||
|
@ -1169,6 +1138,8 @@ bool ngen_readm_immediate(RuntimeBlockInfo* block, shil_opcode* op, bool staging
|
|||
MOV(rd, r0);
|
||||
else if (reg.IsAllocf(op->rd))
|
||||
VMOV(reg.mapfs(op->rd), r0);
|
||||
else
|
||||
die("Unsupported");
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -1184,20 +1155,14 @@ bool ngen_writemem_immediate(RuntimeBlockInfo* block, shil_opcode* op, bool stag
|
|||
void* ptr = _vmem_write_const(op->rs1._imm, isram, memop_bytes(optp));
|
||||
|
||||
eReg rs2 = r1;
|
||||
eFSReg rs2f = f1;
|
||||
eFSReg rs2f = f0;
|
||||
if (op->rs2.is_imm())
|
||||
{
|
||||
MOV32(rs2, op->rs2._imm);
|
||||
if (optp == SZ_32F)
|
||||
VMOV(rs2f, rs2);
|
||||
}
|
||||
else if (optp == SZ_32F)
|
||||
rs2f = reg.mapf(op->rs2);
|
||||
else
|
||||
{
|
||||
if (optp == SZ_32F)
|
||||
rs2f = reg.mapf(op->rs2);
|
||||
else
|
||||
rs2 = reg.mapg(op->rs2);
|
||||
}
|
||||
rs2 = reg.mapg(op->rs2);
|
||||
|
||||
if (isram)
|
||||
{
|
||||
MOV32(r0, (u32)ptr);
|
||||
|
@ -1208,7 +1173,7 @@ bool ngen_writemem_immediate(RuntimeBlockInfo* block, shil_opcode* op, bool stag
|
|||
break;
|
||||
|
||||
case SZ_16:
|
||||
STRH(rs2, r0);
|
||||
STRH(rs2, r0, 0);
|
||||
break;
|
||||
|
||||
case SZ_32I:
|
||||
|
@ -1229,7 +1194,9 @@ bool ngen_writemem_immediate(RuntimeBlockInfo* block, shil_opcode* op, bool stag
|
|||
if (optp == SZ_64F)
|
||||
die("SZ_64F not supported");
|
||||
MOV32(r0, op->rs1._imm);
|
||||
if (r1 != rs2)
|
||||
if (optp == SZ_32F)
|
||||
VMOV(r1, rs2f);
|
||||
else if (r1 != rs2)
|
||||
MOV(r1, rs2);
|
||||
|
||||
CALL((u32)ptr);
|
||||
|
@ -1351,45 +1318,17 @@ void ngen_compile_opcode(RuntimeBlockInfo* block, shil_opcode* op, bool staging,
|
|||
break;
|
||||
|
||||
case SZ_32I:
|
||||
if (op->flags2!=0x1337)
|
||||
STR(rs2, r1, r8, Offset, true);
|
||||
else
|
||||
{
|
||||
emit_Skip(-4);
|
||||
AND(r1,raddr,0x3F);
|
||||
ADD(r1,r1,r8);
|
||||
STR(rs2, r1, sq_offs);
|
||||
}
|
||||
STR(rs2, r1, r8, Offset, true);
|
||||
break;
|
||||
|
||||
case SZ_32F:
|
||||
if (op->flags2!=0x1337)
|
||||
{
|
||||
ADD(r1,r1,r8); //3 opcodes: there's no [REG+REG] VLDR, also required for SQ
|
||||
VSTR(rs2f, r1, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
emit_Skip(-4);
|
||||
AND(r1,raddr,0x3F);
|
||||
ADD(r1,r1,r8);
|
||||
VSTR(rs2f, r1, sq_offs / 4);
|
||||
}
|
||||
ADD(r1, r1, r8); //3 opcodes: there's no [REG+REG] VLDR, also required for SQ
|
||||
VSTR(rs2f, r1, 0);
|
||||
break;
|
||||
|
||||
case SZ_64F:
|
||||
if (op->flags2!=0x1337)
|
||||
{
|
||||
ADD(r1,r1,r8); //3 opcodes: there's no [REG+REG] VLDR, also required for SQ
|
||||
VSTR(d0,r1,0); //TODO: use reg alloc
|
||||
}
|
||||
else
|
||||
{
|
||||
emit_Skip(-4);
|
||||
AND(r1,raddr,0x3F);
|
||||
ADD(r1,r1,r8);
|
||||
VSTR(d0,r1,sq_offs/4);
|
||||
}
|
||||
ADD(r1, r1, r8); //3 opcodes: there's no [REG+REG] VLDR, also required for SQ
|
||||
VSTR(d0, r1, 0); //TODO: use reg alloc
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
@ -1427,8 +1366,8 @@ void ngen_compile_opcode(RuntimeBlockInfo* block, shil_opcode* op, bool staging,
|
|||
verify(op->rd.is_reg() && op->rd._reg==reg_pc_dyn);
|
||||
if (op->rs2.is_imm())
|
||||
{
|
||||
MOV32(r2, (u32)op->rs2._imm);
|
||||
ADD(r4,reg.mapg(op->rs1),r2);
|
||||
MOV32(r2, op->rs2.imm_value());
|
||||
ADD(r4, reg.mapg(op->rs1), r2);
|
||||
}
|
||||
else //if (r4!=rs1.reg)
|
||||
{
|
||||
|
@ -1547,7 +1486,6 @@ void ngen_compile_opcode(RuntimeBlockInfo* block, shil_opcode* op, bool staging,
|
|||
break;
|
||||
}
|
||||
|
||||
//#define CANONICALTEST
|
||||
#ifndef CANONICALTEST
|
||||
case shop_neg: ngen_Unary(op,NEG); break;
|
||||
case shop_not: ngen_Unary(op,NOT); break;
|
||||
|
@ -1564,7 +1502,6 @@ void ngen_compile_opcode(RuntimeBlockInfo* block, shil_opcode* op, bool staging,
|
|||
case shop_add: ngen_Binary(op,ADD,ADD); break;
|
||||
case shop_sub: ngen_Binary(op,SUB,SUB); break;
|
||||
case shop_ror: ngen_Binary(op,ROR,ROR); break;
|
||||
|
||||
|
||||
case shop_adc:
|
||||
{
|
||||
|
@ -1598,7 +1535,6 @@ void ngen_compile_opcode(RuntimeBlockInfo* block, shil_opcode* op, bool staging,
|
|||
eReg rs1 = GetParam(op->rs1, r1);
|
||||
eReg rs2 = GetParam(op->rs2, r2);
|
||||
if (rd2 != rs1) {
|
||||
verify(rd2 != rs1);
|
||||
LSR(rd2, rs2, 1, true); //C=rs2, rd2=0
|
||||
AND(rd2, rs1, 1); //get new carry
|
||||
} else {
|
||||
|
@ -1698,14 +1634,24 @@ void ngen_compile_opcode(RuntimeBlockInfo* block, shil_opcode* op, bool staging,
|
|||
CALL((u32)UpdateSR);
|
||||
break;
|
||||
}
|
||||
/* TODO Update this to use quotient sign as well
|
||||
|
||||
case shop_div32p2:
|
||||
{
|
||||
CMP(reg.mapg(op->rs3), 0);
|
||||
SUB(reg.mapg(op->rd), reg.mapg(op->rs1), reg.mapg(op->rs2), CC_EQ);
|
||||
eReg remainder = reg.mapg(op->rs1);
|
||||
eReg divisor = reg.mapg(op->rs2);
|
||||
eReg T = reg.mapg(op->rs3);
|
||||
|
||||
LSR(r0, T, 31);
|
||||
EOR(r0, r0, T);
|
||||
NOT(r0, r0);
|
||||
SBFX(r0, r0, 0, 1);
|
||||
AND(r0, r0, divisor);
|
||||
TST(T, 1);
|
||||
NEG(r1, r0, EQ);
|
||||
MOV(r1, r0, NE);
|
||||
ADD(reg.mapg(op->rd), remainder, r1);
|
||||
}
|
||||
break;
|
||||
*/
|
||||
|
||||
case shop_test:
|
||||
case shop_seteq:
|
||||
|
@ -1758,7 +1704,7 @@ void ngen_compile_opcode(RuntimeBlockInfo* block, shil_opcode* op, bool staging,
|
|||
MOVW(rd, 1, opcls2[op->op-shop_test]);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case shop_setpeq:
|
||||
{
|
||||
eReg rs1 = GetParam(op->rs1, r1);
|
||||
|
@ -1804,12 +1750,14 @@ void ngen_compile_opcode(RuntimeBlockInfo* block, shil_opcode* op, bool staging,
|
|||
break;
|
||||
case shop_mul_u64:
|
||||
{
|
||||
UMULL(reg.mapg(op->rd2), reg.mapg(op->rd), reg.mapg(op->rs1), reg.mapg(op->rs2));
|
||||
eReg rs2 = GetParam(op->rs2, r2);
|
||||
UMULL(reg.mapg(op->rd2), reg.mapg(op->rd), reg.mapg(op->rs1), rs2);
|
||||
}
|
||||
break;
|
||||
case shop_mul_s64:
|
||||
{
|
||||
SMULL(reg.mapg(op->rd2), reg.mapg(op->rd), reg.mapg(op->rs1), reg.mapg(op->rs2));
|
||||
eReg rs2 = GetParam(op->rs2, r2);
|
||||
SMULL(reg.mapg(op->rd2), reg.mapg(op->rd), reg.mapg(op->rs1), rs2);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1872,7 +1820,7 @@ void ngen_compile_opcode(RuntimeBlockInfo* block, shil_opcode* op, bool staging,
|
|||
case shop_pref:
|
||||
{
|
||||
ConditionCode cc = CC_EQ;
|
||||
if (op->flags != 0x1337 && !op->rs1.is_imm())
|
||||
if (!op->rs1.is_imm())
|
||||
{
|
||||
LSR(r1,reg.mapg(op->rs1),26);
|
||||
MOV(r0,reg.mapg(op->rs1));
|
||||
|
@ -1880,15 +1828,15 @@ void ngen_compile_opcode(RuntimeBlockInfo* block, shil_opcode* op, bool staging,
|
|||
}
|
||||
else
|
||||
{
|
||||
// The decoder or SSA pass has already checked that the
|
||||
// The SSA pass has already checked that the
|
||||
// destination is a store queue so no need to check
|
||||
MOV(r0,reg.mapg(op->rs1));
|
||||
MOV32(r0, op->rs1.imm_value());
|
||||
cc = CC_AL;
|
||||
}
|
||||
|
||||
if (CCN_MMUCR.AT)
|
||||
{
|
||||
CALL((unat)&do_sqw_mmu,op->flags==0x1337?CC_AL:CC_EQ);
|
||||
CALL((unat)&do_sqw_mmu, cc);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue