On Sat, Jul 04, 2009 at 03:23:40AM -0700, Gabe Black wrote:
> In case anyone is still reading this thread, that approach worked quite 
> well. I'm now moving forward with what I was trying to do in the first 
> place, namely entirely eliminate the ISA defined register files as 
> described in my pdf long ago.

If you are changing this code, I should tell you about the changes I
have been making in order to support ARM on O3, because those might
influence what you do. 

The really big change is that you have to support predicated operations
that aren't executed. These are possible on ARM, and become a big issue
for O3 support, because they are always partially executed to evaluate 
the condition codes in Cpsr. If the condition is false, then the operation 
*copies* the destination registers:

    def template PredOpExecute {{
        Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
                Trace::InstRecord *traceData) const
        {   
            Fault fault = NoFault;
            %(op_decl)s;
            %(op_rd)s;

            if (%(predicate_test)s)
            {   
                %(code)s;
                if (fault == NoFault)
                {   
                    %(op_wb)s;
                }
            } else {
                %(op_copy)s;        // <--- 
            }
            return fault;
        }

That's necessary because register renaming takes place *before* it is 
known whether the operation will execute or not. Rd (as input) and Rd (as
output) are different physical registers. The destination registers need
to be source registers.

There is also an important optimisation that you can make: you can 
redirect the Cpsr and Rd inputs to the zero register if the operation 
is unconditional. 

I've attached a patch to suggest how this could be done. Incidentally, I
really like the idea of making isa_parser.py into a class or package,
because my patch needs to access globals in isa_parser.py and it wasn't
easy to arrange this (I passed globals() as a parameter in the end).

What the patch does in isa_parser.py:
1.  Adds a "makeCopy" operation to every subclass of Operand. (You 
    can't use makeRead then makeWrite because they sometimes do sign 
    extension.) "makeCopy" is generated by the new "%(op_copy)s" 
    template code. 
2.  Allows any ISA to specify post-processor methods for
    (a) the operand list (fixup_operands_fn, e.g. ArmAddCpsrAndCopy)
    (b) each operand (op_desc.post_process_fn, e.g. ArmPostProc)
    (c) each InstObjParams (e.g. ArmAddToConstructor)


What the patch does in the ARM ISA definition:
1.  Adds %(op_copy)s as appropriate.
2.  Calls ArmAddToConstructor on every InstObjParams; this adds some
    flags to every constructor in decoder.cc. These include:
    (a) flags[IsCond] (if operation is conditional),
    (b) flags[IsControl] etc. (if operation writes to PC).
3.  As an optimisation, ArmAddToConstructor also sets "conditional sources",
    to the zero register if flags[IsCond] == false.
4.  Calls ArmAddCpsrAndCopy on every operand list genereated inside
    InstObjParams. This adds the Cpsr (if it's not already present) and
    adds all destination registers as sources. These are only used if
    the operation is conditional. A side effect of this step is that the
    substitution "new_code = re.sub(r'^', 'Cpsr = Cpsr;', new_code)" is
    not needed any more - a good thing, because most operations don't
    change Cpsr.
5.  Calls ArmPostProc on every operand (just before finalize) to make
    all %(op_copy)s code dependent on 
    (1) flags[IsCond] == true
    (2) destination register != PC
    This is because you do not want to write to the PC unless you are
    really changing it.
6.  There is some special processing for load operations which I haven't 
    completely finished yet. Specifically; the generation of EA is the
    only part of a load which is guaranteed to execute on O3, since the
    load may not issue if flags[IsCond] == true, so the EA generator
    must also do "%(op_copy)s".
7.  There are few bug fixes for bugs that only show up if speculative
    execution is used.

I hope that this patch will be useful to you. You can probably find 
better ways of doing each step than my "post processor" approach, 
but the key thing is support for something like "op_copy" which 
is used if a predicated operation is not executed. Without that, there 
can be no O3 support for ARM. 
  
Incidentally, O3 + ARM is very nearly working now :). Some changes are
necessary inside src/cpu/o3/ - I haven't included these in this patch to
avoid confusion, but I will send them out when they are fully working,
and when the isa_parser.py changes are more stable.

-- 
Jack Whitham
[email protected]

diff -rU5 m5-vanilla/src/arch/arm/isa/decoder.isa 
m5/src/arch/arm/isa/decoder.isa
--- m5-vanilla/src/arch/arm/isa/decoder.isa     2009-07-03 10:41:31.000000000 
+0100
+++ m5/src/arch/arm/isa/decoder.isa     2009-07-03 16:25:25.000000000 +0100
@@ -689,11 +689,11 @@
             // ARM System Call (SoftWare Interrupt)
             1: swi({{ if (testPredicate(Cpsr, condCode))
                       {
                           xc->syscall(IMMED_23_0);
                       }
-            }});
+            }}, IsSerializeAfter, IsNonSpeculative, IsSyscall);
         }
     }
 }
 }
 }
Only in m5/src/arch/arm/isa: decoder.isa.orig
Only in m5/src/arch/arm/isa: decoder.isa.rej
diff -rU5 m5-vanilla/src/arch/arm/isa/formats/basic.isa 
m5/src/arch/arm/isa/formats/basic.isa
--- m5-vanilla/src/arch/arm/isa/formats/basic.isa       2009-07-03 
10:41:31.000000000 +0100
+++ m5/src/arch/arm/isa/formats/basic.isa       2009-07-03 10:53:42.000000000 
+0100
@@ -92,11 +92,13 @@
 }
 }};
 
 // The most basic instruction format...
 def format BasicOp(code, *flags) {{
-        iop = InstObjParams(name, Name, 'ArmStaticInst', code, flags)
+        iop = InstObjParams(name, Name, 'ArmStaticInst', code, flags,
+                    fixup_operands_fn = ArmAddCpsrAndCopy)
+        ArmAddToConstructor(iop)
         header_output = BasicDeclare.subst(iop)
         decoder_output = BasicConstructor.subst(iop)
         decode_block = BasicDecode.subst(iop)
         exec_output = BasicExecute.subst(iop)
 }};
diff -rU5 m5-vanilla/src/arch/arm/isa/formats/branch.isa 
m5/src/arch/arm/isa/formats/branch.isa
--- m5-vanilla/src/arch/arm/isa/formats/branch.isa      2009-07-03 
10:41:31.000000000 +0100
+++ m5/src/arch/arm/isa/formats/branch.isa      2009-07-03 10:57:31.000000000 
+0100
@@ -61,11 +61,13 @@
         icode += '  LR = LR;\n'
     icode += '};\n'
 
     code = icode
 
-    iop = InstObjParams(name, Name, 'Branch', code, inst_flags)
+    iop = InstObjParams(name, Name, 'Branch', code, inst_flags,
+                    fixup_operands_fn = ArmAddCpsrAndCopy)
+    ArmAddToConstructor(iop)
     header_output = BasicDeclare.subst(iop)
     decoder_output = BasicConstructor.subst(iop)
     decode_block = BasicDecode.subst(iop)
     exec_output = BasicExecute.subst(iop)
 }};
@@ -99,11 +101,13 @@
         icode += '  LR = LR;\n'
     icode += '};\n'
 
     code = icode
 
-    iop = InstObjParams(name, Name, 'BranchExchange', code, inst_flags)
+    iop = InstObjParams(name, Name, 'BranchExchange', code, inst_flags,
+                    fixup_operands_fn = ArmAddCpsrAndCopy)
+    ArmAddToConstructor(iop)
     header_output = BasicDeclare.subst(iop)
     decoder_output = BasicConstructor.subst(iop)
     decode_block = BasicDecode.subst(iop)
     exec_output = BasicExecute.subst(iop)
 }};
@@ -119,10 +123,11 @@
             code += '/* Code Needed to Clear Execute & Inst Hazards */\n'
         else:
             inst_flags += (x, )
 
     iop = InstObjParams(name, Name, 'Jump', code, inst_flags)
+    ArmAddToConstructor(iop)
     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)
diff -rU5 m5-vanilla/src/arch/arm/isa/formats/fp.isa 
m5/src/arch/arm/isa/formats/fp.isa
--- m5-vanilla/src/arch/arm/isa/formats/fp.isa  2009-07-03 10:41:31.000000000 
+0100
+++ m5/src/arch/arm/isa/formats/fp.isa  2009-07-03 16:43:53.000000000 +0100
@@ -46,10 +46,12 @@
                 if (%(predicate_test)s) {
                     %(code)s;
                     if (fault == NoFault) {
                         %(op_wb)s;
                     }
+                } else {
+                    %(op_copy)s;
                 }
 
                 return fault;
         }
 }};
@@ -80,31 +82,37 @@
 
         cblk = code
         iop = InstObjParams(name, Name, 'PredOp',
                             {"code": cblk,
                              "predicate_test": predicateTest},
-                            flags)
+                            flags,
+                            fixup_operands_fn = ArmAddCpsrAndCopy)
+        ArmAddToConstructor(iop)
         header_output = BasicDeclare.subst(iop)
         decoder_output = BasicConstructor.subst(iop)
         exec_output = FPAExecute.subst(iop)
 
         sng_cblk = code
         sng_iop = InstObjParams(name, Name+'S', 'PredOp',
-                                {"code": sng_cblk,
-                                 "predicate_test": predicateTest},
-                                flags)
+                            {"code": sng_cblk,
+                             "predicate_test": predicateTest},
+                            flags,
+                            fixup_operands_fn = ArmAddCpsrAndCopy)
+        ArmAddToConstructor(iop)
         header_output += BasicDeclare.subst(sng_iop)
         decoder_output += BasicConstructor.subst(sng_iop)
         exec_output += FPAExecute.subst(sng_iop)
 
         dbl_code = re.sub(r'\.sf', '.df', orig_code)
 
         dbl_cblk = dbl_code
         dbl_iop = InstObjParams(name, Name+'D', 'PredOp',
-                                {"code": dbl_cblk,
-                                 "predicate_test": predicateTest},
-                                flags)
+                            {"code": dbl_cblk,
+                             "predicate_test": predicateTest},
+                            flags,
+                            fixup_operands_fn = ArmAddCpsrAndCopy)
+        ArmAddToConstructor(iop)
         header_output += BasicDeclare.subst(dbl_iop)
         decoder_output += BasicConstructor.subst(dbl_iop)
         exec_output += FPAExecute.subst(dbl_iop)
 
         decode_block = FloatDoubleDecode.subst(iop)
@@ -127,11 +135,13 @@
 def format FloatCmp(fReg1, fReg2, *flags) {{
         code = calcFPCcCode % vars()
         iop = InstObjParams(name, Name, 'PredOp',
                             {"code": code,
                              "predicate_test": predicateTest},
-                             flags)
+                             flags,
+                             fixup_operands_fn = ArmAddCpsrAndCopy)
+        ArmAddToConstructor(iop)
         header_output = BasicDeclare.subst(iop)
         decoder_output = BasicConstructor.subst(iop)
         decode_block = BasicDecode.subst(iop)
         exec_output = FPAExecute.subst(iop)
 }};
diff -rU5 m5-vanilla/src/arch/arm/isa/formats/macromem.isa 
m5/src/arch/arm/isa/formats/macromem.isa
--- m5-vanilla/src/arch/arm/isa/formats/macromem.isa    2009-07-03 
10:41:31.000000000 +0100
+++ m5/src/arch/arm/isa/formats/macromem.isa    2009-07-03 16:44:36.000000000 
+0100
@@ -41,10 +41,12 @@
 {
     public:
         // Constructor
         %(class_name)s(ExtMachInst machInst);
         %(BasicExecDeclare)s
+
+        bool unknown_puswl;
 };
 }};
 
 def template MacroStoreConstructor {{
 inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
@@ -54,10 +56,11 @@
     uint32_t regs_to_handle = reglist;
     uint32_t j = 0,
              start_addr = 0,
              end_addr = 0;
 
+    unknown_puswl = false;
     switch (puswl)
     {
         case 0x00: //       stmda
         case 0x01: //     L ldmda_l
         case 0x02: //    W  stmda_w
@@ -85,29 +88,35 @@
         case 0x1b: // PU WL ldmib
             start_addr = 4;
             end_addr = (ones << 2) + 4;
             break;
         default:
-            panic("Unhandled Load/Store Multiple Instruction, "
-                "puswl = 0x%x", (unsigned) puswl);
+            // Unhandled load/store multiple instruction
+            // panics if executed.
+            flags[IsNonSpeculative] = true;
+            unknown_puswl = true;
             break;
     }
 
     //TODO - Add addi_uop/subi_uop here to create starting addresses
     //Just using addi with 0 offset makes a "copy" of Rn for our use
     uint32_t newMachInst = 0;
     newMachInst = machInst & 0xffff0000;
     microOps[0] = new Addi_uop(newMachInst);
+    int i;
+    int pcindex = -1;
 
-    for (int i = 1; i < ones+1; i++)
+    for (i = 1; i < ones+1; i++)
     {
         // Get next available bit for transfer
         while (! ( regs_to_handle & (1<<j)))
             j++;
         regs_to_handle &= ~(1<<j);
 
         microOps[i] = gen_ldrstr_uop(machInst, loadop, j, start_addr);
+        if (j == PCReg)
+            pcindex = i;
 
         if (up)
             start_addr += 4;
         else
             start_addr -= 4;
@@ -133,27 +142,42 @@
         newMachInst |= 0x02400000;
         newMachInst |= ((rn << 16) | (rn << 12));
         newMachInst |= (ones << 2);
         if (up)
         {
-            microOps[numMicroops-1] = new Addi_rd_uop(newMachInst);
+            microOps[i] = new Addi_rd_uop(newMachInst);
         }
         else
         {
-            microOps[numMicroops-1] = new Subi_rd_uop(newMachInst);
+            microOps[i] = new Subi_rd_uop(newMachInst);
         }
+        i++;
     }
-    microOps[numMicroops-1]->setLastMicroop();
+
+    if (loadop && (pcindex != -1)) {
+        // Reorder: move PC load to the final slot.
+        // This operation can cause a branch so it is
+        // important that it is the final uop.
+        StaticInstPtr temp = microOps[i - 1];
+        microOps[i - 1] = microOps[pcindex];
+        microOps[pcindex] = temp;
+    }
+
+    microOps[i - 1]->setLastMicroop();
 }
 
 }};
 
 def template MacroStoreExecute {{
 Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord 
*traceData) const
 {
     Fault fault = NoFault;
 
+    if (unknown_puswl) {
+        panic("Unhandled Load/Store Multiple Instruction, "
+            "puswl = 0x%x", (unsigned) puswl);
+    }
     %(fp_enable_check)s;
     %(op_decl)s;
     %(op_rd)s;
     %(code)s;
     if (fault == NoFault)
@@ -250,33 +274,39 @@
 }
 }};
 
 
 def format ArmMacroStore(code, mem_flags = [], inst_flag = [], *opt_flags) {{
-    iop = InstObjParams(name, Name, 'ArmMacroMemoryOp', code, opt_flags)
+    iop = InstObjParams(name, Name, 'ArmMacroMemoryOp', code, opt_flags,
+                        fixup_operands_fn = ArmAddCpsrAndCopy)
+    ArmAddToConstructor(iop)
     header_output = MacroStoreDeclare.subst(iop)
     decoder_output = MacroStoreConstructor.subst(iop)
     decode_block = BasicDecode.subst(iop)
     exec_output = MacroStoreExecute.subst(iop)
 }};
 
 def format ArmMacroFPAOp(code, mem_flags = [], inst_flag = [], *opt_flags) {{
     iop = InstObjParams(name, Name, 'ArmMacroFPAOp',
                         {"code": code,
                          "predicate_test": predicateTest},
-                        opt_flags)
+                        opt_flags,
+                        fixup_operands_fn = ArmAddCpsrAndCopy)
+    ArmAddToConstructor(iop)
     header_output = BasicDeclare.subst(iop)
     decoder_output = MacroFPAConstructor.subst(iop)
     decode_block = BasicDecode.subst(iop)
     exec_output = PredOpExecute.subst(iop)
 }};
 
 def format ArmMacroFMOp(code, mem_flags = [], inst_flag = [], *opt_flags) {{
     iop = InstObjParams(name, Name, 'ArmMacroFMOp',
                         {"code": code,
                          "predicate_test": predicateTest},
-                        opt_flags)
+                        opt_flags,
+                        fixup_operands_fn = ArmAddCpsrAndCopy)
+    ArmAddToConstructor(iop)
     header_output = BasicDeclare.subst(iop)
     decoder_output = MacroFMConstructor.subst(iop)
     decode_block = BasicDecode.subst(iop)
     exec_output = PredOpExecute.subst(iop)
 }};
diff -rU5 m5-vanilla/src/arch/arm/isa/formats/mem.isa 
m5/src/arch/arm/isa/formats/mem.isa
--- m5-vanilla/src/arch/arm/isa/formats/mem.isa 2009-07-03 10:41:31.000000000 
+0100
+++ m5/src/arch/arm/isa/formats/mem.isa 2009-07-03 12:41:38.000000000 +0100
@@ -133,10 +133,12 @@
         {
             if (fault == NoFault) {
                 %(op_wb)s;
                 xc->setEA(EA);
             }
+        } else {
+            %(op_copy)s;
         }
 
         return fault;
     }
 }};
@@ -161,10 +163,12 @@
             }
 
             if (fault == NoFault) {
                 %(op_wb)s;
             }
+        } else {
+            %(op_copy)s;
         }
 
         return fault;
     }
 }};
@@ -189,10 +193,12 @@
             }
 
             if (fault == NoFault) {
                 %(op_wb)s;
             }
+        } else {
+            %(op_copy)s;
         }
 
         return fault;
     }
 }};
@@ -212,10 +218,12 @@
         if (%(predicate_test)s)
         {
             if (fault == NoFault) {
                 fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, 
memAccessFlags);
             }
+        } else {
+            %(op_copy)s;
         }
 
         return fault;
     }
 }};
@@ -241,10 +249,12 @@
             }
 
             if (fault == NoFault) {
                 %(op_wb)s;
             }
+        } else {
+            %(op_copy)s;
         }
 
         return fault;
     }
 }};
@@ -272,10 +282,12 @@
             }
 
             if (fault == NoFault) {
                 %(op_wb)s;
             }
+        } else {
+            %(op_copy)s;
         }
 
         return fault;
     }
 }};
@@ -305,10 +317,12 @@
             }
 
             if (fault == NoFault) {
                 %(op_wb)s;
             }
+        } else {
+            %(op_copy)s;
         }
 
         return fault;
     }
 }};
@@ -338,10 +352,12 @@
 
             // Need to write back any potential address register update
             if (fault == NoFault) {
                 %(op_wb)s;
             }
+        } else {
+            %(op_copy)s;
         }
 
         return fault;
     }
 }};
@@ -352,17 +368,20 @@
                                       %(CPU_exec_context)s *xc,
                                       Trace::InstRecord *traceData) const
     {
         Fault fault = NoFault;
 
-        %(op_dest_decl)s;
+        %(op_decl)s; 
+        %(op_rd)s;
 
         if (%(predicate_test)s)
         {
             if (fault == NoFault) {
                 %(op_wb)s;
             }
+        } else {
+            %(op_copy)s;
         }
 
         return fault;
     }
 }};
@@ -379,10 +398,12 @@
         if (%(predicate_test)s)
         {
             if (fault == NoFault) {
                 %(op_wb)s;
             }
+        } else {
+            %(op_copy)s;
         }
 
         return fault;
     }
 }};
@@ -403,10 +424,12 @@
             EA = xc->getEA();
 
             if (fault == NoFault) {
                 %(memacc_code)s;
             }
+        } else {
+            %(op_copy)s;
         }
 
         return NoFault;
     }
 }};
@@ -425,10 +448,12 @@
         if (%(predicate_test)s)
         {
             if (fault == NoFault) {
                 %(memacc_code)s;
             }
+        } else {
+            %(op_copy)s;
         }
 
         return NoFault;
     }
 }};
diff -rU5 m5-vanilla/src/arch/arm/isa/formats/pred.isa 
m5/src/arch/arm/isa/formats/pred.isa
--- m5-vanilla/src/arch/arm/isa/formats/pred.isa        2009-07-03 
10:41:31.000000000 +0100
+++ m5/src/arch/arm/isa/formats/pred.isa        2009-07-03 12:47:21.000000000 
+0100
@@ -51,10 +51,12 @@
             %(code)s;
             if (fault == NoFault)
             {
                 %(op_wb)s;
             }
+        } else {
+            %(op_copy)s;
         }
 
         return fault;
     }
 }};
@@ -149,20 +151,30 @@
     immCode = '''uint32_t op2 = shift_rm_imm(Rm, shift_size,
                                              shift, Cpsr<29:0>);
                  op2 = op2;''' + code
     regIop = InstObjParams(name, Name, 'PredIntOp',
                            {"code": regCode,
-                            "predicate_test": predicateTest})
+                            "predicate_test": predicateTest},
+                           fixup_operands_fn = ArmAddCpsrAndCopy)
     immIop = InstObjParams(name, Name + "Imm", 'PredIntOp',
                            {"code": immCode,
-                            "predicate_test": predicateTest})
+                            "predicate_test": predicateTest},
+                           fixup_operands_fn = ArmAddCpsrAndCopy)
     regCcIop = InstObjParams(name, Name + "Cc", 'PredIntOp',
-                             {"code": regCode + regCcCode,
-                              "predicate_test": predicateTest})
+                           {"code": regCode + regCcCode,
+                            "predicate_test": predicateTest},
+                           fixup_operands_fn = ArmAddCpsrAndCopy)
     immCcIop = InstObjParams(name, Name + "ImmCc", 'PredIntOp',
-                             {"code": immCode + immCcCode,
-                              "predicate_test": predicateTest})
+                           {"code": immCode + immCcCode,
+                            "predicate_test": predicateTest},
+                           fixup_operands_fn = ArmAddCpsrAndCopy)
+    
+    ArmAddToConstructor(regIop)
+    ArmAddToConstructor(immIop)
+    ArmAddToConstructor(regCcIop)
+    ArmAddToConstructor(immCcIop)
+
     header_output = BasicDeclare.subst(regIop) + \
                     BasicDeclare.subst(immIop) + \
                     BasicDeclare.subst(regCcIop) + \
                     BasicDeclare.subst(immCcIop)
     decoder_output = BasicConstructor.subst(regIop) + \
@@ -177,15 +189,19 @@
 }};
 
 def format DataImmOp(code, flagtype = logic) {{
     code += "resTemp = resTemp;"
     iop = InstObjParams(name, Name, 'PredImmOp',
-                        {"code": code,
-                         "predicate_test": predicateTest})
+                           {"code": code,
+                            "predicate_test": predicateTest},
+                           fixup_operands_fn = ArmAddCpsrAndCopy)
     ccIop = InstObjParams(name, Name + "Cc", 'PredImmOp',
-                          {"code": code + getImmCcCode(flagtype),
-                           "predicate_test": predicateTest})
+                           {"code": code + getImmCcCode(flagtype),
+                            "predicate_test": predicateTest},
+                           fixup_operands_fn = ArmAddCpsrAndCopy)
+    ArmAddToConstructor(iop)
+    ArmAddToConstructor(ccIop)
     header_output = BasicDeclare.subst(iop) + \
                     BasicDeclare.subst(ccIop)
     decoder_output = BasicConstructor.subst(iop) + \
                      BasicConstructor.subst(ccIop)
     exec_output = PredOpExecute.subst(iop) + \
@@ -193,50 +209,58 @@
     decode_block = DataImmDecode.subst(iop)
 }};
 
 def format PredOp(code, *opt_flags) {{
     iop = InstObjParams(name, Name, 'PredOp',
-                        {"code": code,
-                         "predicate_test": predicateTest},
-                        opt_flags)
+                           {"code": code,
+                            "predicate_test": predicateTest},
+                           opt_flags,
+                           fixup_operands_fn = ArmAddCpsrAndCopy)
+    ArmAddToConstructor(iop)
     header_output = BasicDeclare.subst(iop)
     decoder_output = BasicConstructor.subst(iop)
     decode_block = BasicDecode.subst(iop)
     exec_output = PredOpExecute.subst(iop)
 }};
 
 def format PredImmOp(code, *opt_flags) {{
     iop = InstObjParams(name, Name, 'PredImmOp',
-                        {"code": code,
-                         "predicate_test": predicateTest},
-                        opt_flags)
+                           {"code": code,
+                            "predicate_test": predicateTest},
+                           opt_flags,
+                           fixup_operands_fn = ArmAddCpsrAndCopy)
+    ArmAddToConstructor(iop)
     header_output = BasicDeclare.subst(iop)
     decoder_output = BasicConstructor.subst(iop)
     decode_block = BasicDecode.subst(iop)
     exec_output = PredOpExecute.subst(iop)
 }};
 
 def format PredImmOpCc(code, icValue, ivValue, *opt_flags) {{
     ccCode = calcCcCode % vars()
     code += ccCode;
     iop = InstObjParams(name, Name, 'PredImmOp',
-                        {"code": code,
-                         "cc_code": ccCode,
-                         "predicate_test": predicateTest},
-                        opt_flags)
+                           {"code": code,
+                            "cc_code": ccCode,
+                            "predicate_test": predicateTest},
+                           opt_flags,
+                           fixup_operands_fn = ArmAddCpsrAndCopy)
+    ArmAddToConstructor(iop)
     header_output = BasicDeclare.subst(iop)
     decoder_output = BasicConstructor.subst(iop)
     decode_block = BasicDecode.subst(iop)
     exec_output = PredOpExecute.subst(iop)
 }};
 
 def format PredIntOp(code, *opt_flags) {{
     new_code = ArmGenericCodeSubs(code)
     iop = InstObjParams(name, Name, 'PredIntOp',
-                        {"code": new_code,
-                         "predicate_test": predicateTest},
-                        opt_flags)
+                           {"code": new_code,
+                            "predicate_test": predicateTest},
+                           opt_flags,
+                           fixup_operands_fn = ArmAddCpsrAndCopy)
+    ArmAddToConstructor(iop)
     header_output = BasicDeclare.subst(iop)
     decoder_output = BasicConstructor.subst(iop)
     decode_block = BasicDecode.subst(iop)
     exec_output = PredOpExecute.subst(iop)
 }};
@@ -244,14 +268,16 @@
 def format PredIntOpCc(code, icValue, ivValue, *opt_flags) {{
     ccCode = calcCcCode % vars()
     code += ccCode;
     new_code = ArmGenericCodeSubs(code)
     iop = InstObjParams(name, Name, 'PredIntOp',
-                        {"code": new_code,
-                         "cc_code": ccCode,
-                         "predicate_test": predicateTest},
-                        opt_flags)
+                           {"code": new_code,
+                            "cc_code": ccCode,
+                            "predicate_test": predicateTest},
+                           opt_flags,
+                           fixup_operands_fn = ArmAddCpsrAndCopy)
+    ArmAddToConstructor(iop)
     header_output = BasicDeclare.subst(iop)
     decoder_output = BasicConstructor.subst(iop)
     decode_block = BasicDecode.subst(iop)
     exec_output = PredOpExecute.subst(iop)
 }};
diff -rU5 m5-vanilla/src/arch/arm/isa/formats/util.isa 
m5/src/arch/arm/isa/formats/util.isa
--- m5-vanilla/src/arch/arm/isa/formats/util.isa        2009-07-03 
10:41:31.000000000 +0100
+++ m5/src/arch/arm/isa/formats/util.isa        2009-07-04 13:38:42.000000000 
+0100
@@ -33,11 +33,10 @@
 # Generic substitutions for Arm instructions
 def ArmGenericCodeSubs(code):
     # Substitute in the shifted portion of operations
     new_code = re.sub(r'Rm_Imm', 'shift_rm_imm(Rm, shift_size, shift, 
Cpsr<29:>)', code)
     new_code = re.sub(r'Rm_Rs', 'shift_rm_rs(Rm, Rs, shift, Cpsr<29:>)', 
new_code)
-    new_code = re.sub(r'^', 'Cpsr = Cpsr;', new_code)
     return new_code
 
 def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
                   base_class = 'Memory',
                   decode_template = BasicDecode, exec_template_base = ''):
@@ -59,19 +58,24 @@
     # turn affects the object's overall operand list).
     iop = InstObjParams(name, Name, base_class,
                         {'ea_code': ea_code,
                          'memacc_code': memacc_code,
                          'predicate_test': predicateTest},
-                        inst_flags)
+                        inst_flags, fixup_operands_fn = ArmFixupEA)
     ea_iop = InstObjParams(name, Name, base_class,
-                           {'ea_code': ea_code,
-                            'predicate_test': predicateTest},
-                           inst_flags)
+                        {'ea_code': ea_code,
+                         'predicate_test': predicateTest},
+                        inst_flags, fixup_operands_fn = ArmAddCpsrAndCopy)
     memacc_iop = InstObjParams(name, Name, base_class,
-                               {'memacc_code': memacc_code,
-                                'predicate_test': predicateTest},
-                               inst_flags)
+                        {'memacc_code': memacc_code,
+                         'predicate_test': predicateTest},
+                        inst_flags, fixup_operands_fn = ArmAddCpsrAndCopy)
+
+    ArmAddToConstructor(iop)
+    ArmAddToConstructor(ea_iop)
+    ArmAddToConstructor(memacc_iop)
+   
 
     if mem_flags:
         s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
         iop.constructor += s
         memacc_iop.constructor += s
@@ -96,10 +100,143 @@
             EACompExecute.subst(ea_iop)
             + memAccExecTemplate.subst(memacc_iop)
             + fullExecTemplate.subst(iop)
             + initiateAccTemplate.subst(iop)
             + completeAccTemplate.subst(iop))
+
+def ArmAddCpsrAndCopy(operands, isa_parser_dict):
+    # Called during construction of the operand list, to make
+    # ARM-specific changes to the operand list for each instruction.
+    operandNameMap = isa_parser_dict['operandNameMap']
+
+    # Destination-only registers are "conditional sources"
+    # meaning that they are also used as sources *only* if
+    # the operation is conditional. They are copied from source
+    # to destination. This preserves correct behavior during
+    # register renaming.
+    operands.arm_conditional_sources = []
+
+    # 1. Add Cpsr if it is not already a source register
+    cpsr = False
+    for op_desc in operands.items:
+        if ( op_desc.isReg() 
+        and op_desc.base_name == "Cpsr" ):
+            op_desc.is_src = True
+            cpsr = True
+
+    if not cpsr:
+        op_full = op_base = "Cpsr"
+        op_ext = None
+        is_src = True
+        is_dest = False
+        op_desc = operandNameMap[op_base](op_full, op_ext,
+                                          is_src, is_dest)
+        operands.append(op_desc)
+
+        # Cpsr is also a conditional source in this case
+        operands.arm_conditional_sources.append(op_desc)
+
+    # 2. Add other conditional sources (destination-only registers)
+    for op_desc in operands.items:
+        if op_desc.isReg():
+            if op_desc.is_dest and not op_desc.is_src:
+                op_desc.is_src = True
+                operands.arm_conditional_sources.append(op_desc)
+            
+            # Every operand that is both a source and a dest is a copy.
+            op_desc.is_copy = op_desc.is_dest and op_desc.is_src
+
+            # Add post process fn to modify copy output appropriately
+            assert op_desc.post_process_fn == None
+            op_desc.post_process_fn = ArmPostProc
+
+def ArmPostProc(op_desc):
+    if (not op_desc.is_copy):
+        return
+
+    # Modify op_copy output - only copy if the operation is
+    # conditional.
+    # If the destination is the PC register; don't copy -
+    # load the next PC instead. 
+
+    op_desc.op_copy = """
+if (flags[IsCond]) {
+    if (_destRegIdx[%d] != PCReg)
+    {
+        %s
+    }
+}""" % (op_desc.dest_reg_idx, op_desc.op_copy)
+
+
+def ArmAddToConstructor(iop):
+    # Called after the constructor (for decode.cc) has been produced
+
+    # 1. Evaluation of _conditional and loadPC flags.
+    iop.constructor += """
+
+    if (COND_CODE < 0xe) {
+        // Instruction is conditional
+        flags[IsCond] = true;
+    }
+    if (true) {
+        // Check for writes to PC
+        int i;
+        for (i = 0; i < _numDestRegs; i++) {
+            if (_destRegIdx[i] == PCReg) {
+                flags[IsControl] = true;
+                flags[IsIndirectControl] = true;
+                flags[IsCondControl] = flags[IsCond];
+                flags[IsUncondControl] = !flags[IsCond];
+
+                // If the instruction is a load:
+                flags[IsMemoryIndirectControl] = flags[IsLoad];
+            }
+        }
+    }
+    if (!flags[IsCond]) {
+        // If unconditional - redirect all conditional sources 
+        // to the zero register
+"""
+    for op_desc in iop.operands.arm_conditional_sources:
+        iop.constructor += "_srcRegIdx[%d] = zero_reg;\n" % (
+                op_desc.src_reg_idx)
+    iop.constructor += "}\n"
+
+def ArmFixupEA(operands, isa_parser_dict):
+    # Add Rd as a source and destination
+    # EA computation must copy Rd in case the
+    # memory operation is not executed.
+    operandNameMap = isa_parser_dict['operandNameMap']
+
+    rd_op_desc = operands.find_base("Rd")
+    if ( rd_op_desc == None ):
+        op_full = op_base = "Rd"
+        op_ext = None
+        is_src = False
+        is_dest = True
+        rd_op_desc = operandNameMap[op_base](op_full, op_ext,
+                                      is_src, is_dest)
+        operands.append(rd_op_desc)
+
+    # Add Cpsr and copy code
+    ArmAddCpsrAndCopy(operands, isa_parser_dict)
+
+    # Use post-processor to remove op_wb code for Rd
+    # so that it isn't written if the memory operation
+    # is executed.
+    assert rd_op_desc == operands.find_base("Rd")
+    assert rd_op_desc.post_process_fn == ArmPostProc
+    rd_op_desc.post_process_fn = ArmPostProcEA
+    rd_op_desc.always_include = True
+
+def ArmPostProcEA(op_desc):
+    # XXX - this code may not work for both types of memory access operation
+    #op_desc.op_wb = "/* EA - Rd not written back */\n"
+    ArmPostProc(op_desc) 
+    op_desc.op_copy += "/* Ea - Rd copied */\n"
+
+
 }};
 
 
 output header {{
         std::string inst2string(MachInst machInst);
@@ -133,14 +270,15 @@
     {
         StaticInstPtr newInst;
         uint32_t newMachInst = baseinst & 0xffff0000;
         newMachInst |= (rd << 12);
         newMachInst |= disp;
-        if (loadop)
+        if (loadop) {
             newInst = new Ldr_uop(newMachInst);
-        else
+        } else {
             newInst = new Str_uop(newMachInst);
+        }
         return newInst;
     }
 
     // Emits uops for a double fp move
     int
diff -rU5 m5-vanilla/src/arch/arm/isa/operands.isa 
m5/src/arch/arm/isa/operands.isa
--- m5-vanilla/src/arch/arm/isa/operands.isa    2009-07-03 10:41:31.000000000 
+0100
+++ m5/src/arch/arm/isa/operands.isa    2009-07-03 12:54:08.000000000 +0100
@@ -46,12 +46,12 @@
     'Rm': ('IntReg', 'uw', 'RM', 'IsInteger', 2),
     'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 3),
     'Rn': ('IntReg', 'uw', 'RN', 'IsInteger', 4),
 
     'Raddr': ('IntReg', 'uw', '17', 'IsInteger', 5),
-    'Rhi': ('IntReg', 'uw', '18', 'IsInteger', 5),
-    'Rlo': ('IntReg', 'uw', '19', 'IsInteger', 6),
+    'Rhi': ('IntReg', 'uw', '19', 'IsInteger', 5),
+    'Rlo': ('IntReg', 'uw', '20', 'IsInteger', 6),
     'LR': ('IntReg', 'uw', '14', 'IsInteger', 6),
 
     #General Purpose Floating Point Reg Operands
     'Fd': ('FloatReg', 'df', 'FD', 'IsFloating', 1),
     'Fn': ('FloatReg', 'df', 'FN', 'IsFloating', 2),
diff -rU5 m5-vanilla/src/arch/arm/regfile/int_regfile.hh 
m5/src/arch/arm/regfile/int_regfile.hh
--- m5-vanilla/src/arch/arm/regfile/int_regfile.hh      2009-07-03 
10:41:31.000000000 +0100
+++ m5/src/arch/arm/regfile/int_regfile.hh      2009-07-03 12:53:41.000000000 
+0100
@@ -48,14 +48,16 @@
         return "";
     }
 
     enum MiscIntRegNums {
         zero_reg = NumIntArchRegs,
-        addr_reg,
+        addr_reg,           // 17
 
-        rhi,
-        rlo,
+        CPSR_for_O3,        // 18
+
+        rhi,                // 19
+        rlo,                // 20
 
         r8_fiq,    /* FIQ mode register bank */
         r9_fiq,
         r10_fiq,
         r11_fiq,
Only in m5/src/arch/arm/regfile: int_regfile.hh.orig
diff -rU5 m5-vanilla/src/arch/isa_parser.py m5/src/arch/isa_parser.py
--- m5-vanilla/src/arch/isa_parser.py   2009-07-03 10:41:31.000000000 +0100
+++ m5/src/arch/isa_parser.py   2009-07-03 12:58:19.000000000 +0100
@@ -967,18 +967,21 @@
 
 # Error handler.  Just call exit.  Output formatted to work under
 # Emacs compile-mode.  Optional 'print_traceback' arg, if set to True,
 # prints a Python stack backtrace too (can be handy when trying to
 # debug the parser itself).
-def error(lineno, string, print_traceback = False):
+def error(lineno, string, print_traceback = True):
     spaces = ""
     for (filename, line) in fileNameStack[0:-1]:
         print spaces + "In file included from " + filename + ":"
         spaces += "  "
     # Print a Python stack backtrace if requested.
     if (print_traceback):
-        traceback.print_exc()
+        if ( sys.exc_info()[ 0 ] != None ):
+            traceback.print_exc()
+        else:
+            traceback.print_stack()
     if lineno != 0:
         line_str = "%d:" % lineno
     else:
         line_str = ""
     sys.exit(spaces + "%s:%s %s" % (fileNameStack[-1][0], line_str, string))
@@ -1090,10 +1093,11 @@
             myDict['op_dest_decl'] = \
                       operands.concatSomeAttrStrings(is_dest, 'op_dest_decl')
 
             myDict['op_rd'] = operands.concatAttrStrings('op_rd')
             myDict['op_wb'] = operands.concatAttrStrings('op_wb')
+            myDict['op_copy'] = operands.concatAttrStrings('op_copy')
 
             if d.operands.memOperand:
                 myDict['mem_acc_size'] = d.operands.memOperand.mem_acc_size
                 myDict['mem_acc_type'] = d.operands.memOperand.mem_acc_type
 
@@ -1176,10 +1180,14 @@
     def __init__(self, full_name, ext, is_src, is_dest):
         self.full_name = full_name
         self.ext = ext
         self.is_src = is_src
         self.is_dest = is_dest
+        self.is_copy = False
+        self.always_include = False
+        self.post_process_fn = None
+
         # The 'effective extension' (eff_ext) is either the actual
         # extension, if one was explicitly provided, or the default.
         if ext:
             self.eff_ext = ext
         else:
@@ -1194,19 +1202,25 @@
             if self.ctype in ['Twin32_t', 'Twin64_t']:
                 self.mem_acc_type = 'Twin'
             else:
                 self.mem_acc_type = 'uint'
 
+
     # Finalize additional fields (primarily code fields).  This step
     # is done separately since some of these fields may depend on the
     # register index enumeration that hasn't been performed yet at the
     # time of __init__().
     def finalize(self):
         self.flags = self.getFlags()
         self.constructor = self.makeConstructor()
         self.op_decl = self.makeDecl()
 
+        if self.is_copy:
+            self.op_copy = self.makeCopy()
+        else:
+            self.op_copy = ''
+
         if self.is_src:
             self.op_rd = self.makeRead()
             self.op_src_decl = self.makeDecl()
         else:
             self.op_rd = ''
@@ -1217,10 +1231,14 @@
             self.op_dest_decl = self.makeDecl()
         else:
             self.op_wb = ''
             self.op_dest_decl = ''
 
+        if ( self.post_process_fn != None ):
+            self.post_process_fn(self)
+
+
     def isMem(self):
         return 0
 
     def isReg(self):
         return 0
@@ -1250,10 +1268,13 @@
     def makeDecl(self):
         # Note that initializations in the declarations are solely
         # to avoid 'uninitialized variable' errors from the compiler.
         return self.ctype + ' ' + self.base_name + ' = 0;\n';
 
+    def makeCopy(self):
+        return ""
+
 class IntRegOperand(Operand):
     def isReg(self):
         return 1
 
     def isIntReg(self):
@@ -1283,10 +1304,15 @@
             return '%s = %s;\n' % (self.base_name, int_reg_val)
         else:
             return '%s = bits(xc->readIntRegOperand(this, %d), %d, 0);\n' % \
                    (self.base_name, self.src_reg_idx, self.size-1)
 
+    def makeCopy(self):
+        return """xc->setIntRegOperand(this, %d,  // copy
+                    xc->readIntRegOperand(this, %d));""" % (self.dest_reg_idx,
+                            self.src_reg_idx)
+        
     def makeWrite(self):
         if (self.ctype == 'float' or self.ctype == 'double'):
             error(0, 'Attempt to write integer register as FP')
         if (self.size != self.dflt_size and self.is_signed):
             final_val = 'sext<%d>(%s)' % (self.size, self.base_name)
@@ -1344,10 +1370,16 @@
             return '%s = bits(%s, %d, 0);\n' % \
                    (self.base_name, base, self.size-1)
         else:
             return '%s = %s;\n' % (self.base_name, base)
 
+    def makeCopy(self):
+        return """xc->setFloatRegOperandBits(this, %d,  // copy
+            xc->readFloatRegOperandBits(this, %d), 64);""" % (
+                            self.dest_reg_idx,
+                            self.src_reg_idx)
+        
     def makeWrite(self):
         final_val = self.base_name
         final_ctype = self.ctype
         widthSpecifier = ''
         width = 0
@@ -1405,10 +1437,16 @@
             return '%s = %s;\n' % (self.base_name, base)
         else:
             return '%s = bits(%s, %d, 0);\n' % \
                    (self.base_name, base, self.size-1)
 
+    def makeCopy(self):
+        return """\nxc->setMiscRegOperand(this, %d, // copy
+            xc->readMiscRegOperand(this, %d));""" % (self.dest_reg_idx,
+                            self.src_reg_idx)
+        
+
     def makeWrite(self):
         if (self.ctype == 'float' or self.ctype == 'double'):
             error(0, 'Attempt to write control register as FP')
         wb = 'xc->setMiscRegOperand(this, %s, %s);\n' % \
              (self.dest_reg_idx, self.base_name)
@@ -1617,11 +1655,11 @@
 
 class OperandList:
 
     # Find all the operands in the given code block.  Returns an operand
     # descriptor list (instance of class OperandList).
-    def __init__(self, code):
+    def __init__(self, code, fixup_operands_fn):
         self.items = []
         self.bases = {}
         # delete comments so we don't match on reg specifiers inside
         code = commentRE.sub('', code)
         # search for operands
@@ -1651,10 +1689,15 @@
                 op_desc = operandNameMap[op_base](op_full, op_ext,
                                                   is_src, is_dest)
                 self.append(op_desc)
             # start next search after end of current match
             next_pos = match.end()
+
+        # ISA-specific changes to the operands applied here
+        if fixup_operands_fn:
+            fixup_operands_fn(self, globals())
+
         self.sort()
         # enumerate source & dest register operands... used in building
         # constructor later
         self.numSrcRegs = 0
         self.numDestRegs = 0
@@ -1765,10 +1808,16 @@
                     # if not, add a reference to it to this sub list
                     self.append(master_list.bases[op_base])
 
             # start next search after end of current match
             next_pos = match.end()
+
+        for op_desc in master_list.items:
+            if (op_desc.always_include
+            and not self.find_base(op_desc.base_name)):
+                self.append(op_desc)
+
         self.sort()
         self.memOperand = None
         for op_desc in self.items:
             if op_desc.isMem():
                 if self.memOperand:
@@ -1818,20 +1867,21 @@
 # OpClass constants end in 'Op' except No_OpClass
 opClassRE = re.compile(r'.*Op|No_OpClass')
 
 class InstObjParams:
     def __init__(self, mnem, class_name, base_class = '',
-                 snippets = {}, opt_args = []):
+                 snippets = {}, opt_args = [], 
+                 fixup_operands_fn = None):
         self.mnemonic = mnem
         self.class_name = class_name
         self.base_class = base_class
         if not isinstance(snippets, dict):
             snippets = {'code' : snippets}
         compositeCode = ' '.join(map(str, snippets.values()))
         self.snippets = snippets
 
-        self.operands = OperandList(compositeCode)
+        self.operands = OperandList(compositeCode, fixup_operands_fn)
         self.constructor = self.operands.concatAttrStrings('constructor')
         self.constructor += \
                  '\n\t_numSrcRegs = %d;' % self.operands.numSrcRegs
         self.constructor += \
                  '\n\t_numDestRegs = %d;' % self.operands.numDestRegs
diff -rU5 m5-vanilla/src/cpu/base_dyn_inst.hh m5/src/cpu/base_dyn_inst.hh
--- m5-vanilla/src/cpu/base_dyn_inst.hh 2009-07-03 10:41:31.000000000 +0100
+++ m5/src/cpu/base_dyn_inst.hh 2009-07-03 10:53:42.000000000 +0100
@@ -488,17 +488,20 @@
     bool isStoreConditional() const
     { return staticInst->isStoreConditional(); }
     bool isInstPrefetch() const { return staticInst->isInstPrefetch(); }
     bool isDataPrefetch() const { return staticInst->isDataPrefetch(); }
     bool isCopy()         const { return staticInst->isCopy(); }
+    bool isCond()         const { return staticInst->isCond(); }
     bool isInteger()      const { return staticInst->isInteger(); }
     bool isFloating()     const { return staticInst->isFloating(); }
     bool isControl()      const { return staticInst->isControl(); }
     bool isCall()         const { return staticInst->isCall(); }
     bool isReturn()       const { return staticInst->isReturn(); }
     bool isDirectCtrl()   const { return staticInst->isDirectCtrl(); }
     bool isIndirectCtrl() const { return staticInst->isIndirectCtrl(); }
+    bool isMemoryIndirectCtrl() const 
+    { return staticInst->isMemoryIndirectCtrl(); }
     bool isCondCtrl()     const { return staticInst->isCondCtrl(); }
     bool isUncondCtrl()   const { return staticInst->isUncondCtrl(); }
     bool isCondDelaySlot() const { return staticInst->isCondDelaySlot(); }
     bool isThreadSync()   const { return staticInst->isThreadSync(); }
     bool isSerializing()  const { return staticInst->isSerializing(); }
diff -rU5 m5-vanilla/src/cpu/static_inst.hh m5/src/cpu/static_inst.hh
--- m5-vanilla/src/cpu/static_inst.hh   2009-07-03 10:41:31.000000000 +0100
+++ m5/src/cpu/static_inst.hh   2009-07-03 10:53:42.000000000 +0100
@@ -138,14 +138,16 @@
         IsStoreConditional,    ///< Store conditional instruction.
         IsIndexed,      ///< Accesses memory with an indexed address 
computation
         IsInstPrefetch, ///< Instruction-cache prefetch.
         IsDataPrefetch, ///< Data-cache prefetch.
         IsCopy,         ///< Fast Cache block copy
+        IsCond,         ///< Predicated operation that may not be executed
 
         IsControl,              ///< Control transfer instruction.
         IsDirectControl,        ///< PC relative control transfer.
         IsIndirectControl,      ///< Register indirect control transfer.
+        IsMemoryIndirectControl,///< Memory indirect control transfer.
         IsCondControl,          ///< Conditional control transfer.
         IsUncondControl,        ///< Unconditional control transfer.
         IsCall,                 ///< Subroutine call.
         IsReturn,               ///< Subroutine return.
 
@@ -246,18 +248,21 @@
     bool isStoreConditional()     const { return flags[IsStoreConditional]; }
     bool isInstPrefetch() const { return flags[IsInstPrefetch]; }
     bool isDataPrefetch() const { return flags[IsDataPrefetch]; }
     bool isCopy()         const { return flags[IsCopy];}
 
+    bool isCond()         const { return flags[IsCond];}
+
     bool isInteger()      const { return flags[IsInteger]; }
     bool isFloating()     const { return flags[IsFloating]; }
 
     bool isControl()      const { return flags[IsControl]; }
     bool isCall()         const { return flags[IsCall]; }
     bool isReturn()       const { return flags[IsReturn]; }
     bool isDirectCtrl()   const { return flags[IsDirectControl]; }
     bool isIndirectCtrl() const { return flags[IsIndirectControl]; }
+    bool isMemoryIndirectCtrl() const { return flags[IsMemoryIndirectControl]; 
}
     bool isCondCtrl()     const { return flags[IsCondControl]; }
     bool isUncondCtrl()   const { return flags[IsUncondControl]; }
     bool isCondDelaySlot() const { return flags[IsCondDelaySlot]; }
 
     bool isThreadSync()   const { return flags[IsThreadSync]; }
_______________________________________________
m5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/m5-dev

Reply via email to