Skip to content

Commit e8c9d1e

Browse files
author
Jozef Kolek
committedNov 24, 2014
[mips][microMIPS] Implement LBU16, LHU16, LW16, SB16, SH16 and SW16 instructions
Differential Revision: http://reviews.llvm.org/D5122 llvm-svn: 222653
1 parent 1904fa2 commit e8c9d1e

File tree

7 files changed

+209
-0
lines changed

7 files changed

+209
-0
lines changed
 

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

+46
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,15 @@ class MipsOperand : public MCParsedAsmOperand {
765765
addExpr(Inst, Expr);
766766
}
767767

768+
void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
769+
assert(N == 2 && "Invalid number of operands!");
770+
771+
Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPRMM16Reg()));
772+
773+
const MCExpr *Expr = getMemOff();
774+
addExpr(Inst, Expr);
775+
}
776+
768777
void addRegListOperands(MCInst &Inst, unsigned N) const {
769778
assert(N == 1 && "Invalid number of operands!");
770779

@@ -797,6 +806,9 @@ class MipsOperand : public MCParsedAsmOperand {
797806
template <unsigned Bits> bool isMemWithSimmOffset() const {
798807
return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
799808
}
809+
bool isMemWithGRPMM16Base() const {
810+
return isMem() && getMemBase()->isMM16AsmReg();
811+
}
800812
bool isInvNum() const { return Kind == k_Immediate; }
801813
bool isLSAImm() const {
802814
if (!isConstantImm())
@@ -1272,6 +1284,40 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
12721284
Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
12731285
return Error(IDLoc, "immediate operand value out of range");
12741286
break;
1287+
case Mips::LBU16_MM:
1288+
Opnd = Inst.getOperand(2);
1289+
if (!Opnd.isImm())
1290+
return Error(IDLoc, "expected immediate operand kind");
1291+
Imm = Opnd.getImm();
1292+
if (Imm < -1 || Imm > 14)
1293+
return Error(IDLoc, "immediate operand value out of range");
1294+
break;
1295+
case Mips::SB16_MM:
1296+
Opnd = Inst.getOperand(2);
1297+
if (!Opnd.isImm())
1298+
return Error(IDLoc, "expected immediate operand kind");
1299+
Imm = Opnd.getImm();
1300+
if (Imm < 0 || Imm > 15)
1301+
return Error(IDLoc, "immediate operand value out of range");
1302+
break;
1303+
case Mips::LHU16_MM:
1304+
case Mips::SH16_MM:
1305+
Opnd = Inst.getOperand(2);
1306+
if (!Opnd.isImm())
1307+
return Error(IDLoc, "expected immediate operand kind");
1308+
Imm = Opnd.getImm();
1309+
if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1310+
return Error(IDLoc, "immediate operand value out of range");
1311+
break;
1312+
case Mips::LW16_MM:
1313+
case Mips::SW16_MM:
1314+
Opnd = Inst.getOperand(2);
1315+
if (!Opnd.isImm())
1316+
return Error(IDLoc, "expected immediate operand kind");
1317+
Imm = Opnd.getImm();
1318+
if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1319+
return Error(IDLoc, "immediate operand value out of range");
1320+
break;
12751321
}
12761322
}
12771323

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

+42
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,48 @@ MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo,
634634
return (OffBits & 0xFFFF) | RegBits;
635635
}
636636

637+
unsigned MipsMCCodeEmitter::
638+
getMemEncodingMMImm4(const MCInst &MI, unsigned OpNo,
639+
SmallVectorImpl<MCFixup> &Fixups,
640+
const MCSubtargetInfo &STI) const {
641+
// Base register is encoded in bits 6-4, offset is encoded in bits 3-0.
642+
assert(MI.getOperand(OpNo).isReg());
643+
unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),
644+
Fixups, STI) << 4;
645+
unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),
646+
Fixups, STI);
647+
648+
return (OffBits & 0xF) | RegBits;
649+
}
650+
651+
unsigned MipsMCCodeEmitter::
652+
getMemEncodingMMImm4Lsl1(const MCInst &MI, unsigned OpNo,
653+
SmallVectorImpl<MCFixup> &Fixups,
654+
const MCSubtargetInfo &STI) const {
655+
// Base register is encoded in bits 6-4, offset is encoded in bits 3-0.
656+
assert(MI.getOperand(OpNo).isReg());
657+
unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),
658+
Fixups, STI) << 4;
659+
unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),
660+
Fixups, STI) >> 1;
661+
662+
return (OffBits & 0xF) | RegBits;
663+
}
664+
665+
unsigned MipsMCCodeEmitter::
666+
getMemEncodingMMImm4Lsl2(const MCInst &MI, unsigned OpNo,
667+
SmallVectorImpl<MCFixup> &Fixups,
668+
const MCSubtargetInfo &STI) const {
669+
// Base register is encoded in bits 6-4, offset is encoded in bits 3-0.
670+
assert(MI.getOperand(OpNo).isReg());
671+
unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),
672+
Fixups, STI) << 4;
673+
unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),
674+
Fixups, STI) >> 2;
675+
676+
return (OffBits & 0xF) | RegBits;
677+
}
678+
637679
unsigned MipsMCCodeEmitter::
638680
getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo,
639681
SmallVectorImpl<MCFixup> &Fixups,

‎llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h

+9
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,15 @@ class MipsMCCodeEmitter : public MCCodeEmitter {
142142
unsigned getMemEncoding(const MCInst &MI, unsigned OpNo,
143143
SmallVectorImpl<MCFixup> &Fixups,
144144
const MCSubtargetInfo &STI) const;
145+
unsigned getMemEncodingMMImm4(const MCInst &MI, unsigned OpNo,
146+
SmallVectorImpl<MCFixup> &Fixups,
147+
const MCSubtargetInfo &STI) const;
148+
unsigned getMemEncodingMMImm4Lsl1(const MCInst &MI, unsigned OpNo,
149+
SmallVectorImpl<MCFixup> &Fixups,
150+
const MCSubtargetInfo &STI) const;
151+
unsigned getMemEncodingMMImm4Lsl2(const MCInst &MI, unsigned OpNo,
152+
SmallVectorImpl<MCFixup> &Fixups,
153+
const MCSubtargetInfo &STI) const;
145154
unsigned getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo,
146155
SmallVectorImpl<MCFixup> &Fixups,
147156
const MCSubtargetInfo &STI) const;

‎llvm/lib/Target/Mips/MicroMipsInstrFormats.td

+12
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,18 @@ class ADDIUR2_FM_MM16 {
108108
let Inst{0} = 0;
109109
}
110110

111+
class LOAD_STORE_FM_MM16<bits<6> op> {
112+
bits<3> rt;
113+
bits<7> addr;
114+
115+
bits<16> Inst;
116+
117+
let Inst{15-10} = op;
118+
let Inst{9-7} = rt;
119+
let Inst{6-4} = addr{6-4};
120+
let Inst{3-0} = addr{3-0};
121+
}
122+
111123
class ADDIUS5_FM_MM16 {
112124
bits<5> rd;
113125
bits<4> imm;

‎llvm/lib/Target/Mips/MicroMipsInstrInfo.td

+55
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,32 @@ def immZExt2Shift : ImmLeaf<i32, [{return Imm >= 1 && Imm <= 8;}]>;
4646

4747
def immLi16 : ImmLeaf<i32, [{return Imm >= -1 && Imm <= 126;}]>;
4848

49+
def MicroMipsMemGPRMM16AsmOperand : AsmOperandClass {
50+
let Name = "MicroMipsMem";
51+
let RenderMethod = "addMicroMipsMemOperands";
52+
let ParserMethod = "parseMemOperand";
53+
let PredicateMethod = "isMemWithGRPMM16Base";
54+
}
55+
56+
class mem_mm_4_generic : Operand<i32> {
57+
let PrintMethod = "printMemOperand";
58+
let MIOperandInfo = (ops ptr_rc, simm4);
59+
let OperandType = "OPERAND_MEMORY";
60+
let ParserMatchClass = MicroMipsMemGPRMM16AsmOperand;
61+
}
62+
63+
def mem_mm_4 : mem_mm_4_generic {
64+
let EncoderMethod = "getMemEncodingMMImm4";
65+
}
66+
67+
def mem_mm_4_lsl1 : mem_mm_4_generic {
68+
let EncoderMethod = "getMemEncodingMMImm4Lsl1";
69+
}
70+
71+
def mem_mm_4_lsl2 : mem_mm_4_generic {
72+
let EncoderMethod = "getMemEncodingMMImm4Lsl2";
73+
}
74+
4975
def mem_mm_12 : Operand<i32> {
5076
let PrintMethod = "printMemOperand";
5177
let MIOperandInfo = (ops GPR32, simm12);
@@ -156,6 +182,22 @@ class ShiftIMM16<string opstr, Operand ImmOpnd, RegisterOperand RO,
156182
MicroMipsInst16<(outs RO:$rd), (ins RO:$rt, ImmOpnd:$shamt),
157183
!strconcat(opstr, "\t$rd, $rt, $shamt"), [], Itin, FrmR>;
158184

185+
class LoadMM16<string opstr, DAGOperand RO, SDPatternOperator OpNode,
186+
InstrItinClass Itin, Operand MemOpnd> :
187+
MicroMipsInst16<(outs RO:$rt), (ins MemOpnd:$addr),
188+
!strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI> {
189+
let canFoldAsLoad = 1;
190+
let mayLoad = 1;
191+
}
192+
193+
class StoreMM16<string opstr, DAGOperand RTOpnd, DAGOperand RO,
194+
SDPatternOperator OpNode, InstrItinClass Itin,
195+
Operand MemOpnd> :
196+
MicroMipsInst16<(outs), (ins RTOpnd:$rt, MemOpnd:$addr),
197+
!strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI> {
198+
let mayStore = 1;
199+
}
200+
159201
class AddImmUR2<string opstr, RegisterOperand RO> :
160202
MicroMipsInst16<(outs RO:$rd), (ins RO:$rs, simm3_lsa2:$imm),
161203
!strconcat(opstr, "\t$rd, $rs, $imm"),
@@ -316,6 +358,19 @@ def SLL16_MM : ShiftIMM16<"sll16", uimm3_shift, GPRMM16Opnd, II_SLL>,
316358
SHIFT_FM_MM16<0>;
317359
def SRL16_MM : ShiftIMM16<"srl16", uimm3_shift, GPRMM16Opnd, II_SRL>,
318360
SHIFT_FM_MM16<1>;
361+
def LBU16_MM : LoadMM16<"lbu16", GPRMM16Opnd, zextloadi8, II_LBU,
362+
mem_mm_4>, LOAD_STORE_FM_MM16<0x02>;
363+
def LHU16_MM : LoadMM16<"lhu16", GPRMM16Opnd, zextloadi16, II_LHU,
364+
mem_mm_4_lsl1>, LOAD_STORE_FM_MM16<0x0a>;
365+
def LW16_MM : LoadMM16<"lw16", GPRMM16Opnd, load, II_LW, mem_mm_4_lsl2>,
366+
LOAD_STORE_FM_MM16<0x1a>;
367+
def SB16_MM : StoreMM16<"sb16", GPRMM16OpndZero, GPRMM16Opnd, truncstorei8,
368+
II_SB, mem_mm_4>, LOAD_STORE_FM_MM16<0x22>;
369+
def SH16_MM : StoreMM16<"sh16", GPRMM16OpndZero, GPRMM16Opnd, truncstorei16,
370+
II_SH, mem_mm_4_lsl1>,
371+
LOAD_STORE_FM_MM16<0x2a>;
372+
def SW16_MM : StoreMM16<"sw16", GPRMM16OpndZero, GPRMM16Opnd, store, II_SW,
373+
mem_mm_4_lsl2>, LOAD_STORE_FM_MM16<0x3a>;
319374
def ADDIUR1SP_MM : AddImmUR1SP<"addiur1sp", GPRMM16Opnd>, ADDIUR1SP_FM_MM16;
320375
def ADDIUR2_MM : AddImmUR2<"addiur2", GPRMM16Opnd>, ADDIUR2_FM_MM16;
321376
def ADDIUS5_MM : AddImmUS5<"addius5", GPR32Opnd>, ADDIUS5_FM_MM16;

‎llvm/test/MC/Mips/micromips-16-bit-instructions.s

+21
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@
1818
# CHECK-EL: xor16 $17, $5 # encoding: [0x4d,0x44]
1919
# CHECK-EL: sll16 $3, $16, 5 # encoding: [0x8a,0x25]
2020
# CHECK-EL: srl16 $4, $17, 6 # encoding: [0x1d,0x26]
21+
# CHECK-EL: lbu16 $3, 4($17) # encoding: [0x94,0x09]
22+
# CHECK-EL: lhu16 $3, 4($16) # encoding: [0x82,0x29]
23+
# CHECK-EL: lw16 $4, 8($17) # encoding: [0x12,0x6a]
24+
# CHECK-EL: sb16 $3, 4($16) # encoding: [0x84,0x89]
25+
# CHECK-EL: sh16 $4, 8($17) # encoding: [0x14,0xaa]
26+
# CHECK-EL: sw16 $4, 4($17) # encoding: [0x11,0xea]
27+
# CHECK-EL: sw16 $zero, 4($17) # encoding: [0x11,0xe8]
2128
# CHECK-EL: li16 $3, -1 # encoding: [0xff,0xed]
2229
# CHECK-EL: li16 $3, 126 # encoding: [0xfe,0xed]
2330
# CHECK-EL: addiur1sp $7, 4 # encoding: [0x83,0x6f]
@@ -48,6 +55,13 @@
4855
# CHECK-EB: xor16 $17, $5 # encoding: [0x44,0x4d]
4956
# CHECK-EB: sll16 $3, $16, 5 # encoding: [0x25,0x8a]
5057
# CHECK-EB: srl16 $4, $17, 6 # encoding: [0x26,0x1d]
58+
# CHECK-EB: lbu16 $3, 4($17) # encoding: [0x09,0x94]
59+
# CHECK-EB: lhu16 $3, 4($16) # encoding: [0x29,0x82]
60+
# CHECK-EB: lw16 $4, 8($17) # encoding: [0x6a,0x12]
61+
# CHECK-EB: sb16 $3, 4($16) # encoding: [0x89,0x84]
62+
# CHECK-EB: sh16 $4, 8($17) # encoding: [0xaa,0x14]
63+
# CHECK-EB: sw16 $4, 4($17) # encoding: [0xea,0x11]
64+
# CHECK-EB: sw16 $zero, 4($17) # encoding: [0xe8,0x11]
5165
# CHECK-EB: li16 $3, -1 # encoding: [0xed,0xff]
5266
# CHECK-EB: li16 $3, 126 # encoding: [0xed,0xfe]
5367
# CHECK-EB: addiur1sp $7, 4 # encoding: [0x6f,0x83]
@@ -76,6 +90,13 @@
7690
xor16 $17, $5
7791
sll16 $3, $16, 5
7892
srl16 $4, $17, 6
93+
lbu16 $3, 4($17)
94+
lhu16 $3, 4($16)
95+
lw16 $4, 8($17)
96+
sb16 $3, 4($16)
97+
sh16 $4, 8($17)
98+
sw16 $4, 4($17)
99+
sw16 $0, 4($17)
79100
li16 $3, -1
80101
li16 $3, 126
81102
addiur1sp $7, 4

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

+24
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,27 @@
2929
swm32 $16, $19, 8($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: consecutive register numbers expected
3030
swm32 $16-$25, 8($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid register operand
3131
lwm32 $16, $17, $18, $19, $20, $21, $22, $23, $24, 8($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid register operand
32+
lbu16 $9, 8($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
33+
lhu16 $9, 4($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
34+
lw16 $9, 8($17) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
35+
sb16 $9, 4($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
36+
sh16 $9, 8($17) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
37+
sw16 $9, 4($17) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
38+
lbu16 $3, -2($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range
39+
lhu16 $3, 64($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range
40+
lw16 $4, 68($17) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range
41+
sb16 $3, 64($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range
42+
sh16 $4, 68($17) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range
43+
sw16 $4, 64($17) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range
44+
lbu16 $3, -2($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range
45+
lhu16 $3, 64($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range
46+
lw16 $4, 68($17) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range
47+
sb16 $16, 4($16) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
48+
sh16 $16, 8($17) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
49+
sw16 $16, 4($17) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
50+
lbu16 $16, 8($9) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
51+
lhu16 $16, 4($9) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
52+
lw16 $17, 8($10) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
53+
sb16 $7, 4($9) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
54+
sh16 $7, 8($9) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
55+
sw16 $7, 4($10) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction

0 commit comments

Comments
 (0)
Please sign in to comment.