Windows NT 4.0 source code leak
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.

1002 lines
32 KiB

4 years ago
  1. // TITLE("Fast Integer Division and Remainder")
  2. //++
  3. //
  4. // Copyright (c) 1993 Digital Equipment Corporation
  5. //
  6. // Module Name:
  7. //
  8. // divide2.s
  9. //
  10. // Abstract:
  11. //
  12. // This module implements high-performance versions of the integer divide
  13. // and remainder routines that are called by assembler pseudo-ops.
  14. //
  15. // Author:
  16. //
  17. // Thomas Van Baak (tvb) 12-Jan-1993
  18. // Ken Lesniak (lesniak) 04-Nov-1992
  19. //
  20. // Environment:
  21. //
  22. // Any mode.
  23. //
  24. // Revision History:
  25. //
  26. //--
  27. #include "ksalpha.h"
  28. //
  29. // Implementation Notes:
  30. //
  31. // There are no Alpha machine instructions for performing integer division
  32. // (divl, divlu, divq, divqu) or remainder (reml, remlu, remq, remqu). The
  33. // machine instructions generated for these assembler pseudo instructions
  34. // are dependent on the type of operands.
  35. //
  36. // Division and remainder by constant values are replaced with a sequence
  37. // of instructions that depend on the data type and the value of the
  38. // constant. Shifting or reciprocal multiplication are used in most cases
  39. // to generate the result. No run-time code is necessary in these cases.
  40. //
  41. // Division and remainder by non-constant values are replaced with a
  42. // procedure call to a library routine to perform the operation. This file
  43. // contains those routines.
  44. //
  45. // This code is adapted from the Alpha/OSF version by Ken Lesniak.
  46. //
  47. // There are two sets of these eight functions. The __div set were used
  48. // by an earlier version of the acc compiler. This is the new __2div set.
  49. // The new functions are about an order of magnitude faster.
  50. //
  51. // The new function names differ from the original set of functions so
  52. // that the old and new compilers can co-exist for a time.
  53. //
  54. // Both the division algorithm code and the large division tables used by
  55. // the code are contained in the fastdiv.s file which is included several
  56. // times from this file.
  57. //
  58. //
  59. // Define common stack frame for functions in this file.
  60. //
  61. .struct 0
  62. DvRa: .space 8 // save register ra
  63. DvJr: .space 8 // save register t9
  64. DvNu: .space 8 // save register t10
  65. DvDi: .space 8 // save register t11
  66. DvT0: .space 8 // save register t0
  67. DvT1: .space 8 // save register t1
  68. DvT2: .space 8 // save register t2
  69. DvT3: .space 8 // save register t3
  70. DvT4: .space 8 // save register a0
  71. .space 8 // ensure 16-byte stack alignment
  72. DvFrameLength: // length of stack frame
  73. //
  74. // Define non-standard calling convention required by the compiler.
  75. //
  76. // The compiler uses t9, t10, t11, t12 as indicated below. All other
  77. // registers (except AT) must be preserved by this calling convention.
  78. //
  79. // For the fastdiv code, since register a0 must be preserved anyway (it
  80. // is used by gentrap), define temp register T4 to be a0. Similarly,
  81. // register J4 must be preserved, so define temp register T5 to be Jr.
  82. // And the fastdiv code allows Qu to also be temp register T6.
  83. //
  84. #define Jr t9 // ($23) return address
  85. #define Nu t10 // ($24) dividend (numerator)
  86. #define Di t11 // ($25) divisor (denominator)
  87. #define Qu t12 // ($27) result (quotient)
  88. #define Re Qu // ($27) result (remainder)
  89. #define T0 t0 // standard temp
  90. #define T1 t1 // standard temp
  91. #define T2 t2 // standard temp
  92. #define T3 t3 // standard temp
  93. #define T4 a0 // may use a0 as temp
  94. #define T5 Jr // may use Jr as temp
  95. #define T6 Qu // may overload Qu as temp T6 only
  96. #ifdef DIV2_DEBUG
  97. //
  98. // In order to debug locally, re-define some of the registers so that
  99. // these functions can be called using a standard calling convention.
  100. //
  101. #undef Jr
  102. #define Jr ra // standard return address register
  103. #undef Nu
  104. #define Nu a0 // dividend argument in a0
  105. #undef Di
  106. #define Di a1 // divisor argument in a1
  107. #undef Qu
  108. #define Qu v0 // quotient result in v0
  109. #undef Re
  110. #define Re v0 // remainder result in v0
  111. #undef T4
  112. #define T4 t4 // normal temp
  113. #endif
  114. SBTTL("Signed Long Integer Division")
  115. //++
  116. //
  117. // LONG
  118. // __2divl (
  119. // IN LONG Dividend,
  120. // IN LONG Divisor
  121. // )
  122. //
  123. // Routine Description:
  124. //
  125. // This function divides a signed 32-bit integer by a signed 32-bit integer
  126. // and returns the signed 32-bit integer result.
  127. //
  128. // Arguments:
  129. //
  130. // Dividend (t10) - Supplies the dividend (numerator) value.
  131. //
  132. // Divisor (t11) - Supplies the divisor (denominator) value.
  133. //
  134. // Return Value:
  135. //
  136. // The 32-bit integer result (quotient) is returned in register t12.
  137. //
  138. // Note:
  139. //
  140. // This function uses a non-standard calling procedure. The return address
  141. // is stored in the t9 register and the return value is in the t10 register.
  142. // No other registers are modified.
  143. //
  144. //--
  145. NESTED_ENTRY(__2divl, DvFrameLength, Jr)
  146. //
  147. // This prologue is magic. When executed during a call, it will save the
  148. // value of register ra (twice) and register t9 in the stack frame, even
  149. // though these registers are not modified by this function. The stores
  150. // appear to unnecessary.
  151. //
  152. // But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
  153. // is reverse executed by virtual unwind to reset the stack pointer and to
  154. // obtain the return address. The return address is the value of RA the
  155. // first time it is restored, which will be the saved value of t9.
  156. //
  157. .set noreorder
  158. .set noat
  159. lda sp, -DvFrameLength(sp) // allocate stack frame
  160. stq ra, DvRa(sp) // save ra register
  161. stq ra, DvJr(sp) // backtrace return address
  162. stq Jr, DvJr(sp) // save actual return address
  163. stq Nu, DvNu(sp) // save original dividend
  164. stq Di, DvDi(sp) // save original divisor
  165. stq t0, DvT0(sp) // save temp registers
  166. stq t1, DvT1(sp) //
  167. stq t2, DvT2(sp) //
  168. stq t3, DvT3(sp) //
  169. stq T4, DvT4(sp) //
  170. .set at
  171. .set reorder
  172. PROLOGUE_END
  173. addl Nu, 0, Nu // convert LONG dividend to quadword
  174. addl Di, 0, Di // convert LONG divisor to quadword
  175. //
  176. // Check for division of the most negative integer (0x800...00) by the least
  177. // negative (-1). The result would be an integer which is one greater than the
  178. // maximum positive integer. Since this cannot be represented, an overflow must
  179. // be generated.
  180. //
  181. addl Di, 1, t0 // 0 if Di == -1; != 0 otherwise
  182. mov Nu, t1 // copy dividend
  183. cmovne t0, 0, t1 // replace w/ 0 if divisor != -1
  184. sublv zero, t1, t1 // trap if dividend == 0x800..00
  185. //
  186. // Convert negative arguments to positive for the division algorithm.
  187. //
  188. subq zero, Nu, t0 // negate dividend
  189. cmovlt Nu, t0, Nu // get absolute value of dividend
  190. subq zero, Di, t0 // negate divisor
  191. cmovlt Di, t0, Di // get absolute value of divisor
  192. //
  193. // Set up defines and include the main body of the division code.
  194. //
  195. #define FASTDIV_OPTIONS (THIRTY_TWO_BIT | SIGNED | DIVISION)
  196. #include "fastdiv.s"
  197. //
  198. // Restore some registers and set the correct sign of the quotient.
  199. //
  200. ldq Jr, DvJr(sp) // restore return address
  201. ldq Nu, DvNu(sp) // restore original dividend
  202. ldq Di, DvDi(sp) // restore original divisor
  203. addl Qu, 0, Qu // ensure quotient is in canonical form
  204. subl zero, Qu, t1 // negate LONG quotient
  205. xor Nu, Di, t0 // compute sign of quotient
  206. addl t0, 0, t0 // ensure quotient is in canonical form
  207. cmovlt t0, t1, Qu // use negated quotient if necessary
  208. //
  209. // Restore other saved registers and return with quotient in register Qu.
  210. //
  211. ldq t0, DvT0(sp) // restore temp registers
  212. ldq t1, DvT1(sp) //
  213. ldq t2, DvT2(sp) //
  214. ldq t3, DvT3(sp) //
  215. ldq T4, DvT4(sp) //
  216. lda sp, DvFrameLength(sp) // deallocate stack frame
  217. ret zero, (Jr) // return
  218. .end __2divl
  219. SBTTL("Unsigned Long Integer Division")
  220. //++
  221. //
  222. // ULONG
  223. // __2divlu (
  224. // IN ULONG Dividend,
  225. // IN ULONG Divisor
  226. // )
  227. //
  228. // Routine Description:
  229. //
  230. // This function divides an unsigned 32-bit integer by an unsigned 32-bit
  231. // integer and returns the unsigned 32-bit integer result.
  232. //
  233. // Arguments:
  234. //
  235. // Dividend (t10) - Supplies the dividend (numerator) value.
  236. //
  237. // Divisor (t11) - Supplies the divisor (denominator) value.
  238. //
  239. // Return Value:
  240. //
  241. // The 32-bit integer result (quotient) is returned in register t12.
  242. //
  243. // Note:
  244. //
  245. // This function uses a non-standard calling procedure. The return address
  246. // is stored in the t9 register and the return value is in the t10 register.
  247. // No other registers are modified.
  248. //
  249. //--
  250. NESTED_ENTRY(__2divlu, DvFrameLength, Jr)
  251. //
  252. // This prologue is magic. When executed during a call, it will save the
  253. // value of register ra (twice) and register t9 in the stack frame, even
  254. // though these registers are not modified by this function. The stores
  255. // appear to unnecessary.
  256. //
  257. // But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
  258. // is reverse executed by virtual unwind to reset the stack pointer and to
  259. // obtain the return address. The return address is the value of RA the
  260. // first time it is restored, which will be the saved value of t9.
  261. //
  262. .set noreorder
  263. .set noat
  264. lda sp, -DvFrameLength(sp) // allocate stack frame
  265. stq ra, DvRa(sp) // save ra register
  266. stq ra, DvJr(sp) // backtrace return address
  267. stq Jr, DvJr(sp) // save actual return address
  268. stq Nu, DvNu(sp) // save original dividend
  269. stq Di, DvDi(sp) // save original divisor
  270. stq t0, DvT0(sp) // save temp registers
  271. stq t1, DvT1(sp) //
  272. stq t2, DvT2(sp) //
  273. stq t3, DvT3(sp) //
  274. stq T4, DvT4(sp) //
  275. .set at
  276. .set reorder
  277. PROLOGUE_END
  278. zap Nu, 0xf0, Nu // convert ULONG dividend to quadword
  279. zap Di, 0xf0, Di // convert ULONG divisor to quadword
  280. //
  281. // Set up defines and include the main body of the division code.
  282. //
  283. #define FASTDIV_OPTIONS (THIRTY_TWO_BIT | UNSIGNED | DIVISION)
  284. #include "fastdiv.s"
  285. //
  286. // Restore all saved registers and return with quotient in register Qu.
  287. //
  288. ldq Jr, DvJr(sp) // restore return address
  289. ldq Nu, DvNu(sp) // restore original dividend
  290. ldq Di, DvDi(sp) // restore original divisor
  291. ldq t0, DvT0(sp) // restore temp registers
  292. ldq t1, DvT1(sp) //
  293. ldq t2, DvT2(sp) //
  294. ldq t3, DvT3(sp) //
  295. ldq T4, DvT4(sp) //
  296. lda sp, DvFrameLength(sp) // deallocate stack frame
  297. ret zero, (Jr) // return
  298. .end __2divlu
  299. SBTTL("Signed Quad Integer Division")
  300. //++
  301. //
  302. // LONGLONG
  303. // __2divq (
  304. // IN LONGLONG Dividend,
  305. // IN LONGLONG Divisor
  306. // )
  307. //
  308. // Routine Description:
  309. //
  310. // This function divides a signed 64-bit integer by a signed 64-bit integer
  311. // and returns the signed 64-bit integer result.
  312. //
  313. // Arguments:
  314. //
  315. // Dividend (t10) - Supplies the dividend (numerator) value.
  316. //
  317. // Divisor (t11) - Supplies the divisor (denominator) value.
  318. //
  319. // Return Value:
  320. //
  321. // The 64-bit integer result (quotient) is returned in register t12.
  322. //
  323. // Note:
  324. //
  325. // This function uses a non-standard calling procedure. The return address
  326. // is stored in the t9 register and the return value is in the t10 register.
  327. // No other registers are modified.
  328. //
  329. //--
  330. NESTED_ENTRY(__2divq, DvFrameLength, Jr)
  331. //
  332. // This prologue is magic. When executed during a call, it will save the
  333. // value of register ra (twice) and register t9 in the stack frame, even
  334. // though these registers are not modified by this function. The stores
  335. // appear to unnecessary.
  336. //
  337. // But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
  338. // is reverse executed by virtual unwind to reset the stack pointer and to
  339. // obtain the return address. The return address is the value of RA the
  340. // first time it is restored, which will be the saved value of t9.
  341. //
  342. .set noreorder
  343. .set noat
  344. lda sp, -DvFrameLength(sp) // allocate stack frame
  345. stq ra, DvRa(sp) // save ra register
  346. stq ra, DvJr(sp) // backtrace return address
  347. stq Jr, DvJr(sp) // save actual return address
  348. stq Nu, DvNu(sp) // save original dividend
  349. stq Di, DvDi(sp) // save original divisor
  350. stq t0, DvT0(sp) // save temp registers
  351. stq t1, DvT1(sp) //
  352. stq t2, DvT2(sp) //
  353. stq t3, DvT3(sp) //
  354. stq T4, DvT4(sp) //
  355. .set at
  356. .set reorder
  357. PROLOGUE_END
  358. //
  359. // Check for division of the most negative integer (0x800..00) by the least
  360. // negative (-1). The result would be an integer which is one greater than the
  361. // maximum positive integer. Since this cannot be represented, an overflow must
  362. // be generated.
  363. //
  364. addq Di, 1, t0 // 0 if Di == -1; != 0 otherwise
  365. mov Nu, t1 // copy dividend
  366. cmovne t0, 0, t1 // replace w/ 0 if divisor != -1
  367. subqv zero, t1, t1 // trap if dividend == 0x800..00
  368. //
  369. // Convert negative arguments to positive for the division algorithm.
  370. //
  371. subq zero, Nu, t0 // negate dividend
  372. cmovlt Nu, t0, Nu // get absolute value of dividend
  373. subq zero, Di, t0 // negate divisor
  374. cmovlt Di, t0, Di // get absolute value of divisor
  375. //
  376. // Set up defines and include the main body of the division code.
  377. //
  378. #define FASTDIV_OPTIONS (SIXTY_FOUR_BIT | SIGNED | DIVISION)
  379. #include "fastdiv.s"
  380. //
  381. // Restore some registers and set the correct sign of the quotient.
  382. //
  383. ldq Jr, DvJr(sp) // restore return address
  384. ldq Nu, DvNu(sp) // restore original dividend
  385. ldq Di, DvDi(sp) // restore original divisor
  386. subq zero, Qu, t1 // negate quadword quotient
  387. xor Nu, Di, t0 // compute sign of quotient
  388. cmovlt t0, t1, Qu // use negated quotient if necessary
  389. //
  390. // Restore other saved registers and return with quotient in register Qu.
  391. //
  392. ldq t0, DvT0(sp) // restore temp registers
  393. ldq t1, DvT1(sp) //
  394. ldq t2, DvT2(sp) //
  395. ldq t3, DvT3(sp) //
  396. ldq T4, DvT4(sp) //
  397. lda sp, DvFrameLength(sp) // deallocate stack frame
  398. ret zero, (Jr) // return
  399. .end __2divq
  400. SBTTL("Unsigned Quad Integer Division")
  401. //++
  402. //
  403. // ULONGLONG
  404. // __2divqu (
  405. // IN ULONGLONG Dividend,
  406. // IN ULONGLONG Divisor
  407. // )
  408. //
  409. // Routine Description:
  410. //
  411. // This function divides an unsigned 64-bit integer by an unsigned 64-bit
  412. // integer and returns the unsigned 64-bit integer result.
  413. //
  414. // Arguments:
  415. //
  416. // Dividend (t10) - Supplies the dividend (numerator) value.
  417. //
  418. // Divisor (t11) - Supplies the divisor (denominator) value.
  419. //
  420. // Return Value:
  421. //
  422. // The 64-bit integer result (quotient) is returned in register t12.
  423. //
  424. // Note:
  425. //
  426. // This function uses a non-standard calling procedure. The return address
  427. // is stored in the t9 register and the return value is in the t10 register.
  428. // No other registers are modified.
  429. //
  430. //--
  431. NESTED_ENTRY(__2divqu, DvFrameLength, Jr)
  432. //
  433. // This prologue is magic. When executed during a call, it will save the
  434. // value of register ra (twice) and register t9 in the stack frame, even
  435. // though these registers are not modified by this function. The stores
  436. // appear to unnecessary.
  437. //
  438. // But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
  439. // is reverse executed by virtual unwind to reset the stack pointer and to
  440. // obtain the return address. The return address is the value of RA the
  441. // first time it is restored, which will be the saved value of t9.
  442. //
  443. .set noreorder
  444. .set noat
  445. lda sp, -DvFrameLength(sp) // allocate stack frame
  446. stq ra, DvRa(sp) // save ra register
  447. stq ra, DvJr(sp) // backtrace return address
  448. stq Jr, DvJr(sp) // save actual return address
  449. stq t0, DvT0(sp) // save temp registers
  450. stq t1, DvT1(sp) //
  451. stq t2, DvT2(sp) //
  452. stq t3, DvT3(sp) //
  453. stq T4, DvT4(sp) //
  454. .set at
  455. .set reorder
  456. PROLOGUE_END
  457. //
  458. // Set up defines and include the main body of the division code.
  459. //
  460. #define FASTDIV_OPTIONS (SIXTY_FOUR_BIT | UNSIGNED | DIVISION)
  461. #include "fastdiv.s"
  462. //
  463. // Restore all saved registers and return with quotient in register Qu.
  464. //
  465. ldq Jr, DvJr(sp) // restore return address
  466. ldq t0, DvT0(sp) // restore temp registers
  467. ldq t1, DvT1(sp) //
  468. ldq t2, DvT2(sp) //
  469. ldq t3, DvT3(sp) //
  470. ldq T4, DvT4(sp) //
  471. lda sp, DvFrameLength(sp) // deallocate stack frame
  472. ret zero, (Jr) // return
  473. .end __2divqu
  474. SBTTL("Signed Long Integer Remainder")
  475. //++
  476. //
  477. // LONG
  478. // __2reml (
  479. // IN LONG Dividend,
  480. // IN LONG Divisor
  481. // )
  482. //
  483. // Routine Description:
  484. //
  485. // This function divides a signed 32-bit integer by a signed 32-bit integer
  486. // and returns the signed 32-bit integer remainder result.
  487. //
  488. // Arguments:
  489. //
  490. // Dividend (t10) - Supplies the dividend (numerator) value.
  491. //
  492. // Divisor (t11) - Supplies the divisor (denominator) value.
  493. //
  494. // Return Value:
  495. //
  496. // The 32-bit integer result (remainder) is returned in register t12.
  497. //
  498. // Note:
  499. //
  500. // This function uses a non-standard calling procedure. The return address
  501. // is stored in the t9 register and the return value is in the t10 register.
  502. // No other registers are modified.
  503. //
  504. //--
  505. NESTED_ENTRY(__2reml, DvFrameLength, Jr)
  506. //
  507. // This prologue is magic. When executed during a call, it will save the
  508. // value of register ra (twice) and register t9 in the stack frame, even
  509. // though these registers are not modified by this function. The stores
  510. // appear to unnecessary.
  511. //
  512. // But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
  513. // is reverse executed by virtual unwind to reset the stack pointer and to
  514. // obtain the return address. The return address is the value of RA the
  515. // first time it is restored, which will be the saved value of t9.
  516. //
  517. .set noreorder
  518. .set noat
  519. lda sp, -DvFrameLength(sp) // allocate stack frame
  520. stq ra, DvRa(sp) // save ra register
  521. stq ra, DvJr(sp) // backtrace return address
  522. stq Jr, DvJr(sp) // save actual return address
  523. stq Nu, DvNu(sp) // save original dividend
  524. stq Di, DvDi(sp) // save original divisor
  525. stq t0, DvT0(sp) // save temp registers
  526. stq t1, DvT1(sp) //
  527. stq t2, DvT2(sp) //
  528. stq t3, DvT3(sp) //
  529. stq T4, DvT4(sp) //
  530. .set at
  531. .set reorder
  532. PROLOGUE_END
  533. addl Nu, 0, Nu // convert LONG dividend to quadword
  534. addl Di, 0, Di // convert LONG divisor to quadword
  535. //
  536. // Check for division of the most negative integer (0x800..00) by the least
  537. // negative (-1). The result would be an integer which is one greater than the
  538. // maximum positive integer. Since this cannot be represented, an overflow must
  539. // be generated.
  540. //
  541. addl Di, 1, t0 // 0 if Di == -1; != 0 otherwise
  542. mov Nu, t1 // copy dividend
  543. cmovne t0, 0, t1 // replace w/ 0 if divisor != -1
  544. sublv zero, t1, t1 // trap if dividend == 0x800..00
  545. //
  546. // Convert negative arguments to positive for the division algorithm.
  547. //
  548. subq zero, Nu, t0 // negate dividend
  549. cmovlt Nu, t0, Nu // get absolute value of dividend
  550. subq zero, Di, t0 // negate divisor
  551. cmovlt Di, t0, Di // get absolute value of divisor
  552. //
  553. // Set up defines and include the main body of the division code.
  554. //
  555. #define FASTDIV_OPTIONS (THIRTY_TWO_BIT | SIGNED | REMAINDER)
  556. #include "fastdiv.s"
  557. //
  558. // Restore some registers and set the correct sign of the remainder.
  559. //
  560. ldq Jr, DvJr(sp) // restore return address
  561. ldq Nu, DvNu(sp) // restore original dividend
  562. ldq Di, DvDi(sp) // restore original divisor
  563. addl Qu, 0, Qu // ensure remainder is in canonical form
  564. subl zero, Qu, t1 // negate LONG remainder
  565. addl Nu, 0, t0 // get dividend in canonical form
  566. cmovlt t0, t1, Qu // use negated remainder if necessary
  567. //
  568. // Restore other saved registers and return with remainder in register Qu.
  569. //
  570. ldq t0, DvT0(sp) // restore temp registers
  571. ldq t1, DvT1(sp) //
  572. ldq t2, DvT2(sp) //
  573. ldq t3, DvT3(sp) //
  574. ldq T4, DvT4(sp) //
  575. lda sp, DvFrameLength(sp) // deallocate stack frame
  576. ret zero, (Jr) // return
  577. .end __2reml
  578. SBTTL("Unsigned Long Integer Remainder")
  579. //++
  580. //
  581. // ULONG
  582. // __2remlu (
  583. // IN ULONG Dividend,
  584. // IN ULONG Divisor
  585. // )
  586. //
  587. // Routine Description:
  588. //
  589. // This function divides an unsigned 32-bit integer by an unsigned 32-bit
  590. // integer and returns the unsigned 32-bit integer remainder result.
  591. //
  592. // Arguments:
  593. //
  594. // Dividend (t10) - Supplies the dividend (numerator) value.
  595. //
  596. // Divisor (t11) - Supplies the divisor (denominator) value.
  597. //
  598. // Return Value:
  599. //
  600. // The 32-bit integer result (remainder) is returned in register t12.
  601. //
  602. // Note:
  603. //
  604. // This function uses a non-standard calling procedure. The return address
  605. // is stored in the t9 register and the return value is in the t10 register.
  606. // No other registers are modified.
  607. //
  608. //--
  609. NESTED_ENTRY(__2remlu, DvFrameLength, Jr)
  610. //
  611. // This prologue is magic. When executed during a call, it will save the
  612. // value of register ra (twice) and register t9 in the stack frame, even
  613. // though these registers are not modified by this function. The stores
  614. // appear to unnecessary.
  615. //
  616. // But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
  617. // is reverse executed by virtual unwind to reset the stack pointer and to
  618. // obtain the return address. The return address is the value of RA the
  619. // first time it is restored, which will be the saved value of t9.
  620. //
  621. .set noreorder
  622. .set noat
  623. lda sp, -DvFrameLength(sp) // allocate stack frame
  624. stq ra, DvRa(sp) // save ra register
  625. stq ra, DvJr(sp) // backtrace return address
  626. stq Jr, DvJr(sp) // save actual return address
  627. stq Nu, DvNu(sp) // save original dividend
  628. stq Di, DvDi(sp) // save original divisor
  629. stq t0, DvT0(sp) // save temp registers
  630. stq t1, DvT1(sp) //
  631. stq t2, DvT2(sp) //
  632. stq t3, DvT3(sp) //
  633. stq T4, DvT4(sp) //
  634. .set at
  635. .set reorder
  636. PROLOGUE_END
  637. zap Nu, 0xf0, Nu // convert ULONG dividend to quadword
  638. zap Di, 0xf0, Di // convert ULONG divisor to quadword
  639. //
  640. // Set up defines and include the main body of the division code.
  641. //
  642. #define FASTDIV_OPTIONS (THIRTY_TWO_BIT | UNSIGNED | REMAINDER)
  643. #include "fastdiv.s"
  644. //
  645. // Restore all saved registers and return with remainder in register Qu.
  646. //
  647. ldq Jr, DvJr(sp) // restore return address
  648. ldq Nu, DvNu(sp) // restore original dividend
  649. ldq Di, DvDi(sp) // restore original divisor
  650. ldq t0, DvT0(sp) // restore temp registers
  651. ldq t1, DvT1(sp) //
  652. ldq t2, DvT2(sp) //
  653. ldq t3, DvT3(sp) //
  654. ldq T4, DvT4(sp) //
  655. lda sp, DvFrameLength(sp) // deallocate stack frame
  656. ret zero, (Jr) // return
  657. .end __2remlu
  658. SBTTL("Signed Quad Integer Remainder")
  659. //++
  660. //
  661. // LONGLONG
  662. // __2remq (
  663. // IN LONGLONG Dividend,
  664. // IN LONGLONG Divisor
  665. // )
  666. //
  667. // Routine Description:
  668. //
  669. // This function divides a signed 64-bit integer by a signed 64-bit integer
  670. // and returns the signed 64-bit integer remainder result.
  671. //
  672. // Arguments:
  673. //
  674. // Dividend (t10) - Supplies the dividend (numerator) value.
  675. //
  676. // Divisor (t11) - Supplies the divisor (denominator) value.
  677. //
  678. // Return Value:
  679. //
  680. // The 64-bit integer result (remainder) is returned in register t12.
  681. //
  682. // Note:
  683. //
  684. // This function uses a non-standard calling procedure. The return address
  685. // is stored in the t9 register and the return value is in the t10 register.
  686. // No other registers are modified.
  687. //
  688. //--
  689. NESTED_ENTRY(__2remq, DvFrameLength, Jr)
  690. //
  691. // This prologue is magic. When executed during a call, it will save the
  692. // value of register ra (twice) and register t9 in the stack frame, even
  693. // though these registers are not modified by this function. The stores
  694. // appear to unnecessary.
  695. //
  696. // But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
  697. // is reverse executed by virtual unwind to reset the stack pointer and to
  698. // obtain the return address. The return address is the value of RA the
  699. // first time it is restored, which will be the saved value of t9.
  700. //
  701. .set noreorder
  702. .set noat
  703. lda sp, -DvFrameLength(sp) // allocate stack frame
  704. stq ra, DvRa(sp) // save ra register
  705. stq ra, DvJr(sp) // backtrace return address
  706. stq Jr, DvJr(sp) // save actual return address
  707. stq Nu, DvNu(sp) // save original dividend
  708. stq Di, DvDi(sp) // save original divisor
  709. stq t0, DvT0(sp) // save temp registers
  710. stq t1, DvT1(sp) //
  711. stq t2, DvT2(sp) //
  712. stq t3, DvT3(sp) //
  713. stq T4, DvT4(sp) //
  714. .set at
  715. .set reorder
  716. PROLOGUE_END
  717. //
  718. // Check for division of the most negative integer (0x800..00) by the least
  719. // negative (-1). The result would be an integer which is one greater than the
  720. // maximum positive integer. Since this cannot be represented, an overflow must
  721. // be generated.
  722. //
  723. addq Di, 1, t0 // 0 if Di == -1; != 0 otherwise
  724. mov Nu, t1 // copy dividend
  725. cmovne t0, 0, t1 // replace w/ 0 if divisor != -1
  726. subqv zero, t1, t1 // trap if dividend == 0x800..00
  727. //
  728. // Convert negative arguments to positive for the division algorithm.
  729. //
  730. subq zero, Nu, t0 // negate dividend
  731. cmovlt Nu, t0, Nu // get absolute value of dividend
  732. subq zero, Di, t0 // negate divisor
  733. cmovlt Di, t0, Di // get absolute value of divisor
  734. //
  735. // Set up defines and include the main body of the division code.
  736. //
  737. #define FASTDIV_OPTIONS (SIXTY_FOUR_BIT | SIGNED | REMAINDER)
  738. #include "fastdiv.s"
  739. //
  740. // Restore some registers and set the correct sign of the remainder.
  741. //
  742. ldq Jr, DvJr(sp) // restore return address
  743. ldq Nu, DvNu(sp) // restore original dividend
  744. ldq Di, DvDi(sp) // restore original divisor
  745. subq zero, Qu, t1 // negate quadword remainder
  746. cmovlt Nu, t1, Qu // use negated remainder if necessary
  747. //
  748. // Restore other saved registers and return with remainder in register Qu.
  749. //
  750. ldq t0, DvT0(sp) // restore temp registers
  751. ldq t1, DvT1(sp) //
  752. ldq t2, DvT2(sp) //
  753. ldq t3, DvT3(sp) //
  754. ldq T4, DvT4(sp) //
  755. lda sp, DvFrameLength(sp) // deallocate stack frame
  756. ret zero, (Jr) // return
  757. .end __2remq
  758. SBTTL("Unsigned Quad Integer Remainder")
  759. //++
  760. //
  761. // ULONGLONG
  762. // __2remqu (
  763. // IN ULONGLONG Dividend,
  764. // IN ULONGLONG Divisor
  765. // )
  766. //
  767. // Routine Description:
  768. //
  769. // This function divides an unsigned 64-bit integer by an unsigned 64-bit
  770. // integer and returns the unsigned 64-bit integer remainder result.
  771. //
  772. // Arguments:
  773. //
  774. // Dividend (t10) - Supplies the dividend (numerator) value.
  775. //
  776. // Divisor (t11) - Supplies the divisor (denominator) value.
  777. //
  778. // Return Value:
  779. //
  780. // The 64-bit integer result (remainder) is returned in register t12.
  781. //
  782. // Note:
  783. //
  784. // This function uses a non-standard calling procedure. The return address
  785. // is stored in the t9 register and the return value is in the t10 register.
  786. // No other registers are modified.
  787. //
  788. //--
  789. NESTED_ENTRY(__2remqu, DvFrameLength, Jr)
  790. //
  791. // This prologue is magic. When executed during a call, it will save the
  792. // value of register ra (twice) and register t9 in the stack frame, even
  793. // though these registers are not modified by this function. The stores
  794. // appear to unnecessary.
  795. //
  796. // But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
  797. // is reverse executed by virtual unwind to reset the stack pointer and to
  798. // obtain the return address. The return address is the value of RA the
  799. // first time it is restored, which will be the saved value of t9.
  800. //
  801. .set noreorder
  802. .set noat
  803. lda sp, -DvFrameLength(sp) // allocate stack frame
  804. stq ra, DvRa(sp) // save ra register
  805. stq ra, DvJr(sp) // backtrace return address
  806. stq Jr, DvJr(sp) // save actual return address
  807. stq t0, DvT0(sp) // save temp registers
  808. stq t1, DvT1(sp) //
  809. stq t2, DvT2(sp) //
  810. stq t3, DvT3(sp) //
  811. stq T4, DvT4(sp) //
  812. .set at
  813. .set reorder
  814. PROLOGUE_END
  815. //
  816. // Set up defines and include the main body of the division code.
  817. //
  818. #define FASTDIV_OPTIONS (SIXTY_FOUR_BIT | UNSIGNED | REMAINDER)
  819. #include "fastdiv.s"
  820. //
  821. // Restore all saved registers and return with remainder in register Qu.
  822. //
  823. ldq Jr, DvJr(sp) // restore return address
  824. ldq t0, DvT0(sp) // restore temp registers
  825. ldq t1, DvT1(sp) //
  826. ldq t2, DvT2(sp) //
  827. ldq t3, DvT3(sp) //
  828. ldq T4, DvT4(sp) //
  829. lda sp, DvFrameLength(sp) // deallocate stack frame
  830. ret zero, (Jr) // return
  831. .end __2remqu
  832. //
  833. // Now get one copy of the tables needed by the division code.
  834. //
  835. #define FASTDIV_TABLES
  836. #include "fastdiv.s"