diff options
Diffstat (limited to 'gas/config/tc-arc.c')
-rw-r--r-- | gas/config/tc-arc.c | 152 |
1 files changed, 117 insertions, 35 deletions
diff --git a/gas/config/tc-arc.c b/gas/config/tc-arc.c index 70886dd55e5..4e4dcb37df6 100644 --- a/gas/config/tc-arc.c +++ b/gas/config/tc-arc.c @@ -45,8 +45,8 @@ #define MAJOR_OPCODE(x) (((x) & 0xF8000000) >> 27) #define SUB_OPCODE(x) (((x) & 0x003F0000) >> 16) -#define LP_INSN(x) ((MAJOR_OPCODE (x) == 0x4) && \ - (SUB_OPCODE (x) == 0x28)) +#define LP_INSN(x) ((MAJOR_OPCODE (x) == 0x4) \ + && (SUB_OPCODE (x) == 0x28)) /* Equal to MAX_PRECISION in atof-ieee.c. */ #define MAX_LITTLENUMS 6 @@ -102,7 +102,8 @@ enum arc_rlx_types #define is_spfp_p(op) (((sc) == SPX)) #define is_dpfp_p(op) (((sc) == DPX)) #define is_fpuda_p(op) (((sc) == DPA)) -#define is_br_jmp_insn_p(op) (((op)->insn_class == BRANCH || (op)->insn_class == JUMP)) +#define is_br_jmp_insn_p(op) (((op)->insn_class == BRANCH \ + || (op)->insn_class == JUMP)) #define is_kernel_insn_p(op) (((op)->insn_class == KERNEL)) #define is_nps400_p(op) (((sc) == NPS400)) @@ -420,6 +421,9 @@ static struct hash_control *arc_reg_hash; /* The hash table of aux register symbols. */ static struct hash_control *arc_aux_hash; +/* The hash table of address types. */ +static struct hash_control *arc_addrtype_hash; + /* A table of CPU names and opcode sets. */ static const struct cpu_type { @@ -461,6 +465,12 @@ static const struct cpu_type /* Used to define a bracket as operand in tokens. */ #define O_bracket O_md32 +/* Used to define a colon as an operand in tokens. */ +#define O_colon O_md31 + +/* Used to define address types in nps400. */ +#define O_addrtype O_md30 + /* Dummy relocation, to be sorted out. */ #define DUMMY_RELOC_ARC_ENTRY (BFD_RELOC_UNUSED + 1) @@ -553,56 +563,56 @@ const relax_typeS md_relax_table[] = /* BL_S s13 -> BL s25. */ - RELAX_TABLE_ENTRY(13, 1, 2, ARC_RLX_BL), - RELAX_TABLE_ENTRY(25, 1, 4, ARC_RLX_NONE), + RELAX_TABLE_ENTRY (13, 1, 2, ARC_RLX_BL), + RELAX_TABLE_ENTRY (25, 1, 4, ARC_RLX_NONE), /* B_S s10 -> B s25. */ - RELAX_TABLE_ENTRY(10, 1, 2, ARC_RLX_B), - RELAX_TABLE_ENTRY(25, 1, 4, ARC_RLX_NONE), + RELAX_TABLE_ENTRY (10, 1, 2, ARC_RLX_B), + RELAX_TABLE_ENTRY (25, 1, 4, ARC_RLX_NONE), /* ADD_S c,b, u3 -> ADD<.f> a,b,u6 -> ADD<.f> a,b,limm. */ - RELAX_TABLE_ENTRY(3, 0, 2, ARC_RLX_ADD_U6), - RELAX_TABLE_ENTRY(6, 0, 4, ARC_RLX_ADD_LIMM), - RELAX_TABLE_ENTRY_MAX(0, 8, ARC_RLX_NONE), + RELAX_TABLE_ENTRY (3, 0, 2, ARC_RLX_ADD_U6), + RELAX_TABLE_ENTRY (6, 0, 4, ARC_RLX_ADD_LIMM), + RELAX_TABLE_ENTRY_MAX (0, 8, ARC_RLX_NONE), /* LD_S a, [b, u7] -> LD<zz><.x><.aa><.di> a, [b, s9] -> LD<zz><.x><.aa><.di> a, [b, limm] */ - RELAX_TABLE_ENTRY(7, 0, 2, ARC_RLX_LD_S9), - RELAX_TABLE_ENTRY(9, 1, 4, ARC_RLX_LD_LIMM), - RELAX_TABLE_ENTRY_MAX(1, 8, ARC_RLX_NONE), + RELAX_TABLE_ENTRY (7, 0, 2, ARC_RLX_LD_S9), + RELAX_TABLE_ENTRY (9, 1, 4, ARC_RLX_LD_LIMM), + RELAX_TABLE_ENTRY_MAX (1, 8, ARC_RLX_NONE), /* MOV_S b, u8 -> MOV<.f> b, s12 -> MOV<.f> b, limm. */ - RELAX_TABLE_ENTRY(8, 0, 2, ARC_RLX_MOV_S12), - RELAX_TABLE_ENTRY(8, 0, 4, ARC_RLX_MOV_LIMM), - RELAX_TABLE_ENTRY_MAX(0, 8, ARC_RLX_NONE), + RELAX_TABLE_ENTRY (8, 0, 2, ARC_RLX_MOV_S12), + RELAX_TABLE_ENTRY (8, 0, 4, ARC_RLX_MOV_LIMM), + RELAX_TABLE_ENTRY_MAX (0, 8, ARC_RLX_NONE), /* SUB_S c, b, u3 -> SUB<.f> a, b, u6 -> SUB<.f> a, b, limm. */ - RELAX_TABLE_ENTRY(3, 0, 2, ARC_RLX_SUB_U6), - RELAX_TABLE_ENTRY(6, 0, 4, ARC_RLX_SUB_LIMM), - RELAX_TABLE_ENTRY_MAX(0, 8, ARC_RLX_NONE), + RELAX_TABLE_ENTRY (3, 0, 2, ARC_RLX_SUB_U6), + RELAX_TABLE_ENTRY (6, 0, 4, ARC_RLX_SUB_LIMM), + RELAX_TABLE_ENTRY_MAX (0, 8, ARC_RLX_NONE), /* MPY<.f> a, b, u6 -> MPY<.f> a, b, limm. */ - RELAX_TABLE_ENTRY(6, 0, 4, ARC_RLX_MPY_LIMM), - RELAX_TABLE_ENTRY_MAX(0, 8, ARC_RLX_NONE), + RELAX_TABLE_ENTRY (6, 0, 4, ARC_RLX_MPY_LIMM), + RELAX_TABLE_ENTRY_MAX (0, 8, ARC_RLX_NONE), /* MOV<.f><.cc> b, u6 -> MOV<.f><.cc> b, limm. */ - RELAX_TABLE_ENTRY(6, 0, 4, ARC_RLX_MOV_RLIMM), - RELAX_TABLE_ENTRY_MAX(0, 8, ARC_RLX_NONE), + RELAX_TABLE_ENTRY (6, 0, 4, ARC_RLX_MOV_RLIMM), + RELAX_TABLE_ENTRY_MAX (0, 8, ARC_RLX_NONE), /* ADD<.f><.cc> b, b, u6 -> ADD<.f><.cc> b, b, limm. */ - RELAX_TABLE_ENTRY(6, 0, 4, ARC_RLX_ADD_RRLIMM), - RELAX_TABLE_ENTRY_MAX(0, 8, ARC_RLX_NONE), + RELAX_TABLE_ENTRY (6, 0, 4, ARC_RLX_ADD_RRLIMM), + RELAX_TABLE_ENTRY_MAX (0, 8, ARC_RLX_NONE), }; /* Order of this table's entries matters! */ @@ -979,6 +989,8 @@ debug_exp (expressionS *t) case O_logical_or: name = "O_logical_or"; break; case O_index: name = "O_index"; break; case O_bracket: name = "O_bracket"; break; + case O_colon: name = "O_colon"; break; + case O_addrtype: name = "O_addrtype"; break; } switch (t->X_md) @@ -1067,6 +1079,16 @@ tokenize_arguments (char *str, ++num_args; break; + case ':': + input_line_pointer++; + if (!saw_arg || num_args == ntok) + goto err; + tok->X_op = O_colon; + saw_arg = FALSE; + ++tok; + ++num_args; + break; + case '@': /* We have labels, function names and relocations, all starting with @ symbol. Sort them out. */ @@ -1693,8 +1715,7 @@ find_opcode_match (const struct arc_opcode_hash_entry *entry, const struct arc_operand *operand = &arc_operands[*opidx]; /* Only take input from real operands. */ - if ((operand->flags & ARC_OPERAND_FAKE) - && !(operand->flags & ARC_OPERAND_BRAKET)) + if (ARC_OPERAND_IS_FAKE (operand)) continue; /* When we expect input, make sure we have it. */ @@ -1704,6 +1725,12 @@ find_opcode_match (const struct arc_opcode_hash_entry *entry, /* Match operand type with expression type. */ switch (operand->flags & ARC_OPERAND_TYPECHECK_MASK) { + case ARC_OPERAND_ADDRTYPE: + /* Check to be an address type. */ + if (tok[tokidx].X_op != O_addrtype) + goto match_failed; + break; + case ARC_OPERAND_IR: /* Check to be a register. */ if ((tok[tokidx].X_op != O_register @@ -1755,6 +1782,12 @@ find_opcode_match (const struct arc_opcode_hash_entry *entry, goto match_failed; break; + case ARC_OPERAND_COLON: + /* Check if colon is also in opcode table as operand. */ + if (tok[tokidx].X_op != O_colon) + goto match_failed; + break; + case ARC_OPERAND_LIMM: case ARC_OPERAND_SIGNED: case ARC_OPERAND_UNSIGNED: @@ -2010,8 +2043,9 @@ pseudo_operand_match (const expressionS *tok, case O_symbol: /* Handle all symbols as long immediates or signed 9. */ - if (operand_real->flags & ARC_OPERAND_LIMM || - ((operand_real->flags & ARC_OPERAND_SIGNED) && operand_real->bits == 9)) + if (operand_real->flags & ARC_OPERAND_LIMM + || ((operand_real->flags & ARC_OPERAND_SIGNED) + && operand_real->bits == 9)) ret = TRUE; break; @@ -2094,8 +2128,8 @@ find_special_case_pseudo (const char *opname, operand_pseudo = &pseudo_insn->operand[i]; operand_real = &arc_operands[operand_pseudo->operand_idx]; - if (operand_real->flags & ARC_OPERAND_BRAKET && - !operand_pseudo->needs_insert) + if (operand_real->flags & ARC_OPERAND_BRAKET + && !operand_pseudo->needs_insert) continue; /* Has to be inserted (i.e. this token does not exist yet). */ @@ -2461,6 +2495,22 @@ declare_register_set (void) } } +/* Construct a symbol for an address type. */ + +static void +declare_addrtype (const char *name, int number) +{ + const char *err; + symbolS *addrtypeS = symbol_create (name, undefined_section, + number, &zero_address_frag); + + err = hash_insert (arc_addrtype_hash, S_GET_NAME (addrtypeS), + (void *) addrtypeS); + if (err) + as_fatal (_("Inserting \"%s\" into address type table failed: %s"), + name, err); +} + /* Port-specific assembler initialization. This function is called once, at assembler startup time. */ @@ -2575,6 +2625,28 @@ md_begin (void) as_fatal (_("internal error: can't hash aux register '%s': %s"), auxr->name, retval); } + + /* Address type declaration. */ + arc_addrtype_hash = hash_new (); + if (arc_addrtype_hash == NULL) + as_fatal (_("Virtual memory exhausted")); + + declare_addrtype ("bd", ARC_NPS400_ADDRTYPE_BD); + declare_addrtype ("jid", ARC_NPS400_ADDRTYPE_JID); + declare_addrtype ("lbd", ARC_NPS400_ADDRTYPE_LBD); + declare_addrtype ("mbd", ARC_NPS400_ADDRTYPE_MBD); + declare_addrtype ("sd", ARC_NPS400_ADDRTYPE_SD); + declare_addrtype ("sm", ARC_NPS400_ADDRTYPE_SM); + declare_addrtype ("xa", ARC_NPS400_ADDRTYPE_XA); + declare_addrtype ("xd", ARC_NPS400_ADDRTYPE_XD); + declare_addrtype ("cd", ARC_NPS400_ADDRTYPE_CD); + declare_addrtype ("cbd", ARC_NPS400_ADDRTYPE_CBD); + declare_addrtype ("cjid", ARC_NPS400_ADDRTYPE_CJID); + declare_addrtype ("clbd", ARC_NPS400_ADDRTYPE_CLBD); + declare_addrtype ("cm", ARC_NPS400_ADDRTYPE_CM); + declare_addrtype ("csd", ARC_NPS400_ADDRTYPE_CSD); + declare_addrtype ("cxa", ARC_NPS400_ADDRTYPE_CXA); + declare_addrtype ("cxd", ARC_NPS400_ADDRTYPE_CXD); } /* Write a value out to the object file, using the appropriate @@ -3254,7 +3326,7 @@ arc_parse_name (const char *name, if (!assembling_insn) return FALSE; - /* Handle only registers. */ + /* Handle only registers and address types. */ if (e->X_op != O_absent) return FALSE; @@ -3265,6 +3337,15 @@ arc_parse_name (const char *name, e->X_add_number = S_GET_VALUE (sym); return TRUE; } + + sym = hash_find (arc_addrtype_hash, name); + if (sym) + { + e->X_op = O_addrtype; + e->X_add_number = S_GET_VALUE (sym); + return TRUE; + } + return FALSE; } @@ -3726,8 +3807,7 @@ assemble_insn (const struct arc_opcode *opcode, const struct arc_operand *operand = &arc_operands[*argidx]; const expressionS *t = (const expressionS *) 0; - if ((operand->flags & ARC_OPERAND_FAKE) - && !(operand->flags & ARC_OPERAND_BRAKET)) + if (ARC_OPERAND_IS_FAKE (operand)) continue; if (operand->flags & ARC_OPERAND_DUPLICATE) @@ -3764,7 +3844,9 @@ assemble_insn (const struct arc_opcode *opcode, break; case O_bracket: - /* Ignore brackets. */ + case O_colon: + case O_addrtype: + /* Ignore brackets, colons, and address types. */ break; case O_absent: |