Skip to content

Commit 0bb4cba

Browse files
committed
Add tentative (untested) support for M extension, reduce size of STORE and OP_0000000 lookup tables
1 parent 064e2ac commit 0bb4cba

File tree

4 files changed

+172
-37
lines changed

4 files changed

+172
-37
lines changed

.github/.devcontainer/Dockerfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ COPY --from=ghcr.io/astral-sh/uv:0.7.6 /uv /uvx /bin/
44

55
ENV PATH=$PATH:/opt/riscv/bin
66

7-
COPY --from=ghcr.io/object-object/mlogv32-riscv-gnu-toolchain:rv32i-ilp32 /opt/riscv /opt/riscv
7+
COPY --from=ghcr.io/object-object/mlogv32-riscv-gnu-toolchain:rv32ima-ilp32 /opt/riscv /opt/riscv
88

99
# avoid permission issues with cargo if cargo install runs as root
1010
USER vscode
1111

1212
RUN rustup toolchain install nightly-2024-11-16
1313

1414
RUN rustup target add riscv32i-unknown-none-elf
15+
RUN rustup target add riscv32ima-unknown-none-elf
1516

1617
RUN rustup component add --toolchain nightly-2024-11-16 clippy llvm-tools
1718

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ RISC-V processor in Mindustry logic. Requires Mindustry build 149+.
66

77
## Architecture
88

9-
Extensions: `rv32i_Zicsr_Zicntr_Zihintpause`
9+
Extensions: `rv32im_Zicsr_Zicntr_Zihintpause`
1010

1111
Memory consists of three sections. Two are directly accessible by code: ROM (rx) and RAM (rw). The third section is an instruction cache, which takes up 4x as much space as the executable portion of memory. The instruction cache is updated at reset and whenever an instruction writes to RAM.
1212

src/main.mlog

Lines changed: 159 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -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
235243
access_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
402402
swap_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

698706
decode_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

733742
decode_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

745746
decode_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+
754760
decode_MISC-MEM:
755761
jump decode_illegal_instruction notEqual funct3 0
756762

@@ -898,15 +904,15 @@ BNE:
898904
BLT:
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

906912
BGE:
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+
12181344
FENCE:
12191345
# I-type: arg1=rs1, arg2=imm, arg3=rd
12201346

src/tools/registers.mlog

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -485,15 +485,15 @@ format_op_id:
485485
format "SRLI"; set @counter ret
486486
format "SRAI"; set @counter ret
487487
format "ADD"; set @counter ret
488-
format "SUB"; set @counter ret
489488
format "SLL"; set @counter ret
490489
format "SLT"; set @counter ret
491490
format "SLTU"; set @counter ret
492491
format "XOR"; set @counter ret
493492
format "SRL"; set @counter ret
494-
format "SRA"; set @counter ret
495493
format "OR"; set @counter ret
496494
format "AND"; set @counter ret
495+
format "SUB"; set @counter ret
496+
format "SRA"; set @counter ret
497497
format "FENCE"; set @counter ret
498498
format "PRIV"; set @counter ret
499499
format "CSRRW"; set @counter ret
@@ -502,6 +502,14 @@ format_op_id:
502502
format "CSRRWI"; set @counter ret
503503
format "CSRRSI"; set @counter ret
504504
format "CSRRCI"; set @counter ret
505+
format "MUL"; set @counter ret
506+
format "MULH"; set @counter ret
507+
format "MULHSU"; set @counter ret
508+
format "MULHU"; set @counter ret
509+
format "DIV"; set @counter ret
510+
format "DIVU"; set @counter ret
511+
format "REM"; set @counter ret
512+
format "REMU"; set @counter ret
505513
format_op_id__unknown:
506514
format n; set @counter ret
507515

0 commit comments

Comments
 (0)