diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -3625,8 +3625,25 @@ TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI); TOut.emitRRI(Inst.getOpcode(), DstReg, TmpReg, LoOffset, IDLoc, STI); + return; + } + + assert(OffsetOp.isExpr() && "expected expression operand kind"); + if (inPicMode()) { + // FIXME: + // a) Fix lw/sw $reg, symbol($reg) instruction expanding. + // b) If expression includes offset (sym + number), do not + // encode the offset into a relocation. Take it in account + // in the last load/store instruction. + // c) Check that immediates of R_MIPS_GOT16/R_MIPS_LO16 relocations + // do not exceed 16-bit. + // d) Use R_MIPS_GOT_PAGE/R_MIPS_GOT_OFST relocations instead + // of R_MIPS_GOT_DISP in appropriate cases to reduce number + // of GOT entries. + expandLoadAddress(TmpReg, Mips::NoRegister, OffsetOp, !ABI.ArePtrs64bit(), + IDLoc, Out, STI); + TOut.emitRRI(Inst.getOpcode(), DstReg, TmpReg, 0, IDLoc, STI); } else { - assert(OffsetOp.isExpr() && "expected expression operand kind"); const MCExpr *ExprOffset = OffsetOp.getExpr(); MCOperand LoOperand = MCOperand::createExpr( MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext())); diff --git a/llvm/test/MC/Mips/mips-expansions.s b/llvm/test/MC/Mips/mips-expansions.s --- a/llvm/test/MC/Mips/mips-expansions.s +++ b/llvm/test/MC/Mips/mips-expansions.s @@ -50,6 +50,7 @@ # CHECK-LE: lhu $4, 4($4) # LW/SW and LDC1/SDC1 of symbol address, done by MipsAsmParser::expandMemInst(): +# NON-PIC code .set noat lw $10, symbol($4) # CHECK-LE: lui $10, %hi(symbol) # encoding: [A,A,0x0a,0x3c] @@ -105,6 +106,64 @@ # CHECK-LE: lui $1, %hi(symbol) # CHECK-LE: sdc1 $f0, %lo(symbol)($1) +# PIC code + .option pic2 + .set noat + lw $10, symbol($4) +# CHECK-LE: lw $10, %got(symbol)($gp) # encoding: [A,A,0x8a,0x8f] +# CHECK-LE: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT +# CHECK-LE-FIXME: addu $10, $10, $4 # encoding: [0x21,0x50,0x44,0x01] +# CHECK-LE: lw $10, 0($10) # encoding: [0x00,0x00,0x4a,0x8d] + .set at + sw $10, symbol($9) +# CHECK-LE: lw $1, %got(symbol)($gp) # encoding: [A,A,0x81,0x8f] +# CHECK-LE: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT +# CHECK-LE-FIXME: addu $1, $1, $9 # encoding: [0x21,0x08,0x29,0x00] +# CHECK-LE: sw $10, 0($1) # encoding: [0x00,0x00,0x2a,0xac] + + lw $8, 1f+8 +# CHECK-LE: lw $8, %got(($tmp0)+8)($gp) # encoding: [A,A,0x88,0x8f] +# CHECK-LE: # fixup A - offset: 0, value: %got(($tmp0)+8), kind: fixup_Mips_GOT +# CHECK-LE: addiu $8, $8, %lo(($tmp0)+8) # encoding: [A,A,0x08,0x25] +# CHECK-LE: # fixup A - offset: 0, value: %lo(($tmp0)+8), kind: fixup_Mips_LO16 +# CHECK-LE: lw $8, 0($8) # encoding: [0x00,0x00,0x08,0x8d] + sw $8, 1f+8 +# CHECK-LE: lw $1, %got(($tmp0)+8)($gp) # encoding: [A,A,0x81,0x8f] +# CHECK-LE: # fixup A - offset: 0, value: %got(($tmp0)+8), kind: fixup_Mips_GOT +# CHECK-LE: addiu $1, $1, %lo(($tmp0)+8) # encoding: [A,A,0x21,0x24] +# CHECK-LE: # fixup A - offset: 0, value: %lo(($tmp0)+8), kind: fixup_Mips_LO16 +# CHECK-LE: sw $8, 0($1) # encoding: [0x00,0x00,0x28,0xac] + + lw $10, 655483($4) +# CHECK-LE: lui $10, 10 # encoding: [0x0a,0x00,0x0a,0x3c] +# CHECK-LE: addu $10, $10, $4 # encoding: [0x21,0x50,0x44,0x01] +# CHECK-LE: lw $10, 123($10) # encoding: [0x7b,0x00,0x4a,0x8d] + sw $10, 123456($9) +# CHECK-LE: lui $1, 2 # encoding: [0x02,0x00,0x01,0x3c] +# CHECK-LE: addu $1, $1, $9 # encoding: [0x21,0x08,0x29,0x00] +# CHECK-LE: sw $10, -7616($1) # encoding: [0x40,0xe2,0x2a,0xac] + + lw $8, symbol+8 +# CHECK-LE: lw $8, %got(symbol+8)($gp) # encoding: [A,A,0x88,0x8f] +# CHECK-LE: # fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT +# CHECK-LE: addiu $8, $8, 8 # encoding: [0x08,0x00,0x08,0x25] +# CHECK-LE: lw $8, 0($8) # encoding: [0x00,0x00,0x08,0x8d] + sw $8, symbol+8 +# CHECK-LE: lw $1, %got(symbol+8)($gp) # encoding: [A,A,0x81,0x8f] +# CHECK-LE: # fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT +# CHECK-LE: addiu $1, $1, 8 # encoding: [0x08,0x00,0x21,0x24] +# CHECK-LE: sw $8, 0($1) # encoding: [0x00,0x00,0x28,0xac] + + ldc1 $f0, symbol +# CHECK-LE: lw $1, %got(symbol)($gp) # encoding: [A,A,0x81,0x8f] +# CHECK-LE: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT +# CHECK-LE: ldc1 $f0, 0($1) # encoding: [0x00,0x00,0x20,0xd4] + sdc1 $f0, symbol +# CHECK-LE: lw $1, %got(symbol)($gp) # encoding: [A,A,0x81,0x8f] +# CHECK-LE: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT +# CHECK-LE: sdc1 $f0, 0($1) # encoding: [0x00,0x00,0x20,0xf4] + .option pic0 + # Test BNE with an immediate as the 2nd operand. bne $2, 0, 1332 # CHECK-LE: bnez $2, 1332 # encoding: [0x4d,0x01,0x40,0x14] diff --git a/llvm/test/MC/Mips/mips64-expansions.s b/llvm/test/MC/Mips/mips64-expansions.s --- a/llvm/test/MC/Mips/mips64-expansions.s +++ b/llvm/test/MC/Mips/mips64-expansions.s @@ -466,3 +466,56 @@ # CHECK-NEXT: dsll $4, $4, 16 # CHECK-NEXT: daddu $4, $4, $3 # CHECK-NEXT: lhu $4, -32764($4) + +# LW/SW and LDC1/SDC1 of symbol address, done by MipsAsmParser::expandMemInst(): + .option pic2 + lw $10, symbol($4) +# CHECK: ld $10, %got_disp(symbol)($gp) # encoding: [A,A,0x8a,0xdf] +# CHECK: # fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP +# CHECK-FIXME: daddu $10, $10, $4 # encoding: [0x2d,0x50,0x44,0x01] +# CHECK: lw $10, 0($10) # encoding: [0x00,0x00,0x4a,0x8d] + sw $10, symbol($9) +# CHECK: ld $1, %got_disp(symbol)($gp) # encoding: [A,A,0x81,0xdf] +# CHECK: # fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP +# CHECK-FIXME: daddu $1, $1, $9 # encoding: [0x2d,0x08,0x29,0x00] +# CHECK: sw $10, 0($1) # encoding: [0x00,0x00,0x2a,0xac] + + lw $8, sym+8 +# CHECK: ld $8, %got_disp(sym)($gp) # encoding: [A,A,0x88,0xdf] +# CHECK: # fixup A - offset: 0, value: %got_disp(sym), kind: fixup_Mips_GOT_DISP +# CHECK: daddiu $8, $8, 8 # encoding: [0x08,0x00,0x08,0x65] +# CHECK: lw $8, 0($8) # encoding: [0x00,0x00,0x08,0x8d] + sw $8, sym+8 +# CHECK: ld $1, %got_disp(sym)($gp) # encoding: [A,A,0x81,0xdf] +# CHECK: # fixup A - offset: 0, value: %got_disp(sym), kind: fixup_Mips_GOT_DISP +# CHECK: daddiu $1, $1, 8 # encoding: [0x08,0x00,0x21,0x64] +# CHECK: sw $8, 0($1) # encoding: [0x00,0x00,0x28,0xac] + + lw $10, 655483($4) +# CHECK: lui $10, 10 # encoding: [0x0a,0x00,0x0a,0x3c] +# CHECK: daddu $10, $10, $4 # encoding: [0x2d,0x50,0x44,0x01] +# CHECK: lw $10, 123($10) # encoding: [0x7b,0x00,0x4a,0x8d] + sw $10, 123456($9) +# CHECK: lui $1, 2 # encoding: [0x02,0x00,0x01,0x3c] +# CHECK: daddu $1, $1, $9 # encoding: [0x2d,0x08,0x29,0x00] +# CHECK: sw $10, -7616($1) # encoding: [0x40,0xe2,0x2a,0xac] + + lw $8, symbol+8 +# CHECK: ld $8, %got_disp(symbol)($gp) # encoding: [A,A,0x88,0xdf] +# CHECK: # fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP +# CHECK: daddiu $8, $8, 8 # encoding: [0x08,0x00,0x08,0x65] +# CHECK: lw $8, 0($8) # encoding: [0x00,0x00,0x08,0x8d] + sw $8, symbol+8 +# CHECK: ld $1, %got_disp(symbol)($gp) # encoding: [A,A,0x81,0xdf] +# CHECK: # fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP +# CHECK: daddiu $1, $1, 8 # encoding: [0x08,0x00,0x21,0x64] +# CHECK: sw $8, 0($1) # encoding: [0x00,0x00,0x28,0xac] + + ldc1 $f0, symbol +# CHECK: ld $1, %got_disp(symbol)($gp) # encoding: [A,A,0x81,0xdf] +# CHECK: # fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP +# CHECK: ldc1 $f0, 0($1) # encoding: [0x00,0x00,0x20,0xd4] + sdc1 $f0, symbol +# CHECK: ld $1, %got_disp(symbol)($gp) # encoding: [A,A,0x81,0xdf] +# CHECK: # fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP +# CHECK: sdc1 $f0, 0($1) # encoding: [0x00,0x00,0x20,0xf4]