diff --git a/sim/arm/ChangeLog b/sim/arm/ChangeLog
index b66a3403bc3..2c893e00a2d 100644
--- a/sim/arm/ChangeLog
+++ b/sim/arm/ChangeLog
@@ -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.
diff --git a/sim/arm/armcopro.c b/sim/arm/armcopro.c
index 48be6806ea2..db7ee60d69c 100644
--- a/sim/arm/armcopro.c
+++ b/sim/arm/armcopro.c
@@ -19,37 +19,880 @@
 #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 NoCoPro3R (ARMul_State * state, unsigned, ARMword);
-static unsigned NoCoPro4R (ARMul_State * state, unsigned, ARMword, ARMword);
-static unsigned NoCoPro4W (ARMul_State * state, unsigned, ARMword, ARMword *);
+static unsigned
+NoCoPro4W (ARMul_State * state ATTRIBUTE_UNUSED,
+	   unsigned      a     ATTRIBUTE_UNUSED,
+	   ARMword       b     ATTRIBUTE_UNUSED,
+	   ARMword *     c     ATTRIBUTE_UNUSED)
+{
+  return ARMul_CANT;
+}
 
-/***************************************************************************\
-*                Define Co-Processor instruction handlers here              *
-\***************************************************************************/
+/* The XScale Co-processors.  */
+
+/* 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;
     }
-  return (ARMul_CANT);
+  else if (type == ARMul_BUSY)
+    {
+      if (ARMul_Time (state) >= finish)
+	return ARMul_DONE;
+      else
+	return ARMul_BUSY;
+    }
+  
+  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);
-}
diff --git a/sim/arm/armdefs.h b/sim/arm/armdefs.h
index 61ab9c5816d..204dc6bee3d 100644
--- a/sim/arm/armdefs.h
+++ b/sim/arm/armdefs.h
@@ -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                    *
diff --git a/sim/arm/armemu.c b/sim/arm/armemu.c
index 9d3dcba60d4..6413728b771 100644
--- a/sim/arm/armemu.c
+++ b/sim/arm/armemu.c
@@ -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:
diff --git a/sim/arm/armemu.h b/sim/arm/armemu.h
index 81ecd523d17..8fd5f356d33 100644
--- a/sim/arm/armemu.h
+++ b/sim/arm/armemu.h
@@ -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);
diff --git a/sim/arm/arminit.c b/sim/arm/arminit.c
index a3f0001c7cc..2f6e73df3ca 100644
--- a/sim/arm/arminit.c
+++ b/sim/arm/arminit.c
@@ -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)
diff --git a/sim/arm/armos.c b/sim/arm/armos.c
index 958d4cde6ff..62b3ff5694b 100644
--- a/sim/arm/armos.c
+++ b/sim/arm/armos.c
@@ -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 */
diff --git a/sim/arm/armsupp.c b/sim/arm/armsupp.c
index 27ee35ba192..2d0390d1cbe 100644
--- a/sim/arm/armsupp.c
+++ b/sim/arm/armsupp.c
@@ -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;
diff --git a/sim/arm/thumbemu.c b/sim/arm/thumbemu.c
index dc90dd7cf48..3351c2f65da 100644
--- a/sim/arm/thumbemu.c
+++ b/sim/arm/thumbemu.c
@@ -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 */
diff --git a/sim/arm/wrapper.c b/sim/arm/wrapper.c
index b5ecd31cebd..f6c4b05c6e6 100644
--- a/sim/arm/wrapper.c
+++ b/sim/arm/wrapper.c
@@ -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 */
-
-    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);
+	 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 3: /* armv3 */
-    case 4: /* armv3m */
+    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 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 */
diff --git a/sim/configure b/sim/configure
index 49452c3e626..8d324ad74ec 100755
--- a/sim/configure
+++ b/sim/configure
@@ -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
diff --git a/sim/configure.in b/sim/configure.in
index b0fa140f5f7..e472f8862b9 100644
--- a/sim/configure.in
+++ b/sim/configure.in
@@ -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