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/vi/float.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/vi/float.c')
-rwxr-xr-x | sys/src/cmd/vi/float.c | 783 |
1 files changed, 783 insertions, 0 deletions
diff --git a/sys/src/cmd/vi/float.c b/sys/src/cmd/vi/float.c new file mode 100755 index 000000000..8f1bbaf97 --- /dev/null +++ b/sys/src/cmd/vi/float.c @@ -0,0 +1,783 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mach.h> +#define Extern extern +#include "mips.h" + +void unimp(ulong); +void Ifcmp(ulong); +void Ifdiv(ulong); +void Ifmul(ulong); +void Ifadd(ulong); +void Ifsub(ulong); +void Ifmov(ulong); +void Icvtd(ulong); +void Icvtw(ulong); +void Icvts(ulong); +void Ifabs(ulong); +void Ifneg(ulong); + +Inst cop1[] = { + { Ifadd, "add.f", Ifloat }, + { Ifsub, "sub.f", Ifloat }, + { Ifmul, "mul.f", Ifloat }, + { Ifdiv, "div.f", Ifloat }, + { unimp, "", }, + { Ifabs, "abs.f", Ifloat }, + { Ifmov, "mov.f", Ifloat }, + { Ifneg, "neg.f", Ifloat }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { Icvts, "cvt.s", Ifloat }, + { Icvtd, "cvt.d", Ifloat }, + { unimp, "", }, + { unimp, "", }, + { Icvtw, "cvt.w", Ifloat }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { unimp, "", }, + { Ifcmp, "c.f", Ifloat }, + { Ifcmp, "c.un", Ifloat }, + { Ifcmp, "c.eq", Ifloat }, + { Ifcmp, "c.ueq", Ifloat }, + { Ifcmp, "c.olt", Ifloat }, + { Ifcmp, "c.ult", Ifloat }, + { Ifcmp, "c.ole", Ifloat }, + { Ifcmp, "c.ule", Ifloat }, + { Ifcmp, "c,sf", Ifloat }, + { Ifcmp, "c.ngle",Ifloat }, + { Ifcmp, "c.seq", Ifloat }, + { Ifcmp, "c.ngl", Ifloat }, + { Ifcmp, "c.lt", Ifloat }, + { Ifcmp, "c.nge", Ifloat }, + { Ifcmp, "c.le", Ifloat }, + { Ifcmp, "c.ngt", Ifloat }, + { 0 } +}; + +void +unimp(ulong inst) +{ + print("op %ld\n", inst&0x3f); + Bprint(bioout, "Unimplemented floating point Trap IR %.8lux\n", inst); + longjmp(errjmp, 0); +} + +void +inval(ulong inst) +{ + Bprint(bioout, "Invalid Operation Exception IR %.8lux\n", inst); + longjmp(errjmp, 0); +} + +void +ifmt(int r) +{ + Bprint(bioout, "Invalid Floating Data Format f%d pc 0x%lux\n", r, reg.pc); + longjmp(errjmp, 0); +} + +void +floatop(int dst, int s1, int s2) +{ + if(reg.ft[s1] == FPd && s1 != 24) + ifmt(s1); + if(reg.ft[s2] == FPd && s2 != 24) + ifmt(s2); + reg.ft[dst] = FPs; +} + +void +doubop(int dst, int s1, int s2) +{ + ulong l; + + if(reg.ft[s1] != FPd) { + if(reg.ft[s1] == FPs && s1 != 24) + ifmt(s1); + l = reg.di[s1]; + reg.di[s1] = reg.di[s1+1]; + reg.di[s1+1] = l; + reg.ft[s1] = FPd; + } + if(reg.ft[s2] != FPd) { + if(reg.ft[s2] == FPs && s2 != 24) + ifmt(s2); + l = reg.di[s2]; + reg.di[s2] = reg.di[s2+1]; + reg.di[s2+1] = l; + reg.ft[s2] = FPd; + } + reg.ft[dst] = FPd; +} + +void +Iswc1(ulong inst) +{ + int off; + ulong l; + int rt, rb, ert; + + Getrbrt(rb, rt, inst); + off = (short)(inst&0xffff); + + if(trace) + itrace("swc1\tf%d,0x%x(r%d) ea=%lux", rt, off, rb, reg.r[rb]+off); + + ert = rt&~1; + if(reg.ft[ert] == FPd) { + l = reg.di[ert]; + reg.di[ert] = reg.di[ert+1]; + reg.di[ert+1] = l; + reg.ft[ert] = FPmemory; + } + putmem_w(reg.r[rb]+off, reg.di[rt]); +} + +void +Ifsub(ulong ir) +{ + char fmt; + int fs, ft, fd; + + Getf3(fs, ft, fd, ir); + + switch((ir>>21)&0xf) { + default: + unimp(ir); + case 0: /* single */ + fmt = 's'; + floatop(fd, fs, ft); + reg.fl[fd] = reg.fl[fs] - reg.fl[ft]; + break; + case 1: /* double */ + fmt = 'd'; + doubop(fd, fs, ft); + reg.fd[fd>>1] = reg.fd[fs>>1] - reg.fd[ft>>1]; + break; + case 4: + fmt = 'w'; + reg.di[fd] = reg.di[fs] - reg.di[ft]; + break; + } + if(trace) + itrace("sub.%c\tf%d,f%d,f%d", fmt, fd, fs, ft); +} + +void +Ifmov(ulong ir) +{ + char fmt; + int fs, fd; + + Getf2(fs, fd, ir); + + switch((ir>>21)&0xf) { + default: + unimp(ir); + case 0: /* single */ + fmt = 's'; + reg.fl[fd] = reg.fl[fs]; + reg.ft[fd] = reg.ft[fs]; + break; + case 1: /* double */ + fmt = 'd'; + reg.fd[fd>>1] = reg.fd[fs>>1]; + reg.ft[fd] = reg.ft[fs]; + break; + case 4: + fmt = 'w'; + reg.di[fd] = reg.di[fs]; + reg.ft[fd] = reg.ft[fs]; + break; + } + if(trace) + itrace("mov.%c\tf%d,f%d", fmt, fd, fs); +} + +void +Ifabs(ulong ir) +{ + char fmt; + int fs, fd; + + Getf2(fs, fd, ir); + + switch((ir>>21)&0xf) { + default: + unimp(ir); + case 0: /* single */ + fmt = 's'; + floatop(fd, fs, fs); + if(reg.fl[fs] < 0.0) + reg.fl[fd] = -reg.fl[fs]; + else + reg.fl[fd] = reg.fl[fs]; + break; + case 1: /* double */ + fmt = 'd'; + doubop(fd, fs, fs); + if(reg.fd[fs>>1] < 0.0) + reg.fd[fd>>1] = -reg.fd[fs>>1]; + else + reg.fd[fd>>1] = reg.fd[fs>>1]; + break; + case 4: + fmt = 'w'; + if((long)reg.di[fs] < 0) + reg.di[fd] = -reg.di[fs]; + else + reg.di[fd] = reg.di[fs]; + break; + } + if(trace) + itrace("abs.%c\tf%d,f%d", fmt, fd, fs); +} + +void +Ifneg(ulong ir) +{ + char fmt; + int fs, fd; + + Getf2(fs, fd, ir); + + switch((ir>>21)&0xf) { + default: + unimp(ir); + case 0: /* single */ + fmt = 's'; + floatop(fd, fs, fs); + reg.fl[fd] = -reg.fl[fs]; + break; + case 1: /* double */ + fmt = 'd'; + doubop(fd, fs, fs); + reg.fd[fd>>1] = -reg.fd[fs>>1]; + break; + case 4: + fmt = 'w'; + reg.di[fd] = -reg.di[fs]; + break; + } + if(trace) + itrace("neg.%c\tf%d,f%d", fmt, fd, fs); +} + +void +Icvtd(ulong ir) +{ + char fmt; + int fs, fd; + + Getf2(fs, fd, ir); + + switch((ir>>21)&0xf) { + default: + unimp(ir); + case 0: /* single */ + fmt = 's'; + floatop(fs, fs, fs); + reg.fd[fd>>1] = reg.fl[fs]; + reg.ft[fd] = FPd; + break; + case 1: /* double */ + fmt = 'd'; + doubop(fd, fs, fs); + reg.fd[fd>>1] = reg.fd[fs>>1]; + break; + case 4: + fmt = 'w'; + reg.fd[fd>>1] = (long)reg.di[fs]; + reg.ft[fd] = FPd; + break; + } + if(trace) + itrace("cvt.d.%c\tf%d,f%d", fmt, fd, fs); +} + +void +Icvts(ulong ir) +{ + char fmt; + int fs, fd; + + Getf2(fs, fd, ir); + + switch((ir>>21)&0xf) { + default: + unimp(ir); + case 0: /* single */ + fmt = 's'; + floatop(fd, fs, fs); + reg.fl[fd] = reg.fl[fs]; + break; + case 1: /* double */ + fmt = 'd'; + doubop(fs, fs, fs); + reg.fl[fd] = reg.fd[fs>>1]; + reg.ft[fd] = FPs; + break; + case 4: + fmt = 'w'; + reg.fl[fd] = (long)reg.di[fs]; + reg.ft[fd] = FPs; + break; + } + if(trace) + itrace("cvt.s.%c\tf%d,f%d", fmt, fd, fs); +} + +void +Icvtw(ulong ir) +{ + long v; + char fmt; + int fs, fd; + + Getf2(fs, fd, ir); + + switch((ir>>21)&0xf) { + default: + unimp(ir); + case 0: /* single */ + fmt = 's'; + floatop(fs, fs, fs); + v = reg.fl[fs]; + break; + case 1: /* double */ + fmt = 'd'; + doubop(fs, fs, fs); + v = reg.fd[fs>>1]; + break; + case 4: + fmt = 'w'; + v = reg.di[fs]; + break; + } + reg.di[fd] = v; + reg.ft[fd] = FPmemory; + if(trace) + itrace("cvt.w.%c\tf%d,f%d", fmt, fd, fs); +} + +void +Ifadd(ulong ir) +{ + char fmt; + int fs, ft, fd; + + Getf3(fs, ft, fd, ir); + + switch((ir>>21)&0xf) { + default: + unimp(ir); + case 0: /* single */ + fmt = 's'; + floatop(fd, fs, ft); + reg.fl[fd] = reg.fl[fs] + reg.fl[ft]; + break; + case 1: /* double */ + fmt = 'd'; + doubop(fd, fs, ft); + reg.fd[fd>>1] = reg.fd[fs>>1] + reg.fd[ft>>1]; + break; + case 4: + fmt = 'w'; + reg.di[fd] = reg.di[fs] + reg.di[ft]; + break; + } + if(trace) + itrace("add.%c\tf%d,f%d,f%d", fmt, fd, fs, ft); +} + +void +Ifmul(ulong ir) +{ + char fmt; + int fs, ft, fd; + + Getf3(fs, ft, fd, ir); + + switch((ir>>21)&0xf) { + default: + unimp(ir); + case 0: /* single */ + fmt = 's'; + floatop(fd, fs, ft); + reg.fl[fd] = reg.fl[fs] * reg.fl[ft]; + break; + case 1: /* double */ + fmt = 'd'; + doubop(fd, fs, ft); + reg.fd[fd>>1] = reg.fd[fs>>1] * reg.fd[ft>>1]; + break; + case 4: + fmt = 'w'; + reg.di[fd] = reg.di[fs] * reg.di[ft]; + break; + } + if(trace) + itrace("mul.%c\tf%d,f%d,f%d", fmt, fd, fs, ft); +} + +void +Ifdiv(ulong ir) +{ + char fmt; + int fs, ft, fd; + + Getf3(fs, ft, fd, ir); + + switch((ir>>21)&0xf) { + default: + unimp(ir); + case 0: /* single */ + fmt = 's'; + floatop(fd, fs, ft); + reg.fl[fd] = reg.fl[fs] / reg.fl[ft]; + break; + case 1: /* double */ + fmt = 'd'; + doubop(fd, fs, ft); + reg.fd[fd>>1] = reg.fd[fs>>1] / reg.fd[ft>>1]; + break; + case 4: + fmt = 'w'; + reg.di[fd] = reg.di[fs] / reg.di[ft]; + break; + } + if(trace) + itrace("div.%c\tf%d,f%d,f%d", fmt, fd, fs, ft); +} + +void +Ilwc1(ulong inst) +{ + int rt, rb; + int off; + + Getrbrt(rb, rt, inst); + off = (short)(inst&0xffff); + + if(trace) + itrace("lwc1\tf%d,0x%x(r%d) ea=%lux", rt, off, rb, reg.r[rb]+off); + + reg.di[rt] = getmem_w(reg.r[rb]+off); + reg.ft[rt] = FPmemory; +} + +void +Ibcfbct(ulong inst) +{ + int takeit; + int off; + ulong npc; + + off = (short)(inst&0xffff); + + takeit = 0; + npc = reg.pc + (off<<2) + 4; + if(inst&(1<<16)) { + if(trace) + itrace("bc1t\t0x%lux", npc); + + if(reg.fpsr&FP_CBIT) + takeit = 1; + } + else { + if(trace) + itrace("bc1f\t0x%lux", npc); + + if((reg.fpsr&FP_CBIT) == 0) + takeit = 1; + } + + if(takeit) { + /* Do the delay slot */ + reg.ir = ifetch(reg.pc+4); + Statbra(); + Iexec(reg.ir); + reg.pc = npc-4; + } +} + +void +Imtct(ulong ir) +{ + int rt, fs; + + SpecialGetrtrd(rt, fs, ir); + if(ir&(1<<22)) { /* CT */ + if(trace) + itrace("ctc1\tr%d,f%d", rt, fs); + } + else { /* MT */ + if(trace) + itrace("mtc1\tr%d,f%d", rt, fs); + + reg.di[fs] = reg.r[rt]; + reg.ft[fs] = FPmemory; + } +} + +void +Imfcf(ulong ir) +{ + int rt, fs; + + SpecialGetrtrd(rt, fs, ir); + if(ir&(1<<22)) { /* CF */ + if(trace) + itrace("cfc1\tr%d,f%d", rt, fs); + } + else { /* MF */ + if(trace) + itrace("mfc1\tr%d,f%d", rt, fs); + + reg.r[rt] = reg.di[fs]; + } +} + +void +Icop1(ulong ir) +{ + Inst *i; + + switch((ir>>23)&7) { + case 0: + Imfcf(ir); + break; + case 1: + Imtct(ir); + break; + case 2: + case 3: + Ibcfbct(ir); + break; + case 4: + case 5: + case 6: + case 7: + i = &cop1[ir&0x3f]; + i->count++; + (*i->func)(ir); + } +} + +void +Ifcmp(ulong ir) +{ + char fmt; + int fc; + int ft, fs; + + SpecialGetrtrd(ft, fs, ir); + + SET(fc); + switch((ir>>21)&0xf) { + default: + unimp(ir); + case 0: /* single */ + fmt = 's'; + floatop(fs, fs, ft); + if(isNaN(reg.fl[fs]) || isNaN(reg.fl[ft])) { + fc = FP_U; + break; + } + if(reg.fl[fs] == reg.fl[ft]) { + fc = FP_E; + break; + } + if(reg.fl[fs] < reg.fl[ft]) { + fc = FP_L; + break; + } + if(reg.fl[fs] > reg.fl[ft]) { + fc = FP_G; + break; + } + print("vi: bad in fcmp"); + break; + case 1: /* double */ + fmt = 'd'; + doubop(fs, fs, ft); + if(isNaN(reg.fd[fs>>1]) || isNaN(reg.fd[ft>>1])) { + fc = FP_U; + break; + } + if(reg.fd[fs>>1] == reg.fd[ft>>1]) { + fc = FP_E; + break; + } + if(reg.fd[fs>>1] < reg.fd[ft>>1]) { + fc = FP_L; + break; + } + if(reg.fd[fs>>1] > reg.fd[ft>>1]) { + fc = FP_G; + break; + } + print("vi: bad in fcmp"); + break; + case 4: + fmt = 'w'; + if(reg.di[fs] == reg.di[ft]) { + fc = FP_E; + break; + } + if(reg.di[fs] < reg.di[ft]) { + fc = FP_L; + break; + } + if(reg.di[fs] > reg.di[ft]) { + fc = FP_G; + break; + } + break; + } + + reg.fpsr &= ~FP_CBIT; + switch(ir&0xf) { + case 0: + if(trace) + itrace("c.f.%c\tf%d,f%d", fmt, fs, ft); + break; + case 1: + if(trace) + itrace("c.un.%c\tf%d,f%d", fmt, fs, ft); + if(fc == FP_U) + reg.fpsr |= FP_CBIT; + break; + case 2: + if(trace) + itrace("c.eq.%c\tf%d,f%d", fmt, fs, ft); + if(fc == FP_E) + reg.fpsr |= FP_CBIT; + break; + case 3: + if(trace) + itrace("c.ueq.%c\tf%d,f%d", fmt, fs, ft); + if(fc == FP_E || fc == FP_U) + reg.fpsr |= FP_CBIT; + break; + case 4: + if(trace) + itrace("c.lt.%c\tf%d,f%d", fmt, fs, ft); + if(fc == FP_L) + reg.fpsr |= FP_CBIT; + break; + case 5: + if(trace) + itrace("c.ult.%c\tf%d,f%d", fmt, fs, ft); + if(fc == FP_L || fc == FP_U) + reg.fpsr |= FP_CBIT; + break; + case 6: + if(trace) + itrace("c.le.%c\tf%d,f%d", fmt, fs, ft); + if(fc == FP_E || fc == FP_L) + reg.fpsr |= FP_CBIT; + break; + case 7: + if(trace) + itrace("c.ule.%c\tf%d,f%d", fmt, fs, ft); + if(fc == FP_E || fc == FP_L || fc == FP_U) + reg.fpsr |= FP_CBIT; + break; + case 8: + if(trace) + itrace("c.sf.%c\tf%d,f%d", fmt, fs, ft); + if(fc == FP_U) + inval(ir); + break; + case 9: + if(trace) + itrace("c.ngle.%c\tf%d,f%d", fmt, fs, ft); + if(fc == FP_U) { + reg.fpsr |= FP_CBIT; + inval(ir); + } + break; + case 10: + if(trace) + itrace("c.seq.%c\tf%d,f%d", fmt, fs, ft); + if(fc == FP_E) + reg.fpsr |= FP_CBIT; + if(fc == FP_U) + inval(ir); + break; + case 11: + if(trace) + itrace("c.ngl.%c\tf%d,f%d", fmt, fs, ft); + if(fc == FP_E || fc == FP_U) + reg.fpsr |= FP_CBIT; + if(fc == FP_U) + inval(ir); + break; + case 12: + if(trace) + itrace("c.lt.%c\tf%d,f%d", fmt, fs, ft); + if(fc == FP_L) + reg.fpsr |= FP_CBIT; + if(fc == FP_U) + inval(ir); + break; + case 13: + if(trace) + itrace("c.nge.%c\tf%d,f%d", fmt, fs, ft); + if(fc == FP_L || fc == FP_U) + reg.fpsr |= FP_CBIT; + if(fc == FP_U) + inval(ir); + break; + case 14: + if(trace) + itrace("c.le.%c\tf%d,f%d", fmt, fs, ft); + if(fc == FP_E || fc == FP_L) + reg.fpsr |= FP_CBIT; + if(fc == FP_U) + inval(ir); + break; + case 15: + if(trace) + itrace("c.ngt.%c\tf%d,f%d", fmt, fs, ft); + if(fc == FP_E || fc == FP_L || fc == FP_U) + reg.fpsr |= FP_CBIT; + if(fc == FP_U) + inval(ir); + break; + } + USED(fmt); +} |