1120 lines
30 KiB
C++
1120 lines
30 KiB
C++
/*
|
|
******************************************************************************
|
|
* Xenia : Xbox 360 Emulator Research Project *
|
|
******************************************************************************
|
|
* Copyright 2013 Ben Vanik. All rights reserved. *
|
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
|
******************************************************************************
|
|
*/
|
|
|
|
#include "xenia/cpu/ppc/ppc_emit-private.h"
|
|
|
|
#include "xenia/base/assert.h"
|
|
#include "xenia/cpu/ppc/ppc_context.h"
|
|
#include "xenia/cpu/ppc/ppc_hir_builder.h"
|
|
|
|
#include <stddef.h>
|
|
|
|
namespace xe {
|
|
namespace cpu {
|
|
namespace ppc {
|
|
|
|
// TODO(benvanik): remove when enums redefined.
|
|
using namespace xe::cpu::hir;
|
|
|
|
using xe::cpu::hir::Value;
|
|
|
|
Value* CalculateEA(PPCHIRBuilder& f, uint32_t ra, uint32_t rb) {
|
|
return f.Add(f.LoadGPR(ra), f.LoadGPR(rb));
|
|
}
|
|
|
|
Value* CalculateEA_0(PPCHIRBuilder& f, uint32_t ra, uint32_t rb) {
|
|
if (ra) {
|
|
return f.Add(f.LoadGPR(ra), f.LoadGPR(rb));
|
|
} else {
|
|
return f.LoadGPR(rb);
|
|
}
|
|
}
|
|
|
|
Value* CalculateEA_i(PPCHIRBuilder& f, uint32_t ra, uint64_t imm) {
|
|
return f.Add(f.LoadGPR(ra), f.LoadConstantUint64(imm));
|
|
}
|
|
|
|
Value* CalculateEA_0_i(PPCHIRBuilder& f, uint32_t ra, uint64_t imm) {
|
|
if (ra) {
|
|
return f.Add(f.LoadGPR(ra), f.LoadConstantUint64(imm));
|
|
} else {
|
|
return f.LoadConstantUint64(imm);
|
|
}
|
|
}
|
|
|
|
void StoreEA(PPCHIRBuilder& f, uint32_t rt, Value* ea) {
|
|
// Stored back as 64bit right after the add, it seems.
|
|
// f.StoreGPR(rt, f.ZeroExtend(f.Truncate(ea, INT32_TYPE), INT64_TYPE));
|
|
f.StoreGPR(rt, ea);
|
|
}
|
|
|
|
// Integer load (A-13)
|
|
|
|
int InstrEmit_lbz(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + EXTS(D)
|
|
// RT <- i56.0 || MEM(EA, 1)
|
|
Value* ea = CalculateEA_0_i(f, i.D.RA, XEEXTS16(i.D.DS));
|
|
Value* rt = f.ZeroExtend(f.Load(ea, INT8_TYPE), INT64_TYPE);
|
|
f.StoreGPR(i.D.RT, rt);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_lbzu(PPCHIRBuilder& f, const InstrData& i) {
|
|
// EA <- (RA) + EXTS(D)
|
|
// RT <- i56.0 || MEM(EA, 1)
|
|
// RA <- EA
|
|
Value* ea = CalculateEA_i(f, i.D.RA, XEEXTS16(i.D.DS));
|
|
Value* rt = f.ZeroExtend(f.Load(ea, INT8_TYPE), INT64_TYPE);
|
|
f.StoreGPR(i.D.RT, rt);
|
|
StoreEA(f, i.D.RA, ea);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_lbzux(PPCHIRBuilder& f, const InstrData& i) {
|
|
// EA <- (RA) + (RB)
|
|
// RT <- i56.0 || MEM(EA, 1)
|
|
// RA <- EA
|
|
Value* ea = CalculateEA(f, i.X.RA, i.X.RB);
|
|
Value* rt = f.ZeroExtend(f.Load(ea, INT8_TYPE), INT64_TYPE);
|
|
f.StoreGPR(i.X.RT, rt);
|
|
StoreEA(f, i.X.RA, ea);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_lbzx(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + (RB)
|
|
// RT <- i56.0 || MEM(EA, 1)
|
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
|
Value* rt = f.ZeroExtend(f.Load(ea, INT8_TYPE), INT64_TYPE);
|
|
f.StoreGPR(i.X.RT, rt);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_lha(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + EXTS(D)
|
|
// RT <- EXTS(MEM(EA, 2))
|
|
Value* ea = CalculateEA_0_i(f, i.D.RA, XEEXTS16(i.D.DS));
|
|
Value* rt = f.SignExtend(f.ByteSwap(f.Load(ea, INT16_TYPE)), INT64_TYPE);
|
|
f.StoreGPR(i.D.RT, rt);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_lhau(PPCHIRBuilder& f, const InstrData& i) {
|
|
// EA <- (RA) + EXTS(D)
|
|
// RT <- EXTS(MEM(EA, 2))
|
|
// RA <- EA
|
|
Value* ea = CalculateEA_i(f, i.D.RA, XEEXTS16(i.D.DS));
|
|
Value* rt = f.SignExtend(f.ByteSwap(f.Load(ea, INT16_TYPE)), INT64_TYPE);
|
|
f.StoreGPR(i.D.RT, rt);
|
|
StoreEA(f, i.D.RA, ea);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_lhaux(PPCHIRBuilder& f, const InstrData& i) {
|
|
// EA <- (RA) + (RB)
|
|
// RT <- EXTS(MEM(EA, 2))
|
|
// RA <- EA
|
|
Value* ea = CalculateEA(f, i.X.RA, i.X.RB);
|
|
Value* rt = f.SignExtend(f.ByteSwap(f.Load(ea, INT16_TYPE)), INT64_TYPE);
|
|
f.StoreGPR(i.X.RT, rt);
|
|
StoreEA(f, i.X.RA, ea);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_lhax(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + (RB)
|
|
// RT <- EXTS(MEM(EA, 2))
|
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
|
Value* rt = f.SignExtend(f.ByteSwap(f.Load(ea, INT16_TYPE)), INT64_TYPE);
|
|
f.StoreGPR(i.X.RT, rt);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_lhz(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + EXTS(D)
|
|
// RT <- i48.0 || MEM(EA, 2)
|
|
Value* ea = CalculateEA_0_i(f, i.D.RA, XEEXTS16(i.D.DS));
|
|
Value* rt = f.ZeroExtend(f.ByteSwap(f.Load(ea, INT16_TYPE)), INT64_TYPE);
|
|
f.StoreGPR(i.D.RT, rt);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_lhzu(PPCHIRBuilder& f, const InstrData& i) {
|
|
// EA <- (RA) + EXTS(D)
|
|
// RT <- i48.0 || MEM(EA, 2)
|
|
// RA <- EA
|
|
Value* ea = CalculateEA_i(f, i.D.RA, XEEXTS16(i.D.DS));
|
|
Value* rt = f.ZeroExtend(f.ByteSwap(f.Load(ea, INT16_TYPE)), INT64_TYPE);
|
|
f.StoreGPR(i.D.RT, rt);
|
|
StoreEA(f, i.D.RA, ea);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_lhzux(PPCHIRBuilder& f, const InstrData& i) {
|
|
// EA <- (RA) + (RB)
|
|
// RT <- i48.0 || MEM(EA, 2)
|
|
// RA <- EA
|
|
Value* ea = CalculateEA(f, i.X.RA, i.X.RB);
|
|
Value* rt = f.ZeroExtend(f.ByteSwap(f.Load(ea, INT16_TYPE)), INT64_TYPE);
|
|
f.StoreGPR(i.X.RT, rt);
|
|
StoreEA(f, i.X.RA, ea);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_lhzx(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + (RB)
|
|
// RT <- i48.0 || MEM(EA, 2)
|
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
|
Value* rt = f.ZeroExtend(f.ByteSwap(f.Load(ea, INT16_TYPE)), INT64_TYPE);
|
|
f.StoreGPR(i.X.RT, rt);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_lwa(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + EXTS(D || 00)
|
|
// RT <- EXTS(MEM(EA, 4))
|
|
Value* ea = CalculateEA_0_i(f, i.DS.RA, XEEXTS16(i.DS.DS << 2));
|
|
Value* rt = f.SignExtend(f.ByteSwap(f.Load(ea, INT32_TYPE)), INT64_TYPE);
|
|
f.StoreGPR(i.DS.RT, rt);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_lwaux(PPCHIRBuilder& f, const InstrData& i) {
|
|
// EA <- (RA) + (RB)
|
|
// RT <- EXTS(MEM(EA, 4))
|
|
// RA <- EA
|
|
Value* ea = CalculateEA(f, i.X.RA, i.X.RB);
|
|
Value* rt = f.SignExtend(f.ByteSwap(f.Load(ea, INT32_TYPE)), INT64_TYPE);
|
|
f.StoreGPR(i.X.RT, rt);
|
|
StoreEA(f, i.X.RA, ea);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_lwax(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + (RB)
|
|
// RT <- EXTS(MEM(EA, 4))
|
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
|
Value* rt = f.SignExtend(f.ByteSwap(f.Load(ea, INT32_TYPE)), INT64_TYPE);
|
|
f.StoreGPR(i.X.RT, rt);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_lwz(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + EXTS(D)
|
|
// RT <- i32.0 || MEM(EA, 4)
|
|
Value* ea = CalculateEA_0_i(f, i.D.RA, XEEXTS16(i.D.DS));
|
|
Value* rt = f.ZeroExtend(f.ByteSwap(f.Load(ea, INT32_TYPE)), INT64_TYPE);
|
|
f.StoreGPR(i.D.RT, rt);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_lwzu(PPCHIRBuilder& f, const InstrData& i) {
|
|
// EA <- (RA) + EXTS(D)
|
|
// RT <- i32.0 || MEM(EA, 4)
|
|
// RA <- EA
|
|
Value* ea = CalculateEA_i(f, i.D.RA, XEEXTS16(i.D.DS));
|
|
Value* rt = f.ZeroExtend(f.ByteSwap(f.Load(ea, INT32_TYPE)), INT64_TYPE);
|
|
f.StoreGPR(i.D.RT, rt);
|
|
StoreEA(f, i.D.RA, ea);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_lwzux(PPCHIRBuilder& f, const InstrData& i) {
|
|
// EA <- (RA) + (RB)
|
|
// RT <- i32.0 || MEM(EA, 4)
|
|
// RA <- EA
|
|
Value* ea = CalculateEA(f, i.X.RA, i.X.RB);
|
|
Value* rt = f.ZeroExtend(f.ByteSwap(f.Load(ea, INT32_TYPE)), INT64_TYPE);
|
|
f.StoreGPR(i.X.RT, rt);
|
|
StoreEA(f, i.X.RA, ea);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_lwzx(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + (RB)
|
|
// RT <- i32.0 || MEM(EA, 4)
|
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
|
Value* rt = f.ZeroExtend(f.ByteSwap(f.Load(ea, INT32_TYPE)), INT64_TYPE);
|
|
f.StoreGPR(i.X.RT, rt);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_ld(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + EXTS(DS || 0b00)
|
|
// RT <- MEM(EA, 8)
|
|
Value* ea = CalculateEA_0_i(f, i.DS.RA, XEEXTS16(i.DS.DS << 2));
|
|
Value* rt = f.ByteSwap(f.Load(ea, INT64_TYPE));
|
|
f.StoreGPR(i.DS.RT, rt);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_ldu(PPCHIRBuilder& f, const InstrData& i) {
|
|
// EA <- (RA) + EXTS(DS || 0b00)
|
|
// RT <- MEM(EA, 8)
|
|
// RA <- EA
|
|
Value* ea = CalculateEA_i(f, i.DS.RA, XEEXTS16(i.DS.DS << 2));
|
|
Value* rt = f.ByteSwap(f.Load(ea, INT64_TYPE));
|
|
f.StoreGPR(i.DS.RT, rt);
|
|
StoreEA(f, i.DS.RA, ea);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_ldux(PPCHIRBuilder& f, const InstrData& i) {
|
|
// EA <- (RA) + (RB)
|
|
// RT <- MEM(EA, 8)
|
|
// RA <- EA
|
|
Value* ea = CalculateEA(f, i.X.RA, i.X.RB);
|
|
Value* rt = f.ByteSwap(f.Load(ea, INT64_TYPE));
|
|
f.StoreGPR(i.X.RT, rt);
|
|
StoreEA(f, i.X.RA, ea);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_ldx(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + (RB)
|
|
// RT <- MEM(EA, 8)
|
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
|
Value* rt = f.ByteSwap(f.Load(ea, INT64_TYPE));
|
|
f.StoreGPR(i.X.RT, rt);
|
|
return 0;
|
|
}
|
|
|
|
// Integer store (A-14)
|
|
|
|
int InstrEmit_stb(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + EXTS(D)
|
|
// MEM(EA, 1) <- (RS)[56:63]
|
|
Value* ea = CalculateEA_0_i(f, i.D.RA, XEEXTS16(i.D.DS));
|
|
f.Store(ea, f.Truncate(f.LoadGPR(i.D.RT), INT8_TYPE));
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_stbu(PPCHIRBuilder& f, const InstrData& i) {
|
|
// EA <- (RA) + EXTS(D)
|
|
// MEM(EA, 1) <- (RS)[56:63]
|
|
// RA <- EA
|
|
Value* ea = CalculateEA_i(f, i.D.RA, XEEXTS16(i.D.DS));
|
|
f.Store(ea, f.Truncate(f.LoadGPR(i.D.RT), INT8_TYPE));
|
|
StoreEA(f, i.D.RA, ea);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_stbux(PPCHIRBuilder& f, const InstrData& i) {
|
|
// EA <- (RA) + (RB)
|
|
// MEM(EA, 1) <- (RS)[56:63]
|
|
// RA <- EA
|
|
Value* ea = CalculateEA(f, i.X.RA, i.X.RB);
|
|
f.Store(ea, f.Truncate(f.LoadGPR(i.X.RT), INT8_TYPE));
|
|
StoreEA(f, i.X.RA, ea);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_stbx(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + (RB)
|
|
// MEM(EA, 1) <- (RS)[56:63]
|
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
|
f.Store(ea, f.Truncate(f.LoadGPR(i.X.RT), INT8_TYPE));
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_sth(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + EXTS(D)
|
|
// MEM(EA, 2) <- (RS)[48:63]
|
|
Value* ea = CalculateEA_0_i(f, i.D.RA, XEEXTS16(i.D.DS));
|
|
f.Store(ea, f.ByteSwap(f.Truncate(f.LoadGPR(i.D.RT), INT16_TYPE)));
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_sthu(PPCHIRBuilder& f, const InstrData& i) {
|
|
// EA <- (RA) + EXTS(D)
|
|
// MEM(EA, 2) <- (RS)[48:63]
|
|
// RA <- EA
|
|
Value* ea = CalculateEA_i(f, i.D.RA, XEEXTS16(i.D.DS));
|
|
f.Store(ea, f.ByteSwap(f.Truncate(f.LoadGPR(i.D.RT), INT16_TYPE)));
|
|
StoreEA(f, i.D.RA, ea);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_sthux(PPCHIRBuilder& f, const InstrData& i) {
|
|
// EA <- (RA) + (RB)
|
|
// MEM(EA, 2) <- (RS)[48:63]
|
|
// RA <- EA
|
|
Value* ea = CalculateEA(f, i.X.RA, i.X.RB);
|
|
f.Store(ea, f.ByteSwap(f.Truncate(f.LoadGPR(i.X.RT), INT16_TYPE)));
|
|
StoreEA(f, i.X.RA, ea);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_sthx(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + (RB)
|
|
// MEM(EA, 2) <- (RS)[48:63]
|
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
|
f.Store(ea, f.ByteSwap(f.Truncate(f.LoadGPR(i.X.RT), INT16_TYPE)));
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_stw(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + EXTS(D)
|
|
// MEM(EA, 4) <- (RS)[32:63]
|
|
Value* ea = CalculateEA_0_i(f, i.D.RA, XEEXTS16(i.D.DS));
|
|
f.Store(ea, f.ByteSwap(f.Truncate(f.LoadGPR(i.D.RT), INT32_TYPE)));
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_stwu(PPCHIRBuilder& f, const InstrData& i) {
|
|
// EA <- (RA) + EXTS(D)
|
|
// MEM(EA, 4) <- (RS)[32:63]
|
|
// RA <- EA
|
|
Value* ea = CalculateEA_i(f, i.D.RA, XEEXTS16(i.D.DS));
|
|
f.Store(ea, f.ByteSwap(f.Truncate(f.LoadGPR(i.D.RT), INT32_TYPE)));
|
|
StoreEA(f, i.D.RA, ea);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_stwux(PPCHIRBuilder& f, const InstrData& i) {
|
|
// EA <- (RA) + (RB)
|
|
// MEM(EA, 4) <- (RS)[32:63]
|
|
// RA <- EA
|
|
Value* ea = CalculateEA(f, i.X.RA, i.X.RB);
|
|
f.Store(ea, f.ByteSwap(f.Truncate(f.LoadGPR(i.X.RT), INT32_TYPE)));
|
|
StoreEA(f, i.X.RA, ea);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_stwx(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + (RB)
|
|
// MEM(EA, 4) <- (RS)[32:63]
|
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
|
f.Store(ea, f.ByteSwap(f.Truncate(f.LoadGPR(i.X.RT), INT32_TYPE)));
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_std(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + EXTS(DS || 0b00)
|
|
// MEM(EA, 8) <- (RS)
|
|
Value* ea = CalculateEA_0_i(f, i.DS.RA, XEEXTS16(i.DS.DS << 2));
|
|
f.Store(ea, f.ByteSwap(f.LoadGPR(i.DS.RT)));
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_stdu(PPCHIRBuilder& f, const InstrData& i) {
|
|
// EA <- (RA) + EXTS(DS || 0b00)
|
|
// MEM(EA, 8) <- (RS)
|
|
// RA <- EA
|
|
Value* ea = CalculateEA_i(f, i.DS.RA, XEEXTS16(i.DS.DS << 2));
|
|
f.Store(ea, f.ByteSwap(f.LoadGPR(i.DS.RT)));
|
|
StoreEA(f, i.DS.RA, ea);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_stdux(PPCHIRBuilder& f, const InstrData& i) {
|
|
// EA <- (RA) + (RB)
|
|
// MEM(EA, 8) <- (RS)
|
|
// RA <- EA
|
|
Value* ea = CalculateEA(f, i.X.RA, i.X.RB);
|
|
f.Store(ea, f.ByteSwap(f.LoadGPR(i.X.RT)));
|
|
StoreEA(f, i.X.RA, ea);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_stdx(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + (RB)
|
|
// MEM(EA, 8) <- (RS)
|
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
|
f.Store(ea, f.ByteSwap(f.LoadGPR(i.X.RT)));
|
|
return 0;
|
|
}
|
|
|
|
// Integer load and store with byte reverse (A-1
|
|
|
|
int InstrEmit_lhbrx(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + (RB)
|
|
// RT <- i48.0 || bswap(MEM(EA, 2))
|
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
|
Value* rt = f.ZeroExtend(f.Load(ea, INT16_TYPE), INT64_TYPE);
|
|
StoreEA(f, i.X.RT, rt);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_lwbrx(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + (RB)
|
|
// RT <- i32.0 || bswap(MEM(EA, 4))
|
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
|
Value* rt = f.ZeroExtend(f.Load(ea, INT32_TYPE), INT64_TYPE);
|
|
f.StoreGPR(i.X.RT, rt);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_ldbrx(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + (RB)
|
|
// RT <- bswap(MEM(EA, 8))
|
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
|
Value* rt = f.Load(ea, INT64_TYPE);
|
|
f.StoreGPR(i.X.RT, rt);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_sthbrx(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + (RB)
|
|
// MEM(EA, 2) <- bswap((RS)[48:63])
|
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
|
f.Store(ea, f.Truncate(f.LoadGPR(i.X.RT), INT16_TYPE));
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_stwbrx(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + (RB)
|
|
// MEM(EA, 4) <- bswap((RS)[32:63])
|
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
|
f.Store(ea, f.Truncate(f.LoadGPR(i.X.RT), INT32_TYPE));
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_stdbrx(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + (RB)
|
|
// MEM(EA, 8) <- bswap(RS)
|
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
|
f.Store(ea, f.LoadGPR(i.X.RT));
|
|
return 0;
|
|
}
|
|
|
|
// Integer load and store multiple (A-16)
|
|
|
|
int InstrEmit_lmw(PPCHIRBuilder& f, const InstrData& i) {
|
|
XEINSTRNOTIMPLEMENTED();
|
|
return 1;
|
|
}
|
|
|
|
int InstrEmit_stmw(PPCHIRBuilder& f, const InstrData& i) {
|
|
XEINSTRNOTIMPLEMENTED();
|
|
return 1;
|
|
}
|
|
|
|
// Integer load and store string (A-17)
|
|
|
|
int InstrEmit_lswi(PPCHIRBuilder& f, const InstrData& i) {
|
|
XEINSTRNOTIMPLEMENTED();
|
|
return 1;
|
|
}
|
|
|
|
int InstrEmit_lswx(PPCHIRBuilder& f, const InstrData& i) {
|
|
XEINSTRNOTIMPLEMENTED();
|
|
return 1;
|
|
}
|
|
|
|
int InstrEmit_stswi(PPCHIRBuilder& f, const InstrData& i) {
|
|
XEINSTRNOTIMPLEMENTED();
|
|
return 1;
|
|
}
|
|
|
|
int InstrEmit_stswx(PPCHIRBuilder& f, const InstrData& i) {
|
|
XEINSTRNOTIMPLEMENTED();
|
|
return 1;
|
|
}
|
|
|
|
// Memory synchronization (A-18)
|
|
|
|
int InstrEmit_eieio(PPCHIRBuilder& f, const InstrData& i) {
|
|
f.MemoryBarrier();
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_sync(PPCHIRBuilder& f, const InstrData& i) {
|
|
f.MemoryBarrier();
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_isync(PPCHIRBuilder& f, const InstrData& i) {
|
|
// XEINSTRNOTIMPLEMENTED();
|
|
f.Nop();
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_ldarx(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + (RB)
|
|
// RESERVE <- 1
|
|
// RESERVE_LENGTH <- 8
|
|
// RESERVE_ADDR <- real_addr(EA)
|
|
// RT <- MEM(EA, 8)
|
|
|
|
// NOTE: we assume we are within a global lock.
|
|
// We could assert here that the block (or its parent) has taken a global lock
|
|
// already, but I haven't see anything but interrupt callbacks (which are
|
|
// always under a global lock) do that yet.
|
|
// We issue a memory barrier here to make sure that we get good values.
|
|
f.MemoryBarrier();
|
|
|
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
|
Value* rt = f.ByteSwap(f.Load(ea, INT64_TYPE));
|
|
f.StoreReserved(rt);
|
|
f.StoreGPR(i.X.RT, rt);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_lwarx(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + (RB)
|
|
// RESERVE <- 1
|
|
// RESERVE_LENGTH <- 4
|
|
// RESERVE_ADDR <- real_addr(EA)
|
|
// RT <- i32.0 || MEM(EA, 4)
|
|
|
|
// NOTE: we assume we are within a global lock.
|
|
// We could assert here that the block (or its parent) has taken a global lock
|
|
// already, but I haven't see anything but interrupt callbacks (which are
|
|
// always under a global lock) do that yet.
|
|
// We issue a memory barrier here to make sure that we get good values.
|
|
f.MemoryBarrier();
|
|
|
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
|
Value* rt = f.ZeroExtend(f.ByteSwap(f.Load(ea, INT32_TYPE)), INT64_TYPE);
|
|
f.StoreReserved(rt);
|
|
f.StoreGPR(i.X.RT, rt);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_stdcx(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + (RB)
|
|
// RESERVE stuff...
|
|
// MEM(EA, 8) <- (RS)
|
|
// n <- 1 if store performed
|
|
// CR0[LT GT EQ SO] = 0b00 || n || XER[SO]
|
|
|
|
// NOTE: we assume we are within a global lock.
|
|
// As we have been exclusively executing this entire time, we assume that no
|
|
// one else could have possibly touched the memory and must always succeed.
|
|
// We use atomic compare exchange here to support reserved load/store without
|
|
// being under the global lock (flag disable_global_lock - see mtmsr/mtmsrd).
|
|
// This will always succeed if under the global lock, however.
|
|
|
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
|
Value* rt = f.ByteSwap(f.LoadGPR(i.X.RT));
|
|
Value* res = f.ByteSwap(f.LoadReserved());
|
|
Value* v = f.AtomicCompareExchange(ea, res, rt);
|
|
f.StoreContext(offsetof(PPCContext, cr0.cr0_eq), v);
|
|
f.StoreContext(offsetof(PPCContext, cr0.cr0_lt), f.LoadZeroInt8());
|
|
f.StoreContext(offsetof(PPCContext, cr0.cr0_gt), f.LoadZeroInt8());
|
|
|
|
// Issue memory barrier for when we go out of lock and want others to see our
|
|
// updates.
|
|
f.MemoryBarrier();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_stwcx(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + (RB)
|
|
// RESERVE stuff...
|
|
// MEM(EA, 4) <- (RS)[32:63]
|
|
// n <- 1 if store performed
|
|
// CR0[LT GT EQ SO] = 0b00 || n || XER[SO]
|
|
|
|
// NOTE: we assume we are within a global lock.
|
|
// As we have been exclusively executing this entire time, we assume that no
|
|
// one else could have possibly touched the memory and must always succeed.
|
|
// We use atomic compare exchange here to support reserved load/store without
|
|
// being under the global lock (flag disable_global_lock - see mtmsr/mtmsrd).
|
|
// This will always succeed if under the global lock, however.
|
|
|
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
|
Value* rt = f.ByteSwap(f.Truncate(f.LoadGPR(i.X.RT), INT32_TYPE));
|
|
Value* res = f.ByteSwap(f.Truncate(f.LoadReserved(), INT32_TYPE));
|
|
Value* v = f.AtomicCompareExchange(ea, res, rt);
|
|
f.StoreContext(offsetof(PPCContext, cr0.cr0_eq), v);
|
|
f.StoreContext(offsetof(PPCContext, cr0.cr0_lt), f.LoadZeroInt8());
|
|
f.StoreContext(offsetof(PPCContext, cr0.cr0_gt), f.LoadZeroInt8());
|
|
|
|
// Issue memory barrier for when we go out of lock and want others to see our
|
|
// updates.
|
|
f.MemoryBarrier();
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Floating-point load (A-19)
|
|
|
|
int InstrEmit_lfd(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + EXTS(D)
|
|
// FRT <- MEM(EA, 8)
|
|
Value* ea = CalculateEA_0_i(f, i.D.RA, XEEXTS16(i.D.DS));
|
|
Value* rt = f.Cast(f.ByteSwap(f.Load(ea, INT64_TYPE)), FLOAT64_TYPE);
|
|
f.StoreFPR(i.D.RT, rt);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_lfdu(PPCHIRBuilder& f, const InstrData& i) {
|
|
// EA <- (RA) + EXTS(D)
|
|
// FRT <- MEM(EA, 8)
|
|
// RA <- EA
|
|
Value* ea = CalculateEA_i(f, i.D.RA, XEEXTS16(i.D.DS));
|
|
Value* rt = f.Cast(f.ByteSwap(f.Load(ea, INT64_TYPE)), FLOAT64_TYPE);
|
|
f.StoreFPR(i.D.RT, rt);
|
|
StoreEA(f, i.D.RA, ea);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_lfdux(PPCHIRBuilder& f, const InstrData& i) {
|
|
// EA <- (RA) + (RB)
|
|
// FRT <- MEM(EA, 8)
|
|
// RA <- EA
|
|
Value* ea = CalculateEA(f, i.X.RA, i.X.RB);
|
|
Value* rt = f.Cast(f.ByteSwap(f.Load(ea, INT64_TYPE)), FLOAT64_TYPE);
|
|
f.StoreFPR(i.X.RT, rt);
|
|
StoreEA(f, i.X.RA, ea);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_lfdx(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + (RB)
|
|
// FRT <- MEM(EA, 8)
|
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
|
Value* rt = f.Cast(f.ByteSwap(f.Load(ea, INT64_TYPE)), FLOAT64_TYPE);
|
|
f.StoreFPR(i.X.RT, rt);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_lfs(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + EXTS(D)
|
|
// FRT <- DOUBLE(MEM(EA, 4))
|
|
Value* ea = CalculateEA_0_i(f, i.D.RA, XEEXTS16(i.D.DS));
|
|
Value* rt = f.Convert(
|
|
f.Cast(f.ByteSwap(f.Load(ea, INT32_TYPE)), FLOAT32_TYPE), FLOAT64_TYPE);
|
|
f.StoreFPR(i.D.RT, rt);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_lfsu(PPCHIRBuilder& f, const InstrData& i) {
|
|
// EA <- (RA) + EXTS(D)
|
|
// FRT <- DOUBLE(MEM(EA, 4))
|
|
// RA <- EA
|
|
Value* ea = CalculateEA_i(f, i.D.RA, XEEXTS16(i.D.DS));
|
|
Value* rt = f.Convert(
|
|
f.Cast(f.ByteSwap(f.Load(ea, INT32_TYPE)), FLOAT32_TYPE), FLOAT64_TYPE);
|
|
f.StoreFPR(i.D.RT, rt);
|
|
StoreEA(f, i.D.RA, ea);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_lfsux(PPCHIRBuilder& f, const InstrData& i) {
|
|
// EA <- (RA) + (RB)
|
|
// FRT <- DOUBLE(MEM(EA, 4))
|
|
// RA <- EA
|
|
Value* ea = CalculateEA(f, i.X.RA, i.X.RB);
|
|
Value* rt = f.Convert(
|
|
f.Cast(f.ByteSwap(f.Load(ea, INT32_TYPE)), FLOAT32_TYPE), FLOAT64_TYPE);
|
|
f.StoreFPR(i.X.RT, rt);
|
|
StoreEA(f, i.X.RA, ea);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_lfsx(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + (RB)
|
|
// FRT <- DOUBLE(MEM(EA, 4))
|
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
|
Value* rt = f.Convert(
|
|
f.Cast(f.ByteSwap(f.Load(ea, INT32_TYPE)), FLOAT32_TYPE), FLOAT64_TYPE);
|
|
f.StoreFPR(i.X.RT, rt);
|
|
return 0;
|
|
}
|
|
|
|
// Floating-point store (A-20)
|
|
|
|
int InstrEmit_stfd(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + EXTS(D)
|
|
// MEM(EA, 8) <- (FRS)
|
|
Value* ea = CalculateEA_0_i(f, i.D.RA, XEEXTS16(i.D.DS));
|
|
f.Store(ea, f.ByteSwap(f.Cast(f.LoadFPR(i.D.RT), INT64_TYPE)));
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_stfdu(PPCHIRBuilder& f, const InstrData& i) {
|
|
// EA <- (RA) + EXTS(D)
|
|
// MEM(EA, 8) <- (FRS)
|
|
// RA <- EA
|
|
Value* ea = CalculateEA_i(f, i.D.RA, XEEXTS16(i.D.DS));
|
|
f.Store(ea, f.ByteSwap(f.Cast(f.LoadFPR(i.D.RT), INT64_TYPE)));
|
|
StoreEA(f, i.D.RA, ea);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_stfdux(PPCHIRBuilder& f, const InstrData& i) {
|
|
// EA <- (RA) + (RB)
|
|
// MEM(EA, 8) <- (FRS)
|
|
// RA <- EA
|
|
Value* ea = CalculateEA(f, i.X.RA, i.X.RB);
|
|
f.Store(ea, f.ByteSwap(f.Cast(f.LoadFPR(i.X.RT), INT64_TYPE)));
|
|
StoreEA(f, i.X.RA, ea);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_stfdx(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + (RB)
|
|
// MEM(EA, 8) <- (FRS)
|
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
|
f.Store(ea, f.ByteSwap(f.Cast(f.LoadFPR(i.X.RT), INT64_TYPE)));
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_stfiwx(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + (RB)
|
|
// MEM(EA, 4) <- (FRS)[32:63]
|
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
|
f.Store(ea, f.ByteSwap(f.Truncate(f.Cast(f.LoadFPR(i.X.RT), INT64_TYPE),
|
|
INT32_TYPE)));
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_stfs(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + EXTS(D)
|
|
// MEM(EA, 4) <- SINGLE(FRS)
|
|
Value* ea = CalculateEA_0_i(f, i.D.RA, XEEXTS16(i.D.DS));
|
|
f.Store(ea, f.ByteSwap(f.Cast(f.Convert(f.LoadFPR(i.D.RT), FLOAT32_TYPE),
|
|
INT32_TYPE)));
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_stfsu(PPCHIRBuilder& f, const InstrData& i) {
|
|
// EA <- (RA) + EXTS(D)
|
|
// MEM(EA, 4) <- SINGLE(FRS)
|
|
// RA <- EA
|
|
Value* ea = CalculateEA_i(f, i.D.RA, XEEXTS16(i.D.DS));
|
|
f.Store(ea, f.ByteSwap(f.Cast(f.Convert(f.LoadFPR(i.D.RT), FLOAT32_TYPE),
|
|
INT32_TYPE)));
|
|
StoreEA(f, i.D.RA, ea);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_stfsux(PPCHIRBuilder& f, const InstrData& i) {
|
|
// EA <- (RA) + (RB)
|
|
// MEM(EA, 4) <- SINGLE(FRS)
|
|
// RA <- EA
|
|
Value* ea = CalculateEA(f, i.X.RA, i.X.RB);
|
|
f.Store(ea, f.ByteSwap(f.Cast(f.Convert(f.LoadFPR(i.X.RT), FLOAT32_TYPE),
|
|
INT32_TYPE)));
|
|
StoreEA(f, i.X.RA, ea);
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_stfsx(PPCHIRBuilder& f, const InstrData& i) {
|
|
// if RA = 0 then
|
|
// b <- 0
|
|
// else
|
|
// b <- (RA)
|
|
// EA <- b + (RB)
|
|
// MEM(EA, 4) <- SINGLE(FRS)
|
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
|
f.Store(ea, f.ByteSwap(f.Cast(f.Convert(f.LoadFPR(i.X.RT), FLOAT32_TYPE),
|
|
INT32_TYPE)));
|
|
return 0;
|
|
}
|
|
|
|
// Cache management (A-27)
|
|
|
|
int InstrEmit_dcbf(PPCHIRBuilder& f, const InstrData& i) {
|
|
// No-op for now.
|
|
// TODO(benvanik): use prefetch
|
|
// XEINSTRNOTIMPLEMENTED();
|
|
f.Nop();
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_dcbst(PPCHIRBuilder& f, const InstrData& i) {
|
|
// No-op for now.
|
|
// TODO(benvanik): use prefetch
|
|
// XEINSTRNOTIMPLEMENTED();
|
|
f.Nop();
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_dcbt(PPCHIRBuilder& f, const InstrData& i) {
|
|
// No-op for now.
|
|
// TODO(benvanik): use prefetch
|
|
// XEINSTRNOTIMPLEMENTED();
|
|
f.Nop();
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_dcbtst(PPCHIRBuilder& f, const InstrData& i) {
|
|
// No-op for now.
|
|
// TODO(benvanik): use prefetch
|
|
// XEINSTRNOTIMPLEMENTED();
|
|
f.Nop();
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_dcbz(PPCHIRBuilder& f, const InstrData& i) {
|
|
// EA <- (RA) + (RB)
|
|
// memset(EA & ~31, 0, 32)
|
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
|
// dcbz - 32 byte set
|
|
int block_size = 32;
|
|
int address_mask = ~31;
|
|
f.Memset(f.And(ea, f.LoadConstantInt64(address_mask)), f.LoadZeroInt8(),
|
|
f.LoadConstantInt64(block_size));
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_dcbz128(PPCHIRBuilder& f, const InstrData& i) {
|
|
// EA <- (RA) + (RB)
|
|
// memset(EA & ~31, 0, 32)
|
|
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
|
// dcbz128 - 128 byte set
|
|
int block_size = 128;
|
|
int address_mask = ~127;
|
|
f.Memset(f.And(ea, f.LoadConstantInt64(address_mask)), f.LoadZeroInt8(),
|
|
f.LoadConstantInt64(block_size));
|
|
return 0;
|
|
}
|
|
|
|
int InstrEmit_icbi(PPCHIRBuilder& f, const InstrData& i) {
|
|
// XEINSTRNOTIMPLEMENTED();
|
|
f.Nop();
|
|
return 0;
|
|
}
|
|
|
|
void RegisterEmitCategoryMemory() {
|
|
XEREGISTERINSTR(lbz);
|
|
XEREGISTERINSTR(lbzu);
|
|
XEREGISTERINSTR(lbzux);
|
|
XEREGISTERINSTR(lbzx);
|
|
XEREGISTERINSTR(lha);
|
|
XEREGISTERINSTR(lhau);
|
|
XEREGISTERINSTR(lhaux);
|
|
XEREGISTERINSTR(lhax);
|
|
XEREGISTERINSTR(lhz);
|
|
XEREGISTERINSTR(lhzu);
|
|
XEREGISTERINSTR(lhzux);
|
|
XEREGISTERINSTR(lhzx);
|
|
XEREGISTERINSTR(lwa);
|
|
XEREGISTERINSTR(lwaux);
|
|
XEREGISTERINSTR(lwax);
|
|
XEREGISTERINSTR(lwz);
|
|
XEREGISTERINSTR(lwzu);
|
|
XEREGISTERINSTR(lwzux);
|
|
XEREGISTERINSTR(lwzx);
|
|
XEREGISTERINSTR(ld);
|
|
XEREGISTERINSTR(ldu);
|
|
XEREGISTERINSTR(ldux);
|
|
XEREGISTERINSTR(ldx);
|
|
XEREGISTERINSTR(stb);
|
|
XEREGISTERINSTR(stbu);
|
|
XEREGISTERINSTR(stbux);
|
|
XEREGISTERINSTR(stbx);
|
|
XEREGISTERINSTR(sth);
|
|
XEREGISTERINSTR(sthu);
|
|
XEREGISTERINSTR(sthux);
|
|
XEREGISTERINSTR(sthx);
|
|
XEREGISTERINSTR(stw);
|
|
XEREGISTERINSTR(stwu);
|
|
XEREGISTERINSTR(stwux);
|
|
XEREGISTERINSTR(stwx);
|
|
XEREGISTERINSTR(std);
|
|
XEREGISTERINSTR(stdu);
|
|
XEREGISTERINSTR(stdux);
|
|
XEREGISTERINSTR(stdx);
|
|
XEREGISTERINSTR(lhbrx);
|
|
XEREGISTERINSTR(lwbrx);
|
|
XEREGISTERINSTR(ldbrx);
|
|
XEREGISTERINSTR(sthbrx);
|
|
XEREGISTERINSTR(stwbrx);
|
|
XEREGISTERINSTR(stdbrx);
|
|
XEREGISTERINSTR(lmw);
|
|
XEREGISTERINSTR(stmw);
|
|
XEREGISTERINSTR(lswi);
|
|
XEREGISTERINSTR(lswx);
|
|
XEREGISTERINSTR(stswi);
|
|
XEREGISTERINSTR(stswx);
|
|
XEREGISTERINSTR(eieio);
|
|
XEREGISTERINSTR(sync);
|
|
XEREGISTERINSTR(isync);
|
|
XEREGISTERINSTR(ldarx);
|
|
XEREGISTERINSTR(lwarx);
|
|
XEREGISTERINSTR(stdcx);
|
|
XEREGISTERINSTR(stwcx);
|
|
XEREGISTERINSTR(lfd);
|
|
XEREGISTERINSTR(lfdu);
|
|
XEREGISTERINSTR(lfdux);
|
|
XEREGISTERINSTR(lfdx);
|
|
XEREGISTERINSTR(lfs);
|
|
XEREGISTERINSTR(lfsu);
|
|
XEREGISTERINSTR(lfsux);
|
|
XEREGISTERINSTR(lfsx);
|
|
XEREGISTERINSTR(stfd);
|
|
XEREGISTERINSTR(stfdu);
|
|
XEREGISTERINSTR(stfdux);
|
|
XEREGISTERINSTR(stfdx);
|
|
XEREGISTERINSTR(stfiwx);
|
|
XEREGISTERINSTR(stfs);
|
|
XEREGISTERINSTR(stfsu);
|
|
XEREGISTERINSTR(stfsux);
|
|
XEREGISTERINSTR(stfsx);
|
|
XEREGISTERINSTR(dcbf);
|
|
XEREGISTERINSTR(dcbst);
|
|
XEREGISTERINSTR(dcbt);
|
|
XEREGISTERINSTR(dcbtst);
|
|
XEREGISTERINSTR(dcbz);
|
|
XEREGISTERINSTR(dcbz128);
|
|
XEREGISTERINSTR(icbi);
|
|
}
|
|
|
|
} // namespace ppc
|
|
} // namespace cpu
|
|
} // namespace xe
|