]> git.lizzy.rs Git - plan9front.git/commitdiff
realemu: implement IDIV, mark 0xE0000 writeable, fix DIV overfow trap
authormischief <mischief@offblast.org>
Sat, 1 Feb 2014 20:27:07 +0000 (12:27 -0800)
committermischief <mischief@offblast.org>
Sat, 1 Feb 2014 20:27:07 +0000 (12:27 -0800)
sys/src/cmd/aux/realemu/xec.c

index 5a5f8a8cff86b13576b3d3f71c9729eb3b74ac12..90c8bc1ec36b8c3a5c38efbf67e67f6a89d12c0e 100644 (file)
@@ -769,12 +769,58 @@ opdiv(Cpu *cpu, Inst *i)
        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)
@@ -1249,6 +1295,7 @@ static void (*exctab[NUMOP])(Cpu *cpu, Inst*) = {
        [OMUL] = opmul,
        [OIMUL] = opimul,
        [ODIV] = opdiv,
+       [OIDIV] = opidiv,
 
        [OLEA] = oplea,
        [OMOV] = opmov,