Add support for ARM's v5TE architecture and Intel's XScale extenstions
authorNick Clifton <nickc@redhat.com>
Thu, 30 Nov 2000 01:55:12 +0000 (01:55 +0000)
committerNick Clifton <nickc@redhat.com>
Thu, 30 Nov 2000 01:55:12 +0000 (01:55 +0000)
12 files changed:
sim/arm/ChangeLog
sim/arm/armcopro.c
sim/arm/armdefs.h
sim/arm/armemu.c
sim/arm/armemu.h
sim/arm/arminit.c
sim/arm/armos.c
sim/arm/armsupp.c
sim/arm/thumbemu.c
sim/arm/wrapper.c
sim/configure
sim/configure.in

index b66a3403bc323c8a548a558118d75e4218f49a04..2c893e00a2d1260d835d82b73166300486b13486 100644 (file)
@@ -1,3 +1,30 @@
+2000-11-29  Nick Clifton  <nickc@redhat.com>
+
+       * armdefs.h (State): Add 'v5e' and 'xscale' fields.
+       (ARM_v5e_Prop): Define.
+       (ARM_XScale_Prop): Define.
+       
+       * wrapper.c (sim_create_inferior): Select processor based on
+       machine number.
+       (SWI_vector_installed): New boolean.  Set to true if the SWI
+       vector address is written to by the executable.
+       
+       * arminit.c (ARMul_NewState): Switch default to 32 bit mode.
+       (ARMul_SelectProcessor): Initialise v5e and xscale signals.
+       (ARMul_Abort): Fix calculation of LR address.
+
+       * armos.c (ARMul_OSHandleSWI): If a SWI vector has been installed
+       and a SWI is not handled by the simulator, pass the SWI off to the
+       vector, otherwise issue a warning message and continue.
+
+       * armsupp.c (ARMul_CPSRAltered): Set S bit aswell.
+       
+       * thumbemu.c: Add v5 instruction simulation.
+       * armemu.c: Add v5, XScale and El Segundo instruction simulation.
+
+       * armcopro.c: Add XScale co-processor emulation.
+       * armemu.h: Add exported XScale co-processor functions.
+       
 2000-09-15  Nick Clifton  <nickc@redhat.com>
 
        * armdefs.h: Rename StrongARM property to v4_ARM and add v5 ARM
@@ -189,7 +216,6 @@ Thu Sep  2 18:15:53 1999  Andrew Cagney  <cagney@b1.cygnus.com>
 
        * configure: Regenerated to track ../common/aclocal.m4 changes.
 
-
 1999-05-08  Felix Lee  <flee@cygnus.com>
 
        * configure: Regenerated to track ../common/aclocal.m4 changes.
index 48be6806ea22a059c83b1b065a3643c0be62037c..db7ee60d69c95c0aaa3cfc568abdeeabf245b7b6 100644 (file)
 #include "armemu.h"
 #include "ansidecl.h"
 
-extern unsigned ARMul_CoProInit (ARMul_State * state);
-extern void ARMul_CoProExit (ARMul_State * state);
-extern void ARMul_CoProAttach (ARMul_State * state, unsigned number,
-                              ARMul_CPInits * init, ARMul_CPExits * exit,
-                              ARMul_LDCs * ldc, ARMul_STCs * stc,
-                              ARMul_MRCs * mrc, ARMul_MCRs * mcr,
-                              ARMul_CDPs * cdp,
-                              ARMul_CPReads * read, ARMul_CPWrites * write);
-extern void ARMul_CoProDetach (ARMul_State * state, unsigned number);
+/* Dummy Co-processors.  */
 
+static unsigned
+NoCoPro3R (ARMul_State * state ATTRIBUTE_UNUSED,
+          unsigned      a     ATTRIBUTE_UNUSED,
+          ARMword       b     ATTRIBUTE_UNUSED)
+{
+  return ARMul_CANT;
+}
 
-/***************************************************************************\
-*                            Dummy Co-processors                            *
-\***************************************************************************/
+static unsigned
+NoCoPro4R (ARMul_State * state ATTRIBUTE_UNUSED,
+          unsigned      a     ATTRIBUTE_UNUSED,
+          ARMword       b     ATTRIBUTE_UNUSED,
+          ARMword       c     ATTRIBUTE_UNUSED)
+{
+  return ARMul_CANT;
+}
+
+static unsigned
+NoCoPro4W (ARMul_State * state ATTRIBUTE_UNUSED,
+          unsigned      a     ATTRIBUTE_UNUSED,
+          ARMword       b     ATTRIBUTE_UNUSED,
+          ARMword *     c     ATTRIBUTE_UNUSED)
+{
+  return ARMul_CANT;
+}
 
-static unsigned NoCoPro3R (ARMul_State * state, unsigned, ARMword);
-static unsigned NoCoPro4R (ARMul_State * state, unsigned, ARMword, ARMword);
-static unsigned NoCoPro4W (ARMul_State * state, unsigned, ARMword, ARMword *);
+/* The XScale Co-processors.  */
 
-/***************************************************************************\
-*                Define Co-Processor instruction handlers here              *
-\***************************************************************************/
+/* Coprocessor 15:  System Control.  */
+
+/* There are two sets of registers for copro 15.
+   One set is available when opcode_2 is 0 and
+   the other set when opcode_2 >= 1.  */
+static ARMword XScale_cp15_opcode_2_is_0_Regs[16];
+static ARMword XScale_cp15_opcode_2_is_not_0_Regs[16];
+/* There are also a set of breakpoint registers
+   which are accessed via CRm instead of opcode_2.  */
+static ARMword XScale_cp15_DBR1;
+static ARMword XScale_cp15_DBCON;
+static ARMword XScale_cp15_IBCR0;
+static ARMword XScale_cp15_IBCR1;
+
+static unsigned
+XScale_cp15_init (ARMul_State * state ATTRIBUTE_UNUSED)
+{
+  int i;
+
+  for (i = 16; i--;)
+    {
+      XScale_cp15_opcode_2_is_0_Regs[i] = 0;
+      XScale_cp15_opcode_2_is_not_0_Regs[i] = 0;
+    }
+
+  /* Initialise the processor ID.  */
+  XScale_cp15_opcode_2_is_0_Regs[0] = 0x69052000;
+
+  /* Initialise the cache type.  */
+  XScale_cp15_opcode_2_is_not_0_Regs[0] = 0x0B1AA1AA;
+
+  /* Initialise the ARM Control Register.  */
+  XScale_cp15_opcode_2_is_0_Regs[1] = 0x00000078;
+  
+}
+
+/* Check an access to a register.  */
+
+static unsigned
+check_cp15_access (ARMul_State * state,
+                  unsigned      reg,
+                  unsigned      CRm,
+                  unsigned      opcode_1,
+                  unsigned      opcode_2)
+{
+  /* Do not allow access to these register in USER mode.  */
+  if (state->Mode == USER26MODE || state->Mode == USER32MODE)
+    return ARMul_CANT;
+
+  /* Opcode_1should be zero.  */
+  if (opcode_1 != 0)
+    return ARMul_CANT;
+  
+  /* Different register have different access requirements.  */
+  switch (reg)
+    {
+    case 0:
+    case 1:
+      /* CRm must be 0.  Opcode_2 can be anything.  */
+      if (CRm != 0)
+       return ARMul_CANT;
+      break;      
+    case 2:
+    case 3:
+      /* CRm must be 0.  Opcode_2 must be zero.  */
+      if ((CRm != 0) || (opcode_2 != 0))
+       return ARMul_CANT;
+      break;
+    case 4:
+      /* Access not allowed.  */
+      return ARMul_CANT;
+    case 5:
+    case 6:
+      /* Opcode_2 must be zero.  CRm must be 0.  */
+      if ((CRm != 0) || (opcode_2 != 0))
+       return ARMul_CANT;
+      break;
+    case 7:
+      /* Permissable combinations:
+          Opcode_2  CRm
+             0       5
+             0       6
+             0       7
+             1       5
+             1       6
+             1      10
+             4      10
+             5       2
+             6       5  */
+      switch (opcode_2)
+       {
+       default:               return ARMul_CANT;
+       case 6: if (CRm !=  5) return ARMul_CANT; break;
+       case 5: if (CRm !=  2) return ARMul_CANT; break;
+       case 4: if (CRm != 10) return ARMul_CANT; break;
+       case 1: if ((CRm != 5) && (CRm != 6) && (CRm != 10)) return ARMul_CANT; break;
+       case 0: if ((CRm < 5) || (CRm > 7)) return ARMul_CANT; break;
+       }
+      break;
+      
+    case 8:
+      /* Permissable combinations:
+          Opcode_2  CRm
+             0       5
+             0       6
+             0       7
+             1       5
+             1       6  */
+      if (opcode_2 > 1)
+       return ARMul_CANT;
+      if ((CRm < 5) || (CRm > 7))
+       return ARMul_CANT;
+      if (opcode_2 == 1 && CRm == 7)
+       return ARMul_CANT;
+      break;
+    case 9:
+      /* Opcode_2 must be zero or one.  CRm must be 1 or 2.  */
+      if (   ((CRm != 0) && (CRm != 1))
+         || ((opcode_2 != 1) && (opcode_2 != 2)))
+       return ARMul_CANT;
+      break;
+    case 10:
+      /* Opcode_2 must be zero or one.  CRm must be 4 or 8.  */
+      if (   ((CRm != 0) && (CRm != 1))
+         || ((opcode_2 != 4) && (opcode_2 != 8)))
+       return ARMul_CANT;
+      break;
+    case 11:
+      /* Access not allowed.  */
+      return ARMul_CANT;
+    case 12:
+      /* Access not allowed.  */
+      return ARMul_CANT;
+    case 13:
+      /* Opcode_2 must be zero.  CRm must be 0.  */
+      if ((CRm != 0) || (opcode_2 != 0))
+       return ARMul_CANT;
+      break;
+    case 14:
+      /* Opcode_2 must be 0.  CRm must be 0, 3, 4, 8 or 9.  */
+      if (opcode_2 != 0)
+       return ARMul_CANT;
+
+      if ((CRm != 0) && (CRm != 3) && (CRm != 4) && (CRm != 8) && (CRm != 9))
+       return ARMul_CANT;
+      break;
+    case 15:
+      /* Opcode_2 must be zero.  CRm must be 1.  */
+      if ((CRm != 1) || (opcode_2 != 0))
+       return ARMul_CANT;
+      break;
+    default:
+      /* Should never happen.  */
+      return ARMul_CANT;
+    }
+  
+  return ARMul_DONE;
+}
+
+/* Store a value into one of coprocessor 15's registers.  */
+
+void
+write_cp15_reg (unsigned reg, unsigned opcode_2, unsigned CRm, ARMword value)
+{
+  if (opcode_2)
+    {
+      switch (reg)
+       {
+       case 0: /* Cache Type.  */
+         /* Writes are not allowed.  */
+         return;
+
+       case 1: /* Auxillary Control.  */
+         /* Only BITS (5, 4) and BITS (1, 0) can be written.  */
+         value &= 0x33;
+         break;
+         
+       default:
+         return;
+       }
+      
+      XScale_cp15_opcode_2_is_not_0_Regs [reg] = value;
+    }
+  else
+    {
+      switch (reg)
+       {
+       case 0: /* ID.  */
+         /* Writes are not allowed.  */
+         return;
+
+       case 1: /* ARM Control.  */
+         /* Only BITS (13, 11), BITS (9, 7) and BITS (2, 0) can be written.
+            BITS (31, 14) and BIT (10) write as zero, BITS (6, 3) write as one.  */
+         value &= 0x00003b87;
+         value |= 0x00000078;
+         break;
+
+       case 2: /* Translation Table Base.  */
+         /* Only BITS (31, 14) can be written.  */
+         value &= 0xffffc000;
+         break;
+         
+       case 3: /* Domain Access Control.  */
+         /* All bits writable.  */
+         break;
+         
+       case 5: /* Fault Status Register.  */
+         /* BITS (10, 9) and BITS (7, 0) can be written.  */
+         value &= 0x000006ff;
+         break;
+
+       case 6: /* Fault Address Register.  */
+         /* All bits writable.  */
+         break;
+
+       case 7: /* Cache Functions.  */
+       case 8: /* TLB Operations.  */
+       case 10: /* TLB Lock Down.  */
+         /* Ignore writes.  */
+         return;
+
+       case 9: /* Data Cache Lock.  */
+         /* Only BIT (0) can be written.  */
+         value &= 0x1;
+         break;
+
+       case 13: /* Process ID.  */
+         /* Only BITS (31, 25) are writable.  */
+         value &= 0xfe000000;
+         break;
+
+       case 14: /* DBR0, DBR1, DBCON, IBCR0, IBCR1 */
+         /* All bits can be written.  Which register is accessed is
+            dependent upon CRm.  */
+         switch (CRm)
+           {
+           case 0: /* DBR0 */
+             break;
+           case 3: /* DBR1 */
+             XScale_cp15_DBR1 = value;
+             break;
+           case 4: /* DBCON */
+             XScale_cp15_DBCON = value;
+             break;
+           case 8: /* IBCR0 */
+             XScale_cp15_IBCR0 = value;
+             break;
+           case 9: /* IBCR1 */
+             XScale_cp15_IBCR1 = value;
+             break;
+           default:
+             return;
+           }
+         break;
+
+       case 15: /* Coprpcessor Access Register.  */
+         /* Access is only valid if CRm == 1.  */
+         if (CRm != 1)
+           return;
+         
+         /* Only BITS (13, 0) may be written.  */
+         value &= 0x00003fff;
+         break;
+         
+       default:
+         return;
+       }
+
+      XScale_cp15_opcode_2_is_0_Regs [reg] = value;
+    }
+  
+  return;
+}
+
+/* Return the value in a cp13 register.  */
+
+static ARMword
+read_cp15_reg (unsigned reg, unsigned opcode_2, unsigned CRm)
+{
+  if (opcode_2 == 0)
+    {
+      if (reg == 15 && CRm != 1)
+       return 0;
+
+      if (reg == 14)
+       {
+         switch (CRm)
+           {
+           case 3: return XScale_cp15_DBR1;
+           case 4: return XScale_cp15_DBCON;
+           case 8: return XScale_cp15_IBCR0;
+           case 9: return XScale_cp15_IBCR1;
+           default:
+             break;
+           }
+       }
+      
+      return XScale_cp15_opcode_2_is_0_Regs [reg];
+    }
+  else
+    return XScale_cp15_opcode_2_is_not_0_Regs [reg];
+
+  return 0;
+}
+
+static unsigned
+XScale_cp15_LDC (ARMul_State * state, unsigned type, ARMword instr, ARMword data)
+{
+  unsigned reg = BITS (12, 15);
+  unsigned result;
+  
+  result = check_cp15_access (state, reg, 0, 0, 0);
+  
+  if (result == ARMul_DONE && type == ARMul_DATA)
+    write_cp15_reg (reg, 0, 0, data);
+
+  return result;
+}
+
+static unsigned
+XScale_cp15_STC (ARMul_State * state, unsigned type, ARMword instr, ARMword * data)
+{
+  unsigned reg = BITS (12, 15);
+  unsigned result;
+  
+  result = check_cp15_access (state, reg, 0, 0, 0);
+  
+  if (result == ARMul_DONE && type == ARMul_DATA)
+    * data = read_cp15_reg (reg, 0, 0);
+  
+  return result;
+}
+
+static unsigned
+XScale_cp15_MRC (ARMul_State * state,
+             unsigned      type ATTRIBUTE_UNUSED,
+             ARMword       instr,
+             ARMword *     value)
+{
+  unsigned opcode_2 = BITS (5, 7);
+  unsigned CRm = BITS (0, 3);
+  unsigned reg = BITS (16, 19);
+  unsigned result;
+  
+  result = check_cp15_access (state, reg, CRm, BITS (21, 23), opcode_2);
+  
+  if (result == ARMul_DONE)
+    * value = read_cp15_reg (reg, opcode_2, CRm);
+  
+  return result;
+}
+
+static unsigned
+XScale_cp15_MCR (ARMul_State * state,
+             unsigned      type ATTRIBUTE_UNUSED,
+             ARMword       instr,
+             ARMword       value)
+{
+  unsigned opcode_2 = BITS (5, 7);
+  unsigned CRm = BITS (0, 3);
+  unsigned reg = BITS (16, 19);
+  unsigned result;
+  
+  result = check_cp15_access (state, reg, CRm, BITS (21, 23), opcode_2);
+  
+  if (result == ARMul_DONE)
+    write_cp15_reg (reg, opcode_2, CRm, value);
+  
+  return result;
+}
+
+static unsigned
+XScale_cp15_read_reg (ARMul_State * state ATTRIBUTE_UNUSED,
+                  unsigned      reg,
+                  ARMword *     value)
+{
+  /* FIXME: Not sure what to do about the alternative register set
+     here.  For now default to just accessing CRm == 0 registers.  */
+  * value = read_cp15_reg (reg, 0, 0);
+  
+  return TRUE;
+}
+
+static unsigned
+XScale_cp15_write_reg (ARMul_State * state ATTRIBUTE_UNUSED,
+                   unsigned      reg,
+                   ARMword       value)
+{
+  /* FIXME: Not sure what to do about the alternative register set
+     here.  For now default to just accessing CRm == 0 registers.  */
+  write_cp15_reg (reg, 0, 0, value);
+  
+  return TRUE;
+}
+
+/* Coprocessor 13:  Interrupt Controller and Bus Controller.  */
+
+/* There are two sets of registers for copro 13.
+   One set (of three registers) is available when CRm is 0
+   and the other set (of six registers) when CRm is 1.  */
+
+static ARMword XScale_cp13_CR0_Regs[16];
+static ARMword XScale_cp13_CR1_Regs[16];
+
+static unsigned
+XScale_cp13_init (ARMul_State * state ATTRIBUTE_UNUSED)
+{
+  int i;
+
+  for (i = 16; i--;)
+    {
+      XScale_cp13_CR0_Regs[i] = 0;
+      XScale_cp13_CR1_Regs[i] = 0;
+    }
+}
+
+/* Check an access to a register.  */
+
+static unsigned
+check_cp13_access (ARMul_State * state,
+                  unsigned      reg,
+                  unsigned      CRm,
+                  unsigned      opcode_1,
+                  unsigned      opcode_2)
+{
+  /* Do not allow access to these register in USER mode.  */
+  if (state->Mode == USER26MODE || state->Mode == USER32MODE)
+    return ARMul_CANT;
+
+  /* The opcodes should be zero.  */
+  if ((opcode_1 != 0) || (opcode_2 != 0))
+    return ARMul_CANT;
+  
+  /* Do not allow access to these register if bit 13 of coprocessor
+     15's register 15 is zero.  */
+  if ((XScale_cp15_opcode_2_is_0_Regs[15] & (1 << 13)) == 0)
+    return ARMul_CANT;
+  
+  /* Registers 0, 4 and 8 are defined when CRm == 0.
+     Registers 0, 4, 5, 6, 7, 8 are defined when CRm == 1.
+     For all other CRm values undefined behaviour results.  */
+  if (CRm == 0)
+    {
+      if (reg == 0 || reg == 4 || reg == 8)
+       return ARMul_DONE;
+    }
+  else if (CRm == 1)
+    {
+      if (reg == 0 || (reg >= 4 && reg <= 8))
+       return ARMul_DONE;
+    }
+
+  return ARMul_CANT;
+}
+
+/* Store a value into one of coprocessor 13's registers.  */
+
+static void
+write_cp13_reg (unsigned reg, unsigned CRm, ARMword value)
+{
+  switch (CRm)
+    {
+    case 0:
+      switch (reg)
+       {
+       case 0: /* INTCTL */
+         /* Only BITS (3:0) can be written.  */
+         value &= 0xf;
+         break;
+         
+       case 4: /* INTSRC */
+         /* No bits may be written.  */
+         return;
+         
+       case 8: /* INTSTR */
+         /* Only BITS (1:0) can be written.  */
+         value &= 0x3;
+         break;
+         
+       default:
+         /* Should not happen.  Ignore any writes to unimplemented registers.  */
+         return;
+       }
+      
+      XScale_cp13_CR0_Regs [reg] = value;
+      break;
+
+    case 1:
+      switch (reg)
+       {
+       case 0: /* BCUCTL */
+         /* Only BITS (30:28) and BITS (3:0) can be written.
+            BIT(31) is write ignored.  */
+         value &= 0x7000000f;
+         value |= XScale_cp13_CR1_Regs[0] & (1UL << 31);
+         break;
+         
+       case 4: /* ELOG0 */
+       case 5: /* ELOG1 */
+       case 6: /* ECAR0 */
+       case 7: /* ECAR1 */
+         /* No bits can be written.  */
+         return;
+
+       case 8: /* ECTST */
+         /* Only BITS (7:0) can be written.  */
+         value &= 0xff;
+         break;
+         
+       default:
+         /* Should not happen.  Ignore any writes to unimplemented registers.  */
+         return;
+       }
+      
+      XScale_cp13_CR1_Regs [reg] = value;
+      break;
+
+    default:
+      /* Should not happen.  */
+      break;
+    }
+  
+  return;
+}
+
+/* Return the value in a cp13 register.  */
+
+static ARMword
+read_cp13_reg (unsigned reg, unsigned CRm)
+{
+  if (CRm == 0)
+    return XScale_cp13_CR0_Regs [reg];
+  else if (CRm == 1)
+    return XScale_cp13_CR1_Regs [reg];
+
+  return 0;
+}
+
+static unsigned
+XScale_cp13_LDC (ARMul_State * state, unsigned type, ARMword instr, ARMword data)
+{
+  unsigned reg = BITS (12, 15);
+  unsigned result;
+  
+  result = check_cp13_access (state, reg, 0, 0, 0);
+  
+  if (result == ARMul_DONE && type == ARMul_DATA)
+    write_cp13_reg (reg, 0, data);
+
+  return result;
+}
+
+static unsigned
+XScale_cp13_STC (ARMul_State * state, unsigned type, ARMword instr, ARMword * data)
+{
+  unsigned reg = BITS (12, 15);
+  unsigned result;
+  
+  result = check_cp13_access (state, reg, 0, 0, 0);
+  
+  if (result == ARMul_DONE && type == ARMul_DATA)
+    * data = read_cp13_reg (reg, 0);
+  
+  return result;
+}
+
+static unsigned
+XScale_cp13_MRC (ARMul_State * state,
+             unsigned      type ATTRIBUTE_UNUSED,
+             ARMword       instr,
+             ARMword *     value)
+{
+  unsigned CRm = BITS (0, 3);
+  unsigned reg = BITS (16, 19);
+  unsigned result;
+  
+  result = check_cp13_access (state, reg, CRm, BITS (21, 23), BITS (5, 7));
+  
+  if (result == ARMul_DONE)
+    * value = read_cp13_reg (reg, CRm);
+  
+  return result;
+}
+
+static unsigned
+XScale_cp13_MCR (ARMul_State * state,
+             unsigned      type ATTRIBUTE_UNUSED,
+             ARMword       instr,
+             ARMword       value)
+{
+  unsigned CRm = BITS (0, 3);
+  unsigned reg = BITS (16, 19);
+  unsigned result;
+  
+  result = check_cp13_access (state, reg, CRm, BITS (21, 23), BITS (5, 7));
+  
+  if (result == ARMul_DONE)
+    write_cp13_reg (reg, CRm, value);
+  
+  return result;
+}
+
+static unsigned
+XScale_cp13_read_reg
+(
+ ARMul_State * state ATTRIBUTE_UNUSED,
+ unsigned      reg,
+ ARMword *     value
+)
+{
+  /* FIXME: Not sure what to do about the alternative register set
+     here.  For now default to just accessing CRm == 0 registers.  */
+  * value = read_cp13_reg (reg, 0);
+  
+  return TRUE;
+}
+
+static unsigned
+XScale_cp13_write_reg
+(
+ ARMul_State * state ATTRIBUTE_UNUSED,
+ unsigned      reg,
+ ARMword       value
+)
+{
+  /* FIXME: Not sure what to do about the alternative register set
+     here.  For now default to just accessing CRm == 0 registers.  */
+  write_cp13_reg (reg, 0, value);
+  
+  return TRUE;
+}
+
+/* Coprocessor 14:  Performance Monitoring,  Clock and Power management,
+   Software Debug.  */
+
+static ARMword XScale_cp14_Regs[16];
+
+static unsigned
+XScale_cp14_init (ARMul_State * state ATTRIBUTE_UNUSED)
+{
+  int i;
+
+  for (i = 16; i--;)
+    XScale_cp14_Regs[i] = 0;
+}
+
+/* Check an access to a register.  */
+
+static unsigned
+check_cp14_access (ARMul_State * state,
+                  unsigned      reg,
+                  unsigned      CRm,
+                  unsigned      opcode1,
+                  unsigned      opcode2)
+{
+  /* Not allowed to access these register in USER mode.  */
+  if (state->Mode == USER26MODE || state->Mode == USER32MODE)
+    return ARMul_CANT;
+
+  /* CRm should be zero.  */
+  if (CRm != 0)
+    return ARMul_CANT;
+
+  /* OPcodes should be zero.  */
+  if (opcode1 != 0 || opcode2 != 0)
+    return ARMul_CANT;
+  
+  /* Accessing registers 4 or 5 has unpredicatable results.  */
+  if (reg >= 4 && reg <= 5)
+    return ARMul_CANT;
+
+  return ARMul_DONE;
+}
+
+/* Store a value into one of coprocessor 14's registers.  */
+
+void
+write_cp14_reg (unsigned reg, ARMword value)
+{
+  switch (reg)
+    {
+    case 0: /* PMNC */
+      /* Only BITS (27:12), BITS (10:8) and BITS (6:0) can be written.  */
+      value &= 0x0ffff77f;
+      break;
+
+    case 4:
+    case 5:
+      /* We should not normally reach this code.  The debugger interface
+        can bypass the normal checks though, so it could happen.  */
+      value = 0;
+      break;
+      
+    case 6: /* CCLKCFG */
+      /* Only BITS (3:0) can be written.  */
+      value &= 0xf;
+      break;
+
+    case 7: /* PWRMODE */
+      /* Although BITS (1:0) can be written with non-zero values, this would
+        have the side effect of putting the processor to sleep.  Thus in
+        order for the register to be read again, it would have to go into
+        ACTIVE mode, which means that any read will see these bits as zero.
+        
+        Rather than trying to implement complex reset-to-zero-upon-read logic
+        we just override the write value with zero.  */
+      value = 0;
+      break;
+
+    case 10: /* DCSR */
+      /* Only BITS (31:30), BITS (23:22), BITS (20:16) and BITS (5:0) can
+        be written.  */
+      value &= 0xc0df003f;
+      break;
+
+    case 11: /* TBREG */
+      /* No writes are permitted.  */
+      value = 0;
+      break;
+      
+    case 14: /* TXRXCTRL */
+      /* Only BITS (31:30) can be written.  */
+      value &= 0xc0000000;
+      break;
+      
+    default:
+      /* All bits can be written.  */
+      break;
+    }
+
+  XScale_cp14_Regs [reg] = value;
+}
+
+/* Return the value in a cp14 register.  Not a static function since
+   it is used by the code to emulate the BKPT instruction in armemu.c.  */
+
+ARMword
+read_cp14_reg (unsigned reg)
+{
+  return XScale_cp14_Regs [reg];
+}
+
+static unsigned
+XScale_cp14_LDC (ARMul_State * state, unsigned type, ARMword instr, ARMword data)
+{
+  unsigned reg = BITS (12, 15);
+  unsigned result;
+  
+  result = check_cp14_access (state, reg, 0, 0, 0);
+  
+  if (result == ARMul_DONE && type == ARMul_DATA)
+    write_cp14_reg (reg, data);
+
+  return result;
+}
+
+static unsigned
+XScale_cp14_STC (ARMul_State * state, unsigned type, ARMword instr, ARMword * data)
+{
+  unsigned reg = BITS (12, 15);
+  unsigned result;
+  
+  result = check_cp14_access (state, reg, 0, 0, 0);
+  
+  if (result == ARMul_DONE && type == ARMul_DATA)
+    * data = read_cp14_reg (reg);
+  
+  return result;
+}
+
+static unsigned
+XScale_cp14_MRC
+(
+ ARMul_State * state,
+ unsigned      type ATTRIBUTE_UNUSED,
+ ARMword       instr,
+ ARMword *     value
+)
+{
+  unsigned reg = BITS (16, 19);
+  unsigned result;
+  
+  result = check_cp14_access (state, reg, BITS (0, 3), BITS (21, 23), BITS (5, 7));
+  
+  if (result == ARMul_DONE)
+    * value = read_cp14_reg (reg);
+  
+  return result;
+}
+
+static unsigned
+XScale_cp14_MCR
+(
+ ARMul_State * state,
+ unsigned      type ATTRIBUTE_UNUSED,
+ ARMword       instr,
+ ARMword       value
+)
+{
+  unsigned reg = BITS (16, 19);
+  unsigned result;
+  
+  result = check_cp14_access (state, reg, BITS (0, 3), BITS (21, 23), BITS (5, 7));
+  
+  if (result == ARMul_DONE)
+    write_cp14_reg (reg, value);
+  
+  return result;
+}
+
+static unsigned
+XScale_cp14_read_reg
+(
+ ARMul_State * state ATTRIBUTE_UNUSED,
+ unsigned      reg,
+ ARMword *     value
+)
+{
+  * value = read_cp14_reg (reg);
+  
+  return TRUE;
+}
+
+static unsigned
+XScale_cp14_write_reg
+(
+ ARMul_State * state ATTRIBUTE_UNUSED,
+ unsigned      reg,
+ ARMword       value
+)
+{
+  write_cp14_reg (reg, value);
+  
+  return TRUE;
+}
 
 /* Here's ARMulator's MMU definition.  A few things to note:
-1) it has eight registers, but only two are defined.
-2) you can only access its registers with MCR and MRC.
-3) MMU Register 0 (ID) returns 0x41440110
-4) Register 1 only has 4 bits defined.  Bits 0 to 3 are unused, bit 4
-controls 32/26 bit program space, bit 5 controls 32/26 bit data space,
-bit 6 controls late abort timimg and bit 7 controls big/little endian.
-*/
+   1) It has eight registers, but only two are defined.
+   2) You can only access its registers with MCR and MRC.
+   3) MMU Register 0 (ID) returns 0x41440110
+   4) Register 1 only has 4 bits defined.  Bits 0 to 3 are unused, bit 4
+      controls 32/26 bit program space, bit 5 controls 32/26 bit data space,
+      bit 6 controls late abort timimg and bit 7 controls big/little endian.  */
 
 static ARMword MMUReg[8];
 
@@ -58,12 +901,17 @@ MMUInit (ARMul_State * state)
 {
   MMUReg[1] = state->prog32Sig << 4 |
     state->data32Sig << 5 | state->lateabtSig << 6 | state->bigendSig << 7;
+
   ARMul_ConsolePrint (state, ", MMU present");
-  return (TRUE);
+
+  return TRUE;
 }
 
 static unsigned
-MMUMRC (ARMul_State * state ATTRIBUTE_UNUSED, unsigned type ATTRIBUTE_UNUSED, ARMword instr, ARMword * value)
+MMUMRC (ARMul_State * state ATTRIBUTE_UNUSED,
+       unsigned      type ATTRIBUTE_UNUSED,
+       ARMword       instr,
+       ARMword *     value)
 {
   int reg = BITS (16, 19) & 7;
 
@@ -71,16 +919,20 @@ MMUMRC (ARMul_State * state ATTRIBUTE_UNUSED, unsigned type ATTRIBUTE_UNUSED, AR
     *value = 0x41440110;
   else
     *value = MMUReg[reg];
-  return (ARMul_DONE);
+
+  return ARMul_DONE;
 }
 
 static unsigned
-MMUMCR (ARMul_State * state, unsigned type ATTRIBUTE_UNUSED, ARMword instr, ARMword value)
+MMUMCR (ARMul_State * state,
+       unsigned      type ATTRIBUTE_UNUSED,
+       ARMword       instr,
+       ARMword       value)
 {
   int reg = BITS (16, 19) & 7;
 
   MMUReg[reg] = value;
-  
+
   if (reg == 1)
     {
       ARMword p,d,l,b;
@@ -90,22 +942,22 @@ MMUMCR (ARMul_State * state, unsigned type ATTRIBUTE_UNUSED, ARMword instr, ARMw
       l = state->lateabtSig;
       b = state->bigendSig;
       
-      state->prog32Sig = value >> 4 & 1;
-      state->data32Sig = value >> 5 & 1;
+      state->prog32Sig  = value >> 4 & 1;
+      state->data32Sig  = value >> 5 & 1;
       state->lateabtSig = value >> 6 & 1;
-      state->bigendSig = value >> 7 & 1;
+      state->bigendSig  = value >> 7 & 1;
 
-      if (p != state->prog32Sig
+      if (   p != state->prog32Sig
          || d != state->data32Sig
          || l != state->lateabtSig
          || b != state->bigendSig)
-       state->Emulate = CHANGEMODE;    /* Force ARMulator to notice these now.  */
+       /* Force ARMulator to notice these now.  */
+       state->Emulate = CHANGEMODE;
     }
-  
+
   return ARMul_DONE;
 }
 
-
 static unsigned
 MMURead (ARMul_State * state ATTRIBUTE_UNUSED, unsigned reg, ARMword * value)
 {
@@ -113,7 +965,8 @@ MMURead (ARMul_State * state ATTRIBUTE_UNUSED, unsigned reg, ARMword * value)
     *value = 0x41440110;
   else if (reg < 8)
     *value = MMUReg[reg];
-  return (TRUE);
+
+  return TRUE;
 }
 
 static unsigned
@@ -121,7 +974,7 @@ MMUWrite (ARMul_State * state, unsigned reg, ARMword value)
 {
   if (reg < 8)
     MMUReg[reg] = value;
-  
+
   if (reg == 1)
     {
       ARMword p,d,l,b;
@@ -131,126 +984,132 @@ MMUWrite (ARMul_State * state, unsigned reg, ARMword value)
       l = state->lateabtSig;
       b = state->bigendSig;
       
-      state->prog32Sig = value >> 4 & 1;
-      state->data32Sig = value >> 5 & 1;
+      state->prog32Sig  = value >> 4 & 1;
+      state->data32Sig  = value >> 5 & 1;
       state->lateabtSig = value >> 6 & 1;
-      state->bigendSig = value >> 7 & 1;
-
+      state->bigendSig  = value >> 7 & 1;
       
-      if (p != state->prog32Sig
+      if (   p != state->prog32Sig
          || d != state->data32Sig
          || l != state->lateabtSig
          || b != state->bigendSig)
-       state->Emulate = CHANGEMODE;    /* Force ARMulator to notice these now.  */
+       /* Force ARMulator to notice these now.  */     
+       state->Emulate = CHANGEMODE;
     }
-  
+
   return TRUE;
 }
 
 
 /* What follows is the Validation Suite Coprocessor.  It uses two
-co-processor numbers (4 and 5) and has the follwing functionality.
-Sixteen registers.  Both co-processor nuimbers can be used in an MCR and
-MRC to access these registers.  CP 4 can LDC and STC to and from the
-registers.  CP 4 and CP 5 CDP 0 will busy wait for the number of cycles
-specified by a CP register.  CP 5 CDP 1 issues a FIQ after a number of
-cycles (specified in a CP register), CDP 2 issues an IRQW in the same
-way, CDP 3 and 4 turn of the FIQ and IRQ source, and CDP 5 stores a 32
-bit time value in a CP register (actually it's the total number of N, S,
-I, C and F cyles) */
+   co-processor numbers (4 and 5) and has the follwing functionality.
+   Sixteen registers.  Both co-processor nuimbers can be used in an MCR
+   and MRC to access these registers.  CP 4 can LDC and STC to and from
+   the registers.  CP 4 and CP 5 CDP 0 will busy wait for the number of
+   cycles specified by a CP register.  CP 5 CDP 1 issues a FIQ after a
+   number of cycles (specified in a CP register), CDP 2 issues an IRQW
+   in the same way, CDP 3 and 4 turn of the FIQ and IRQ source, and CDP 5
+   stores a 32 bit time value in a CP register (actually it's the total
+   number of N, S, I, C and F cyles).  */
 
 static ARMword ValReg[16];
 
 static unsigned
-ValLDC (ARMul_State * state ATTRIBUTE_UNUSED, unsigned type, ARMword instr, ARMword data)
+ValLDC (ARMul_State * state ATTRIBUTE_UNUSED,
+       unsigned      type,
+       ARMword       instr,
+       ARMword        data)
 {
   static unsigned words;
 
   if (type != ARMul_DATA)
-    {
-      words = 0;
-      return (ARMul_DONE);
-    }
-  if (BIT (22))
-    {                          /* it's a long access, get two words */
-      ValReg[BITS (12, 15)] = data;
-      if (words++ == 4)
-       return (ARMul_DONE);
-      else
-       return (ARMul_INC);
-    }
+    words = 0;
   else
-    {                          /* get just one word */
+    {
       ValReg[BITS (12, 15)] = data;
-      return (ARMul_DONE);
+
+      if (BIT (22))
+       /* It's a long access, get two words.  */
+       if (words++ != 4)
+         return ARMul_INC;
     }
+  
+  return ARMul_DONE;
 }
 
 static unsigned
-ValSTC (ARMul_State * state ATTRIBUTE_UNUSED, unsigned type, ARMword instr, ARMword * data)
+ValSTC (ARMul_State * state ATTRIBUTE_UNUSED,
+       unsigned      type,
+       ARMword       instr,
+       ARMword *     data)
 {
   static unsigned words;
 
   if (type != ARMul_DATA)
-    {
-      words = 0;
-      return (ARMul_DONE);
-    }
-  if (BIT (22))
-    {                          /* it's a long access, get two words */
-      *data = ValReg[BITS (12, 15)];
-      if (words++ == 4)
-       return (ARMul_DONE);
-      else
-       return (ARMul_INC);
-    }
+    words = 0;
   else
-    {                          /* get just one word */
-      *data = ValReg[BITS (12, 15)];
-      return (ARMul_DONE);
+    {
+      * data = ValReg[BITS (12, 15)];
+
+      if (BIT (22))
+       /* It's a long access, get two words.  */
+       if (words++ != 4)
+         return ARMul_INC;
     }
+
+  return ARMul_DONE;
 }
 
 static unsigned
-ValMRC (ARMul_State * state ATTRIBUTE_UNUSED, unsigned type ATTRIBUTE_UNUSED, ARMword instr, ARMword * value)
+ValMRC (ARMul_State * state ATTRIBUTE_UNUSED,
+       unsigned      type  ATTRIBUTE_UNUSED,
+       ARMword       instr,
+       ARMword *     value)
 {
   *value = ValReg[BITS (16, 19)];
-  return (ARMul_DONE);
+
+  return ARMul_DONE;
 }
 
 static unsigned
-ValMCR (ARMul_State * state ATTRIBUTE_UNUSED, unsigned type ATTRIBUTE_UNUSED, ARMword instr, ARMword value)
+ValMCR (ARMul_State * state ATTRIBUTE_UNUSED,
+       unsigned      type  ATTRIBUTE_UNUSED,
+       ARMword       instr,
+       ARMword       value)
 {
   ValReg[BITS (16, 19)] = value;
-  return (ARMul_DONE);
+
+  return ARMul_DONE;
 }
 
 static unsigned
 ValCDP (ARMul_State * state, unsigned type, ARMword instr)
 {
   static unsigned long finish = 0;
-  ARMword howlong;
 
-  howlong = ValReg[BITS (0, 3)];
-  if (BITS (20, 23) == 0)
+  if (BITS (20, 23) != 0)
+    return ARMul_CANT;
+
+  if (type == ARMul_FIRST)
     {
-      if (type == ARMul_FIRST)
-       {                       /* First cycle of a busy wait */
-         finish = ARMul_Time (state) + howlong;
-         if (howlong == 0)
-           return (ARMul_DONE);
-         else
-           return (ARMul_BUSY);
-       }
-      else if (type == ARMul_BUSY)
-       {
-         if (ARMul_Time (state) >= finish)
-           return (ARMul_DONE);
-         else
-           return (ARMul_BUSY);
-       }
+      ARMword howlong;
+      
+      howlong = ValReg[BITS (0, 3)];
+      
+      /* First cycle of a busy wait.  */
+      finish = ARMul_Time (state) + howlong;
+      
+      return howlong == 0 ? ARMul_DONE : ARMul_BUSY;
+    }
+  else if (type == ARMul_BUSY)
+    {
+      if (ARMul_Time (state) >= finish)
+       return ARMul_DONE;
+      else
+       return ARMul_BUSY;
     }
-  return (ARMul_CANT);
+  
+  return ARMul_CANT;
 }
 
 static unsigned
@@ -258,7 +1117,7 @@ DoAFIQ (ARMul_State * state)
 {
   state->NfiqSig = LOW;
   state->Exception++;
-  return (0);
+  return 0;
 }
 
 static unsigned
@@ -266,7 +1125,7 @@ DoAIRQ (ARMul_State * state)
 {
   state->NirqSig = LOW;
   state->Exception++;
-  return (0);
+  return 0;
 }
 
 static unsigned
@@ -276,50 +1135,56 @@ IntCDP (ARMul_State * state, unsigned type, ARMword instr)
   ARMword howlong;
 
   howlong = ValReg[BITS (0, 3)];
+
   switch ((int) BITS (20, 23))
     {
     case 0:
       if (type == ARMul_FIRST)
-       {                       /* First cycle of a busy wait */
+       {
+         /* First cycle of a busy wait.  */
          finish = ARMul_Time (state) + howlong;
-         if (howlong == 0)
-           return (ARMul_DONE);
-         else
-           return (ARMul_BUSY);
+
+         return howlong == 0 ? ARMul_DONE : ARMul_BUSY;
        }
       else if (type == ARMul_BUSY)
        {
          if (ARMul_Time (state) >= finish)
-           return (ARMul_DONE);
+           return ARMul_DONE;
          else
-           return (ARMul_BUSY);
+           return ARMul_BUSY;
        }
-      return (ARMul_DONE);
+      return ARMul_DONE;
+      
     case 1:
       if (howlong == 0)
        ARMul_Abort (state, ARMul_FIQV);
       else
        ARMul_ScheduleEvent (state, howlong, DoAFIQ);
-      return (ARMul_DONE);
+      return ARMul_DONE;
+      
     case 2:
       if (howlong == 0)
        ARMul_Abort (state, ARMul_IRQV);
       else
        ARMul_ScheduleEvent (state, howlong, DoAIRQ);
-      return (ARMul_DONE);
+      return ARMul_DONE;
+      
     case 3:
       state->NfiqSig = HIGH;
       state->Exception--;
-      return (ARMul_DONE);
+      return ARMul_DONE;
+      
     case 4:
       state->NirqSig = HIGH;
       state->Exception--;
-      return (ARMul_DONE);
+      return ARMul_DONE;
+      
     case 5:
       ValReg[BITS (0, 3)] = ARMul_Time (state);
-      return (ARMul_DONE);
+      return ARMul_DONE;
     }
-  return (ARMul_CANT);
+  
+  return ARMul_CANT;
 }
 
 /***************************************************************************\
@@ -329,18 +1194,20 @@ IntCDP (ARMul_State * state, unsigned type, ARMword instr)
 unsigned
 ARMul_CoProInit (ARMul_State * state)
 {
-  register unsigned i;
+  unsigned int i;
 
-  for (i = 0; i < 16; i++)     /* initialise tham all first */
+  /* Initialise tham all first.  */
+  for (i = 0; i < 16; i++)
     ARMul_CoProDetach (state, i);
 
-  /* Install CoPro Instruction handlers here
-     The format is
-     ARMul_CoProAttach(state, CP Number, Init routine, Exit routine
-     LDC routine, STC routine, MRC routine, MCR routine,
-     CDP routine, Read Reg routine, Write Reg routine) ;
-   */
-
+  /* Install CoPro Instruction handlers here.
+     The format is:
+     ARMul_CoProAttach (state, CP Number,
+                        Init routine, Exit routine
+                        LDC routine, STC routine,
+                       MRC routine, MCR routine,
+                        CDP routine,
+                       Read Reg routine, Write Reg routine).  */
   ARMul_CoProAttach (state, 4, NULL, NULL,
                     ValLDC, ValSTC, ValMRC, ValMCR, ValCDP, NULL, NULL);
 
@@ -350,13 +1217,28 @@ ARMul_CoProInit (ARMul_State * state)
   ARMul_CoProAttach (state, 15, MMUInit, NULL,
                     NULL, NULL, MMUMRC, MMUMCR, NULL, MMURead, MMUWrite);
 
+  ARMul_CoProAttach (state, 13, XScale_cp13_init, NULL,
+                    XScale_cp13_LDC, XScale_cp13_STC, XScale_cp13_MRC,
+                    XScale_cp13_MCR, NULL, XScale_cp13_read_reg,
+                    XScale_cp13_write_reg);
+  
+  ARMul_CoProAttach (state, 14, XScale_cp14_init, NULL,
+                    XScale_cp14_LDC, XScale_cp14_STC, XScale_cp14_MRC,
+                    XScale_cp14_MCR, NULL, XScale_cp14_read_reg,
+                    XScale_cp14_write_reg);
+  
+  ARMul_CoProAttach (state, 15, XScale_cp15_init, NULL,
+                    NULL, NULL, XScale_cp15_MRC, XScale_cp15_MCR,
+                    NULL, XScale_cp15_read_reg, XScale_cp15_write_reg);
 
-  /* No handlers below here */
+  /* No handlers below here */
 
-  for (i = 0; i < 16; i++)     /* Call all the initialisation routines */
+  /* Call all the initialisation routines.  */
+  for (i = 0; i < 16; i++)
     if (state->CPInit[i])
       (state->CPInit[i]) (state);
-  return (TRUE);
+
+  return TRUE;
 }
 
 /***************************************************************************\
@@ -371,7 +1253,8 @@ ARMul_CoProExit (ARMul_State * state)
   for (i = 0; i < 16; i++)
     if (state->CPExit[i])
       (state->CPExit[i]) (state);
-  for (i = 0; i < 16; i++)     /* Detach all handlers */
+
+  for (i = 0; i < 16; i++)     /* Detach all handlers.  */
     ARMul_CoProDetach (state, i);
 }
 
@@ -380,11 +1263,17 @@ ARMul_CoProExit (ARMul_State * state)
 \***************************************************************************/
 
 void
-ARMul_CoProAttach (ARMul_State * state, unsigned number,
-                  ARMul_CPInits * init, ARMul_CPExits * exit,
-                  ARMul_LDCs * ldc, ARMul_STCs * stc,
-                  ARMul_MRCs * mrc, ARMul_MCRs * mcr, ARMul_CDPs * cdp,
-                  ARMul_CPReads * read, ARMul_CPWrites * write)
+ARMul_CoProAttach (ARMul_State *    state,
+                  unsigned         number,
+                  ARMul_CPInits *  init,
+                  ARMul_CPExits *  exit,
+                  ARMul_LDCs *     ldc,
+                  ARMul_STCs *     stc,
+                  ARMul_MRCs *     mrc,
+                  ARMul_MCRs *     mcr,
+                  ARMul_CDPs *     cdp,
+                  ARMul_CPReads *  read,
+                  ARMul_CPWrites * write)
 {
   if (init != NULL)
     state->CPInit[number] = init;
@@ -412,40 +1301,9 @@ ARMul_CoProDetach (ARMul_State * state, unsigned number)
   ARMul_CoProAttach (state, number, NULL, NULL,
                     NoCoPro4R, NoCoPro4W, NoCoPro4W, NoCoPro4R,
                     NoCoPro3R, NULL, NULL);
+
   state->CPInit[number] = NULL;
   state->CPExit[number] = NULL;
   state->CPRead[number] = NULL;
   state->CPWrite[number] = NULL;
 }
-
-/***************************************************************************\
-*         There is no CoPro around, so Undefined Instruction trap           *
-\***************************************************************************/
-
-static unsigned
-NoCoPro3R (ARMul_State * state ATTRIBUTE_UNUSED,
-          unsigned a ATTRIBUTE_UNUSED,
-          ARMword b ATTRIBUTE_UNUSED)
-{
-  return (ARMul_CANT);
-}
-
-static unsigned
-NoCoPro4R (
-          ARMul_State * state ATTRIBUTE_UNUSED,
-          unsigned a ATTRIBUTE_UNUSED,
-          ARMword b ATTRIBUTE_UNUSED,
-          ARMword c ATTRIBUTE_UNUSED)
-{
-  return (ARMul_CANT);
-}
-
-static unsigned
-NoCoPro4W (
-          ARMul_State * state ATTRIBUTE_UNUSED,
-          unsigned a ATTRIBUTE_UNUSED,
-          ARMword b ATTRIBUTE_UNUSED,
-          ARMword * c ATTRIBUTE_UNUSED)
-{
-  return (ARMul_CANT);
-}
index 61ab9c5816d060f2443f6ddfcdd1977b7a3b4b60..204dc6bee3dc0e458ab86121018d7b7dfe343e61 100644 (file)
@@ -30,6 +30,7 @@ typedef char *VoidStar;
 #endif
 
 typedef unsigned long ARMword; /* must be 32 bits wide */
+typedef unsigned long long ARMdword;   /* Must be at least 64 bits wide.  */
 typedef struct ARMul_State ARMul_State;
 
 typedef unsigned ARMul_CPInits (ARMul_State * state);
@@ -56,9 +57,13 @@ struct ARMul_State
   unsigned ErrorCode;          /* type of illegal instruction */
   ARMword Reg[16];             /* the current register file */
   ARMword RegBank[7][16];      /* all the registers */
+  /* 40 bit accumulator.  We always keep this 64 bits wide,
+     and move only 40 bits out of it in an MRA insn.  */
+  ARMdword Accumulator;
   ARMword Cpsr;                        /* the current psr */
   ARMword Spsr[7];             /* the exception psr's */
   ARMword NFlag, ZFlag, CFlag, VFlag, IFFlags; /* dummy flags for speed */
+  ARMword SFlag;
 #ifdef MODET
   ARMword TFlag;               /* Thumb state */
 #endif
@@ -125,6 +130,8 @@ struct ARMul_State
 
   unsigned is_v4;              /* Are we emulating a v4 architecture (or higher) ?  */
   unsigned is_v5;              /* Are we emulating a v5 architecture ?  */
+  unsigned is_v5e;             /* Are we emulating a v5e architecture ?  */
+  unsigned is_XScale;          /* Are we emulating an XScale architecture ?  */
   unsigned verbose;            /* Print various messages like the banner */
 };
 
@@ -150,6 +157,8 @@ struct ARMul_State
 #define ARM_Lock_Prop    0x20
 #define ARM_v4_Prop      0x40
 #define ARM_v5_Prop      0x80
+#define ARM_v5e_Prop     0x100
+#define ARM_XScale_Prop  0x200
 
 /***************************************************************************\
 *                   Macros to extract instruction fields                    *
index 9d3dcba60d435113413cec0dd5350fb75f963795..6413728b771206442498dbd2d81996e48298abaa 100644 (file)
@@ -459,6 +459,30 @@ ARMul_Emulate26 (register ARMul_State * state)
          temp = TRUE;
          break;
        case NV:
+         if (state->is_v5)
+           {
+             if (BITS (25, 27) == 5) /* BLX(1) */
+               {
+                 ARMword dest;
+                 
+                 state->Reg[14] = pc + 4;
+                 
+                 dest = pc + 8 + 1; /* Force entry into Thumb mode.  */
+                 if (BIT (23))
+                   dest += (NEGBRANCH + (BIT (24) << 1));
+                 else
+                   dest += POSBRANCH + (BIT (24) << 1);
+                 
+                 WriteR15Branch (state, dest);
+                 goto donext;
+               }
+             else if ((instr & 0xFC70F000) == 0xF450F000)
+               /* The PLD instruction.  Ignored.  */
+               goto donext;
+             else
+               /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2.  */
+               ARMul_UndefInstr (state, instr);
+           }
          temp = FALSE;
          break;
        case EQ:
@@ -513,6 +537,63 @@ ARMul_Emulate26 (register ARMul_State * state)
        {                       /* if the condition codes don't match, stop here */
        mainswitch:
 
+         if (state->is_XScale)
+           {
+             if (BIT (20) == 0 && BITS (25, 27) == 0)
+               {
+                 if (BITS (4, 7) == 0xD)
+                   {
+                     /* XScale Load Consecutive insn.  */
+                     ARMword temp = GetLS7RHS (state, instr);
+                     ARMword temp2 = BIT (23) ? LHS + temp : LHS - temp;
+                     ARMword addr = BIT (24) ? temp2 : temp;
+                     
+                     if (BIT (12))
+                       ARMul_UndefInstr (state, instr);
+                     else if (addr & 7)
+                       /* Alignment violation.  */
+                       ARMul_Abort (state, ARMul_DataAbortV);
+                     else
+                       {
+                         int wb = BIT (24) && BIT (21);
+                         
+                         state->Reg[BITS (12, 15)] =
+                           ARMul_LoadWordN (state, addr);
+                         state->Reg[BITS (12, 15) + 1] =
+                           ARMul_LoadWordN (state, addr + 4);
+                         if (wb)
+                           LSBase = addr;
+                       }
+
+                     goto donext;
+                   }
+                 else if (BITS (4, 7) == 0xF)
+                   {
+                     /* XScale Store Consecutive insn.  */
+                     ARMword temp = GetLS7RHS (state, instr);
+                     ARMword temp2 = BIT (23) ? LHS + temp : LHS - temp;
+                     ARMword addr = BIT (24) ? temp2 : temp;
+
+                     if (BIT (12))
+                       ARMul_UndefInstr (state, instr);
+                     else if (addr & 7)
+                       /* Alignment violation.  */
+                       ARMul_Abort (state, ARMul_DataAbortV);
+                     else
+                       {
+                         ARMul_StoreWordN (state, addr,
+                                           state->Reg[BITS (12, 15)]);
+                         ARMul_StoreWordN (state, addr + 4,
+                                           state->Reg[BITS (12, 15) + 1]);
+
+                         if (BIT (21))
+                           LSBase = addr;
+                       }
+
+                     goto donext;
+                   }
+               }
+           }
 
          switch ((int) BITS (20, 27))
            {
@@ -1000,6 +1081,48 @@ ARMul_Emulate26 (register ARMul_State * state)
              break;
 
            case 0x10:          /* TST reg and MRS CPSR and SWP word */
+             if (state->is_v5e)
+               {
+                 if (BIT (4) == 0 && BIT (7) == 1)
+                   {
+                     /* ElSegundo SMLAxy insn.  */
+                     ARMword op1 = state->Reg[BITS (0, 3)];
+                     ARMword op2 = state->Reg[BITS (8, 11)];
+                     ARMword Rn = state->Reg[BITS (12, 15)];
+                     
+                     if (BIT (5))
+                       op1 >>= 16;
+                     if (BIT (6))
+                       op2 >>= 16;
+                     op1 &= 0xFFFF;
+                     op2 &= 0xFFFF;
+                     if (op1 & 0x8000)
+                       op1 -= 65536;
+                     if (op2 & 0x8000)
+                       op2 -= 65536;
+                     op1 *= op2;
+                     
+                     if (AddOverflow (op1, Rn, op1 + Rn))
+                       SETS;
+                     state->Reg[BITS (16, 19)] = op1 + Rn;
+                     break;
+                   }
+
+                 if (BITS (4, 11) == 5)
+                   {
+                     /* ElSegundo QADD insn.  */
+                     ARMword op1 = state->Reg[BITS (0, 3)];
+                     ARMword op2 = state->Reg[BITS (16, 19)];
+                     ARMword result = op1 + op2;
+                     if (AddOverflow (op1, op2, result))
+                       {
+                         result = POS (result) ? 0x80000000 : 0x7fffffff;
+                         SETS;
+                       }
+                     state->Reg[BITS (12, 15)] = result;
+                     break;
+                   }
+               }
 #ifdef MODET
              if (BITS (4, 11) == 0xB)
                {
@@ -1072,6 +1195,72 @@ ARMul_Emulate26 (register ARMul_State * state)
              break;
 
            case 0x12:          /* TEQ reg and MSR reg to CPSR (ARM6) */
+             if (state->is_v5)
+               {
+                 if (BITS (4, 7) == 3)
+                   {
+                     /* BLX(2) */
+                     ARMword temp;
+
+                     if (TFLAG)
+                       temp = (pc + 2) | 1;
+                     else
+                       temp = pc + 4;
+
+                     WriteR15Branch (state, state->Reg[RHSReg]);
+                     state->Reg[14] = temp;
+                     break;
+                   }
+               }
+
+             if (state->is_v5e)
+               {
+                 if (BIT (4) == 0 && BIT (7) == 1
+                     && (BIT (5) == 0 || BITS (12, 15) == 0))
+                   {
+                     /* ElSegundo SMLAWy/SMULWy insn.  */
+                     unsigned long long op1 = state->Reg[BITS (0, 3)];
+                     unsigned long long op2 = state->Reg[BITS (8, 11)];
+                     unsigned long long result;
+
+                     if (BIT (6))
+                       op2 >>= 16;
+                     if (op1 & 0x80000000)
+                       op1 -= 1ULL << 32;
+                     op2 &= 0xFFFF;
+                     if (op2 & 0x8000)
+                       op2 -= 65536;
+                     result = (op1 * op2) >> 16;
+
+                     if (BIT (5) == 0)
+                       {
+                         ARMword Rn = state->Reg[BITS (12, 15)];
+                         
+                         if (AddOverflow (result, Rn, result + Rn))
+                           SETS;
+                         result += Rn;
+                       }
+                     state->Reg[BITS (16, 19)] = result;
+                     break;
+                   }
+
+                 if (BITS (4, 11) == 5)
+                   {
+                     /* ElSegundo QSUB insn.  */
+                     ARMword op1 = state->Reg[BITS (0, 3)];
+                     ARMword op2 = state->Reg[BITS (16, 19)];
+                     ARMword result = op1 - op2;
+
+                     if (SubOverflow (op1, op2, result))
+                       {
+                         result = POS (result) ? 0x80000000 : 0x7fffffff;
+                         SETS;
+                       }
+
+                     state->Reg[BITS (12, 15)] = result;
+                     break;
+                   }
+               }
 #ifdef MODET
              if (BITS (4, 11) == 0xB)
                {
@@ -1079,18 +1268,68 @@ ARMul_Emulate26 (register ARMul_State * state)
                  SHPREDOWNWB ();
                  break;
                }
-#endif
-#ifdef MODET
              if (BITS (4, 27) == 0x12FFF1)
-               {               /* BX */
+               {
+                 /* BX */
                  WriteR15Branch (state, state->Reg[RHSReg]);
                  break;
                }
 #endif
+             if (state->is_v5)
+               {
+                 if (BITS (4, 7) == 0x7)
+                   {
+                     ARMword value;
+                     extern int SWI_vector_installed;
+
+                     /* Hardware is allowed to optionally override this
+                        instruction and treat it as a breakpoint.  Since
+                        this is a simulator not hardware, we take the position
+                        that if a SWI vector was not installed, then an Abort
+                        vector was probably not installed either, and so
+                        normally this instruction would be ignored, even if an
+                        Abort is generated.  This is a bad thing, since GDB
+                        uses this instruction for its breakpoints (at least in
+                        Thumb mode it does).  So intercept the instruction here
+                        and generate a breakpoint SWI instead.  */
+                     if (! SWI_vector_installed)
+                       ARMul_OSHandleSWI (state, SWI_Breakpoint);
+                     else
+                   
+                       /* BKPT - normally this will cause an abort, but for the
+                          XScale if bit 31 in register 10 of coprocessor 14 is
+                          clear, then this is treated as a no-op.  */
+                       if (state->is_XScale)
+                         {
+                           if (read_cp14_reg (10) & (1UL << 31))
+                             {
+                               ARMword value;
+                               
+                               value = read_cp14_reg (10);
+                               value &= ~0x1c;
+                               value |= 0xc;
+                               
+                               write_cp14_reg (10, value);
+                               write_cp15_reg (5, 0, 0, 0x200);  /* Set FSR.  */
+                               write_cp15_reg (6, 0, 0, pc);     /* Set FAR.  */
+                             }
+                           else
+                             break;
+                         }
+
+                     ARMul_Abort (state, ARMul_PrefetchAbortV);
+                     break;
+                   }
+               }
              if (DESTReg == 15)
-               {               /* MSR reg to CPSR */
+               {
+                 /* MSR reg to CPSR */
                  UNDEF_MSRPC;
                  temp = DPRegRHS;
+#ifdef MODET
+                 /* Don't allow TBIT to be set by MSR.  */
+                 temp &= ~ TBIT;
+#endif
                  ARMul_FixCPSR (state, instr, temp);
                }
              else
@@ -1128,6 +1367,60 @@ ARMul_Emulate26 (register ARMul_State * state)
              break;
 
            case 0x14:          /* CMP reg and MRS SPSR and SWP byte */
+             if (state->is_v5e)
+               {
+                 if (BIT (4) == 0 && BIT (7) == 1)
+                   {
+                     /* ElSegundo SMLALxy insn.  */
+                     unsigned long long op1 = state->Reg[BITS (0, 3)];
+                     unsigned long long op2 = state->Reg[BITS (8, 11)];
+                     unsigned long long dest;
+                     unsigned long long result;
+
+                     if (BIT (5))
+                       op1 >>= 16;
+                     if (BIT (6))
+                       op2 >>= 16;
+                     op1 &= 0xFFFF;
+                     if (op1 & 0x8000)
+                       op1 -= 65536;
+                     op2 &= 0xFFFF;
+                     if (op2 & 0x8000)
+                       op2 -= 65536;
+
+                     dest = (unsigned long long) state->Reg[BITS (16, 19)] << 32;
+                     dest |= state->Reg[BITS (12, 15)];
+                     dest += op1 * op2;
+                     state->Reg[BITS (12, 15)] = dest;
+                     state->Reg[BITS (16, 19)] = dest >> 32;
+                     break;
+                   }
+
+                 if (BITS (4, 11) == 5)
+                   {
+                     /* ElSegundo QDADD insn.  */
+                     ARMword op1 = state->Reg[BITS (0, 3)];
+                     ARMword op2 = state->Reg[BITS (16, 19)];
+                     ARMword op2d = op2 + op2;
+                     ARMword result;
+
+                     if (AddOverflow (op2, op2, op2d))
+                       {
+                         SETS;
+                         op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;
+                       }
+
+                     result = op1 + op2d;
+                     if (AddOverflow (op1, op2d, result))
+                       {
+                         SETS;
+                         result = POS (result) ? 0x80000000 : 0x7fffffff;
+                       }
+
+                     state->Reg[BITS (12, 15)] = result;
+                     break;
+                   }
+               }
 #ifdef MODET
              if (BITS (4, 7) == 0xB)
                {
@@ -1207,6 +1500,72 @@ ARMul_Emulate26 (register ARMul_State * state)
              break;
 
            case 0x16:          /* CMN reg and MSR reg to SPSR */
+             if (state->is_v5e)
+               {
+                 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
+                   {
+                     /* ElSegundo SMULxy insn.  */
+                     ARMword op1 = state->Reg[BITS (0, 3)];
+                     ARMword op2 = state->Reg[BITS (8, 11)];
+                     ARMword Rn = state->Reg[BITS (12, 15)];
+
+                     if (BIT (5))
+                       op1 >>= 16;
+                     if (BIT (6))
+                       op2 >>= 16;
+                     op1 &= 0xFFFF;
+                     op2 &= 0xFFFF;
+                     if (op1 & 0x8000)
+                       op1 -= 65536;
+                     if (op2 & 0x8000)
+                       op2 -= 65536;
+
+                     state->Reg[BITS (16, 19)] = op1 * op2;
+                     break;
+                   }
+
+                 if (BITS (4, 11) == 5)
+                   {
+                     /* ElSegundo QDSUB insn.  */
+                     ARMword op1 = state->Reg[BITS (0, 3)];
+                     ARMword op2 = state->Reg[BITS (16, 19)];
+                     ARMword op2d = op2 + op2;
+                     ARMword result;
+
+                     if (AddOverflow (op2, op2, op2d))
+                       {
+                         SETS;
+                         op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;
+                       }
+
+                     result = op1 - op2d;
+                     if (SubOverflow (op1, op2d, result))
+                       {
+                         SETS;
+                         result = POS (result) ? 0x80000000 : 0x7fffffff;
+                       }
+
+                     state->Reg[BITS (12, 15)] = result;
+                     break;
+                   }
+               }
+
+             if (state->is_v5)
+               {
+                 if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF)
+                   {
+                     /* ARM5 CLZ insn.  */
+                     ARMword op1 = state->Reg[BITS (0, 3)];
+                     int result = 32;
+
+                     if (op1)
+                       for (result = 0; (op1 & 0x80000000) == 0; op1 <<= 1)
+                         result++;
+
+                     state->Reg[BITS (12, 15)] = result;
+                     break;
+                   }
+               }
 #ifdef MODET
              if (BITS (4, 7) == 0xB)
                {
@@ -2393,7 +2752,7 @@ ARMul_Emulate26 (register ARMul_State * state)
                {
                  /* Check for the special breakpoint opcode.
                     This value should correspond to the value defined
-                    as ARM_BE_BREAKPOINT in gdb/arm-tdep.c.  */
+                    as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h.  */
                  if (BITS (0, 19) == 0xfdefe)
                    {
                      if (!ARMul_OSHandleSWI (state, SWI_Breakpoint))
@@ -2642,11 +3001,56 @@ ARMul_Emulate26 (register ARMul_State * state)
 \***************************************************************************/
 
            case 0xc4:
+             if (state->is_XScale)
+               {
+                 if (BITS (4, 7) != 0x00)
+                   ARMul_UndefInstr (state, instr);
+
+                 if (BITS (8, 11) != 0x00)
+                   ARMul_UndefInstr (state, instr); /* Not CP0.  */
+
+                 /* XScale MAR insn.  Move two registers into accumulator.  */
+                 if (BITS (0, 3) == 0x00)
+                   {
+                     state->Accumulator = state->Reg[BITS (12, 15)];
+                     state->Accumulator += (ARMdword) state->Reg[BITS (16, 19)] << 32;
+                     break;
+                   }
+                 /* Access to any other acc is unpredicatable.  */
+                 break;
+               }
+             /* Drop through.  */
+             
            case 0xc0:          /* Store , No WriteBack , Post Dec */
              ARMul_STC (state, instr, LHS);
              break;
 
            case 0xc5:
+             if (state->is_XScale)
+               {
+                 if (BITS (4, 7) != 0x00)
+                   ARMul_UndefInstr (state, instr);
+
+                 if (BITS (8, 11) != 0x00)
+                   ARMul_UndefInstr (state, instr); /* Not CP0.  */
+
+                 /* XScale MRA insn.  Move accumulator into two registers.  */
+                 if (BITS (0, 3) == 0x00)
+                   {
+                     ARMword t1 = (state->Accumulator >> 32) & 255;
+
+                     if (t1 & 128)
+                       t1 -= 256;
+
+                     state->Reg[BITS (12, 15)] = state->Accumulator;
+                     state->Reg[BITS (16, 19)] = t1;
+                     break;
+                   }
+                 /* Access to any other acc is unpredicatable.  */
+                 break;
+               }
+             /* Drop through.  */
+
            case 0xc1:          /* Load , No WriteBack , Post Dec */
              ARMul_LDC (state, instr, LHS);
              break;
@@ -2743,6 +3147,88 @@ ARMul_Emulate26 (register ARMul_State * state)
 \***************************************************************************/
 
            case 0xe2:
+             if (state->is_XScale)
+               switch (BITS (18, 19))
+                 {
+                 case 0x0:
+                   {
+                     /* XScale MIA instruction.  Signed multiplication of two 32 bit
+                        values and addition to 40 bit accumulator.  */
+                     long long Rm = state->Reg[MULLHSReg];
+                     long long Rs = state->Reg[MULACCReg];
+
+                     if (Rm & (1 << 31))
+                       Rm -= 1ULL << 32;
+                     if (Rs & (1 << 31))
+                       Rs -= 1ULL << 32;
+                     state->Accumulator += Rm * Rs;
+                   }
+                   goto donext;
+
+                 case 0x2:
+                   {
+                     /* XScale MIAPH instruction.  */
+                     ARMword t1 = state->Reg[MULLHSReg] >> 16;
+                     ARMword t2 = state->Reg[MULACCReg] >> 16;
+                     ARMword t3 = state->Reg[MULLHSReg] & 0xffff;
+                     ARMword t4 = state->Reg[MULACCReg] & 0xffff;
+                     long long t5;
+
+                     if (t1 & (1 << 15))
+                       t1 -= 1 << 16;
+                     if (t2 & (1 << 15))
+                       t2 -= 1 << 16;
+                     if (t3 & (1 << 15))
+                       t3 -= 1 << 16;
+                     if (t4 & (1 << 15))
+                       t4 -= 1 << 16;
+                     t1 *= t2;
+                     t5 = t1;
+                     if (t5 & (1 << 31))
+                       t5 -= 1ULL << 32;
+                     state->Accumulator += t5;
+                     t3 *= t4;
+                     t5 = t3;
+                     if (t5 & (1 << 31))
+                       t5 -= 1ULL << 32;
+                     state->Accumulator += t5;
+                   }
+                   goto donext;
+
+                 case 0x3:
+                   {
+                     /* XScale MIAxy instruction.  */
+                     ARMword t1;
+                     ARMword t2;
+                     long long t5;
+
+                     if (BIT (17))
+                       t1 = state->Reg[MULLHSReg] >> 16;
+                     else
+                       t1 = state->Reg[MULLHSReg] & 0xffff;
+
+                     if (BIT (16))
+                       t2 = state->Reg[MULACCReg] >> 16;
+                     else
+                       t2 = state->Reg[MULACCReg] & 0xffff;
+
+                     if (t1 & (1 << 15))
+                       t1 -= 1 << 16;
+                     if (t2 & (1 << 15))
+                       t2 -= 1 << 16;
+                     t1 *= t2;
+                     t5 = t1;
+                     if (t5 & (1 << 31))
+                       t5 -= 1ULL << 32;
+                     state->Accumulator += t5;
+                   }
+                   goto donext;
+
+                 default:
+                   break;
+                 }
+             /* Drop through.  */
+
            case 0xe0:
            case 0xe4:
            case 0xe6:
index 81ecd523d176299f777056fd90c4d2ecb523e1fd..8fd5f356d33922031b86d211e7007fb5f2827809 100644 (file)
@@ -55,6 +55,7 @@ extern ARMword isize;
 #define ZBIT (1L << 30)
 #define CBIT (1L << 29)
 #define VBIT (1L << 28)
+#define SBIT (1L << 27)
 #define IBIT (1L << 7)
 #define FBIT (1L << 6)
 #define IFBITS (3L << 6)
@@ -98,6 +99,10 @@ extern ARMword isize;
 #define CLEARV state->VFlag = 0
 #define ASSIGNV(res) state->VFlag = res
 
+#define SFLAG state->SFlag
+#define SETS state->SFlag = 1
+#define CLEARS state->SFlag = 0
+#define ASSIGNS(res) state->SFlag = res
 
 #define IFLAG (state->IFFlags >> 1)
 #define FFLAG (state->IFFlags & 1)
@@ -110,7 +115,12 @@ extern ARMword isize;
 #define PSR_XBITS (0x0000ff00L)
 #define PSR_CBITS (0x000000ffL)
 
+#if defined MODE32 || defined MODET
+#define CCBITS (0xf8000000L)
+#else
 #define CCBITS (0xf0000000L)
+#endif
+
 #define INTBITS (0xc0L)
 
 #if defined MODET && defined MODE32
@@ -149,7 +159,7 @@ extern ARMword isize;
 #define R15PCMODE (state->Reg[15] & (R15PCBITS | R15MODEBITS))
 #define R15MODE (state->Reg[15] & R15MODEBITS)
 
-#define ECC ((NFLAG << 31) | (ZFLAG << 30) | (CFLAG << 29) | (VFLAG << 28))
+#define ECC ((NFLAG << 31) | (ZFLAG << 30) | (CFLAG << 29) | (VFLAG << 28) | (SFLAG << 27))
 #define EINT (IFFLAGS << 6)
 #define ER15INT (IFFLAGS << 26)
 #define EMODE (state->Mode)
@@ -472,3 +482,14 @@ extern tdstate ARMul_ThumbDecode (ARMul_State * state, ARMword pc,
 #define UNDEF_IllegalMode
 #define UNDEF_Prog32SigChange
 #define UNDEF_Data32SigChange
+
+/* Coprocessor support functions.  */
+extern unsigned ARMul_CoProInit (ARMul_State *);
+extern void     ARMul_CoProExit (ARMul_State *);
+extern void     ARMul_CoProAttach (ARMul_State *, unsigned, ARMul_CPInits *, ARMul_CPExits *,
+                                  ARMul_LDCs *, ARMul_STCs *, ARMul_MRCs *, ARMul_MCRs *,
+                                  ARMul_CDPs *, ARMul_CPReads *, ARMul_CPWrites *);
+extern void     ARMul_CoProDetach (ARMul_State *, unsigned);
+extern void     write_cp15_reg (unsigned, unsigned, unsigned, ARMword);
+extern void     write_cp14_reg (unsigned, ARMword);
+extern ARMword  read_cp14_reg  (unsigned);
index a3f0001c7ccedb20f55b4c2676d14fcfabe5d487..2f6e73df3ca35406ddb973b6174cd0bce97c5eba 100644 (file)
@@ -86,7 +86,8 @@ ARMul_NewState (void)
   for (i = 0; i < 7; i++)
     state->Spsr[i] = 0;
 
-  state->Mode = USER26MODE;
+  /* state->Mode = USER26MODE;  */
+  state->Mode = USER32MODE;
 
   state->CallDebug = FALSE;
   state->Debug = FALSE;
@@ -113,19 +114,16 @@ ARMul_NewState (void)
   for (i = 0; i < EVENTLISTSIZE; i++)
     *(state->EventPtr + i) = NULL;
 
-#ifdef ARM61
-  state->prog32Sig = LOW;
-  state->data32Sig = LOW;
-#else
   state->prog32Sig = HIGH;
   state->data32Sig = HIGH;
-#endif
 
   state->lateabtSig = LOW;
   state->bigendSig = LOW;
 
   state->is_v4 = LOW;
   state->is_v5 = LOW;
+  state->is_v5e = LOW;
+  state->is_XScale = LOW;
 
   ARMul_Reset (state);
 
@@ -154,6 +152,8 @@ ARMul_SelectProcessor (ARMul_State * state, unsigned properties)
 
   state->is_v4 = (properties & (ARM_v4_Prop | ARM_v5_Prop)) ? HIGH : LOW;
   state->is_v5 = (properties & ARM_v5_Prop) ? HIGH : LOW;
+  state->is_v5e = (properties & ARM_v5e_Prop) ? HIGH : LOW;
+  state->is_XScale = (properties & ARM_XScale_Prop) ? HIGH : LOW;
 }
 
 /***************************************************************************\
@@ -261,6 +261,8 @@ ARMul_Abort (ARMul_State * state, ARMword vector)
 {
   ARMword temp;
   int isize = INSN_SIZE;
+  int esize = (TFLAG ? 0 : 4);
+  int e2size = (TFLAG ? -4 : 0);
 
   state->Aborted = FALSE;
 
@@ -288,19 +290,19 @@ ARMul_Abort (ARMul_State * state, ARMword vector)
       break;
     case ARMul_PrefetchAbortV: /* Prefetch Abort */
       state->AbortAddr = 1;
-      SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE, isize);
+      SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE, esize);
       break;
     case ARMul_DataAbortV:     /* Data Abort */
-      SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE, isize);
+      SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE, e2size);
       break;
     case ARMul_AddrExceptnV:   /* Address Exception */
       SETABORT (IBIT, SVC26MODE, isize);
       break;
     case ARMul_IRQV:           /* IRQ */
-      SETABORT (IBIT, state->prog32Sig ? IRQ32MODE : IRQ26MODE, isize);
+      SETABORT (IBIT, state->prog32Sig ? IRQ32MODE : IRQ26MODE, esize);
       break;
     case ARMul_FIQV:           /* FIQ */
-      SETABORT (INTBITS, state->prog32Sig ? FIQ32MODE : FIQ26MODE, isize);
+      SETABORT (INTBITS, state->prog32Sig ? FIQ32MODE : FIQ26MODE, esize);
       break;
     }
   if (ARMul_MODE32BIT)
index 958d4cde6ff92e48ce6d5b7b3d23d30bdc7ff4f5..62b3ff5694bf820610a9f5358819a187cd52b432 100644 (file)
@@ -70,6 +70,8 @@ extern int _fisatty (FILE *);
 
 #include "armdefs.h"
 #include "armos.h"
+#include "armemu.h"
+
 #ifndef NOOS
 #ifndef VALIDATE
 /* #ifndef ASIM */
@@ -445,11 +447,6 @@ ARMul_OSHandleSWI (ARMul_State * state, ARMword number)
       state->Reg[0] = OSptr->ErrorNo;
       return (TRUE);
 
-    case SWI_Breakpoint:
-      state->EndCondition = RDIError_BreakpointReached;
-      state->Emulate = FALSE;
-      return (TRUE);
-
     case SWI_GetEnv:
       state->Reg[0] = ADDRCMDLINE;
       if (state->MemSize)
@@ -459,6 +456,11 @@ ARMul_OSHandleSWI (ARMul_State * state, ARMword number)
 
       WriteCommandLineTo (state, state->Reg[0]);
       return (TRUE);
+      
+    case SWI_Breakpoint:
+      state->EndCondition = RDIError_BreakpointReached;
+      state->Emulate = FALSE;
+      return (TRUE);
 
       /* Handle Angel SWIs as well as Demon ones */
     case AngelSWI_ARM:
@@ -587,29 +589,58 @@ ARMul_OSHandleSWI (ARMul_State * state, ARMword number)
          return TRUE;
        }
 
+    case 0x90:
+    case 0x92:
+      /* These are used by the FPE code.  */
+      return TRUE;
+      
     default:
-      state->Emulate = FALSE;
-      return (FALSE);
+      {
+       /* If there is a SWI vector installed use it.  */
+       extern int SWI_vector_installed;
+       
+       if (SWI_vector_installed && number != SWI_Breakpoint)
+         {
+           ARMword cpsr;
+           ARMword i_size;
+           
+           cpsr = ARMul_GetCPSR (state);
+           i_size = INSN_SIZE;
+           
+           ARMul_SetSPSR (state, SVC32MODE, cpsr);
+           
+           cpsr &= ~0xbf;
+           cpsr |= SVC32MODE | 0x80;
+           ARMul_SetCPSR (state, cpsr);
+           
+           state->RegBank[SVCBANK][14] = state->Reg[14] = state->Reg[15] - i_size;
+           state->NextInstr            = RESUME;
+           state->Reg[15]              = state->pc = ARMSWIV;
+           FLUSHPIPE;
+         }
+       else
+         fprintf (stderr, "unknown SWI encountered - %x - ignoring\n", number);
+       return TRUE;
+      }
     }
 }
 
 #ifndef NOOS
 #ifndef ASIM
 
-/***************************************************************************\
-* The emulator calls this routine when an Exception occurs.  The second     *
-* parameter is the address of the relevant exception vector.  Returning     *
-* FALSE from this routine causes the trap to be taken, TRUE causes it to    *
-* be ignored (so set state->Emulate to FALSE!).                             *
-\***************************************************************************/
+/* The emulator calls this routine when an Exception occurs.  The second
+   parameter is the address of the relevant exception vector.  Returning
+   FALSE from this routine causes the trap to be taken, TRUE causes it to
+   be ignored (so set state->Emulate to FALSE!).  */
 
 unsigned
-ARMul_OSException (ARMul_State * state ATTRIBUTE_UNUSED, ARMword vector ATTRIBUTE_UNUSED, ARMword pc ATTRIBUTE_UNUSED)
-{                              /* don't use this here */
-  return (FALSE);
+ARMul_OSException (
+                  ARMul_State * state  ATTRIBUTE_UNUSED,
+                  ARMword       vector ATTRIBUTE_UNUSED,
+                  ARMword       pc     ATTRIBUTE_UNUSED)
+{
+  return FALSE;
 }
 
 #endif
-
-
 #endif /* NOOS */
index 27ee35ba192459d0fc321058936f12930753669c..2d0390d1cbe6b99c11e8550c3f7fd9410b7ea8f7 100644 (file)
@@ -302,6 +302,8 @@ ARMul_CPSRAltered (ARMul_State * state)
   state->Cpsr &= ~CBIT;
   ASSIGNV ((state->Cpsr & VBIT) != 0);
   state->Cpsr &= ~VBIT;
+  ASSIGNS ((state->Cpsr & SBIT) != 0);
+  state->Cpsr &= ~SBIT;
 #ifdef MODET
   ASSIGNT ((state->Cpsr & TBIT) != 0);
   state->Cpsr &= ~TBIT;
index dc90dd7cf486ddf974b02634f40c651b52f2e62c..3351c2f65da08f8019a7a7750d686983757f7d6c 100644 (file)
@@ -209,11 +209,19 @@ tdstate ARMul_ThumbDecode (state, pc, tinstr, ainstr)
              *ainstr = 0xE12FFF10      /* base */
                | ((tinstr & 0x0078) >> 3);     /* Rd */
              break;
+           case 0xE:           /* UNDEFINED */
+           case 0xF:           /* UNDEFINED */
+             if (state->is_v5)
+               {
+                 /* BLX Rs; BLX Hs */
+                 *ainstr = 0xE12FFF30  /* base */
+                   | ((tinstr & 0x0078) >> 3); /* Rd */
+                 break;
+               }
+             /* Drop through.  */
            case 0x0:           /* UNDEFINED */
            case 0x4:           /* UNDEFINED */
            case 0x8:           /* UNDEFINED */
-           case 0xE:           /* UNDEFINED */
-           case 0xF:           /* UNDEFINED */
              valid = t_undefined;
              break;
            }
@@ -322,30 +330,48 @@ tdstate ARMul_ThumbDecode (state, pc, tinstr, ainstr)
       break;
     case 22:
     case 23:
-      if ((tinstr & 0x0F00) == 0x0000)
+      switch (tinstr & 0x0F00)
        {
+       case 0x0000:
          /* Format 13 */
          /* NOTE: The instruction contains a shift left of 2
-            equivalent (implemented as ROR #30): */
+            equivalent (implemented as ROR #30):  */
          *ainstr = ((tinstr & (1 << 7))        /* base */
                     ? 0xE24DDF00       /* SUB */
                     : 0xE28DDF00)      /* ADD */
            | (tinstr & 0x007F);        /* off7 */
-       }
-      else if ((tinstr & 0x0F00) == 0x0e00)
-       *ainstr = 0xEF000000 | SWI_Breakpoint;
-      else
-       {
-         /* Format 14 */
-         ARMword subset[4] = {
-           0xE92D0000,         /* STMDB sp!,{rlist}    */
-           0xE92D4000,         /* STMDB sp!,{rlist,lr} */
-           0xE8BD0000,         /* LDMIA sp!,{rlist}    */
-           0xE8BD8000          /* LDMIA sp!,{rlist,pc} */
-         };
-         *ainstr = subset[((tinstr & (1 << 11)) >> 10)
-                          | ((tinstr & (1 << 8)) >> 8)]        /* base */
-           | (tinstr & 0x00FF);        /* mask8 */
+         break;
+       case 0x0400:
+         /* Format 14 - Push */
+         * ainstr = 0xE92D0000 | (tinstr & 0x00FF);
+         break;
+       case 0x0500:
+         /* Format 14 - Push + LR */
+         * ainstr = 0xE92D4000 | (tinstr & 0x00FF);
+         break;
+       case 0x0c00:
+         /* Format 14 - Pop */
+         * ainstr = 0xE8BD0000 | (tinstr & 0x00FF);
+         break;
+       case 0x0d00:
+         /* Format 14 - Pop + PC */
+         * ainstr = 0xE8BD8000 | (tinstr & 0x00FF);
+         break;
+       case 0x0e00:
+         if (state->is_v5)
+           {
+             /* This is normally an undefined instruction.  The v5t architecture 
+                defines this particular pattern as a BKPT instruction, for
+                hardware assisted debugging.  We map onto the arm BKPT
+                instruction.  */
+             * ainstr = 0xE1200070 | ((tinstr & 0xf0) << 4) | (tinstr & 0xf);
+             break;
+           }
+         /* Drop through.  */
+       default:
+         /* Everything else is an undefined instruction.  */
+         valid = t_undefined;
+         break;
        }
       break;
     case 24:                   /* STMIA */
@@ -446,6 +472,34 @@ tdstate ARMul_ThumbDecode (state, pc, tinstr, ainstr)
       valid = t_branch;
       break;
     case 29:                   /* UNDEFINED */
+      if (state->is_v5)
+       {
+         if (tinstr & 1)
+           {
+             valid = t_undefined;
+             break;
+           }
+         /* Drop through.  */
+         
+       do_blx2:                        /* BLX instruction 2 */
+         /* Format 19 */
+         /* There is no single ARM instruction equivalent for this
+            instruction. Also, it should only ever be matched with the
+            fmt19 "BL/BLX instruction 1" instruction.  However, we do
+            allow the simulation of it on its own, with undefined results
+            if r14 is not suitably initialised.  */
+         {
+           ARMword tmp = (pc + 2);
+           
+           state->Reg[15] = ((state->Reg[14] + ((tinstr & 0x07FF) << 1))
+                             & 0xFFFFFFFC);
+           CLEART;
+           state->Reg[14] = (tmp | 1);
+           valid = t_branch;
+           FLUSHPIPE;
+           break;
+         }
+       }
       valid = t_undefined;
       break;
     case 30:                   /* BL instruction 1 */
@@ -461,7 +515,14 @@ tdstate ARMul_ThumbDecode (state, pc, tinstr, ainstr)
       valid = t_branch;                /* in-case we don't have the 2nd half */
       tinstr = next_instr;     /* move the instruction down */
       if (((tinstr & 0xF800) >> 11) != 31)
-       break;                  /* exit, since not correct instruction */
+       {
+         if (((tinstr & 0xF800) >> 11) == 29)
+           {
+             pc += 2;
+             goto do_blx2;
+           }
+         break;                /* exit, since not correct instruction */
+       }
       /* else we fall through to process the second half of the BL */
       pc += 2;                 /* point the pc at the 2nd half */
     case 31:                   /* BL instruction 2 */
index b5ecd31cebd499f68d7ab6c0f66ccacda213af8b..f6c4b05c6e6d38270adf97a295e99226a947ac1a 100644 (file)
@@ -114,6 +114,8 @@ ARMul_Debug (ARMul_State * state ATTRIBUTE_UNUSED, ARMword pc ATTRIBUTE_UNUSED,
   return 0;
 }
 
+int SWI_vector_installed = FALSE;
+
 int
 sim_write (sd, addr, buffer, size)
      SIM_DESC sd ATTRIBUTE_UNUSED;
@@ -125,6 +127,9 @@ sim_write (sd, addr, buffer, size)
 
   init ();
 
+  if ((addr <= 0x8) && ((addr + size) >= 0x8))
+    SWI_vector_installed = TRUE;
+
   for (i = 0; i < size; i++)
     ARMul_WriteByte (state, addr + i, buffer[i]);
 
@@ -216,37 +221,47 @@ sim_create_inferior (sd, abfd, argv, env)
                                        "Unknown machine type; please update sim_create_inferior.\n");
       /* fall through */
 
-    case 0: /* arm */
+    case 0:
       /* We wouldn't set the machine type with earlier toolchains, so we
-        explicitly select a processor capable of supporting all ARM
-        32bit mode. */
-      /* fall through */
+        explicitly select a processor capable of supporting all ARMs in
+        32bit mode.  */
+    case bfd_mach_arm_5:
+    case bfd_mach_arm_5T:
+      ARMul_SelectProcessor (state, ARM_v5_Prop);
+      break;
 
-    case 5: /* armv4 */
-    case 6: /* armv4t */
-    case 7: /* armv5 */
-    case 8: /* armv5t */
-      if (mach == 7 || mach == 8)
-       ARMul_SelectProcessor (state, ARM_v5_Prop);
-      else
-       ARMul_SelectProcessor (state, ARM_v4_Prop);
-      /* Reset mode to ARM.  A gdb user may rerun a program that had entered
-        THUMB mode from the start and cause the ARM-mode startup code to be
-        executed in THUMB mode. */
-      ARMul_SetCPSR (state, USER32MODE);
+    case bfd_mach_arm_5TE:
+      ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop);
+      break;
+
+    case bfd_mach_arm_XScale:
+      ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop | ARM_XScale_Prop);
       break;
 
-    case 3: /* armv3 */
-    case 4: /* armv3m */
+    case bfd_mach_arm_4:
+    case bfd_mach_arm_4T:
+      ARMul_SelectProcessor (state, ARM_v4_Prop);
+      break;
+
+    case bfd_mach_arm_3:
+    case bfd_mach_arm_3M:
       ARMul_SelectProcessor (state, ARM_Lock_Prop);
       break;
 
-    case 1: /* armv2 */
-    case 2: /* armv2a */
+    case bfd_mach_arm_2:
+    case bfd_mach_arm_2a:
       ARMul_SelectProcessor (state, ARM_Fix26_Prop);
       break;
     }
 
+  if (mach > 3)
+    {
+      /* Reset mode to ARM.  A gdb user may rerun a program that had entered
+        THUMB mode from the start and cause the ARM-mode startup code to be
+        executed in THUMB mode. */
+      ARMul_SetCPSR (state, USER32MODE);
+    }
+  
   if (argv != NULL)
     {
       /*
@@ -354,6 +369,7 @@ sim_store_register (sd, rn, memory, length)
      int length ATTRIBUTE_UNUSED;
 {
   init ();
+
   if (rn == 25)
     {
       state->Cpsr = frommem (state, memory);
@@ -374,6 +390,7 @@ sim_fetch_register (sd, rn, memory, length)
   ARMword regval;
 
   init ();
+
   if (rn < 16)
     regval = ARMul_GetReg (state, state->Mode, rn);
   else if (rn == 25)           /* FIXME: use PS_REGNUM from gdb/config/arm/tm-arm.h */
index 49452c3e6261a07f2894cae312a92abb42ca1886..8d324ad74ec25a3f0c99a138587ec3b0584ed9ec 100755 (executable)
@@ -1415,6 +1415,10 @@ case "${target}" in
        sim_target=arm
        extra_subdirs="${extra_subdirs} testsuite"
        ;;
+  xscale-*-*)
+       sim_target=arm
+       extra_subdirs="${extra_subdirs} testsuite"
+       ;;
   d10v-*-*)            sim_target=d10v ;;
   d30v-*-*)
        sim_target=d30v
index b0fa140f5f79f46d6ff7aaa259f7d8f8fadbf597..e472f8862b90273a0834ae00e86b3e1851b061e8 100644 (file)
@@ -54,6 +54,10 @@ case "${target}" in
        sim_target=arm
        extra_subdirs="${extra_subdirs} testsuite"
        ;;
+  xscale-*-*)
+       sim_target=arm
+       extra_subdirs="${extra_subdirs} testsuite"
+       ;;
   d10v-*-*)            sim_target=d10v ;;
   d30v-*-*)
        sim_target=d30v