authorgravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-03-17 17:45:20-07:00
committergravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-05-11 02:17:11-07:00
log9b2a4582c983a4171de9ab9843d0af1d807ddbff
treed48479067b383ab4e7ef1ff30d53eca7e3e33e8a
parentf67fa73fe8bc5cc38af826c396d912b7f72b3261

riscv: implement 64 bit immediate into register loading

LLVM has a better myriad sequence for this, where they don't allocate a temporary register, but for now this will do.

1 files changed, 39 insertions(+), 4 deletions(-)

src/arch/riscv64/CodeGen.zig+39-4
...@@ -2633,8 +2633,17 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, src_val: MCValue) Inner...@@ -2633,8 +2633,17 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, src_val: MCValue) Inner
2633 switch (src_val) {2633 switch (src_val) {
2634 .none => return,2634 .none => return,
2635 .dead => unreachable,2635 .dead => unreachable,
2636 .undef => {
2637 if (!self.wantSafety()) return;
2638 try self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaaaaaaaaaa });
2639 },
2636 .immediate => {2640 .immediate => {
2637 const reg = try self.copyToTmpRegister(ty, src_val);2641 const reg = try self.register_manager.allocReg(null, gp);
2642 const reg_lock = self.register_manager.lockReg(reg);
2643 defer if (reg_lock) |lock| self.register_manager.unlockReg(lock);
2644
2645 try self.genSetReg(ty, reg, src_val);
2646
2638 return self.genSetStack(ty, stack_offset, .{ .register = reg });2647 return self.genSetStack(ty, stack_offset, .{ .register = reg });
2639 },2648 },
2640 .register => |reg| {2649 .register => |reg| {
...@@ -2724,6 +2733,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, src_val: MCValue) Inner...@@ -2724,6 +2733,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, src_val: MCValue) Inner
2724 // memcpy(src, dst, len)2733 // memcpy(src, dst, len)
2725 try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg);2734 try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg);
2726 },2735 },
2736
2727 else => return self.fail("TODO: genSetStack {s}", .{@tagName(src_val)}),2737 else => return self.fail("TODO: genSetStack {s}", .{@tagName(src_val)}),
2728 }2738 }
2729}2739}
...@@ -2826,9 +2836,34 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_val: MCValue) InnerError!...@@ -2826,9 +2836,34 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_val: MCValue) InnerError!
2826 } },2836 } },
2827 });2837 });
2828 } else {2838 } else {
2829 // li rd, immediate2839 const temp = try self.register_manager.allocReg(null, gp);
2830 // "Myriad sequences"2840 const maybe_temp_lock = self.register_manager.lockReg(temp);
2831 return self.fail("TODO genSetReg 33-64 bit immediates for riscv64", .{}); // glhf2841 defer if (maybe_temp_lock) |temp_lock| self.register_manager.unlockReg(temp_lock);
2842
2843 const lo32: i32 = @truncate(x);
2844 const carry: i32 = if (lo32 < 0) 1 else 0;
2845 const hi32: i32 = @truncate((x >> 32) +% carry);
2846
2847 try self.genSetReg(Type.i32, temp, .{ .immediate = @bitCast(@as(i64, lo32)) });
2848 try self.genSetReg(Type.i32, reg, .{ .immediate = @bitCast(@as(i64, hi32)) });
2849
2850 _ = try self.addInst(.{
2851 .tag = .slli,
2852 .data = .{ .i_type = .{
2853 .imm12 = 32,
2854 .rd = reg,
2855 .rs1 = reg,
2856 } },
2857 });
2858
2859 _ = try self.addInst(.{
2860 .tag = .add,
2861 .data = .{ .r_type = .{
2862 .rd = reg,
2863 .rs1 = reg,
2864 .rs2 = temp,
2865 } },
2866 });
2832 }2867 }
2833 },2868 },
2834 .register => |src_reg| {2869 .register => |src_reg| {