// ARM ARM B1-3
 
     SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR);
-    
+
     // panic if SCTLR.VE because I have no idea what to do with vectored
     // interrupts
     assert(!sctlr.ve);
-    
+
     if (!sctlr.v)
         return offset();
     return offset() + HighVecs;
     }
 
     Addr pc = tc->readPC();
-    DPRINTF(Faults, "Invoking Fault: %s cpsr: %#x PC: %#x lr: %#x\n",
-            name(), cpsr, pc, tc->readIntReg(INTREG_LR));
     Addr newPc = getVector(tc) | (sctlr.te ? (ULL(1) << PcTBitShift) : 0);
+    DPRINTF(Faults, "Invoking Fault: %s cpsr: %#x PC: %#x lr: %#x newVector: %#x\n",
+            name(), cpsr, pc, tc->readIntReg(INTREG_LR), newPc);
     tc->setPC(newPc);
     tc->setNextPC(newPc + cpsr.t ? 2 : 4 );
     tc->setMicroPC(0);
 }
 
+void
+Reset::invoke(ThreadContext *tc)
+{
+    tc->getCpuPtr()->clearInterrupts();
+    tc->clearArchRegs();
+    ArmFault::invoke(tc);
+}
+
 #else
 
 void
 
     bool fiqDisable() { return vals.fiqDisable; }
 };
 
-
-class Reset : public ArmFaultVals<Reset> {};
+class Reset : public ArmFaultVals<Reset>
+#if FULL_SYSTEM
+{
+  public:
+    void invoke(ThreadContext *tc);
+};
+#else
+{};
+#endif //FULL_SYSTEM
 
 class UndefinedInstruction : public ArmFaultVals<UndefinedInstruction>
 {
 
 
     static uint32_t
     cpsrWriteByInstr(CPSR cpsr, uint32_t val,
-            uint8_t byteMask, bool affectState)
+            uint8_t byteMask, bool affectState, bool nmfi)
     {
         bool privileged = (cpsr.mode != MODE_USER);
 
                 bitMask = bitMask | (1 << 5);
         }
 
-        return ((uint32_t)cpsr & ~bitMask) | (val & bitMask);
+        bool cpsr_f = cpsr.f;
+        uint32_t new_cpsr = ((uint32_t)cpsr & ~bitMask) | (val & bitMask);
+        if (nmfi && !cpsr_f)
+            new_cpsr &= ~(1 << 6);
+        return new_cpsr;
     }
 
     static uint32_t
 
  * Copyright (c) 2009 ARM Limited
  * All rights reserved.
  *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * 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
 
 /*
+ * Copyright (c) 2010 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * Copyright (c) 2006 The Regents of The University of Michigan
- * Copyright (c) 2009 ARM Limited
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 
 #include "arch/arm/faults.hh"
 #include "arch/arm/isa_traits.hh"
+#include "arch/arm/miscregs.hh"
 #include "arch/arm/registers.hh"
 #include "cpu/thread_context.hh"
 #include "params/ArmInterrupts.hh"
   private:
     BaseCPU * cpu;
 
+    bool interrupts[NumInterruptTypes];
     uint64_t intStatus;
 
   public:
     void
     post(int int_num, int index)
     {
+        DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
+
+        if (int_num < 0 || int_num >= NumInterruptTypes)
+            panic("int_num out of bounds\n");
+
+        if (index != 0)
+            panic("No support for other interrupt indexes\n");
+
+        interrupts[int_num] = true;
+        intStatus |= ULL(1) << int_num;
     }
 
     void
     clear(int int_num, int index)
     {
+        DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
+
+        if (int_num < 0 || int_num >= NumInterruptTypes)
+            panic("int_num out of bounds\n");
+
+        if (index != 0)
+            panic("No support for other interrupt indexes\n");
+
+        interrupts[int_num] = false;
+        intStatus &= ~(ULL(1) << int_num);
+
     }
 
     void
     clearAll()
     {
+        DPRINTF(Interrupt, "Interrupts all cleared\n");
         intStatus = 0;
+        memset(interrupts, 0, sizeof(interrupts));
     }
 
     bool
     checkInterrupts(ThreadContext *tc) const
     {
-        return intStatus;
+        if (!intStatus)
+            return false;
+
+        CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
+
+        return ((interrupts[INT_IRQ] && !cpsr.i) ||
+                (interrupts[INT_FIQ] && !cpsr.f) ||
+                (interrupts[INT_ABT] && !cpsr.a) ||
+                (interrupts[INT_RST]));
     }
 
     Fault
     getInterrupt(ThreadContext *tc)
     {
-        warn_once("ARM  Interrupts not handled\n");
-        return NoFault;
+        if (!intStatus)
+            return NoFault;
+
+        CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
+
+        if (interrupts[INT_IRQ] && !cpsr.i)
+            return new Interrupt;
+        if (interrupts[INT_FIQ] && !cpsr.f)
+            return new FastInterrupt;
+        if (interrupts[INT_ABT] && !cpsr.a)
+            return new DataAbort(0, false, 0,
+                    ArmFault::AsynchronousExternalAbort);
+        if (interrupts[INT_RST])
+           return new Reset;
+
+        panic("intStatus and interrupts not in sync\n");
     }
 
     void
     updateIntrInfo(ThreadContext *tc)
     {
-
+        ; // nothing to do
     }
 
     void
     serialize(std::ostream &os)
     {
+        SERIALIZE_ARRAY(interrupts, NumInterruptTypes);
+        SERIALIZE_SCALAR(intStatus);
     }
 
     void
     unserialize(Checkpoint *cp, const std::string §ion)
     {
+        UNSERIALIZE_ARRAY(interrupts, NumInterruptTypes);
+        UNSERIALIZE_SCALAR(intStatus);
     }
 };
 } // namespace ARM_ISA
 
       public:
         void clear()
         {
+            SCTLR sctlr_rst = miscRegs[MISCREG_SCTLR_RST];
+
             memset(miscRegs, 0, sizeof(miscRegs));
             CPSR cpsr = 0;
             cpsr.mode = MODE_USER;
             updateRegMap(cpsr);
 
             SCTLR sctlr = 0;
-            sctlr.nmfi = 1;
+            sctlr.nmfi = (bool)sctlr_rst.nmfi;
+            sctlr.v = (bool)sctlr_rst.v;
+            sctlr.u    = 1;
             sctlr.rao1 = 1;
             sctlr.rao2 = 1;
             sctlr.rao3 = 1;
             sctlr.rao4 = 1;
             miscRegs[MISCREG_SCTLR] = sctlr;
+            miscRegs[MISCREG_SCTLR_RST] = sctlr_rst;
+
 
             /*
              * Technically this should be 0, but we don't support those
                              (miscRegs[MISCREG_FPEXC] & ~fpexcMask);
                 }
                 break;
+              case MISCREG_SCTLR:
+                {
+                    SCTLR sctlr = miscRegs[MISCREG_SCTLR];
+                    SCTLR new_sctlr = newVal;
+                    new_sctlr.nmfi =  (bool)sctlr.nmfi;
+                    miscRegs[MISCREG_SCTLR] = (MiscReg)new_sctlr;
+                    return;
+                }
               case MISCREG_TLBTR:
               case MISCREG_MVFR0:
               case MISCREG_MVFR1:
               case MISCREG_FPSID:
                 return;
             }
-            return setMiscRegNoEffect(misc_reg, newVal);
+            setMiscRegNoEffect(misc_reg, newVal);
         }
 
         int
 
         ISA()
         {
+            SCTLR sctlr;
+            sctlr = 0;
+            miscRegs[MISCREG_SCTLR_RST] = sctlr;
+
             clear();
         }
     };
 
 #endif
                 }
                 default: PredImmOp::msr_i_cpsr({{
+                            SCTLR sctlr = Sctlr;
                             uint32_t newCpsr =
                                 cpsrWriteByInstr(Cpsr | CondCodes,
-                                                 rotated_imm, RN, false);
+                                                 rotated_imm, RN, false, sctlr.nmfi);
                             Cpsr = ~CondCodesMask & newCpsr;
                             CondCodes = CondCodesMask & newCpsr;
                 }});
 
         buildRegRegDataInst(mnem, regRegCode, flagType)
         if subsPcLr:
             code += '''
+            SCTLR sctlr = Sctlr;
             uint32_t newCpsr =
-                cpsrWriteByInstr(Cpsr | CondCodes, Spsr, 0xF, true);
+                cpsrWriteByInstr(Cpsr | CondCodes, Spsr, 0xF, true, sctlr.nmfi);
             Cpsr = ~CondCodesMask & newCpsr;
             CondCodes = CondCodesMask & newCpsr;
             '''
 
             wbDiff = 8
         accCode = '''
         CPSR cpsr = Cpsr;
+        SCTLR sctlr = Sctlr;
         NPC = cSwap<uint32_t>(Mem.ud, cpsr.e);
         uint32_t newCpsr =
             cpsrWriteByInstr(cpsr | CondCodes,
                              cSwap<uint32_t>(Mem.ud >> 32, cpsr.e),
-                             0xF, true);
+                             0xF, true, sctlr.nmfi);
         Cpsr = ~CondCodesMask & newCpsr;
         CondCodes = CondCodesMask & newCpsr;
         '''
 
 
     microLdrRetUopCode = '''
         CPSR cpsr = Cpsr;
+        SCTLR sctlr = Sctlr;
         uint32_t newCpsr =
-            cpsrWriteByInstr(cpsr | CondCodes, Spsr, 0xF, true);
+            cpsrWriteByInstr(cpsr | CondCodes, Spsr, 0xF, true, sctlr.nmfi);
         Cpsr = ~CondCodesMask & newCpsr;
         CondCodes = CondCodesMask & newCpsr;
         IWNPC = cSwap(Mem.uw, cpsr.e) | ((Spsr & 0x20) ? 1 : 0);
 
     exec_output += PredOpExecute.subst(mrsSpsrIop)
 
     msrCpsrRegCode = '''
+        SCTLR sctlr = Sctlr;
         uint32_t newCpsr =
-            cpsrWriteByInstr(Cpsr | CondCodes, Op1, byteMask, false);
+            cpsrWriteByInstr(Cpsr | CondCodes, Op1, byteMask, false, sctlr.nmfi);
         Cpsr = ~CondCodesMask & newCpsr;
         CondCodes = CondCodesMask & newCpsr;
     '''
     exec_output += PredOpExecute.subst(msrSpsrRegIop)
 
     msrCpsrImmCode = '''
+        SCTLR sctlr = Sctlr;
         uint32_t newCpsr =
-            cpsrWriteByInstr(Cpsr | CondCodes, imm, byteMask, false);
+            cpsrWriteByInstr(Cpsr | CondCodes, imm, byteMask, false, sctlr.nmfi);
         Cpsr = ~CondCodesMask & newCpsr;
         CondCodes = CondCodesMask & newCpsr;
     '''
     bool setMode = bits(imm, 8);
     bool enable = bits(imm, 9);
     CPSR cpsr = Cpsr;
+    SCTLR sctlr = Sctlr;
     if (cpsr.mode != MODE_USER) {
         if (enable) {
             if (f) cpsr.f = 0;
             if (i) cpsr.i = 0;
             if (a) cpsr.a = 0;
         } else {
-            if (f) cpsr.f = 1;
+            if (f && !sctlr.nmfi) cpsr.f = 1;
             if (i) cpsr.i = 1;
             if (a) cpsr.a = 1;
         }
 
     const int LogVMPageSize = 12;      // 4K bytes
     const int VMPageSize = (1 << LogVMPageSize);
 
+    // Shouldn't this be 1 because of Thumb?! Dynamic? --Ali
     const int BranchPredAddrShiftAmt = 2; // instructions are 4-byte aligned
 
     const int MachineBytes = 4;
     // Memory accesses cannot be unaligned
     const bool HasUnalignedMemAcc = false;
 
+    enum InterruptTypes
+    {
+        INT_RST,
+        INT_ABT,
+        INT_IRQ,
+        INT_FIQ,
+        NumInterruptTypes
+    };
+
     // These otherwise unused bits of the PC are used to select a mode
     // like the J and T bits of the CPSR.
     static const Addr PcJBitShift = 33;
 
         MISCREG_FPEXC,
         MISCREG_MVFR0,
         MISCREG_MVFR1,
+        MISCREG_SCTLR_RST,
         MISCREG_SEV_MAILBOX,
 
         // CP15 registers
         "cpsr", "spsr", "spsr_fiq", "spsr_irq", "spsr_svc",
         "spsr_mon", "spsr_und", "spsr_abt",
         "fpsr", "fpsid", "fpscr", "fpexc", "mvfr0", "mvfr1",
-        "sev_mailbox",
+        "sctlr_rst", "sev_mailbox",
         "sctlr", "dccisw", "dccimvac", "dccmvac",
         "contextidr", "tpidrurw", "tpidruro", "tpidrprw",
         "cp15isb", "cp15dsb", "cp15dmb", "cpacr",
 
         PC = nextPC = nextNPC = 0;
         memset(intRegs, 0, sizeof(intRegs));
         memset(floatRegs.i, 0, sizeof(floatRegs.i));
+        isa.clear();
     }
 
     //