1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Linux/PA-RISC Project (http://www.parisc-linux.org/) 4 * 5 * Floating-point emulation code 6 * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> 7 */ 8 /* 9 * BEGIN_DESC 10 * 11 * File: 12 * @(#) pa/fp/fpudispatch.c $Revision: 1.1 $ 13 * 14 * Purpose: 15 * <<please update with a synopsis of the functionality provided by this file>> 16 * 17 * External Interfaces: 18 * <<the following list was autogenerated, please review>> 19 * emfpudispatch(ir, dummy1, dummy2, fpregs) 20 * fpudispatch(ir, excp_code, holder, fpregs) 21 * 22 * Internal Interfaces: 23 * <<the following list was autogenerated, please review>> 24 * static u_int decode_06(u_int, u_int *) 25 * static u_int decode_0c(u_int, u_int, u_int, u_int *) 26 * static u_int decode_0e(u_int, u_int, u_int, u_int *) 27 * static u_int decode_26(u_int, u_int *) 28 * static u_int decode_2e(u_int, u_int *) 29 * static void update_status_cbit(u_int *, u_int, u_int, u_int) 30 * 31 * Theory: 32 * <<please update with a overview of the operation of this file>> 33 * 34 * END_DESC 35 */ 36 37 #define FPUDEBUG 0 38 39 #include "float.h" 40 #include <linux/bug.h> 41 #include <linux/kernel.h> 42 #include <asm/processor.h> 43 /* #include <sys/debug.h> */ 44 /* #include <machine/sys/mdep_private.h> */ 45 46 #define COPR_INST 0x30000000 47 48 /* 49 * definition of extru macro. If pos and len are constants, the compiler 50 * will generate an extru instruction when optimized 51 */ 52 #define extru(r,pos,len) (((r) >> (31-(pos))) & (( 1 << (len)) - 1)) 53 /* definitions of bit field locations in the instruction */ 54 #define fpmajorpos 5 55 #define fpr1pos 10 56 #define fpr2pos 15 57 #define fptpos 31 58 #define fpsubpos 18 59 #define fpclass1subpos 16 60 #define fpclasspos 22 61 #define fpfmtpos 20 62 #define fpdfpos 18 63 #define fpnulpos 26 64 /* 65 * the following are the extra bits for the 0E major op 66 */ 67 #define fpxr1pos 24 68 #define fpxr2pos 19 69 #define fpxtpos 25 70 #define fpxpos 23 71 #define fp0efmtpos 20 72 /* 73 * the following are for the multi-ops 74 */ 75 #define fprm1pos 10 76 #define fprm2pos 15 77 #define fptmpos 31 78 #define fprapos 25 79 #define fptapos 20 80 #define fpmultifmt 26 81 /* 82 * the following are for the fused FP instructions 83 */ 84 /* fprm1pos 10 */ 85 /* fprm2pos 15 */ 86 #define fpraupos 18 87 #define fpxrm2pos 19 88 /* fpfmtpos 20 */ 89 #define fpralpos 23 90 #define fpxrm1pos 24 91 /* fpxtpos 25 */ 92 #define fpfusedsubop 26 93 /* fptpos 31 */ 94 95 /* 96 * offset to constant zero in the FP emulation registers 97 */ 98 #define fpzeroreg (32*sizeof(double)/sizeof(u_int)) 99 100 /* 101 * extract the major opcode from the instruction 102 */ 103 #define get_major(op) extru(op,fpmajorpos,6) 104 /* 105 * extract the two bit class field from the FP instruction. The class is at bit 106 * positions 21-22 107 */ 108 #define get_class(op) extru(op,fpclasspos,2) 109 /* 110 * extract the 3 bit subop field. For all but class 1 instructions, it is 111 * located at bit positions 16-18 112 */ 113 #define get_subop(op) extru(op,fpsubpos,3) 114 /* 115 * extract the 2 or 3 bit subop field from class 1 instructions. It is located 116 * at bit positions 15-16 (PA1.1) or 14-16 (PA2.0) 117 */ 118 #define get_subop1_PA1_1(op) extru(op,fpclass1subpos,2) /* PA89 (1.1) fmt */ 119 #define get_subop1_PA2_0(op) extru(op,fpclass1subpos,3) /* PA 2.0 fmt */ 120 121 /* definitions of unimplemented exceptions */ 122 #define MAJOR_0C_EXCP 0x09 123 #define MAJOR_0E_EXCP 0x0b 124 #define MAJOR_06_EXCP 0x03 125 #define MAJOR_26_EXCP 0x23 126 #define MAJOR_2E_EXCP 0x2b 127 #define PA83_UNIMP_EXCP 0x01 128 129 /* 130 * Special Defines for TIMEX specific code 131 */ 132 133 #define FPU_TYPE_FLAG_POS (EM_FPU_TYPE_OFFSET>>2) 134 #define TIMEX_ROLEX_FPU_MASK (TIMEX_EXTEN_FLAG|ROLEX_EXTEN_FLAG) 135 136 /* 137 * Static function definitions 138 */ 139 #define _PROTOTYPES 140 #if defined(_PROTOTYPES) || defined(_lint) 141 static u_int decode_0c(u_int, u_int, u_int, u_int *); 142 static u_int decode_0e(u_int, u_int, u_int, u_int *); 143 static u_int decode_06(u_int, u_int *); 144 static u_int decode_26(u_int, u_int *); 145 static u_int decode_2e(u_int, u_int *); 146 static void update_status_cbit(u_int *, u_int, u_int, u_int); 147 #else /* !_PROTOTYPES&&!_lint */ 148 static u_int decode_0c(); 149 static u_int decode_0e(); 150 static u_int decode_06(); 151 static u_int decode_26(); 152 static u_int decode_2e(); 153 static void update_status_cbit(); 154 #endif /* _PROTOTYPES&&!_lint */ 155 156 #define VASSERT(x) 157 158 static void parisc_linux_get_fpu_type(u_int fpregs[]) 159 { 160 /* on pa-linux the fpu type is not filled in by the 161 * caller; it is constructed here 162 */ 163 if (boot_cpu_data.cpu_type == pcxs) 164 fpregs[FPU_TYPE_FLAG_POS] = TIMEX_EXTEN_FLAG; 165 else if (boot_cpu_data.cpu_type == pcxt || 166 boot_cpu_data.cpu_type == pcxt_) 167 fpregs[FPU_TYPE_FLAG_POS] = ROLEX_EXTEN_FLAG; 168 else if (boot_cpu_data.cpu_type >= pcxu) 169 fpregs[FPU_TYPE_FLAG_POS] = PA2_0_FPU_FLAG; 170 } 171 172 /* 173 * this routine will decode the excepting floating point instruction and 174 * call the appropriate emulation routine. 175 * It is called by decode_fpu with the following parameters: 176 * fpudispatch(current_ir, unimplemented_code, 0, &Fpu_register) 177 * where current_ir is the instruction to be emulated, 178 * unimplemented_code is the exception_code that the hardware generated 179 * and &Fpu_register is the address of emulated FP reg 0. 180 */ 181 u_int 182 fpudispatch(u_int ir, u_int excp_code, u_int holder, u_int fpregs[]) 183 { 184 u_int class, subop; 185 u_int fpu_type_flags; 186 187 /* All FP emulation code assumes that ints are 4-bytes in length */ 188 VASSERT(sizeof(int) == 4); 189 190 parisc_linux_get_fpu_type(fpregs); 191 192 fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */ 193 194 class = get_class(ir); 195 if (class == 1) { 196 if (fpu_type_flags & PA2_0_FPU_FLAG) 197 subop = get_subop1_PA2_0(ir); 198 else 199 subop = get_subop1_PA1_1(ir); 200 } 201 else 202 subop = get_subop(ir); 203 204 if (FPUDEBUG) printk("class %d subop %d\n", class, subop); 205 206 switch (excp_code) { 207 case MAJOR_0C_EXCP: 208 case PA83_UNIMP_EXCP: 209 return(decode_0c(ir,class,subop,fpregs)); 210 case MAJOR_0E_EXCP: 211 return(decode_0e(ir,class,subop,fpregs)); 212 case MAJOR_06_EXCP: 213 return(decode_06(ir,fpregs)); 214 case MAJOR_26_EXCP: 215 return(decode_26(ir,fpregs)); 216 case MAJOR_2E_EXCP: 217 return(decode_2e(ir,fpregs)); 218 default: 219 /* "crashme Night Gallery painting nr 2. (asm_crash.s). 220 * This was fixed for multi-user kernels, but 221 * workstation kernels had a panic here. This allowed 222 * any arbitrary user to panic the kernel by executing 223 * setting the FP exception registers to strange values 224 * and generating an emulation trap. The emulation and 225 * exception code must never be able to panic the 226 * kernel. 227 */ 228 return(UNIMPLEMENTEDEXCEPTION); 229 } 230 } 231 232 /* 233 * this routine is called by $emulation_trap to emulate a coprocessor 234 * instruction if one doesn't exist 235 */ 236 u_int 237 emfpudispatch(u_int ir, u_int dummy1, u_int dummy2, u_int fpregs[]) 238 { 239 u_int class, subop, major; 240 u_int fpu_type_flags; 241 242 /* All FP emulation code assumes that ints are 4-bytes in length */ 243 VASSERT(sizeof(int) == 4); 244 245 fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */ 246 247 major = get_major(ir); 248 class = get_class(ir); 249 if (class == 1) { 250 if (fpu_type_flags & PA2_0_FPU_FLAG) 251 subop = get_subop1_PA2_0(ir); 252 else 253 subop = get_subop1_PA1_1(ir); 254 } 255 else 256 subop = get_subop(ir); 257 switch (major) { 258 case 0x0C: 259 return(decode_0c(ir,class,subop,fpregs)); 260 case 0x0E: 261 return(decode_0e(ir,class,subop,fpregs)); 262 case 0x06: 263 return(decode_06(ir,fpregs)); 264 case 0x26: 265 return(decode_26(ir,fpregs)); 266 case 0x2E: 267 return(decode_2e(ir,fpregs)); 268 default: 269 return(PA83_UNIMP_EXCP); 270 } 271 } 272 273 274 static u_int 275 decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[]) 276 { 277 u_int r1,r2,t; /* operand register offsets */ 278 u_int fmt; /* also sf for class 1 conversions */ 279 u_int df; /* for class 1 conversions */ 280 u_int *status; 281 u_int retval, local_status; 282 u_int fpu_type_flags; 283 284 if (ir == COPR_INST) { 285 fpregs[0] = EMULATION_VERSION << 11; 286 return(NOEXCEPTION); 287 } 288 status = &fpregs[0]; /* fp status register */ 289 local_status = fpregs[0]; /* and local copy */ 290 r1 = extru(ir,fpr1pos,5) * sizeof(double)/sizeof(u_int); 291 if (r1 == 0) /* map fr0 source to constant zero */ 292 r1 = fpzeroreg; 293 t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int); 294 if (t == 0 && class != 2) /* don't allow fr0 as a dest */ 295 return(MAJOR_0C_EXCP); 296 fmt = extru(ir,fpfmtpos,2); /* get fmt completer */ 297 298 switch (class) { 299 case 0: 300 switch (subop) { 301 case 0: /* COPR 0,0 emulated above*/ 302 case 1: 303 return(MAJOR_0C_EXCP); 304 case 2: /* FCPY */ 305 switch (fmt) { 306 case 2: /* illegal */ 307 return(MAJOR_0C_EXCP); 308 case 3: /* quad */ 309 t &= ~3; /* force to even reg #s */ 310 r1 &= ~3; 311 fpregs[t+3] = fpregs[r1+3]; 312 fpregs[t+2] = fpregs[r1+2]; 313 case 1: /* double */ 314 fpregs[t+1] = fpregs[r1+1]; 315 case 0: /* single */ 316 fpregs[t] = fpregs[r1]; 317 return(NOEXCEPTION); 318 } 319 case 3: /* FABS */ 320 switch (fmt) { 321 case 2: /* illegal */ 322 return(MAJOR_0C_EXCP); 323 case 3: /* quad */ 324 t &= ~3; /* force to even reg #s */ 325 r1 &= ~3; 326 fpregs[t+3] = fpregs[r1+3]; 327 fpregs[t+2] = fpregs[r1+2]; 328 case 1: /* double */ 329 fpregs[t+1] = fpregs[r1+1]; 330 case 0: /* single */ 331 /* copy and clear sign bit */ 332 fpregs[t] = fpregs[r1] & 0x7fffffff; 333 return(NOEXCEPTION); 334 } 335 case 6: /* FNEG */ 336 switch (fmt) { 337 case 2: /* illegal */ 338 return(MAJOR_0C_EXCP); 339 case 3: /* quad */ 340 t &= ~3; /* force to even reg #s */ 341 r1 &= ~3; 342 fpregs[t+3] = fpregs[r1+3]; 343 fpregs[t+2] = fpregs[r1+2]; 344 case 1: /* double */ 345 fpregs[t+1] = fpregs[r1+1]; 346 case 0: /* single */ 347 /* copy and invert sign bit */ 348 fpregs[t] = fpregs[r1] ^ 0x80000000; 349 return(NOEXCEPTION); 350 } 351 case 7: /* FNEGABS */ 352 switch (fmt) { 353 case 2: /* illegal */ 354 return(MAJOR_0C_EXCP); 355 case 3: /* quad */ 356 t &= ~3; /* force to even reg #s */ 357 r1 &= ~3; 358 fpregs[t+3] = fpregs[r1+3]; 359 fpregs[t+2] = fpregs[r1+2]; 360 case 1: /* double */ 361 fpregs[t+1] = fpregs[r1+1]; 362 case 0: /* single */ 363 /* copy and set sign bit */ 364 fpregs[t] = fpregs[r1] | 0x80000000; 365 return(NOEXCEPTION); 366 } 367 case 4: /* FSQRT */ 368 switch (fmt) { 369 case 0: 370 return(sgl_fsqrt(&fpregs[r1],0, 371 &fpregs[t],status)); 372 case 1: 373 return(dbl_fsqrt(&fpregs[r1],0, 374 &fpregs[t],status)); 375 case 2: 376 case 3: /* quad not implemented */ 377 return(MAJOR_0C_EXCP); 378 } 379 case 5: /* FRND */ 380 switch (fmt) { 381 case 0: 382 return(sgl_frnd(&fpregs[r1],0, 383 &fpregs[t],status)); 384 case 1: 385 return(dbl_frnd(&fpregs[r1],0, 386 &fpregs[t],status)); 387 case 2: 388 case 3: /* quad not implemented */ 389 return(MAJOR_0C_EXCP); 390 } 391 } /* end of switch (subop) */ 392 393 case 1: /* class 1 */ 394 df = extru(ir,fpdfpos,2); /* get dest format */ 395 if ((df & 2) || (fmt & 2)) { 396 /* 397 * fmt's 2 and 3 are illegal of not implemented 398 * quad conversions 399 */ 400 return(MAJOR_0C_EXCP); 401 } 402 /* 403 * encode source and dest formats into 2 bits. 404 * high bit is source, low bit is dest. 405 * bit = 1 --> double precision 406 */ 407 fmt = (fmt << 1) | df; 408 switch (subop) { 409 case 0: /* FCNVFF */ 410 switch(fmt) { 411 case 0: /* sgl/sgl */ 412 return(MAJOR_0C_EXCP); 413 case 1: /* sgl/dbl */ 414 return(sgl_to_dbl_fcnvff(&fpregs[r1],0, 415 &fpregs[t],status)); 416 case 2: /* dbl/sgl */ 417 return(dbl_to_sgl_fcnvff(&fpregs[r1],0, 418 &fpregs[t],status)); 419 case 3: /* dbl/dbl */ 420 return(MAJOR_0C_EXCP); 421 } 422 case 1: /* FCNVXF */ 423 switch(fmt) { 424 case 0: /* sgl/sgl */ 425 return(sgl_to_sgl_fcnvxf(&fpregs[r1],0, 426 &fpregs[t],status)); 427 case 1: /* sgl/dbl */ 428 return(sgl_to_dbl_fcnvxf(&fpregs[r1],0, 429 &fpregs[t],status)); 430 case 2: /* dbl/sgl */ 431 return(dbl_to_sgl_fcnvxf(&fpregs[r1],0, 432 &fpregs[t],status)); 433 case 3: /* dbl/dbl */ 434 return(dbl_to_dbl_fcnvxf(&fpregs[r1],0, 435 &fpregs[t],status)); 436 } 437 case 2: /* FCNVFX */ 438 switch(fmt) { 439 case 0: /* sgl/sgl */ 440 return(sgl_to_sgl_fcnvfx(&fpregs[r1],0, 441 &fpregs[t],status)); 442 case 1: /* sgl/dbl */ 443 return(sgl_to_dbl_fcnvfx(&fpregs[r1],0, 444 &fpregs[t],status)); 445 case 2: /* dbl/sgl */ 446 return(dbl_to_sgl_fcnvfx(&fpregs[r1],0, 447 &fpregs[t],status)); 448 case 3: /* dbl/dbl */ 449 return(dbl_to_dbl_fcnvfx(&fpregs[r1],0, 450 &fpregs[t],status)); 451 } 452 case 3: /* FCNVFXT */ 453 switch(fmt) { 454 case 0: /* sgl/sgl */ 455 return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0, 456 &fpregs[t],status)); 457 case 1: /* sgl/dbl */ 458 return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0, 459 &fpregs[t],status)); 460 case 2: /* dbl/sgl */ 461 return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0, 462 &fpregs[t],status)); 463 case 3: /* dbl/dbl */ 464 return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0, 465 &fpregs[t],status)); 466 } 467 case 5: /* FCNVUF (PA2.0 only) */ 468 switch(fmt) { 469 case 0: /* sgl/sgl */ 470 return(sgl_to_sgl_fcnvuf(&fpregs[r1],0, 471 &fpregs[t],status)); 472 case 1: /* sgl/dbl */ 473 return(sgl_to_dbl_fcnvuf(&fpregs[r1],0, 474 &fpregs[t],status)); 475 case 2: /* dbl/sgl */ 476 return(dbl_to_sgl_fcnvuf(&fpregs[r1],0, 477 &fpregs[t],status)); 478 case 3: /* dbl/dbl */ 479 return(dbl_to_dbl_fcnvuf(&fpregs[r1],0, 480 &fpregs[t],status)); 481 } 482 case 6: /* FCNVFU (PA2.0 only) */ 483 switch(fmt) { 484 case 0: /* sgl/sgl */ 485 return(sgl_to_sgl_fcnvfu(&fpregs[r1],0, 486 &fpregs[t],status)); 487 case 1: /* sgl/dbl */ 488 return(sgl_to_dbl_fcnvfu(&fpregs[r1],0, 489 &fpregs[t],status)); 490 case 2: /* dbl/sgl */ 491 return(dbl_to_sgl_fcnvfu(&fpregs[r1],0, 492 &fpregs[t],status)); 493 case 3: /* dbl/dbl */ 494 return(dbl_to_dbl_fcnvfu(&fpregs[r1],0, 495 &fpregs[t],status)); 496 } 497 case 7: /* FCNVFUT (PA2.0 only) */ 498 switch(fmt) { 499 case 0: /* sgl/sgl */ 500 return(sgl_to_sgl_fcnvfut(&fpregs[r1],0, 501 &fpregs[t],status)); 502 case 1: /* sgl/dbl */ 503 return(sgl_to_dbl_fcnvfut(&fpregs[r1],0, 504 &fpregs[t],status)); 505 case 2: /* dbl/sgl */ 506 return(dbl_to_sgl_fcnvfut(&fpregs[r1],0, 507 &fpregs[t],status)); 508 case 3: /* dbl/dbl */ 509 return(dbl_to_dbl_fcnvfut(&fpregs[r1],0, 510 &fpregs[t],status)); 511 } 512 case 4: /* undefined */ 513 return(MAJOR_0C_EXCP); 514 } /* end of switch subop */ 515 516 case 2: /* class 2 */ 517 fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; 518 r2 = extru(ir, fpr2pos, 5) * sizeof(double)/sizeof(u_int); 519 if (r2 == 0) 520 r2 = fpzeroreg; 521 if (fpu_type_flags & PA2_0_FPU_FLAG) { 522 /* FTEST if nullify bit set, otherwise FCMP */ 523 if (extru(ir, fpnulpos, 1)) { /* FTEST */ 524 switch (fmt) { 525 case 0: 526 /* 527 * arg0 is not used 528 * second param is the t field used for 529 * ftest,acc and ftest,rej 530 * third param is the subop (y-field) 531 */ 532 BUG(); 533 /* Unsupported 534 * return(ftest(0L,extru(ir,fptpos,5), 535 * &fpregs[0],subop)); 536 */ 537 case 1: 538 case 2: 539 case 3: 540 return(MAJOR_0C_EXCP); 541 } 542 } else { /* FCMP */ 543 switch (fmt) { 544 case 0: 545 retval = sgl_fcmp(&fpregs[r1], 546 &fpregs[r2],extru(ir,fptpos,5), 547 &local_status); 548 update_status_cbit(status,local_status, 549 fpu_type_flags, subop); 550 return(retval); 551 case 1: 552 retval = dbl_fcmp(&fpregs[r1], 553 &fpregs[r2],extru(ir,fptpos,5), 554 &local_status); 555 update_status_cbit(status,local_status, 556 fpu_type_flags, subop); 557 return(retval); 558 case 2: /* illegal */ 559 case 3: /* quad not implemented */ 560 return(MAJOR_0C_EXCP); 561 } 562 } 563 } /* end of if for PA2.0 */ 564 else { /* PA1.0 & PA1.1 */ 565 switch (subop) { 566 case 2: 567 case 3: 568 case 4: 569 case 5: 570 case 6: 571 case 7: 572 return(MAJOR_0C_EXCP); 573 case 0: /* FCMP */ 574 switch (fmt) { 575 case 0: 576 retval = sgl_fcmp(&fpregs[r1], 577 &fpregs[r2],extru(ir,fptpos,5), 578 &local_status); 579 update_status_cbit(status,local_status, 580 fpu_type_flags, subop); 581 return(retval); 582 case 1: 583 retval = dbl_fcmp(&fpregs[r1], 584 &fpregs[r2],extru(ir,fptpos,5), 585 &local_status); 586 update_status_cbit(status,local_status, 587 fpu_type_flags, subop); 588 return(retval); 589 case 2: /* illegal */ 590 case 3: /* quad not implemented */ 591 return(MAJOR_0C_EXCP); 592 } 593 case 1: /* FTEST */ 594 switch (fmt) { 595 case 0: 596 /* 597 * arg0 is not used 598 * second param is the t field used for 599 * ftest,acc and ftest,rej 600 * third param is the subop (y-field) 601 */ 602 BUG(); 603 /* unsupported 604 * return(ftest(0L,extru(ir,fptpos,5), 605 * &fpregs[0],subop)); 606 */ 607 case 1: 608 case 2: 609 case 3: 610 return(MAJOR_0C_EXCP); 611 } 612 } /* end of switch subop */ 613 } /* end of else for PA1.0 & PA1.1 */ 614 case 3: /* class 3 */ 615 r2 = extru(ir,fpr2pos,5) * sizeof(double)/sizeof(u_int); 616 if (r2 == 0) 617 r2 = fpzeroreg; 618 switch (subop) { 619 case 5: 620 case 6: 621 case 7: 622 return(MAJOR_0C_EXCP); 623 624 case 0: /* FADD */ 625 switch (fmt) { 626 case 0: 627 return(sgl_fadd(&fpregs[r1],&fpregs[r2], 628 &fpregs[t],status)); 629 case 1: 630 return(dbl_fadd(&fpregs[r1],&fpregs[r2], 631 &fpregs[t],status)); 632 case 2: /* illegal */ 633 case 3: /* quad not implemented */ 634 return(MAJOR_0C_EXCP); 635 } 636 case 1: /* FSUB */ 637 switch (fmt) { 638 case 0: 639 return(sgl_fsub(&fpregs[r1],&fpregs[r2], 640 &fpregs[t],status)); 641 case 1: 642 return(dbl_fsub(&fpregs[r1],&fpregs[r2], 643 &fpregs[t],status)); 644 case 2: /* illegal */ 645 case 3: /* quad not implemented */ 646 return(MAJOR_0C_EXCP); 647 } 648 case 2: /* FMPY */ 649 switch (fmt) { 650 case 0: 651 return(sgl_fmpy(&fpregs[r1],&fpregs[r2], 652 &fpregs[t],status)); 653 case 1: 654 return(dbl_fmpy(&fpregs[r1],&fpregs[r2], 655 &fpregs[t],status)); 656 case 2: /* illegal */ 657 case 3: /* quad not implemented */ 658 return(MAJOR_0C_EXCP); 659 } 660 case 3: /* FDIV */ 661 switch (fmt) { 662 case 0: 663 return(sgl_fdiv(&fpregs[r1],&fpregs[r2], 664 &fpregs[t],status)); 665 case 1: 666 return(dbl_fdiv(&fpregs[r1],&fpregs[r2], 667 &fpregs[t],status)); 668 case 2: /* illegal */ 669 case 3: /* quad not implemented */ 670 return(MAJOR_0C_EXCP); 671 } 672 case 4: /* FREM */ 673 switch (fmt) { 674 case 0: 675 return(sgl_frem(&fpregs[r1],&fpregs[r2], 676 &fpregs[t],status)); 677 case 1: 678 return(dbl_frem(&fpregs[r1],&fpregs[r2], 679 &fpregs[t],status)); 680 case 2: /* illegal */ 681 case 3: /* quad not implemented */ 682 return(MAJOR_0C_EXCP); 683 } 684 } /* end of class 3 switch */ 685 } /* end of switch(class) */ 686 687 /* If we get here, something is really wrong! */ 688 return(MAJOR_0C_EXCP); 689 } 690 691 static u_int 692 decode_0e(ir,class,subop,fpregs) 693 u_int ir,class,subop; 694 u_int fpregs[]; 695 { 696 u_int r1,r2,t; /* operand register offsets */ 697 u_int fmt; /* also sf for class 1 conversions */ 698 u_int df; /* dest format for class 1 conversions */ 699 u_int *status; 700 u_int retval, local_status; 701 u_int fpu_type_flags; 702 703 status = &fpregs[0]; 704 local_status = fpregs[0]; 705 r1 = ((extru(ir,fpr1pos,5)<<1)|(extru(ir,fpxr1pos,1))); 706 if (r1 == 0) 707 r1 = fpzeroreg; 708 t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1))); 709 if (t == 0 && class != 2) 710 return(MAJOR_0E_EXCP); 711 if (class < 2) /* class 0 or 1 has 2 bit fmt */ 712 fmt = extru(ir,fpfmtpos,2); 713 else /* class 2 and 3 have 1 bit fmt */ 714 fmt = extru(ir,fp0efmtpos,1); 715 /* 716 * An undefined combination, double precision accessing the 717 * right half of a FPR, can get us into trouble. 718 * Let's just force proper alignment on it. 719 */ 720 if (fmt == DBL) { 721 r1 &= ~1; 722 if (class != 1) 723 t &= ~1; 724 } 725 726 switch (class) { 727 case 0: 728 switch (subop) { 729 case 0: /* unimplemented */ 730 case 1: 731 return(MAJOR_0E_EXCP); 732 case 2: /* FCPY */ 733 switch (fmt) { 734 case 2: 735 case 3: 736 return(MAJOR_0E_EXCP); 737 case 1: /* double */ 738 fpregs[t+1] = fpregs[r1+1]; 739 case 0: /* single */ 740 fpregs[t] = fpregs[r1]; 741 return(NOEXCEPTION); 742 } 743 case 3: /* FABS */ 744 switch (fmt) { 745 case 2: 746 case 3: 747 return(MAJOR_0E_EXCP); 748 case 1: /* double */ 749 fpregs[t+1] = fpregs[r1+1]; 750 case 0: /* single */ 751 fpregs[t] = fpregs[r1] & 0x7fffffff; 752 return(NOEXCEPTION); 753 } 754 case 6: /* FNEG */ 755 switch (fmt) { 756 case 2: 757 case 3: 758 return(MAJOR_0E_EXCP); 759 case 1: /* double */ 760 fpregs[t+1] = fpregs[r1+1]; 761 case 0: /* single */ 762 fpregs[t] = fpregs[r1] ^ 0x80000000; 763 return(NOEXCEPTION); 764 } 765 case 7: /* FNEGABS */ 766 switch (fmt) { 767 case 2: 768 case 3: 769 return(MAJOR_0E_EXCP); 770 case 1: /* double */ 771 fpregs[t+1] = fpregs[r1+1]; 772 case 0: /* single */ 773 fpregs[t] = fpregs[r1] | 0x80000000; 774 return(NOEXCEPTION); 775 } 776 case 4: /* FSQRT */ 777 switch (fmt) { 778 case 0: 779 return(sgl_fsqrt(&fpregs[r1],0, 780 &fpregs[t], status)); 781 case 1: 782 return(dbl_fsqrt(&fpregs[r1],0, 783 &fpregs[t], status)); 784 case 2: 785 case 3: 786 return(MAJOR_0E_EXCP); 787 } 788 case 5: /* FRMD */ 789 switch (fmt) { 790 case 0: 791 return(sgl_frnd(&fpregs[r1],0, 792 &fpregs[t], status)); 793 case 1: 794 return(dbl_frnd(&fpregs[r1],0, 795 &fpregs[t], status)); 796 case 2: 797 case 3: 798 return(MAJOR_0E_EXCP); 799 } 800 } /* end of switch (subop */ 801 802 case 1: /* class 1 */ 803 df = extru(ir,fpdfpos,2); /* get dest format */ 804 /* 805 * Fix Crashme problem (writing to 31R in double precision) 806 * here too. 807 */ 808 if (df == DBL) { 809 t &= ~1; 810 } 811 if ((df & 2) || (fmt & 2)) 812 return(MAJOR_0E_EXCP); 813 814 fmt = (fmt << 1) | df; 815 switch (subop) { 816 case 0: /* FCNVFF */ 817 switch(fmt) { 818 case 0: /* sgl/sgl */ 819 return(MAJOR_0E_EXCP); 820 case 1: /* sgl/dbl */ 821 return(sgl_to_dbl_fcnvff(&fpregs[r1],0, 822 &fpregs[t],status)); 823 case 2: /* dbl/sgl */ 824 return(dbl_to_sgl_fcnvff(&fpregs[r1],0, 825 &fpregs[t],status)); 826 case 3: /* dbl/dbl */ 827 return(MAJOR_0E_EXCP); 828 } 829 case 1: /* FCNVXF */ 830 switch(fmt) { 831 case 0: /* sgl/sgl */ 832 return(sgl_to_sgl_fcnvxf(&fpregs[r1],0, 833 &fpregs[t],status)); 834 case 1: /* sgl/dbl */ 835 return(sgl_to_dbl_fcnvxf(&fpregs[r1],0, 836 &fpregs[t],status)); 837 case 2: /* dbl/sgl */ 838 return(dbl_to_sgl_fcnvxf(&fpregs[r1],0, 839 &fpregs[t],status)); 840 case 3: /* dbl/dbl */ 841 return(dbl_to_dbl_fcnvxf(&fpregs[r1],0, 842 &fpregs[t],status)); 843 } 844 case 2: /* FCNVFX */ 845 switch(fmt) { 846 case 0: /* sgl/sgl */ 847 return(sgl_to_sgl_fcnvfx(&fpregs[r1],0, 848 &fpregs[t],status)); 849 case 1: /* sgl/dbl */ 850 return(sgl_to_dbl_fcnvfx(&fpregs[r1],0, 851 &fpregs[t],status)); 852 case 2: /* dbl/sgl */ 853 return(dbl_to_sgl_fcnvfx(&fpregs[r1],0, 854 &fpregs[t],status)); 855 case 3: /* dbl/dbl */ 856 return(dbl_to_dbl_fcnvfx(&fpregs[r1],0, 857 &fpregs[t],status)); 858 } 859 case 3: /* FCNVFXT */ 860 switch(fmt) { 861 case 0: /* sgl/sgl */ 862 return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0, 863 &fpregs[t],status)); 864 case 1: /* sgl/dbl */ 865 return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0, 866 &fpregs[t],status)); 867 case 2: /* dbl/sgl */ 868 return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0, 869 &fpregs[t],status)); 870 case 3: /* dbl/dbl */ 871 return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0, 872 &fpregs[t],status)); 873 } 874 case 5: /* FCNVUF (PA2.0 only) */ 875 switch(fmt) { 876 case 0: /* sgl/sgl */ 877 return(sgl_to_sgl_fcnvuf(&fpregs[r1],0, 878 &fpregs[t],status)); 879 case 1: /* sgl/dbl */ 880 return(sgl_to_dbl_fcnvuf(&fpregs[r1],0, 881 &fpregs[t],status)); 882 case 2: /* dbl/sgl */ 883 return(dbl_to_sgl_fcnvuf(&fpregs[r1],0, 884 &fpregs[t],status)); 885 case 3: /* dbl/dbl */ 886 return(dbl_to_dbl_fcnvuf(&fpregs[r1],0, 887 &fpregs[t],status)); 888 } 889 case 6: /* FCNVFU (PA2.0 only) */ 890 switch(fmt) { 891 case 0: /* sgl/sgl */ 892 return(sgl_to_sgl_fcnvfu(&fpregs[r1],0, 893 &fpregs[t],status)); 894 case 1: /* sgl/dbl */ 895 return(sgl_to_dbl_fcnvfu(&fpregs[r1],0, 896 &fpregs[t],status)); 897 case 2: /* dbl/sgl */ 898 return(dbl_to_sgl_fcnvfu(&fpregs[r1],0, 899 &fpregs[t],status)); 900 case 3: /* dbl/dbl */ 901 return(dbl_to_dbl_fcnvfu(&fpregs[r1],0, 902 &fpregs[t],status)); 903 } 904 case 7: /* FCNVFUT (PA2.0 only) */ 905 switch(fmt) { 906 case 0: /* sgl/sgl */ 907 return(sgl_to_sgl_fcnvfut(&fpregs[r1],0, 908 &fpregs[t],status)); 909 case 1: /* sgl/dbl */ 910 return(sgl_to_dbl_fcnvfut(&fpregs[r1],0, 911 &fpregs[t],status)); 912 case 2: /* dbl/sgl */ 913 return(dbl_to_sgl_fcnvfut(&fpregs[r1],0, 914 &fpregs[t],status)); 915 case 3: /* dbl/dbl */ 916 return(dbl_to_dbl_fcnvfut(&fpregs[r1],0, 917 &fpregs[t],status)); 918 } 919 case 4: /* undefined */ 920 return(MAJOR_0C_EXCP); 921 } /* end of switch subop */ 922 case 2: /* class 2 */ 923 /* 924 * Be careful out there. 925 * Crashme can generate cases where FR31R is specified 926 * as the source or target of a double precision operation. 927 * Since we just pass the address of the floating-point 928 * register to the emulation routines, this can cause 929 * corruption of fpzeroreg. 930 */ 931 if (fmt == DBL) 932 r2 = (extru(ir,fpr2pos,5)<<1); 933 else 934 r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1))); 935 fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; 936 if (r2 == 0) 937 r2 = fpzeroreg; 938 if (fpu_type_flags & PA2_0_FPU_FLAG) { 939 /* FTEST if nullify bit set, otherwise FCMP */ 940 if (extru(ir, fpnulpos, 1)) { /* FTEST */ 941 /* not legal */ 942 return(MAJOR_0E_EXCP); 943 } else { /* FCMP */ 944 switch (fmt) { 945 /* 946 * fmt is only 1 bit long 947 */ 948 case 0: 949 retval = sgl_fcmp(&fpregs[r1], 950 &fpregs[r2],extru(ir,fptpos,5), 951 &local_status); 952 update_status_cbit(status,local_status, 953 fpu_type_flags, subop); 954 return(retval); 955 case 1: 956 retval = dbl_fcmp(&fpregs[r1], 957 &fpregs[r2],extru(ir,fptpos,5), 958 &local_status); 959 update_status_cbit(status,local_status, 960 fpu_type_flags, subop); 961 return(retval); 962 } 963 } 964 } /* end of if for PA2.0 */ 965 else { /* PA1.0 & PA1.1 */ 966 switch (subop) { 967 case 1: 968 case 2: 969 case 3: 970 case 4: 971 case 5: 972 case 6: 973 case 7: 974 return(MAJOR_0E_EXCP); 975 case 0: /* FCMP */ 976 switch (fmt) { 977 /* 978 * fmt is only 1 bit long 979 */ 980 case 0: 981 retval = sgl_fcmp(&fpregs[r1], 982 &fpregs[r2],extru(ir,fptpos,5), 983 &local_status); 984 update_status_cbit(status,local_status, 985 fpu_type_flags, subop); 986 return(retval); 987 case 1: 988 retval = dbl_fcmp(&fpregs[r1], 989 &fpregs[r2],extru(ir,fptpos,5), 990 &local_status); 991 update_status_cbit(status,local_status, 992 fpu_type_flags, subop); 993 return(retval); 994 } 995 } /* end of switch subop */ 996 } /* end of else for PA1.0 & PA1.1 */ 997 case 3: /* class 3 */ 998 /* 999 * Be careful out there. 1000 * Crashme can generate cases where FR31R is specified 1001 * as the source or target of a double precision operation. 1002 * Since we just pass the address of the floating-point 1003 * register to the emulation routines, this can cause 1004 * corruption of fpzeroreg. 1005 */ 1006 if (fmt == DBL) 1007 r2 = (extru(ir,fpr2pos,5)<<1); 1008 else 1009 r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1))); 1010 if (r2 == 0) 1011 r2 = fpzeroreg; 1012 switch (subop) { 1013 case 5: 1014 case 6: 1015 case 7: 1016 return(MAJOR_0E_EXCP); 1017 1018 /* 1019 * Note that fmt is only 1 bit for class 3 */ 1020 case 0: /* FADD */ 1021 switch (fmt) { 1022 case 0: 1023 return(sgl_fadd(&fpregs[r1],&fpregs[r2], 1024 &fpregs[t],status)); 1025 case 1: 1026 return(dbl_fadd(&fpregs[r1],&fpregs[r2], 1027 &fpregs[t],status)); 1028 } 1029 case 1: /* FSUB */ 1030 switch (fmt) { 1031 case 0: 1032 return(sgl_fsub(&fpregs[r1],&fpregs[r2], 1033 &fpregs[t],status)); 1034 case 1: 1035 return(dbl_fsub(&fpregs[r1],&fpregs[r2], 1036 &fpregs[t],status)); 1037 } 1038 case 2: /* FMPY or XMPYU */ 1039 /* 1040 * check for integer multiply (x bit set) 1041 */ 1042 if (extru(ir,fpxpos,1)) { 1043 /* 1044 * emulate XMPYU 1045 */ 1046 switch (fmt) { 1047 case 0: 1048 /* 1049 * bad instruction if t specifies 1050 * the right half of a register 1051 */ 1052 if (t & 1) 1053 return(MAJOR_0E_EXCP); 1054 BUG(); 1055 /* unsupported 1056 * impyu(&fpregs[r1],&fpregs[r2], 1057 * &fpregs[t]); 1058 */ 1059 return(NOEXCEPTION); 1060 case 1: 1061 return(MAJOR_0E_EXCP); 1062 } 1063 } 1064 else { /* FMPY */ 1065 switch (fmt) { 1066 case 0: 1067 return(sgl_fmpy(&fpregs[r1], 1068 &fpregs[r2],&fpregs[t],status)); 1069 case 1: 1070 return(dbl_fmpy(&fpregs[r1], 1071 &fpregs[r2],&fpregs[t],status)); 1072 } 1073 } 1074 case 3: /* FDIV */ 1075 switch (fmt) { 1076 case 0: 1077 return(sgl_fdiv(&fpregs[r1],&fpregs[r2], 1078 &fpregs[t],status)); 1079 case 1: 1080 return(dbl_fdiv(&fpregs[r1],&fpregs[r2], 1081 &fpregs[t],status)); 1082 } 1083 case 4: /* FREM */ 1084 switch (fmt) { 1085 case 0: 1086 return(sgl_frem(&fpregs[r1],&fpregs[r2], 1087 &fpregs[t],status)); 1088 case 1: 1089 return(dbl_frem(&fpregs[r1],&fpregs[r2], 1090 &fpregs[t],status)); 1091 } 1092 } /* end of class 3 switch */ 1093 } /* end of switch(class) */ 1094 1095 /* If we get here, something is really wrong! */ 1096 return(MAJOR_0E_EXCP); 1097 } 1098 1099 1100 /* 1101 * routine to decode the 06 (FMPYADD and FMPYCFXT) instruction 1102 */ 1103 static u_int 1104 decode_06(ir,fpregs) 1105 u_int ir; 1106 u_int fpregs[]; 1107 { 1108 u_int rm1, rm2, tm, ra, ta; /* operands */ 1109 u_int fmt; 1110 u_int error = 0; 1111 u_int status; 1112 u_int fpu_type_flags; 1113 union { 1114 double dbl; 1115 float flt; 1116 struct { u_int i1; u_int i2; } ints; 1117 } mtmp, atmp; 1118 1119 1120 status = fpregs[0]; /* use a local copy of status reg */ 1121 fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */ 1122 fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */ 1123 if (fmt == 0) { /* DBL */ 1124 rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int); 1125 if (rm1 == 0) 1126 rm1 = fpzeroreg; 1127 rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int); 1128 if (rm2 == 0) 1129 rm2 = fpzeroreg; 1130 tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int); 1131 if (tm == 0) 1132 return(MAJOR_06_EXCP); 1133 ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int); 1134 ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int); 1135 if (ta == 0) 1136 return(MAJOR_06_EXCP); 1137 1138 if (fpu_type_flags & TIMEX_ROLEX_FPU_MASK) { 1139 1140 if (ra == 0) { 1141 /* special case FMPYCFXT, see sgl case below */ 1142 if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2], 1143 &mtmp.ints.i1,&status)) 1144 error = 1; 1145 if (dbl_to_sgl_fcnvfxt(&fpregs[ta], 1146 &atmp.ints.i1,&atmp.ints.i1,&status)) 1147 error = 1; 1148 } 1149 else { 1150 1151 if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1, 1152 &status)) 1153 error = 1; 1154 if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1, 1155 &status)) 1156 error = 1; 1157 } 1158 } 1159 1160 else 1161 1162 { 1163 if (ra == 0) 1164 ra = fpzeroreg; 1165 1166 if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1, 1167 &status)) 1168 error = 1; 1169 if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1, 1170 &status)) 1171 error = 1; 1172 1173 } 1174 1175 if (error) 1176 return(MAJOR_06_EXCP); 1177 else { 1178 /* copy results */ 1179 fpregs[tm] = mtmp.ints.i1; 1180 fpregs[tm+1] = mtmp.ints.i2; 1181 fpregs[ta] = atmp.ints.i1; 1182 fpregs[ta+1] = atmp.ints.i2; 1183 fpregs[0] = status; 1184 return(NOEXCEPTION); 1185 } 1186 } 1187 else { /* SGL */ 1188 /* 1189 * calculate offsets for single precision numbers 1190 * See table 6-14 in PA-89 architecture for mapping 1191 */ 1192 rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */ 1193 rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */ 1194 1195 rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */ 1196 rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */ 1197 1198 tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */ 1199 tm |= extru(ir,fptmpos-4,1); /* add right word offset */ 1200 1201 ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */ 1202 ra |= extru(ir,fprapos-4,1); /* add right word offset */ 1203 1204 ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */ 1205 ta |= extru(ir,fptapos-4,1); /* add right word offset */ 1206 1207 if (ra == 0x20 &&(fpu_type_flags & TIMEX_ROLEX_FPU_MASK)) { 1208 /* special case FMPYCFXT (really 0) 1209 * This instruction is only present on the Timex and 1210 * Rolex fpu's in so if it is the special case and 1211 * one of these fpu's we run the FMPYCFXT instruction 1212 */ 1213 if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1, 1214 &status)) 1215 error = 1; 1216 if (sgl_to_sgl_fcnvfxt(&fpregs[ta],&atmp.ints.i1, 1217 &atmp.ints.i1,&status)) 1218 error = 1; 1219 } 1220 else { 1221 if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1, 1222 &status)) 1223 error = 1; 1224 if (sgl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1, 1225 &status)) 1226 error = 1; 1227 } 1228 if (error) 1229 return(MAJOR_06_EXCP); 1230 else { 1231 /* copy results */ 1232 fpregs[tm] = mtmp.ints.i1; 1233 fpregs[ta] = atmp.ints.i1; 1234 fpregs[0] = status; 1235 return(NOEXCEPTION); 1236 } 1237 } 1238 } 1239 1240 /* 1241 * routine to decode the 26 (FMPYSUB) instruction 1242 */ 1243 static u_int 1244 decode_26(ir,fpregs) 1245 u_int ir; 1246 u_int fpregs[]; 1247 { 1248 u_int rm1, rm2, tm, ra, ta; /* operands */ 1249 u_int fmt; 1250 u_int error = 0; 1251 u_int status; 1252 union { 1253 double dbl; 1254 float flt; 1255 struct { u_int i1; u_int i2; } ints; 1256 } mtmp, atmp; 1257 1258 1259 status = fpregs[0]; 1260 fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */ 1261 if (fmt == 0) { /* DBL */ 1262 rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int); 1263 if (rm1 == 0) 1264 rm1 = fpzeroreg; 1265 rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int); 1266 if (rm2 == 0) 1267 rm2 = fpzeroreg; 1268 tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int); 1269 if (tm == 0) 1270 return(MAJOR_26_EXCP); 1271 ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int); 1272 if (ra == 0) 1273 return(MAJOR_26_EXCP); 1274 ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int); 1275 if (ta == 0) 1276 return(MAJOR_26_EXCP); 1277 1278 if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status)) 1279 error = 1; 1280 if (dbl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status)) 1281 error = 1; 1282 if (error) 1283 return(MAJOR_26_EXCP); 1284 else { 1285 /* copy results */ 1286 fpregs[tm] = mtmp.ints.i1; 1287 fpregs[tm+1] = mtmp.ints.i2; 1288 fpregs[ta] = atmp.ints.i1; 1289 fpregs[ta+1] = atmp.ints.i2; 1290 fpregs[0] = status; 1291 return(NOEXCEPTION); 1292 } 1293 } 1294 else { /* SGL */ 1295 /* 1296 * calculate offsets for single precision numbers 1297 * See table 6-14 in PA-89 architecture for mapping 1298 */ 1299 rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */ 1300 rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */ 1301 1302 rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */ 1303 rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */ 1304 1305 tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */ 1306 tm |= extru(ir,fptmpos-4,1); /* add right word offset */ 1307 1308 ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */ 1309 ra |= extru(ir,fprapos-4,1); /* add right word offset */ 1310 1311 ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */ 1312 ta |= extru(ir,fptapos-4,1); /* add right word offset */ 1313 1314 if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status)) 1315 error = 1; 1316 if (sgl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status)) 1317 error = 1; 1318 if (error) 1319 return(MAJOR_26_EXCP); 1320 else { 1321 /* copy results */ 1322 fpregs[tm] = mtmp.ints.i1; 1323 fpregs[ta] = atmp.ints.i1; 1324 fpregs[0] = status; 1325 return(NOEXCEPTION); 1326 } 1327 } 1328 1329 } 1330 1331 /* 1332 * routine to decode the 2E (FMPYFADD,FMPYNFADD) instructions 1333 */ 1334 static u_int 1335 decode_2e(ir,fpregs) 1336 u_int ir; 1337 u_int fpregs[]; 1338 { 1339 u_int rm1, rm2, ra, t; /* operands */ 1340 u_int fmt; 1341 1342 fmt = extru(ir,fpfmtpos,1); /* get fmt completer */ 1343 if (fmt == DBL) { /* DBL */ 1344 rm1 = extru(ir,fprm1pos,5) * sizeof(double)/sizeof(u_int); 1345 if (rm1 == 0) 1346 rm1 = fpzeroreg; 1347 rm2 = extru(ir,fprm2pos,5) * sizeof(double)/sizeof(u_int); 1348 if (rm2 == 0) 1349 rm2 = fpzeroreg; 1350 ra = ((extru(ir,fpraupos,3)<<2)|(extru(ir,fpralpos,3)>>1)) * 1351 sizeof(double)/sizeof(u_int); 1352 if (ra == 0) 1353 ra = fpzeroreg; 1354 t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int); 1355 if (t == 0) 1356 return(MAJOR_2E_EXCP); 1357 1358 if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */ 1359 return(dbl_fmpynfadd(&fpregs[rm1], &fpregs[rm2], 1360 &fpregs[ra], &fpregs[0], &fpregs[t])); 1361 } else { 1362 return(dbl_fmpyfadd(&fpregs[rm1], &fpregs[rm2], 1363 &fpregs[ra], &fpregs[0], &fpregs[t])); 1364 } 1365 } /* end DBL */ 1366 else { /* SGL */ 1367 rm1 = (extru(ir,fprm1pos,5)<<1)|(extru(ir,fpxrm1pos,1)); 1368 if (rm1 == 0) 1369 rm1 = fpzeroreg; 1370 rm2 = (extru(ir,fprm2pos,5)<<1)|(extru(ir,fpxrm2pos,1)); 1371 if (rm2 == 0) 1372 rm2 = fpzeroreg; 1373 ra = (extru(ir,fpraupos,3)<<3)|extru(ir,fpralpos,3); 1374 if (ra == 0) 1375 ra = fpzeroreg; 1376 t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1))); 1377 if (t == 0) 1378 return(MAJOR_2E_EXCP); 1379 1380 if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */ 1381 return(sgl_fmpynfadd(&fpregs[rm1], &fpregs[rm2], 1382 &fpregs[ra], &fpregs[0], &fpregs[t])); 1383 } else { 1384 return(sgl_fmpyfadd(&fpregs[rm1], &fpregs[rm2], 1385 &fpregs[ra], &fpregs[0], &fpregs[t])); 1386 } 1387 } /* end SGL */ 1388 } 1389 1390 /* 1391 * update_status_cbit 1392 * 1393 * This routine returns the correct FP status register value in 1394 * *status, based on the C-bit & V-bit returned by the FCMP 1395 * emulation routine in new_status. The architecture type 1396 * (PA83, PA89 or PA2.0) is available in fpu_type. The y_field 1397 * and the architecture type are used to determine what flavor 1398 * of FCMP is being emulated. 1399 */ 1400 static void 1401 update_status_cbit(status, new_status, fpu_type, y_field) 1402 u_int *status, new_status; 1403 u_int fpu_type; 1404 u_int y_field; 1405 { 1406 /* 1407 * For PA89 FPU's which implement the Compare Queue and 1408 * for PA2.0 FPU's, update the Compare Queue if the y-field = 0, 1409 * otherwise update the specified bit in the Compare Array. 1410 * Note that the y-field will always be 0 for non-PA2.0 FPU's. 1411 */ 1412 if ((fpu_type & TIMEX_EXTEN_FLAG) || 1413 (fpu_type & ROLEX_EXTEN_FLAG) || 1414 (fpu_type & PA2_0_FPU_FLAG)) { 1415 if (y_field == 0) { 1416 *status = ((*status & 0x04000000) >> 5) | /* old Cbit */ 1417 ((*status & 0x003ff000) >> 1) | /* old CQ */ 1418 (new_status & 0xffc007ff); /* all other bits*/ 1419 } else { 1420 *status = (*status & 0x04000000) | /* old Cbit */ 1421 ((new_status & 0x04000000) >> (y_field+4)) | 1422 (new_status & ~0x04000000 & /* other bits */ 1423 ~(0x04000000 >> (y_field+4))); 1424 } 1425 } 1426 /* if PA83, just update the C-bit */ 1427 else { 1428 *status = new_status; 1429 } 1430 } 1431