vfphw.S 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * linux/arch/arm/vfp/vfphw.S
  4. *
  5. * Copyright (C) 2004 ARM Limited.
  6. * Written by Deep Blue Solutions Limited.
  7. */
  8. #include <linux/init.h>
  9. #include <linux/linkage.h>
  10. #include <asm/thread_info.h>
  11. #include <asm/vfpmacros.h>
  12. #include <linux/kern_levels.h>
  13. #include <asm/assembler.h>
  14. #include <asm/asm-offsets.h>
  15. .macro DBGSTR1, str, arg
  16. #ifdef DEBUG
  17. stmfd sp!, {r0-r3, ip, lr}
  18. mov r1, \arg
  19. ldr r0, =1f
  20. bl _printk
  21. ldmfd sp!, {r0-r3, ip, lr}
  22. .pushsection .rodata, "a"
  23. 1: .ascii KERN_DEBUG "VFP: \str\n"
  24. .byte 0
  25. .previous
  26. #endif
  27. .endm
  28. ENTRY(vfp_load_state)
  29. @ Load the current VFP state
  30. @ r0 - load location
  31. @ returns FPEXC
  32. DBGSTR1 "load VFP state %p", r0
  33. @ Load the saved state back into the VFP
  34. VFPFLDMIA r0, r1 @ reload the working registers while
  35. @ FPEXC is in a safe state
  36. ldmia r0, {r0-r3} @ load FPEXC, FPSCR, FPINST, FPINST2
  37. tst r0, #FPEXC_EX @ is there additional state to restore?
  38. beq 1f
  39. VFPFMXR FPINST, r2 @ restore FPINST (only if FPEXC.EX is set)
  40. tst r0, #FPEXC_FP2V @ is there an FPINST2 to write?
  41. beq 1f
  42. VFPFMXR FPINST2, r3 @ FPINST2 if needed (and present)
  43. 1:
  44. VFPFMXR FPSCR, r1 @ restore status
  45. ret lr
  46. ENDPROC(vfp_load_state)
  47. ENTRY(vfp_save_state)
  48. @ Save the current VFP state
  49. @ r0 - save location
  50. @ r1 - FPEXC
  51. DBGSTR1 "save VFP state %p", r0
  52. VFPFSTMIA r0, r2 @ save the working registers
  53. VFPFMRX r2, FPSCR @ current status
  54. tst r1, #FPEXC_EX @ is there additional state to save?
  55. beq 1f
  56. VFPFMRX r3, FPINST @ FPINST (only if FPEXC.EX is set)
  57. tst r1, #FPEXC_FP2V @ is there an FPINST2 to read?
  58. beq 1f
  59. VFPFMRX r12, FPINST2 @ FPINST2 if needed (and present)
  60. 1:
  61. stmia r0, {r1, r2, r3, r12} @ save FPEXC, FPSCR, FPINST, FPINST2
  62. ret lr
  63. ENDPROC(vfp_save_state)
  64. .macro tbl_branch, base, tmp, shift
  65. #ifdef CONFIG_THUMB2_KERNEL
  66. adr \tmp, 1f
  67. add \tmp, \tmp, \base, lsl \shift
  68. ret \tmp
  69. #else
  70. add pc, pc, \base, lsl \shift
  71. mov r0, r0
  72. #endif
  73. 1:
  74. .endm
  75. ENTRY(vfp_get_float)
  76. tbl_branch r0, r3, #3
  77. .fpu vfpv2
  78. .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
  79. 1: vmov r0, s\dr
  80. ret lr
  81. .org 1b + 8
  82. .endr
  83. .irp dr,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
  84. 1: vmov r0, s\dr
  85. ret lr
  86. .org 1b + 8
  87. .endr
  88. ENDPROC(vfp_get_float)
  89. ENTRY(vfp_put_float)
  90. tbl_branch r1, r3, #3
  91. .fpu vfpv2
  92. .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
  93. 1: vmov s\dr, r0
  94. ret lr
  95. .org 1b + 8
  96. .endr
  97. .irp dr,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
  98. 1: vmov s\dr, r0
  99. ret lr
  100. .org 1b + 8
  101. .endr
  102. ENDPROC(vfp_put_float)
  103. ENTRY(vfp_get_double)
  104. tbl_branch r0, r3, #3
  105. .fpu vfpv2
  106. .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
  107. 1: vmov r0, r1, d\dr
  108. ret lr
  109. .org 1b + 8
  110. .endr
  111. #ifdef CONFIG_VFPv3
  112. @ d16 - d31 registers
  113. .fpu vfpv3
  114. .irp dr,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
  115. 1: vmov r0, r1, d\dr
  116. ret lr
  117. .org 1b + 8
  118. .endr
  119. #endif
  120. @ virtual register 16 (or 32 if VFPv3) for compare with zero
  121. mov r0, #0
  122. mov r1, #0
  123. ret lr
  124. ENDPROC(vfp_get_double)
  125. ENTRY(vfp_put_double)
  126. tbl_branch r2, r3, #3
  127. .fpu vfpv2
  128. .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
  129. 1: vmov d\dr, r0, r1
  130. ret lr
  131. .org 1b + 8
  132. .endr
  133. #ifdef CONFIG_VFPv3
  134. .fpu vfpv3
  135. @ d16 - d31 registers
  136. .irp dr,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
  137. 1: vmov d\dr, r0, r1
  138. ret lr
  139. .org 1b + 8
  140. .endr
  141. #endif
  142. ENDPROC(vfp_put_double)