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