Skip to content
ARMInstrThumb.td 38.3 KiB
Newer Older
//===- ARMInstrThumb.td - Thumb support for ARM ---------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file describes the Thumb instruction set.
//
//===----------------------------------------------------------------------===//

//===----------------------------------------------------------------------===//
// Thumb specific DAG Nodes.
//

def ARMtcall : SDNode<"ARMISD::tCALL", SDT_ARMcall,
                      [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;

def imm_neg_XFORM : SDNodeXForm<imm, [{
  return CurDAG->getTargetConstant(-(int)N->getZExtValue(), MVT::i32);
}]>;
def imm_comp_XFORM : SDNodeXForm<imm, [{
  return CurDAG->getTargetConstant(~((uint32_t)N->getZExtValue()), MVT::i32);
}]>;


/// imm0_7 predicate - True if the 32-bit immediate is in the range [0,7].
def imm0_7 : PatLeaf<(i32 imm), [{
  return (uint32_t)N->getZExtValue() < 8;
}]>;
def imm0_7_neg : PatLeaf<(i32 imm), [{
  return (uint32_t)-N->getZExtValue() < 8;
}], imm_neg_XFORM>;

def imm0_255 : PatLeaf<(i32 imm), [{
  return (uint32_t)N->getZExtValue() < 256;
}]>;
def imm0_255_comp : PatLeaf<(i32 imm), [{
  return ~((uint32_t)N->getZExtValue()) < 256;
}]>;

def imm8_255 : PatLeaf<(i32 imm), [{
  return (uint32_t)N->getZExtValue() >= 8 && (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 : SDNodeXForm<imm, [{
  unsigned V = ARM_AM::getThumbImmNonShiftedVal((unsigned)N->getZExtValue());
  return CurDAG->getTargetConstant(V, MVT::i32);
}]>;

def thumb_immshifted_shamt : SDNodeXForm<imm, [{
  unsigned V = ARM_AM::getThumbImmValShift((unsigned)N->getZExtValue());
  return CurDAG->getTargetConstant(V, MVT::i32);
// Scaled 4 immediate.
def t_imm_s4 : Operand<i32> {
  let PrintMethod = "printThumbS4ImmOperand";
}

// Define Thumb specific addressing modes.

// t_addrmode_rr := reg + reg
//
def t_addrmode_rr : Operand<i32>,
                    ComplexPattern<i32, 2, "SelectThumbAddrModeRR", []> {
  let PrintMethod = "printThumbAddrModeRROperand";
  let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg);
// t_addrmode_s4 := reg + reg
//                  reg + imm5 * 4
def t_addrmode_s4 : Operand<i32>,
                    ComplexPattern<i32, 3, "SelectThumbAddrModeS4", []> {
  let PrintMethod = "printThumbAddrModeS4Operand";
  let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg);

// t_addrmode_s2 := reg + reg
//                  reg + imm5 * 2
//
def t_addrmode_s2 : Operand<i32>,
                    ComplexPattern<i32, 3, "SelectThumbAddrModeS2", []> {
  let PrintMethod = "printThumbAddrModeS2Operand";
  let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg);

// t_addrmode_s1 := reg + reg
//                  reg + imm5
//
def t_addrmode_s1 : Operand<i32>,
                    ComplexPattern<i32, 3, "SelectThumbAddrModeS1", []> {
  let PrintMethod = "printThumbAddrModeS1Operand";
  let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm, tGPR:$offsreg);
}

// t_addrmode_sp := sp + imm8 * 4
//
def t_addrmode_sp : Operand<i32>,
                    ComplexPattern<i32, 2, "SelectThumbAddrModeSP", []> {
  let PrintMethod = "printThumbAddrModeSPOperand";
  let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
}

//===----------------------------------------------------------------------===//
//  Miscellaneous Instructions.
//

// FIXME: Marking these as hasSideEffects is necessary to prevent machine DCE
// from removing one half of the matched pairs. That breaks PEI, which assumes
// these will always be in pairs, and asserts if it finds otherwise. Better way?
let Defs = [SP], Uses = [SP], hasSideEffects = 1 in {
PseudoInst<(outs), (ins i32imm:$amt1, i32imm:$amt2), NoItinerary,
           [(ARMcallseq_end imm:$amt1, imm:$amt2)]>, Requires<[IsThumb1Only]>;
Jim Grosbach's avatar
Jim Grosbach committed
def tADJCALLSTACKDOWN :
PseudoInst<(outs), (ins i32imm:$amt), NoItinerary,
           [(ARMcallseq_start imm:$amt)]>, Requires<[IsThumb1Only]>;
def tNOP : T1pI<(outs), (ins), NoItinerary, "nop", "",
                [/* For disassembly only; pattern left blank */]>,
           T1Encoding<0b101111> {
  let Inst{9-8} = 0b11;
  let Inst{7-0} = 0b00000000;
} 

def tYIELD : T1pI<(outs), (ins), NoItinerary, "yield", "",
                  [/* For disassembly only; pattern left blank */]>,
             T1Encoding<0b101111> {
  let Inst{9-8} = 0b11;
  let Inst{7-0} = 0b00010000;
} 

def tWFE : T1pI<(outs), (ins), NoItinerary, "wfe", "",
                [/* For disassembly only; pattern left blank */]>,
           T1Encoding<0b101111> {
  let Inst{9-8} = 0b11;
  let Inst{7-0} = 0b00100000;
} 

def tWFI : T1pI<(outs), (ins), NoItinerary, "wfi", "",
                [/* For disassembly only; pattern left blank */]>,
           T1Encoding<0b101111> {
  let Inst{9-8} = 0b11;
  let Inst{7-0} = 0b00110000;
} 

def tSEV : T1pI<(outs), (ins), NoItinerary, "sev", "",
                [/* For disassembly only; pattern left blank */]>,
           T1Encoding<0b101111> {
  let Inst{9-8} = 0b11;
  let Inst{7-0} = 0b01000000;
} 

def tSETENDBE : T1I<(outs), (ins), NoItinerary, "setend\tbe",
                    [/* For disassembly only; pattern left blank */]>,
                T1Encoding<0b101101> {
  let Inst{9-5} = 0b10010;
  let Inst{3} = 1;
}

def tSETENDLE : T1I<(outs), (ins), NoItinerary, "setend\tle",
                    [/* For disassembly only; pattern left blank */]>,
                T1Encoding<0b101101> {
  let Inst{9-5} = 0b10010;
  let Inst{3} = 0;
}

// The i32imm operand $val can be used by a debugger to store more information
// about the breakpoint.
def tBKPT : T1I<(outs), (ins i32imm:$val), NoItinerary, "bkpt\t$val",
                [/* For disassembly only; pattern left blank */]>,
            T1Encoding<0b101111> {
  let Inst{9-8} = 0b10;
}

// Change Processor State is a system instruction -- for disassembly only.
// The singleton $opt operand contains the following information:
// opt{4-0} = mode ==> don't care
// opt{5} = changemode ==> 0 (false for 16-bit Thumb instr)
// opt{8-6} = AIF from Inst{2-0}
// opt{10-9} = 1:imod from Inst{4} with 0b10 as enable and 0b11 as disable
Loading
Loading full blame...