p = amem(sp->cpu, a->len, RSS, ar(sp));
p->off -= a->len;
+ p->off &= mask(sp->len*8);
aw(p, ar(a));
aw(sp, p->off);
}
}
static void
-opbt(Cpu *cpu, Inst *i)
+opbittest(Cpu *cpu, Inst *i)
{
ulong a, m;
int n, s;
s = x->len*8;
if(x->tag == TMEM){
x = adup(x);
- x->off += n / s;
+ x->off += (n / s) * x->len;
x->off &= mask(i->alen*8);
}
a = ar(x);
n = (uvlong)ar(ra)<<s | (uvlong)ar(qa);
q = n/d;
if(q > m)
- trap(cpu, EGPF);
+ trap(cpu, EDIV0);
r = n%d;
aw(ra, r);
aw(qa, q);
}
-
+
+static void
+opidiv(Cpu *cpu, Inst *i)
+{
+ Iarg *qa, *ra;
+ vlong n, q, min, max;
+ long r, d;
+ int s;
+
+ s = i->a1->len*8;
+ d = ars(i->a1);
+ if(d == 0)
+ trap(cpu, EDIV0);
+ if(s == 8){
+ qa = areg(cpu, 1, RAX);
+ ra = adup(qa);
+ ra->tag |= TH;
+ } else {
+ qa = areg(cpu, i->olen, RAX);
+ ra = areg(cpu, i->olen, RDX);
+ }
+ n = (vlong)ars(ra)<<s | (uvlong)ars(qa);
+ q = n/d;
+ r = n%d;
+
+ /* check for overflow based on operand size */
+ switch(s) {
+ case 8:
+ min = (char)0x80;
+ max = 0x7F;
+ break;
+ case 16:
+ min = (short)0x8000;
+ max = 0x7FFF;
+ break;
+ case 32:
+ min = (long)0x80000000;
+ max = 0x7FFFFFFF;
+ break;
+ }
+
+ if(q > max || q < min)
+ trap(cpu, EDIV0);
+
+ aw(ra, r);
+ aw(qa, q);
+}
static int
cctrue(Cpu *cpu, Inst *i)
} tab[] = {
0,
5,
- 0x756e6547,
- 0x49656e69,
- 0x6c65746e,
+ 0x756e6547, /* Genu */
+ 0x6c65746e, /* ntel */
+ 0x49656e69, /* ineI */
1,
4<<8,
0x00000000,
opmovs(Cpu *cpu, Inst *i)
{
Iarg *cx, *d, *s;
- ulong c;
+ ulong c, m;
int n;
+ m = mask(i->alen*8);
d = adup(i->a1);
s = adup(i->a2);
n = s->len;
while(c){
aw(d, ar(s));
d->off += n;
+ d->off &= m;
s->off += n;
+ s->off &= m;
c--;
}
aw(areg(cpu, i->alen, RDI), d->off);
oplods(Cpu *cpu, Inst *i)
{
Iarg *cx, *s;
- ulong c;
+ ulong c, m;
int n;
+ m = mask(i->alen*8);
s = adup(i->a2);
n = s->len;
if(cpu->reg[RFL] & DF)
}
if(c){
s->off += n*(c-1);
+ s->off &= m;
aw(i->a1, ar(s));
s->off += n;
+ s->off &= m;
}
aw(areg(cpu, i->alen, RSI), s->off);
if(cx)
opstos(Cpu *cpu, Inst *i)
{
Iarg *cx, *d;
- ulong c, a;
+ ulong c, a, m;
int n;
+ m = mask(i->alen*8);
d = adup(i->a1);
n = d->len;
if(cpu->reg[RFL] & DF)
while(c){
aw(d, a);
d->off += n;
+ d->off &= m;
c--;
}
aw(areg(cpu, i->alen, RDI), d->off);
}
static int
-repcond(Cpu *cpu, int rep)
+repcond(ulong *f, int rep)
{
- switch(rep){
- case OREPNE:
- return (cpu->reg[RFL] & ZF) == 0;
- case OREPE:
- default:
- return !rep || (cpu->reg[RFL] & ZF) != 0;
- }
+ if(rep == OREPNE)
+ return (*f & ZF) == 0;
+ return (*f & ZF) != 0;
}
static void
opscas(Cpu *cpu, Inst *i)
{
- Iarg *cx, *s;
- ulong c;
+ Iarg *cx, *d;
+ ulong *f, c, m;
long a;
- int n;
+ int n, z;
- s = adup(i->a1);
- n = s->len;
- if(cpu->reg[RFL] & DF)
+ m = mask(i->alen*8);
+ d = adup(i->a1);
+ n = d->len;
+ z = n*8;
+ f = cpu->reg + RFL;
+ if(*f & DF)
n = -n;
if(i->rep){
cx = areg(cpu, i->alen, RCX);
}
a = ars(i->a2);
while(c){
- sub(cpu->reg + RFL, a, ars(s), 0, s->len*8);
- s->off += n;
+ sub(f, a, ars(d), 0, z);
+ d->off += n;
+ d->off &= m;
c--;
- if(repcond(cpu, i->rep))
+ if(!repcond(f, i->rep))
break;
}
- aw(areg(cpu, i->alen, RDI), s->off);
+ aw(areg(cpu, i->alen, RDI), d->off);
if(cx)
aw(cx, c);
}
opcmps(Cpu *cpu, Inst *i)
{
Iarg *cx, *s, *d;
- ulong c;
- int n;
+ ulong *f, c, m;
+ int n, z;
+ m = mask(i->alen*8);
d = adup(i->a1);
s = adup(i->a2);
n = s->len;
- if(cpu->reg[RFL] & DF)
+ z = n*8;
+ f = cpu->reg + RFL;
+ if(*f & DF)
n = -n;
if(i->rep){
cx = areg(cpu, i->alen, RCX);
c = 1;
}
while(c){
- sub(cpu->reg + RFL, ars(s), ars(d), 0, s->len*8);
+ sub(f, ars(s), ars(d), 0, z);
s->off += n;
+ s->off &= m;
d->off += n;
+ d->off &= m;
c--;
- if(repcond(cpu, i->rep))
+ if(!repcond(f, i->rep))
break;
}
aw(areg(cpu, i->alen, RDI), d->off);
[OROL] = oprol,
[OROR] = opror,
- [OBT] = opbt,
- [OBTS] = opbt,
- [OBTR] = opbt,
- [OBTC] = opbt,
+ [OBT] = opbittest,
+ [OBTS] = opbittest,
+ [OBTR] = opbittest,
+ [OBTC] = opbittest,
[OBSF] = opbitscan,
[OBSR] = opbitscan,
[OMUL] = opmul,
[OIMUL] = opimul,
[ODIV] = opdiv,
+ [OIDIV] = opidiv,
[OLEA] = oplea,
[OMOV] = opmov,