Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / legion / src / procs / sunsparc / common / fpsim_support.s
/*
* ========== Copyright Header Begin ==========================================
*
* OpenSPARC T2 Processor File: fpsim_support.s
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
*
* The above named program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License version 2 as published by the Free Software Foundation.
*
* The above named program is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*
* ========== Copyright Header End ============================================
*/
/*==========================================================================*
*
* fpsim_support.s : assembly language routines used by FPSIM libraries.
*
* Author: Robert Rethemeyer
*
* (c) Copyright 2006 Sun Microsystems, Inc.
*
* Design:
* This is a collection of functions that explicitly invoke the various
* SPARC floating-point instructions, using a supplied rounding mode,
* and returning the exception bits extracted from %fsr.cexc.
* Each routine is essentially a wrapper around the FP instruction.
*
* Why do this in assembly and not C? One or more of the following reasons:
* 1. No way to do it except using library calls (e.g. fiddling with %fsr)
* 2. C does not provide an easy way to do it (e.g. add & get carry)
* 3. The compiler may substitute its own code to satisfy the C standard
* 4. The compiler does not generate the intended code (e.g. for "D=S*S",
* it will generate FMULS followed by FSTOD, instead of FSMULD.
*
* These are all leaf subroutines that may use/trash registers:
* %o0-%o5, %f0-%f3, %g1
* Exception bits are returned in %o0
* FP result is returned by Store using result pointer parameter.
*
* $Id: fpsim_support.s,v 1.5 2006/12/07 20:52:05 bobsmail Exp $
*
*==========================================================================*/
/*********************************************************************
* ATTENTION: This code is part of a library shared by multiple
* projects. DO NOT MAKE CHANGES TO THIS CODE WITHIN YOUR PROJECT.
* Instead, contact the owner/maintainer of the library, currently:
* Robert.Rethemeyer@Sun.COM +1-408-616-5717 (x45717)
* Systems Group: TVT: FrontEnd Technologies
* The CVS source code repository for the library is at:
* /import/ftap-blimp1/cvs/fpsim
* DO NOT COMMIT CHANGES TO THAT REPOSITORY: contact the maintainer.
********************************************************************/
#define FUNCTION(FNAME) .global FNAME; .type FNAME,#function; FNAME:
#define ENDFUNC(FNAME) .size FNAME,.-FNAME
/* SET_ROUNDING:
1. save current FSR in caller-provided temp area (2 words)
2. mask off TEM, NS, CEXC bits
3. insert caller's rounding mode bits
4. load new FSR
5. save current GSR in g1
6. clear GSR
*/
#define SET_ROUNDING(ROUND,TEMPFSR) \
st %fsr, [TEMPFSR+0]; \
lduw [TEMPFSR+0], %o5; \
set 0x303FFFE0, %g1; \
and %o5, %g1, %o5; \
sllx ROUND, 30, %g1; \
or %o5, %g1, %o5; \
rd %gsr, %g1; \
stw %o5, [TEMPFSR+4]; \
ld [TEMPFSR+4], %fsr; \
wr %g0, %g0, %gsr;
/* RESTORE_FSR:
1. save updated FSR
2. restore previous FSR
3. load updated FSR in %o0
4. restore previous GSR
*/
#define RESTORE_FSR(TEMPFSR) \
st %fsr, [TEMPFSR+4]; \
lduw [TEMPFSR+4], %o0; \
ld [TEMPFSR+0], %fsr; \
wr %g1, %g0, %gsr;
.section ".text"
/*==========================================================================*/
! int asm_faddd( double* op1, double* op2, double* rslt, int rnd, int* tmp );
! %o0 %o0 %o1 %o2 %o3 %o4
FUNCTION(asm_faddd)
SET_ROUNDING(%o3,%o4)
ldd [%o0], %f0
ldd [%o1], %f2
faddd %f0, %f2, %f4
std %f4, [%o2]
RESTORE_FSR(%o4)
retl
and %o0, 0x1F, %o0;
ENDFUNC(asm_faddd)
/*==========================================================================*/
! int asm_fsubd( double* op1, double* op2, double* rslt, int rnd, int* tmp );
! %o0 %o0 %o1 %o2 %o3 %o4
FUNCTION(asm_fsubd)
SET_ROUNDING(%o3,%o4)
ldd [%o0], %f0
ldd [%o1], %f2
fsubd %f0, %f2, %f4
std %f4, [%o2]
RESTORE_FSR(%o4)
retl
and %o0, 0x1F, %o0;
ENDFUNC(asm_fsubd)
/*==========================================================================*/
! int asm_fmuld( double* op1, double* op2, double* rslt, int rnd, int* tmp );
! %o0 %o0 %o1 %o2 %o3 %o4
FUNCTION(asm_fmuld)
SET_ROUNDING(%o3,%o4)
ldd [%o0], %f0
ldd [%o1], %f2
fmuld %f0, %f2, %f4
std %f4, [%o2]
RESTORE_FSR(%o4)
retl
and %o0, 0x1F, %o0;
ENDFUNC(asm_fmuld)
/*==========================================================================*/
! int asm_fdivd( double* op1, double* op2, double* rslt, int rnd, int* tmp );
! %o0 %o0 %o1 %o2 %o3 %o4
FUNCTION(asm_fdivd)
SET_ROUNDING(%o3,%o4)
ldd [%o0], %f0
ldd [%o1], %f2
fdivd %f0, %f2, %f4
std %f4, [%o2]
RESTORE_FSR(%o4)
retl
and %o0, 0x1F, %o0;
ENDFUNC(asm_fdivd)
/*==========================================================================*/
! int asm_fsqrtd( double* op2, double* rslt, int rnd, int* tmp );
! %o0 %o0 %o1 %o2 %o3
FUNCTION(asm_fsqrtd)
SET_ROUNDING(%o2,%o3)
ldd [%o0], %f0
fsqrtd %f0, %f2
std %f2, [%o1]
RESTORE_FSR(%o3)
retl
and %o0, 0x1F, %o0;
ENDFUNC(asm_fsqrtd)
/*==========================================================================*/
! int asm_fadds( float* op1, float* op2, float* rslt, int rnd, int* tmp );
! %o0 %o0 %o1 %o2 %o3 %o4
FUNCTION(asm_fadds)
SET_ROUNDING(%o3,%o4)
ld [%o0], %f0
ld [%o1], %f1
fadds %f0, %f1, %f2
st %f2, [%o2]
RESTORE_FSR(%o4)
retl
and %o0, 0x1F, %o0;
ENDFUNC(asm_fadds)
/*==========================================================================*/
! int asm_fsubs( float* op1, float* op2, float* rslt, int rnd, int* tmp );
! %o0 %o0 %o1 %o2 %o3 %o4
FUNCTION(asm_fsubs)
SET_ROUNDING(%o3,%o4)
ld [%o0], %f0
ld [%o1], %f1
fsubs %f0, %f1, %f2
st %f2, [%o2]
RESTORE_FSR(%o4)
retl
and %o0, 0x1F, %o0;
ENDFUNC(asm_fsubs)
/*==========================================================================*/
! int asm_fmuls( float* op1, float* op2, float* rslt, int rnd, int* tmp );
! %o0 %o0 %o1 %o2 %o3 %o4
FUNCTION(asm_fmuls)
SET_ROUNDING(%o3,%o4)
ld [%o0], %f0
ld [%o1], %f1
fmuls %f0, %f1, %f2
st %f2, [%o2]
RESTORE_FSR(%o4)
retl
and %o0, 0x1F, %o0;
ENDFUNC(asm_fmuls)
/*==========================================================================*/
! int asm_fdivs( float* op1, float* op2, float* rslt, int rnd, int* tmp )
! %o0 %o0 %o1 %o2 %o3 %o4
FUNCTION(asm_fdivs)
SET_ROUNDING(%o3,%o4)
ld [%o0], %f0
ld [%o1], %f1
fdivs %f0, %f1, %f2
st %f2, [%o2]
RESTORE_FSR(%o4)
retl
and %o0, 0x1F, %o0;
ENDFUNC(asm_fdivs)
/*==========================================================================*/
! int asm_fsqrts( float* op2, float* rslt, int rnd, int* tmp );
! %o0 %o0 %o1 %o2 %o3
FUNCTION(asm_fsqrts)
SET_ROUNDING(%o2,%o3)
ld [%o0], %f0
fsqrts %f0, %f1
st %f1, [%o1]
RESTORE_FSR(%o3)
retl
and %o0, 0x1F, %o0;
ENDFUNC(asm_fsqrts)
/*==========================================================================*/
! int asm_fsmuld( float* op1, float* op2, double* rslt, int* tmp );
! %o0 %o0 %o1 %o2 %o3
FUNCTION(asm_fsmuld)
SET_ROUNDING(%g0,%o3)
ld [%o0], %f0
ld [%o1], %f1
fsmuld %f0, %f1, %f2
std %f2, [%o2]
RESTORE_FSR(%o3)
retl
and %o0, 0x1F, %o0;
ENDFUNC(asm_fsmuld)
/*==========================================================================*/
! int asm_fstod( float* op2, double* rslt, int rnd, int* tmp );
! %o0 %o0 %o1 %o2 %o3
FUNCTION(asm_fstod)
SET_ROUNDING(%o2,%o3)
ld [%o0], %f0
fstod %f0, %f2
std %f2, [%o1]
RESTORE_FSR(%o3)
retl
and %o0, 0x1F, %o0;
ENDFUNC(asm_fstod)
/*==========================================================================*/
! int asm_fdtos( double* op2, float* rslt, int rnd, int* tmp );
! %o0 %o0 %o1 %o2 %o3
FUNCTION(asm_fdtos)
SET_ROUNDING(%o2,%o3)
ldd [%o0], %f0
fdtos %f0, %f2
st %f2, [%o1]
RESTORE_FSR(%o3)
retl
and %o0, 0x1F, %o0;
ENDFUNC(asm_fdtos)
/*==========================================================================*/
! int asm_fstox( float* op2, uint64* rslt, int rnd, int* tmp );
! %o0 %o0 %o1 %o2 %o3
FUNCTION(asm_fstox)
SET_ROUNDING(%o2,%o3)
ld [%o0], %f0
fstox %f0, %f2
std %f2, [%o1]
RESTORE_FSR(%o3)
retl
and %o0, 0x1F, %o0;
ENDFUNC(asm_fstox)
/*==========================================================================*/
! int asm_fdtox( double* op2, uint64* rslt, int rnd, int* tmp );
! %o0 %o0 %o1 %o2 %o3
FUNCTION(asm_fdtox)
SET_ROUNDING(%o2,%o3)
ldd [%o0], %f0
fdtox %f0, %f2
std %f2, [%o1]
RESTORE_FSR(%o3)
retl
and %o0, 0x1F, %o0;
ENDFUNC(asm_fdtox)
/*==========================================================================*/
! int asm_fstoi( float* op2, uint* rslt, int rnd, int* tmp );
! %o0 %o0 %o1 %o2 %o3
FUNCTION(asm_fstoi)
SET_ROUNDING(%o2,%o3)
ld [%o0], %f0
fstoi %f0, %f1
st %f1, [%o1]
RESTORE_FSR(%o3)
retl
and %o0, 0x1F, %o0;
ENDFUNC(asm_fstoi)
/*==========================================================================*/
! int asm_fdtoi( double* op2, uint* rslt, int rnd, int* tmp );
! %o0 %o0 %o1 %o2 %o3
FUNCTION(asm_fdtoi)
SET_ROUNDING(%o2,%o3)
ldd [%o0], %f0
fdtoi %f0, %f2
st %f2, [%o1]
RESTORE_FSR(%o3)
retl
and %o0, 0x1F, %o0;
ENDFUNC(asm_fdtoi)
/*==========================================================================*/
! int asm_fxtos( uint64* op2, float* rslt, int rnd, int* tmp );
! %o0 %o0 %o1 %o2 %o3
FUNCTION(asm_fxtos)
SET_ROUNDING(%o2,%o3)
ldd [%o0], %f0
fxtos %f0, %f2
st %f2, [%o1]
RESTORE_FSR(%o3)
retl
and %o0, 0x1F, %o0;
ENDFUNC(asm_fxtos)
/*==========================================================================*/
! int asm_fxtod( uint64* op2, double* rslt, int rnd, int* tmp );
! %o0 %o0 %o1 %o2 %o3
FUNCTION(asm_fxtod)
SET_ROUNDING(%o2,%o3)
ldd [%o0], %f0
fxtod %f0, %f2
std %f2, [%o1]
RESTORE_FSR(%o3)
retl
and %o0, 0x1F, %o0;
ENDFUNC(asm_fxtod)
/*==========================================================================*/
! int asm_fitos( uint* op2, float* rslt, int rnd, int* tmp );
! %o0 %o0 %o1 %o2 %o3
FUNCTION(asm_fitos)
SET_ROUNDING(%o2,%o3)
ld [%o0], %f0
fitos %f0, %f1
st %f1, [%o1]
RESTORE_FSR(%o3)
retl
and %o0, 0x1F, %o0;
ENDFUNC(asm_fitos)
/*==========================================================================*/
! void asm_fitod( uint* op2, double* rslt );
! %o0 %o1
FUNCTION(asm_fitod)
ld [%o0], %f1
fitod %f1, %f2
retl
std %f2, [%o1]
ENDFUNC(asm_fitod)
/*==========================================================================*/
! Add 2 integers and return carry-out:
! int asm_addc( uint64 op1, uint64 op2, uint64* res );
! %o0 %o0 %o1 %o2
FUNCTION(asm_addc)
addcc %o0, %o1, %o3 ! add
clr %o0 ! carry = 0
stx %o3, [%o2]
retl
movcs %xcc, 1, %o0 ! get carry-out
ENDFUNC(asm_addc)
/*==========================================================================*/
! Subtract 2 integers and return borrow-out:
! int asm_subc( uint64 op1, uint64 op2, uint64* res );
! %o0 %o0 %o1 %o2
FUNCTION(asm_subc)
subcc %o0, %o1, %o3 ! sub
clr %o0 ! borrow = 0
stx %o3, [%o2]
retl
movcs %xcc, 1, %o0 ! get borrow-out
ENDFUNC(asm_subc)