@@ -35,10 +35,16 @@ func rem(w *OutputWriter, command AssemblyCommand) { /* rem & remu instructions
3535 dst := irArgExpr (w , command .Arguments [0 ])
3636 lhs := irArgExpr (w , command .Arguments [1 ])
3737 rhs := irArgExpr (w , command .Arguments [2 ])
38+
39+ // RISC-V: division by zero: rem(a, 0) = a
3840 if command .Name == "remu" {
39- Emit (w , IRStmtAssign (dst , irU32 (w , IRBinop ("%" , irU32 (w , lhs ), irU32 (w , rhs )))))
41+ u_lhs := irU32 (w , lhs )
42+ u_rhs := irU32 (w , rhs )
43+ Emit (w , IRStmtAssign (dst , IRIfExpr (IRBinop ("==" , u_rhs , IRLit (0 )), u_lhs , irU32 (w , IRBinop ("%" , u_lhs , u_rhs )))))
4044 } else {
41- Emit (w , IRStmtAssign (dst , irI32 (w , IRBinop ("%" , irI32 (w , lhs ), irI32 (w , rhs )))))
45+ i_lhs := irI32 (w , lhs )
46+ i_rhs := irI32 (w , rhs )
47+ Emit (w , IRStmtAssign (dst , IRIfExpr (IRBinop ("==" , i_rhs , IRLit (0 )), i_lhs , irI32 (w , IRBinop ("%" , i_lhs , i_rhs )))))
4248 }
4349}
4450func neg (w * OutputWriter , command AssemblyCommand ) { /* neg & negi instructions */
@@ -47,13 +53,24 @@ func neg(w *OutputWriter, command AssemblyCommand) { /* neg & negi instructions
4753 Emit (w , IRStmtAssign (dst , irI32 (w , IRUnop ("-" , irI32 (w , src )))))
4854}
4955
50- /** mulh — high 32 bits of 64-bit product */
5156func mulh (w * OutputWriter , command AssemblyCommand ) {
5257 dst := irArgExpr (w , command .Arguments [0 ])
5358 lhs := irArgExpr (w , command .Arguments [1 ])
5459 rhs := irArgExpr (w , command .Arguments [2 ])
55- Emit (w , IRStmtAssign (dst ,
56- IRCall (BIT32_BAND ,
57- IRCall (BIT32_LSHIFT , lhs , rhs ),
58- IRLitHex (0xFFFFFFFF ))))
60+
61+ // Use math.floor( (a * b) / 2^32 ) for mulh
62+ // We use u32 for all operands to ensure we stay in the realm of Luau's 53-bit mantissa correctly if possible,
63+ // but for full 64-bit mul we might need care.
64+ // RISC-V mulhu/mulh/mulhsu have different sign handling.
65+
66+ if command .Name == "mulhu" {
67+ u_lhs := irU32 (w , lhs )
68+ u_rhs := irU32 (w , rhs )
69+ Emit (w , IRStmtAssign (dst , irU32 (w , IRCall (MATH_FLOOR , IRBinop ("/" , IRBinop ("*" , u_lhs , u_rhs ), IRLit (0x100000000 ))))))
70+ } else {
71+ // mulh (signed)
72+ i_lhs := irI32 (w , lhs )
73+ i_rhs := irI32 (w , rhs )
74+ Emit (w , IRStmtAssign (dst , irI32 (w , IRCall (MATH_FLOOR , IRBinop ("/" , IRBinop ("*" , i_lhs , i_rhs ), IRLit (0x100000000 ))))))
75+ }
5976}
0 commit comments