From a72d6b4e2a3250dc8f9bf3f452d5caf2d63fd7a3 Mon Sep 17 00:00:00 2001 From: Christian Groessler Date: Sat, 4 Oct 2003 21:11:05 +0000 Subject: [PATCH] 2003-10-04 Christian Groessler * tc-z8k.c (newfix): Tell fix_new_exp about pc relativeness. (md_apply_fix3): Fix R_JR, R_DISP7, and R_CALLR cases. (md_pcrel_from): This function now gets called. Supply return value. --- gas/ChangeLog | 7 +++++ gas/config/tc-z8k.c | 62 +++++++++++++++++++++++++++++++++++++-------- 2 files changed, 59 insertions(+), 10 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index dc034effda8..6563dff0dd3 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,10 @@ +2003-10-04 Christian Groessler + + * tc-z8k.c (newfix): Tell fix_new_exp about pc relativeness. + (md_apply_fix3): Fix R_JR, R_DISP7, and R_CALLR cases. + (md_pcrel_from): This function now gets called. Supply return + value. + 2003-10-04 Nick Clifton * as.c: Convert to ISO C90. diff --git a/gas/config/tc-z8k.c b/gas/config/tc-z8k.c index 451cb8a1eda..bab6012d3f3 100644 --- a/gas/config/tc-z8k.c +++ b/gas/config/tc-z8k.c @@ -985,15 +985,24 @@ newfix (ptr, type, size, operand) int size; /* nibbles. */ expressionS *operand; { + int is_pcrel = 0; + if (operand->X_add_symbol || operand->X_op_symbol || operand->X_add_number) { + switch(type) + { + case R_JR: + case R_DISP7: + case R_CALLR: + is_pcrel = 1; + } fix_new_exp (frag_now, ptr, size / 2, operand, - 0, + is_pcrel, type); } } @@ -1455,6 +1464,9 @@ md_section_align (seg, size) & (-1 << section_alignment[(int) seg])); } +/* Attempt to simplify or eliminate a fixup. To indicate that a fixup + has been eliminated, set fix->fx_done. If fix->fx_addsy is non-NULL, + we will have to generate a reloc entry. */ void md_apply_fix3 (fixP, valP, segment) fixS * fixP; @@ -1471,34 +1483,62 @@ md_apply_fix3 (fixP, valP, segment) break; case R_JR: - val = val - fixP->fx_frag->fr_address + fixP->fx_where - fixP->fx_size; + if (fixP->fx_addsy) + { + fixP->fx_no_overflow = 1; + fixP->fx_done = 0; + } + else + { if (val & 1) as_bad (_("cannot branch to odd address")); val /= 2; if (val > 127 || val < -128) - as_bad (_("relative jump out of range")); + as_warn (_("relative jump out of range")); *buf++ = val; fixP->fx_no_overflow = 1; + fixP->fx_done = 1; + } break; case R_DISP7: - val = val - fixP->fx_frag->fr_address + fixP->fx_where - fixP->fx_size; + if (fixP->fx_addsy) + { + fixP->fx_no_overflow = 1; + fixP->fx_done = 0; + } + else + { if (val & 1) as_bad (_("cannot branch to odd address")); val /= 2; - if (val > 0 || val < -128) + if (val > 0 || val < -127) as_bad (_("relative jump out of range")); - *buf = (*buf & 0x80) | (val & 0x7f); + *buf = (*buf & 0x80) | (-val & 0x7f); fixP->fx_no_overflow = 1; + fixP->fx_done = 1; + } break; case R_CALLR: - if (val > 8191 || val < -8192) + if (fixP->fx_addsy) + { + fixP->fx_no_overflow = 1; + fixP->fx_done = 0; + } + else + { + if (val & 1) + as_bad (_("cannot branch to odd address")); + if (val > 4096 || val < -4095) as_bad (_("relative call out of range")); - val = -val; + val = -val / 2; *buf = (*buf & 0xf0) | ((val >> 8) & 0xf); buf++; *buf++ = val & 0xff; + fixP->fx_no_overflow = 1; + fixP->fx_done = 1; + } break; case R_IMM8: @@ -1568,11 +1608,13 @@ md_number_to_chars (ptr, use, nbytes) number_to_chars_bigendian (ptr, use, nbytes); } +/* On the Z8000, a PC-relative offset is relative to the address of the + instruction plus its size. */ long md_pcrel_from (fixP) - fixS *fixP ATTRIBUTE_UNUSED; + fixS *fixP; { - abort (); + return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address; } void -- 2.30.2