You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

trampoline-armv4.pl 5.4 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. #!/usr/bin/env perl
  2. # Copyright (c) 2019, Google Inc.
  3. #
  4. # Permission to use, copy, modify, and/or distribute this software for any
  5. # purpose with or without fee is hereby granted, provided that the above
  6. # copyright notice and this permission notice appear in all copies.
  7. #
  8. # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  11. # SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  13. # OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  14. # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. # This file defines helper functions for crypto/test/abi_test.h on 32-bit
  16. # ARM. See that header for details on how to use this.
  17. #
  18. # For convenience, this file is linked into libcrypto, where consuming builds
  19. # already support architecture-specific sources. The static linker should drop
  20. # this code in non-test binaries. This includes a shared library build of
  21. # libcrypto, provided --gc-sections (ELF), -dead_strip (iOS), or equivalent is
  22. # used.
  23. #
  24. # References:
  25. #
  26. # AAPCS: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042f/IHI0042F_aapcs.pdf
  27. # iOS ARMv6: https://developer.apple.com/library/archive/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARMv6FunctionCallingConventions.html
  28. # iOS ARMv7: https://developer.apple.com/library/archive/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARMv7FunctionCallingConventions.html
  29. use strict;
  30. my $flavour = shift;
  31. my $output = shift;
  32. if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
  33. $0 =~ m/(.*[\/\\])[^\/\\]+$/;
  34. my $dir = $1;
  35. my $xlate;
  36. ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
  37. ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
  38. die "can't locate arm-xlate.pl";
  39. open OUT, "| \"$^X\" \"$xlate\" $flavour \"$output\"";
  40. *STDOUT = *OUT;
  41. my ($func, $state, $argv, $argc) = ("r0", "r1", "r2", "r3");
  42. my $code = <<____;
  43. .syntax unified
  44. .arch armv7-a
  45. .fpu vfp
  46. .text
  47. @ abi_test_trampoline loads callee-saved registers from |state|, calls |func|
  48. @ with |argv|, then saves the callee-saved registers into |state|. It returns
  49. @ the result of |func|. The |unwind| argument is unused.
  50. @ uint32_t abi_test_trampoline(void (*func)(...), CallerState *state,
  51. @ const uint32_t *argv, size_t argc,
  52. @ int unwind);
  53. .type abi_test_trampoline, %function
  54. .globl abi_test_trampoline
  55. .align 4
  56. abi_test_trampoline:
  57. .Labi_test_trampoline_begin:
  58. @ Save parameters and all callee-saved registers. For convenience, we
  59. @ save r9 on iOS even though it's volatile.
  60. vstmdb sp!, {d8-d15}
  61. stmdb sp!, {r0-r11,lr}
  62. @ Reserve stack space for six (10-4) stack parameters, plus an extra 4
  63. @ bytes to keep it 8-byte-aligned (see APCS, section 5.3).
  64. sub sp, sp, #28
  65. @ Every register in APCS is either non-volatile or a parameter (except
  66. @ r9 on iOS), so this code, by the actual call, loses all its scratch
  67. @ registers. First fill in stack parameters while there are registers
  68. @ to spare.
  69. cmp $argc, #4
  70. bls .Lstack_args_done
  71. mov r4, sp @ r4 is the output pointer.
  72. add r5, $argv, $argc, lsl #2 @ Set r5 to the end of argv.
  73. add $argv, $argv, #16 @ Skip four arguments.
  74. .Lstack_args_loop:
  75. ldr r6, [$argv], #4
  76. cmp $argv, r5
  77. str r6, [r4], #4
  78. bne .Lstack_args_loop
  79. .Lstack_args_done:
  80. @ Load registers from |$state|.
  81. vldmia $state!, {d8-d15}
  82. #if defined(__APPLE__)
  83. @ r9 is not volatile on iOS.
  84. ldmia $state!, {r4-r8,r10-r11}
  85. #else
  86. ldmia $state!, {r4-r11}
  87. #endif
  88. @ Load register parameters. This uses up our remaining registers, so we
  89. @ repurpose lr as scratch space.
  90. ldr $argc, [sp, #40] @ Reload argc.
  91. ldr lr, [sp, #36] @ Load argv into lr.
  92. cmp $argc, #3
  93. bhi .Larg_r3
  94. beq .Larg_r2
  95. cmp $argc, #1
  96. bhi .Larg_r1
  97. beq .Larg_r0
  98. b .Largs_done
  99. .Larg_r3:
  100. ldr r3, [lr, #12] @ argv[3]
  101. .Larg_r2:
  102. ldr r2, [lr, #8] @ argv[2]
  103. .Larg_r1:
  104. ldr r1, [lr, #4] @ argv[1]
  105. .Larg_r0:
  106. ldr r0, [lr] @ argv[0]
  107. .Largs_done:
  108. @ With every other register in use, load the function pointer into lr
  109. @ and call the function.
  110. ldr lr, [sp, #28]
  111. blx lr
  112. @ r1-r3 are free for use again. The trampoline only supports
  113. @ single-return functions. Pass r4-r11 to the caller.
  114. ldr $state, [sp, #32]
  115. vstmia $state!, {d8-d15}
  116. #if defined(__APPLE__)
  117. @ r9 is not volatile on iOS.
  118. stmia $state!, {r4-r8,r10-r11}
  119. #else
  120. stmia $state!, {r4-r11}
  121. #endif
  122. @ Unwind the stack and restore registers.
  123. add sp, sp, #44 @ 44 = 28+16
  124. ldmia sp!, {r4-r11,lr} @ Skip r0-r3 (see +16 above).
  125. vldmia sp!, {d8-d15}
  126. bx lr
  127. .size abi_test_trampoline,.-abi_test_trampoline
  128. ____
  129. # abi_test_clobber_* zeros the corresponding register. These are used to test
  130. # the ABI-testing framework.
  131. foreach (0..12) {
  132. # This loop skips r13 (sp), r14 (lr, implicitly clobbered by every call), and
  133. # r15 (pc).
  134. $code .= <<____;
  135. .type abi_test_clobber_r$_, %function
  136. .globl abi_test_clobber_r$_
  137. .align 4
  138. abi_test_clobber_r$_:
  139. mov r$_, #0
  140. bx lr
  141. .size abi_test_clobber_r$_,.-abi_test_clobber_r$_
  142. ____
  143. }
  144. foreach (0..15) {
  145. my $lo = "s".(2*$_);
  146. my $hi = "s".(2*$_+1);
  147. $code .= <<____;
  148. .type abi_test_clobber_d$_, %function
  149. .globl abi_test_clobber_d$_
  150. .align 4
  151. abi_test_clobber_d$_:
  152. mov r0, #0
  153. vmov $lo, r0
  154. vmov $hi, r0
  155. bx lr
  156. .size abi_test_clobber_d$_,.-abi_test_clobber_d$_
  157. ____
  158. }
  159. print $code;
  160. close STDOUT;