//===-- ARMInstrThumb.td - Thumb support for ARM -----------*- tablegen -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file describes the Thumb instruction set. // //===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// // Thumb specific DAG Nodes. // def ARMtsecall : SDNode<"ARMISD::tSECALL", SDT_ARMcall, [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, SDNPVariadic]>; def imm_sr_XFORM: SDNodeXFormgetZExtValue(); return CurDAG->getTargetConstant((Imm == 32 ? 0 : Imm), SDLoc(N), MVT::i32); }]>; def ThumbSRImmAsmOperand: ImmAsmOperand<1,32> { let Name = "ImmThumbSR"; } def imm_sr : Operand, PatLeaf<(imm), [{ uint64_t Imm = N->getZExtValue(); return Imm > 0 && Imm <= 32; }], imm_sr_XFORM> { let PrintMethod = "printThumbSRImm"; let ParserMatchClass = ThumbSRImmAsmOperand; } def imm0_7_neg : PatLeaf<(i32 imm), [{ return (uint32_t)-N->getZExtValue() < 8; }], imm_neg_XFORM>; def ThumbModImmNeg1_7AsmOperand : AsmOperandClass { let Name = "ThumbModImmNeg1_7"; } def mod_imm1_7_neg : Operand, PatLeaf<(imm), [{ unsigned Value = -(unsigned)N->getZExtValue(); return 0 < Value && Value < 8; }], imm_neg_XFORM> { let ParserMatchClass = ThumbModImmNeg1_7AsmOperand; } def ThumbModImmNeg8_255AsmOperand : AsmOperandClass { let Name = "ThumbModImmNeg8_255"; } def mod_imm8_255_neg : Operand, PatLeaf<(imm), [{ unsigned Value = -(unsigned)N->getZExtValue(); return 7 < Value && Value < 256; }], imm_neg_XFORM> { let ParserMatchClass = ThumbModImmNeg8_255AsmOperand; } def imm0_255_comp : PatLeaf<(i32 imm), [{ return ~((uint32_t)N->getZExtValue()) < 256; }]>; def imm8_255_neg : PatLeaf<(i32 imm), [{ unsigned Val = -N->getZExtValue(); return Val >= 8 && Val < 256; }], imm_neg_XFORM>; // Break imm's up into two pieces: an immediate + a left shift. This uses // thumb_immshifted to match and thumb_immshifted_val and thumb_immshifted_shamt // to get the val/shift pieces. def thumb_immshifted : PatLeaf<(imm), [{ return ARM_AM::isThumbImmShiftedVal((unsigned)N->getZExtValue()); }]>; def thumb_immshifted_val : SDNodeXFormgetZExtValue()); return CurDAG->getTargetConstant(V, SDLoc(N), MVT::i32); }]>; def thumb_immshifted_shamt : SDNodeXFormgetZExtValue()); return CurDAG->getTargetConstant(V, SDLoc(N), MVT::i32); }]>; def imm256_510 : ImmLeaf= 256 && Imm < 511; }]>; def thumb_imm256_510_addend : SDNodeXFormgetTargetConstant(N->getZExtValue() - 255, SDLoc(N), MVT::i32); }]>; // Scaled 4 immediate. def t_imm0_1020s4_asmoperand: AsmOperandClass { let Name = "Imm0_1020s4"; } def t_imm0_1020s4 : Operand { let PrintMethod = "printThumbS4ImmOperand"; let ParserMatchClass = t_imm0_1020s4_asmoperand; let OperandType = "OPERAND_IMMEDIATE"; } def t_imm0_508s4_asmoperand: AsmOperandClass { let Name = "Imm0_508s4"; } def t_imm0_508s4 : Operand { let PrintMethod = "printThumbS4ImmOperand"; let ParserMatchClass = t_imm0_508s4_asmoperand; let OperandType = "OPERAND_IMMEDIATE"; } // Alias use only, so no printer is necessary. def t_imm0_508s4_neg_asmoperand: AsmOperandClass { let Name = "Imm0_508s4Neg"; } def t_imm0_508s4_neg : Operand { let ParserMatchClass = t_imm0_508s4_neg_asmoperand; let OperandType = "OPERAND_IMMEDIATE"; } // Define Thumb specific addressing modes. // unsigned 8-bit, 2-scaled memory offset class OperandUnsignedOffset_b8s2 : AsmOperandClass { let Name = "UnsignedOffset_b8s2"; let PredicateMethod = "isUnsignedOffset<8, 2>"; } def UnsignedOffset_b8s2 : OperandUnsignedOffset_b8s2; // thumb style PC relative operand. signed, 8 bits magnitude, // two bits shift. can be represented as either [pc, #imm], #imm, // or relocatable expression... def ThumbMemPC : AsmOperandClass { let Name = "ThumbMemPC"; } let OperandType = "OPERAND_PCREL" in { def t_brtarget : Operand { let EncoderMethod = "getThumbBRTargetOpValue"; let DecoderMethod = "DecodeThumbBROperand"; } // ADR instruction labels. def t_adrlabel : Operand { let EncoderMethod = "getThumbAdrLabelOpValue"; let PrintMethod = "printAdrLabelOperand<2>"; let ParserMatchClass = UnsignedOffset_b8s2; } def thumb_br_target : Operand { let ParserMatchClass = ThumbBranchTarget; let EncoderMethod = "getThumbBranchTargetOpValue"; let OperandType = "OPERAND_PCREL"; } def thumb_bl_target : Operand { let ParserMatchClass = ThumbBranchTarget; let EncoderMethod = "getThumbBLTargetOpValue"; let DecoderMethod = "DecodeThumbBLTargetOperand"; } // Target for BLX *from* thumb mode. def thumb_blx_target : Operand { let ParserMatchClass = ARMBranchTarget; let EncoderMethod = "getThumbBLXTargetOpValue"; let DecoderMethod = "DecodeThumbBLXOffset"; } def thumb_bcc_target : Operand { let ParserMatchClass = ThumbBranchTarget; let EncoderMethod = "getThumbBCCTargetOpValue"; let DecoderMethod = "DecodeThumbBCCTargetOperand"; } def thumb_cb_target : Operand { let ParserMatchClass = ThumbBranchTarget; let EncoderMethod = "getThumbCBTargetOpValue"; let DecoderMethod = "DecodeThumbCmpBROperand"; } // t_addrmode_pc :=