arch-power: Fix branch instructions
authorSandipan Das <sandipan@linux.vnet.ibm.com>
Thu, 7 Jun 2018 14:30:41 +0000 (20:00 +0530)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 24 Jan 2021 03:39:23 +0000 (03:39 +0000)
This fixes the following branch instructions in order to
support 64-bit addressing:
  * Branch (b[l][a])
  * Branch Conditional (bc[l][a])
  * Branch Conditional to Link Register (bclr[l])
  * Branch Conditional to Count Register (bcctr[l])

This also fixes disassembly generation for all of the above.

Change-Id: I7cad4e1b3b2945ab06c4ffc8c79842f1453c85ec
Signed-off-by: Sandipan Das <sandipan@linux.vnet.ibm.com>
src/arch/power/insts/branch.cc
src/arch/power/insts/branch.hh
src/arch/power/isa/decoder.isa
src/arch/power/isa/formats/branch.isa
src/arch/power/isa/formats/util.isa
src/arch/power/types.hh

index 3511b6b3c9d3e1e331b6f7cc0a591627d2d17340..fce3d3f64827706fb570354327e77cb548416a0d 100644 (file)
@@ -52,21 +52,37 @@ PCDependentDisassembly::disassemble(
     return *cachedDisassembly;
 }
 
+
 PowerISA::PCState
-BranchPCRel::branchTarget(const PowerISA::PCState &pc) const
+BranchOp::branchTarget(const PowerISA::PCState &pc) const
 {
-    return (uint32_t)(pc.pc() + disp);
+    if (aaSet) {
+        return disp;
+    } else {
+        return pc.pc() + disp;
+    }
 }
 
+
 std::string
-BranchPCRel::generateDisassembly(
-        Addr pc, const Loader::SymbolTable *symtab) const
+BranchOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
 {
     std::stringstream ss;
+    Addr target;
 
-    ccprintf(ss, "%-10s ", mnemonic);
+    // Generate correct mnemonic
+    std::string myMnemonic(mnemonic);
+
+    // Additional characters depending on isa bits being set
+    if (lkSet) myMnemonic = myMnemonic + "l";
+    if (aaSet) myMnemonic = myMnemonic + "a";
+    ccprintf(ss, "%-10s ", myMnemonic);
 
-    Addr target = pc + disp;
+    if (aaSet) {
+        target = disp;
+    } else {
+        target = pc + disp;
+    }
 
     Loader::SymbolTable::const_iterator it;
     if (symtab && (it = symtab->find(target)) != symtab->end())
@@ -77,46 +93,40 @@ BranchPCRel::generateDisassembly(
     return ss.str();
 }
 
-PowerISA::PCState
-BranchNonPCRel::branchTarget(const PowerISA::PCState &pc) const
-{
-    return targetAddr;
-}
-
-std::string
-BranchNonPCRel::generateDisassembly(
-        Addr pc, const Loader::SymbolTable *symtab) const
-{
-    std::stringstream ss;
-
-    ccprintf(ss, "%-10s ", mnemonic);
-
-    Loader::SymbolTable::const_iterator it;
-    if (symtab && (it = symtab->find(targetAddr)) != symtab->end())
-        ss << it->name;
-    else
-        ccprintf(ss, "%#x", targetAddr);
-
-    return ss.str();
-}
 
 PowerISA::PCState
-BranchPCRelCond::branchTarget(const PowerISA::PCState &pc) const
+BranchDispCondOp::branchTarget(const PowerISA::PCState &pc) const
 {
-    return (uint32_t)(pc.pc() + disp);
+    if (aaSet) {
+        return disp;
+    } else {
+        return pc.pc() + disp;
+    }
 }
 
+
 std::string
-BranchPCRelCond::generateDisassembly(
-        Addr pc, const Loader::SymbolTable *symtab) const
+BranchDispCondOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
 {
     std::stringstream ss;
+    Addr target;
 
-    ccprintf(ss, "%-10s ", mnemonic);
+    // Generate the correct mnemonic
+    std::string myMnemonic(mnemonic);
 
-    ss << bo << ", " << bi << ", ";
+    // Additional characters depending on isa bits being set
+    if (lkSet) myMnemonic = myMnemonic + "l";
+    if (aaSet) myMnemonic = myMnemonic + "a";
+    ccprintf(ss, "%-10s ", myMnemonic);
 
-    Addr target = pc + disp;
+    // Print BI and BO fields
+    ss << crBit << ", " << opts << ", ";
+
+    if (aaSet) {
+        target = disp;
+    } else {
+        target = pc + disp;
+    }
 
     Loader::SymbolTable::const_iterator it;
     if (symtab && (it = symtab->find(target)) != symtab->end())
@@ -127,47 +137,29 @@ BranchPCRelCond::generateDisassembly(
     return ss.str();
 }
 
-PowerISA::PCState
-BranchNonPCRelCond::branchTarget(const PowerISA::PCState &pc) const
-{
-    return targetAddr;
-}
-
-std::string
-BranchNonPCRelCond::generateDisassembly(
-        Addr pc, const Loader::SymbolTable *symtab) const
-{
-    std::stringstream ss;
-
-    ccprintf(ss, "%-10s ", mnemonic);
-
-    ss << bo << ", " << bi << ", ";
-
-    Loader::SymbolTable::const_iterator it;
-    if (symtab && (it = symtab->find(targetAddr)) != symtab->end())
-        ss << it->name;
-    else
-        ccprintf(ss, "%#x", targetAddr);
-
-    return ss.str();
-}
 
 PowerISA::PCState
-BranchRegCond::branchTarget(ThreadContext *tc) const
+BranchRegCondOp::branchTarget(ThreadContext *tc) const
 {
-    uint32_t regVal = tc->readIntReg(_srcRegIdx[_numSrcRegs - 1].index());
-    return regVal & 0xfffffffc;
+    Addr addr = tc->readIntReg(_srcRegIdx[_numSrcRegs - 1].index());
+    return addr & -4ULL;
 }
 
+
 std::string
-BranchRegCond::generateDisassembly(
-        Addr pc, const Loader::SymbolTable *symtab) const
+BranchRegCondOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
 {
     std::stringstream ss;
 
+    // Generate the correct mnemonic
+    std::string myMnemonic(mnemonic);
+
+    // Additional characters depending on isa bits being set
+    if (lkSet) myMnemonic = myMnemonic + "l";
     ccprintf(ss, "%-10s ", mnemonic);
 
-    ss << bo << ", " << bi << ", ";
+    // Print the BI and BO fields
+    ss << crBit << ", " << opts;
 
     return ss.str();
 }
index 435b4fdff29ad8e9a2a81cadc0ebc47b0609a13d..1a010221060a06ab6be26d93d7e5c2c1454f646e 100644 (file)
@@ -63,55 +63,25 @@ class PCDependentDisassembly : public PowerStaticInst
     disassemble(Addr pc, const Loader::SymbolTable *symtab) const;
 };
 
-/**
- * Base class for unconditional, PC-relative branches.
- */
-class BranchPCRel : public PCDependentDisassembly
-{
-  protected:
-
-    /// Displacement
-    uint32_t disp;
-
-    /// Constructor.
-    BranchPCRel(const char *mnem, MachInst _machInst, OpClass __opClass)
-        : PCDependentDisassembly(mnem, _machInst, __opClass),
-          disp(machInst.li << 2)
-    {
-        // If bit 26 is 1 then sign extend
-        if (disp & 0x2000000) {
-            disp |= 0xfc000000;
-        }
-    }
-
-    PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const override;
-
-    /// Explicitly import the otherwise hidden branchTarget
-    using StaticInst::branchTarget;
-
-    std::string generateDisassembly(
-            Addr pc, const Loader::SymbolTable *symtab) const override;
-};
 
 /**
- * Base class for unconditional, non PC-relative branches.
+ * Base class for unconditional, PC-relative or absolute address branches.
  */
-class BranchNonPCRel : public PCDependentDisassembly
+class BranchOp : public PCDependentDisassembly
 {
   protected:
 
-    /// Target address
-    uint32_t targetAddr;
+    bool aaSet;
+    bool lkSet;
+    uint64_t disp;
 
-    /// Constructor.
-    BranchNonPCRel(const char *mnem, MachInst _machInst, OpClass __opClass)
-        : PCDependentDisassembly(mnem, _machInst, __opClass),
-          targetAddr(machInst.li << 2)
+    /// Constructor
+    BranchOp(const char *mnem, MachInst _machInst, OpClass __opClass)
+      : PCDependentDisassembly(mnem, _machInst, __opClass),
+        aaSet(false),
+        lkSet(false),
+        disp(sext<26>(machInst.li << 2))
     {
-        // If bit 26 is 1 then sign extend
-        if (targetAddr & 0x2000000) {
-            targetAddr |= 0xfc000000;
-        }
     }
 
     PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const override;
@@ -123,104 +93,74 @@ class BranchNonPCRel : public PCDependentDisassembly
             Addr pc, const Loader::SymbolTable *symtab) const override;
 };
 
+
 /**
  * Base class for conditional branches.
  */
-class BranchCond : public PCDependentDisassembly
+class BranchCondOp : public PCDependentDisassembly
 {
   protected:
 
-    /// Fields needed for conditions
-    uint32_t bo;
-    uint32_t bi;
+    bool lkSet;
+    uint32_t crBit;
+    uint32_t opts;
 
-    /// Constructor.
-    BranchCond(const char *mnem, MachInst _machInst, OpClass __opClass)
-        : PCDependentDisassembly(mnem, _machInst, __opClass),
-          bo(machInst.bo),
-          bi(machInst.bi)
+    /// Constructor
+    BranchCondOp(const char *mnem, MachInst _machInst, OpClass __opClass)
+      : PCDependentDisassembly(mnem, _machInst, __opClass),
+        lkSet(false),
+        crBit(machInst.bi),
+        opts(machInst.bo)
     {
     }
 
     inline bool
-    ctrOk(uint32_t& ctr) const
+    checkCtr(uint64_t& ctr) const
     {
-        bool ctr_ok;
-        if (bo & 4) {
-            ctr_ok = true;
+        bool ctrOk;
+        if (opts & 0x4) {
+            ctrOk = true;
         } else {
             ctr--;
             if (ctr != 0) {
-                ctr_ok = ((bo & 2) == 0);
+                ctrOk = ((opts & 0x2) == 0);
             } else {
-                ctr_ok = ((bo & 2) != 0);
+                ctrOk = ((opts & 0x2) != 0);
             }
         }
-        return ctr_ok;
+        return ctrOk;
     }
 
     inline bool
-    condOk(uint32_t cr) const
+    checkCond(uint32_t cr) const
     {
-        bool cond_ok;
-        if (bo & 16) {
-            cond_ok = true;
+        bool condOk;
+        if (opts & 0x10) {
+            condOk = true;
         } else {
-            cond_ok = (((cr >> (31 - bi)) & 1) == ((bo >> 3) & 1));
+            condOk = (((cr >> (31 - crBit)) & 0x1) == ((opts >> 3) & 0x1));
         }
-        return cond_ok;
+        return condOk;
     }
 };
 
-/**
- * Base class for conditional, PC-relative branches.
- */
-class BranchPCRelCond : public BranchCond
-{
-  protected:
-
-    /// Displacement
-    uint32_t disp;
-
-    /// Constructor.
-    BranchPCRelCond(const char *mnem, MachInst _machInst, OpClass __opClass)
-        : BranchCond(mnem, _machInst, __opClass),
-          disp(machInst.bd << 2)
-    {
-        // If bit 16 is 1 then sign extend
-        if (disp & 0x8000) {
-            disp |= 0xffff0000;
-        }
-    }
-
-    PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const override;
-
-    /// Explicitly import the otherwise hidden branchTarget
-    using StaticInst::branchTarget;
-
-    std::string generateDisassembly(
-            Addr pc, const Loader::SymbolTable *symtab) const override;
-};
 
 /**
- * Base class for conditional, non PC-relative branches.
+ * Base class for conditional, PC-relative or absolute address branches.
  */
-class BranchNonPCRelCond : public BranchCond
+class BranchDispCondOp : public BranchCondOp
 {
   protected:
 
-    /// Target address
-    uint32_t targetAddr;
+    bool aaSet;
+    uint64_t disp;
 
-    /// Constructor.
-    BranchNonPCRelCond(const char *mnem, MachInst _machInst, OpClass __opClass)
-        : BranchCond(mnem, _machInst, __opClass),
-          targetAddr(machInst.bd << 2)
+    /// Constructor
+    BranchDispCondOp(const char *mnem, MachInst _machInst, OpClass __opClass)
+      : BranchCondOp(mnem, _machInst, __opClass),
+        aaSet(false),
+        disp(sext<14>(machInst.bd << 2))
     {
-        // If bit 16 is 1 then sign extend
-        if (targetAddr & 0x8000) {
-            targetAddr |= 0xffff0000;
-        }
     }
 
     PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const override;
@@ -232,16 +172,22 @@ class BranchNonPCRelCond : public BranchCond
             Addr pc, const Loader::SymbolTable *symtab) const override;
 };
 
+
 /**
- * Base class for conditional, register-based branches
+ * Base class for conditional, register-based branches.
  */
-class BranchRegCond : public BranchCond
+class BranchRegCondOp : public BranchCondOp
 {
   protected:
 
+    // TODO: For now, the hint value (BH) is ignored and always considered
+    //       to be zero. Instruction flags should vary depending on this.
+    uint32_t hint;
+
     /// Constructor.
-    BranchRegCond(const char *mnem, MachInst _machInst, OpClass __opClass)
-        : BranchCond(mnem, _machInst, __opClass)
+    BranchRegCondOp(const char *mnem, MachInst _machInst, OpClass __opClass)
+      : BranchCondOp(mnem, _machInst, __opClass),
+        hint(machInst.bh)
     {
     }
 
index 7517c281819030d99caf85cead1ef50551f5d4ae..69048ba8cfffbfec7f82936d6cb7b6e524db08e4 100644 (file)
 //
 decode PO default Unknown::unknown() {
 
-    18: decode AA {
-
-        // Unconditionally branch relative to PC.
-        format BranchPCRel {
-            0: b({{ NIA = (uint32_t)(CIA + disp); }});
-        }
-
-        // Unconditionally branch to fixed address.
-        format BranchNonPCRel {
-            1: ba({{ NIA = targetAddr; }});
-        }
+    // Unconditionally branch to a PC-relative or absoulute address.
+    format BranchOp {
+        18: b({{ NIA = CIA + disp; }},
+              {{ NIA = disp; }});
     }
 
-    16: decode AA {
-
-        // Conditionally branch relative to PC based on CR and CTR.
-        format BranchPCRelCondCtr {
-            0: bc({{ NIA = (uint32_t)(CIA + disp); }});
-        }
-
-        // Conditionally branch to fixed address based on CR and CTR.
-        format BranchNonPCRelCondCtr {
-            1: bca({{ NIA = targetAddr; }});
-        }
+    // Conditionally branch to a PC-relative or absoulute address based
+    // on CR and CTR.
+    format BranchDispCondOp {
+        16: bc({{ NIA = CIA + disp; }},
+               {{ NIA = disp; }});
     }
 
     19: decode XL_XO {
 
-        // Conditionally branch to address in LR based on CR and CTR.
-        format BranchLrCondCtr {
-           16: bclr({{ NIA = LR & 0xfffffffc; }});
-        }
-
-        // Conditionally branch to address in CTR based on CR.
-        format BranchCtrCond {
-           528: bcctr({{ NIA = CTR & 0xfffffffc; }});
+        // Conditionally branch to an address in a register based on
+        // either CR only or both CR and CTR.
+        format BranchRegCondOp {
+            16: bclr({{ NIA = LR & -4ULL; }}, true, [ IsReturn ]);
+            528: bcctr({{ NIA = CTR & -4ULL; }});
         }
 
         // Condition register manipulation instructions.
index 3481438bbecf00c259785a1b9f1fbf00a6bf8ae3..8b7ee5e017cfa35a300282df23070b0658725307 100644 (file)
 // - Do not use bclrl as a subroutine call.
 //
 // Therefore, I've flagged all versions that update the link register (LR)
-// as calls, except bclrl (BranchLrCtrCond format) which is flagged as
+// as calls, except bclrl (BranchRegCondOp format) which is flagged as
 // a return.
 
 
-let {{
+// Instruction class constructor template when AA is set.
+def template BranchAaConstructor {{
+        %(class_name)s::%(class_name)s(ExtMachInst machInst)
+          : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
+        {
+            %(constructor)s;
+            aaSet = true;
+        }
+}};
 
-# Simple code to update link register (LR).
-updateLrCode = 'LR = CIA + 4;'
 
+// Instruction class constructor template when LK is set.
+def template BranchLkConstructor {{
+        %(class_name)s::%(class_name)s(ExtMachInst machInst)
+          : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
+        {
+            %(constructor)s;
+            lkSet = true;
+        }
 }};
 
-// Instructions that unconditionally branch relative to the current PC.
-def format BranchPCRel(br_code, inst_flags = []) {{
-    inst_flags += ('IsUncondControl', 'IsDirectControl')
-    basic_code = br_code
 
-    # The version that does not update LR
-    (header_output, decoder_output, decode_block, exec_output) = \
-        GenAluOp(name, Name, 'BranchPCRel', basic_code, inst_flags,
-                 CheckLkDecode, BasicConstructor)
+// Instruction class constructor template when both AA and LK are set.
+def template BranchAaLkConstructor {{
+        %(class_name)s::%(class_name)s(ExtMachInst machInst)
+          : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
+        {
+            %(constructor)s;
+            aaSet = true;
+            lkSet = true;
+        }
+}};
+
+
+let {{
+
+# Simple code to update link register (LR).
+updateLrCode = 'LR = CIA + 4;'
 
-    # The version that does the update
-    update_code = basic_code + updateLrCode
-    update_flags = inst_flags + [ 'IsCall' ]
-    (header_output_up, decoder_output_up, _, exec_output_up) = \
-        GenAluOp(name, Name + 'UpdateLr', 'BranchPCRel', update_code,
-                 update_flags, CheckLkDecode, BasicConstructor)
-
-    # Add the outputs together
-    header_output += header_output_up
-    decoder_output += decoder_output_up
-    exec_output += exec_output_up
 }};
 
-// Instructions that unconditionally branch to a specific address.
-def format BranchNonPCRel(br_code, inst_flags = []) {{
+
+// Instructions that unconditionally branch either to an address relative
+// to the current PC or an absolute address.
+def format BranchOp(code, code_aa1, inst_flags = []) {{
     inst_flags += ('IsUncondControl', 'IsDirectControl')
-    basic_code = br_code
 
-    # The version that does not update LR
-    (header_output, decoder_output, decode_block, exec_output) = \
-        GenAluOp(name, Name, 'BranchNonPCRel', basic_code, inst_flags,
-                 CheckLkDecode, BasicConstructor)
+    # Setup the 4 code versions and add code to update LR if necessary
+    code_lk1 = code + updateLrCode
+    code_aa1_lk1 = code_aa1 + updateLrCode
 
-    # The version that does the update
-    update_code = basic_code + updateLrCode
-    update_flags = inst_flags + [ 'IsCall' ]
-    (header_output_up, decoder_output_up, _, exec_output_up) = \
-        GenAluOp(name, Name + 'UpdateLr', 'BranchNonPCRel', update_code,
-                 update_flags, CheckLkDecode, BasicConstructor)
-
-    # Add the outputs together
-    header_output += header_output_up
-    decoder_output += decoder_output_up
-    exec_output += exec_output_up
+    # Generate the classes
+    (header_output, decoder_output, decode_block, exec_output) = \
+        GenAluOp(name, Name, 'BranchOp', code, inst_flags,
+                 CheckAaLkDecode, BasicConstructor)
+    (header_output_aa1, decoder_output_aa1, _, exec_output_aa1) = \
+        GenAluOp(name, Name + 'AaSet', 'BranchOp', code_aa1, inst_flags,
+                 CheckAaLkDecode, BranchAaConstructor)
+    (header_output_lk1, decoder_output_lk1, _, exec_output_lk1) = \
+        GenAluOp(name, Name + 'LkSet', 'BranchOp', code_lk1, inst_flags,
+                 CheckAaLkDecode, BranchLkConstructor)
+    (header_output_aa1_lk1, decoder_output_aa1_lk1, _, exec_output_aa1_lk1) = \
+        GenAluOp(name, Name + 'AaSetLkSet', 'BranchOp', code_aa1_lk1,
+                 inst_flags, CheckAaLkDecode, BranchAaLkConstructor)
+
+    # Finally, add to the other outputs
+    header_output += \
+        header_output_aa1 + header_output_lk1 + header_output_aa1_lk1
+    decoder_output += \
+        decoder_output_aa1 + decoder_output_lk1 + decoder_output_aa1_lk1
+    exec_output += \
+        exec_output_aa1 + exec_output_lk1 + exec_output_aa1_lk1
 }};
 
+
 let {{
 
 # Check the condition register (CR) allows the branch to be taken.
 def GetCondCode(br_code):
-    cond_code =  'if(condOk(CR)) {\n'
+    cond_code =  'if (checkCond(CR)) {\n'
     cond_code += '    ' + br_code + '\n'
     cond_code += '} else {\n'
     cond_code += '    NIA = NIA;\n'
@@ -109,12 +131,12 @@ def GetCondCode(br_code):
 
 # Check the condition register (CR) and count register (CTR) allow the
 # branch to be taken. Also, in certain situations, decrement the count
-# register too. This takes place in ctrOk within BranchCond classes.
+# register too. This takes place in checkCtr within BranchCondOp classes.
 def GetCtrCondCode(br_code):
-    cond_code =  'uint32_t ctr = CTR;\n'
-    cond_code += 'bool ctr_ok = ctrOk(ctr);\n'
-    cond_code += 'bool cond_ok = condOk(CR);\n'
-    cond_code += 'if(ctr_ok && cond_ok) {\n'
+    cond_code =  'uint64_t ctr = CTR;\n'
+    cond_code += 'bool ctrOk = checkCtr(ctr);\n'
+    cond_code += 'bool condOk = checkCond(CR);\n'
+    cond_code += 'if (ctrOk && condOk) {\n'
     cond_code += '    ' + br_code + '\n'
     cond_code += '} else {\n'
     cond_code += '    NIA = NIA;\n'
@@ -124,97 +146,70 @@ def GetCtrCondCode(br_code):
 
 }};
 
-// Instructions that conditionally branch relative to the current PC based on
-// the condition register (CR) and count register (CTR).
-def format BranchPCRelCondCtr(br_code, inst_flags = []) {{
-    inst_flags += ('IsCondControl', 'IsDirectControl')
-    basic_code = GetCtrCondCode(br_code)
-
-    # The version that does not update LR
-    (header_output, decoder_output, decode_block, exec_output) = \
-        GenAluOp(name, Name, 'BranchPCRelCond', basic_code, inst_flags,
-                 CheckLkDecode, BasicConstructor)
 
-    # The version that does the update
-    update_code = basic_code + updateLrCode
-    update_flags = inst_flags + [ 'IsCall' ]
-    (header_output_up, decoder_output_up, _, exec_output_up) = \
-        GenAluOp(name, Name + 'UpdateLr', 'BranchPCRelCond', update_code,
-                 update_flags, CheckLkDecode, BasicConstructor)
-
-    # Add the outputs together
-    header_output += header_output_up
-    decoder_output += decoder_output_up
-    exec_output += exec_output_up
-}};
-
-// Instructions that conditionally branch to a specific address based on the
+// Instructions that conditionally branch either to an address relative
+// to the current PC or an absolute address depending on the value of the
 // condition register (CR) and count register (CTR).
-def format BranchNonPCRelCondCtr(br_code, inst_flags = []) {{
+def format BranchDispCondOp(code, code_aa1, inst_flags = []) {{
     inst_flags += ('IsCondControl', 'IsDirectControl')
-    basic_code = GetCtrCondCode(br_code)
 
-    # The version that does not update LR
-    (header_output, decoder_output, decode_block, exec_output) = \
-        GenAluOp(name, Name, 'BranchNonPCRelCond', basic_code, inst_flags,
-                 CheckLkDecode, BasicConstructor)
+    # Setup the 4 code versions and add code to update LR if necessary
+    code = GetCtrCondCode(code)
+    code_aa1 = GetCtrCondCode(code_aa1)
+    code_lk1 = code + updateLrCode
+    code_aa1_lk1 = code_aa1 + updateLrCode
+    inst_flags_lk1 = inst_flags + [ 'IsCall' ]
 
-    # The version that does the update
-    update_code = basic_code + updateLrCode
-    update_flags = inst_flags + [ 'IsCall' ]
-    (header_output_up, decoder_output_up, _, exec_output_up) = \
-        GenAluOp(name, Name + 'UpdateLr', 'BranchNonPCRelCond', update_code,
-                 update_flags, CheckLkDecode, BasicConstructor)
-
-    # Add the outputs together
-    header_output += header_output_up
-    decoder_output += decoder_output_up
-    exec_output += exec_output_up
-}};
-
-// Instructions that conditionally branch to the address in the link register
-// (LR) based on the condition register (CR) and count register (CTR).
-def format BranchLrCondCtr(br_code, inst_flags = []) {{
-    inst_flags += ('IsCondControl', 'IsIndirectControl', 'IsReturn')
-    basic_code = GetCtrCondCode(br_code)
-
-    # The version that does not update LR
+    # Generate the classes
     (header_output, decoder_output, decode_block, exec_output) = \
-        GenAluOp(name, Name, 'BranchRegCond', basic_code, inst_flags,
-                 CheckLkDecode, BasicConstructor)
-
-    # The version that does the update
-    update_code = basic_code + updateLrCode
-    (header_output_up, decoder_output_up, _, exec_output_up) = \
-        GenAluOp(name, Name + 'UpdateLr', 'BranchRegCond', update_code,
-                 inst_flags, CheckLkDecode, BasicConstructor)
-
-    # Add the outputs together
-    header_output += header_output_up
-    decoder_output += decoder_output_up
-    exec_output += exec_output_up
+        GenAluOp(name, Name, 'BranchDispCondOp', code, inst_flags,
+                 CheckAaLkDecode, BasicConstructor)
+    (header_output_aa1, decoder_output_aa1, _, exec_output_aa1) = \
+        GenAluOp(name, Name + 'AaSet', 'BranchDispCondOp', code_aa1,
+                 inst_flags, CheckAaLkDecode, BranchAaConstructor)
+    (header_output_lk1, decoder_output_lk1, _, exec_output_lk1) = \
+        GenAluOp(name, Name + 'LkSet', 'BranchDispCondOp', code_lk1,
+                 inst_flags_lk1, CheckAaLkDecode, BranchLkConstructor)
+    (header_output_aa1_lk1, decoder_output_aa1_lk1, _, exec_output_aa1_lk1) = \
+        GenAluOp(name, Name + 'AaSetLkSet', 'BranchDispCondOp', code_aa1_lk1,
+                 inst_flags_lk1, CheckAaLkDecode, BranchAaLkConstructor)
+
+    # Finally, add to the other outputs
+    header_output += \
+        header_output_aa1 + header_output_lk1 + header_output_aa1_lk1
+    decoder_output += \
+        decoder_output_aa1 + decoder_output_lk1 + decoder_output_aa1_lk1
+    exec_output += \
+        exec_output_aa1 + exec_output_lk1 + exec_output_aa1_lk1
 }};
 
-// Instructions that conditionally branch to the address in the count register
-// (CTR) based on the condition register (CR).
-def format BranchCtrCond(br_code, inst_flags = []) {{
+
+// Instructions that conditionally branch to an address in a register
+// depending on the value of the condition register (CR) and count
+// register (CTR).
+def format BranchRegCondOp(code, checkCTR = 0, inst_flags = []) {{
     inst_flags += ('IsCondControl', 'IsIndirectControl')
-    basic_code = GetCondCode(br_code)
 
-    # The version that does not update LR
+    # Setup the 2 code versions and add code to update LR if necessary
+    if checkCTR:
+        code = GetCtrCondCode(code)
+    else:
+        code = GetCondCode(code)
+    code_lk1 = code + updateLrCode
+    inst_flags_lk1 = inst_flags
+    if 'IsReturn' not in inst_flags:
+        inst_flags_lk1 += [ 'IsCall' ]
+
+    # Generate the classes
     (header_output, decoder_output, decode_block, exec_output) = \
-        GenAluOp(name, Name, 'BranchRegCond', basic_code, inst_flags,
+        GenAluOp(name, Name, 'BranchRegCondOp', code, inst_flags,
                  CheckLkDecode, BasicConstructor)
-
-    # The version that does the update
-    update_code = basic_code + updateLrCode
-    update_flags = inst_flags + [ 'IsCall' ]
-    (header_output_up, decoder_output_up, _, exec_output_up) = \
-        GenAluOp(name, Name + 'UpdateLr', 'BranchRegCond', update_code,
-                 update_flags, CheckLkDecode, BasicConstructor)
-
-    # Add the outputs together
-    header_output += header_output_up
-    decoder_output += decoder_output_up
-    exec_output += exec_output_up
+    (header_output_lk1, decoder_output_lk1, _, exec_output_lk1) = \
+        GenAluOp(name, Name + 'LkSet', 'BranchRegCondOp', code_lk1,
+                 inst_flags_lk1, CheckLkDecode, BranchLkConstructor)
+
+    # Finally, add to the other outputs
+    header_output += header_output_lk1
+    decoder_output += decoder_output_lk1
+    exec_output += exec_output_lk1
 }};
index 1bb78e6ad2fc8d6546a49cc6078695c0f4fe0662..8b2e4251592ee272c11b98a71620e93d99e146e8 100644 (file)
@@ -78,11 +78,38 @@ def template CheckLkDecode {{
      if (LK == 0) {
          return new %(class_name)s(machInst);
      } else {
-         return new %(class_name)sUpdateLr(machInst);
+         return new %(class_name)sLkSet(machInst);
      }
  }
 }};
 
+def template CheckAaDecode {{
+ {
+     if (AA == 0) {
+         return new %(class_name)s(machInst);
+     } else {
+         return new %(class_name)sAaSet(machInst);
+     }
+ }
+}};
+
+def template CheckAaLkDecode {{
+ {
+     if (AA == 0) {
+         if (LK == 0) {
+             return new %(class_name)s(machInst);
+         } else {
+             return new %(class_name)sLkSet(machInst);
+         }
+     } else {
+         if (LK == 0) {
+             return new %(class_name)sAaSet(machInst);
+         } else {
+             return new %(class_name)sAaSetLkSet(machInst);
+         }
+     }
+ }
+}};
 
 let {{
 
@@ -163,5 +190,3 @@ output decoder {{
     }
 
 }};
-
-
index a805a472823f80393bd7ebee88ada38f9b24344f..74cd7b43a9eb7df393b720a2d4ad27e03cbd0f9a 100644 (file)
@@ -66,13 +66,17 @@ BitUnion32(ExtMachInst)
 
     // Special purpose register identifier
     Bitfield<20, 11> spr;
-    Bitfield<25,  2> li;
-    Bitfield<1>      aa;
     Bitfield<25, 23> bf;
+    Bitfield<20, 18> bfa;
+
+    // Branch instruction fields
+    Bitfield<1>      aa;
     Bitfield<15,  2> bd;
-    Bitfield<25, 21> bo;
     Bitfield<20, 16> bi;
-    Bitfield<20, 18> bfa;
+    Bitfield<12, 11> bh;
+    Bitfield<25, 21> bo;
+    Bitfield<25,  2> li;
+    Bitfield<0>      lk;
 
     // Record bits
     Bitfield<0>      rc31;