From: Sandipan Das Date: Wed, 6 Jun 2018 21:27:03 +0000 (+0530) Subject: arch-power: Fix fixed-point load and store instructions X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e0532a971be556ef89bf6522a857a909b8906bf9;p=gem5.git 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 --- diff --git a/src/arch/power/insts/mem.cc b/src/arch/power/insts/mem.cc index 68a33c6a3..85a5aee83 100644 --- a/src/arch/power/insts/mem.cc +++ b/src/arch/power/insts/mem.cc @@ -40,6 +40,7 @@ MemOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const return csprintf("%-10s", mnemonic); } + std::string MemDispOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const { @@ -60,16 +61,160 @@ MemDispOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const // 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 6c41b1636..ad2c23fce 100644 --- a/src/arch/power/insts/mem.hh +++ b/src/arch/power/insts/mem.hh @@ -77,6 +77,44 @@ class MemDispOp : public MemOp Addr pc, const 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 bce946557..19c6669d2 100644 --- a/src/arch/power/isa/decoder.isa +++ b/src/arch/power/isa/decoder.isa @@ -146,14 +146,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; }}); } } @@ -161,19 +159,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 { @@ -253,9 +251,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; }}); @@ -265,7 +263,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; }}); @@ -274,10 +272,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) { @@ -296,7 +294,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 47ffc916b..31c050e20 100644 --- a/src/arch/power/isa/formats/mem.isa +++ b/src/arch/power/isa/formats/mem.isa @@ -239,7 +239,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) }}; @@ -248,7 +248,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) }}; @@ -261,7 +261,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') }}; @@ -275,7 +275,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') }}; @@ -298,6 +298,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 75511712e..c50c3e6fd 100644 --- a/src/arch/power/isa/operands.isa +++ b/src/arch/power/isa/operands.isa @@ -43,9 +43,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 83917ec0c..929f765e0 100644 --- a/src/arch/power/types.hh +++ b/src/arch/power/types.hh @@ -54,6 +54,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;