void mpxorfixfix(Mpint *a, Mpint *b) { int i; long x, *a1, *b1; if(a->ovf || b->ovf) { yyerror("ovf in mporfixfix"); mpmovecfix(a, 0); a->ovf = 1; return; } if(a->neg) { a->neg = 0; mpneg(a); } if(b->neg) mpneg(b); a1 = &a->a[0]; b1 = &b->a[0]; for(i=0; i<Mpprec; i++) { x = *a1 ^ *b1++; *a1++ = x; } if(b->neg) mpneg(b); if(x & Mpsign) { a->neg = 1; mpneg(a); } }
int Bconv(Fmt *fp) { char buf[500], *p; Mpint *xval, q, r, ten; int f; xval = va_arg(fp->args, Mpint*); mpmovefixfix(&q, xval); f = 0; if(mptestfix(&q) < 0) { f = 1; mpnegfix(&q); } mpmovecfix(&ten, 10); p = &buf[sizeof(buf)]; *--p = 0; for(;;) { mpdivmodfixfix(&q, &r, &q, &ten); *--p = mpgetfix(&r) + '0'; if(mptestfix(&q) <= 0) break; } if(f) *--p = '-'; return fmtstrcpy(fp, p); }
int mpcmpfixc(Mpint *b, vlong c) { Mpint c1; mpmovecfix(&c1, c); return mpcmpfixfix(b, &c1); }
void mpmulcfix(Mpint *a, vlong c) { Mpint b; mpmovecfix(&b, c); mpmulfixfix(a, &b); }
int mpcmpfixc(Mpint *b, vlong c) { Mpint a; mpmovecfix(&a, c); return mpcmpfixfix(&a, b); }
int Bconv(Fmt *fp) { char buf[500], *p; Mpint *xval, q, r, ten, sixteen; int f, digit; xval = va_arg(fp->args, Mpint*); mpmovefixfix(&q, xval); f = 0; if(mptestfix(&q) < 0) { f = 1; mpnegfix(&q); } p = &buf[sizeof(buf)]; *--p = 0; if(fp->flags & FmtSharp) { // Hexadecimal mpmovecfix(&sixteen, 16); for(;;) { mpdivmodfixfix(&q, &r, &q, &sixteen); digit = mpgetfix(&r); if(digit < 10) *--p = digit + '0'; else *--p = digit - 10 + 'A'; if(mptestfix(&q) <= 0) break; } *--p = 'x'; *--p = '0'; } else { // Decimal mpmovecfix(&ten, 10); for(;;) { mpdivmodfixfix(&q, &r, &q, &ten); *--p = mpgetfix(&r) + '0'; if(mptestfix(&q) <= 0) break; } } if(f) *--p = '-'; return fmtstrcpy(fp, p); }
void mpaddcfix(Mpint *a, vlong c) { Mpint b; mpmovecfix(&b, c); mpaddfixfix(a, &b, 0); }
void mpcomfix(Mpint *a) { Mpint b; mpmovecfix(&b, 1); mpnegfix(a); mpsubfixfix(a, &b); }
void mplshfixfix(Mpint *a, Mpint *b) { vlong s; if(a->ovf || b->ovf) { yyerror("ovf in mporfixfix"); mpmovecfix(a, 0); a->ovf = 1; return; } s = mpgetfix(b); if(s < 0 || s >= Mpprec*Mpscale) { yyerror("stupid shift: %lld", s); mpmovecfix(a, 0); return; } mpshiftfix(a, s); }
void mpdivmodfixfix(Mpint *q, Mpint *r, Mpint *n, Mpint *d) { int i, ns, ds; ns = n->neg; ds = d->neg; n->neg = 0; d->neg = 0; mpmovefixfix(r, n); mpmovecfix(q, 0); // shift denominator until it // is larger than numerator for(i=0; i<Mpprec*Mpscale; i++) { if(mpcmp(d, r) > 0) break; mplsh(d); } // if it never happens // denominator is probably zero if(i >= Mpprec*Mpscale) { q->ovf = 1; r->ovf = 1; n->neg = ns; d->neg = ds; yyerror("set ovf in mpdivmodfixfix"); return; } // shift denominator back creating // quotient a bit at a time // when done the remaining numerator // will be the remainder for(; i>0; i--) { mplsh(q); mprsh(d); if(mpcmp(d, r) <= 0) { mpaddcfix(q, 1); mpsubfixfix(r, d); } } n->neg = ns; d->neg = ds; r->neg = ns; q->neg = ns^ds; }
int mptestfix(Mpint *a) { Mpint b; int r; mpmovecfix(&b, 0); r = mpcmp(a, &b); if(a->neg) { if(r > 0) return -1; if(r < 0) return +1; } return r; }
void mpmulfixfix(Mpint *a, Mpint *b) { int i, j, na, nb; long *a1, x; Mpint s, q; if(a->ovf || b->ovf) { yyerror("ovf in mpmulfixfix"); a->ovf = 1; return; } // pick the smaller // to test for bits na = mplen(a); nb = mplen(b); if(na > nb) { mpmovefixfix(&s, a); a1 = &b->a[0]; na = nb; } else { mpmovefixfix(&s, b); a1 = &a->a[0]; } s.neg = 0; mpmovecfix(&q, 0); for(i=0; i<na; i++) { x = *a1++; for(j=0; j<Mpscale; j++) { if(x & 1) mpaddfixfix(&q, &s); mplsh(&s); x >>= 1; } } q.neg = a->neg ^ b->neg; mpmovefixfix(a, &q); if(a->ovf) yyerror("set ovf in mpmulfixfix"); }
void mpmulfract(Mpint *a, Mpint *b) { int i, j; long *a1, x; Mpint s, q; if(a->ovf || b->ovf) { yyerror("ovf in mpmulflt"); a->ovf = 1; return; } mpmovefixfix(&s, b); a1 = &a->a[Mpprec]; s.neg = 0; mpmovecfix(&q, 0); for(i=0; i<Mpprec; i++) { x = *--a1; if(x == 0) { mprshw(&s); continue; } for(j=0; j<Mpscale; j++) { x <<= 1; if(x & Mpbase) mpaddfixfix(&q, &s); mprsh(&s); } } q.neg = a->neg ^ b->neg; mpmovefixfix(a, &q); if(a->ovf) yyerror("set ovf in mpmulflt"); }
// // fixed point input // required syntax is [+-][0[x]]d* // void mpatofix(Mpint *a, char *as) { int c, f; char *s, *s0; s = as; f = 0; mpmovecfix(a, 0); c = *s++; switch(c) { case '-': f = 1; case '+': c = *s++; if(c != '0') break; case '0': goto oct; } while(c) { if(c >= '0' && c <= '9') { mpmulcfix(a, 10); mpaddcfix(a, c-'0'); c = *s++; continue; } goto bad; } goto out; oct: c = *s++; if(c == 'x' || c == 'X') goto hex; while(c) { if(c >= '0' && c <= '7') { mpmulcfix(a, 8); mpaddcfix(a, c-'0'); c = *s++; continue; } goto bad; } goto out; hex: s0 = s; c = *s; while(c) { if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) { s++; c = *s; continue; } goto bad; } mphextofix(a, s0, s-s0); if(a->ovf) goto bad; out: if(f) mpnegfix(a); return; bad: yyerror("constant too large: %s", as); mpmovecfix(a, 0); }
/* * look for * unsafe.Sizeof * unsafe.Offsetof * rewrite with a constant */ Node* unsafenmagic(Node *fn, NodeList *args) { Node *r, *n; Sym *s; Type *t, *tr; long v; Val val; if(fn == N || fn->op != ONAME || (s = fn->sym) == S) goto no; if(strcmp(s->package, "unsafe") != 0) goto no; if(args == nil) { yyerror("missing argument for %S", s); goto no; } r = args->n; n = nod(OLITERAL, N, N); if(strcmp(s->name, "Sizeof") == 0) { typecheck(&r, Erv); tr = r->type; if(r->op == OLITERAL && r->val.ctype == CTSTR) tr = types[TSTRING]; if(tr == T) goto no; v = tr->width; goto yes; } if(strcmp(s->name, "Offsetof") == 0) { if(r->op != ODOT && r->op != ODOTPTR) goto no; typecheck(&r, Erv); v = r->xoffset; goto yes; } if(strcmp(s->name, "Alignof") == 0) { typecheck(&r, Erv); tr = r->type; if(r->op == OLITERAL && r->val.ctype == CTSTR) tr = types[TSTRING]; if(tr == T) goto no; // make struct { byte; T; } t = typ(TSTRUCT); t->type = typ(TFIELD); t->type->type = types[TUINT8]; t->type->down = typ(TFIELD); t->type->down->type = tr; // compute struct widths dowidth(t); // the offset of T is its required alignment v = t->type->down->width; goto yes; } no: return N; yes: if(args->next != nil) yyerror("extra arguments for %S", s); // any side effects disappear; ignore init val.ctype = CTINT; val.u.xval = mal(sizeof(*n->val.u.xval)); mpmovecfix(val.u.xval, v); n = nod(OLITERAL, N, N); n->val = val; n->type = types[TINT]; return n; }
void mpaddfixfix(Mpint *a, Mpint *b) { int i, c; long x, *a1, *b1; if(a->ovf || b->ovf) { yyerror("ovf in mpaddxx"); a->ovf = 1; return; } c = 0; a1 = &a->a[0]; b1 = &b->a[0]; if(a->neg != b->neg) goto sub; // perform a+b for(i=0; i<Mpprec; i++) { x = *a1 + *b1++ + c; c = 0; if(x >= Mpbase) { x -= Mpbase; c = 1; } *a1++ = x; } a->ovf = c; if(a->ovf) yyerror("set ovf in mpaddxx"); return; sub: // perform a-b switch(mpcmp(a, b)) { case 0: mpmovecfix(a, 0); break; case 1: for(i=0; i<Mpprec; i++) { x = *a1 - *b1++ - c; c = 0; if(x < 0) { x += Mpbase; c = 1; } *a1++ = x; } break; case -1: a->neg ^= 1; for(i=0; i<Mpprec; i++) { x = *b1++ - *a1 - c; c = 0; if(x < 0) { x += Mpbase; c = 1; } *a1++ = x; } break; } }
// // fixed point input // required syntax is [+-][0[x]]d* // void mpatofix(Mpint *a, char *as) { int c, f; char *s; s = as; f = 0; mpmovecfix(a, 0); c = *s++; switch(c) { case '-': f = 1; case '+': c = *s++; if(c != '0') break; case '0': goto oct; } while(c) { if(c >= '0' && c <= '9') { mpmulcfix(a, 10); mpaddcfix(a, c-'0'); c = *s++; continue; } goto bad; } goto out; oct: c = *s++; if(c == 'x' || c == 'X') goto hex; while(c) { if(c >= '0' && c <= '7') { mpmulcfix(a, 8); mpaddcfix(a, c-'0'); c = *s++; continue; } goto bad; } goto out; hex: c = *s++; while(c) { if(c >= '0' && c <= '9') { mpmulcfix(a, 16); mpaddcfix(a, c-'0'); c = *s++; continue; } if(c >= 'a' && c <= 'f') { mpmulcfix(a, 16); mpaddcfix(a, c+10-'a'); c = *s++; continue; } if(c >= 'A' && c <= 'F') { mpmulcfix(a, 16); mpaddcfix(a, c+10-'A'); c = *s++; continue; } goto bad; } out: if(f) mpnegfix(a); return; bad: yyerror("set ovf in mpatov: %s", as); mpmovecfix(a, 0); }
/* * look for * unsafe.Sizeof * unsafe.Offsetof * rewrite with a constant */ Node* unsafenmagic(Node *nn) { Node *r, *n; Sym *s; Type *t, *tr; long v; Val val; Node *fn; NodeList *args; fn = nn->left; args = nn->list; if(safemode || fn == N || fn->op != ONAME || (s = fn->sym) == S) goto no; if(s->pkg != unsafepkg) goto no; if(args == nil) { yyerror("missing argument for %S", s); goto no; } r = args->n; if(strcmp(s->name, "Sizeof") == 0) { typecheck(&r, Erv); defaultlit(&r, T); tr = r->type; if(tr == T) goto bad; dowidth(tr); v = tr->width; goto yes; } if(strcmp(s->name, "Offsetof") == 0) { typecheck(&r, Erv); if(r->op != ODOT && r->op != ODOTPTR) goto bad; typecheck(&r, Erv); v = r->xoffset; goto yes; } if(strcmp(s->name, "Alignof") == 0) { typecheck(&r, Erv); defaultlit(&r, T); tr = r->type; if(tr == T) goto bad; // make struct { byte; T; } t = typ(TSTRUCT); t->type = typ(TFIELD); t->type->type = types[TUINT8]; t->type->down = typ(TFIELD); t->type->down->type = tr; // compute struct widths dowidth(t); // the offset of T is its required alignment v = t->type->down->width; goto yes; } no: return N; bad: yyerror("invalid expression %#N", nn); v = 0; goto ret; yes: if(args->next != nil) yyerror("extra arguments for %S", s); ret: // any side effects disappear; ignore init val.ctype = CTINT; val.u.xval = mal(sizeof(*n->val.u.xval)); mpmovecfix(val.u.xval, v); n = nod(OLITERAL, N, N); n->val = val; n->type = types[TINT]; return n; }