diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/ki/float.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/ki/float.c')
-rwxr-xr-x | sys/src/cmd/ki/float.c | 445 |
1 files changed, 445 insertions, 0 deletions
diff --git a/sys/src/cmd/ki/float.c b/sys/src/cmd/ki/float.c new file mode 100755 index 000000000..a73472901 --- /dev/null +++ b/sys/src/cmd/ki/float.c @@ -0,0 +1,445 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#define Extern extern +#include "sparc.h" + +void +ldf(ulong ir) +{ + ulong ea; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(ea, ir); + if(trace) + itrace("ldf\tf%d,0x%lux(r%d) ea=%lux",rd, ea, rs1, ea+reg.r[rs1]); + ea += reg.r[rs1]; + } + else { + ea = reg.r[rs1] + reg.r[rs2]; + if(trace) + itrace("ldf\tf%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea); + } + + reg.di[rd] = getmem_w(ea); +} + +void +lddf(ulong ir) +{ + ulong ea; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(ea, ir); + if(trace) + itrace("lddf\tf%d,0x%lux(r%d) ea=%lux", + rd, ea, rs1, ea+reg.r[rs1]); + ea += reg.r[rs1]; + } + else { + ea = reg.r[rs1] + reg.r[rs2]; + if(trace) + itrace("lddf\tf%d,[r%d+r%d] ea=%lux", rd, rs1, rs2, ea); + } + + if(ea&7) { + Bprint(bioout, "mem_address_not_aligned [load addr %.8lux]\n", ea); + longjmp(errjmp, 0); + } + if(rd&1) + undef(ir); + + reg.di[rd] = getmem_w(ea); + reg.di[rd+1] = getmem_w(ea+4); +} + +void +stf(ulong ir) +{ + ulong ea; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(ea, ir); + if(trace) + itrace("stf\tf%d,0x%lux(r%d) %lux=%g", + rd, ea, rs1, ea+reg.r[rs1], reg.fl[rd]); + ea += reg.r[rs1]; + } + else { + ea = reg.r[rs1] + reg.r[rs2]; + if(trace) + itrace("stf\tf%d,[r%d+r%d] %lux=%lux", + rd, rs1, rs2, ea, reg.r[rd]); + } + + putmem_w(ea, reg.di[rd]); +} + +void +stdf(ulong ir) +{ + ulong ea; + int rd, rs1, rs2; + + getrop23(ir); + if(ir&IMMBIT) { + ximm(ea, ir); + if(trace) + itrace("stdf\tf%d,0x%lux(r%d) %lux=%g", + rd, ea, rs1, ea+reg.r[rs1], reg.fl[rd]); + ea += reg.r[rs1]; + } + else { + ea = reg.r[rs1] + reg.r[rs2]; + if(trace) + itrace("stdf\tf%d,[r%d+r%d] %lux=%lux", + rd, rs1, rs2, ea, reg.r[rd]); + } + + if(ea&7) { + Bprint(bioout, "mem_address_not_aligned [store addr %.8lux]\n", ea); + longjmp(errjmp, 0); + } + if(rd&1) + undef(ir); + + putmem_w(ea, reg.di[rd]); + putmem_w(ea+4, reg.di[rd+1]); +} + +void +fcmp(ulong ir) +{ + int fc, rd, rs1, rs2; + + getrop23(ir); + USED(rd); + SET(fc); + switch((ir>>5)&0x1FF) { + default: + undef(ir); + case 0x51: /* fcmps */ + if(trace) + itrace("fcmps\tf%d,f%d", rs1, rs2); + if(isNaN(reg.fl[rs1]) || isNaN(reg.fl[rs2])) { + fc = 3; + break; + } + if(reg.fl[rs1] == reg.fl[rs2]) { + fc = 0; + break; + } + if(reg.fl[rs1] < reg.fl[rs2]) { + fc = 1; + break; + } + if(reg.fl[rs1] > reg.fl[rs2]) { + fc = 2; + break; + } + print("ki: fcmp error\n"); + break; + case 0x52: + if(trace) + itrace("fcmpd\tf%d,f%d", rs1, rs2); + rs1 >>= 1; + rs2 >>= 1; + if(isNaN(reg.fd[rs1]) || isNaN(reg.fd[rs2])) { + fc = 3; + break; + } + if(reg.fd[rs1] == reg.fd[rs2]) { + fc = 0; + break; + } + if(reg.fd[rs1] < reg.fd[rs2]) { + fc = 1; + break; + } + if(reg.fd[rs1] > reg.fd[rs2]) { + fc = 2; + break; + } + print("ki: fcmp error\n"); + break; + case 0x55: /* fcmpes */ + if(trace) + itrace("fcmpes\tf%d,f%d", rs1, rs2); + rs1 >>= 1; + rs2 >>= 2; + if(isNaN(reg.fl[rs1]) || isNaN(reg.fl[rs2])) { + Bprint(bioout, "invalid_fp_register\n"); + longjmp(errjmp, 0); + } + if(reg.fl[rs1] == reg.fl[rs2]) { + fc = 0; + break; + } + if(reg.fl[rs1] < reg.fl[rs2]) { + fc = 1; + break; + } + if(reg.fl[rs1] > reg.fl[rs2]) { + fc = 2; + break; + } + print("ki: fcmp error\n"); + break; + case 0x56: + if(trace) + itrace("fcmped\tf%d,f%d", rs1, rs2); + if(isNaN(reg.fd[rs1]) || isNaN(reg.fd[rs2])) { + Bprint(bioout, "invalid_fp_register\n"); + longjmp(errjmp, 0); + } + if(reg.fd[rs1] == reg.fd[rs2]) { + fc = 0; + break; + } + if(reg.fd[rs1] < reg.fd[rs2]) { + fc = 1; + break; + } + if(reg.fd[rs1] > reg.fd[rs2]) { + fc = 2; + break; + } + print("ki: fcmp error\n"); + break; + + } + reg.fpsr = (reg.fpsr&~(0x3<<10)) | (fc<<10); +} + +void +fbcc(ulong ir) +{ + char *op; + ulong npc; + int takeit, fc, ba, anul; + + fc = (reg.fpsr>>10)&3; + ba = 0; + SET(op, takeit); + switch((ir>>25)&0x0F) { + case 0: + op = "fbn"; + takeit = 0; + break; + case 1: + op = "fbne"; + takeit = fc == FP_L || fc == FP_G || fc == FP_U; + break; + case 2: + op = "fblg"; + takeit = fc == FP_L || fc == FP_G; + break; + case 3: + op = "fbul"; + takeit = fc == FP_L || fc == FP_U; + break; + case 4: + op = "fbl"; + takeit = fc == FP_L; + break; + case 5: + op = "fbug"; + takeit = fc == FP_U || fc == FP_G; + break; + case 6: + op = "fbg"; + takeit = fc == FP_G; + break; + case 7: + op = "fbu"; + takeit = fc == FP_U; + break; + case 8: + op = "fba"; + ba = 1; + takeit = 1; + break; + case 9: + op = "fbe"; + takeit = fc == FP_E; + break; + case 10: + op = "fbue"; + takeit = fc == FP_E || fc == FP_U; + break; + case 11: + op = "fbge"; + takeit = fc == FP_E || fc == FP_G; + break; + case 12: + op = "fbuge"; + takeit = fc == FP_E || fc == FP_G || fc == FP_U; + break; + case 13: + op = "fble"; + takeit = fc == FP_E || fc == FP_L; + break; + case 14: + op = "fbule"; + takeit = fc == FP_E || fc == FP_L || fc == FP_U; + break; + case 15: + op = "fbo"; + takeit = fc == FP_E || fc == FP_L || fc == FP_G; + break; + } + + npc = ir & 0x3FFFFF; + if(npc & (1<<21)) + npc |= ~((1<<22)-1); + npc = (npc<<2) + reg.pc; + + anul = ir&ANUL; + if(trace) { + if(anul) + itrace("%s,a\t%lux", op, npc); + else + itrace("%s\t%lux", op, npc); + } + + if(takeit == 0) { + reg.pc += 4; + if(anul == 0) { + reg.ir = ifetch(reg.pc); + delay(reg.pc+4); + } + else + anulled++; + return; + } + + ci->taken++; + if(ba && anul) { + reg.pc = npc-4; + anulled++; + return; + } + reg.ir = ifetch(reg.pc+4); + delay(npc); + reg.pc = npc-4; +} + +void +farith(ulong ir) +{ + char *op; + long v; + int rd, rs1, rs2, fmt; + + fmt = 0; + getrop23(ir); + switch((ir>>5)&0x1FF) { + default: + undef(ir); + case 0x41: + reg.fl[rd] = reg.fl[rs1] + reg.fl[rs2]; + op = "fadds"; + break; + case 0x42: + reg.fd[rd>>1] = reg.fd[rs1>>1] + reg.fd[rs2>>1]; + op = "faddd"; + break; + case 0x45: + reg.fl[rd] = reg.fl[rs1] - reg.fl[rs2]; + op = "fsubs"; + break; + case 0x46: + reg.fd[rd>>1] = reg.fd[rs1>>1] - reg.fd[rs2>>1]; + op = "fsubd"; + break; + case 0x4d: + if(reg.fl[rs2] == 0.0) { + Bprint(bioout, "fp_exception DZ\n"); + longjmp(errjmp, 0); + } + reg.fl[rd] = reg.fl[rs1] / reg.fl[rs2]; + op = "fdivs"; + break; + case 0x4e: + if(reg.fd[rs2>>1] == 0.0) { + Bprint(bioout, "fp_exception DZ\n"); + longjmp(errjmp, 0); + } + reg.fd[rd>>1] = reg.fd[rs1>>1] / reg.fd[rs2>>1]; + op = "fdivd"; + break; + case 0x49: + reg.fl[rd] = reg.fl[rs1] * reg.fl[rs2]; + op = "fmuls"; + break; + case 0x4a: + reg.fd[rd>>1] = reg.fd[rs1>>1] * reg.fd[rs2>>1]; + op = "fmuld"; + break; + case 0xc4: + reg.fl[rd] = (long)reg.di[rs2]; + fmt = 1; + op = "fitos"; + break; + case 0xc8: + reg.fd[rd>>1] = (long)reg.di[rs2]; + fmt = 1; + op = "fitod"; + break; + case 0xd1: + v = reg.fl[rs2]; + reg.di[rd] = v; + fmt = 1; + op = "fstoi"; + break; + case 0xd2: + v = reg.fd[rs2>>1]; + reg.di[rd] = v; + fmt = 1; + op = "fdtoi"; + break; + case 0x01: + reg.di[rd] = reg.di[rs2]; + fmt = 1; + op = "fmovs"; + break; + case 0x05: + reg.fl[rd] = -reg.fl[rs2]; + fmt = 1; + op = "fnegs"; + break; + case 0x09: + reg.fl[rd] = fabs(reg.fl[rs2]); + fmt = 1; + op = "fabss"; + break; + case 0xc9: + reg.fd[rd>>1] = reg.fl[rs2]; + fmt = 1; + op = "fstod"; + break; + case 0xc6: + reg.fl[rd] = reg.fd[rs2>>1]; + fmt = 1; + op = "fdtos"; + break; + } + + if(trace) { + switch(fmt) { + case 0: + itrace("%s\tf%d,f%d,f%d", op, rs1, rs2, rd); + break; + case 1: + itrace("%s\tf%d,f%d", op, rs2, rd); + break; + } + } +} |