Blame sysdeps/alpha/div_libc.h

Packit 6c4009
/* Copyright (C) 2004-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library.  If not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
/* Common bits for implementing software divide.  */
Packit 6c4009
Packit 6c4009
#include <sysdep.h>
Packit 6c4009
#ifdef __linux__
Packit 6c4009
# include <asm/gentrap.h>
Packit 6c4009
# include <asm/pal.h>
Packit 6c4009
#else
Packit 6c4009
# include <machine/pal.h>
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
/* These are not normal C functions.  Argument registers are t10 and t11;
Packit 6c4009
   the result goes in t12; the return address is in t9.  Only t12 and AT
Packit 6c4009
   may be clobbered.  */
Packit 6c4009
#define X	t10
Packit 6c4009
#define Y	t11
Packit 6c4009
#define RV	t12
Packit 6c4009
#define RA	t9
Packit 6c4009
Packit 6c4009
/* The secureplt format does not allow the division routines to be called
Packit 6c4009
   via plt; there aren't enough registers free to be clobbered.  Avoid
Packit 6c4009
   setting the symbol type to STT_FUNC, so that the linker won't be tempted
Packit 6c4009
   to create a plt entry.  */
Packit 6c4009
#define funcnoplt notype
Packit 6c4009
Packit 6c4009
/* None of these functions should use implicit anything.  */
Packit 6c4009
	.set	nomacro
Packit 6c4009
	.set	noat
Packit 6c4009
Packit 6c4009
/* Code fragment to invoke _mcount for profiling.  This should be invoked
Packit 6c4009
   directly after allocation of the stack frame.  */
Packit 6c4009
.macro CALL_MCOUNT
Packit 6c4009
#ifdef PROF
Packit 6c4009
	stq	ra, 0(sp)
Packit 6c4009
	stq	pv, 8(sp)
Packit 6c4009
	stq	gp, 16(sp)
Packit 6c4009
	cfi_rel_offset (ra, 0)
Packit 6c4009
	cfi_rel_offset (pv, 8)
Packit 6c4009
	cfi_rel_offset (gp, 16)
Packit 6c4009
	br	AT, 1f
Packit 6c4009
	.set	macro
Packit 6c4009
1:	ldgp	gp, 0(AT)
Packit 6c4009
	mov	RA, ra
Packit 6c4009
	lda	AT, _mcount
Packit 6c4009
	jsr	AT, (AT), _mcount
Packit 6c4009
	.set	nomacro
Packit 6c4009
	ldq	ra, 0(sp)
Packit 6c4009
	ldq	pv, 8(sp)
Packit 6c4009
	ldq	gp, 16(sp)
Packit 6c4009
	cfi_restore (ra)
Packit 6c4009
	cfi_restore (pv)
Packit 6c4009
	cfi_restore (gp)
Packit 6c4009
	/* Realign subsequent code with what we'd have without this
Packit 6c4009
	   macro at all.  This means aligned with one arithmetic insn
Packit 6c4009
	   used within the bundle.  */
Packit 6c4009
	.align	4
Packit 6c4009
	nop
Packit 6c4009
#endif
Packit 6c4009
.endm
Packit 6c4009
Packit 6c4009
/* In order to make the below work, all top-level divide routines must
Packit 6c4009
   use the same frame size.  */
Packit 6c4009
#define FRAME	64
Packit 6c4009
Packit 6c4009
/* Code fragment to generate an integer divide-by-zero fault.  When
Packit 6c4009
   building libc.so, we arrange for there to be one copy of this code
Packit 6c4009
   placed late in the dso, such that all branches are forward.  When
Packit 6c4009
   building libc.a, we use multiple copies to avoid having an out of
Packit 6c4009
   range branch.  Users should jump to DIVBYZERO.  */
Packit 6c4009
Packit 6c4009
.macro DO_DIVBYZERO
Packit 6c4009
#ifdef PIC
Packit 6c4009
#define DIVBYZERO	__divbyzero
Packit 6c4009
	.section .gnu.linkonce.t.divbyzero, "ax", @progbits
Packit 6c4009
	.globl	__divbyzero
Packit 6c4009
	.type	__divbyzero, @function
Packit 6c4009
	.usepv	__divbyzero, no
Packit 6c4009
	.hidden	__divbyzero
Packit 6c4009
#else
Packit 6c4009
#define DIVBYZERO	$divbyzero
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
	.align	4
Packit 6c4009
DIVBYZERO:
Packit 6c4009
	cfi_startproc
Packit 6c4009
	cfi_return_column (RA)
Packit 6c4009
	cfi_def_cfa_offset (FRAME)
Packit 6c4009
Packit 6c4009
	mov	a0, RV
Packit 6c4009
	unop
Packit 6c4009
	lda	a0, GEN_INTDIV
Packit 6c4009
	call_pal PAL_gentrap
Packit 6c4009
Packit 6c4009
	mov	RV, a0
Packit 6c4009
	clr	RV
Packit 6c4009
	lda	sp, FRAME(sp)
Packit 6c4009
	cfi_def_cfa_offset (0)
Packit 6c4009
	ret	$31, (RA), 1
Packit 6c4009
Packit 6c4009
	cfi_endproc
Packit 6c4009
	.size	DIVBYZERO, .-DIVBYZERO
Packit 6c4009
.endm
Packit 6c4009
Packit 6c4009
/* Like the ev6 instructions, but fall back to stack use on prior machines.  */
Packit 6c4009
Packit 6c4009
	.arch	ev6
Packit 6c4009
Packit 6c4009
.macro _ITOFS  gr, fr, slot
Packit 6c4009
#ifdef __alpha_fix__
Packit 6c4009
	itofs	\gr, \fr
Packit 6c4009
#else
Packit 6c4009
	stl	\gr, \slot(sp)
Packit 6c4009
	lds	\fr, \slot(sp)
Packit 6c4009
#endif
Packit 6c4009
.endm
Packit 6c4009
Packit 6c4009
.macro _ITOFT  gr, fr, slot
Packit 6c4009
#ifdef __alpha_fix__
Packit 6c4009
	itoft	\gr, \fr
Packit 6c4009
#else
Packit 6c4009
	stq	\gr, \slot(sp)
Packit 6c4009
	ldt	\fr, \slot(sp)
Packit 6c4009
#endif
Packit 6c4009
.endm
Packit 6c4009
Packit 6c4009
.macro _FTOIT  fr, gr, slot
Packit 6c4009
#ifdef __alpha_fix__
Packit 6c4009
	ftoit	\fr, \gr
Packit 6c4009
#else
Packit 6c4009
	stt	\fr, \slot(sp)
Packit 6c4009
	ldq	\gr, \slot(sp)
Packit 6c4009
#endif
Packit 6c4009
.endm
Packit 6c4009
Packit 6c4009
/* Similarly, but move two registers.  Schedules better for pre-ev6.  */
Packit 6c4009
Packit 6c4009
.macro _ITOFT2 gr1, fr1, slot1, gr2, fr2, slot2
Packit 6c4009
#ifdef __alpha_fix__
Packit 6c4009
	itoft	\gr1, \fr1
Packit 6c4009
	itoft	\gr2, \fr2
Packit 6c4009
#else
Packit 6c4009
	stq	\gr1, \slot1(sp)
Packit 6c4009
	stq	\gr2, \slot2(sp)
Packit 6c4009
	ldt	\fr1, \slot1(sp)
Packit 6c4009
	ldt	\fr2, \slot2(sp)
Packit 6c4009
#endif
Packit 6c4009
.endm