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/sources/patch/0l-fix-float Date: Wed Jan 1 06:49:17 CET 2014 Signed-off-by: lunaria21@gmail.com --- /sys/src/cmd/vl/asm.c Wed Jan 1 06:44:03 2014 +++ /sys/src/cmd/vl/asm.c Wed Jan 1 06:44:02 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/obj.c Wed Jan 1 06:44:05 2014 +++ /sys/src/cmd/vl/obj.c Wed Jan 1 06:44:04 2014 @@ -1389,6 +1389,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 */ @@ -1413,6 +1414,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");