aboutsummaryrefslogtreecommitdiff
path: root/gas/config
diff options
context:
space:
mode:
authorJeff Law <law@redhat.com>1999-09-19 18:13:50 +0000
committerJeff Law <law@redhat.com>1999-09-19 18:13:50 +0000
commit77c02e18c1ffb850aa605a1f6cef04530b3cf2fc (patch)
tree6aaf29ccaf9bd509ba5b79c5d405b3313e32306a /gas/config
parent3610d1317daaf338ec6ae4ae45bbfcd006ff03a8 (diff)
downloadgdb-77c02e18c1ffb850aa605a1f6cef04530b3cf2fc.zip
gdb-77c02e18c1ffb850aa605a1f6cef04530b3cf2fc.tar.gz
gdb-77c02e18c1ffb850aa605a1f6cef04530b3cf2fc.tar.bz2
* config/tc-hppa.c (pa_ip): Handle 'X' operand.
(md_apply_fix): Handle 22bit pc-rel branches.
Diffstat (limited to 'gas/config')
-rw-r--r--gas/config/tc-hppa.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/gas/config/tc-hppa.c b/gas/config/tc-hppa.c
index 36722bb..56f8255 100644
--- a/gas/config/tc-hppa.c
+++ b/gas/config/tc-hppa.c
@@ -2865,6 +2865,45 @@ pa_ip (str)
continue;
}
+ /* Handle a 22 bit branch displacement. */
+ case 'X':
+ the_insn.field_selector = pa_chk_field_selector (&s);
+ get_expression (s);
+ s = expr_end;
+ the_insn.pcrel = 1;
+ if (!the_insn.exp.X_add_symbol
+ || !strcmp (S_GET_NAME (the_insn.exp.X_add_symbol),
+ "L$0\001"))
+ {
+ unsigned int w3, w2, w1, w, result;
+
+ num = evaluate_absolute (&the_insn);
+ if (num % 4)
+ {
+ as_bad (_("Branch to unaligned address"));
+ break;
+ }
+ CHECK_FIELD (num, 8388607, -8388608, 0);
+
+ if (the_insn.exp.X_add_symbol)
+ num -= 8;
+
+ sign_unext (num >> 2, 22, &result);
+ dis_assemble_22 (result, &w3, &w1, &w2, &w);
+ INSERT_FIELD_AND_CONTINUE (opcode,
+ ((w3 << 21) | (w2 << 2)
+ | (w1 << 16) | w),
+ 0);
+ }
+ else
+ {
+ the_insn.reloc = R_HPPA_PCREL_CALL;
+ the_insn.format = 22;
+ the_insn.arg_reloc = last_call_desc.arg_reloc;
+ memset (&last_call_desc, 0, sizeof (struct call_desc));
+ continue;
+ }
+
/* Handle an absolute 17 bit branch target. */
case 'z':
the_insn.field_selector = pa_chk_field_selector (&s);
@@ -3961,6 +4000,29 @@ md_apply_fix (fixP, valp)
break;
}
+ case 22:
+ {
+ int distance = *valp, w3;
+
+ CHECK_FIELD (new_val, 8388607, -8388608, 0);
+
+ /* If this is an absolute branch (ie no link) with an out of
+ range target, then we want to complain. */
+ if (fixP->fx_r_type == R_HPPA_PCREL_CALL
+ && (distance > 8388607 || distance < -8388608)
+ && (bfd_get_32 (stdoutput, buf) & 0xffe00000) == 0xe8000000)
+ CHECK_FIELD (distance, 8388607, -8388608, 0);
+
+ /* Mask off 22 bits to be changed. */
+ bfd_put_32 (stdoutput,
+ bfd_get_32 (stdoutput, buf) & 0xfc00e002,
+ buf);
+ sign_unext ((new_val - 8) >> 2, 22, &resulti);
+ dis_assemble_22 (resulti, &w3, &w1, &w2, &w);
+ result = ((w3 << 21) | (w2 << 2) | (w1 << 16) | w);
+ break;
+ }
+
case 32:
result = 0;
bfd_put_32 (stdoutput, new_val, buf);