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