diff options
Diffstat (limited to 'gas/config/tc-s390.c')
-rw-r--r-- | gas/config/tc-s390.c | 111 |
1 files changed, 82 insertions, 29 deletions
diff --git a/gas/config/tc-s390.c b/gas/config/tc-s390.c index b846134..b073d8e 100644 --- a/gas/config/tc-s390.c +++ b/gas/config/tc-s390.c @@ -24,6 +24,8 @@ #include "subsegs.h" #include "dwarf2dbg.h" #include "dw2gencfi.h" +#include "sframe.h" +#include "gen-sframe.h" #include "opcode/s390.h" #include "elf/s390.h" @@ -97,6 +99,17 @@ const char FLT_CHARS[] = "dD"; /* The dwarf2 data alignment, adjusted for 32 or 64 bit. */ int s390_cie_data_alignment; +/* Register numbers used for SFrame stack trace info. */ + +/* Designated stack pointer DWARF register number according to s390x ELF ABI. */ +const unsigned int s390_sframe_cfa_sp_reg = 15; + +/* Preferred frame pointer DWARF register number according to s390x ELF ABI. */ +const unsigned int s390_sframe_cfa_fp_reg = 11; + +/* Designated return address DWARF register number according to s390x ELF ABI. */ +const unsigned int s390_sframe_cfa_ra_reg = DWARF2_DEFAULT_RETURN_COLUMN; + /* The target specific pseudo-ops which we support. */ /* Define the prototypes for the pseudo-ops */ @@ -727,9 +740,9 @@ s390_insert_operand (unsigned char *insn, { if (operand->flags & S390_OPERAND_PCREL) { - val = (offsetT) ((addressT) val << 1); - min = (offsetT) ((addressT) min << 1); - max = (offsetT) ((addressT) max << 1); + val = (addressT) val << 1; + min = (addressT) min << 1; + max = (addressT) max << 1; } s390_bad_operand_out_of_range (operand_number, val, min, max, @@ -738,7 +751,7 @@ s390_insert_operand (unsigned char *insn, return; } /* val is ok, now restrict it to operand->bits bits. */ - uval = (addressT) val & ((((addressT) 1 << (operand->bits-1)) << 1) - 1); + uval = val & ((((addressT) 1 << (operand->bits-1)) << 1) - 1); /* val is restrict, now check for special case. */ if (operand->bits == 20 && operand->shift == 20) uval = (uval >> 12) | ((uval & 0xfff) << 8); @@ -748,8 +761,8 @@ s390_insert_operand (unsigned char *insn, addressT min, max; max = (((addressT) 1 << (operand->bits - 1)) << 1) - 1; - min = (offsetT) 0; - uval = (addressT) val; + min = 0; + uval = val; /* Vector register operands have an additional bit in the RXB field. */ @@ -1316,7 +1329,7 @@ s390_elf_cons (int nbytes /* 1=.byte, 2=.word, 4=.long */) as_bad (_("relocation not applicable")); } else - emit_expr (&exp, (unsigned int) nbytes); + emit_expr (&exp, nbytes); } while (*input_line_pointer++ == ','); @@ -1906,8 +1919,7 @@ md_gather_operands (char *str, fixP = fix_new_exp (frag_now, f - frag_now->fr_literal, 4, &fixups[i].exp, (operand->flags & S390_OPERAND_PCREL) != 0, - ((bfd_reloc_code_real_type) - (fixups[i].opindex + (int) BFD_RELOC_UNUSED))); + fixups[i].opindex + BFD_RELOC_UNUSED); /* s390_insert_operand () does the range checking. */ if (operand->flags & S390_OPERAND_PCREL) fixP->fx_no_overflow = 1; @@ -1931,8 +1943,8 @@ md_assemble (char *str) *s++ = '\0'; /* Look up the opcode in the hash table. */ - opcode = (struct s390_opcode *) str_hash_find (s390_opcode_hash, str); - if (opcode == (const struct s390_opcode *) NULL) + opcode = str_hash_find (s390_opcode_hash, str); + if (opcode == NULL) { as_bad (_("Unrecognized opcode: `%s'"), str); return; @@ -1988,9 +2000,8 @@ s390_insn (int ignore ATTRIBUTE_UNUSED) *s++ = '\0'; /* Look up the opcode in the hash table. */ - opformat = (struct s390_opcode *) - str_hash_find (s390_opformat_hash, input_line_pointer); - if (opformat == (const struct s390_opcode *) NULL) + opformat = str_hash_find (s390_opformat_hash, input_line_pointer); + if (opformat == NULL) { as_bad (_("Unrecognized opcode format: `%s'"), input_line_pointer); return; @@ -2085,7 +2096,7 @@ s390_literals (int ignore ATTRIBUTE_UNUSED) /* Emit symbol for start of literal pool. */ S_SET_SEGMENT (lp_sym, now_seg); - S_SET_VALUE (lp_sym, (valueT) frag_now_fix ()); + S_SET_VALUE (lp_sym, frag_now_fix ()); symbol_set_frag (lp_sym, frag_now); while (lpe_list) @@ -2093,7 +2104,7 @@ s390_literals (int ignore ATTRIBUTE_UNUSED) lpe = lpe_list; lpe_list = lpe_list->next; S_SET_SEGMENT (lpe->sym, now_seg); - S_SET_VALUE (lpe->sym, (valueT) frag_now_fix ()); + S_SET_VALUE (lpe->sym, frag_now_fix ()); symbol_set_frag (lpe->sym, frag_now); /* Emit literal pool entry. */ @@ -2491,19 +2502,19 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) else fixP->fx_done = 1; - if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED) + if (fixP->fx_r_type >= BFD_RELOC_UNUSED) { const struct s390_operand *operand; int opindex; - opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED; + opindex = fixP->fx_r_type - BFD_RELOC_UNUSED; operand = &s390_operands[opindex]; if (fixP->fx_done) { /* Insert the fully resolved operand value. */ s390_insert_operand ((unsigned char *) where, operand, - (offsetT) value, fixP->fx_file, fixP->fx_line, 0); + value, fixP->fx_file, fixP->fx_line, 0); return; } @@ -2632,9 +2643,9 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) if (fixP->fx_pcrel) value >>= 1; - mop = bfd_getb16 ((unsigned char *) where); - mop |= (unsigned short) (value & 0xfff); - bfd_putb16 ((bfd_vma) mop, (unsigned char *) where); + mop = bfd_getb16 (where); + mop |= value & 0xfff; + bfd_putb16 (mop, where); } break; @@ -2644,10 +2655,10 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) if (fixP->fx_done) { unsigned int mop; - mop = bfd_getb32 ((unsigned char *) where); - mop |= (unsigned int) ((value & 0xfff) << 8 | - (value & 0xff000) >> 12); - bfd_putb32 ((bfd_vma) mop, (unsigned char *) where); + mop = bfd_getb32 (where); + mop |= ((value & 0xfff) << 8 + | (value & 0xff000) >> 12); + bfd_putb32 (mop, where); } break; @@ -2687,9 +2698,9 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) unsigned int mop; value >>= 1; - mop = bfd_getb32 ((unsigned char *) where - 1); - mop |= (unsigned int) (value & 0xffffff); - bfd_putb32 ((bfd_vma) mop, (unsigned char *) where - 1); + mop = bfd_getb32 (where - 1); + mop |= value & 0xffffff; + bfd_putb32 (mop, where - 1); } break; @@ -2867,6 +2878,48 @@ tc_s390_regname_to_dw2regnum (char *regname) return regnum; } +/* Whether SFrame stack trace info is supported. */ + +bool +s390_support_sframe_p (void) +{ + /* At this time, SFrame is supported for s390x (64-bit) only. */ + return (s390_arch_size == 64); +} + +/* Specify if RA tracking is needed. */ + +bool +s390_sframe_ra_tracking_p (void) +{ + return true; +} + +/* Specify the fixed offset to recover RA from CFA. + (useful only when RA tracking is not needed). */ + +offsetT +s390_sframe_cfa_ra_offset (void) +{ + return (offsetT) SFRAME_CFA_FIXED_RA_INVALID; +} + +/* Get the abi/arch identifier for SFrame. */ + +unsigned char +s390_sframe_get_abi_arch (void) +{ + unsigned char sframe_abi_arch = 0; + + if (s390_support_sframe_p ()) + { + gas_assert (target_big_endian); + sframe_abi_arch = SFRAME_ABI_S390X_ENDIAN_BIG; + } + + return sframe_abi_arch; +} + void s390_elf_final_processing (void) { |