vlrt.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. // Inferno's libkern/vlrt-arm.c
  2. // http://code.google.com/p/inferno-os/source/browse/libkern/vlrt-arm.c
  3. //
  4. // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
  5. // Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com). All rights reserved.
  6. // Portions Copyright 2009 The Go Authors. All rights reserved.
  7. //
  8. // Permission is hereby granted, free of charge, to any person obtaining a copy
  9. // of this software and associated documentation files (the "Software"), to deal
  10. // in the Software without restriction, including without limitation the rights
  11. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. // copies of the Software, and to permit persons to whom the Software is
  13. // furnished to do so, subject to the following conditions:
  14. //
  15. // The above copyright notice and this permission notice shall be included in
  16. // all copies or substantial portions of the Software.
  17. //
  18. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. // THE SOFTWARE.
  25. // +build arm 386
  26. package runtime
  27. import "unsafe"
  28. const (
  29. sign32 = 1 << (32 - 1)
  30. sign64 = 1 << (64 - 1)
  31. )
  32. func float64toint64(d float64) (y uint64) {
  33. _d2v(&y, d)
  34. return
  35. }
  36. func float64touint64(d float64) (y uint64) {
  37. _d2v(&y, d)
  38. return
  39. }
  40. func int64tofloat64(y int64) float64 {
  41. if y < 0 {
  42. return -uint64tofloat64(-uint64(y))
  43. }
  44. return uint64tofloat64(uint64(y))
  45. }
  46. func uint64tofloat64(y uint64) float64 {
  47. hi := float64(uint32(y >> 32))
  48. lo := float64(uint32(y))
  49. d := hi*(1<<32) + lo
  50. return d
  51. }
  52. func _d2v(y *uint64, d float64) {
  53. x := *(*uint64)(unsafe.Pointer(&d))
  54. xhi := uint32(x>>32)&0xfffff | 0x100000
  55. xlo := uint32(x)
  56. sh := 1075 - int32(uint32(x>>52)&0x7ff)
  57. var ylo, yhi uint32
  58. if sh >= 0 {
  59. sh := uint32(sh)
  60. /* v = (hi||lo) >> sh */
  61. if sh < 32 {
  62. if sh == 0 {
  63. ylo = xlo
  64. yhi = xhi
  65. } else {
  66. ylo = xlo>>sh | xhi<<(32-sh)
  67. yhi = xhi >> sh
  68. }
  69. } else {
  70. if sh == 32 {
  71. ylo = xhi
  72. } else if sh < 64 {
  73. ylo = xhi >> (sh - 32)
  74. }
  75. }
  76. } else {
  77. /* v = (hi||lo) << -sh */
  78. sh := uint32(-sh)
  79. if sh <= 11 {
  80. ylo = xlo << sh
  81. yhi = xhi<<sh | xlo>>(32-sh)
  82. } else {
  83. /* overflow */
  84. yhi = uint32(d) /* causes something awful */
  85. }
  86. }
  87. if x&sign64 != 0 {
  88. if ylo != 0 {
  89. ylo = -ylo
  90. yhi = ^yhi
  91. } else {
  92. yhi = -yhi
  93. }
  94. }
  95. *y = uint64(yhi)<<32 | uint64(ylo)
  96. }
  97. func uint64div(n, d uint64) uint64 {
  98. // Check for 32 bit operands
  99. if uint32(n>>32) == 0 && uint32(d>>32) == 0 {
  100. if uint32(d) == 0 {
  101. panicdivide()
  102. }
  103. return uint64(uint32(n) / uint32(d))
  104. }
  105. q, _ := dodiv(n, d)
  106. return q
  107. }
  108. func uint64mod(n, d uint64) uint64 {
  109. // Check for 32 bit operands
  110. if uint32(n>>32) == 0 && uint32(d>>32) == 0 {
  111. if uint32(d) == 0 {
  112. panicdivide()
  113. }
  114. return uint64(uint32(n) % uint32(d))
  115. }
  116. _, r := dodiv(n, d)
  117. return r
  118. }
  119. func int64div(n, d int64) int64 {
  120. // Check for 32 bit operands
  121. if int64(int32(n)) == n && int64(int32(d)) == d {
  122. if int32(n) == -0x80000000 && int32(d) == -1 {
  123. // special case: 32-bit -0x80000000 / -1 = -0x80000000,
  124. // but 64-bit -0x80000000 / -1 = 0x80000000.
  125. return 0x80000000
  126. }
  127. if int32(d) == 0 {
  128. panicdivide()
  129. }
  130. return int64(int32(n) / int32(d))
  131. }
  132. nneg := n < 0
  133. dneg := d < 0
  134. if nneg {
  135. n = -n
  136. }
  137. if dneg {
  138. d = -d
  139. }
  140. uq, _ := dodiv(uint64(n), uint64(d))
  141. q := int64(uq)
  142. if nneg != dneg {
  143. q = -q
  144. }
  145. return q
  146. }
  147. func int64mod(n, d int64) int64 {
  148. // Check for 32 bit operands
  149. if int64(int32(n)) == n && int64(int32(d)) == d {
  150. if int32(d) == 0 {
  151. panicdivide()
  152. }
  153. return int64(int32(n) % int32(d))
  154. }
  155. nneg := n < 0
  156. if nneg {
  157. n = -n
  158. }
  159. if d < 0 {
  160. d = -d
  161. }
  162. _, ur := dodiv(uint64(n), uint64(d))
  163. r := int64(ur)
  164. if nneg {
  165. r = -r
  166. }
  167. return r
  168. }
  169. //go:noescape
  170. func _mul64by32(lo64 *uint64, a uint64, b uint32) (hi32 uint32)
  171. //go:noescape
  172. func _div64by32(a uint64, b uint32, r *uint32) (q uint32)
  173. func dodiv(n, d uint64) (q, r uint64) {
  174. if GOARCH == "arm" {
  175. // arm doesn't have a division instruction, so
  176. // slowdodiv is the best that we can do.
  177. // TODO: revisit for arm64.
  178. return slowdodiv(n, d)
  179. }
  180. if d > n {
  181. return 0, n
  182. }
  183. if uint32(d>>32) != 0 {
  184. t := uint32(n>>32) / uint32(d>>32)
  185. var lo64 uint64
  186. hi32 := _mul64by32(&lo64, d, t)
  187. if hi32 != 0 || lo64 > n {
  188. return slowdodiv(n, d)
  189. }
  190. return uint64(t), n - lo64
  191. }
  192. // d is 32 bit
  193. var qhi uint32
  194. if uint32(n>>32) >= uint32(d) {
  195. if uint32(d) == 0 {
  196. panicdivide()
  197. }
  198. qhi = uint32(n>>32) / uint32(d)
  199. n -= uint64(uint32(d)*qhi) << 32
  200. } else {
  201. qhi = 0
  202. }
  203. var rlo uint32
  204. qlo := _div64by32(n, uint32(d), &rlo)
  205. return uint64(qhi)<<32 + uint64(qlo), uint64(rlo)
  206. }
  207. func slowdodiv(n, d uint64) (q, r uint64) {
  208. if d == 0 {
  209. panicdivide()
  210. }
  211. // Set up the divisor and find the number of iterations needed.
  212. capn := n
  213. if n >= sign64 {
  214. capn = sign64
  215. }
  216. i := 0
  217. for d < capn {
  218. d <<= 1
  219. i++
  220. }
  221. for ; i >= 0; i-- {
  222. q <<= 1
  223. if n >= d {
  224. n -= d
  225. q |= 1
  226. }
  227. d >>= 1
  228. }
  229. return q, n
  230. }