1/* $NetBSD: fpemu.S,v 1.1 2002/06/05 01:04:20 fredette Exp $ */ 2 3/* $OpenBSD: fpemu.S,v 1.4 2001/03/29 02:18:45 mickey Exp $ */ 4 5/* 6 * Copyright (c) 2000 Michael Shalayeff 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by Michael Shalayeff. 20 * 4. The name of the author may not be used to endorse or promote products 21 * derived from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35#include <machine/asm.h> 36#include "assym.h" 37 38#define FPEMU_VERSION (1 << 11) 39 40#define FP_TABLE2(name, ep0, ep1, ep2, ep3) \ 41 ldil L%$fpemu_tbl$name, t1 ! \ 42 ldo R%$fpemu_tbl$name(t1), t1 ! \ 43 ldwx,s r1(t1), t2 ! \ 44 bv r0(t2) ! \ 45 nop ! \ 46 .label $fpemu_tbl$name ! \ 47 .import __CONCAT(__CONCAT(ep0,_),name), code ! \ 48 .import __CONCAT(__CONCAT(ep1,_),name), code ! \ 49 .import __CONCAT(__CONCAT(ep2,_),name), code ! \ 50 .import __CONCAT(__CONCAT(ep3,_),name), code ! \ 51 .word __CONCAT(__CONCAT(ep0,_),name), __CONCAT(__CONCAT(ep1,_),name), __CONCAT(__CONCAT(ep2,_),name), __CONCAT(__CONCAT(ep3,_),name) 52 53#define FP_TABLE3(name,ep0,ep1,ep2,ep3,ep4,ep5,ep6,ep7,ep8,ep9,epa,epb,epc,epd,epe,epf) \ 54 ldil L%$fpemu_tbl$name, t1 ! \ 55 ldo R%$fpemu_tbl$name(t1), t1 ! \ 56 ldwx,s r1(t1), t2 ! \ 57 bv r0(t2) ! \ 58 nop ! \ 59 .label $fpemu_tbl$name ! \ 60 .import __CONCAT(__CONCAT(ep0,_),name), code ! \ 61 .import __CONCAT(__CONCAT(ep1,_),name), code ! \ 62 .import __CONCAT(__CONCAT(ep2,_),name), code ! \ 63 .import __CONCAT(__CONCAT(ep3,_),name), code ! \ 64 .import __CONCAT(__CONCAT(ep4,_),name), code ! \ 65 .import __CONCAT(__CONCAT(ep5,_),name), code ! \ 66 .import __CONCAT(__CONCAT(ep6,_),name), code ! \ 67 .import __CONCAT(__CONCAT(ep7,_),name), code ! \ 68 .import __CONCAT(__CONCAT(ep8,_),name), code ! \ 69 .import __CONCAT(__CONCAT(ep9,_),name), code ! \ 70 .import __CONCAT(__CONCAT(epa,_),name), code ! \ 71 .import __CONCAT(__CONCAT(epb,_),name), code ! \ 72 .import __CONCAT(__CONCAT(epc,_),name), code ! \ 73 .import __CONCAT(__CONCAT(epd,_),name), code ! \ 74 .import __CONCAT(__CONCAT(epe,_),name), code ! \ 75 .import __CONCAT(__CONCAT(epf,_),name), code ! \ 76 .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) 77 78 .section .bss 79 80 .export $fpemu_stack, data 81$fpemu_stack 82 .comm NBPG 83 84 .text 85/* 86 * fpu_emulate(iir) 87 */ 88LEAF_ENTRY(fpu_emulate) 89 90 extru arg0, 22, 2, arg3 91 extru arg0, 18, 3, r31 92 comib,= 1, arg3, $fpu_cln1 93 nop 94 extru arg0, 16, 2, r31 95 96$fpu_cln1 97 /* 98 * theoreticaly we would need to determine the fpu instruction 99 * exception type (there could be 4 of those, but stick w/ 100 * non-timex fpus for now. 101 */ 102 ldi 1, ret0 103 extru,<> arg0, 10, 5, r1 104 ldi 32, r1 /* fpemu zero reg */ 105 extru,<> arg0, 31, 5, t1 106 b,n $fpemu_nzt 107 comib,=,n 2, arg3, $fpemu_exit 108$fpemu_nzt 109 copy arg0, t4 110 sh3add r1, arg2, arg0 111 extru arg1, 20, 2, r1 112 sh3add t1, arg2, arg1 113 114 /* 115 * arg0 -- source register (address) 116 * arg1 -- target register (address) 117 * arg2 -- fpregs context 118 * arg3 -- class 119 * r31 -- subop 120 * r1 -- format specifier 121 * (t4 -- copy or arg0, ie iir) 122 */ 123 comib,=,n 0, arg3, $fpemu0c_0 124 comib,=,n 1, arg3, $fpemu0c_1 125 comib,=,n 2, arg3, $fpemu0c_2 126 comib,=,n 3, arg3, $fpemu0c_3 127 128$fpemu0c_0 129 comib,=,n 0, r31, $fpemu0c_0_0 130 comib,=,n 1, r31, $fpemu_exit 131 comib,=,n 2, r31, $fpemu0c_0_2 132 comib,=,n 3, r31, $fpemu0c_0_3 133 comib,=,n 4, r31, $fpemu0c_0_4 134 comib,=,n 5, r31, $fpemu0c_0_5 135 comib,=,n 6, r31, $fpemu_exit 136 comib,=,n 7, r31, $fpemu_exit 137 138$fpemu0c_0_0 139 ldi FPEMU_VERSION, t4 140 stw t4, 0(arg2) 141 bv 0(rp) 142 copy r0, ret0 143 144$fpemu0c_0_2 /* fcpy */ 145 comib,=,n 2, r1, $fpemu_exit 146 subi 3, r1, r1 147 ldw 0*4(arg0), t1 148 ldw 1*4(arg0), t2 149 ldw 2*4(arg0), t3 150 ldw 3*4(arg0), t4 151 blr,n r1, r0 152 nop 153 stw t3, 2*4(arg1) 154 stw t4, 3*4(arg1) 155 stw t2, 1*4(arg1) 156 nop 157 nop 158 nop 159 stw t1, 0*4(arg1) 160 bv 0(rp) 161 copy r0, ret0 162 163$fpemu0c_0_3 /* fabs */ 164 comib,=,n 2, r1, $fpemu_exit 165 subi 3, r1, r1 166 ldw 0*4(arg0), t1 167 ldw 1*4(arg0), t2 168 ldw 2*4(arg0), t3 169 ldw 3*4(arg0), t4 170 depi 0, 0, 1, t1 171 blr,n r1, r0 172 nop 173 stw t3, 2*4(arg1) 174 stw t4, 3*4(arg1) 175 stw t2, 1*4(arg1) 176 nop 177 nop 178 nop 179 stw t1, 0*4(arg1) 180 bv 0(rp) 181 copy r0, ret0 182 183$fpemu0c_0_4 /* fsqrt */ 184 /* quad not implemented */ 185 FP_TABLE2(fsqrt,sgl,dbl,invalid,invalid) 186 187$fpemu0c_0_5 /* frnd */ 188 /* quad not implemented */ 189 FP_TABLE2(frnd,sgl,dbl,invalid,quad) 190 191$fpemu0c_1 192 extru t4, 18, 2, t2 193 sh2add r1, t2, r1 194 comib,=,n 0, r31, $fpemu0c_1_0 195 comib,=,n 1, r31, $fpemu0c_1_1 196 comib,=,n 2, r31, $fpemu0c_1_2 197 comib,=,n 3, r31, $fpemu0c_1_3 198 199$fpemu0c_1_0 /* fcnvff */ 200#define sgl_to_quad_fcnvff invalid_fcnvff 201#define dbl_to_quad_fcnvff invalid_fcnvff 202#define quad_to_sgl_fcnvff invalid_fcnvff 203#define quad_to_dbl_fcnvff invalid_fcnvff 204 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) 205 206$fpemu0c_1_1 /* fcnvxf */ 207#define sgl_to_quad_fcnvxf invalid_fcnvxf 208#define dbl_to_quad_fcnvxf invalid_fcnvxf 209#define quad_to_sgl_fcnvxf invalid_fcnvxf 210#define quad_to_dbl_fcnvxf invalid_fcnvxf 211#define quad_to_quad_fcnvxf invalid_fcnvxf 212 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) 213 214$fpemu0c_1_2 /* fcnvfx */ 215#define sgl_to_quad_fcnvfx invalid_fcnvfx 216#define dbl_to_quad_fcnvfx invalid_fcnvfx 217#define quad_to_sgl_fcnvfx invalid_fcnvfx 218#define quad_to_dbl_fcnvfx invalid_fcnvfx 219#define quad_to_quad_fcnvfx invalid_fcnvfx 220 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) 221 222$fpemu0c_1_3 /* fcnvfxt */ 223#define sgl_to_quad_fcnvfxt invalid_fcnvfxt 224#define dbl_to_quad_fcnvfxt invalid_fcnvfxt 225#define quad_to_sgl_fcnvfxt invalid_fcnvfxt 226#define quad_to_dbl_fcnvfxt invalid_fcnvfxt 227#define quad_to_quad_fcnvfxt invalid_fcnvfxt 228 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) 229 230 231$fpemu0c_2 232 comib,=,n 0, r31, $fpemu0c_2_0 233 comib,=,n 1, r31, $fpemu0c_2_1 234 comib,=,n 2, r31, $fpemu_exit 235 comib,=,n 3, r31, $fpemu_exit 236 comib,=,n 4, r31, $fpemu_exit 237 comib,=,n 5, r31, $fpemu_exit 238 comib,=,n 6, r31, $fpemu_exit 239 comib,=,n 7, r31, $fpemu_exit 240 241$fpemu0c_2_0 242 copy arg2, arg3 243 extru,<> t4, 15, 5, t1 244 ldi 32, t1 245 sh3add t1, arg3, arg1 246 extru t4, 31, 5, arg2 247 FP_TABLE2(fcmp,sgl,dbl,invalid,invalid) 248 249$fpemu0c_2_1 250 comib,<>,n 0, r1, $fpemu_exit 251 252 /* extru t4, 31, 5, arg1 */ 253 /* XXX timex is much more compilicated */ 254 ldw 0(arg2), t1 255 ldi 0, ret0 256 extru,<> t1, 5, 1, r0 257 bv,n r0(rp) 258 259 /* advance the pcqueue */ 260 mtctl r0, pcsq 261 mfctl pcsq, t2 262 mtctl t2, pcsq 263 mtctl t2, pcsq 264 mtctl r0, pcoq 265 mfctl pcoq, t2 266 mtctl t2, pcoq 267 ldo 4(t2), t2 268 bv r0(rp) 269 mtctl t2, pcoq 270 271$fpemu0c_3 272 copy arg2, arg3 273 extru,<> t4, 31, 5, t1 274 ldi 32, t1 275 sh3add t1, arg3, arg2 276 277 comib,=,n 0, r31, $fpemu0c_3_0 278 comib,=,n 1, r31, $fpemu0c_3_1 279 comib,=,n 2, r31, $fpemu0c_3_2 280 comib,=,n 3, r31, $fpemu0c_3_3 281 comib,=,n 4, r31, $fpemu0c_3_4 282 comib,=,n 5, r31, $fpemu_exit 283 comib,=,n 6, r31, $fpemu_exit 284 comib,=,n 7, r31, $fpemu_exit 285 286$fpemu0c_3_0 /* fadd */ 287 FP_TABLE2(fadd,sgl,dbl,invalid,invalid) 288 289$fpemu0c_3_1 /* fsub */ 290 FP_TABLE2(fsub,sgl,dbl,invalid,invalid) 291 292$fpemu0c_3_2 /* fmpy */ 293 FP_TABLE2(fmpy,sgl,dbl,invalid,invalid) 294 295$fpemu0c_3_3 /* fdiv */ 296 FP_TABLE2(fdiv,sgl,dbl,invalid,invalid) 297 298$fpemu0c_3_4 /* frem */ 299 FP_TABLE2(frem,sgl,dbl,invalid,invalid) 300 301 .export $fpemu_exit, code 302$fpemu_exit 303 /* these look very ugly, but we don't want to mess up w/ m4 just 304 * for the sake of overall world prettieness value growth XXX */ 305invalid_fsqrt 306invalid_frnd 307invalid_fcnvff 308invalid_fcnvxf 309invalid_fcnvfx 310invalid_fcnvfxt 311invalid_fcmp 312invalid_fadd 313invalid_fsub 314invalid_fmpy 315invalid_fdiv 316invalid_frem 317 bv,n 0(rp) 318EXIT(fpu_emulate) 319 320 321 .end 322 323