Index: config/tc-mips.c =================================================================== RCS file: /cvs/uberbaum/gas/config/tc-mips.c,v retrieving revision 1.162 diff -u -2 -p -r1.162 tc-mips.c --- config/tc-mips.c 5 Sep 2002 00:01:18 -0000 1.162 +++ config/tc-mips.c 10 Sep 2002 03:15:11 -0000 @@ -1835,4 +1835,5 @@ append_insn (place, ip, address_expr, re case BFD_RELOC_LO16: + case BFD_RELOC_MIPS_GOT_DISP: ip->insn_opcode |= address_expr->X_add_number & 0xffff; break; @@ -3586,18 +3587,30 @@ load_address (counter, reg, ep, used_at) nop addiu $reg,$reg, (BFD_RELOC_LO16) + If we have NewABI, we want + lw $reg,($gp) (BFD_RELOC_MIPS_GOT_DISP) If there is a constant, it must be added in after. */ ex.X_add_number = ep->X_add_number; ep->X_add_number = 0; frag_grow (20); - macro_build ((char *) NULL, counter, ep, - HAVE_32BIT_ADDRESSES ? "lw" : "ld", "t,o(b)", - reg, (int) BFD_RELOC_MIPS_GOT16, mips_gp_register); - macro_build ((char *) NULL, counter, (expressionS *) NULL, "nop", ""); - p = frag_var (rs_machine_dependent, 4, 0, - RELAX_ENCODE (0, 4, -8, 0, 0, mips_opts.warn_about_macros), - ep->X_add_symbol, (offsetT) 0, (char *) NULL); - macro_build (p, counter, ep, - HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu", - "t,r,j", reg, reg, (int) BFD_RELOC_LO16); + if (HAVE_NEWABI) + { + macro_build ((char *) NULL, counter, ep, + HAVE_32BIT_ADDRESSES ? "lw" : "ld", "t,o(b)", reg, + (int) BFD_RELOC_MIPS_GOT_DISP, mips_gp_register); + } + else + { + macro_build ((char *) NULL, counter, ep, + HAVE_32BIT_ADDRESSES ? "lw" : "ld", "t,o(b)", + reg, (int) BFD_RELOC_MIPS_GOT16, mips_gp_register); + macro_build ((char *) NULL, counter, (expressionS *) NULL, "nop", ""); + p = frag_var (rs_machine_dependent, 4, 0, + RELAX_ENCODE (0, 4, -8, 0, 0, mips_opts.warn_about_macros), + ep->X_add_symbol, (offsetT) 0, (char *) NULL); + macro_build (p, counter, ep, + HAVE_32BIT_ADDRESSES ? "addiu" : "daddiu", + "t,r,j", reg, reg, (int) BFD_RELOC_LO16); + } + if (ex.X_add_number != 0) { @@ -4631,5 +4644,14 @@ macro (ip) For a local symbol, we want the same instruction sequence, but we output a BFD_RELOC_LO16 reloc on the - addiu instruction. */ + addiu instruction. + + For NewABI, we want for local or external data addresses + lw $tempreg,($gp) (BFD_RELOC_MIPS_GOT_DISP) + For a local function symbol, we want + lw $tempreg,($gp) (BFD_RELOC_MIPS_GOT_PAGE) + nop + addiu $tempreg,$tempreg, (BFD_RELOC_MIPS_GOT_OFST) + */ + expr1.X_add_number = offset_expr.X_add_number; offset_expr.X_add_number = 0; @@ -4637,4 +4659,6 @@ macro (ip) if (expr1.X_add_number == 0 && tempreg == PIC_CALL_REG) lw_reloc_type = (int) BFD_RELOC_MIPS_CALL16; + else if (HAVE_NEWABI) + lw_reloc_type = (int) BFD_RELOC_MIPS_GOT_DISP; macro_build ((char *) NULL, &icnt, &offset_expr, HAVE_32BIT_ADDRESSES ? "lw" : "ld", @@ -4736,4 +4760,5 @@ macro (ip) int lui_reloc_type = (int) BFD_RELOC_MIPS_GOT_HI16; int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT_LO16; + int local_reloc_type = (int) BFD_RELOC_MIPS_GOT16; /* This is the large GOT case. If this is a reference to an @@ -4777,29 +4802,8 @@ macro (ip) addu $tempreg,$tempreg,$at - For NewABI, we want for data addresses - lw $tempreg,($gp) (BFD_RELOC_MIPS_GOT_DISP) - If tempreg is PIC_CALL_REG pointing to a external symbol, we want - lw $tempreg,($gp) (BFD_RELOC_MIPS_CALL16) + For NewABI, we want for local data addresses + lw $tempreg,($gp) (BFD_RELOC_MIPS_GOT_DISP) */ - if (HAVE_NEWABI) - { - int reloc_type = (tempreg == PIC_CALL_REG - ? BFD_RELOC_MIPS_CALL16 - : BFD_RELOC_MIPS_GOT_DISP); - - macro_build ((char *) NULL, &icnt, &offset_expr, - HAVE_32BIT_ADDRESSES ? "lw" : "ld", - "t,o(b)", tempreg, reloc_type, mips_gp_register); - - if (breg != 0) - macro_build ((char *) NULL, &icnt, (expressionS *) NULL, - HAVE_32BIT_ADDRESSES ? "addu" : "daddu", - "d,v,t", treg, tempreg, breg); - if (! used_at) - return; - - break; - } expr1.X_add_number = offset_expr.X_add_number; offset_expr.X_add_number = 0; @@ -4814,4 +4818,5 @@ macro (ip) lw_reloc_type = (int) BFD_RELOC_MIPS_CALL_LO16; } + macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u", tempreg, lui_reloc_type); @@ -4922,10 +4927,19 @@ macro (ip) p += 4; } + + if (HAVE_NEWABI) + local_reloc_type = (int) BFD_RELOC_MIPS_GOT_DISP; macro_build (p, &icnt, &offset_expr, HAVE_32BIT_ADDRESSES ? "lw" : "ld", - "t,o(b)", tempreg, (int) BFD_RELOC_MIPS_GOT16, + "t,o(b)", tempreg, + local_reloc_type, mips_gp_register); p += 4; - if (expr1.X_add_number >= -0x8000 + if (expr1.X_add_number == 0 && HAVE_NEWABI) + { + /* BFD_RELOC_MIPS_GOT_DISP is sufficient for newabi */ + } + else + if (expr1.X_add_number >= -0x8000 && expr1.X_add_number < 0x8000) { @@ -5598,4 +5612,5 @@ macro (ip) { char *p; + int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT16; /* If this is a reference to an external symbol, we want @@ -5603,9 +5618,6 @@ macro (ip) nop $treg,0($tempreg) - Otherwise we want - lw $tempreg,($gp) (BFD_RELOC_MIPS_GOT16) - nop - addiu $tempreg,$tempreg, (BFD_RELOC_LO16) - $treg,0($tempreg) + If we have NewABI, we want + lw $reg,($gp) (BFD_RELOC_MIPS_GOT_DISP) If there is a base register, we add it to $tempreg before the . If there is a constant, we stick it in the @@ -5617,4 +5629,6 @@ macro (ip) expr1.X_add_number = offset_expr.X_add_number; offset_expr.X_add_number = 0; + if (HAVE_NEWABI) + lw_reloc_type = (int) BFD_RELOC_MIPS_GOT_DISP; if (expr1.X_add_number < -0x8000 || expr1.X_add_number >= 0x8000) @@ -5623,5 +5637,5 @@ macro (ip) macro_build ((char *) NULL, &icnt, &offset_expr, HAVE_32BIT_ADDRESSES ? "lw" : "ld", "t,o(b)", tempreg, - (int) BFD_RELOC_MIPS_GOT16, mips_gp_register); + (int) lw_reloc_type, mips_gp_register); macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", ""); p = frag_var (rs_machine_dependent, 4, 0, @@ -5668,4 +5682,5 @@ macro (ip) expr1.X_add_number = offset_expr.X_add_number; offset_expr.X_add_number = 0; + if (expr1.X_add_number < -0x8000 || expr1.X_add_number >= 0x8000) @@ -5715,4 +5730,5 @@ macro (ip) p += 4; } + macro_build (p, &icnt, &offset_expr, HAVE_32BIT_ADDRESSES ? "lw" : "ld", @@ -10419,7 +10435,4 @@ mips_after_parse_args () mips_opts.fp32 = file_mips_fp32; - if (HAVE_NEWABI) - mips_big_got = 1; - if (mips_flag_mdebug < 0) { @@ -10643,4 +10656,5 @@ md_apply_fix3 (fixP, valP, seg) long insn; valueT value; + static int previous_fx_r_type = 0; assert (fixP->fx_size == 4 @@ -10742,6 +10756,12 @@ md_apply_fix3 (fixP, valP, seg) fixP->fx_addnumber = value; /* Remember value for tc_gen_reloc. */ - if (fixP->fx_addsy == NULL && ! fixP->fx_pcrel) + /* We are not done if this is a composite relocation to set up gp. */ + if (fixP->fx_addsy == NULL && ! fixP->fx_pcrel + && !(fixP->fx_r_type == BFD_RELOC_MIPS_SUB + || (previous_fx_r_type == BFD_RELOC_MIPS_SUB + && (fixP->fx_r_type == BFD_RELOC_HI16_S + || fixP->fx_r_type == BFD_RELOC_LO16)))) fixP->fx_done = 1; + previous_fx_r_type = fixP->fx_r_type; switch (fixP->fx_r_type) @@ -12636,5 +12656,6 @@ tc_gen_reloc (section, fixp) reloc and generate a new one. */ if (fixp->fx_frag->fr_opcode != NULL - && (fixp->fx_r_type == BFD_RELOC_GPREL16 + && ((fixp->fx_r_type == BFD_RELOC_GPREL16 + && ! HAVE_NEWABI) || fixp->fx_r_type == BFD_RELOC_MIPS_GOT16 || fixp->fx_r_type == BFD_RELOC_MIPS_CALL16 @@ -12643,5 +12664,5 @@ tc_gen_reloc (section, fixp) || fixp->fx_r_type == BFD_RELOC_MIPS_CALL_HI16 || fixp->fx_r_type == BFD_RELOC_MIPS_CALL_LO16) - && ! HAVE_NEWABI) + ) { arelent *reloc2; @@ -12704,13 +12735,30 @@ tc_gen_reloc (section, fixp) case BFD_RELOC_MIPS_GOT16: break; - case BFD_RELOC_MIPS_CALL16: case BFD_RELOC_MIPS_GOT_LO16: case BFD_RELOC_MIPS_CALL_LO16: fixp->fx_r_type = BFD_RELOC_MIPS_GOT16; break; + case BFD_RELOC_MIPS_CALL16: + if (HAVE_NEWABI) + { + /* BFD_RELOC_MIPS_GOT16;*/ + fixp->fx_r_type = BFD_RELOC_MIPS_GOT_PAGE; + reloc2->howto = bfd_reloc_type_lookup + (stdoutput, BFD_RELOC_MIPS_GOT_OFST); + } + else + fixp->fx_r_type = BFD_RELOC_MIPS_GOT16; + break; } } else abort (); + + /* newabi uses R_MIPS_GOT_DISP for local symbols */ + if (HAVE_NEWABI && BFD_RELOC_MIPS_GOT_LO16) + { + fixp->fx_r_type = BFD_RELOC_MIPS_GOT_DISP; + retval[1] = NULL; + } }