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