forked from Imagelibrary/binutils-gdb
Add support for _x and _s flags to MSR instruction
This commit is contained in:
@@ -1,3 +1,19 @@
|
||||
2000-05-15 Nick Clifton <nickc@cygnus.com>
|
||||
|
||||
* config/tc-arm.c (struct asm_psr): Add boolean field
|
||||
distinguishing between CSPR and SPSR. Rename 'number' field
|
||||
to 'field'.
|
||||
(psrs): Rearrange contents to match new asm_psr structure.
|
||||
(arm_psr_parse): Move next to psr_required_here. Make it
|
||||
return an asm_psr structure.
|
||||
(psr_required_here): Use asm_psr structure returned by
|
||||
arm_psr_parse.
|
||||
(do_msr): Reorganise to allow psr_required_here to be called
|
||||
only once.
|
||||
(md_undefined_name): Mark 'name' parameter as unused, since
|
||||
the COFF target does not use it.
|
||||
|
||||
|
||||
2000-05-14 David O'Brien <obrien@FreeBSD.org>
|
||||
|
||||
* config/te-386bsd.h: Clean up comments to adhere to the GNU coding
|
||||
|
||||
@@ -381,39 +381,50 @@ static CONST struct asm_flg cplong_flag[] =
|
||||
struct asm_psr
|
||||
{
|
||||
CONST char * template;
|
||||
unsigned long number;
|
||||
boolean cpsr;
|
||||
unsigned long field;
|
||||
};
|
||||
|
||||
#define PSR_FIELD_MASK 0x000f0000
|
||||
#define SPSR_BIT (1 << 22) /* The bit that distnguishes CPSR and SPSR. */
|
||||
#define PSR_SHIFT 16 /* How many bits to shift the PSR_xxx bits up by. */
|
||||
|
||||
#define PSR_FLAGS 0x00080000
|
||||
#define PSR_CONTROL 0x00010000 /* Undocumented instruction, its use is discouraged by ARM */
|
||||
#define PSR_ALL 0x00090000
|
||||
|
||||
#define CPSR_ALL 0
|
||||
#define SPSR_ALL 1
|
||||
#define CPSR_FLG 2
|
||||
#define SPSR_FLG 3
|
||||
#define CPSR_CTL 4
|
||||
#define SPSR_CTL 5
|
||||
#define PSR_c (1 << 0)
|
||||
#define PSR_x (1 << 1)
|
||||
#define PSR_s (1 << 2)
|
||||
#define PSR_f (1 << 3)
|
||||
|
||||
static CONST struct asm_psr psrs[] =
|
||||
{
|
||||
/* Valid <psr>'s */
|
||||
{"cpsr", CPSR_ALL},
|
||||
{"cpsr_all", CPSR_ALL},
|
||||
{"spsr", SPSR_ALL},
|
||||
{"spsr_all", SPSR_ALL},
|
||||
|
||||
/* Valid <psrf>'s */
|
||||
{"cpsr_flg", CPSR_FLG},
|
||||
{"spsr_flg", SPSR_FLG},
|
||||
|
||||
/* Valid <psrc>'s */
|
||||
{"cpsr_c", CPSR_CTL},
|
||||
{"cpsr_ctl", CPSR_CTL},
|
||||
{"spsr_c", SPSR_CTL},
|
||||
{"spsr_ctl", SPSR_CTL}
|
||||
{"CPSR", true, PSR_c | PSR_f},
|
||||
{"CPSR_all", true, PSR_c | PSR_f},
|
||||
{"SPSR", false, PSR_c | PSR_f},
|
||||
{"SPSR_all", false, PSR_c | PSR_f},
|
||||
{"CPSR_flg", true, PSR_f},
|
||||
{"CPSR_f", true, PSR_f},
|
||||
{"SPSR_flg", false, PSR_f},
|
||||
{"SPSR_f", false, PSR_f},
|
||||
{"CPSR_c", true, PSR_c},
|
||||
{"CPSR_ctl", true, PSR_c},
|
||||
{"SPSR_c", false, PSR_c},
|
||||
{"SPSR_ctl", false, PSR_c},
|
||||
{"CPSR_x", true, PSR_x},
|
||||
{"CPSR_s", true, PSR_s},
|
||||
{"SPSR_x", false, PSR_x},
|
||||
{"SPSR_s", false, PSR_s},
|
||||
/* For backwards compatability with older toolchain we also
|
||||
support lower case versions of some of these flags. */
|
||||
{"cpsr", true, PSR_c | PSR_f},
|
||||
{"cpsr_all", true, PSR_c | PSR_f},
|
||||
{"spsr", false, PSR_c | PSR_f},
|
||||
{"spsr_all", false, PSR_c | PSR_f},
|
||||
{"cpsr_flg", true, PSR_f},
|
||||
{"cpsr_f", true, PSR_f},
|
||||
{"spsr_flg", false, PSR_f},
|
||||
{"spsr_f", false, PSR_f},
|
||||
{"cpsr_c", true, PSR_c},
|
||||
{"cpsr_ctl", true, PSR_c},
|
||||
{"spsr_c", false, PSR_c},
|
||||
{"spsr_ctl", false, PSR_c}
|
||||
};
|
||||
|
||||
/* Functions called by parser. */
|
||||
@@ -458,7 +469,7 @@ static void do_fp_to_reg PARAMS ((char *, unsigned long));
|
||||
|
||||
static void fix_new_arm PARAMS ((fragS *, int, short, expressionS *, int, int));
|
||||
static int arm_reg_parse PARAMS ((char **));
|
||||
static int arm_psr_parse PARAMS ((char **));
|
||||
static CONST struct asm_psr * arm_psr_parse PARAMS ((char **));
|
||||
static void symbol_locate PARAMS ((symbolS *, CONST char *, segT, valueT, fragS *));
|
||||
static int add_to_lit_pool PARAMS ((void));
|
||||
static unsigned validate_immediate PARAMS ((unsigned));
|
||||
@@ -467,7 +478,7 @@ static int validate_offset_imm PARAMS ((unsigned int, int));
|
||||
static void opcode_select PARAMS ((int));
|
||||
static void end_of_line PARAMS ((char *));
|
||||
static int reg_required_here PARAMS ((char **, int));
|
||||
static int psr_required_here PARAMS ((char **, int, int));
|
||||
static int psr_required_here PARAMS ((char **));
|
||||
static int co_proc_number PARAMS ((char **));
|
||||
static int cp_opc_expr PARAMS ((char **, int, int));
|
||||
static int cp_reg_required_here PARAMS ((char **, int));
|
||||
@@ -569,8 +580,8 @@ static CONST struct asm_opcode insns[] =
|
||||
{"mrs", 0x010f0000, NULL, NULL, ARM_6UP, do_mrs},
|
||||
{"msr", 0x0120f000, NULL, NULL, ARM_6UP, do_msr},
|
||||
/* ScottB: our code uses 0x0128f000 for msr.
|
||||
NickC: but this is wrong because the bits 16 and 19 are handled
|
||||
by the PSR_xxx defines above. */
|
||||
NickC: but this is wrong because the bits 16 through 19 are
|
||||
handled by the PSR_xxx defines above. */
|
||||
|
||||
/* ARM 7M long multiplies - need signed/unsigned flags! */
|
||||
{"smull", 0x00c00090, NULL, s_flag, ARM_LONGMUL, do_mull},
|
||||
@@ -1562,27 +1573,65 @@ reg_required_here (str, shift)
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
static int
|
||||
psr_required_here (str, cpsr, spsr)
|
||||
char ** str;
|
||||
int cpsr;
|
||||
int spsr;
|
||||
static CONST struct asm_psr *
|
||||
arm_psr_parse (ccp)
|
||||
register char ** ccp;
|
||||
{
|
||||
int psr;
|
||||
char * start = *str;
|
||||
psr = arm_psr_parse (str);
|
||||
|
||||
if (psr == cpsr || psr == spsr)
|
||||
char * start = * ccp;
|
||||
char c;
|
||||
char * p;
|
||||
CONST struct asm_psr * psr;
|
||||
|
||||
p = start;
|
||||
|
||||
/* Skip to the end of the next word in the input stream. */
|
||||
do
|
||||
{
|
||||
if (psr == spsr)
|
||||
inst.instruction |= 1 << 22;
|
||||
c = *p++;
|
||||
}
|
||||
while (isalpha (c) || c == '_');
|
||||
|
||||
/* Terminate the word. */
|
||||
*--p = 0;
|
||||
|
||||
/* Now locate the word in the psr hash table. */
|
||||
psr = (CONST struct asm_psr *) hash_find (arm_psr_hsh, start);
|
||||
|
||||
/* Restore the input stream. */
|
||||
*p = c;
|
||||
|
||||
/* If we found a valid match, advance the
|
||||
stream pointer past the end of the word. */
|
||||
*ccp = p;
|
||||
|
||||
return psr;
|
||||
}
|
||||
|
||||
/* Parse the input looking for a PSR flag. */
|
||||
static int
|
||||
psr_required_here (str)
|
||||
char ** str;
|
||||
{
|
||||
char * start = *str;
|
||||
CONST struct asm_psr * psr;
|
||||
|
||||
psr = arm_psr_parse (str);
|
||||
|
||||
if (psr)
|
||||
{
|
||||
/* If this is the SPSR that is being modified, set the R bit. */
|
||||
if (! psr->cpsr)
|
||||
inst.instruction |= SPSR_BIT;
|
||||
|
||||
/* Set the psr flags in the MSR instruction. */
|
||||
inst.instruction |= psr->field << PSR_SHIFT;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/* In the few cases where we might be able to accept something else
|
||||
this error can be overridden. */
|
||||
inst.error = _("<psr(f)> expected");
|
||||
/* In the few cases where we might be able to accept
|
||||
something else this error can be overridden. */
|
||||
inst.error = _("flag for {c}psr instruction expected");
|
||||
|
||||
/* Restore the start point. */
|
||||
*str = start;
|
||||
@@ -1874,104 +1923,110 @@ do_mrs (str, flags)
|
||||
return;
|
||||
}
|
||||
|
||||
if (skip_past_comma (&str) == FAIL
|
||||
|| psr_required_here (& str, CPSR_ALL, SPSR_ALL) == FAIL)
|
||||
if (skip_past_comma (&str) == FAIL)
|
||||
{
|
||||
inst.error = _("<psr> expected");
|
||||
inst.error = _("comma expected after register name");
|
||||
return;
|
||||
}
|
||||
|
||||
skip_whitespace (str);
|
||||
|
||||
if ( strcmp (str, "CPSR") == 0
|
||||
|| strcmp (str, "SPSR") == 0
|
||||
/* Lower case versions for backwards compatability. */
|
||||
|| strcmp (str, "cpsr") == 0
|
||||
|| strcmp (str, "spsr") == 0)
|
||||
str += 4;
|
||||
/* This is for backwards compatability with older toolchains. */
|
||||
else if (strcmp (str, "cpsr_all") == 0
|
||||
|| strcmp (str, "spsr_all") == 0)
|
||||
str += 7;
|
||||
else
|
||||
{
|
||||
inst.error = _("{C|S}PSR expected");
|
||||
return;
|
||||
}
|
||||
|
||||
if (* str == 's' || * str == 'S')
|
||||
inst.instruction |= SPSR_BIT;
|
||||
|
||||
inst.instruction |= flags;
|
||||
end_of_line (str);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Three possible forms: "<psr>, Rm", "<psrf>, Rm", "<psrf>, #expression". */
|
||||
/* Two possible forms:
|
||||
"{C|S}PSR_<field>, Rm",
|
||||
"{C|S}PSR_f, #expression". */
|
||||
static void
|
||||
do_msr (str, flags)
|
||||
char * str;
|
||||
unsigned long flags;
|
||||
{
|
||||
int reg;
|
||||
skip_whitespace (str);
|
||||
|
||||
if (psr_required_here (& str) == FAIL)
|
||||
return;
|
||||
|
||||
if (skip_past_comma (& str) == FAIL)
|
||||
{
|
||||
inst.error = _("comma missing after psr flags");
|
||||
return;
|
||||
}
|
||||
|
||||
skip_whitespace (str);
|
||||
|
||||
if (psr_required_here (&str, CPSR_ALL, SPSR_ALL) == SUCCESS)
|
||||
if (reg_required_here (& str, 0) != FAIL)
|
||||
{
|
||||
inst.instruction |= PSR_ALL;
|
||||
inst.error = NULL;
|
||||
inst.instruction |= flags;
|
||||
end_of_line (str);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Sytax should be "<psr>, Rm" */
|
||||
if (skip_past_comma (&str) == FAIL
|
||||
|| (reg = reg_required_here (&str, 0)) == FAIL)
|
||||
{
|
||||
inst.error = BAD_ARGS;
|
||||
return;
|
||||
}
|
||||
if (! is_immediate_prefix (* str))
|
||||
{
|
||||
inst.error = _("only a register or immediate value can follow a psr flag");
|
||||
return;
|
||||
}
|
||||
|
||||
str ++;
|
||||
inst.error = NULL;
|
||||
|
||||
if (my_get_expression (& inst.reloc.exp, & str))
|
||||
{
|
||||
inst.error = _("only a register or immediate value can follow a psr flag");
|
||||
return;
|
||||
}
|
||||
|
||||
if (inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
|
||||
{
|
||||
inst.error = _("can only set flag field with immediate value");
|
||||
return;
|
||||
}
|
||||
|
||||
flags |= INST_IMMEDIATE;
|
||||
|
||||
if (inst.reloc.exp.X_add_symbol)
|
||||
{
|
||||
inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
|
||||
inst.reloc.pc_rel = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (psr_required_here (& str, CPSR_FLG, SPSR_FLG) == SUCCESS)
|
||||
inst.instruction |= PSR_FLAGS;
|
||||
else if (psr_required_here (& str, CPSR_CTL, SPSR_CTL) == SUCCESS)
|
||||
inst.instruction |= PSR_CONTROL;
|
||||
else
|
||||
unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
|
||||
|
||||
if (value == (unsigned) FAIL)
|
||||
{
|
||||
inst.error = BAD_ARGS;
|
||||
inst.error = _("Invalid constant");
|
||||
return;
|
||||
}
|
||||
|
||||
if (skip_past_comma (&str) == FAIL)
|
||||
{
|
||||
inst.error = BAD_ARGS;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Syntax could be "<psrf>, rm", "<psrf>, #expression" */
|
||||
|
||||
if ((reg = reg_required_here (& str, 0)) != FAIL)
|
||||
;
|
||||
/* Immediate expression. */
|
||||
else if (is_immediate_prefix (* str))
|
||||
{
|
||||
str ++;
|
||||
inst.error = NULL;
|
||||
|
||||
if (my_get_expression (& inst.reloc.exp, & str))
|
||||
{
|
||||
inst.error = _("Register or shift expression expected");
|
||||
return;
|
||||
}
|
||||
|
||||
if (inst.reloc.exp.X_add_symbol)
|
||||
{
|
||||
inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
|
||||
inst.reloc.pc_rel = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
|
||||
if (value == (unsigned) FAIL)
|
||||
{
|
||||
inst.error = _("Invalid constant");
|
||||
return;
|
||||
}
|
||||
|
||||
inst.instruction |= value;
|
||||
}
|
||||
|
||||
flags |= INST_IMMEDIATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
inst.error = _("Error: unrecognised syntax for second argument to msr instruction");
|
||||
return;
|
||||
}
|
||||
inst.instruction |= value;
|
||||
}
|
||||
|
||||
inst.error = NULL;
|
||||
inst.instruction |= flags;
|
||||
end_of_line (str);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Long Multiply Parser
|
||||
@@ -5241,7 +5296,7 @@ md_section_align (segment, size)
|
||||
/* ARGSUSED */
|
||||
symbolS *
|
||||
md_undefined_symbol (name)
|
||||
char * name;
|
||||
char * name ATTRIBUTE_UNUSED;
|
||||
{
|
||||
#ifdef OBJ_ELF
|
||||
if (name[0] == '_' && name[1] == 'G'
|
||||
@@ -5306,33 +5361,6 @@ arm_reg_parse (ccp)
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
static int
|
||||
arm_psr_parse (ccp)
|
||||
register char ** ccp;
|
||||
{
|
||||
char * start = * ccp;
|
||||
char c;
|
||||
char * p;
|
||||
CONST struct asm_psr * psr;
|
||||
|
||||
p = start;
|
||||
c = *p++;
|
||||
while (isalpha (c) || c == '_')
|
||||
c = *p++;
|
||||
|
||||
*--p = 0;
|
||||
psr = (CONST struct asm_psr *) hash_find (arm_psr_hsh, start);
|
||||
*p = c;
|
||||
|
||||
if (psr)
|
||||
{
|
||||
*ccp = p;
|
||||
return psr->number;
|
||||
}
|
||||
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
int
|
||||
md_apply_fix3 (fixP, val, seg)
|
||||
fixS * fixP;
|
||||
@@ -6411,7 +6439,7 @@ _("Warning: Use of the 'nv' conditional is deprecated\n"));
|
||||
* -m[arm]8[10] Arm 8 processors
|
||||
* -m[arm]9[20][tdmi] Arm 9 processors
|
||||
* -mstrongarm[110[0]] StrongARM processors
|
||||
* -m[arm]v[2345] Arm architectures
|
||||
* -m[arm]v[2345[t]] Arm architectures
|
||||
* -mall All (except the ARM1)
|
||||
* FP variants:
|
||||
* -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
2000-05-15 Nick Clifton <nickc@cygnus.com>
|
||||
|
||||
* gas/arm/arch4t.s: Add tests of new fields to msr instruction.
|
||||
|
||||
2000-05-11 Ulf Carlsson <ulfc@engr.sgi.com>
|
||||
|
||||
* gas/mips/mips.exp: Include *-*-linux* in svr4pic.
|
||||
|
||||
@@ -18,4 +18,18 @@ foo:
|
||||
|
||||
strh r2, bar
|
||||
strneh r3, [r3]
|
||||
|
||||
msr CPSR_f, #2
|
||||
msr CPSR_c, r3
|
||||
msr CPSR_x, r4
|
||||
msr CPSR_s, r5
|
||||
msr CPSR_f, r6
|
||||
msr CPSR_all, r7
|
||||
|
||||
msr SPSR_f, #4
|
||||
msr SPSR_c, r8
|
||||
msr SPSR_x, r9
|
||||
msr SPSR_s, r10
|
||||
msr SPSR_f, r11
|
||||
msr SPSR_all, r12
|
||||
bar:
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
2000-05-15 Nick Clifton <nickc@cygnus.com>
|
||||
|
||||
* arm-opc.h: Use upper case for flasg in MSR and MRS
|
||||
instructions. Allow any bit to be set in the field_mask of
|
||||
the MSR instruction.
|
||||
|
||||
* arm-dis.c (print_insn_arm): Decode _x and _s bits of the
|
||||
field_mask of an MSR instruction.
|
||||
|
||||
2000-05-11 Thomas de Lellis <tdel@windriver.com>
|
||||
|
||||
* arm-opc.c: Disassembly of thumb ldsb/ldsh
|
||||
|
||||
@@ -420,7 +420,7 @@ print_insn_arm (pc, info, given)
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
switch (given & 0x00090000)
|
||||
switch (given & 0x000f0000)
|
||||
{
|
||||
default:
|
||||
func (stream, "_???");
|
||||
@@ -429,10 +429,16 @@ print_insn_arm (pc, info, given)
|
||||
func (stream, "_all");
|
||||
break;
|
||||
case 0x10000:
|
||||
func (stream, "_ctl");
|
||||
func (stream, "_c");
|
||||
break;
|
||||
case 0x20000:
|
||||
func (stream, "_x");
|
||||
break;
|
||||
case 0x40000:
|
||||
func (stream, "_s");
|
||||
break;
|
||||
case 0x80000:
|
||||
func (stream, "_flg");
|
||||
func (stream, "_f");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Opcode table for the ARM.
|
||||
|
||||
Copyright 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
|
||||
Copyright 1994, 1995, 1996, 1997, 2000 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -93,8 +93,8 @@ static struct arm_opcode arm_opcodes[] =
|
||||
{0x00a00000, 0x0de00000, "adc%c%20's\t%12-15r, %16-19r, %o"},
|
||||
{0x00c00000, 0x0de00000, "sbc%c%20's\t%12-15r, %16-19r, %o"},
|
||||
{0x00e00000, 0x0de00000, "rsc%c%20's\t%12-15r, %16-19r, %o"},
|
||||
{0x0120f000, 0x0db6f000, "msr%c\t%22?scpsr%C, %o"},
|
||||
{0x010f0000, 0x0fbf0fff, "mrs%c\t%12-15r, %22?scpsr"},
|
||||
{0x0120f000, 0x0db0f000, "msr%c\t%22?SCPSR%C, %o"},
|
||||
{0x010f0000, 0x0fbf0fff, "mrs%c\t%12-15r, %22?SCPSR"},
|
||||
{0x01000000, 0x0de00000, "tst%c%p\t%16-19r, %o"},
|
||||
{0x01200000, 0x0de00000, "teq%c%p\t%16-19r, %o"},
|
||||
{0x01400000, 0x0de00000, "cmp%c%p\t%16-19r, %o"},
|
||||
@@ -164,7 +164,7 @@ static struct arm_opcode arm_opcodes[] =
|
||||
{0x0e000010, 0x0f100010, "mcr%c\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
|
||||
{0x0c000000, 0x0e100000, "stc%c%22'l\t%8-11d, cr%12-15d, %A"},
|
||||
{0x0c100000, 0x0e100000, "ldc%c%22'l\t%8-11d, cr%12-15d, %A"},
|
||||
|
||||
|
||||
/* The rest. */
|
||||
{0x00000000, 0x00000000, "undefined instruction %0-31x"},
|
||||
{0x00000000, 0x00000000, 0}
|
||||
|
||||
Reference in New Issue
Block a user