23 [18] {fariths, "fdivs", Ifloat},
24 [20] {fariths, "fsubs", Ifloat},
25 [21] {fariths, "fadds", Ifloat},
26 [22] {unimp, "fsqrts", Ifloat},
27 [24] {unimp, "fres", Ifloat},
28 [25] {fariths, "fmuls", Ifloat},
29 [28] {fariths, "fmsubs", Ifloat},
30 [29] {fariths, "fmadds", Ifloat},
31 [30] {fariths, "fnmsubs", Ifloat},
32 [31] {fariths, "fnmadds", Ifloat},
35 Inset ops59 = {op59, nelem(op59)};
38 [12] {farith, "frsp", Ifloat},
39 [14] {farith, "fctiw", Ifloat},
40 [15] {farith, "fctiwz", Ifloat},
41 [18] {farith, "fdiv", Ifloat},
42 [20] {farith, "fsub", Ifloat},
43 [21] {farith, "fadd", Ifloat},
44 [22] {unimp, "frsqrt", Ifloat},
45 [23] {unimp, "fsel", Ifloat},
46 [25] {farith, "fmul", Ifloat},
47 [26] {unimp, "frsqrte", Ifloat},
48 [28] {farith, "fmsub", Ifloat},
49 [29] {farith, "fmadd", Ifloat},
50 [30] {farith, "fnmsub", Ifloat},
51 [31] {farith, "fnmadd", Ifloat},
54 Inset ops63a= {op63a, nelem(op63a)};
57 [0] {fcmp, "fcmpu", Ifloat},
58 [32] {fcmp, "fcmpo", Ifloat},
59 [38] {mtfsb1, "mtfsb1", Ifloat},
60 [40] {farith2, "fneg", Ifloat},
61 [64] {mcrfs, "mcrfs", Ifloat},
62 [70] {mtfsb0, "mtfsb0", Ifloat},
63 [72] {farith2, "fmr", Ifloat},
64 [134] {mtfsfi, "mtfsfi", Ifloat},
65 [136] {farith2, "fnabs", Ifloat},
66 [264] {farith2, "fabs", Ifloat},
67 [583] {mffs, "mffs", Ifloat},
68 [711] {mtfsf, "mtfsf", Ifloat},
71 Inset ops63b = {op63b, nelem(op63b)};
78 /* Normally initialised by the kernel */
79 reg.fd[27] = 4503601774854144.0;
84 for(i = 0; i < 27; i++)
85 reg.fd[i] = reg.fd[28];
104 return ((uvlong)f.hi<<32) | f.lo;
111 int imm, ra, rd, upd;
119 upd = (ir&(1L<<26))!=0;
129 itrace("%s\tf%d,%ld(r%d) ea=%lux", ci->name, rd, imm, ra, ea);
147 upd = ((ir>>1)&0x3FF)==567;
153 itrace("%s\tf%d,(r%d+r%d) ea=%lux", ci->name, rd, ra, rb, ea);
158 itrace("%s\tf%d,(r%d) ea=%lux", ci->name, rd, rb, ea);
169 int imm, ra, rd, upd;
173 upd = (ir&(1L<<26))!=0;
183 itrace("%s\tf%d,%ld(r%d) ea=%lux", ci->name, rd, imm, ra, ea);
185 reg.fd[rd] = v2fp(getmem_v(ea));
196 upd = ((ir>>1)&0x3FF)==631;
202 itrace("%s\tf%d,(r%d+r%d) ea=%lux", ci->name, rd, ra, rb, ea);
207 itrace("%s\tf%d,(r%d) ea=%lux", ci->name, rd, rb, ea);
210 reg.fd[rd] = v2fp(getmem_v(ea));
217 int imm, ra, rd, upd;
225 upd = (ir&(1L<<26))!=0;
235 itrace("%s\tf%d,%ld(r%d) %lux=%g",
236 ci->name, rd, imm, ra, ea, reg.fd[rd]);
237 u.f = reg.fd[rd]; /* BUG: actual PPC conversion is more subtle than this */
253 upd = getxo(ir)==695;
259 itrace("%s\tf%d,(r%d+r%d) %lux=%g", ci->name, rd, ra, rb, ea, (float)reg.fd[rd]);
264 itrace("%s\tf%d,(r%d) %lux=%g", ci->name, rd, rb, ea, (float)reg.fd[rd]);
267 u.f = reg.fd[rd]; /* BUG: actual PPC conversion is more subtle than this */
275 int imm, ra, rd, upd;
279 upd = (ir&(1L<<26))!=0;
289 itrace("%s\tf%d,%ld(r%d) %lux=%g",
290 ci->name, rd, imm, ra, ea, reg.fd[rd]);
292 putmem_v(ea, fp2v(reg.fd[rd]));
303 upd = ((ir>>1)&0x3FF)==759;
309 itrace("%s\tf%d,(r%d+r%d) %lux=%g", ci->name, rd, ra, rb, ea, reg.fd[rd]);
314 itrace("%s\tf%d,(r%d) %lux=%g", ci->name, rd, rb, ea, reg.fd[rd]);
317 putmem_v(ea, fp2v(reg.fd[rd]));
324 static ulong fpscr0[] ={
326 FPS_UX|FPS_ZX|FPS_XX|FPS_VXSNAN,
327 FPS_VXISI|FPS_VXIDI|FPS_VXZDZ|FPS_VXIMZ,
334 if(rb || ra&3 || rd&3)
338 reg.cr = (reg.cr & ~mkCR(rd, 0xF)) | mkCR(rd, getCR(ra, reg.fpscr));
339 reg.fpscr &= ~fpscr0[ra];
341 itrace("mcrfs\tcrf%d,crf%d\n", rd, ra);
356 /* it's anyone's guess how CR1 should be set when ir&1 */
357 reg.cr &= ~mkCR(1, 0xE); /* leave SO, reset others */
359 itrace("mffs%s\tfr%d\n", ir&1?".":"", rd);
370 reg.fpscr |= (1L << (31-rd));
371 /* BUG: should set summary bits */
373 reg.cr &= ~mkCR(1, 0xE); /* BUG: manual unclear: leave SO, reset others? */
375 itrace("mtfsb1%s\tfr%d\n", ir&1?".":"", rd);
386 reg.fpscr &= ~(1L << (31-rd));
388 reg.cr &= ~mkCR(1, 0xE); /* BUG: manual unclear: leave SO, reset others? */
390 itrace("mtfsb0%s\tfr%d\n", ir&1?".":"", rd);
400 if(ir & ((1L << 25)|(1L << 16)))
402 rb = (ir >> 11) & 0x1F;
403 fm = (ir >> 17) & 0xFF;
407 if(fm & (1 << (7-i)))
408 reg.fpscr = (reg.fpscr & ~mkCR(i, 0xF)) | mkCR(i, getCR(i, v));
409 /* BUG: should set FEX and VX `according to the usual rule' */
411 reg.cr &= ~mkCR(1, 0xE); /* BUG: manual unclear: leave SO, reset others? */
413 itrace("mtfsf%s\t#%.2x,fr%d", ir&1?".":"", fm, rb);
421 if(ir & ((0x7F << 16)|(1L << 11)))
423 rd = (ir >> 23) & 0xF;
424 imm = (ir >> 12) & 0xF;
425 reg.fpscr = (reg.fpscr & ~mkCR(rd, 0xF)) | mkCR(rd, imm);
426 /* BUG: should set FEX and VX `according to the usual rule' */
428 reg.cr &= ~mkCR(1, 0xE); /* BUG: manual unclear: leave SO, reset others? */
430 itrace("mtfsfi%s\tcrf%d,#%x", ir&1?".":"", rd, imm);
448 itrace("fcmpu\tcr%d,f%d,f%d", rd, ra, rb);
449 if(isNaN(reg.fd[ra]) || isNaN(reg.fd[rb])) {
453 if(reg.fd[ra] == reg.fd[rb]) {
457 if(reg.fd[ra] < reg.fd[rb]) {
461 if(reg.fd[ra] > reg.fd[rb]) {
465 print("qi: fcmp error\n");
469 itrace("fcmpo\tcr%d,f%d,f%d", rd, ra, rb);
470 if(isNaN(reg.fd[ra]) || isNaN(reg.fd[rb])) { /* BUG: depends whether quiet or signalling ... */
472 Bprint(bioout, "invalid_fp_register\n");
475 if(reg.fd[ra] == reg.fd[rb]) {
479 if(reg.fd[ra] < reg.fd[rb]) {
483 if(reg.fd[ra] > reg.fd[rb]) {
487 print("qi: fcmp error\n");
492 reg.cr = (reg.cr & ~mkCR(rd,~0)) | mkCR(rd, fc);
493 reg.fpscr = (reg.fpscr & ~0xF800) | (fc<<11);
494 /* BUG: update FX, VXSNAN, VXVC */
498 * the farith functions probably don't produce the right results
499 * in the presence of NaNs, Infs, etc., esp. wrt exception handling,
504 int rd, ra, rb, rc, fmt;
511 switch(getxo(ir)&0x1F) { /* partial XO decode */
515 if((float)reg.fd[rb] == 0.0) {
516 Bprint(bioout, "fp_exception ZX\n");
517 reg.fpscr |= FPS_ZX | FPS_FX;
520 reg.fd[rd] = (float)(reg.fd[ra] / reg.fd[rb]);
523 reg.fd[rd] = (float)(reg.fd[ra] - reg.fd[rb]);
526 reg.fd[rd] = (float)(reg.fd[ra] + reg.fd[rb]);
529 reg.fd[rd] = (float)(reg.fd[ra] * reg.fd[rc]);
533 reg.fd[rd] = (float)((reg.fd[ra] * reg.fd[rc]) - reg.fd[rb]);
537 reg.fd[rd] = (float)((reg.fd[ra] * reg.fd[rc]) + reg.fd[rb]);
541 reg.fd[rd] = (float)-((reg.fd[ra] * reg.fd[rc]) - reg.fd[rb]);
545 reg.fd[rd] = (float)-((reg.fd[ra] * reg.fd[rc]) + reg.fd[rb]);
556 reg.cr = (reg.cr & ~mkCR(1, ~0)) | mkCR(1, (fpscr>>28));
561 itrace("%s%s\tfr%d,fr%d,fr%d", ci->name, cc, rd, ra, rb);
564 itrace("%s%s\tfr%d,fr%d", ci->name, cc, rd, rb);
567 itrace("%s%s\tfr%d,fr%d,fr%d,fr%d", ci->name, cc, rd, ra, rc, rb);
577 int rd, ra, rb, rc, fmt;
587 switch(getxo(ir)&0x1F) { /* partial XO decode */
591 reg.fd[rd] = (float)reg.fd[rb];
594 case 14: /* fctiw */ /* BUG: ignores rounding mode */
595 case 15: /* fctiwz */
599 else if(d < 0x80000000)
603 reg.fd[rd] = v2fp(vl);
608 if(reg.fd[rb] == 0.0) {
609 Bprint(bioout, "fp_exception ZX\n");
610 reg.fpscr |= FPS_ZX | FPS_FX;
613 reg.fd[rd] = reg.fd[ra] / reg.fd[rb];
616 reg.fd[rd] = reg.fd[ra] - reg.fd[rb];
619 reg.fd[rd] = reg.fd[ra] + reg.fd[rb];
622 reg.fd[rd] = reg.fd[ra] * reg.fd[rc];
626 reg.fd[rd] = (reg.fd[ra] * reg.fd[rc]) - reg.fd[rb];
630 reg.fd[rd] = (reg.fd[ra] * reg.fd[rc]) + reg.fd[rb];
634 reg.fd[rd] = -((reg.fd[ra] * reg.fd[rc]) - reg.fd[rb]);
638 reg.fd[rd] = -((reg.fd[ra] * reg.fd[rc]) + reg.fd[rb]);
650 reg.cr = (reg.cr & ~mkCR(1, ~0)) | mkCR(1, (fpscr>>28));
655 itrace("%s%s\tfr%d,fr%d,fr%d", ci->name, cc, rd, ra, rb);
658 itrace("%s%s\tfr%d,fr%d", ci->name, cc, rd, rb);
661 itrace("%s%s\tfr%d,fr%d,fr%d,fr%d", ci->name, cc, rd, ra, rc, rb);
675 switch(getxo(ir)) { /* full XO decode */
679 reg.fd[rd] = -reg.fd[rb];
682 reg.fd[rd] = reg.fd[rb];
685 reg.fd[rd] = -fabs(reg.fd[rb]);
688 reg.fd[rd] = fabs(reg.fd[rb]);
698 reg.cr = (reg.cr & ~mkCR(1, ~0)) | mkCR(1, (fpscr>>28));
701 itrace("%s%s\tfr%d,fr%d", ci->name, cc, rd, rb);
719 if(fpscr != reg.fpscr) {
740 reg.fpscr = (reg.fpscr & ~0xF800) | (0<<15) | (c<<11); /* unsure about class bit */