aboutsummaryrefslogtreecommitdiff
path: root/src/arch
diff options
context:
space:
mode:
authorDavid Rubin <daviru007@icloud.com>2024-05-25 14:15:21 -0700
committerDavid Rubin <daviru007@icloud.com>2024-06-13 02:22:06 -0700
commitd69c48370a0381c7dce463c68b2097dd8fa67eb7 (patch)
treea5f2fc954e7bd6b73164c8ef1c8742b5f2827649 /src/arch
parent206e66858c69cd667aad3779837493968bfcd228 (diff)
downloadzig-d69c48370a0381c7dce463c68b2097dd8fa67eb7.tar.gz
zig-d69c48370a0381c7dce463c68b2097dd8fa67eb7.zip
riscv: integer + float `@abs`
Diffstat (limited to 'src/arch')
-rw-r--r--src/arch/riscv64/CodeGen.zig71
-rw-r--r--src/arch/riscv64/Encoding.zig8
-rw-r--r--src/arch/riscv64/Lower.zig20
-rw-r--r--src/arch/riscv64/Mir.zig13
4 files changed, 109 insertions, 3 deletions
diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig
index f252c9e6b7..cca02cb1a0 100644
--- a/src/arch/riscv64/CodeGen.zig
+++ b/src/arch/riscv64/CodeGen.zig
@@ -3377,18 +3377,83 @@ fn airAbs(func: *Func, inst: Air.Inst.Index) !void {
const ty = func.typeOf(ty_op.operand);
const scalar_ty = ty.scalarType(zcu);
const operand = try func.resolveInst(ty_op.operand);
- _ = operand;
switch (scalar_ty.zigTypeTag(zcu)) {
.Int => if (ty.zigTypeTag(zcu) == .Vector) {
return func.fail("TODO implement airAbs for {}", .{ty.fmt(zcu)});
} else {
- return func.fail("TODO: implement airAbs for Int", .{});
+ const return_mcv = try func.copyToNewRegister(inst, operand);
+ const operand_reg = return_mcv.register;
+
+ const temp_reg, const temp_lock = try func.allocReg(.int);
+ defer func.register_manager.unlockReg(temp_lock);
+
+ _ = try func.addInst(.{
+ .tag = .srai,
+ .ops = .rri,
+ .data = .{ .i_type = .{
+ .rd = temp_reg,
+ .rs1 = operand_reg,
+ .imm12 = Immediate.s(63),
+ } },
+ });
+
+ _ = try func.addInst(.{
+ .tag = .xor,
+ .ops = .rrr,
+ .data = .{ .r_type = .{
+ .rd = operand_reg,
+ .rs1 = operand_reg,
+ .rs2 = temp_reg,
+ } },
+ });
+
+ _ = try func.addInst(.{
+ .tag = .sub,
+ .ops = .rrr,
+ .data = .{ .r_type = .{
+ .rd = operand_reg,
+ .rs1 = operand_reg,
+ .rs2 = temp_reg,
+ } },
+ });
+
+ break :result return_mcv;
+ },
+ .Float => {
+ const float_bits = scalar_ty.floatBits(zcu.getTarget());
+ switch (float_bits) {
+ 16 => return func.fail("TODO: airAbs 16-bit float", .{}),
+ 32 => {},
+ 64 => {},
+ 80 => return func.fail("TODO: airAbs 80-bit float", .{}),
+ 128 => return func.fail("TODO: airAbs 128-bit float", .{}),
+ else => unreachable,
+ }
+
+ const return_mcv = try func.copyToNewRegister(inst, operand);
+ const operand_reg = return_mcv.register;
+
+ assert(operand_reg.class() == .float);
+
+ _ = try func.addInst(.{
+ .tag = .pseudo,
+ .ops = .pseudo_fabs,
+ .data = .{
+ .fabs = .{
+ .rd = operand_reg,
+ .rs = operand_reg,
+ .bits = float_bits,
+ },
+ },
+ });
+
+ break :result return_mcv;
},
else => return func.fail("TODO: implement airAbs {}", .{scalar_ty.fmt(zcu)}),
}
- break :result .{.unreach};
+ break :result .unreach;
};
return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
}
diff --git a/src/arch/riscv64/Encoding.zig b/src/arch/riscv64/Encoding.zig
index a944cac634..6f412935e4 100644
--- a/src/arch/riscv64/Encoding.zig
+++ b/src/arch/riscv64/Encoding.zig
@@ -130,6 +130,7 @@ pub const Mnemonic = enum {
fles,
fsgnjns,
+ fsgnjxs,
// D extension (64-bit float)
faddd,
@@ -150,6 +151,7 @@ pub const Mnemonic = enum {
fled,
fsgnjnd,
+ fsgnjxd,
pub fn encoding(mnem: Mnemonic) Enc {
return switch (mnem) {
@@ -218,6 +220,9 @@ pub const Mnemonic = enum {
.fsgnjns => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .S, .rm = 0b000 } } },
.fsgnjnd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .D, .rm = 0b000 } } },
+ .fsgnjxs => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .S, .rm = 0b0010} } },
+ .fsgnjxd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .D, .rm = 0b0010} } },
+
// LOAD
@@ -392,6 +397,9 @@ pub const InstEnc = enum {
.fsgnjns,
.fsgnjnd,
+
+ .fsgnjxs,
+ .fsgnjxd,
=> .R,
.ecall,
diff --git a/src/arch/riscv64/Lower.zig b/src/arch/riscv64/Lower.zig
index 99270c8a7e..560f8349df 100644
--- a/src/arch/riscv64/Lower.zig
+++ b/src/arch/riscv64/Lower.zig
@@ -208,6 +208,26 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
});
},
+ .pseudo_fabs => {
+ const fabs = inst.data.fabs;
+ assert(fabs.rs.class() == .float and fabs.rd.class() == .float);
+
+ const mnem: Encoding.Mnemonic = switch (fabs.bits) {
+ 16 => return lower.fail("TODO: airAbs Float 16", .{}),
+ 32 => .fsgnjxs,
+ 64 => .fsgnjxd,
+ 80 => return lower.fail("TODO: airAbs Float 80", .{}),
+ 128 => return lower.fail("TODO: airAbs Float 128", .{}),
+ else => unreachable,
+ };
+
+ try lower.emit(mnem, &.{
+ .{ .reg = fabs.rs },
+ .{ .reg = fabs.rd },
+ .{ .reg = fabs.rd },
+ });
+ },
+
.pseudo_compare => {
const compare = inst.data.compare;
const op = compare.op;
diff --git a/src/arch/riscv64/Mir.zig b/src/arch/riscv64/Mir.zig
index dd79a8dd83..76822c3968 100644
--- a/src/arch/riscv64/Mir.zig
+++ b/src/arch/riscv64/Mir.zig
@@ -76,6 +76,8 @@ pub const Inst = struct {
fmuls,
fdivs,
+ fabss,
+
fmins,
fmaxs,
@@ -94,6 +96,8 @@ pub const Inst = struct {
fmuld,
fdivd,
+ fabsd,
+
fmind,
fmaxd,
@@ -194,6 +198,12 @@ pub const Inst = struct {
rs: Register,
},
+ fabs: struct {
+ rd: Register,
+ rs: Register,
+ bits: u16,
+ },
+
compare: struct {
rd: Register,
rs1: Register,
@@ -273,6 +283,9 @@ pub const Inst = struct {
/// Jumps. Uses `inst` payload.
pseudo_j,
+ /// Floating point absolute value.
+ pseudo_fabs,
+
/// Dead inst, ignored by the emitter.
pseudo_dead,