From c67e42c950b142df5bf62ec004b4ada59f45689f Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 23 May 2000 01:48:04 +0000 Subject: [PATCH] * config/tc-ia64.c (FUNC_PC_RELATIVE): New. (pseudo_func): Add pcrel. (operand_match): Handle IA64_OPND_TGT64. (build_insn): Likewise. (md_begin): Initialize pseudo_func[FUNC_PC_RELATIVE]. (ia64_gen_real_reloc_type): Handle FUNC_PC_RELATIVE. (fix_insn): Handle all three 64-bit relocation types. --- gas/ChangeLog | 12 ++- gas/config/tc-ia64.c | 218 ++++++++++++++++++++++++++++--------------- 2 files changed, 153 insertions(+), 77 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 9f69a28464d..ddcb37a3dce 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,13 @@ +2000-05-22 Richard Henderson + + * config/tc-ia64.c (FUNC_PC_RELATIVE): New. + (pseudo_func): Add pcrel. + (operand_match): Handle IA64_OPND_TGT64. + (build_insn): Likewise. + (md_begin): Initialize pseudo_func[FUNC_PC_RELATIVE]. + (ia64_gen_real_reloc_type): Handle FUNC_PC_RELATIVE. + (fix_insn): Handle all three 64-bit relocation types. + Mon May 22 22:43:32 2000 Hans-Peter Nilsson * obj.h (struct format_ops): New members begin, app_file, @@ -410,7 +420,7 @@ Tue Apr 25 11:02:02 2000 Jeffrey A Law (law@cygnus.com) 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 (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. diff --git a/gas/config/tc-ia64.c b/gas/config/tc-ia64.c index e109d546a4f..a0f4ee639ba 100644 --- a/gas/config/tc-ia64.c +++ b/gas/config/tc-ia64.c @@ -77,6 +77,7 @@ enum reloc_func FUNC_FPTR_RELATIVE, FUNC_GP_RELATIVE, FUNC_LT_RELATIVE, + FUNC_PC_RELATIVE, FUNC_PLT_RELATIVE, FUNC_SEC_RELATIVE, FUNC_SEG_RELATIVE, @@ -434,6 +435,7 @@ pseudo_func[] = { "fptr", PSEUDO_FUNC_RELOC }, { "gprel", PSEUDO_FUNC_RELOC }, { "ltoff", PSEUDO_FUNC_RELOC }, + { "pcrel", PSEUDO_FUNC_RELOC }, { "pltoff", PSEUDO_FUNC_RELOC }, { "secrel", PSEUDO_FUNC_RELOC }, { "segrel", PSEUDO_FUNC_RELOC }, @@ -4003,9 +4005,11 @@ operand_match (idesc, index, e) fix->code = BFD_RELOC_IA64_PCREL21M; else if (opnd == IA64_OPND_TGT25c) fix->code = BFD_RELOC_IA64_PCREL21B; - else - /* FIXME -- use appropriate relocation type */ - as_bad (_("long branch targets not implemented")); + else if (opnd == IA64_OPND_TGT64) + fix->code = BFD_RELOC_IA64_PCREL60B; + else + abort (); + fix->code = ia64_gen_real_reloc_type (e->X_op_symbol, fix->code); fix->opnd = idesc->operands[index]; fix->expr = *e; @@ -4222,86 +4226,109 @@ build_insn (slot, insnp) for (i = 0; i < NELEMS (idesc->operands) && idesc->operands[i]; ++i) { - if (idesc->operands[i] == IA64_OPND_IMMU64) + if (slot->opnd[i].X_op == O_register + || slot->opnd[i].X_op == O_constant + || slot->opnd[i].X_op == O_index) + val = slot->opnd[i].X_add_number; + else if (slot->opnd[i].X_op == O_big) { - val = slot->opnd[i].X_add_number; + /* This must be the value 0x10000000000000000. */ + assert (idesc->operands[i] == IA64_OPND_IMM8M1U8); + val = 0; + } + else + val = 0; + + switch (idesc->operands[i]) + { + case IA64_OPND_IMMU64: *insnp++ = (val >> 22) & 0x1ffffffffffLL; insn |= (((val & 0x7f) << 13) | (((val >> 7) & 0x1ff) << 27) | (((val >> 16) & 0x1f) << 22) | (((val >> 21) & 0x1) << 21) | (((val >> 63) & 0x1) << 36)); - } - else if (idesc->operands[i] == IA64_OPND_IMMU62) - { - val = slot->opnd[i].X_add_number & 0x3fffffffffffffffULL; + continue; + + case IA64_OPND_IMMU62: + val &= 0x3fffffffffffffffULL; if (val != slot->opnd[i].X_add_number) as_warn (_("Value truncated to 62 bits")); *insnp++ = (val >> 21) & 0x1ffffffffffLL; insn |= (((val & 0xfffff) << 6) | (((val >> 20) & 0x1) << 36)); - } - else if (idesc->operands[i] == IA64_OPND_TGT64) - { - // FIXME -- need to implement the target address encoding properly - as_bad (_("long branch target encoding not implemented")); - *insnp++ = 0; - } - else if (slot->opnd[i].X_op == O_register - || slot->opnd[i].X_op == O_constant - || slot->opnd[i].X_op == O_index - || slot->opnd[i].X_op == O_big) - { - if (slot->opnd[i].X_op == O_big) - { - /* This must be the value 0x10000000000000000. */ - assert (idesc->operands[i] == IA64_OPND_IMM8M1U8); - val = 0; - } - else - val = slot->opnd[i].X_add_number; + continue; - switch (idesc->operands[i]) - { - case IA64_OPND_AR3: val -= REG_AR; break; - case IA64_OPND_B1: case IA64_OPND_B2: val -= REG_BR; break; - case IA64_OPND_CR3: val -= REG_CR; break; - case IA64_OPND_F1: case IA64_OPND_F2: - case IA64_OPND_F3: case IA64_OPND_F4: val -= REG_FR; break; - case IA64_OPND_P1: case IA64_OPND_P2: val -= REG_P; break; - - case IA64_OPND_R1: case IA64_OPND_R2: - case IA64_OPND_R3: case IA64_OPND_R3_2: - case IA64_OPND_CPUID_R3: case IA64_OPND_DBR_R3: - case IA64_OPND_DTR_R3: case IA64_OPND_ITR_R3: - case IA64_OPND_IBR_R3: case IA64_OPND_MR3: - case IA64_OPND_MSR_R3: case IA64_OPND_PKR_R3: - case IA64_OPND_PMC_R3: case IA64_OPND_PMD_R3: - case IA64_OPND_RR_R3: - val -= REG_GR; - break; + case IA64_OPND_TGT64: + val >>= 4; + *insnp++ = ((val >> 20) & 0x7fffffffffLL) << 2; + insn |= ((((val >> 59) & 0x1) << 36) + | (((val >> 0) & 0xfffff) << 13)); + continue; - default: - break; + case IA64_OPND_AR3: + val -= REG_AR; + break; + + case IA64_OPND_B1: + case IA64_OPND_B2: + val -= REG_BR; + break; + + case IA64_OPND_CR3: + val -= REG_CR; + break; + + case IA64_OPND_F1: + case IA64_OPND_F2: + case IA64_OPND_F3: + case IA64_OPND_F4: + val -= REG_FR; + break; + + case IA64_OPND_P1: + case IA64_OPND_P2: + val -= REG_P; + break; + + case IA64_OPND_R1: + case IA64_OPND_R2: + case IA64_OPND_R3: + case IA64_OPND_R3_2: + case IA64_OPND_CPUID_R3: + case IA64_OPND_DBR_R3: + case IA64_OPND_DTR_R3: + case IA64_OPND_ITR_R3: + case IA64_OPND_IBR_R3: + case IA64_OPND_MR3: + case IA64_OPND_MSR_R3: + case IA64_OPND_PKR_R3: + case IA64_OPND_PMC_R3: + case IA64_OPND_PMD_R3: + case IA64_OPND_RR_R3: + val -= REG_GR; + break; + + default: + break; + } + + odesc = elf64_ia64_operands + idesc->operands[i]; + err = (*odesc->insert) (odesc, val, &insn); + if (err) + as_bad_where (slot->src_file, slot->src_line, + "Bad operand value: %s", err); + if (idesc->flags & IA64_OPCODE_PSEUDO) + { + if ((idesc->flags & IA64_OPCODE_F2_EQ_F3) + && odesc == elf64_ia64_operands + IA64_OPND_F3) + { + o2desc = elf64_ia64_operands + IA64_OPND_F2; + (*o2desc->insert) (o2desc, val, &insn); } - odesc = elf64_ia64_operands + idesc->operands[i]; - err = (*odesc->insert) (odesc, val, &insn); - if (err) - as_bad_where (slot->src_file, slot->src_line, - "Bad operand value: %s", err); - if (idesc->flags & IA64_OPCODE_PSEUDO) + if ((idesc->flags & IA64_OPCODE_LEN_EQ_64MCNT) + && (odesc == elf64_ia64_operands + IA64_OPND_CPOS6a + || odesc == elf64_ia64_operands + IA64_OPND_POS6)) { - if ((idesc->flags & IA64_OPCODE_F2_EQ_F3) - && odesc == elf64_ia64_operands + IA64_OPND_F3) - { - o2desc = elf64_ia64_operands + IA64_OPND_F2; - (*o2desc->insert) (o2desc, val, &insn); - - } - if ((idesc->flags & IA64_OPCODE_LEN_EQ_64MCNT) - && (odesc == elf64_ia64_operands + IA64_OPND_CPOS6a - || odesc == elf64_ia64_operands + IA64_OPND_POS6)) - { - o2desc = elf64_ia64_operands + IA64_OPND_LEN6; - (*o2desc->insert) (o2desc, 64 - val, &insn); - } + o2desc = elf64_ia64_operands + IA64_OPND_LEN6; + (*o2desc->insert) (o2desc, 64 - val, &insn); } } } @@ -4797,6 +4824,10 @@ md_begin () symbol_new (".", undefined_section, FUNC_LT_RELATIVE, &zero_address_frag); + pseudo_func[FUNC_PC_RELATIVE].u.sym = + symbol_new (".", undefined_section, FUNC_PC_RELATIVE, + &zero_address_frag); + pseudo_func[FUNC_PLT_RELATIVE].u.sym = symbol_new (".", undefined_section, FUNC_PLT_RELATIVE, &zero_address_frag); @@ -7960,6 +7991,19 @@ ia64_gen_real_reloc_type (sym, r_type) } break; + case FUNC_PC_RELATIVE: + switch (r_type) + { + case BFD_RELOC_IA64_IMM22: new = BFD_RELOC_IA64_PCREL22; break; + case BFD_RELOC_IA64_IMM64: new = BFD_RELOC_IA64_PCREL64I; break; + case BFD_RELOC_IA64_DIR32MSB: new = BFD_RELOC_IA64_PCREL32MSB; break; + case BFD_RELOC_IA64_DIR32LSB: new = BFD_RELOC_IA64_PCREL32LSB; break; + case BFD_RELOC_IA64_DIR64MSB: new = BFD_RELOC_IA64_PCREL64MSB; break; + case BFD_RELOC_IA64_DIR64LSB: new = BFD_RELOC_IA64_PCREL64LSB; break; + default: break; + } + break; + case FUNC_PLT_RELATIVE: switch (r_type) { @@ -8063,7 +8107,7 @@ fix_insn (fix, odesc, value) slot = fix->fx_where & 0x3; fixpos = fix->fx_frag->fr_literal + (fix->fx_where - slot); - /* bundles are always in little-endian byte order */ + /* Bundles are always in little-endian byte order */ t0 = bfd_getl64 (fixpos); t1 = bfd_getl64 (fixpos + 8); control_bits = t0 & 0x1f; @@ -8071,18 +8115,40 @@ fix_insn (fix, odesc, value) insn[1] = ((t0 >> 46) & 0x3ffff) | ((t1 & 0x7fffff) << 18); insn[2] = (t1 >> 23) & 0x1ffffffffffLL; - err = (*odesc->insert) (odesc, value, insn + slot); - if (err) + err = NULL; + if (odesc - elf64_ia64_operands == IA64_OPND_IMMU64) { - as_bad_where (fix->fx_file, fix->fx_line, err); - return; + insn[1] = (value >> 22) & 0x1ffffffffffLL; + insn[2] |= (((value & 0x7f) << 13) + | (((value >> 7) & 0x1ff) << 27) + | (((value >> 16) & 0x1f) << 22) + | (((value >> 21) & 0x1) << 21) + | (((value >> 63) & 0x1) << 36)); } + else if (odesc - elf64_ia64_operands == IA64_OPND_IMMU62) + { + if (value & ~0x3fffffffffffffffULL) + err = "integer operand out of range"; + insn[1] = (value >> 21) & 0x1ffffffffffLL; + insn[2] |= (((value & 0xfffff) << 6) | (((value >> 20) & 0x1) << 36)); + } + else if (odesc - elf64_ia64_operands == IA64_OPND_TGT64) + { + value >>= 4; + insn[1] = ((value >> 20) & 0x7fffffffffLL) << 2; + insn[2] |= ((((value >> 59) & 0x1) << 36) + | (((value >> 0) & 0xfffff) << 13)); + } + else + err = (*odesc->insert) (odesc, value, insn + slot); + + if (err) + as_bad_where (fix->fx_file, fix->fx_line, err); t0 = control_bits | (insn[0] << 5) | (insn[1] << 46); t1 = ((insn[1] >> 18) & 0x7fffff) | (insn[2] << 23); md_number_to_chars (fixpos + 0, t0, 8); md_number_to_chars (fixpos + 8, t1, 8); - } /* Attempt to simplify or even eliminate a fixup. The return value is -- 2.30.2