aboutsummaryrefslogtreecommitdiff
path: root/gas/config/tc-s390.c
diff options
context:
space:
mode:
Diffstat (limited to 'gas/config/tc-s390.c')
-rw-r--r--gas/config/tc-s390.c111
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)
{