Blame mpn/x86/x86-defs.m4

Packit 5c3484
divert(-1)
Packit 5c3484
Packit 5c3484
dnl  m4 macros for x86 assembler.
Packit 5c3484
Packit 5c3484
dnl  Copyright 1999-2003, 2007, 2010, 2012, 2014 Free Software Foundation, Inc.
Packit 5c3484
Packit 5c3484
dnl  This file is part of the GNU MP Library.
Packit 5c3484
dnl
Packit 5c3484
dnl  The GNU MP Library is free software; you can redistribute it and/or modify
Packit 5c3484
dnl  it under the terms of either:
Packit 5c3484
dnl
Packit 5c3484
dnl    * the GNU Lesser General Public License as published by the Free
Packit 5c3484
dnl      Software Foundation; either version 3 of the License, or (at your
Packit 5c3484
dnl      option) any later version.
Packit 5c3484
dnl
Packit 5c3484
dnl  or
Packit 5c3484
dnl
Packit 5c3484
dnl    * the GNU General Public License as published by the Free Software
Packit 5c3484
dnl      Foundation; either version 2 of the License, or (at your option) any
Packit 5c3484
dnl      later version.
Packit 5c3484
dnl
Packit 5c3484
dnl  or both in parallel, as here.
Packit 5c3484
dnl
Packit 5c3484
dnl  The GNU MP Library is distributed in the hope that it will be useful, but
Packit 5c3484
dnl  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
Packit 5c3484
dnl  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
Packit 5c3484
dnl  for more details.
Packit 5c3484
dnl
Packit 5c3484
dnl  You should have received copies of the GNU General Public License and the
Packit 5c3484
dnl  GNU Lesser General Public License along with the GNU MP Library.  If not,
Packit 5c3484
dnl  see https://www.gnu.org/licenses/.
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Notes:
Packit 5c3484
dnl
Packit 5c3484
dnl  m4 isn't perfect for processing BSD style x86 assembler code, the main
Packit 5c3484
dnl  problems are,
Packit 5c3484
dnl
Packit 5c3484
dnl  1. Doing define(foo,123) and then using foo in an addressing mode like
Packit 5c3484
dnl     foo(%ebx) expands as a macro rather than a constant.  This is worked
Packit 5c3484
dnl     around by using deflit() from asm-defs.m4, instead of define().
Packit 5c3484
dnl
Packit 5c3484
dnl  2. Immediates in macro definitions need a space or `' to stop the $
Packit 5c3484
dnl     looking like a macro parameter.  For example,
Packit 5c3484
dnl
Packit 5c3484
dnl	        define(foo, `mov $ 123, %eax')
Packit 5c3484
dnl
Packit 5c3484
dnl     This is only a problem in macro definitions, not in ordinary text,
Packit 5c3484
dnl     and not in macro parameters like text passed to forloop() or ifdef().
Packit 5c3484
Packit 5c3484
Packit 5c3484
deflit(GMP_LIMB_BYTES, 4)
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Libtool gives -DPIC -DDLL_EXPORT to indicate a cygwin or mingw DLL.  We
Packit 5c3484
dnl  undefine PIC since we don't need to be position independent in this
Packit 5c3484
dnl  case and definitely don't want the ELF style _GLOBAL_OFFSET_TABLE_ etc.
Packit 5c3484
Packit 5c3484
ifdef(`DLL_EXPORT',`undefine(`PIC')')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: CPUVEC_FUNCS_LIST
Packit 5c3484
dnl
Packit 5c3484
dnl  A list of the functions from gmp-impl.h x86 struct cpuvec_t, in the
Packit 5c3484
dnl  order they appear in that structure.
Packit 5c3484
Packit 5c3484
define(CPUVEC_FUNCS_LIST,
Packit 5c3484
``add_n',
Packit 5c3484
`addlsh1_n',
Packit 5c3484
`addlsh2_n',
Packit 5c3484
`addmul_1',
Packit 5c3484
`addmul_2',
Packit 5c3484
`bdiv_dbm1c',
Packit 5c3484
`cnd_add_n',
Packit 5c3484
`cnd_sub_n',
Packit 5c3484
`com',
Packit 5c3484
`copyd',
Packit 5c3484
`copyi',
Packit 5c3484
`divexact_1',
Packit 5c3484
`divrem_1',
Packit 5c3484
`gcd_1',
Packit 5c3484
`lshift',
Packit 5c3484
`lshiftc',
Packit 5c3484
`mod_1',
Packit 5c3484
`mod_1_1p',
Packit 5c3484
`mod_1_1p_cps',
Packit 5c3484
`mod_1s_2p',
Packit 5c3484
`mod_1s_2p_cps',
Packit 5c3484
`mod_1s_4p',
Packit 5c3484
`mod_1s_4p_cps',
Packit 5c3484
`mod_34lsub1',
Packit 5c3484
`modexact_1c_odd',
Packit 5c3484
`mul_1',
Packit 5c3484
`mul_basecase',
Packit 5c3484
`mullo_basecase',
Packit 5c3484
`preinv_divrem_1',
Packit 5c3484
`preinv_mod_1',
Packit 5c3484
`redc_1',
Packit 5c3484
`redc_2',
Packit 5c3484
`rshift',
Packit 5c3484
`sqr_basecase',
Packit 5c3484
`sub_n',
Packit 5c3484
`sublsh1_n',
Packit 5c3484
`submul_1'')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Called: PROLOGUE_cpu(GSYM_PREFIX`'foo)
Packit 5c3484
dnl
Packit 5c3484
dnl  In the x86 code we use explicit TEXT and ALIGN() calls in the code,
Packit 5c3484
dnl  since different alignments are wanted in various circumstances.  So for
Packit 5c3484
dnl  instance,
Packit 5c3484
dnl
Packit 5c3484
dnl                  TEXT
Packit 5c3484
dnl                  ALIGN(16)
Packit 5c3484
dnl          PROLOGUE(mpn_add_n)
Packit 5c3484
dnl          ...
Packit 5c3484
dnl          EPILOGUE()
Packit 5c3484
Packit 5c3484
define(`PROLOGUE_cpu',
Packit 5c3484
m4_assert_numargs(1)
Packit 5c3484
m4_assert_defined(`WANT_PROFILING')
Packit 5c3484
	`GLOBL	$1
Packit 5c3484
	TYPE($1,`function')
Packit 5c3484
	COFF_TYPE($1)
Packit 5c3484
$1:
Packit 5c3484
ifelse(WANT_PROFILING,`prof',      `	call_mcount')
Packit 5c3484
ifelse(WANT_PROFILING,`gprof',     `	call_mcount')
Packit 5c3484
ifelse(WANT_PROFILING,`instrument',`	call_instrument(enter)')
Packit 5c3484
')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: COFF_TYPE(GSYM_PREFIX`'foo)
Packit 5c3484
dnl
Packit 5c3484
dnl  Emit COFF style ".def ... .endef" type information for a function, when
Packit 5c3484
dnl  supported.  The argument should include any GSYM_PREFIX.
Packit 5c3484
dnl
Packit 5c3484
dnl  See autoconf macro GMP_ASM_COFF_TYPE for HAVE_COFF_TYPE.
Packit 5c3484
Packit 5c3484
define(COFF_TYPE,
Packit 5c3484
m4_assert_numargs(1)
Packit 5c3484
m4_assert_defined(`HAVE_COFF_TYPE')
Packit 5c3484
`ifelse(HAVE_COFF_TYPE,yes,
Packit 5c3484
	`.def	$1
Packit 5c3484
	.scl	2
Packit 5c3484
	.type	32
Packit 5c3484
	.endef')')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: call_mcount
Packit 5c3484
dnl
Packit 5c3484
dnl  For `gprof' style profiling, %ebp is setup as a frame pointer.  None of
Packit 5c3484
dnl  the assembler routines use %ebp this way, so it's done only for the
Packit 5c3484
dnl  benefit of mcount.  glibc sysdeps/i386/i386-mcount.S shows how mcount
Packit 5c3484
dnl  gets the current function from (%esp) and the parent from 4(%ebp).
Packit 5c3484
dnl
Packit 5c3484
dnl  For `prof' style profiling gcc generates mcount calls without setting
Packit 5c3484
dnl  up %ebp, and the same is done here.
Packit 5c3484
Packit 5c3484
define(`call_mcount',
Packit 5c3484
m4_assert_numargs(-1)
Packit 5c3484
m4_assert_defined(`WANT_PROFILING')
Packit 5c3484
m4_assert_defined(`MCOUNT_PIC_REG')
Packit 5c3484
m4_assert_defined(`MCOUNT_NONPIC_REG')
Packit 5c3484
m4_assert_defined(`MCOUNT_PIC_CALL')
Packit 5c3484
m4_assert_defined(`MCOUNT_NONPIC_CALL')
Packit 5c3484
`ifelse(ifdef(`PIC',`MCOUNT_PIC_REG',`MCOUNT_NONPIC_REG'),,,
Packit 5c3484
`	DATA
Packit 5c3484
	ALIGN(4)
Packit 5c3484
L(mcount_data_`'mcount_counter):
Packit 5c3484
	W32	0
Packit 5c3484
	TEXT
Packit 5c3484
')dnl
Packit 5c3484
ifelse(WANT_PROFILING,`gprof',
Packit 5c3484
`	pushl	%ebp
Packit 5c3484
	movl	%esp, %ebp
Packit 5c3484
')dnl
Packit 5c3484
ifdef(`PIC',
Packit 5c3484
`	pushl	%ebx
Packit 5c3484
	call_movl_eip_to_ebx
Packit 5c3484
L(mcount_here_`'mcount_counter):
Packit 5c3484
	addl	$_GLOBAL_OFFSET_TABLE_+[.-L(mcount_here_`'mcount_counter)], %ebx
Packit 5c3484
ifelse(MCOUNT_PIC_REG,,,
Packit 5c3484
`	leal	L(mcount_data_`'mcount_counter)@GOTOFF(%ebx), MCOUNT_PIC_REG')
Packit 5c3484
MCOUNT_PIC_CALL
Packit 5c3484
	popl	%ebx
Packit 5c3484
',`dnl non-PIC
Packit 5c3484
ifelse(MCOUNT_NONPIC_REG,,,
Packit 5c3484
`	movl	`$'L(mcount_data_`'mcount_counter), MCOUNT_NONPIC_REG
Packit 5c3484
')dnl
Packit 5c3484
MCOUNT_NONPIC_CALL
Packit 5c3484
')dnl
Packit 5c3484
ifelse(WANT_PROFILING,`gprof',
Packit 5c3484
`	popl	%ebp
Packit 5c3484
')
Packit 5c3484
define(`mcount_counter',incr(mcount_counter))
Packit 5c3484
')
Packit 5c3484
Packit 5c3484
define(mcount_counter,1)
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: call_instrument(enter|exit)
Packit 5c3484
dnl
Packit 5c3484
dnl  Call __cyg_profile_func_enter or __cyg_profile_func_exit.
Packit 5c3484
dnl
Packit 5c3484
dnl  For PIC, most routines don't require _GLOBAL_OFFSET_TABLE_ themselves
Packit 5c3484
dnl  so %ebx is just setup for these calls.  It's a bit wasteful to repeat
Packit 5c3484
dnl  the setup for the exit call having done it earlier for the enter, but
Packit 5c3484
dnl  there's nowhere very convenient to hold %ebx through the length of a
Packit 5c3484
dnl  routine, in general.
Packit 5c3484
dnl
Packit 5c3484
dnl  For PIC, because instrument_current_function will be within the current
Packit 5c3484
dnl  object file we can get it just as an offset from %eip, there's no need
Packit 5c3484
dnl  to use the GOT.
Packit 5c3484
dnl
Packit 5c3484
dnl  No attempt is made to maintain the stack alignment gcc generates with
Packit 5c3484
dnl  -mpreferred-stack-boundary.  This wouldn't be hard, but it seems highly
Packit 5c3484
dnl  unlikely the instrumenting functions would be doing anything that'd
Packit 5c3484
dnl  benefit from alignment, in particular they're unlikely to be using
Packit 5c3484
dnl  doubles or long doubles on the stack.
Packit 5c3484
dnl
Packit 5c3484
dnl  The FRAME scheme is used to conveniently account for the register saves
Packit 5c3484
dnl  before accessing the return address.  Any previous value is saved and
Packit 5c3484
dnl  restored, since plenty of code keeps a value across a "ret" in the
Packit 5c3484
dnl  middle of a routine.
Packit 5c3484
Packit 5c3484
define(call_instrument,
Packit 5c3484
m4_assert_numargs(1)
Packit 5c3484
`	pushdef(`FRAME',0)
Packit 5c3484
ifelse($1,exit,
Packit 5c3484
`	pushl	%eax	FRAME_pushl()	C return value
Packit 5c3484
')
Packit 5c3484
ifdef(`PIC',
Packit 5c3484
`	pushl	%ebx	FRAME_pushl()
Packit 5c3484
	call_movl_eip_to_ebx
Packit 5c3484
L(instrument_here_`'instrument_count):
Packit 5c3484
	movl	%ebx, %ecx
Packit 5c3484
	addl	$_GLOBAL_OFFSET_TABLE_+[.-L(instrument_here_`'instrument_count)], %ebx
Packit 5c3484
	C use addl rather than leal to avoid old gas bugs, see mpn/x86/README
Packit 5c3484
	addl	$instrument_current_function-L(instrument_here_`'instrument_count), %ecx
Packit 5c3484
	pushl	m4_empty_if_zero(FRAME)(%esp)	FRAME_pushl()	C return addr
Packit 5c3484
	pushl	%ecx				FRAME_pushl()	C this function
Packit 5c3484
	call	GSYM_PREFIX`'__cyg_profile_func_$1@PLT
Packit 5c3484
	addl	$`'8, %esp
Packit 5c3484
	popl	%ebx
Packit 5c3484
',
Packit 5c3484
`	C non-PIC
Packit 5c3484
	pushl	m4_empty_if_zero(FRAME)(%esp)	FRAME_pushl()	C return addr
Packit 5c3484
	pushl	$instrument_current_function	FRAME_pushl()	C this function
Packit 5c3484
	call	GSYM_PREFIX`'__cyg_profile_func_$1
Packit 5c3484
	addl	$`'8, %esp
Packit 5c3484
')
Packit 5c3484
ifelse($1,exit,
Packit 5c3484
`	popl	%eax			C return value
Packit 5c3484
')
Packit 5c3484
	popdef(`FRAME')
Packit 5c3484
define(`instrument_count',incr(instrument_count))
Packit 5c3484
')
Packit 5c3484
define(instrument_count,1)
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: instrument_current_function
Packit 5c3484
dnl
Packit 5c3484
dnl  Return the current function name for instrumenting purposes.  This is
Packit 5c3484
dnl  PROLOGUE_current_function, but it sticks at the first such name seen.
Packit 5c3484
dnl
Packit 5c3484
dnl  Sticking to the first name seen ensures that multiple-entrypoint
Packit 5c3484
dnl  functions like mpn_add_nc and mpn_add_n will make enter and exit calls
Packit 5c3484
dnl  giving the same function address.
Packit 5c3484
Packit 5c3484
define(instrument_current_function,
Packit 5c3484
m4_assert_numargs(-1)
Packit 5c3484
`ifdef(`instrument_current_function_seen',
Packit 5c3484
`instrument_current_function_seen',
Packit 5c3484
`define(`instrument_current_function_seen',PROLOGUE_current_function)dnl
Packit 5c3484
PROLOGUE_current_function')')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: call_movl_eip_to_ebx
Packit 5c3484
dnl
Packit 5c3484
dnl  Generate a call to L(movl_eip_to_ebx), and record the need for that
Packit 5c3484
dnl  routine.
Packit 5c3484
Packit 5c3484
define(call_movl_eip_to_ebx,
Packit 5c3484
m4_assert_numargs(-1)
Packit 5c3484
`call	L(movl_eip_to_ebx)
Packit 5c3484
define(`movl_eip_to_ebx_needed',1)')
Packit 5c3484
Packit 5c3484
dnl  Usage: generate_movl_eip_to_ebx
Packit 5c3484
dnl
Packit 5c3484
dnl  Emit a L(movl_eip_to_ebx) routine, if needed and not already generated.
Packit 5c3484
Packit 5c3484
define(generate_movl_eip_to_ebx,
Packit 5c3484
m4_assert_numargs(-1)
Packit 5c3484
`ifelse(movl_eip_to_ebx_needed,1,
Packit 5c3484
`ifelse(movl_eip_to_ebx_done,1,,
Packit 5c3484
`L(movl_eip_to_ebx):
Packit 5c3484
	movl	(%esp), %ebx
Packit 5c3484
	ret_internal
Packit 5c3484
define(`movl_eip_to_ebx_done',1)
Packit 5c3484
')')')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: ret
Packit 5c3484
dnl
Packit 5c3484
dnl  Generate a "ret", but if doing instrumented profiling then call
Packit 5c3484
dnl  __cyg_profile_func_exit first.
Packit 5c3484
Packit 5c3484
define(ret,
Packit 5c3484
m4_assert_numargs(-1)
Packit 5c3484
m4_assert_defined(`WANT_PROFILING')
Packit 5c3484
`ifelse(WANT_PROFILING,instrument,
Packit 5c3484
`ret_instrument',
Packit 5c3484
`ret_internal')
Packit 5c3484
generate_movl_eip_to_ebx
Packit 5c3484
')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: ret_internal
Packit 5c3484
dnl
Packit 5c3484
dnl  A plain "ret", without any __cyg_profile_func_exit call.  This can be
Packit 5c3484
dnl  used for a return which is internal to some function, such as when
Packit 5c3484
dnl  getting %eip for PIC.
Packit 5c3484
Packit 5c3484
define(ret_internal,
Packit 5c3484
m4_assert_numargs(-1)
Packit 5c3484
``ret'')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: ret_instrument
Packit 5c3484
dnl
Packit 5c3484
dnl  Generate call to __cyg_profile_func_exit and then a ret.  If a ret has
Packit 5c3484
dnl  already been seen from this function then jump to that chunk of code,
Packit 5c3484
dnl  rather than emitting it again.
Packit 5c3484
Packit 5c3484
define(ret_instrument,
Packit 5c3484
m4_assert_numargs(-1)
Packit 5c3484
`ifelse(m4_unquote(ret_instrument_seen_`'instrument_current_function),1,
Packit 5c3484
`jmp	L(instrument_exit_`'instrument_current_function)',
Packit 5c3484
`define(ret_instrument_seen_`'instrument_current_function,1)
Packit 5c3484
L(instrument_exit_`'instrument_current_function):
Packit 5c3484
call_instrument(exit)
Packit 5c3484
	ret_internal')')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: _GLOBAL_OFFSET_TABLE_
Packit 5c3484
dnl
Packit 5c3484
dnl  Expand to _GLOBAL_OFFSET_TABLE_ plus any necessary underscore prefix.
Packit 5c3484
dnl  This lets us write plain _GLOBAL_OFFSET_TABLE_ in SVR4 style, but still
Packit 5c3484
dnl  work with systems requiring an extra underscore such as OpenBSD.
Packit 5c3484
dnl
Packit 5c3484
dnl  deflit is used so "leal _GLOBAL_OFFSET_TABLE_(%eax), %ebx" will come
Packit 5c3484
dnl  out right, though that form doesn't work properly in gas (see
Packit 5c3484
dnl  mpn/x86/README).
Packit 5c3484
Packit 5c3484
deflit(_GLOBAL_OFFSET_TABLE_,
Packit 5c3484
m4_assert_defined(`GOT_GSYM_PREFIX')
Packit 5c3484
`GOT_GSYM_PREFIX`_GLOBAL_OFFSET_TABLE_'')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  --------------------------------------------------------------------------
Packit 5c3484
dnl  Various x86 macros.
Packit 5c3484
dnl
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: ALIGN_OFFSET(bytes,offset)
Packit 5c3484
dnl
Packit 5c3484
dnl  Align to `offset' away from a multiple of `bytes'.
Packit 5c3484
dnl
Packit 5c3484
dnl  This is useful for testing, for example align to something very strict
Packit 5c3484
dnl  and see what effect offsets from it have, "ALIGN_OFFSET(256,32)".
Packit 5c3484
dnl
Packit 5c3484
dnl  Generally you wouldn't execute across the padding, but it's done with
Packit 5c3484
dnl  nop's so it'll work.
Packit 5c3484
Packit 5c3484
define(ALIGN_OFFSET,
Packit 5c3484
m4_assert_numargs(2)
Packit 5c3484
`ALIGN($1)
Packit 5c3484
forloop(`i',1,$2,`	nop
Packit 5c3484
')')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: defframe(name,offset)
Packit 5c3484
dnl
Packit 5c3484
dnl  Make a definition like the following with which to access a parameter
Packit 5c3484
dnl  or variable on the stack.
Packit 5c3484
dnl
Packit 5c3484
dnl         define(name,`FRAME+offset(%esp)')
Packit 5c3484
dnl
Packit 5c3484
dnl  Actually m4_empty_if_zero(FRAME+offset) is used, which will save one
Packit 5c3484
dnl  byte if FRAME+offset is zero, by putting (%esp) rather than 0(%esp).
Packit 5c3484
dnl  Use define(`defframe_empty_if_zero_disabled',1) if for some reason the
Packit 5c3484
dnl  zero offset is wanted.
Packit 5c3484
dnl
Packit 5c3484
dnl  The new macro also gets a check that when it's used FRAME is actually
Packit 5c3484
dnl  defined, and that the final %esp offset isn't negative, which would
Packit 5c3484
dnl  mean an attempt to access something below the current %esp.
Packit 5c3484
dnl
Packit 5c3484
dnl  deflit() is used rather than a plain define(), so the new macro won't
Packit 5c3484
dnl  delete any following parenthesized expression.  name(%edi) will come
Packit 5c3484
dnl  out say as 16(%esp)(%edi).  This isn't valid assembler and should
Packit 5c3484
dnl  provoke an error, which is better than silently giving just 16(%esp).
Packit 5c3484
dnl
Packit 5c3484
dnl  See README for more on the suggested way to access the stack frame.
Packit 5c3484
Packit 5c3484
define(defframe,
Packit 5c3484
m4_assert_numargs(2)
Packit 5c3484
`deflit(`$1',
Packit 5c3484
m4_assert_defined(`FRAME')
Packit 5c3484
`defframe_check_notbelow(`$1',$2,FRAME)dnl
Packit 5c3484
defframe_empty_if_zero(FRAME+($2))(%esp)')')
Packit 5c3484
Packit 5c3484
dnl  Called: defframe_empty_if_zero(expression)
Packit 5c3484
define(defframe_empty_if_zero,
Packit 5c3484
m4_assert_numargs(1)
Packit 5c3484
`ifelse(defframe_empty_if_zero_disabled,1,
Packit 5c3484
`eval($1)',
Packit 5c3484
`m4_empty_if_zero($1)')')
Packit 5c3484
Packit 5c3484
dnl  Called: defframe_check_notbelow(`name',offset,FRAME)
Packit 5c3484
define(defframe_check_notbelow,
Packit 5c3484
m4_assert_numargs(3)
Packit 5c3484
`ifelse(eval(($3)+($2)<0),1,
Packit 5c3484
`m4_error(`$1 at frame offset $2 used when FRAME is only $3 bytes
Packit 5c3484
')')')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: FRAME_pushl()
Packit 5c3484
dnl         FRAME_popl()
Packit 5c3484
dnl         FRAME_addl_esp(n)
Packit 5c3484
dnl         FRAME_subl_esp(n)
Packit 5c3484
dnl
Packit 5c3484
dnl  Adjust FRAME appropriately for a pushl or popl, or for an addl or subl
Packit 5c3484
dnl  %esp of n bytes.
Packit 5c3484
dnl
Packit 5c3484
dnl  Using these macros is completely optional.  Sometimes it makes more
Packit 5c3484
dnl  sense to put explicit deflit(`FRAME',N) forms, especially when there's
Packit 5c3484
dnl  jumps and different sequences of FRAME values need to be used in
Packit 5c3484
dnl  different places.
Packit 5c3484
Packit 5c3484
define(FRAME_pushl,
Packit 5c3484
m4_assert_numargs(0)
Packit 5c3484
m4_assert_defined(`FRAME')
Packit 5c3484
`deflit(`FRAME',eval(FRAME+4))')
Packit 5c3484
Packit 5c3484
define(FRAME_popl,
Packit 5c3484
m4_assert_numargs(0)
Packit 5c3484
m4_assert_defined(`FRAME')
Packit 5c3484
`deflit(`FRAME',eval(FRAME-4))')
Packit 5c3484
Packit 5c3484
define(FRAME_addl_esp,
Packit 5c3484
m4_assert_numargs(1)
Packit 5c3484
m4_assert_defined(`FRAME')
Packit 5c3484
`deflit(`FRAME',eval(FRAME-($1)))')
Packit 5c3484
Packit 5c3484
define(FRAME_subl_esp,
Packit 5c3484
m4_assert_numargs(1)
Packit 5c3484
m4_assert_defined(`FRAME')
Packit 5c3484
`deflit(`FRAME',eval(FRAME+($1)))')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: defframe_pushl(name)
Packit 5c3484
dnl
Packit 5c3484
dnl  Do a combination FRAME_pushl() and a defframe() to name the stack
Packit 5c3484
dnl  location just pushed.  This should come after a pushl instruction.
Packit 5c3484
dnl  Putting it on the same line works and avoids lengthening the code.  For
Packit 5c3484
dnl  example,
Packit 5c3484
dnl
Packit 5c3484
dnl         pushl   %eax     defframe_pushl(VAR_COUNTER)
Packit 5c3484
dnl
Packit 5c3484
dnl  Notice the defframe() is done with an unquoted -FRAME thus giving its
Packit 5c3484
dnl  current value without tracking future changes.
Packit 5c3484
Packit 5c3484
define(defframe_pushl,
Packit 5c3484
m4_assert_numargs(1)
Packit 5c3484
`FRAME_pushl()defframe(`$1',-FRAME)')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  --------------------------------------------------------------------------
Packit 5c3484
dnl  Assembler instruction macros.
Packit 5c3484
dnl
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: emms_or_femms
Packit 5c3484
dnl         femms_available_p
Packit 5c3484
dnl
Packit 5c3484
dnl  femms_available_p expands to 1 or 0 according to whether the AMD 3DNow
Packit 5c3484
dnl  femms instruction is available.  emms_or_femms expands to femms if
Packit 5c3484
dnl  available, or emms if not.
Packit 5c3484
dnl
Packit 5c3484
dnl  emms_or_femms is meant for use in the K6 directory where plain K6
Packit 5c3484
dnl  (without femms) and K6-2 and K6-3 (with a slightly faster femms) are
Packit 5c3484
dnl  supported together.
Packit 5c3484
dnl
Packit 5c3484
dnl  On K7 femms is no longer faster and is just an alias for emms, so plain
Packit 5c3484
dnl  emms may as well be used.
Packit 5c3484
Packit 5c3484
define(femms_available_p,
Packit 5c3484
m4_assert_numargs(-1)
Packit 5c3484
`m4_ifdef_anyof_p(
Packit 5c3484
	`HAVE_HOST_CPU_k62',
Packit 5c3484
	`HAVE_HOST_CPU_k63',
Packit 5c3484
	`HAVE_HOST_CPU_athlon')')
Packit 5c3484
Packit 5c3484
define(emms_or_femms,
Packit 5c3484
m4_assert_numargs(-1)
Packit 5c3484
`ifelse(femms_available_p,1,`femms',`emms')')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: femms
Packit 5c3484
dnl
Packit 5c3484
dnl  Gas 2.9.1 which comes with FreeBSD 3.4 doesn't support femms, so the
Packit 5c3484
dnl  following is a replacement using .byte.
Packit 5c3484
Packit 5c3484
define(femms,
Packit 5c3484
m4_assert_numargs(-1)
Packit 5c3484
`.byte	15,14	C AMD 3DNow femms')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: jadcl0(op)
Packit 5c3484
dnl
Packit 5c3484
dnl  Generate a jnc/incl as a substitute for adcl $0,op.  Note this isn't an
Packit 5c3484
dnl  exact replacement, since it doesn't set the flags like adcl does.
Packit 5c3484
dnl
Packit 5c3484
dnl  This finds a use in K6 mpn_addmul_1, mpn_submul_1, mpn_mul_basecase and
Packit 5c3484
dnl  mpn_sqr_basecase because on K6 an adcl is slow, the branch
Packit 5c3484
dnl  misprediction penalty is small, and the multiply algorithm used leads
Packit 5c3484
dnl  to a carry bit on average only 1/4 of the time.
Packit 5c3484
dnl
Packit 5c3484
dnl  jadcl0_disabled can be set to 1 to instead generate an ordinary adcl
Packit 5c3484
dnl  for comparison.  For example,
Packit 5c3484
dnl
Packit 5c3484
dnl		define(`jadcl0_disabled',1)
Packit 5c3484
dnl
Packit 5c3484
dnl  When using a register operand, eg. "jadcl0(%edx)", the jnc/incl code is
Packit 5c3484
dnl  the same size as an adcl.  This makes it possible to use the exact same
Packit 5c3484
dnl  computed jump code when testing the relative speed of the two.
Packit 5c3484
Packit 5c3484
define(jadcl0,
Packit 5c3484
m4_assert_numargs(1)
Packit 5c3484
`ifelse(jadcl0_disabled,1,
Packit 5c3484
	`adcl	$`'0, $1',
Packit 5c3484
	`jnc	L(jadcl0_`'jadcl0_counter)
Packit 5c3484
	incl	$1
Packit 5c3484
L(jadcl0_`'jadcl0_counter):
Packit 5c3484
define(`jadcl0_counter',incr(jadcl0_counter))')')
Packit 5c3484
Packit 5c3484
define(jadcl0_counter,1)
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: x86_lookup(target, key,value, key,value, ...)
Packit 5c3484
dnl         x86_lookup_p(target, key,value, key,value, ...)
Packit 5c3484
dnl
Packit 5c3484
dnl  Look for `target' among the `key' parameters.
Packit 5c3484
dnl
Packit 5c3484
dnl  x86_lookup expands to the corresponding `value', or generates an error
Packit 5c3484
dnl  if `target' isn't found.
Packit 5c3484
dnl
Packit 5c3484
dnl  x86_lookup_p expands to 1 if `target' is found, or 0 if not.
Packit 5c3484
Packit 5c3484
define(x86_lookup,
Packit 5c3484
m4_assert_numargs_range(1,999)
Packit 5c3484
`ifelse(eval($#<3),1,
Packit 5c3484
`m4_error(`unrecognised part of x86 instruction: $1
Packit 5c3484
')',
Packit 5c3484
`ifelse(`$1',`$2', `$3',
Packit 5c3484
`x86_lookup(`$1',shift(shift(shift($@))))')')')
Packit 5c3484
Packit 5c3484
define(x86_lookup_p,
Packit 5c3484
m4_assert_numargs_range(1,999)
Packit 5c3484
`ifelse(eval($#<3),1, `0',
Packit 5c3484
`ifelse(`$1',`$2',    `1',
Packit 5c3484
`x86_lookup_p(`$1',shift(shift(shift($@))))')')')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: x86_opcode_reg32(reg)
Packit 5c3484
dnl         x86_opcode_reg32_p(reg)
Packit 5c3484
dnl
Packit 5c3484
dnl  x86_opcode_reg32 expands to the standard 3 bit encoding for the given
Packit 5c3484
dnl  32-bit register, eg. `%ebp' turns into 5.
Packit 5c3484
dnl
Packit 5c3484
dnl  x86_opcode_reg32_p expands to 1 if reg is a valid 32-bit register, or 0
Packit 5c3484
dnl  if not.
Packit 5c3484
Packit 5c3484
define(x86_opcode_reg32,
Packit 5c3484
m4_assert_numargs(1)
Packit 5c3484
`x86_lookup(`$1',x86_opcode_reg32_list)')
Packit 5c3484
Packit 5c3484
define(x86_opcode_reg32_p,
Packit 5c3484
m4_assert_onearg()
Packit 5c3484
`x86_lookup_p(`$1',x86_opcode_reg32_list)')
Packit 5c3484
Packit 5c3484
define(x86_opcode_reg32_list,
Packit 5c3484
``%eax',0,
Packit 5c3484
`%ecx',1,
Packit 5c3484
`%edx',2,
Packit 5c3484
`%ebx',3,
Packit 5c3484
`%esp',4,
Packit 5c3484
`%ebp',5,
Packit 5c3484
`%esi',6,
Packit 5c3484
`%edi',7')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: x86_opcode_tttn(cond)
Packit 5c3484
dnl
Packit 5c3484
dnl  Expand to the 4-bit "tttn" field value for the given x86 branch
Packit 5c3484
dnl  condition (like `c', `ae', etc).
Packit 5c3484
Packit 5c3484
define(x86_opcode_tttn,
Packit 5c3484
m4_assert_numargs(1)
Packit 5c3484
`x86_lookup(`$1',x86_opcode_ttn_list)')
Packit 5c3484
Packit 5c3484
define(x86_opcode_tttn_list,
Packit 5c3484
``o',  0,
Packit 5c3484
`no',  1,
Packit 5c3484
`b',   2, `c',  2, `nae',2,
Packit 5c3484
`nb',  3, `nc', 3, `ae', 3,
Packit 5c3484
`e',   4, `z',  4,
Packit 5c3484
`ne',  5, `nz', 5,
Packit 5c3484
`be',  6, `na', 6,
Packit 5c3484
`nbe', 7, `a',  7,
Packit 5c3484
`s',   8,
Packit 5c3484
`ns',  9,
Packit 5c3484
`p',  10, `pe', 10, `npo',10,
Packit 5c3484
`np', 11, `npe',11, `po', 11,
Packit 5c3484
`l',  12, `nge',12,
Packit 5c3484
`nl', 13, `ge', 13,
Packit 5c3484
`le', 14, `ng', 14,
Packit 5c3484
`nle',15, `g',  15')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: cmovCC(%srcreg,%dstreg)
Packit 5c3484
dnl
Packit 5c3484
dnl  Emit a cmov instruction, using a .byte sequence, since various past
Packit 5c3484
dnl  versions of gas don't know cmov.  For example,
Packit 5c3484
dnl
Packit 5c3484
dnl         cmovz(  %eax, %ebx)
Packit 5c3484
dnl
Packit 5c3484
dnl  The source operand can only be a plain register.  (m4 code implementing
Packit 5c3484
dnl  full memory addressing modes exists, believe it or not, but isn't
Packit 5c3484
dnl  currently needed and isn't included.)
Packit 5c3484
dnl
Packit 5c3484
dnl  All the standard conditions are defined.  Attempting to use one without
Packit 5c3484
dnl  the macro parentheses, such as just "cmovbe %eax, %ebx", will provoke
Packit 5c3484
dnl  an error.  This protects against writing something old gas wouldn't
Packit 5c3484
dnl  understand.
Packit 5c3484
Packit 5c3484
dnl  Called: define_cmov_many(cond,tttn,cond,tttn,...)
Packit 5c3484
define(define_cmov_many,
Packit 5c3484
`ifelse(m4_length(`$1'),0,,
Packit 5c3484
`define_cmov(`$1',`$2')define_cmov_many(shift(shift($@)))')')
Packit 5c3484
Packit 5c3484
dnl  Called: define_cmov(cond,tttn)
Packit 5c3484
dnl  Emit basically define(cmov<cond>,`cmov_internal(<cond>,<ttn>,`$1',`$2')')
Packit 5c3484
define(define_cmov,
Packit 5c3484
m4_assert_numargs(2)
Packit 5c3484
`define(`cmov$1',
Packit 5c3484
m4_instruction_wrapper()
Packit 5c3484
m4_assert_numargs(2)
Packit 5c3484
`cmov_internal'(m4_doublequote($`'0),``$2'',dnl
Packit 5c3484
m4_doublequote($`'1),m4_doublequote($`'2)))')
Packit 5c3484
Packit 5c3484
define_cmov_many(x86_opcode_tttn_list)
Packit 5c3484
Packit 5c3484
dnl  Called: cmov_internal(name,tttn,src,dst)
Packit 5c3484
define(cmov_internal,
Packit 5c3484
m4_assert_numargs(4)
Packit 5c3484
`.byte	dnl
Packit 5c3484
15, dnl
Packit 5c3484
eval(64+$2), dnl
Packit 5c3484
eval(192+8*x86_opcode_reg32(`$4')+x86_opcode_reg32(`$3')) dnl
Packit 5c3484
	C `$1 $3, $4'')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: x86_opcode_regmmx(reg)
Packit 5c3484
dnl
Packit 5c3484
dnl  Validate the given mmx register, and return its number, 0 to 7.
Packit 5c3484
Packit 5c3484
define(x86_opcode_regmmx,
Packit 5c3484
m4_assert_numargs(1)
Packit 5c3484
`x86_lookup(`$1',x86_opcode_regmmx_list)')
Packit 5c3484
Packit 5c3484
define(x86_opcode_regmmx_list,
Packit 5c3484
``%mm0',0,
Packit 5c3484
`%mm1',1,
Packit 5c3484
`%mm2',2,
Packit 5c3484
`%mm3',3,
Packit 5c3484
`%mm4',4,
Packit 5c3484
`%mm5',5,
Packit 5c3484
`%mm6',6,
Packit 5c3484
`%mm7',7')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: psadbw(%srcreg,%dstreg)
Packit 5c3484
dnl
Packit 5c3484
dnl  Oldish versions of gas don't know psadbw, in particular gas 2.9.1 on
Packit 5c3484
dnl  FreeBSD 3.3 and 3.4 doesn't, so instead emit .byte sequences.  For
Packit 5c3484
dnl  example,
Packit 5c3484
dnl
Packit 5c3484
dnl         psadbw( %mm1, %mm2)
Packit 5c3484
dnl
Packit 5c3484
dnl  Only register->register forms are supported here, which suffices for
Packit 5c3484
dnl  the current code.
Packit 5c3484
Packit 5c3484
define(psadbw,
Packit 5c3484
m4_instruction_wrapper()
Packit 5c3484
m4_assert_numargs(2)
Packit 5c3484
`.byte 0x0f,0xf6,dnl
Packit 5c3484
eval(192+x86_opcode_regmmx(`$2')*8+x86_opcode_regmmx(`$1')) dnl
Packit 5c3484
	C `psadbw $1, $2'')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: Zdisp(inst,op,op,op)
Packit 5c3484
dnl
Packit 5c3484
dnl  Generate explicit .byte sequences if necessary to force a byte-sized
Packit 5c3484
dnl  zero displacement on an instruction.  For example,
Packit 5c3484
dnl
Packit 5c3484
dnl         Zdisp(  movl,   0,(%esi), %eax)
Packit 5c3484
dnl
Packit 5c3484
dnl  expands to
Packit 5c3484
dnl
Packit 5c3484
dnl                 .byte   139,70,0  C movl 0(%esi), %eax
Packit 5c3484
dnl
Packit 5c3484
dnl  If the displacement given isn't 0, then normal assembler code is
Packit 5c3484
dnl  generated.  For example,
Packit 5c3484
dnl
Packit 5c3484
dnl         Zdisp(  movl,   4,(%esi), %eax)
Packit 5c3484
dnl
Packit 5c3484
dnl  expands to
Packit 5c3484
dnl
Packit 5c3484
dnl                 movl    4(%esi), %eax
Packit 5c3484
dnl
Packit 5c3484
dnl  This means a single Zdisp() form can be used with an expression for the
Packit 5c3484
dnl  displacement, and .byte will be used only if necessary.  The
Packit 5c3484
dnl  displacement argument is eval()ed.
Packit 5c3484
dnl
Packit 5c3484
dnl  Because there aren't many places a 0(reg) form is wanted, Zdisp is
Packit 5c3484
dnl  implemented with a table of instructions and encodings.  A new entry is
Packit 5c3484
dnl  needed for any different operation or registers.  The table is split
Packit 5c3484
dnl  into separate macros to avoid overflowing BSD m4 macro expansion space.
Packit 5c3484
Packit 5c3484
define(Zdisp,
Packit 5c3484
m4_assert_numargs(4)
Packit 5c3484
`define(`Zdisp_found',0)dnl
Packit 5c3484
Zdisp_1($@)dnl
Packit 5c3484
Zdisp_2($@)dnl
Packit 5c3484
Zdisp_3($@)dnl
Packit 5c3484
Zdisp_4($@)dnl
Packit 5c3484
ifelse(Zdisp_found,0,
Packit 5c3484
`m4_error(`unrecognised instruction in Zdisp: $1 $2 $3 $4
Packit 5c3484
')')')
Packit 5c3484
Packit 5c3484
define(Zdisp_1,`dnl
Packit 5c3484
Zdisp_match( adcl, 0,(%edx), %eax,        `0x13,0x42,0x00',           $@)`'dnl
Packit 5c3484
Zdisp_match( adcl, 0,(%edx), %ebx,        `0x13,0x5a,0x00',           $@)`'dnl
Packit 5c3484
Zdisp_match( adcl, 0,(%edx), %esi,        `0x13,0x72,0x00',           $@)`'dnl
Packit 5c3484
Zdisp_match( addl, %ebx, 0,(%edi),        `0x01,0x5f,0x00',           $@)`'dnl
Packit 5c3484
Zdisp_match( addl, %ecx, 0,(%edi),        `0x01,0x4f,0x00',           $@)`'dnl
Packit 5c3484
Zdisp_match( addl, %esi, 0,(%edi),        `0x01,0x77,0x00',           $@)`'dnl
Packit 5c3484
Zdisp_match( sbbl, 0,(%edx), %eax,        `0x1b,0x42,0x00',           $@)`'dnl
Packit 5c3484
Zdisp_match( sbbl, 0,(%edx), %esi,        `0x1b,0x72,0x00',           $@)`'dnl
Packit 5c3484
Zdisp_match( subl, %ecx, 0,(%edi),        `0x29,0x4f,0x00',           $@)`'dnl
Packit 5c3484
Zdisp_match( movzbl, 0,(%eax,%ebp), %eax, `0x0f,0xb6,0x44,0x28,0x00', $@)`'dnl
Packit 5c3484
Zdisp_match( movzbl, 0,(%ecx,%edi), %edi, `0x0f,0xb6,0x7c,0x39,0x00', $@)`'dnl
Packit 5c3484
Zdisp_match( adc, 0,(%ebx,%ecx,4), %eax,  `0x13,0x44,0x8b,0x00',      $@)`'dnl
Packit 5c3484
Zdisp_match( sbb, 0,(%ebx,%ecx,4), %eax,  `0x1b,0x44,0x8b,0x00',      $@)`'dnl
Packit 5c3484
')
Packit 5c3484
define(Zdisp_2,`dnl
Packit 5c3484
Zdisp_match( movl, %eax, 0,(%edi),        `0x89,0x47,0x00',           $@)`'dnl
Packit 5c3484
Zdisp_match( movl, %ebx, 0,(%edi),        `0x89,0x5f,0x00',           $@)`'dnl
Packit 5c3484
Zdisp_match( movl, %esi, 0,(%edi),        `0x89,0x77,0x00',           $@)`'dnl
Packit 5c3484
Zdisp_match( movl, 0,(%ebx), %eax,        `0x8b,0x43,0x00',           $@)`'dnl
Packit 5c3484
Zdisp_match( movl, 0,(%ebx), %esi,        `0x8b,0x73,0x00',           $@)`'dnl
Packit 5c3484
Zdisp_match( movl, 0,(%edx), %eax,        `0x8b,0x42,0x00',           $@)`'dnl
Packit 5c3484
Zdisp_match( movl, 0,(%esi), %eax,        `0x8b,0x46,0x00',           $@)`'dnl
Packit 5c3484
Zdisp_match( movl, 0,(%esi,%ecx,4), %eax, `0x8b,0x44,0x8e,0x00',      $@)`'dnl
Packit 5c3484
Zdisp_match( mov, 0,(%esi,%ecx,4), %eax,  `0x8b,0x44,0x8e,0x00',      $@)`'dnl
Packit 5c3484
Zdisp_match( mov, %eax, 0,(%edi,%ecx,4),  `0x89,0x44,0x8f,0x00',      $@)`'dnl
Packit 5c3484
')
Packit 5c3484
define(Zdisp_3,`dnl
Packit 5c3484
Zdisp_match( movq, 0,(%eax,%ecx,8), %mm0, `0x0f,0x6f,0x44,0xc8,0x00', $@)`'dnl
Packit 5c3484
Zdisp_match( movq, 0,(%ebx,%eax,4), %mm0, `0x0f,0x6f,0x44,0x83,0x00', $@)`'dnl
Packit 5c3484
Zdisp_match( movq, 0,(%ebx,%eax,4), %mm2, `0x0f,0x6f,0x54,0x83,0x00', $@)`'dnl
Packit 5c3484
Zdisp_match( movq, 0,(%ebx,%ecx,4), %mm0, `0x0f,0x6f,0x44,0x8b,0x00', $@)`'dnl
Packit 5c3484
Zdisp_match( movq, 0,(%edx), %mm0,        `0x0f,0x6f,0x42,0x00',      $@)`'dnl
Packit 5c3484
Zdisp_match( movq, 0,(%esi), %mm0,        `0x0f,0x6f,0x46,0x00',      $@)`'dnl
Packit 5c3484
Zdisp_match( movq, %mm0, 0,(%edi),        `0x0f,0x7f,0x47,0x00',      $@)`'dnl
Packit 5c3484
Zdisp_match( movq, %mm2, 0,(%ecx,%eax,4), `0x0f,0x7f,0x54,0x81,0x00', $@)`'dnl
Packit 5c3484
Zdisp_match( movq, %mm2, 0,(%edx,%eax,4), `0x0f,0x7f,0x54,0x82,0x00', $@)`'dnl
Packit 5c3484
Zdisp_match( movq, %mm0, 0,(%edx,%ecx,8), `0x0f,0x7f,0x44,0xca,0x00', $@)`'dnl
Packit 5c3484
')
Packit 5c3484
define(Zdisp_4,`dnl
Packit 5c3484
Zdisp_match( movd, 0,(%eax,%ecx,4), %mm0, `0x0f,0x6e,0x44,0x88,0x00', $@)`'dnl
Packit 5c3484
Zdisp_match( movd, 0,(%eax,%ecx,8), %mm1, `0x0f,0x6e,0x4c,0xc8,0x00', $@)`'dnl
Packit 5c3484
Zdisp_match( movd, 0,(%edx,%ecx,8), %mm0, `0x0f,0x6e,0x44,0xca,0x00', $@)`'dnl
Packit 5c3484
Zdisp_match( movd, %mm0, 0,(%eax,%ecx,4), `0x0f,0x7e,0x44,0x88,0x00', $@)`'dnl
Packit 5c3484
Zdisp_match( movd, %mm0, 0,(%ecx,%eax,4), `0x0f,0x7e,0x44,0x81,0x00', $@)`'dnl
Packit 5c3484
Zdisp_match( movd, %mm2, 0,(%ecx,%eax,4), `0x0f,0x7e,0x54,0x81,0x00', $@)`'dnl
Packit 5c3484
Zdisp_match( movd, %mm0, 0,(%edx,%ecx,4), `0x0f,0x7e,0x44,0x8a,0x00', $@)`'dnl
Packit 5c3484
')
Packit 5c3484
Packit 5c3484
define(Zdisp_match,
Packit 5c3484
m4_assert_numargs(9)
Packit 5c3484
`ifelse(eval(m4_stringequal_p(`$1',`$6')
Packit 5c3484
	&& m4_stringequal_p(`$2',0)
Packit 5c3484
	&& m4_stringequal_p(`$3',`$8')
Packit 5c3484
	&& m4_stringequal_p(`$4',`$9')),1,
Packit 5c3484
`define(`Zdisp_found',1)dnl
Packit 5c3484
ifelse(eval(`$7'),0,
Packit 5c3484
`	.byte	$5  C `$1 0$3, $4'',
Packit 5c3484
`	$6	$7$8, $9')',
Packit 5c3484
Packit 5c3484
`ifelse(eval(m4_stringequal_p(`$1',`$6')
Packit 5c3484
	&& m4_stringequal_p(`$2',`$7')
Packit 5c3484
	&& m4_stringequal_p(`$3',0)
Packit 5c3484
	&& m4_stringequal_p(`$4',`$9')),1,
Packit 5c3484
`define(`Zdisp_found',1)dnl
Packit 5c3484
ifelse(eval(`$8'),0,
Packit 5c3484
`	.byte	$5  C `$1 $2, 0$4'',
Packit 5c3484
`	$6	$7, $8$9')')')')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: shldl(count,src,dst)
Packit 5c3484
dnl         shrdl(count,src,dst)
Packit 5c3484
dnl         shldw(count,src,dst)
Packit 5c3484
dnl         shrdw(count,src,dst)
Packit 5c3484
dnl
Packit 5c3484
dnl  Generate a double-shift instruction, possibly omitting a %cl count
Packit 5c3484
dnl  parameter if that's what the assembler requires, as indicated by
Packit 5c3484
dnl  WANT_SHLDL_CL in config.m4.  For example,
Packit 5c3484
dnl
Packit 5c3484
dnl         shldl(  %cl, %eax, %ebx)
Packit 5c3484
dnl
Packit 5c3484
dnl  turns into either
Packit 5c3484
dnl
Packit 5c3484
dnl         shldl   %cl, %eax, %ebx
Packit 5c3484
dnl  or
Packit 5c3484
dnl         shldl   %eax, %ebx
Packit 5c3484
dnl
Packit 5c3484
dnl  Immediate counts are always passed through unchanged.  For example,
Packit 5c3484
dnl
Packit 5c3484
dnl         shrdl(  $2, %esi, %edi)
Packit 5c3484
dnl  becomes
Packit 5c3484
dnl         shrdl   $2, %esi, %edi
Packit 5c3484
dnl
Packit 5c3484
dnl
Packit 5c3484
dnl  If you forget to use the macro form "shldl( ...)" and instead write
Packit 5c3484
dnl  just a plain "shldl ...", an error results.  This ensures the necessary
Packit 5c3484
dnl  variant treatment of %cl isn't accidentally bypassed.
Packit 5c3484
Packit 5c3484
define(define_shd_instruction,
Packit 5c3484
m4_assert_numargs(1)
Packit 5c3484
`define($1,
Packit 5c3484
m4_instruction_wrapper()
Packit 5c3484
m4_assert_numargs(3)
Packit 5c3484
`shd_instruction'(m4_doublequote($`'0),m4_doublequote($`'1),dnl
Packit 5c3484
m4_doublequote($`'2),m4_doublequote($`'3)))')
Packit 5c3484
Packit 5c3484
dnl  Effectively: define(shldl,`shd_instruction(`$0',`$1',`$2',`$3')') etc
Packit 5c3484
define_shd_instruction(shldl)
Packit 5c3484
define_shd_instruction(shrdl)
Packit 5c3484
define_shd_instruction(shldw)
Packit 5c3484
define_shd_instruction(shrdw)
Packit 5c3484
Packit 5c3484
dnl  Called: shd_instruction(op,count,src,dst)
Packit 5c3484
define(shd_instruction,
Packit 5c3484
m4_assert_numargs(4)
Packit 5c3484
m4_assert_defined(`WANT_SHLDL_CL')
Packit 5c3484
`ifelse(eval(m4_stringequal_p(`$2',`%cl') && !WANT_SHLDL_CL),1,
Packit 5c3484
``$1'	`$3', `$4'',
Packit 5c3484
``$1'	`$2', `$3', `$4'')')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: ASSERT([cond][,instructions])
Packit 5c3484
dnl
Packit 5c3484
dnl  If WANT_ASSERT is 1, output the given instructions and expect the given
Packit 5c3484
dnl  flags condition to then be satisfied.  For example,
Packit 5c3484
dnl
Packit 5c3484
dnl         ASSERT(ne, `cmpl %eax, %ebx')
Packit 5c3484
dnl
Packit 5c3484
dnl  The instructions can be omitted to just assert a flags condition with
Packit 5c3484
dnl  no extra calculation.  For example,
Packit 5c3484
dnl
Packit 5c3484
dnl         ASSERT(nc)
Packit 5c3484
dnl
Packit 5c3484
dnl  When `instructions' is not empty, a pushf/popf is added to preserve the
Packit 5c3484
dnl  flags, but the instructions themselves must preserve any registers that
Packit 5c3484
dnl  matter.  FRAME is adjusted for the push and pop, so the instructions
Packit 5c3484
dnl  given can use defframe() stack variables.
Packit 5c3484
dnl
Packit 5c3484
dnl  The condition can be omitted to just output the given instructions when
Packit 5c3484
dnl  assertion checking is wanted.  In this case the pushf/popf is omitted.
Packit 5c3484
dnl  For example,
Packit 5c3484
dnl
Packit 5c3484
dnl         ASSERT(, `movl %eax, VAR_KEEPVAL')
Packit 5c3484
Packit 5c3484
define(ASSERT,
Packit 5c3484
m4_assert_numargs_range(1,2)
Packit 5c3484
m4_assert_defined(`WANT_ASSERT')
Packit 5c3484
`ifelse(WANT_ASSERT,1,
Packit 5c3484
`ifelse(`$1',,
Packit 5c3484
	`$2',
Packit 5c3484
	`C ASSERT
Packit 5c3484
ifelse(`$2',,,`	pushf	ifdef(`FRAME',`FRAME_pushl()')')
Packit 5c3484
	$2
Packit 5c3484
	j`$1'	L(ASSERT_ok`'ASSERT_counter)
Packit 5c3484
	ud2	C assertion failed
Packit 5c3484
L(ASSERT_ok`'ASSERT_counter):
Packit 5c3484
ifelse(`$2',,,`	popf	ifdef(`FRAME',`FRAME_popl()')')
Packit 5c3484
define(`ASSERT_counter',incr(ASSERT_counter))')')')
Packit 5c3484
Packit 5c3484
define(ASSERT_counter,1)
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: movl_text_address(label,register)
Packit 5c3484
dnl
Packit 5c3484
dnl  Get the address of a text segment label, using either a plain movl or a
Packit 5c3484
dnl  position-independent calculation, as necessary.  For example,
Packit 5c3484
dnl
Packit 5c3484
dnl         movl_code_address(L(foo),%eax)
Packit 5c3484
dnl
Packit 5c3484
dnl  This macro is only meant for use in ASSERT()s or when testing, since
Packit 5c3484
dnl  the PIC sequence it generates will want to be done with a ret balancing
Packit 5c3484
dnl  the call on CPUs with return address branch prediction.
Packit 5c3484
dnl
Packit 5c3484
dnl  The addl generated here has a backward reference to the label, and so
Packit 5c3484
dnl  won't suffer from the two forwards references bug in old gas (described
Packit 5c3484
dnl  in mpn/x86/README).
Packit 5c3484
Packit 5c3484
define(movl_text_address,
Packit 5c3484
m4_assert_numargs(2)
Packit 5c3484
`ifdef(`PIC',
Packit 5c3484
	`call	L(movl_text_address_`'movl_text_address_counter)
Packit 5c3484
L(movl_text_address_`'movl_text_address_counter):
Packit 5c3484
	popl	$2	C %eip
Packit 5c3484
	addl	`$'$1-L(movl_text_address_`'movl_text_address_counter), $2
Packit 5c3484
define(`movl_text_address_counter',incr(movl_text_address_counter))',
Packit 5c3484
	`movl	`$'$1, $2')')
Packit 5c3484
Packit 5c3484
define(movl_text_address_counter,1)
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: notl_or_xorl_GMP_NUMB_MASK(reg)
Packit 5c3484
dnl
Packit 5c3484
dnl  Expand to either "notl `reg'" or "xorl $GMP_NUMB_BITS,`reg'" as
Packit 5c3484
dnl  appropriate for nails in use or not.
Packit 5c3484
Packit 5c3484
define(notl_or_xorl_GMP_NUMB_MASK,
Packit 5c3484
m4_assert_numargs(1)
Packit 5c3484
`ifelse(GMP_NAIL_BITS,0,
Packit 5c3484
`notl	`$1'',
Packit 5c3484
`xorl	$GMP_NUMB_MASK, `$1'')')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage LEA(symbol,reg)
Packit 5c3484
dnl  Usage LEAL(symbol_local_to_file,reg)
Packit 5c3484
Packit 5c3484
define(`LEA',
Packit 5c3484
m4_assert_numargs(2)
Packit 5c3484
`ifdef(`PIC',`dnl
Packit 5c3484
ifelse(index(defn(`load_eip'), `$2'),-1,
Packit 5c3484
`m4append(`load_eip',
Packit 5c3484
`	TEXT
Packit 5c3484
	ALIGN(16)
Packit 5c3484
L(movl_eip_`'substr($2,1)):
Packit 5c3484
	movl	(%esp), $2
Packit 5c3484
	ret_internal
Packit 5c3484
')')dnl
Packit 5c3484
	call	L(movl_eip_`'substr($2,1))
Packit 5c3484
	addl	$_GLOBAL_OFFSET_TABLE_, $2
Packit 5c3484
	movl	$1@GOT($2), $2
Packit 5c3484
',`
Packit 5c3484
	movl	`$'$1, $2
Packit 5c3484
')')
Packit 5c3484
Packit 5c3484
define(`LEAL',
Packit 5c3484
m4_assert_numargs(2)
Packit 5c3484
`ifdef(`PIC',`dnl
Packit 5c3484
ifelse(index(defn(`load_eip'), `$2'),-1,
Packit 5c3484
`m4append(`load_eip',
Packit 5c3484
`	TEXT
Packit 5c3484
	ALIGN(16)
Packit 5c3484
L(movl_eip_`'substr($2,1)):
Packit 5c3484
	movl	(%esp), $2
Packit 5c3484
	ret_internal
Packit 5c3484
')')dnl
Packit 5c3484
	call	L(movl_eip_`'substr($2,1))
Packit 5c3484
	addl	$_GLOBAL_OFFSET_TABLE_, $2
Packit 5c3484
	leal	$1@GOTOFF($2), $2
Packit 5c3484
',`
Packit 5c3484
	movl	`$'$1, $2
Packit 5c3484
')')
Packit 5c3484
Packit 5c3484
dnl ASM_END
Packit 5c3484
Packit 5c3484
define(`ASM_END',`load_eip')
Packit 5c3484
Packit 5c3484
define(`load_eip', `')		dnl updated in LEA/LEAL
Packit 5c3484
Packit 5c3484
Packit 5c3484
define(`DEF_OBJECT',
Packit 5c3484
m4_assert_numargs_range(1,2)
Packit 5c3484
	`RODATA
Packit 5c3484
	ALIGN(ifelse($#,1,2,$2))
Packit 5c3484
$1:
Packit 5c3484
')
Packit 5c3484
Packit 5c3484
define(`END_OBJECT',
Packit 5c3484
m4_assert_numargs(1)
Packit 5c3484
`	SIZE(`$1',.-`$1')')
Packit 5c3484
Packit 5c3484
dnl  Usage: CALL(funcname)
Packit 5c3484
dnl
Packit 5c3484
Packit 5c3484
define(`CALL',
Packit 5c3484
m4_assert_numargs(1)
Packit 5c3484
`ifdef(`PIC',
Packit 5c3484
  `call	GSYM_PREFIX`'$1@PLT',
Packit 5c3484
  `call	GSYM_PREFIX`'$1')')
Packit 5c3484
Packit 5c3484
ifdef(`PIC',
Packit 5c3484
`define(`PIC_WITH_EBX')',
Packit 5c3484
`undefine(`PIC_WITH_EBX')')
Packit 5c3484
Packit 5c3484
divert`'dnl