You've already forked linux-packaging-mono
							
							
		
			
				
	
	
		
			410 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			410 lines
		
	
	
		
			8.6 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
 | |
| 5:
 | |
|   addeq r0, #1
 | |
| @ CHECK: it eq
 | |
| @ CHECK: addeq
 | |
| @ CHECK: it eq
 | |
| @ CHECK: addeq
 | |
| @ 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
 |