ref: e003d49fe15e535c5c6183e7a865cca50769dbf3
parent: fcf2f14760571f495aa25cd54909c449d1df0215
author: cinap_lenrek <cinap_lenrek@centraldogma>
date: Fri Apr 22 09:06:55 EDT 2011
realemu: implement CMPS and SCAS instructions
--- a/sys/src/cmd/aux/realemu/xec.c
+++ b/sys/src/cmd/aux/realemu/xec.c
@@ -1040,10 +1040,87 @@
}
aw(areg(cpu, i->alen, RDI), d->off);
if(cx)
- aw(cx, 0);
+ aw(cx, c);
}
+static int
+repcond(Cpu *cpu, int rep)
+{
+ switch(rep){
+ case OREPNE:
+ return (cpu->reg[RFL] & ZF) == 0;
+ case OREPE:
+ default:
+ return !rep || (cpu->reg[RFL] & ZF) != 0;
+ }
+}
+
static void
+opscas(Cpu *cpu, Inst *i)
+{
+ Iarg *cx, *s;
+ ulong c;
+ long a;
+ int n;
+
+ s = adup(i->a1);
+ n = s->len;
+ if(cpu->reg[RFL] & DF)
+ n = -n;
+ if(i->rep){
+ cx = areg(cpu, i->alen, RCX);
+ c = ar(cx);
+ } else {
+ cx = nil;
+ c = 1;
+ }
+ a = ars(i->a2);
+ while(c){
+ sub(cpu->reg + RFL, a, ars(s), 0, s->len*8);
+ s->off += n;
+ c--;
+ if(repcond(cpu, i->rep))
+ break;
+ }
+ aw(areg(cpu, i->alen, RDI), s->off);
+ if(cx)
+ aw(cx, c);
+}
+
+static void
+opcmps(Cpu *cpu, Inst *i)
+{
+ Iarg *cx, *s, *d;
+ ulong c;
+ int n;
+
+ d = adup(i->a1);
+ s = adup(i->a2);
+ n = s->len;
+ if(cpu->reg[RFL] & DF)
+ n = -n;
+ if(i->rep){
+ cx = areg(cpu, i->alen, RCX);
+ c = ar(cx);
+ } else {
+ cx = nil;
+ c = 1;
+ }
+ while(c){
+ sub(cpu->reg + RFL, ars(s), ars(d), 0, s->len*8);
+ s->off += n;
+ d->off += n;
+ c--;
+ if(repcond(cpu, i->rep))
+ break;
+ }
+ aw(areg(cpu, i->alen, RDI), d->off);
+ aw(areg(cpu, i->alen, RSI), s->off);
+ if(cx)
+ aw(cx, c);
+}
+
+static void
opin(Cpu *cpu, Inst *i)
{
Bus *io;
@@ -1159,8 +1236,10 @@
[OCPUID] = opcpuid,
[OMOVS] = opmovs,
- [OSTOS] = opstos,
[OLODS] = oplods,
+ [OSTOS] = opstos,
+ [OSCAS] = opscas,
+ [OCMPS] = opcmps,
[OIN] = opin,
[OOUT] = opout,