imulvc.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. /* imulvc.c Copyright (C) 1993-2002 Codemist Ltd */
  2. /*
  3. * This code may be used and modified, and redistributed in binary
  4. * or source form, subject to the "CCL Public License", which should
  5. * accompany it. This license is a variant on the BSD license, and thus
  6. * permits use of code derived from this in either open and commercial
  7. * projects: but it does require that updates to this code be made
  8. * available back to the originators of the package.
  9. * Before merging other code in with this or linking this code
  10. * with other packages or libraries please check that the license terms
  11. * of the other material are compatible with those of this.
  12. */
  13. /* Signature: 77597f94 08-Apr-2002 */
  14. /*
  15. * This code implements Imultiply and Idivide in 80386 (and up) assembly
  16. * code. I use the __stdcall calling convention.
  17. */
  18. #include "machine.h"
  19. #include "tags.h"
  20. #include "externs.h"
  21. #include "cslerror.h"
  22. #include "sys.h"
  23. /*
  24. * Get rid of unwanted warnings about lack of return values...
  25. */
  26. #pragma warning (disable : 4035)
  27. unsigned32 __stdcall Imultiply(unsigned32 *rlow,
  28. unsigned32 a, unsigned32 b, unsigned32 c)
  29. {
  30. /*
  31. * uns64 r = (uns64)a*(uns64)b + (uns64)c;
  32. * *rlow = (unsigned32)(r & 0x7fffffff);
  33. * return (unsigned32)(r >> 31);
  34. */
  35. __asm
  36. {
  37. mov eax, b
  38. mul a
  39. mov ecx, rlow
  40. add eax, c
  41. adc edx, 0 ; carry into top half
  42. add eax, eax
  43. adc edx, edx
  44. shr eax, 1
  45. mov DWORD PTR [ecx], eax
  46. mov eax, edx
  47. }
  48. }
  49. unsigned32 __stdcall Idiv10_9(unsigned32 *qp, unsigned32 high31, unsigned32 low31)
  50. {
  51. /*
  52. * uns64 p = ((uns64)high31 << 31) | (uns64)low31;
  53. * *qp = (unsigned32)(p / (uns64)1000000000U);
  54. * return (unsigned32)(p % (uns64)1000000000U);
  55. */
  56. __asm {
  57. mov edx, high31
  58. mov eax, low31
  59. shl eax, 1
  60. shr edx, 1
  61. rcr eax, 1 ; That glued together 31+31 bits
  62. mov ecx, 1000000000
  63. div ecx
  64. mov ecx, qp
  65. mov DWORD PTR [ecx], eax
  66. mov eax, edx
  67. }
  68. }
  69. unsigned32 __stdcall Idivide(unsigned32 *qp, unsigned32 a,
  70. unsigned32 b, unsigned32 c)
  71. {
  72. /*
  73. * uns64 p = ((uns64)a << 31) | (uns64)b;
  74. * *qp = (unsigned32)(p / (uns64)c);
  75. * return (unsigned32)(p % (uns64)c);
  76. */
  77. __asm {
  78. mov edx, a
  79. mov eax, b
  80. shl eax, 1
  81. shr edx, 1
  82. rcr eax, 1 ; That glued together 31+31 bits
  83. mov ecx, c
  84. div ecx
  85. mov ecx, qp
  86. mov DWORD PTR [ecx], eax
  87. mov eax, edx
  88. }
  89. }
  90. /* end of imulvc.c */