realemu: handle address overflow

This commit is contained in:
cinap_lenrek 2011-04-29 05:49:58 +00:00
parent daef42e6b3
commit c0ebaf7ee8

View file

@ -15,6 +15,7 @@ push(Iarg *sp, Iarg *a)
p = amem(sp->cpu, a->len, RSS, ar(sp)); p = amem(sp->cpu, a->len, RSS, ar(sp));
p->off -= a->len; p->off -= a->len;
p->off &= mask(sp->len*8);
aw(p, ar(a)); aw(p, ar(a));
aw(sp, p->off); aw(sp, p->off);
} }
@ -495,12 +496,9 @@ opbittest(Cpu *cpu, Inst *i)
x = i->a1; x = i->a1;
s = x->len*8; s = x->len*8;
if(x->tag == TMEM){ if(x->tag == TMEM){
int z;
x = adup(x); x = adup(x);
x->off += (n / s) * x->len; x->off += (n / s) * x->len;
z = i->alen*8; x->off &= mask(i->alen*8);
x->off &= mask(z);
} }
a = ar(x); a = ar(x);
n &= s-1; n &= s-1;
@ -972,9 +970,10 @@ static void
opmovs(Cpu *cpu, Inst *i) opmovs(Cpu *cpu, Inst *i)
{ {
Iarg *cx, *d, *s; Iarg *cx, *d, *s;
ulong c; ulong c, m;
int n; int n;
m = mask(i->alen*8);
d = adup(i->a1); d = adup(i->a1);
s = adup(i->a2); s = adup(i->a2);
n = s->len; n = s->len;
@ -990,7 +989,9 @@ opmovs(Cpu *cpu, Inst *i)
while(c){ while(c){
aw(d, ar(s)); aw(d, ar(s));
d->off += n; d->off += n;
d->off &= m;
s->off += n; s->off += n;
s->off &= m;
c--; c--;
} }
aw(areg(cpu, i->alen, RDI), d->off); aw(areg(cpu, i->alen, RDI), d->off);
@ -1003,9 +1004,10 @@ static void
oplods(Cpu *cpu, Inst *i) oplods(Cpu *cpu, Inst *i)
{ {
Iarg *cx, *s; Iarg *cx, *s;
ulong c; ulong c, m;
int n; int n;
m = mask(i->alen*8);
s = adup(i->a2); s = adup(i->a2);
n = s->len; n = s->len;
if(cpu->reg[RFL] & DF) if(cpu->reg[RFL] & DF)
@ -1019,8 +1021,10 @@ oplods(Cpu *cpu, Inst *i)
} }
if(c){ if(c){
s->off += n*(c-1); s->off += n*(c-1);
s->off &= m;
aw(i->a1, ar(s)); aw(i->a1, ar(s));
s->off += n; s->off += n;
s->off &= m;
} }
aw(areg(cpu, i->alen, RSI), s->off); aw(areg(cpu, i->alen, RSI), s->off);
if(cx) if(cx)
@ -1031,9 +1035,10 @@ static void
opstos(Cpu *cpu, Inst *i) opstos(Cpu *cpu, Inst *i)
{ {
Iarg *cx, *d; Iarg *cx, *d;
ulong c, a; ulong c, a, m;
int n; int n;
m = mask(i->alen*8);
d = adup(i->a1); d = adup(i->a1);
n = d->len; n = d->len;
if(cpu->reg[RFL] & DF) if(cpu->reg[RFL] & DF)
@ -1049,6 +1054,7 @@ opstos(Cpu *cpu, Inst *i)
while(c){ while(c){
aw(d, a); aw(d, a);
d->off += n; d->off += n;
d->off &= m;
c--; c--;
} }
aw(areg(cpu, i->alen, RDI), d->off); aw(areg(cpu, i->alen, RDI), d->off);
@ -1059,26 +1065,25 @@ opstos(Cpu *cpu, Inst *i)
static int static int
repcond(Cpu *cpu, int rep) repcond(Cpu *cpu, int rep)
{ {
switch(rep){ if(rep == OREPNE)
case OREPNE:
return (cpu->reg[RFL] & ZF) == 0; return (cpu->reg[RFL] & ZF) == 0;
case OREPE: return !rep || (cpu->reg[RFL] & ZF) != 0;
default:
return !rep || (cpu->reg[RFL] & ZF) != 0;
}
} }
static void static void
opscas(Cpu *cpu, Inst *i) opscas(Cpu *cpu, Inst *i)
{ {
Iarg *cx, *s; Iarg *cx, *d;
ulong c; ulong *f, c, m;
long a; long a;
int n; int n, z;
s = adup(i->a1); m = mask(i->alen*8);
n = s->len; d = adup(i->a1);
if(cpu->reg[RFL] & DF) n = d->len;
z = n*8;
f = cpu->reg + RFL;
if(*f & DF)
n = -n; n = -n;
if(i->rep){ if(i->rep){
cx = areg(cpu, i->alen, RCX); cx = areg(cpu, i->alen, RCX);
@ -1089,13 +1094,14 @@ opscas(Cpu *cpu, Inst *i)
} }
a = ars(i->a2); a = ars(i->a2);
while(c){ while(c){
sub(cpu->reg + RFL, a, ars(s), 0, s->len*8); sub(f, a, ars(d), 0, z);
s->off += n; d->off += n;
d->off &= m;
c--; c--;
if(repcond(cpu, i->rep)) if(repcond(cpu, i->rep))
break; break;
} }
aw(areg(cpu, i->alen, RDI), s->off); aw(areg(cpu, i->alen, RDI), d->off);
if(cx) if(cx)
aw(cx, c); aw(cx, c);
} }
@ -1104,13 +1110,16 @@ static void
opcmps(Cpu *cpu, Inst *i) opcmps(Cpu *cpu, Inst *i)
{ {
Iarg *cx, *s, *d; Iarg *cx, *s, *d;
ulong c; ulong *f, c, m;
int n; int n, z;
m = mask(i->alen*8);
d = adup(i->a1); d = adup(i->a1);
s = adup(i->a2); s = adup(i->a2);
n = s->len; n = s->len;
if(cpu->reg[RFL] & DF) z = n*8;
f = cpu->reg + RFL;
if(*f & DF)
n = -n; n = -n;
if(i->rep){ if(i->rep){
cx = areg(cpu, i->alen, RCX); cx = areg(cpu, i->alen, RCX);
@ -1120,9 +1129,11 @@ opcmps(Cpu *cpu, Inst *i)
c = 1; c = 1;
} }
while(c){ 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 += n;
s->off &= m;
d->off += n; d->off += n;
d->off &= m;
c--; c--;
if(repcond(cpu, i->rep)) if(repcond(cpu, i->rep))
break; break;