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.

999 lines
31 KiB

4 years ago
  1. // TITLE("Large Integer Arithmetic")
  2. //++
  3. //
  4. // Copyright (c) 1990 Microsoft Corporation
  5. // Copyright (c) 1993 Digital Equipment Corporation
  6. //
  7. // Module Name:
  8. //
  9. // largeint.s
  10. //
  11. // Abstract:
  12. //
  13. // This module implements routines for performing extended integer
  14. // arithmetic.
  15. //
  16. // Author:
  17. //
  18. // David N. Cutler (davec) 18-Apr-1990
  19. //
  20. // Environment:
  21. //
  22. // Any mode.
  23. //
  24. // Revision History:
  25. //
  26. // Thomas Van Baak (tvb) 9-May-1992
  27. //
  28. // Adapted for Alpha AXP.
  29. //
  30. //--
  31. #include "ksalpha.h"
  32. //
  33. // Alpha AXP Implementation Notes:
  34. //
  35. // The LargeInteger functions defined below implement a set of portable
  36. // 64-bit integer arithmetic operations for x86, Mips, and Alpha systems
  37. // using the LARGE_INTEGER data type. Code using LARGE_INTEGER variables
  38. // and calling these functions will be portable across all NT platforms.
  39. // This is the recommended approach to 64-bit arithmetic on NT.
  40. //
  41. // However, if performance is more important than portability, then for
  42. // Alpha systems, the native 64-bit integer data types may be used instead
  43. // of the LARGE_INTEGER type and the LargeInteger functions. The Alpha C
  44. // compilers support a __int64 data type (renamed LONGLONG in the system
  45. // header files). All C integer arithmetic operators may be used with
  46. // these quadword types. This eliminates the need for, and the overhead
  47. // of, any of the portable LargeInteger functions.
  48. //
  49. // In general, a LARGE_INTEGER cannot simply be converted to a LONGLONG
  50. // because of explicit references in application code to the 32-bit LowPart
  51. // and HighPart members of the LARGE_INTEGER structure.
  52. //
  53. // The performance difference between using the portable LARGE_INTEGER
  54. // types with LargeInteger functions and the Alpha LONGLONG types and
  55. // operations is often not significant enough to warrant modifying otherwise
  56. // portable code. In addition, future compiler optimization and inlining may
  57. // actually result in identical performance between portable LARGE_INTEGER
  58. // code and Alpha specific LONGLONG code. Therefore it is recommended to
  59. // keep NT source code portable.
  60. //
  61. // The Alpha source for the large integer functions below differs from the
  62. // Mips version since for Alpha a 64-bit argument or return value is passed
  63. // through a 64-bit integer register. In addition, most operations are
  64. // implemented with a single instruction. The division routines below,
  65. // however, like Mips, use a simple shift/subtract algorithm which is
  66. // considerably slower than the algorithm used by Alpha runtime division
  67. // routines.
  68. //
  69. SBTTL("Convert Long to Large Integer")
  70. //++
  71. //
  72. // LARGE_INTEGER
  73. // RtlConvertLongToLargeInteger (
  74. // IN LONG SignedInteger
  75. // )
  76. //
  77. // Routine Description:
  78. //
  79. // This function converts a signed integer to a signed large integer
  80. // and returns the result.
  81. //
  82. // Arguments:
  83. //
  84. // SignedInteger (a0) - Supplies the value to convert.
  85. //
  86. // Return Value:
  87. //
  88. // The large integer result is returned as the function value in v0.
  89. //
  90. //--
  91. LEAF_ENTRY(RtlConvertLongToLargeInteger)
  92. addl a0, 0, v0 // ensure canonical (signed long) form
  93. ret zero, (ra) // return
  94. .end RtlConvertLongToLargeInteger
  95. SBTTL("Convert Ulong to Large Integer")
  96. //++
  97. //
  98. // LARGE_INTEGER
  99. // RtlConvertUlongToLargeInteger (
  100. // IN ULONG UnsignedInteger
  101. // )
  102. //
  103. // Routine Description:
  104. //
  105. // This function converts an unsigned integer to a signed large
  106. // integer and returns the result.
  107. //
  108. // Arguments:
  109. //
  110. // UnsignedInteger (a0) - Supplies the value to convert.
  111. //
  112. // Return Value:
  113. //
  114. // The large integer result is returned as the function value in v0.
  115. //
  116. //--
  117. LEAF_ENTRY(RtlConvertUlongToLargeInteger)
  118. zap a0, 0xf0, v0 // convert canonical ULONG to quadword
  119. ret zero, (ra) // return
  120. .end RtlConvertUlongToLargeInteger
  121. SBTTL("Enlarged Signed Integer Multiply")
  122. //++
  123. //
  124. // LARGE_INTEGER
  125. // RtlEnlargedIntegerMultiply (
  126. // IN LONG Multiplicand,
  127. // IN LONG Multiplier
  128. // )
  129. //
  130. // Routine Description:
  131. //
  132. // This function multiplies a signed integer by a signed integer and
  133. // returns a signed large integer result.
  134. //
  135. // N.B. An overflow is not possible.
  136. //
  137. // Arguments:
  138. //
  139. // Multiplicand (a0) - Supplies the multiplicand value.
  140. //
  141. // Multiplier (a1) - Supplies the multiplier value.
  142. //
  143. // Return Value:
  144. //
  145. // The large integer result is returned as the function value in v0.
  146. //
  147. //--
  148. LEAF_ENTRY(RtlEnlargedIntegerMultiply)
  149. addl a0, 0, a0 // ensure canonical (signed long) form
  150. addl a1, 0, a1 // ensure canonical (signed long) form
  151. mulq a0, a1, v0 // multiply signed both quadwords
  152. ret zero, (ra) // return
  153. .end RtlEnlargedIntegerMultiply
  154. SBTTL("Enlarged Unsigned Divide")
  155. //++
  156. //
  157. // ULONG
  158. // RtlEnlargedUnsignedDivide (
  159. // IN ULARGE_INTEGER Dividend,
  160. // IN ULONG Divisor,
  161. // IN OUT PULONG Remainder OPTIONAL
  162. // )
  163. //
  164. // Routine Description:
  165. //
  166. // This function divides an unsigned large integer by an unsigned long
  167. // and returns the resultant quotient and optionally the remainder.
  168. //
  169. // N.B. An overflow or divide by zero exception is possible.
  170. //
  171. // Arguments:
  172. //
  173. // Dividend (a0) - Supplies the unsigned 64-bit dividend value.
  174. //
  175. // Divisor (a1) - Supplies the unsigned 32-bit divisor value.
  176. //
  177. // Remainder (a2) - Supplies an optional pointer to a variable that
  178. // receives the unsigned 32-bit remainder.
  179. //
  180. // Return Value:
  181. //
  182. // The unsigned long integer quotient is returned as the function value.
  183. //
  184. //--
  185. LEAF_ENTRY(RtlEnlargedUnsignedDivide)
  186. //
  187. // Check for division by zero.
  188. //
  189. zap a1, 0xf0, a1 // convert ULONG divisor to quadword
  190. beq a1, 30f // trap if divisor is zero
  191. //
  192. // Check for overflow. If the divisor is less than the upper half of the
  193. // dividend the quotient would be wider than 32 bits.
  194. //
  195. srl a0, 32, t0 // get upper longword of dividend
  196. cmpule a1, t0, t1 // is divisor <= upper dividend?
  197. bne t1, 40f // if ne[true], then overflow trap
  198. //
  199. // Perform the shift/subtract loop 8 times and 4 bits per loop.
  200. //
  201. // t0 - Temp used for 0/1 results of compares.
  202. // t1 - High 64-bits of 128-bit (t1, a0) dividend.
  203. // t2 - Loop counter.
  204. //
  205. ldiq t2, 32/4 // set iteration count
  206. srl a0, 32, t1 // get top 32 bits of carry-out
  207. sll a0, 32, a0 // preshift first 32 bits left
  208. 10: cmplt a0, 0, t0 // predict low-dividend shift carry-out
  209. addq a0, a0, a0 // shift low-dividend left
  210. addq t1, t1, t1 // shift high-dividend left
  211. bis t1, t0, t1 // merge in carry-out of low-dividend
  212. cmpule a1, t1, t0 // if dividend >= divisor,
  213. addq a0, t0, a0 // then set quotient bit
  214. subq t1, a1, t0 // subtract divisor from dividend,
  215. cmovlbs a0, t0, t1 // if dividend >= divisor
  216. cmplt a0, 0, t0 // predict low-dividend shift carry-out
  217. addq a0, a0, a0 // shift low-dividend left
  218. addq t1, t1, t1 // shift high-dividend left
  219. bis t1, t0, t1 // merge in carry-out of low-dividend
  220. cmpule a1, t1, t0 // if dividend >= divisor,
  221. addq a0, t0, a0 // then set quotient bit
  222. subq t1, a1, t0 // subtract divisor from dividend,
  223. cmovlbs a0, t0, t1 // if dividend >= divisor
  224. cmplt a0, 0, t0 // predict low-dividend shift carry-out
  225. addq a0, a0, a0 // shift low-dividend left
  226. addq t1, t1, t1 // shift high-dividend left
  227. bis t1, t0, t1 // merge in carry-out of low-dividend
  228. cmpule a1, t1, t0 // if dividend >= divisor,
  229. addq a0, t0, a0 // then set quotient bit
  230. subq t1, a1, t0 // subtract divisor from dividend,
  231. cmovlbs a0, t0, t1 // if dividend >= divisor
  232. cmplt a0, 0, t0 // predict low-dividend shift carry-out
  233. addq a0, a0, a0 // shift low-dividend left
  234. addq t1, t1, t1 // shift high-dividend left
  235. bis t1, t0, t1 // merge in carry-out of low-dividend
  236. cmpule a1, t1, t0 // if dividend >= divisor,
  237. addq a0, t0, a0 // then set quotient bit
  238. subq t1, a1, t0 // subtract divisor from dividend,
  239. cmovlbs a0, t0, t1 // if dividend >= divisor
  240. subq t2, 1, t2 // any more iterations?
  241. bne t2, 10b //
  242. //
  243. // Finished with remainder value in t1 and quotient value in a0.
  244. //
  245. addl a0, 0, v0 // set longword quotient return value
  246. beq a2, 20f // skip optional remainder store
  247. stl t1, 0(a2) // store longword remainder
  248. 20: ret zero, (ra) // return
  249. //
  250. // Generate an exception for divide by zero and return a zero quotient if the
  251. // caller continues execution.
  252. //
  253. 30: ldil a0, GENTRAP_INTEGER_DIVIDE_BY_ZERO
  254. GENERATE_TRAP
  255. ldil v0, 0 // return zero quotient
  256. ret zero, (ra) // return
  257. //
  258. // Generate an exception for overflow.
  259. //
  260. 40: ldiq a0, 0x8000000000000000 //
  261. subqv zero, a0, v0 // negate in order to overflow
  262. trapb // wait for trap to occur
  263. ret zero, (ra) // return
  264. .end RtlEnlargedUnsignedDivide
  265. SBTTL("Enlarged Unsigned Integer Multiply")
  266. //++
  267. //
  268. // LARGE_INTEGER
  269. // RtlEnlargedUnsignedMultiply (
  270. // IN ULONG Multiplicand,
  271. // IN ULONG Multiplier
  272. // )
  273. //
  274. // Routine Description:
  275. //
  276. // This function multiplies an unsigned integer by an unsigned integer
  277. // and returns a signed large integer result.
  278. //
  279. // Arguments:
  280. //
  281. // Multiplicand (a0) - Supplies the multiplicand value.
  282. //
  283. // Multiplier (a1) - Supplies the multiplier value.
  284. //
  285. // Return Value:
  286. //
  287. // The large integer result is returned as the function value in v0.
  288. //
  289. //--
  290. LEAF_ENTRY(RtlEnlargedUnsignedMultiply)
  291. zap a0, 0xf0, a0 // convert canonical ULONG to quadword
  292. zap a1, 0xf0, a1 // convert canonical ULONG to quadword
  293. mulq a0, a1, v0 // multiply signed both quadwords
  294. ret zero, (ra) // return
  295. .end RtlEnlargedUnsignedMultiply
  296. SBTTL("Extended Integer Multiply")
  297. //++
  298. //
  299. // LARGE_INTEGER
  300. // RtlExtendedIntegerMultiply (
  301. // IN LARGE_INTEGER Multiplicand,
  302. // IN LONG Multiplier
  303. // )
  304. //
  305. // Routine Description:
  306. //
  307. // This function multiplies a signed large integer by a signed integer and
  308. // returns the signed large integer result.
  309. //
  310. // N.B. An overflow is possible, but no exception is generated.
  311. //
  312. // Arguments:
  313. //
  314. // Multiplicand (a0) - Supplies the multiplicand value.
  315. //
  316. // Multiplier (a1) - Supplies the multiplier value.
  317. //
  318. // Return Value:
  319. //
  320. // The large integer result is returned as the function value in v0.
  321. //
  322. //--
  323. LEAF_ENTRY(RtlExtendedIntegerMultiply)
  324. addl a1, 0, a1 // ensure canonical (signed long) form
  325. mulq a0, a1, v0 // multiply signed both quadwords
  326. ret zero, (ra) // return
  327. .end RtlExtendedIntegerMultiply
  328. SBTTL("Extended Large Integer Divide")
  329. //++
  330. //
  331. // LARGE_INTEGER
  332. // RtlExtendedLargeIntegerDivide (
  333. // IN LARGE_INTEGER Dividend,
  334. // IN ULONG Divisor,
  335. // IN OUT PULONG Remainder OPTIONAL
  336. // )
  337. //
  338. // Routine Description:
  339. //
  340. // This function divides an unsigned large integer by an unsigned long
  341. // and returns the quadword quotient and optionally the long remainder.
  342. //
  343. // N.B. A divide by zero exception is possible.
  344. //
  345. // Arguments:
  346. //
  347. // Dividend (a0) - Supplies the dividend value.
  348. //
  349. // Divisor (a1) - Supplies the divisor value.
  350. //
  351. // Remainder (a2) - Supplies an optional pointer to a variable that
  352. // receives the remainder.
  353. //
  354. // Return Value:
  355. //
  356. // The large integer result is returned as the function value in v0.
  357. //
  358. //--
  359. LEAF_ENTRY(RtlExtendedLargeIntegerDivide)
  360. //
  361. // Check for division by zero.
  362. //
  363. zap a1, 0xf0, a1 // convert canonical ULONG to quadword
  364. beq a1, 30f // trap if divisor is zero
  365. //
  366. // Perform the shift/subtract loop 16 times and 4 bits per loop.
  367. //
  368. // t0 - Temp used for 0/1 results of compares.
  369. // t1 - High 64-bits of 128-bit (t1, a0) dividend.
  370. // t2 - Loop counter.
  371. //
  372. ldiq t2, 64/4 // set iteration count
  373. ldiq t1, 0 // zero-extend dividend to 128 bits
  374. 10: cmplt a0, 0, t0 // predict low-dividend shift carry-out
  375. addq a0, a0, a0 // shift low-dividend left
  376. addq t1, t1, t1 // shift high-dividend left
  377. bis t1, t0, t1 // merge in carry-out of low-dividend
  378. cmpule a1, t1, t0 // if dividend >= divisor,
  379. addq a0, t0, a0 // then set quotient bit
  380. subq t1, a1, t0 // subtract divisor from dividend,
  381. cmovlbs a0, t0, t1 // if dividend >= divisor
  382. cmplt a0, 0, t0 // predict low-dividend shift carry-out
  383. addq a0, a0, a0 // shift low-dividend left
  384. addq t1, t1, t1 // shift high-dividend left
  385. bis t1, t0, t1 // merge in carry-out of low-dividend
  386. cmpule a1, t1, t0 // if dividend >= divisor,
  387. addq a0, t0, a0 // then set quotient bit
  388. subq t1, a1, t0 // subtract divisor from dividend,
  389. cmovlbs a0, t0, t1 // if dividend >= divisor
  390. cmplt a0, 0, t0 // predict low-dividend shift carry-out
  391. addq a0, a0, a0 // shift low-dividend left
  392. addq t1, t1, t1 // shift high-dividend left
  393. bis t1, t0, t1 // merge in carry-out of low-dividend
  394. cmpule a1, t1, t0 // if dividend >= divisor,
  395. addq a0, t0, a0 // then set quotient bit
  396. subq t1, a1, t0 // subtract divisor from dividend,
  397. cmovlbs a0, t0, t1 // if dividend >= divisor
  398. cmplt a0, 0, t0 // predict low-dividend shift carry-out
  399. addq a0, a0, a0 // shift low-dividend left
  400. addq t1, t1, t1 // shift high-dividend left
  401. bis t1, t0, t1 // merge in carry-out of low-dividend
  402. cmpule a1, t1, t0 // if dividend >= divisor,
  403. addq a0, t0, a0 // then set quotient bit
  404. subq t1, a1, t0 // subtract divisor from dividend,
  405. cmovlbs a0, t0, t1 // if dividend >= divisor
  406. subq t2, 1, t2 // any more iterations?
  407. bne t2, 10b //
  408. //
  409. // Finished with remainder value in t1 and quotient value in a0.
  410. //
  411. mov a0, v0 // set quadword quotient return value
  412. beq a2, 20f // skip optional remainder store
  413. stl t1, 0(a2) // store longword remainder
  414. 20: ret zero, (ra) // return
  415. //
  416. // Generate an exception for divide by zero.
  417. //
  418. 30: ldil a0, GENTRAP_INTEGER_DIVIDE_BY_ZERO
  419. GENERATE_TRAP
  420. br zero, 30b // in case they continue
  421. .end RtlExtendedLargeIntegerDivide
  422. SBTTL("Extended Magic Divide")
  423. //++
  424. //
  425. // LARGE_INTEGER
  426. // RtlExtendedMagicDivide (
  427. // IN LARGE_INTEGER Dividend,
  428. // IN LARGE_INTEGER MagicDivisor,
  429. // IN CCHAR ShiftCount
  430. // )
  431. //
  432. // Routine Description:
  433. //
  434. // This function divides a signed large integer by an unsigned large integer
  435. // and returns the signed large integer result. The division is performed
  436. // using reciprocal multiplication of a signed large integer value by an
  437. // unsigned large integer fraction which represents the most significant
  438. // 64-bits of the reciprocal divisor rounded up in its least significant bit
  439. // and normalized with respect to bit 63. A shift count is also provided
  440. // which is used to truncate the fractional bits from the result value.
  441. //
  442. // Arguments:
  443. //
  444. // Dividend (a0) - Supplies the dividend value.
  445. //
  446. // MagicDivisor (a1) - Supplies the magic divisor value which
  447. // is a 64-bit multiplicative reciprocal.
  448. //
  449. // Shiftcount (a2) - Supplies the right shift adjustment value.
  450. //
  451. // Return Value:
  452. //
  453. // The large integer result is returned as the function value in v0.
  454. //
  455. //--
  456. LEAF_ENTRY(RtlExtendedMagicDivide)
  457. //
  458. // Make the dividend positive for the reciprocal multiplication to work.
  459. //
  460. negq a0, t0 // negate dividend
  461. cmovgt a0, a0, t0 // get absolute value in t0
  462. //
  463. // Multiply both quadword arguments together and take only the upper 64 bits of
  464. // the resulting 128 bit product. This can be done using the umulh instruction.
  465. //
  466. // Division of a dividend by a constant divisor through reciprocal
  467. // multiplication works because a/b is equivalent to (a*x)/(b*x) for any
  468. // value of x. Now if b is a constant, some "magic" integer x can be chosen,
  469. // based on the value of b, so that (b*x) is very close to a large power of
  470. // two (e.g., 2^64). Then a/b = (a*x)/(b*x) = (a*x)/(2^64) = (a*x)>>64. This
  471. // effectively turns the problem of division by a constant into multiplication
  472. // by a constant which is a much faster operation.
  473. //
  474. umulh t0, a1, t1 // multiply high both quadword arguments
  475. sra t1, a2, t1 // shift result right by requested amount
  476. //
  477. // Make the result negative if the dividend was negative.
  478. //
  479. negq t1, t0 // negate result
  480. cmovgt a0, t1, t0 // restore sign of dividend
  481. mov t0, v0 // set quadword result return value
  482. ret zero, (ra) // return
  483. .end RtlExtendedMagicDivide
  484. SBTTL("Large Integer Add")
  485. //++
  486. //
  487. // LARGE_INTEGER
  488. // RtlLargeIntegerAdd (
  489. // IN LARGE_INTEGER Addend1,
  490. // IN LARGE_INTEGER Addend2
  491. // )
  492. //
  493. // Routine Description:
  494. //
  495. // This function adds a signed large integer to a signed large integer and
  496. // returns the signed large integer result.
  497. //
  498. // N.B. An overflow is possible, but no exception is generated.
  499. //
  500. // Arguments:
  501. //
  502. // Addend1 (a0) - Supplies the first addend value.
  503. //
  504. // Addend2 (a1) - Supplies the second addend value.
  505. //
  506. // Return Value:
  507. //
  508. // The large integer result is returned as the function value in v0.
  509. //
  510. //--
  511. LEAF_ENTRY(RtlLargeIntegerAdd)
  512. addq a0, a1, v0 // add both quadword arguments
  513. ret zero, (ra) // return
  514. .end RtlLargeIntegerAdd
  515. SBTTL("Large Integer Arithmetic Shift Right")
  516. //++
  517. //
  518. // LARGE_INTEGER
  519. // RtlLargeIntegerArithmeticShift (
  520. // IN LARGE_INTEGER LargeInteger,
  521. // IN CCHAR ShiftCount
  522. // )
  523. //
  524. // Routine Description:
  525. //
  526. // This function shifts a signed large integer right by an unsigned integer
  527. // modulo 64 and returns the shifted signed large integer result.
  528. //
  529. // Arguments:
  530. //
  531. // LargeInteger (a0) - Supplies the large integer to be shifted.
  532. //
  533. // ShiftCount (a1) - Supplies the right shift count.
  534. //
  535. // Return Value:
  536. //
  537. // The large integer result is returned as the function value in v0.
  538. //
  539. //--
  540. LEAF_ENTRY(RtlLargeIntegerArithmeticShift)
  541. sra a0, a1, v0 // shift the quadword right/arithmetic
  542. ret zero, (ra) // return
  543. .end RtlLargeIntegerArithmeticShift
  544. SBTTL("Large Integer Divide")
  545. //++
  546. //
  547. // LARGE_INTEGER
  548. // RtlLargeIntegerDivide (
  549. // IN LARGE_INTEGER Dividend,
  550. // IN LARGE_INTEGER Divisor,
  551. // IN OUT PLARGE_INTEGER Remainder OPTIONAL
  552. // )
  553. //
  554. // Routine Description:
  555. //
  556. // This function divides an unsigned large integer by an unsigned large
  557. // integer and returns the quadword quotient and optionally the quadword
  558. // remainder.
  559. //
  560. // N.B. A divide by zero exception is possible.
  561. //
  562. // Arguments:
  563. //
  564. // Dividend (a0) - Supplies the dividend value.
  565. //
  566. // Divisor (a1) - Supplies the divisor value.
  567. //
  568. // Remainder (a2) - Supplies an optional pointer to a variable that
  569. // receives the remainder.
  570. //
  571. // Return Value:
  572. //
  573. // The large integer result is returned as the function value in v0.
  574. //
  575. //--
  576. LEAF_ENTRY(RtlLargeIntegerDivide)
  577. //
  578. // Check for division by zero.
  579. //
  580. beq a1, 30f // trap if divisor is zero
  581. //
  582. // Perform the shift/subtract loop 16 times and 4 bits per loop.
  583. //
  584. // t0 - Temp used for 0/1 results of compares.
  585. // t1 - High 64-bits of 128-bit (t1, a0) dividend.
  586. // t2 - Loop counter.
  587. //
  588. ldiq t2, 64/4 // set iteration count
  589. ldiq t1, 0 // zero-extend dividend to 128 bits
  590. 10: cmplt a0, 0, t0 // predict low-dividend shift carry-out
  591. addq a0, a0, a0 // shift low-dividend left
  592. addq t1, t1, t1 // shift high-dividend left
  593. bis t1, t0, t1 // merge in carry-out of low-dividend
  594. cmpule a1, t1, t0 // if dividend >= divisor,
  595. addq a0, t0, a0 // then set quotient bit
  596. subq t1, a1, t0 // subtract divisor from dividend,
  597. cmovlbs a0, t0, t1 // if dividend >= divisor
  598. cmplt a0, 0, t0 // predict low-dividend shift carry-out
  599. addq a0, a0, a0 // shift low-dividend left
  600. addq t1, t1, t1 // shift high-dividend left
  601. bis t1, t0, t1 // merge in carry-out of low-dividend
  602. cmpule a1, t1, t0 // if dividend >= divisor,
  603. addq a0, t0, a0 // then set quotient bit
  604. subq t1, a1, t0 // subtract divisor from dividend,
  605. cmovlbs a0, t0, t1 // if dividend >= divisor
  606. cmplt a0, 0, t0 // predict low-dividend shift carry-out
  607. addq a0, a0, a0 // shift low-dividend left
  608. addq t1, t1, t1 // shift high-dividend left
  609. bis t1, t0, t1 // merge in carry-out of low-dividend
  610. cmpule a1, t1, t0 // if dividend >= divisor,
  611. addq a0, t0, a0 // then set quotient bit
  612. subq t1, a1, t0 // subtract divisor from dividend,
  613. cmovlbs a0, t0, t1 // if dividend >= divisor
  614. cmplt a0, 0, t0 // predict low-dividend shift carry-out
  615. addq a0, a0, a0 // shift low-dividend left
  616. addq t1, t1, t1 // shift high-dividend left
  617. bis t1, t0, t1 // merge in carry-out of low-dividend
  618. cmpule a1, t1, t0 // if dividend >= divisor,
  619. addq a0, t0, a0 // then set quotient bit
  620. subq t1, a1, t0 // subtract divisor from dividend,
  621. cmovlbs a0, t0, t1 // if dividend >= divisor
  622. subq t2, 1, t2 // any more iterations?
  623. bne t2, 10b //
  624. //
  625. // Finished with remainder value in t1 and quotient value in a0.
  626. //
  627. mov a0, v0 // set quadword quotient return value
  628. beq a2, 20f // skip optional remainder store
  629. stq t1, 0(a2) // store quadword remainder
  630. 20: ret zero, (ra) // return
  631. //
  632. // Generate an exception for divide by zero.
  633. //
  634. 30: ldil a0, GENTRAP_INTEGER_DIVIDE_BY_ZERO
  635. GENERATE_TRAP
  636. br zero, 30b // in case they continue
  637. .end RtlLargeIntegerDivide
  638. SBTTL("Large Integer Negate")
  639. //++
  640. //
  641. // LARGE_INTEGER
  642. // RtlLargeIntegerNegate (
  643. // IN LARGE_INTEGER Subtrahend
  644. // )
  645. //
  646. // Routine Description:
  647. //
  648. // This function negates a signed large integer and returns the signed
  649. // large integer result.
  650. //
  651. // N.B. An overflow is possible, but no exception is generated.
  652. //
  653. // Arguments:
  654. //
  655. // Subtrahend (a0) - Supplies the subtrahend value.
  656. //
  657. // Return Value:
  658. //
  659. // The large integer result is returned as the function value in v0.
  660. //
  661. //--
  662. LEAF_ENTRY(RtlLargeIntegerNegate)
  663. subq zero, a0, v0 // negate the quadword argument
  664. ret zero, (ra) // return
  665. .end RtlLargeIntegerNegate
  666. SBTTL("Large Integer Shift Left")
  667. //++
  668. //
  669. // LARGE_INTEGER
  670. // RtlLargeIntegerShiftLeft (
  671. // IN LARGE_INTEGER LargeInteger,
  672. // IN CCHAR ShiftCount
  673. // )
  674. //
  675. // Routine Description:
  676. //
  677. // This function shifts a signed large integer left by an unsigned integer
  678. // modulo 64 and returns the shifted signed large integer result.
  679. //
  680. // Arguments:
  681. //
  682. // LargeInteger (a0) - Supplies the large integer to be shifted.
  683. //
  684. // ShiftCount (a1) - Supplies the left shift count.
  685. //
  686. // Return Value:
  687. //
  688. // The large integer result is returned as the function value in v0.
  689. //
  690. //--
  691. LEAF_ENTRY(RtlLargeIntegerShiftLeft)
  692. sll a0, a1, v0 // shift the quadword argument left
  693. ret zero, (ra) // return
  694. .end RtlLargeIntegerShiftLeft
  695. SBTTL("Large Integer Logical Shift Right")
  696. //++
  697. //
  698. // LARGE_INTEGER
  699. // RtlLargeIntegerShiftRight (
  700. // IN LARGE_INTEGER LargeInteger,
  701. // IN CCHAR ShiftCount
  702. // )
  703. //
  704. // Routine Description:
  705. //
  706. // This function shifts an unsigned large integer right by an unsigned
  707. // integer modulo 64 and returns the shifted unsigned large integer result.
  708. //
  709. // Arguments:
  710. //
  711. // LargeInteger (a0) - Supplies the large integer to be shifted.
  712. //
  713. // ShiftCount (a1) - Supplies the right shift count.
  714. //
  715. // Return Value:
  716. //
  717. // The large integer result is returned as the function value in v0.
  718. //
  719. //--
  720. LEAF_ENTRY(RtlLargeIntegerShiftRight)
  721. srl a0, a1, v0 // shift the quadword right/logical
  722. ret zero, (ra) // return
  723. .end RtlLargeIntegerShiftRight
  724. SBTTL("Large Integer Subtract")
  725. //++
  726. //
  727. // LARGE_INTEGER
  728. // RtlLargeIntegerSubtract (
  729. // IN LARGE_INTEGER Minuend,
  730. // IN LARGE_INTEGER Subtrahend
  731. // )
  732. //
  733. // Routine Description:
  734. //
  735. // This function subtracts a signed large integer from a signed large
  736. // integer and returns the signed large integer result.
  737. //
  738. // N.B. An overflow is possible, but no exception is generated.
  739. //
  740. // Arguments:
  741. //
  742. // Minuend (a0) - Supplies the minuend value.
  743. //
  744. // Subtrahend (a1) - Supplies the subtrahend value.
  745. //
  746. // Return Value:
  747. //
  748. // The large integer result is returned as the function value in v0.
  749. //
  750. //--
  751. LEAF_ENTRY(RtlLargeIntegerSubtract)
  752. subq a0, a1, v0 // subtract the quadword arguments
  753. ret zero, (ra) // return
  754. .end RtlLargeIntegerSubtract
  755. SBTTL("128-bit Signed Integer Multiplication")
  756. //++
  757. //
  758. // VOID
  759. // Rtlp128BitSignedMultiply (
  760. // IN LONGLONG Multiplicand,
  761. // IN LONGLONG Multiplier,
  762. // IN OUT PULONGLONG ProductLower,
  763. // IN OUT PLONGLONG ProductUpper
  764. // )
  765. //
  766. // Routine Description:
  767. //
  768. // This function multiplies a signed quadword (or signed large integer)
  769. // by a signed quadword (or signed large integer) and returns the full
  770. // 128-bit signed product indirectly through pointers to two quadwords.
  771. //
  772. // N.B. Signed multiplication is implemented with an unsigned multiply
  773. // followed by up to two subtractions. The subtractions are necessary for
  774. // the following reason. Within an N-bit register, a negative N-bit two's
  775. // compliment signed integer (-x), is equal to (2^N - x). So in this case
  776. // of 64x64 bit multiplication, the following holds:
  777. //
  778. // (-x) * (-y) =
  779. // (2^64 - x) * (2^64 - y) =
  780. // 2^128 - (2^64)*x - (2^64)*y + (x*y)
  781. //
  782. // The lower 64-bits of the 128-bit product is determined solely by the
  783. // (x*y) term. For a 128-bit result, the 2^128 term is irrelevant. And if
  784. // either the x and/or the y operand is negative, then either y and/or x
  785. // must be subtracted from the upper 64 bits of the 128-bit product.
  786. //
  787. // Arguments:
  788. //
  789. // Multiplicand (a0) - Supplies the multiplicand value.
  790. //
  791. // Multiplier (a1) - Supplies the multiplier value.
  792. //
  793. // ProductLower (a2) - Supplies a pointer to an unsigned quadword variable
  794. // that receives the lower 64-bits of the product.
  795. //
  796. // ProductLower (a3) - Supplies a pointer to a signed quadword variable
  797. // that receives the upper 64-bits of the product.
  798. //
  799. // Return Value:
  800. //
  801. // None.
  802. //
  803. //--
  804. LEAF_ENTRY(Rtlp128BitSignedMultiply)
  805. mulq a0, a1, t0 // get lower 64 bits of product
  806. stq t0, 0(a2) // store lower half of 128-bit product
  807. umulh a0, a1, t1 // get upper 64 bits of product
  808. subq t1, a0, t2 // subtract first operand from product
  809. cmovge a1, t1, t2 // if second operand is negative
  810. subq t2, a1, t3 // subtract second operand from product
  811. cmovge a0, t2, t3 // if first operand is negative
  812. stq t3, 0(a3) // store upper half of 128-bit product
  813. ret zero, (ra) // return
  814. .end Rtlp128BitSignedMultiply
  815. SBTTL("128-bit Unsigned Integer Multiplication")
  816. //++
  817. //
  818. // VOID
  819. // Rtlp128BitUnsignedMultiply (
  820. // IN ULONGLONG Multiplicand,
  821. // IN ULONGLONG Multiplier,
  822. // IN OUT PULONGLONG ProductLower,
  823. // IN OUT PULONGLONG ProductUpper
  824. // )
  825. //
  826. // Routine Description:
  827. //
  828. // This function multiplies an unsigned quadword (or large integer) by an
  829. // unsigned quadword (or large integer) and returns the full 128-bit unsigned
  830. // product indirectly through pointers to two unsigned quadwords.
  831. //
  832. // Arguments:
  833. //
  834. // Multiplicand (a0) - Supplies the multiplicand value.
  835. //
  836. // Multiplier (a1) - Supplies the multiplier value.
  837. //
  838. // ProductLower (a2) - Supplies a pointer to an unsigned quadword variable
  839. // that receives the lower 64-bits of the product.
  840. //
  841. // ProductLower (a3) - Supplies a pointer to an unsigned quadword variable
  842. // that receives the upper 64-bits of the product.
  843. //
  844. // Return Value:
  845. //
  846. // None.
  847. //
  848. //--
  849. LEAF_ENTRY(Rtlp128BitUnsignedMultiply)
  850. mulq a0, a1, t0 // get lower 64 bits of product
  851. stq t0, 0(a2) // store lower half of 128-bit product
  852. umulh a0, a1, t1 // get upper 64 bits of product
  853. stq t1, 0(a3) // store upper half of 128-bit product
  854. ret zero, (ra) // return
  855. .end Rtlp128BitUnsignedMultiply