Compiler projects using llvm
@ RUN: llvm-mc -triple thumbv7a--none-eabi -arm-implicit-it=always < %s -show-encoding | FileCheck %s

@ Single instruction
  .section test1
@ CHECK-LABEL: test1
  addeq r0, #1
@ CHECK: it eq
@ CHECK: addeq

@ Multiple instructions, same condition
  .section test2
@ CHECK-LABEL: test2
  addeq r0, #1
  addeq r0, #1
  addeq r0, #1
  addeq r0, #1
@ CHECK: itttt eq
@ CHECK: addeq
@ CHECK: addeq
@ CHECK: addeq
@ CHECK: addeq

@ Multiple instructions, equal but opposite conditions
  .section test3
@ CHECK-LABEL: test3
  addeq r0, #1
  addne r0, #1
  addeq r0, #1
  addne r0, #1
@ CHECK: itete eq
@ CHECK: addeq
@ CHECK: addne
@ CHECK: addeq
@ CHECK: addne

@ Multiple instructions, unrelated conditions
  .section test4
@ CHECK-LABEL: test4
  addeq r0, #1
  addlt r0, #1
  addeq r0, #1
  addge r0, #1
@ CHECK: it eq
@ CHECK: addeq
@ CHECK: it lt
@ CHECK: addlt
@ CHECK: it eq
@ CHECK: addeq
@ CHECK: it ge
@ CHECK: addge

@ More than 4 instructions eligible for a block
  .section test5
@ CHECK-LABEL: test5
  addeq r0, #1
  addeq r0, #1
  addeq r0, #1
  addeq r0, #1
  addeq r0, #1
  addeq r0, #1
@ CHECK: itttt eq
@ CHECK: addeq
@ CHECK: addeq
@ CHECK: addeq
@ CHECK: addeq
@ CHECK: itt eq
@ CHECK: addeq
@ CHECK: addeq

@ Flush on a label
  .section test6
@ CHECK-LABEL: test6
  addeq r0, #1
label:
  addeq r0, #1
five:
  addeq r0, #1
@ CHECK: it eq
@ CHECK: addeq
@ CHECK: label
@ CHECK: it eq
@ CHECK: addeq
@ CHECK: five
@ CHECK: it eq
@ CHECK: addeq

@ Flush on a section-change directive
  .section test7a
@ CHECK-LABEL: test7a
  addeq r0, #1
  .section test7b
  addeq r0, #1
  .previous
  addeq r0, #1
  .pushsection test7c
  addeq r0, #1
  .popsection
  addeq r0, #1
@ CHECK: it eq
@ CHECK: addeq
@ CHECK: it eq
@ CHECK: addeq
@ CHECK: it eq
@ CHECK: addeq
@ CHECK: it eq
@ CHECK: addeq
@ CHECK: it eq
@ CHECK: addeq

@ Flush on an ISA change (even to the same ISA)
  .section test8
@ CHECK-LABEL: test8
  addeq r0, #1
  .thumb
  addeq r0, #1
  .arm
  addeq r0, #1
  .thumb
  addeq r0, #1
@ CHECK: it eq
@ CHECK: addeq
@ CHECK: it eq
@ CHECK: addeq
@ CHECK: addeq
@ CHECK: it eq
@ CHECK: addeq

@ Flush on an arch, cpu or fpu change
  .section test9
@ CHECK-LABEL: test9
  addeq r0, #1
  .arch armv7-a
  addeq r0, #1
  .cpu cortex-a15
  addeq r0, #1
  .fpu vfpv3
  addeq r0, #1
@ CHECK: it eq
@ CHECK: addeq
@ CHECK: it eq
@ CHECK: addeq
@ CHECK: it eq
@ CHECK: addeq
@ CHECK: it eq
@ CHECK: addeq

@ Flush on an unpredicable instruction
  .section test10
@ CHECK-LABEL: test10
  addeq r0, #1
  setend le
  addeq r0, #1
  hvc #0
  addeq r0, #1
@ CHECK: it eq
@ CHECK: addeq
@ CHECK: setend le
@ CHECK: it eq
@ CHECK: addeq
@ CHECK: hvc.w #0
@ CHECK: it eq
@ CHECK: addeq

@ Flush when reaching an explicit IT instruction
  .section test11
@ CHECK-LABEL: test11
  addeq r0, #1
  it eq
  addeq r0, #1
@ CHECK: it eq
@ CHECK: addeq
@ CHECK: it eq
@ CHECK: addeq

@ Don't extend an explicit IT instruction
  .section test12
@ CHECK-LABEL: test12
  it eq
  addeq r0, #1
  addeq r0, #1
@ CHECK: it eq
@ CHECK: addeq
@ CHECK: it eq
@ CHECK: addeq

@ Branch-like instructions can only be used at the end of an IT block, so
@ terminate it.
  .section test13
@ CHECK-LABEL: test13
  .cpu cortex-a15
  addeq pc, r0
  addeq pc, sp, pc
  ldreq pc, [r0, #4]
  ldreq pc, [r0, #-4]
  ldreq pc, [r0, r1]
  ldreq pc, [pc, #-0]
  moveq pc, r0
  bleq #4
  blxeq #4
  blxeq r0
  bxeq r0
  bxjeq r0
  tbbeq [r0, r1]
  tbheq [r0, r1, lsl #1]
  ereteq
  rfeiaeq r0
  rfeiaeq r0!
  rfedbeq r0
  rfedbeq r0!
  smceq #0
  ldmiaeq r0, {pc}
  ldmiaeq r0!, {r1, pc}
  ldmdbeq r0, {pc}
  ldmdbeq r0!, {r1, pc}
  popeq {pc}
  .arch armv8-m.main
  bxnseq r0
  blxnseq r0
@ CHECK: it eq
@ CHECK: addeq pc, r0
@ CHECK: it eq
@ CHECK: addeq pc, sp, pc
@ CHECK: it eq
@ CHECK: ldreq.w pc, [r0, #4]
@ CHECK: it eq
@ CHECK: ldreq pc, [r0, #-4]
@ CHECK: it eq
@ CHECK: ldreq.w pc, [r0, r1]
@ CHECK: it eq
@ CHECK: ldreq.w pc, [pc, #-0]
@ CHECK: it eq
@ CHECK: moveq pc, r0
@ CHECK: it eq
@ CHECK: bleq #4
@ CHECK: it eq
@ CHECK: blxeq #4
@ CHECK: it eq
@ CHECK: blxeq r0
@ CHECK: it eq
@ CHECK: bxeq r0
@ CHECK: it eq
@ CHECK: bxjeq r0
@ CHECK: it eq
@ CHECK: tbbeq [r0, r1]
@ CHECK: it eq
@ CHECK: tbheq [r0, r1, lsl #1]
@ CHECK: it eq
@ CHECK: ereteq
@ CHECK: it eq
@ CHECK: rfeiaeq r0
@ CHECK: it eq
@ CHECK: rfeiaeq r0!
@ CHECK: it eq
@ CHECK: rfedbeq r0
@ CHECK: it eq
@ CHECK: rfedbeq r0!
@ CHECK: it eq
@ CHECK: smceq #0
@ CHECK: it eq
@ CHECK: ldmeq.w r0, {pc}
@ CHECK: it eq
@ CHECK: ldmeq.w r0!, {r1, pc}
@ CHECK: it eq
@ CHECK: ldmdbeq r0, {pc}
@ CHECK: it eq
@ CHECK: ldmdbeq r0!, {r1, pc}
@ CHECK: it eq
@ CHECK: popeq {pc}
@ CHECK: it eq
@ CHECK: bxnseq r0
@ CHECK: it eq
@ CHECK: blxnseq r0

@ Thumb 16-bit ALU instructions set the flags iff they are not in an IT block,
@ so instruction matching must change when generating an implicit IT block.
  .section test14
@ CHECK-LABEL: test14
@ Outside an IT block, the 16-bit encoding must set flags
  add r0, #1
@ CHECK:add.w   r0, r0, #1              @ encoding: [0x00,0xf1,0x01,0x00] 
  adds r0, #1
@ CHECK: adds    r0, #1                  @ encoding: [0x01,0x30]
@ Inside an IT block, the 16-bit encoding can not set flags
  addeq r0, #1
@ CHECK: itt eq
@ CHECK: addeq   r0, #1                  @ encoding: [0x01,0x30]
  addseq r0, #1
@ CHECK: addseq.w        r0, r0, #1      @ encoding: [0x10,0xf1,0x01,0x00]

@ Some variants of the B instruction have their own condition code field, and
@ are not valid in IT blocks.
  .section test15
@ CHECK-LABEL: test15
@ Outside of an IT block, the 4 variants (narrow/wide,
@ predicated/non-predicated) are selected as normal, and the predicated
@ encodings are used instead of opening a new IT block:
  b #0x100
@ CHECK: b       #256                    @ encoding: [0x80,0xe0] 
  b #0x800
@ CHECK: b.w     #2048                   @ encoding: [0x00,0xf0,0x00,0xbc]
  beq #0x4
@ CHECK-NOT: it
@ CHECK: beq     #4                      @ encoding: [0x02,0xd0]
  beq #0x100
@ CHECK-NOT: it
@ CHECK: beq.w   #256                    @ encoding: [0x00,0xf0,0x80,0x80]

@ We could support "beq #0x100000" to "beq #0x1fffffc" by using t2Bcc in
@ an IT block (these currently fail as the target is out of range). However, long
@ ranges like this are rarely assembly-time constants, so this probably isn't
@ worth doing.

@ If we already have an open IT block, we can use the non-predicated encodings,
@ which have a greater range:
  addeq r0, r1
  beq #0x4
@ CHECK: itt eq
@ CHECK: addeq r0, r1
@ CHECK: beq     #4                      @ encoding: [0x02,0xe0]
  addeq r0, r1
  beq #0x100
@ CHECK: itt eq
@ CHECK: addeq r0, r1
@ CHECK: beq     #256                    @ encoding: [0x80,0xe0]
  addeq r0, r1
  beq #0x800
@ CHECK: itt eq
@ CHECK: addeq r0, r1
@ CHECK: beq.w   #2048                   @ encoding: [0x00,0xf0,0x00,0xbc]

@ If we have an open but incompatible IT block, we close it and use the
@ self-predicated encodings, without an IT block:
  addeq r0, r1
  bgt #0x4
@ CHECK: it eq
@ CHECK: addeq r0, r1
@ CHECK: bgt     #4                      @ encoding: [0x02,0xdc]
  addeq r0, r1
  bgt #0x100
@ CHECK: it eq
@ CHECK: addeq r0, r1
@ CHECK: bgt.w   #256                    @ encoding: [0x00,0xf3,0x80,0x80]

@ Breakpoint instructions are allowed in IT blocks, but are always executed
@ regardless of the condition flags. We could continue an IT block through
@ them, but currently do not.
  .section test16
@ CHECK-LABEL: test16
  addeq r0, r1
  bkpt #0
  addeq r0, r1
@ CHECK: it eq
@ CHECK: addeq r0, r1
@ CHECK: bkpt #0
@ CHECK: it eq
@ CHECK: addeq r0, r1

@ The .if directive causes entire assembly statments to be dropped before they
@ reach the IT block generation code. This happens to be exactly what we want,
@ and allows IT blocks to extend into and out of .if blocks. Only one arm of the
@ .if will be seen by the IT state tracking code, so the subeq shouldn't have
@ any effect here.
  .section test17
@ CHECK-LABEL: test17
  addeq r0, r1
  .if 1
  addeq r0, r1
  .else
  subeq r0, r1
  .endif
  addeq r0, r1
@ CHECK: ittt eq
@ CHECK: addeq
@ CHECK: addeq
@ CHECK: addeq

@ TODO: There are some other directives which we could continue through, such
@ as .set and .global, but we currently conservatively flush the IT block before
@ every directive (except for .if and friends, which are handled separately).
  .section test18
@ CHECK-LABEL: test18
  addeq r0, r1
  .set s, 1
  addeq r0, r1
@ CHECK: it eq
@ CHECK: addeq
@ CHECK: it eq
@ CHECK: addeq

@ The .rept directive can be used to create long IT blocks.
  .section test19
@ CHECK-LABEL: test19
  .rept 3
  addeq r0, r1
  subne r0, r1
  .endr
@ CHECK: itete eq
@ CHECK:  addeq r0, r1
@ CHECK:  subne r0, r0, r1
@ CHECK:  addeq r0, r1
@ CHECK:  subne r0, r0, r1
@ CHECK: ite eq
@ CHECK:  addeq r0, r1
@ CHECK:  subne r0, r0, r1

@ Flush at end of file
  .section test99
@ CHECK-LABEL: test99
  addeq r0, #1
@ CHECK: it eq
@ CHECK: addeq