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 {...@@ -6712,9 +6712,65 @@ fn airArrayToSlice(func: *Func, inst: Air.Inst.Index) !void {
67126712
6713fn airFloatFromInt(func: *Func, inst: Air.Inst.Index) !void {6713fn airFloatFromInt(func: *Func, inst: Air.Inst.Index) !void {
6714 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;6714 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 {}", .{6715 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
6716 func.target.cpu.arch,6716 const pt = func.pt;
6717 });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 };
6718 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });6774 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
6719}6775}
67206776
...@@ -6726,7 +6782,7 @@ fn airIntFromFloat(func: *Func, inst: Air.Inst.Index) !void {...@@ -6726,7 +6782,7 @@ fn airIntFromFloat(func: *Func, inst: Air.Inst.Index) !void {
67266782
6727 const operand = try func.resolveInst(ty_op.operand);6783 const operand = try func.resolveInst(ty_op.operand);
6728 const src_ty = func.typeOf(ty_op.operand);6784 const src_ty = func.typeOf(ty_op.operand);
6729 const dst_ty = func.typeOfIndex(inst);6785 const dst_ty = ty_op.ty.toType();
67306786
6731 const is_unsigned = dst_ty.isUnsignedInt(zcu);6787 const is_unsigned = dst_ty.isUnsignedInt(zcu);
6732 const src_bits = src_ty.bitSize(pt);6788 const src_bits = src_ty.bitSize(pt);
...@@ -6740,7 +6796,7 @@ fn airIntFromFloat(func: *Func, inst: Air.Inst.Index) !void {...@@ -6740,7 +6796,7 @@ fn airIntFromFloat(func: *Func, inst: Air.Inst.Index) !void {
67406796
6741 const int_mod: Mir.FcvtOp = switch (dst_bits) {6797 const int_mod: Mir.FcvtOp = switch (dst_bits) {
6742 32 => if (is_unsigned) .wu else .w,6798 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,
6744 else => return func.fail("TODO: airIntFromFloat dst size: {d}", .{dst_bits}),6800 else => return func.fail("TODO: airIntFromFloat dst size: {d}", .{dst_bits}),
6745 };6801 };
67466802
src/arch/riscv64/encoding.zig+10
...@@ -280,6 +280,16 @@ pub const Lir = struct {...@@ -280,6 +280,16 @@ pub const Lir = struct {
280 .fcvtld => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11000, .fmt = .D, .rm = 0b111, .width = .l } } },280 .fcvtld => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11000, .fmt = .D, .rm = 0b111, .width = .l } } },
281 .fcvtlud => .{ .opcode = .OP_FP, .format = .R, .data = .{ .fcvt = .{ .funct5 = 0b11000, .fmt = .D, .rm = 0b111, .width = .lu } } },281 .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
283 // LOAD293 // LOAD
284294
285 .lb => .{ .opcode = .LOAD, .format = .I, .data = .{ .f = .{ .funct3 = 0b000 } } },295 .lb => .{ .opcode = .LOAD, .format = .I, .data = .{ .f = .{ .funct3 = 0b000 } } },
src/arch/riscv64/mnem.zig+10
...@@ -127,6 +127,16 @@ pub const Mnemonic = enum(u16) {...@@ -127,6 +127,16 @@ pub const Mnemonic = enum(u16) {
127 fcvtld,127 fcvtld,
128 fcvtlud,128 fcvtlud,
129129
130 fcvtsw,
131 fcvtswu,
132 fcvtsl,
133 fcvtslu,
134
135 fcvtdw,
136 fcvtdwu,
137 fcvtdl,
138 fcvtdlu,
139
130 fsgnjns,140 fsgnjns,
131 fsgnjnd,141 fsgnjnd,
132142
test/behavior/align.zig+1
...@@ -514,6 +514,7 @@ test "struct field explicit alignment" {...@@ -514,6 +514,7 @@ test "struct field explicit alignment" {
514 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;514 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
515 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO515 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
516 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // flaky516 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // flaky
517 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
517518
518 const S = struct {519 const S = struct {
519 const Node = struct {520 const Node = struct {
test/behavior/cast.zig-2
...@@ -104,7 +104,6 @@ test "@floatFromInt" {...@@ -104,7 +104,6 @@ test "@floatFromInt" {
104 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO104 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
105 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO105 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
106 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO106 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
107 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
108107
109 const S = struct {108 const S = struct {
110 fn doTheTest() !void {109 fn doTheTest() !void {
...@@ -163,7 +162,6 @@ test "@intFromFloat" {...@@ -163,7 +162,6 @@ test "@intFromFloat" {
163 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO162 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
164 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO163 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
165 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO164 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
166 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
167165
168 try testIntFromFloats();166 try testIntFromFloats();
169 try comptime testIntFromFloats();167 try comptime testIntFromFloats();