forked from OSchip/llvm-project
[MSP430] Add more tests for ABI and calling convention
Patch by Kristina Bessonova! Differential Revision: https://reviews.llvm.org/D54582 llvm-svn: 347040
This commit is contained in:
parent
1bf52c59b7
commit
cad2b83182
|
@ -0,0 +1,38 @@
|
||||||
|
; RUN: llc < %s | FileCheck %s
|
||||||
|
|
||||||
|
target datalayout = "e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16"
|
||||||
|
target triple = "msp430-generic-generic"
|
||||||
|
|
||||||
|
; Test the r4-r10 callee-saved registers (MSP430 EABI p. 3.2.2).
|
||||||
|
|
||||||
|
@g = global float 0.0
|
||||||
|
|
||||||
|
define void @foo() {
|
||||||
|
; CHECK-LABEL: foo:
|
||||||
|
; CHECK-NOT: push r15
|
||||||
|
; CHECK-NOT: push r14
|
||||||
|
; CHECK-NOT: push r13
|
||||||
|
; CHECK-NOT: push r12
|
||||||
|
; CHECK-NOT: push r11
|
||||||
|
; CHECK: push r10
|
||||||
|
; CHECK: push r9
|
||||||
|
; CHECK: push r8
|
||||||
|
; CHECK: push r7
|
||||||
|
; CHECK: push r6
|
||||||
|
; CHECK: push r5
|
||||||
|
; CHECK: push r4
|
||||||
|
%t1 = load volatile float, float* @g
|
||||||
|
%t2 = load volatile float, float* @g
|
||||||
|
%t3 = load volatile float, float* @g
|
||||||
|
%t4 = load volatile float, float* @g
|
||||||
|
%t5 = load volatile float, float* @g
|
||||||
|
%t6 = load volatile float, float* @g
|
||||||
|
%t7 = load volatile float, float* @g
|
||||||
|
store volatile float %t1, float* @g
|
||||||
|
store volatile float %t2, float* @g
|
||||||
|
store volatile float %t3, float* @g
|
||||||
|
store volatile float %t4, float* @g
|
||||||
|
store volatile float %t5, float* @g
|
||||||
|
store volatile float %t6, float* @g
|
||||||
|
ret void
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
; RUN: llc < %s | FileCheck %s
|
||||||
|
|
||||||
|
target datalayout = "e-p:16:16:16-i8:8:8-i16:16:16-i32:16:32-n8:16-a0:16:16"
|
||||||
|
target triple = "msp430---elf"
|
||||||
|
|
||||||
|
declare i32 @direct(i32 %a)
|
||||||
|
|
||||||
|
define i32 @test_direct(i32 %a) nounwind {
|
||||||
|
; CHECK-LABEL: test_direct:
|
||||||
|
; CHECK: call #direct
|
||||||
|
%1 = call i32 @direct(i32 %a)
|
||||||
|
ret i32 %1
|
||||||
|
}
|
||||||
|
|
||||||
|
define i16 @test_indirect(i16 (i16)* %a, i16 %b) nounwind {
|
||||||
|
; CHECK-LABEL: test_indirect:
|
||||||
|
; CHECK: mov r12, r14
|
||||||
|
; CHECK: mov r13, r12
|
||||||
|
; CHECK: call r14
|
||||||
|
%1 = call i16 %a(i16 %b)
|
||||||
|
ret i16 %1
|
||||||
|
}
|
|
@ -54,6 +54,29 @@ entry:
|
||||||
; CHECK: call #f_i16_i64_i16
|
; CHECK: call #f_i16_i64_i16
|
||||||
call void @f_i16_i64_i16(i16 1, i64 72623859790382856, i16 2)
|
call void @f_i16_i64_i16(i16 1, i64 72623859790382856, i16 2)
|
||||||
|
|
||||||
|
; Check that r15 is not used and the last i32 argument passed through the stack.
|
||||||
|
; CHECK: mov #258, 10(r1)
|
||||||
|
; CHECK: mov #772, 8(r1)
|
||||||
|
; CHECK: mov #258, 6(r1)
|
||||||
|
; CHECK: mov #772, 4(r1)
|
||||||
|
; CHECK: mov #1286, 2(r1)
|
||||||
|
; CHECK: mov #1800, 0(r1)
|
||||||
|
; CHECK: mov #1, r12
|
||||||
|
; CHECK: mov #772, r13
|
||||||
|
; CHECK: mov #258, r14
|
||||||
|
call void @f_i16_i64_i32_i32(i16 1, i64 72623859790382856, i32 16909060, i32 16909060)
|
||||||
|
|
||||||
|
; CHECK: mov #258, 6(r1)
|
||||||
|
; CHECK: mov #772, 4(r1)
|
||||||
|
; CHECK: mov #1286, 2(r1)
|
||||||
|
; CHECK: mov #1800, 0(r1)
|
||||||
|
; CHECK: mov #1800, r12
|
||||||
|
; CHECK: mov #1286, r13
|
||||||
|
; CHECK: mov #772, r14
|
||||||
|
; CHECK: mov #258, r15
|
||||||
|
; CHECK: call #f_i64_i64
|
||||||
|
call void @f_i64_i64(i64 72623859790382856, i64 72623859790382856)
|
||||||
|
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,4 +159,60 @@ define void @f_i16_i64_i16(i16 %a, i64 %b, i16 %c) #0 {
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define void @f_i64_i64(i64 %a, i64 %b) #0 {
|
||||||
|
; CHECK: f_i64_i64:
|
||||||
|
; CHECK: mov r15, &g_i64+6
|
||||||
|
; CHECK: mov r14, &g_i64+4
|
||||||
|
; CHECK: mov r13, &g_i64+2
|
||||||
|
; CHECK: mov r12, &g_i64
|
||||||
|
store volatile i64 %a, i64* @g_i64, align 2
|
||||||
|
; CHECK: mov 10(r4), &g_i64+6
|
||||||
|
; CHECK: mov 8(r4), &g_i64+4
|
||||||
|
; CHECK: mov 6(r4), &g_i64+2
|
||||||
|
; CHECK: mov 4(r4), &g_i64
|
||||||
|
store volatile i64 %b, i64* @g_i64, align 2
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @f_i16_i64_i32_i32(i16 %a, i64 %b, i32 %c, i32 %d) #0 {
|
||||||
|
; CHECK-LABEL: f_i16_i64_i32_i32:
|
||||||
|
; CHECK: mov r12, &g_i16
|
||||||
|
store volatile i16 %a, i16* @g_i16, align 2
|
||||||
|
; CHECK: mov 10(r4), &g_i64+6
|
||||||
|
; CHECK: mov 8(r4), &g_i64+4
|
||||||
|
; CHECK: mov 6(r4), &g_i64+2
|
||||||
|
; CHECK: mov 4(r4), &g_i64
|
||||||
|
store volatile i64 %b, i64* @g_i64, align 2
|
||||||
|
; CHECK: mov r14, &g_i32+2
|
||||||
|
; CHECK: mov r13, &g_i32
|
||||||
|
store volatile i32 %c, i32* @g_i32, align 2
|
||||||
|
; CHECK: mov 14(r4), &g_i32+2
|
||||||
|
; CHECK: mov 12(r4), &g_i32
|
||||||
|
store volatile i32 %d, i32* @g_i32, align 2
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
; MSP430 EABI p. 6.3
|
||||||
|
; For helper functions which take two long long arguments
|
||||||
|
; the first argument is passed in R8::R11 and the second argument
|
||||||
|
; is in R12::R15.
|
||||||
|
|
||||||
|
@g_i64_2 = common global i64 0, align 2
|
||||||
|
|
||||||
|
define i64 @helper_call_i64() #0 {
|
||||||
|
%1 = load i64, i64* @g_i64, align 2
|
||||||
|
%2 = load i64, i64* @g_i64_2, align 2
|
||||||
|
; CHECK-LABEL: helper_call_i64:
|
||||||
|
; CHECK: mov &g_i64, r8
|
||||||
|
; CHECK: mov &g_i64+2, r9
|
||||||
|
; CHECK: mov &g_i64+4, r10
|
||||||
|
; CHECK: mov &g_i64+6, r11
|
||||||
|
; CHECK: mov &g_i64_2, r12
|
||||||
|
; CHECK: mov &g_i64_2+2, r13
|
||||||
|
; CHECK: mov &g_i64_2+4, r14
|
||||||
|
; CHECK: mov &g_i64_2+6, r15
|
||||||
|
; CHECK: call #__mspabi_divlli
|
||||||
|
%3 = sdiv i64 %1, %2
|
||||||
|
ret i64 %3
|
||||||
|
}
|
||||||
|
|
||||||
attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
; RUN: llc < %s | FileCheck %s
|
||||||
|
|
||||||
|
target datalayout = "e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16"
|
||||||
|
target triple = "msp430-generic-generic"
|
||||||
|
|
||||||
|
@llvm.used = appending global [1 x i8*] [i8* bitcast (void ()* @ISR to i8*)], section "llvm.metadata"
|
||||||
|
|
||||||
|
; MSP430 EABI p. 3.9
|
||||||
|
; Interrupt functions must save all the registers that are used, even those
|
||||||
|
; that are normally considered callee-saved.
|
||||||
|
|
||||||
|
; To return from an interrupt function, the function must execute the special
|
||||||
|
; instruction RETI, which restores the SR register and branches to the PC where
|
||||||
|
; the interrupt occurred.
|
||||||
|
|
||||||
|
@g = global float 0.0
|
||||||
|
|
||||||
|
define msp430_intrcc void @ISR() #0 {
|
||||||
|
entry:
|
||||||
|
; CHECK-LABEL: ISR:
|
||||||
|
; CHECK: push r15
|
||||||
|
; CHECK: push r14
|
||||||
|
; CHECK: push r13
|
||||||
|
; CHECK: push r12
|
||||||
|
; CHECK: push r11
|
||||||
|
; CHECK: push r10
|
||||||
|
; CHECK: push r9
|
||||||
|
; CHECK: push r8
|
||||||
|
; CHECK: push r7
|
||||||
|
; CHECK: push r6
|
||||||
|
; CHECK: push r5
|
||||||
|
; CHECK: push r4
|
||||||
|
%t1 = load volatile float, float* @g
|
||||||
|
%t2 = load volatile float, float* @g
|
||||||
|
%t3 = load volatile float, float* @g
|
||||||
|
%t4 = load volatile float, float* @g
|
||||||
|
%t5 = load volatile float, float* @g
|
||||||
|
%t6 = load volatile float, float* @g
|
||||||
|
%t7 = load volatile float, float* @g
|
||||||
|
store volatile float %t1, float* @g
|
||||||
|
store volatile float %t2, float* @g
|
||||||
|
store volatile float %t3, float* @g
|
||||||
|
store volatile float %t4, float* @g
|
||||||
|
store volatile float %t5, float* @g
|
||||||
|
store volatile float %t6, float* @g
|
||||||
|
; CHECK: reti
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
target datalayout = "e-p:16:16:16-i8:8:8-i16:16:16-i32:16:32-n8:16"
|
target datalayout = "e-p:16:16:16-i8:8:8-i16:16:16-i32:16:32-n8:16"
|
||||||
target triple = "msp430---elf"
|
target triple = "msp430---elf"
|
||||||
|
|
||||||
; Allow simple structures to be returned by value.
|
; Pass large structures by reference (MSP430 EABI p. 3.5)
|
||||||
|
|
||||||
%s = type { i64, i64 }
|
%s = type { i64, i64 }
|
||||||
|
|
||||||
|
@ -20,4 +20,36 @@ define %s @fred() #0 {
|
||||||
ret %s {i64 72623859790382856, i64 651345242494996224}
|
ret %s {i64 72623859790382856, i64 651345242494996224}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
%struct.S = type { i16, i16, i16 }
|
||||||
|
|
||||||
|
@a = common global i16 0, align 2
|
||||||
|
@b = common global i16 0, align 2
|
||||||
|
@c = common global i16 0, align 2
|
||||||
|
|
||||||
|
define void @test() #1 {
|
||||||
|
; CHECK-LABEL: test:
|
||||||
|
%1 = alloca %struct.S, align 2
|
||||||
|
; CHECK: mov r1, r12
|
||||||
|
; CHECK-NEXT: call #sret
|
||||||
|
call void @sret(%struct.S* nonnull sret %1) #3
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @sret(%struct.S* noalias nocapture sret) #0 {
|
||||||
|
; CHECK-LABEL: sret:
|
||||||
|
; CHECK: mov &a, 0(r12)
|
||||||
|
; CHECK: mov &b, 2(r12)
|
||||||
|
; CHECK: mov &c, 4(r12)
|
||||||
|
%2 = getelementptr inbounds %struct.S, %struct.S* %0, i16 0, i32 0
|
||||||
|
%3 = load i16, i16* @a, align 2
|
||||||
|
store i16 %3, i16* %2, align 2
|
||||||
|
%4 = getelementptr inbounds %struct.S, %struct.S* %0, i16 0, i32 1
|
||||||
|
%5 = load i16, i16* @b, align 2
|
||||||
|
store i16 %5, i16* %4, align 2
|
||||||
|
%6 = getelementptr inbounds %struct.S, %struct.S* %0, i16 0, i32 2
|
||||||
|
%7 = load i16, i16* @c, align 2
|
||||||
|
store i16 %7, i16* %6, align 2
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
attributes #0 = { nounwind }
|
attributes #0 = { nounwind }
|
||||||
|
|
Loading…
Reference in New Issue