authorgravatar for paul.verigo@gmail.comPavel Verigo <paul.verigo@gmail.com> 2026-04-09 00:12:10+02:00
committergravatar for paul.verigo@gmail.comPavel Verigo <paul.verigo@gmail.com> 2026-04-09 00:15:33+02:00
log773def30c24f739647112e8221fdf398b5ef12e7
treea61f7045dff9aa5d66eba3a0510ecb030a659439
parent5b5f828019331fc7714d39b760e12b488bfd577f

stage2-wasm: fix bug in big endian limb64 + tiny fixes


3 files changed, 100 insertions(+), 38 deletions(-)

lib/compiler_rt/limb64.zig+96-25
...@@ -33,6 +33,24 @@ fn limbCount(bits: u16) u16 {...@@ -33,6 +33,24 @@ fn limbCount(bits: u16) u16 {
33 return @divExact(std.zig.target.intByteSize(&builtin.target, bits), 8);33 return @divExact(std.zig.target.intByteSize(&builtin.target, bits), 8);
34}34}
3535
36fn varLimbs(ptr: [*]u64, bits: u16) []u64 {
37 const limb_cnt = usedLimbCount(bits);
38 const true_limb_cnt = limbCount(bits);
39 return switch (endian) {
40 .little => ptr[0..limb_cnt],
41 .big => ptr[true_limb_cnt - limb_cnt .. true_limb_cnt],
42 };
43}
44
45fn constLimbs(ptr: [*]const u64, bits: u16) []const u64 {
46 const limb_cnt = usedLimbCount(bits);
47 const true_limb_cnt = limbCount(bits);
48 return switch (endian) {
49 .little => ptr[0..limb_cnt],
50 .big => ptr[true_limb_cnt - limb_cnt .. true_limb_cnt],
51 };
52}
53
36fn fixLastLimb(out_ptr: [*]u64, is_signed: bool, bits: u16) void {54fn fixLastLimb(out_ptr: [*]u64, is_signed: bool, bits: u16) void {
37 const limb_cnt = usedLimbCount(bits);55 const limb_cnt = usedLimbCount(bits);
38 const true_limb_cnt = limbCount(bits);56 const true_limb_cnt = limbCount(bits);
...@@ -77,9 +95,9 @@ comptime {...@@ -77,9 +95,9 @@ comptime {
7795
78fn __addo_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, b_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) bool {96fn __addo_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, b_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) bool {
79 const limb_cnt = usedLimbCount(bits);97 const limb_cnt = usedLimbCount(bits);
80 const out = out_ptr[0..limb_cnt];98 const out = varLimbs(out_ptr, bits);
81 const a = a_ptr[0..limb_cnt];99 const a = constLimbs(a_ptr, bits);
82 const b = b_ptr[0..limb_cnt];100 const b = constLimbs(b_ptr, bits);
83101
84 var carry: u1 = 0;102 var carry: u1 = 0;
85 var i: usize = 0;103 var i: usize = 0;
...@@ -143,6 +161,9 @@ test __addo_limb64 {...@@ -143,6 +161,9 @@ test __addo_limb64 {
143 try test__addo_limb64(i64, maxInt(i64), 1, .{ minInt(i64), true });161 try test__addo_limb64(i64, maxInt(i64), 1, .{ minInt(i64), true });
144 try test__addo_limb64(i65, maxInt(i65), 1, .{ minInt(i65), true });162 try test__addo_limb64(i65, maxInt(i65), 1, .{ minInt(i65), true });
145 try test__addo_limb64(i255, -3, 2, .{ -1, false });163 try test__addo_limb64(i255, -3, 2, .{ -1, false });
164
165 try test__addo_limb64(u150, maxInt(u150), 2, .{ 1, true });
166 try test__addo_limb64(i150, -3, 2, .{ -1, false });
146}167}
147168
148comptime {169comptime {
...@@ -151,9 +172,9 @@ comptime {...@@ -151,9 +172,9 @@ comptime {
151172
152fn __subo_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, b_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) bool {173fn __subo_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, b_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) bool {
153 const limb_cnt = usedLimbCount(bits);174 const limb_cnt = usedLimbCount(bits);
154 const out = out_ptr[0..limb_cnt];175 const out = varLimbs(out_ptr, bits);
155 const a = a_ptr[0..limb_cnt];176 const a = constLimbs(a_ptr, bits);
156 const b = b_ptr[0..limb_cnt];177 const b = constLimbs(b_ptr, bits);
157178
158 var borrow: u1 = 0;179 var borrow: u1 = 0;
159 var i: usize = 0;180 var i: usize = 0;
...@@ -216,6 +237,9 @@ test __subo_limb64 {...@@ -216,6 +237,9 @@ test __subo_limb64 {
216 try test__subo_limb64(i64, minInt(i64), 1, .{ maxInt(i64), true });237 try test__subo_limb64(i64, minInt(i64), 1, .{ maxInt(i64), true });
217 try test__subo_limb64(i65, minInt(i65), 1, .{ maxInt(i65), true });238 try test__subo_limb64(i65, minInt(i65), 1, .{ maxInt(i65), true });
218 try test__subo_limb64(i255, -1, 2, .{ -3, false });239 try test__subo_limb64(i255, -1, 2, .{ -3, false });
240
241 try test__subo_limb64(u150, 2, maxInt(u150), .{ 3, true });
242 try test__subo_limb64(i150, -3, 2, .{ -5, false });
219}243}
220244
221comptime {245comptime {
...@@ -227,8 +251,8 @@ comptime {...@@ -227,8 +251,8 @@ comptime {
227// a > b -> 1251// a > b -> 1
228fn __cmp_limb64(a_ptr: [*]const u64, b_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) i8 {252fn __cmp_limb64(a_ptr: [*]const u64, b_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) i8 {
229 const limb_cnt = usedLimbCount(bits);253 const limb_cnt = usedLimbCount(bits);
230 const a = a_ptr[0..limb_cnt];254 const a = constLimbs(a_ptr, bits);
231 const b = b_ptr[0..limb_cnt];255 const b = constLimbs(b_ptr, bits);
232256
233 var i: usize = 0;257 var i: usize = 0;
234 if (is_signed) {258 if (is_signed) {
...@@ -284,6 +308,9 @@ test __cmp_limb64 {...@@ -284,6 +308,9 @@ test __cmp_limb64 {
284 try test__cmp_limb64(i255, -3, 2, -1);308 try test__cmp_limb64(i255, -3, 2, -1);
285 try test__cmp_limb64(i255, -5, -5, 0);309 try test__cmp_limb64(i255, -5, -5, 0);
286 try test__cmp_limb64(i255, 2, -3, 1);310 try test__cmp_limb64(i255, 2, -3, 1);
311
312 try test__cmp_limb64(u150, maxInt(u150) - 5, maxInt(u150) - 5, 0);
313 try test__cmp_limb64(i150, minInt(i150), -5, -1);
287}314}
288315
289comptime {316comptime {
...@@ -324,6 +351,9 @@ test __and_limb64 {...@@ -324,6 +351,9 @@ test __and_limb64 {
324 try test__and_limb64(i64, -1, 2, 2);351 try test__and_limb64(i64, -1, 2, 2);
325 try test__and_limb64(i65, minInt(i65), -1, minInt(i65));352 try test__and_limb64(i65, minInt(i65), -1, minInt(i65));
326 try test__and_limb64(i255, -1, 2, 2);353 try test__and_limb64(i255, -1, 2, 2);
354
355 try test__and_limb64(u150, maxInt(u150), 7, 7);
356 try test__and_limb64(i150, -2, 3, 2);
327}357}
328358
329comptime {359comptime {
...@@ -364,6 +394,9 @@ test __or_limb64 {...@@ -364,6 +394,9 @@ test __or_limb64 {
364 try test__or_limb64(i64, -1, 2, -1);394 try test__or_limb64(i64, -1, 2, -1);
365 try test__or_limb64(i65, minInt(i65), 1, minInt(i65) + 1);395 try test__or_limb64(i65, minInt(i65), 1, minInt(i65) + 1);
366 try test__or_limb64(i255, -3, 2, -1);396 try test__or_limb64(i255, -3, 2, -1);
397
398 try test__or_limb64(u150, maxInt(u150) - 1, 3, maxInt(u150));
399 try test__or_limb64(i150, -2, 3, -1);
367}400}
368401
369comptime {402comptime {
...@@ -404,6 +437,9 @@ test __xor_limb64 {...@@ -404,6 +437,9 @@ test __xor_limb64 {
404 try test__xor_limb64(i64, -1, 2, -3);437 try test__xor_limb64(i64, -1, 2, -3);
405 try test__xor_limb64(i65, minInt(i65), -1, maxInt(i65));438 try test__xor_limb64(i65, minInt(i65), -1, maxInt(i65));
406 try test__xor_limb64(i255, -3, 2, -1);439 try test__xor_limb64(i255, -3, 2, -1);
440
441 try test__xor_limb64(u150, maxInt(u150) - 1, 3, maxInt(u150) - 2);
442 try test__xor_limb64(i150, -2, 3, -3);
407}443}
408444
409comptime {445comptime {
...@@ -412,8 +448,8 @@ comptime {...@@ -412,8 +448,8 @@ comptime {
412448
413fn __not_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) void {449fn __not_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) void {
414 const limb_cnt = usedLimbCount(bits);450 const limb_cnt = usedLimbCount(bits);
415 const out = out_ptr[0..limb_cnt];451 const out = varLimbs(out_ptr, bits);
416 const a = a_ptr[0..limb_cnt];452 const a = constLimbs(a_ptr, bits);
417453
418 var i: usize = 0;454 var i: usize = 0;
419 while (i < limb_cnt - 1) : (i += 1) {455 while (i < limb_cnt - 1) : (i += 1) {
...@@ -450,6 +486,9 @@ test __not_limb64 {...@@ -450,6 +486,9 @@ test __not_limb64 {
450 try test__not_limb64(i64, -1, 0);486 try test__not_limb64(i64, -1, 0);
451 try test__not_limb64(i65, minInt(i65), maxInt(i65));487 try test__not_limb64(i65, minInt(i65), maxInt(i65));
452 try test__not_limb64(i255, -3, 2);488 try test__not_limb64(i255, -3, 2);
489
490 try test__not_limb64(u150, maxInt(u150), 0);
491 try test__not_limb64(i150, maxInt(i150), minInt(i150));
453}492}
454493
455comptime {494comptime {
...@@ -458,8 +497,8 @@ comptime {...@@ -458,8 +497,8 @@ comptime {
458497
459fn __shlo_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, shift: u16, is_signed: bool, bits: u16) callconv(.c) bool {498fn __shlo_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, shift: u16, is_signed: bool, bits: u16) callconv(.c) bool {
460 const limb_cnt = usedLimbCount(bits);499 const limb_cnt = usedLimbCount(bits);
461 const out = out_ptr[0..limb_cnt];500 const out = varLimbs(out_ptr, bits);
462 const a = a_ptr[0..limb_cnt];501 const a = constLimbs(a_ptr, bits);
463502
464 assert(shift < bits);503 assert(shift < bits);
465504
...@@ -541,6 +580,9 @@ test __shlo_limb64 {...@@ -541,6 +580,9 @@ test __shlo_limb64 {
541 try test__shlo_limb64(i633, -1 << 299, 333, .{ -1 << 632, false });580 try test__shlo_limb64(i633, -1 << 299, 333, .{ -1 << 632, false });
542 try test__shlo_limb64(i633, -1 << 300, 333, .{ 0, true });581 try test__shlo_limb64(i633, -1 << 300, 333, .{ 0, true });
543 try test__shlo_limb64(i633, -1 << 298, 333, .{ -1 << 631, false });582 try test__shlo_limb64(i633, -1 << 298, 333, .{ -1 << 631, false });
583
584 try test__shlo_limb64(u150, maxInt(u150), 1, .{ maxInt(u150) - 1, true });
585 try test__shlo_limb64(i150, -3, 1, .{ -6, false });
544}586}
545587
546comptime {588comptime {
...@@ -549,8 +591,8 @@ comptime {...@@ -549,8 +591,8 @@ comptime {
549591
550fn __shr_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, shift: u16, is_signed: bool, bits: u16) callconv(.c) void {592fn __shr_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, shift: u16, is_signed: bool, bits: u16) callconv(.c) void {
551 const limb_cnt = usedLimbCount(bits);593 const limb_cnt = usedLimbCount(bits);
552 const out = out_ptr[0..limb_cnt];594 const out = varLimbs(out_ptr, bits);
553 const a = a_ptr[0..limb_cnt];595 const a = constLimbs(a_ptr, bits);
554596
555 assert(shift < bits);597 assert(shift < bits);
556598
...@@ -572,6 +614,8 @@ fn __shr_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, shift: u16, is_signed: boo...@@ -572,6 +614,8 @@ fn __shr_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, shift: u16, is_signed: boo
572 carry = if (bit_shift != 0) (limb << @intCast(64 - bit_shift)) else 0;614 carry = if (bit_shift != 0) (limb << @intCast(64 - bit_shift)) else 0;
573 }615 }
574 }616 }
617
618 fixLastLimb(out_ptr, is_signed, bits);
575}619}
576620
577fn test__shr_limb64(comptime T: type, a: T, shift: u16, expected: T) !void {621fn test__shr_limb64(comptime T: type, a: T, shift: u16, expected: T) !void {
...@@ -609,6 +653,9 @@ test __shr_limb64 {...@@ -609,6 +653,9 @@ test __shr_limb64 {
609 try test__shr_limb64(i633, -1 << 333, 333, -1);653 try test__shr_limb64(i633, -1 << 333, 333, -1);
610 try test__shr_limb64(i633, -1 << 334, 333, -2);654 try test__shr_limb64(i633, -1 << 334, 333, -2);
611 try test__shr_limb64(i633, -1 << 332, 333, -1);655 try test__shr_limb64(i633, -1 << 332, 333, -1);
656
657 try test__shr_limb64(u150, maxInt(u150), 1, maxInt(u149));
658 try test__shr_limb64(i150, -3, 1, -2);
612}659}
613660
614comptime {661comptime {
...@@ -617,7 +664,7 @@ comptime {...@@ -617,7 +664,7 @@ comptime {
617664
618fn __clz_limb64(a_ptr: [*]const u64, bits: u16) callconv(.c) u16 {665fn __clz_limb64(a_ptr: [*]const u64, bits: u16) callconv(.c) u16 {
619 const limb_cnt = usedLimbCount(bits);666 const limb_cnt = usedLimbCount(bits);
620 const a = a_ptr[0..limb_cnt];667 const a = constLimbs(a_ptr, bits);
621668
622 var res: u16 = 0;669 var res: u16 = 0;
623 var i: usize = 0;670 var i: usize = 0;
...@@ -667,6 +714,9 @@ test __clz_limb64 {...@@ -667,6 +714,9 @@ test __clz_limb64 {
667 try test__clz_limb64(i65, 1 << 32, 32);714 try test__clz_limb64(i65, 1 << 32, 32);
668 try test__clz_limb64(i128, 0, 128);715 try test__clz_limb64(i128, 0, 128);
669 try test__clz_limb64(i255, 1 << 130, 124);716 try test__clz_limb64(i255, 1 << 130, 124);
717
718 try test__clz_limb64(u150, 1 << 31, 118);
719 try test__clz_limb64(i150, maxInt(u65) - 1, 85);
670}720}
671721
672comptime {722comptime {
...@@ -675,7 +725,7 @@ comptime {...@@ -675,7 +725,7 @@ comptime {
675725
676fn __ctz_limb64(a_ptr: [*]const u64, bits: u16) callconv(.c) u16 {726fn __ctz_limb64(a_ptr: [*]const u64, bits: u16) callconv(.c) u16 {
677 const limb_cnt = usedLimbCount(bits);727 const limb_cnt = usedLimbCount(bits);
678 const a = a_ptr[0..limb_cnt];728 const a = constLimbs(a_ptr, bits);
679729
680 var res: u16 = 0;730 var res: u16 = 0;
681 var i: usize = 0;731 var i: usize = 0;
...@@ -720,6 +770,9 @@ test __ctz_limb64 {...@@ -720,6 +770,9 @@ test __ctz_limb64 {
720 try test__ctz_limb64(i65, 0, 65);770 try test__ctz_limb64(i65, 0, 65);
721 try test__ctz_limb64(i128, -1 << 73, 73);771 try test__ctz_limb64(i128, -1 << 73, 73);
722 try test__ctz_limb64(i255, 1 << 130, 130);772 try test__ctz_limb64(i255, 1 << 130, 130);
773
774 try test__ctz_limb64(u150, 1 << 101, 101);
775 try test__ctz_limb64(i150, -1 << 74, 74);
723}776}
724777
725comptime {778comptime {
...@@ -728,7 +781,7 @@ comptime {...@@ -728,7 +781,7 @@ comptime {
728781
729fn __popcount_limb64(a_ptr: [*]const u64, bits: u16) callconv(.c) u16 {782fn __popcount_limb64(a_ptr: [*]const u64, bits: u16) callconv(.c) u16 {
730 const limb_cnt = usedLimbCount(bits);783 const limb_cnt = usedLimbCount(bits);
731 const a = a_ptr[0..limb_cnt];784 const a = constLimbs(a_ptr, bits);
732785
733 var res: u16 = 0;786 var res: u16 = 0;
734 var i: usize = 0;787 var i: usize = 0;
...@@ -766,6 +819,9 @@ test __popcount_limb64 {...@@ -766,6 +819,9 @@ test __popcount_limb64 {
766 try test__popcount_limb64(i65, -1, 65);819 try test__popcount_limb64(i65, -1, 65);
767 try test__popcount_limb64(i128, -1 << 7, 121);820 try test__popcount_limb64(i128, -1 << 7, 121);
768 try test__popcount_limb64(i255, -1 << 200, 55);821 try test__popcount_limb64(i255, -1 << 200, 55);
822
823 try test__popcount_limb64(u150, (1 << 149) | (1 << 65) | 1, 3);
824 try test__popcount_limb64(i150, -1 << 7, 143);
769}825}
770826
771comptime {827comptime {
...@@ -774,8 +830,8 @@ comptime {...@@ -774,8 +830,8 @@ comptime {
774830
775fn __bitreverse_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) void {831fn __bitreverse_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) void {
776 const limb_cnt = usedLimbCount(bits);832 const limb_cnt = usedLimbCount(bits);
777 const out = out_ptr[0..limb_cnt];833 const out = varLimbs(out_ptr, bits);
778 const a = a_ptr[0..limb_cnt];834 const a = constLimbs(a_ptr, bits);
779835
780 var i: usize = 0;836 var i: usize = 0;
781 while (i < limb_cnt) : (i += 1) {837 while (i < limb_cnt) : (i += 1) {
...@@ -813,6 +869,9 @@ test __bitreverse_limb64 {...@@ -813,6 +869,9 @@ test __bitreverse_limb64 {
813 try test__bitreverse_limb64(i65, minInt(i65), 1);869 try test__bitreverse_limb64(i65, minInt(i65), 1);
814 try test__bitreverse_limb64(i128, 1 << 63, 1 << 64);870 try test__bitreverse_limb64(i128, 1 << 63, 1 << 64);
815 try test__bitreverse_limb64(i255, 1 << 130, 1 << 124);871 try test__bitreverse_limb64(i255, 1 << 130, 1 << 124);
872
873 try test__bitreverse_limb64(u150, 1 << 9, 1 << 140);
874 try test__bitreverse_limb64(i150, minInt(i150), 1);
816}875}
817876
818comptime {877comptime {
...@@ -821,8 +880,8 @@ comptime {...@@ -821,8 +880,8 @@ comptime {
821880
822fn __byteswap_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) void {881fn __byteswap_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) void {
823 const limb_cnt = usedLimbCount(bits);882 const limb_cnt = usedLimbCount(bits);
824 const out = out_ptr[0..limb_cnt];883 const out = varLimbs(out_ptr, bits);
825 const a = a_ptr[0..limb_cnt];884 const a = constLimbs(a_ptr, bits);
826885
827 assert(bits % 8 == 0);886 assert(bits % 8 == 0);
828887
...@@ -862,6 +921,9 @@ test __byteswap_limb64 {...@@ -862,6 +921,9 @@ test __byteswap_limb64 {
862 try test__byteswap_limb64(i72, -1, -1);921 try test__byteswap_limb64(i72, -1, -1);
863 try test__byteswap_limb64(i128, 1 << 56, 1 << 64);922 try test__byteswap_limb64(i128, 1 << 56, 1 << 64);
864 try test__byteswap_limb64(i248, minInt(i248), 128);923 try test__byteswap_limb64(i248, minInt(i248), 128);
924
925 try test__byteswap_limb64(u152, 1, 1 << 144);
926 try test__byteswap_limb64(i152, 1 << 56, 1 << 88);
865}927}
866928
867comptime {929comptime {
...@@ -881,15 +943,19 @@ inline fn add3(x: *[3]u64, start: usize, v0: u64) void {...@@ -881,15 +943,19 @@ inline fn add3(x: *[3]u64, start: usize, v0: u64) void {
881943
882fn mulwide(a: u64, b: u64) [2]u64 {944fn mulwide(a: u64, b: u64) [2]u64 {
883 const muldXi = @import("mulXi3.zig").muldXi;945 const muldXi = @import("mulXi3.zig").muldXi;
884 return @bitCast(muldXi(u64, a, b));946 const limbs: [2]u64 = @bitCast(muldXi(u64, a, b));
947 return switch (endian) {
948 .little => limbs,
949 .big => .{ limbs[1], limbs[0] },
950 };
885}951}
886952
887fn __mulo_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, b_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) bool {953fn __mulo_limb64(out_ptr: [*]u64, a_ptr: [*]const u64, b_ptr: [*]const u64, is_signed: bool, bits: u16) callconv(.c) bool {
888 const limb_cnt = usedLimbCount(bits);954 const limb_cnt = usedLimbCount(bits);
889955
890 const out = out_ptr[0..limb_cnt];956 const out = varLimbs(out_ptr, bits);
891 const a = a_ptr[0..limb_cnt];957 const a = constLimbs(a_ptr, bits);
892 const b = b_ptr[0..limb_cnt];958 const b = constLimbs(b_ptr, bits);
893959
894 @memset(out, 0);960 @memset(out, 0);
895961
...@@ -1002,6 +1068,9 @@ test __mulo_limb64 {...@@ -1002,6 +1068,9 @@ test __mulo_limb64 {
1002 try test__mulo_limb64(i200, 1 << 100, 1 << 99, .{ minInt(i200), true });1068 try test__mulo_limb64(i200, 1 << 100, 1 << 99, .{ minInt(i200), true });
1003 try test__mulo_limb64(i200, maxInt(i200), maxInt(i200), .{ 1, true });1069 try test__mulo_limb64(i200, maxInt(i200), maxInt(i200), .{ 1, true });
1004 try test__mulo_limb64(i200, minInt(i200), minInt(i200), .{ 0, true });1070 try test__mulo_limb64(i200, minInt(i200), minInt(i200), .{ 0, true });
1071
1072 try test__mulo_limb64(u150, maxInt(u150), 2, .{ maxInt(u150) - 1, true });
1073 try test__mulo_limb64(i150, maxInt(i150), 2, .{ -2, true });
1005}1074}
10061075
1007comptime {1076comptime {
...@@ -1052,4 +1121,6 @@ test __abs_limb64 {...@@ -1052,4 +1121,6 @@ test __abs_limb64 {
1052 try test__abs_limb64(i200, -1 << 198, 1 << 198);1121 try test__abs_limb64(i200, -1 << 198, 1 << 198);
1053 try test__abs_limb64(i255, -5, 5);1122 try test__abs_limb64(i255, -5, 5);
1054 try test__abs_limb64(i255, minInt(i255), 1 << 254);1123 try test__abs_limb64(i255, minInt(i255), 1 << 254);
1124
1125 try test__abs_limb64(i150, -40, 40);
1055}1126}
src/codegen/wasm/CodeGen.zig+3-13
...@@ -1320,6 +1320,7 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -1320,6 +1320,7 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
1320 .mod,1320 .mod,
1321 .max,1321 .max,
1322 .min,1322 .min,
1323 .div_exact,
1323 .div_trunc,1324 .div_trunc,
1324 .div_floor,1325 .div_floor,
1325 => |tag| {1326 => |tag| {
...@@ -1345,6 +1346,7 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -1345,6 +1346,7 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
1345 .mod => try cg.floatMod(float_ty, lhs, rhs),1346 .mod => try cg.floatMod(float_ty, lhs, rhs),
1346 .max => try cg.floatMax(float_ty, lhs, rhs),1347 .max => try cg.floatMax(float_ty, lhs, rhs),
1347 .min => try cg.floatMin(float_ty, lhs, rhs),1348 .min => try cg.floatMin(float_ty, lhs, rhs),
1349 .div_exact => try cg.floatDiv(float_ty, lhs, rhs),
1348 .div_trunc => try cg.floatDivTrunc(float_ty, lhs, rhs),1350 .div_trunc => try cg.floatDivTrunc(float_ty, lhs, rhs),
1349 .div_floor => try cg.floatDivFloor(float_ty, lhs, rhs),1351 .div_floor => try cg.floatDivFloor(float_ty, lhs, rhs),
1350 else => unreachable,1352 else => unreachable,
...@@ -1362,6 +1364,7 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -1362,6 +1364,7 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
1362 .mod => try cg.intMod(int_ty, lhs, rhs),1364 .mod => try cg.intMod(int_ty, lhs, rhs),
1363 .max => try cg.intMax(int_ty, lhs, rhs),1365 .max => try cg.intMax(int_ty, lhs, rhs),
1364 .min => try cg.intMin(int_ty, lhs, rhs),1366 .min => try cg.intMin(int_ty, lhs, rhs),
1367 .div_exact => try cg.intDiv(int_ty, lhs, rhs),
1365 .div_trunc => try cg.intDiv(int_ty, lhs, rhs),1368 .div_trunc => try cg.intDiv(int_ty, lhs, rhs),
1366 .div_floor => try cg.intDivFloor(int_ty, lhs, rhs),1369 .div_floor => try cg.intDivFloor(int_ty, lhs, rhs),
1367 else => unreachable,1370 else => unreachable,
...@@ -1385,19 +1388,6 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -1385,19 +1388,6 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
1385 const result = try cg.floatDiv(.fromType(cg, ty), lhs, rhs);1388 const result = try cg.floatDiv(.fromType(cg, ty), lhs, rhs);
1386 try cg.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });1389 try cg.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
1387 },1390 },
1388 .div_exact => {
1389 const bin_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
1390 const lhs = try cg.resolveInst(bin_op.lhs);
1391 const rhs = try cg.resolveInst(bin_op.rhs);
1392 const ty = cg.typeOfIndex(inst);
1393
1394 if (ty.zigTypeTag(zcu) == .vector) {
1395 return cg.fail("TODO: implement AIR op: div_exact for vectors", .{});
1396 }
1397
1398 const result = try cg.intDiv(.fromType(cg, ty), lhs, rhs);
1399 try cg.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
1400 },
1401 .abs => {1391 .abs => {
1402 const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;1392 const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
1403 const operand = try cg.resolveInst(ty_op.operand);1393 const operand = try cg.resolveInst(ty_op.operand);
test/behavior/saturating_arithmetic.zig+1
...@@ -326,6 +326,7 @@ test "saturating shift-left large rhs" {...@@ -326,6 +326,7 @@ test "saturating shift-left large rhs" {
326 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;326 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
327 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;327 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
328 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;328 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
329 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
329330
330 {331 {
331 var lhs: u8 = undefined;332 var lhs: u8 = undefined;