summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/hppa/hppa/fpemu.S320
1 files changed, 320 insertions, 0 deletions
diff --git a/sys/arch/hppa/hppa/fpemu.S b/sys/arch/hppa/hppa/fpemu.S
new file mode 100644
index 00000000000..339db60765e
--- /dev/null
+++ b/sys/arch/hppa/hppa/fpemu.S
@@ -0,0 +1,320 @@
+/* $OpenBSD: fpemu.S,v 1.1 2000/01/11 09:47:25 mickey Exp $ */
+
+/*
+ * Copyright (c) 2000 Michael Shalayeff
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Michael Shalayeff.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+#include "assym.h"
+
+#define FPEMU_VERSION (1 << 11)
+
+#define FP_TABLE2(name, ep0, ep1, ep2, ep3) \
+ ldil L%$fpemu_tbl$name, t1 ! \
+ ldo R%$fpemu_tbl$name(t1), t1 ! \
+ ldwx,s r1(t1), t2 ! \
+ bv r0(t2) ! \
+ nop ! \
+ .label $fpemu_tbl$name ! \
+ .import __CONCAT(__CONCAT(ep0,_),name), code ! \
+ .import __CONCAT(__CONCAT(ep1,_),name), code ! \
+ .import __CONCAT(__CONCAT(ep2,_),name), code ! \
+ .import __CONCAT(__CONCAT(ep3,_),name), code ! \
+ .word __CONCAT(__CONCAT(ep0,_),name), __CONCAT(__CONCAT(ep1,_),name), __CONCAT(__CONCAT(ep2,_),name), __CONCAT(__CONCAT(ep3,_),name)
+
+#define FP_TABLE3(name,ep0,ep1,ep2,ep3,ep4,ep5,ep6,ep7,ep8,ep9,epa,epb,epc,epd,epe,epf) \
+ ldil L%$fpemu_tbl$name, t1 ! \
+ ldo R%$fpemu_tbl$name(t1), t1 ! \
+ ldwx,s r1(t1), t2 ! \
+ bv r0(t2) ! \
+ nop ! \
+ .label $fpemu_tbl$name ! \
+ .import __CONCAT(__CONCAT(ep0,_),name), code ! \
+ .import __CONCAT(__CONCAT(ep1,_),name), code ! \
+ .import __CONCAT(__CONCAT(ep2,_),name), code ! \
+ .import __CONCAT(__CONCAT(ep3,_),name), code ! \
+ .import __CONCAT(__CONCAT(ep4,_),name), code ! \
+ .import __CONCAT(__CONCAT(ep5,_),name), code ! \
+ .import __CONCAT(__CONCAT(ep6,_),name), code ! \
+ .import __CONCAT(__CONCAT(ep7,_),name), code ! \
+ .import __CONCAT(__CONCAT(ep8,_),name), code ! \
+ .import __CONCAT(__CONCAT(ep9,_),name), code ! \
+ .import __CONCAT(__CONCAT(epa,_),name), code ! \
+ .import __CONCAT(__CONCAT(epb,_),name), code ! \
+ .import __CONCAT(__CONCAT(epc,_),name), code ! \
+ .import __CONCAT(__CONCAT(epd,_),name), code ! \
+ .import __CONCAT(__CONCAT(epe,_),name), code ! \
+ .import __CONCAT(__CONCAT(epf,_),name), code ! \
+ .word __CONCAT(__CONCAT(ep0,_),name), __CONCAT(__CONCAT(ep1,_),name), __CONCAT(__CONCAT(ep2,_),name), __CONCAT(__CONCAT(ep3,_),name), __CONCAT(__CONCAT(ep4,_),name), __CONCAT(__CONCAT(ep5,_),name), __CONCAT(__CONCAT(ep6,_),name), __CONCAT(__CONCAT(ep7,_),name), __CONCAT(__CONCAT(ep8,_),name), __CONCAT(__CONCAT(ep9,_),name), __CONCAT(__CONCAT(epa,_),name), __CONCAT(__CONCAT(epb,_),name), __CONCAT(__CONCAT(epc,_),name), __CONCAT(__CONCAT(epd,_),name), __CONCAT(__CONCAT(epe,_),name), __CONCAT(__CONCAT(epf,_),name)
+
+ .space $PRIVATE$
+ .subspa $BSS$
+
+ .export $fpemu_stack, data
+$fpemu_stack
+ .block NBPG
+
+/*
+ * fpu_emulate(iir)
+ */
+ENTRY(fpu_emulate)
+
+ extru arg0, 22, 2, arg3
+ extru arg0, 18, 3, r31
+ comib,= 1, arg3, $fpu_cln1
+ nop
+ extru arg0, 16, 2, r31
+
+$fpu_cln1
+ /*
+ * theoreticaly we would need to determine the fpu instruction
+ * exception type (there could be 4 of those, but stick w/
+ * non-timex fpus for now.
+ */
+ ldi 1, ret0
+ extru,<> arg0, 10, 5, r1
+ ldi 32, r1 /* fpemu zero reg */
+ extru,<> arg0, 31, 5, t1
+ b,n $fpemu_nzt
+ comib,=,n 2, arg3, $fpemu_exit
+$fpemu_nzt
+ copy arg0, t4
+ sh3add r1, arg2, arg0
+ extru arg1, 20, 2, r1
+ sh3add t1, arg2, arg1
+
+ /*
+ * arg0 -- source register (address)
+ * arg1 -- target register (address)
+ * arg2 -- fpregs context
+ * arg3 -- class
+ * r31 -- subop
+ * r1 -- format specifier
+ * (t4 -- copy or arg0, ie iir)
+ */
+ comib,=,n 0, arg3, $fpemu0c_0
+ comib,=,n 1, arg3, $fpemu0c_1
+ comib,=,n 2, arg3, $fpemu0c_2
+ comib,=,n 3, arg3, $fpemu0c_3
+
+$fpemu0c_0
+ comib,=,n 0, r31, $fpemu0c_0_0
+ comib,=,n 1, r31, $fpemu_exit
+ comib,=,n 2, r31, $fpemu0c_0_2
+ comib,=,n 3, r31, $fpemu0c_0_3
+ comib,=,n 4, r31, $fpemu0c_0_4
+ comib,=,n 5, r31, $fpemu0c_0_5
+ comib,=,n 6, r31, $fpemu_exit
+ comib,=,n 7, r31, $fpemu_exit
+
+$fpemu0c_0_0
+ ldi FPEMU_VERSION, t4
+ stw t4, 0(arg2)
+ bv 0(rp)
+ copy r0, ret0
+
+$fpemu0c_0_2 /* fcpy */
+ comib,=,n 2, r1, $fpemu_exit
+ subi 3, r1, r1
+ ldw 0*4(arg0), t1
+ ldw 1*4(arg0), t2
+ ldw 2*4(arg0), t3
+ ldw 3*4(arg0), t4
+ blr,n r1, r0
+ nop
+ stw t3, 2*4(arg1)
+ stw t4, 3*4(arg1)
+ stw t2, 1*4(arg1)
+ nop
+ nop
+ nop
+ stw t1, 0*4(arg1)
+ bv 0(rp)
+ copy r0, ret0
+
+$fpemu0c_0_3 /* fabs */
+ comib,=,n 2, r1, $fpemu_exit
+ subi 3, r1, r1
+ ldw 0*4(arg0), t1
+ ldw 1*4(arg0), t2
+ ldw 2*4(arg0), t3
+ ldw 3*4(arg0), t4
+ depi 0, 0, 1, t1
+ blr,n r1, r0
+ nop
+ stw t3, 2*4(arg1)
+ stw t4, 3*4(arg1)
+ stw t2, 1*4(arg1)
+ nop
+ nop
+ nop
+ stw t1, 0*4(arg1)
+ bv 0(rp)
+ copy r0, ret0
+
+$fpemu0c_0_4 /* fsqrt */
+ /* quad not implemented */
+ FP_TABLE2(fsqrt,sgl,dbl,invalid,invalid)
+
+$fpemu0c_0_5 /* frnd */
+ /* quad not implemented */
+ FP_TABLE2(frnd,sgl,dbl,invalid,invalid)
+
+$fpemu0c_1
+ extru t4, 18, 2, t2
+ sh2add r1, t2, r1
+ comib,=,n 0, r31, $fpemu0c_1_0
+ comib,=,n 1, r31, $fpemu0c_1_1
+ comib,=,n 2, r31, $fpemu0c_1_2
+ comib,=,n 3, r31, $fpemu0c_1_3
+
+$fpemu0c_1_0 /* fcnvff */
+#define sgl_to_quad_fcnvff invalid_fcnvff
+#define dbl_to_quad_fcnvff invalid_fcnvff
+#define quad_to_sgl_fcnvff invalid_fcnvff
+#define quad_to_dbl_fcnvff invalid_fcnvff
+ FP_TABLE3(fcnvff, invalid, sgl_to_dbl, invalid, sgl_to_quad, dbl_to_sgl, invalid, invalid, dbl_to_quad, invalid, invalid, invalid, invalid, quad_to_sgl, quad_to_dbl, invalid, invalid)
+
+$fpemu0c_1_1 /* fcnvxf */
+#define sgl_to_quad_fcnvxf invalid_fcnvxf
+#define dbl_to_quad_fcnvxf invalid_fcnvxf
+#define quad_to_sgl_fcnvxf invalid_fcnvxf
+#define quad_to_dbl_fcnvxf invalid_fcnvxf
+#define quad_to_quad_fcnvxf invalid_fcnvxf
+ FP_TABLE3(fcnvxf, sgl_to_sgl, sgl_to_dbl, invalid, sgl_to_quad, dbl_to_sgl, dbl_to_dbl, invalid, dbl_to_quad, invalid, invalid, invalid, invalid, quad_to_sgl, quad_to_dbl, invalid, quad_to_quad)
+
+$fpemu0c_1_2 /* fcnvfx */
+#define sgl_to_quad_fcnvfx invalid_fcnvfx
+#define dbl_to_quad_fcnvfx invalid_fcnvfx
+#define quad_to_sgl_fcnvfx invalid_fcnvfx
+#define quad_to_dbl_fcnvfx invalid_fcnvfx
+#define quad_to_quad_fcnvfx invalid_fcnvfx
+ FP_TABLE3(fcnvfx, sgl_to_sgl, sgl_to_dbl, invalid, sgl_to_quad, dbl_to_sgl, dbl_to_dbl, invalid, dbl_to_quad, invalid, invalid, invalid, invalid, quad_to_sgl, quad_to_dbl, invalid, quad_to_quad)
+
+$fpemu0c_1_3 /* fcnvfxt */
+#define sgl_to_quad_fcnvfxt invalid_fcnvfxt
+#define dbl_to_quad_fcnvfxt invalid_fcnvfxt
+#define quad_to_sgl_fcnvfxt invalid_fcnvfxt
+#define quad_to_dbl_fcnvfxt invalid_fcnvfxt
+#define quad_to_quad_fcnvfxt invalid_fcnvfxt
+ FP_TABLE3(fcnvfxt, sgl_to_sgl, sgl_to_dbl, invalid, sgl_to_quad, dbl_to_sgl, dbl_to_dbl, invalid, dbl_to_quad, invalid, invalid, invalid, invalid, quad_to_sgl, quad_to_dbl, invalid, quad_to_quad)
+
+
+$fpemu0c_2
+ comib,=,n 0, r31, $fpemu0c_2_0
+ comib,=,n 1, r31, $fpemu0c_2_1
+ comib,=,n 2, r31, $fpemu_exit
+ comib,=,n 3, r31, $fpemu_exit
+ comib,=,n 4, r31, $fpemu_exit
+ comib,=,n 5, r31, $fpemu_exit
+ comib,=,n 6, r31, $fpemu_exit
+ comib,=,n 7, r31, $fpemu_exit
+
+$fpemu0c_2_0
+ copy arg2, arg3
+ extru,<> t4, 15, 5, t1
+ ldi 32, t1
+ sh3add t1, arg3, arg1
+ extru t4, 31, 5, arg2
+ FP_TABLE2(fcmp,sgl,dbl,invalid,invalid)
+
+$fpemu0c_2_1
+ comib,<>,n 0, r1, $fpemu_exit
+
+ /* extru t4, 31, 5, arg1 */
+ /* XXX timex is much more compilicated */
+ ldw 0(arg2), t1
+ ldi 0, ret0
+ extru,<> t1, 5, 1, r0
+ bv,n r0(rp)
+
+ /* advance the pcqueue */
+ mtctl r0, pcsq
+ mfctl pcsq, t2
+ mtctl t2, pcsq
+ mtctl t2, pcsq
+ mtctl r0, pcoq
+ mfctl pcoq, t2
+ mtctl t2, pcoq
+ ldo 4(t2), t2
+ bv r0(rp)
+ mtctl t2, pcoq
+
+$fpemu0c_3
+ copy arg2, arg3
+ extru,<> t4, 31, 5, t1
+ ldi 32, t1
+ sh3add t1, arg3, arg2
+
+ comib,=,n 0, r31, $fpemu0c_3_0
+ comib,=,n 1, r31, $fpemu0c_3_1
+ comib,=,n 2, r31, $fpemu0c_3_2
+ comib,=,n 3, r31, $fpemu0c_3_3
+ comib,=,n 4, r31, $fpemu0c_3_4
+ comib,=,n 5, r31, $fpemu_exit
+ comib,=,n 6, r31, $fpemu_exit
+ comib,=,n 7, r31, $fpemu_exit
+
+$fpemu0c_3_0 /* fadd */
+ FP_TABLE2(fadd,sgl,dbl,invalid,invalid)
+
+$fpemu0c_3_1 /* fsub */
+ FP_TABLE2(fsub,sgl,dbl,invalid,invalid)
+
+$fpemu0c_3_2 /* fmpy */
+ FP_TABLE2(fmpy,sgl,dbl,invalid,invalid)
+
+$fpemu0c_3_3 /* fdiv */
+ FP_TABLE2(fdiv,sgl,dbl,invalid,invalid)
+
+$fpemu0c_3_4 /* frem */
+ FP_TABLE2(frem,sgl,dbl,invalid,invalid)
+
+ .export $fpemu_exit, code
+$fpemu_exit
+ /* these look very ugly, but we don't want to mess up w/ m4 just
+ * for the sake of overall world prettieness value growth XXX */
+invalid_fsqrt
+invalid_frnd
+invalid_fcnvff
+invalid_fcnvxf
+invalid_fcnvfx
+invalid_fcnvfxt
+invalid_fcmp
+invalid_fadd
+invalid_fsub
+invalid_fmpy
+invalid_fdiv
+invalid_frem
+ bv,n 0(rp)
+EXIT(fpu_emulate)
+
+
+ .end
+