1 1.5 andvar /* $NetBSD: fpudispatch.c,v 1.5 2023/09/03 21:43:48 andvar Exp $ */ 2 1.1 fredette 3 1.1 fredette /* 4 1.1 fredette * (c) Copyright 1991 HEWLETT-PACKARD COMPANY 5 1.1 fredette * 6 1.1 fredette * To anyone who acknowledges that this file is provided "AS IS" 7 1.1 fredette * without any express or implied warranty: 8 1.1 fredette * permission to use, copy, modify, and distribute this file 9 1.1 fredette * for any purpose is hereby granted without fee, provided that 10 1.1 fredette * the above copyright notice and this notice appears in all 11 1.1 fredette * copies, and that the name of Hewlett-Packard Company not be 12 1.1 fredette * used in advertising or publicity pertaining to distribution 13 1.1 fredette * of the software without specific, written prior permission. 14 1.1 fredette * Hewlett-Packard Company makes no representations about the 15 1.1 fredette * suitability of this software for any purpose. 16 1.1 fredette */ 17 1.1 fredette 18 1.1 fredette /* Source: /n/schirf/u/baford/CVS/mach4-parisc/kernel/parisc/fpudispatch.c,v 19 1.1 fredette * Revision: 1.4 Author: mike 20 1.1 fredette * State: Exp Locker: 21 1.1 fredette * Date: 1994/07/21 17:36:35 22 1.1 fredette */ 23 1.2 lukem 24 1.2 lukem #include <sys/cdefs.h> 25 1.5 andvar __KERNEL_RCSID(0, "$NetBSD: fpudispatch.c,v 1.5 2023/09/03 21:43:48 andvar Exp $"); 26 1.1 fredette 27 1.1 fredette #include <sys/types.h> 28 1.1 fredette #include <sys/systm.h> 29 1.1 fredette 30 1.1 fredette #include "../spmath/float.h" 31 1.1 fredette /* 32 1.1 fredette * XXX fredette - hack to glue the bulk of 33 1.1 fredette * the spmath library to this dispatcher. 34 1.1 fredette */ 35 1.1 fredette #define dbl_integer unsigned 36 1.1 fredette #define sgl_floating_point unsigned 37 1.1 fredette #define dbl_floating_point unsigned 38 1.1 fredette #include "../spmath/sgl_float.h" 39 1.1 fredette #include "../spmath/dbl_float.h" 40 1.1 fredette #include "../spmath/cnv_float.h" 41 1.1 fredette #include "../spmath/md.h" 42 1.1 fredette #include "../spmath/fpudispatch.h" 43 1.1 fredette 44 1.1 fredette /* 45 1.1 fredette * version of EMULATION software for COPR,0,0 instruction 46 1.1 fredette */ 47 1.1 fredette #define EMULATION_VERSION 3 48 1.1 fredette #define COPR_INST 0x30000000 49 1.1 fredette 50 1.1 fredette /* 51 1.1 fredette * definition of extru macro. If pos and len are constants, the compiler 52 1.1 fredette * will generate an extru instruction when optimized 53 1.1 fredette */ 54 1.1 fredette #define extru(r,pos,len) (((r) >> (31-(pos))) & (( 1 << (len)) - 1)) 55 1.1 fredette /* definitions of bit field locations in the instruction */ 56 1.1 fredette #define fpmajorpos 5 57 1.1 fredette #define fpr1pos 10 58 1.1 fredette #define fpr2pos 15 59 1.1 fredette #define fptpos 31 60 1.1 fredette #define fpsubpos 18 61 1.1 fredette #define fpclass1subpos 16 62 1.1 fredette #define fpclasspos 22 63 1.1 fredette #define fpfmtpos 20 64 1.1 fredette #define fpdfpos 18 65 1.1 fredette /* 66 1.1 fredette * the following are the extra bits for the 0E major op 67 1.1 fredette */ 68 1.1 fredette #define fpxr1pos 24 69 1.1 fredette #define fpxr2pos 19 70 1.1 fredette #define fpxtpos 25 71 1.1 fredette #define fpxpos 23 72 1.1 fredette #define fp0efmtpos 20 73 1.1 fredette /* 74 1.1 fredette * the following are for the multi-ops 75 1.1 fredette */ 76 1.1 fredette #define fprm1pos 10 77 1.1 fredette #define fprm2pos 15 78 1.1 fredette #define fptmpos 31 79 1.1 fredette #define fprapos 25 80 1.1 fredette #define fptapos 20 81 1.1 fredette #define fpmultifmt 26 82 1.1 fredette 83 1.1 fredette /* 84 1.1 fredette * offset to constant zero in the FP emulation registers 85 1.1 fredette */ 86 1.1 fredette #define fpzeroreg (32*sizeof(double)/sizeof(unsigned)) 87 1.1 fredette 88 1.1 fredette /* 89 1.1 fredette * extract the major opcode from the instruction 90 1.1 fredette */ 91 1.1 fredette #define get_major(op) extru(op,fpmajorpos,6) 92 1.1 fredette /* 93 1.1 fredette * extract the two bit class field from the FP instruction. The class is at bit 94 1.1 fredette * positions 21-22 95 1.1 fredette */ 96 1.1 fredette #define get_class(op) extru(op,fpclasspos,2) 97 1.1 fredette /* 98 1.1 fredette * extract the 3 bit subop field. For all but class 1 instructions, it is 99 1.1 fredette * located at bit positions 16-18 100 1.1 fredette */ 101 1.1 fredette #define get_subop(op) extru(op,fpsubpos,3) 102 1.1 fredette /* 103 1.1 fredette * extract the 2 bit subop field from class 1 instructions. It is located 104 1.1 fredette * at bit positions 15-16 105 1.1 fredette */ 106 1.1 fredette #define get_subop1(op) extru(op,fpclass1subpos,2) 107 1.1 fredette 108 1.1 fredette /* definitions of unimplemented exceptions */ 109 1.1 fredette #define MAJOR_0C_EXCP UNIMPLEMENTEDEXCEPTION 110 1.1 fredette #define MAJOR_0E_EXCP UNIMPLEMENTEDEXCEPTION 111 1.1 fredette #define MAJOR_06_EXCP UNIMPLEMENTEDEXCEPTION 112 1.1 fredette #define MAJOR_26_EXCP UNIMPLEMENTEDEXCEPTION 113 1.1 fredette #define PA83_UNIMP_EXCP UNIMPLEMENTEDEXCEPTION 114 1.1 fredette 115 1.1 fredette int 116 1.4 dsl decode_0c(unsigned ir,unsigned class,unsigned subop,unsigned fpregs[]) 117 1.1 fredette { 118 1.1 fredette unsigned r1,r2,t; /* operand register offsets */ 119 1.1 fredette unsigned fmt; /* also sf for class 1 conversions */ 120 1.1 fredette unsigned df; /* for class 1 conversions */ 121 1.1 fredette unsigned *status; 122 1.1 fredette 123 1.1 fredette if (ir == COPR_INST) { 124 1.1 fredette fpregs[0] = EMULATION_VERSION << 11; 125 1.1 fredette return(NOEXCEPTION); 126 1.1 fredette } 127 1.1 fredette status = &fpregs[0]; /* fp status register */ 128 1.1 fredette r1 = extru(ir,fpr1pos,5) * sizeof(double)/sizeof(unsigned); 129 1.1 fredette if (r1 == 0) /* map fr0 source to constant zero */ 130 1.1 fredette r1 = fpzeroreg; 131 1.1 fredette t = extru(ir,fptpos,5) * sizeof(double)/sizeof(unsigned); 132 1.1 fredette if (t == 0 && class != 2) /* don't allow fr0 as a dest */ 133 1.1 fredette return(MAJOR_0C_EXCP); 134 1.1 fredette fmt = extru(ir,fpfmtpos,2); /* get fmt completer */ 135 1.1 fredette 136 1.1 fredette switch (class) { 137 1.1 fredette case 0: 138 1.1 fredette switch (subop) { 139 1.1 fredette case 0: /* COPR 0,0 emulated above*/ 140 1.1 fredette case 1: 141 1.1 fredette case 6: 142 1.1 fredette case 7: 143 1.1 fredette return(MAJOR_0C_EXCP); 144 1.1 fredette case 2: /* FCPY */ 145 1.1 fredette switch (fmt) { 146 1.1 fredette case 2: /* illegal */ 147 1.1 fredette return(MAJOR_0C_EXCP); 148 1.1 fredette case 3: /* quad */ 149 1.1 fredette fpregs[t+3] = fpregs[r1+3]; 150 1.1 fredette fpregs[t+2] = fpregs[r1+2]; 151 1.1 fredette case 1: /* double */ 152 1.1 fredette fpregs[t+1] = fpregs[r1+1]; 153 1.1 fredette case 0: /* single */ 154 1.1 fredette fpregs[t] = fpregs[r1]; 155 1.1 fredette return(NOEXCEPTION); 156 1.1 fredette } 157 1.1 fredette case 3: /* FABS */ 158 1.1 fredette switch (fmt) { 159 1.1 fredette case 2: /* illegal */ 160 1.1 fredette return(MAJOR_0C_EXCP); 161 1.1 fredette case 3: /* quad */ 162 1.1 fredette fpregs[t+3] = fpregs[r1+3]; 163 1.1 fredette fpregs[t+2] = fpregs[r1+2]; 164 1.1 fredette case 1: /* double */ 165 1.1 fredette fpregs[t+1] = fpregs[r1+1]; 166 1.1 fredette case 0: /* single */ 167 1.1 fredette /* copy and clear sign bit */ 168 1.1 fredette fpregs[t] = fpregs[r1] & 0x7fffffff; 169 1.1 fredette return(NOEXCEPTION); 170 1.1 fredette } 171 1.1 fredette case 4: /* FSQRT */ 172 1.1 fredette switch (fmt) { 173 1.1 fredette case 0: 174 1.1 fredette return(sgl_fsqrt(&fpregs[r1], 175 1.1 fredette &fpregs[t],status)); 176 1.1 fredette case 1: 177 1.1 fredette return(dbl_fsqrt(&fpregs[r1], 178 1.1 fredette &fpregs[t],status)); 179 1.1 fredette case 2: 180 1.1 fredette case 3: /* quad not implemented */ 181 1.1 fredette return(MAJOR_0C_EXCP); 182 1.1 fredette } 183 1.1 fredette case 5: /* FRND */ 184 1.1 fredette switch (fmt) { 185 1.1 fredette case 0: 186 1.1 fredette return(sgl_frnd(&fpregs[r1], 187 1.1 fredette &fpregs[t],status)); 188 1.1 fredette case 1: 189 1.1 fredette return(dbl_frnd(&fpregs[r1], 190 1.1 fredette &fpregs[t],status)); 191 1.1 fredette case 2: 192 1.1 fredette case 3: /* quad not implemented */ 193 1.1 fredette return(MAJOR_0C_EXCP); 194 1.1 fredette } 195 1.1 fredette } /* end of switch (subop) */ 196 1.1 fredette 197 1.1 fredette case 1: /* class 1 */ 198 1.1 fredette df = extru(ir,fpdfpos,2); /* get dest format */ 199 1.1 fredette if ((df & 2) || (fmt & 2)) { 200 1.1 fredette /* 201 1.1 fredette * fmt's 2 and 3 are illegal of not implemented 202 1.1 fredette * quad conversions 203 1.1 fredette */ 204 1.1 fredette return(MAJOR_0C_EXCP); 205 1.1 fredette } 206 1.1 fredette /* 207 1.1 fredette * encode source and dest formats into 2 bits. 208 1.1 fredette * high bit is source, low bit is dest. 209 1.1 fredette * bit = 1 --> double precision 210 1.1 fredette */ 211 1.1 fredette fmt = (fmt << 1) | df; 212 1.1 fredette switch (subop) { 213 1.1 fredette case 0: /* FCNVFF */ 214 1.1 fredette switch(fmt) { 215 1.1 fredette case 0: /* sgl/sgl */ 216 1.1 fredette return(MAJOR_0C_EXCP); 217 1.1 fredette case 1: /* sgl/dbl */ 218 1.1 fredette return(sgl_to_dbl_fcnvff(&fpregs[r1], 219 1.1 fredette &fpregs[t],status)); 220 1.1 fredette case 2: /* dbl/sgl */ 221 1.1 fredette return(dbl_to_sgl_fcnvff(&fpregs[r1], 222 1.1 fredette &fpregs[t],status)); 223 1.1 fredette case 3: /* dbl/dbl */ 224 1.1 fredette return(MAJOR_0C_EXCP); 225 1.1 fredette } 226 1.1 fredette case 1: /* FCNVXF */ 227 1.1 fredette switch(fmt) { 228 1.1 fredette case 0: /* sgl/sgl */ 229 1.1 fredette return(sgl_to_sgl_fcnvxf(&fpregs[r1], 230 1.1 fredette &fpregs[t],status)); 231 1.1 fredette case 1: /* sgl/dbl */ 232 1.1 fredette return(sgl_to_dbl_fcnvxf(&fpregs[r1], 233 1.1 fredette &fpregs[t],status)); 234 1.1 fredette case 2: /* dbl/sgl */ 235 1.1 fredette return(dbl_to_sgl_fcnvxf(&fpregs[r1], 236 1.1 fredette &fpregs[t],status)); 237 1.1 fredette case 3: /* dbl/dbl */ 238 1.1 fredette return(dbl_to_dbl_fcnvxf(&fpregs[r1], 239 1.1 fredette &fpregs[t],status)); 240 1.1 fredette } 241 1.1 fredette case 2: /* FCNVFX */ 242 1.1 fredette switch(fmt) { 243 1.1 fredette case 0: /* sgl/sgl */ 244 1.1 fredette return(sgl_to_sgl_fcnvfx(&fpregs[r1], 245 1.1 fredette &fpregs[t],status)); 246 1.1 fredette case 1: /* sgl/dbl */ 247 1.1 fredette return(sgl_to_dbl_fcnvfx(&fpregs[r1], 248 1.1 fredette &fpregs[t],status)); 249 1.1 fredette case 2: /* dbl/sgl */ 250 1.1 fredette return(dbl_to_sgl_fcnvfx(&fpregs[r1], 251 1.1 fredette &fpregs[t],status)); 252 1.1 fredette case 3: /* dbl/dbl */ 253 1.1 fredette return(dbl_to_dbl_fcnvfx(&fpregs[r1], 254 1.1 fredette &fpregs[t],status)); 255 1.1 fredette } 256 1.1 fredette case 3: /* FCNVFXT */ 257 1.1 fredette switch(fmt) { 258 1.1 fredette case 0: /* sgl/sgl */ 259 1.1 fredette return(sgl_to_sgl_fcnvfxt(&fpregs[r1], 260 1.1 fredette &fpregs[t],status)); 261 1.1 fredette case 1: /* sgl/dbl */ 262 1.1 fredette return(sgl_to_dbl_fcnvfxt(&fpregs[r1], 263 1.1 fredette &fpregs[t],status)); 264 1.1 fredette case 2: /* dbl/sgl */ 265 1.1 fredette return(dbl_to_sgl_fcnvfxt(&fpregs[r1], 266 1.1 fredette &fpregs[t],status)); 267 1.1 fredette case 3: /* dbl/dbl */ 268 1.1 fredette return(dbl_to_dbl_fcnvfxt(&fpregs[r1], 269 1.1 fredette &fpregs[t],status)); 270 1.1 fredette } 271 1.1 fredette } /* end of switch subop */ 272 1.1 fredette 273 1.1 fredette case 2: /* class 2 */ 274 1.1 fredette r2 = extru(ir, fpr2pos, 5) * sizeof(double)/sizeof(unsigned); 275 1.1 fredette if (r2 == 0) 276 1.1 fredette r2 = fpzeroreg; 277 1.1 fredette switch (subop) { 278 1.1 fredette case 2: 279 1.1 fredette case 3: 280 1.1 fredette case 4: 281 1.1 fredette case 5: 282 1.1 fredette case 6: 283 1.1 fredette case 7: 284 1.1 fredette return(MAJOR_0C_EXCP); 285 1.1 fredette case 0: /* FCMP */ 286 1.1 fredette switch (fmt) { 287 1.1 fredette case 0: 288 1.1 fredette return(sgl_fcmp(&fpregs[r1],&fpregs[r2], 289 1.1 fredette extru(ir,fptpos,5),status)); 290 1.1 fredette case 1: 291 1.1 fredette return(dbl_fcmp(&fpregs[r1],&fpregs[r2], 292 1.1 fredette extru(ir,fptpos,5),status)); 293 1.1 fredette case 2: /* illegal */ 294 1.1 fredette case 3: /* quad not implemented */ 295 1.1 fredette return(MAJOR_0C_EXCP); 296 1.1 fredette } 297 1.1 fredette case 1: /* FTEST */ 298 1.1 fredette switch (fmt) { 299 1.1 fredette case 0: 300 1.1 fredette /* 301 1.1 fredette * arg0 is not used 302 1.1 fredette * second param is the t field used for 303 1.1 fredette * ftest,acc and ftest,rej 304 1.1 fredette */ 305 1.1 fredette /* XXX fredette - broken */ 306 1.1 fredette #if 0 307 1.1 fredette return(ftest(0,extru(ir,fptpos,5), 308 1.1 fredette &fpregs[0])); 309 1.1 fredette #else 310 1.1 fredette panic("ftest"); 311 1.1 fredette #endif 312 1.1 fredette case 1: 313 1.1 fredette case 2: 314 1.1 fredette case 3: 315 1.1 fredette return(MAJOR_0C_EXCP); 316 1.1 fredette } 317 1.1 fredette } /* end if switch for class 2*/ 318 1.1 fredette case 3: /* class 3 */ 319 1.1 fredette r2 = extru(ir,fpr2pos,5) * sizeof(double)/sizeof(unsigned); 320 1.1 fredette if (r2 == 0) 321 1.1 fredette r2 = fpzeroreg; 322 1.1 fredette switch (subop) { 323 1.1 fredette case 5: 324 1.1 fredette case 6: 325 1.1 fredette case 7: 326 1.1 fredette return(MAJOR_0C_EXCP); 327 1.1 fredette 328 1.1 fredette case 0: /* FADD */ 329 1.1 fredette switch (fmt) { 330 1.1 fredette case 0: 331 1.1 fredette return(sgl_fadd(&fpregs[r1],&fpregs[r2], 332 1.1 fredette &fpregs[t],status)); 333 1.1 fredette case 1: 334 1.1 fredette return(dbl_fadd(&fpregs[r1],&fpregs[r2], 335 1.1 fredette &fpregs[t],status)); 336 1.1 fredette case 2: /* illegal */ 337 1.1 fredette case 3: /* quad not implemented */ 338 1.1 fredette return(MAJOR_0C_EXCP); 339 1.1 fredette } 340 1.1 fredette case 1: /* FSUB */ 341 1.1 fredette switch (fmt) { 342 1.1 fredette case 0: 343 1.1 fredette return(sgl_fsub(&fpregs[r1],&fpregs[r2], 344 1.1 fredette &fpregs[t],status)); 345 1.1 fredette case 1: 346 1.1 fredette return(dbl_fsub(&fpregs[r1],&fpregs[r2], 347 1.1 fredette &fpregs[t],status)); 348 1.1 fredette case 2: /* illegal */ 349 1.1 fredette case 3: /* quad not implemented */ 350 1.1 fredette return(MAJOR_0C_EXCP); 351 1.1 fredette } 352 1.1 fredette case 2: /* FMPY */ 353 1.1 fredette switch (fmt) { 354 1.1 fredette case 0: 355 1.1 fredette return(sgl_fmpy(&fpregs[r1],&fpregs[r2], 356 1.1 fredette &fpregs[t],status)); 357 1.1 fredette case 1: 358 1.1 fredette return(dbl_fmpy(&fpregs[r1],&fpregs[r2], 359 1.1 fredette &fpregs[t],status)); 360 1.1 fredette case 2: /* illegal */ 361 1.1 fredette case 3: /* quad not implemented */ 362 1.1 fredette return(MAJOR_0C_EXCP); 363 1.1 fredette } 364 1.1 fredette case 3: /* FDIV */ 365 1.1 fredette switch (fmt) { 366 1.1 fredette case 0: 367 1.1 fredette return(sgl_fdiv(&fpregs[r1],&fpregs[r2], 368 1.1 fredette &fpregs[t],status)); 369 1.1 fredette case 1: 370 1.1 fredette return(dbl_fdiv(&fpregs[r1],&fpregs[r2], 371 1.1 fredette &fpregs[t],status)); 372 1.1 fredette case 2: /* illegal */ 373 1.1 fredette case 3: /* quad not implemented */ 374 1.1 fredette return(MAJOR_0C_EXCP); 375 1.1 fredette } 376 1.1 fredette case 4: /* FREM */ 377 1.1 fredette switch (fmt) { 378 1.1 fredette case 0: 379 1.1 fredette return(sgl_frem(&fpregs[r1],&fpregs[r2], 380 1.1 fredette &fpregs[t],status)); 381 1.1 fredette case 1: 382 1.1 fredette return(dbl_frem(&fpregs[r1],&fpregs[r2], 383 1.1 fredette &fpregs[t],status)); 384 1.1 fredette case 2: /* illegal */ 385 1.1 fredette case 3: /* quad not implemented */ 386 1.1 fredette return(MAJOR_0C_EXCP); 387 1.1 fredette } 388 1.1 fredette } /* end of class 3 switch */ 389 1.1 fredette } /* end of switch(class) */ 390 1.1 fredette panic("decode_0c"); 391 1.1 fredette } 392 1.1 fredette 393 1.1 fredette int 394 1.4 dsl decode_0e(unsigned ir,unsigned class,unsigned subop,unsigned fpregs[]) 395 1.1 fredette { 396 1.1 fredette unsigned r1,r2,t; /* operand register offsets */ 397 1.1 fredette unsigned fmt; /* also sf for class 1 conversions */ 398 1.1 fredette unsigned df; /* dest format for class 1 conversions */ 399 1.1 fredette unsigned *status; 400 1.1 fredette 401 1.1 fredette status = &fpregs[0]; 402 1.1 fredette r1 = ((extru(ir,fpr1pos,5)<<1)|(extru(ir,fpxr1pos,1))); 403 1.1 fredette if (r1 == 0) 404 1.1 fredette r1 = fpzeroreg; 405 1.1 fredette t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1))); 406 1.1 fredette if (t == 0 && class != 2) 407 1.1 fredette return(MAJOR_0E_EXCP); 408 1.1 fredette if (class < 2) /* class 0 or 1 has 2 bit fmt */ 409 1.1 fredette fmt = extru(ir,fpfmtpos,2); 410 1.1 fredette else /* class 2 and 3 have 1 bit fmt */ 411 1.1 fredette fmt = extru(ir,fp0efmtpos,1); 412 1.1 fredette 413 1.1 fredette switch (class) { 414 1.1 fredette case 0: 415 1.1 fredette switch (subop) { 416 1.1 fredette case 0: /* unimplemented */ 417 1.1 fredette case 1: 418 1.1 fredette case 6: 419 1.1 fredette case 7: 420 1.1 fredette return(MAJOR_0E_EXCP); 421 1.1 fredette case 2: /* FCPY */ 422 1.1 fredette switch (fmt) { 423 1.1 fredette case 2: 424 1.1 fredette case 3: 425 1.1 fredette return(MAJOR_0E_EXCP); 426 1.1 fredette case 1: /* double */ 427 1.1 fredette fpregs[t+1] = fpregs[r1+1]; 428 1.1 fredette case 0: /* single */ 429 1.1 fredette fpregs[t] = fpregs[r1]; 430 1.1 fredette return(NOEXCEPTION); 431 1.1 fredette } 432 1.1 fredette case 3: /* FABS */ 433 1.1 fredette switch (fmt) { 434 1.1 fredette case 2: 435 1.1 fredette case 3: 436 1.1 fredette return(MAJOR_0E_EXCP); 437 1.1 fredette case 1: /* double */ 438 1.1 fredette fpregs[t+1] = fpregs[r1+1]; 439 1.1 fredette case 0: /* single */ 440 1.1 fredette fpregs[t] = fpregs[r1] & 0x7fffffff; 441 1.1 fredette return(NOEXCEPTION); 442 1.1 fredette } 443 1.1 fredette case 4: /* FSQRT */ 444 1.1 fredette switch (fmt) { 445 1.1 fredette case 0: 446 1.1 fredette return(sgl_fsqrt(&fpregs[r1], 447 1.1 fredette &fpregs[t], status)); 448 1.1 fredette case 1: 449 1.1 fredette return(dbl_fsqrt(&fpregs[r1], 450 1.1 fredette &fpregs[t], status)); 451 1.1 fredette case 2: 452 1.1 fredette case 3: 453 1.1 fredette return(MAJOR_0E_EXCP); 454 1.1 fredette } 455 1.1 fredette case 5: /* FRMD */ 456 1.1 fredette switch (fmt) { 457 1.1 fredette case 0: 458 1.1 fredette return(sgl_frnd(&fpregs[r1], 459 1.1 fredette &fpregs[t], status)); 460 1.1 fredette case 1: 461 1.1 fredette return(dbl_frnd(&fpregs[r1], 462 1.1 fredette &fpregs[t], status)); 463 1.1 fredette case 2: 464 1.1 fredette case 3: 465 1.1 fredette return(MAJOR_0E_EXCP); 466 1.1 fredette } 467 1.1 fredette } /* end of switch (subop */ 468 1.1 fredette 469 1.1 fredette case 1: /* class 1 */ 470 1.1 fredette df = extru(ir,fpdfpos,2); /* get dest format */ 471 1.1 fredette if ((df & 2) || (fmt & 2)) 472 1.1 fredette return(MAJOR_0E_EXCP); 473 1.1 fredette 474 1.1 fredette fmt = (fmt << 1) | df; 475 1.1 fredette switch (subop) { 476 1.1 fredette case 0: /* FCNVFF */ 477 1.1 fredette switch(fmt) { 478 1.1 fredette case 0: /* sgl/sgl */ 479 1.1 fredette return(MAJOR_0E_EXCP); 480 1.1 fredette case 1: /* sgl/dbl */ 481 1.1 fredette return(sgl_to_dbl_fcnvff(&fpregs[r1], 482 1.1 fredette &fpregs[t],status)); 483 1.1 fredette case 2: /* dbl/sgl */ 484 1.1 fredette return(dbl_to_sgl_fcnvff(&fpregs[r1], 485 1.1 fredette &fpregs[t],status)); 486 1.1 fredette case 3: /* dbl/dbl */ 487 1.1 fredette return(MAJOR_0E_EXCP); 488 1.1 fredette } 489 1.1 fredette case 1: /* FCNVXF */ 490 1.1 fredette switch(fmt) { 491 1.1 fredette case 0: /* sgl/sgl */ 492 1.1 fredette return(sgl_to_sgl_fcnvxf(&fpregs[r1], 493 1.1 fredette &fpregs[t],status)); 494 1.1 fredette case 1: /* sgl/dbl */ 495 1.1 fredette return(sgl_to_dbl_fcnvxf(&fpregs[r1], 496 1.1 fredette &fpregs[t],status)); 497 1.1 fredette case 2: /* dbl/sgl */ 498 1.1 fredette return(dbl_to_sgl_fcnvxf(&fpregs[r1], 499 1.1 fredette &fpregs[t],status)); 500 1.1 fredette case 3: /* dbl/dbl */ 501 1.1 fredette return(dbl_to_dbl_fcnvxf(&fpregs[r1], 502 1.1 fredette &fpregs[t],status)); 503 1.1 fredette } 504 1.1 fredette case 2: /* FCNVFX */ 505 1.1 fredette switch(fmt) { 506 1.1 fredette case 0: /* sgl/sgl */ 507 1.1 fredette return(sgl_to_sgl_fcnvfx(&fpregs[r1], 508 1.1 fredette &fpregs[t],status)); 509 1.1 fredette case 1: /* sgl/dbl */ 510 1.1 fredette return(sgl_to_dbl_fcnvfx(&fpregs[r1], 511 1.1 fredette &fpregs[t],status)); 512 1.1 fredette case 2: /* dbl/sgl */ 513 1.1 fredette return(dbl_to_sgl_fcnvfx(&fpregs[r1], 514 1.1 fredette &fpregs[t],status)); 515 1.1 fredette case 3: /* dbl/dbl */ 516 1.1 fredette return(dbl_to_dbl_fcnvfx(&fpregs[r1], 517 1.1 fredette &fpregs[t],status)); 518 1.1 fredette } 519 1.1 fredette case 3: /* FCNVFXT */ 520 1.1 fredette switch(fmt) { 521 1.1 fredette case 0: /* sgl/sgl */ 522 1.1 fredette return(sgl_to_sgl_fcnvfxt(&fpregs[r1], 523 1.1 fredette &fpregs[t],status)); 524 1.1 fredette case 1: /* sgl/dbl */ 525 1.1 fredette return(sgl_to_dbl_fcnvfxt(&fpregs[r1], 526 1.1 fredette &fpregs[t],status)); 527 1.1 fredette case 2: /* dbl/sgl */ 528 1.1 fredette return(dbl_to_sgl_fcnvfxt(&fpregs[r1], 529 1.1 fredette &fpregs[t],status)); 530 1.1 fredette case 3: /* dbl/dbl */ 531 1.1 fredette return(dbl_to_dbl_fcnvfxt(&fpregs[r1], 532 1.1 fredette &fpregs[t],status)); 533 1.1 fredette } 534 1.1 fredette } /* end of switch subop */ 535 1.1 fredette case 2: /* class 2 */ 536 1.1 fredette r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1))); 537 1.1 fredette if (r2 == 0) 538 1.1 fredette r2 = fpzeroreg; 539 1.1 fredette switch (subop) { 540 1.1 fredette case 1: 541 1.1 fredette case 2: 542 1.1 fredette case 3: 543 1.1 fredette case 4: 544 1.1 fredette case 5: 545 1.1 fredette case 6: 546 1.1 fredette case 7: 547 1.1 fredette return(MAJOR_0E_EXCP); 548 1.1 fredette case 0: /* FCMP */ 549 1.1 fredette switch (fmt) { 550 1.1 fredette /* 551 1.1 fredette * fmt is only 1 bit long 552 1.1 fredette */ 553 1.1 fredette case 0: 554 1.1 fredette return(sgl_fcmp(&fpregs[r1],&fpregs[r2], 555 1.1 fredette extru(ir,fptpos,5),status)); 556 1.1 fredette case 1: 557 1.1 fredette return(dbl_fcmp(&fpregs[r1],&fpregs[r2], 558 1.1 fredette extru(ir,fptpos,5),status)); 559 1.1 fredette } 560 1.1 fredette } /* end of switch for class 2 */ 561 1.1 fredette case 3: /* class 3 */ 562 1.1 fredette r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1))); 563 1.1 fredette if (r2 == 0) 564 1.1 fredette r2 = fpzeroreg; 565 1.1 fredette switch (subop) { 566 1.1 fredette case 5: 567 1.1 fredette case 6: 568 1.1 fredette case 7: 569 1.1 fredette return(MAJOR_0E_EXCP); 570 1.1 fredette 571 1.1 fredette /* 572 1.1 fredette * Note that fmt is only 1 bit for class 3 */ 573 1.1 fredette case 0: /* FADD */ 574 1.1 fredette switch (fmt) { 575 1.1 fredette case 0: 576 1.1 fredette return(sgl_fadd(&fpregs[r1],&fpregs[r2], 577 1.1 fredette &fpregs[t],status)); 578 1.1 fredette case 1: 579 1.1 fredette return(dbl_fadd(&fpregs[r1],&fpregs[r2], 580 1.1 fredette &fpregs[t],status)); 581 1.1 fredette } 582 1.1 fredette case 1: /* FSUB */ 583 1.1 fredette switch (fmt) { 584 1.1 fredette case 0: 585 1.1 fredette return(sgl_fsub(&fpregs[r1],&fpregs[r2], 586 1.1 fredette &fpregs[t],status)); 587 1.1 fredette case 1: 588 1.1 fredette return(dbl_fsub(&fpregs[r1],&fpregs[r2], 589 1.1 fredette &fpregs[t],status)); 590 1.1 fredette } 591 1.1 fredette case 2: /* FMPY or XMPYU */ 592 1.1 fredette /* 593 1.1 fredette * check for integer multiply (x bit set) 594 1.1 fredette */ 595 1.1 fredette if (extru(ir,fpxpos,1)) { 596 1.1 fredette /* 597 1.1 fredette * emulate XMPYU 598 1.1 fredette */ 599 1.1 fredette switch (fmt) { 600 1.1 fredette case 0: 601 1.1 fredette /* 602 1.1 fredette * bad instruction if t specifies 603 1.1 fredette * the right half of a register 604 1.1 fredette */ 605 1.1 fredette if (t & 1) 606 1.1 fredette return(MAJOR_0E_EXCP); 607 1.1 fredette /* XXX fredette - broken. */ 608 1.1 fredette #if 0 609 1.1 fredette impyu(&fpregs[r1],&fpregs[r2], 610 1.1 fredette &fpregs[t]); 611 1.1 fredette return(NOEXCEPTION); 612 1.1 fredette #else 613 1.1 fredette panic("impyu"); 614 1.1 fredette #endif 615 1.1 fredette case 1: 616 1.1 fredette return(MAJOR_0E_EXCP); 617 1.1 fredette } 618 1.1 fredette } 619 1.1 fredette else { /* FMPY */ 620 1.1 fredette switch (fmt) { 621 1.1 fredette case 0: 622 1.1 fredette return(sgl_fmpy(&fpregs[r1], 623 1.1 fredette &fpregs[r2],&fpregs[t],status)); 624 1.1 fredette case 1: 625 1.1 fredette return(dbl_fmpy(&fpregs[r1], 626 1.1 fredette &fpregs[r2],&fpregs[t],status)); 627 1.1 fredette } 628 1.1 fredette } 629 1.1 fredette case 3: /* FDIV */ 630 1.1 fredette switch (fmt) { 631 1.1 fredette case 0: 632 1.1 fredette return(sgl_fdiv(&fpregs[r1],&fpregs[r2], 633 1.1 fredette &fpregs[t],status)); 634 1.1 fredette case 1: 635 1.1 fredette return(dbl_fdiv(&fpregs[r1],&fpregs[r2], 636 1.1 fredette &fpregs[t],status)); 637 1.1 fredette } 638 1.1 fredette case 4: /* FREM */ 639 1.1 fredette switch (fmt) { 640 1.1 fredette case 0: 641 1.1 fredette return(sgl_frem(&fpregs[r1],&fpregs[r2], 642 1.1 fredette &fpregs[t],status)); 643 1.1 fredette case 1: 644 1.1 fredette return(dbl_frem(&fpregs[r1],&fpregs[r2], 645 1.1 fredette &fpregs[t],status)); 646 1.1 fredette } 647 1.1 fredette } /* end of class 3 switch */ 648 1.1 fredette } /* end of switch(class) */ 649 1.1 fredette panic("decode_0e"); 650 1.1 fredette } 651 1.1 fredette 652 1.1 fredette 653 1.1 fredette /* 654 1.1 fredette * routine to decode the 06 (FMPYADD and FMPYCFXT) instruction 655 1.1 fredette */ 656 1.1 fredette int 657 1.4 dsl decode_06(unsigned ir,unsigned fpregs[]) 658 1.1 fredette { 659 1.1 fredette unsigned rm1, rm2, tm, ra, ta; /* operands */ 660 1.1 fredette unsigned fmt; 661 1.1 fredette unsigned error = 0; 662 1.1 fredette unsigned status; 663 1.1 fredette union { 664 1.1 fredette double dbl; 665 1.1 fredette float flt; 666 1.1 fredette struct { unsigned i1; unsigned i2; } ints; 667 1.1 fredette } mtmp, atmp; 668 1.1 fredette 669 1.1 fredette 670 1.1 fredette status = fpregs[0]; /* use a local copy of status reg */ 671 1.1 fredette fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */ 672 1.1 fredette if (fmt == 0) { /* DBL */ 673 1.1 fredette rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(unsigned); 674 1.1 fredette if (rm1 == 0) 675 1.1 fredette rm1 = fpzeroreg; 676 1.1 fredette rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(unsigned); 677 1.1 fredette if (rm2 == 0) 678 1.1 fredette rm2 = fpzeroreg; 679 1.1 fredette tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(unsigned); 680 1.1 fredette if (tm == 0) 681 1.1 fredette return(MAJOR_06_EXCP); 682 1.1 fredette ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(unsigned); 683 1.1 fredette ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(unsigned); 684 1.1 fredette if (ta == 0) 685 1.1 fredette return(MAJOR_06_EXCP); 686 1.1 fredette 687 1.1 fredette #ifdef TIMEX 688 1.1 fredette if (ra == 0) { 689 1.1 fredette /* special case FMPYCFXT */ 690 1.1 fredette if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],(unsigned *) &mtmp, 691 1.1 fredette &status)) 692 1.1 fredette error = 1; 693 1.1 fredette if (dbl_to_sgl_fcnvfxt(&fpregs[ta],(unsigned *) &atmp, 694 1.5 andvar &status)) 695 1.1 fredette error = 1; 696 1.1 fredette } 697 1.1 fredette else { 698 1.1 fredette #else 699 1.1 fredette if (ra == 0) 700 1.1 fredette ra = fpzeroreg; 701 1.1 fredette #endif 702 1.1 fredette 703 1.1 fredette if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],(unsigned *) &mtmp, 704 1.1 fredette &status)) 705 1.1 fredette error = 1; 706 1.1 fredette if (dbl_fadd(&fpregs[ta], &fpregs[ra], (unsigned *) &atmp, 707 1.1 fredette &status)) 708 1.1 fredette error = 1; 709 1.1 fredette #ifdef TIMEX 710 1.1 fredette } 711 1.1 fredette #endif 712 1.1 fredette if (error) 713 1.1 fredette return(MAJOR_06_EXCP); 714 1.1 fredette else { 715 1.1 fredette /* copy results */ 716 1.1 fredette fpregs[tm] = mtmp.ints.i1; 717 1.1 fredette fpregs[tm+1] = mtmp.ints.i2; 718 1.1 fredette fpregs[ta] = atmp.ints.i1; 719 1.1 fredette fpregs[ta+1] = atmp.ints.i2; 720 1.1 fredette fpregs[0] = status; 721 1.1 fredette return(NOEXCEPTION); 722 1.1 fredette } 723 1.1 fredette } 724 1.1 fredette else { /* SGL */ 725 1.1 fredette /* 726 1.1 fredette * calculate offsets for single precision numbers 727 1.1 fredette * See table 6-14 in PA-89 architecture for mapping 728 1.1 fredette */ 729 1.1 fredette rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */ 730 1.1 fredette rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */ 731 1.1 fredette 732 1.1 fredette rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */ 733 1.1 fredette rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */ 734 1.1 fredette 735 1.1 fredette tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */ 736 1.1 fredette tm |= extru(ir,fptmpos-4,1); /* add right word offset */ 737 1.1 fredette 738 1.1 fredette ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */ 739 1.1 fredette ra |= extru(ir,fprapos-4,1); /* add right word offset */ 740 1.1 fredette 741 1.1 fredette ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */ 742 1.1 fredette ta |= extru(ir,fptapos-4,1); /* add right word offset */ 743 1.1 fredette 744 1.1 fredette if (ra == 0x20) { /* special case FMPYCFXT (really 0) */ 745 1.1 fredette if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],(unsigned *) &mtmp, 746 1.1 fredette &status)) 747 1.1 fredette error = 1; 748 1.1 fredette /* XXX fredette - this is broken */ 749 1.1 fredette #if 0 750 1.1 fredette if (sgl_to_sgl_fcnvfxt(&fpregs[ta],(unsigned *) &atmp, 751 1.1 fredette (unsigned *) &atmp,&status)) 752 1.1 fredette error = 1; 753 1.1 fredette #else 754 1.1 fredette panic("FMPYADD"); 755 1.1 fredette #endif 756 1.1 fredette } 757 1.1 fredette else { 758 1.1 fredette if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],(unsigned *) &mtmp, 759 1.1 fredette &status)) 760 1.1 fredette error = 1; 761 1.1 fredette if (sgl_fadd(&fpregs[ta], &fpregs[ra], (unsigned *) &atmp, 762 1.1 fredette &status)) 763 1.1 fredette error = 1; 764 1.1 fredette } 765 1.1 fredette if (error) 766 1.1 fredette return(MAJOR_06_EXCP); 767 1.1 fredette else { 768 1.1 fredette /* copy results */ 769 1.1 fredette fpregs[tm] = mtmp.ints.i1; 770 1.1 fredette fpregs[ta] = atmp.ints.i1; 771 1.1 fredette fpregs[0] = status; 772 1.1 fredette return(NOEXCEPTION); 773 1.1 fredette } 774 1.1 fredette } 775 1.1 fredette } 776 1.1 fredette 777 1.1 fredette /* 778 1.1 fredette * routine to decode the 26 (FMPYSUB) instruction 779 1.1 fredette */ 780 1.1 fredette int 781 1.4 dsl decode_26(unsigned ir,unsigned fpregs[]) 782 1.1 fredette { 783 1.1 fredette unsigned rm1, rm2, tm, ra, ta; /* operands */ 784 1.1 fredette unsigned fmt; 785 1.1 fredette unsigned error = 0; 786 1.1 fredette unsigned status; 787 1.1 fredette union { 788 1.1 fredette double dbl; 789 1.1 fredette float flt; 790 1.1 fredette struct { unsigned i1; unsigned i2; } ints; 791 1.1 fredette } mtmp, atmp; 792 1.1 fredette 793 1.1 fredette 794 1.1 fredette status = fpregs[0]; 795 1.1 fredette fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */ 796 1.1 fredette if (fmt == 0) { /* DBL */ 797 1.1 fredette rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(unsigned); 798 1.1 fredette if (rm1 == 0) 799 1.1 fredette rm1 = fpzeroreg; 800 1.1 fredette rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(unsigned); 801 1.1 fredette if (rm2 == 0) 802 1.1 fredette rm2 = fpzeroreg; 803 1.1 fredette tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(unsigned); 804 1.1 fredette if (tm == 0) 805 1.1 fredette return(MAJOR_26_EXCP); 806 1.1 fredette ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(unsigned); 807 1.1 fredette if (ra == 0) 808 1.1 fredette return(MAJOR_26_EXCP); 809 1.1 fredette ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(unsigned); 810 1.1 fredette if (ta == 0) 811 1.1 fredette return(MAJOR_26_EXCP); 812 1.1 fredette 813 1.1 fredette if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],(unsigned *) &mtmp, 814 1.1 fredette &status)) 815 1.1 fredette error = 1; 816 1.1 fredette if (dbl_fsub(&fpregs[ta], &fpregs[ra], (unsigned *) &atmp, 817 1.1 fredette &status)) 818 1.1 fredette error = 1; 819 1.1 fredette if (error) 820 1.1 fredette return(MAJOR_26_EXCP); 821 1.1 fredette else { 822 1.1 fredette /* copy results */ 823 1.1 fredette fpregs[tm] = mtmp.ints.i1; 824 1.1 fredette fpregs[tm+1] = mtmp.ints.i2; 825 1.1 fredette fpregs[ta] = atmp.ints.i1; 826 1.1 fredette fpregs[ta+1] = atmp.ints.i2; 827 1.1 fredette fpregs[0] = status; 828 1.1 fredette return(NOEXCEPTION); 829 1.1 fredette } 830 1.1 fredette } 831 1.1 fredette else { /* SGL */ 832 1.1 fredette /* 833 1.1 fredette * calculate offsets for single precision numbers 834 1.1 fredette * See table 6-14 in PA-89 architecture for mapping 835 1.1 fredette */ 836 1.1 fredette rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */ 837 1.1 fredette rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */ 838 1.1 fredette 839 1.1 fredette rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */ 840 1.1 fredette rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */ 841 1.1 fredette 842 1.1 fredette tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */ 843 1.1 fredette tm |= extru(ir,fptmpos-4,1); /* add right word offset */ 844 1.1 fredette 845 1.1 fredette ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */ 846 1.1 fredette ra |= extru(ir,fprapos-4,1); /* add right word offset */ 847 1.1 fredette 848 1.1 fredette ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */ 849 1.1 fredette ta |= extru(ir,fptapos-4,1); /* add right word offset */ 850 1.1 fredette 851 1.1 fredette if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],(unsigned *) &mtmp, 852 1.1 fredette &status)) 853 1.1 fredette error = 1; 854 1.1 fredette if (sgl_fsub(&fpregs[ta], &fpregs[ra], (unsigned *) &atmp, 855 1.1 fredette &status)) 856 1.1 fredette error = 1; 857 1.1 fredette if (error) 858 1.1 fredette return(MAJOR_26_EXCP); 859 1.1 fredette else { 860 1.1 fredette /* copy results */ 861 1.1 fredette fpregs[tm] = mtmp.ints.i1; 862 1.1 fredette fpregs[ta] = atmp.ints.i1; 863 1.1 fredette fpregs[0] = status; 864 1.1 fredette return(NOEXCEPTION); 865 1.1 fredette } 866 1.1 fredette } 867 1.1 fredette 868 1.1 fredette } 869