llvm.org GIT mirror llvm / ac79e4c
- Implement asm parsing support for LDRSBT, LDRHT, LDRSHT and STRHT also fix the encoding of the later. - Add a new encoding bit to describe the index mode used in AM3. - Teach printAddrMode3Operand to check by the addressing mode which index mode to print. - Testcases. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@128832 91177308-0d34-0410-b5e6-96231b3b80d8 Bruno Cardoso Lopes 9 years ago
8 changed file(s) with 258 addition(s) and 32 deletion(s). Raw diff Collapse all Expand all
408408 // The first operand is always a Reg. The second operand is a reg if in
409409 // reg/reg form, otherwise it's reg#0. The third field encodes the operation
410410 // in bit 12, the immediate in bits 0-11, and the shift op in 13-15. The
411 // forth operand 16-17 encodes the index mode.
411 // fourth operand 16-17 encodes the index mode.
412412 //
413413 // If this addressing mode is a frame index (before prolog/epilog insertion
414414 // and code rewriting), this operand will have the form: FI#, reg0,
445445 //
446446 // The first operand is always a Reg. The second operand is a reg if in
447447 // reg/reg form, otherwise it's reg#0. The third field encodes the operation
448 // in bit 8, the immediate in bits 0-7.
448 // in bit 8, the immediate in bits 0-7. The fourth operand 9-10 encodes the
449 // index mode.
449450
450451 /// getAM3Opc - This function encodes the addrmode3 opc field.
451 static inline unsigned getAM3Opc(AddrOpc Opc, unsigned char Offset) {
452 static inline unsigned getAM3Opc(AddrOpc Opc, unsigned char Offset,
453 unsigned IdxMode = 0) {
452454 bool isSub = Opc == sub;
453 return ((int)isSub << 8) | Offset;
455 return ((int)isSub << 8) | Offset | (IdxMode << 9);
454456 }
455457 static inline unsigned char getAM3Offset(unsigned AM3Opc) {
456458 return AM3Opc & 0xFF;
457459 }
458460 static inline AddrOpc getAM3Op(unsigned AM3Opc) {
459461 return ((AM3Opc >> 8) & 1) ? sub : add;
462 }
463 static inline unsigned getAM3IdxMode(unsigned AM3Opc) {
464 return (AM3Opc >> 9);
460465 }
461466
462467 //===--------------------------------------------------------------------===//
576576 let Inst{15-12} = Rt; // Rt
577577 let Inst{7-4} = op;
578578 }
579
580 // FIXME: Merge with the above class when addrmode2 gets used for LDR, LDRB
581 // but for now use this class for LDRSBT, LDRHT, LDSHT.
582 class AI3ldstidxT op, bit op20, bit isLd, bit isPre, dag oops, dag iops,
583 IndexMode im, Format f, InstrItinClass itin, string opc,
584 string asm, string cstr, list pattern>
585 : I
586 opc, asm, cstr, pattern> {
587 // {13} 1 == imm8, 0 == Rm
588 // {12-9} Rn
589 // {8} isAdd
590 // {7-4} imm7_4/zero
591 // {3-0} imm3_0/Rm
592 bits<14> addr;
593 bits<4> Rt;
594 let Inst{27-25} = 0b000;
595 let Inst{24} = isPre; // P bit
596 let Inst{23} = addr{8}; // U bit
597 let Inst{22} = addr{13}; // 1 == imm8, 0 == Rm
598 let Inst{20} = op20; // L bit
599 let Inst{19-16} = addr{12-9}; // Rn
600 let Inst{15-12} = Rt; // Rt
601 let Inst{11-8} = addr{7-4}; // imm7_4/zero
602 let Inst{7-4} = op;
603 let Inst{3-0} = addr{3-0}; // imm3_0/Rm
604 let AsmMatchConverter = "CvtLdWriteBackRegAddrMode3";
605 }
606
579607 class AI3stridx op, bit isByte, bit isPre, dag oops, dag iops,
580608 IndexMode im, Format f, InstrItinClass itin, string opc,
581609 string asm, string cstr, list pattern>
648676 string opc, string asm, string cstr, list pattern>
649677 : I
650678 opc, asm, cstr,pattern> {
679 // {13} 1 == imm8, 0 == Rm
680 // {12-9} Rn
681 // {8} isAdd
682 // {7-4} imm7_4/zero
683 // {3-0} imm3_0/Rm
684 bits<14> addr;
685 bits<4> Rt;
686 let Inst{3-0} = addr{3-0}; // imm3_0/Rm
651687 let Inst{4} = 1;
652688 let Inst{5} = 1; // H bit
653689 let Inst{6} = 0; // S bit
654690 let Inst{7} = 1;
691 let Inst{11-8} = addr{7-4}; // imm7_4/zero
692 let Inst{15-12} = Rt; // Rt
693 let Inst{19-16} = addr{12-9}; // Rn
655694 let Inst{20} = 0; // L bit
656695 let Inst{21} = 0; // W bit
696 let Inst{22} = addr{13}; // 1 == imm8, 0 == Rm
697 let Inst{23} = addr{8}; // U bit
657698 let Inst{24} = 0; // P bit
658699 let Inst{27-25} = 0b000;
659700 }
474474
475475 // Define ARM specific addressing modes.
476476
477 def MemMode2AsmOperand : AsmOperandClass {
478 let Name = "MemMode2";
479 let SuperClasses = [];
480 let ParserMethod = "tryParseMemMode2Operand";
481 }
482
483 def MemMode3AsmOperand : AsmOperandClass {
484 let Name = "MemMode3";
485 let SuperClasses = [];
486 let ParserMethod = "tryParseMemMode3Operand";
487 }
477488
478489 // addrmode_imm12 := reg +/- imm12
479490 //
497508 let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);
498509 }
499510
500 def MemMode2AsmOperand : AsmOperandClass {
501 let Name = "MemMode2";
502 let SuperClasses = [];
503 let ParserMethod = "tryParseMemMode2Operand";
504 }
505
506511 // addrmode2 := reg +/- imm12
507512 // := reg +/- reg shop imm
508513 //
529534 ComplexPattern {
530535 let EncoderMethod = "getAddrMode3OpValue";
531536 let PrintMethod = "printAddrMode3Operand";
537 let ParserMatchClass = MemMode3AsmOperand;
532538 let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);
533539 }
534540
17621768 let Inst{11-0} = addr{11-0};
17631769 let AsmMatchConverter = "CvtLdWriteBackRegAddrMode2";
17641770 }
1765 def LDRSBT : AI3ldstidx<0b1101, 1, 1, 0, (outs GPR:$dst, GPR:$base_wb),
1766 (ins GPR:$base, am3offset:$offset), IndexModePost,
1767 LdMiscFrm, IIC_iLoad_bh_ru,
1768 "ldrsbt", "\t$dst, [$base], $offset", "$base = $base_wb", []> {
1771 def LDRSBT : AI3ldstidxT<0b1101, 1, 1, 0, (outs GPR:$Rt, GPR:$base_wb),
1772 (ins addrmode3:$addr), IndexModePost, LdMiscFrm, IIC_iLoad_bh_ru,
1773 "ldrsbt", "\t$Rt, $addr", "$addr.base = $base_wb", []> {
17691774 let Inst{21} = 1; // overwrite
17701775 }
1771 def LDRHT : AI3ldstidx<0b1011, 1, 1, 0, (outs GPR:$dst, GPR:$base_wb),
1772 (ins GPR:$base, am3offset:$offset), IndexModePost,
1773 LdMiscFrm, IIC_iLoad_bh_ru,
1774 "ldrht", "\t$dst, [$base], $offset", "$base = $base_wb", []> {
1776 def LDRHT : AI3ldstidxT<0b1011, 1, 1, 0, (outs GPR:$Rt, GPR:$base_wb),
1777 (ins addrmode3:$addr), IndexModePost, LdMiscFrm, IIC_iLoad_bh_ru,
1778 "ldrht", "\t$Rt, $addr", "$addr.base = $base_wb", []> {
17751779 let Inst{21} = 1; // overwrite
17761780 }
1777 def LDRSHT : AI3ldstidx<0b1111, 1, 1, 0, (outs GPR:$dst, GPR:$base_wb),
1778 (ins GPR:$base, am3offset:$offset), IndexModePost,
1779 LdMiscFrm, IIC_iLoad_bh_ru,
1780 "ldrsht", "\t$dst, [$base], $offset", "$base = $base_wb", []> {
1781 def LDRSHT : AI3ldstidxT<0b1111, 1, 1, 0, (outs GPR:$Rt, GPR:$base_wb),
1782 (ins addrmode3:$addr), IndexModePost, LdMiscFrm, IIC_iLoad_bh_ru,
1783 "ldrsht", "\t$Rt, $addr", "$addr.base = $base_wb", []> {
17811784 let Inst{21} = 1; // overwrite
17821785 }
17831786 }
18691872 let AsmMatchConverter = "CvtStWriteBackRegAddrMode2";
18701873 }
18711874
1872 def STRHT: AI3sthpo<(outs GPR:$base_wb),
1873 (ins GPR:$src, GPR:$base,am3offset:$offset),
1875 def STRHT: AI3sthpo<(outs GPR:$base_wb), (ins GPR:$Rt, addrmode3:$addr),
18741876 StMiscFrm, IIC_iStore_bh_ru,
1875 "strht", "\t$src, [$base], $offset", "$base = $base_wb",
1877 "strht", "\t$Rt, $addr", "$addr.base = $base_wb",
18761878 [/* For disassembly only; pattern left blank */]> {
18771879 let Inst{21} = 1; // overwrite
1880 let AsmMatchConverter = "CvtStWriteBackRegAddrMode3";
18781881 }
18791882
18801883 //===----------------------------------------------------------------------===//
9797 SmallVectorImpl&);
9898 OperandMatchResultTy tryParseMemMode2Operand(
9999 SmallVectorImpl&);
100 OperandMatchResultTy tryParseMemMode3Operand(
101 SmallVectorImpl&);
100102
101103 // Asm Match Converter Methods
102104 bool CvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
103105 const SmallVectorImpl &);
104106 bool CvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
107 const SmallVectorImpl &);
108 bool CvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
109 const SmallVectorImpl &);
110 bool CvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
105111 const SmallVectorImpl &);
106112
107113 public:
370376
371377 return true;
372378 }
379 bool isMemMode3() const {
380 if (getMemAddrMode() != ARMII::AddrMode3)
381 return false;
382
383 if (getMemOffsetIsReg()) {
384 if (getMemOffsetRegShifted())
385 return false; // No shift with offset reg allowed
386 return true;
387 }
388
389 if (getMemNegative() &&
390 !(getMemPostindexed() || getMemPreindexed()))
391 return false;
392
393 const MCConstantExpr *CE = dyn_cast(getMemOffset());
394 if (!CE) return false;
395 int64_t Value = CE->getValue();
396
397 // The offset must be in the range 0-255 (imm8).
398 if (Value > 255 || Value < -255)
399 return false;
400
401 return true;
402 }
373403 bool isMemMode5() const {
374404 if (!isMemory() || getMemOffsetIsReg() || getMemWriteback() ||
375405 getMemNegative())
536566 else
537567 Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM2Opc(ARM_AM::sub,
538568 -Offset, ARM_AM::no_shift, IdxMode)));
569 }
570
571 void addMemMode3Operands(MCInst &Inst, unsigned N) const {
572 assert(isMemMode3() && "Invalid mode or number of operands!");
573 Inst.addOperand(MCOperand::CreateReg(getMemBaseRegNum()));
574 unsigned IdxMode = (getMemPreindexed() | getMemPostindexed() << 1);
575
576 if (getMemOffsetIsReg()) {
577 Inst.addOperand(MCOperand::CreateReg(getMemOffsetRegNum()));
578
579 ARM_AM::AddrOpc AMOpc = getMemNegative() ? ARM_AM::sub : ARM_AM::add;
580 Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM3Opc(AMOpc, 0,
581 IdxMode)));
582 return;
583 }
584
585 // Create a operand placeholder to always yield the same number of operands.
586 Inst.addOperand(MCOperand::CreateReg(0));
587
588 // FIXME: #-0 is encoded differently than #0. Does the parser preserve
589 // the difference?
590 const MCConstantExpr *CE = dyn_cast(getMemOffset());
591 assert(CE && "Non-constant mode 3 offset operand!");
592 int64_t Offset = CE->getValue();
593
594 if (Offset >= 0)
595 Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM3Opc(ARM_AM::add,
596 Offset, IdxMode)));
597 else
598 Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM3Opc(ARM_AM::sub,
599 -Offset, IdxMode)));
539600 }
540601
541602 void addMemMode5Operands(MCInst &Inst, unsigned N) const {
12181279 return MatchOperand_Success;
12191280 }
12201281
1282 /// tryParseMemMode3Operand - Try to parse memory addressing mode 3 operand.
1283 ARMAsmParser::OperandMatchResultTy ARMAsmParser::
1284 tryParseMemMode3Operand(SmallVectorImpl &Operands) {
1285 assert(Parser.getTok().is(AsmToken::LBrac) && "Token is not a \"[\"");
1286
1287 if (ParseMemory(Operands, ARMII::AddrMode3))
1288 return MatchOperand_NoMatch;
1289
1290 return MatchOperand_Success;
1291 }
1292
12211293 /// CvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
12221294 /// Needed here because the Asm Gen Matcher can't handle properly tied operands
12231295 /// when they refer multiple MIOperands inside a single one.
12441316 Inst.addOperand(MCOperand::CreateImm(0));
12451317 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
12461318 ((ARMOperand*)Operands[3])->addMemMode2Operands(Inst, 3);
1319 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
1320 return true;
1321 }
1322
1323 /// CvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
1324 /// Needed here because the Asm Gen Matcher can't handle properly tied operands
1325 /// when they refer multiple MIOperands inside a single one.
1326 bool ARMAsmParser::
1327 CvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
1328 const SmallVectorImpl &Operands) {
1329 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
1330
1331 // Create a writeback register dummy placeholder.
1332 Inst.addOperand(MCOperand::CreateImm(0));
1333
1334 ((ARMOperand*)Operands[3])->addMemMode3Operands(Inst, 3);
1335 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
1336 return true;
1337 }
1338
1339 /// CvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
1340 /// Needed here because the Asm Gen Matcher can't handle properly tied operands
1341 /// when they refer multiple MIOperands inside a single one.
1342 bool ARMAsmParser::
1343 CvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
1344 const SmallVectorImpl &Operands) {
1345 // Create a writeback register dummy placeholder.
1346 Inst.addOperand(MCOperand::CreateImm(0));
1347 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
1348 ((ARMOperand*)Operands[3])->addMemMode3Operands(Inst, 3);
12471349 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
12481350 return true;
12491351 }
13091411
13101412 const AsmToken &ExclaimTok = Parser.getTok();
13111413 if (ExclaimTok.is(AsmToken::Exclaim)) {
1414 // None of addrmode3 instruction uses "!"
1415 if (AddrMode == ARMII::AddrMode3)
1416 return true;
1417
13121418 WBOp = ARMOperand::CreateToken(ExclaimTok.getString(),
13131419 ExclaimTok.getLoc());
13141420 Writeback = true;
13491455 if (!OffsetIsReg) {
13501456 if (!Offset)
13511457 Offset = MCConstantExpr::Create(0, getContext());
1458 } else {
1459 if (AddrMode == ARMII::AddrMode3 && OffsetRegShifted) {
1460 Error(E, "shift amount not supported");
1461 return true;
1462 }
13521463 }
13531464
13541465 Operands.push_back(ARMOperand::CreateMem(AddrMode, BaseRegNum, OffsetIsReg,
12361236 "Expect 1 reg operand followed by 1 imm operand");
12371237
12381238 ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub;
1239 unsigned IndexMode =
1240 (TID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift;
12391241 if (getAM3IBit(insn) == 1) {
12401242 MI.addOperand(MCOperand::CreateReg(0));
12411243
12421244 // Disassemble the 8-bit immediate offset.
12431245 unsigned Imm4H = (insn >> ARMII::ImmHiShift) & 0xF;
12441246 unsigned Imm4L = insn & 0xF;
1245 unsigned Offset = ARM_AM::getAM3Opc(AddrOpcode, (Imm4H << 4) | Imm4L);
1247 unsigned Offset = ARM_AM::getAM3Opc(AddrOpcode, (Imm4H << 4) | Imm4L,
1248 IndexMode);
12461249 MI.addOperand(MCOperand::CreateImm(Offset));
12471250 } else {
12481251 // Disassemble the offset reg (Rm).
12491252 MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
12501253 decodeRm(insn))));
1251 unsigned Offset = ARM_AM::getAM3Opc(AddrOpcode, 0);
1254 unsigned Offset = ARM_AM::getAM3Opc(AddrOpcode, 0, IndexMode);
12521255 MI.addOperand(MCOperand::CreateImm(Offset));
12531256 }
12541257 OpIdx += 2;
180180 }
181181 }
182182
183 //===--------------------------------------------------------------------===//
184 // Addressing Mode #2
185 //===--------------------------------------------------------------------===//
186
183187 void ARMInstPrinter::printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
184188 raw_ostream &O) {
185189 const MCOperand &MO1 = MI->getOperand(Op);
275279 << " #" << ShImm;
276280 }
277281
278 void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned OpNum,
279 raw_ostream &O) {
280 const MCOperand &MO1 = MI->getOperand(OpNum);
281 const MCOperand &MO2 = MI->getOperand(OpNum+1);
282 const MCOperand &MO3 = MI->getOperand(OpNum+2);
282 //===--------------------------------------------------------------------===//
283 // Addressing Mode #3
284 //===--------------------------------------------------------------------===//
285
286 void ARMInstPrinter::printAM3PostIndexOp(const MCInst *MI, unsigned Op,
287 raw_ostream &O) {
288 const MCOperand &MO1 = MI->getOperand(Op);
289 const MCOperand &MO2 = MI->getOperand(Op+1);
290 const MCOperand &MO3 = MI->getOperand(Op+2);
291
292 O << "[" << getRegisterName(MO1.getReg()) << "], ";
293
294 if (MO2.getReg()) {
295 O << (char)ARM_AM::getAM3Op(MO3.getImm())
296 << getRegisterName(MO2.getReg());
297 return;
298 }
299
300 unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm());
301 O << '#'
302 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
303 << ImmOffs;
304 }
305
306 void ARMInstPrinter::printAM3PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
307 raw_ostream &O) {
308 const MCOperand &MO1 = MI->getOperand(Op);
309 const MCOperand &MO2 = MI->getOperand(Op+1);
310 const MCOperand &MO3 = MI->getOperand(Op+2);
283311
284312 O << '[' << getRegisterName(MO1.getReg());
285313
294322 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
295323 << ImmOffs;
296324 O << ']';
325 }
326
327 void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned Op,
328 raw_ostream &O) {
329 const MCOperand &MO3 = MI->getOperand(Op+2);
330 unsigned IdxMode = ARM_AM::getAM3IdxMode(MO3.getImm());
331
332 if (IdxMode == ARMII::IndexModePost) {
333 printAM3PostIndexOp(MI, Op, O);
334 return;
335 }
336 printAM3PreOrOffsetIndexOp(MI, Op, O);
297337 }
298338
299339 void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,
4848 raw_ostream &O);
4949 void printAddrMode2OffsetOperand(const MCInst *MI, unsigned OpNum,
5050 raw_ostream &O);
51
5152 void printAddrMode3Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
53 void printAM3PostIndexOp(const MCInst *MI, unsigned OpNum, raw_ostream &O);
54 void printAM3PreOrOffsetIndexOp(const MCInst *MI, unsigned OpNum,
55 raw_ostream &O);
5256 void printAddrMode3OffsetOperand(const MCInst *MI, unsigned OpNum,
5357 raw_ostream &O);
58
5459 void printLdStmModeOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
5560 void printAddrMode5Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
5661 void printAddrMode6Operand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
0 @ RUN: llvm-mc -mcpu=cortex-a8 -triple arm-unknown-unknown -show-encoding %s | FileCheck %s
1
2 @ CHECK: ldrsbt r1, [r0], +r2 @ encoding: [0xd2,0x10,0xb0,0xe0]
3 @ CHECK: ldrsbt r1, [r0], #4 @ encoding: [0xd4,0x10,0xf0,0xe0]
4 @ CHECK: ldrsht r1, [r0], +r2 @ encoding: [0xf2,0x10,0xb0,0xe0]
5 @ CHECK: ldrsht r1, [r0], #4 @ encoding: [0xf4,0x10,0xf0,0xe0]
6 @ CHECK: ldrht r1, [r0], +r2 @ encoding: [0xb2,0x10,0xb0,0xe0]
7 @ CHECK: ldrht r1, [r0], #4 @ encoding: [0xb4,0x10,0xf0,0xe0]
8 @ CHECK: strht r1, [r0], +r2 @ encoding: [0xb2,0x10,0xa0,0xe0]
9 @ CHECK: strht r1, [r0], #4 @ encoding: [0xb4,0x10,0xe0,0xe0]
10 ldrsbt r1, [r0], r2
11 ldrsbt r1, [r0], #4
12 ldrsht r1, [r0], r2
13 ldrsht r1, [r0], #4
14 ldrht r1, [r0], r2
15 ldrht r1, [r0], #4
16 strht r1, [r0], r2
17 strht r1, [r0], #4