Skip to content

Commit fba875f

Browse files
committedApr 29, 2016
[mips][ias] Split expandMemInst between MipsAsmParser and MipsTargetStreamer. Almost NFC.
Summary: The portion in MipsAsmParser is responsible for figuring out which expansion to use, while the portion in MipsTargetStreamer is responsible for emitting it. This allows us to remove the call to isIntegratedAssemblerRequired() which is currently ensuring the effect of .cprestore only occurs when writing objects. The small functional change is that the memory offsets are now correctly printed as signed values. Reviewers: sdardis Subscribers: dsanders, sdardis, llvm-commits Differential Revision: http://reviews.llvm.org/D19714 llvm-svn: 268042
1 parent a736b37 commit fba875f

File tree

5 files changed

+207
-68
lines changed

5 files changed

+207
-68
lines changed
 

‎llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp

+91-66
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,13 @@ class MipsAsmParser : public MCTargetAsmParser {
201201
const MCSubtargetInfo *STI);
202202

203203
void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
204-
const MCSubtargetInfo *STI, bool isLoad, bool isImmOpnd);
204+
const MCSubtargetInfo *STI, bool IsLoad, bool IsImmOpnd);
205+
206+
void expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
207+
const MCSubtargetInfo *STI, bool IsImmOpnd);
208+
209+
void expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
210+
const MCSubtargetInfo *STI, bool IsImmOpnd);
205211

206212
bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
207213
const MCSubtargetInfo *STI);
@@ -2526,78 +2532,97 @@ bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
25262532
}
25272533

25282534
void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2529-
const MCSubtargetInfo *STI, bool isLoad,
2530-
bool isImmOpnd) {
2535+
const MCSubtargetInfo *STI, bool IsLoad,
2536+
bool IsImmOpnd) {
2537+
if (IsLoad) {
2538+
expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2539+
return;
2540+
}
2541+
expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
2542+
}
2543+
2544+
void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2545+
const MCSubtargetInfo *STI, bool IsImmOpnd) {
25312546
MipsTargetStreamer &TOut = getTargetStreamer();
2532-
MCOperand HiOperand, LoOperand;
2533-
unsigned TmpRegNum;
2534-
// 1st operand is either the source or destination register.
2535-
assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2536-
unsigned RegOpNum = Inst.getOperand(0).getReg();
2537-
// 2nd operand is the base register.
2538-
assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2539-
unsigned BaseRegNum = Inst.getOperand(1).getReg();
2540-
// 3rd operand is either an immediate or expression.
2541-
if (isImmOpnd) {
2542-
assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2543-
unsigned ImmOffset = Inst.getOperand(2).getImm();
2544-
unsigned LoOffset = ImmOffset & 0x0000ffff;
2545-
unsigned HiOffset = (ImmOffset & 0xffff0000) >> 16;
2546-
// If msb of LoOffset is 1(negative number) we must increment HiOffset.
2547-
if (LoOffset & 0x8000)
2548-
HiOffset++;
2549-
LoOperand = MCOperand::createImm(LoOffset);
2550-
HiOperand = MCOperand::createImm(HiOffset);
2551-
} else {
2552-
const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
2553-
LoOperand = MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo"));
2554-
HiOperand = MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi"));
2555-
}
2556-
// These are some of the types of expansions we perform here:
2557-
// 1) lw $8, sym => lui $8, %hi(sym)
2558-
// lw $8, %lo(sym)($8)
2559-
// 2) lw $8, offset($9) => lui $8, %hi(offset)
2560-
// add $8, $8, $9
2561-
// lw $8, %lo(offset)($9)
2562-
// 3) lw $8, offset($8) => lui $at, %hi(offset)
2563-
// add $at, $at, $8
2564-
// lw $8, %lo(offset)($at)
2565-
// 4) sw $8, sym => lui $at, %hi(sym)
2566-
// sw $8, %lo(sym)($at)
2567-
// 5) sw $8, offset($8) => lui $at, %hi(offset)
2568-
// add $at, $at, $8
2569-
// sw $8, %lo(offset)($at)
2570-
// 6) ldc1 $f0, sym => lui $at, %hi(sym)
2571-
// ldc1 $f0, %lo(sym)($at)
2572-
//
2573-
// For load instructions we can use the destination register as a temporary
2574-
// if base and dst are different (examples 1 and 2) and if the base register
2575-
// is general purpose otherwise we must use $at (example 6) and error if it's
2576-
// not available. For stores we must use $at (examples 4 and 5) because we
2577-
// must not clobber the source register setting up the offset.
2547+
2548+
unsigned DstReg = Inst.getOperand(0).getReg();
2549+
unsigned BaseReg = Inst.getOperand(1).getReg();
2550+
25782551
const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2579-
int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2580-
unsigned RegClassIDOp0 =
2581-
getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2582-
bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2583-
(RegClassIDOp0 == Mips::GPR64RegClassID);
2584-
if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
2585-
TmpRegNum = RegOpNum;
2586-
else {
2552+
int16_t DstRegClass = Desc.OpInfo[0].RegClass;
2553+
unsigned DstRegClassID =
2554+
getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
2555+
bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
2556+
(DstRegClassID == Mips::GPR64RegClassID);
2557+
2558+
if (IsImmOpnd) {
2559+
// Try to use DstReg as the temporary.
2560+
if (IsGPR && (BaseReg != DstReg)) {
2561+
TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2562+
Inst.getOperand(2).getImm(), DstReg, IDLoc,
2563+
STI);
2564+
return;
2565+
}
2566+
25872567
// At this point we need AT to perform the expansions and we exit if it is
25882568
// not available.
2589-
TmpRegNum = getATReg(IDLoc);
2590-
if (!TmpRegNum)
2569+
unsigned ATReg = getATReg(IDLoc);
2570+
if (!ATReg)
25912571
return;
2572+
2573+
TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
2574+
Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
2575+
return;
2576+
}
2577+
2578+
const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
2579+
MCOperand LoOperand =
2580+
MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo"));
2581+
MCOperand HiOperand =
2582+
MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi"));
2583+
2584+
// Try to use DstReg as the temporary.
2585+
if (IsGPR && (BaseReg != DstReg)) {
2586+
TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2587+
LoOperand, DstReg, IDLoc, STI);
2588+
return;
2589+
}
2590+
2591+
// At this point we need AT to perform the expansions and we exit if it is
2592+
// not available.
2593+
unsigned ATReg = getATReg(IDLoc);
2594+
if (!ATReg)
2595+
return;
2596+
2597+
TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
2598+
LoOperand, ATReg, IDLoc, STI);
2599+
}
2600+
2601+
void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
2602+
const MCSubtargetInfo *STI,
2603+
bool IsImmOpnd) {
2604+
MipsTargetStreamer &TOut = getTargetStreamer();
2605+
2606+
unsigned SrcReg = Inst.getOperand(0).getReg();
2607+
unsigned BaseReg = Inst.getOperand(1).getReg();
2608+
2609+
unsigned ATReg = getATReg(IDLoc);
2610+
if (!ATReg)
2611+
return;
2612+
2613+
if (IsImmOpnd) {
2614+
TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
2615+
Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
2616+
return;
25922617
}
25932618

2594-
TOut.emitRX(Mips::LUi, TmpRegNum, HiOperand, IDLoc, STI);
2595-
// Add temp register to base.
2596-
if (BaseRegNum != Mips::ZERO)
2597-
TOut.emitRRR(Mips::ADDu, TmpRegNum, TmpRegNum, BaseRegNum, IDLoc, STI);
2598-
// And finally, create original instruction with low part
2599-
// of offset and new base.
2600-
TOut.emitRRX(Inst.getOpcode(), RegOpNum, TmpRegNum, LoOperand, IDLoc, STI);
2619+
const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
2620+
MCOperand LoOperand =
2621+
MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo"));
2622+
MCOperand HiOperand =
2623+
MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi"));
2624+
TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
2625+
LoOperand, ATReg, IDLoc, STI);
26012626
}
26022627

26032628
bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,

‎llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp

+100
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,106 @@ void MipsTargetStreamer::emitNop(SMLoc IDLoc, const MCSubtargetInfo *STI) {
207207
emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
208208
}
209209

210+
/// Emit a store instruction with an immediate offset. The immediate is
211+
/// expected to be out-of-range for a simm16 and will be expanded to
212+
/// appropriate instructions.
213+
void MipsTargetStreamer::emitStoreWithImmOffset(
214+
unsigned Opcode, unsigned SrcReg, unsigned BaseReg, int64_t Offset,
215+
unsigned ATReg, SMLoc IDLoc, const MCSubtargetInfo *STI) {
216+
// sw $8, offset($8) => lui $at, %hi(offset)
217+
// add $at, $at, $8
218+
// sw $8, %lo(offset)($at)
219+
220+
unsigned LoOffset = Offset & 0x0000ffff;
221+
unsigned HiOffset = (Offset & 0xffff0000) >> 16;
222+
223+
// If msb of LoOffset is 1(negative number) we must increment HiOffset
224+
// to account for the sign-extension of the low part.
225+
if (LoOffset & 0x8000)
226+
HiOffset++;
227+
228+
// Generate the base address in ATReg.
229+
emitRI(Mips::LUi, ATReg, HiOffset, IDLoc, STI);
230+
if (BaseReg != Mips::ZERO)
231+
emitRRR(Mips::ADDu, ATReg, ATReg, BaseReg, IDLoc, STI);
232+
// Emit the store with the adjusted base and offset.
233+
emitRRI(Opcode, SrcReg, ATReg, LoOffset, IDLoc, STI);
234+
}
235+
236+
/// Emit a store instruction with an symbol offset. Symbols are assumed to be
237+
/// out of range for a simm16 will be expanded to appropriate instructions.
238+
void MipsTargetStreamer::emitStoreWithSymOffset(
239+
unsigned Opcode, unsigned SrcReg, unsigned BaseReg, MCOperand &HiOperand,
240+
MCOperand &LoOperand, unsigned ATReg, SMLoc IDLoc,
241+
const MCSubtargetInfo *STI) {
242+
// sw $8, sym => lui $at, %hi(sym)
243+
// sw $8, %lo(sym)($at)
244+
245+
// Generate the base address in ATReg.
246+
emitRX(Mips::LUi, ATReg, HiOperand, IDLoc, STI);
247+
if (BaseReg != Mips::ZERO)
248+
emitRRR(Mips::ADDu, ATReg, ATReg, BaseReg, IDLoc, STI);
249+
// Emit the store with the adjusted base and offset.
250+
emitRRX(Opcode, SrcReg, ATReg, LoOperand, IDLoc, STI);
251+
}
252+
253+
/// Emit a load instruction with an immediate offset. The immediate is expected
254+
/// to be out-of-range for a simm16 and will be expanded to appropriate
255+
/// instructions. DstReg and TmpReg are permitted to be the same register iff
256+
/// DstReg is distinct from BaseReg and DstReg is a GPR. It is the callers
257+
/// responsibility to identify such cases and pass the appropriate register in
258+
/// TmpReg.
259+
void MipsTargetStreamer::emitLoadWithImmOffset(unsigned Opcode, unsigned DstReg,
260+
unsigned BaseReg, int64_t Offset,
261+
unsigned TmpReg, SMLoc IDLoc,
262+
const MCSubtargetInfo *STI) {
263+
// 1) lw $8, offset($9) => lui $8, %hi(offset)
264+
// add $8, $8, $9
265+
// lw $8, %lo(offset)($9)
266+
// 2) lw $8, offset($8) => lui $at, %hi(offset)
267+
// add $at, $at, $8
268+
// lw $8, %lo(offset)($at)
269+
270+
unsigned LoOffset = Offset & 0x0000ffff;
271+
unsigned HiOffset = (Offset & 0xffff0000) >> 16;
272+
273+
// If msb of LoOffset is 1(negative number) we must increment HiOffset
274+
// to account for the sign-extension of the low part.
275+
if (LoOffset & 0x8000)
276+
HiOffset++;
277+
278+
// Generate the base address in TmpReg.
279+
emitRI(Mips::LUi, TmpReg, HiOffset, IDLoc, STI);
280+
if (BaseReg != Mips::ZERO)
281+
emitRRR(Mips::ADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI);
282+
// Emit the load with the adjusted base and offset.
283+
emitRRI(Opcode, DstReg, TmpReg, LoOffset, IDLoc, STI);
284+
}
285+
286+
/// Emit a load instruction with an symbol offset. Symbols are assumed to be
287+
/// out of range for a simm16 will be expanded to appropriate instructions.
288+
/// DstReg and TmpReg are permitted to be the same register iff DstReg is a
289+
/// GPR. It is the callers responsibility to identify such cases and pass the
290+
/// appropriate register in TmpReg.
291+
void MipsTargetStreamer::emitLoadWithSymOffset(unsigned Opcode, unsigned DstReg,
292+
unsigned BaseReg,
293+
MCOperand &HiOperand,
294+
MCOperand &LoOperand,
295+
unsigned TmpReg, SMLoc IDLoc,
296+
const MCSubtargetInfo *STI) {
297+
// 1) lw $8, sym => lui $8, %hi(sym)
298+
// lw $8, %lo(sym)($8)
299+
// 2) ldc1 $f0, sym => lui $at, %hi(sym)
300+
// ldc1 $f0, %lo(sym)($at)
301+
302+
// Generate the base address in TmpReg.
303+
emitRX(Mips::LUi, TmpReg, HiOperand, IDLoc, STI);
304+
if (BaseReg != Mips::ZERO)
305+
emitRRR(Mips::ADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI);
306+
// Emit the load with the adjusted base and offset.
307+
emitRRX(Opcode, DstReg, TmpReg, LoOperand, IDLoc, STI);
308+
}
309+
210310
MipsTargetAsmStreamer::MipsTargetAsmStreamer(MCStreamer &S,
211311
formatted_raw_ostream &OS)
212312
: MipsTargetStreamer(S), OS(OS) {}

‎llvm/lib/Target/Mips/MipsTargetStreamer.h

+14
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,20 @@ class MipsTargetStreamer : public MCTargetStreamer {
116116
void emitEmptyDelaySlot(bool hasShortDelaySlot, SMLoc IDLoc,
117117
const MCSubtargetInfo *STI);
118118
void emitNop(SMLoc IDLoc, const MCSubtargetInfo *STI);
119+
void emitStoreWithImmOffset(unsigned Opcode, unsigned SrcReg,
120+
unsigned BaseReg, int64_t Offset, unsigned ATReg,
121+
SMLoc IDLoc, const MCSubtargetInfo *STI);
122+
void emitStoreWithSymOffset(unsigned Opcode, unsigned SrcReg,
123+
unsigned BaseReg, MCOperand &HiOperand,
124+
MCOperand &LoOperand, unsigned ATReg, SMLoc IDLoc,
125+
const MCSubtargetInfo *STI);
126+
void emitLoadWithImmOffset(unsigned Opcode, unsigned DstReg, unsigned BaseReg,
127+
int64_t Offset, unsigned TmpReg, SMLoc IDLoc,
128+
const MCSubtargetInfo *STI);
129+
void emitLoadWithSymOffset(unsigned Opcode, unsigned DstReg, unsigned BaseReg,
130+
MCOperand &HiOperand, MCOperand &LoOperand,
131+
unsigned ATReg, SMLoc IDLoc,
132+
const MCSubtargetInfo *STI);
119133

120134
void forbidModuleDirective() { ModuleDirectiveAllowed = false; }
121135
void reallowModuleDirective() { ModuleDirectiveAllowed = true; }

‎llvm/test/MC/Mips/micromips-expansions.s

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
# CHECK: lw $10, 123($10) # encoding: [0x4a,0xfd,0x7b,0x00]
4040
# CHECK: lui $1, 2 # encoding: [0xa1,0x41,0x02,0x00]
4141
# CHECK: addu $1, $1, $9 # encoding: [0x21,0x01,0x50,0x09]
42-
# CHECK: sw $10, 57920($1) # encoding: [0x41,0xf9,0x40,0xe2]
42+
# CHECK: sw $10, -7616($1) # encoding: [0x41,0xf9,0x40,0xe2]
4343

4444
li $5,123
4545
li $6,-2345

‎llvm/test/MC/Mips/mips-expansions.s

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
sw $10, 123456($9)
4848
# CHECK-LE: lui $1, 2 # encoding: [0x02,0x00,0x01,0x3c]
4949
# CHECK-LE: addu $1, $1, $9 # encoding: [0x21,0x08,0x29,0x00]
50-
# CHECK-LE: sw $10, 57920($1) # encoding: [0x40,0xe2,0x2a,0xac]
50+
# CHECK-LE: sw $10, -7616($1) # encoding: [0x40,0xe2,0x2a,0xac]
5151

5252
lw $8, symbol
5353
# CHECK-LE: lui $8, %hi(symbol) # encoding: [A,A,0x08,0x3c]

0 commit comments

Comments
 (0)
Please sign in to comment.