/* * ========== 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