diff options
author | Jacob Bramley <jacob.bramley@arm.com> | 2020-10-30 18:25:43 +0000 |
---|---|---|
committer | Jacob Bramley <jacob.bramley@arm.com> | 2020-11-05 14:34:47 +0000 |
commit | c4ef66e95e71f13cb4f1d2983d401fe49bdcc0a7 (patch) | |
tree | 7d1be638b0813c5a1358f528626046411567a339 /src | |
parent | f73036bad9bdb8c853d783c7f94be1f298cb508d (diff) | |
download | vixl-c4ef66e95e71f13cb4f1d2983d401fe49bdcc0a7.tar.gz |
Make the stack size configurable.
Also fix the implementation of stack guards, and make these configurable
too.
Change-Id: Ic62ee326ed725616322ca8fa26d38b9a089d5043
Diffstat (limited to 'src')
-rw-r--r-- | src/aarch64/logic-aarch64.cc | 160 | ||||
-rw-r--r-- | src/aarch64/simulator-aarch64.cc | 205 | ||||
-rw-r--r-- | src/aarch64/simulator-aarch64.h | 382 |
3 files changed, 398 insertions, 349 deletions
diff --git a/src/aarch64/logic-aarch64.cc b/src/aarch64/logic-aarch64.cc index 821c1db9..cb82f715 100644 --- a/src/aarch64/logic-aarch64.cc +++ b/src/aarch64/logic-aarch64.cc @@ -170,7 +170,7 @@ SimFloat16 Simulator::UFixedToFloat16(uint64_t src, void Simulator::ld1(VectorFormat vform, LogicVRegister dst, uint64_t addr) { dst.ClearForWrite(vform); for (int i = 0; i < LaneCountFromFormat(vform); i++) { - dst.ReadUintFromMem(vform, i, addr); + LoadLane(dst, vform, i, addr); addr += LaneSizeInBytesFromFormat(vform); } } @@ -180,7 +180,7 @@ void Simulator::ld1(VectorFormat vform, LogicVRegister dst, int index, uint64_t addr) { - dst.ReadUintFromMem(vform, index, addr); + LoadLane(dst, vform, index, addr); } @@ -189,13 +189,13 @@ void Simulator::ld1r(VectorFormat vform, LogicVRegister dst, uint64_t addr, bool is_signed) { - unsigned unpack_size = LaneSizeInBitsFromFormat(unpack_vform); + unsigned unpack_size = LaneSizeInBytesFromFormat(unpack_vform); dst.ClearForWrite(vform); for (int i = 0; i < LaneCountFromFormat(vform); i++) { if (is_signed) { - dst.ReadIntFromMem(vform, unpack_size, i, addr); + LoadIntToLane(dst, vform, unpack_size, i, addr); } else { - dst.ReadUintFromMem(vform, unpack_size, i, addr); + LoadUintToLane(dst, vform, unpack_size, i, addr); } } } @@ -215,8 +215,8 @@ void Simulator::ld2(VectorFormat vform, int esize = LaneSizeInBytesFromFormat(vform); uint64_t addr2 = addr1 + esize; for (int i = 0; i < LaneCountFromFormat(vform); i++) { - dst1.ReadUintFromMem(vform, i, addr1); - dst2.ReadUintFromMem(vform, i, addr2); + LoadLane(dst1, vform, i, addr1); + LoadLane(dst2, vform, i, addr2); addr1 += 2 * esize; addr2 += 2 * esize; } @@ -231,8 +231,8 @@ void Simulator::ld2(VectorFormat vform, dst1.ClearForWrite(vform); dst2.ClearForWrite(vform); uint64_t addr2 = addr1 + LaneSizeInBytesFromFormat(vform); - dst1.ReadUintFromMem(vform, index, addr1); - dst2.ReadUintFromMem(vform, index, addr2); + LoadLane(dst1, vform, index, addr1); + LoadLane(dst2, vform, index, addr2); } @@ -244,8 +244,8 @@ void Simulator::ld2r(VectorFormat vform, dst2.ClearForWrite(vform); uint64_t addr2 = addr + LaneSizeInBytesFromFormat(vform); for (int i = 0; i < LaneCountFromFormat(vform); i++) { - dst1.ReadUintFromMem(vform, i, addr); - dst2.ReadUintFromMem(vform, i, addr2); + LoadLane(dst1, vform, i, addr); + LoadLane(dst2, vform, i, addr2); } } @@ -262,9 +262,9 @@ void Simulator::ld3(VectorFormat vform, uint64_t addr2 = addr1 + esize; uint64_t addr3 = addr2 + esize; for (int i = 0; i < LaneCountFromFormat(vform); i++) { - dst1.ReadUintFromMem(vform, i, addr1); - dst2.ReadUintFromMem(vform, i, addr2); - dst3.ReadUintFromMem(vform, i, addr3); + LoadLane(dst1, vform, i, addr1); + LoadLane(dst2, vform, i, addr2); + LoadLane(dst3, vform, i, addr3); addr1 += 3 * esize; addr2 += 3 * esize; addr3 += 3 * esize; @@ -283,9 +283,9 @@ void Simulator::ld3(VectorFormat vform, dst3.ClearForWrite(vform); uint64_t addr2 = addr1 + LaneSizeInBytesFromFormat(vform); uint64_t addr3 = addr2 + LaneSizeInBytesFromFormat(vform); - dst1.ReadUintFromMem(vform, index, addr1); - dst2.ReadUintFromMem(vform, index, addr2); - dst3.ReadUintFromMem(vform, index, addr3); + LoadLane(dst1, vform, index, addr1); + LoadLane(dst2, vform, index, addr2); + LoadLane(dst3, vform, index, addr3); } @@ -300,9 +300,9 @@ void Simulator::ld3r(VectorFormat vform, uint64_t addr2 = addr + LaneSizeInBytesFromFormat(vform); uint64_t addr3 = addr2 + LaneSizeInBytesFromFormat(vform); for (int i = 0; i < LaneCountFromFormat(vform); i++) { - dst1.ReadUintFromMem(vform, i, addr); - dst2.ReadUintFromMem(vform, i, addr2); - dst3.ReadUintFromMem(vform, i, addr3); + LoadLane(dst1, vform, i, addr); + LoadLane(dst2, vform, i, addr2); + LoadLane(dst3, vform, i, addr3); } } @@ -322,10 +322,10 @@ void Simulator::ld4(VectorFormat vform, uint64_t addr3 = addr2 + esize; uint64_t addr4 = addr3 + esize; for (int i = 0; i < LaneCountFromFormat(vform); i++) { - dst1.ReadUintFromMem(vform, i, addr1); - dst2.ReadUintFromMem(vform, i, addr2); - dst3.ReadUintFromMem(vform, i, addr3); - dst4.ReadUintFromMem(vform, i, addr4); + LoadLane(dst1, vform, i, addr1); + LoadLane(dst2, vform, i, addr2); + LoadLane(dst3, vform, i, addr3); + LoadLane(dst4, vform, i, addr4); addr1 += 4 * esize; addr2 += 4 * esize; addr3 += 4 * esize; @@ -348,10 +348,10 @@ void Simulator::ld4(VectorFormat vform, uint64_t addr2 = addr1 + LaneSizeInBytesFromFormat(vform); uint64_t addr3 = addr2 + LaneSizeInBytesFromFormat(vform); uint64_t addr4 = addr3 + LaneSizeInBytesFromFormat(vform); - dst1.ReadUintFromMem(vform, index, addr1); - dst2.ReadUintFromMem(vform, index, addr2); - dst3.ReadUintFromMem(vform, index, addr3); - dst4.ReadUintFromMem(vform, index, addr4); + LoadLane(dst1, vform, index, addr1); + LoadLane(dst2, vform, index, addr2); + LoadLane(dst3, vform, index, addr3); + LoadLane(dst4, vform, index, addr4); } @@ -369,17 +369,17 @@ void Simulator::ld4r(VectorFormat vform, uint64_t addr3 = addr2 + LaneSizeInBytesFromFormat(vform); uint64_t addr4 = addr3 + LaneSizeInBytesFromFormat(vform); for (int i = 0; i < LaneCountFromFormat(vform); i++) { - dst1.ReadUintFromMem(vform, i, addr); - dst2.ReadUintFromMem(vform, i, addr2); - dst3.ReadUintFromMem(vform, i, addr3); - dst4.ReadUintFromMem(vform, i, addr4); + LoadLane(dst1, vform, i, addr); + LoadLane(dst2, vform, i, addr2); + LoadLane(dst3, vform, i, addr3); + LoadLane(dst4, vform, i, addr4); } } void Simulator::st1(VectorFormat vform, LogicVRegister src, uint64_t addr) { for (int i = 0; i < LaneCountFromFormat(vform); i++) { - src.WriteUintToMem(vform, i, addr); + StoreLane(src, vform, i, addr); addr += LaneSizeInBytesFromFormat(vform); } } @@ -389,19 +389,19 @@ void Simulator::st1(VectorFormat vform, LogicVRegister src, int index, uint64_t addr) { - src.WriteUintToMem(vform, index, addr); + StoreLane(src, vform, index, addr); } void Simulator::st2(VectorFormat vform, - LogicVRegister dst, - LogicVRegister dst2, + LogicVRegister src, + LogicVRegister src2, uint64_t addr) { int esize = LaneSizeInBytesFromFormat(vform); uint64_t addr2 = addr + esize; for (int i = 0; i < LaneCountFromFormat(vform); i++) { - dst.WriteUintToMem(vform, i, addr); - dst2.WriteUintToMem(vform, i, addr2); + StoreLane(src, vform, i, addr); + StoreLane(src2, vform, i, addr2); addr += 2 * esize; addr2 += 2 * esize; } @@ -409,28 +409,28 @@ void Simulator::st2(VectorFormat vform, void Simulator::st2(VectorFormat vform, - LogicVRegister dst, - LogicVRegister dst2, + LogicVRegister src, + LogicVRegister src2, int index, uint64_t addr) { int esize = LaneSizeInBytesFromFormat(vform); - dst.WriteUintToMem(vform, index, addr); - dst2.WriteUintToMem(vform, index, addr + 1 * esize); + StoreLane(src, vform, index, addr); + StoreLane(src2, vform, index, addr + 1 * esize); } void Simulator::st3(VectorFormat vform, - LogicVRegister dst, - LogicVRegister dst2, - LogicVRegister dst3, + LogicVRegister src, + LogicVRegister src2, + LogicVRegister src3, uint64_t addr) { int esize = LaneSizeInBytesFromFormat(vform); uint64_t addr2 = addr + esize; uint64_t addr3 = addr2 + esize; for (int i = 0; i < LaneCountFromFormat(vform); i++) { - dst.WriteUintToMem(vform, i, addr); - dst2.WriteUintToMem(vform, i, addr2); - dst3.WriteUintToMem(vform, i, addr3); + StoreLane(src, vform, i, addr); + StoreLane(src2, vform, i, addr2); + StoreLane(src3, vform, i, addr3); addr += 3 * esize; addr2 += 3 * esize; addr3 += 3 * esize; @@ -439,33 +439,33 @@ void Simulator::st3(VectorFormat vform, void Simulator::st3(VectorFormat vform, - LogicVRegister dst, - LogicVRegister dst2, - LogicVRegister dst3, + LogicVRegister src, + LogicVRegister src2, + LogicVRegister src3, int index, uint64_t addr) { int esize = LaneSizeInBytesFromFormat(vform); - dst.WriteUintToMem(vform, index, addr); - dst2.WriteUintToMem(vform, index, addr + 1 * esize); - dst3.WriteUintToMem(vform, index, addr + 2 * esize); + StoreLane(src, vform, index, addr); + StoreLane(src2, vform, index, addr + 1 * esize); + StoreLane(src3, vform, index, addr + 2 * esize); } void Simulator::st4(VectorFormat vform, - LogicVRegister dst, - LogicVRegister dst2, - LogicVRegister dst3, - LogicVRegister dst4, + LogicVRegister src, + LogicVRegister src2, + LogicVRegister src3, + LogicVRegister src4, uint64_t addr) { int esize = LaneSizeInBytesFromFormat(vform); uint64_t addr2 = addr + esize; uint64_t addr3 = addr2 + esize; uint64_t addr4 = addr3 + esize; for (int i = 0; i < LaneCountFromFormat(vform); i++) { - dst.WriteUintToMem(vform, i, addr); - dst2.WriteUintToMem(vform, i, addr2); - dst3.WriteUintToMem(vform, i, addr3); - dst4.WriteUintToMem(vform, i, addr4); + StoreLane(src, vform, i, addr); + StoreLane(src2, vform, i, addr2); + StoreLane(src3, vform, i, addr3); + StoreLane(src4, vform, i, addr4); addr += 4 * esize; addr2 += 4 * esize; addr3 += 4 * esize; @@ -475,17 +475,17 @@ void Simulator::st4(VectorFormat vform, void Simulator::st4(VectorFormat vform, - LogicVRegister dst, - LogicVRegister dst2, - LogicVRegister dst3, - LogicVRegister dst4, + LogicVRegister src, + LogicVRegister src2, + LogicVRegister src3, + LogicVRegister src4, int index, uint64_t addr) { int esize = LaneSizeInBytesFromFormat(vform); - dst.WriteUintToMem(vform, index, addr); - dst2.WriteUintToMem(vform, index, addr + 1 * esize); - dst3.WriteUintToMem(vform, index, addr + 2 * esize); - dst4.WriteUintToMem(vform, index, addr + 3 * esize); + StoreLane(src, vform, index, addr); + StoreLane(src2, vform, index, addr + 1 * esize); + StoreLane(src3, vform, index, addr + 2 * esize); + StoreLane(src4, vform, index, addr + 3 * esize); } @@ -7019,7 +7019,7 @@ void Simulator::SVEStructuredStoreHelper(VectorFormat vform, for (int r = 0; r < reg_count; r++) { uint64_t element_address = addr.GetElementAddress(i, r); - zt[r].WriteUintToMem(unpack_vform, i << unpack_shift, element_address); + StoreLane(zt[r], unpack_vform, i << unpack_shift, element_address); } } @@ -7068,9 +7068,6 @@ void Simulator::SVEStructuredLoadHelper(VectorFormat vform, ReadVRegister(zt_codes[3]), }; - VectorFormat unpack_vform = - SVEFormatFromLaneSizeInBytesLog2(msize_in_bytes_log2); - for (int i = 0; i < LaneCountFromFormat(vform); i++) { for (int r = 0; r < reg_count; r++) { uint64_t element_address = addr.GetElementAddress(i, r); @@ -7081,16 +7078,9 @@ void Simulator::SVEStructuredLoadHelper(VectorFormat vform, } if (is_signed) { - zt[r].ReadIntFromMem(vform, - LaneSizeInBitsFromFormat(unpack_vform), - i, - element_address); - + LoadIntToLane(zt[r], vform, msize_in_bytes, i, element_address); } else { - zt[r].ReadUintFromMem(vform, - LaneSizeInBitsFromFormat(unpack_vform), - i, - element_address); + LoadUintToLane(zt[r], vform, msize_in_bytes, i, element_address); } } } @@ -7216,7 +7206,7 @@ void Simulator::SVEFaultTolerantLoadHelper(VectorFormat vform, // First-faulting loads always load the first active element, regardless // of FFR. The result will be discarded if its FFR lane is inactive, but // it could still generate a fault. - value = Memory::Read(msize_in_bytes, element_address); + value = MemReadUint(msize_in_bytes, element_address); // All subsequent elements have non-fault semantics. type = kSVENonFaultLoad; @@ -7228,7 +7218,7 @@ void Simulator::SVEFaultTolerantLoadHelper(VectorFormat vform, bool can_read = (i < fake_fault_at_lane) && CanReadMemory(element_address, msize_in_bytes); if (can_read) { - value = Memory::Read(msize_in_bytes, element_address); + value = MemReadUint(msize_in_bytes, element_address); } else { // Propagate the fault to the end of FFR. for (int j = i; j < LaneCountFromFormat(vform); j++) { diff --git a/src/aarch64/simulator-aarch64.cc b/src/aarch64/simulator-aarch64.cc index 692a0596..cd5a2d6c 100644 --- a/src/aarch64/simulator-aarch64.cc +++ b/src/aarch64/simulator-aarch64.cc @@ -67,8 +67,10 @@ SimSystemRegister SimSystemRegister::DefaultValueFor(SystemRegister id) { } -Simulator::Simulator(Decoder* decoder, FILE* stream) - : movprfx_(NULL), cpu_features_auditor_(decoder, CPUFeatures::All()) { +Simulator::Simulator(Decoder* decoder, FILE* stream, SimStack::Allocated stack) + : memory_(std::move(stack)), + movprfx_(NULL), + cpu_features_auditor_(decoder, CPUFeatures::All()) { // Ensure that shift operations act as the simulator expects. VIXL_ASSERT((static_cast<int32_t>(-1) >> 1) == -1); VIXL_ASSERT((static_cast<uint32_t>(-1) >> 1) == 0x7fffffff); @@ -101,18 +103,6 @@ Simulator::Simulator(Decoder* decoder, FILE* stream) ResetState(); - // Allocate and set up the simulator stack. - stack_ = new byte[stack_size_]; - stack_limit_ = stack_ + stack_protection_size_; - // Configure the starting stack pointer. - // - Find the top of the stack. - byte* tos = stack_ + stack_size_; - // - There's a protection region at both ends of the stack. - tos -= stack_protection_size_; - // - The stack pointer must be 16-byte aligned. - tos = AlignDown(tos, 16); - WriteSp(tos); - // Print a warning about exclusive-access instructions, but only the first // time they are encountered. This warning can be silenced using // SilenceExclusiveAccessWarning(). @@ -192,6 +182,8 @@ void Simulator::ResetState() { ResetVRegisters(); ResetPRegisters(); + WriteSp(memory_.GetStack().GetBase()); + pc_ = NULL; pc_modified_ = false; @@ -221,7 +213,6 @@ void Simulator::SetVectorLengthInBits(unsigned vector_length) { } Simulator::~Simulator() { - delete[] stack_; // The decoder may outlive the simulator. decoder_->RemoveVisitor(print_disasm_); delete print_disasm_; @@ -1272,7 +1263,7 @@ uint16_t Simulator::PrintPartialAccess(uint16_t access_mask, const char* sep = ""; for (int i = struct_element_count - 1; i >= 0; i--) { int offset = lane_size_in_bytes * i; - uint64_t nibble = Memory::Read(lane_size_in_bytes, address + offset); + uint64_t nibble = MemReadUint(lane_size_in_bytes, address + offset); fprintf(stream_, "%s%0*" PRIx64, sep, lane_size_in_nibbles, nibble); sep = "'"; } @@ -2015,7 +2006,7 @@ void Simulator::LoadAcquireRCpcUnscaledOffsetHelper(const Instruction* instr) { VIXL_ALIGNMENT_EXCEPTION(); } - WriteRegister<T1>(rt, static_cast<T1>(Memory::Read<T2>(address))); + WriteRegister<T1>(rt, static_cast<T1>(MemRead<T2>(address))); // Approximate load-acquire by issuing a full barrier after the load. __sync_synchronize(); @@ -2045,7 +2036,7 @@ void Simulator::StoreReleaseUnscaledOffsetHelper(const Instruction* instr) { // Approximate store-release by issuing a full barrier after the load. __sync_synchronize(); - Memory::Write<T>(address, ReadRegister<T>(rt)); + MemWrite<T>(address, ReadRegister<T>(rt)); LogWrite(rt, GetPrintRegisterFormat(element_size), address); } @@ -2132,7 +2123,7 @@ void Simulator::VisitLoadStorePAC(const Instruction* instr) { // Verify that the calculated address is available to the host. VIXL_ASSERT(address == addr_ptr); - WriteXRegister(dst, Memory::Read<uint64_t>(addr_ptr), NoRegLog); + WriteXRegister(dst, MemRead<uint64_t>(addr_ptr), NoRegLog); unsigned access_size = 1 << 3; LogRead(dst, GetPrintRegisterFormatForSize(access_size), addr_ptr); } @@ -2160,92 +2151,92 @@ void Simulator::LoadStoreHelper(const Instruction* instr, LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreMask)); switch (op) { case LDRB_w: - WriteWRegister(srcdst, Memory::Read<uint8_t>(address), NoRegLog); + WriteWRegister(srcdst, MemRead<uint8_t>(address), NoRegLog); extend_to_size = kWRegSizeInBytes; break; case LDRH_w: - WriteWRegister(srcdst, Memory::Read<uint16_t>(address), NoRegLog); + WriteWRegister(srcdst, MemRead<uint16_t>(address), NoRegLog); extend_to_size = kWRegSizeInBytes; break; case LDR_w: - WriteWRegister(srcdst, Memory::Read<uint32_t>(address), NoRegLog); + WriteWRegister(srcdst, MemRead<uint32_t>(address), NoRegLog); extend_to_size = kWRegSizeInBytes; break; case LDR_x: - WriteXRegister(srcdst, Memory::Read<uint64_t>(address), NoRegLog); + WriteXRegister(srcdst, MemRead<uint64_t>(address), NoRegLog); extend_to_size = kXRegSizeInBytes; break; case LDRSB_w: - WriteWRegister(srcdst, Memory::Read<int8_t>(address), NoRegLog); + WriteWRegister(srcdst, MemRead<int8_t>(address), NoRegLog); extend_to_size = kWRegSizeInBytes; break; case LDRSH_w: - WriteWRegister(srcdst, Memory::Read<int16_t>(address), NoRegLog); + WriteWRegister(srcdst, MemRead<int16_t>(address), NoRegLog); extend_to_size = kWRegSizeInBytes; break; case LDRSB_x: - WriteXRegister(srcdst, Memory::Read<int8_t>(address), NoRegLog); + WriteXRegister(srcdst, MemRead<int8_t>(address), NoRegLog); extend_to_size = kXRegSizeInBytes; break; case LDRSH_x: - WriteXRegister(srcdst, Memory::Read<int16_t>(address), NoRegLog); + WriteXRegister(srcdst, MemRead<int16_t>(address), NoRegLog); extend_to_size = kXRegSizeInBytes; break; case LDRSW_x: - WriteXRegister(srcdst, Memory::Read<int32_t>(address), NoRegLog); + WriteXRegister(srcdst, MemRead<int32_t>(address), NoRegLog); extend_to_size = kXRegSizeInBytes; break; case LDR_b: - WriteBRegister(srcdst, Memory::Read<uint8_t>(address), NoRegLog); + WriteBRegister(srcdst, MemRead<uint8_t>(address), NoRegLog); rt_is_vreg = true; break; case LDR_h: - WriteHRegister(srcdst, Memory::Read<uint16_t>(address), NoRegLog); + WriteHRegister(srcdst, MemRead<uint16_t>(address), NoRegLog); rt_is_vreg = true; break; case LDR_s: - WriteSRegister(srcdst, Memory::Read<float>(address), NoRegLog); + WriteSRegister(srcdst, MemRead<float>(address), NoRegLog); rt_is_vreg = true; break; case LDR_d: - WriteDRegister(srcdst, Memory::Read<double>(address), NoRegLog); + WriteDRegister(srcdst, MemRead<double>(address), NoRegLog); rt_is_vreg = true; break; case LDR_q: - WriteQRegister(srcdst, Memory::Read<qreg_t>(address), NoRegLog); + WriteQRegister(srcdst, MemRead<qreg_t>(address), NoRegLog); rt_is_vreg = true; break; case STRB_w: - Memory::Write<uint8_t>(address, ReadWRegister(srcdst)); + MemWrite<uint8_t>(address, ReadWRegister(srcdst)); break; case STRH_w: - Memory::Write<uint16_t>(address, ReadWRegister(srcdst)); + MemWrite<uint16_t>(address, ReadWRegister(srcdst)); break; case STR_w: - Memory::Write<uint32_t>(address, ReadWRegister(srcdst)); + MemWrite<uint32_t>(address, ReadWRegister(srcdst)); break; case STR_x: - Memory::Write<uint64_t>(address, ReadXRegister(srcdst)); + MemWrite<uint64_t>(address, ReadXRegister(srcdst)); break; case STR_b: - Memory::Write<uint8_t>(address, ReadBRegister(srcdst)); + MemWrite<uint8_t>(address, ReadBRegister(srcdst)); rt_is_vreg = true; break; case STR_h: - Memory::Write<uint16_t>(address, ReadHRegisterBits(srcdst)); + MemWrite<uint16_t>(address, ReadHRegisterBits(srcdst)); rt_is_vreg = true; break; case STR_s: - Memory::Write<float>(address, ReadSRegister(srcdst)); + MemWrite<float>(address, ReadSRegister(srcdst)); rt_is_vreg = true; break; case STR_d: - Memory::Write<double>(address, ReadDRegister(srcdst)); + MemWrite<double>(address, ReadDRegister(srcdst)); rt_is_vreg = true; break; case STR_q: - Memory::Write<qreg_t>(address, ReadQRegister(srcdst)); + MemWrite<qreg_t>(address, ReadQRegister(srcdst)); rt_is_vreg = true; break; @@ -2326,64 +2317,64 @@ void Simulator::LoadStorePairHelper(const Instruction* instr, // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS). We // will print a more detailed log. case LDP_w: { - WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog); - WriteWRegister(rt2, Memory::Read<uint32_t>(address2), NoRegLog); + WriteWRegister(rt, MemRead<uint32_t>(address), NoRegLog); + WriteWRegister(rt2, MemRead<uint32_t>(address2), NoRegLog); break; } case LDP_s: { - WriteSRegister(rt, Memory::Read<float>(address), NoRegLog); - WriteSRegister(rt2, Memory::Read<float>(address2), NoRegLog); + WriteSRegister(rt, MemRead<float>(address), NoRegLog); + WriteSRegister(rt2, MemRead<float>(address2), NoRegLog); rt_is_vreg = true; break; } case LDP_x: { - WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog); - WriteXRegister(rt2, Memory::Read<uint64_t>(address2), NoRegLog); + WriteXRegister(rt, MemRead<uint64_t>(address), NoRegLog); + WriteXRegister(rt2, MemRead<uint64_t>(address2), NoRegLog); break; } case LDP_d: { - WriteDRegister(rt, Memory::Read<double>(address), NoRegLog); - WriteDRegister(rt2, Memory::Read<double>(address2), NoRegLog); + WriteDRegister(rt, MemRead<double>(address), NoRegLog); + WriteDRegister(rt2, MemRead<double>(address2), NoRegLog); rt_is_vreg = true; break; } case LDP_q: { - WriteQRegister(rt, Memory::Read<qreg_t>(address), NoRegLog); - WriteQRegister(rt2, Memory::Read<qreg_t>(address2), NoRegLog); + WriteQRegister(rt, MemRead<qreg_t>(address), NoRegLog); + WriteQRegister(rt2, MemRead<qreg_t>(address2), NoRegLog); rt_is_vreg = true; break; } case LDPSW_x: { - WriteXRegister(rt, Memory::Read<int32_t>(address), NoRegLog); - WriteXRegister(rt2, Memory::Read<int32_t>(address2), NoRegLog); + WriteXRegister(rt, MemRead<int32_t>(address), NoRegLog); + WriteXRegister(rt2, MemRead<int32_t>(address2), NoRegLog); sign_extend = true; break; } case STP_w: { - Memory::Write<uint32_t>(address, ReadWRegister(rt)); - Memory::Write<uint32_t>(address2, ReadWRegister(rt2)); + MemWrite<uint32_t>(address, ReadWRegister(rt)); + MemWrite<uint32_t>(address2, ReadWRegister(rt2)); break; } case STP_s: { - Memory::Write<float>(address, ReadSRegister(rt)); - Memory::Write<float>(address2, ReadSRegister(rt2)); + MemWrite<float>(address, ReadSRegister(rt)); + MemWrite<float>(address2, ReadSRegister(rt2)); rt_is_vreg = true; break; } case STP_x: { - Memory::Write<uint64_t>(address, ReadXRegister(rt)); - Memory::Write<uint64_t>(address2, ReadXRegister(rt2)); + MemWrite<uint64_t>(address, ReadXRegister(rt)); + MemWrite<uint64_t>(address2, ReadXRegister(rt2)); break; } case STP_d: { - Memory::Write<double>(address, ReadDRegister(rt)); - Memory::Write<double>(address2, ReadDRegister(rt2)); + MemWrite<double>(address, ReadDRegister(rt)); + MemWrite<double>(address2, ReadDRegister(rt2)); rt_is_vreg = true; break; } case STP_q: { - Memory::Write<qreg_t>(address, ReadQRegister(rt)); - Memory::Write<qreg_t>(address2, ReadQRegister(rt2)); + MemWrite<qreg_t>(address, ReadQRegister(rt)); + MemWrite<qreg_t>(address2, ReadQRegister(rt2)); rt_is_vreg = true; break; } @@ -2443,7 +2434,7 @@ void Simulator::CompareAndSwapHelper(const Instruction* instr) { // associated with that location, even if the compare subsequently fails. local_monitor_.Clear(); - T data = Memory::Read<T>(address); + T data = MemRead<T>(address); if (is_acquire) { // Approximate load-acquire by issuing a full barrier after the load. __sync_synchronize(); @@ -2454,7 +2445,7 @@ void Simulator::CompareAndSwapHelper(const Instruction* instr) { // Approximate store-release by issuing a full barrier before the store. __sync_synchronize(); } - Memory::Write<T>(address, newvalue); + MemWrite<T>(address, newvalue); LogWrite(rt, GetPrintRegisterFormatForSize(element_size), address); } WriteRegister<T>(rs, data, NoRegLog); @@ -2490,8 +2481,8 @@ void Simulator::CompareAndSwapPairHelper(const Instruction* instr) { // associated with that location, even if the compare subsequently fails. local_monitor_.Clear(); - T data_low = Memory::Read<T>(address); - T data_high = Memory::Read<T>(address2); + T data_low = MemRead<T>(address); + T data_high = MemRead<T>(address2); if (is_acquire) { // Approximate load-acquire by issuing a full barrier after the load. @@ -2506,8 +2497,8 @@ void Simulator::CompareAndSwapPairHelper(const Instruction* instr) { __sync_synchronize(); } - Memory::Write<T>(address, newvalue_low); - Memory::Write<T>(address2, newvalue_high); + MemWrite<T>(address, newvalue_low); + MemWrite<T>(address2, newvalue_high); } WriteRegister<T>(rs + 1, data_high, NoRegLog); @@ -2675,43 +2666,43 @@ void Simulator::VisitLoadStoreExclusive(const Instruction* instr) { case LDAXRB_w: case LDARB_w: case LDLARB: - WriteWRegister(rt, Memory::Read<uint8_t>(address), NoRegLog); + WriteWRegister(rt, MemRead<uint8_t>(address), NoRegLog); reg_size = kWRegSizeInBytes; break; case LDXRH_w: case LDAXRH_w: case LDARH_w: case LDLARH: - WriteWRegister(rt, Memory::Read<uint16_t>(address), NoRegLog); + WriteWRegister(rt, MemRead<uint16_t>(address), NoRegLog); reg_size = kWRegSizeInBytes; break; case LDXR_w: case LDAXR_w: case LDAR_w: case LDLAR_w: - WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog); + WriteWRegister(rt, MemRead<uint32_t>(address), NoRegLog); reg_size = kWRegSizeInBytes; break; case LDXR_x: case LDAXR_x: case LDAR_x: case LDLAR_x: - WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog); + WriteXRegister(rt, MemRead<uint64_t>(address), NoRegLog); reg_size = kXRegSizeInBytes; break; case LDXP_w: case LDAXP_w: - WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog); + WriteWRegister(rt, MemRead<uint32_t>(address), NoRegLog); WriteWRegister(rt2, - Memory::Read<uint32_t>(address + element_size), + MemRead<uint32_t>(address + element_size), NoRegLog); reg_size = kWRegSizeInBytes; break; case LDXP_x: case LDAXP_x: - WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog); + WriteXRegister(rt, MemRead<uint64_t>(address), NoRegLog); WriteXRegister(rt2, - Memory::Read<uint64_t>(address + element_size), + MemRead<uint64_t>(address + element_size), NoRegLog); reg_size = kXRegSizeInBytes; break; @@ -2755,37 +2746,35 @@ void Simulator::VisitLoadStoreExclusive(const Instruction* instr) { case STLXRB_w: case STLRB_w: case STLLRB: - Memory::Write<uint8_t>(address, ReadWRegister(rt)); + MemWrite<uint8_t>(address, ReadWRegister(rt)); break; case STXRH_w: case STLXRH_w: case STLRH_w: case STLLRH: - Memory::Write<uint16_t>(address, ReadWRegister(rt)); + MemWrite<uint16_t>(address, ReadWRegister(rt)); break; case STXR_w: case STLXR_w: case STLR_w: case STLLR_w: - Memory::Write<uint32_t>(address, ReadWRegister(rt)); + MemWrite<uint32_t>(address, ReadWRegister(rt)); break; case STXR_x: case STLXR_x: case STLR_x: case STLLR_x: - Memory::Write<uint64_t>(address, ReadXRegister(rt)); + MemWrite<uint64_t>(address, ReadXRegister(rt)); break; case STXP_w: case STLXP_w: - Memory::Write<uint32_t>(address, ReadWRegister(rt)); - Memory::Write<uint32_t>(address + element_size, - ReadWRegister(rt2)); + MemWrite<uint32_t>(address, ReadWRegister(rt)); + MemWrite<uint32_t>(address + element_size, ReadWRegister(rt2)); break; case STXP_x: case STLXP_x: - Memory::Write<uint64_t>(address, ReadXRegister(rt)); - Memory::Write<uint64_t>(address + element_size, - ReadXRegister(rt2)); + MemWrite<uint64_t>(address, ReadXRegister(rt)); + MemWrite<uint64_t>(address + element_size, ReadXRegister(rt2)); break; default: VIXL_UNREACHABLE(); @@ -2818,7 +2807,7 @@ void Simulator::AtomicMemorySimpleHelper(const Instruction* instr) { T value = ReadRegister<T>(rs); - T data = Memory::Read<T>(address); + T data = MemRead<T>(address); if (is_acquire) { // Approximate load-acquire by issuing a full barrier after the load. @@ -2859,7 +2848,7 @@ void Simulator::AtomicMemorySimpleHelper(const Instruction* instr) { __sync_synchronize(); } - Memory::Write<T>(address, result); + MemWrite<T>(address, result); WriteRegister<T>(rt, data, NoRegLog); PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size); @@ -2881,7 +2870,7 @@ void Simulator::AtomicMemorySwapHelper(const Instruction* instr) { CheckIsValidUnalignedAtomicAccess(rn, address, element_size); - T data = Memory::Read<T>(address); + T data = MemRead<T>(address); if (is_acquire) { // Approximate load-acquire by issuing a full barrier after the load. __sync_synchronize(); @@ -2891,7 +2880,7 @@ void Simulator::AtomicMemorySwapHelper(const Instruction* instr) { // Approximate store-release by issuing a full barrier before the store. __sync_synchronize(); } - Memory::Write<T>(address, ReadRegister<T>(rs)); + MemWrite<T>(address, ReadRegister<T>(rs)); WriteRegister<T>(rt, data); @@ -2910,7 +2899,7 @@ void Simulator::LoadAcquireRCpcHelper(const Instruction* instr) { CheckIsValidUnalignedAtomicAccess(rn, address, element_size); - WriteRegister<T>(rt, Memory::Read<T>(address)); + WriteRegister<T>(rt, MemRead<T>(address)); // Approximate load-acquire by issuing a full barrier after the load. __sync_synchronize(); @@ -3031,27 +3020,27 @@ void Simulator::VisitLoadLiteral(const Instruction* instr) { // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_VREGS), then // print a more detailed log. case LDR_w_lit: - WriteWRegister(rt, Memory::Read<uint32_t>(address), NoRegLog); + WriteWRegister(rt, MemRead<uint32_t>(address), NoRegLog); LogRead(rt, kPrintWReg, address); break; case LDR_x_lit: - WriteXRegister(rt, Memory::Read<uint64_t>(address), NoRegLog); + WriteXRegister(rt, MemRead<uint64_t>(address), NoRegLog); LogRead(rt, kPrintXReg, address); break; case LDR_s_lit: - WriteSRegister(rt, Memory::Read<float>(address), NoRegLog); + WriteSRegister(rt, MemRead<float>(address), NoRegLog); LogVRead(rt, kPrintSRegFP, address); break; case LDR_d_lit: - WriteDRegister(rt, Memory::Read<double>(address), NoRegLog); + WriteDRegister(rt, MemRead<double>(address), NoRegLog); LogVRead(rt, kPrintDRegFP, address); break; case LDR_q_lit: - WriteQRegister(rt, Memory::Read<qreg_t>(address), NoRegLog); + WriteQRegister(rt, MemRead<qreg_t>(address), NoRegLog); LogVRead(rt, kPrintReg1Q, address); break; case LDRSW_x_lit: - WriteXRegister(rt, Memory::Read<int32_t>(address), NoRegLog); + WriteXRegister(rt, MemRead<int32_t>(address), NoRegLog); LogExtendingRead(rt, kPrintXReg, kWRegSizeInBytes, address); break; @@ -4439,7 +4428,7 @@ void Simulator::SysOp_W(int op, int64_t val) { case CIVAC: { // Perform a dummy memory access to ensure that we have read access // to the specified address. - volatile uint8_t y = Memory::Read<uint8_t>(val); + volatile uint8_t y = MemRead<uint8_t>(val); USE(y); // TODO: Implement "case ZVA:". break; @@ -9739,7 +9728,7 @@ void Simulator::VisitSVELoadPredicateRegister(const Instruction* instr) { uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9); uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * pl; for (int i = 0; i < pl; i++) { - pt.Insert(i, Memory::Read<uint8_t>(address + i)); + pt.Insert(i, MemRead<uint8_t>(address + i)); } LogPRead(instr->GetPt(), address); break; @@ -9759,7 +9748,7 @@ void Simulator::VisitSVELoadVectorRegister(const Instruction* instr) { uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9); uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * vl; for (int i = 0; i < vl; i++) { - zt.Insert(i, Memory::Read<uint8_t>(address + i)); + zt.Insert(i, MemRead<uint8_t>(address + i)); } LogZRead(instr->GetRt(), address); break; @@ -10694,7 +10683,7 @@ void Simulator::VisitSVEStorePredicateRegister(const Instruction* instr) { uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9); uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * pl; for (int i = 0; i < pl; i++) { - Memory::Write(address + i, pt.GetLane<uint8_t>(i)); + MemWrite(address + i, pt.GetLane<uint8_t>(i)); } LogPWrite(instr->GetPt(), address); break; @@ -10714,7 +10703,7 @@ void Simulator::VisitSVEStoreVectorRegister(const Instruction* instr) { uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9); uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * vl; for (int i = 0; i < vl; i++) { - Memory::Write(address + i, zt.GetLane<uint8_t>(i)); + MemWrite(address + i, zt.GetLane<uint8_t>(i)); } LogZWrite(instr->GetRt(), address); break; @@ -11878,11 +11867,11 @@ void Simulator::DoRuntimeCall(const Instruction* instr) { // The appropriate `Simulator::SimulateRuntimeCall()` wrapper and the function // to call are passed inlined in the assembly. uintptr_t call_wrapper_address = - Memory::Read<uintptr_t>(instr + kRuntimeCallWrapperOffset); + MemRead<uintptr_t>(instr + kRuntimeCallWrapperOffset); uintptr_t function_address = - Memory::Read<uintptr_t>(instr + kRuntimeCallFunctionOffset); + MemRead<uintptr_t>(instr + kRuntimeCallFunctionOffset); RuntimeCallType call_type = static_cast<RuntimeCallType>( - Memory::Read<uint32_t>(instr + kRuntimeCallTypeOffset)); + MemRead<uint32_t>(instr + kRuntimeCallTypeOffset)); auto runtime_call_wrapper = reinterpret_cast<void (*)(Simulator*, uintptr_t)>(call_wrapper_address); @@ -11917,7 +11906,7 @@ void Simulator::DoConfigureCPUFeatures(const Instruction* instr) { // Read the kNone-terminated list of features. CPUFeatures parameters; while (true) { - ElementType feature = Memory::Read<ElementType>(instr + offset); + ElementType feature = MemRead<ElementType>(instr + offset); offset += element_size; if (feature == static_cast<ElementType>(CPUFeatures::kNone)) break; parameters.Combine(static_cast<CPUFeatures::Feature>(feature)); diff --git a/src/aarch64/simulator-aarch64.h b/src/aarch64/simulator-aarch64.h index 1e7d3079..f8bc2754 100644 --- a/src/aarch64/simulator-aarch64.h +++ b/src/aarch64/simulator-aarch64.h @@ -27,6 +27,7 @@ #ifndef VIXL_AARCH64_SIMULATOR_AARCH64_H_ #define VIXL_AARCH64_SIMULATOR_AARCH64_H_ +#include <memory> #include <vector> #include "../globals-vixl.h" @@ -54,11 +55,112 @@ namespace vixl { namespace aarch64 { +class SimStack { + public: + SimStack() {} + explicit SimStack(size_t size) : usable_size_(size) {} + + // Guard against accesses above the stack base. This could occur, for example, + // if the first simulated function tries to read stack arguments that haven't + // been properly initialised in the Simulator's stack. + void SetBaseGuardSize(size_t size) { base_guard_size_ = size; } + + // Guard against stack overflows. The size should be large enough to detect + // the largest stride made (by `MacroAssembler::Claim()` or equivalent) whilst + // initialising stack objects. + void SetLimitGuardSize(size_t size) { limit_guard_size_ = size; } + + // The minimum usable size of the stack. + // Equal to "stack base" - "stack limit", in AAPCS64 terminology. + void SetUsableSize(size_t size) { usable_size_ = size; } + + // Set the minimum alignment for the stack parameters. + void AlignToBytesLog2(int align_log2) { align_log2_ = align_log2; } + + class Allocated { + public: + // Using AAPCS64 terminology, highest addresses at the top: + // + // data_.get() + alloc_size -> + // | + // | Base guard + // GetBase() -> | | + // | | + // | | AAPCS64-legal + // | Usable stack | values of 'sp'. + // | | + // | | + // GetLimit() -> | + // | Limit guard + // data_.get() -> | + // + // The Simulator detects (and forbids) accesses to either guard region. + + char* GetBase() const { return base_; } + char* GetLimit() const { return limit_; } + + template <typename T> + bool IsAccessInGuardRegion(const T* base, size_t size) const { + VIXL_ASSERT(size > 0); + // Inclusive bounds. + const char* start = reinterpret_cast<const char*>(base); + const char* end = start + size - 1; + const char* data_start = data_.get(); + const char* data_end = data_start + alloc_size_ - 1; + bool in_base_guard = (start <= data_end) && (end >= base_); + bool in_limit_guard = (start <= limit_) && (end >= data_start); + return in_base_guard || in_limit_guard; + } + + private: + std::unique_ptr<char[]> data_; + char* limit_; + char* base_; + size_t alloc_size_; + + friend class SimStack; + }; + + // Allocate the stack, locking the parameters. + Allocated Allocate() { + size_t align_to = 1 << align_log2_; + size_t l = AlignUp(limit_guard_size_, align_to); + size_t u = AlignUp(usable_size_, align_to); + size_t b = AlignUp(base_guard_size_, align_to); + size_t size = l + u + b; + + Allocated a; + size_t alloc_size = (align_to - 1) + size; + a.data_ = std::make_unique<char[]>(alloc_size); + void* data = a.data_.get(); + auto data_aligned = + reinterpret_cast<char*>(std::align(align_to, size, data, alloc_size)); + a.limit_ = data_aligned + l - 1; + a.base_ = data_aligned + l + u; + a.alloc_size_ = alloc_size; + return a; + } + + private: + size_t base_guard_size_ = 256; + size_t limit_guard_size_ = 4 * 1024; + size_t usable_size_ = 8 * 1024; + size_t align_log2_ = 4; + + static const size_t kDefaultBaseGuardSize = 256; + static const size_t kDefaultLimitGuardSize = 4 * 1024; + static const size_t kDefaultUsableSize = 8 * 1024; +}; + // Representation of memory, with typed getters and setters for access. class Memory { public: + explicit Memory(SimStack::Allocated stack) : stack_(std::move(stack)) {} + + const SimStack::Allocated& GetStack() { return stack_; } + template <typename T> - static T AddressUntag(T address) { + T AddressUntag(T address) const { // Cast the address using a C-style cast. A reinterpret_cast would be // appropriate, but it can't cast one integral type to another. uint64_t bits = (uint64_t)address; @@ -66,18 +168,35 @@ class Memory { } template <typename T, typename A> - static T Read(A address) { + T Read(A address) const { T value; address = AddressUntag(address); - VIXL_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) || - (sizeof(value) == 4) || (sizeof(value) == 8) || - (sizeof(value) == 16)); - memcpy(&value, reinterpret_cast<const char*>(address), sizeof(value)); + VIXL_STATIC_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) || + (sizeof(value) == 4) || (sizeof(value) == 8) || + (sizeof(value) == 16)); + auto base = reinterpret_cast<const char*>(address); + if (stack_.IsAccessInGuardRegion(base, sizeof(value))) { + VIXL_ABORT_WITH_MSG("Attempt to read from stack guard region"); + } + memcpy(&value, base, sizeof(value)); return value; } + template <typename T, typename A> + void Write(A address, T value) const { + address = AddressUntag(address); + VIXL_STATIC_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) || + (sizeof(value) == 4) || (sizeof(value) == 8) || + (sizeof(value) == 16)); + auto base = reinterpret_cast<char*>(address); + if (stack_.IsAccessInGuardRegion(base, sizeof(value))) { + VIXL_ABORT_WITH_MSG("Attempt to write to stack guard region"); + } + memcpy(base, &value, sizeof(value)); + } + template <typename A> - static uint64_t Read(int size_in_bytes, A address) { + uint64_t ReadUint(int size_in_bytes, A address) const { switch (size_in_bytes) { case 1: return Read<uint8_t>(address); @@ -92,14 +211,39 @@ class Memory { return 0; } - template <typename T, typename A> - static void Write(A address, T value) { - address = AddressUntag(address); - VIXL_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) || - (sizeof(value) == 4) || (sizeof(value) == 8) || - (sizeof(value) == 16)); - memcpy(reinterpret_cast<char*>(address), &value, sizeof(value)); + template <typename A> + int64_t ReadInt(int size_in_bytes, A address) const { + switch (size_in_bytes) { + case 1: + return Read<int8_t>(address); + case 2: + return Read<int16_t>(address); + case 4: + return Read<int32_t>(address); + case 8: + return Read<int64_t>(address); + } + VIXL_UNREACHABLE(); + return 0; + } + + template <typename A> + void Write(int size_in_bytes, A address, uint64_t value) const { + switch (size_in_bytes) { + case 1: + return Write(address, static_cast<uint8_t>(value)); + case 2: + return Write(address, static_cast<uint16_t>(value)); + case 4: + return Write(address, static_cast<uint32_t>(value)); + case 8: + return Write(address, value); + } + VIXL_UNREACHABLE(); } + + private: + SimStack::Allocated stack_; }; // Represent a register (r0-r31, v0-v31, z0-z31, p0-p15). @@ -478,136 +622,6 @@ class LogicVRegister { } } - void ReadIntFromMem(VectorFormat vform, - unsigned msize_in_bits, - int index, - uint64_t addr) const { - if (IsSVEFormat(vform)) register_.NotifyAccessAsZ(); - int64_t value; - switch (msize_in_bits) { - case 8: - value = Memory::Read<int8_t>(addr); - break; - case 16: - value = Memory::Read<int16_t>(addr); - break; - case 32: - value = Memory::Read<int32_t>(addr); - break; - case 64: - value = Memory::Read<int64_t>(addr); - break; - default: - VIXL_UNREACHABLE(); - return; - } - - unsigned esize_in_bits = LaneSizeInBitsFromFormat(vform); - VIXL_ASSERT(esize_in_bits >= msize_in_bits); - switch (esize_in_bits) { - case 8: - register_.Insert(index, static_cast<int8_t>(value)); - break; - case 16: - register_.Insert(index, static_cast<int16_t>(value)); - break; - case 32: - register_.Insert(index, static_cast<int32_t>(value)); - break; - case 64: - register_.Insert(index, static_cast<int64_t>(value)); - break; - default: - VIXL_UNREACHABLE(); - return; - } - } - - void ReadUintFromMem(VectorFormat vform, - unsigned msize_in_bits, - int index, - uint64_t addr) const { - if (IsSVEFormat(vform)) register_.NotifyAccessAsZ(); - uint64_t value; - switch (msize_in_bits) { - case 8: - value = Memory::Read<uint8_t>(addr); - break; - case 16: - value = Memory::Read<uint16_t>(addr); - break; - case 32: - value = Memory::Read<uint32_t>(addr); - break; - case 64: - value = Memory::Read<uint64_t>(addr); - break; - default: - VIXL_UNREACHABLE(); - return; - } - - unsigned esize_in_bits = LaneSizeInBitsFromFormat(vform); - VIXL_ASSERT(esize_in_bits >= msize_in_bits); - switch (esize_in_bits) { - case 8: - register_.Insert(index, static_cast<uint8_t>(value)); - break; - case 16: - register_.Insert(index, static_cast<uint16_t>(value)); - break; - case 32: - register_.Insert(index, static_cast<uint32_t>(value)); - break; - case 64: - register_.Insert(index, static_cast<uint64_t>(value)); - break; - default: - VIXL_UNREACHABLE(); - return; - } - } - - void ReadUintFromMem(VectorFormat vform, int index, uint64_t addr) const { - if (IsSVEFormat(vform)) register_.NotifyAccessAsZ(); - switch (LaneSizeInBitsFromFormat(vform)) { - case 8: - register_.Insert(index, Memory::Read<uint8_t>(addr)); - break; - case 16: - register_.Insert(index, Memory::Read<uint16_t>(addr)); - break; - case 32: - register_.Insert(index, Memory::Read<uint32_t>(addr)); - break; - case 64: - register_.Insert(index, Memory::Read<uint64_t>(addr)); - break; - default: - VIXL_UNREACHABLE(); - return; - } - } - - void WriteUintToMem(VectorFormat vform, int index, uint64_t addr) const { - if (IsSVEFormat(vform)) register_.NotifyAccessAsZ(); - uint64_t value = Uint(vform, index); - switch (LaneSizeInBitsFromFormat(vform)) { - case 8: - Memory::Write(addr, static_cast<uint8_t>(value)); - break; - case 16: - Memory::Write(addr, static_cast<uint16_t>(value)); - break; - case 32: - Memory::Write(addr, static_cast<uint32_t>(value)); - break; - case 64: - Memory::Write(addr, value); - break; - } - } - template <typename T> T Float(int index) const { return register_.GetLane<T>(index); @@ -1005,7 +1019,9 @@ class SimExclusiveGlobalMonitor { class Simulator : public DecoderVisitor { public: - explicit Simulator(Decoder* decoder, FILE* stream = stdout); + explicit Simulator(Decoder* decoder, + FILE* stream = stdout, + SimStack::Allocated stack = SimStack().Allocate()); ~Simulator(); void ResetState(); @@ -1083,7 +1099,7 @@ class Simulator : public DecoderVisitor { void WritePc(const Instruction* new_pc, BranchLogMode log_mode = LogBranches) { if (log_mode == LogBranches) LogTakenBranch(new_pc); - pc_ = Memory::AddressUntag(new_pc); + pc_ = memory_.AddressUntag(new_pc); pc_modified_ = true; } VIXL_DEPRECATED("WritePc", void set_pc(const Instruction* new_pc)) { @@ -1689,6 +1705,63 @@ class Simulator : public DecoderVisitor { } } + template <typename T, typename A> + T MemRead(A address) const { + return memory_.Read<T>(address); + } + + template <typename T, typename A> + void MemWrite(A address, T value) const { + return memory_.Write(address, value); + } + + template <typename A> + uint64_t MemReadUint(int size_in_bytes, A address) const { + return memory_.ReadUint(size_in_bytes, address); + } + + template <typename A> + int64_t MemReadInt(int size_in_bytes, A address) const { + return memory_.ReadInt(size_in_bytes, address); + } + + template <typename A> + void MemWrite(int size_in_bytes, A address, uint64_t value) const { + return memory_.Write(size_in_bytes, address, value); + } + + void LoadLane(LogicVRegister dst, + VectorFormat vform, + int index, + uint64_t addr) const { + unsigned msize_in_bytes = LaneSizeInBytesFromFormat(vform); + LoadUintToLane(dst, vform, msize_in_bytes, index, addr); + } + + void LoadUintToLane(LogicVRegister dst, + VectorFormat vform, + unsigned msize_in_bytes, + int index, + uint64_t addr) const { + dst.SetUint(vform, index, MemReadUint(msize_in_bytes, addr)); + } + + void LoadIntToLane(LogicVRegister dst, + VectorFormat vform, + unsigned msize_in_bytes, + int index, + uint64_t addr) const { + dst.SetInt(vform, index, MemReadInt(msize_in_bytes, addr)); + } + + void StoreLane(const LogicVRegister& src, + VectorFormat vform, + int index, + uint64_t addr) const { + unsigned msize_in_bytes = LaneSizeInBytesFromFormat(vform); + MemWrite(msize_in_bytes, addr, src.Uint(vform, index)); + } + uint64_t ComputeMemOperandAddress(const MemOperand& mem_op) const; template <typename T> @@ -1697,7 +1770,7 @@ class Simulator : public DecoderVisitor { return ReadCPURegister<T>(operand.GetCPURegister()); } else { VIXL_ASSERT(operand.IsMemOperand()); - return Memory::Read<T>(ComputeMemOperandAddress(operand.GetMemOperand())); + return MemRead<T>(ComputeMemOperandAddress(operand.GetMemOperand())); } } @@ -1718,7 +1791,7 @@ class Simulator : public DecoderVisitor { WriteCPURegister(operand.GetCPURegister(), raw, log_mode); } else { VIXL_ASSERT(operand.IsMemOperand()); - Memory::Write(ComputeMemOperandAddress(operand.GetMemOperand()), value); + MemWrite(ComputeMemOperandAddress(operand.GetMemOperand()), value); } } @@ -4502,14 +4575,11 @@ class Simulator : public DecoderVisitor { static const uint32_t kConditionFlagsMask = 0xf0000000; - // Stack - byte* stack_; - static const int stack_protection_size_ = 256; - // 8 KB stack. - // TODO: Make this configurable, or automatically allocate space as it runs - // out (like the OS would try to do). - static const int stack_size_ = 8 * 1024 + 2 * stack_protection_size_; - byte* stack_limit_; + Memory memory_; + + static const size_t kDefaultStackGuardStartSize = 0; + static const size_t kDefaultStackGuardEndSize = 4 * 1024; + static const size_t kDefaultStackUsableSize = 8 * 1024; Decoder* decoder_; // Indicates if the pc has been modified by the instruction and should not be |