mirror of https://github.com/inolen/redream.git
added OP_LOAD_HOST and OP_STORE_HOST for directly accessing host memory
added lookup table for fsca removed sin, cos ir ops
This commit is contained in:
parent
a039b60d52
commit
f457e8e9d8
|
@ -21,7 +21,7 @@ bool Holly::Init() {
|
|||
maple_ = dc_->maple;
|
||||
sh4_ = dc_->sh4;
|
||||
|
||||
// initialize registers
|
||||
// initialize registers
|
||||
#define HOLLY_REG(addr, name, flags, default, type) \
|
||||
holly_regs_[name##_OFFSET] = {flags, default};
|
||||
#include "hw/holly/holly_regs.inc"
|
||||
|
|
|
@ -20,7 +20,7 @@ bool PVR2::Init() {
|
|||
palette_ram_ = dc_->palette_ram;
|
||||
video_ram_ = dc_->video_ram;
|
||||
|
||||
// initialize registers
|
||||
// initialize registers
|
||||
#define PVR_REG(addr, name, flags, default, type) \
|
||||
pvr_regs_[name##_OFFSET] = {flags, default};
|
||||
#include "hw/holly/pvr2_regs.inc"
|
||||
|
|
|
@ -86,7 +86,7 @@ void InterpreterEmitter::TranslateInstr(Instr &ir_i, IntInstr *instr) {
|
|||
// HACK instead of writing out ctx and an array of IntValues, it'd be nice
|
||||
// to encode exactly what's needed for each instruction into the codegen
|
||||
// buffer
|
||||
if (ir_i.op() == OP_LOAD || ir_i.op() == OP_STORE) {
|
||||
if (ir_i.op() == OP_LOAD_GUEST || ir_i.op() == OP_STORE_GUEST) {
|
||||
instr->ctx = &memory_;
|
||||
} else if (ir_i.op() == OP_LOAD_CONTEXT || ir_i.op() == OP_STORE_CONTEXT ||
|
||||
ir_i.op() == OP_CALL_EXTERNAL) {
|
||||
|
@ -341,6 +341,154 @@ struct helper<T, ARG, ACC_IMM> {
|
|||
//
|
||||
// interpreter callbacks
|
||||
//
|
||||
INT_CALLBACK(LOAD_HOST_I8) {
|
||||
uint64_t addr = LOAD_ARG0();
|
||||
R v = dvm::load<int8_t>(reinterpret_cast<void *>(addr));
|
||||
STORE_RESULT(v);
|
||||
}
|
||||
INT_CALLBACK(LOAD_HOST_I16) {
|
||||
uint64_t addr = LOAD_ARG0();
|
||||
R v = dvm::load<int16_t>(reinterpret_cast<void *>(addr));
|
||||
STORE_RESULT(v);
|
||||
}
|
||||
INT_CALLBACK(LOAD_HOST_I32) {
|
||||
uint64_t addr = LOAD_ARG0();
|
||||
R v = dvm::load<int32_t>(reinterpret_cast<void *>(addr));
|
||||
STORE_RESULT(v);
|
||||
}
|
||||
INT_CALLBACK(LOAD_HOST_I64) {
|
||||
uint64_t addr = LOAD_ARG0();
|
||||
R v = dvm::load<int64_t>(reinterpret_cast<void *>(addr));
|
||||
STORE_RESULT(v);
|
||||
}
|
||||
INT_CALLBACK(LOAD_HOST_F32) {
|
||||
uint64_t addr = LOAD_ARG0();
|
||||
int32_t v = dvm::load<int32_t>(reinterpret_cast<void *>(addr));
|
||||
STORE_RESULT(dvm::load<float>(&v));
|
||||
}
|
||||
INT_CALLBACK(LOAD_HOST_F64) {
|
||||
uint64_t addr = LOAD_ARG0();
|
||||
int64_t v = dvm::load<int64_t>(reinterpret_cast<void *>(addr));
|
||||
STORE_RESULT(dvm::load<double>(&v));
|
||||
}
|
||||
REGISTER_INT_CALLBACK(LOAD_HOST, LOAD_HOST_I8, I8, I64, V);
|
||||
REGISTER_INT_CALLBACK(LOAD_HOST, LOAD_HOST_I16, I16, I64, V);
|
||||
REGISTER_INT_CALLBACK(LOAD_HOST, LOAD_HOST_I32, I32, I64, V);
|
||||
REGISTER_INT_CALLBACK(LOAD_HOST, LOAD_HOST_I64, I64, I64, V);
|
||||
REGISTER_INT_CALLBACK(LOAD_HOST, LOAD_HOST_F32, F32, I64, V);
|
||||
REGISTER_INT_CALLBACK(LOAD_HOST, LOAD_HOST_F64, F64, I64, V);
|
||||
|
||||
INT_CALLBACK(STORE_HOST_I8) {
|
||||
uint64_t addr = LOAD_ARG0();
|
||||
A1 v = LOAD_ARG1();
|
||||
dvm::store(reinterpret_cast<void *>(addr), v);
|
||||
}
|
||||
INT_CALLBACK(STORE_HOST_I16) {
|
||||
uint64_t addr = LOAD_ARG0();
|
||||
A1 v = LOAD_ARG1();
|
||||
dvm::store(reinterpret_cast<void *>(addr), v);
|
||||
}
|
||||
INT_CALLBACK(STORE_HOST_I32) {
|
||||
uint64_t addr = LOAD_ARG0();
|
||||
A1 v = LOAD_ARG1();
|
||||
dvm::store(reinterpret_cast<void *>(addr), v);
|
||||
}
|
||||
INT_CALLBACK(STORE_HOST_I64) {
|
||||
uint64_t addr = LOAD_ARG0();
|
||||
A1 v = LOAD_ARG1();
|
||||
dvm::store(reinterpret_cast<void *>(addr), v);
|
||||
}
|
||||
INT_CALLBACK(STORE_HOST_F32) {
|
||||
uint64_t addr = LOAD_ARG0();
|
||||
A1 v = LOAD_ARG1();
|
||||
dvm::store(reinterpret_cast<void *>(addr), dvm::load<uint32_t>(&v));
|
||||
}
|
||||
INT_CALLBACK(STORE_HOST_F64) {
|
||||
uint64_t addr = LOAD_ARG0();
|
||||
A1 v = LOAD_ARG1();
|
||||
dvm::store(reinterpret_cast<void *>(addr), dvm::load<uint64_t>(&v));
|
||||
}
|
||||
REGISTER_INT_CALLBACK(STORE_HOST, STORE_HOST_I8, V, I64, I8);
|
||||
REGISTER_INT_CALLBACK(STORE_HOST, STORE_HOST_I16, V, I64, I16);
|
||||
REGISTER_INT_CALLBACK(STORE_HOST, STORE_HOST_I32, V, I64, I32);
|
||||
REGISTER_INT_CALLBACK(STORE_HOST, STORE_HOST_I64, V, I64, I64);
|
||||
REGISTER_INT_CALLBACK(STORE_HOST, STORE_HOST_F32, V, I64, F32);
|
||||
REGISTER_INT_CALLBACK(STORE_HOST, STORE_HOST_F64, V, I64, F64);
|
||||
|
||||
INT_CALLBACK(LOAD_GUEST_I8) {
|
||||
uint32_t addr = LOAD_ARG0();
|
||||
R v = reinterpret_cast<Memory *>(i->ctx)->R8(addr);
|
||||
STORE_RESULT(v);
|
||||
}
|
||||
INT_CALLBACK(LOAD_GUEST_I16) {
|
||||
uint32_t addr = LOAD_ARG0();
|
||||
R v = reinterpret_cast<Memory *>(i->ctx)->R16(addr);
|
||||
STORE_RESULT(v);
|
||||
}
|
||||
INT_CALLBACK(LOAD_GUEST_I32) {
|
||||
uint32_t addr = LOAD_ARG0();
|
||||
R v = reinterpret_cast<Memory *>(i->ctx)->R32(addr);
|
||||
STORE_RESULT(v);
|
||||
}
|
||||
INT_CALLBACK(LOAD_GUEST_I64) {
|
||||
uint32_t addr = LOAD_ARG0();
|
||||
R v = reinterpret_cast<Memory *>(i->ctx)->R64(addr);
|
||||
STORE_RESULT(v);
|
||||
}
|
||||
INT_CALLBACK(LOAD_GUEST_F32) {
|
||||
uint32_t addr = LOAD_ARG0();
|
||||
uint32_t v = reinterpret_cast<Memory *>(i->ctx)->R32(addr);
|
||||
STORE_RESULT(dvm::load<float>(&v));
|
||||
}
|
||||
INT_CALLBACK(LOAD_GUEST_F64) {
|
||||
uint32_t addr = LOAD_ARG0();
|
||||
uint64_t v = reinterpret_cast<Memory *>(i->ctx)->R64(addr);
|
||||
STORE_RESULT(dvm::load<double>(&v));
|
||||
}
|
||||
REGISTER_INT_CALLBACK(LOAD_GUEST, LOAD_GUEST_I8, I8, I32, V);
|
||||
REGISTER_INT_CALLBACK(LOAD_GUEST, LOAD_GUEST_I16, I16, I32, V);
|
||||
REGISTER_INT_CALLBACK(LOAD_GUEST, LOAD_GUEST_I32, I32, I32, V);
|
||||
REGISTER_INT_CALLBACK(LOAD_GUEST, LOAD_GUEST_I64, I64, I32, V);
|
||||
REGISTER_INT_CALLBACK(LOAD_GUEST, LOAD_GUEST_F32, F32, I32, V);
|
||||
REGISTER_INT_CALLBACK(LOAD_GUEST, LOAD_GUEST_F64, F64, I32, V);
|
||||
|
||||
INT_CALLBACK(STORE_GUEST_I8) {
|
||||
uint32_t addr = LOAD_ARG0();
|
||||
A1 v = LOAD_ARG1();
|
||||
reinterpret_cast<Memory *>(i->ctx)->W8(addr, v);
|
||||
}
|
||||
INT_CALLBACK(STORE_GUEST_I16) {
|
||||
uint32_t addr = LOAD_ARG0();
|
||||
A1 v = LOAD_ARG1();
|
||||
reinterpret_cast<Memory *>(i->ctx)->W16(addr, v);
|
||||
}
|
||||
INT_CALLBACK(STORE_GUEST_I32) {
|
||||
uint32_t addr = LOAD_ARG0();
|
||||
A1 v = LOAD_ARG1();
|
||||
reinterpret_cast<Memory *>(i->ctx)->W32(addr, v);
|
||||
}
|
||||
INT_CALLBACK(STORE_GUEST_I64) {
|
||||
uint32_t addr = LOAD_ARG0();
|
||||
A1 v = LOAD_ARG1();
|
||||
reinterpret_cast<Memory *>(i->ctx)->W64(addr, v);
|
||||
}
|
||||
INT_CALLBACK(STORE_GUEST_F32) {
|
||||
uint32_t addr = LOAD_ARG0();
|
||||
A1 v = LOAD_ARG1();
|
||||
reinterpret_cast<Memory *>(i->ctx)->W32(addr, dvm::load<uint32_t>(&v));
|
||||
}
|
||||
INT_CALLBACK(STORE_GUEST_F64) {
|
||||
uint32_t addr = LOAD_ARG0();
|
||||
A1 v = LOAD_ARG1();
|
||||
reinterpret_cast<Memory *>(i->ctx)->W64(addr, dvm::load<uint64_t>(&v));
|
||||
}
|
||||
REGISTER_INT_CALLBACK(STORE_GUEST, STORE_GUEST_I8, V, I32, I8);
|
||||
REGISTER_INT_CALLBACK(STORE_GUEST, STORE_GUEST_I16, V, I32, I16);
|
||||
REGISTER_INT_CALLBACK(STORE_GUEST, STORE_GUEST_I32, V, I32, I32);
|
||||
REGISTER_INT_CALLBACK(STORE_GUEST, STORE_GUEST_I64, V, I32, I64);
|
||||
REGISTER_INT_CALLBACK(STORE_GUEST, STORE_GUEST_F32, V, I32, F32);
|
||||
REGISTER_INT_CALLBACK(STORE_GUEST, STORE_GUEST_F64, V, I32, F64);
|
||||
|
||||
INT_CALLBACK(LOAD_CONTEXT) {
|
||||
A0 offset = LOAD_ARG0();
|
||||
R v = dvm::load<R>(reinterpret_cast<uint8_t *>(i->ctx) + offset);
|
||||
|
@ -389,80 +537,6 @@ REGISTER_INT_CALLBACK(STORE_LOCAL, STORE_LOCAL, V, I32, I64);
|
|||
REGISTER_INT_CALLBACK(STORE_LOCAL, STORE_LOCAL, V, I32, F32);
|
||||
REGISTER_INT_CALLBACK(STORE_LOCAL, STORE_LOCAL, V, I32, F64);
|
||||
|
||||
INT_CALLBACK(LOAD_I8) {
|
||||
uint32_t addr = static_cast<uint32_t>(LOAD_ARG0());
|
||||
R v = reinterpret_cast<Memory *>(i->ctx)->R8(addr);
|
||||
STORE_RESULT(v);
|
||||
}
|
||||
INT_CALLBACK(LOAD_I16) {
|
||||
uint32_t addr = static_cast<uint32_t>(LOAD_ARG0());
|
||||
R v = reinterpret_cast<Memory *>(i->ctx)->R16(addr);
|
||||
STORE_RESULT(v);
|
||||
}
|
||||
INT_CALLBACK(LOAD_I32) {
|
||||
uint32_t addr = static_cast<uint32_t>(LOAD_ARG0());
|
||||
R v = reinterpret_cast<Memory *>(i->ctx)->R32(addr);
|
||||
STORE_RESULT(v);
|
||||
}
|
||||
INT_CALLBACK(LOAD_I64) {
|
||||
uint32_t addr = static_cast<uint32_t>(LOAD_ARG0());
|
||||
R v = reinterpret_cast<Memory *>(i->ctx)->R64(addr);
|
||||
STORE_RESULT(v);
|
||||
}
|
||||
INT_CALLBACK(LOAD_F32) {
|
||||
uint32_t addr = static_cast<uint32_t>(LOAD_ARG0());
|
||||
uint32_t v = reinterpret_cast<Memory *>(i->ctx)->R32(addr);
|
||||
STORE_RESULT(dvm::load<float>(&v));
|
||||
}
|
||||
INT_CALLBACK(LOAD_F64) {
|
||||
uint32_t addr = static_cast<uint32_t>(LOAD_ARG0());
|
||||
uint64_t v = reinterpret_cast<Memory *>(i->ctx)->R64(addr);
|
||||
STORE_RESULT(dvm::load<double>(&v));
|
||||
}
|
||||
REGISTER_INT_CALLBACK(LOAD, LOAD_I8, I8, I32, V);
|
||||
REGISTER_INT_CALLBACK(LOAD, LOAD_I16, I16, I32, V);
|
||||
REGISTER_INT_CALLBACK(LOAD, LOAD_I32, I32, I32, V);
|
||||
REGISTER_INT_CALLBACK(LOAD, LOAD_I64, I64, I32, V);
|
||||
REGISTER_INT_CALLBACK(LOAD, LOAD_F32, F32, I32, V);
|
||||
REGISTER_INT_CALLBACK(LOAD, LOAD_F64, F64, I32, V);
|
||||
|
||||
INT_CALLBACK(STORE_I8) {
|
||||
uint32_t addr = static_cast<uint32_t>(LOAD_ARG0());
|
||||
A1 v = LOAD_ARG1();
|
||||
reinterpret_cast<Memory *>(i->ctx)->W8(addr, v);
|
||||
}
|
||||
INT_CALLBACK(STORE_I16) {
|
||||
uint32_t addr = static_cast<uint32_t>(LOAD_ARG0());
|
||||
A1 v = LOAD_ARG1();
|
||||
reinterpret_cast<Memory *>(i->ctx)->W16(addr, v);
|
||||
}
|
||||
INT_CALLBACK(STORE_I32) {
|
||||
uint32_t addr = static_cast<uint32_t>(LOAD_ARG0());
|
||||
A1 v = LOAD_ARG1();
|
||||
reinterpret_cast<Memory *>(i->ctx)->W32(addr, v);
|
||||
}
|
||||
INT_CALLBACK(STORE_I64) {
|
||||
uint32_t addr = static_cast<uint32_t>(LOAD_ARG0());
|
||||
A1 v = LOAD_ARG1();
|
||||
reinterpret_cast<Memory *>(i->ctx)->W64(addr, v);
|
||||
}
|
||||
INT_CALLBACK(STORE_F32) {
|
||||
uint32_t addr = static_cast<uint32_t>(LOAD_ARG0());
|
||||
A1 v = LOAD_ARG1();
|
||||
reinterpret_cast<Memory *>(i->ctx)->W32(addr, dvm::load<uint32_t>(&v));
|
||||
}
|
||||
INT_CALLBACK(STORE_F64) {
|
||||
uint32_t addr = static_cast<uint32_t>(LOAD_ARG0());
|
||||
A1 v = LOAD_ARG1();
|
||||
reinterpret_cast<Memory *>(i->ctx)->W64(addr, dvm::load<uint64_t>(&v));
|
||||
}
|
||||
REGISTER_INT_CALLBACK(STORE, STORE_I8, V, I32, I8);
|
||||
REGISTER_INT_CALLBACK(STORE, STORE_I16, V, I32, I16);
|
||||
REGISTER_INT_CALLBACK(STORE, STORE_I32, V, I32, I32);
|
||||
REGISTER_INT_CALLBACK(STORE, STORE_I64, V, I32, I64);
|
||||
REGISTER_INT_CALLBACK(STORE, STORE_F32, V, I32, F32);
|
||||
REGISTER_INT_CALLBACK(STORE, STORE_F64, V, I32, F64);
|
||||
|
||||
INT_CALLBACK(CAST) {
|
||||
A0 v = LOAD_ARG0();
|
||||
STORE_RESULT(static_cast<R>(v));
|
||||
|
@ -728,28 +802,6 @@ INT_CALLBACK(ABSF) {
|
|||
REGISTER_INT_CALLBACK(ABS, ABSF, F32, F32, V);
|
||||
REGISTER_INT_CALLBACK(ABS, ABSF, F64, F64, V);
|
||||
|
||||
INT_CALLBACK(SINF) {
|
||||
A0 v = LOAD_ARG0();
|
||||
STORE_RESULT(sinf(v));
|
||||
}
|
||||
INT_CALLBACK(SIN) {
|
||||
A0 v = LOAD_ARG0();
|
||||
STORE_RESULT(sin(v));
|
||||
}
|
||||
REGISTER_INT_CALLBACK(SIN, SINF, F32, F32, V);
|
||||
REGISTER_INT_CALLBACK(SIN, SIN, F64, F64, V);
|
||||
|
||||
INT_CALLBACK(COSF) {
|
||||
A0 v = LOAD_ARG0();
|
||||
STORE_RESULT(cosf(v));
|
||||
}
|
||||
INT_CALLBACK(COS) {
|
||||
A0 v = LOAD_ARG0();
|
||||
STORE_RESULT(cos(v));
|
||||
}
|
||||
REGISTER_INT_CALLBACK(COS, COSF, F32, F32, V);
|
||||
REGISTER_INT_CALLBACK(COS, COS, F64, F64, V);
|
||||
|
||||
INT_CALLBACK(AND) {
|
||||
A0 lhs = LOAD_ARG0();
|
||||
A1 rhs = LOAD_ARG1();
|
||||
|
|
|
@ -440,6 +440,275 @@ void X64Emitter::RestoreArgs() {
|
|||
mov(int_arg1, reinterpret_cast<uintptr_t>(memory_->protected_base()));
|
||||
}
|
||||
|
||||
EMITTER(LOAD_HOST) {
|
||||
const Xbyak::Reg &a = e.GetRegister(instr->arg0());
|
||||
|
||||
if (IsFloatType(instr->result()->type())) {
|
||||
const Xbyak::Xmm &result = e.GetXMMRegister(instr->result());
|
||||
|
||||
switch (instr->result()->type()) {
|
||||
case VALUE_F32:
|
||||
e.vmovss(result, e.dword[a]);
|
||||
break;
|
||||
case VALUE_F64:
|
||||
e.vmovsd(result, e.qword[a]);
|
||||
break;
|
||||
default:
|
||||
LOG_FATAL("Unexpected result type");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
const Xbyak::Reg &result = e.GetRegister(instr->result());
|
||||
|
||||
switch (instr->result()->type()) {
|
||||
case VALUE_I8:
|
||||
e.mov(result, e.byte[a]);
|
||||
break;
|
||||
case VALUE_I16:
|
||||
e.mov(result, e.word[a]);
|
||||
break;
|
||||
case VALUE_I32:
|
||||
e.mov(result, e.dword[a]);
|
||||
break;
|
||||
case VALUE_I64:
|
||||
e.mov(result, e.qword[a]);
|
||||
break;
|
||||
default:
|
||||
LOG_FATAL("Unexpected load result type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EMITTER(STORE_HOST) {
|
||||
const Xbyak::Reg &a = e.GetRegister(instr->arg0());
|
||||
|
||||
if (IsFloatType(instr->arg1()->type())) {
|
||||
const Xbyak::Xmm &b = e.GetXMMRegister(instr->arg1());
|
||||
|
||||
switch (instr->arg1()->type()) {
|
||||
case VALUE_F32:
|
||||
e.movss(e.dword[a], b);
|
||||
break;
|
||||
case VALUE_F64:
|
||||
e.movsd(e.qword[a], b);
|
||||
break;
|
||||
default:
|
||||
LOG_FATAL("Unexpected value type");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
const Xbyak::Reg &b = e.GetRegister(instr->arg1());
|
||||
|
||||
switch (instr->arg1()->type()) {
|
||||
case VALUE_I8:
|
||||
e.mov(e.byte[a], b);
|
||||
break;
|
||||
case VALUE_I16:
|
||||
e.mov(e.word[a], b);
|
||||
break;
|
||||
case VALUE_I32:
|
||||
e.mov(e.dword[a], b);
|
||||
break;
|
||||
case VALUE_I64:
|
||||
e.mov(e.qword[a], b);
|
||||
break;
|
||||
default:
|
||||
LOG_FATAL("Unexpected store value type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EMITTER(LOAD_GUEST) {
|
||||
const Xbyak::Reg &result = e.GetRegister(instr->result());
|
||||
|
||||
if (instr->arg0()->constant()) {
|
||||
// try to resolve the address to a physical page
|
||||
uint32_t addr = static_cast<uint32_t>(instr->arg0()->value<int32_t>());
|
||||
uint8_t *host_addr = nullptr;
|
||||
MemoryRegion *region = nullptr;
|
||||
uint32_t offset = 0;
|
||||
|
||||
e.memory().Lookup(addr, &host_addr, ®ion, &offset);
|
||||
|
||||
// if the address maps to a physical page, not a dynamic handler, make it
|
||||
// fast
|
||||
if (host_addr) {
|
||||
// FIXME it'd be nice if xbyak had a mov operation which would convert
|
||||
// the displacement to a RIP-relative address when finalizing code so
|
||||
// we didn't have to store the absolute address in the scratch register
|
||||
e.mov(e.rax, reinterpret_cast<uintptr_t>(host_addr));
|
||||
|
||||
switch (instr->result()->type()) {
|
||||
case VALUE_I8:
|
||||
e.mov(result, e.byte[e.rax]);
|
||||
break;
|
||||
case VALUE_I16:
|
||||
e.mov(result, e.word[e.rax]);
|
||||
break;
|
||||
case VALUE_I32:
|
||||
e.mov(result, e.dword[e.rax]);
|
||||
break;
|
||||
case VALUE_I64:
|
||||
e.mov(result, e.qword[e.rax]);
|
||||
break;
|
||||
default:
|
||||
LOG_FATAL("Unexpected load result type");
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const Xbyak::Reg &a = e.GetRegister(instr->arg0());
|
||||
|
||||
if (e.block_flags() & BF_SLOWMEM) {
|
||||
void *fn = nullptr;
|
||||
switch (instr->result()->type()) {
|
||||
case VALUE_I8:
|
||||
fn = reinterpret_cast<void *>(
|
||||
static_cast<uint8_t (*)(Memory *, uint32_t)>(&Memory::R8));
|
||||
break;
|
||||
case VALUE_I16:
|
||||
fn = reinterpret_cast<void *>(
|
||||
static_cast<uint16_t (*)(Memory *, uint32_t)>(&Memory::R16));
|
||||
break;
|
||||
case VALUE_I32:
|
||||
fn = reinterpret_cast<void *>(
|
||||
static_cast<uint32_t (*)(Memory *, uint32_t)>(&Memory::R32));
|
||||
break;
|
||||
case VALUE_I64:
|
||||
fn = reinterpret_cast<void *>(
|
||||
static_cast<uint64_t (*)(Memory *, uint32_t)>(&Memory::R64));
|
||||
break;
|
||||
default:
|
||||
LOG_FATAL("Unexpected load result type");
|
||||
break;
|
||||
}
|
||||
|
||||
e.mov(int_arg0, reinterpret_cast<uintptr_t>(&e.memory()));
|
||||
e.mov(int_arg1, a);
|
||||
e.mov(e.rax, reinterpret_cast<uintptr_t>(fn));
|
||||
e.call(e.rax);
|
||||
e.mov(result, e.rax);
|
||||
e.RestoreArgs();
|
||||
} else {
|
||||
switch (instr->result()->type()) {
|
||||
case VALUE_I8:
|
||||
e.mov(result, e.byte[a.cvt64() + int_arg1]);
|
||||
break;
|
||||
case VALUE_I16:
|
||||
e.mov(result, e.word[a.cvt64() + int_arg1]);
|
||||
break;
|
||||
case VALUE_I32:
|
||||
e.mov(result, e.dword[a.cvt64() + int_arg1]);
|
||||
break;
|
||||
case VALUE_I64:
|
||||
e.mov(result, e.qword[a.cvt64() + int_arg1]);
|
||||
break;
|
||||
default:
|
||||
LOG_FATAL("Unexpected load result type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EMITTER(STORE_GUEST) {
|
||||
if (instr->arg0()->constant()) {
|
||||
// try to resolve the address to a physical page
|
||||
uint32_t addr = static_cast<uint32_t>(instr->arg0()->value<int32_t>());
|
||||
uint8_t *host_addr = nullptr;
|
||||
MemoryRegion *bank = nullptr;
|
||||
uint32_t offset = 0;
|
||||
|
||||
e.memory().Lookup(addr, &host_addr, &bank, &offset);
|
||||
|
||||
if (host_addr) {
|
||||
const Xbyak::Reg &b = e.GetRegister(instr->arg1());
|
||||
|
||||
// FIXME it'd be nice if xbyak had a mov operation which would convert
|
||||
// the displacement to a RIP-relative address when finalizing code so
|
||||
// we didn't have to store the absolute address in the scratch register
|
||||
e.mov(e.rax, reinterpret_cast<uintptr_t>(host_addr));
|
||||
|
||||
switch (instr->arg1()->type()) {
|
||||
case VALUE_I8:
|
||||
e.mov(e.byte[e.rax], b);
|
||||
break;
|
||||
case VALUE_I16:
|
||||
e.mov(e.word[e.rax], b);
|
||||
break;
|
||||
case VALUE_I32:
|
||||
e.mov(e.dword[e.rax], b);
|
||||
break;
|
||||
case VALUE_I64:
|
||||
e.mov(e.qword[e.rax], b);
|
||||
break;
|
||||
default:
|
||||
LOG_FATAL("Unexpected store value type");
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const Xbyak::Reg &a = e.GetRegister(instr->arg0());
|
||||
const Xbyak::Reg &b = e.GetRegister(instr->arg1());
|
||||
|
||||
if (e.block_flags() & BF_SLOWMEM) {
|
||||
void *fn = nullptr;
|
||||
switch (instr->arg1()->type()) {
|
||||
case VALUE_I8:
|
||||
fn = reinterpret_cast<void *>(
|
||||
static_cast<void (*)(Memory *, uint32_t, uint8_t)>(&Memory::W8));
|
||||
break;
|
||||
case VALUE_I16:
|
||||
fn = reinterpret_cast<void *>(
|
||||
static_cast<void (*)(Memory *, uint32_t, uint16_t)>(&Memory::W16));
|
||||
break;
|
||||
case VALUE_I32:
|
||||
fn = reinterpret_cast<void *>(
|
||||
static_cast<void (*)(Memory *, uint32_t, uint32_t)>(&Memory::W32));
|
||||
break;
|
||||
case VALUE_I64:
|
||||
fn = reinterpret_cast<void *>(
|
||||
static_cast<void (*)(Memory *, uint32_t, uint64_t)>(&Memory::W64));
|
||||
break;
|
||||
default:
|
||||
LOG_FATAL("Unexpected store value type");
|
||||
break;
|
||||
}
|
||||
|
||||
e.mov(int_arg0, reinterpret_cast<uintptr_t>(&e.memory()));
|
||||
e.mov(int_arg1, a);
|
||||
e.mov(int_arg2, b);
|
||||
e.mov(e.rax, reinterpret_cast<uintptr_t>(fn));
|
||||
e.call(e.rax);
|
||||
e.RestoreArgs();
|
||||
} else {
|
||||
switch (instr->arg1()->type()) {
|
||||
case VALUE_I8:
|
||||
e.mov(e.byte[a.cvt64() + int_arg1], b);
|
||||
break;
|
||||
case VALUE_I16:
|
||||
e.mov(e.word[a.cvt64() + int_arg1], b);
|
||||
break;
|
||||
case VALUE_I32:
|
||||
e.mov(e.dword[a.cvt64() + int_arg1], b);
|
||||
break;
|
||||
case VALUE_I64:
|
||||
e.mov(e.qword[a.cvt64() + int_arg1], b);
|
||||
break;
|
||||
default:
|
||||
LOG_FATAL("Unexpected store value type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EMITTER(LOAD_CONTEXT) {
|
||||
int offset = instr->arg0()->value<int32_t>();
|
||||
|
||||
|
@ -624,195 +893,6 @@ EMITTER(STORE_LOCAL) {
|
|||
}
|
||||
}
|
||||
|
||||
EMITTER(LOAD) {
|
||||
const Xbyak::Reg &result = e.GetRegister(instr->result());
|
||||
|
||||
if (instr->arg0()->constant()) {
|
||||
// try to resolve the address to a physical page
|
||||
uint32_t addr = static_cast<uint32_t>(instr->arg0()->value<int32_t>());
|
||||
uint8_t *host_addr = nullptr;
|
||||
MemoryRegion *region = nullptr;
|
||||
uint32_t offset = 0;
|
||||
|
||||
e.memory().Lookup(addr, &host_addr, ®ion, &offset);
|
||||
|
||||
// if the address maps to a physical page, not a dynamic handler, make it
|
||||
// fast
|
||||
if (host_addr) {
|
||||
// FIXME it'd be nice if xbyak had a mov operation which would convert
|
||||
// the displacement to a RIP-relative address when finalizing code so
|
||||
// we didn't have to store the absolute address in the scratch register
|
||||
e.mov(e.rax, reinterpret_cast<uintptr_t>(host_addr));
|
||||
|
||||
switch (instr->result()->type()) {
|
||||
case VALUE_I8:
|
||||
e.mov(result, e.byte[e.rax]);
|
||||
break;
|
||||
case VALUE_I16:
|
||||
e.mov(result, e.word[e.rax]);
|
||||
break;
|
||||
case VALUE_I32:
|
||||
e.mov(result, e.dword[e.rax]);
|
||||
break;
|
||||
case VALUE_I64:
|
||||
e.mov(result, e.qword[e.rax]);
|
||||
break;
|
||||
default:
|
||||
LOG_FATAL("Unexpected load result type");
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const Xbyak::Reg &a = e.GetRegister(instr->arg0());
|
||||
|
||||
if (e.block_flags() & BF_SLOWMEM) {
|
||||
void *fn = nullptr;
|
||||
switch (instr->result()->type()) {
|
||||
case VALUE_I8:
|
||||
fn = reinterpret_cast<void *>(
|
||||
static_cast<uint8_t (*)(Memory *, uint32_t)>(&Memory::R8));
|
||||
break;
|
||||
case VALUE_I16:
|
||||
fn = reinterpret_cast<void *>(
|
||||
static_cast<uint16_t (*)(Memory *, uint32_t)>(&Memory::R16));
|
||||
break;
|
||||
case VALUE_I32:
|
||||
fn = reinterpret_cast<void *>(
|
||||
static_cast<uint32_t (*)(Memory *, uint32_t)>(&Memory::R32));
|
||||
break;
|
||||
case VALUE_I64:
|
||||
fn = reinterpret_cast<void *>(
|
||||
static_cast<uint64_t (*)(Memory *, uint32_t)>(&Memory::R64));
|
||||
break;
|
||||
default:
|
||||
LOG_FATAL("Unexpected load result type");
|
||||
break;
|
||||
}
|
||||
|
||||
e.mov(int_arg0, reinterpret_cast<uintptr_t>(&e.memory()));
|
||||
e.mov(int_arg1, a);
|
||||
e.mov(e.rax, reinterpret_cast<uintptr_t>(fn));
|
||||
e.call(e.rax);
|
||||
e.mov(result, e.rax);
|
||||
e.RestoreArgs();
|
||||
} else {
|
||||
switch (instr->result()->type()) {
|
||||
case VALUE_I8:
|
||||
e.mov(result, e.byte[a.cvt64() + int_arg1]);
|
||||
break;
|
||||
case VALUE_I16:
|
||||
e.mov(result, e.word[a.cvt64() + int_arg1]);
|
||||
break;
|
||||
case VALUE_I32:
|
||||
e.mov(result, e.dword[a.cvt64() + int_arg1]);
|
||||
break;
|
||||
case VALUE_I64:
|
||||
e.mov(result, e.qword[a.cvt64() + int_arg1]);
|
||||
break;
|
||||
default:
|
||||
LOG_FATAL("Unexpected load result type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EMITTER(STORE) {
|
||||
if (instr->arg0()->constant()) {
|
||||
// try to resolve the address to a physical page
|
||||
uint32_t addr = static_cast<uint32_t>(instr->arg0()->value<int32_t>());
|
||||
uint8_t *host_addr = nullptr;
|
||||
MemoryRegion *bank = nullptr;
|
||||
uint32_t offset = 0;
|
||||
|
||||
e.memory().Lookup(addr, &host_addr, &bank, &offset);
|
||||
|
||||
if (host_addr) {
|
||||
const Xbyak::Reg &b = e.GetRegister(instr->arg1());
|
||||
|
||||
// FIXME it'd be nice if xbyak had a mov operation which would convert
|
||||
// the displacement to a RIP-relative address when finalizing code so
|
||||
// we didn't have to store the absolute address in the scratch register
|
||||
e.mov(e.rax, reinterpret_cast<uintptr_t>(host_addr));
|
||||
|
||||
switch (instr->arg1()->type()) {
|
||||
case VALUE_I8:
|
||||
e.mov(e.byte[e.rax], b);
|
||||
break;
|
||||
case VALUE_I16:
|
||||
e.mov(e.word[e.rax], b);
|
||||
break;
|
||||
case VALUE_I32:
|
||||
e.mov(e.dword[e.rax], b);
|
||||
break;
|
||||
case VALUE_I64:
|
||||
e.mov(e.qword[e.rax], b);
|
||||
break;
|
||||
default:
|
||||
LOG_FATAL("Unexpected store value type");
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const Xbyak::Reg &a = e.GetRegister(instr->arg0());
|
||||
const Xbyak::Reg &b = e.GetRegister(instr->arg1());
|
||||
|
||||
if (e.block_flags() & BF_SLOWMEM) {
|
||||
void *fn = nullptr;
|
||||
switch (instr->arg1()->type()) {
|
||||
case VALUE_I8:
|
||||
fn = reinterpret_cast<void *>(
|
||||
static_cast<void (*)(Memory *, uint32_t, uint8_t)>(&Memory::W8));
|
||||
break;
|
||||
case VALUE_I16:
|
||||
fn = reinterpret_cast<void *>(
|
||||
static_cast<void (*)(Memory *, uint32_t, uint16_t)>(&Memory::W16));
|
||||
break;
|
||||
case VALUE_I32:
|
||||
fn = reinterpret_cast<void *>(
|
||||
static_cast<void (*)(Memory *, uint32_t, uint32_t)>(&Memory::W32));
|
||||
break;
|
||||
case VALUE_I64:
|
||||
fn = reinterpret_cast<void *>(
|
||||
static_cast<void (*)(Memory *, uint32_t, uint64_t)>(&Memory::W64));
|
||||
break;
|
||||
default:
|
||||
LOG_FATAL("Unexpected store value type");
|
||||
break;
|
||||
}
|
||||
|
||||
e.mov(int_arg0, reinterpret_cast<uintptr_t>(&e.memory()));
|
||||
e.mov(int_arg1, a);
|
||||
e.mov(int_arg2, b);
|
||||
e.mov(e.rax, reinterpret_cast<uintptr_t>(fn));
|
||||
e.call(e.rax);
|
||||
e.RestoreArgs();
|
||||
} else {
|
||||
switch (instr->arg1()->type()) {
|
||||
case VALUE_I8:
|
||||
e.mov(e.byte[a.cvt64() + int_arg1], b);
|
||||
break;
|
||||
case VALUE_I16:
|
||||
e.mov(e.word[a.cvt64() + int_arg1], b);
|
||||
break;
|
||||
case VALUE_I32:
|
||||
e.mov(e.dword[a.cvt64() + int_arg1], b);
|
||||
break;
|
||||
case VALUE_I64:
|
||||
e.mov(e.qword[a.cvt64() + int_arg1], b);
|
||||
break;
|
||||
default:
|
||||
LOG_FATAL("Unexpected store value type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EMITTER(CAST) {
|
||||
if (IsFloatType(instr->result()->type())) {
|
||||
const Xbyak::Xmm &result = e.GetXMMRegister(instr->result());
|
||||
|
@ -876,7 +956,7 @@ EMITTER(ZEXT) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (result.isBit(64)) {
|
||||
if (result.isBit(64) && a.isBit(32)) {
|
||||
// mov will automatically zero fill the upper 32-bits
|
||||
e.mov(result.cvt32(), a);
|
||||
} else {
|
||||
|
@ -1354,52 +1434,6 @@ EMITTER(ABS) {
|
|||
}
|
||||
}
|
||||
|
||||
EMITTER(SIN) {
|
||||
CHECK(IsFloatType(instr->result()->type()));
|
||||
|
||||
const Xbyak::Xmm &result = e.GetXMMRegister(instr->result());
|
||||
const Xbyak::Xmm &a = e.GetXMMRegister(instr->arg0());
|
||||
|
||||
// FIXME xmm registers aren't callee saved, this would probably break if we
|
||||
// used the lower indexed xmm registers
|
||||
if (instr->result()->type() == VALUE_F32) {
|
||||
e.movss(e.xmm0, a);
|
||||
e.mov(e.rax, (uint64_t) reinterpret_cast<float (*)(float)>(&sinf));
|
||||
e.call(e.rax);
|
||||
e.movss(result, e.xmm0);
|
||||
} else {
|
||||
e.movsd(e.xmm0, a);
|
||||
e.mov(e.rax, (uint64_t) reinterpret_cast<double (*)(double)>(&sin));
|
||||
e.call(e.rax);
|
||||
e.movsd(result, e.xmm0);
|
||||
}
|
||||
|
||||
e.RestoreArgs();
|
||||
}
|
||||
|
||||
EMITTER(COS) {
|
||||
CHECK(IsFloatType(instr->result()->type()));
|
||||
|
||||
const Xbyak::Xmm &result = e.GetXMMRegister(instr->result());
|
||||
const Xbyak::Xmm &a = e.GetXMMRegister(instr->arg0());
|
||||
|
||||
// FIXME xmm registers aren't callee saved, this would probably break if we
|
||||
// used the lower indexed xmm registers
|
||||
if (instr->result()->type() == VALUE_F32) {
|
||||
e.movss(e.xmm0, a);
|
||||
e.mov(e.rax, (uint64_t) reinterpret_cast<float (*)(float)>(&cosf));
|
||||
e.call(e.rax);
|
||||
e.movss(result, e.xmm0);
|
||||
} else {
|
||||
e.movsd(e.xmm0, a);
|
||||
e.mov(e.rax, (uint64_t) reinterpret_cast<double (*)(double)>(&cos));
|
||||
e.call(e.rax);
|
||||
e.movsd(result, e.xmm0);
|
||||
}
|
||||
|
||||
e.RestoreArgs();
|
||||
}
|
||||
|
||||
EMITTER(AND) {
|
||||
CHECK(IsIntType(instr->result()->type()));
|
||||
|
||||
|
|
|
@ -10,6 +10,10 @@ using namespace dvm::jit::frontend;
|
|||
using namespace dvm::jit::frontend::sh4;
|
||||
using namespace dvm::jit::ir;
|
||||
|
||||
static uint32_t s_fsca_table[0x20000] = {
|
||||
#include "jit/frontend/sh4/sh4_fsca.inc"
|
||||
};
|
||||
|
||||
typedef void (*EmitCallback)(SH4Builder &b, const FPUState &,
|
||||
const sh4::Instr &i);
|
||||
|
||||
|
@ -191,14 +195,14 @@ EMITTER(MOVI) {
|
|||
// MOV.W @(disp,PC),Rn
|
||||
EMITTER(MOVWLPC) {
|
||||
uint32_t addr = (i.disp * 2) + i.addr + 4;
|
||||
Value *v = b.SExt(b.Load(b.AllocConstant(addr), VALUE_I16), VALUE_I32);
|
||||
Value *v = b.SExt(b.LoadGuest(b.AllocConstant(addr), VALUE_I16), VALUE_I32);
|
||||
b.StoreRegister(i.Rn, v);
|
||||
}
|
||||
|
||||
// MOV.L @(disp,PC),Rn
|
||||
EMITTER(MOVLLPC) {
|
||||
uint32_t addr = (i.disp * 4) + (i.addr & ~3) + 4;
|
||||
Value *v = b.Load(b.AllocConstant(addr), VALUE_I32);
|
||||
Value *v = b.LoadGuest(b.AllocConstant(addr), VALUE_I32);
|
||||
b.StoreRegister(i.Rn, v);
|
||||
}
|
||||
|
||||
|
@ -212,40 +216,40 @@ EMITTER(MOV) {
|
|||
EMITTER(MOVBS) {
|
||||
Value *addr = b.LoadRegister(i.Rn, VALUE_I32);
|
||||
Value *v = b.LoadRegister(i.Rm, VALUE_I8);
|
||||
b.Store(addr, v);
|
||||
b.StoreGuest(addr, v);
|
||||
}
|
||||
|
||||
// MOV.W Rm,@Rn
|
||||
EMITTER(MOVWS) {
|
||||
Value *addr = b.LoadRegister(i.Rn, VALUE_I32);
|
||||
Value *v = b.LoadRegister(i.Rm, VALUE_I16);
|
||||
b.Store(addr, v);
|
||||
b.StoreGuest(addr, v);
|
||||
}
|
||||
|
||||
// MOV.L Rm,@Rn
|
||||
EMITTER(MOVLS) {
|
||||
Value *addr = b.LoadRegister(i.Rn, VALUE_I32);
|
||||
Value *v = b.LoadRegister(i.Rm, VALUE_I32);
|
||||
b.Store(addr, v);
|
||||
b.StoreGuest(addr, v);
|
||||
}
|
||||
|
||||
// MOV.B @Rm,Rn
|
||||
EMITTER(MOVBL) {
|
||||
Value *v =
|
||||
b.SExt(b.Load(b.LoadRegister(i.Rm, VALUE_I32), VALUE_I8), VALUE_I32);
|
||||
b.SExt(b.LoadGuest(b.LoadRegister(i.Rm, VALUE_I32), VALUE_I8), VALUE_I32);
|
||||
b.StoreRegister(i.Rn, v);
|
||||
}
|
||||
|
||||
// MOV.W @Rm,Rn
|
||||
EMITTER(MOVWL) {
|
||||
Value *v =
|
||||
b.SExt(b.Load(b.LoadRegister(i.Rm, VALUE_I32), VALUE_I16), VALUE_I32);
|
||||
Value *v = b.SExt(b.LoadGuest(b.LoadRegister(i.Rm, VALUE_I32), VALUE_I16),
|
||||
VALUE_I32);
|
||||
b.StoreRegister(i.Rn, v);
|
||||
}
|
||||
|
||||
// MOV.L @Rm,Rn
|
||||
EMITTER(MOVLL) {
|
||||
Value *v = b.Load(b.LoadRegister(i.Rm, VALUE_I32), VALUE_I32);
|
||||
Value *v = b.LoadGuest(b.LoadRegister(i.Rm, VALUE_I32), VALUE_I32);
|
||||
b.StoreRegister(i.Rn, v);
|
||||
}
|
||||
|
||||
|
@ -258,7 +262,7 @@ EMITTER(MOVBM) {
|
|||
|
||||
// store Rm at (Rn)
|
||||
Value *v = b.LoadRegister(i.Rm, VALUE_I8);
|
||||
b.Store(addr, v);
|
||||
b.StoreGuest(addr, v);
|
||||
}
|
||||
|
||||
// MOV.W Rm,@-Rn
|
||||
|
@ -270,7 +274,7 @@ EMITTER(MOVWM) {
|
|||
|
||||
// store Rm at (Rn)
|
||||
Value *v = b.LoadRegister(i.Rm, VALUE_I16);
|
||||
b.Store(addr, v);
|
||||
b.StoreGuest(addr, v);
|
||||
}
|
||||
|
||||
// MOV.L Rm,@-Rn
|
||||
|
@ -282,14 +286,14 @@ EMITTER(MOVLM) {
|
|||
|
||||
// store Rm at (Rn)
|
||||
Value *v = b.LoadRegister(i.Rm, VALUE_I32);
|
||||
b.Store(addr, v);
|
||||
b.StoreGuest(addr, v);
|
||||
}
|
||||
|
||||
// MOV.B @Rm+,Rn
|
||||
EMITTER(MOVBP) {
|
||||
// store (Rm) at Rn
|
||||
Value *addr = b.LoadRegister(i.Rm, VALUE_I32);
|
||||
Value *v = b.SExt(b.Load(addr, VALUE_I8), VALUE_I32);
|
||||
Value *v = b.SExt(b.LoadGuest(addr, VALUE_I8), VALUE_I32);
|
||||
b.StoreRegister(i.Rn, v);
|
||||
|
||||
// increase Rm by 1
|
||||
|
@ -302,7 +306,7 @@ EMITTER(MOVBP) {
|
|||
EMITTER(MOVWP) {
|
||||
// store (Rm) at Rn
|
||||
Value *addr = b.LoadRegister(i.Rm, VALUE_I32);
|
||||
Value *v = b.SExt(b.Load(addr, VALUE_I16), VALUE_I32);
|
||||
Value *v = b.SExt(b.LoadGuest(addr, VALUE_I16), VALUE_I32);
|
||||
b.StoreRegister(i.Rn, v);
|
||||
|
||||
// increase Rm by 2
|
||||
|
@ -315,7 +319,7 @@ EMITTER(MOVWP) {
|
|||
EMITTER(MOVLP) {
|
||||
// store (Rm) at Rn
|
||||
Value *addr = b.LoadRegister(i.Rm, VALUE_I32);
|
||||
Value *v = b.Load(addr, VALUE_I32);
|
||||
Value *v = b.LoadGuest(addr, VALUE_I32);
|
||||
b.StoreRegister(i.Rn, v);
|
||||
|
||||
// increase Rm by 2
|
||||
|
@ -329,7 +333,7 @@ EMITTER(MOVBS0D) {
|
|||
Value *addr =
|
||||
b.Add(b.AllocConstant((uint32_t)i.disp), b.LoadRegister(i.Rn, VALUE_I32));
|
||||
Value *v = b.LoadRegister(0, VALUE_I8);
|
||||
b.Store(addr, v);
|
||||
b.StoreGuest(addr, v);
|
||||
}
|
||||
|
||||
// MOV.W R0,@(disp,Rn)
|
||||
|
@ -337,7 +341,7 @@ EMITTER(MOVWS0D) {
|
|||
Value *addr = b.Add(b.AllocConstant((uint32_t)i.disp * 2),
|
||||
b.LoadRegister(i.Rn, VALUE_I32));
|
||||
Value *v = b.LoadRegister(0, VALUE_I16);
|
||||
b.Store(addr, v);
|
||||
b.StoreGuest(addr, v);
|
||||
}
|
||||
|
||||
// MOV.L Rm,@(disp,Rn)
|
||||
|
@ -345,14 +349,14 @@ EMITTER(MOVLSMD) {
|
|||
Value *addr = b.Add(b.AllocConstant((uint32_t)i.disp * 4),
|
||||
b.LoadRegister(i.Rn, VALUE_I32));
|
||||
Value *v = b.LoadRegister(i.Rm, VALUE_I32);
|
||||
b.Store(addr, v);
|
||||
b.StoreGuest(addr, v);
|
||||
}
|
||||
|
||||
// MOV.B @(disp,Rm),R0
|
||||
EMITTER(MOVBLD0) {
|
||||
Value *addr =
|
||||
b.Add(b.AllocConstant((uint32_t)i.disp), b.LoadRegister(i.Rm, VALUE_I32));
|
||||
Value *v = b.SExt(b.Load(addr, VALUE_I8), VALUE_I32);
|
||||
Value *v = b.SExt(b.LoadGuest(addr, VALUE_I8), VALUE_I32);
|
||||
b.StoreRegister(0, v);
|
||||
}
|
||||
|
||||
|
@ -360,7 +364,7 @@ EMITTER(MOVBLD0) {
|
|||
EMITTER(MOVWLD0) {
|
||||
Value *addr = b.Add(b.AllocConstant((uint32_t)i.disp * 2),
|
||||
b.LoadRegister(i.Rm, VALUE_I32));
|
||||
Value *v = b.SExt(b.Load(addr, VALUE_I16), VALUE_I32);
|
||||
Value *v = b.SExt(b.LoadGuest(addr, VALUE_I16), VALUE_I32);
|
||||
b.StoreRegister(0, v);
|
||||
}
|
||||
|
||||
|
@ -368,7 +372,7 @@ EMITTER(MOVWLD0) {
|
|||
EMITTER(MOVLLDN) {
|
||||
Value *addr = b.Add(b.AllocConstant((uint32_t)i.disp * 4),
|
||||
b.LoadRegister(i.Rm, VALUE_I32));
|
||||
Value *v = b.Load(addr, VALUE_I32);
|
||||
Value *v = b.LoadGuest(addr, VALUE_I32);
|
||||
b.StoreRegister(i.Rn, v);
|
||||
}
|
||||
|
||||
|
@ -377,7 +381,7 @@ EMITTER(MOVBS0) {
|
|||
Value *addr =
|
||||
b.Add(b.LoadRegister(0, VALUE_I32), b.LoadRegister(i.Rn, VALUE_I32));
|
||||
Value *v = b.LoadRegister(i.Rm, VALUE_I8);
|
||||
b.Store(addr, v);
|
||||
b.StoreGuest(addr, v);
|
||||
}
|
||||
|
||||
// MOV.W Rm,@(R0,Rn)
|
||||
|
@ -385,7 +389,7 @@ EMITTER(MOVWS0) {
|
|||
Value *addr =
|
||||
b.Add(b.LoadRegister(0, VALUE_I32), b.LoadRegister(i.Rn, VALUE_I32));
|
||||
Value *v = b.LoadRegister(i.Rm, VALUE_I16);
|
||||
b.Store(addr, v);
|
||||
b.StoreGuest(addr, v);
|
||||
}
|
||||
|
||||
// MOV.L Rm,@(R0,Rn)
|
||||
|
@ -393,14 +397,14 @@ EMITTER(MOVLS0) {
|
|||
Value *addr =
|
||||
b.Add(b.LoadRegister(0, VALUE_I32), b.LoadRegister(i.Rn, VALUE_I32));
|
||||
Value *v = b.LoadRegister(i.Rm, VALUE_I32);
|
||||
b.Store(addr, v);
|
||||
b.StoreGuest(addr, v);
|
||||
}
|
||||
|
||||
// MOV.B @(R0,Rm),Rn
|
||||
EMITTER(MOVBL0) {
|
||||
Value *addr =
|
||||
b.Add(b.LoadRegister(0, VALUE_I32), b.LoadRegister(i.Rm, VALUE_I32));
|
||||
Value *v = b.SExt(b.Load(addr, VALUE_I8), VALUE_I32);
|
||||
Value *v = b.SExt(b.LoadGuest(addr, VALUE_I8), VALUE_I32);
|
||||
b.StoreRegister(i.Rn, v);
|
||||
}
|
||||
|
||||
|
@ -408,7 +412,7 @@ EMITTER(MOVBL0) {
|
|||
EMITTER(MOVWL0) {
|
||||
Value *addr =
|
||||
b.Add(b.LoadRegister(0, VALUE_I32), b.LoadRegister(i.Rm, VALUE_I32));
|
||||
Value *v = b.SExt(b.Load(addr, VALUE_I16), VALUE_I32);
|
||||
Value *v = b.SExt(b.LoadGuest(addr, VALUE_I16), VALUE_I32);
|
||||
b.StoreRegister(i.Rn, v);
|
||||
}
|
||||
|
||||
|
@ -416,7 +420,7 @@ EMITTER(MOVWL0) {
|
|||
EMITTER(MOVLL0) {
|
||||
Value *addr =
|
||||
b.Add(b.LoadRegister(0, VALUE_I32), b.LoadRegister(i.Rm, VALUE_I32));
|
||||
Value *v = b.Load(addr, VALUE_I32);
|
||||
Value *v = b.LoadGuest(addr, VALUE_I32);
|
||||
b.StoreRegister(i.Rn, v);
|
||||
}
|
||||
|
||||
|
@ -424,41 +428,41 @@ EMITTER(MOVLL0) {
|
|||
EMITTER(MOVBS0G) {
|
||||
Value *addr = b.Add(b.AllocConstant((uint32_t)i.disp), b.LoadGBR());
|
||||
Value *v = b.LoadRegister(0, VALUE_I8);
|
||||
b.Store(addr, v);
|
||||
b.StoreGuest(addr, v);
|
||||
}
|
||||
|
||||
// MOV.W R0,@(disp,GBR)
|
||||
EMITTER(MOVWS0G) {
|
||||
Value *addr = b.Add(b.AllocConstant((uint32_t)i.disp * 2), b.LoadGBR());
|
||||
Value *v = b.LoadRegister(0, VALUE_I16);
|
||||
b.Store(addr, v);
|
||||
b.StoreGuest(addr, v);
|
||||
}
|
||||
|
||||
// MOV.L R0,@(disp,GBR)
|
||||
EMITTER(MOVLS0G) {
|
||||
Value *addr = b.Add(b.AllocConstant((uint32_t)i.disp * 4), b.LoadGBR());
|
||||
Value *v = b.LoadRegister(0, VALUE_I32);
|
||||
b.Store(addr, v);
|
||||
b.StoreGuest(addr, v);
|
||||
}
|
||||
|
||||
// MOV.B @(disp,GBR),R0
|
||||
EMITTER(MOVBLG0) {
|
||||
Value *addr = b.Add(b.AllocConstant((uint32_t)i.disp), b.LoadGBR());
|
||||
Value *v = b.SExt(b.Load(addr, VALUE_I8), VALUE_I32);
|
||||
Value *v = b.SExt(b.LoadGuest(addr, VALUE_I8), VALUE_I32);
|
||||
b.StoreRegister(0, v);
|
||||
}
|
||||
|
||||
// MOV.W @(disp,GBR),R0
|
||||
EMITTER(MOVWLG0) {
|
||||
Value *addr = b.Add(b.AllocConstant((uint32_t)i.disp * 2), b.LoadGBR());
|
||||
Value *v = b.SExt(b.Load(addr, VALUE_I16), VALUE_I32);
|
||||
Value *v = b.SExt(b.LoadGuest(addr, VALUE_I16), VALUE_I32);
|
||||
b.StoreRegister(0, v);
|
||||
}
|
||||
|
||||
// MOV.L @(disp,GBR),R0
|
||||
EMITTER(MOVLLG0) {
|
||||
Value *addr = b.Add(b.AllocConstant((uint32_t)i.disp * 4), b.LoadGBR());
|
||||
Value *v = b.Load(addr, VALUE_I32);
|
||||
Value *v = b.LoadGuest(addr, VALUE_I32);
|
||||
b.StoreRegister(0, v);
|
||||
}
|
||||
|
||||
|
@ -842,8 +846,8 @@ EMITTER(ANDI) {
|
|||
// AND.B #imm,@(R0,GBR)
|
||||
EMITTER(ANDB) {
|
||||
Value *addr = b.Add(b.LoadRegister(0, VALUE_I32), b.LoadGBR());
|
||||
Value *v = b.Load(addr, VALUE_I8);
|
||||
b.Store(addr, b.And(v, b.AllocConstant((uint8_t)i.imm)));
|
||||
Value *v = b.LoadGuest(addr, VALUE_I8);
|
||||
b.StoreGuest(addr, b.And(v, b.AllocConstant((uint8_t)i.imm)));
|
||||
}
|
||||
|
||||
// NOT Rm,Rn
|
||||
|
@ -869,15 +873,15 @@ EMITTER(ORI) {
|
|||
// OR.B #imm,@(R0,GBR)
|
||||
EMITTER(ORB) {
|
||||
Value *addr = b.Add(b.LoadRegister(0, VALUE_I32), b.LoadGBR());
|
||||
Value *v = b.Load(addr, VALUE_I8);
|
||||
b.Store(addr, b.Or(v, b.AllocConstant((uint8_t)i.imm)));
|
||||
Value *v = b.LoadGuest(addr, VALUE_I8);
|
||||
b.StoreGuest(addr, b.Or(v, b.AllocConstant((uint8_t)i.imm)));
|
||||
}
|
||||
|
||||
// TAS.B @Rn
|
||||
EMITTER(TAS) {
|
||||
Value *addr = b.LoadRegister(i.Rn, VALUE_I32);
|
||||
Value *v = b.Load(addr, VALUE_I8);
|
||||
b.Store(addr, b.Or(v, b.AllocConstant((uint8_t)0x80)));
|
||||
Value *v = b.LoadGuest(addr, VALUE_I8);
|
||||
b.StoreGuest(addr, b.Or(v, b.AllocConstant((uint8_t)0x80)));
|
||||
b.StoreT(b.EQ(v, b.AllocConstant((uint8_t)0)));
|
||||
}
|
||||
|
||||
|
@ -898,7 +902,7 @@ EMITTER(TSTI) {
|
|||
// TST.B #imm,@(R0,GBR)
|
||||
EMITTER(TSTB) {
|
||||
Value *addr = b.Add(b.LoadRegister(0, VALUE_I32), b.LoadGBR());
|
||||
Value *v = b.Load(addr, VALUE_I8);
|
||||
Value *v = b.LoadGuest(addr, VALUE_I8);
|
||||
Value *imm = b.AllocConstant((uint8_t)i.imm);
|
||||
b.StoreT(b.EQ(b.And(v, imm), b.AllocConstant((uint8_t)0)));
|
||||
}
|
||||
|
@ -920,7 +924,8 @@ EMITTER(XORI) {
|
|||
// XOR.B #imm,@(R0,GBR)
|
||||
EMITTER(XORB) {
|
||||
Value *addr = b.Add(b.LoadRegister(0, VALUE_I32), b.LoadGBR());
|
||||
b.Store(addr, b.Xor(b.Load(addr, VALUE_I8), b.AllocConstant((uint8_t)i.imm)));
|
||||
b.StoreGuest(addr, b.Xor(b.LoadGuest(addr, VALUE_I8),
|
||||
b.AllocConstant((uint8_t)i.imm)));
|
||||
}
|
||||
|
||||
// ROTL Rn
|
||||
|
@ -1212,7 +1217,7 @@ EMITTER(LDCRBANK) {
|
|||
// LDC.L @Rm+,SR
|
||||
EMITTER(LDCMSR) {
|
||||
Value *addr = b.LoadRegister(i.Rm, VALUE_I32);
|
||||
Value *v = b.Load(addr, VALUE_I32);
|
||||
Value *v = b.LoadGuest(addr, VALUE_I32);
|
||||
b.StoreSR(v);
|
||||
// reload Rm, sr store could have swapped banks
|
||||
addr = b.LoadRegister(i.Rm, VALUE_I32);
|
||||
|
@ -1222,7 +1227,7 @@ EMITTER(LDCMSR) {
|
|||
// LDC.L @Rm+,GBR
|
||||
EMITTER(LDCMGBR) {
|
||||
Value *addr = b.LoadRegister(i.Rm, VALUE_I32);
|
||||
Value *v = b.Load(addr, VALUE_I32);
|
||||
Value *v = b.LoadGuest(addr, VALUE_I32);
|
||||
b.StoreGBR(v);
|
||||
b.StoreRegister(i.Rm, b.Add(addr, b.AllocConstant(4)));
|
||||
}
|
||||
|
@ -1230,7 +1235,7 @@ EMITTER(LDCMGBR) {
|
|||
// LDC.L @Rm+,VBR
|
||||
EMITTER(LDCMVBR) {
|
||||
Value *addr = b.LoadRegister(i.Rm, VALUE_I32);
|
||||
Value *v = b.Load(addr, VALUE_I32);
|
||||
Value *v = b.LoadGuest(addr, VALUE_I32);
|
||||
b.StoreContext(offsetof(SH4Context, vbr), v);
|
||||
b.StoreRegister(i.Rm, b.Add(addr, b.AllocConstant(4)));
|
||||
}
|
||||
|
@ -1238,7 +1243,7 @@ EMITTER(LDCMVBR) {
|
|||
// LDC.L @Rm+,SSR
|
||||
EMITTER(LDCMSSR) {
|
||||
Value *addr = b.LoadRegister(i.Rm, VALUE_I32);
|
||||
Value *v = b.Load(addr, VALUE_I32);
|
||||
Value *v = b.LoadGuest(addr, VALUE_I32);
|
||||
b.StoreContext(offsetof(SH4Context, ssr), v);
|
||||
b.StoreRegister(i.Rm, b.Add(addr, b.AllocConstant(4)));
|
||||
}
|
||||
|
@ -1246,7 +1251,7 @@ EMITTER(LDCMSSR) {
|
|||
// LDC.L @Rm+,SPC
|
||||
EMITTER(LDCMSPC) {
|
||||
Value *addr = b.LoadRegister(i.Rm, VALUE_I32);
|
||||
Value *v = b.Load(addr, VALUE_I32);
|
||||
Value *v = b.LoadGuest(addr, VALUE_I32);
|
||||
b.StoreContext(offsetof(SH4Context, spc), v);
|
||||
b.StoreRegister(i.Rm, b.Add(addr, b.AllocConstant(4)));
|
||||
}
|
||||
|
@ -1254,7 +1259,7 @@ EMITTER(LDCMSPC) {
|
|||
// LDC.L @Rm+,DBR
|
||||
EMITTER(LDCMDBR) {
|
||||
Value *addr = b.LoadRegister(i.Rm, VALUE_I32);
|
||||
Value *v = b.Load(addr, VALUE_I32);
|
||||
Value *v = b.LoadGuest(addr, VALUE_I32);
|
||||
b.StoreContext(offsetof(SH4Context, dbr), v);
|
||||
b.StoreRegister(i.Rm, b.Add(addr, b.AllocConstant(4)));
|
||||
}
|
||||
|
@ -1264,7 +1269,7 @@ EMITTER(LDCMRBANK) {
|
|||
int reg = i.Rn & 0x7;
|
||||
Value *addr = b.LoadRegister(i.Rm, VALUE_I32);
|
||||
b.StoreRegister(i.Rm, b.Add(addr, b.AllocConstant(4)));
|
||||
Value *v = b.Load(addr, VALUE_I32);
|
||||
Value *v = b.LoadGuest(addr, VALUE_I32);
|
||||
b.StoreContext(offsetof(SH4Context, ralt) + reg * 4, v);
|
||||
}
|
||||
|
||||
|
@ -1289,7 +1294,7 @@ EMITTER(LDSPR) {
|
|||
// LDS.L @Rm+,MACH
|
||||
EMITTER(LDSMMACH) {
|
||||
Value *addr = b.LoadRegister(i.Rm, VALUE_I32);
|
||||
Value *v = b.Load(addr, VALUE_I32);
|
||||
Value *v = b.LoadGuest(addr, VALUE_I32);
|
||||
b.StoreContext(offsetof(SH4Context, mach), v);
|
||||
b.StoreRegister(i.Rm, b.Add(addr, b.AllocConstant(4)));
|
||||
}
|
||||
|
@ -1297,7 +1302,7 @@ EMITTER(LDSMMACH) {
|
|||
// LDS.L @Rm+,MACL
|
||||
EMITTER(LDSMMACL) {
|
||||
Value *addr = b.LoadRegister(i.Rm, VALUE_I32);
|
||||
Value *v = b.Load(addr, VALUE_I32);
|
||||
Value *v = b.LoadGuest(addr, VALUE_I32);
|
||||
b.StoreContext(offsetof(SH4Context, macl), v);
|
||||
b.StoreRegister(i.Rm, b.Add(addr, b.AllocConstant(4)));
|
||||
}
|
||||
|
@ -1305,7 +1310,7 @@ EMITTER(LDSMMACL) {
|
|||
// LDS.L @Rm+,PR
|
||||
EMITTER(LDSMPR) {
|
||||
Value *addr = b.LoadRegister(i.Rm, VALUE_I32);
|
||||
Value *v = b.Load(addr, VALUE_I32);
|
||||
Value *v = b.LoadGuest(addr, VALUE_I32);
|
||||
b.StorePR(v);
|
||||
b.StoreRegister(i.Rm, b.Add(addr, b.AllocConstant(4)));
|
||||
}
|
||||
|
@ -1403,7 +1408,7 @@ EMITTER(STCMSR) {
|
|||
Value *addr = b.Sub(b.LoadRegister(i.Rn, VALUE_I32), b.AllocConstant(4));
|
||||
b.StoreRegister(i.Rn, addr);
|
||||
Value *v = b.LoadSR();
|
||||
b.Store(addr, v);
|
||||
b.StoreGuest(addr, v);
|
||||
}
|
||||
|
||||
// STC.L GBR,@-Rn
|
||||
|
@ -1411,7 +1416,7 @@ EMITTER(STCMGBR) {
|
|||
Value *addr = b.Sub(b.LoadRegister(i.Rn, VALUE_I32), b.AllocConstant(4));
|
||||
b.StoreRegister(i.Rn, addr);
|
||||
Value *v = b.LoadGBR();
|
||||
b.Store(addr, v);
|
||||
b.StoreGuest(addr, v);
|
||||
}
|
||||
|
||||
// STC.L VBR,@-Rn
|
||||
|
@ -1419,7 +1424,7 @@ EMITTER(STCMVBR) {
|
|||
Value *addr = b.Sub(b.LoadRegister(i.Rn, VALUE_I32), b.AllocConstant(4));
|
||||
b.StoreRegister(i.Rn, addr);
|
||||
Value *v = b.LoadContext(offsetof(SH4Context, vbr), VALUE_I32);
|
||||
b.Store(addr, v);
|
||||
b.StoreGuest(addr, v);
|
||||
}
|
||||
|
||||
// STC.L SSR,@-Rn
|
||||
|
@ -1427,7 +1432,7 @@ EMITTER(STCMSSR) {
|
|||
Value *addr = b.Sub(b.LoadRegister(i.Rn, VALUE_I32), b.AllocConstant(4));
|
||||
b.StoreRegister(i.Rn, addr);
|
||||
Value *v = b.LoadContext(offsetof(SH4Context, ssr), VALUE_I32);
|
||||
b.Store(addr, v);
|
||||
b.StoreGuest(addr, v);
|
||||
}
|
||||
|
||||
// STC.L SPC,@-Rn
|
||||
|
@ -1435,7 +1440,7 @@ EMITTER(STCMSPC) {
|
|||
Value *addr = b.Sub(b.LoadRegister(i.Rn, VALUE_I32), b.AllocConstant(4));
|
||||
b.StoreRegister(i.Rn, addr);
|
||||
Value *v = b.LoadContext(offsetof(SH4Context, spc), VALUE_I32);
|
||||
b.Store(addr, v);
|
||||
b.StoreGuest(addr, v);
|
||||
}
|
||||
|
||||
// STC.L SGR,@-Rn
|
||||
|
@ -1443,7 +1448,7 @@ EMITTER(STCMSGR) {
|
|||
Value *addr = b.Sub(b.LoadRegister(i.Rn, VALUE_I32), b.AllocConstant(4));
|
||||
b.StoreRegister(i.Rn, addr);
|
||||
Value *v = b.LoadContext(offsetof(SH4Context, sgr), VALUE_I32);
|
||||
b.Store(addr, v);
|
||||
b.StoreGuest(addr, v);
|
||||
}
|
||||
|
||||
// STC.L DBR,@-Rn
|
||||
|
@ -1451,7 +1456,7 @@ EMITTER(STCMDBR) {
|
|||
Value *addr = b.Sub(b.LoadRegister(i.Rn, VALUE_I32), b.AllocConstant(4));
|
||||
b.StoreRegister(i.Rn, addr);
|
||||
Value *v = b.LoadContext(offsetof(SH4Context, dbr), VALUE_I32);
|
||||
b.Store(addr, v);
|
||||
b.StoreGuest(addr, v);
|
||||
}
|
||||
|
||||
// STC.L Rm_BANK,@-Rn
|
||||
|
@ -1459,7 +1464,8 @@ EMITTER(STCMRBANK) {
|
|||
int reg = i.Rm & 0x7;
|
||||
Value *addr = b.Sub(b.LoadRegister(i.Rn, VALUE_I32), b.AllocConstant(4));
|
||||
b.StoreRegister(i.Rn, addr);
|
||||
b.Store(addr, b.LoadContext(offsetof(SH4Context, ralt) + reg * 4, VALUE_I32));
|
||||
b.StoreGuest(addr,
|
||||
b.LoadContext(offsetof(SH4Context, ralt) + reg * 4, VALUE_I32));
|
||||
}
|
||||
|
||||
// STS MACH,Rn
|
||||
|
@ -1486,7 +1492,7 @@ EMITTER(STSMMACH) {
|
|||
b.StoreRegister(i.Rn, addr);
|
||||
|
||||
Value *mach = b.LoadContext(offsetof(SH4Context, mach), VALUE_I32);
|
||||
b.Store(addr, mach);
|
||||
b.StoreGuest(addr, mach);
|
||||
}
|
||||
|
||||
// STS.L MACL,@-Rn
|
||||
|
@ -1495,7 +1501,7 @@ EMITTER(STSMMACL) {
|
|||
b.StoreRegister(i.Rn, addr);
|
||||
|
||||
Value *macl = b.LoadContext(offsetof(SH4Context, macl), VALUE_I32);
|
||||
b.Store(addr, macl);
|
||||
b.StoreGuest(addr, macl);
|
||||
}
|
||||
|
||||
// STS.L PR,@-Rn
|
||||
|
@ -1504,7 +1510,7 @@ EMITTER(STSMPR) {
|
|||
b.StoreRegister(i.Rn, addr);
|
||||
|
||||
Value *pr = b.LoadPR();
|
||||
b.Store(addr, pr);
|
||||
b.StoreGuest(addr, pr);
|
||||
}
|
||||
|
||||
// TRAPA #imm
|
||||
|
@ -1555,26 +1561,26 @@ EMITTER(FMOV1) {
|
|||
|
||||
if (fpu.double_precision) {
|
||||
if (i.Rn & 1) {
|
||||
b.StoreRegisterXF(i.Rn | 0x1, b.Load(addr, VALUE_I32));
|
||||
b.StoreRegisterXF(i.Rn & 0xe,
|
||||
b.Load(b.Add(addr, b.AllocConstant(4)), VALUE_I32));
|
||||
b.StoreRegisterXF(i.Rn | 0x1, b.LoadGuest(addr, VALUE_I32));
|
||||
b.StoreRegisterXF(
|
||||
i.Rn & 0xe, b.LoadGuest(b.Add(addr, b.AllocConstant(4)), VALUE_I32));
|
||||
} else {
|
||||
b.StoreRegisterF(i.Rn | 0x1, b.Load(addr, VALUE_I32));
|
||||
b.StoreRegisterF(i.Rn | 0x1, b.LoadGuest(addr, VALUE_I32));
|
||||
b.StoreRegisterF(i.Rn & 0xe,
|
||||
b.Load(b.Add(addr, b.AllocConstant(4)), VALUE_I32));
|
||||
b.LoadGuest(b.Add(addr, b.AllocConstant(4)), VALUE_I32));
|
||||
}
|
||||
} else if (fpu.single_precision_pair) {
|
||||
if (i.Rn & 1) {
|
||||
b.StoreRegisterXF(i.Rn & 0xe, b.Load(addr, VALUE_I32));
|
||||
b.StoreRegisterXF(i.Rn | 0x1,
|
||||
b.Load(b.Add(addr, b.AllocConstant(4)), VALUE_I32));
|
||||
b.StoreRegisterXF(i.Rn & 0xe, b.LoadGuest(addr, VALUE_I32));
|
||||
b.StoreRegisterXF(
|
||||
i.Rn | 0x1, b.LoadGuest(b.Add(addr, b.AllocConstant(4)), VALUE_I32));
|
||||
} else {
|
||||
b.StoreRegisterF(i.Rn & 0xe, b.Load(addr, VALUE_I32));
|
||||
b.StoreRegisterF(i.Rn & 0xe, b.LoadGuest(addr, VALUE_I32));
|
||||
b.StoreRegisterF(i.Rn | 0x1,
|
||||
b.Load(b.Add(addr, b.AllocConstant(4)), VALUE_I32));
|
||||
b.LoadGuest(b.Add(addr, b.AllocConstant(4)), VALUE_I32));
|
||||
}
|
||||
} else {
|
||||
b.StoreRegisterF(i.Rn, b.Load(addr, VALUE_I32));
|
||||
b.StoreRegisterF(i.Rn, b.LoadGuest(addr, VALUE_I32));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1588,21 +1594,21 @@ EMITTER(FMOV2) {
|
|||
|
||||
// FMOV with PR=1 assumes the values are word-swapped in memory
|
||||
if (fpu.double_precision) {
|
||||
b.StoreRegisterXF(i.Rn | 0x1, b.Load(addr, VALUE_I32));
|
||||
b.StoreRegisterXF(i.Rn | 0x1, b.LoadGuest(addr, VALUE_I32));
|
||||
b.StoreRegisterXF(i.Rn & 0xe,
|
||||
b.Load(b.Add(addr, b.AllocConstant(4)), VALUE_I32));
|
||||
b.LoadGuest(b.Add(addr, b.AllocConstant(4)), VALUE_I32));
|
||||
} else if (fpu.single_precision_pair) {
|
||||
if (i.Rn & 1) {
|
||||
b.StoreRegisterXF(i.Rn & 0xe, b.Load(addr, VALUE_I32));
|
||||
b.StoreRegisterXF(i.Rn | 0x1,
|
||||
b.Load(b.Add(addr, b.AllocConstant(4)), VALUE_I32));
|
||||
b.StoreRegisterXF(i.Rn & 0xe, b.LoadGuest(addr, VALUE_I32));
|
||||
b.StoreRegisterXF(
|
||||
i.Rn | 0x1, b.LoadGuest(b.Add(addr, b.AllocConstant(4)), VALUE_I32));
|
||||
} else {
|
||||
b.StoreRegisterF(i.Rn & 0xe, b.Load(addr, VALUE_I32));
|
||||
b.StoreRegisterF(i.Rn & 0xe, b.LoadGuest(addr, VALUE_I32));
|
||||
b.StoreRegisterF(i.Rn | 0x1,
|
||||
b.Load(b.Add(addr, b.AllocConstant(4)), VALUE_I32));
|
||||
b.LoadGuest(b.Add(addr, b.AllocConstant(4)), VALUE_I32));
|
||||
}
|
||||
} else {
|
||||
b.StoreRegisterF(i.Rn, b.Load(addr, VALUE_I32));
|
||||
b.StoreRegisterF(i.Rn, b.LoadGuest(addr, VALUE_I32));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1615,23 +1621,23 @@ EMITTER(FMOV3) {
|
|||
|
||||
// FMOV with PR=1 assumes the values are word-swapped in memory
|
||||
if (fpu.double_precision) {
|
||||
b.StoreRegisterXF(i.Rn | 0x1, b.Load(addr, VALUE_I32));
|
||||
b.StoreRegisterXF(i.Rn | 0x1, b.LoadGuest(addr, VALUE_I32));
|
||||
b.StoreRegisterXF(i.Rn & 0xe,
|
||||
b.Load(b.Add(addr, b.AllocConstant(4)), VALUE_I32));
|
||||
b.LoadGuest(b.Add(addr, b.AllocConstant(4)), VALUE_I32));
|
||||
b.StoreRegister(i.Rm, b.Add(addr, b.AllocConstant(8)));
|
||||
} else if (fpu.single_precision_pair) {
|
||||
if (i.Rn & 1) {
|
||||
b.StoreRegisterXF(i.Rn & 0xe, b.Load(addr, VALUE_I32));
|
||||
b.StoreRegisterXF(i.Rn | 0x1,
|
||||
b.Load(b.Add(addr, b.AllocConstant(4)), VALUE_I32));
|
||||
b.StoreRegisterXF(i.Rn & 0xe, b.LoadGuest(addr, VALUE_I32));
|
||||
b.StoreRegisterXF(
|
||||
i.Rn | 0x1, b.LoadGuest(b.Add(addr, b.AllocConstant(4)), VALUE_I32));
|
||||
} else {
|
||||
b.StoreRegisterF(i.Rn & 0xe, b.Load(addr, VALUE_I32));
|
||||
b.StoreRegisterF(i.Rn & 0xe, b.LoadGuest(addr, VALUE_I32));
|
||||
b.StoreRegisterF(i.Rn | 0x1,
|
||||
b.Load(b.Add(addr, b.AllocConstant(4)), VALUE_I32));
|
||||
b.LoadGuest(b.Add(addr, b.AllocConstant(4)), VALUE_I32));
|
||||
}
|
||||
b.StoreRegister(i.Rm, b.Add(addr, b.AllocConstant(8)));
|
||||
} else {
|
||||
b.StoreRegisterF(i.Rn, b.Load(addr, VALUE_I32));
|
||||
b.StoreRegisterF(i.Rn, b.LoadGuest(addr, VALUE_I32));
|
||||
b.StoreRegister(i.Rm, b.Add(addr, b.AllocConstant(4)));
|
||||
}
|
||||
}
|
||||
|
@ -1644,21 +1650,21 @@ EMITTER(FMOV4) {
|
|||
Value *addr = b.LoadRegister(i.Rn, VALUE_I32);
|
||||
|
||||
if (fpu.double_precision) {
|
||||
b.Store(addr, b.LoadRegisterXF(i.Rm | 0x1, VALUE_I32));
|
||||
b.Store(b.Add(addr, b.AllocConstant(4)),
|
||||
b.LoadRegisterXF(i.Rm & 0xe, VALUE_I32));
|
||||
b.StoreGuest(addr, b.LoadRegisterXF(i.Rm | 0x1, VALUE_I32));
|
||||
b.StoreGuest(b.Add(addr, b.AllocConstant(4)),
|
||||
b.LoadRegisterXF(i.Rm & 0xe, VALUE_I32));
|
||||
} else if (fpu.single_precision_pair) {
|
||||
if (i.Rm & 1) {
|
||||
b.Store(addr, b.LoadRegisterXF(i.Rm & 0xe, VALUE_I32));
|
||||
b.Store(b.Add(addr, b.AllocConstant(4)),
|
||||
b.LoadRegisterXF(i.Rm | 0x1, VALUE_I32));
|
||||
b.StoreGuest(addr, b.LoadRegisterXF(i.Rm & 0xe, VALUE_I32));
|
||||
b.StoreGuest(b.Add(addr, b.AllocConstant(4)),
|
||||
b.LoadRegisterXF(i.Rm | 0x1, VALUE_I32));
|
||||
} else {
|
||||
b.Store(addr, b.LoadRegisterF(i.Rm & 0xe, VALUE_I32));
|
||||
b.Store(b.Add(addr, b.AllocConstant(4)),
|
||||
b.LoadRegisterF(i.Rm | 0x1, VALUE_I32));
|
||||
b.StoreGuest(addr, b.LoadRegisterF(i.Rm & 0xe, VALUE_I32));
|
||||
b.StoreGuest(b.Add(addr, b.AllocConstant(4)),
|
||||
b.LoadRegisterF(i.Rm | 0x1, VALUE_I32));
|
||||
}
|
||||
} else {
|
||||
b.Store(addr, b.LoadRegisterF(i.Rm, VALUE_I32));
|
||||
b.StoreGuest(addr, b.LoadRegisterF(i.Rm, VALUE_I32));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1670,25 +1676,25 @@ EMITTER(FMOV5) {
|
|||
if (fpu.double_precision) {
|
||||
Value *addr = b.Sub(b.LoadRegister(i.Rn, VALUE_I32), b.AllocConstant(8));
|
||||
b.StoreRegister(i.Rn, addr);
|
||||
b.Store(addr, b.LoadRegisterXF(i.Rm | 0x1, VALUE_I32));
|
||||
b.Store(b.Add(addr, b.AllocConstant(4)),
|
||||
b.LoadRegisterXF(i.Rm & 0xe, VALUE_I32));
|
||||
b.StoreGuest(addr, b.LoadRegisterXF(i.Rm | 0x1, VALUE_I32));
|
||||
b.StoreGuest(b.Add(addr, b.AllocConstant(4)),
|
||||
b.LoadRegisterXF(i.Rm & 0xe, VALUE_I32));
|
||||
} else if (fpu.single_precision_pair) {
|
||||
Value *addr = b.Sub(b.LoadRegister(i.Rn, VALUE_I32), b.AllocConstant(8));
|
||||
b.StoreRegister(i.Rn, addr);
|
||||
if (i.Rm & 1) {
|
||||
b.Store(addr, b.LoadRegisterXF(i.Rm & 0xe, VALUE_I32));
|
||||
b.Store(b.Add(addr, b.AllocConstant(4)),
|
||||
b.LoadRegisterXF(i.Rm | 0x1, VALUE_I32));
|
||||
b.StoreGuest(addr, b.LoadRegisterXF(i.Rm & 0xe, VALUE_I32));
|
||||
b.StoreGuest(b.Add(addr, b.AllocConstant(4)),
|
||||
b.LoadRegisterXF(i.Rm | 0x1, VALUE_I32));
|
||||
} else {
|
||||
b.Store(addr, b.LoadRegisterF(i.Rm & 0xe, VALUE_I32));
|
||||
b.Store(b.Add(addr, b.AllocConstant(4)),
|
||||
b.LoadRegisterF(i.Rm | 0x1, VALUE_I32));
|
||||
b.StoreGuest(addr, b.LoadRegisterF(i.Rm & 0xe, VALUE_I32));
|
||||
b.StoreGuest(b.Add(addr, b.AllocConstant(4)),
|
||||
b.LoadRegisterF(i.Rm | 0x1, VALUE_I32));
|
||||
}
|
||||
} else {
|
||||
Value *addr = b.Sub(b.LoadRegister(i.Rn, VALUE_I32), b.AllocConstant(4));
|
||||
b.StoreRegister(i.Rn, addr);
|
||||
b.Store(addr, b.LoadRegisterF(i.Rm, VALUE_I32));
|
||||
b.StoreGuest(addr, b.LoadRegisterF(i.Rm, VALUE_I32));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1701,21 +1707,21 @@ EMITTER(FMOV6) {
|
|||
b.Add(b.LoadRegister(0, VALUE_I32), b.LoadRegister(i.Rn, VALUE_I32));
|
||||
|
||||
if (fpu.double_precision) {
|
||||
b.Store(addr, b.LoadRegisterXF(i.Rm | 0x1, VALUE_I32));
|
||||
b.Store(b.Add(addr, b.AllocConstant(4)),
|
||||
b.LoadRegisterXF(i.Rm & 0xe, VALUE_I32));
|
||||
b.StoreGuest(addr, b.LoadRegisterXF(i.Rm | 0x1, VALUE_I32));
|
||||
b.StoreGuest(b.Add(addr, b.AllocConstant(4)),
|
||||
b.LoadRegisterXF(i.Rm & 0xe, VALUE_I32));
|
||||
} else if (fpu.single_precision_pair) {
|
||||
if (i.Rm & 1) {
|
||||
b.Store(addr, b.LoadRegisterXF(i.Rm & 0xe, VALUE_I32));
|
||||
b.Store(b.Add(addr, b.AllocConstant(4)),
|
||||
b.LoadRegisterXF(i.Rm | 0x1, VALUE_I32));
|
||||
b.StoreGuest(addr, b.LoadRegisterXF(i.Rm & 0xe, VALUE_I32));
|
||||
b.StoreGuest(b.Add(addr, b.AllocConstant(4)),
|
||||
b.LoadRegisterXF(i.Rm | 0x1, VALUE_I32));
|
||||
} else {
|
||||
b.Store(addr, b.LoadRegisterF(i.Rm & 0xe, VALUE_I32));
|
||||
b.Store(b.Add(addr, b.AllocConstant(4)),
|
||||
b.LoadRegisterF(i.Rm | 0x1, VALUE_I32));
|
||||
b.StoreGuest(addr, b.LoadRegisterF(i.Rm & 0xe, VALUE_I32));
|
||||
b.StoreGuest(b.Add(addr, b.AllocConstant(4)),
|
||||
b.LoadRegisterF(i.Rm | 0x1, VALUE_I32));
|
||||
}
|
||||
} else {
|
||||
b.Store(addr, b.LoadRegisterF(i.Rm, VALUE_I32));
|
||||
b.StoreGuest(addr, b.LoadRegisterF(i.Rm, VALUE_I32));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1904,7 +1910,7 @@ EMITTER(LDSFPUL) {
|
|||
// LDS.L @Rm+,FPSCR
|
||||
EMITTER(LDSMFPSCR) {
|
||||
Value *addr = b.LoadRegister(i.Rm, VALUE_I32);
|
||||
Value *v = b.Load(addr, VALUE_I32);
|
||||
Value *v = b.LoadGuest(addr, VALUE_I32);
|
||||
b.StoreFPSCR(v);
|
||||
b.StoreRegister(i.Rm, b.Add(addr, b.AllocConstant(4)));
|
||||
}
|
||||
|
@ -1912,7 +1918,7 @@ EMITTER(LDSMFPSCR) {
|
|||
// LDS.L @Rm+,FPUL
|
||||
EMITTER(LDSMFPUL) {
|
||||
Value *addr = b.LoadRegister(i.Rm, VALUE_I32);
|
||||
Value *v = b.Load(addr, VALUE_I32);
|
||||
Value *v = b.LoadGuest(addr, VALUE_I32);
|
||||
b.StoreContext(offsetof(SH4Context, fpul), v);
|
||||
b.StoreRegister(i.Rm, b.Add(addr, b.AllocConstant(4)));
|
||||
}
|
||||
|
@ -1930,7 +1936,7 @@ EMITTER(STSFPUL) {
|
|||
EMITTER(STSMFPSCR) {
|
||||
Value *addr = b.Sub(b.LoadRegister(i.Rn, VALUE_I32), b.AllocConstant(4));
|
||||
b.StoreRegister(i.Rn, addr);
|
||||
b.Store(addr, b.LoadFPSCR());
|
||||
b.StoreGuest(addr, b.LoadFPSCR());
|
||||
}
|
||||
|
||||
// STS.L FPUL,@-Rn
|
||||
|
@ -1938,7 +1944,7 @@ EMITTER(STSMFPUL) {
|
|||
Value *addr = b.Sub(b.LoadRegister(i.Rn, VALUE_I32), b.AllocConstant(4));
|
||||
b.StoreRegister(i.Rn, addr);
|
||||
Value *fpul = b.LoadContext(offsetof(SH4Context, fpul), VALUE_I32);
|
||||
b.Store(addr, fpul);
|
||||
b.StoreGuest(addr, fpul);
|
||||
}
|
||||
|
||||
// FIPR FVm,FVn PR=0 1111nnmm11101101
|
||||
|
@ -1959,16 +1965,16 @@ EMITTER(FIPR) {
|
|||
EMITTER(FSCA) {
|
||||
int n = i.Rn << 1;
|
||||
|
||||
Value *angle = b.SMul(
|
||||
b.SMul(b.Div(b.Cast(b.ZExt(b.LoadContext(offsetof(SH4Context, fpul),
|
||||
VALUE_I16),
|
||||
VALUE_I32),
|
||||
VALUE_F32),
|
||||
b.AllocConstant(65536.0f)),
|
||||
b.AllocConstant(2.0f)),
|
||||
b.AllocConstant((float)M_PI));
|
||||
b.StoreRegisterF(n, b.Sin(angle));
|
||||
b.StoreRegisterF(n + 1, b.Cos(angle));
|
||||
Value *fpul = b.LoadContext(offsetof(SH4Context, fpul), VALUE_I16);
|
||||
fpul = b.ZExt(fpul, VALUE_I64);
|
||||
|
||||
Value *fsca_table = b.AllocConstant(reinterpret_cast<uint64_t>(s_fsca_table));
|
||||
Value *fsca_offset = b.Shl(fpul, 3);
|
||||
Value *addr = b.Add(fsca_table, fsca_offset);
|
||||
|
||||
b.StoreRegisterF(n, b.LoadHost(addr, VALUE_F32));
|
||||
b.StoreRegisterF(n + 1,
|
||||
b.LoadHost(b.Add(addr, b.AllocConstant(4ll)), VALUE_F32));
|
||||
}
|
||||
|
||||
// FTRV XMTRX,FVn PR=0 1111nn0111111101
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -239,6 +239,42 @@ void IRBuilder::RemoveBlock(Block *block) {
|
|||
block->~Block();
|
||||
}
|
||||
|
||||
Value *IRBuilder::LoadHost(Value *addr, ValueTy type) {
|
||||
CHECK_EQ(VALUE_I64, addr->type());
|
||||
|
||||
Instr *instr = AppendInstr(OP_LOAD_HOST);
|
||||
Value *result = AllocDynamic(type);
|
||||
instr->set_arg0(addr);
|
||||
instr->set_result(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void IRBuilder::StoreHost(Value *addr, Value *v) {
|
||||
CHECK_EQ(VALUE_I64, addr->type());
|
||||
|
||||
Instr *instr = AppendInstr(OP_STORE_HOST);
|
||||
instr->set_arg0(addr);
|
||||
instr->set_arg1(v);
|
||||
}
|
||||
|
||||
Value *IRBuilder::LoadGuest(Value *addr, ValueTy type) {
|
||||
CHECK_EQ(VALUE_I32, addr->type());
|
||||
|
||||
Instr *instr = AppendInstr(OP_LOAD_GUEST);
|
||||
Value *result = AllocDynamic(type);
|
||||
instr->set_arg0(addr);
|
||||
instr->set_result(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void IRBuilder::StoreGuest(Value *addr, Value *v) {
|
||||
CHECK_EQ(VALUE_I32, addr->type());
|
||||
|
||||
Instr *instr = AppendInstr(OP_STORE_GUEST);
|
||||
instr->set_arg0(addr);
|
||||
instr->set_arg1(v);
|
||||
}
|
||||
|
||||
Value *IRBuilder::LoadContext(size_t offset, ValueTy type) {
|
||||
Instr *instr = AppendInstr(OP_LOAD_CONTEXT);
|
||||
Value *result = AllocDynamic(type);
|
||||
|
@ -267,24 +303,6 @@ void IRBuilder::StoreLocal(Local *local, Value *v) {
|
|||
instr->set_arg1(v);
|
||||
}
|
||||
|
||||
Value *IRBuilder::Load(Value *addr, ValueTy type) {
|
||||
CHECK_EQ(VALUE_I32, addr->type());
|
||||
|
||||
Instr *instr = AppendInstr(OP_LOAD);
|
||||
Value *result = AllocDynamic(type);
|
||||
instr->set_arg0(addr);
|
||||
instr->set_result(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void IRBuilder::Store(Value *addr, Value *v) {
|
||||
CHECK_EQ(VALUE_I32, addr->type());
|
||||
|
||||
Instr *instr = AppendInstr(OP_STORE);
|
||||
instr->set_arg0(addr);
|
||||
instr->set_arg1(v);
|
||||
}
|
||||
|
||||
Value *IRBuilder::Cast(Value *v, ValueTy dest_type) {
|
||||
CHECK((IsIntType(v->type()) && IsFloatType(dest_type)) ||
|
||||
(IsFloatType(v->type()) && IsIntType(dest_type)));
|
||||
|
@ -536,22 +554,6 @@ Value *IRBuilder::Abs(Value *a) {
|
|||
return result;
|
||||
}
|
||||
|
||||
Value *IRBuilder::Sin(Value *a) {
|
||||
Instr *instr = AppendInstr(OP_SIN);
|
||||
Value *result = AllocDynamic(a->type());
|
||||
instr->set_arg0(a);
|
||||
instr->set_result(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
Value *IRBuilder::Cos(Value *a) {
|
||||
Instr *instr = AppendInstr(OP_COS);
|
||||
Value *result = AllocDynamic(a->type());
|
||||
instr->set_arg0(a);
|
||||
instr->set_result(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
Value *IRBuilder::And(Value *a, Value *b) {
|
||||
CHECK_EQ(a->type(), b->type());
|
||||
|
||||
|
|
|
@ -378,6 +378,14 @@ class IRBuilder {
|
|||
Block *AppendBlock();
|
||||
void RemoveBlock(Block *block);
|
||||
|
||||
// direct access to host memory
|
||||
Value *LoadHost(Value *addr, ValueTy type);
|
||||
void StoreHost(Value *addr, Value *v);
|
||||
|
||||
// guest memory operations
|
||||
Value *LoadGuest(Value *addr, ValueTy type);
|
||||
void StoreGuest(Value *addr, Value *v);
|
||||
|
||||
// context operations
|
||||
Value *LoadContext(size_t offset, ValueTy type);
|
||||
void StoreContext(size_t offset, Value *v, InstrFlag flags = IF_NONE);
|
||||
|
@ -386,10 +394,6 @@ class IRBuilder {
|
|||
Value *LoadLocal(Local *local);
|
||||
void StoreLocal(Local *local, Value *v);
|
||||
|
||||
// memory operations
|
||||
Value *Load(Value *addr, ValueTy type);
|
||||
void Store(Value *addr, Value *v);
|
||||
|
||||
// cast / conversion operations
|
||||
Value *Cast(Value *v, ValueTy dest_type);
|
||||
Value *SExt(Value *v, ValueTy dest_type);
|
||||
|
@ -418,8 +422,6 @@ class IRBuilder {
|
|||
Value *Neg(Value *a);
|
||||
Value *Sqrt(Value *a);
|
||||
Value *Abs(Value *a);
|
||||
Value *Sin(Value *a);
|
||||
Value *Cos(Value *a);
|
||||
|
||||
// bitwise operations
|
||||
Value *And(Value *a, Value *b);
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
IR_OP(LOAD_HOST)
|
||||
IR_OP(STORE_HOST)
|
||||
IR_OP(LOAD_GUEST)
|
||||
IR_OP(STORE_GUEST)
|
||||
IR_OP(LOAD_CONTEXT)
|
||||
IR_OP(STORE_CONTEXT)
|
||||
IR_OP(LOAD_LOCAL)
|
||||
IR_OP(STORE_LOCAL)
|
||||
IR_OP(LOAD)
|
||||
IR_OP(STORE)
|
||||
IR_OP(CAST)
|
||||
IR_OP(SEXT)
|
||||
IR_OP(ZEXT)
|
||||
|
@ -27,8 +29,6 @@ IR_OP(DIV)
|
|||
IR_OP(NEG)
|
||||
IR_OP(SQRT)
|
||||
IR_OP(ABS)
|
||||
IR_OP(SIN)
|
||||
IR_OP(COS)
|
||||
IR_OP(AND)
|
||||
IR_OP(OR)
|
||||
IR_OP(XOR)
|
||||
|
|
|
@ -5,4 +5,4 @@ test_fsca:
|
|||
rts
|
||||
nop
|
||||
# REGISTER_OUT fr2 0x3f800000
|
||||
# REGISTER_OUT fr3 0xb33bbd2e
|
||||
# REGISTER_OUT fr3 0x80000000
|
||||
|
|
|
@ -74,7 +74,7 @@ TEST_SH4(test_fmuld,(uint8_t *)"\x02\xf2\x0b\x00\x09\x00\x02\xf1\x0b\x00\x09\x00
|
|||
TEST_SH4(test_fnegf,(uint8_t *)"\x4d\xf0\x0b\x00\x09\x00\x4d\xf0\x0b\x00\x09\x00",12,0x6,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0x40800000,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xc0800000,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d)
|
||||
TEST_SH4(test_fnegd,(uint8_t *)"\x4d\xf0\x0b\x00\x09\x00\x4d\xf0\x0b\x00\x09\x00",12,0x0,0xc0001,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0x0,0x40140000,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0x0L,0xc0140000L,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d)
|
||||
TEST_SH4(test_frchg,(uint8_t *)"\x6a\x01\xfd\xfb\x6a\x02\x0a\xd0\x0a\xf0\x02\x63\xfd\xfb\x0a\xf0\x02\x64\x0b\x00\x09\x00\x09\x00\x09\x00\x09\x00\x09\x00\x09\x00\x00\x00\x00\x00\x09\x00\x09\x00\x09\x00\x09\x00\x09\x00\x09\x00\x20\x00\x01\x8c\x09\x00\x09\x00\x09\x00\x09\x00\x09\x00\x09\x00",64,0x0,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0x41500000,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0x40001,0x240001,0x0,0x41500000,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d)
|
||||
TEST_SH4(test_fsca,(uint8_t *)"\x5a\x40\xfd\xf2\x0b\x00\x09\x00",8,0x0,0xbaadf00d,0x4000,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0x3f800000,0xb33bbd2e,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d)
|
||||
TEST_SH4(test_fsca,(uint8_t *)"\x5a\x40\xfd\xf2\x0b\x00\x09\x00",8,0x0,0xbaadf00d,0x4000,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0x3f800000,0x80000000,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d)
|
||||
TEST_SH4(test_fschg,(uint8_t *)"\x6a\x00\xfd\xf3\x6a\x01\x0b\x00\x09\x00",10,0x0,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0x40001,0x140001,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d)
|
||||
TEST_SH4(test_fsrra,(uint8_t *)"\x7d\xf0\x0b\x00\x09\x00",6,0x0,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0x40800000,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0x3f000000,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d)
|
||||
TEST_SH4(test_fsqrtd,(uint8_t *)"\x6d\xf0\x0b\x00\x09\x00\x6d\xf0\x0b\x00\x09\x00",12,0x0,0xc0001,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0x0,0x40100000,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0x0,0x40000000,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d,0xbaadf00d)
|
||||
|
|
Loading…
Reference in New Issue