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