diff options
-rw-r--r-- | gas/ChangeLog | 16 | ||||
-rw-r--r-- | gas/config/tc-arm.c | 304 | ||||
-rw-r--r-- | gas/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gas/testsuite/gas/arm/arch4t.s | 14 | ||||
-rw-r--r-- | opcodes/ChangeLog | 9 | ||||
-rw-r--r-- | opcodes/arm-dis.c | 12 | ||||
-rw-r--r-- | opcodes/arm-opc.h | 8 |
7 files changed, 222 insertions, 145 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index a1d76a9..439deda 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -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 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 diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index e121ed4..5e0f39b 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -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. diff --git a/gas/testsuite/gas/arm/arch4t.s b/gas/testsuite/gas/arm/arch4t.s index 8d28f7f..417b3c6 100644 --- a/gas/testsuite/gas/arm/arch4t.s +++ b/gas/testsuite/gas/arm/arch4t.s @@ -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: diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index c183c60..199e30f 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -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 diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c index f131ada..a3e7112 100644 --- a/opcodes/arm-dis.c +++ b/opcodes/arm-dis.c @@ -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; diff --git a/opcodes/arm-opc.h b/opcodes/arm-opc.h index 8beb65f..5ecde4b 100644 --- a/opcodes/arm-opc.h +++ b/opcodes/arm-opc.h @@ -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} |