Commit Diff


commit - cc17802d9c1b8d811f2045b6e047326d85dc3444
commit + 0ed5ecb832e32efc6b14ca4073ee2fb0a6f3018a
blob - 1e8765501eefc02cf51b9f751f1b7208f15ce810
blob + 05d839119a65abac506979add72e7529eddb1714
--- src/cpu.c
+++ src/cpu.c
@@ -282,10 +282,6 @@ void cpu_exec (u32 instr)
 		case 0b0000000'000: // add
 			c = a + b;
 			alu ("add");
-			break;
-		case 0b0000001'000: // mul
-			c = a * b;
-			alu ("mul");
 			break;
 		case 0b0100000'000: // sub
 			c = a - b;
@@ -306,19 +302,11 @@ void cpu_exec (u32 instr)
 		case 0b0000000'100: // xor
 			c = a ^ b;
 			alu ("xor");
-			break;
-		case 0b0000001'100: // div
-			c = b != 0 ? (i64)a / (i64)b : -1;
-			alu ("div");
 			break;
 		case 0b0000000'101: // srl
 			c = a >> (b & 0x3f);
 			alu ("srl");
 			break;
-		case 0b0000001'101: // divu
-			c = b != 0 ? a / b : -1;
-			alu ("divu");
-			break;
 		case 0b0100000'101: // sra
 			c = (i64)a >> (b & 0x3f);
 			alu ("sra");
@@ -327,16 +315,40 @@ void cpu_exec (u32 instr)
 			c = a | b;
 			alu ("or");
 			break;
-		case 0b0000001'110: // rem
-			c = b != 0 ? (i64)a % (i64)b : -1;
-			alu ("rem");
-			break;
 		case 0b0000000'111: // and
 			c = a & b;
 			alu ("and");
+			break;
+		case 0b0000001'000: // mul
+			c = a * b;
+			alu ("mul");
+			break;
+		case 0b0000001'001: // mulh
+			c = ((i128)a * (i128)b) >> 64;
+			alu ("mulh");
+			break;
+		case 0b0000001'010: // mulhsu
+			c = ((u128)a * (i128)b) >> 64;
+			alu ("mulhsu");
+			break;
+		case 0b0000001'011: // mulhu
+			c = ((u128)a * (u128)b) >> 64;
+			alu ("mulhu");
+			break;
+		case 0b0000001'100: // div
+			c = b != 0 ? (i64)a / (i64)b : -1;
+			alu ("div");
 			break;
+		case 0b0000001'101: // divu
+			c = b != 0 ? a / b : -1;
+			alu ("divu");
+			break;
+		case 0b0000001'110: // rem
+			c = b != 0 ? (i64)a % (i64)b : a;
+			alu ("rem");
+			break;
 		case 0b0000001'111: // remu
-			c = b != 0 ? a % b : -1;
+			c = b != 0 ? a % b : 1;
 			alu ("remu");
 			break;
 		}
@@ -366,6 +378,26 @@ void cpu_exec (u32 instr)
 			c = extend ((i64)a >> (b & 0x1f));
 			alu ("sraw");
 			break;
+		case 0b000001'000: // mulw
+			c = extend (a * b);
+			alu ("mulw");
+			break;
+		case 0b000001'001: // divw
+			c = extend (b != 0 ? (i32)a / (i32)b : -1);
+			alu ("divw");
+			break;
+		case 0b000001'010: // divuw
+			c = extend (b != 0 ? (u32)a / (u32)b : -1);
+			alu ("divuw");
+			break;
+		case 0b000001'011: // remw
+			c = extend (b != 0 ? (i32)a % (i32)b : (i32)a);
+			alu ("divw");
+			break;
+		case 0b000001'100: // remuw
+			c = extend (b != 0 ? (u32)a % (u32)b : (u32)b);
+			alu ("divuw");
+			break;
 		default:
 			goto ud;
 		}
blob - f1fa870f78600a53528abcc226d280124e392286
blob + 733bc6a143bc3c452314d63bcd9212448a2861ba
--- src/linurv.h
+++ src/linurv.h
@@ -51,11 +51,13 @@ typedef uint8_t  u8;
 typedef uint16_t u16;
 typedef uint32_t u32;
 typedef uint64_t u64;
+typedef __uint128_t u128;
 
 typedef int8_t   i8;
 typedef int16_t  i16;
 typedef int32_t  i32;
 typedef int64_t  i64;
+typedef __int128_t i128;
 
 typedef unsigned int uint;