Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / ss / lib / cpu / src / SS_Float.s
/*
* ========== Copyright Header Begin ==========================================
*
* OpenSPARC T2 Processor File: SS_Float.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 ============================================
*/
#if !defined(ARCH_X64)
.register %g2,#scratch
.register %g3,#scratch
.section ".text"
! All functions that check for FPU enabled branch here when it's disabled
! and have to throw a trap. I exect %o0=pc, %o1=npc, %o2=strand_ptr, %o3=instr_ptr
! so all that's required is setting %o4 to the trap number. There's two entry
! points here: one that restores the host fsr, and the other doesn't.
.align 8
.global fpop_disabled_trap_fsr
.type fpop_disabled_trap_fsr, #function
fpop_disabled_trap_fsr:
ldx [S_PTR + S_FSR_CPU],%fsr ! Load host's %fsr
.global fpop_disabled_trap
.type fpop_disabled_trap, #function
fpop_disabled_trap:
ldptr [S_PTR + TRAP],%g1 ! In v8plus mode we need to convert
jmpl %g1,%g0 ! from v9 to v8plus first before we
mov T_FP_DISABLED,%o4 ! handle the trap
#define FSR_CEXC_TO_AEXC_SFT 5
#define FSR_CEXC 0x01f
#define FSR_AEXC (FSR_CEXC << FSR_CEXC_TO_AEXC_SFT)
#define FSR_AEXC_CEXC (FSR_CEXC+FSR_AEXC)
#define FSR_FTT_SFT 14
#define FSR_FTT_MSK (0x7 << FSR_FTT_SFT)
#define FSR_IEEE_754_EXC (1 << FSR_FTT_SFT)
/*
* fsr_cpu - the fsr of the host
* fsr_tmp - tmp for getting fsr after operation
* fsr_run - the fsr of the simulated cpu with:
* fsr_run.tem = 0 - this so we can catch ieee traps
* fsr_run.aexc = 0 -
* fsr_run.cexc = 0 - this so we can catch ieee traps
* fsr_tem - the fsr.tem field of the simulated cpu
* fsr_exc - the fsr.cexc and fsr.aexc fields of the simulated cpu
*/
.global fpop_retl
.global fpop_retl_f
.global fpop_retl_d
.type fpop_retl , #function
.type fpop_retl_f, #function
.type fpop_retl_d, #function
!============================================================================
! fpop_retl_d is the tail code for floating point functions that have a double
! precision result and update %fsr
! %g3 - rd index
! %g5 - cpu %gsr to be restored
! %f8 (%f9) - fpop result
!============================================================================
.align 8
fpop_retl_d:
wr %g5,%gsr ! Restore host %gsr
stx %fsr,[S_PTR + S_FSR_TMP] ! Grab host's %fsr ... and get instr result
ldx [S_PTR + S_FSR_TMP],%g1
ldx [S_PTR + S_FSR_TEM],%g4 ! Get simulated fsr tem
ldx [S_PTR + S_FSR_EXC],%g5 ! Get simulated fsr aexc and cexc
andn %g1,FSR_AEXC_CEXC,%g2 ! Clear aexc and cexc of fsr_run
andcc %g1,FSR_CEXC,%g1 ! Extract cexc, and check if any traps occured
be %xcc,fpop_fprs_d ! No traps then update fprs and FRF and return
ldx [S_PTR + S_FSR_CPU],%fsr ! Load host's %fsr
andcc %g1,%g4,%g0 ! (tem & cexc) == 0?
and %g5,FSR_AEXC,%g5 ! Get previous fsr aexc
bne %xcc,fpop_trap ! if (tem & cexc) goto fpop_raise_trap
or %g1,%g5,%g4 ! Combine previous aexc and new cexc
sllx %g1,FSR_CEXC_TO_AEXC_SFT,%g5 ! In case of no trap then cexc gets or'ed with aexc
or %g4,%g5,%g1
stx %g1,[S_PTR + S_FSR_EXC]
ba,a %xcc,fpop_fprs_dd
fpop_fprs_d:
andn %g5,FSR_CEXC,%g1 ! clear fsr.cexc as no trap occured
stx %g1,[S_PTR + S_FSR_EXC] ! Save fsr_exc for next fpop
fpop_fprs_dd:
mov R_NPC,R_PC ! pc = npc
add R_NPC,4,R_NPC ! npc = npc + 4
ldub [S_PTR + S_FPRS],%g5 ! set fprs.dl and/or fprs.du based on the
sub %g3,S_FRF - 32*4,%g4 ! index rd. Convert the rd index to 1 (%f)
stx %g2,[S_PTR + S_FSR_RUN] ! Save fsr_run for next fpop
srlx %g4,7,%g4 ! or 2 (%d) value and or it with the previous
stx R_NPC,[S_PTR + S_NPC]
or %g5,%g4,%g5 ! fprs value.
std %f8,[S_PTR + %g3] ! Update register file
V8_PC
retl
stb %g5,[S_PTR + S_FPRS] ! Update fprs.dl and fprs.du
!============================================================================
! fpop_retl_d is the tail code for floating point functions that have a single
! precision result and update %fsr
! %g3 - rd index
! %g5 - cpu %gsr to be restored
! %f8 (%f9) - fpop result
!============================================================================
.align 8
fpop_retl_f:
wr %g5,%gsr ! Restore host %gsr
stx %fsr,[S_PTR + S_FSR_TMP] ! Grab host's %fsr ... and get instr result
ldx [S_PTR + S_FSR_TMP],%g1
ldx [S_PTR + S_FSR_TEM],%g4 ! Get simulated fsr tem
ldx [S_PTR + S_FSR_EXC],%g5 ! Get simulated fsr aexc and cexc
andn %g1,FSR_AEXC_CEXC,%g2 ! Clear aexc and cexc of fsr_run
andcc %g1,FSR_CEXC,%g1 ! Extract cexc, and check if any traps occured
be %xcc,fpop_fprs_f ! No traps then update fprs and FRF and return
ldx [S_PTR + S_FSR_CPU],%fsr ! Load host's %fsr
andcc %g1,%g4,%g0 ! (tem & cexc) == 0?
and %g5,FSR_AEXC,%g5 ! Get previous fsr aexc
bne %xcc,fpop_trap ! if (tem & cexc) goto fpop_raise_trap
or %g1,%g5,%g4 ! Combine previous aexc and new cexc
sllx %g1,FSR_CEXC_TO_AEXC_SFT,%g5 ! In case of no trap then cexc gets or'ed with aexc
or %g4,%g5,%g1
stx %g1,[S_PTR + S_FSR_EXC]
ba,a %xcc,fpop_fprs_ff
fpop_fprs_f:
andn %g5,FSR_CEXC,%g1 ! clear fsr.cexc as no trap occured
stx %g1,[S_PTR + S_FSR_EXC] ! Save fsr_exc for next fpop
fpop_fprs_ff:
mov R_NPC,R_PC ! pc = npc
add R_NPC,4,R_NPC ! npc = npc + 4
ldub [S_PTR + S_FPRS],%g5 ! set fprs.dl and/or fprs.du based on the
sub %g3,S_FRF - 32*4,%g4 ! index rd. Convert the rd index to 1 (%f)
stx %g2,[S_PTR + S_FSR_RUN] ! Save fsr_run for next fpop
srlx %g4,7,%g4 ! or 2 (%d) value and or it with the previous
stx R_NPC,[S_PTR + S_NPC]
or %g5,%g4,%g5 ! fprs value.
st %f8,[S_PTR + %g3] ! Update register file
V8_PC
retl
stb %g5,[S_PTR + S_FPRS] ! Update fprs.dl and fprs.du
!============================================================================
! fpop_retl is the tail code for floating point functions that do
! not cause and results other then an update of %fsr
! %g5 - cpu %gsr to be restored
!============================================================================
fpop_retl:
wr %g5,%gsr ! Restore host %gsr
stx %fsr,[S_PTR + S_FSR_TMP] ! Grab host's %fsr ... and get instr result
ldx [S_PTR + S_FSR_TMP],%g1
ldx [S_PTR + S_FSR_TEM],%g4 ! Get simulated fsr tem
ldx [S_PTR + S_FSR_EXC],%g5 ! Get simulated fsr aexc and cexc
andn %g1,FSR_AEXC_CEXC,%g2 ! Clear aexc and cexc of fsr_run
andcc %g1,FSR_CEXC,%g1 ! Extract cexc, and check if any traps occured
be %xcc,fpop_fprs ! No traps then update fprs and FRF and return
ldx [S_PTR + S_FSR_CPU],%fsr ! Load host's %fsr
andcc %g1,%g4,%g0 ! (tem & cexc) == 0?
and %g5,FSR_AEXC,%g5 ! Get previous fsr aexc
bne %xcc,fpop_trap ! if (tem & cexc) goto fpop_raise_trap
or %g1,%g5,%g4 ! Combine previous aexc and new cexc
sllx %g1,FSR_CEXC_TO_AEXC_SFT,%g5 ! In case of no trap then cexc gets or'ed with aexc
or %g4,%g5,%g1
stx %g1,[S_PTR + S_FSR_EXC]
ba,a %xcc,fpop_fprs_
fpop_fprs:
andn %g5,FSR_CEXC,%g1 ! clear fsr.cexc as no trap occured
stx %g1,[S_PTR + S_FSR_EXC] ! Save fsr_exc for next fpop
fpop_fprs_:
mov R_NPC,R_PC ! pc = npc
add R_NPC,4,R_NPC ! npc = npc + 4
stx R_NPC,[S_PTR + S_NPC]
V8_PC
retl
stx %g2,[S_PTR + S_FSR_RUN] ! Save fsr_run for next fpop
!============================================================================
! fpop_trap is the branched to from the fpop_retl functions above in case
! and FP_EXCEPTION_IEEE_754 trap needs to be thrown.
!============================================================================
fpop_trap:
sethi %hi(FSR_FTT_MSK),%g4 ! Clear old ftt
ldptr [S_PTR + TRAP],%g5
andn %g2,%g4,%g2 ! Clear old ftt
sethi %hi(FSR_IEEE_754_EXC),%g4 ! Set ftt to IEEE exception
stx %g1,[S_PTR + S_FSR_EXC]
or %g2,%g4,%g2 ! Set ftt to IEEE exception
mov T_FP_EXCEPTION_IEEE_754,%o4
jmpl %g5,%g0 ! trap(pc,npc,s,i,T_FP_EXCEPTION_IEEE_754)
stx %g2,[S_PTR + S_FSR_RUN] ! Save simulated fsr
!============================================================================
! opf_fprs_gsr_d: store double result %f8 in drf[%g3], update fprs, pc and npc
!============================================================================
.global opf_fprs_gsr_d
.type opf_fprs_gsr_d, #function
opf_fprs_gsr_d:
rd %gsr,%g1
sub %g3,S_FRF - 32*4,%g4 ! index rd. Convert the rd index to 1 (%f)
wr %g5,%gsr ! Restore host %gsr
ldub [S_PTR + S_FPRS],%g5 ! set fprs.dl and/or fprs.du based on the
srlx %g4,7,%g4 ! or 2 (%d) value and or it with the previous
std %f8,[S_PTR + %g3] ! Update register file
mov R_NPC,R_PC ! pc = npc
add R_NPC,4,R_NPC ! npc = npc + 4
stx R_NPC,[S_PTR + S_NPC]
stx %g1,[S_PTR + S_GSR]
or %g5,%g4,%g5 ! fprs value.
V8_PC
retl
stb %g5,[S_PTR + S_FPRS] ! Update fprs.dl and fprs.du
!============================================================================
! opf_fprs_gsr_f: store float result %f8 in frf[%g3], update fprs, pc and npc
!============================================================================
.global opf_fprs_gsr_f
.type opf_fprs_gsr_f, #function
opf_fprs_gsr_f:
rd %gsr,%g1
sub %g3,S_FRF - 32*4,%g4 ! index rd. Convert the rd index to 1 (%f)
mov R_NPC,R_PC ! pc = npc
wr %g5,%gsr ! Restore host %gsr
ldub [S_PTR + S_FPRS],%g5 ! set fprs.dl and/or fprs.du based on the
add R_NPC,4,R_NPC ! npc = npc + 4
srlx %g4,7,%g4 ! or 2 (%d) value and or it with the previous
st %f8,[S_PTR + %g3] ! Update register file
stx R_NPC,[S_PTR + S_NPC]
stx %g1,[S_PTR + S_GSR]
or %g5,%g4,%g5 ! fprs value.
V8_PC
retl
stb %g5,[S_PTR + S_FPRS] ! Update fprs.dl and fprs.du
!============================================================================
! opf_fprs_d: store double result %f8 in drf[%g3], update fprs, pc and npc
!============================================================================
.global opf_fprs_d
.type opf_fprs_d, #function
opf_fprs_d:
mov R_NPC,R_PC ! pc = npc
sub %g3,S_FRF - 32*4,%g4 ! index rd. Convert the rd index to 1 (%f)
ldub [S_PTR + S_FPRS],%g5 ! set fprs.dl and/or fprs.du based on the
add R_NPC,4,R_NPC ! npc = npc + 4
srlx %g4,7,%g4 ! or 2 (%d) value and or it with the previous
std %f8,[S_PTR + %g3] ! Update register file
stx R_NPC,[S_PTR + S_NPC]
or %g5,%g4,%g5 ! fprs value.
V8_PC
retl
stb %g5,[S_PTR + S_FPRS] ! Update fprs.dl and fprs.du
!============================================================================
! opf_fprs_f: store double result %f8 in drf[%g3], update fprs, pc and npc
!============================================================================
.global opf_fprs_f
.type opf_fprs_f, #function
opf_fprs_f:
mov R_NPC,R_PC ! pc = npc
sub %g3,S_FRF - 32*4,%g4 ! index rd. Convert the rd index to 1 (%f)
ldub [S_PTR + S_FPRS],%g5 ! set fprs.dl and/or fprs.du based on the
add R_NPC,4,R_NPC ! npc = npc + 4
srlx %g4,7,%g4 ! or 2 (%d) value and or it with the previous
st %f8,[S_PTR + %g3] ! Update register file
stx R_NPC,[S_PTR + S_NPC]
or %g5,%g4,%g5 ! fprs value.
V8_PC
retl
stb %g5,[S_PTR + S_FPRS] ! Update fprs.dl and fprs.du
#endif