from /n/sources/patch/0l-fix-float; author lunaria21@gmail.com this patch is to fix two issues about floating point in 0l/vl in little endian mode. 1. fix floating point register ordering in MOVD. the least significant bits should be held in even numbered fp register, regardless of the endianess. in LE mode it is the first 4 bytes hold them, which is different from BE. 2. 0l/vl outputs wrong bits for single precision floats in little endian mode. this patch fixes it by using fnuxi4 instead of fnuxi8. the debug output is added as well. cf. inferno's 0l. both are tested on loongson 2E machine, seems okay. Reference: /n/atom/patch/applied/mipslefloat Date: Wed Feb 19 04:02:33 CET 2014 Signed-off-by: quanstro@quanstro.net --- /sys/src/cmd/vl/asm.c Wed Feb 19 04:02:02 2014 +++ /sys/src/cmd/vl/asm.c Wed Feb 19 04:02:04 2014 @@ -669,7 +669,7 @@ fl = ieeedtof(p->to.ieee); cast = (char*)&fl; for(; i>16, REGZERO, REGTMP); o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP); o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP); - o4 = OP_IRR(opirr(AMOVF+ALAST), 0, REGTMP, p->to.reg+1); - o5 = OP_IRR(opirr(AMOVF+ALAST), 4, REGTMP, p->to.reg); + if(little) { + o4 = OP_IRR(opirr(AMOVF+ALAST), 0, REGTMP, p->to.reg); + o5 = OP_IRR(opirr(AMOVF+ALAST), 4, REGTMP, p->to.reg+1); + } else { + o4 = OP_IRR(opirr(AMOVF+ALAST), 0, REGTMP, p->to.reg+1); + o5 = OP_IRR(opirr(AMOVF+ALAST), 4, REGTMP, p->to.reg); + } break; case 16: o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP); @@ -1029,8 +1034,13 @@ o4 = OP_IRR(opirr(AMOVF+ALAST), 0, REGTMP, p->to.reg); break; case 8: - o1 = OP_IRR(opirr(AMOVF+ALAST), v, r, p->to.reg+1); - o2 = OP_IRR(opirr(AMOVF+ALAST), v+4, r, p->to.reg); + if(little) { + o1 = OP_IRR(opirr(AMOVF+ALAST), v, r, p->to.reg); + o2 = OP_IRR(opirr(AMOVF+ALAST), v+4, r, p->to.reg+1); + } else { + o1 = OP_IRR(opirr(AMOVF+ALAST), v, r, p->to.reg+1); + o2 = OP_IRR(opirr(AMOVF+ALAST), v+4, r, p->to.reg); + } break; case 4: o1 = OP_IRR(opirr(AMOVF+ALAST), v, r, p->to.reg); @@ -1050,8 +1060,13 @@ o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP); o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP); o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP); - o4 = OP_IRR(opirr(AMOVF), 0, REGTMP, p->from.reg+1); - o5 = OP_IRR(opirr(AMOVF), 4, REGTMP, p->from.reg); + if(little) { + o4 = OP_IRR(opirr(AMOVF), 0, REGTMP, p->from.reg); + o5 = OP_IRR(opirr(AMOVF), 4, REGTMP, p->from.reg+1); + } else { + o4 = OP_IRR(opirr(AMOVF), 0, REGTMP, p->from.reg+1); + o5 = OP_IRR(opirr(AMOVF), 4, REGTMP, p->from.reg); + } break; case 16: if(r == REGTMP) @@ -1062,8 +1077,13 @@ o4 = OP_IRR(opirr(AMOVF), 0, REGTMP, p->from.reg); break; case 8: - o1 = OP_IRR(opirr(AMOVF), v, r, p->from.reg+1); - o2 = OP_IRR(opirr(AMOVF), v+4, r, p->from.reg); + if(little) { + o1 = OP_IRR(opirr(AMOVF), v, r, p->from.reg); + o2 = OP_IRR(opirr(AMOVF), v+4, r, p->from.reg+1); + } else { + o1 = OP_IRR(opirr(AMOVF), v, r, p->from.reg+1); + o2 = OP_IRR(opirr(AMOVF), v+4, r, p->from.reg); + } break; case 4: o1 = OP_IRR(opirr(AMOVF), v, r, p->from.reg); --- /sys/src/cmd/vl/noop.c Wed Feb 19 04:02:05 2014 +++ /sys/src/cmd/vl/noop.c Wed Feb 19 04:02:06 2014 @@ -7,7 +7,7 @@ * and "{ echo moon; echo plot } | scat". */ enum { - Mips24k = 0, + Mips24k = 1, }; static int --- /sys/src/cmd/vl/obj.c Wed Feb 19 04:02:08 2014 +++ /sys/src/cmd/vl/obj.c Wed Feb 19 04:02:10 2014 @@ -1332,6 +1332,7 @@ if(i >= 3) inuxi1[i-3] = c; inuxi4[i] = c; + fnuxi4[i] = c; fnuxi8[i] = c+4; fnuxi8[i+4] = c; } else { /* oddball little-endian case */ @@ -1356,6 +1357,9 @@ for(i=0; i<4; i++) Bprint(&bso, "%d", inuxi4[i]); Bprint(&bso, "\nfnuxi = "); + for(i=0; i<4; i++) + Bprint(&bso, "%d", fnuxi4[i]); + Bprint(&bso, " "); for(i=0; i<8; i++) Bprint(&bso, "%d", fnuxi8[i]); Bprint(&bso, "\n");