From df88fc610975b0be07a1cd49199eb9917a7748e3 Mon Sep 17 00:00:00 2001 From: Kai Backman Date: Fri, 6 Aug 2010 16:57:49 -0700 Subject: [PATCH] arm: bugfixes and syscall - integer divide by zero raises panic - float comparisons involving NaNs work - syscall interface actually handles return values and errno correctly. R=rsc, bradfitzpatrick CC=golang-dev https://golang.org/cl/1847047 --- src/cmd/5g/cgen.c | 11 +- src/pkg/runtime/arm/vlop.s | 2 +- src/pkg/runtime/arm/vlrt.c | 773 ++++++++++++++++---------------- src/pkg/syscall/asm_linux_arm.s | 49 +- test/arm-pass.txt | 4 +- 5 files changed, 446 insertions(+), 393 deletions(-) diff --git a/src/cmd/5g/cgen.c b/src/cmd/5g/cgen.c index b0c9b88da4..310ea99c5b 100644 --- a/src/cmd/5g/cgen.c +++ b/src/cmd/5g/cgen.c @@ -1044,7 +1044,16 @@ bgen(Node *n, int true, Prog *to) cgen(nr, &n2); gcmp(optoas(OCMP, nr->type), &n1, &n2); - patch(gbranch(a, nr->type), to); + if(isfloat[nl->type->etype]) { + p1 = gbranch(ABVS, nr->type); + patch(gbranch(a, nr->type), to); + if(n->op == ONE) + patch(p1, to); + else + patch(p1, pc); + } else { + patch(gbranch(a, nr->type), to); + } regfree(&n1); regfree(&n2); diff --git a/src/pkg/runtime/arm/vlop.s b/src/pkg/runtime/arm/vlop.s index c9e7090fc0..f95f0f1d89 100644 --- a/src/pkg/runtime/arm/vlop.s +++ b/src/pkg/runtime/arm/vlop.s @@ -62,7 +62,7 @@ TEXT save<>(SB), 7, $0 MOVW 20(FP), R(D) /* denominator */ CMP $0, R(D) BNE s1 - SWI 0 + BL panicdivide(SB) /* MOVW -1(R(D)), R(TMP) /* divide by zero fault */ s1: RET diff --git a/src/pkg/runtime/arm/vlrt.c b/src/pkg/runtime/arm/vlrt.c index 76b777a354..51ae15baa4 100644 --- a/src/pkg/runtime/arm/vlrt.c +++ b/src/pkg/runtime/arm/vlrt.c @@ -23,6 +23,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +// declared here to avoid include of runtime.h +void panicstring(char*); + typedef unsigned long ulong; typedef unsigned int uint; typedef unsigned short ushort; @@ -31,6 +34,12 @@ typedef signed char schar; #define SIGN(n) (1UL<<(n-1)) +void +panicdivide(void) +{ + panicstring("integer divide by zero"); +} + typedef struct Vlong Vlong; struct Vlong { @@ -47,8 +56,8 @@ struct Vlong ushort loms; ushort hils; ushort hims; - }; - }; + }; + }; }; void abort(void); @@ -56,90 +65,90 @@ void abort(void); void _addv(Vlong *r, Vlong a, Vlong b) { - ulong lo, hi; + ulong lo, hi; - lo = a.lo + b.lo; - hi = a.hi + b.hi; - if(lo < a.lo) - hi++; - r->lo = lo; - r->hi = hi; + lo = a.lo + b.lo; + hi = a.hi + b.hi; + if(lo < a.lo) + hi++; + r->lo = lo; + r->hi = hi; } void _subv(Vlong *r, Vlong a, Vlong b) { - ulong lo, hi; + ulong lo, hi; - lo = a.lo - b.lo; - hi = a.hi - b.hi; - if(lo > a.lo) - hi--; - r->lo = lo; - r->hi = hi; + lo = a.lo - b.lo; + hi = a.hi - b.hi; + if(lo > a.lo) + hi--; + r->lo = lo; + r->hi = hi; } void _d2v(Vlong *y, double d) { - union { double d; struct Vlong; } x; - ulong xhi, xlo, ylo, yhi; - int sh; + union { double d; struct Vlong; } x; + ulong xhi, xlo, ylo, yhi; + int sh; - x.d = d; + x.d = d; - xhi = (x.hi & 0xfffff) | 0x100000; - xlo = x.lo; - sh = 1075 - ((x.hi >> 20) & 0x7ff); + xhi = (x.hi & 0xfffff) | 0x100000; + xlo = x.lo; + sh = 1075 - ((x.hi >> 20) & 0x7ff); - ylo = 0; - yhi = 0; - if(sh >= 0) { - /* v = (hi||lo) >> sh */ - if(sh < 32) { - if(sh == 0) { - ylo = xlo; - yhi = xhi; - } else { - ylo = (xlo >> sh) | (xhi << (32-sh)); - yhi = xhi >> sh; - } - } else { - if(sh == 32) { - ylo = xhi; - } else - if(sh < 64) { - ylo = xhi >> (sh-32); - } - } - } else { - /* v = (hi||lo) << -sh */ - sh = -sh; - if(sh <= 10) { - ylo = xlo << sh; - yhi = (xhi << sh) | (xlo >> (32-sh)); - } else { - /* overflow */ - yhi = d; /* causes something awful */ - } - } - if(x.hi & SIGN(32)) { - if(ylo != 0) { - ylo = -ylo; - yhi = ~yhi; - } else - yhi = -yhi; - } + ylo = 0; + yhi = 0; + if(sh >= 0) { + /* v = (hi||lo) >> sh */ + if(sh < 32) { + if(sh == 0) { + ylo = xlo; + yhi = xhi; + } else { + ylo = (xlo >> sh) | (xhi << (32-sh)); + yhi = xhi >> sh; + } + } else { + if(sh == 32) { + ylo = xhi; + } else + if(sh < 64) { + ylo = xhi >> (sh-32); + } + } + } else { + /* v = (hi||lo) << -sh */ + sh = -sh; + if(sh <= 10) { + ylo = xlo << sh; + yhi = (xhi << sh) | (xlo >> (32-sh)); + } else { + /* overflow */ + yhi = d; /* causes something awful */ + } + } + if(x.hi & SIGN(32)) { + if(ylo != 0) { + ylo = -ylo; + yhi = ~yhi; + } else + yhi = -yhi; + } - y->hi = yhi; - y->lo = ylo; + y->hi = yhi; + y->lo = ylo; } void _f2v(Vlong *y, float f) { - _d2v(y, f); + _d2v(y, f); } void @@ -151,21 +160,21 @@ void double _v2d(Vlong x) { - if(x.hi & SIGN(32)) { - if(x.lo) { - x.lo = -x.lo; - x.hi = ~x.hi; - } else - x.hi = -x.hi; - return -((long)x.hi*4294967296. + x.lo); - } - return (long)x.hi*4294967296. + x.lo; + if(x.hi & SIGN(32)) { + if(x.lo) { + x.lo = -x.lo; + x.hi = ~x.hi; + } else + x.hi = -x.hi; + return -((long)x.hi*4294967296. + x.lo); + } + return (long)x.hi*4294967296. + x.lo; } float _v2f(Vlong x) { - return _v2d(x); + return _v2d(x); } void @@ -178,75 +187,75 @@ void static void dodiv(Vlong num, Vlong den, Vlong *q, Vlong *r) { - ulong numlo, numhi, denhi, denlo, quohi, quolo, t; - int i; + ulong numlo, numhi, denhi, denlo, quohi, quolo, t; + int i; - numhi = num.hi; - numlo = num.lo; - denhi = den.hi; - denlo = den.lo; + numhi = num.hi; + numlo = num.lo; + denhi = den.hi; + denlo = den.lo; - /* - * get a divide by zero - */ - if(denlo==0 && denhi==0) { - numlo = numlo / denlo; - } + /* + * get a divide by zero + */ + if(denlo==0 && denhi==0) { + panicdivide(); + } - /* - * set up the divisor and find the number of iterations needed - */ - if(numhi >= SIGN(32)) { - quohi = SIGN(32); - quolo = 0; - } else { - quohi = numhi; - quolo = numlo; - } - i = 0; - while(denhi < quohi || (denhi == quohi && denlo < quolo)) { - denhi = (denhi<<1) | (denlo>>31); - denlo <<= 1; - i++; - } + /* + * set up the divisor and find the number of iterations needed + */ + if(numhi >= SIGN(32)) { + quohi = SIGN(32); + quolo = 0; + } else { + quohi = numhi; + quolo = numlo; + } + i = 0; + while(denhi < quohi || (denhi == quohi && denlo < quolo)) { + denhi = (denhi<<1) | (denlo>>31); + denlo <<= 1; + i++; + } - quohi = 0; - quolo = 0; - for(; i >= 0; i--) { - quohi = (quohi<<1) | (quolo>>31); - quolo <<= 1; - if(numhi > denhi || (numhi == denhi && numlo >= denlo)) { - t = numlo; - numlo -= denlo; - if(numlo > t) - numhi--; - numhi -= denhi; - quolo |= 1; - } - denlo = (denlo>>1) | (denhi<<31); - denhi >>= 1; - } + quohi = 0; + quolo = 0; + for(; i >= 0; i--) { + quohi = (quohi<<1) | (quolo>>31); + quolo <<= 1; + if(numhi > denhi || (numhi == denhi && numlo >= denlo)) { + t = numlo; + numlo -= denlo; + if(numlo > t) + numhi--; + numhi -= denhi; + quolo |= 1; + } + denlo = (denlo>>1) | (denhi<<31); + denhi >>= 1; + } - if(q) { - q->lo = quolo; - q->hi = quohi; - } - if(r) { - r->lo = numlo; - r->hi = numhi; - } + if(q) { + q->lo = quolo; + q->hi = quohi; + } + if(r) { + r->lo = numlo; + r->hi = numhi; + } } void _divvu(Vlong *q, Vlong n, Vlong d) { - if(n.hi == 0 && d.hi == 0) { - q->hi = 0; - q->lo = n.lo / d.lo; - return; - } - dodiv(n, d, q, 0); + if(n.hi == 0 && d.hi == 0) { + q->hi = 0; + q->lo = n.lo / d.lo; + return; + } + dodiv(n, d, q, 0); } void @@ -259,12 +268,12 @@ void _modvu(Vlong *r, Vlong n, Vlong d) { - if(n.hi == 0 && d.hi == 0) { - r->hi = 0; - r->lo = n.lo % d.lo; - return; - } - dodiv(n, d, 0, r); + if(n.hi == 0 && d.hi == 0) { + r->hi = 0; + r->lo = n.lo % d.lo; + return; + } + dodiv(n, d, 0, r); } void @@ -277,20 +286,20 @@ static void vneg(Vlong *v) { - if(v->lo == 0) { - v->hi = -v->hi; - return; - } - v->lo = -v->lo; - v->hi = ~v->hi; + if(v->lo == 0) { + v->hi = -v->hi; + return; + } + v->lo = -v->lo; + v->hi = ~v->hi; } void _divv(Vlong *q, Vlong n, Vlong d) { - long nneg, dneg; + long nneg, dneg; - if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) { + if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) { if((long)n.lo == -0x80000000 && (long)d.lo == -1) { // special case: 32-bit -0x80000000 / -1 causes wrong sign q->lo = 0x80000000; @@ -300,16 +309,16 @@ _divv(Vlong *q, Vlong n, Vlong d) q->lo = (long)n.lo / (long)d.lo; q->hi = ((long)q->lo) >> 31; return; - } - nneg = n.hi >> 31; - if(nneg) - vneg(&n); - dneg = d.hi >> 31; - if(dneg) - vneg(&d); - dodiv(n, d, q, 0); - if(nneg != dneg) - vneg(q); + } + nneg = n.hi >> 31; + if(nneg) + vneg(&n); + dneg = d.hi >> 31; + if(dneg) + vneg(&d); + dodiv(n, d, q, 0); + if(nneg != dneg) + vneg(q); } void @@ -321,22 +330,22 @@ void void _modv(Vlong *r, Vlong n, Vlong d) { - long nneg, dneg; + long nneg, dneg; - if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) { - r->lo = (long)n.lo % (long)d.lo; - r->hi = ((long)r->lo) >> 31; - return; - } - nneg = n.hi >> 31; - if(nneg) - vneg(&n); - dneg = d.hi >> 31; - if(dneg) - vneg(&d); - dodiv(n, d, 0, r); - if(nneg) - vneg(r); + if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) { + r->lo = (long)n.lo % (long)d.lo; + r->hi = ((long)r->lo) >> 31; + return; + } + nneg = n.hi >> 31; + if(nneg) + vneg(&n); + dneg = d.hi >> 31; + if(dneg) + vneg(&d); + dodiv(n, d, 0, r); + if(nneg) + vneg(r); } void @@ -348,439 +357,439 @@ void void _rshav(Vlong *r, Vlong a, int b) { - long t; + long t; - t = a.hi; - if(b >= 32) { - r->hi = t>>31; - if(b >= 64) { - /* this is illegal re C standard */ - r->lo = t>>31; - return; - } - r->lo = t >> (b-32); - return; - } - if(b <= 0) { - r->hi = t; - r->lo = a.lo; - return; - } - r->hi = t >> b; - r->lo = (t << (32-b)) | (a.lo >> b); + t = a.hi; + if(b >= 32) { + r->hi = t>>31; + if(b >= 64) { + /* this is illegal re C standard */ + r->lo = t>>31; + return; + } + r->lo = t >> (b-32); + return; + } + if(b <= 0) { + r->hi = t; + r->lo = a.lo; + return; + } + r->hi = t >> b; + r->lo = (t << (32-b)) | (a.lo >> b); } void _rshlv(Vlong *r, Vlong a, int b) { - ulong t; + ulong t; - t = a.hi; - if(b >= 32) { - r->hi = 0; - if(b >= 64) { - /* this is illegal re C standard */ - r->lo = 0; - return; - } - r->lo = t >> (b-32); - return; - } - if(b <= 0) { - r->hi = t; - r->lo = a.lo; - return; - } - r->hi = t >> b; - r->lo = (t << (32-b)) | (a.lo >> b); + t = a.hi; + if(b >= 32) { + r->hi = 0; + if(b >= 64) { + /* this is illegal re C standard */ + r->lo = 0; + return; + } + r->lo = t >> (b-32); + return; + } + if(b <= 0) { + r->hi = t; + r->lo = a.lo; + return; + } + r->hi = t >> b; + r->lo = (t << (32-b)) | (a.lo >> b); } void _lshv(Vlong *r, Vlong a, int b) { - ulong t; + ulong t; - t = a.lo; - if(b >= 32) { - r->lo = 0; - if(b >= 64) { - /* this is illegal re C standard */ - r->hi = 0; - return; - } - r->hi = t << (b-32); - return; - } - if(b <= 0) { - r->lo = t; - r->hi = a.hi; - return; - } - r->lo = t << b; - r->hi = (t >> (32-b)) | (a.hi << b); + t = a.lo; + if(b >= 32) { + r->lo = 0; + if(b >= 64) { + /* this is illegal re C standard */ + r->hi = 0; + return; + } + r->hi = t << (b-32); + return; + } + if(b <= 0) { + r->lo = t; + r->hi = a.hi; + return; + } + r->lo = t << b; + r->hi = (t >> (32-b)) | (a.hi << b); } void _andv(Vlong *r, Vlong a, Vlong b) { - r->hi = a.hi & b.hi; - r->lo = a.lo & b.lo; + r->hi = a.hi & b.hi; + r->lo = a.lo & b.lo; } void _orv(Vlong *r, Vlong a, Vlong b) { - r->hi = a.hi | b.hi; - r->lo = a.lo | b.lo; + r->hi = a.hi | b.hi; + r->lo = a.lo | b.lo; } void _xorv(Vlong *r, Vlong a, Vlong b) { - r->hi = a.hi ^ b.hi; - r->lo = a.lo ^ b.lo; + r->hi = a.hi ^ b.hi; + r->lo = a.lo ^ b.lo; } void _vpp(Vlong *l, Vlong *r) { - l->hi = r->hi; - l->lo = r->lo; - r->lo++; - if(r->lo == 0) - r->hi++; + l->hi = r->hi; + l->lo = r->lo; + r->lo++; + if(r->lo == 0) + r->hi++; } void _vmm(Vlong *l, Vlong *r) { - l->hi = r->hi; - l->lo = r->lo; - if(r->lo == 0) - r->hi--; - r->lo--; + l->hi = r->hi; + l->lo = r->lo; + if(r->lo == 0) + r->hi--; + r->lo--; } void _ppv(Vlong *l, Vlong *r) { - r->lo++; - if(r->lo == 0) - r->hi++; - l->hi = r->hi; - l->lo = r->lo; + r->lo++; + if(r->lo == 0) + r->hi++; + l->hi = r->hi; + l->lo = r->lo; } void _mmv(Vlong *l, Vlong *r) { - if(r->lo == 0) - r->hi--; - r->lo--; - l->hi = r->hi; - l->lo = r->lo; + if(r->lo == 0) + r->hi--; + r->lo--; + l->hi = r->hi; + l->lo = r->lo; } void _vasop(Vlong *ret, void *lv, void fn(Vlong*, Vlong, Vlong), int type, Vlong rv) { - Vlong t, u; + Vlong t, u; - u = *ret; - switch(type) { - default: - abort(); - break; + u = *ret; + switch(type) { + default: + abort(); + break; - case 1: /* schar */ - t.lo = *(schar*)lv; - t.hi = t.lo >> 31; - fn(&u, t, rv); - *(schar*)lv = u.lo; - break; + case 1: /* schar */ + t.lo = *(schar*)lv; + t.hi = t.lo >> 31; + fn(&u, t, rv); + *(schar*)lv = u.lo; + break; - case 2: /* uchar */ - t.lo = *(uchar*)lv; - t.hi = 0; - fn(&u, t, rv); - *(uchar*)lv = u.lo; - break; + case 2: /* uchar */ + t.lo = *(uchar*)lv; + t.hi = 0; + fn(&u, t, rv); + *(uchar*)lv = u.lo; + break; - case 3: /* short */ - t.lo = *(short*)lv; - t.hi = t.lo >> 31; - fn(&u, t, rv); - *(short*)lv = u.lo; - break; + case 3: /* short */ + t.lo = *(short*)lv; + t.hi = t.lo >> 31; + fn(&u, t, rv); + *(short*)lv = u.lo; + break; - case 4: /* ushort */ - t.lo = *(ushort*)lv; - t.hi = 0; - fn(&u, t, rv); - *(ushort*)lv = u.lo; - break; + case 4: /* ushort */ + t.lo = *(ushort*)lv; + t.hi = 0; + fn(&u, t, rv); + *(ushort*)lv = u.lo; + break; - case 9: /* int */ - t.lo = *(int*)lv; - t.hi = t.lo >> 31; - fn(&u, t, rv); - *(int*)lv = u.lo; - break; + case 9: /* int */ + t.lo = *(int*)lv; + t.hi = t.lo >> 31; + fn(&u, t, rv); + *(int*)lv = u.lo; + break; - case 10: /* uint */ - t.lo = *(uint*)lv; - t.hi = 0; - fn(&u, t, rv); - *(uint*)lv = u.lo; - break; + case 10: /* uint */ + t.lo = *(uint*)lv; + t.hi = 0; + fn(&u, t, rv); + *(uint*)lv = u.lo; + break; - case 5: /* long */ - t.lo = *(long*)lv; - t.hi = t.lo >> 31; - fn(&u, t, rv); - *(long*)lv = u.lo; - break; + case 5: /* long */ + t.lo = *(long*)lv; + t.hi = t.lo >> 31; + fn(&u, t, rv); + *(long*)lv = u.lo; + break; - case 6: /* ulong */ - t.lo = *(ulong*)lv; - t.hi = 0; - fn(&u, t, rv); - *(ulong*)lv = u.lo; - break; + case 6: /* ulong */ + t.lo = *(ulong*)lv; + t.hi = 0; + fn(&u, t, rv); + *(ulong*)lv = u.lo; + break; - case 7: /* vlong */ - case 8: /* uvlong */ - fn(&u, *(Vlong*)lv, rv); - *(Vlong*)lv = u; - break; - } - *ret = u; + case 7: /* vlong */ + case 8: /* uvlong */ + fn(&u, *(Vlong*)lv, rv); + *(Vlong*)lv = u; + break; + } + *ret = u; } void _p2v(Vlong *ret, void *p) { - long t; + long t; - t = (ulong)p; - ret->lo = t; - ret->hi = 0; + t = (ulong)p; + ret->lo = t; + ret->hi = 0; } void _sl2v(Vlong *ret, long sl) { - long t; + long t; - t = sl; - ret->lo = t; - ret->hi = t >> 31; + t = sl; + ret->lo = t; + ret->hi = t >> 31; } void _ul2v(Vlong *ret, ulong ul) { - long t; + long t; - t = ul; - ret->lo = t; - ret->hi = 0; + t = ul; + ret->lo = t; + ret->hi = 0; } void _si2v(Vlong *ret, int si) { - long t; + long t; - t = si; - ret->lo = t; - ret->hi = t >> 31; + t = si; + ret->lo = t; + ret->hi = t >> 31; } void _ui2v(Vlong *ret, uint ui) { - long t; + long t; - t = ui; - ret->lo = t; - ret->hi = 0; + t = ui; + ret->lo = t; + ret->hi = 0; } void _sh2v(Vlong *ret, long sh) { - long t; + long t; - t = (sh << 16) >> 16; - ret->lo = t; - ret->hi = t >> 31; + t = (sh << 16) >> 16; + ret->lo = t; + ret->hi = t >> 31; } void _uh2v(Vlong *ret, ulong ul) { - long t; + long t; - t = ul & 0xffff; - ret->lo = t; - ret->hi = 0; + t = ul & 0xffff; + ret->lo = t; + ret->hi = 0; } void _sc2v(Vlong *ret, long uc) { - long t; + long t; - t = (uc << 24) >> 24; - ret->lo = t; - ret->hi = t >> 31; + t = (uc << 24) >> 24; + ret->lo = t; + ret->hi = t >> 31; } void _uc2v(Vlong *ret, ulong ul) { - long t; + long t; - t = ul & 0xff; - ret->lo = t; - ret->hi = 0; + t = ul & 0xff; + ret->lo = t; + ret->hi = 0; } long _v2sc(Vlong rv) { - long t; + long t; - t = rv.lo & 0xff; - return (t << 24) >> 24; + t = rv.lo & 0xff; + return (t << 24) >> 24; } long _v2uc(Vlong rv) { - return rv.lo & 0xff; + return rv.lo & 0xff; } long _v2sh(Vlong rv) { - long t; + long t; - t = rv.lo & 0xffff; - return (t << 16) >> 16; + t = rv.lo & 0xffff; + return (t << 16) >> 16; } long _v2uh(Vlong rv) { - return rv.lo & 0xffff; + return rv.lo & 0xffff; } long _v2sl(Vlong rv) { - return rv.lo; + return rv.lo; } long _v2ul(Vlong rv) { - return rv.lo; + return rv.lo; } long _v2si(Vlong rv) { - return rv.lo; + return rv.lo; } long _v2ui(Vlong rv) { - return rv.lo; + return rv.lo; } int _testv(Vlong rv) { - return rv.lo || rv.hi; + return rv.lo || rv.hi; } int _eqv(Vlong lv, Vlong rv) { - return lv.lo == rv.lo && lv.hi == rv.hi; + return lv.lo == rv.lo && lv.hi == rv.hi; } int _nev(Vlong lv, Vlong rv) { - return lv.lo != rv.lo || lv.hi != rv.hi; + return lv.lo != rv.lo || lv.hi != rv.hi; } int _ltv(Vlong lv, Vlong rv) { - return (long)lv.hi < (long)rv.hi || - (lv.hi == rv.hi && lv.lo < rv.lo); + return (long)lv.hi < (long)rv.hi || + (lv.hi == rv.hi && lv.lo < rv.lo); } int _lev(Vlong lv, Vlong rv) { - return (long)lv.hi < (long)rv.hi || - (lv.hi == rv.hi && lv.lo <= rv.lo); + return (long)lv.hi < (long)rv.hi || + (lv.hi == rv.hi && lv.lo <= rv.lo); } int _gtv(Vlong lv, Vlong rv) { - return (long)lv.hi > (long)rv.hi || - (lv.hi == rv.hi && lv.lo > rv.lo); + return (long)lv.hi > (long)rv.hi || + (lv.hi == rv.hi && lv.lo > rv.lo); } int _gev(Vlong lv, Vlong rv) { - return (long)lv.hi > (long)rv.hi || - (lv.hi == rv.hi && lv.lo >= rv.lo); + return (long)lv.hi > (long)rv.hi || + (lv.hi == rv.hi && lv.lo >= rv.lo); } int _lov(Vlong lv, Vlong rv) { - return lv.hi < rv.hi || - (lv.hi == rv.hi && lv.lo < rv.lo); + return lv.hi < rv.hi || + (lv.hi == rv.hi && lv.lo < rv.lo); } int _lsv(Vlong lv, Vlong rv) { - return lv.hi < rv.hi || - (lv.hi == rv.hi && lv.lo <= rv.lo); + return lv.hi < rv.hi || + (lv.hi == rv.hi && lv.lo <= rv.lo); } int _hiv(Vlong lv, Vlong rv) { - return lv.hi > rv.hi || - (lv.hi == rv.hi && lv.lo > rv.lo); + return lv.hi > rv.hi || + (lv.hi == rv.hi && lv.lo > rv.lo); } int _hsv(Vlong lv, Vlong rv) { - return lv.hi > rv.hi || - (lv.hi == rv.hi && lv.lo >= rv.lo); + return lv.hi > rv.hi || + (lv.hi == rv.hi && lv.lo >= rv.lo); } diff --git a/src/pkg/syscall/asm_linux_arm.s b/src/pkg/syscall/asm_linux_arm.s index 830d41c788..a5790885b4 100644 --- a/src/pkg/syscall/asm_linux_arm.s +++ b/src/pkg/syscall/asm_linux_arm.s @@ -17,9 +17,21 @@ TEXT ·Syscall(SB),7,$0 MOVW 12(SP), R1 MOVW 16(SP), R2 SWI $0 - MOVW R0, 20(SP) // r1 - MOVW R1, 24(SP) // r2 + MOVW $0xfffff001, R1 + CMP R1, R0 + BLS ok + MOVW $-1, R1 + MOVW R1, 20(SP) // r1 + MOVW $0, R2 + MOVW R2, 24(SP) // r2 + RSB $0, R0, R0 + MOVW R0, 28(SP) // errno + BL runtime·exitsyscall(SB) + RET +ok: + MOVW R0, 20(SP) // r1 MOVW $0, R0 + MOVW R0, 24(SP) // r2 MOVW R0, 28(SP) // errno BL runtime·exitsyscall(SB) RET @@ -36,9 +48,21 @@ TEXT ·Syscall6(SB),7,$0 MOVW 24(SP), R4 MOVW 28(SP), R5 SWI $0 - MOVW R0, 32(SP) // r1 - MOVW R1, 36(SP) // r2 + MOVW $0xfffff001, R1 + CMP R1, R0 + BLS ok6 + MOVW $-1, R1 + MOVW R1, 32(SP) // r1 + MOVW $0, R2 + MOVW R2, 36(SP) // r2 + RSB $0, R0, R0 + MOVW R0, 40(SP) // errno + BL runtime·exitsyscall(SB) + RET +ok6: + MOVW R0, 32(SP) // r1 MOVW $0, R0 + MOVW R0, 36(SP) // r2 MOVW R0, 40(SP) // errno BL runtime·exitsyscall(SB) RET @@ -50,8 +74,19 @@ TEXT ·RawSyscall(SB),7,$0 MOVW 12(SP), R1 MOVW 16(SP), R2 SWI $0 - MOVW R0, 20(SP) // r1 - MOVW R1, 24(SP) // r2 - MOVW $0, R0 + MOVW $0xfffff001, R1 + CMP R1, R0 + BLS ok1 + MOVW $-1, R1 + MOVW R1, 20(SP) // r1 + MOVW $0, R2 + MOVW R2, 24(SP) // r2 + RSB $0, R0, R0 + MOVW R0, 28(SP) // errno + RET +ok1: + MOVW R0, 20(SP) // r1 + MOVW $0, R0 + MOVW R0, 24(SP) // r2 MOVW R0, 28(SP) // errno RET diff --git a/test/arm-pass.txt b/test/arm-pass.txt index 0a586a077b..2c7230f100 100644 --- a/test/arm-pass.txt +++ b/test/arm-pass.txt @@ -43,7 +43,7 @@ ./env.go ./escape.go ./float_lit.go -# ./floatcmp.go # fail, BUG +./floatcmp.go ./for.go ./func.go ./func1.go @@ -116,7 +116,7 @@ ./varerr.go ./varinit.go ./vectors.go -# ./zerodivide.go # fail, BUG +./zerodivide.go ken/array.go ken/chan.go ken/chan1.go