From 48f338c44c7d69d2aa93d6ea5c7145bd90c9253d Mon Sep 17 00:00:00 2001 From: Sandipan Das Date: Thu, 7 Jun 2018 02:57:03 +0530 Subject: [PATCH] arch-power: Fix fixed-point load and store instructions This fixes the following load and store instructions as a result of the change in register widths: * Load Word and Zero (lwz) * Load Word and Zero Indexed (lwzx) * Load Word and Zero with Update (lwzu) * Load Word and Zero with Update Indexed (lwzux) * Load Word Algebraic (lwa) * Load Word And Reserve Indexed (lwarx) * Store Word (stw) * Store Word Indexed (stwx) * Store Word with Update (stwu) * Store Word with Update Indexed (stwux) * Store Word Conditional Indexed (stwcx.) This also fixes disassembly generation for all of the above. Change-Id: I1a25cdb5ffe86145b7ffcf2c2bd7b27048a415d2 Signed-off-by: Sandipan Das --- src/arch/power/insts/mem.cc | 153 ++++++++++++++++++++++++++++- src/arch/power/insts/mem.hh | 38 +++++++ src/arch/power/isa/decoder.isa | 26 +++-- src/arch/power/isa/formats/mem.isa | 18 +++- src/arch/power/isa/operands.isa | 6 +- src/arch/power/types.hh | 1 + 6 files changed, 217 insertions(+), 25 deletions(-) diff --git a/src/arch/power/insts/mem.cc b/src/arch/power/insts/mem.cc index 8566f04bb..dc7eebd22 100644 --- a/src/arch/power/insts/mem.cc +++ b/src/arch/power/insts/mem.cc @@ -38,6 +38,7 @@ MemOp::generateDisassembly(Addr pc, const Loader::SymbolTable *symtab) const return csprintf("%-10s", mnemonic); } + std::string MemDispOp::generateDisassembly( Addr pc, const Loader::SymbolTable *symtab) const @@ -59,16 +60,160 @@ MemDispOp::generateDisassembly( // Print the data register for a store else { - printReg(ss, _srcRegIdx[1]); + if (_numSrcRegs > 0) { + printReg(ss, _srcRegIdx[0]); + } } // Print the displacement - ss << ", " << (int32_t)disp; + ss << ", " << disp; + ss << "("; + + // Print the address register for a load + if (!flags[IsStore]) { + if (_numSrcRegs > 0) { + printReg(ss, _srcRegIdx[0]); + } + + // The address register is skipped if it is R0 + else { + ss << "0"; + } + } + + // Print the address register for a store + else { + if (_numSrcRegs > 1) { + printReg(ss, _srcRegIdx[1]); + } + + // The address register is skipped if it is R0 + else { + ss << "0"; + } + } + + ss << ")"; + + return ss.str(); +} + + +std::string +MemDispShiftOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + // Print the destination only for a load + if (!flags[IsStore]) { + if (_numDestRegs > 0) { + + // If the instruction updates the source register with the + // EA, then this source register is placed in position 0, + // therefore we print the last destination register. + printReg(ss, _destRegIdx[_numDestRegs-1]); + } + } + + // Print the data register for a store + else { + if (_numSrcRegs > 0) { + printReg(ss, _srcRegIdx[0]); + } + } - // Print the address register + // Print the displacement + ss << ", " << (disp << 2); ss << "("; - printReg(ss, _srcRegIdx[0]); + + // Print the address register for a load + if (!flags[IsStore]) { + if (_numSrcRegs > 0) { + printReg(ss, _srcRegIdx[0]); + } + + // The address register is skipped if it is R0 + else { + ss << "0"; + } + } + + // Print the address register for a store + else { + if (_numSrcRegs > 1) { + printReg(ss, _srcRegIdx[1]); + } + + // The address register is skipped if it is R0 + else { + ss << "0"; + } + } + ss << ")"; return ss.str(); } + + +std::string +MemIndexOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const +{ + std::stringstream ss; + + ccprintf(ss, "%-10s ", mnemonic); + + // Print the destination only for a load + if (!flags[IsStore]) { + if (_numDestRegs > 0) { + + // If the instruction updates the source register with the + // EA, then this source register is placed in position 0, + // therefore we print the last destination register. + printReg(ss, _destRegIdx[_numDestRegs-1]); + } + } + + // Print the data register for a store + else { + if (_numSrcRegs > 0) { + printReg(ss, _srcRegIdx[0]); + } + } + + ss << ", "; + + // Print the address registers for a load + if (!flags[IsStore]) { + if (_numSrcRegs > 1) { + printReg(ss, _srcRegIdx[0]); + ss << ", "; + printReg(ss, _srcRegIdx[1]); + } + + // The first address register is skipped if it is R0 + else if (_numSrcRegs > 0) { + ss << "0, "; + printReg(ss, _srcRegIdx[0]); + } + } + + // Print the address registers for a store + else { + if (_numSrcRegs > 2) { + printReg(ss, _srcRegIdx[1]); + ss << ", "; + printReg(ss, _srcRegIdx[2]); + } + + // The first address register is skipped if it is R0 + else if (_numSrcRegs > 1) { + ss << "0, "; + printReg(ss, _srcRegIdx[1]); + } + } + + return ss.str(); +} diff --git a/src/arch/power/insts/mem.hh b/src/arch/power/insts/mem.hh index de9b46cdb..d489455c9 100644 --- a/src/arch/power/insts/mem.hh +++ b/src/arch/power/insts/mem.hh @@ -75,6 +75,44 @@ class MemDispOp : public MemOp Addr pc, const Loader::SymbolTable *symtab) const override; }; +/** + * Class for memory operations with shifted displacement. + */ +class MemDispShiftOp : public MemOp +{ + protected: + + int16_t disp; + + /// Constructor + MemDispShiftOp(const char *mnem, MachInst _machInst, OpClass __opClass) + : MemOp(mnem, _machInst, __opClass), + disp(sext<14>(machInst.ds)) + { + } + + std::string generateDisassembly( + Addr pc, const SymbolTable *symtab) const override; +}; + + +/** + * Class for memory operations with register indexed addressing. + */ +class MemIndexOp : public MemOp +{ + protected: + + /// Constructor + MemIndexOp(const char *mnem, MachInst _machInst, OpClass __opClass) + : MemOp(mnem, _machInst, __opClass) + { + } + + std::string generateDisassembly( + Addr pc, const SymbolTable *symtab) const override; +}; + } // namespace PowerISA #endif //__ARCH_POWER_INSTS_MEM_HH__ diff --git a/src/arch/power/isa/decoder.isa b/src/arch/power/isa/decoder.isa index 4dd555c72..85b554172 100644 --- a/src/arch/power/isa/decoder.isa +++ b/src/arch/power/isa/decoder.isa @@ -144,14 +144,12 @@ decode PO default Unknown::unknown() { 34: lbz({{ Rt = Mem_ub; }}); 40: lhz({{ Rt = Mem_uh; }}); 42: lha({{ Rt = Mem_sh; }}); - 32: lwz({{ Rt = Mem; }}); + 32: lwz({{ Rt = Mem_uw; }}); } 58: decode DS_XO { - format LoadDispOp { - 2: lwa({{ Rt = Mem_sw; }}, - {{ EA = Ra + (disp & 0xfffffffc); }}, - {{ EA = disp & 0xfffffffc; }}); + format LoadDispShiftOp { + 2: lwa({{ Rt = Mem_sw; }}); } } @@ -159,19 +157,19 @@ decode PO default Unknown::unknown() { 35: lbzu({{ Rt = Mem_ub; }}); 41: lhzu({{ Rt = Mem_uh; }}); 43: lhau({{ Rt = Mem_sh; }}); - 33: lwzu({{ Rt = Mem; }}); + 33: lwzu({{ Rt = Mem_uw; }}); } format StoreDispOp { 38: stb({{ Mem_ub = Rs_ub; }}); 44: sth({{ Mem_uh = Rs_uh; }}); - 36: stw({{ Mem = Rs; }}); + 36: stw({{ Mem = Rs_uw; }}); } format StoreDispUpdateOp { 39: stbu({{ Mem_ub = Rs_ub; }}); 45: sthu({{ Mem_uh = Rs_uh; }}); - 37: stwu({{ Mem = Rs; }}); + 37: stwu({{ Mem = Rs_uw; }}); } format IntImmArithCheckRaOp { @@ -251,9 +249,9 @@ decode PO default Unknown::unknown() { 87: lbzx({{ Rt = Mem_ub; }}); 279: lhzx({{ Rt = Mem_uh; }}); 343: lhax({{ Rt = Mem_sh; }}); - 23: lwzx({{ Rt = Mem; }}); + 23: lwzx({{ Rt = Mem_uw; }}); 341: lwax({{ Rt = Mem_sw; }}); - 20: lwarx({{ Rt = Mem_sw; Rsv = 1; RsvLen = 4; RsvAddr = EA; }}); + 20: lwarx({{ Rt = Mem_uw; Rsv = 1; RsvLen = 4; RsvAddr = EA; }}); 535: lfsx({{ Ft_sf = Mem_sf; }}); 599: lfdx({{ Ft = Mem_df; }}); 855: lfiwax({{ Ft_uw = Mem; }}); @@ -263,7 +261,7 @@ decode PO default Unknown::unknown() { 119: lbzux({{ Rt = Mem_ub; }}); 311: lhzux({{ Rt = Mem_uh; }}); 375: lhaux({{ Rt = Mem_sh; }}); - 55: lwzux({{ Rt = Mem; }}); + 55: lwzux({{ Rt = Mem_uw; }}); 373: lwaux({{ Rt = Mem_sw; }}); 567: lfsux({{ Ft_sf = Mem_sf; }}); 631: lfdux({{ Ft = Mem_df; }}); @@ -272,10 +270,10 @@ decode PO default Unknown::unknown() { format StoreIndexOp { 215: stbx({{ Mem_ub = Rs_ub; }}); 407: sthx({{ Mem_uh = Rs_uh; }}); - 151: stwx({{ Mem = Rs; }}); + 151: stwx({{ Mem_uw = Rs_uw; }}); 150: stwcx({{ bool store_performed = false; - Mem = Rs; + Mem_uw = Rs_uw; if (Rsv) { if (RsvLen == 4) { if (RsvAddr == EA) { @@ -294,7 +292,7 @@ decode PO default Unknown::unknown() { format StoreIndexUpdateOp { 247: stbux({{ Mem_ub = Rs_ub; }}); 439: sthux({{ Mem_uh = Rs_uh; }}); - 183: stwux({{ Mem = Rs; }}); + 183: stwux({{ Mem_uw = Rs_uw; }}); } format IntOp { diff --git a/src/arch/power/isa/formats/mem.isa b/src/arch/power/isa/formats/mem.isa index d0ce1a5ac..bd99a683c 100644 --- a/src/arch/power/isa/formats/mem.isa +++ b/src/arch/power/isa/formats/mem.isa @@ -237,7 +237,7 @@ def format LoadIndexOp(memacc_code, ea_code = {{ EA = Ra + Rb; }}, mem_flags = [], inst_flags = []) {{ (header_output, decoder_output, decode_block, exec_output) = \ GenMemOp(name, Name, memacc_code, ea_code, ea_code_ra0, - 'MemOp', 'Load', mem_flags, inst_flags) + 'MemIndexOp', 'Load', mem_flags, inst_flags) }}; @@ -246,7 +246,7 @@ def format StoreIndexOp(memacc_code, ea_code = {{ EA = Ra + Rb; }}, mem_flags = [], inst_flags = []) {{ (header_output, decoder_output, decode_block, exec_output) = \ GenMemOp(name, Name, memacc_code, ea_code, ea_code_ra0, - 'MemOp', 'Store', mem_flags, inst_flags) + 'MemIndexOp', 'Store', mem_flags, inst_flags) }}; @@ -259,7 +259,7 @@ def format LoadIndexUpdateOp(memacc_code, ea_code = {{ EA = Ra + Rb; }}, # Generate the class (header_output, decoder_output, decode_block, exec_output) = \ LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, - base_class = 'MemOp', + base_class = 'MemIndexOp', exec_template_base = 'Load') }}; @@ -273,7 +273,7 @@ def format StoreIndexUpdateOp(memacc_code, ea_code = {{ EA = Ra + Rb; }}, # Generate the class (header_output, decoder_output, decode_block, exec_output) = \ LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, - base_class = 'MemOp', + base_class = 'MemIndexOp', exec_template_base = 'Store') }}; @@ -296,6 +296,16 @@ def format StoreDispOp(memacc_code, ea_code = {{ EA = Ra + disp; }}, }}; +def format LoadDispShiftOp(memacc_code, + ea_code = {{ EA = Ra + (disp << 2); }}, + ea_code_ra0 = {{ EA = (disp << 2); }}, + mem_flags = [], inst_flags = []) {{ + (header_output, decoder_output, decode_block, exec_output) = \ + GenMemOp(name, Name, memacc_code, ea_code, ea_code_ra0, + 'MemDispShiftOp', 'Load', mem_flags, inst_flags) +}}; + + def format LoadDispUpdateOp(memacc_code, ea_code = {{ EA = Ra + disp; }}, mem_flags = [], inst_flags = []) {{ diff --git a/src/arch/power/isa/operands.isa b/src/arch/power/isa/operands.isa index 25756357b..6cc72fe04 100644 --- a/src/arch/power/isa/operands.isa +++ b/src/arch/power/isa/operands.isa @@ -41,9 +41,9 @@ def operand_types {{ def operands {{ # General Purpose Integer Reg Operands - 'Ra': ('IntReg', 'ud', 'RA', 'IsInteger', 1), - 'Rb': ('IntReg', 'ud', 'RB', 'IsInteger', 2), - 'Rs': ('IntReg', 'ud', 'RS', 'IsInteger', 3), + 'Rs': ('IntReg', 'ud', 'RS', 'IsInteger', 1), + 'Ra': ('IntReg', 'ud', 'RA', 'IsInteger', 2), + 'Rb': ('IntReg', 'ud', 'RB', 'IsInteger', 3), 'Rt': ('IntReg', 'ud', 'RT', 'IsInteger', 4), # General Purpose Floating Point Reg Operands diff --git a/src/arch/power/types.hh b/src/arch/power/types.hh index e37659c89..1221f1246 100644 --- a/src/arch/power/types.hh +++ b/src/arch/power/types.hh @@ -52,6 +52,7 @@ BitUnion32(ExtMachInst) // Immediate fields Bitfield<15, 0> si; Bitfield<15, 0> d; + Bitfield<15, 2> ds; // Special purpose register identifier Bitfield<20, 11> spr; -- 2.30.2