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:
Anthony Pesch 2016-01-25 23:21:42 -08:00
parent a039b60d52
commit f457e8e9d8
11 changed files with 66146 additions and 514 deletions

View File

@ -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"

View File

@ -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"

View File

@ -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();

View File

@ -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, &region, &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, &region, &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()));

View File

@ -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

View File

@ -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());

View File

@ -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);

View File

@ -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)

View File

@ -5,4 +5,4 @@ test_fsca:
rts
nop
# REGISTER_OUT fr2 0x3f800000
# REGISTER_OUT fr3 0xb33bbd2e
# REGISTER_OUT fr3 0x80000000

View File

@ -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)