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