@@ -213,15 +213,15 @@ done_pause_step:
213213 jump SRLI always
214214 jump SRAI always
215215 jump ADD always
216- jump SUB always
217216 jump SLL always
218217 jump SLT always
219218 jump SLTU always
220219 jump XOR always
221220 jump SRL always
222- jump SRA always
223221 jump OR always
224222 jump AND always
223+ jump SUB always
224+ jump SRA always
225225 jump FENCE always
226226 jump PRIV always
227227 jump CSRRW always
@@ -230,6 +230,14 @@ done_pause_step:
230230 jump CSRRWI always
231231 jump CSRRSI always
232232 jump CSRRCI always
233+ jump MUL always
234+ jump MULH always
235+ jump MULHSU always
236+ jump MULHU always
237+ jump DIV always
238+ jump DIVU always
239+ jump REM always
240+ jump REMU always
233241
234242# we jump here at the start of the main loop if icache_var is null
235243access_icache:
@@ -380,19 +388,11 @@ extend_sign:
380388 set @counter ret
381389
382390# converts a pair of two's complement unsigned values to signed, or vice versa
383- # this converts two values at once because every usage of it needs to convert two values
391+ # this converts two values at once because most usages of it need to convert two values
384392# also, the values are assumed to be in rs1 and rs2
385393# rs1, rs2 -> result1, result2
386- swap_signedness:
387- # rs1 < 2^31 ? (rs1 + 2^32) % 2^32 : rs1 - 2^32
388- jump swap_signedness__s2u_1 lessThan rs1 0x80000000 # 2^31
389- op sub result1 rs1 0x100000000 # 2^32
390- jump swap_signedness__done_1 always
391- swap_signedness__s2u_1:
392- op add result1 rs1 0x100000000
393- op mod result1 result1 0x100000000
394- swap_signedness__done_1:
395-
394+ swap_signedness_rs1_rs2:
395+ # value < 2^31 ? (value + 2^32) % 2^32 : value - 2^32
396396 jump swap_signedness__s2u_2 lessThan rs2 0x80000000
397397 op sub result2 rs2 0x100000000
398398 jump swap_signedness__done_2 always
@@ -401,6 +401,17 @@ swap_signedness__s2u_2:
401401 op mod result2 result2 0x100000000
402402swap_signedness__done_2:
403403
404+ # converts a two's complement unsigned value in rs1 to signed, or vice versa
405+ # rs1 -> result1
406+ swap_signedness_rs1:
407+ jump swap_signedness__s2u_1 lessThan rs1 0x80000000 # 2^31
408+ op sub result1 rs1 0x100000000 # 2^32
409+ jump swap_signedness__done_1 always
410+ swap_signedness__s2u_1:
411+ op add result1 rs1 0x100000000
412+ op mod result1 result1 0x100000000
413+ swap_signedness__done_1:
414+
404415 set @counter ret
405416
406417# get the variable name in CSRS for the specified CSR, and also check if it's read-only
@@ -689,11 +700,8 @@ decode_STORE:
689700
690701 jump decode_illegal_instruction greaterThanEq funct3 3
691702
692- op add @counter @counter funct3_x2
693-
694- set op_id 16; jump end_decode always # SB
695- set op_id 17; jump end_decode always # SH
696- set op_id 18; jump end_decode always # SW
703+ op add op_id 16 funct3 # 16 (SB) to 18 (SW)
704+ jump end_decode always
697705
698706decode_OP-IMM:
699707 op add @counter @counter funct3_x2
@@ -728,29 +736,27 @@ decode_OP:
728736 # R-type: arg1=rs1, arg2=rs2, arg3=rd
729737 jump decode_OP_0000000 equal funct7 0b0000000
730738 jump decode_OP_0100000 equal funct7 0b0100000
739+ jump decode_OP_0000001 equal funct7 0b0000001
731740 jump decode_illegal_instruction always
732741
733742decode_OP_0000000:
734- op add @counter @counter funct3_x2
735-
736- set op_id 28; jump end_decode always # ADD
737- set op_id 30; jump end_decode always # SLL
738- set op_id 31; jump end_decode always # SLT
739- set op_id 32; jump end_decode always # SLTU
740- set op_id 33; jump end_decode always # XOR
741- set op_id 34; jump end_decode always # SRL
742- set op_id 36; jump end_decode always # OR
743- set op_id 37; jump end_decode always # AND
743+ op add op_id 28 funct3 # 28 (ADD) to 35 (AND)
744+ jump end_decode always
744745
745746decode_OP_0100000:
746- set op_id 29 # SUB
747+ set op_id 36 # SUB
747748 jump end_decode equal funct3 0b000
748749
749- set op_id 35 # SRA
750+ set op_id 37 # SRA
750751 jump end_decode equal funct3 0b101
751752
752753 jump decode_illegal_instruction always
753754
755+ # M extension
756+ decode_OP_0000001:
757+ op add op_id 46 funct3 # 46 (MUL) to 53 (REMU)
758+ jump end_decode always
759+
754760decode_MISC-MEM:
755761 jump decode_illegal_instruction notEqual funct3 0
756762
@@ -898,15 +904,15 @@ BNE:
898904BLT:
899905 # B-type: arg1=rs1, arg2=rs2, arg3=imm
900906 op add ret @counter 1
901- jump swap_signedness always
907+ jump swap_signedness_rs1_rs2 always
902908
903909 jump conditional_branch lessThan result1 result2
904910 jump end_instruction always
905911
906912BGE:
907913 # B-type: arg1=rs1, arg2=rs2, arg3=imm
908914 op add ret @counter 1
909- jump swap_signedness always
915+ jump swap_signedness_rs1_rs2 always
910916
911917 jump conditional_branch greaterThanEq result1 result2
912918 jump end_instruction always
@@ -1080,7 +1086,7 @@ SLTI:
10801086
10811087 set rs2 arg2
10821088 op add ret @counter 1
1083- jump swap_signedness always
1089+ jump swap_signedness_rs1_rs2 always
10841090
10851091 op lessThan result result1 result2
10861092
@@ -1215,6 +1221,126 @@ AND:
12151221 set arg2 rs2
12161222 jump ANDI always
12171223
1224+ MUL:
1225+ # R-type: arg1=rs1, arg2=rs2, arg3=rd
1226+ jump end_instruction equal arg3 0
1227+
1228+ # https://github.com/es-shims/Math.imul/blob/dab2a3bfc9ce5f4af97057c64ae1880fdbac57a5/implementation.js
1229+
1230+ op shr rs1_high rs1 16
1231+ op and rs1_high rs1_high 0xffff
1232+
1233+ op and rs1_low rs1 0xffff
1234+
1235+ op shr rs2_high rs2 16
1236+ op and rs2_high rs2_high 0xffff
1237+
1238+ op and rs2_low rs2 0xffff
1239+
1240+ op mul low_low rs1_low rs2_low
1241+ op mul high_low rs1_high rs2_low
1242+ op mul low_high rs1_low rs2_high
1243+
1244+ op add result high_low low_high
1245+ op shl result result 16
1246+ op add result result low_low
1247+ op and result result 0xffffffff
1248+
1249+ write result REGISTERS arg3
1250+ jump end_instruction always
1251+
1252+ # MULH[[S]U] can safely be implemented using double multiplication because we only care about the high order bits
1253+
1254+ MULH:
1255+ # R-type: arg1=rs1, arg2=rs2, arg3=rd
1256+ op add ret @counter 1
1257+ jump swap_signedness_rs1_rs2 always
1258+
1259+ mulh_s_u:
1260+ jump end_instruction equal arg3 0
1261+
1262+ op mul result result1 result2
1263+ op shr result result 32
1264+ op and result result 0xffffffff
1265+
1266+ write result REGISTERS arg3
1267+ jump end_instruction always
1268+
1269+ MULHSU:
1270+ # R-type: arg1=rs1, arg2=rs2, arg3=rd
1271+ op add ret @counter 1
1272+ jump swap_signedness_rs1 always
1273+ set result2 rs2
1274+ jump mulh_s_u always
1275+
1276+ MULHU:
1277+ # R-type: arg1=rs1, arg2=rs2, arg3=rd
1278+ set result1 rs1
1279+ set result2 rs2
1280+ jump mulh_s_u always
1281+
1282+ DIV:
1283+ # R-type: arg1=rs1, arg2=rs2, arg3=rd
1284+ jump end_instruction equal arg3 0
1285+
1286+ jump div_by_zero equal arg2 0
1287+
1288+ op add ret @counter 1
1289+ jump swap_signedness_rs1_rs2 always
1290+
1291+ op idiv result result1 result2
1292+ op and result result 0xffffffff
1293+
1294+ write result REGISTERS arg3
1295+ jump end_instruction always
1296+
1297+ DIVU:
1298+ # R-type: arg1=rs1, arg2=rs2, arg3=rd
1299+ jump end_instruction equal arg3 0
1300+
1301+ jump div_by_zero equal arg2 0
1302+
1303+ op idiv result rs1 rs2
1304+
1305+ write result REGISTERS arg3
1306+ jump end_instruction always
1307+
1308+ div_by_zero:
1309+ # all bits set
1310+ write 0xffffffff REGISTERS arg3
1311+ jump end_instruction always
1312+
1313+ REM:
1314+ # R-type: arg1=rs1, arg2=rs2, arg3=rd
1315+ jump end_instruction equal arg3 0
1316+
1317+ jump rem_by_zero equal arg2 0
1318+
1319+ op add ret @counter 1
1320+ jump swap_signedness_rs1_rs2 always
1321+
1322+ op mod result result1 result2
1323+ op and result result 0xffffffff
1324+
1325+ write result REGISTERS arg3
1326+ jump end_instruction always
1327+
1328+ REMU:
1329+ # R-type: arg1=rs1, arg2=rs2, arg3=rd
1330+ jump end_instruction equal arg3 0
1331+
1332+ jump rem_by_zero equal arg2 0
1333+
1334+ op mod result rs1 rs2
1335+
1336+ write result REGISTERS arg3
1337+ jump end_instruction always
1338+
1339+ rem_by_zero:
1340+ # dividend
1341+ write rs1 REGISTERS arg3
1342+ jump end_instruction always
1343+
12181344FENCE:
12191345 # I-type: arg1=rs1, arg2=imm, arg3=rd
12201346
0 commit comments