| ... | ... | @@ -1123,6 +1123,7 @@ const required_features = [_]Target.riscv.Feature{ |
| 1123 | 1123 | .a, |
| 1124 | 1124 | .zicsr, |
| 1125 | 1125 | .v, |
| 1126 | .zbb, |
| 1126 | 1127 | }; |
| 1127 | 1128 | |
| 1128 | 1129 | fn gen(func: *Func) !void { |
| ... | ... | @@ -2385,20 +2386,24 @@ fn genBinOp( |
| 2385 | 2386 | .mul, |
| 2386 | 2387 | .mul_wrap, |
| 2387 | 2388 | .rem, |
| 2389 | .div_trunc, |
| 2388 | 2390 | => { |
| 2389 | | if (!math.isPowerOfTwo(bit_size)) |
| 2390 | | return func.fail( |
| 2391 | | "TODO: genBinOp {s} non-pow 2, found {}", |
| 2392 | | .{ @tagName(tag), bit_size }, |
| 2393 | | ); |
| 2394 | | |
| 2395 | 2391 | switch (tag) { |
| 2396 | 2392 | .rem, |
| 2393 | .div_trunc, |
| 2397 | 2394 | => { |
| 2398 | | try func.truncateRegister(lhs_ty, lhs_reg); |
| 2399 | | try func.truncateRegister(rhs_ty, rhs_reg); |
| 2395 | if (!math.isPowerOfTwo(bit_size)) { |
| 2396 | try func.truncateRegister(lhs_ty, lhs_reg); |
| 2397 | try func.truncateRegister(rhs_ty, rhs_reg); |
| 2398 | } |
| 2399 | }, |
| 2400 | else => { |
| 2401 | if (!math.isPowerOfTwo(bit_size)) |
| 2402 | return func.fail( |
| 2403 | "TODO: genBinOp verify {s} non-pow 2, found {}", |
| 2404 | .{ @tagName(tag), bit_size }, |
| 2405 | ); |
| 2400 | 2406 | }, |
| 2401 | | else => {}, |
| 2402 | 2407 | } |
| 2403 | 2408 | |
| 2404 | 2409 | switch (lhs_ty.zigTypeTag(zcu)) { |
| ... | ... | @@ -2420,8 +2425,12 @@ fn genBinOp( |
| 2420 | 2425 | else => unreachable, |
| 2421 | 2426 | }, |
| 2422 | 2427 | .rem => switch (bit_size) { |
| 2423 | | 64 => if (is_unsigned) .remu else .rem, |
| 2424 | | else => if (is_unsigned) .remuw else .remu, |
| 2428 | 8, 16, 32 => if (is_unsigned) .remuw else .remw, |
| 2429 | else => if (is_unsigned) .remu else .rem, |
| 2430 | }, |
| 2431 | .div_trunc => switch (bit_size) { |
| 2432 | 8, 16, 32 => if (is_unsigned) .divuw else .divw, |
| 2433 | else => if (is_unsigned) .divu else .div, |
| 2425 | 2434 | }, |
| 2426 | 2435 | else => unreachable, |
| 2427 | 2436 | }; |
| ... | ... | @@ -2455,7 +2464,7 @@ fn genBinOp( |
| 2455 | 2464 | 64 => .fmuld, |
| 2456 | 2465 | else => unreachable, |
| 2457 | 2466 | }, |
| 2458 | | else => unreachable, |
| 2467 | else => return func.fail("TODO: genBinOp {s} Float", .{@tagName(tag)}), |
| 2459 | 2468 | }; |
| 2460 | 2469 | |
| 2461 | 2470 | _ = try func.addInst(.{ |
| ... | ... | @@ -2588,46 +2597,6 @@ fn genBinOp( |
| 2588 | 2597 | } |
| 2589 | 2598 | }, |
| 2590 | 2599 | |
| 2591 | | .div_trunc, |
| 2592 | | => { |
| 2593 | | if (!math.isPowerOfTwo(bit_size)) |
| 2594 | | return func.fail( |
| 2595 | | "TODO: genBinOp {s} non-pow 2, found {}", |
| 2596 | | .{ @tagName(tag), bit_size }, |
| 2597 | | ); |
| 2598 | | |
| 2599 | | const mir_tag: Mir.Inst.Tag = switch (tag) { |
| 2600 | | .div_trunc => switch (bit_size) { |
| 2601 | | 8, 16, 32 => if (is_unsigned) .divuw else .divw, |
| 2602 | | 64 => if (is_unsigned) .divu else .div, |
| 2603 | | else => unreachable, |
| 2604 | | }, |
| 2605 | | else => unreachable, |
| 2606 | | }; |
| 2607 | | |
| 2608 | | _ = try func.addInst(.{ |
| 2609 | | .tag = mir_tag, |
| 2610 | | .ops = .rrr, |
| 2611 | | .data = .{ |
| 2612 | | .r_type = .{ |
| 2613 | | .rd = dst_reg, |
| 2614 | | .rs1 = lhs_reg, |
| 2615 | | .rs2 = rhs_reg, |
| 2616 | | }, |
| 2617 | | }, |
| 2618 | | }); |
| 2619 | | |
| 2620 | | if (!is_unsigned) { |
| 2621 | | // truncate when the instruction is larger than the bit size. |
| 2622 | | switch (bit_size) { |
| 2623 | | 8, 16 => try func.truncateRegister(lhs_ty, dst_reg), |
| 2624 | | 32 => {}, // divw affects the first 32-bits |
| 2625 | | 64 => {}, // div affects the entire register |
| 2626 | | else => unreachable, |
| 2627 | | } |
| 2628 | | } |
| 2629 | | }, |
| 2630 | | |
| 2631 | 2600 | .shr, |
| 2632 | 2601 | .shr_exact, |
| 2633 | 2602 | .shl, |
| ... | ... | @@ -3740,7 +3709,59 @@ fn airGetUnionTag(func: *Func, inst: Air.Inst.Index) !void { |
| 3740 | 3709 | |
| 3741 | 3710 | fn airClz(func: *Func, inst: Air.Inst.Index) !void { |
| 3742 | 3711 | const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 3743 | | const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airClz for {}", .{func.target.cpu.arch}); |
| 3712 | const operand = try func.resolveInst(ty_op.operand); |
| 3713 | const ty = func.typeOf(ty_op.operand); |
| 3714 | |
| 3715 | const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: { |
| 3716 | const src_reg, const src_lock = try func.promoteReg(ty, operand); |
| 3717 | defer if (src_lock) |lock| func.register_manager.unlockReg(lock); |
| 3718 | |
| 3719 | const dst_reg: Register = if (func.reuseOperand( |
| 3720 | inst, |
| 3721 | ty_op.operand, |
| 3722 | 0, |
| 3723 | operand, |
| 3724 | ) and operand == .register) |
| 3725 | operand.register |
| 3726 | else |
| 3727 | (try func.allocRegOrMem(func.typeOfIndex(inst), inst, true)).register; |
| 3728 | |
| 3729 | const bit_size = ty.bitSize(func.pt); |
| 3730 | if (!math.isPowerOfTwo(bit_size)) try func.truncateRegister(ty, src_reg); |
| 3731 | |
| 3732 | if (bit_size > 64) { |
| 3733 | return func.fail("TODO: airClz > 64 bits, found {d}", .{bit_size}); |
| 3734 | } |
| 3735 | |
| 3736 | _ = try func.addInst(.{ |
| 3737 | .tag = switch (bit_size) { |
| 3738 | 32 => .clzw, |
| 3739 | else => .clz, |
| 3740 | }, |
| 3741 | .ops = .rrr, |
| 3742 | .data = .{ |
| 3743 | .r_type = .{ |
| 3744 | .rs2 = .zero, // rs2 is 0 filled in the spec |
| 3745 | .rs1 = src_reg, |
| 3746 | .rd = dst_reg, |
| 3747 | }, |
| 3748 | }, |
| 3749 | }); |
| 3750 | |
| 3751 | if (!(bit_size == 32 or bit_size == 64)) { |
| 3752 | _ = try func.addInst(.{ |
| 3753 | .tag = .addi, |
| 3754 | .ops = .rri, |
| 3755 | .data = .{ .i_type = .{ |
| 3756 | .rd = dst_reg, |
| 3757 | .rs1 = dst_reg, |
| 3758 | .imm12 = Immediate.s(-@as(i12, @intCast(64 - bit_size % 64))), |
| 3759 | } }, |
| 3760 | }); |
| 3761 | } |
| 3762 | |
| 3763 | break :result .{ .register = dst_reg }; |
| 3764 | }; |
| 3744 | 3765 | return func.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 3745 | 3766 | } |
| 3746 | 3767 | |