Commit 69188ad9 authored by Russ Cox's avatar Russ Cox

arm: prop up software floating point

Just enough to make mov instructions work,
which in turn is enough to make strconv work
when it avoids any floating point calculations.
That makes a bunch of other packages pass
their tests.

Should suffice until hardware floating point
is available.

Enable package tests that now pass
(some due to earlier fixes).

Looks like there is a new integer math bug
exposed in the fmt and json tests.

R=ken2
CC=golang-dev
https://golang.org/cl/2638041
parent f16b6b14
...@@ -21,7 +21,8 @@ OFILES=\ ...@@ -21,7 +21,8 @@ OFILES=\
ggen.$O\ ggen.$O\
gsubr.$O\ gsubr.$O\
cgen.$O\ cgen.$O\
cgen64.$O cgen64.$O\
cplx.$O\
LIB=\ LIB=\
../gc/gc.a\ ../gc/gc.a\
......
...@@ -28,12 +28,6 @@ cgen(Node *n, Node *res) ...@@ -28,12 +28,6 @@ cgen(Node *n, Node *res)
if(res == N || res->type == T) if(res == N || res->type == T)
fatal("cgen: res nil"); fatal("cgen: res nil");
// TODO compile complex
if(n != N && n->type != T && iscomplex[n->type->etype])
return;
if(res != N && res->type != T && iscomplex[res->type->etype])
return;
while(n->op == OCONVNOP) while(n->op == OCONVNOP)
n = n->left; n = n->left;
...@@ -53,6 +47,7 @@ cgen(Node *n, Node *res) ...@@ -53,6 +47,7 @@ cgen(Node *n, Node *res)
goto ret; goto ret;
} }
// update addressability for string, slice // update addressability for string, slice
// can't do in walk because n->left->addable // can't do in walk because n->left->addable
// changes if n->left is an escaping local variable. // changes if n->left is an escaping local variable.
...@@ -69,7 +64,9 @@ cgen(Node *n, Node *res) ...@@ -69,7 +64,9 @@ cgen(Node *n, Node *res)
// if both are addressable, move // if both are addressable, move
if(n->addable && res->addable) { if(n->addable && res->addable) {
if (is64(n->type) || is64(res->type) || n->op == OREGISTER || res->op == OREGISTER) { if(is64(n->type) || is64(res->type) ||
n->op == OREGISTER || res->op == OREGISTER ||
iscomplex[n->type->etype] || iscomplex[res->type->etype]) {
gmove(n, res); gmove(n, res);
} else { } else {
regalloc(&n1, n->type, N); regalloc(&n1, n->type, N);
...@@ -99,8 +96,13 @@ cgen(Node *n, Node *res) ...@@ -99,8 +96,13 @@ cgen(Node *n, Node *res)
return; return;
} }
if(complexop(n, res)) {
complexgen(n, res);
return;
}
// if n is sudoaddable generate addr and move // if n is sudoaddable generate addr and move
if (!is64(n->type) && !is64(res->type)) { if (!is64(n->type) && !is64(res->type) && !iscomplex[n->type->etype] && !iscomplex[res->type->etype]) {
a = optoas(OAS, n->type); a = optoas(OAS, n->type);
if(sudoaddable(a, n, &addr, &w)) { if(sudoaddable(a, n, &addr, &w)) {
if (res->op != OREGISTER) { if (res->op != OREGISTER) {
......
...@@ -539,6 +539,11 @@ gmove(Node *f, Node *t) ...@@ -539,6 +539,11 @@ gmove(Node *f, Node *t)
tt = simsimtype(t->type); tt = simsimtype(t->type);
cvt = t->type; cvt = t->type;
if(iscomplex[ft] || iscomplex[tt]) {
complexmove(f, t);
return;
}
// cannot have two memory operands; // cannot have two memory operands;
// except 64-bit, which always copies via registers anyway. // except 64-bit, which always copies via registers anyway.
if(!is64(f->type) && !is64(t->type) && ismem(f) && ismem(t)) if(!is64(f->type) && !is64(t->type) && ismem(f) && ismem(t))
......
...@@ -175,7 +175,7 @@ cgen(Node *n, Node *res) ...@@ -175,7 +175,7 @@ cgen(Node *n, Node *res)
case OREAL: case OREAL:
case OIMAG: case OIMAG:
case OCMPLX: case OCMPLX:
// TODO compile complex fatal("unexpected complex");
return; return;
// these call bgen to get a bool value // these call bgen to get a bool value
......
...@@ -387,13 +387,13 @@ codeblk(int32 addr, int32 size) ...@@ -387,13 +387,13 @@ codeblk(int32 addr, int32 size)
break; break;
if(addr < sym->value) { if(addr < sym->value) {
Bprint(&bso, "%-20s %.8llux|", "_", addr); Bprint(&bso, "%-20s %.8llux|", "_", (vlong)addr);
for(; addr < sym->value; addr++) for(; addr < sym->value; addr++)
Bprint(&bso, " %.2ux", 0); Bprint(&bso, " %.2ux", 0);
Bprint(&bso, "\n"); Bprint(&bso, "\n");
} }
p = sym->text; p = sym->text;
Bprint(&bso, "%.6llux\t%-20s | %P\n", addr, sym->name, p); Bprint(&bso, "%.6llux\t%-20s | %P\n", (vlong)addr, sym->name, p);
for(p = p->link; p != P; p = p->link) { for(p = p->link; p != P; p = p->link) {
if(p->link != P) if(p->link != P)
epc = p->link->pc; epc = p->link->pc;
...@@ -408,7 +408,7 @@ codeblk(int32 addr, int32 size) ...@@ -408,7 +408,7 @@ codeblk(int32 addr, int32 size)
} }
if(addr < eaddr) { if(addr < eaddr) {
Bprint(&bso, "%-20s %.8llux|", "_", addr); Bprint(&bso, "%-20s %.8llux|", "_", (vlong)addr);
for(; addr < eaddr; addr++) for(; addr < eaddr; addr++)
Bprint(&bso, " %.2ux", 0); Bprint(&bso, " %.2ux", 0);
} }
......
...@@ -204,22 +204,14 @@ endif ...@@ -204,22 +204,14 @@ endif
ifeq ($(GOARCH),arm) ifeq ($(GOARCH),arm)
# Tests that fail, probably 5g bugs. # Tests that fail, probably 5g bugs.
# Disable so that dashboard all.bash can catch regressions. # Disable so that dashboard all.bash can catch regressions.
NOTEST+=cmath # floating point NOTEST+=cmath # software floating point (lack of) accuracy
NOTEST+=crypto/block # weird bit error NOTEST+=math # software floating point (lack of) accuracy
NOTEST+=encoding/binary # floating point? NOTEST+=strconv # software floating point (lack of) accuracy
NOTEST+=exp/datafmt # crash
NOTEST+=exp/eval # crash NOTEST+=fmt # spurious uint overflow
NOTEST+=flag # floating point NOTEST+=gob # something involving complex
NOTEST+=fmt # floating point NOTEST+=json # spurious uint overflow
NOTEST+=go/printer # crash
NOTEST+=gob # floating point
NOTEST+=image/png # bit errors
NOTEST+=json # floating point
NOTEST+=math # floating point
NOTEST+=os/signal # crash NOTEST+=os/signal # crash
NOTEST+=strconv # floating point
NOTEST+=syslog # unix syslog
NOTEST+=xml # floating point
endif endif
TEST=\ TEST=\
......
...@@ -169,7 +169,7 @@ s2d(uint32 s) ...@@ -169,7 +169,7 @@ s2d(uint32 s)
return DNINF; return DNINF;
if ((s & ~(1ul << 31)) == FNAN) if ((s & ~(1ul << 31)) == FNAN)
return DNAN; return DNAN;
return (uint64)(s & 0x80000000) << 63 | // sign return (uint64)(s & 0x80000000) << 32 | // sign
(uint64)((s >> 23 &0xff) + (DOUBLE_EXPBIAS - SINGLE_EXPBIAS)) << 52 | // exponent (uint64)((s >> 23 &0xff) + (DOUBLE_EXPBIAS - SINGLE_EXPBIAS)) << 52 | // exponent
(uint64)(s & 0x7fffff) << 29; // mantissa (uint64)(s & 0x7fffff) << 29; // mantissa
} }
...@@ -211,7 +211,10 @@ dataprocess(uint32* pc) ...@@ -211,7 +211,10 @@ dataprocess(uint32* pc)
if (unary) { if (unary) {
switch (opcode) { switch (opcode) {
case 0: // mvf case 0: // mvf
m->freg[dest] = frhs(rhs); fd = frhs(rhs);
if(prec == 0)
fd = s2d(d2s(fd));
m->freg[dest] = fd;
goto ret; goto ret;
default: default:
goto undef; goto undef;
......
...@@ -15,9 +15,11 @@ package strconv ...@@ -15,9 +15,11 @@ package strconv
import ( import (
"math" "math"
"os" "os"
"runtime"
) )
var optimize = true // can change for testing // TODO(rsc): remove "arm" check
var optimize = runtime.GOARCH != "arm" // can change for testing
// TODO(rsc): Better truncation handling. // TODO(rsc): Better truncation handling.
func stringToDecimal(s string) (neg bool, d *decimal, trunc bool, ok bool) { func stringToDecimal(s string) (neg bool, d *decimal, trunc bool, ok bool) {
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
package strconv package strconv
import "math" import "math"
import "runtime"
// TODO: move elsewhere? // TODO: move elsewhere?
type floatInfo struct { type floatInfo struct {
...@@ -23,6 +24,9 @@ var float32info = floatInfo{23, 8, -127} ...@@ -23,6 +24,9 @@ var float32info = floatInfo{23, 8, -127}
var float64info = floatInfo{52, 11, -1023} var float64info = floatInfo{52, 11, -1023}
func floatsize() int { func floatsize() int {
if runtime.GOARCH == "arm" { // TODO(rsc): remove
return 32
}
// Figure out whether float is float32 or float64. // Figure out whether float is float32 or float64.
// 1e-35 is representable in both, but 1e-70 // 1e-35 is representable in both, but 1e-70
// is too small for a float32. // is too small for a float32.
......
...@@ -6,9 +6,17 @@ ...@@ -6,9 +6,17 @@
package strconv package strconv
import "runtime"
func NewDecimal(i uint64) *decimal { return newDecimal(i) } func NewDecimal(i uint64) *decimal { return newDecimal(i) }
func SetOptimize(b bool) bool { func SetOptimize(b bool) bool {
if runtime.GOARCH == "arm" {
// optimize is always false on arm,
// because the software floating point
// has such terrible multiplication.
return false
}
old := optimize old := optimize
optimize = b optimize = b
return old return old
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment