authorgravatar for koachan@protonmail.comKoakuma <koachan@protonmail.com> 2022-07-09 16:04:26+07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-09-14 16:57:31-07:00
logde17fe66a541b3277579d351f7a362d3f07ea91d
tree00b4c14fb1cc6ec0d856fc3d387393928b567f7a
parentab3d3b260bc24d1a3e16329371d9a2438e043506

stage2: sparc64: Tidy up binOp and enable more operations

sub, mul, addwrap, subwrap, mulwrap, shr, shr_exact

1 files changed, 108 insertions(+), 125 deletions(-)

src/arch/sparc64/CodeGen.zig+108-125
...@@ -499,20 +499,29 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -499,20 +499,29 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
499 .ptr_sub => try self.airPtrArithmetic(inst, .ptr_sub),499 .ptr_sub => try self.airPtrArithmetic(inst, .ptr_sub),
500500
501 .add => try self.airBinOp(inst, .add),501 .add => try self.airBinOp(inst, .add),
502 .addwrap => @panic("TODO try self.airAddWrap(inst)"),502 .addwrap => try self.airBinOp(inst, .addwrap),
503 .sub => try self.airBinOp(inst, .sub),
504 .subwrap => try self.airBinOp(inst, .subwrap),
505 .mul => try self.airBinOp(inst, .mul),
506 .mulwrap => try self.airBinOp(inst, .mulwrap),
507 .shl => try self.airBinOp(inst, .shl),
508 .shl_exact => try self.airBinOp(inst, .shl_exact),
509 .shr => try self.airBinOp(inst, .shr),
510 .shr_exact => try self.airBinOp(inst, .shr_exact),
511 .bool_and => try self.airBinOp(inst, .bool_and),
512 .bool_or => try self.airBinOp(inst, .bool_or),
513 .bit_and => try self.airBinOp(inst, .bit_and),
514 .bit_or => try self.airBinOp(inst, .bit_or),
515 .xor => try self.airBinOp(inst, .xor),
516
503 .add_sat => @panic("TODO try self.airAddSat(inst)"),517 .add_sat => @panic("TODO try self.airAddSat(inst)"),
504 .sub => @panic("TODO try self.airBinOp(inst)"),
505 .subwrap => @panic("TODO try self.airSubWrap(inst)"),
506 .sub_sat => @panic("TODO try self.airSubSat(inst)"),518 .sub_sat => @panic("TODO try self.airSubSat(inst)"),
507 .mul => @panic("TODO try self.airMul(inst)"),
508 .mulwrap => @panic("TODO try self.airMulWrap(inst)"),
509 .mul_sat => @panic("TODO try self.airMulSat(inst)"),519 .mul_sat => @panic("TODO try self.airMulSat(inst)"),
510 .rem => try self.airRem(inst),
511 .mod => try self.airMod(inst),
512 .shl, .shl_exact => @panic("TODO try self.airShl(inst)"),
513 .shl_sat => @panic("TODO try self.airShlSat(inst)"),520 .shl_sat => @panic("TODO try self.airShlSat(inst)"),
514 .min => @panic("TODO try self.airMin(inst)"),521 .min => @panic("TODO try self.airMin(inst)"),
515 .max => @panic("TODO try self.airMax(inst)"),522 .max => @panic("TODO try self.airMax(inst)"),
523 .rem => try self.airRem(inst),
524 .mod => try self.airMod(inst),
516 .slice => try self.airSlice(inst),525 .slice => try self.airSlice(inst),
517526
518 .sqrt,527 .sqrt,
...@@ -548,13 +557,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -548,13 +557,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
548 .cmp_vector => @panic("TODO try self.airCmpVector(inst)"),557 .cmp_vector => @panic("TODO try self.airCmpVector(inst)"),
549 .cmp_lt_errors_len => try self.airCmpLtErrorsLen(inst),558 .cmp_lt_errors_len => try self.airCmpLtErrorsLen(inst),
550559
551 .bool_and => try self.airBinOp(inst, .bool_and),
552 .bool_or => try self.airBinOp(inst, .bool_or),
553 .bit_and => try self.airBinOp(inst, .bit_and),
554 .bit_or => try self.airBinOp(inst, .bit_or),
555 .xor => try self.airBinOp(inst, .xor),
556 .shr, .shr_exact => @panic("TODO try self.airShr(inst)"),
557
558 .alloc => try self.airAlloc(inst),560 .alloc => try self.airAlloc(inst),
559 .ret_ptr => try self.airRetPtr(inst),561 .ret_ptr => try self.airRetPtr(inst),
560 .arg => try self.airArg(inst),562 .arg => try self.airArg(inst),
...@@ -2397,6 +2399,10 @@ fn binOp(...@@ -2397,6 +2399,10 @@ fn binOp(
2397 switch (tag) {2399 switch (tag) {
2398 .add,2400 .add,
2399 .sub,2401 .sub,
2402 .mul,
2403 .bit_and,
2404 .bit_or,
2405 .xor,
2400 .cmp_eq,2406 .cmp_eq,
2401 => {2407 => {
2402 switch (lhs_ty.zigTypeTag()) {2408 switch (lhs_ty.zigTypeTag()) {
...@@ -2411,12 +2417,20 @@ fn binOp(...@@ -2411,12 +2417,20 @@ fn binOp(
2411 // operands2417 // operands
2412 const lhs_immediate_ok = switch (tag) {2418 const lhs_immediate_ok = switch (tag) {
2413 .add => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12),2419 .add => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12),
2420 .mul => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12),
2421 .bit_and => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12),
2422 .bit_or => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12),
2423 .xor => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12),
2414 .sub, .cmp_eq => false,2424 .sub, .cmp_eq => false,
2415 else => unreachable,2425 else => unreachable,
2416 };2426 };
2417 const rhs_immediate_ok = switch (tag) {2427 const rhs_immediate_ok = switch (tag) {
2418 .add,2428 .add,
2419 .sub,2429 .sub,
2430 .mul,
2431 .bit_and,
2432 .bit_or,
2433 .xor,
2420 .cmp_eq,2434 .cmp_eq,
2421 => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12),2435 => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12),
2422 else => unreachable,2436 else => unreachable,
...@@ -2425,6 +2439,10 @@ fn binOp(...@@ -2425,6 +2439,10 @@ fn binOp(
2425 const mir_tag: Mir.Inst.Tag = switch (tag) {2439 const mir_tag: Mir.Inst.Tag = switch (tag) {
2426 .add => .add,2440 .add => .add,
2427 .sub => .sub,2441 .sub => .sub,
2442 .mul => .mulx,
2443 .bit_and => .@"and",
2444 .bit_or => .@"or",
2445 .xor => .xor,
2428 .cmp_eq => .cmp,2446 .cmp_eq => .cmp,
2429 else => unreachable,2447 else => unreachable,
2430 };2448 };
...@@ -2446,72 +2464,60 @@ fn binOp(...@@ -2446,72 +2464,60 @@ fn binOp(
2446 }2464 }
2447 },2465 },
24482466
2449 .div_trunc => {2467 .addwrap,
2468 .subwrap,
2469 .mulwrap,
2470 => {
2471 const base_tag: Air.Inst.Tag = switch (tag) {
2472 .addwrap => .add,
2473 .subwrap => .sub,
2474 .mulwrap => .mul,
2475 else => unreachable,
2476 };
2477
2478 // Generate the base operation
2479 const result = try self.binOp(base_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
2480
2481 // Truncate if necessary
2450 switch (lhs_ty.zigTypeTag()) {2482 switch (lhs_ty.zigTypeTag()) {
2451 .Vector => return self.fail("TODO binary operations on vectors", .{}),2483 .Vector => return self.fail("TODO binary operations on vectors", .{}),
2452 .Int => {2484 .Int => {
2453 assert(lhs_ty.eql(rhs_ty, mod));
2454 const int_info = lhs_ty.intInfo(self.target.*);2485 const int_info = lhs_ty.intInfo(self.target.*);
2455 if (int_info.bits <= 64) {2486 if (int_info.bits <= 64) {
2456 const rhs_immediate_ok = switch (tag) {2487 const result_reg = result.register;
2457 .div_trunc => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12),2488 try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits);
2458 else => unreachable,2489 return result;
2459 };
2460
2461 const mir_tag: Mir.Inst.Tag = switch (tag) {
2462 .div_trunc => switch (int_info.signedness) {
2463 .signed => Mir.Inst.Tag.sdivx,
2464 .unsigned => Mir.Inst.Tag.udivx,
2465 },
2466 else => unreachable,
2467 };
2468
2469 if (rhs_immediate_ok) {
2470 return try self.binOpImmediate(mir_tag, lhs, rhs, lhs_ty, true, metadata);
2471 } else {
2472 return try self.binOpRegister(mir_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
2473 }
2474 } else {2490 } else {
2475 return self.fail("TODO binary operations on int with bits > 64", .{});2491 return self.fail("TODO binary operations on integers > u64/i64", .{});
2476 }2492 }
2477 },2493 },
2478 else => unreachable,2494 else => unreachable,
2479 }2495 }
2480 },2496 },
24812497
2482 .mul => {2498 .div_trunc => {
2483 switch (lhs_ty.zigTypeTag()) {2499 switch (lhs_ty.zigTypeTag()) {
2484 .Vector => return self.fail("TODO binary operations on vectors", .{}),2500 .Vector => return self.fail("TODO binary operations on vectors", .{}),
2485 .Int => {2501 .Int => {
2486 assert(lhs_ty.eql(rhs_ty, mod));2502 assert(lhs_ty.eql(rhs_ty, mod));
2487 const int_info = lhs_ty.intInfo(self.target.*);2503 const int_info = lhs_ty.intInfo(self.target.*);
2488 if (int_info.bits <= 64) {2504 if (int_info.bits <= 64) {
2489 // Only say yes if the operation is
2490 // commutative, i.e. we can swap both of the
2491 // operands
2492 const lhs_immediate_ok = switch (tag) {
2493 .mul => lhs == .immediate and lhs.immediate <= std.math.maxInt(u12),
2494 else => unreachable,
2495 };
2496 const rhs_immediate_ok = switch (tag) {2505 const rhs_immediate_ok = switch (tag) {
2497 .mul => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12),2506 .div_trunc => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12),
2498 else => unreachable,2507 else => unreachable,
2499 };2508 };
25002509
2501 const mir_tag: Mir.Inst.Tag = switch (tag) {2510 const mir_tag: Mir.Inst.Tag = switch (tag) {
2502 .mul => .mulx,2511 .div_trunc => switch (int_info.signedness) {
2512 .signed => Mir.Inst.Tag.sdivx,
2513 .unsigned => Mir.Inst.Tag.udivx,
2514 },
2503 else => unreachable,2515 else => unreachable,
2504 };2516 };
25052517
2506 if (rhs_immediate_ok) {2518 if (rhs_immediate_ok) {
2507 // At this point, rhs is an immediate2519 return try self.binOpImmediate(mir_tag, lhs, rhs, lhs_ty, true, metadata);
2508 return try self.binOpImmediate(mir_tag, lhs, rhs, lhs_ty, false, metadata);
2509 } else if (lhs_immediate_ok) {
2510 // swap lhs and rhs
2511 // At this point, lhs is an immediate
2512 return try self.binOpImmediate(mir_tag, rhs, lhs, rhs_ty, true, metadata);
2513 } else {2520 } else {
2514 // TODO convert large immediates to register before adding
2515 return try self.binOpRegister(mir_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);2521 return try self.binOpRegister(mir_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
2516 }2522 }
2517 } else {2523 } else {
...@@ -2552,58 +2558,6 @@ fn binOp(...@@ -2552,58 +2558,6 @@ fn binOp(
2552 }2558 }
2553 },2559 },
25542560
2555 .bit_and,
2556 .bit_or,
2557 .xor,
2558 => {
2559 switch (lhs_ty.zigTypeTag()) {
2560 .Vector => return self.fail("TODO binary operations on vectors", .{}),
2561 .Int => {
2562 assert(lhs_ty.eql(rhs_ty, mod));
2563 const int_info = lhs_ty.intInfo(self.target.*);
2564 if (int_info.bits <= 64) {
2565 // Only say yes if the operation is
2566 // commutative, i.e. we can swap both of the
2567 // operands
2568 const lhs_immediate_ok = switch (tag) {
2569 .bit_and,
2570 .bit_or,
2571 .xor,
2572 => lhs == .immediate and lhs.immediate <= std.math.maxInt(u13),
2573 else => unreachable,
2574 };
2575 const rhs_immediate_ok = switch (tag) {
2576 .bit_and,
2577 .bit_or,
2578 .xor,
2579 => rhs == .immediate and rhs.immediate <= std.math.maxInt(u13),
2580 else => unreachable,
2581 };
2582
2583 const mir_tag: Mir.Inst.Tag = switch (tag) {
2584 .bit_and => .@"and",
2585 .bit_or => .@"or",
2586 .xor => .xor,
2587 else => unreachable,
2588 };
2589
2590 if (rhs_immediate_ok) {
2591 return try self.binOpImmediate(mir_tag, lhs, rhs, lhs_ty, false, metadata);
2592 } else if (lhs_immediate_ok) {
2593 // swap lhs and rhs
2594 return try self.binOpImmediate(mir_tag, rhs, lhs, rhs_ty, true, metadata);
2595 } else {
2596 // TODO convert large immediates to register before adding
2597 return try self.binOpRegister(mir_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
2598 }
2599 } else {
2600 return self.fail("TODO binary operations on int with bits > 64", .{});
2601 }
2602 },
2603 else => unreachable,
2604 }
2605 },
2606
2607 .bool_and,2561 .bool_and,
2608 .bool_or,2562 .bool_or,
2609 => {2563 => {
...@@ -2624,36 +2578,41 @@ fn binOp(...@@ -2624,36 +2578,41 @@ fn binOp(
2624 }2578 }
2625 },2579 },
26262580
2627 .shl => {2581 .shl,
2582 .shr,
2583 => {
2628 const base_tag: Air.Inst.Tag = switch (tag) {2584 const base_tag: Air.Inst.Tag = switch (tag) {
2629 .shl => .shl_exact,2585 .shl => .shl_exact,
2586 .shr => .shr_exact,
2630 else => unreachable,2587 else => unreachable,
2631 };2588 };
26322589
2633 // Generate a shl_exact/shr_exact2590 // Generate the base operation
2634 const result = try self.binOp(base_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);2591 const result = try self.binOp(base_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
26352592
2636 // Truncate if necessary2593 // Truncate if necessary
2637 switch (tag) {2594 switch (lhs_ty.zigTypeTag()) {
2638 .shl => switch (lhs_ty.zigTypeTag()) {2595 .Vector => return self.fail("TODO binary operations on vectors", .{}),
2639 .Vector => return self.fail("TODO binary operations on vectors", .{}),2596 .Int => {
2640 .Int => {2597 const int_info = lhs_ty.intInfo(self.target.*);
2641 const int_info = lhs_ty.intInfo(self.target.*);2598 if (int_info.bits <= 64) {
2642 if (int_info.bits <= 64) {2599 // 32 and 64 bit operands doesn't need truncating
2643 const result_reg = result.register;2600 if (int_info.bits == 32 or int_info.bits == 64) return result;
2644 try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits);2601
2645 return result;2602 const result_reg = result.register;
2646 } else {2603 try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits);
2647 return self.fail("TODO binary operations on integers > u64/i64", .{});2604 return result;
2648 }2605 } else {
2649 },2606 return self.fail("TODO binary operations on integers > u64/i64", .{});
2650 else => unreachable,2607 }
2651 },2608 },
2652 else => unreachable,2609 else => unreachable,
2653 }2610 }
2654 },2611 },
26552612
2656 .shl_exact => {2613 .shl_exact,
2614 .shr_exact,
2615 => {
2657 switch (lhs_ty.zigTypeTag()) {2616 switch (lhs_ty.zigTypeTag()) {
2658 .Vector => return self.fail("TODO binary operations on vectors", .{}),2617 .Vector => return self.fail("TODO binary operations on vectors", .{}),
2659 .Int => {2618 .Int => {
...@@ -2662,7 +2621,11 @@ fn binOp(...@@ -2662,7 +2621,11 @@ fn binOp(
2662 const rhs_immediate_ok = rhs == .immediate;2621 const rhs_immediate_ok = rhs == .immediate;
26632622
2664 const mir_tag: Mir.Inst.Tag = switch (tag) {2623 const mir_tag: Mir.Inst.Tag = switch (tag) {
2665 .shl_exact => .sllx,2624 .shl_exact => if (int_info.bits <= 32) Mir.Inst.Tag.sll else Mir.Inst.Tag.sllx,
2625 .shr_exact => switch (int_info.signedness) {
2626 .signed => if (int_info.bits <= 32) Mir.Inst.Tag.sra else Mir.Inst.Tag.srax,
2627 .unsigned => if (int_info.bits <= 32) Mir.Inst.Tag.srl else Mir.Inst.Tag.srlx,
2628 },
2666 else => unreachable,2629 else => unreachable,
2667 };2630 };
26682631
...@@ -2769,7 +2732,21 @@ fn binOpImmediate(...@@ -2769,7 +2732,21 @@ fn binOpImmediate(
2769 .rs2_or_imm = .{ .imm = @intCast(u12, rhs.immediate) },2732 .rs2_or_imm = .{ .imm = @intCast(u12, rhs.immediate) },
2770 },2733 },
2771 },2734 },
2772 .sllx => .{2735 .sll,
2736 .srl,
2737 .sra,
2738 => .{
2739 .shift = .{
2740 .is_imm = true,
2741 .rd = dest_reg,
2742 .rs1 = lhs_reg,
2743 .rs2_or_imm = .{ .imm = @intCast(u5, rhs.immediate) },
2744 },
2745 },
2746 .sllx,
2747 .srlx,
2748 .srax,
2749 => .{
2773 .shift = .{2750 .shift = .{
2774 .is_imm = true,2751 .is_imm = true,
2775 .rd = dest_reg,2752 .rd = dest_reg,
...@@ -2893,7 +2870,13 @@ fn binOpRegister(...@@ -2893,7 +2870,13 @@ fn binOpRegister(
2893 .rs2_or_imm = .{ .rs2 = rhs_reg },2870 .rs2_or_imm = .{ .rs2 = rhs_reg },
2894 },2871 },
2895 },2872 },
2896 .sllx => .{2873 .sll,
2874 .srl,
2875 .sra,
2876 .sllx,
2877 .srlx,
2878 .srax,
2879 => .{
2897 .shift = .{2880 .shift = .{
2898 .is_imm = false,2881 .is_imm = false,
2899 .rd = dest_reg,2882 .rd = dest_reg,