diff options
author | Nick Clifton <nickc@redhat.com> | 2000-05-15 19:25:22 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2000-05-15 19:25:22 +0000 |
commit | 322f2c4579460de0fe10c89e9cd45588ae57b730 (patch) | |
tree | ebbb4a70bee123cdda0196ba5f6b838e1a4c60ba /gas/config | |
parent | 47cf603ed45d09dceda47b6da42a1d88a141ad82 (diff) | |
download | gdb-322f2c4579460de0fe10c89e9cd45588ae57b730.zip gdb-322f2c4579460de0fe10c89e9cd45588ae57b730.tar.gz gdb-322f2c4579460de0fe10c89e9cd45588ae57b730.tar.bz2 |
Add support for _x and _s flags to MSR instruction
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/tc-arm.c | 304 |
1 files changed, 166 insertions, 138 deletions
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 109de30..4c71976 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -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 CONST struct asm_psr * +arm_psr_parse (ccp) + register char ** ccp; +{ + 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 + { + 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, cpsr, spsr) +psr_required_here (str) char ** str; - int cpsr; - int spsr; { - int psr; char * start = *str; - psr = arm_psr_parse (str); + CONST struct asm_psr * psr; - if (psr == cpsr || psr == spsr) + psr = arm_psr_parse (str); + + if (psr) { - if (psr == spsr) - inst.instruction |= 1 << 22; + /* 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 - { - inst.error = BAD_ARGS; - return; - } + unsigned value = validate_immediate (inst.reloc.exp.X_add_number); - if (skip_past_comma (&str) == FAIL) + if (value == (unsigned) FAIL) { - inst.error = BAD_ARGS; + inst.error = _("Invalid constant"); 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 |