authorgravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-07-24 19:31:51-07:00
committergravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-07-26 04:19:16-07:00
logc00a5ff792e78564673d0dc76b901c98b938bb9b
treef95878ab09d8666ebf4a610869241635130ed3e3
parent1a7d89a84d7fef87eb45da8207bbeb852e3f0c02
signaturelock-open Commit is signed but in an unrecognized format.

riscv: implement `@floatFromInt`


5 files changed, 82 insertions(+), 7 deletions(-)

src/arch/riscv64/CodeGen.zig+61-5
......@@ -6712,9 +6712,65 @@ fn airArrayToSlice(func: *Func, inst: Air.Inst.Index) !void {
67126712
67136713fn airFloatFromInt(func: *Func, inst: Air.Inst.Index) !void {
67146714 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
6715 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airFloatFromInt for {}", .{
6716 func.target.cpu.arch,
6717 });
6715 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
6716 const pt = func.pt;
6717 const zcu = pt.zcu;
6718
6719 const operand = try func.resolveInst(ty_op.operand);
6720
6721 const src_ty = func.typeOf(ty_op.operand);
6722 const dst_ty = ty_op.ty.toType();
6723
6724 const src_reg, const src_lock = try func.promoteReg(src_ty, operand);
6725 defer if (src_lock) |lock| func.register_manager.unlockReg(lock);
6726
6727 const is_unsigned = dst_ty.isUnsignedInt(zcu);
6728 const src_bits = src_ty.bitSize(pt);
6729 const dst_bits = dst_ty.bitSize(pt);
6730
6731 switch (src_bits) {
6732 32, 64 => {},
6733 else => try func.truncateRegister(src_ty, src_reg),
6734 }
6735
6736 const int_mod: Mir.FcvtOp = switch (src_bits) {
6737 8, 16, 32 => if (is_unsigned) .wu else .w,
6738 64 => if (is_unsigned) .lu else .l,
6739 else => return func.fail("TODO: airFloatFromInt src size: {d}", .{src_bits}),
6740 };
6741
6742 const float_mod: enum { s, d } = switch (dst_bits) {
6743 32 => .s,
6744 64 => .d,
6745 else => return func.fail("TODO: airFloatFromInt dst size {d}", .{dst_bits}),
6746 };
6747
6748 const dst_reg, const dst_lock = try func.allocReg(.int);
6749 defer func.register_manager.unlockReg(dst_lock);
6750
6751 _ = try func.addInst(.{
6752 .tag = switch (float_mod) {
6753 .s => switch (int_mod) {
6754 .l => .fcvtsl,
6755 .lu => .fcvtslu,
6756 .w => .fcvtsw,
6757 .wu => .fcvtswu,
6758 },
6759 .d => switch (int_mod) {
6760 .l => .fcvtdl,
6761 .lu => .fcvtdlu,
6762 .w => .fcvtdw,
6763 .wu => .fcvtdwu,
6764 },
6765 },
6766 .data = .{ .rr = .{
6767 .rd = dst_reg,
6768 .rs = src_reg,
6769 } },
6770 });
6771
6772 break :result .{ .register = dst_reg };
6773 };
67186774 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
67196775}
67206776
......@@ -6726,7 +6782,7 @@ fn airIntFromFloat(func: *Func, inst: Air.Inst.Index) !void {
67266782
67276783 const operand = try func.resolveInst(ty_op.operand);
67286784 const src_ty = func.typeOf(ty_op.operand);
6729 const dst_ty = func.typeOfIndex(inst);
6785 const dst_ty = ty_op.ty.toType();
67306786
67316787 const is_unsigned = dst_ty.isUnsignedInt(zcu);
67326788 const src_bits = src_ty.bitSize(pt);
......@@ -6740,7 +6796,7 @@ fn airIntFromFloat(func: *Func, inst: Air.Inst.Index) !void {
67406796
67416797 const int_mod: Mir.FcvtOp = switch (dst_bits) {
67426798 32 => if (is_unsigned) .wu else .w,
6743 64 => if (is_unsigned) .lu else .l,
6799 8, 16, 64 => if (is_unsigned) .lu else .l,
67446800 else => return func.fail("TODO: airIntFromFloat dst size: {d}", .{dst_bits}),
67456801 };
67466802
src/arch/riscv64/encoding.zig+10
......@@ -280,6 +280,16 @@ pub const Lir = struct {
280280 .fcvtld => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11000, .fmt = .D, .rm = 0b111, .width = .l } } },
281281 .fcvtlud => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11000, .fmt = .D, .rm = 0b111, .width = .lu } } },
282282
283 .fcvtsw => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .S, .rm = 0b111, .width = .w } } },
284 .fcvtswu => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .S, .rm = 0b111, .width = .wu } } },
285 .fcvtsl => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .S, .rm = 0b111, .width = .l } } },
286 .fcvtslu => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .S, .rm = 0b111, .width = .lu } } },
287
288 .fcvtdw => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .D, .rm = 0b111, .width = .w } } },
289 .fcvtdwu => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .D, .rm = 0b111, .width = .wu } } },
290 .fcvtdl => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .D, .rm = 0b111, .width = .l } } },
291 .fcvtdlu => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11010, .fmt = .D, .rm = 0b111, .width = .lu } } },
292
283293 // LOAD
284294
285295 .lb => .{ .opcode = .LOAD, .format = .I, .data = .{ .f = .{ .funct3 = 0b000 } } },
src/arch/riscv64/mnem.zig+10
......@@ -127,6 +127,16 @@ pub const Mnemonic = enum(u16) {
127127 fcvtld,
128128 fcvtlud,
129129
130 fcvtsw,
131 fcvtswu,
132 fcvtsl,
133 fcvtslu,
134
135 fcvtdw,
136 fcvtdwu,
137 fcvtdl,
138 fcvtdlu,
139
130140 fsgnjns,
131141 fsgnjnd,
132142
test/behavior/align.zig+1
......@@ -514,6 +514,7 @@ test "struct field explicit alignment" {
514514 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
515515 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
516516 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // flaky
517 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
517518
518519 const S = struct {
519520 const Node = struct {
test/behavior/cast.zig-2
......@@ -104,7 +104,6 @@ test "@floatFromInt" {
104104 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
105105 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
106106 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
107 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
108107
109108 const S = struct {
110109 fn doTheTest() !void {
......@@ -163,7 +162,6 @@ test "@intFromFloat" {
163162 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
164163 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
165164 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
166 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
167165
168166 try testIntFromFloats();
169167 try comptime testIntFromFloats();