Blame mpn/x86_64/x86_64-defs.m4

Packit 5c3484
divert(-1)
Packit 5c3484
Packit 5c3484
dnl  m4 macros for amd64 assembler.
Packit 5c3484
Packit 5c3484
dnl  Copyright 1999-2005, 2008, 2009, 2011-2013 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  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 amd64 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
`	GLOBL	$1
Packit 5c3484
	TYPE($1,`function')
Packit 5c3484
$1:
rpm-build c3cd4f
	CFPROT_ENDBR
Packit 5c3484
')
Packit 5c3484
rpm-build c3cd4f
dnl Generates the endbr64 instructions
rpm-build c3cd4f
dnl Using macro, so it can be easily extended to use some arch specific conditional defines
rpm-build c3cd4f
define(`CFPROT_ENDBR',
rpm-build c3cd4f
``
rpm-build c3cd4f
	endbr64''
rpm-build c3cd4f
)
rpm-build c3cd4f
rpm-build c3cd4f
dnl Append the .gnu-property to the end of files
rpm-build c3cd4f
dnl This is needed for a -fcf-protection 
rpm-build c3cd4f
dnl Again, using macro for easy arch specific defines
rpm-build c3cd4f
dnl
rpm-build c3cd4f
define(`CF_PROT',``
rpm-build c3cd4f
	.section	.note.gnu.property,"a"
rpm-build c3cd4f
	.align 8
rpm-build c3cd4f
	.long	 1f - 0f
rpm-build c3cd4f
	.long	 4f - 1f
rpm-build c3cd4f
	.long	 5
rpm-build c3cd4f
0:
rpm-build c3cd4f
	.string	 "GNU"
rpm-build c3cd4f
1:
rpm-build c3cd4f
	.align 8
rpm-build c3cd4f
	.long	 0xc0000002
rpm-build c3cd4f
	.long	 3f - 2f
rpm-build c3cd4f
2:
rpm-build c3cd4f
	.long	 0x3
rpm-build c3cd4f
3:
rpm-build c3cd4f
 	.align 8
rpm-build c3cd4f
4:
rpm-build c3cd4f
'')
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, `cmpq %rax, %rbx')
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 pushfq/popfq is added for
Packit 5c3484
dnl  convenience to preserve the flags, but the instructions themselves must
Packit 5c3484
dnl  preserve any registers that matter.
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(, `movq %rax, 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
`ifelse(`$2',,,
Packit 5c3484
`	pushfq')
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',,,`	popfq')
Packit 5c3484
define(`ASSERT_counter',incr(ASSERT_counter))')')')
Packit 5c3484
Packit 5c3484
define(ASSERT_counter,1)
Packit 5c3484
Packit 5c3484
define(`LEA',`dnl
Packit 5c3484
ifdef(`PIC',
Packit 5c3484
	`mov	$1@GOTPCREL(%rip), $2'
Packit 5c3484
,
Packit 5c3484
	`movabs	`$'$1, $2')
Packit 5c3484
')
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
Packit 5c3484
define(`R32',
Packit 5c3484
	`ifelse($1,`%rax',`%eax',
Packit 5c3484
		$1,`%rbx',`%ebx',
Packit 5c3484
		$1,`%rcx',`%ecx',
Packit 5c3484
		$1,`%rdx',`%edx',
Packit 5c3484
		$1,`%rsi',`%esi',
Packit 5c3484
		$1,`%rdi',`%edi',
Packit 5c3484
		$1,`%rbp',`%ebp',
Packit 5c3484
		$1,`%r8',`%r8d',
Packit 5c3484
		$1,`%r9',`%r9d',
Packit 5c3484
		$1,`%r10',`%r10d',
Packit 5c3484
		$1,`%r11',`%r11d',
Packit 5c3484
		$1,`%r12',`%r12d',
Packit 5c3484
		$1,`%r13',`%r13d',
Packit 5c3484
		$1,`%r14',`%r14d',
Packit 5c3484
		$1,`%r15',`%r15d')')
Packit 5c3484
define(`R8',
Packit 5c3484
	`ifelse($1,`%rax',`%al',
Packit 5c3484
		$1,`%rbx',`%bl',
Packit 5c3484
		$1,`%rcx',`%cl',
Packit 5c3484
		$1,`%rdx',`%dl',
Packit 5c3484
		$1,`%rsi',`%sil',
Packit 5c3484
		$1,`%rdi',`%dil',
Packit 5c3484
		$1,`%rbp',`%bpl',
Packit 5c3484
		$1,`%r8',`%r8b',
Packit 5c3484
		$1,`%r9',`%r9b',
Packit 5c3484
		$1,`%r10',`%r10b',
Packit 5c3484
		$1,`%r11',`%r11b',
Packit 5c3484
		$1,`%r12',`%r12b',
Packit 5c3484
		$1,`%r13',`%r13b',
Packit 5c3484
		$1,`%r14',`%r14b',
Packit 5c3484
		$1,`%r15',`%r15b')')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: CALL(funcname)
Packit 5c3484
dnl
Packit 5c3484
Packit 5c3484
define(`CALL',`dnl
Packit 5c3484
ifdef(`PIC',
Packit 5c3484
	`call	GSYM_PREFIX`'$1@PLT'
Packit 5c3484
,
Packit 5c3484
	`call	GSYM_PREFIX`'$1'
Packit 5c3484
)')
Packit 5c3484
Packit 5c3484
Packit 5c3484
define(`JUMPTABSECT', `.section	.data.rel.ro.local,"aw",@progbits')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: JMPENT(targlabel,tablabel)
Packit 5c3484
Packit 5c3484
define(`JMPENT',`dnl
Packit 5c3484
ifdef(`PIC',
Packit 5c3484
	`.long	$1-$2'dnl
Packit 5c3484
,
Packit 5c3484
	`.quad	$1'dnl
Packit 5c3484
)')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  These macros are defined just for DOS64, where they provide calling
Packit 5c3484
dnl  sequence glue code.
Packit 5c3484
Packit 5c3484
define(`FUNC_ENTRY',`')
Packit 5c3484
define(`FUNC_EXIT',`')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Target ABI macros.
Packit 5c3484
Packit 5c3484
define(`IFDOS',   `')
Packit 5c3484
define(`IFSTD',   `$1')
Packit 5c3484
define(`IFELF',   `$1')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: PROTECT(symbol)
Packit 5c3484
dnl
Packit 5c3484
dnl  Used for private GMP symbols that should never be overridden by users.
Packit 5c3484
dnl  This can save reloc entries and improve shlib sharing as well as
Packit 5c3484
dnl  application startup times
Packit 5c3484
Packit 5c3484
define(`PROTECT',  `.hidden $1')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage: x86_lookup(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
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
Packit 5c3484
dnl  Usage: x86_opcode_regxmm(reg)
Packit 5c3484
dnl
Packit 5c3484
dnl  Validate the given xmm register, and return its number, 0 to 7.
Packit 5c3484
Packit 5c3484
define(x86_opcode_regxmm,
Packit 5c3484
m4_assert_numargs(1)
Packit 5c3484
`x86_lookup(`$1',x86_opcode_regxmm_list)')
Packit 5c3484
Packit 5c3484
define(x86_opcode_regxmm_list,
Packit 5c3484
``%xmm0',0,
Packit 5c3484
`%xmm1',1,
Packit 5c3484
`%xmm2',2,
Packit 5c3484
`%xmm3',3,
Packit 5c3484
`%xmm4',4,
Packit 5c3484
`%xmm5',5,
Packit 5c3484
`%xmm6',6,
Packit 5c3484
`%xmm7',7,
Packit 5c3484
`%xmm8',8,
Packit 5c3484
`%xmm9',9,
Packit 5c3484
`%xmm10',10,
Packit 5c3484
`%xmm11',11,
Packit 5c3484
`%xmm12',12,
Packit 5c3484
`%xmm13',13,
Packit 5c3484
`%xmm14',14,
Packit 5c3484
`%xmm15',15')
Packit 5c3484
Packit 5c3484
dnl  Usage: palignr($imm,%srcreg,%dstreg)
Packit 5c3484
dnl
Packit 5c3484
dnl  Emit a palignr instruction, using a .byte sequence, since obsolete but
Packit 5c3484
dnl  still distributed versions of gas don't know SSSE3 instructions.
Packit 5c3484
Packit 5c3484
define(`palignr',
Packit 5c3484
m4_assert_numargs(3)
Packit 5c3484
`.byte	0x66,dnl
Packit 5c3484
ifelse(eval(x86_opcode_regxmm($3) >= 8 || x86_opcode_regxmm($2) >= 8),1,
Packit 5c3484
       `eval(0x40+x86_opcode_regxmm($3)/8*4+x86_opcode_regxmm($2)/8),')dnl
Packit 5c3484
0x0f,0x3a,0x0f,dnl
Packit 5c3484
eval(0xc0+x86_opcode_regxmm($3)%8*8+x86_opcode_regxmm($2)%8),dnl
Packit 5c3484
substr($1,1)')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage
Packit 5c3484
dnl
Packit 5c3484
dnl    regnum(op)   raw operand index (so slightly misnamed)
Packit 5c3484
dnl    regnumh(op)  high bit of register operand nimber
Packit 5c3484
dnl    ix(op)       0 for reg operand, 1 for plain pointer operand.
Packit 5c3484
dnl
Packit 5c3484
Packit 5c3484
define(`regnum',`x86_lookup(`$1',oplist)')
Packit 5c3484
define(`regnumh',`eval(regnum($1)/8 & 1)')
Packit 5c3484
define(`ix',`eval(regnum($1)/16)')
Packit 5c3484
define(`oplist',
Packit 5c3484
``%rax',   0, `%rcx',   1, `%rdx',   2,  `%rbx',   3,
Packit 5c3484
 `%rsp',   4, `%rbp',   5, `%rsi',   6,  `%rdi',   7,
Packit 5c3484
 `%r8',    8, `%r9',    9, `%r10',  10,  `%r11',  11,
Packit 5c3484
 `%r12',  12, `%r13',  13, `%r14',  14,  `%r15',  15,
Packit 5c3484
 `(%rax)',16, `(%rcx)',17, `(%rdx)',18,  `(%rbx)',19,
Packit 5c3484
 `(%rsp)',20, `(%rbp)',21, `(%rsi)',22,  `(%rdi)',23,
Packit 5c3484
 `(%r8)', 24, `(%r9)', 25, `(%r10)',26,  `(%r11)',27,
Packit 5c3484
 `(%r12)',28, `(%r13)',29, `(%r14)',30,  `(%r15)',31')
Packit 5c3484
Packit 5c3484
Packit 5c3484
dnl  Usage
Packit 5c3484
dnl
Packit 5c3484
dnl     mulx(reg1,reg2,reg3)
Packit 5c3484
dnl
Packit 5c3484
dnl  or
Packit 5c3484
dnl
Packit 5c3484
dnl     mulx((reg1),reg2,reg3)
Packit 5c3484
dnl
Packit 5c3484
dnl  where reg1 is any register but rsp,rbp,r12,r13, or
Packit 5c3484
dnl
Packit 5c3484
dnl     mulx(off,(reg1),reg2,reg3)
Packit 5c3484
dnl
Packit 5c3484
dnl  where reg1 is any register but rsp,r12.
Packit 5c3484
dnl
Packit 5c3484
dnl  The exceptions are due to special coding needed for some registers; rsp
Packit 5c3484
dnl  and r12 need an extra byte 0x24 at the end while rbp and r13 lack the
Packit 5c3484
dnl  offset-less form.
Packit 5c3484
dnl
Packit 5c3484
dnl  Other addressing forms are not handled.  Invalid forms are not properly
Packit 5c3484
dnl  detected.  Offsets that don't fit one byte are not handled correctly.
Packit 5c3484
Packit 5c3484
define(`mulx',`dnl
Packit 5c3484
.byte	0xc4`'dnl
Packit 5c3484
ifelse(`$#',3,`dnl
Packit 5c3484
,eval(0xe2^32*regnumh($1)^128*regnumh($3))`'dnl
Packit 5c3484
,eval(0xfb-8*regnum($2))`'dnl
Packit 5c3484
,0xf6`'dnl
Packit 5c3484
,eval(0xc0+(7 & regnum($1))+8*(7 & regnum($3))-0xc0*ix($1))`'dnl
Packit 5c3484
',`$#',4,`dnl
Packit 5c3484
,eval(0xe2^32*regnumh($2)^128*regnumh($4))`'dnl
Packit 5c3484
,eval(0xfb-8*regnum($3))`'dnl
Packit 5c3484
,0xf6`'dnl
Packit 5c3484
,eval(0x40+(7 & regnum($2))+8*(7 & regnum($4)))`'dnl
Packit 5c3484
,eval(($1 + 256) % 256)`'dnl
Packit 5c3484
')')
Packit 5c3484
Packit 5c3484
dnl  Usage
Packit 5c3484
dnl
Packit 5c3484
dnl     adcx(reg1,reg2)
Packit 5c3484
dnl     adox(reg1,reg2)
Packit 5c3484
dnl
Packit 5c3484
dnl  or
Packit 5c3484
dnl
Packit 5c3484
dnl     adcx((reg1),reg2)
Packit 5c3484
dnl     adox((reg1),reg2)
Packit 5c3484
dnl
Packit 5c3484
dnl  where reg1 is any register but rsp,rbp,r12,r13, or
Packit 5c3484
dnl
Packit 5c3484
dnl     adcx(off,(reg1),reg2)
Packit 5c3484
dnl     adox(off,(reg1),reg2)
Packit 5c3484
dnl
Packit 5c3484
dnl  where reg1 is any register but rsp,r12.
Packit 5c3484
dnl
Packit 5c3484
dnl  The exceptions are due to special coding needed for some registers; rsp
Packit 5c3484
dnl  and r12 need an extra byte 0x24 at the end while rbp and r13 lack the
Packit 5c3484
dnl  offset-less form.
Packit 5c3484
dnl
Packit 5c3484
dnl  Other addressing forms are not handled.  Invalid forms are not properly
Packit 5c3484
dnl  detected.  Offsets that don't fit one byte are not handled correctly.
Packit 5c3484
Packit 5c3484
define(`adx_helper',`dnl
Packit 5c3484
,eval(0x48+regnumh($1)+4*regnumh($2))`'dnl
Packit 5c3484
,0x0f`'dnl
Packit 5c3484
,0x38`'dnl
Packit 5c3484
,0xf6`'dnl
Packit 5c3484
')
Packit 5c3484
Packit 5c3484
define(`adx',`dnl
Packit 5c3484
ifelse(`$#',2,`dnl
Packit 5c3484
adx_helper($1,$2)dnl
Packit 5c3484
,eval(0xc0+(7 & regnum($1))+8*(7 & regnum($2))-0xc0*ix($1))`'dnl
Packit 5c3484
',`$#',3,`dnl
Packit 5c3484
adx_helper($2,$3)dnl
Packit 5c3484
,eval(0x40+(7 & regnum($2))+8*(7 & regnum($3)))`'dnl
Packit 5c3484
,eval(($1 + 256) % 256)`'dnl
Packit 5c3484
')')
Packit 5c3484
Packit 5c3484
define(`adcx',`dnl
Packit 5c3484
.byte	0x66`'dnl
Packit 5c3484
adx($@)')
Packit 5c3484
Packit 5c3484
define(`adox',`dnl
Packit 5c3484
.byte	0xf3`'dnl
Packit 5c3484
adx($@)')
Packit 5c3484
Packit 5c3484
divert`'dnl