@@ -134,6 +134,9 @@ reset__decode:
134134 op sub decode_duration @time decode_start_time
135135 set STATE "running"
136136
137+ # clear LR/SC reservation set
138+ set reservation_set null
139+
137140 # start executing code at address 4 (address 0 is __etext)
138141 set pc 4
139142 set icache_var null
@@ -238,6 +241,17 @@ done_pause_step:
238241 jump DIVU always
239242 jump REM always
240243 jump REMU always
244+ jump AMOADD.W always
245+ jump AMOSWAP.W always
246+ jump LR.W always
247+ jump SC.W always
248+ jump AMOXOR.W always
249+ jump AMOOR.W always
250+ jump AMOAND.W always
251+ jump AMOMIN.W always
252+ jump AMOMAX.W always
253+ jump AMOMINU.W always
254+ jump AMOMAXU.W always
241255
242256# we jump here at the start of the main loop if icache_var is null
243257access_icache:
@@ -387,29 +401,29 @@ extend_sign:
387401
388402 set @counter ret
389403
390- # converts a pair of two's complement unsigned values to signed, or vice versa
404+ # converts a pair of two's complement unsigned values to signed in-place , or vice versa
391405# this converts two values at once because most usages of it need to convert two values
392406# also, the values are assumed to be in rs1 and rs2
393- # rs1, rs2 -> result1, result2
407+ # rs1, rs2 -> rs1, rs2
394408swap_signedness_rs1_rs2:
395409 # value < 2^31 ? (value + 2^32) % 2^32 : value - 2^32
396410 jump swap_signedness__s2u_2 lessThan rs2 0x80000000
397- op sub result2 rs2 0x100000000
411+ op sub rs2 rs2 0x100000000
398412 jump swap_signedness__done_2 always
399413swap_signedness__s2u_2:
400- op add result2 rs2 0x100000000
401- op mod result2 result2 0x100000000
414+ op add rs2 rs2 0x100000000
415+ op mod rs2 rs2 0x100000000
402416swap_signedness__done_2:
403417
404- # converts a two's complement unsigned value in rs1 to signed, or vice versa
405- # rs1 -> result1
418+ # converts a two's complement unsigned value in rs1 to signed in-place , or vice versa
419+ # rs1 -> rs1
406420swap_signedness_rs1:
407421 jump swap_signedness__s2u_1 lessThan rs1 0x80000000 # 2^31
408- op sub result1 rs1 0x100000000 # 2^32
422+ op sub rs1 rs1 0x100000000 # 2^32
409423 jump swap_signedness__done_1 always
410424swap_signedness__s2u_1:
411- op add result1 rs1 0x100000000
412- op mod result1 result1 0x100000000
425+ op add rs1 rs1 0x100000000
426+ op mod rs1 rs1 0x100000000
413427swap_signedness__done_1:
414428
415429 set @counter ret
@@ -572,7 +586,7 @@ decode__ok:
572586 jump decode_STORE always
573587 jump decode_illegal_instruction always # STORE-FP
574588 jump decode_illegal_instruction always # custom-1
575- jump decode_illegal_instruction always # AMO
589+ jump decode_AMO always
576590 jump decode_OP always
577591 jump decode_LUI always
578592 jump decode_illegal_instruction always # OP-32
@@ -703,6 +717,32 @@ decode_STORE:
703717 op add op_id 16 funct3 # 16 (SB) to 18 (SW)
704718 jump end_decode always
705719
720+ decode_AMO:
721+ # R-type: arg1=rs1, arg2=rs2, arg3=rd
722+ jump decode_illegal_instruction notEqual funct3 0b010
723+
724+ # funct5
725+ # mlogv32 is single-hart, so just ignore aq and rl
726+ op shr funct5 funct7 2
727+
728+ # funct5 either has bits in [4:2] or [1:0] set, never both
729+ # (ab)use that so we don't need 32 lookup table entries
730+ jump decode_AMO__high greaterThan funct5 0b11
731+
732+ # low bits
733+ op add op_id 54 funct5 # 54 (AMOADD.W) to 57 (SC.W)
734+ jump end_decode always
735+
736+ decode_AMO__high:
737+ # high bits
738+ op and low funct5 0b11
739+ jump decode_illegal_instruction notEqual low 0b00
740+
741+ # note: funct5 >> 2 starts at 1, not 0
742+ op shr funct5 funct5 2
743+ op add op_id 57 funct5 # 58 (AMOXOR.W) to 64 (AMOMAXU.W)
744+ jump end_decode always
745+
706746decode_OP-IMM:
707747 op add @counter @counter funct3_x2
708748
@@ -906,15 +946,15 @@ BLT:
906946 op add ret @counter 1
907947 jump swap_signedness_rs1_rs2 always
908948
909- jump conditional_branch lessThan result1 result2
949+ jump conditional_branch lessThan rs1 rs2
910950 jump end_instruction always
911951
912952BGE:
913953 # B-type: arg1=rs1, arg2=rs2, arg3=imm
914954 op add ret @counter 1
915955 jump swap_signedness_rs1_rs2 always
916956
917- jump conditional_branch greaterThanEq result1 result2
957+ jump conditional_branch greaterThanEq rs1 rs2
918958 jump end_instruction always
919959
920960BLTU:
@@ -1070,6 +1110,152 @@ SW:
10701110 set length 32
10711111 jump store_value always
10721112
1113+ LR.W:
1114+ # R-type: arg1=rs1, arg2=0, arg3=rd
1115+ # check alignment
1116+ op mod alignment rs1 4
1117+ jump misaligned_load notEqual alignment 0
1118+
1119+ # load value
1120+ set address rs1
1121+ op add ret @counter 1
1122+ jump load_word always
1123+
1124+ # register reservation set
1125+ # TODO: implement Za64rs?
1126+ set reservation_set rs1
1127+
1128+ jump end_instruction equal arg3 0
1129+ write result REGISTERS arg3
1130+ jump end_instruction always
1131+
1132+ SC.W:
1133+ # R-type: arg1=rs1, arg2=rs2, arg3=rd
1134+
1135+ # check address and alignment
1136+ jump inaccessible_store lessThan rs1 RAM_START
1137+ jump inaccessible_store greaterThanEq rs1 RAM_END
1138+
1139+ op mod alignment rs1 4
1140+ jump misaligned_load notEqual alignment 0
1141+
1142+ # check if reservation is valid and contains rs1
1143+ op strictEqual success rs1 reservation_set
1144+
1145+ # invalidate reservation
1146+ set reservation_set null
1147+
1148+ # write 0 to rd if successful, else write 1
1149+ jump SC.W__no_write_rd equal arg3 0
1150+ op notEqual result success true
1151+ write result REGISTERS arg3
1152+ SC.W__no_write_rd:
1153+
1154+ # conditionally write value
1155+ jump end_instruction notEqual success true
1156+
1157+ set address rs1
1158+ op add access_ram__ret @counter 1
1159+ jump access_ram always
1160+
1161+ set value rs2
1162+
1163+ atomic_store_word:
1164+ op add ret @counter 1
1165+ jump swap_endianness always
1166+
1167+ write result ram variable
1168+
1169+ set instruction value
1170+ set decode_var null
1171+ op add decode_ret @counter 1
1172+ jump decode always
1173+
1174+ jump end_instruction always
1175+
1176+ AMOSWAP.W:
1177+ # R-type: arg1=rs1, arg2=rs2, arg3=rd
1178+ set amo_op 0 # swap
1179+
1180+ amo:
1181+ # check address and alignment
1182+ jump inaccessible_store lessThan rs1 RAM_START
1183+ jump inaccessible_store greaterThanEq rs1 RAM_END
1184+
1185+ op mod alignment rs1 4
1186+ jump misaligned_load notEqual alignment 0
1187+
1188+ # read
1189+ set address rs1
1190+ op add ret @counter 1
1191+ jump load_word always
1192+
1193+ # put value in rd
1194+ jump amo__no_write_rd equal arg3 0
1195+ write result REGISTERS arg3
1196+ amo__no_write_rd:
1197+
1198+ # modify
1199+ op add @counter @counter amo_op
1200+
1201+ set result rs2; jump amo__done_modify always # swap
1202+ op add result result rs2; jump amo__done_modify always # add
1203+ op and result result rs2; jump amo__done_modify always # and
1204+ op or result result rs2; jump amo__done_modify always # or
1205+ op xor result result rs2; jump amo__done_modify always # xor
1206+ op min result result rs2; jump amo__done_modify always # min
1207+ op max result result rs2 # max
1208+
1209+ amo__done_modify:
1210+
1211+ # write
1212+ op and value result 0xffffffff
1213+ jump atomic_store_word always
1214+
1215+ AMOADD.W:
1216+ # R-type: arg1=rs1, arg2=rs2, arg3=rd
1217+ set amo_op 2 # add
1218+ jump amo always
1219+
1220+ AMOAND.W:
1221+ # R-type: arg1=rs1, arg2=rs2, arg3=rd
1222+ set amo_op 4 # and
1223+ jump amo always
1224+
1225+ AMOOR.W:
1226+ # R-type: arg1=rs1, arg2=rs2, arg3=rd
1227+ set amo_op 6 # or
1228+ jump amo always
1229+
1230+ AMOXOR.W:
1231+ # R-type: arg1=rs1, arg2=rs2, arg3=rd
1232+ set amo_op 8 # xor
1233+ jump amo always
1234+
1235+ AMOMIN.W:
1236+ # R-type: arg1=rs1, arg2=rs2, arg3=rd
1237+ op add ret @counter 1
1238+ jump swap_signedness_rs1_rs2 always
1239+ set amo_op 10 # min
1240+ jump amo always
1241+
1242+ AMOMAX.W:
1243+ # R-type: arg1=rs1, arg2=rs2, arg3=rd
1244+ op add ret @counter 1
1245+ jump swap_signedness_rs1_rs2 always
1246+ set amo_op 12 # max
1247+ jump amo always
1248+
1249+ AMOMINU.W:
1250+ # R-type: arg1=rs1, arg2=rs2, arg3=rd
1251+ set amo_op 10 # min
1252+ jump amo always
1253+
1254+ AMOMAXU.W:
1255+ # R-type: arg1=rs1, arg2=rs2, arg3=rd
1256+ set amo_op 12 # max
1257+ jump amo always
1258+
10731259ADDI:
10741260 # I-type: arg1=rs1, arg2=imm, arg3=rd
10751261 jump end_instruction equal arg3 0
@@ -1088,7 +1274,7 @@ SLTI:
10881274 op add ret @counter 1
10891275 jump swap_signedness_rs1_rs2 always
10901276
1091- op lessThan result result1 result2
1277+ op lessThan result rs1 rs2
10921278
10931279 write result REGISTERS arg3
10941280 jump end_instruction always
@@ -1259,7 +1445,7 @@ MULH:
12591445mulh_s_u:
12601446 jump end_instruction equal arg3 0
12611447
1262- op mul result result1 result2
1448+ op mul result rs1 rs2
12631449 op shr result result 32
12641450 op and result result 0xffffffff
12651451
@@ -1270,25 +1456,22 @@ MULHSU:
12701456 # R-type: arg1=rs1, arg2=rs2, arg3=rd
12711457 op add ret @counter 1
12721458 jump swap_signedness_rs1 always
1273- set result2 rs2
12741459 jump mulh_s_u always
12751460
12761461MULHU:
12771462 # R-type: arg1=rs1, arg2=rs2, arg3=rd
1278- set result1 rs1
1279- set result2 rs2
12801463 jump mulh_s_u always
12811464
12821465DIV:
12831466 # R-type: arg1=rs1, arg2=rs2, arg3=rd
12841467 jump end_instruction equal arg3 0
12851468
1286- jump div_by_zero equal arg2 0
1469+ jump div_by_zero equal rs2 0
12871470
12881471 op add ret @counter 1
12891472 jump swap_signedness_rs1_rs2 always
12901473
1291- op idiv result result1 result2
1474+ op idiv result rs1 rs2
12921475 op and result result 0xffffffff
12931476
12941477 write result REGISTERS arg3
@@ -1298,7 +1481,7 @@ DIVU:
12981481 # R-type: arg1=rs1, arg2=rs2, arg3=rd
12991482 jump end_instruction equal arg3 0
13001483
1301- jump div_by_zero equal arg2 0
1484+ jump div_by_zero equal rs2 0
13021485
13031486 op idiv result rs1 rs2
13041487
@@ -1314,12 +1497,12 @@ REM:
13141497 # R-type: arg1=rs1, arg2=rs2, arg3=rd
13151498 jump end_instruction equal arg3 0
13161499
1317- jump rem_by_zero equal arg2 0
1500+ jump rem_by_zero equal rs2 0
13181501
13191502 op add ret @counter 1
13201503 jump swap_signedness_rs1_rs2 always
13211504
1322- op mod result result1 result2
1505+ op mod result rs1 rs2
13231506 op and result result 0xffffffff
13241507
13251508 write result REGISTERS arg3
@@ -1329,7 +1512,7 @@ REMU:
13291512 # R-type: arg1=rs1, arg2=rs2, arg3=rd
13301513 jump end_instruction equal arg3 0
13311514
1332- jump rem_by_zero equal arg2 0
1515+ jump rem_by_zero equal rs2 0
13331516
13341517 op mod result rs1 rs2
13351518
0 commit comments