diff --git a/TODO.md b/TODO.md index 9ac5a05d1..7d37f2ac5 100644 --- a/TODO.md +++ b/TODO.md @@ -44,92 +44,18 @@ KeBugCheck: ``` rlwimix rldiclx -addcx -addex -addicx -andisx -cntlzdx -dcbf -dcbz -divdux -divdx -divwx -eieio -eqvx -extshx -extswx -fabsx -faddsx -faddx -fcfidx -fcmpu -fctidzx -fctiwzx -fdivsx -fdivx -fmaddsx -fmaddx -fmrx -fmsubsx -fmsubx -fmulsx -fmulx -fnegx -fnmsubsx -fnmsubx -frspx -fselx -fsqrtx -fsubsx -fsubx -ldarx -ldx +lwarx +stwcx lfd lfdx lfs lfsu -lfsux lfsx -lha -lhax -lhzu -lhzx -lwa -lwarx -lwax -lwbrx -lwzux -mftb -mulldx -nandx -negx -orcx -rldiclx -rldicrx -rldimix -rlwnmx -sldx -sradix -sradx -srawx -srdx -srwx -stbx -stdcx -stdx stfd -stfdu -stfdx stfiwx stfs stfsu stfsx -stwbrx -stwcx -stwux -subfcx -subfzex -sync ``` ### XER CA bit (carry) diff --git a/include/xenia/cpu/codegen/function_generator.h b/include/xenia/cpu/codegen/function_generator.h index af2a04ac7..0b48a75c4 100644 --- a/include/xenia/cpu/codegen/function_generator.h +++ b/include/xenia/cpu/codegen/function_generator.h @@ -83,13 +83,16 @@ public: llvm::Value* gpr_value(uint32_t n); void update_gpr_value(uint32_t n, llvm::Value* value); + llvm::Value* fpr_value(uint32_t n); + void update_fpr_value(uint32_t n, llvm::Value* value); llvm::Value* GetMembase(); llvm::Value* GetMemoryAddress(uint32_t cia, llvm::Value* addr); llvm::Value* ReadMemory( - uint32_t cia, llvm::Value* addr, uint32_t size, bool extend); + uint32_t cia, llvm::Value* addr, uint32_t size, bool acquire = false); void WriteMemory( - uint32_t cia, llvm::Value* addr, uint32_t size, llvm::Value* value); + uint32_t cia, llvm::Value* addr, uint32_t size, llvm::Value* value, + bool release = false); private: void GenerateSharedBlocks(); @@ -128,6 +131,7 @@ private: llvm::Value* ctr; llvm::Value* cr[8]; llvm::Value* gpr[32]; + llvm::Value* fpr[32]; } locals_; }; diff --git a/src/cpu/codegen/emit_memory.cc b/src/cpu/codegen/emit_memory.cc index 10a9fca40..386ea54fc 100644 --- a/src/cpu/codegen/emit_memory.cc +++ b/src/cpu/codegen/emit_memory.cc @@ -182,9 +182,34 @@ XEEMITTER(ldx, 0x7C00002A, X )(FunctionGenerator& g, IRBuilder<>& b, I return 1; } +XEDISASMR(lha, 0xA8000000, D )(InstrData& i, InstrDisasm& d) { + d.Init("lha", "Load Halfword Algebraic", 0); + d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kWrite); + if (i.D.RA) { + d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead); + } else { + d.AddUImmOperand(0, 1); + } + d.AddSImmOperand(XEEXTS16(i.D.DS), 2); + return d.Finish(); +} XEEMITTER(lha, 0xA8000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + EXTS(D) + // RT <- EXTS(MEM(EA, 2)) + + Value* ea = b.getInt64(XEEXTS16(i.D.DS)); + if (i.D.RA) { + ea = b.CreateAdd(g.gpr_value(i.D.RA), ea); + } + Value* v = b.CreateSExt(g.ReadMemory(i.address, ea, 2, false), + b.getInt64Ty()); + g.update_gpr_value(i.D.RT, v); + + return 0; } XEEMITTER(lhau, 0xAC000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { @@ -197,9 +222,34 @@ XEEMITTER(lhaux, 0x7C0002EE, X )(FunctionGenerator& g, IRBuilder<>& b, I return 1; } +XEDISASMR(lhax, 0x7C0002AE, X )(InstrData& i, InstrDisasm& d) { + d.Init("lhax", "Load Halfword Algebraic Indexed", 0); + d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite); + if (i.X.RA) { + d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead); + } else { + d.AddUImmOperand(0, 1); + } + d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead); + return d.Finish(); +} XEEMITTER(lhax, 0x7C0002AE, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + (RB) + // RT <- EXTS(MEM(EA, 2)) + + Value* ea = g.gpr_value(i.X.RB); + if (i.X.RA) { + ea = b.CreateAdd(g.gpr_value(i.X.RA), ea); + } + Value* v = b.CreateSExt(g.ReadMemory(i.address, ea, 2, false), + b.getInt64Ty()); + g.update_gpr_value(i.X.RT, v); + + return 0; } XEDISASMR(lhz, 0xA0000000, D )(InstrData& i, InstrDisasm& d) { @@ -231,24 +281,103 @@ XEEMITTER(lhz, 0xA0000000, D )(FunctionGenerator& g, IRBuilder<>& b, I return 0; } +XEDISASMR(lhzu, 0xA4000000, D )(InstrData& i, InstrDisasm& d) { + d.Init("lhzu", "Load Halfword and Zero with Update", 0); + d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kWrite); + d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kReadWrite); + d.AddSImmOperand(XEEXTS16(i.D.DS), 2); + return d.Finish(); +} XEEMITTER(lhzu, 0xA4000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // EA <- (RA) + EXTS(D) + // RT <- i48.0 || MEM(EA, 2) + // RA <- EA + + Value* ea = b.CreateAdd(g.gpr_value(i.D.RA), b.getInt64(XEEXTS16(i.D.DS))); + Value* v = g.ReadMemory(i.address, ea, 2, false); + g.update_gpr_value(i.D.RT, v); + g.update_gpr_value(i.D.RA, ea); + + return 0; } +XEDISASMR(lhzux, 0x7C00026E, X )(InstrData& i, InstrDisasm& d) { + d.Init("lhzux", "Load Halfword and Zero with Update Indexed", 0); + d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite); + d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kReadWrite); + d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead); + return d.Finish(); +} XEEMITTER(lhzux, 0x7C00026E, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // EA <- (RA) + (RB) + // RT <- i48.0 || MEM(EA, 2) + // RA <- EA + + Value* ea = b.CreateAdd(g.gpr_value(i.X.RA), g.gpr_value(i.X.RB)); + Value* v = g.ReadMemory(i.address, ea, 2, false); + g.update_gpr_value(i.X.RT, v); + g.update_gpr_value(i.X.RA, ea); + + return 0; } +XEDISASMR(lhzx, 0x7C00022E, X )(InstrData& i, InstrDisasm& d) { + d.Init("lhzx", "Load Halfword and Zero Indexed", 0); + d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite); + if (i.X.RA) { + d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead); + } else { + d.AddUImmOperand(0, 1); + } + d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead); + return d.Finish(); +} XEEMITTER(lhzx, 0x7C00022E, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + (RB) + // RT <- i48.0 || MEM(EA, 2) + + Value* ea = g.gpr_value(i.X.RB); + if (i.X.RA) { + ea = b.CreateAdd(g.gpr_value(i.X.RA), ea); + } + Value* v = g.ReadMemory(i.address, ea, 2, false); + g.update_gpr_value(i.X.RT, v); + + return 0; } +XEDISASMR(lwa, 0xE8000002, DS )(InstrData& i, InstrDisasm& d) { + d.Init("lwa", "Load Word Algebraic", 0); + d.AddRegOperand(InstrRegister::kGPR, i.DS.RT, InstrRegister::kWrite); + if (i.D.RA) { + d.AddRegOperand(InstrRegister::kGPR, i.DS.RA, InstrRegister::kRead); + } else { + d.AddUImmOperand(0, 1); + } + d.AddSImmOperand(XEEXTS16(i.DS.DS << 2), 2); + return d.Finish(); +} XEEMITTER(lwa, 0xE8000002, DS )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + EXTS(D || 00) + // RT <- EXTS(MEM(EA, 4)) + + Value* ea = b.getInt64(XEEXTS16(i.DS.DS << 2)); + if (i.DS.RA) { + ea = b.CreateAdd(g.gpr_value(i.DS.RA), ea); + } + Value* v = b.CreateSExt(g.ReadMemory(i.address, ea, 4, false), + b.getInt64Ty()); + g.update_gpr_value(i.DS.RT, v); + + return 0; } XEDISASMR(lwaux, 0x7C0002EA, X )(InstrData& i, InstrDisasm& d) { @@ -351,9 +480,24 @@ XEEMITTER(lwzu, 0x84000000, D )(FunctionGenerator& g, IRBuilder<>& b, I return 0; } +XEDISASMR(lwzux, 0x7C00006E, X )(InstrData& i, InstrDisasm& d) { + d.Init("lwzux", "Load Word and Zero with Update Indexed", 0); + d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite); + d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kReadWrite); + d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead); + return d.Finish(); +} XEEMITTER(lwzux, 0x7C00006E, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // EA <- (RA) + (RB) + // RT <- i32.0 || MEM(EA, 4) + // RA <- EA + + Value* ea = b.CreateAdd(g.gpr_value(i.X.RA), g.gpr_value(i.X.RB)); + Value* v = g.ReadMemory(i.address, ea, 4, false); + g.update_gpr_value(i.X.RT, v); + g.update_gpr_value(i.X.RA, ea); + + return 0; } XEDISASMR(lwzx, 0x7C00002E, X )(InstrData& i, InstrDisasm& d) { @@ -536,14 +680,53 @@ XEEMITTER(stdu, 0xF8000001, DS )(FunctionGenerator& g, IRBuilder<>& b, I return 0; } +XEDISASMR(stdux, 0x7C00016A, X )(InstrData& i, InstrDisasm& d) { + d.Init("stdux", "Store Doubleword with Update Indexed", 0); + d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead); + if (i.DS.RA) { + d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead); + } else { + d.AddUImmOperand(0, 1); + } + d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead); + return d.Finish(); +} XEEMITTER(stdux, 0x7C00016A, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + (RB) + // MEM(EA, 8) <- (RS) + + Value* ea = g.gpr_value(i.X.RB); + if (i.X.RA) { + ea = b.CreateAdd(g.gpr_value(i.X.RA), ea); + } + Value* v = g.gpr_value(i.X.RT); + g.WriteMemory(i.address, ea, 8, v); + + return 0; } +XEDISASMR(stdx, 0x7C00012A, X )(InstrData& i, InstrDisasm& d) { + d.Init("stdx", "Store Doubleword Indexed", 0); + d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead); + d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kReadWrite); + d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead); + return d.Finish(); +} XEEMITTER(stdx, 0x7C00012A, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // EA <- (RA) + (RB) + // MEM(EA, 8) <- (RS) + // RA <- EA + + Value* ea = b.CreateAdd(g.gpr_value(i.X.RA), g.gpr_value(i.X.RB)); + Value* v = g.gpr_value(i.X.RT); + g.WriteMemory(i.address, ea, 8, v); + g.update_gpr_value(i.X.RA, ea); + + return 0; } XEDISASMR(sth, 0xB0000000, D )(InstrData& i, InstrDisasm& d) { @@ -831,9 +1014,38 @@ XEEMITTER(ldarx, 0x7C0000A8, X )(FunctionGenerator& g, IRBuilder<>& b, I return 1; } +XEDISASMR(lwarx, 0x7C000028, X )(InstrData& i, InstrDisasm& d) { + d.Init("lwarx", "Load Word And Reserve Indexed", 0); + d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite); + if (i.X.RA) { + d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead); + } else { + d.AddUImmOperand(0, 1); + } + d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead); + return d.Finish(); +} XEEMITTER(lwarx, 0x7C000028, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // 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) + + // TODO(benvanik): make this right + + Value* ea = g.gpr_value(i.X.RB); + if (i.X.RA) { + ea = b.CreateAdd(g.gpr_value(i.X.RA), ea); + } + Value* v = g.ReadMemory(i.address, ea, 4, /* acquire */ true); + g.update_gpr_value(i.X.RT, v); + + return 0; } XEEMITTER(stdcx, 0x7C0001AD, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { @@ -841,9 +1053,40 @@ XEEMITTER(stdcx, 0x7C0001AD, X )(FunctionGenerator& g, IRBuilder<>& b, I return 1; } +XEDISASMR(stwcx, 0x7C00012D, X )(InstrData& i, InstrDisasm& d) { + d.Init("stwcx", "Store Word Conditional Indexed", + InstrDisasm::kRc); + d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead); + if (i.D.RA) { + d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead); + } else { + d.AddUImmOperand(0, 1); + } + d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead); + return d.Finish(); +} XEEMITTER(stwcx, 0x7C00012D, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // 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] + + // TODO(benvanik): make this right + + Value* ea = b.getInt64(XEEXTS16(i.D.DS)); + if (i.D.RA) { + ea = b.CreateAdd(g.gpr_value(i.D.RA), ea); + } + Value* v = g.gpr_value(i.D.RT); + g.WriteMemory(i.address, ea, 4, v, /* release */ true); + // TODO(benvanik): update CR0 + + return 0; } XEEMITTER(sync, 0x7C0004AC, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { @@ -854,92 +1097,447 @@ XEEMITTER(sync, 0x7C0004AC, X )(FunctionGenerator& g, IRBuilder<>& b, I // Floating-point load (A-19) +XEDISASMR(lfd, 0xC8000000, D )(InstrData& i, InstrDisasm& d) { + d.Init("lfd", "Load Floating-Point Double", 0); + d.AddRegOperand(InstrRegister::kFPR, i.D.RT, InstrRegister::kWrite); + if (i.D.RA) { + d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead); + } else { + d.AddUImmOperand(0, 1); + } + d.AddSImmOperand(XEEXTS16(i.D.DS), 2); + return d.Finish(); +} XEEMITTER(lfd, 0xC8000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + EXTS(D) + // FRT <- MEM(EA, 8) + + Value* ea = b.getInt64(XEEXTS16(i.D.DS)); + if (i.D.RA) { + ea = b.CreateAdd(g.gpr_value(i.D.RA), ea); + } + Value* v = g.ReadMemory(i.address, ea, 8, false); + v = b.CreateBitCast(v, b.getDoubleTy()); + g.update_fpr_value(i.D.RT, v); + + return 0; } +XEDISASMR(lfdu, 0xCC000000, D )(InstrData& i, InstrDisasm& d) { + d.Init("lfdu", "Load Floating-Point Double with Update", 0); + d.AddRegOperand(InstrRegister::kFPR, i.D.RT, InstrRegister::kWrite); + d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kReadWrite); + d.AddSImmOperand(XEEXTS16(i.D.DS), 2); + return d.Finish(); +} XEEMITTER(lfdu, 0xCC000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // EA <- (RA) + EXTS(D) + // FRT <- MEM(EA, 8) + // RA <- EA + + Value* ea = b.CreateAdd(g.gpr_value(i.D.RA), b.getInt64(XEEXTS16(i.D.DS))); + Value* v = g.ReadMemory(i.address, ea, 8, false); + v = b.CreateBitCast(v, b.getDoubleTy()); + g.update_fpr_value(i.D.RT, v); + g.update_gpr_value(i.D.RA, ea); + + return 0; } +XEDISASMR(lfdux, 0x7C0004EE, X )(InstrData& i, InstrDisasm& d) { + d.Init("lfdux", "Load Floating-Point Double with Update Indexed", 0); + d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kWrite); + d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kReadWrite); + d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead); + return d.Finish(); +} XEEMITTER(lfdux, 0x7C0004EE, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // EA <- (RA) + (RB) + // FRT <- MEM(EA, 8) + // RA <- EA + + Value* ea = b.CreateAdd(g.gpr_value(i.X.RA), g.gpr_value(i.X.RB)); + Value* v = g.ReadMemory(i.address, ea, 8, false); + v = b.CreateBitCast(v, b.getDoubleTy()); + g.update_fpr_value(i.X.RT, v); + g.update_gpr_value(i.X.RA, ea); + + return 0; } +XEDISASMR(lfdx, 0x7C0004AE, X )(InstrData& i, InstrDisasm& d) { + d.Init("lfdx", "Load Floating-Point Double Indexed", 0); + d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kWrite); + if (i.X.RA) { + d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead); + } else { + d.AddUImmOperand(0, 1); + } + d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead); + return d.Finish(); +} XEEMITTER(lfdx, 0x7C0004AE, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + (RB) + // FRT <- MEM(EA, 8) + + Value* ea = g.gpr_value(i.X.RB); + if (i.X.RA) { + ea = b.CreateAdd(g.gpr_value(i.X.RA), ea); + } + Value* v = g.ReadMemory(i.address, ea, 8, false); + v = b.CreateBitCast(v, b.getDoubleTy()); + g.update_fpr_value(i.X.RT, v); + + return 0; } +XEDISASMR(lfs, 0xC0000000, D )(InstrData& i, InstrDisasm& d) { + d.Init("lfs", "Load Floating-Point Single", 0); + d.AddRegOperand(InstrRegister::kFPR, i.D.RT, InstrRegister::kWrite); + if (i.D.RA) { + d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead); + } else { + d.AddUImmOperand(0, 1); + } + d.AddSImmOperand(XEEXTS16(i.D.DS), 2); + return d.Finish(); +} XEEMITTER(lfs, 0xC0000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + EXTS(D) + // FRT <- DOUBLE(MEM(EA, 4)) + + Value* ea = b.getInt64(XEEXTS16(i.D.DS)); + if (i.D.RA) { + ea = b.CreateAdd(g.gpr_value(i.D.RA), ea); + } + Value* v = g.ReadMemory(i.address, ea, 4, false); + v = b.CreateFPExt(b.CreateBitCast(v, b.getFloatTy()), b.getDoubleTy()); + g.update_fpr_value(i.D.RT, v); + + return 0; } +XEDISASMR(lfsu, 0xC4000000, D )(InstrData& i, InstrDisasm& d) { + d.Init("lfsu", "Load Floating-Point Single with Update", 0); + d.AddRegOperand(InstrRegister::kFPR, i.D.RT, InstrRegister::kWrite); + d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kReadWrite); + d.AddSImmOperand(XEEXTS16(i.D.DS), 2); + return d.Finish(); +} XEEMITTER(lfsu, 0xC4000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // EA <- (RA) + EXTS(D) + // FRT <- DOUBLE(MEM(EA, 4)) + // RA <- EA + + Value* ea = b.CreateAdd(g.gpr_value(i.D.RA), b.getInt64(XEEXTS16(i.D.DS))); + Value* v = g.ReadMemory(i.address, ea, 4, false); + v = b.CreateFPExt(b.CreateBitCast(v, b.getFloatTy()), b.getDoubleTy()); + g.update_fpr_value(i.D.RT, v); + g.update_gpr_value(i.D.RA, ea); + + return 0; } +XEDISASMR(lfsux, 0x7C00046E, X )(InstrData& i, InstrDisasm& d) { + d.Init("lfsux", "Load Floating-Point Single with Update Indexed", 0); + d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kWrite); + d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kReadWrite); + d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead); + return d.Finish(); +} XEEMITTER(lfsux, 0x7C00046E, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // EA <- (RA) + (RB) + // FRT <- DOUBLE(MEM(EA, 4)) + // RA <- EA + + Value* ea = b.CreateAdd(g.gpr_value(i.X.RA), g.gpr_value(i.X.RB)); + Value* v = g.ReadMemory(i.address, ea, 4, false); + v = b.CreateFPExt(b.CreateBitCast(v, b.getFloatTy()), b.getDoubleTy()); + g.update_fpr_value(i.X.RT, v); + g.update_gpr_value(i.X.RA, ea); + + return 0; } +XEDISASMR(lfsx, 0x7C00042E, X )(InstrData& i, InstrDisasm& d) { + d.Init("lfsx", "Load Floating-Point Single Indexed", 0); + d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kWrite); + if (i.X.RA) { + d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead); + } else { + d.AddUImmOperand(0, 1); + } + d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead); + return d.Finish(); +} XEEMITTER(lfsx, 0x7C00042E, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + (RB) + // FRT <- DOUBLE(MEM(EA, 4)) + + Value* ea = g.gpr_value(i.X.RB); + if (i.X.RA) { + ea = b.CreateAdd(g.gpr_value(i.X.RA), ea); + } + Value* v = g.ReadMemory(i.address, ea, 4, false); + v = b.CreateFPExt(b.CreateBitCast(v, b.getFloatTy()), b.getDoubleTy()); + g.update_fpr_value(i.X.RT, v); + + return 0; } // Floating-point store (A-20) +XEDISASMR(stfd, 0xD8000000, D )(InstrData& i, InstrDisasm& d) { + d.Init("stfd", "Store Floating-Point Double", 0); + d.AddRegOperand(InstrRegister::kFPR, i.D.RT, InstrRegister::kRead); + if (i.D.RA) { + d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead); + } else { + d.AddUImmOperand(0, 1); + } + d.AddSImmOperand(XEEXTS16(i.D.DS), 2); + return d.Finish(); +} XEEMITTER(stfd, 0xD8000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + EXTS(D) + // MEM(EA, 8) <- (FRS) + + Value* ea = b.getInt64(XEEXTS16(i.D.DS)); + if (i.D.RA) { + ea = b.CreateAdd(g.gpr_value(i.D.RA), ea); + } + Value* v = g.fpr_value(i.D.RT); + v = b.CreateBitCast(v, b.getInt64Ty()); + g.WriteMemory(i.address, ea, 8, v); + + return 0; } +XEDISASMR(stfdu, 0xDC000000, D )(InstrData& i, InstrDisasm& d) { + d.Init("stfdu", "Store Floating-Point Double with Update", 0); + d.AddRegOperand(InstrRegister::kFPR, i.D.RT, InstrRegister::kRead); + d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kReadWrite); + d.AddSImmOperand(XEEXTS16(i.D.DS), 2); + return d.Finish(); +} XEEMITTER(stfdu, 0xDC000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // EA <- (RA) + EXTS(D) + // MEM(EA, 8) <- (FRS) + // RA <- EA + + Value* ea = b.CreateAdd(g.gpr_value(i.D.RA), + b.getInt64(XEEXTS16(i.D.DS))); + Value* v = g.fpr_value(i.D.RT); + v = b.CreateBitCast(v, b.getInt64Ty()); + g.WriteMemory(i.address, ea, 8, v); + g.update_gpr_value(i.D.RA, ea); + + return 0; } +XEDISASMR(stfdux, 0x7C0005EE, X )(InstrData& i, InstrDisasm& d) { + d.Init("stfdux", "Store Floating-Point Double with Update Indexed", 0); + d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kRead); + d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kReadWrite); + d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead); + return d.Finish(); +} XEEMITTER(stfdux, 0x7C0005EE, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // EA <- (RA) + (RB) + // MEM(EA, 8) <- (FRS) + // RA <- EA + + Value* ea = b.CreateAdd(g.gpr_value(i.X.RA), g.gpr_value(i.X.RB)); + Value* v = g.fpr_value(i.X.RT); + v = b.CreateBitCast(v, b.getInt64Ty()); + g.WriteMemory(i.address, ea, 8, v); + g.update_gpr_value(i.X.RA, ea); + + return 0; } +XEDISASMR(stfdx, 0x7C0005AE, X )(InstrData& i, InstrDisasm& d) { + d.Init("stfdx", "Store Floating-Point Double Indexed", 0); + d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kRead); + if (i.X.RA) { + d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead); + } else { + d.AddUImmOperand(0, 1); + } + d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead); + return d.Finish(); +} XEEMITTER(stfdx, 0x7C0005AE, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + (RB) + // MEM(EA, 8) <- (FRS) + + Value* ea = g.gpr_value(i.X.RB); + if (i.X.RA) { + ea = b.CreateAdd(g.gpr_value(i.X.RA), ea); + } + Value* v = g.fpr_value(i.X.RT); + v = b.CreateBitCast(v, b.getInt64Ty()); + g.WriteMemory(i.address, ea, 8, v); + + return 0; } +XEDISASMR(stfiwx, 0x7C0007AE, X )(InstrData& i, InstrDisasm& d) { + d.Init("stfiwx", "Store Floating-Point as Integer Word Indexed", 0); + d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kRead); + if (i.X.RA) { + d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead); + } else { + d.AddUImmOperand(0, 1); + } + d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead); + return d.Finish(); +} XEEMITTER(stfiwx, 0x7C0007AE, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + (RB) + // MEM(EA, 4) <- (FRS)[32:63] + + Value* ea = g.gpr_value(i.X.RB); + if (i.X.RA) { + ea = b.CreateAdd(g.gpr_value(i.D.RA), ea); + } + Value* v = g.fpr_value(i.X.RT); + v = b.CreateBitCast(v, b.getInt64Ty()); + g.WriteMemory(i.address, ea, 4, v); + + return 0; } +XEDISASMR(stfs, 0xD0000000, D )(InstrData& i, InstrDisasm& d) { + d.Init("stfs", "Store Floating-Point Single", 0); + d.AddRegOperand(InstrRegister::kFPR, i.D.RT, InstrRegister::kRead); + if (i.D.RA) { + d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead); + } else { + d.AddUImmOperand(0, 1); + } + d.AddSImmOperand(XEEXTS16(i.D.DS), 2); + return d.Finish(); +} XEEMITTER(stfs, 0xD0000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + EXTS(D) + // MEM(EA, 4) <- SINGLE(FRS) + + Value* ea = b.getInt64(XEEXTS16(i.D.DS)); + if (i.D.RA) { + ea = b.CreateAdd(g.gpr_value(i.D.RA), ea); + } + Value* v = g.fpr_value(i.D.RT); + v = b.CreateBitCast(b.CreateFPTrunc(v, b.getFloatTy()), b.getInt32Ty()); + g.WriteMemory(i.address, ea, 4, v); + + return 0; } +XEDISASMR(stfsu, 0xD4000000, D )(InstrData& i, InstrDisasm& d) { + d.Init("stfsu", "Store Floating-Point Single with Update", 0); + d.AddRegOperand(InstrRegister::kFPR, i.D.RT, InstrRegister::kRead); + d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kReadWrite); + d.AddSImmOperand(XEEXTS16(i.D.DS), 2); + return d.Finish(); +} XEEMITTER(stfsu, 0xD4000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // EA <- (RA) + EXTS(D) + // MEM(EA, 4) <- SINGLE(FRS) + // RA <- EA + + Value* ea = b.CreateAdd(g.gpr_value(i.D.RA), + b.getInt64(XEEXTS16(i.D.DS))); + Value* v = g.fpr_value(i.D.RT); + v = b.CreateBitCast(b.CreateFPTrunc(v, b.getFloatTy()), b.getInt32Ty()); + g.WriteMemory(i.address, ea, 4, v); + g.update_gpr_value(i.D.RA, ea); + + return 0; } +XEDISASMR(stfsux, 0x7C00056E, X )(InstrData& i, InstrDisasm& d) { + d.Init("stfsux", "Store Floating-Point Single with Update Indexed", 0); + d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kRead); + d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kReadWrite); + d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead); + return d.Finish(); +} XEEMITTER(stfsux, 0x7C00056E, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // EA <- (RA) + (RB) + // MEM(EA, 4) <- SINGLE(FRS) + // RA <- EA + + Value* ea = b.CreateAdd(g.gpr_value(i.X.RA), g.gpr_value(i.X.RB)); + Value* v = g.fpr_value(i.X.RT); + v = b.CreateBitCast(b.CreateFPTrunc(v, b.getFloatTy()), b.getInt32Ty()); + g.WriteMemory(i.address, ea, 4, v); + g.update_gpr_value(i.X.RA, ea); + + return 0; } +XEDISASMR(stfsx, 0x7C00052E, X )(InstrData& i, InstrDisasm& d) { + d.Init("stfsx", "Store Floating-Point Single Indexed", 0); + d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kRead); + if (i.X.RA) { + d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead); + } else { + d.AddUImmOperand(0, 1); + } + d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead); + return d.Finish(); +} XEEMITTER(stfsx, 0x7C00052E, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + // if RA = 0 then + // b <- 0 + // else + // b <- (RA) + // EA <- b + (RB) + // MEM(EA, 4) <- SINGLE(FRS) + + Value* ea = g.gpr_value(i.X.RB); + if (i.X.RA) { + ea = b.CreateAdd(g.gpr_value(i.X.RA), ea); + } + Value* v = g.fpr_value(i.X.RT); + v = b.CreateBitCast(b.CreateFPTrunc(v, b.getFloatTy()), b.getInt32Ty()); + g.WriteMemory(i.address, ea, 4, v); + + return 0; } @@ -998,36 +1596,36 @@ void RegisterEmitCategoryMemory() { XEREGISTERINSTR(ldu, 0xE8000001); XEREGISTEREMITTER(ldux, 0x7C00006A); XEREGISTEREMITTER(ldx, 0x7C00002A); - XEREGISTEREMITTER(lha, 0xA8000000); + XEREGISTERINSTR(lha, 0xA8000000); XEREGISTEREMITTER(lhau, 0xAC000000); XEREGISTEREMITTER(lhaux, 0x7C0002EE); - XEREGISTEREMITTER(lhax, 0x7C0002AE); + XEREGISTERINSTR(lhax, 0x7C0002AE); XEREGISTERINSTR(lhz, 0xA0000000); - XEREGISTEREMITTER(lhzu, 0xA4000000); - XEREGISTEREMITTER(lhzux, 0x7C00026E); - XEREGISTEREMITTER(lhzx, 0x7C00022E); - XEREGISTEREMITTER(lwa, 0xE8000002); - XEREGISTEREMITTER(lwaux, 0x7C0002EA); - XEREGISTEREMITTER(lwax, 0x7C0002AA); + XEREGISTERINSTR(lhzu, 0xA4000000); + XEREGISTERINSTR(lhzux, 0x7C00026E); + XEREGISTERINSTR(lhzx, 0x7C00022E); + XEREGISTERINSTR(lwa, 0xE8000002); + XEREGISTERINSTR(lwaux, 0x7C0002EA); + XEREGISTERINSTR(lwax, 0x7C0002AA); XEREGISTERINSTR(lwz, 0x80000000); XEREGISTERINSTR(lwzu, 0x84000000); - XEREGISTEREMITTER(lwzux, 0x7C00006E); + XEREGISTERINSTR(lwzux, 0x7C00006E); XEREGISTERINSTR(lwzx, 0x7C00002E); XEREGISTERINSTR(stb, 0x98000000); XEREGISTERINSTR(stbu, 0x9C000000); - XEREGISTEREMITTER(stbux, 0x7C0001EE); - XEREGISTEREMITTER(stbx, 0x7C0001AE); + XEREGISTERINSTR(stbux, 0x7C0001EE); + XEREGISTERINSTR(stbx, 0x7C0001AE); XEREGISTERINSTR(std, 0xF8000000); XEREGISTERINSTR(stdu, 0xF8000001); - XEREGISTEREMITTER(stdux, 0x7C00016A); - XEREGISTEREMITTER(stdx, 0x7C00012A); + XEREGISTERINSTR(stdux, 0x7C00016A); + XEREGISTERINSTR(stdx, 0x7C00012A); XEREGISTERINSTR(sth, 0xB0000000); XEREGISTERINSTR(sthu, 0xB4000000); - XEREGISTEREMITTER(sthux, 0x7C00036E); + XEREGISTERINSTR(sthux, 0x7C00036E); XEREGISTERINSTR(sthx, 0x7C00032E); XEREGISTERINSTR(stw, 0x90000000); XEREGISTERINSTR(stwu, 0x94000000); - XEREGISTEREMITTER(stwux, 0x7C00016E); + XEREGISTERINSTR(stwux, 0x7C00016E); XEREGISTERINSTR(stwx, 0x7C00012E); XEREGISTEREMITTER(lhbrx, 0x7C00062C); XEREGISTEREMITTER(lwbrx, 0x7C00042C); @@ -1044,27 +1642,27 @@ void RegisterEmitCategoryMemory() { XEREGISTEREMITTER(eieio, 0x7C0006AC); XEREGISTEREMITTER(isync, 0x4C00012C); XEREGISTEREMITTER(ldarx, 0x7C0000A8); - XEREGISTEREMITTER(lwarx, 0x7C000028); + XEREGISTERINSTR(lwarx, 0x7C000028); XEREGISTEREMITTER(stdcx, 0x7C0001AD); - XEREGISTEREMITTER(stwcx, 0x7C00012D); + XEREGISTERINSTR(stwcx, 0x7C00012D); XEREGISTEREMITTER(sync, 0x7C0004AC); - XEREGISTEREMITTER(lfd, 0xC8000000); - XEREGISTEREMITTER(lfdu, 0xCC000000); - XEREGISTEREMITTER(lfdux, 0x7C0004EE); - XEREGISTEREMITTER(lfdx, 0x7C0004AE); - XEREGISTEREMITTER(lfs, 0xC0000000); - XEREGISTEREMITTER(lfsu, 0xC4000000); - XEREGISTEREMITTER(lfsux, 0x7C00046E); - XEREGISTEREMITTER(lfsx, 0x7C00042E); - XEREGISTEREMITTER(stfd, 0xD8000000); - XEREGISTEREMITTER(stfdu, 0xDC000000); - XEREGISTEREMITTER(stfdux, 0x7C0005EE); - XEREGISTEREMITTER(stfdx, 0x7C0005AE); - XEREGISTEREMITTER(stfiwx, 0x7C0007AE); - XEREGISTEREMITTER(stfs, 0xD0000000); - XEREGISTEREMITTER(stfsu, 0xD4000000); - XEREGISTEREMITTER(stfsux, 0x7C00056E); - XEREGISTEREMITTER(stfsx, 0x7C00052E); + XEREGISTERINSTR(lfd, 0xC8000000); + XEREGISTERINSTR(lfdu, 0xCC000000); + XEREGISTERINSTR(lfdux, 0x7C0004EE); + XEREGISTERINSTR(lfdx, 0x7C0004AE); + XEREGISTERINSTR(lfs, 0xC0000000); + XEREGISTERINSTR(lfsu, 0xC4000000); + XEREGISTERINSTR(lfsux, 0x7C00046E); + XEREGISTERINSTR(lfsx, 0x7C00042E); + XEREGISTERINSTR(stfd, 0xD8000000); + XEREGISTERINSTR(stfdu, 0xDC000000); + XEREGISTERINSTR(stfdux, 0x7C0005EE); + XEREGISTERINSTR(stfdx, 0x7C0005AE); + XEREGISTERINSTR(stfiwx, 0x7C0007AE); + XEREGISTERINSTR(stfs, 0xD0000000); + XEREGISTERINSTR(stfsu, 0xD4000000); + XEREGISTERINSTR(stfsux, 0x7C00056E); + XEREGISTERINSTR(stfsx, 0x7C00052E); XEREGISTEREMITTER(dcbf, 0x7C0000AC); XEREGISTEREMITTER(dcbst, 0x7C00006C); XEREGISTERINSTR(dcbt, 0x7C00022C); diff --git a/src/cpu/codegen/function_generator.cc b/src/cpu/codegen/function_generator.cc index b3bb30e71..34f8ec779 100644 --- a/src/cpu/codegen/function_generator.cc +++ b/src/cpu/codegen/function_generator.cc @@ -77,6 +77,9 @@ FunctionGenerator::FunctionGenerator( for (size_t n = 0; n < XECOUNT(locals_.gpr); n++) { locals_.gpr[n] = NULL; } + for (size_t n = 0; n < XECOUNT(locals_.fpr); n++) { + locals_.fpr[n] = NULL; + } if (FLAGS_log_codegen) { printf("%s:\n", fn->name()); @@ -548,6 +551,15 @@ void FunctionGenerator::SetupLocals() { } gpr_t >>= 2; } + + uint64_t fpr_t = access_bits_.fpr; + for (int n = 0; n < 32; n++) { + if (fpr_t & 3) { + xesnprintfa(name, XECOUNT(name), "f%d", n); + locals_.fpr[n] = SetupLocal(b.getDoubleTy(), name); + } + fpr_t >>= 2; + } } Value* FunctionGenerator::SetupLocal(llvm::Type* type, const char* name) { @@ -611,7 +623,6 @@ void FunctionGenerator::FillRegisters() { b.getInt8Ty()), cr_n); } - // Note that we skip zero. for (size_t n = 0; n < XECOUNT(locals_.gpr); n++) { if (locals_.gpr[n]) { b.CreateStore(LoadStateValue( @@ -619,6 +630,14 @@ void FunctionGenerator::FillRegisters() { b.getInt64Ty()), locals_.gpr[n]); } } + + for (size_t n = 0; n < XECOUNT(locals_.fpr); n++) { + if (locals_.fpr[n]) { + b.CreateStore(LoadStateValue( + offsetof(xe_ppc_state_t, f) + 8 * n, + b.getDoubleTy()), locals_.fpr[n]); + } + } } void FunctionGenerator::SpillRegisters() { @@ -672,7 +691,6 @@ void FunctionGenerator::SpillRegisters() { cr); } - // Note that we skip zero. for (uint32_t n = 0; n < XECOUNT(locals_.gpr); n++) { Value* v = locals_.gpr[n]; if (v) { @@ -682,6 +700,16 @@ void FunctionGenerator::SpillRegisters() { b.CreateLoad(locals_.gpr[n])); } } + + for (uint32_t n = 0; n < XECOUNT(locals_.fpr); n++) { + Value* v = locals_.fpr[n]; + if (v) { + StoreStateValue( + offsetof(xe_ppc_state_t, f) + 8 * n, + b.getDoubleTy(), + b.CreateLoad(locals_.fpr[n])); + } + } } Value* FunctionGenerator::xer_value() { @@ -879,6 +907,21 @@ void FunctionGenerator::update_gpr_value(uint32_t n, Value* value) { b.CreateStore(value, locals_.gpr[n]); } +Value* FunctionGenerator::fpr_value(uint32_t n) { + XEASSERT(n >= 0 && n < 32); + XEASSERTNOTNULL(locals_.fpr[n]); + IRBuilder<>& b = *builder_; + return b.CreateLoad(locals_.fpr[n]); +} + +void FunctionGenerator::update_fpr_value(uint32_t n, Value* value) { + XEASSERT(n >= 0 && n < 32); + XEASSERTNOTNULL(locals_.fpr[n]); + IRBuilder<>& b = *builder_; + value = b.CreateFPExtOrFPTrunc(value, b.getDoubleTy()); + b.CreateStore(value, locals_.fpr[n]); +} + Value* FunctionGenerator::GetMembase() { Value* v = gen_module_->getGlobalVariable("xe_memory_base"); return builder_->CreateLoad(v); @@ -916,7 +959,7 @@ Value* FunctionGenerator::GetMemoryAddress(uint32_t cia, Value* addr) { } Value* FunctionGenerator::ReadMemory( - uint32_t cia, Value* addr, uint32_t size, bool extend) { + uint32_t cia, Value* addr, uint32_t size, bool acquire) { IRBuilder<>& b = *builder_; Type* dataTy = NULL; @@ -945,7 +988,13 @@ Value* FunctionGenerator::ReadMemory( Value* address = GetMemoryAddress(cia, addr); Value* ptr = b.CreatePointerCast(address, pointerTy); - Value* value = b.CreateLoad(ptr); + LoadInst* load_value = b.CreateLoad(ptr); + if (acquire) { + load_value->setAlignment(size); + load_value->setVolatile(true); + load_value->setAtomic(Acquire); + } + Value* value = load_value; // Swap after loading. // TODO(benvanik): find a way to avoid this! @@ -959,7 +1008,7 @@ Value* FunctionGenerator::ReadMemory( } void FunctionGenerator::WriteMemory( - uint32_t cia, Value* addr, uint32_t size, Value* value) { + uint32_t cia, Value* addr, uint32_t size, Value* value, bool release) { IRBuilder<>& b = *builder_; Type* dataTy = NULL; @@ -1002,5 +1051,10 @@ void FunctionGenerator::WriteMemory( value = b.CreateCall(bswap, value); } - b.CreateStore(value, ptr); + StoreInst* store_value = b.CreateStore(value, ptr); + if (release) { + store_value->setAlignment(size); + store_value->setVolatile(true); + store_value->setAtomic(Release); + } }