@@ -2877,7 +2877,7 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2877
2877
SrcReg != Mips::ZERO_64;
2878
2878
warnIfNoMacro (IDLoc);
2879
2879
2880
- if (inPicMode () && ABI. IsO32 () ) {
2880
+ if (inPicMode ()) {
2881
2881
MCValue Res;
2882
2882
if (!SymExpr->evaluateAsRelocatable (Res, nullptr , nullptr )) {
2883
2883
Error (IDLoc, " expected relocatable expression" );
@@ -2888,6 +2888,7 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2888
2888
return true ;
2889
2889
}
2890
2890
2891
+ bool IsPtr64 = ABI.ArePtrs64bit ();
2891
2892
bool IsLocalSym =
2892
2893
Res.getSymA ()->getSymbol ().isInSection () ||
2893
2894
Res.getSymA ()->getSymbol ().isTemporary () ||
@@ -2897,117 +2898,66 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
2897
2898
2898
2899
// The case where the result register is $25 is somewhat special. If the
2899
2900
// symbol in the final relocation is external and not modified with a
2900
- // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
2901
+ // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16
2902
+ // or R_MIPS_CALL16 instead of R_MIPS_GOT_DISP in 64-bit case.
2901
2903
if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2902
2904
Res.getConstant () == 0 && !IsLocalSym) {
2903
2905
const MCExpr *CallExpr =
2904
2906
MipsMCExpr::create (MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext ());
2905
- TOut.emitRRX (Mips::LW, DstReg, GPReg, MCOperand::createExpr (CallExpr) ,
2906
- IDLoc, STI);
2907
+ TOut.emitRRX (IsPtr64 ? Mips::LD : Mips:: LW, DstReg, GPReg,
2908
+ MCOperand::createExpr (CallExpr), IDLoc, STI);
2907
2909
return false ;
2908
2910
}
2909
2911
2910
- // The remaining cases are:
2911
- // External GOT: lw $tmp, %got(symbol)($gp)
2912
- // >addiu $tmp, $tmp, offset
2913
- // >addiu $rd, $tmp, $rs
2914
- // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2915
- // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2916
- // >addiu $rd, $tmp, $rs
2917
- // The addiu's marked with a '>' may be omitted if they are redundant. If
2918
- // this happens then the last instruction must use $rd as the result
2919
- // register.
2920
2912
const MipsMCExpr *GotExpr = nullptr ;
2921
2913
const MCExpr *LoExpr = nullptr ;
2922
- if (IsLocalSym) {
2923
- GotExpr = MipsMCExpr::create (MipsMCExpr::MEK_GOT, SymExpr, getContext ());
2924
- LoExpr = MipsMCExpr::create (MipsMCExpr::MEK_LO, SymExpr, getContext ());
2925
- } else {
2926
- // External symbols fully resolve the symbol with just the %got(symbol)
2927
- // but we must still account for any offset to the symbol for expressions
2928
- // like symbol+8.
2929
- GotExpr =
2930
- MipsMCExpr::create (MipsMCExpr::MEK_GOT, Res.getSymA (), getContext ());
2931
- if (Res.getConstant () != 0 )
2914
+ if (IsPtr64) {
2915
+ // The remaining cases are:
2916
+ // Small offset: ld $tmp, %got_disp(symbol)($gp)
2917
+ // >daddiu $tmp, $tmp, offset
2918
+ // >daddu $rd, $tmp, $rs
2919
+ // The daddiu's marked with a '>' may be omitted if they are redundant. If
2920
+ // this happens then the last instruction must use $rd as the result
2921
+ // register.
2922
+ GotExpr = MipsMCExpr::create (MipsMCExpr::MEK_GOT_DISP, Res.getSymA (),
2923
+ getContext ());
2924
+ if (Res.getConstant () != 0 ) {
2925
+ // Symbols fully resolve with just the %got_disp(symbol) but we
2926
+ // must still account for any offset to the symbol for
2927
+ // expressions like symbol+8.
2932
2928
LoExpr = MCConstantExpr::create (Res.getConstant (), getContext ());
2933
- }
2934
-
2935
- unsigned TmpReg = DstReg;
2936
- if (UseSrcReg &&
2937
- getContext ().getRegisterInfo ()->isSuperOrSubRegisterEq (DstReg,
2938
- SrcReg)) {
2939
- // If $rs is the same as $rd, we need to use AT.
2940
- // If it is not available we exit.
2941
- unsigned ATReg = getATReg (IDLoc);
2942
- if (!ATReg)
2943
- return true ;
2944
- TmpReg = ATReg;
2945
- }
2946
-
2947
- TOut.emitRRX (Mips::LW, TmpReg, GPReg, MCOperand::createExpr (GotExpr), IDLoc,
2948
- STI);
2949
-
2950
- if (LoExpr)
2951
- TOut.emitRRX (Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr (LoExpr),
2952
- IDLoc, STI);
2953
-
2954
- if (UseSrcReg)
2955
- TOut.emitRRR (Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2956
-
2957
- return false ;
2958
- }
2959
-
2960
- if (inPicMode () && ABI.ArePtrs64bit ()) {
2961
- MCValue Res;
2962
- if (!SymExpr->evaluateAsRelocatable (Res, nullptr , nullptr )) {
2963
- Error (IDLoc, " expected relocatable expression" );
2964
- return true ;
2965
- }
2966
- if (Res.getSymB () != nullptr ) {
2967
- Error (IDLoc, " expected relocatable expression with only one symbol" );
2968
- return true ;
2969
- }
2970
-
2971
- // The case where the result register is $25 is somewhat special. If the
2972
- // symbol in the final relocation is external and not modified with a
2973
- // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT_DISP.
2974
- if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
2975
- Res.getConstant () == 0 &&
2976
- !(Res.getSymA ()->getSymbol ().isInSection () ||
2977
- Res.getSymA ()->getSymbol ().isTemporary () ||
2978
- (Res.getSymA ()->getSymbol ().isELF () &&
2979
- cast<MCSymbolELF>(Res.getSymA ()->getSymbol ()).getBinding () ==
2980
- ELF::STB_LOCAL))) {
2981
- const MCExpr *CallExpr =
2982
- MipsMCExpr::create (MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext ());
2983
- TOut.emitRRX (Mips::LD, DstReg, GPReg, MCOperand::createExpr (CallExpr),
2984
- IDLoc, STI);
2985
- return false ;
2986
- }
2987
2929
2988
- // The remaining cases are:
2989
- // Small offset: ld $tmp, %got_disp(symbol)($gp)
2990
- // >daddiu $tmp, $tmp, offset
2991
- // >daddu $rd, $tmp, $rs
2992
- // The daddiu's marked with a '>' may be omitted if they are redundant. If
2993
- // this happens then the last instruction must use $rd as the result
2994
- // register.
2995
- const MipsMCExpr *GotExpr = MipsMCExpr::create (MipsMCExpr::MEK_GOT_DISP,
2996
- Res.getSymA (),
2997
- getContext ());
2998
- const MCExpr *LoExpr = nullptr ;
2999
- if (Res.getConstant () != 0 ) {
3000
- // Symbols fully resolve with just the %got_disp(symbol) but we
3001
- // must still account for any offset to the symbol for
3002
- // expressions like symbol+8.
3003
- LoExpr = MCConstantExpr::create (Res.getConstant (), getContext ());
3004
-
3005
- // FIXME: Offsets greater than 16 bits are not yet implemented.
3006
- // FIXME: The correct range is a 32-bit sign-extended number.
3007
- if (Res.getConstant () < -0x8000 || Res.getConstant () > 0x7fff ) {
3008
- Error (IDLoc, " macro instruction uses large offset, which is not "
3009
- " currently supported" );
3010
- return true ;
2930
+ // FIXME: Offsets greater than 16 bits are not yet implemented.
2931
+ // FIXME: The correct range is a 32-bit sign-extended number.
2932
+ if (Res.getConstant () < -0x8000 || Res.getConstant () > 0x7fff ) {
2933
+ Error (IDLoc, " macro instruction uses large offset, which is not "
2934
+ " currently supported" );
2935
+ return true ;
2936
+ }
2937
+ }
2938
+ } else {
2939
+ // The remaining cases are:
2940
+ // External GOT: lw $tmp, %got(symbol)($gp)
2941
+ // >addiu $tmp, $tmp, offset
2942
+ // >addiu $rd, $tmp, $rs
2943
+ // Local GOT: lw $tmp, %got(symbol+offset)($gp)
2944
+ // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
2945
+ // >addiu $rd, $tmp, $rs
2946
+ // The addiu's marked with a '>' may be omitted if they are redundant. If
2947
+ // this happens then the last instruction must use $rd as the result
2948
+ // register.
2949
+ if (IsLocalSym) {
2950
+ GotExpr =
2951
+ MipsMCExpr::create (MipsMCExpr::MEK_GOT, SymExpr, getContext ());
2952
+ LoExpr = MipsMCExpr::create (MipsMCExpr::MEK_LO, SymExpr, getContext ());
2953
+ } else {
2954
+ // External symbols fully resolve the symbol with just the %got(symbol)
2955
+ // but we must still account for any offset to the symbol for
2956
+ // expressions like symbol+8.
2957
+ GotExpr = MipsMCExpr::create (MipsMCExpr::MEK_GOT, Res.getSymA (),
2958
+ getContext ());
2959
+ if (Res.getConstant () != 0 )
2960
+ LoExpr = MCConstantExpr::create (Res.getConstant (), getContext ());
3011
2961
}
3012
2962
}
3013
2963
@@ -3023,15 +2973,16 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
3023
2973
TmpReg = ATReg;
3024
2974
}
3025
2975
3026
- TOut.emitRRX (Mips::LD, TmpReg, GPReg, MCOperand::createExpr (GotExpr), IDLoc ,
3027
- STI);
2976
+ TOut.emitRRX (IsPtr64 ? Mips::LD : Mips::LW, TmpReg, GPReg ,
2977
+ MCOperand::createExpr (GotExpr), IDLoc, STI);
3028
2978
3029
2979
if (LoExpr)
3030
- TOut.emitRRX (Mips::DADDiu, TmpReg , TmpReg, MCOperand::createExpr (LoExpr) ,
3031
- IDLoc, STI);
2980
+ TOut.emitRRX (IsPtr64 ? Mips::DADDiu : Mips::ADDiu , TmpReg, TmpReg ,
2981
+ MCOperand::createExpr (LoExpr), IDLoc, STI);
3032
2982
3033
2983
if (UseSrcReg)
3034
- TOut.emitRRR (Mips::DADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
2984
+ TOut.emitRRR (IsPtr64 ? Mips::DADDu : Mips::ADDu, DstReg, TmpReg, SrcReg,
2985
+ IDLoc, STI);
3035
2986
3036
2987
return false ;
3037
2988
}
0 commit comments