authorgravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-06-04 04:55:28-07:00
committergravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-07-14 23:02:34-07:00
log09e9812086073d9e8ebfe6f61c227f1ab5859f40
tree8059a03ab0ff21ebfca129c505ba929f6caeefb2
parent571aa694fd150b9f76d78a6ac96c25163f46091a
signaturelock-open Commit is signed but in an unrecognized format.

riscv: vectors part 2


5 files changed, 248 insertions(+), 108 deletions(-)

src/arch/riscv64/CodeGen.zig+180-71
...@@ -995,7 +995,6 @@ fn addInst(func: *Func, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {...@@ -995,7 +995,6 @@ fn addInst(func: *Func, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {
995 .pseudo_dbg_prologue_end,995 .pseudo_dbg_prologue_end,
996 .pseudo_dbg_line_column,996 .pseudo_dbg_line_column,
997 .pseudo_dbg_epilogue_begin,997 .pseudo_dbg_epilogue_begin,
998 .pseudo_mv,
999 .pseudo_dead,998 .pseudo_dead,
1000 => false,999 => false,
1001 }) wip_mir_log.debug("{}", .{func.fmtWipMir(result_index)});1000 }) wip_mir_log.debug("{}", .{func.fmtWipMir(result_index)});
...@@ -2445,6 +2444,7 @@ fn genBinOp(...@@ -2445,6 +2444,7 @@ fn genBinOp(
2445 .Vector => {2444 .Vector => {
2446 const mir_tag: Mir.Inst.Tag = switch (tag) {2445 const mir_tag: Mir.Inst.Tag = switch (tag) {
2447 .add => .vaddvv,2446 .add => .vaddvv,
2447 .sub => .vsubvv,
2448 else => return func.fail("TODO: genBinOp {s} Vector", .{@tagName(tag)}),2448 else => return func.fail("TODO: genBinOp {s} Vector", .{@tagName(tag)}),
2449 };2449 };
24502450
...@@ -2454,7 +2454,6 @@ fn genBinOp(...@@ -2454,7 +2454,6 @@ fn genBinOp(
2454 const elem_size = lhs_ty.childType(zcu).bitSize(pt);2454 const elem_size = lhs_ty.childType(zcu).bitSize(pt);
24552455
2456 try func.setVl(.zero, num_elem, .{2456 try func.setVl(.zero, num_elem, .{
2457 .vlmul = .mf2,
2458 .vsew = switch (elem_size) {2457 .vsew = switch (elem_size) {
2459 8 => .@"8",2458 8 => .@"8",
2460 16 => .@"16",2459 16 => .@"16",
...@@ -2462,6 +2461,7 @@ fn genBinOp(...@@ -2462,6 +2461,7 @@ fn genBinOp(
2462 64 => .@"64",2461 64 => .@"64",
2463 else => unreachable,2462 else => unreachable,
2464 },2463 },
2464 .vlmul = .m1,
2465 .vma = true,2465 .vma = true,
2466 .vta = true,2466 .vta = true,
2467 });2467 });
...@@ -2472,8 +2472,8 @@ fn genBinOp(...@@ -2472,8 +2472,8 @@ fn genBinOp(
2472 .data = .{2472 .data = .{
2473 .r_type = .{2473 .r_type = .{
2474 .rd = dst_reg,2474 .rd = dst_reg,
2475 .rs1 = lhs_reg,2475 .rs1 = rhs_reg,
2476 .rs2 = rhs_reg,2476 .rs2 = lhs_reg,
2477 },2477 },
2478 },2478 },
2479 });2479 });
...@@ -3576,20 +3576,54 @@ fn airArrayElemVal(func: *Func, inst: Air.Inst.Index) !void {...@@ -3576,20 +3576,54 @@ fn airArrayElemVal(func: *Func, inst: Air.Inst.Index) !void {
3576 else => try func.genSetReg(Type.usize, addr_reg, array_mcv.address()),3576 else => try func.genSetReg(Type.usize, addr_reg, array_mcv.address()),
3577 }3577 }
35783578
3579 const dst_mcv = try func.allocRegOrMem(result_ty, inst, false);
3580
3581 if (array_ty.isVector(zcu)) {
3582 // we need to load the vector, vslidedown to get the element we want
3583 // and store that element at in a load frame.
3584
3585 const src_reg, const src_lock = try func.allocReg(.vector);
3586 defer func.register_manager.unlockReg(src_lock);
3587
3588 // load the vector into a temporary register
3589 try func.genCopy(array_ty, .{ .register = src_reg }, .{ .indirect = .{ .reg = addr_reg } });
3590
3591 // we need to construct a 1xbitSize vector because of how lane splitting works in RISC-V
3592 const single_ty = try pt.vectorType(.{ .child = elem_ty.toIntern(), .len = 1 });
3593
3594 // we can do a shortcut here where we don't need a vslicedown
3595 // and can just copy to the frame index.
3596 if (!(index_mcv == .immediate and index_mcv.immediate == 0)) {
3597 const index_reg = try func.copyToTmpRegister(Type.usize, index_mcv);
3598
3599 _ = try func.addInst(.{
3600 .tag = .vslidedownvx,
3601 .ops = .rrr,
3602 .data = .{ .r_type = .{
3603 .rd = src_reg,
3604 .rs1 = index_reg,
3605 .rs2 = src_reg,
3606 } },
3607 });
3608 }
3609
3610 try func.genCopy(single_ty, dst_mcv, .{ .register = src_reg });
3611 break :result dst_mcv;
3612 }
3613
3579 const offset_reg = try func.elemOffset(index_ty, index_mcv, elem_abi_size);3614 const offset_reg = try func.elemOffset(index_ty, index_mcv, elem_abi_size);
3580 const offset_lock = func.register_manager.lockRegAssumeUnused(offset_reg);3615 const offset_lock = func.register_manager.lockRegAssumeUnused(offset_reg);
3581 defer func.register_manager.unlockReg(offset_lock);3616 defer func.register_manager.unlockReg(offset_lock);
3582
3583 const dst_mcv = try func.allocRegOrMem(result_ty, inst, false);
3584 _ = try func.addInst(.{3617 _ = try func.addInst(.{
3585 .tag = .add,3618 .tag = .add,
3586 .ops = .rrr,3619 .ops = .rrr,
3587 .data = .{ .r_type = .{3620 .data = .{ .r_type = .{
3588 .rd = addr_reg,3621 .rd = addr_reg,
3589 .rs1 = offset_reg,3622 .rs1 = addr_reg,
3590 .rs2 = addr_reg,3623 .rs2 = offset_reg,
3591 } },3624 } },
3592 });3625 });
3626
3593 try func.genCopy(elem_ty, dst_mcv, .{ .indirect = .{ .reg = addr_reg } });3627 try func.genCopy(elem_ty, dst_mcv, .{ .indirect = .{ .reg = addr_reg } });
3594 break :result dst_mcv;3628 break :result dst_mcv;
3595 };3629 };
...@@ -5965,6 +5999,27 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -5965,6 +5999,27 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
5965 if (src_reg.id() == reg.id())5999 if (src_reg.id() == reg.id())
5966 return;6000 return;
59676001
6002 // there is no instruction for loading the contents of a vector register
6003 // into an integer register, however we can cheat a bit by setting the element
6004 // size to the total size of the vector, and vmv.x.s will work then
6005 if (src_reg.class() == .vector) {
6006 try func.setVl(.zero, 0, .{
6007 .vsew = switch (ty.totalVectorBits(pt)) {
6008 8 => .@"8",
6009 16 => .@"16",
6010 32 => .@"32",
6011 64 => .@"64",
6012 else => |vec_bits| return func.fail("TODO: genSetReg vec -> {s} bits {d}", .{
6013 @tagName(reg.class()),
6014 vec_bits,
6015 }),
6016 },
6017 .vlmul = .m1,
6018 .vta = true,
6019 .vma = true,
6020 });
6021 }
6022
5968 // mv reg, src_reg6023 // mv reg, src_reg
5969 _ = try func.addInst(.{6024 _ = try func.addInst(.{
5970 .tag = .pseudo,6025 .tag = .pseudo,
...@@ -5978,57 +6033,28 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -5978,57 +6033,28 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
5978 .register_pair => return func.fail("genSetReg should we allow reg -> reg_pair?", .{}),6033 .register_pair => return func.fail("genSetReg should we allow reg -> reg_pair?", .{}),
5979 .load_frame => |frame| {6034 .load_frame => |frame| {
5980 if (reg.class() == .vector) {6035 if (reg.class() == .vector) {
5981 if (abi_size > 8)6036 const addr_reg, const addr_lock = try func.allocReg(.int);
5982 return func.fail("TODO: genSetReg vectors > 8", .{});6037 defer func.register_manager.unlockReg(addr_lock);
5983
5984 const temp_reg = try func.register_manager.allocReg(null, abi.Registers.Integer.temporary);
5985 const temp_lock = func.register_manager.lockRegAssumeUnused(temp_reg);
5986 defer func.register_manager.unlockReg(temp_lock);
5987
5988 try func.setVl(.zero, 1, .{
5989 .vsew = switch (abi_size) {
5990 1 => .@"8",
5991 2 => .@"16",
5992 4 => .@"32",
5993 8 => .@"64",
5994 else => unreachable,
5995 },
5996 .vlmul = .m1,
5997 .vma = true,
5998 .vta = true,
5999 });
6000
6001 try func.genCopy(ty, .{ .register = temp_reg }, .{ .load_frame = frame });
60026038
6039 try func.genCopy(ty, .{ .register = addr_reg }, src_mcv.address());
6040 try func.genCopy(ty, .{ .register = reg }, .{ .indirect = .{ .reg = addr_reg } });
6041 } else {
6003 _ = try func.addInst(.{6042 _ = try func.addInst(.{
6004 .tag = .pseudo,6043 .tag = .pseudo,
6005 .ops = .pseudo_mv,6044 .ops = .pseudo_load_rm,
6006 .data = .{6045 .data = .{ .rm = .{
6007 .rr = .{6046 .r = reg,
6008 .rd = reg,6047 .m = .{
6009 .rs = temp_reg,6048 .base = .{ .frame = frame.index },
6049 .mod = .{
6050 .size = func.memSize(ty),
6051 .unsigned = ty.isUnsignedInt(zcu),
6052 .disp = frame.off,
6053 },
6010 },6054 },
6011 },6055 } },
6012 });6056 });
6013
6014 return;
6015 }6057 }
6016
6017 _ = try func.addInst(.{
6018 .tag = .pseudo,
6019 .ops = .pseudo_load_rm,
6020 .data = .{ .rm = .{
6021 .r = reg,
6022 .m = .{
6023 .base = .{ .frame = frame.index },
6024 .mod = .{
6025 .size = func.memSize(ty),
6026 .unsigned = ty.isUnsignedInt(zcu),
6027 .disp = frame.off,
6028 },
6029 },
6030 } },
6031 });
6032 },6058 },
6033 .memory => |addr| {6059 .memory => |addr| {
6034 try func.genSetReg(ty, reg, .{ .immediate = addr });6060 try func.genSetReg(ty, reg, .{ .immediate = addr });
...@@ -6072,20 +6098,64 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -6072,20 +6098,64 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
6072 });6098 });
6073 },6099 },
6074 .indirect => |reg_off| {6100 .indirect => |reg_off| {
6075 const float_class = dst_reg_class == .float;6101 const load_tag: Mir.Inst.Tag = switch (reg.class()) {
6102 .float => switch (abi_size) {
6103 1 => unreachable, // Zig does not support 8-bit floats
6104 2 => return func.fail("TODO: genSetReg indirect 16-bit float", .{}),
6105 4 => .flw,
6106 8 => .fld,
6107 else => return std.debug.panic("TODO: genSetReg for float size {d}", .{abi_size}),
6108 },
6109 .int => switch (abi_size) {
6110 1 => .lb,
6111 2 => .lh,
6112 4 => .lw,
6113 8 => .ld,
6114 else => return std.debug.panic("TODO: genSetReg for int size {d}", .{abi_size}),
6115 },
6116 .vector => {
6117 assert(reg_off.off == 0);
6118
6119 // There is no vector instruction for loading with an offset to a base register,
6120 // so we need to get an offset register containing the address of the vector first
6121 // and load from it.
6122 const len: u5 = math.cast(u5, ty.vectorLen(zcu)) orelse {
6123 return func.fail("TODO: genSetReg load_frame -> vec reg, vector length doesn't fit into imm avl", .{});
6124 };
6125 const elem_ty = ty.childType(zcu);
6126 const elem_size = elem_ty.abiSize(pt);
60766127
6077 const load_tag: Mir.Inst.Tag = switch (abi_size) {6128 try func.setVl(.zero, len, .{
6078 1 => if (float_class)6129 .vsew = switch (elem_size) {
6079 unreachable // Zig does not support 8-bit floats6130 1 => .@"8",
6080 else6131 2 => .@"16",
6081 .lb,6132 4 => .@"32",
6082 2 => if (float_class)6133 8 => .@"64",
6083 return func.fail("TODO: genSetReg indirect 16-bit float", .{})6134 else => unreachable,
6084 else6135 },
6085 .lh,6136 .vlmul = .m1,
6086 4 => if (float_class) .flw else .lw,6137 .vma = true,
6087 8 => if (float_class) .fld else .ld,6138 .vta = true,
6088 else => return std.debug.panic("TODO: genSetReg for size {d}", .{abi_size}),6139 });
6140
6141 _ = try func.addInst(.{
6142 .tag = .pseudo,
6143 .ops = .pseudo_load_rm,
6144 .data = .{ .rm = .{
6145 .r = reg,
6146 .m = .{
6147 .base = .{ .reg = reg_off.reg },
6148 .mod = .{
6149 .size = func.memSize(elem_ty),
6150 .unsigned = false,
6151 .disp = 0,
6152 },
6153 },
6154 } },
6155 });
6156
6157 return;
6158 },
6089 };6159 };
60906160
6091 _ = try func.addInst(.{6161 _ = try func.addInst(.{
...@@ -6100,7 +6170,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!...@@ -6100,7 +6170,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
6100 },6170 },
6101 .lea_symbol => |sym_off| {6171 .lea_symbol => |sym_off| {
6102 assert(sym_off.off == 0);6172 assert(sym_off.off == 0);
6103
6104 const atom_index = try func.symbolIndex();6173 const atom_index = try func.symbolIndex();
61056174
6106 _ = try func.addInst(.{6175 _ = try func.addInst(.{
...@@ -6166,12 +6235,12 @@ fn genSetMem(...@@ -6166,12 +6235,12 @@ fn genSetMem(
6166 => switch (abi_size) {6235 => switch (abi_size) {
6167 0 => {},6236 0 => {},
6168 1, 2, 4, 8 => {6237 1, 2, 4, 8 => {
6169 // no matter what type, it should use an integer register6238 const reg = try func.register_manager.allocReg(null, abi.Registers.Integer.temporary);
6170 const src_reg = try func.copyToTmpRegister(ty, src_mcv);6239 const src_lock = func.register_manager.lockRegAssumeUnused(reg);
6171 const src_lock = func.register_manager.lockRegAssumeUnused(src_reg);
6172 defer func.register_manager.unlockReg(src_lock);6240 defer func.register_manager.unlockReg(src_lock);
61736241
6174 try func.genSetMem(base, disp, ty, .{ .register = src_reg });6242 try func.genSetReg(ty, reg, src_mcv);
6243 try func.genSetMem(base, disp, ty, .{ .register = reg });
6175 },6244 },
6176 else => try func.genInlineMemcpy(6245 else => try func.genInlineMemcpy(
6177 dst_ptr_mcv,6246 dst_ptr_mcv,
...@@ -6180,6 +6249,46 @@ fn genSetMem(...@@ -6180,6 +6249,46 @@ fn genSetMem(
6180 ),6249 ),
6181 },6250 },
6182 .register => |reg| {6251 .register => |reg| {
6252 if (reg.class() == .vector) {
6253 const addr_reg = try func.copyToTmpRegister(Type.usize, dst_ptr_mcv);
6254
6255 const num_elem: u5 = math.cast(u5, ty.vectorLen(pt.zcu)) orelse {
6256 return func.fail("TODO: genBinOp use vsetvli for larger avl sizes", .{});
6257 };
6258 const elem_size = ty.childType(pt.zcu).bitSize(pt);
6259
6260 try func.setVl(.zero, num_elem, .{
6261 .vsew = switch (elem_size) {
6262 8 => .@"8",
6263 16 => .@"16",
6264 32 => .@"32",
6265 64 => .@"64",
6266 else => unreachable,
6267 },
6268 .vlmul = .m1,
6269 .vma = true,
6270 .vta = true,
6271 });
6272
6273 _ = try func.addInst(.{
6274 .tag = .pseudo,
6275 .ops = .pseudo_store_rm,
6276 .data = .{ .rm = .{
6277 .r = reg,
6278 .m = .{
6279 .base = .{ .reg = addr_reg },
6280 .mod = .{
6281 .disp = 0,
6282 .size = func.memSize(ty.childType(pt.zcu)),
6283 .unsigned = false,
6284 },
6285 },
6286 } },
6287 });
6288
6289 return;
6290 }
6291
6183 const mem_size = switch (base) {6292 const mem_size = switch (base) {
6184 .frame => |base_fi| mem_size: {6293 .frame => |base_fi| mem_size: {
6185 assert(disp >= 0);6294 assert(disp >= 0);
src/arch/riscv64/Emit.zig+1-1
...@@ -75,7 +75,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -75,7 +75,7 @@ pub fn emitMir(emit: *Emit) Error!void {
75 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | lo_r_type,75 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | lo_r_type,
76 .r_addend = 0,76 .r_addend = 0,
77 });77 });
78 } else return emit.fail("TODO: load_symbol_reloc non-ELF", .{});78 } else unreachable;
79 },79 },
80 .call_extern_fn_reloc => |symbol| {80 .call_extern_fn_reloc => |symbol| {
81 if (emit.bin_file.cast(link.File.Elf)) |elf_file| {81 if (emit.bin_file.cast(link.File.Elf)) |elf_file| {
src/arch/riscv64/Encoding.zig+52-17
...@@ -116,8 +116,12 @@ const Enc = struct {...@@ -116,8 +116,12 @@ const Enc = struct {
116 };116 };
117117
118 const VecWidth = enum(u3) {118 const VecWidth = enum(u3) {
119 // zig fmt: off
120 @"8" = 0b000,
121 @"16" = 0b101,
119 @"32" = 0b110,122 @"32" = 0b110,
120 @"64" = 0b111,123 @"64" = 0b111,
124 // zig fmt: on
121 };125 };
122126
123 const VecType = enum(u3) {127 const VecType = enum(u3) {
...@@ -266,15 +270,26 @@ pub const Mnemonic = enum {...@@ -266,15 +270,26 @@ pub const Mnemonic = enum {
266 fsgnjxd,270 fsgnjxd,
267271
268 // V Extension272 // V Extension
273 vle8v,
274 vle16v,
269 vle32v,275 vle32v,
270 vle64v,276 vle64v,
271277
278 vse8v,
279 vse16v,
272 vse32v,280 vse32v,
273 vse64v,281 vse64v,
274282
283 vsoxei8v,
284
275 vaddvv,285 vaddvv,
276 vadcxv,286 vsubvv,
277 vadcvx,287
288 vadcvv,
289
290 vmvvx,
291
292 vslidedownvx,
278293
279 // MISC294 // MISC
280 fence,295 fence,
...@@ -431,19 +446,25 @@ pub const Mnemonic = enum {...@@ -431,19 +446,25 @@ pub const Mnemonic = enum {
431 // LOAD_FP446 // LOAD_FP
432447
433 .flw => .{ .opcode = .LOAD_FP, .data = .{ .f = .{ .funct3 = 0b010 } } },448 .flw => .{ .opcode = .LOAD_FP, .data = .{ .f = .{ .funct3 = 0b010 } } },
434 .fld => .{ .opcode = .LOAD_FP, .data = .{ .f = .{ .funct3 = 0b011 } } },449 .fld => .{ .opcode = .LOAD_FP, .data = .{ .f = .{ .funct3 = 0b011 } } },
435450
436 .vle32v => .{ .opcode = .LOAD_FP, .data = .{ .vecls = .{ .width = .@"32", .umop = .unit, .vm = true, .mop = .unit, .mew = true, .nf = 0b000 } } },451 .vle8v => .{ .opcode = .LOAD_FP, .data = .{ .vecls = .{ .width = .@"8", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } },
437 .vle64v => .{ .opcode = .LOAD_FP, .data = .{ .vecls = .{ .width = .@"64", .umop = .unit, .vm = true, .mop = .unit, .mew = true, .nf = 0b000 } } },452 .vle16v => .{ .opcode = .LOAD_FP, .data = .{ .vecls = .{ .width = .@"16", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } },
453 .vle32v => .{ .opcode = .LOAD_FP, .data = .{ .vecls = .{ .width = .@"32", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } },
454 .vle64v => .{ .opcode = .LOAD_FP, .data = .{ .vecls = .{ .width = .@"64", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } },
438 455
439456
440 // STORE_FP457 // STORE_FP
441458
442 .fsw => .{ .opcode = .STORE_FP, .data = .{ .f = .{ .funct3 = 0b010 } } },459 .fsw => .{ .opcode = .STORE_FP, .data = .{ .f = .{ .funct3 = 0b010 } } },
443 .fsd => .{ .opcode = .STORE_FP, .data = .{ .f = .{ .funct3 = 0b011 } } },460 .fsd => .{ .opcode = .STORE_FP, .data = .{ .f = .{ .funct3 = 0b011 } } },
461
462 .vse8v => .{ .opcode = .STORE_FP, .data = .{ .vecls = .{ .width = .@"8", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } },
463 .vse16v => .{ .opcode = .STORE_FP, .data = .{ .vecls = .{ .width = .@"16", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } },
464 .vse32v => .{ .opcode = .STORE_FP, .data = .{ .vecls = .{ .width = .@"32", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } },
465 .vse64v => .{ .opcode = .STORE_FP, .data = .{ .vecls = .{ .width = .@"64", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .nf = 0b000 } } },
444466
445 .vse32v => .{ .opcode = .STORE_FP, .data = .{ .vecls = .{ .width = .@"32", .umop = .unit, .vm = true, .mop = .unit, .mew = true, .nf = 0b000 } } },467 .vsoxei8v => .{ .opcode = .STORE_FP, .data = .{ .vecls = .{ .width = .@"8", .umop = .unit, .vm = true, .mop = .ord, .mew = false, .nf = 0b000 } } },
446 .vse64v => .{ .opcode = .STORE_FP, .data = .{ .vecls = .{ .width = .@"64", .umop = .unit, .vm = true, .mop = .unit, .mew = true, .nf = 0b000 } } },
447468
448 // JALR469 // JALR
449470
...@@ -516,11 +537,15 @@ pub const Mnemonic = enum {...@@ -516,11 +537,15 @@ pub const Mnemonic = enum {
516 .amomaxud => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .D, .funct5 = 0b11100 } } },537 .amomaxud => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .D, .funct5 = 0b11100 } } },
517538
518 // OP_V539 // OP_V
519 .vsetivli => .{ .opcode = .OP_V, .data = .{ .f = .{ .funct3 = 0b111 } } },540 .vsetivli => .{ .opcode = .OP_V, .data = .{ .f = .{ .funct3 = 0b111 } } },
520 .vsetvli => .{ .opcode = .OP_V, .data = .{ .f = .{ .funct3 = 0b111 } } },541 .vsetvli => .{ .opcode = .OP_V, .data = .{ .f = .{ .funct3 = 0b111 } } },
521 .vaddvv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b000000, .funct3 = .OPIVV } } },542 .vaddvv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b000000, .funct3 = .OPIVV } } },
522 .vadcxv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b010000, .funct3 = .OPMVX } } },543 .vsubvv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b000010, .funct3 = .OPIVV } } },
523 .vadcvx => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b010000, .funct3 = .OPMVV } } },544
545 .vadcvv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b010000, .funct3 = .OPMVV } } },
546 .vmvvx => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b010111, .funct3 = .OPIVX } } },
547
548 .vslidedownvx => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b001111, .funct3 = .OPIVX } } },
524 549
525 // zig fmt: on550 // zig fmt: on
526 };551 };
...@@ -663,13 +688,23 @@ pub const InstEnc = enum {...@@ -663,13 +688,23 @@ pub const InstEnc = enum {
663 .fsgnjxs,688 .fsgnjxs,
664 .fsgnjxd,689 .fsgnjxd,
665690
691 .vle8v,
692 .vle16v,
666 .vle32v,693 .vle32v,
667 .vle64v,694 .vle64v,
695
696 .vse8v,
697 .vse16v,
668 .vse32v,698 .vse32v,
669 .vse64v,699 .vse64v,
700
701 .vsoxei8v,
702
670 .vaddvv,703 .vaddvv,
671 .vadcxv,704 .vsubvv,
672 .vadcvx,705 .vadcvv,
706 .vmvvx,
707 .vslidedownvx,
673 => .R,708 => .R,
674709
675 .ecall,710 .ecall,
src/arch/riscv64/Lower.zig+13-19
...@@ -98,12 +98,8 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index, options: struct {...@@ -98,12 +98,8 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index, options: struct {
98 .dword => .fld,98 .dword => .fld,
99 },99 },
100 .vector => switch (src_size) {100 .vector => switch (src_size) {
101 .byte,101 .byte => .vle8v,
102 .hword,102 .hword => .vle32v,
103 => return lower.fail(
104 "TODO: lowerMir pseudo_load_rm support {s} vector",
105 .{@tagName(src_size)},
106 ),
107 .word => .vle32v,103 .word => .vle32v,
108 .dword => .vle64v,104 .dword => .vle64v,
109 },105 },
...@@ -118,10 +114,11 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index, options: struct {...@@ -118,10 +114,11 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index, options: struct {
118 });114 });
119 },115 },
120 .vector => {116 .vector => {
117 assert(frame_loc.disp == 0);
121 try lower.emit(tag, &.{118 try lower.emit(tag, &.{
122 .{ .reg = rm.r },119 .{ .reg = rm.r },
123 .{ .reg = frame_loc.base },120 .{ .reg = frame_loc.base },
124 .{ .reg = .x0 },121 .{ .reg = .zero },
125 });122 });
126 },123 },
127 }124 }
...@@ -146,12 +143,8 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index, options: struct {...@@ -146,12 +143,8 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index, options: struct {
146 .dword => .fsd,143 .dword => .fsd,
147 },144 },
148 .vector => switch (dest_size) {145 .vector => switch (dest_size) {
149 .byte,146 .byte => .vse8v,
150 .hword,147 .hword => .vse16v,
151 => return lower.fail(
152 "TODO: lowerMir pseudo_load_rm support {s} vector",
153 .{@tagName(dest_size)},
154 ),
155 .word => .vse32v,148 .word => .vse32v,
156 .dword => .vse64v,149 .dword => .vse64v,
157 },150 },
...@@ -166,10 +159,11 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index, options: struct {...@@ -166,10 +159,11 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index, options: struct {
166 });159 });
167 },160 },
168 .vector => {161 .vector => {
162 assert(frame_loc.disp == 0);
169 try lower.emit(tag, &.{163 try lower.emit(tag, &.{
170 .{ .reg = frame_loc.base },
171 .{ .reg = rm.r },164 .{ .reg = rm.r },
172 .{ .reg = .x0 },165 .{ .reg = frame_loc.base },
166 .{ .reg = .zero },
173 });167 });
174 },168 },
175 }169 }
...@@ -204,20 +198,20 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index, options: struct {...@@ -204,20 +198,20 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index, options: struct {
204 });198 });
205 },199 },
206 .vector => {200 .vector => {
207 try lower.emit(.vadcxv, &.{201 try lower.emit(.vmvvx, &.{
208 .{ .reg = rr.rd },202 .{ .reg = rr.rd },
209 .{ .reg = rr.rs },203 .{ .reg = rr.rs },
210 .{ .reg = .zero },204 .{ .reg = .x0 },
211 });205 });
212 },206 },
213 .float => return lower.fail("TODO: lowerMir pseudo_mv int -> {s}", .{@tagName(dst_class)}),207 .float => return lower.fail("TODO: lowerMir pseudo_mv int -> {s}", .{@tagName(dst_class)}),
214 },208 },
215 .vector => switch (dst_class) {209 .vector => switch (dst_class) {
216 .int => {210 .int => {
217 try lower.emit(.vadcvx, &.{211 try lower.emit(.vadcvv, &.{
218 .{ .reg = rr.rd },212 .{ .reg = rr.rd },
219 .{ .reg = rr.rs },
220 .{ .reg = .zero },213 .{ .reg = .zero },
214 .{ .reg = rr.rs },
221 });215 });
222 },216 },
223 .float, .vector => return lower.fail("TODO: lowerMir pseudo_mv vector -> {s}", .{@tagName(dst_class)}),217 .float, .vector => return lower.fail("TODO: lowerMir pseudo_mv vector -> {s}", .{@tagName(dst_class)}),
src/arch/riscv64/Mir.zig+2
...@@ -142,6 +142,8 @@ pub const Inst = struct {...@@ -142,6 +142,8 @@ pub const Inst = struct {
142 vsetivli,142 vsetivli,
143 vsetvl,143 vsetvl,
144 vaddvv,144 vaddvv,
145 vsubvv,
146 vslidedownvx,
145147
146 // A Extension Instructions148 // A Extension Instructions
147 amo,149 amo,