Add support for ARM's v5TE architecture and Intel's XScale extenstions

This commit is contained in:
Nick Clifton
2000-11-30 01:55:12 +00:00
parent 2a1aa0e97c
commit f1129fb8ff
12 changed files with 1772 additions and 251 deletions

View 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> 2000-09-15 Nick Clifton <nickc@redhat.com>
* armdefs.h: Rename StrongARM property to v4_ARM and add v5 ARM * 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. * configure: Regenerated to track ../common/aclocal.m4 changes.
1999-05-08 Felix Lee <flee@cygnus.com> 1999-05-08 Felix Lee <flee@cygnus.com>
* configure: Regenerated to track ../common/aclocal.m4 changes. * configure: Regenerated to track ../common/aclocal.m4 changes.

File diff suppressed because it is too large Load Diff

View File

@ -30,6 +30,7 @@ typedef char *VoidStar;
#endif #endif
typedef unsigned long ARMword; /* must be 32 bits wide */ 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 struct ARMul_State ARMul_State;
typedef unsigned ARMul_CPInits (ARMul_State * state); typedef unsigned ARMul_CPInits (ARMul_State * state);
@ -56,9 +57,13 @@ struct ARMul_State
unsigned ErrorCode; /* type of illegal instruction */ unsigned ErrorCode; /* type of illegal instruction */
ARMword Reg[16]; /* the current register file */ ARMword Reg[16]; /* the current register file */
ARMword RegBank[7][16]; /* all the registers */ 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 Cpsr; /* the current psr */
ARMword Spsr[7]; /* the exception psr's */ ARMword Spsr[7]; /* the exception psr's */
ARMword NFlag, ZFlag, CFlag, VFlag, IFFlags; /* dummy flags for speed */ ARMword NFlag, ZFlag, CFlag, VFlag, IFFlags; /* dummy flags for speed */
ARMword SFlag;
#ifdef MODET #ifdef MODET
ARMword TFlag; /* Thumb state */ ARMword TFlag; /* Thumb state */
#endif #endif
@ -125,6 +130,8 @@ struct ARMul_State
unsigned is_v4; /* Are we emulating a v4 architecture (or higher) ? */ unsigned is_v4; /* Are we emulating a v4 architecture (or higher) ? */
unsigned is_v5; /* Are we emulating a v5 architecture ? */ 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 */ unsigned verbose; /* Print various messages like the banner */
}; };
@ -150,6 +157,8 @@ struct ARMul_State
#define ARM_Lock_Prop 0x20 #define ARM_Lock_Prop 0x20
#define ARM_v4_Prop 0x40 #define ARM_v4_Prop 0x40
#define ARM_v5_Prop 0x80 #define ARM_v5_Prop 0x80
#define ARM_v5e_Prop 0x100
#define ARM_XScale_Prop 0x200
/***************************************************************************\ /***************************************************************************\
* Macros to extract instruction fields * * Macros to extract instruction fields *

View File

@ -459,6 +459,30 @@ ARMul_Emulate26 (register ARMul_State * state)
temp = TRUE; temp = TRUE;
break; break;
case NV: 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; temp = FALSE;
break; break;
case EQ: case EQ:
@ -513,6 +537,63 @@ ARMul_Emulate26 (register ARMul_State * state)
{ /* if the condition codes don't match, stop here */ { /* if the condition codes don't match, stop here */
mainswitch: 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)) switch ((int) BITS (20, 27))
{ {
@ -1000,6 +1081,48 @@ ARMul_Emulate26 (register ARMul_State * state)
break; break;
case 0x10: /* TST reg and MRS CPSR and SWP word */ 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 #ifdef MODET
if (BITS (4, 11) == 0xB) if (BITS (4, 11) == 0xB)
{ {
@ -1072,6 +1195,72 @@ ARMul_Emulate26 (register ARMul_State * state)
break; break;
case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6) */ 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 #ifdef MODET
if (BITS (4, 11) == 0xB) if (BITS (4, 11) == 0xB)
{ {
@ -1079,18 +1268,68 @@ ARMul_Emulate26 (register ARMul_State * state)
SHPREDOWNWB (); SHPREDOWNWB ();
break; break;
} }
#endif
#ifdef MODET
if (BITS (4, 27) == 0x12FFF1) if (BITS (4, 27) == 0x12FFF1)
{ /* BX */ {
/* BX */
WriteR15Branch (state, state->Reg[RHSReg]); WriteR15Branch (state, state->Reg[RHSReg]);
break; break;
} }
#endif #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) if (DESTReg == 15)
{ /* MSR reg to CPSR */ {
/* MSR reg to CPSR */
UNDEF_MSRPC; UNDEF_MSRPC;
temp = DPRegRHS; temp = DPRegRHS;
#ifdef MODET
/* Don't allow TBIT to be set by MSR. */
temp &= ~ TBIT;
#endif
ARMul_FixCPSR (state, instr, temp); ARMul_FixCPSR (state, instr, temp);
} }
else else
@ -1128,6 +1367,60 @@ ARMul_Emulate26 (register ARMul_State * state)
break; break;
case 0x14: /* CMP reg and MRS SPSR and SWP byte */ 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 #ifdef MODET
if (BITS (4, 7) == 0xB) if (BITS (4, 7) == 0xB)
{ {
@ -1207,6 +1500,72 @@ ARMul_Emulate26 (register ARMul_State * state)
break; break;
case 0x16: /* CMN reg and MSR reg to SPSR */ 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 #ifdef MODET
if (BITS (4, 7) == 0xB) if (BITS (4, 7) == 0xB)
{ {
@ -2393,7 +2752,7 @@ ARMul_Emulate26 (register ARMul_State * state)
{ {
/* Check for the special breakpoint opcode. /* Check for the special breakpoint opcode.
This value should correspond to the value defined 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 (BITS (0, 19) == 0xfdefe)
{ {
if (!ARMul_OSHandleSWI (state, SWI_Breakpoint)) if (!ARMul_OSHandleSWI (state, SWI_Breakpoint))
@ -2642,11 +3001,56 @@ ARMul_Emulate26 (register ARMul_State * state)
\***************************************************************************/ \***************************************************************************/
case 0xc4: 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 */ case 0xc0: /* Store , No WriteBack , Post Dec */
ARMul_STC (state, instr, LHS); ARMul_STC (state, instr, LHS);
break; break;
case 0xc5: 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 */ case 0xc1: /* Load , No WriteBack , Post Dec */
ARMul_LDC (state, instr, LHS); ARMul_LDC (state, instr, LHS);
break; break;
@ -2743,6 +3147,88 @@ ARMul_Emulate26 (register ARMul_State * state)
\***************************************************************************/ \***************************************************************************/
case 0xe2: 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 0xe0:
case 0xe4: case 0xe4:
case 0xe6: case 0xe6:

View File

@ -55,6 +55,7 @@ extern ARMword isize;
#define ZBIT (1L << 30) #define ZBIT (1L << 30)
#define CBIT (1L << 29) #define CBIT (1L << 29)
#define VBIT (1L << 28) #define VBIT (1L << 28)
#define SBIT (1L << 27)
#define IBIT (1L << 7) #define IBIT (1L << 7)
#define FBIT (1L << 6) #define FBIT (1L << 6)
#define IFBITS (3L << 6) #define IFBITS (3L << 6)
@ -98,6 +99,10 @@ extern ARMword isize;
#define CLEARV state->VFlag = 0 #define CLEARV state->VFlag = 0
#define ASSIGNV(res) state->VFlag = res #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 IFLAG (state->IFFlags >> 1)
#define FFLAG (state->IFFlags & 1) #define FFLAG (state->IFFlags & 1)
@ -110,7 +115,12 @@ extern ARMword isize;
#define PSR_XBITS (0x0000ff00L) #define PSR_XBITS (0x0000ff00L)
#define PSR_CBITS (0x000000ffL) #define PSR_CBITS (0x000000ffL)
#if defined MODE32 || defined MODET
#define CCBITS (0xf8000000L)
#else
#define CCBITS (0xf0000000L) #define CCBITS (0xf0000000L)
#endif
#define INTBITS (0xc0L) #define INTBITS (0xc0L)
#if defined MODET && defined MODE32 #if defined MODET && defined MODE32
@ -149,7 +159,7 @@ extern ARMword isize;
#define R15PCMODE (state->Reg[15] & (R15PCBITS | R15MODEBITS)) #define R15PCMODE (state->Reg[15] & (R15PCBITS | R15MODEBITS))
#define R15MODE (state->Reg[15] & 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 EINT (IFFLAGS << 6)
#define ER15INT (IFFLAGS << 26) #define ER15INT (IFFLAGS << 26)
#define EMODE (state->Mode) #define EMODE (state->Mode)
@ -472,3 +482,14 @@ extern tdstate ARMul_ThumbDecode (ARMul_State * state, ARMword pc,
#define UNDEF_IllegalMode #define UNDEF_IllegalMode
#define UNDEF_Prog32SigChange #define UNDEF_Prog32SigChange
#define UNDEF_Data32SigChange #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);

View File

@ -86,7 +86,8 @@ ARMul_NewState (void)
for (i = 0; i < 7; i++) for (i = 0; i < 7; i++)
state->Spsr[i] = 0; state->Spsr[i] = 0;
state->Mode = USER26MODE; /* state->Mode = USER26MODE; */
state->Mode = USER32MODE;
state->CallDebug = FALSE; state->CallDebug = FALSE;
state->Debug = FALSE; state->Debug = FALSE;
@ -113,19 +114,16 @@ ARMul_NewState (void)
for (i = 0; i < EVENTLISTSIZE; i++) for (i = 0; i < EVENTLISTSIZE; i++)
*(state->EventPtr + i) = NULL; *(state->EventPtr + i) = NULL;
#ifdef ARM61
state->prog32Sig = LOW;
state->data32Sig = LOW;
#else
state->prog32Sig = HIGH; state->prog32Sig = HIGH;
state->data32Sig = HIGH; state->data32Sig = HIGH;
#endif
state->lateabtSig = LOW; state->lateabtSig = LOW;
state->bigendSig = LOW; state->bigendSig = LOW;
state->is_v4 = LOW; state->is_v4 = LOW;
state->is_v5 = LOW; state->is_v5 = LOW;
state->is_v5e = LOW;
state->is_XScale = LOW;
ARMul_Reset (state); 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_v4 = (properties & (ARM_v4_Prop | ARM_v5_Prop)) ? HIGH : LOW;
state->is_v5 = (properties & 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; ARMword temp;
int isize = INSN_SIZE; int isize = INSN_SIZE;
int esize = (TFLAG ? 0 : 4);
int e2size = (TFLAG ? -4 : 0);
state->Aborted = FALSE; state->Aborted = FALSE;
@ -288,19 +290,19 @@ ARMul_Abort (ARMul_State * state, ARMword vector)
break; break;
case ARMul_PrefetchAbortV: /* Prefetch Abort */ case ARMul_PrefetchAbortV: /* Prefetch Abort */
state->AbortAddr = 1; state->AbortAddr = 1;
SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE, isize); SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE, esize);
break; break;
case ARMul_DataAbortV: /* Data Abort */ case ARMul_DataAbortV: /* Data Abort */
SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE, isize); SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE, e2size);
break; break;
case ARMul_AddrExceptnV: /* Address Exception */ case ARMul_AddrExceptnV: /* Address Exception */
SETABORT (IBIT, SVC26MODE, isize); SETABORT (IBIT, SVC26MODE, isize);
break; break;
case ARMul_IRQV: /* IRQ */ case ARMul_IRQV: /* IRQ */
SETABORT (IBIT, state->prog32Sig ? IRQ32MODE : IRQ26MODE, isize); SETABORT (IBIT, state->prog32Sig ? IRQ32MODE : IRQ26MODE, esize);
break; break;
case ARMul_FIQV: /* FIQ */ case ARMul_FIQV: /* FIQ */
SETABORT (INTBITS, state->prog32Sig ? FIQ32MODE : FIQ26MODE, isize); SETABORT (INTBITS, state->prog32Sig ? FIQ32MODE : FIQ26MODE, esize);
break; break;
} }
if (ARMul_MODE32BIT) if (ARMul_MODE32BIT)

View File

@ -70,6 +70,8 @@ extern int _fisatty (FILE *);
#include "armdefs.h" #include "armdefs.h"
#include "armos.h" #include "armos.h"
#include "armemu.h"
#ifndef NOOS #ifndef NOOS
#ifndef VALIDATE #ifndef VALIDATE
/* #ifndef ASIM */ /* #ifndef ASIM */
@ -445,11 +447,6 @@ ARMul_OSHandleSWI (ARMul_State * state, ARMword number)
state->Reg[0] = OSptr->ErrorNo; state->Reg[0] = OSptr->ErrorNo;
return (TRUE); return (TRUE);
case SWI_Breakpoint:
state->EndCondition = RDIError_BreakpointReached;
state->Emulate = FALSE;
return (TRUE);
case SWI_GetEnv: case SWI_GetEnv:
state->Reg[0] = ADDRCMDLINE; state->Reg[0] = ADDRCMDLINE;
if (state->MemSize) if (state->MemSize)
@ -459,6 +456,11 @@ ARMul_OSHandleSWI (ARMul_State * state, ARMword number)
WriteCommandLineTo (state, state->Reg[0]); WriteCommandLineTo (state, state->Reg[0]);
return (TRUE); return (TRUE);
case SWI_Breakpoint:
state->EndCondition = RDIError_BreakpointReached;
state->Emulate = FALSE;
return (TRUE);
/* Handle Angel SWIs as well as Demon ones */ /* Handle Angel SWIs as well as Demon ones */
case AngelSWI_ARM: case AngelSWI_ARM:
@ -587,29 +589,58 @@ ARMul_OSHandleSWI (ARMul_State * state, ARMword number)
return TRUE; return TRUE;
} }
case 0x90:
case 0x92:
/* These are used by the FPE code. */
return TRUE;
default: 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 NOOS
#ifndef ASIM #ifndef ASIM
/***************************************************************************\ /* The emulator calls this routine when an Exception occurs. The second
* The emulator calls this routine when an Exception occurs. The second * parameter is the address of the relevant exception vector. Returning
* parameter is the address of the relevant exception vector. Returning * FALSE from this routine causes the trap to be taken, TRUE causes it to
* FALSE from this routine causes the trap to be taken, TRUE causes it to * be ignored (so set state->Emulate to FALSE!). */
* be ignored (so set state->Emulate to FALSE!). *
\***************************************************************************/
unsigned unsigned
ARMul_OSException (ARMul_State * state ATTRIBUTE_UNUSED, ARMword vector ATTRIBUTE_UNUSED, ARMword pc ATTRIBUTE_UNUSED) ARMul_OSException (
{ /* don't use this here */ ARMul_State * state ATTRIBUTE_UNUSED,
return (FALSE); ARMword vector ATTRIBUTE_UNUSED,
ARMword pc ATTRIBUTE_UNUSED)
{
return FALSE;
} }
#endif #endif
#endif /* NOOS */ #endif /* NOOS */

View File

@ -302,6 +302,8 @@ ARMul_CPSRAltered (ARMul_State * state)
state->Cpsr &= ~CBIT; state->Cpsr &= ~CBIT;
ASSIGNV ((state->Cpsr & VBIT) != 0); ASSIGNV ((state->Cpsr & VBIT) != 0);
state->Cpsr &= ~VBIT; state->Cpsr &= ~VBIT;
ASSIGNS ((state->Cpsr & SBIT) != 0);
state->Cpsr &= ~SBIT;
#ifdef MODET #ifdef MODET
ASSIGNT ((state->Cpsr & TBIT) != 0); ASSIGNT ((state->Cpsr & TBIT) != 0);
state->Cpsr &= ~TBIT; state->Cpsr &= ~TBIT;

View File

@ -209,11 +209,19 @@ tdstate ARMul_ThumbDecode (state, pc, tinstr, ainstr)
*ainstr = 0xE12FFF10 /* base */ *ainstr = 0xE12FFF10 /* base */
| ((tinstr & 0x0078) >> 3); /* Rd */ | ((tinstr & 0x0078) >> 3); /* Rd */
break; 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 0x0: /* UNDEFINED */
case 0x4: /* UNDEFINED */ case 0x4: /* UNDEFINED */
case 0x8: /* UNDEFINED */ case 0x8: /* UNDEFINED */
case 0xE: /* UNDEFINED */
case 0xF: /* UNDEFINED */
valid = t_undefined; valid = t_undefined;
break; break;
} }
@ -322,30 +330,48 @@ tdstate ARMul_ThumbDecode (state, pc, tinstr, ainstr)
break; break;
case 22: case 22:
case 23: case 23:
if ((tinstr & 0x0F00) == 0x0000) switch (tinstr & 0x0F00)
{ {
case 0x0000:
/* Format 13 */ /* Format 13 */
/* NOTE: The instruction contains a shift left of 2 /* NOTE: The instruction contains a shift left of 2
equivalent (implemented as ROR #30): */ equivalent (implemented as ROR #30): */
*ainstr = ((tinstr & (1 << 7)) /* base */ *ainstr = ((tinstr & (1 << 7)) /* base */
? 0xE24DDF00 /* SUB */ ? 0xE24DDF00 /* SUB */
: 0xE28DDF00) /* ADD */ : 0xE28DDF00) /* ADD */
| (tinstr & 0x007F); /* off7 */ | (tinstr & 0x007F); /* off7 */
} break;
else if ((tinstr & 0x0F00) == 0x0e00) case 0x0400:
*ainstr = 0xEF000000 | SWI_Breakpoint; /* Format 14 - Push */
else * ainstr = 0xE92D0000 | (tinstr & 0x00FF);
{ break;
/* Format 14 */ case 0x0500:
ARMword subset[4] = { /* Format 14 - Push + LR */
0xE92D0000, /* STMDB sp!,{rlist} */ * ainstr = 0xE92D4000 | (tinstr & 0x00FF);
0xE92D4000, /* STMDB sp!,{rlist,lr} */ break;
0xE8BD0000, /* LDMIA sp!,{rlist} */ case 0x0c00:
0xE8BD8000 /* LDMIA sp!,{rlist,pc} */ /* Format 14 - Pop */
}; * ainstr = 0xE8BD0000 | (tinstr & 0x00FF);
*ainstr = subset[((tinstr & (1 << 11)) >> 10) break;
| ((tinstr & (1 << 8)) >> 8)] /* base */ case 0x0d00:
| (tinstr & 0x00FF); /* mask8 */ /* 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; break;
case 24: /* STMIA */ case 24: /* STMIA */
@ -446,6 +472,34 @@ tdstate ARMul_ThumbDecode (state, pc, tinstr, ainstr)
valid = t_branch; valid = t_branch;
break; break;
case 29: /* UNDEFINED */ 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; valid = t_undefined;
break; break;
case 30: /* BL instruction 1 */ 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 */ valid = t_branch; /* in-case we don't have the 2nd half */
tinstr = next_instr; /* move the instruction down */ tinstr = next_instr; /* move the instruction down */
if (((tinstr & 0xF800) >> 11) != 31) 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 */ /* else we fall through to process the second half of the BL */
pc += 2; /* point the pc at the 2nd half */ pc += 2; /* point the pc at the 2nd half */
case 31: /* BL instruction 2 */ case 31: /* BL instruction 2 */

View File

@ -114,6 +114,8 @@ ARMul_Debug (ARMul_State * state ATTRIBUTE_UNUSED, ARMword pc ATTRIBUTE_UNUSED,
return 0; return 0;
} }
int SWI_vector_installed = FALSE;
int int
sim_write (sd, addr, buffer, size) sim_write (sd, addr, buffer, size)
SIM_DESC sd ATTRIBUTE_UNUSED; SIM_DESC sd ATTRIBUTE_UNUSED;
@ -125,6 +127,9 @@ sim_write (sd, addr, buffer, size)
init (); init ();
if ((addr <= 0x8) && ((addr + size) >= 0x8))
SWI_vector_installed = TRUE;
for (i = 0; i < size; i++) for (i = 0; i < size; i++)
ARMul_WriteByte (state, addr + i, buffer[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"); "Unknown machine type; please update sim_create_inferior.\n");
/* fall through */ /* fall through */
case 0: /* arm */ case 0:
/* We wouldn't set the machine type with earlier toolchains, so we /* We wouldn't set the machine type with earlier toolchains, so we
explicitly select a processor capable of supporting all ARM explicitly select a processor capable of supporting all ARMs in
32bit mode. */ 32bit mode. */
/* fall through */ case bfd_mach_arm_5:
case bfd_mach_arm_5T:
case 5: /* armv4 */ ARMul_SelectProcessor (state, ARM_v5_Prop);
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);
break; break;
case 3: /* armv3 */ case bfd_mach_arm_5TE:
case 4: /* armv3m */ 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); ARMul_SelectProcessor (state, ARM_Lock_Prop);
break; break;
case 1: /* armv2 */ case bfd_mach_arm_2:
case 2: /* armv2a */ case bfd_mach_arm_2a:
ARMul_SelectProcessor (state, ARM_Fix26_Prop); ARMul_SelectProcessor (state, ARM_Fix26_Prop);
break; 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) if (argv != NULL)
{ {
/* /*
@ -354,6 +369,7 @@ sim_store_register (sd, rn, memory, length)
int length ATTRIBUTE_UNUSED; int length ATTRIBUTE_UNUSED;
{ {
init (); init ();
if (rn == 25) if (rn == 25)
{ {
state->Cpsr = frommem (state, memory); state->Cpsr = frommem (state, memory);
@ -374,6 +390,7 @@ sim_fetch_register (sd, rn, memory, length)
ARMword regval; ARMword regval;
init (); init ();
if (rn < 16) if (rn < 16)
regval = ARMul_GetReg (state, state->Mode, rn); regval = ARMul_GetReg (state, state->Mode, rn);
else if (rn == 25) /* FIXME: use PS_REGNUM from gdb/config/arm/tm-arm.h */ else if (rn == 25) /* FIXME: use PS_REGNUM from gdb/config/arm/tm-arm.h */

4
sim/configure vendored
View File

@ -1415,6 +1415,10 @@ case "${target}" in
sim_target=arm sim_target=arm
extra_subdirs="${extra_subdirs} testsuite" extra_subdirs="${extra_subdirs} testsuite"
;; ;;
xscale-*-*)
sim_target=arm
extra_subdirs="${extra_subdirs} testsuite"
;;
d10v-*-*) sim_target=d10v ;; d10v-*-*) sim_target=d10v ;;
d30v-*-*) d30v-*-*)
sim_target=d30v sim_target=d30v

View File

@ -54,6 +54,10 @@ case "${target}" in
sim_target=arm sim_target=arm
extra_subdirs="${extra_subdirs} testsuite" extra_subdirs="${extra_subdirs} testsuite"
;; ;;
xscale-*-*)
sim_target=arm
extra_subdirs="${extra_subdirs} testsuite"
;;
d10v-*-*) sim_target=d10v ;; d10v-*-*) sim_target=d10v ;;
d30v-*-*) d30v-*-*)
sim_target=d30v sim_target=d30v