From a02fab7e03ee47033820c17c97674d6c8b992de9 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Fri, 21 Apr 2000 20:34:00 +0000 Subject: [PATCH] * config/tc-hppa.c (md_apply_fix): Handle new PA2.0 formats. * config/tc-hppa.c (CHECK_ALIGN): New macro. Added handling of new operand types l,y,&,fe,fE,fx. --- gas/ChangeLog | 10 ++++ gas/config/tc-hppa.c | 127 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 135 insertions(+), 2 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index ca922ec3473..bbea9c3b31a 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,11 @@ +Fri Apr 21 14:29:43 2000 Jeffrey A Law (law@cygnus.com) + Jason Eckhardt + + * config/tc-hppa.c (md_apply_fix): Handle new PA2.0 formats. + + * config/tc-hppa.c (CHECK_ALIGN): New macro. + Added handling of new operand types l,y,&,fe,fE,fx. + Fri Apr 21 13:20:53 2000 Richard Henderson David Mosberger Timothy Wall @@ -386,6 +394,8 @@ Sat Mar 11 00:01:39 2000 Hans-Peter Nilsson * doc/Makefile.in: Regenerate. * doc/c-m32r.texi (M32R-Opts): Document new command line switch. + + 2000-03-02 Michael Meissner * config/tc-d30v.c (check_range): Remove code that incorrectly diff --git a/gas/config/tc-hppa.c b/gas/config/tc-hppa.c index 7e95a4ad6d0..1dc5af47449 100644 --- a/gas/config/tc-hppa.c +++ b/gas/config/tc-hppa.c @@ -1114,6 +1114,20 @@ static struct default_space_dict pa_def_spaces[] = } \ } +/* Simple alignment checking for FIELD againt ALIGN (a power of two). + IGNORE is used to suppress the error message. */ + +#define CHECK_ALIGN(FIELD, ALIGN, IGNORE) \ + { \ + if ((FIELD) & ((ALIGN) - 1)) \ + { \ + if (! IGNORE) \ + as_bad (_("Field not properly aligned [%d] (%d)."), (ALIGN), \ + (int) (FIELD));\ + break; \ + } \ + } + #define is_DP_relative(exp) \ ((exp).X_op == O_subtract \ && strcmp (S_GET_NAME ((exp).X_op_symbol), "$global$") == 0) @@ -3080,6 +3094,86 @@ pa_ip (str) continue; } + /* Handle a 16 bit immediate at 31 (PA 2.0 wide mode only). */ + case 'l': + the_insn.field_selector = pa_chk_field_selector (&s); + get_expression (s); + s = expr_end; + if (the_insn.exp.X_op == O_constant) + { + unsigned int result; + num = evaluate_absolute (&the_insn); + CHECK_FIELD (num, 32767, -32768, 0); + dis_assemble_16 (num, &result, 1); + INSERT_FIELD_AND_CONTINUE (opcode, result, 0); + } + else + { + /* ??? Is this valid for wide mode? */ + if (is_DP_relative (the_insn.exp)) + the_insn.reloc = R_HPPA_GOTOFF; + else if (is_PC_relative (the_insn.exp)) + the_insn.reloc = R_HPPA_PCREL_CALL; + else + the_insn.reloc = R_HPPA; + the_insn.format = 14; + continue; + } + + /* Handle a word-aligned 16-bit imm. at 31 (PA2.0 wide). */ + case 'y': + the_insn.field_selector = pa_chk_field_selector (&s); + get_expression (s); + s = expr_end; + if (the_insn.exp.X_op == O_constant) + { + unsigned int result; + num = evaluate_absolute (&the_insn); + CHECK_FIELD (num, 32767, -32768, 0); + CHECK_ALIGN (num, 4, 0); + dis_assemble_16 (num, &result, 1); + INSERT_FIELD_AND_CONTINUE (opcode, result, 0); + } + else + { + /* ??? Is this valid for wide mode? */ + if (is_DP_relative (the_insn.exp)) + the_insn.reloc = R_HPPA_GOTOFF; + else if (is_PC_relative (the_insn.exp)) + the_insn.reloc = R_HPPA_PCREL_CALL; + else + the_insn.reloc = R_HPPA; + the_insn.format = 14; + continue; + } + + /* Handle a dword-aligned 16-bit imm. at 31 (PA2.0 wide). */ + case '&': + the_insn.field_selector = pa_chk_field_selector (&s); + get_expression (s); + s = expr_end; + if (the_insn.exp.X_op == O_constant) + { + unsigned int result; + num = evaluate_absolute (&the_insn); + CHECK_FIELD (num, 32767, -32768, 0); + CHECK_ALIGN (num, 8, 0); + dis_assemble_16 (num, &result, 1); + INSERT_FIELD_AND_CONTINUE (opcode, result, 0); + } + else + { + /* ??? Is this valid for wide mode? */ + if (is_DP_relative (the_insn.exp)) + the_insn.reloc = R_HPPA_GOTOFF; + else if (is_PC_relative (the_insn.exp)) + the_insn.reloc = R_HPPA_PCREL_CALL; + else + the_insn.reloc = R_HPPA; + the_insn.format = 14; + continue; + } + /* Handle a 12 bit branch displacement. */ case 'w': the_insn.field_selector = pa_chk_field_selector (&s); @@ -3806,6 +3900,7 @@ pa_ip (str) } /* Handle L/R register halves like 'x'. */ + case 'E': case 'e': { struct pa_11_fp_reg_struct result; @@ -3821,6 +3916,16 @@ pa_ip (str) } continue; } + + /* Float target register (PA 2.0 wide). */ + case 'x': + /* This should be more strict. Small steps. */ + if (strict && *s != '%') + break; + num = pa_parse_number (&s, 0); + CHECK_FIELD (num, 31, 0, 0); + INSERT_FIELD_AND_CONTINUE (opcode, num, 16); + default: abort (); } @@ -4303,12 +4408,30 @@ md_apply_fix (fixP, valp) && S_GET_SEGMENT (fixP->fx_addsy) == hppa_fixP->segment && !(fixP->fx_subsy && S_GET_SEGMENT (fixP->fx_subsy) != hppa_fixP->segment)) - + new_val = hppa_field_adjust (*valp, 0, hppa_fixP->fx_r_field); #undef arg_reloc_stub_needed - + switch (fmt) { + case 10: + CHECK_FIELD (new_val, 8191, -8192, 0); + + /* Mask off 11 bits to be changed. */ + bfd_put_32 (stdoutput, + bfd_get_32 (stdoutput, buf) & 0xffffc00e, + buf); + result = ((new_val & 0x1fff) >> 2) | ((new_val & 0x2000) >> 13); + break; + case -11: + CHECK_FIELD (new_val, 8191, -8192, 0); + + /* Mask off 14 bits to be changed. */ + bfd_put_32 (stdoutput, + bfd_get_32 (stdoutput, buf) & 0xffffc006, + buf); + result = ((new_val & 0x1fff) >> 1) | ((new_val & 0x2000) >> 15); + break; /* Handle all opcodes with the 'j' operand type. */ case 14: CHECK_FIELD (new_val, 8191, -8192, 0); -- 2.30.2