1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
//===----------------------Hexagon builtin routine ------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// Functions that implement common sequences in function prologues and epilogues
// used to save code size
.macro FUNCTION_BEGIN name
.text
.globl \name
.type \name, @function
.falign
\name:
.endm
.macro FUNCTION_END name
.size \name, . - \name
.endm
.macro FALLTHROUGH_TAIL_CALL name0 name1
.size \name0, . - \name0
.globl \name1
.type \name1, @function
.falign
\name1:
.endm
// Save r27:26 at fp+#-8, r25:24 at fp+#-16, r23:22 at fp+#-24, r21:20 at
// fp+#-32, r19:18 at fp+#-40, and r17:16 at fp+#-48.
// The compiler knows that the __save_* functions clobber LR. No other
// registers should be used without informing the compiler.
// Since we can only issue one store per packet, we don't hurt performance by
// simply jumping to the right point in this sequence of stores.
FUNCTION_BEGIN __save_r27_through_r16
memd(fp+#-48) = r17:16
FALLTHROUGH_TAIL_CALL __save_r27_through_r16 __save_r27_through_r18
memd(fp+#-40) = r19:18
FALLTHROUGH_TAIL_CALL __save_r27_through_r18 __save_r27_through_r20
memd(fp+#-32) = r21:20
FALLTHROUGH_TAIL_CALL __save_r27_through_r20 __save_r27_through_r22
memd(fp+#-24) = r23:22
FALLTHROUGH_TAIL_CALL __save_r27_through_r22 __save_r27_through_r24
memd(fp+#-16) = r25:24
{
memd(fp+#-8) = r27:26
jumpr lr
}
FUNCTION_END __save_r27_through_r24
// For each of the *_before_sibcall functions, jumpr lr is executed in parallel
// with deallocframe. That way, the return gets the old value of lr, which is
// where these functions need to return, and at the same time, lr gets the value
// it needs going into the sibcall.
FUNCTION_BEGIN __restore_r27_through_r20_and_deallocframe_before_sibcall
{
r21:20 = memd(fp+#-32)
r23:22 = memd(fp+#-24)
}
FALLTHROUGH_TAIL_CALL __restore_r27_through_r20_and_deallocframe_before_sibcall __restore_r27_through_r24_and_deallocframe_before_sibcall
{
r25:24 = memd(fp+#-16)
jump __restore_r27_through_r26_and_deallocframe_before_sibcall
}
FUNCTION_END __restore_r27_through_r24_and_deallocframe_before_sibcall
FUNCTION_BEGIN __restore_r27_through_r16_and_deallocframe_before_sibcall
r17:16 = memd(fp+#-48)
FALLTHROUGH_TAIL_CALL __restore_r27_through_r16_and_deallocframe_before_sibcall __restore_r27_through_r18_and_deallocframe_before_sibcall
{
r19:18 = memd(fp+#-40)
r21:20 = memd(fp+#-32)
}
FALLTHROUGH_TAIL_CALL __restore_r27_through_r18_and_deallocframe_before_sibcall __restore_r27_through_r22_and_deallocframe_before_sibcall
{
r23:22 = memd(fp+#-24)
r25:24 = memd(fp+#-16)
}
FALLTHROUGH_TAIL_CALL __restore_r27_through_r22_and_deallocframe_before_sibcall __restore_r27_through_r26_and_deallocframe_before_sibcall
{
r27:26 = memd(fp+#-8)
deallocframe
jumpr lr
}
FUNCTION_END __restore_r27_through_r26_and_deallocframe_before_sibcall
// Here we use the extra load bandwidth to restore LR early, allowing the return
// to occur in parallel with the deallocframe.
FUNCTION_BEGIN __restore_r27_through_r16_and_deallocframe
{
r17:16 = memd(fp+#-48)
r19:18 = memd(fp+#-40)
}
FALLTHROUGH_TAIL_CALL __restore_r27_through_r16_and_deallocframe __restore_r27_through_r20_and_deallocframe
{
r21:20 = memd(fp+#-32)
r23:22 = memd(fp+#-24)
}
FALLTHROUGH_TAIL_CALL __restore_r27_through_r20_and_deallocframe __restore_r27_through_r24_and_deallocframe
{
lr = memw(fp+#4)
r25:24 = memd(fp+#-16)
}
{
r27:26 = memd(fp+#-8)
deallocframe
jumpr lr
}
FUNCTION_END __restore_r27_through_r24_and_deallocframe
// Here the load bandwidth is maximized for all three functions.
FUNCTION_BEGIN __restore_r27_through_r18_and_deallocframe
{
r19:18 = memd(fp+#-40)
r21:20 = memd(fp+#-32)
}
FALLTHROUGH_TAIL_CALL __restore_r27_through_r18_and_deallocframe __restore_r27_through_r22_and_deallocframe
{
r23:22 = memd(fp+#-24)
r25:24 = memd(fp+#-16)
}
FALLTHROUGH_TAIL_CALL __restore_r27_through_r22_and_deallocframe __restore_r27_through_r26_and_deallocframe
{
r27:26 = memd(fp+#-8)
deallocframe
}
jumpr lr
FUNCTION_END __restore_r27_through_r26_and_deallocframe
|