| author | |
| committer | |
| log | d69c48370a0381c7dce463c68b2097dd8fa67eb7 |
| tree | a5f2fc954e7bd6b73164c8ef1c8742b5f2827649 |
| parent | 206e66858c69cd667aad3779837493968bfcd228 |
| signature |
8 files changed, 112 insertions(+), 11 deletions(-)
src/arch/riscv64/CodeGen.zig+68-3| ... | @@ -3377,18 +3377,83 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -3377,18 +3377,83 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void { |
| 3377 | const ty = func.typeOf(ty_op.operand); | 3377 | const ty = func.typeOf(ty_op.operand); |
| 3378 | const scalar_ty = ty.scalarType(zcu); | 3378 | const scalar_ty = ty.scalarType(zcu); |
| 3379 | const operand = try func.resolveInst(ty_op.operand); | 3379 | const operand = try func.resolveInst(ty_op.operand); |
| 3380 | _ = operand; | ||
| 3381 | 3380 | ||
| 3382 | switch (scalar_ty.zigTypeTag(zcu)) { | 3381 | switch (scalar_ty.zigTypeTag(zcu)) { |
| 3383 | .Int => if (ty.zigTypeTag(zcu) == .Vector) { | 3382 | .Int => if (ty.zigTypeTag(zcu) == .Vector) { |
| 3384 | return func.fail("TODO implement airAbs for {}", .{ty.fmt(zcu)}); | 3383 | return func.fail("TODO implement airAbs for {}", .{ty.fmt(zcu)}); |
| 3385 | } else { | 3384 | } else { |
| 3386 | return func.fail("TODO: implement airAbs for Int", .{}); | 3385 | const return_mcv = try func.copyToNewRegister(inst, operand); |
| 3386 | const operand_reg = return_mcv.register; | ||
| 3387 | |||
| 3388 | const temp_reg, const temp_lock = try func.allocReg(.int); | ||
| 3389 | defer func.register_manager.unlockReg(temp_lock); | ||
| 3390 | |||
| 3391 | _ = try func.addInst(.{ | ||
| 3392 | .tag = .srai, | ||
| 3393 | .ops = .rri, | ||
| 3394 | .data = .{ .i_type = .{ | ||
| 3395 | .rd = temp_reg, | ||
| 3396 | .rs1 = operand_reg, | ||
| 3397 | .imm12 = Immediate.s(63), | ||
| 3398 | } }, | ||
| 3399 | }); | ||
| 3400 | |||
| 3401 | _ = try func.addInst(.{ | ||
| 3402 | .tag = .xor, | ||
| 3403 | .ops = .rrr, | ||
| 3404 | .data = .{ .r_type = .{ | ||
| 3405 | .rd = operand_reg, | ||
| 3406 | .rs1 = operand_reg, | ||
| 3407 | .rs2 = temp_reg, | ||
| 3408 | } }, | ||
| 3409 | }); | ||
| 3410 | |||
| 3411 | _ = try func.addInst(.{ | ||
| 3412 | .tag = .sub, | ||
| 3413 | .ops = .rrr, | ||
| 3414 | .data = .{ .r_type = .{ | ||
| 3415 | .rd = operand_reg, | ||
| 3416 | .rs1 = operand_reg, | ||
| 3417 | .rs2 = temp_reg, | ||
| 3418 | } }, | ||
| 3419 | }); | ||
| 3420 | |||
| 3421 | break :result return_mcv; | ||
| 3422 | }, | ||
| 3423 | .Float => { | ||
| 3424 | const float_bits = scalar_ty.floatBits(zcu.getTarget()); | ||
| 3425 | switch (float_bits) { | ||
| 3426 | 16 => return func.fail("TODO: airAbs 16-bit float", .{}), | ||
| 3427 | 32 => {}, | ||
| 3428 | 64 => {}, | ||
| 3429 | 80 => return func.fail("TODO: airAbs 80-bit float", .{}), | ||
| 3430 | 128 => return func.fail("TODO: airAbs 128-bit float", .{}), | ||
| 3431 | else => unreachable, | ||
| 3432 | } | ||
| 3433 | |||
| 3434 | const return_mcv = try func.copyToNewRegister(inst, operand); | ||
| 3435 | const operand_reg = return_mcv.register; | ||
| 3436 | |||
| 3437 | assert(operand_reg.class() == .float); | ||
| 3438 | |||
| 3439 | _ = try func.addInst(.{ | ||
| 3440 | .tag = .pseudo, | ||
| 3441 | .ops = .pseudo_fabs, | ||
| 3442 | .data = .{ | ||
| 3443 | .fabs = .{ | ||
| 3444 | .rd = operand_reg, | ||
| 3445 | .rs = operand_reg, | ||
| 3446 | .bits = float_bits, | ||
| 3447 | }, | ||
| 3448 | }, | ||
| 3449 | }); | ||
| 3450 | |||
| 3451 | break :result return_mcv; | ||
| 3387 | }, | 3452 | }, |
| 3388 | else => return func.fail("TODO: implement airAbs {}", .{scalar_ty.fmt(zcu)}), | 3453 | else => return func.fail("TODO: implement airAbs {}", .{scalar_ty.fmt(zcu)}), |
| 3389 | } | 3454 | } |
| 3390 | 3455 | ||
| 3391 | break :result .{.unreach}; | 3456 | break :result .unreach; |
| 3392 | }; | 3457 | }; |
| 3393 | return func.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 3458 | return func.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 3394 | } | 3459 | } |
src/arch/riscv64/Encoding.zig+8| ... | @@ -130,6 +130,7 @@ pub const Mnemonic = enum { | ... | @@ -130,6 +130,7 @@ pub const Mnemonic = enum { |
| 130 | fles, | 130 | fles, |
| 131 | 131 | ||
| 132 | fsgnjns, | 132 | fsgnjns, |
| 133 | fsgnjxs, | ||
| 133 | 134 | ||
| 134 | // D extension (64-bit float) | 135 | // D extension (64-bit float) |
| 135 | faddd, | 136 | faddd, |
| ... | @@ -150,6 +151,7 @@ pub const Mnemonic = enum { | ... | @@ -150,6 +151,7 @@ pub const Mnemonic = enum { |
| 150 | fled, | 151 | fled, |
| 151 | 152 | ||
| 152 | fsgnjnd, | 153 | fsgnjnd, |
| 154 | fsgnjxd, | ||
| 153 | 155 | ||
| 154 | pub fn encoding(mnem: Mnemonic) Enc { | 156 | pub fn encoding(mnem: Mnemonic) Enc { |
| 155 | return switch (mnem) { | 157 | return switch (mnem) { |
| ... | @@ -218,6 +220,9 @@ pub const Mnemonic = enum { | ... | @@ -218,6 +220,9 @@ pub const Mnemonic = enum { |
| 218 | .fsgnjns => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .S, .rm = 0b000 } } }, | 220 | .fsgnjns => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .S, .rm = 0b000 } } }, |
| 219 | .fsgnjnd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .D, .rm = 0b000 } } }, | 221 | .fsgnjnd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .D, .rm = 0b000 } } }, |
| 220 | 222 | ||
| 223 | .fsgnjxs => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .S, .rm = 0b0010} } }, | ||
| 224 | .fsgnjxd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .D, .rm = 0b0010} } }, | ||
| 225 | |||
| 221 | 226 | ||
| 222 | // LOAD | 227 | // LOAD |
| 223 | 228 | ||
| ... | @@ -392,6 +397,9 @@ pub const InstEnc = enum { | ... | @@ -392,6 +397,9 @@ pub const InstEnc = enum { |
| 392 | 397 | ||
| 393 | .fsgnjns, | 398 | .fsgnjns, |
| 394 | .fsgnjnd, | 399 | .fsgnjnd, |
| 400 | |||
| 401 | .fsgnjxs, | ||
| 402 | .fsgnjxd, | ||
| 395 | => .R, | 403 | => .R, |
| 396 | 404 | ||
| 397 | .ecall, | 405 | .ecall, |
src/arch/riscv64/Lower.zig+20| ... | @@ -208,6 +208,26 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { | ... | @@ -208,6 +208,26 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { |
| 208 | }); | 208 | }); |
| 209 | }, | 209 | }, |
| 210 | 210 | ||
| 211 | .pseudo_fabs => { | ||
| 212 | const fabs = inst.data.fabs; | ||
| 213 | assert(fabs.rs.class() == .float and fabs.rd.class() == .float); | ||
| 214 | |||
| 215 | const mnem: Encoding.Mnemonic = switch (fabs.bits) { | ||
| 216 | 16 => return lower.fail("TODO: airAbs Float 16", .{}), | ||
| 217 | 32 => .fsgnjxs, | ||
| 218 | 64 => .fsgnjxd, | ||
| 219 | 80 => return lower.fail("TODO: airAbs Float 80", .{}), | ||
| 220 | 128 => return lower.fail("TODO: airAbs Float 128", .{}), | ||
| 221 | else => unreachable, | ||
| 222 | }; | ||
| 223 | |||
| 224 | try lower.emit(mnem, &.{ | ||
| 225 | .{ .reg = fabs.rs }, | ||
| 226 | .{ .reg = fabs.rd }, | ||
| 227 | .{ .reg = fabs.rd }, | ||
| 228 | }); | ||
| 229 | }, | ||
| 230 | |||
| 211 | .pseudo_compare => { | 231 | .pseudo_compare => { |
| 212 | const compare = inst.data.compare; | 232 | const compare = inst.data.compare; |
| 213 | const op = compare.op; | 233 | const op = compare.op; |
src/arch/riscv64/Mir.zig+13| ... | @@ -76,6 +76,8 @@ pub const Inst = struct { | ... | @@ -76,6 +76,8 @@ pub const Inst = struct { |
| 76 | fmuls, | 76 | fmuls, |
| 77 | fdivs, | 77 | fdivs, |
| 78 | 78 | ||
| 79 | fabss, | ||
| 80 | |||
| 79 | fmins, | 81 | fmins, |
| 80 | fmaxs, | 82 | fmaxs, |
| 81 | 83 | ||
| ... | @@ -94,6 +96,8 @@ pub const Inst = struct { | ... | @@ -94,6 +96,8 @@ pub const Inst = struct { |
| 94 | fmuld, | 96 | fmuld, |
| 95 | fdivd, | 97 | fdivd, |
| 96 | 98 | ||
| 99 | fabsd, | ||
| 100 | |||
| 97 | fmind, | 101 | fmind, |
| 98 | fmaxd, | 102 | fmaxd, |
| 99 | 103 | ||
| ... | @@ -194,6 +198,12 @@ pub const Inst = struct { | ... | @@ -194,6 +198,12 @@ pub const Inst = struct { |
| 194 | rs: Register, | 198 | rs: Register, |
| 195 | }, | 199 | }, |
| 196 | 200 | ||
| 201 | fabs: struct { | ||
| 202 | rd: Register, | ||
| 203 | rs: Register, | ||
| 204 | bits: u16, | ||
| 205 | }, | ||
| 206 | |||
| 197 | compare: struct { | 207 | compare: struct { |
| 198 | rd: Register, | 208 | rd: Register, |
| 199 | rs1: Register, | 209 | rs1: Register, |
| ... | @@ -273,6 +283,9 @@ pub const Inst = struct { | ... | @@ -273,6 +283,9 @@ pub const Inst = struct { |
| 273 | /// Jumps. Uses `inst` payload. | 283 | /// Jumps. Uses `inst` payload. |
| 274 | pseudo_j, | 284 | pseudo_j, |
| 275 | 285 | ||
| 286 | /// Floating point absolute value. | ||
| 287 | pseudo_fabs, | ||
| 288 | |||
| 276 | /// Dead inst, ignored by the emitter. | 289 | /// Dead inst, ignored by the emitter. |
| 277 | pseudo_dead, | 290 | pseudo_dead, |
| 278 | 291 |
test/behavior/abs.zig+3-5| ... | @@ -6,7 +6,6 @@ test "@abs integers" { | ... | @@ -6,7 +6,6 @@ test "@abs integers" { |
| 6 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 6 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 7 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 7 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 8 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 8 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 9 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 10 | 9 | ||
| 11 | try comptime testAbsIntegers(); | 10 | try comptime testAbsIntegers(); |
| 12 | try testAbsIntegers(); | 11 | try testAbsIntegers(); |
| ... | @@ -93,18 +92,17 @@ test "@abs floats" { | ... | @@ -93,18 +92,17 @@ test "@abs floats" { |
| 93 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 92 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 94 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 93 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 95 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | 94 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; |
| 96 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 97 | 95 | ||
| 98 | try comptime testAbsFloats(f16); | 96 | try comptime testAbsFloats(f16); |
| 99 | try testAbsFloats(f16); | 97 | if (builtin.zig_backend != .stage2_riscv64) try testAbsFloats(f16); |
| 100 | try comptime testAbsFloats(f32); | 98 | try comptime testAbsFloats(f32); |
| 101 | try testAbsFloats(f32); | 99 | try testAbsFloats(f32); |
| 102 | try comptime testAbsFloats(f64); | 100 | try comptime testAbsFloats(f64); |
| 103 | try testAbsFloats(f64); | 101 | try testAbsFloats(f64); |
| 104 | try comptime testAbsFloats(f80); | 102 | try comptime testAbsFloats(f80); |
| 105 | if (builtin.zig_backend != .stage2_wasm and builtin.zig_backend != .stage2_spirv64) try testAbsFloats(f80); | 103 | if (builtin.zig_backend != .stage2_wasm and builtin.zig_backend != .stage2_spirv64 and builtin.zig_backend != .stage2_riscv64) try testAbsFloats(f80); |
| 106 | try comptime testAbsFloats(f128); | 104 | try comptime testAbsFloats(f128); |
| 107 | if (builtin.zig_backend != .stage2_wasm and builtin.zig_backend != .stage2_spirv64) try testAbsFloats(f128); | 105 | if (builtin.zig_backend != .stage2_wasm and builtin.zig_backend != .stage2_spirv64 and builtin.zig_backend != .stage2_riscv64) try testAbsFloats(f128); |
| 108 | } | 106 | } |
| 109 | 107 | ||
| 110 | fn testAbsFloats(comptime T: type) !void { | 108 | fn testAbsFloats(comptime T: type) !void { |
test/behavior/cast.zig-1| ... | @@ -2608,7 +2608,6 @@ test "@as does not corrupt values with incompatible representations" { | ... | @@ -2608,7 +2608,6 @@ test "@as does not corrupt values with incompatible representations" { |
| 2608 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 2608 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 2609 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 2609 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 2610 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; | 2610 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; |
| 2611 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 2612 | 2611 | ||
| 2613 | const x: f32 = @as(f16, blk: { | 2612 | const x: f32 = @as(f16, blk: { |
| 2614 | if (false) { | 2613 | if (false) { |
test/behavior/floatop.zig-1| ... | @@ -999,7 +999,6 @@ test "@abs f32/f64" { | ... | @@ -999,7 +999,6 @@ test "@abs f32/f64" { |
| 999 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 999 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1000 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1000 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1001 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1001 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1002 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 1003 | 1002 | ||
| 1004 | try testFabs(f32); | 1003 | try testFabs(f32); |
| 1005 | try comptime testFabs(f32); | 1004 | try comptime testFabs(f32); |
test/behavior/math.zig-1| ... | @@ -1814,7 +1814,6 @@ test "absFloat" { | ... | @@ -1814,7 +1814,6 @@ test "absFloat" { |
| 1814 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1814 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1815 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1815 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1816 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1816 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1817 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 1818 | 1817 | ||
| 1819 | try testAbsFloat(); | 1818 | try testAbsFloat(); |
| 1820 | try comptime testAbsFloat(); | 1819 | try comptime testAbsFloat(); |