Annotation of OpenXM_contrib/pari/src/kernel/ix86/l0asm.txt, Revision 1.1.1.1
1.1 maekawa 1: // Assembly language support for i386 CPU.
2: // Bruno Haible 21.6.1997
3:
4: // An assembly language file for the i386/i486/i586/i686 CPUs:
5: // On Unix, it is preprocessed and then assembled. NB: This file requires
6: // an ANSI C or C++ preprocessor which understands C++ comments.
7: // On Windows, with MSVC, it is preprocessed and then compiled with
8: // optimization. (The MSVC development environment does not have a separate
9: // assembler, we must use the C compiler's inline asm extension. Compiling
10: // without optimization pushes the registers %ebx,%esi,%edi onto the stack
11: // at function entry and pops them at function exit, which is not what we
12: // want because it affects the %esp offsets of the function arguments.)
13:
14: // The assembly language file should
15: // 1. include a configuration file which defines ASM_UNDERSCORE if appropriate.
16: // #ifndef _MSC_VER
17: // #include "config.h"
18: // #endif
19: // 2. include this file.
20: // #include "level0asm.h"
21: // 3. define all assembly language code.
22:
23: // The three different assembler syntaxes for this CPU are a MAJOR annoyance.
24: // In order not to have to maintain several copies of the assembly language
25: // code, we use lots of macros which expand into the correct syntax.
26: // These macros are:
27: // C(name)
28: // This expands to the name of the C variable or function `name'.
29: // On Unix BSD systems, this prepends an underscore.
30: // L(label)
31: // This expands to the name of a local label, having the name `label'.
32: // On Unix ELF systems, where there is no underscore, names beginning
33: // with an alphabetic character are automatically exported, so this
34: // prepends a dot. Note that when defining a label, the `:' must
35: // be inside the parentheses, not outside, because otherwise some
36: // ANSI C preprocessor inserts a space between the label and the `:',
37: // and some assemblers don't like this.
38: // R(reg)
39: // This expands to a reference to register `reg'. On Unix, this
40: // prepends a % charater.
41: // NUM(value)
42: // This expands to an immediate value. On Unix, this prepends a $
43: // character.
44: // ADDR(variable)
45: // This expands to an immediate value, the address of some variable
46: // or function. On Unix, this prepends a $ character. With MSVC,
47: // this prepends the keyword "OFFSET".
48: // About operand sizes: On Unix, a suffix to the instruction specifies the
49: // size of the operands (for example "movb", "movw", "movl"). With
50: // MSVC, there is no such suffix. Instead, the assembler infers the
51: // operand size from the names of the registers ("al" vs. "ax" vs.
52: // "eax"). This works well in most cases, but in instructions like
53: // "mul [esi]" the assembler guesses the operand size: "byte" by
54: // default. So it is better to explicitly specify the operand size
55: // of memory operands (prefix X1, X2, X4, X8).
56: // (Side note about Unix assemblers: Some Unix assemblers allow you
57: // to write "testb %eax,%eax" but silently treat this as
58: // "testb %al,%al".)
59: // X1
60: // This prefixes a memory reference of 1 byte.
61: // X2
62: // This prefixes a memory reference of 2 bytes.
63: // X4
64: // This prefixes a memory reference of 4 bytes.
65: // X8
66: // This prefixes a memory reference of 8 bytes.
67: // MEM(base)
68: // This expands to a memory reference at address `base'.
69: // MEM_DISP(base,displacement)
70: // This expands to a memory reference at address `base+displacement'.
71: // MEM_INDEX(base,index)
72: // This expands to a memory reference at address `base+index'.
73: // MEM_SHINDEX(base,index,size)
74: // This expands to a memory reference at address
75: // `base+index*size', where `size' is 1, 2, 4, or 8.
76: // MEM_DISP_SHINDEX0(displacement,index,size)
77: // This expands to a memory reference at address
78: // `displacement+index*size', where `size' is 1, 2, 4, or 8.
79: // MEM_DISP_SHINDEX(base,displacement,index,size)
80: // This expands to a memory reference at address
81: // `base+displacement+index*size', where `size' is 1, 2, 4, or 8.
82: // INDIR(value)
83: // This expands to an implicit indirection. On Unix, this prepends
84: // a * character.
85: // INSN1(mnemonic,size_suffix,dst)
86: // This expands to an instruction with one operand.
87: // INSN2(mnemonic,size_suffix,src,dst)
88: // This expands to an instruction with two operands. In our notation,
89: // `src' comes first and `dst' second, but they are reversed when
90: // expanding to Intel syntax.
91: // INSN2MOVX(mnemonic,size_suffix,src,dst)
92: // This expands to an instruction with two operands, of type
93: // movsbl/movzbl, which in some syntaxes requires a second suffix.
94: // INSN2SHCL(mnemonic,size_suffix,src,dst)
95: // This expands to an instruction with two operands, of type
96: // shrd/shld, which in some syntaxes requires an additional operand
97: // %cl.
98: // REP, REPZ
99: // This expands to a prefix for string instructions.
100: // _
101: // For instructions which don't have a size suffix, like jump
102: // instructions. Expands to nothing. Needed for MSVC, which has
103: // problems with empty macro arguments.
104: // TEXT()
105: // Switch to the code section.
106: // ALIGN(log)
107: // Align to 2^log bytes.
108: // GLOBL(name)
109: // Declare `name' to be a global symbol.
110: // FUNBEGIN(name)
111: // Start the assembly language code for the C function `name'.
112: // FUNEND()
113: // End the assembly language code for a function.
114:
115: // Define the C(name) and L(label) macros.
116: #ifdef _MSC_VER
117: # define C(entrypoint) entrypoint
118: # define L(label) L##label
119: #else
120: # ifdef ASM_UNDERSCORE
121: # if defined(__STDC__) || defined(__cplusplus)
122: # define C(entrypoint) _##entrypoint
123: # define L(label) L##label
124: # else
125: # define C(entrypoint) _/**/entrypoint
126: # define L(label) L/**/label
127: # endif
128: # else
129: # define C(entrypoint) entrypoint
130: # if defined(__STDC__) || defined(__cplusplus)
131: # define L(label) .L##label
132: # else
133: # define L(label) .L/**/label
134: # endif
135: # endif
136: #endif
137:
138: // Define one of these.
139: // BSD_SYNTAX for GNU assembler version 2.
140: // ELF_SYNTAX for SVR4 and Solaris assemblers.
141: // INTEL_SYNTAX for MS assembler.
142: #ifdef _MSC_VER
143: # define INTEL_SYNTAX
144: #else
145: // On Unix, it happens that the ELF systems (ASM_UNDERSCORE not defined) use
146: // the ELF syntax, while the BSD systems (ASM_UNDERSCORE defined) use the
147: // BSD syntax. Neat to know, this saves us from enumerating all the systems.
148: # ifdef ASM_UNDERSCORE
149: # define BSD_SYNTAX
150: # else
151: # define ELF_SYNTAX
152: # endif
153: #endif
154:
155: #if defined (BSD_SYNTAX) || defined (ELF_SYNTAX)
156: # define R(r) %r
157: # define NUM(n) $##n
158: # define ADDR(a) $##a
159: # define X1
160: # define X2
161: # define X4
162: # define X8
163: # define MEM(base)(R(base))
164: # define MEM_DISP(base,displacement)displacement(R(base))
165: # define MEM_INDEX(base,index)(R(base),R(index))
166: # define MEM_SHINDEX(base,index,size)(R(base),R(index),size)
167: # define MEM_DISP_SHINDEX0(displacement,index,size)displacement(,R(index),size)
168: # define MEM_DISP_SHINDEX(base,displacement,index,size)displacement(R(base),R(index),size)
169: # define INDIR(value)*value
170: # define INSNCONC(mnemonic,size_suffix)mnemonic##size_suffix
171: # define INSN1(mnemonic,size_suffix,dst)INSNCONC(mnemonic,size_suffix) dst
172: # define INSN2(mnemonic,size_suffix,src,dst)INSNCONC(mnemonic,size_suffix) src,dst
173: # define INSN2MOVX(mnemonic,size_suffix,src,dst)INSNCONC(INSNCONC(mnemonic,size_suffix),l) src,dst
174: # if defined(BSD_SYNTAX) || defined(COHERENT)
175: # define INSN2SHCL(mnemonic,size_suffix,src,dst)INSNCONC(mnemonic,size_suffix) R(cl),src,dst
176: # define REPZ repe ;
177: # else
178: # define INSN2SHCL(mnemonic,size_suffix,src,dst)INSNCONC(mnemonic,size_suffix) src,dst
179: # define REPZ repz ;
180: # endif
181: # define REP rep ;
182: # if defined(BSD_SYNTAX) && !(defined(__CYGWIN32__) || defined(__MINGW32__))
183: # define ALIGN(log) .align log,0x90
184: # endif
185: # if defined(ELF_SYNTAX) || defined(__CYGWIN32__) || defined(__MINGW32__)
186: # define ALIGN(log) .align 1<<(log)
187: # endif
188: #endif
189: #ifdef INTEL_SYNTAX
190: # define R(r) r
191: # define NUM(n) n
192: # define ADDR(a) OFFSET a
193: # define X1 BYTE PTR
194: # define X2 WORD PTR
195: # define X4 DWORD PTR
196: # define X8 QWORD PTR
197: # define MEM(base) [base]
198: # define MEM_DISP(base,displacement) [base+(displacement)]
199: # define MEM_INDEX(base,index) [base+index]
200: # define MEM_SHINDEX(base,index,size) [base+index*size]
201: # define MEM_DISP_SHINDEX0(displacement,index,size) [(displacement)+index*size]
202: # define MEM_DISP_SHINDEX(base,displacement,index,size) [base+(displacement)+index*size]
203: # define INDIR(value)value
204: # define INSNCONC(mnemonic,suffix)mnemonic##suffix
205: # define INSN1(mnemonic,size_suffix,dst)mnemonic dst
206: # define INSN2(mnemonic,size_suffix,src,dst)mnemonic dst,src
207: # define INSN2MOVX(mnemonic,size_suffix,src,dst)INSNCONC(mnemonic,x) dst,src
208: # define INSN2SHCL(mnemonic,size_suffix,src,dst)mnemonic dst,src,R(cl)
209: # define REPZ repz
210: # define REP rep
211: # define movsl movs R(eax)
212: # define stosl stos R(eax)
213: # define scasl scas R(eax)
214: # define cmpsl cmpsd
215: # ifdef _MSC_VER
216: // No pseudo-ops available in MS inline assembler.
217: # define ALIGN(log)
218: # else
219: # define ALIGN(log) .align log
220: # endif
221: #endif
222:
223: #ifdef _MSC_VER
224: // No pseudo-ops available in MS inline assembler.
225: # define TEXT()
226: #else
227: # define TEXT() .text
228: #endif
229:
230: #ifdef _MSC_VER
231: # define GLOBL(name)
232: #else
233: # define GLOBL(name) .globl name
234: #endif
235:
236: // Define the FUNBEGIN(name) and FUNEND() macros.
237: #ifdef _MSC_VER
238: // The "naked" attribute avoids the compiler generated prologue and epilogue
239: // (which saves the registers %ebx,%esi,%edi if no optimization is enabled,
240: // and those registers among %ebx,%esi,%edi which occur in the asm code
241: // if optimization is enabled).
242: # define FUNBEGIN(name) __declspec(naked) void name () { __asm {
243: # define FUNEND() } }
244: #else
245: # define FUNBEGIN(name) C(name##:)
246: # define FUNEND()
247: #endif
248:
249: #define _
250:
251: // Here we go!
252:
253: TEXT()
254:
255: // Rules about registers:
256: // Registers %eax,%edx,%ecx may be freely used.
257: // Registers %ebx,%esi,%edi must be saved before being used.
258: // Don't fiddle with register %ebp - some platforms don't like this.
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>