ref: 1fe36bf84947198199b0dcf895aedfd584521e84
parent: 08bb4afb528e91b46ae8eb13277ad51cf8d724ba
author: mischief <[email protected]>
date: Sat Feb 1 07:27:07 EST 2014
realemu: implement IDIV, mark 0xE0000 writeable, fix DIV overfow trap
--- a/sys/src/cmd/aux/realemu/xec.c
+++ b/sys/src/cmd/aux/realemu/xec.c
@@ -769,13 +769,59 @@
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 @@
[OMUL] = opmul,
[OIMUL] = opimul,
[ODIV] = opdiv,
+ [OIDIV] = opidiv,
[OLEA] = oplea,
[OMOV] = opmov,