[BACK]Return to x86-defs.m4 CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gmp / mpn / x86

Annotation of OpenXM_contrib/gmp/mpn/x86/x86-defs.m4, Revision 1.1.1.1

1.1       maekawa     1: divert(-1)
                      2:
                      3: dnl  m4 macros for x86 assembler.
                      4:
                      5:
                      6: dnl  Copyright (C) 1999, 2000 Free Software Foundation, Inc.
                      7: dnl
                      8: dnl  This file is part of the GNU MP Library.
                      9: dnl
                     10: dnl  The GNU MP Library is free software; you can redistribute it and/or
                     11: dnl  modify it under the terms of the GNU Lesser General Public License as
                     12: dnl  published by the Free Software Foundation; either version 2.1 of the
                     13: dnl  License, or (at your option) any later version.
                     14: dnl
                     15: dnl  The GNU MP Library is distributed in the hope that it will be useful,
                     16: dnl  but WITHOUT ANY WARRANTY; without even the implied warranty of
                     17: dnl  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     18: dnl  Lesser General Public License for more details.
                     19: dnl
                     20: dnl  You should have received a copy of the GNU Lesser General Public
                     21: dnl  License along with the GNU MP Library; see the file COPYING.LIB.  If
                     22: dnl  not, write to the Free Software Foundation, Inc., 59 Temple Place -
                     23: dnl  Suite 330, Boston, MA 02111-1307, USA.
                     24:
                     25:
                     26: dnl  Notes:
                     27: dnl
                     28: dnl  m4 isn't perfect for processing BSD style x86 assembler code, the main
                     29: dnl  problems are,
                     30: dnl
                     31: dnl  1. Doing define(foo,123) and then using foo in an addressing mode like
                     32: dnl     foo(%ebx) expands as a macro rather than a constant.  This is worked
                     33: dnl     around by using deflit() from asm-defs.m4, instead of define().
                     34: dnl
                     35: dnl  2. Immediates in macro definitions need a space or `' to stop the $
                     36: dnl     looking like a macro parameter.  For example,
                     37: dnl
                     38: dnl            define(foo, `mov $ 123, %eax')
                     39: dnl
                     40: dnl     This is only a problem in macro definitions, not in ordinary text,
                     41: dnl     nor in macro parameters like text passed to forloop() or ifdef().
                     42:
                     43:
                     44: deflit(BYTES_PER_MP_LIMB, 4)
                     45:
                     46:
                     47: dnl  --------------------------------------------------------------------------
                     48: dnl  Replacement PROLOGUE/EPILOGUE with more sophisticated error checking.
                     49: dnl  Nesting and overlapping not allowed.
                     50: dnl
                     51:
                     52:
                     53: dnl  Usage: PROLOGUE(functionname)
                     54: dnl
                     55: dnl  Generate a function prologue.  functionname gets GSYM_PREFIX added.
                     56: dnl  Examples,
                     57: dnl
                     58: dnl         PROLOGUE(mpn_add_n)
                     59: dnl         PROLOGUE(somefun)
                     60:
                     61: define(`PROLOGUE',
                     62: m4_assert_numargs(1)
                     63: m4_assert_defined(`PROLOGUE_cpu')
                     64: `ifdef(`PROLOGUE_current_function',
                     65: `m4_error(`PROLOGUE'(`PROLOGUE_current_function') needs an `EPILOGUE'() before `PROLOGUE'($1)
                     66: )')dnl
                     67: m4_file_seen()dnl
                     68: define(`PROLOGUE_current_function',`$1')dnl
                     69: PROLOGUE_cpu(GSYM_PREFIX`'$1)')
                     70:
                     71:
                     72: dnl  Usage: EPILOGUE()
                     73: dnl
                     74: dnl  Notice the function name is passed to EPILOGUE_cpu(), letting it use $1
                     75: dnl  instead of the long PROLOGUE_current_function symbol.
                     76:
                     77: define(`EPILOGUE',
                     78: m4_assert_numargs(0)
                     79: m4_assert_defined(`EPILOGUE_cpu')
                     80: `ifdef(`PROLOGUE_current_function',,
                     81: `m4_error(`EPILOGUE'() with no `PROLOGUE'()
                     82: )')dnl
                     83: EPILOGUE_cpu(GSYM_PREFIX`'PROLOGUE_current_function)`'dnl
                     84: undefine(`PROLOGUE_current_function')')
                     85:
                     86: m4wrap_prepend(
                     87: `ifdef(`PROLOGUE_current_function',
                     88: `m4_error(`EPILOGUE() for PROLOGUE('PROLOGUE_current_function`) never seen
                     89: ')')')
                     90:
                     91:
                     92: dnl  Usage: PROLOGUE_assert_inside()
                     93: dnl
                     94: dnl  Use this unquoted on a line on its own at the start of a macro
                     95: dnl  definition to add some code to check the macro is only used inside a
                     96: dnl  PROLOGUE/EPILOGUE pair, and that hence PROLOGUE_current_function is
                     97: dnl  defined.
                     98:
                     99: define(PROLOGUE_assert_inside,
                    100: m4_assert_numargs(0)
                    101: ``PROLOGUE_assert_inside_internal'(m4_doublequote($`'0))`dnl '')
                    102:
                    103: define(PROLOGUE_assert_inside_internal,
                    104: m4_assert_numargs(1)
                    105: `ifdef(`PROLOGUE_current_function',,
                    106: `m4_error(`$1 used outside a PROLOGUE / EPILOGUE pair
                    107: ')')')
                    108:
                    109:
                    110: dnl  Usage: L(labelname)
                    111: dnl         LF(functionname,labelname)
                    112: dnl
                    113: dnl  Generate a local label in the current or given function.  For LF(),
                    114: dnl  functionname gets GSYM_PREFIX added, the same as with PROLOGUE().
                    115: dnl
                    116: dnl  For example, in a function mpn_add_n (and with MPN_PREFIX __gmpn),
                    117: dnl
                    118: dnl         L(bar)          => L__gmpn_add_n__bar
                    119: dnl         LF(somefun,bar) => Lsomefun__bar
                    120: dnl
                    121: dnl  The funtion name and label name get two underscores between them rather
                    122: dnl  than one to guard against clashing with a separate external symbol that
                    123: dnl  happened to be called functionname_labelname.  (Though this would only
                    124: dnl  happen if the local label prefix is is empty.)  Underscores are used so
                    125: dnl  the whole label will still be a valid C identifier and so can be easily
                    126: dnl  used in gdb.
                    127:
                    128: dnl  LSYM_PREFIX can be L$, so defn() is used to prevent L expanding as the
                    129: dnl  L macro and making an infinite recursion.
                    130: define(LF,
                    131: m4_assert_numargs(2)
                    132: m4_assert_defined(`LSYM_PREFIX')
                    133: `defn(`LSYM_PREFIX')GSYM_PREFIX`'$1`'__$2')
                    134:
                    135: define(`L',
                    136: m4_assert_numargs(1)
                    137: PROLOGUE_assert_inside()
                    138: `LF(PROLOGUE_current_function,`$1')')
                    139:
                    140:
                    141: dnl  Called: PROLOGUE_cpu(gsym)
                    142: dnl          EPILOGUE_cpu(gsym)
                    143:
                    144: define(PROLOGUE_cpu,
                    145: m4_assert_numargs(1)
                    146:        `GLOBL  $1
                    147:        TYPE($1,`function')
                    148: $1:')
                    149:
                    150: define(EPILOGUE_cpu,
                    151: m4_assert_numargs(1)
                    152: `      SIZE($1,.-$1)')
                    153:
                    154:
                    155:
                    156: dnl  --------------------------------------------------------------------------
                    157: dnl  Various x86 macros.
                    158: dnl
                    159:
                    160:
                    161: dnl  Usage: ALIGN_OFFSET(bytes,offset)
                    162: dnl
                    163: dnl  Align to `offset' away from a multiple of `bytes'.
                    164: dnl
                    165: dnl  This is useful for testing, for example align to something very strict
                    166: dnl  and see what effect offsets from it have, "ALIGN_OFFSET(256,32)".
                    167: dnl
                    168: dnl  Generally you wouldn't execute across the padding, but it's done with
                    169: dnl  nop's so it'll work.
                    170:
                    171: define(ALIGN_OFFSET,
                    172: m4_assert_numargs(2)
                    173: `ALIGN($1)
                    174: forloop(`i',1,$2,`     nop
                    175: ')')
                    176:
                    177:
                    178: dnl  Usage: defframe(name,offset)
                    179: dnl
                    180: dnl  Make a definition like the following with which to access a parameter
                    181: dnl  or variable on the stack.
                    182: dnl
                    183: dnl         define(name,`FRAME+offset(%esp)')
                    184: dnl
                    185: dnl  Actually m4_empty_if_zero(FRAME+offset) is used, which will save one
                    186: dnl  byte if FRAME+offset is zero, by putting (%esp) rather than 0(%esp).
                    187: dnl  Use define(`defframe_empty_if_zero_disabled',1) if for some reason the
                    188: dnl  zero offset is wanted.
                    189: dnl
                    190: dnl  The new macro also gets a check that when it's used FRAME is actually
                    191: dnl  defined, and that the final %esp offset isn't negative, which would
                    192: dnl  mean an attempt to access something below the current %esp.
                    193: dnl
                    194: dnl  deflit() is used rather than a plain define(), so the new macro won't
                    195: dnl  delete any following parenthesized expression.  name(%edi) will come
                    196: dnl  out say as 16(%esp)(%edi).  This isn't valid assembler and should
                    197: dnl  provoke an error, which is better than silently giving just 16(%esp).
                    198: dnl
                    199: dnl  See README.family for more on the suggested way to access the stack
                    200: dnl  frame.
                    201:
                    202: define(defframe,
                    203: m4_assert_numargs(2)
                    204: `deflit(`$1',
                    205: m4_assert_defined(`FRAME')
                    206: `defframe_check_notbelow(`$1',$2,FRAME)dnl
                    207: defframe_empty_if_zero(FRAME+($2))(%esp)')')
                    208:
                    209: dnl  Called: defframe_empty_if_zero(expression)
                    210: define(defframe_empty_if_zero,
                    211: `ifelse(defframe_empty_if_zero_disabled,1,
                    212: `eval($1)',
                    213: `m4_empty_if_zero($1)')')
                    214:
                    215: dnl  Called: defframe_check_notbelow(`name',offset,FRAME)
                    216: define(defframe_check_notbelow,
                    217: m4_assert_numargs(3)
                    218: `ifelse(eval(($3)+($2)<0),1,
                    219: `m4_error(`$1 at frame offset $2 used when FRAME is only $3 bytes
                    220: ')')')
                    221:
                    222:
                    223: dnl  Usage: FRAME_pushl()
                    224: dnl         FRAME_popl()
                    225: dnl         FRAME_addl_esp(n)
                    226: dnl         FRAME_subl_esp(n)
                    227: dnl
                    228: dnl  Adjust FRAME appropriately for a pushl or popl, or for an addl or subl
                    229: dnl  %esp of n bytes.
                    230: dnl
                    231: dnl  Using these macros is completely optional.  Sometimes it makes more
                    232: dnl  sense to put explicit deflit(`FRAME',N) forms, especially when there's
                    233: dnl  jumps and different sequences of FRAME values need to be used in
                    234: dnl  different places.
                    235:
                    236: define(FRAME_pushl,
                    237: m4_assert_numargs(0)
                    238: m4_assert_defined(`FRAME')
                    239: `deflit(`FRAME',eval(FRAME+4))')
                    240:
                    241: define(FRAME_popl,
                    242: m4_assert_numargs(0)
                    243: m4_assert_defined(`FRAME')
                    244: `deflit(`FRAME',eval(FRAME-4))')
                    245:
                    246: define(FRAME_addl_esp,
                    247: m4_assert_numargs(1)
                    248: m4_assert_defined(`FRAME')
                    249: `deflit(`FRAME',eval(FRAME-($1)))')
                    250:
                    251: define(FRAME_subl_esp,
                    252: m4_assert_numargs(1)
                    253: m4_assert_defined(`FRAME')
                    254: `deflit(`FRAME',eval(FRAME+($1)))')
                    255:
                    256:
                    257: dnl  Usage: defframe_pushl(name)
                    258: dnl
                    259: dnl  Do a combination of a FRAME_pushl() and a defframe() to name the stack
                    260: dnl  location just pushed.  This should come after a pushl instruction.
                    261: dnl  Putting it on the same line works and avoids lengthening the code.  For
                    262: dnl  example,
                    263: dnl
                    264: dnl         pushl   %eax     defframe_pushl(VAR_COUNTER)
                    265: dnl
                    266: dnl  Notice the defframe() is done with an unquoted -FRAME thus giving its
                    267: dnl  current value without tracking future changes.
                    268:
                    269: define(defframe_pushl,
                    270: `FRAME_pushl()defframe(`$1',-FRAME)')
                    271:
                    272:
                    273: dnl  --------------------------------------------------------------------------
                    274: dnl  Assembler instruction macros.
                    275: dnl
                    276:
                    277:
                    278: dnl  Usage: emms_or_femms
                    279: dnl         femms_available_p
                    280: dnl
                    281: dnl  femms_available_p expands to 1 or 0 according to whether the AMD 3DNow
                    282: dnl  femms instruction is available.  emms_or_femms expands to femms if
                    283: dnl  available, or emms if not.
                    284: dnl
                    285: dnl  emms_or_femms is meant for use in the K6 directory where plain K6
                    286: dnl  (without femms) and K6-2 and K6-3 (with a slightly faster femms) are
                    287: dnl  supported together.
                    288: dnl
                    289: dnl  On K7 femms is no longer faster and is just an alias for emms, so plain
                    290: dnl  emms may as well be used.
                    291:
                    292: define(femms_available_p,
                    293: m4_assert_numargs(-1)
                    294: `m4_ifdef_anyof_p(
                    295:        `HAVE_TARGET_CPU_k62',
                    296:        `HAVE_TARGET_CPU_k63',
                    297:        `HAVE_TARGET_CPU_athlon')')
                    298:
                    299: define(emms_or_femms,
                    300: m4_assert_numargs(-1)
                    301: `ifelse(femms_available_p,1,`femms',`emms')')
                    302:
                    303:
                    304: dnl  Usage: femms
                    305: dnl
                    306: dnl  The gas 2.9.1 that comes with FreeBSD 3.4 doesn't support femms, so the
                    307: dnl  following is a replacement using .byte.
                    308: dnl
                    309: dnl  If femms isn't available, an emms is generated instead, for convenience
                    310: dnl  when testing on a machine without femms.
                    311:
                    312: define(femms,
                    313: m4_assert_numargs(-1)
                    314: `ifelse(femms_available_p,1,
                    315: `.byte 15,14   C AMD 3DNow femms',
                    316: `emms`'dnl
                    317: m4_warning(`warning, using emms in place of femms, use for testing only
                    318: ')')')
                    319:
                    320:
                    321: dnl  Usage: jadcl0(op)
                    322: dnl
                    323: dnl  Issue a jnc/incl as a substitute for adcl $0,op.  This isn't an exact
                    324: dnl  replacement, since it doesn't set the flags like adcl does.
                    325: dnl
                    326: dnl  This finds a use in K6 mpn_addmul_1, mpn_submul_1, mpn_mul_basecase and
                    327: dnl  mpn_sqr_basecase because on K6 an adcl is slow, the branch
                    328: dnl  misprediction penalty is small, and the multiply algorithm used leads
                    329: dnl  to a carry bit on average only 1/4 of the time.
                    330: dnl
                    331: dnl  jadcl0_disabled can be set to 1 to instead issue an ordinary adcl for
                    332: dnl  comparison.  For example,
                    333: dnl
                    334: dnl            define(`jadcl0_disabled',1)
                    335: dnl
                    336: dnl  When using a register operand, eg. "jadcl0(%edx)", the jnc/incl code is
                    337: dnl  the same size as an adcl.  This makes it possible to use the exact same
                    338: dnl  computed jump code when testing the relative speed of jnc/incl and adcl
                    339: dnl  with jadcl0_disabled.
                    340:
                    341: define(jadcl0,
                    342: m4_assert_numargs(1)
                    343: `ifelse(jadcl0_disabled,1,
                    344:        `adcl   $`'0, $1',
                    345:        `jnc    1f
                    346:        incl    $1
                    347: 1:dnl')')
                    348:
                    349:
                    350: dnl  Usage: cmov_available_p
                    351: dnl
                    352: dnl  Expand to 1 if cmov is available, 0 if not.
                    353:
                    354: define(cmov_available_p,
                    355: `m4_ifdef_anyof_p(
                    356:        `HAVE_TARGET_CPU_pentiumpro',
                    357:        `HAVE_TARGET_CPU_pentium2',
                    358:        `HAVE_TARGET_CPU_pentium3',
                    359:        `HAVE_TARGET_CPU_athlon')')
                    360:
                    361:
                    362: dnl  Usage: x86_lookup(target, key,value, key,value, ...)
                    363: dnl         x86_lookup_p(target, key,value, key,value, ...)
                    364: dnl
                    365: dnl  Look for `target' among the `key' parameters.
                    366: dnl
                    367: dnl  x86_lookup expands to the corresponding `value', or generates an error
                    368: dnl  if `target' isn't found.
                    369: dnl
                    370: dnl  x86_lookup_p expands to 1 if `target' is found, or 0 if not.
                    371:
                    372: define(x86_lookup,
                    373: `ifelse(eval($#<3),1,
                    374: `m4_error(`unrecognised part of x86 instruction: $1
                    375: ')',
                    376: `ifelse(`$1',`$2', `$3',
                    377: `x86_lookup(`$1',shift(shift(shift($@))))')')')
                    378:
                    379: define(x86_lookup_p,
                    380: `ifelse(eval($#<3),1, `0',
                    381: `ifelse(`$1',`$2',    `1',
                    382: `x86_lookup_p(`$1',shift(shift(shift($@))))')')')
                    383:
                    384:
                    385: dnl  Usage: x86_opcode_reg32(reg)
                    386: dnl         x86_opcode_reg32_p(reg)
                    387: dnl
                    388: dnl  x86_opcode_reg32 expands to the standard 3 bit encoding for the given
                    389: dnl  32-bit register, eg. `%ebp' turns into 5.
                    390: dnl
                    391: dnl  x86_opcode_reg32_p expands to 1 if reg is a valid 32-bit register, or 0
                    392: dnl  if not.
                    393:
                    394: define(x86_opcode_reg32,
                    395: m4_assert_numargs(1)
                    396: `x86_lookup(`$1',x86_opcode_reg32_list)')
                    397:
                    398: define(x86_opcode_reg32_p,
                    399: m4_assert_onearg()
                    400: `x86_lookup_p(`$1',x86_opcode_reg32_list)')
                    401:
                    402: define(x86_opcode_reg32_list,
                    403: ``%eax',0,
                    404: `%ecx',1,
                    405: `%edx',2,
                    406: `%ebx',3,
                    407: `%esp',4,
                    408: `%ebp',5,
                    409: `%esi',6,
                    410: `%edi',7')
                    411:
                    412:
                    413: dnl  Usage: x86_opcode_tttn(cond)
                    414: dnl
                    415: dnl  Expand to the 4-bit "tttn" field value for the given x86 branch
                    416: dnl  condition (like `c', `ae', etc).
                    417:
                    418: define(x86_opcode_tttn,
                    419: m4_assert_numargs(1)
                    420: `x86_lookup(`$1',x86_opcode_ttn_list)')
                    421:
                    422: define(x86_opcode_tttn_list,
                    423: ``o',  0,
                    424: `no',  1,
                    425: `b',   2, `c',  2, `nae',2,
                    426: `nb',  3, `nc', 3, `ae', 3,
                    427: `e',   4, `z',  4,
                    428: `ne',  5, `nz', 5,
                    429: `be',  6, `na', 6,
                    430: `nbe', 7, `a',  7,
                    431: `s',   8,
                    432: `ns',  9,
                    433: `p',  10, `pe', 10, `npo',10,
                    434: `np', 11, `npe',11, `po', 11,
                    435: `l',  12, `nge',12,
                    436: `nl', 13, `ge', 13,
                    437: `le', 14, `ng', 14,
                    438: `nle',15, `g',  15')
                    439:
                    440:
                    441: dnl  Usage: cmovCC(srcreg,dstreg)
                    442: dnl
                    443: dnl  Generate a cmov instruction if the target supports cmov, or simulate it
                    444: dnl  with a conditional jump if not (the latter being meant only for
                    445: dnl  testing).  For example,
                    446: dnl
                    447: dnl         cmovz(  %eax, %ebx)
                    448: dnl
                    449: dnl  cmov instructions are generated using .byte sequences, since only
                    450: dnl  recent versions of gas know cmov.
                    451: dnl
                    452: dnl  The source operand can only be a plain register.  (m4 code implementing
                    453: dnl  full memory addressing modes exists, believe it or not, but isn't
                    454: dnl  currently needed and isn't included.)
                    455: dnl
                    456: dnl  All the standard conditions are defined.  Attempting to use one without
                    457: dnl  the macro parentheses, such as just "cmovbe %eax, %ebx", will provoke
                    458: dnl  an error.  This ensures the necessary .byte sequences aren't
                    459: dnl  accidentally missed.
                    460:
                    461: dnl  Called: define_cmov_many(cond,tttn,cond,tttn,...)
                    462: define(define_cmov_many,
                    463: `ifelse(m4_length(`$1'),0,,
                    464: `define_cmov(`$1',`$2')define_cmov_many(shift(shift($@)))')')
                    465:
                    466: dnl  Called: define_cmov(cond,tttn)
                    467: define(define_cmov,
                    468: m4_assert_numargs(2)
                    469: `define(`cmov$1',
                    470: m4_instruction_wrapper()
                    471: m4_assert_numargs(2)
                    472: `cmov_internal'(m4_doublequote($`'0),``$1',`$2'',dnl
                    473: m4_doublequote($`'1),m4_doublequote($`'2)))')
                    474:
                    475: define_cmov_many(x86_opcode_tttn_list)
                    476:
                    477:
                    478: dnl  Called: cmov_internal(name,cond,tttn,src,dst)
                    479: define(cmov_internal,
                    480: m4_assert_numargs(5)
                    481: `ifelse(cmov_available_p,1,
                    482: `cmov_bytes_tttn(`$1',`$3',`$4',`$5')',
                    483: `m4_warning(`warning, simulating cmov with jump, use for testing only
                    484: ')cmov_simulate(`$2',`$4',`$5')')')
                    485:
                    486: dnl  Called: cmov_simulate(cond,src,dst)
                    487: dnl  If this is going to be used with memory operands for the source it will
                    488: dnl  need to be changed to do a fetch even if the condition is false, so as
                    489: dnl  to trigger exceptions the same way a real cmov does.
                    490: define(cmov_simulate,
                    491: m4_assert_numargs(3)
                    492:        `j$1    1f      C cmov$1 $2, $3
                    493:        jmp     2f
                    494: 1:     movl    $2, $3
                    495: 2:')
                    496:
                    497: dnl  Called: cmov_bytes_tttn(name,tttn,src,dst)
                    498: define(cmov_bytes_tttn,
                    499: m4_assert_numargs(4)
                    500: `.byte dnl
                    501: 15, dnl
                    502: eval(64+$2), dnl
                    503: eval(192+8*x86_opcode_reg32(`$4')+x86_opcode_reg32(`$3')) dnl
                    504:        C `$1 $3, $4'')
                    505:
                    506:
                    507: dnl  Usage: loop_or_decljnz label
                    508: dnl
                    509: dnl  Generate either a "loop" instruction or a "decl %ecx / jnz", whichever
                    510: dnl  is better.  "loop" is better on K6 and probably on 386, on other chips
                    511: dnl  separate decl/jnz is better.
                    512: dnl
                    513: dnl  This macro is just for mpn/x86/divrem_1.asm and mpn/x86/mod_1.asm where
                    514: dnl  this loop_or_decljnz variation is enough to let the code be shared by
                    515: dnl  all chips.
                    516:
                    517: define(loop_or_decljnz,
                    518: `ifelse(loop_is_better_p,1,
                    519:        `loop',
                    520:        `decl   %ecx
                    521:        jnz')')
                    522:
                    523: define(loop_is_better_p,
                    524: `m4_ifdef_anyof_p(`HAVE_TARGET_CPU_k6',
                    525:                   `HAVE_TARGET_CPU_k62',
                    526:                   `HAVE_TARGET_CPU_k63',
                    527:                   `HAVE_TARGET_CPU_i386')')
                    528:
                    529:
                    530: dnl  Usage: Zdisp(inst,op,op,op)
                    531: dnl
                    532: dnl  Generate explicit .byte sequences if necessary to force a byte-sized
                    533: dnl  zero displacement on an instruction.  For example,
                    534: dnl
                    535: dnl         Zdisp(  movl,   0,(%esi), %eax)
                    536: dnl
                    537: dnl  expands to
                    538: dnl
                    539: dnl                 .byte   139,70,0  C movl 0(%esi), %eax
                    540: dnl
                    541: dnl  If the displacement given isn't 0, then normal assembler code is
                    542: dnl  generated.  For example,
                    543: dnl
                    544: dnl         Zdisp(  movl,   4,(%esi), %eax)
                    545: dnl
                    546: dnl  expands to
                    547: dnl
                    548: dnl                 movl    4(%esi), %eax
                    549: dnl
                    550: dnl  This means a single Zdisp() form can be used with an expression for the
                    551: dnl  displacement, and .byte will be used only if necessary.  The
                    552: dnl  displacement argument is eval()ed.
                    553: dnl
                    554: dnl  Because there aren't many places a 0(reg) form is wanted, Zdisp is
                    555: dnl  implemented with a table of instructions and encodings.  A new entry is
                    556: dnl  needed for any different operation or registers.
                    557:
                    558: define(Zdisp,
                    559: `define(`Zdisp_found',0)dnl
                    560: Zdisp_match( movl, %eax, 0,(%edi), `137,71,0',    $@)`'dnl
                    561: Zdisp_match( movl, %ebx, 0,(%edi), `137,95,0',    $@)`'dnl
                    562: Zdisp_match( movl, %esi, 0,(%edi), `137,119,0',   $@)`'dnl
                    563: Zdisp_match( movl, 0,(%ebx), %eax, `139,67,0',    $@)`'dnl
                    564: Zdisp_match( movl, 0,(%ebx), %esi, `139,115,0',   $@)`'dnl
                    565: Zdisp_match( movl, 0,(%esi), %eax, `139,70,0',    $@)`'dnl
                    566: Zdisp_match( movl, 0,(%esi,%ecx,4), %eax, `0x8b,0x44,0x8e,0x00',      $@)`'dnl
                    567: Zdisp_match( addl, %ebx, 0,(%edi), `1,95,0',      $@)`'dnl
                    568: Zdisp_match( addl, %ecx, 0,(%edi), `1,79,0',      $@)`'dnl
                    569: Zdisp_match( addl, %esi, 0,(%edi), `1,119,0',     $@)`'dnl
                    570: Zdisp_match( subl, %ecx, 0,(%edi), `41,79,0',     $@)`'dnl
                    571: Zdisp_match( adcl, 0,(%edx), %esi, `19,114,0',    $@)`'dnl
                    572: Zdisp_match( sbbl, 0,(%edx), %esi, `27,114,0',    $@)`'dnl
                    573: Zdisp_match( movq, 0,(%eax,%ecx,8), %mm0, `0x0f,0x6f,0x44,0xc8,0x00', $@)`'dnl
                    574: Zdisp_match( movq, 0,(%ebx,%eax,4), %mm0, `0x0f,0x6f,0x44,0x83,0x00', $@)`'dnl
                    575: Zdisp_match( movq, 0,(%ebx,%eax,4), %mm2, `0x0f,0x6f,0x54,0x83,0x00', $@)`'dnl
                    576: Zdisp_match( movq, 0,(%esi),        %mm0, `15,111,70,0',     $@)`'dnl
                    577: Zdisp_match( movq, %mm0,        0,(%edi), `15,127,71,0',     $@)`'dnl
                    578: Zdisp_match( movq, %mm2, 0,(%ecx,%eax,4), `0x0f,0x7f,0x54,0x81,0x00', $@)`'dnl
                    579: Zdisp_match( movq, %mm2, 0,(%edx,%eax,4), `0x0f,0x7f,0x54,0x82,0x00', $@)`'dnl
                    580: Zdisp_match( movq, %mm0, 0,(%edx,%ecx,8), `0x0f,0x7f,0x44,0xca,0x00', $@)`'dnl
                    581: Zdisp_match( movd, 0,(%eax,%ecx,8), %mm1, `0x0f,0x6e,0x4c,0xc8,0x00', $@)`'dnl
                    582: Zdisp_match( movd, 0,(%edx,%ecx,8), %mm0, `0x0f,0x6e,0x44,0xca,0x00', $@)`'dnl
                    583: Zdisp_match( movd, %mm0, 0,(%eax,%ecx,4), `0x0f,0x7e,0x44,0x88,0x00', $@)`'dnl
                    584: Zdisp_match( movd, %mm0, 0,(%ecx,%eax,4), `0x0f,0x7e,0x44,0x81,0x00', $@)`'dnl
                    585: Zdisp_match( movd, %mm2, 0,(%ecx,%eax,4), `0x0f,0x7e,0x54,0x81,0x00', $@)`'dnl
                    586: ifelse(Zdisp_found,0,
                    587: `m4_error(`unrecognised instruction in Zdisp: $1 $2 $3 $4
                    588: ')')')
                    589:
                    590: define(Zdisp_match,
                    591: `ifelse(eval(m4_stringequal_p(`$1',`$6')
                    592:        && m4_stringequal_p(`$2',0)
                    593:        && m4_stringequal_p(`$3',`$8')
                    594:        && m4_stringequal_p(`$4',`$9')),1,
                    595: `define(`Zdisp_found',1)dnl
                    596: ifelse(eval(`$7'),0,
                    597: `      .byte   $5  C `$1 0$3, $4'',
                    598: `      $6      $7$8, $9')',
                    599:
                    600: `ifelse(eval(m4_stringequal_p(`$1',`$6')
                    601:        && m4_stringequal_p(`$2',`$7')
                    602:        && m4_stringequal_p(`$3',0)
                    603:        && m4_stringequal_p(`$4',`$9')),1,
                    604: `define(`Zdisp_found',1)dnl
                    605: ifelse(eval(`$8'),0,
                    606: `      .byte   $5  C `$1 $2, 0$4'',
                    607: `      $6      $7, $8$9')')')')
                    608:
                    609:
                    610: dnl  Usage: shldl(count,src,dst)
                    611: dnl         shrdl(count,src,dst)
                    612: dnl         shldw(count,src,dst)
                    613: dnl         shrdw(count,src,dst)
                    614: dnl
                    615: dnl  Generate a double-shift instruction, possibly omitting a %cl count
                    616: dnl  parameter if that's what the assembler requires, as indicated by
                    617: dnl  WANT_SHLDL_CL in config.m4.  For example,
                    618: dnl
                    619: dnl         shldl(  %cl, %eax, %ebx)
                    620: dnl
                    621: dnl  turns into either
                    622: dnl
                    623: dnl         shldl   %cl, %eax, %ebx
                    624: dnl  or
                    625: dnl         shldl   %eax, %ebx
                    626: dnl
                    627: dnl  Immediate counts are always passed through unchanged.  For example,
                    628: dnl
                    629: dnl         shrdl(  $2, %esi, %edi)
                    630: dnl  becomes
                    631: dnl         shrdl   $2, %esi, %edi
                    632: dnl
                    633: dnl
                    634: dnl  If you forget to use the macro form "shldl( ...)" and instead write
                    635: dnl  just a plain "shldl ...", an error results.  This ensures the necessary
                    636: dnl  variant treatment of %cl isn't accidentally bypassed.
                    637:
                    638: define(define_shd_instruction,
                    639: `define($1,
                    640: m4_instruction_wrapper()
                    641: m4_assert_numargs(3)
                    642: `shd_instruction'(m4_doublequote($`'0),m4_doublequote($`'1),dnl
                    643: m4_doublequote($`'2),m4_doublequote($`'3)))')
                    644:
                    645: dnl  Effectively: define(shldl,`shd_instruction(`$0',`$1',`$2',`$3')') etc
                    646: define_shd_instruction(shldl)
                    647: define_shd_instruction(shrdl)
                    648: define_shd_instruction(shldw)
                    649: define_shd_instruction(shrdw)
                    650:
                    651: dnl  Called: shd_instruction(op,count,src,dst)
                    652: define(shd_instruction,
                    653: m4_assert_numargs(4)
                    654: m4_assert_defined(`WANT_SHLDL_CL')
                    655: `ifelse(eval(m4_stringequal_p(`$2',`%cl') && !WANT_SHLDL_CL),1,
                    656: ``$1'  `$3', `$4'',
                    657: ``$1'  `$2', `$3', `$4'')')
                    658:
                    659:
                    660: dnl  Usage: ASSERT(cond, instructions)
                    661: dnl
                    662: dnl  If WANT_ASSERT is 1, output the given instructions and expect the given
                    663: dnl  flags condition to then be satisfied.  For example,
                    664: dnl
                    665: dnl         ASSERT(ne, `cmpl %eax, %ebx')
                    666: dnl
                    667: dnl  The instructions can be omitted to just assert a flags condition with
                    668: dnl  no extra calculation.  For example,
                    669: dnl
                    670: dnl         ASSERT(nc)
                    671: dnl
                    672: dnl  When `instructions' is not empty, a pushf/popf is added to preserve the
                    673: dnl  flags, but the instructions themselves must preserve any registers that
                    674: dnl  matter.  FRAME is adjusted for the push and pop, so the instructions
                    675: dnl  given can use defframe() stack variables.
                    676:
                    677: define(ASSERT,
                    678: m4_assert_numargs_range(1,2)
                    679: `ifelse(WANT_ASSERT,1,
                    680:        `C ASSERT
                    681: ifelse(`$2',,,`        pushf   ifdef(`FRAME',`FRAME_pushl()')')
                    682:        $2
                    683:        j`$1'   1f
                    684:        ud2     C assertion failed
                    685: 1:
                    686: ifelse(`$2',,,`        popf    ifdef(`FRAME',`FRAME_popl()')')
                    687: ')')
                    688:
                    689:
                    690: dnl  Usage: movl_text_address(label,register)
                    691: dnl
                    692: dnl  Get the address of a text segment label, using either a plain movl or a
                    693: dnl  position-independent calculation, as necessary.  For example,
                    694: dnl
                    695: dnl         movl_code_address(L(foo),%eax)
                    696: dnl
                    697: dnl  This macro is only meant for use in ASSERT()s or when testing, since
                    698: dnl  the PIC sequence it generates will want to be done with a ret balancing
                    699: dnl  the call on CPUs with return address branch predition.
                    700: dnl
                    701: dnl  The addl generated here has a backward reference to 1b, and so won't
                    702: dnl  suffer from the two forwards references bug in old gas (described in
                    703: dnl  mpn/x86/README.family).
                    704:
                    705: define(movl_text_address,
                    706: `ifdef(`PIC',
                    707:        `call   1f
                    708: 1:     popl    $2      C %eip
                    709:        addl    `$'$1-1b, $2',
                    710:        `movl   `$'$1, $2')')
                    711:
                    712:
                    713: divert`'dnl

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>