From 7d2e1ee789413e6ace8bcf009897eea10b603f51 Mon Sep 17 00:00:00 2001 From: David Schall Date: Tue, 27 Jun 2023 08:46:39 +0000 Subject: [PATCH] arch: Add instruction size and PC set methods Adds the instruction size to all static instruction. x86, arm and RISC-V decoders add the instruction size to every decoded macro instruction. As microops should reflect the size of the their parent macroop the set method is overwritten to pass the size to all microops. Furthermore, we add a set method to the PC state. It allows setting a PC state to a certain address. Both methods are required for the decoupled front-end. Change-Id: I311fe3f637e867c42dee7781f5373ea2e69e2072 Signed-off-by: David Schall --- src/arch/arm/decoder.hh | 1 + src/arch/arm/insts/pred_inst.hh | 9 +++++++++ src/arch/generic/pcstate.hh | 22 +++++++++++++++++++--- src/arch/riscv/decoder.cc | 3 +++ src/arch/riscv/insts/static_inst.hh | 9 +++++++++ src/arch/x86/decoder.cc | 5 +++-- src/arch/x86/insts/macroop.hh | 8 ++++++++ src/cpu/static_inst.hh | 17 +++++++++++++++++ 8 files changed, 69 insertions(+), 5 deletions(-) diff --git a/src/arch/arm/decoder.hh b/src/arch/arm/decoder.hh index 83690936c0..75488b6750 100644 --- a/src/arch/arm/decoder.hh +++ b/src/arch/arm/decoder.hh @@ -138,6 +138,7 @@ class Decoder : public InstDecoder StaticInstPtr si = defaultCache.decode(this, mach_inst, addr); DPRINTF(Decode, "Decode: Decoded %s instruction: %#x\n", si->getName(), mach_inst); + si->size((!emi.thumb || emi.bigThumb) ? 4 : 2); return si; } diff --git a/src/arch/arm/insts/pred_inst.hh b/src/arch/arm/insts/pred_inst.hh index da3db6c6a5..6f46831edb 100644 --- a/src/arch/arm/insts/pred_inst.hh +++ b/src/arch/arm/insts/pred_inst.hh @@ -378,6 +378,15 @@ class PredMacroOp : public PredOp std::string generateDisassembly( Addr pc, const loader::SymbolTable *symtab) const override; + + + void size(size_t newSize) override + { + for (int i = 0; i < numMicroops; i++) { + microOps[i]->size(newSize); + } + _size = newSize; + } }; /** diff --git a/src/arch/generic/pcstate.hh b/src/arch/generic/pcstate.hh index f1df6e7c39..5c278a4233 100644 --- a/src/arch/generic/pcstate.hh +++ b/src/arch/generic/pcstate.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2020 ARM Limited + * Copyright (c) 2023 The University of Edinburgh * All rights reserved * * The license below extends only to copyright in the software and shall @@ -126,6 +127,13 @@ class PCStateBase : public Serializable _upc = 0; } + virtual void + set(Addr val) + { + _pc = val; + _upc = 0; + } + virtual void advance() = 0; virtual bool branching() const = 0; @@ -309,6 +317,14 @@ class PCStateWithNext : public PCStateBase _npc == ps._npc && _nupc == ps._nupc; } + void + set(Addr val) override + { + PCStateBase::set(val); + _npc = 0; + _nupc = 1; + } + void serialize(CheckpointOut &cp) const override { @@ -359,9 +375,9 @@ class SimplePCState : public PCStateWithNext * @param val The value to set the PC to. */ void - set(Addr val) + set(Addr val) override { - this->pc(val); + Base::set(val); this->npc(val + InstWidth); }; @@ -402,7 +418,7 @@ class UPCState : public SimplePCState } void - set(Addr val) + set(Addr val) override { Base::set(val); this->upc(0); diff --git a/src/arch/riscv/decoder.cc b/src/arch/riscv/decoder.cc index d225871241..b1e2948e93 100644 --- a/src/arch/riscv/decoder.cc +++ b/src/arch/riscv/decoder.cc @@ -96,6 +96,8 @@ Decoder::decode(ExtMachInst mach_inst, Addr addr) if (!si) si = decodeInst(mach_inst); + si->size(compressed(mach_inst) ? 2 : 4); + DPRINTF(Decode, "Decode: Decoded %s instruction: %#x\n", si->getName(), mach_inst); return si; @@ -122,6 +124,7 @@ Decoder::decode(PCStateBase &_next_pc) emi.vtype8 = next_pc.vtype() & 0xff; emi.vill = next_pc.vtype().vill; emi.rv_type = static_cast(next_pc.rvType()); + return decode(emi, next_pc.instAddr()); } diff --git a/src/arch/riscv/insts/static_inst.hh b/src/arch/riscv/insts/static_inst.hh index 74f9ddb452..2e4d94864a 100644 --- a/src/arch/riscv/insts/static_inst.hh +++ b/src/arch/riscv/insts/static_inst.hh @@ -146,6 +146,15 @@ class RiscvMacroInst : public RiscvStaticInst { panic("Tried to execute a macroop directly!\n"); } + + void size(size_t newSize) override + { + for (int i = 0; i < microops.size(); i++) { + microops[i]->size(newSize); + } + _size = newSize; + } + }; /** diff --git a/src/arch/x86/decoder.cc b/src/arch/x86/decoder.cc index ef87ff37c4..af2456d6ab 100644 --- a/src/arch/x86/decoder.cc +++ b/src/arch/x86/decoder.cc @@ -687,6 +687,8 @@ Decoder::decode(ExtMachInst mach_inst, Addr addr) (*instMap)[mach_inst] = si; } + si->size(basePC + offset - origPC); + DPRINTF(Decode, "Decode: Decoded %s instruction: %#x\n", si->getName(), mach_inst); return si; @@ -732,8 +734,7 @@ Decoder::decode(PCStateBase &next_pc) start = 0; } - si = decode(emi, origPC); - return si; + return decode(emi, origPC); } StaticInstPtr diff --git a/src/arch/x86/insts/macroop.hh b/src/arch/x86/insts/macroop.hh index 36718f77fd..071037b173 100644 --- a/src/arch/x86/insts/macroop.hh +++ b/src/arch/x86/insts/macroop.hh @@ -103,6 +103,14 @@ class MacroopBase : public X86StaticInst { return env; } + + void size(size_t newSize) override + { + for (int i = 0; i < numMicroops; i++) { + microops[i]->size(newSize); + } + _size = newSize; + } }; } // namespace X86ISA diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh index 7ecc57d2f0..b98c01f872 100644 --- a/src/cpu/static_inst.hh +++ b/src/cpu/static_inst.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2017, 2020 ARM Limited + * Copyright (c) 2022-2023 The University of Edinburgh * All rights reserved * * The license below extends only to copyright in the software and shall @@ -250,6 +251,11 @@ class StaticInst : public RefCounted, public StaticInstFlags _destRegIdxPtr = dest; } + /** + * Instruction size in bytes. Necessary for dynamic instruction sizes + */ + size_t _size = 0; + /** * Base mnemonic (e.g., "add"). Used by generateDisassembly() * methods. Also useful to readily identify instructions from @@ -307,6 +313,17 @@ class StaticInst : public RefCounted, public StaticInstFlags panic("buildRetPC not defined!"); } + size_t size() const + { + if (_size == 0) fatal( + "Instruction size for this instruction not set! It's size is " + "required for the decoupled front-end. Either use the standard " + "front-end or this ISA needs to be extended with the instruction " + "size. Refer to the X86, Arm or RiscV decoders for an example."); + return _size; + } + virtual void size(size_t newSize) { _size = newSize; } + /** * Return the microop that goes with a particular micropc. This should * only be defined/used in macroops which will contain microops