shithub: riscv

Download patch

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,