Annotation of OpenXM_contrib/pari/src/kernel/ix86/l0asm.txt, Revision 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>