authorgravatar for techatrix@mailbox.orgTechatrix <techatrix@mailbox.org> 2023-09-10 15:40:52+02:00
committergravatar for techatrix@mailbox.orgTechatrix <techatrix@mailbox.org> 2023-09-10 15:40:52+02:00
log673ebfabd1c85c7f701e588aff1a05deaf29cd94
tree2036a8b263d65d802d6ee7ab9db13864f080824f
parent33830d194ea0aaf2ef880efa9b373db167d1a183

wasm: implement negation on f80 and f128


1 files changed, 54 insertions(+), 14 deletions(-)

src/arch/wasm/CodeGen.zig+54-14
......@@ -992,13 +992,12 @@ fn addExtraAssumeCapacity(func: *CodeGen, extra: anytype) error{OutOfMemory}!u32
992992fn typeToValtype(ty: Type, mod: *Module) wasm.Valtype {
993993 const target = mod.getTarget();
994994 return switch (ty.zigTypeTag(mod)) {
995 .Float => blk: {
996 const bits = ty.floatBits(target);
997 if (bits == 16) return wasm.Valtype.i32; // stored/loaded as u16
998 if (bits == 32) break :blk wasm.Valtype.f32;
999 if (bits == 64) break :blk wasm.Valtype.f64;
1000 if (bits == 128) break :blk wasm.Valtype.i64;
1001 return wasm.Valtype.i32; // represented as pointer to stack
995 .Float => switch (ty.floatBits(target)) {
996 16 => wasm.Valtype.i32, // stored/loaded as u16
997 32 => wasm.Valtype.f32,
998 64 => wasm.Valtype.f64,
999 80, 128 => wasm.Valtype.i64,
1000 else => unreachable,
10021001 },
10031002 .Int, .Enum => blk: {
10041003 const info = ty.intInfo(mod);
......@@ -2795,6 +2794,11 @@ fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) In
27952794 }
27962795
27972796 const float_bits = ty.floatBits(func.target);
2797
2798 if (float_op == .neg) {
2799 return func.floatNeg(ty, args[0]);
2800 }
2801
27982802 if (float_bits == 32 or float_bits == 64) {
27992803 if (float_op.toOp()) |op| {
28002804 for (args) |operand| {
......@@ -2804,13 +2808,6 @@ fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) In
28042808 try func.addTag(Mir.Inst.Tag.fromOpcode(opcode));
28052809 return .stack;
28062810 }
2807 } else if (float_bits == 16 and float_op == .neg) {
2808 try func.emitWValue(args[0]);
2809 try func.addImm32(std.math.minInt(i16));
2810 try func.addTag(Mir.Inst.Tag.fromOpcode(.i32_xor));
2811 return .stack;
2812 } else if (float_bits == 128 and float_op == .neg) {
2813 return func.fail("TODO: Implement neg for f128", .{});
28142811 }
28152812
28162813 var fn_name_buf: [64]u8 = undefined;
......@@ -2853,6 +2850,49 @@ fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) In
28532850 return func.callIntrinsic(fn_name, param_types, ty, args);
28542851}
28552852
2853/// NOTE: The result value remains on top of the stack.
2854fn floatNeg(func: *CodeGen, ty: Type, arg: WValue) InnerError!WValue {
2855 const float_bits = ty.floatBits(func.target);
2856 switch (float_bits) {
2857 16 => {
2858 try func.emitWValue(arg);
2859 try func.addImm32(std.math.minInt(i16));
2860 try func.addTag(.i32_xor);
2861 return .stack;
2862 },
2863 32, 64 => {
2864 try func.emitWValue(arg);
2865 const val_type: wasm.Valtype = if (float_bits == 32) .f32 else .f64;
2866 const opcode = buildOpcode(.{ .op = .neg, .valtype1 = val_type });
2867 try func.addTag(Mir.Inst.Tag.fromOpcode(opcode));
2868 return .stack;
2869 },
2870 80, 128 => {
2871 const result = try func.allocStack(ty);
2872 try func.emitWValue(result);
2873 try func.emitWValue(arg);
2874 try func.addMemArg(.i64_load, .{ .offset = 0 + arg.offset(), .alignment = 2 });
2875 try func.addMemArg(.i64_store, .{ .offset = 0 + result.offset(), .alignment = 2 });
2876
2877 try func.emitWValue(result);
2878 try func.emitWValue(arg);
2879 try func.addMemArg(.i64_load, .{ .offset = 8 + arg.offset(), .alignment = 2 });
2880
2881 if (float_bits == 80) {
2882 try func.addImm64(0x8000);
2883 try func.addTag(.i64_xor);
2884 try func.addMemArg(.i64_store16, .{ .offset = 8 + result.offset(), .alignment = 2 });
2885 } else {
2886 try func.addImm64(0x8000000000000000);
2887 try func.addTag(.i64_xor);
2888 try func.addMemArg(.i64_store, .{ .offset = 8 + result.offset(), .alignment = 2 });
2889 }
2890 return result;
2891 },
2892 else => unreachable,
2893 }
2894}
2895
28562896fn airWrapBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
28572897 const mod = func.bin_file.base.options.module.?;
28582898 const bin_op = func.air.instructions.items(.data)[inst].bin_op;