@@ -2791,24 +2791,86 @@ fn buildBinary(
27912791 else = > unreachable ,
27922792 }
27932793 },
2794- .Percent , .PercentEqual = > {
2795- switch (def_type ) {
2796- .Integer = > {
2797- self .MOD (dest , left , right );
2798- try self .wrap (.Integer , dest , dest );
2799- },
2800- .Double = > {
2801- try self .buildExternApiCall (
2802- .fmod ,
2803- dest ,
2804- &[_ ]m.MIR_op_t {
2805- left ,
2806- right ,
2807- },
2808- );
2794+ .Percent , .PercentEqual = > switch (def_type ) {
2795+ .Integer = > {
2796+ const zero_check_label = m .MIR_new_label (self .ctx );
2797+ const done_label = m .MIR_new_label (self .ctx );
2798+ const rhs_negative_label = m .MIR_new_label (self .ctx );
2799+ const adjust_label = m .MIR_new_label (self .ctx );
2800+
2801+ self .BNE (zero_check_label , right , m .MIR_new_int_op (self .ctx , 0 ));
2802+
2803+ try self .buildExternApiCall (
2804+ .exit ,
2805+ null ,
2806+ &[_ ]m.MIR_op_t {m .MIR_new_uint_op (self .ctx , 1 )},
2807+ );
2808+
2809+ self .append (zero_check_label );
2810+
2811+ const quotient = m .MIR_new_reg_op (
2812+ self .ctx ,
2813+ try self .REG ("quotient" , m .MIR_T_I64 ),
2814+ );
2815+
2816+ self .DIV (quotient , left , right );
2817+
2818+ const product = m .MIR_new_reg_op (
2819+ self .ctx ,
2820+ try self .REG ("product" , m .MIR_T_I64 ),
2821+ );
2822+
2823+ self .MUL (product , quotient , right );
2824+
2825+ self .SUB (dest , left , product );
2826+
2827+ self .BEQ (
2828+ m .MIR_new_label_op (self .ctx , done_label ),
2829+ dest ,
2830+ m .MIR_new_int_op (self .ctx , 0 ),
2831+ );
2832+
2833+ self .BLT (
2834+ m .MIR_new_label_op (self .ctx , rhs_negative_label ),
2835+ right ,
2836+ m .MIR_new_int_op (self .ctx , 0 ),
2837+ );
2838+
2839+ self .BLT (
2840+ m .MIR_new_label_op (self .ctx , adjust_label ),
2841+ dest ,
2842+ m .MIR_new_int_op (self .ctx , 0 ),
2843+ );
2844+
2845+ self .JMP (done_label );
2846+
2847+ self .append (rhs_negative_label );
2848+
2849+ self .BGT (
2850+ m .MIR_new_label_op (self .ctx , adjust_label ),
2851+ dest ,
2852+ m .MIR_new_int_op (self .ctx , 0 ),
2853+ );
2854+
2855+ self .JMP (done_label );
2856+
2857+ self .append (adjust_label );
2858+
2859+ self .ADD (dest , dest , right );
2860+
2861+ self .append (done_label );
2862+
2863+ try self .wrap (.Integer , dest , dest );
2864+ },
2865+ .Double = > try self .buildExternApiCall (
2866+ .fmod ,
2867+ dest ,
2868+ &[_ ]m.MIR_op_t {
2869+ left ,
2870+ right ,
28092871 },
2810- else = > unreachable ,
2811- }
2872+ ) ,
2873+ else = > unreachable ,
28122874 },
28132875 .Ampersand , .AmpersandEqual = > {
28142876 self .AND (dest , left , right );
0 commit comments