lbn80386.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. /*
  2. * Copyright (c) 1995 Colin Plumb. All rights reserved.
  3. * For licensing and other legal details, see the file legal.c.
  4. *
  5. * lbn80386.h - This file defines the interfaces to the 80386
  6. * assembly primitives. It is intended to be included in "lbn.h"
  7. * via the "#include BNINCLUDE" mechanism.
  8. */
  9. #define BN_LITTLE_ENDIAN 1
  10. typedef unsigned long bnword32;
  11. #define BNWORD32 bnword32
  12. /* MS-DOS needs the calling convention described to it. */
  13. #ifndef MSDOS
  14. #ifdef __MSDOS
  15. #define MSDOS 1
  16. #endif
  17. #endif
  18. #ifndef MSDOS
  19. #ifdef __MSDOS__
  20. #define MSDOS 1
  21. #endif
  22. #endif
  23. /* By MS-DOS, we mean 16-bit brain-dead MS-DOS. Not 32-bit good things. */
  24. #ifdef __GO32
  25. #undef MSDOS
  26. #endif
  27. #ifdef __GO32__
  28. #undef MSDOS
  29. #endif
  30. #ifdef MSDOS
  31. #define CDECL __cdecl
  32. #else
  33. #define CDECL /*nothing*/
  34. #endif
  35. #ifdef __cplusplus
  36. /* These assembly-language primitives use C names */
  37. extern "C" {
  38. #endif
  39. /* Function prototypes for the asm routines */
  40. void CDECL
  41. lbnMulN1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k);
  42. #define lbnMulN1_32 lbnMulN1_32
  43. bnword32 CDECL
  44. lbnMulAdd1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k);
  45. #define lbnMulAdd1_32 lbnMulAdd1_32
  46. bnword32 CDECL
  47. lbnMulSub1_32(bnword32 *out, bnword32 const *in, unsigned len, bnword32 k);
  48. #define lbnMulSub1_32 lbnMulSub1_32
  49. bnword32 CDECL
  50. lbnDiv21_32(bnword32 *q, bnword32 nh, bnword32 nl, bnword32 d);
  51. #define lbnDiv21_32 lbnDiv21_32
  52. unsigned CDECL
  53. lbnModQ_32(bnword32 const *n, unsigned len, bnword32 d);
  54. #define lbnModQ_32 lbnModQ_32
  55. #ifdef __cplusplus
  56. }
  57. #endif
  58. #if __GNUC__
  59. /*
  60. * Use the (massively cool) GNU inline-assembler extension to define
  61. * inline expansions for various operations.
  62. *
  63. * The massively cool part is that the assembler can have inputs
  64. * and outputs, and you specify the operands and which effective
  65. * addresses are legal and they get substituted into the code.
  66. * (For example, some of the code requires a zero. Rather than
  67. * specify an immediate constant, the expansion specifies an operand
  68. * of zero which can be in various places. This lets GCC use an
  69. * immediate zero, or a register which contains zero if it's available.)
  70. *
  71. * The syntax is asm("asm_code" : outputs : inputs : trashed)
  72. * %0, %1 and so on in the asm code are substituted by the operands
  73. * in left-to-right order (outputs, then inputs).
  74. * The operands contain constraint strings and values to use.
  75. * Outputs must be lvalues, inputs may be rvalues. In the constraints:
  76. * "a" means that the operand must be in eax.
  77. * "d" means that the operand must be in edx.
  78. * "g" means that the operand may be any effective address.
  79. * "=" means that the operand is assigned to.
  80. * "%" means that this operand and the following one may be
  81. * interchanged if desirable.
  82. * "bcDSmn" means that the operand must be in ebx, ecx, esi, edi, memory,
  83. * or an immediate constant. (This is almost the same as "g"
  84. * but allowing it in eax wouldn't help because x is already
  85. * assigned there, and it must not be in edx, since edx is
  86. * overwritten by the multiply before a and b are read.)
  87. *
  88. * Note that GCC uses AT&T assembler syntax, which is rather
  89. * different from Intel syntax. The length (b, w or l) of the
  90. * operation is appended to the opcode, and the *second* operand
  91. * is the destination, not the first. Finally, the register names
  92. * are all preceded with "%". (Doubled here because % is a
  93. * magic character.)
  94. */
  95. /* (ph<<32) + pl = x*y */
  96. #define mul32_ppmm(ph,pl,x,y) \
  97. __asm__("mull %3" : "=d"(ph), "=a"(pl) : "%a"(x), "g"(y))
  98. /* (ph<<32) + pl = x*y + a */
  99. #define mul32_ppmma(ph,pl,x,y,a) \
  100. __asm__("mull %3\n\t" \
  101. "addl %4,%%eax\n\t" \
  102. "adcl %5,%%edx" \
  103. : "=&d"(ph), "=a"(pl) \
  104. : "%a"(x), "g"(y), "bcDSmn"(a), "bcDSmn"(0))
  105. /* (ph<<32) + pl = x*y + a + b */
  106. #define mul32_ppmmaa(ph,pl,x,y,a,b) \
  107. __asm__("mull %3\n\t" \
  108. "addl %4,%%eax\n\t" \
  109. "adcl %6,%%edx\n\t" \
  110. "addl %5,%%eax\n\t" \
  111. "adcl %6,%%edx" \
  112. : "=&d"(ph), "=a"(pl) \
  113. : "%a"(x), "g"(y), "%bcDSmn"(a), "bcDSmn"(b), "bcDSmn"(0))
  114. /* q = ((nh<<32) + nl) / d, return remainder. nh guaranteed < d. */
  115. #undef lbnDiv21_32
  116. #define lbnDiv21_32(q,nh,nl,d) \
  117. ({unsigned _; \
  118. __asm__("divl %4" : "=d"(_), "=a"(*q) : "d"(nh), "a"(nl), "g"(d)); \
  119. _;})
  120. /* No quotient, just return remainder ((nh<<32) + nl) % d */
  121. #define lbnMod21_32(nh,nl,d) \
  122. ({unsigned _; \
  123. __asm__("divl %3" : "=d"(_) : "d"(nh), "a"(nl), "g"(d) : "ax"); \
  124. _;})
  125. #endif /* __GNUC__ */