Home | History | Annotate | Download | only in ARM
      1 ; RUN: llc -mtriple=arm-none-none-eabi -mcpu=cortex-a15 -o - %s | FileCheck --check-prefix=CHECK-A %s
      2 ; RUN: llc -mtriple=thumb-none-none-eabi -mcpu=cortex-a15 -o - %s | FileCheck --check-prefix=CHECK-A-THUMB %s
      3 ; RUN: llc -mtriple=thumb-apple-none-macho -mcpu=cortex-m3 -o - %s | FileCheck --check-prefix=CHECK-M %s
      4 
      5 declare arm_aapcscc void @bar()
      6 
      7 @bigvar = global [16 x i32] zeroinitializer
      8 
      9 define arm_aapcscc void @irq_fn() alignstack(8) "interrupt"="IRQ" {
     10   ; Must save all registers except banked sp and lr (we save lr anyway because
     11   ; we actually need it at the end to execute the return ourselves).
     12 
     13   ; Also need special function return setting pc and CPSR simultaneously.
     14 ; CHECK-A-LABEL: irq_fn:
     15 ; CHECK-A: push {r0, r1, r2, r3, r10, r11, r12, lr}
     16 ; CHECK-A: add r11, sp, #20
     17 ; CHECK-A-NOT: sub sp, sp, #{{[0-9]+}}
     18 ; CHECK-A: bic sp, sp, #7
     19 ; CHECK-A: bl bar
     20 ; CHECK-A: sub sp, r11, #20
     21 ; CHECK-A: pop {r0, r1, r2, r3, r10, r11, r12, lr}
     22 ; CHECK-A: subs pc, lr, #4
     23 
     24 ; CHECK-A-THUMB-LABEL: irq_fn:
     25 ; CHECK-A-THUMB: push.w {r0, r1, r2, r3, r4, r7, r12, lr}
     26 ; CHECK-A-THUMB: add r7, sp, #20
     27 ; CHECK-A-THUMB: mov r4, sp
     28 ; CHECK-A-THUMB: bic r4, r4, #7
     29 ; CHECK-A-THUMB: bl bar
     30 ; CHECK-A-THUMB: sub.w r4, r7,  #20
     31 ; CHECK-A-THUMB: mov sp, r4
     32 ; CHECK-A-THUMB: pop.w {r0, r1, r2, r3, r4, r7, r12, lr}
     33 ; CHECK-A-THUMB: subs pc, lr, #4
     34 
     35   ; Normal AAPCS function (r0-r3 pushed onto stack by hardware, lr set to
     36   ; appropriate sentinel so no special return needed).
     37 ; CHECK-M-LABEL: irq_fn:
     38 ; CHECK-M: push.w {r4, r10, r11, lr}
     39 ; CHECK-M: add.w r11, sp, #8
     40 ; CHECK-M: mov r4, sp
     41 ; CHECK-M: bic r4, r4, #7
     42 ; CHECK-M: mov sp, r4
     43 ; CHECK-M: blx _bar
     44 ; CHECK-M: sub.w r4, r11, #8
     45 ; CHECK-M: mov sp, r4
     46 ; CHECK-M: pop.w {r4, r10, r11, pc}
     47 
     48   call arm_aapcscc void @bar()
     49   ret void
     50 }
     51 
     52 ; We don't push/pop r12, as it is banked for FIQ
     53 define arm_aapcscc void @fiq_fn() alignstack(8) "interrupt"="FIQ" {
     54 ; CHECK-A-LABEL: fiq_fn:
     55 ; CHECK-A: push {r0, r1, r2, r3, r4, r5, r6, r7, r11, lr}
     56   ; 32 to get past r0, r1, ..., r7
     57 ; CHECK-A: add r11, sp, #32
     58 ; CHECK-A: sub sp, sp, #{{[0-9]+}}
     59 ; CHECK-A: bic sp, sp, #7
     60 ; [...]
     61   ; 32 must match above
     62 ; CHECK-A: sub sp, r11, #32
     63 ; CHECK-A: pop {r0, r1, r2, r3, r4, r5, r6, r7, r11, lr}
     64 ; CHECK-A: subs pc, lr, #4
     65 
     66 ; CHECK-A-THUMB-LABEL: fiq_fn:
     67 ; CHECK-M-LABEL: fiq_fn:
     68   %val = load volatile [16 x i32]* @bigvar
     69   store volatile [16 x i32] %val, [16 x i32]* @bigvar
     70   ret void
     71 }
     72 
     73 define arm_aapcscc void @swi_fn() alignstack(8) "interrupt"="SWI" {
     74 ; CHECK-A-LABEL: swi_fn:
     75 ; CHECK-A: push {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}
     76 ; CHECK-A: add r11, sp, #44
     77 ; CHECK-A: sub sp, sp, #{{[0-9]+}}
     78 ; CHECK-A: bic sp, sp, #7
     79 ; [...]
     80 ; CHECK-A: sub sp, r11, #44
     81 ; CHECK-A: pop {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}
     82 ; CHECK-A: subs pc, lr, #0
     83 
     84   %val = load volatile [16 x i32]* @bigvar
     85   store volatile [16 x i32] %val, [16 x i32]* @bigvar
     86   ret void
     87 }
     88 
     89 define arm_aapcscc void @undef_fn() alignstack(8) "interrupt"="UNDEF" {
     90 ; CHECK-A-LABEL: undef_fn:
     91 ; CHECK-A: push {r0, r1, r2, r3, r10, r11, r12, lr}
     92 ; CHECK-A: add r11, sp, #20
     93 ; CHECK-A-NOT: sub sp, sp, #{{[0-9]+}}
     94 ; CHECK-A: bic sp, sp, #7
     95 ; [...]
     96 ; CHECK-A: sub sp, r11, #20
     97 ; CHECK-A: pop {r0, r1, r2, r3, r10, r11, r12, lr}
     98 ; CHECK-A: subs pc, lr, #0
     99 
    100   call void @bar()
    101   ret void
    102 }
    103 
    104 define arm_aapcscc void @abort_fn() alignstack(8) "interrupt"="ABORT" {
    105 ; CHECK-A-LABEL: abort_fn:
    106 ; CHECK-A: push {r0, r1, r2, r3, r10, r11, r12, lr}
    107 ; CHECK-A: add r11, sp, #20
    108 ; CHECK-A-NOT: sub sp, sp, #{{[0-9]+}}
    109 ; CHECK-A: bic sp, sp, #7
    110 ; [...]
    111 ; CHECK-A: sub sp, r11, #20
    112 ; CHECK-A: pop {r0, r1, r2, r3, r10, r11, r12, lr}
    113 ; CHECK-A: subs pc, lr, #4
    114 
    115   call void @bar()
    116   ret void
    117 }
    118 
    119 @var = global double 0.0
    120 
    121 ; We don't save VFP regs, since it would be a massive overhead in the general
    122 ; case.
    123 define arm_aapcscc void @floating_fn() alignstack(8) "interrupt"="IRQ" {
    124 ; CHECK-A-LABEL: floating_fn:
    125 ; CHECK-A-NOT: vpush
    126 ; CHECK-A-NOT: vstr
    127 ; CHECK-A-NOT: vstm
    128 ; CHECK-A: vadd.f64 {{d[0-9]+}}, {{d[0-9]+}}, {{d[0-9]+}}
    129   %lhs = load volatile double* @var
    130   %rhs = load volatile double* @var
    131   %sum = fadd double %lhs, %rhs
    132   store double %sum, double* @var
    133   ret void
    134 }
    135