X-Git-Url: https://oss.titaniummirror.com/gitweb?p=msp430-binutils.git;a=blobdiff_plain;f=gas%2Fconfig%2Ftc-hppa.c;fp=gas%2Fconfig%2Ftc-hppa.c;h=371f9f06dcdc95d3ed6d362d364e07e01f7f34a6;hp=05c7f12375a5d8a29ba79b7ea36854e190b89ff2;hb=d5da4f291af551c0b8b79e1d4a9b173d60e5c10e;hpb=7b5ea4fcdf2819e070665ab5610f8b48e3867c10 diff --git a/gas/config/tc-hppa.c b/gas/config/tc-hppa.c index 05c7f12..371f9f0 100644 --- a/gas/config/tc-hppa.c +++ b/gas/config/tc-hppa.c @@ -1,6 +1,6 @@ /* tc-hppa.c -- Assemble for the PA - Copyright 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + Copyright 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, + 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -583,8 +583,8 @@ const char EXP_CHARS[] = "eE"; As in 0f12.456 or 0d1.2345e12. Be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be - changed in read.c. Ideally it shouldn't hae to know abou it at - all, but nothing is ideal around here. */ + changed in read.c. Ideally it shouldn't have to know about it + at all, but nothing is ideal around here. */ const char FLT_CHARS[] = "rRsSfFdDxXpP"; static struct pa_it the_insn; @@ -948,8 +948,8 @@ static const struct selector_entry selector_table[] = #ifdef OBJ_SOM /* default space and subspace dictionaries */ -#define GDB_SYMBOLS GDB_SYMBOLS_SUBSPACE_NAME -#define GDB_STRINGS GDB_STRINGS_SUBSPACE_NAME +#define GDB_SYMBOLS GDB_SYMBOLS_SUBSPACE_NAME +#define GDB_STRINGS GDB_STRINGS_SUBSPACE_NAME /* pre-defined subsegments (subspaces) for the HPPA. */ #define SUBSEG_CODE 0 @@ -995,6 +995,19 @@ static struct default_space_dict pa_def_spaces[] = #define IS_R_SELECT(S) (*(S) == 'R' || *(S) == 'r') #define IS_L_SELECT(S) (*(S) == 'L' || *(S) == 'l') +/* Store immediate values of shift/deposit/extract functions. */ + +#define SAVE_IMMEDIATE(VALUE) \ + { \ + if (immediate_check) \ + { \ + if (pos == -1) \ + pos = (VALUE); \ + else if (len == -1) \ + len = (VALUE); \ + } \ + } + /* Insert FIELD into OPCODE starting at bit START. Continue pa_ip main loop after insertion. */ @@ -1012,9 +1025,9 @@ static struct default_space_dict pa_def_spaces[] = if ((FIELD) > (HIGH) || (FIELD) < (LOW)) \ { \ if (! IGNORE) \ - as_bad (_("Field out of range [%d..%d] (%d)."), (LOW), (HIGH), \ + as_bad (_("Field out of range [%d..%d] (%d)."), (LOW), (HIGH), \ (int) (FIELD));\ - break; \ + break; \ } \ } @@ -1025,10 +1038,10 @@ static struct default_space_dict pa_def_spaces[] = { \ if ((FIELD) > (HIGH) || (FIELD) < (LOW)) \ { \ - as_bad_where ((FILENAME), (LINE), \ + as_bad_where ((FILENAME), (LINE), \ _("Field out of range [%d..%d] (%d)."), (LOW), (HIGH), \ (int) (FIELD));\ - break; \ + break; \ } \ } @@ -1040,9 +1053,9 @@ static struct default_space_dict pa_def_spaces[] = if ((FIELD) & ((ALIGN) - 1)) \ { \ if (! IGNORE) \ - as_bad (_("Field not properly aligned [%d] (%d)."), (ALIGN), \ + as_bad (_("Field not properly aligned [%d] (%d)."), (ALIGN), \ (int) (FIELD));\ - break; \ + break; \ } \ } @@ -1050,6 +1063,10 @@ static struct default_space_dict pa_def_spaces[] = ((exp).X_op == O_subtract \ && strcmp (S_GET_NAME ((exp).X_op_symbol), "$global$") == 0) +#define is_SB_relative(exp) \ + ((exp).X_op == O_subtract \ + && strcmp (S_GET_NAME ((exp).X_op_symbol), "$segrel$") == 0) + #define is_PC_relative(exp) \ ((exp).X_op == O_subtract \ && strcmp (S_GET_NAME ((exp).X_op_symbol), "$PIC_pcrel$0") == 0) @@ -1233,6 +1250,7 @@ fix_new_hppa (fragS *frag, it now so as not to confuse write.c. Ditto for $PIC_pcrel$0. */ if (new_fix->fx_subsy && (strcmp (S_GET_NAME (new_fix->fx_subsy), "$global$") == 0 + || strcmp (S_GET_NAME (new_fix->fx_subsy), "$segrel$") == 0 || strcmp (S_GET_NAME (new_fix->fx_subsy), "$PIC_pcrel$0") == 0 || strcmp (S_GET_NAME (new_fix->fx_subsy), "$tls_gdidx$") == 0 || strcmp (S_GET_NAME (new_fix->fx_subsy), "$tls_ldidx$") == 0 @@ -1256,6 +1274,8 @@ cons_fix_new_hppa (fragS *frag, int where, int size, expressionS *exp) else if (is_PC_relative (*exp)) rel_type = R_HPPA_PCREL_CALL; #ifdef OBJ_ELF + else if (is_SB_relative (*exp)) + rel_type = R_PARISC_SEGREL32; else if (is_tls_gdidx (*exp)) rel_type = R_PARISC_TLS_GD21L; else if (is_tls_ldidx (*exp)) @@ -1335,61 +1355,10 @@ pa_parse_nullif (char **s) return nullif; } -/* Turn a string in input_line_pointer into a floating point constant of type - type, and store the appropriate bytes in *litP. The number of LITTLENUMS - emitted is stored in *sizeP . An error message or NULL is returned. */ - -#define MAX_LITTLENUMS 6 - char * md_atof (int type, char *litP, int *sizeP) { - int prec; - LITTLENUM_TYPE words[MAX_LITTLENUMS]; - LITTLENUM_TYPE *wordP; - char *t; - - switch (type) - { - - case 'f': - case 'F': - case 's': - case 'S': - prec = 2; - break; - - case 'd': - case 'D': - case 'r': - case 'R': - prec = 4; - break; - - case 'x': - case 'X': - prec = 6; - break; - - case 'p': - case 'P': - prec = 6; - break; - - default: - *sizeP = 0; - return _("Bad call to MD_ATOF()"); - } - t = atof_ieee (input_line_pointer, type, words); - if (t) - input_line_pointer = t; - *sizeP = prec * sizeof (LITTLENUM_TYPE); - for (wordP = words; prec--;) - { - md_number_to_chars (litP, (valueT) (*wordP++), sizeof (LITTLENUM_TYPE)); - litP += sizeof (LITTLENUM_TYPE); - } - return NULL; + return ieee_md_atof (type, litP, sizeP, TRUE); } /* Write out big-endian. */ @@ -1419,13 +1388,25 @@ tc_gen_reloc (asection *section, fixS *fixp) if (fixp->fx_addsy == 0) return &no_relocs; - assert (hppa_fixp != 0); - assert (section != 0); + gas_assert (hppa_fixp != 0); + gas_assert (section != 0); reloc = xmalloc (sizeof (arelent)); reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); + + /* Allow fixup_segment to recognize hand-written pc-relative relocations. + When we went through cons_fix_new_hppa, we classified them as complex. */ + /* ??? It might be better to hide this +8 stuff in tc_cfi_emit_pcrel_expr, + undefine DIFF_EXPR_OK, and let these sorts of complex expressions fail + when R_HPPA_COMPLEX == R_PARISC_UNIMPLEMENTED. */ + if (fixp->fx_r_type == R_HPPA_COMPLEX && fixp->fx_pcrel) + { + fixp->fx_r_type = R_HPPA_PCREL_CALL; + fixp->fx_offset += 8; + } + codes = hppa_gen_reloc_type (stdoutput, fixp->fx_r_type, hppa_fixp->fx_r_format, @@ -1453,7 +1434,7 @@ tc_gen_reloc (asection *section, fixS *fixp) switch (fixp->fx_r_type) { default: - assert (n_relocs == 1); + gas_assert (n_relocs == 1); code = *codes[0]; @@ -1507,7 +1488,7 @@ tc_gen_reloc (asection *section, fixS *fixp) (bfd_reloc_code_real_type) code); reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; - assert (reloc->howto && (unsigned int) code == reloc->howto->type); + gas_assert (reloc->howto && (unsigned int) code == reloc->howto->type); break; } #else /* OBJ_SOM */ @@ -1530,7 +1511,7 @@ tc_gen_reloc (asection *section, fixS *fixp) /* The only time we ever use a R_COMP2 fixup is for the difference of two symbols. With that in mind we fill in all four relocs now and break out of the loop. */ - assert (i == 1); + gas_assert (i == 1); relocs[0]->sym_ptr_ptr = (asymbol **) bfd_abs_section_ptr->symbol_ptr_ptr; relocs[0]->howto @@ -1997,7 +1978,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) case R_PARISC_TLS_LE14R: case R_PARISC_TLS_IE21L: case R_PARISC_TLS_IE14R: - if (fixP->fx_addsy) + if (fixP->fx_addsy) S_SET_THREAD_LOCAL (fixP->fx_addsy); break; default: @@ -2150,8 +2131,8 @@ pa_parse_number (char **s, int is_float) p++; c = *p; /* Tege hack: Special case for general registers as the general - code makes a binary search with case translation, and is VERY - slow. */ + code makes a binary search with case translation, and is VERY + slow. */ if (c == 'r') { p++; @@ -2206,7 +2187,7 @@ pa_parse_number (char **s, int is_float) else { /* And finally, it could be a symbol in the absolute section which - is effectively a constant, or a register alias symbol. */ + is effectively a constant, or a register alias symbol. */ name = p; c = *p; while (is_part_of_name (c)) @@ -2717,7 +2698,7 @@ pa_parse_nonneg_cmpsub_cmpltr (char **s) cmpltr = 7; } /* If we have something like addb,n then there is no condition - completer. */ + completer. */ else if (strcasecmp (name, "n") == 0) { cmpltr = 0; @@ -2791,7 +2772,7 @@ pa_parse_neg_cmpsub_cmpltr (char **s) cmpltr = 7; } /* If we have something like addb,n then there is no condition - completer. */ + completer. */ else if (strcasecmp (name, "n") == 0) { cmpltr = 0; @@ -3017,7 +2998,7 @@ pa_parse_nonneg_add_cmpltr (char **s) cmpltr = 7; } /* If we have something like addb,n then there is no condition - completer. */ + completer. */ else if (strcasecmp (name, "n") == 0) { cmpltr = 0; @@ -3090,7 +3071,7 @@ pa_parse_neg_add_cmpltr (char **s) cmpltr = 7; } /* If we have something like addb,n then there is no condition - completer. */ + completer. */ else if (strcasecmp (name, "n") == 0) { cmpltr = 0; @@ -3191,7 +3172,7 @@ pa_parse_addb_64_cmpltr (char **s) cmpltr = 15; } /* If we have something like addb,n then there is no condition - completer. */ + completer. */ else if (strcasecmp (name, "n") == 0) { cmpltr = 0; @@ -3223,6 +3204,7 @@ pa_ip (char *str) int match = FALSE; int comma = 0; int cmpltr, nullif, flag, cond, num; + int immediate_check = 0, pos = -1, len = -1; unsigned long opcode; struct pa_opcode *insn; @@ -3262,10 +3244,10 @@ pa_ip (char *str) return; } - /* Look up the opcode in the has table. */ + /* Look up the opcode in the hash table. */ if ((insn = (struct pa_opcode *) hash_find (op_hash, str)) == NULL) { - as_bad ("Unknown opcode: `%s'", str); + as_bad (_("Unknown opcode: `%s'"), str); return; } @@ -3289,7 +3271,7 @@ pa_ip (char *str) goto failed; /* Build the opcode, checking as we go to make - sure that the operands match. */ + sure that the operands match. */ for (args = insn->args;; ++args) { /* Absorb white space in instruction. */ @@ -3340,12 +3322,12 @@ pa_ip (char *str) s = s + 1; if (!strncasecmp (s, "%sar", 4)) - { + { s += 4; continue; } else if (!strncasecmp (s, "%cr11", 5)) - { + { s += 5; continue; } @@ -3383,6 +3365,7 @@ pa_ip (char *str) break; s = expr_end; CHECK_FIELD (num, 32, 1, 0); + SAVE_IMMEDIATE(num); INSERT_FIELD_AND_CONTINUE (opcode, 32 - num, 0); /* Handle a 5 bit immediate at 15. */ @@ -3549,7 +3532,7 @@ pa_ip (char *str) } else if (*args == 'J') { - /* M bit is explicit in the major opcode. */ + /* M bit is explicit in the major opcode. */ INSERT_FIELD_AND_CONTINUE (opcode, a, 2); } else if (*args == 'e') @@ -3941,7 +3924,7 @@ pa_ip (char *str) permloc[2] = 8; permloc[3] = 6; for (; i < 4; i++) - { + { switch (*s++) { case '0': @@ -4365,6 +4348,9 @@ pa_ip (char *str) case 'x': case 'y': cmpltr = 0; + /* Check immediate values in shift/extract/deposit + * instructions if they will give undefined behaviour. */ + immediate_check = 1; if (*s == ',') { save_s = s++; @@ -5116,7 +5102,7 @@ pa_ip (char *str) continue; } else - break; + break; /* Handle '%sr0,%r31' implicit operand of be,l instruction. */ case 'Y': @@ -5157,6 +5143,7 @@ pa_ip (char *str) break; s = expr_end; CHECK_FIELD (num, 31, 0, strict); + SAVE_IMMEDIATE(num); INSERT_FIELD_AND_CONTINUE (opcode, 31 - num, 5); /* Handle a 6 bit shift count at 20,22:26. */ @@ -5166,6 +5153,7 @@ pa_ip (char *str) break; s = expr_end; CHECK_FIELD (num, 63, 0, strict); + SAVE_IMMEDIATE(num); num = 63 - num; opcode |= (num & 0x20) << 6; INSERT_FIELD_AND_CONTINUE (opcode, num & 0x1f, 5); @@ -5178,6 +5166,7 @@ pa_ip (char *str) break; s = expr_end; CHECK_FIELD (num, 64, 1, strict); + SAVE_IMMEDIATE(num); num--; opcode |= (num & 0x20) << 3; num = 31 - (num & 0x1f); @@ -5190,6 +5179,7 @@ pa_ip (char *str) break; s = expr_end; CHECK_FIELD (num, 64, 1, strict); + SAVE_IMMEDIATE(num); num--; opcode |= (num & 0x20) << 7; num = 31 - (num & 0x1f); @@ -5202,6 +5192,7 @@ pa_ip (char *str) break; s = expr_end; CHECK_FIELD (num, 31, 0, strict); + SAVE_IMMEDIATE(num); INSERT_FIELD_AND_CONTINUE (opcode, num, 5); /* Handle a 6 bit bit position at 20,22:26. */ @@ -5211,6 +5202,7 @@ pa_ip (char *str) break; s = expr_end; CHECK_FIELD (num, 63, 0, strict); + SAVE_IMMEDIATE(num); opcode |= (num & 0x20) << 6; INSERT_FIELD_AND_CONTINUE (opcode, num & 0x1f, 5); @@ -5453,7 +5445,7 @@ pa_ip (char *str) /* Handle all floating point registers. */ case 'f': switch (*++args) - { + { /* Float target register. */ case 't': if (!pa_parse_number (&s, 3)) @@ -5581,13 +5573,13 @@ pa_ip (char *str) CHECK_FIELD (num, 31, 0, 0); if (the_insn.fpof1 == SGL) { - if (num < 16) - { + if (num < 16) + { as_bad (_("Invalid register for single precision fmpyadd or fmpysub")); break; - } - num &= 0xF; - num |= (pa_number & FP_REG_RSEL ? 1 << 4 : 0); + } + num &= 0xF; + num |= (pa_number & FP_REG_RSEL ? 1 << 4 : 0); } INSERT_FIELD_AND_CONTINUE (opcode, num, 16); } @@ -5601,13 +5593,13 @@ pa_ip (char *str) CHECK_FIELD (num, 31, 0, 0); if (the_insn.fpof1 == SGL) { - if (num < 16) - { + if (num < 16) + { as_bad (_("Invalid register for single precision fmpyadd or fmpysub")); break; - } - num &= 0xF; - num |= (pa_number & FP_REG_RSEL ? 1 << 4 : 0); + } + num &= 0xF; + num |= (pa_number & FP_REG_RSEL ? 1 << 4 : 0); } INSERT_FIELD_AND_CONTINUE (opcode, num, 0); } @@ -5621,13 +5613,13 @@ pa_ip (char *str) CHECK_FIELD (num, 31, 0, 0); if (the_insn.fpof1 == SGL) { - if (num < 16) - { + if (num < 16) + { as_bad (_("Invalid register for single precision fmpyadd or fmpysub")); break; - } - num &= 0xF; - num |= (pa_number & FP_REG_RSEL ? 1 << 4 : 0); + } + num &= 0xF; + num |= (pa_number & FP_REG_RSEL ? 1 << 4 : 0); } INSERT_FIELD_AND_CONTINUE (opcode, num, 6); } @@ -5641,13 +5633,13 @@ pa_ip (char *str) CHECK_FIELD (num, 31, 0, 0); if (the_insn.fpof1 == SGL) { - if (num < 16) - { + if (num < 16) + { as_bad (_("Invalid register for single precision fmpyadd or fmpysub")); break; - } - num &= 0xF; - num |= (pa_number & FP_REG_RSEL ? 1 << 4 : 0); + } + num &= 0xF; + num |= (pa_number & FP_REG_RSEL ? 1 << 4 : 0); } INSERT_FIELD_AND_CONTINUE (opcode, num, 11); } @@ -5718,6 +5710,13 @@ pa_ip (char *str) break; } + if (immediate_check) + { + if (pos != -1 && len != -1 && pos < len - 1) + as_warn (_("Immediates %d and %d will give undefined behavior."), + pos, len); + } + the_insn.opcode = opcode; } @@ -5729,7 +5728,7 @@ md_assemble (char *str) char *to; /* The had better be something to assemble. */ - assert (str); + gas_assert (str); /* If we are within a procedure definition, make sure we've defined a label for the procedure; handle case where the @@ -5949,24 +5948,6 @@ pa_call (int unused ATTRIBUTE_UNUSED) demand_empty_rest_of_line (); } -/* Return TRUE if FRAG1 and FRAG2 are the same. */ - -static bfd_boolean -is_same_frag (fragS *frag1, fragS *frag2) -{ - - if (frag1 == NULL) - return FALSE; - else if (frag2 == NULL) - return FALSE; - else if (frag1 == frag2) - return TRUE; - else if (frag2->fr_type == rs_fill && frag2->fr_fix == 0) - return (is_same_frag (frag1, frag2->fr_next)); - else - return FALSE; -} - #ifdef OBJ_ELF /* Build an entry in the UNWIND subspace from the given function attributes in CALL_INFO. This is not needed for SOM as using @@ -6148,7 +6129,7 @@ pa_callinfo (int unused ATTRIBUTE_UNUSED) last_call_info->ci_unwind.descriptor.save_sp = 1; } /* Is this an unwindable procedure. If so mark it so - in the unwind descriptor. */ + in the unwind descriptor. */ else if ((strncasecmp (name, "no_unwind", 9) == 0)) { p = input_line_pointer; @@ -6156,7 +6137,7 @@ pa_callinfo (int unused ATTRIBUTE_UNUSED) last_call_info->ci_unwind.descriptor.cannot_unwind = 1; } /* Is this an interrupt routine. If so mark it in the - unwind descriptor. */ + unwind descriptor. */ else if ((strncasecmp (name, "hpux_int", 7) == 0)) { p = input_line_pointer; @@ -6217,7 +6198,7 @@ pa_data (int unused ATTRIBUTE_UNUSED) } /* This is different than the standard GAS s_comm(). On HP9000/800 machines, - the .comm pseudo-op has the following symtax: + the .comm pseudo-op has the following syntax: