summaryrefslogtreecommitdiff
path: root/src/arch/arm/isa/formats/branch.isa
diff options
context:
space:
mode:
authorStephen Hines <hines@cs.fsu.edu>2009-04-05 18:53:15 -0700
committerStephen Hines <hines@cs.fsu.edu>2009-04-05 18:53:15 -0700
commit7a7c4c5fca83a8d47c7e71c9c080a882ebe204a9 (patch)
tree727269d84fb4ba0e7db6e1c7ffdeb3e114b71773 /src/arch/arm/isa/formats/branch.isa
parent65332ef3a9df48f7ff11b417b0ffc4a171824931 (diff)
downloadgem5-7a7c4c5fca83a8d47c7e71c9c080a882ebe204a9.tar.xz
arm: add ARM support to M5
Diffstat (limited to 'src/arch/arm/isa/formats/branch.isa')
-rw-r--r--src/arch/arm/isa/formats/branch.isa307
1 files changed, 307 insertions, 0 deletions
diff --git a/src/arch/arm/isa/formats/branch.isa b/src/arch/arm/isa/formats/branch.isa
new file mode 100644
index 000000000..40aa4a952
--- /dev/null
+++ b/src/arch/arm/isa/formats/branch.isa
@@ -0,0 +1,307 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2007-2008 The Florida State University
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: Stephen Hines
+
+////////////////////////////////////////////////////////////////////
+//
+// Control transfer instructions
+//
+
+output header {{
+
+#include <iostream>
+
+ /**
+ * Base class for instructions whose disassembly is not purely a
+ * function of the machine instruction (i.e., it depends on the
+ * PC). This class overrides the disassemble() method to check
+ * the PC and symbol table values before re-using a cached
+ * disassembly string. This is necessary for branches and jumps,
+ * where the disassembly string includes the target address (which
+ * may depend on the PC and/or symbol table).
+ */
+ class PCDependentDisassembly : public PredOp
+ {
+ protected:
+ /// Cached program counter from last disassembly
+ mutable Addr cachedPC;
+
+ /// Cached symbol table pointer from last disassembly
+ mutable const SymbolTable *cachedSymtab;
+
+ /// Constructor
+ PCDependentDisassembly(const char *mnem, MachInst _machInst,
+ OpClass __opClass)
+ : PredOp(mnem, _machInst, __opClass),
+ cachedPC(0), cachedSymtab(0)
+ {
+ }
+
+ const std::string &
+ disassemble(Addr pc, const SymbolTable *symtab) const;
+ };
+
+ /**
+ * Base class for branches (PC-relative control transfers),
+ * conditional or unconditional.
+ */
+ class Branch : public PCDependentDisassembly
+ {
+ protected:
+ /// target address (signed) Displacement .
+ int32_t disp;
+
+ /// Constructor.
+ Branch(const char *mnem, MachInst _machInst, OpClass __opClass)
+ : PCDependentDisassembly(mnem, _machInst, __opClass),
+ disp(OFFSET << 2)
+ {
+ //If Bit 26 is 1 then Sign Extend
+ if ( (disp & 0x02000000) > 0 ) {
+ disp |= 0xFC000000;
+ }
+ }
+
+ Addr branchTarget(Addr branchPC) const;
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+
+ /**
+ * Base class for branch and exchange instructions on the ARM
+ */
+ class BranchExchange : public PredOp
+ {
+ protected:
+ /// Constructor
+ BranchExchange(const char *mnem, MachInst _machInst,
+ OpClass __opClass)
+ : PredOp(mnem, _machInst, __opClass)
+ {
+ }
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+
+
+ /**
+ * Base class for jumps (register-indirect control transfers). In
+ * the Arm ISA, these are always unconditional.
+ */
+ class Jump : public PCDependentDisassembly
+ {
+ protected:
+
+ /// Displacement to target address (signed).
+ int32_t disp;
+
+ uint32_t target;
+
+ public:
+ /// Constructor
+ Jump(const char *mnem, MachInst _machInst, OpClass __opClass)
+ : PCDependentDisassembly(mnem, _machInst, __opClass),
+ disp(OFFSET << 2)
+ {
+ }
+
+ Addr branchTarget(ThreadContext *tc) const;
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ Addr
+ Branch::branchTarget(Addr branchPC) const
+ {
+ return branchPC + 8 + disp;
+ }
+
+ Addr
+ Jump::branchTarget(ThreadContext *tc) const
+ {
+ Addr NPC = tc->readPC() + 8;
+ uint64_t Rb = tc->readIntReg(_srcRegIdx[0]);
+ return (Rb & ~3) | (NPC & 1);
+ }
+
+ const std::string &
+ PCDependentDisassembly::disassemble(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ if (!cachedDisassembly ||
+ pc != cachedPC || symtab != cachedSymtab)
+ {
+ if (cachedDisassembly)
+ delete cachedDisassembly;
+
+ cachedDisassembly =
+ new std::string(generateDisassembly(pc, symtab));
+ cachedPC = pc;
+ cachedSymtab = symtab;
+ }
+
+ return *cachedDisassembly;
+ }
+
+ std::string
+ Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+ Addr target = pc + 8 + disp;
+
+ std::string str;
+ if (symtab && symtab->findSymbol(target, str))
+ ss << str;
+ else
+ ccprintf(ss, "0x%x", target);
+
+ return ss.str();
+ }
+
+ std::string
+ BranchExchange::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+ if (_numSrcRegs > 0) {
+ printReg(ss, _srcRegIdx[0]);
+ }
+
+ return ss.str();
+ }
+
+ std::string
+ Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+ return ss.str();
+ }
+}};
+
+def format Branch(code,*opt_flags) {{
+
+ #Build Instruction Flags
+ #Use Link & Likely Flags to Add Link/Condition Code
+ inst_flags = ('IsDirectControl', )
+ for x in opt_flags:
+ if x == 'Link':
+ code += 'LR = NPC;\n'
+ else:
+ inst_flags += (x, )
+
+ #Take into account uncond. branch instruction
+ if 'cond == 1' in code:
+ inst_flags += ('IsUnCondControl', )
+ else:
+ inst_flags += ('IsCondControl', )
+
+ icode = 'if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) {\n'
+ icode += code
+ icode += ' NPC = NPC + 4 + disp;\n'
+ icode += '} else {\n'
+ icode += ' NPC = NPC;\n'
+ icode += '};\n'
+
+ code = icode
+
+ iop = InstObjParams(name, Name, 'Branch', code, inst_flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+def format BranchExchange(code,*opt_flags) {{
+ #Build Instruction Flags
+ #Use Link & Likely Flags to Add Link/Condition Code
+ inst_flags = ('IsIndirectControl', )
+ for x in opt_flags:
+ if x == 'Link':
+ code += 'LR = NPC;\n'
+ else:
+ inst_flags += (x, )
+
+ #Take into account uncond. branch instruction
+ if 'cond == 1' in code:
+ inst_flags += ('IsUnCondControl', )
+ else:
+ inst_flags += ('IsCondControl', )
+
+ #Condition code
+
+ icode = 'if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode)) {\n'
+ icode += code
+ icode += ' NPC = Rm & 0xfffffffe; // Masks off bottom bit\n'
+ icode += '} else {\n'
+ icode += ' NPC = NPC;\n'
+ icode += '};\n'
+
+ code = icode
+
+ iop = InstObjParams(name, Name, 'BranchExchange', code, inst_flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+def format Jump(code, *opt_flags) {{
+ #Build Instruction Flags
+ #Use Link Flag to Add Link Code
+ inst_flags = ('IsIndirectControl', 'IsUncondControl')
+ for x in opt_flags:
+ if x == 'Link':
+ code = 'LR = NPC;\n' + code
+ elif x == 'ClearHazards':
+ code += '/* Code Needed to Clear Execute & Inst Hazards */\n'
+ else:
+ inst_flags += (x, )
+
+ iop = InstObjParams(name, Name, 'Jump', code, inst_flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+ #exec_output = PredOpExecute.subst(iop)
+}};
+
+