Annotation of OpenXM_contrib/pari/src/kernel/ix86/l0asm.c, Revision 1.1.1.1
1.1 maekawa 1: /***********************************************************************/
2: /** **/
3: /** Low level arithmetic for PARI **/
4: /** written by Bruno Haible 14.11.1992 **/
5: /** macroified 21.1.1998 **/
6: /** **/
7: /***********************************************************************/
8: /* $Id: l0asm.c,v 1.1.1.1 1999/09/16 13:47:45 karim Exp $
9:
10: /* processor: Intel ix86 in native mode
11: * assembler syntax: GNU or SUN, moves go from left to right
12: * compiler: GNU gcc or SUN cc
13: * parameter passing convention: on the stack 4(%esp),8(%esp),...
14: * registers: %eax,%edx,%ecx may be modified,
15: * everything else must be saved and restored
16: * result: passed in %eax
17: * word length: 32 bits
18: */
19:
20: /* If the C compiler is GNU C, better stuff is contained in asmix86inline.h,
21: but we compile and link this file nevertheless because it defines the
22: global variable `hiremainder'. */
23:
24: /* This should ideally be determined at configure time. */
25: #if defined(__EMX__) || defined(__DJGCC__) || defined(__GO32__) || (defined(linux) && !defined(__ELF__)) || defined(__386BSD__) || defined(__NetBSD__) || (defined(__FreeBSD__) && !defined(__ELF__)) || defined(NeXT) || defined(__CYGWIN32__) || defined(__MINGW32__)
26: # define ASM_UNDERSCORE
27: #endif
28:
29: #include "l0asm.h"
30:
31: #if defined(__EMX__) && defined(__NO_AOUT) /* No underscores, rest as is */
32: # undef C
33: # define C(entrypoint) /**/entrypoint
34: #endif
35:
36:
37: #undef ALIGN
38: #ifdef _MSC_VER
39: #define ALIGN
40: #else
41: #if defined(ASM_UNDERSCORE) && !(defined(__CYGWIN32__) || defined(__MINGW32__))
42: /* BSD syntax assembler */
43: #define ALIGN .align 3
44: #else
45: /* ELF syntax assembler */
46: #define ALIGN .align 8
47: #endif
48: #endif
49:
50: GLOBL(C(addll))
51: GLOBL(C(subll))
52: GLOBL(C(addllx))
53: GLOBL(C(subllx))
54: GLOBL(C(shiftl))
55: GLOBL(C(shiftlr))
56: GLOBL(C(bfffo))
57: GLOBL(C(mulll))
58: GLOBL(C(addmul))
59: GLOBL(C(divll))
60: GLOBL(C(overflow))
61: GLOBL(C(hiremainder))
62:
63: #ifdef _MSC_VER
64: unsigned long overflow;
65: unsigned long hiremainder;
66: #else
67: #ifdef BSD_SYNTAX
68: # if defined(__EMX__) && defined(__NO_AOUT) /* Otherwise IBM linker will
69: ignore this module */
70: .data
71: .align 2
72: C(overflow):
73: .long 0
74: C(hiremainder):
75: .long 0
76: .text
77: # else
78: .comm C(overflow),4
79: .comm C(hiremainder),4
80: # endif
81: #endif
82: #ifdef ELF_SYNTAX
83: .comm C(overflow),4,4
84: .comm C(hiremainder),4,4
85: #endif
86: #endif
87:
88: TEXT()
89:
90: ALIGN
91: FUNBEGIN(addll)
92: INSN2(xor,l ,R(edx),R(edx)) /* clear %edx */
93: INSN2(mov,l ,X4 MEM_DISP(esp,4),R(eax)) /* get x */
94: INSN2(add,l ,X4 MEM_DISP(esp,8),R(eax)) /* add y */
95: INSN2(adc,l ,R(edx),R(edx)) /* %edx := carry */
96: INSN2(mov,l ,R(edx),C(overflow)) /* set overflow */
97: ret /* return %eax */
98: FUNEND()
99:
100: ALIGN
101: FUNBEGIN(addllx)
102: INSN2(xor,l ,R(edx),R(edx)) /* clear %edx */
103: INSN2(xor,l ,R(eax),R(eax)) /* clear %eax */
104: INSN2(sub,l ,C(overflow),R(eax)) /* set carry */
105: INSN2(mov,l ,X4 MEM_DISP(esp,4),R(eax)) /* get x */
106: INSN2(adc,l ,X4 MEM_DISP(esp,8),R(eax)) /* add y and carry */
107: INSN2(adc,l ,R(edx),R(edx)) /* %edx := carry */
108: INSN2(mov,l ,R(edx),C(overflow)) /* set overflow */
109: ret /* return %eax */
110: FUNEND()
111:
112: ALIGN
113: FUNBEGIN(subll)
114: INSN2(xor,l ,R(edx),R(edx)) /* clear %edx */
115: INSN2(mov,l ,X4 MEM_DISP(esp,4),R(eax)) /* get x */
116: INSN2(sub,l ,X4 MEM_DISP(esp,8),R(eax)) /* subtract y */
117: INSN2(adc,l ,R(edx),R(edx)) /* %edx := carry */
118: INSN2(mov,l ,R(edx),C(overflow)) /* set overflow */
119: ret /* return %eax */
120: FUNEND()
121:
122: ALIGN
123: FUNBEGIN(subllx)
124: INSN2(xor,l ,R(edx),R(edx)) /* clear %edx */
125: INSN2(xor,l ,R(eax),R(eax)) /* clear %eax */
126: INSN2(sub,l ,C(overflow),R(eax)) /* set carry */
127: INSN2(mov,l ,X4 MEM_DISP(esp,4),R(eax)) /* get x */
128: INSN2(sbb,l ,X4 MEM_DISP(esp,8),R(eax)) /* subtract y and carry */
129: INSN2(adc,l ,R(edx),R(edx)) /* %edx := carry */
130: INSN2(mov,l ,R(edx),C(overflow)) /* set overflow */
131: ret /* return %eax */
132: FUNEND()
133:
134: ALIGN
135: FUNBEGIN(shiftl)
136: INSN2(mov,l ,X4 MEM_DISP(esp,4),R(eax)) /* get x */
137: INSN2(mov,b ,X1 MEM_DISP(esp,8),R(cl)) /* get shift count i */
138: INSN2(xor,l ,R(edx),R(edx)) /* clear %edx */
139: INSN2SHCL(shld,l,R(eax),R(edx)) /* shift %edx left by i bits,
140: feeding in %eax from the right */
141: INSN2(shl,l ,R(cl),R(eax)) /* shift %eax left by i bits */
142: INSN2(mov,l ,R(edx),C(hiremainder)) /* set hiremainder */
143: ret /* return %eax */
144: FUNEND()
145:
146: ALIGN
147: FUNBEGIN(shiftlr)
148: INSN2(mov,l ,X4 MEM_DISP(esp,4),R(eax)) /* get x */
149: INSN2(mov,b ,X1 MEM_DISP(esp,8),R(cl)) /* get shift count i */
150: INSN2(xor,l ,R(edx),R(edx)) /* clear %edx */
151: INSN2SHCL(shrd,l,R(eax),R(edx)) /* shift %edx right by i bits,
152: feeding in %eax from the left */
153: INSN2(shr,l ,R(cl),R(eax)) /* shift %eax right by i bits */
154: INSN2(mov,l ,R(edx),C(hiremainder)) /* set hiremainder */
155: ret /* return %eax */
156: FUNEND()
157:
158: ALIGN
159: FUNBEGIN(bfffo)
160: INSN2(mov,l ,X4 MEM_DISP(esp,4),R(eax)) /* get x */
161: INSN2(bsr,l ,R(eax),R(edx)) /* %edx := number of leading bit */
162: INSN2(mov,l ,NUM(31),R(eax))
163: INSN2(sub,l ,R(edx),R(eax)) /* result is 31 - %edx */
164: ret /* return %eax */
165: FUNEND()
166:
167: ALIGN
168: FUNBEGIN(mulll)
169: INSN2(mov,l ,X4 MEM_DISP(esp,4),R(eax)) /* get x */
170: INSN1(mul,l ,X4 MEM_DISP(esp,8)) /* %edx|%eax := x * y */
171: INSN2(mov,l ,R(edx),C(hiremainder)) /* store high word */
172: ret /* return low word %eax */
173: FUNEND()
174:
175: ALIGN
176: FUNBEGIN(addmul)
177: INSN2(xor,l ,R(ecx),R(ecx)) /* clear %ecx */
178: INSN2(mov,l ,X4 MEM_DISP(esp,4),R(eax)) /* get x */
179: INSN1(mul,l ,X4 MEM_DISP(esp,8)) /* %edx|%eax := x * y */
180: INSN2(add,l ,C(hiremainder),R(eax)) /* add 0|hiremainder */
181: INSN2(adc,l ,R(ecx),R(edx))
182: INSN2(mov,l ,R(edx),C(hiremainder)) /* store high word */
183: ret /* return low word %eax */
184: FUNEND()
185:
186: ALIGN
187: FUNBEGIN(divll)
188: INSN2(mov,l ,X4 MEM_DISP(esp,4),R(eax)) /* get low word x */
189: INSN2(mov,l ,C(hiremainder),R(edx)) /* get high word */
190: INSN1(div,l ,X4 MEM_DISP(esp,8)) /* divide %edx|%eax by y */
191: INSN2(mov,l ,R(edx), C(hiremainder)) /* store remainder */
192: ret /* return quotient %eax */
193: FUNEND()
194:
195: ALIGN
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>