diff options
author | Jeff Law <law@redhat.com> | 1999-09-19 18:13:50 +0000 |
---|---|---|
committer | Jeff Law <law@redhat.com> | 1999-09-19 18:13:50 +0000 |
commit | 77c02e18c1ffb850aa605a1f6cef04530b3cf2fc (patch) | |
tree | 6aaf29ccaf9bd509ba5b79c5d405b3313e32306a /gas/config | |
parent | 3610d1317daaf338ec6ae4ae45bbfcd006ff03a8 (diff) | |
download | gdb-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.c | 62 |
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); |