412 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
			
		
		
	
	
			412 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
@ 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
 |