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 {
995995 .pseudo_dbg_prologue_end,
996996 .pseudo_dbg_line_column,
997997 .pseudo_dbg_epilogue_begin,
998 .pseudo_mv,
999998 .pseudo_dead,
1000999 => false,
10011000 }) wip_mir_log.debug("{}", .{func.fmtWipMir(result_index)});
......@@ -2445,6 +2444,7 @@ fn genBinOp(
24452444 .Vector => {
24462445 const mir_tag: Mir.Inst.Tag = switch (tag) {
24472446 .add => .vaddvv,
2447 .sub => .vsubvv,
24482448 else => return func.fail("TODO: genBinOp {s} Vector", .{@tagName(tag)}),
24492449 };
24502450
......@@ -2454,7 +2454,6 @@ fn genBinOp(
24542454 const elem_size = lhs_ty.childType(zcu).bitSize(pt);
24552455
24562456 try func.setVl(.zero, num_elem, .{
2457 .vlmul = .mf2,
24582457 .vsew = switch (elem_size) {
24592458 8 => .@"8",
24602459 16 => .@"16",
......@@ -2462,6 +2461,7 @@ fn genBinOp(
24622461 64 => .@"64",
24632462 else => unreachable,
24642463 },
2464 .vlmul = .m1,
24652465 .vma = true,
24662466 .vta = true,
24672467 });
......@@ -2472,8 +2472,8 @@ fn genBinOp(
24722472 .data = .{
24732473 .r_type = .{
24742474 .rd = dst_reg,
2475 .rs1 = lhs_reg,
2476 .rs2 = rhs_reg,
2475 .rs1 = rhs_reg,
2476 .rs2 = lhs_reg,
24772477 },
24782478 },
24792479 });
......@@ -3576,20 +3576,54 @@ fn airArrayElemVal(func: *Func, inst: Air.Inst.Index) !void {
35763576 else => try func.genSetReg(Type.usize, addr_reg, array_mcv.address()),
35773577 }
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
35793614 const offset_reg = try func.elemOffset(index_ty, index_mcv, elem_abi_size);
35803615 const offset_lock = func.register_manager.lockRegAssumeUnused(offset_reg);
35813616 defer func.register_manager.unlockReg(offset_lock);
3582
3583 const dst_mcv = try func.allocRegOrMem(result_ty, inst, false);
35843617 _ = try func.addInst(.{
35853618 .tag = .add,
35863619 .ops = .rrr,
35873620 .data = .{ .r_type = .{
35883621 .rd = addr_reg,
3589 .rs1 = offset_reg,
3590 .rs2 = addr_reg,
3622 .rs1 = addr_reg,
3623 .rs2 = offset_reg,
35913624 } },
35923625 });
3626
35933627 try func.genCopy(elem_ty, dst_mcv, .{ .indirect = .{ .reg = addr_reg } });
35943628 break :result dst_mcv;
35953629 };
......@@ -5965,6 +5999,27 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
59655999 if (src_reg.id() == reg.id())
59666000 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
59686023 // mv reg, src_reg
59696024 _ = try func.addInst(.{
59706025 .tag = .pseudo,
......@@ -5978,57 +6033,28 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
59786033 .register_pair => return func.fail("genSetReg should we allow reg -> reg_pair?", .{}),
59796034 .load_frame => |frame| {
59806035 if (reg.class() == .vector) {
5981 if (abi_size > 8)
5982 return func.fail("TODO: genSetReg vectors > 8", .{});
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 });
6036 const addr_reg, const addr_lock = try func.allocReg(.int);
6037 defer func.register_manager.unlockReg(addr_lock);
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 {
60036042 _ = try func.addInst(.{
60046043 .tag = .pseudo,
6005 .ops = .pseudo_mv,
6006 .data = .{
6007 .rr = .{
6008 .rd = reg,
6009 .rs = temp_reg,
6044 .ops = .pseudo_load_rm,
6045 .data = .{ .rm = .{
6046 .r = reg,
6047 .m = .{
6048 .base = .{ .frame = frame.index },
6049 .mod = .{
6050 .size = func.memSize(ty),
6051 .unsigned = ty.isUnsignedInt(zcu),
6052 .disp = frame.off,
6053 },
60106054 },
6011 },
6055 } },
60126056 });
6013
6014 return;
60156057 }
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 });
60326058 },
60336059 .memory => |addr| {
60346060 try func.genSetReg(ty, reg, .{ .immediate = addr });
......@@ -6072,20 +6098,64 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
60726098 });
60736099 },
60746100 .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) {
6078 1 => if (float_class)
6079 unreachable // Zig does not support 8-bit floats
6080 else
6081 .lb,
6082 2 => if (float_class)
6083 return func.fail("TODO: genSetReg indirect 16-bit float", .{})
6084 else
6085 .lh,
6086 4 => if (float_class) .flw else .lw,
6087 8 => if (float_class) .fld else .ld,
6088 else => return std.debug.panic("TODO: genSetReg for size {d}", .{abi_size}),
6128 try func.setVl(.zero, len, .{
6129 .vsew = switch (elem_size) {
6130 1 => .@"8",
6131 2 => .@"16",
6132 4 => .@"32",
6133 8 => .@"64",
6134 else => unreachable,
6135 },
6136 .vlmul = .m1,
6137 .vma = true,
6138 .vta = true,
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 },
60896159 };
60906160
60916161 _ = try func.addInst(.{
......@@ -6100,7 +6170,6 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
61006170 },
61016171 .lea_symbol => |sym_off| {
61026172 assert(sym_off.off == 0);
6103
61046173 const atom_index = try func.symbolIndex();
61056174
61066175 _ = try func.addInst(.{
......@@ -6166,12 +6235,12 @@ fn genSetMem(
61666235 => switch (abi_size) {
61676236 0 => {},
61686237 1, 2, 4, 8 => {
6169 // no matter what type, it should use an integer register
6170 const src_reg = try func.copyToTmpRegister(ty, src_mcv);
6171 const src_lock = func.register_manager.lockRegAssumeUnused(src_reg);
6238 const reg = try func.register_manager.allocReg(null, abi.Registers.Integer.temporary);
6239 const src_lock = func.register_manager.lockRegAssumeUnused(reg);
61726240 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 });
61756244 },
61766245 else => try func.genInlineMemcpy(
61776246 dst_ptr_mcv,
......@@ -6180,6 +6249,46 @@ fn genSetMem(
61806249 ),
61816250 },
61826251 .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
61836292 const mem_size = switch (base) {
61846293 .frame => |base_fi| mem_size: {
61856294 assert(disp >= 0);
src/arch/riscv64/Emit.zig+1-1
......@@ -75,7 +75,7 @@ pub fn emitMir(emit: *Emit) Error!void {
7575 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | lo_r_type,
7676 .r_addend = 0,
7777 });
78 } else return emit.fail("TODO: load_symbol_reloc non-ELF", .{});
78 } else unreachable;
7979 },
8080 .call_extern_fn_reloc => |symbol| {
8181 if (emit.bin_file.cast(link.File.Elf)) |elf_file| {
src/arch/riscv64/Encoding.zig+52-17
......@@ -116,8 +116,12 @@ const Enc = struct {
116116 };
117117
118118 const VecWidth = enum(u3) {
119 // zig fmt: off
120 @"8" = 0b000,
121 @"16" = 0b101,
119122 @"32" = 0b110,
120123 @"64" = 0b111,
124 // zig fmt: on
121125 };
122126
123127 const VecType = enum(u3) {
......@@ -266,15 +270,26 @@ pub const Mnemonic = enum {
266270 fsgnjxd,
267271
268272 // V Extension
273 vle8v,
274 vle16v,
269275 vle32v,
270276 vle64v,
271277
278 vse8v,
279 vse16v,
272280 vse32v,
273281 vse64v,
274282
283 vsoxei8v,
284
275285 vaddvv,
276 vadcxv,
277 vadcvx,
286 vsubvv,
287
288 vadcvv,
289
290 vmvvx,
291
292 vslidedownvx,
278293
279294 // MISC
280295 fence,
......@@ -431,19 +446,25 @@ pub const Mnemonic = enum {
431446 // LOAD_FP
432447
433448 .flw => .{ .opcode = .LOAD_FP, .data = .{ .f = .{ .funct3 = 0b010 } } },
434 .fld => .{ .opcode = .LOAD_FP, .data = .{ .f = .{ .funct3 = 0b011 } } },
435
436 .vle32v => .{ .opcode = .LOAD_FP, .data = .{ .vecls = .{ .width = .@"32", .umop = .unit, .vm = true, .mop = .unit, .mew = true, .nf = 0b000 } } },
437 .vle64v => .{ .opcode = .LOAD_FP, .data = .{ .vecls = .{ .width = .@"64", .umop = .unit, .vm = true, .mop = .unit, .mew = true, .nf = 0b000 } } },
449 .fld => .{ .opcode = .LOAD_FP, .data = .{ .f = .{ .funct3 = 0b011 } } },
450
451 .vle8v => .{ .opcode = .LOAD_FP, .data = .{ .vecls = .{ .width = .@"8", .umop = .unit, .vm = true, .mop = .unit, .mew = false, .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 } } },
438455
439456
440457 // STORE_FP
441458
442 .fsw => .{ .opcode = .STORE_FP, .data = .{ .f = .{ .funct3 = 0b010 } } },
443 .fsd => .{ .opcode = .STORE_FP, .data = .{ .f = .{ .funct3 = 0b011 } } },
459 .fsw => .{ .opcode = .STORE_FP, .data = .{ .f = .{ .funct3 = 0b010 } } },
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 } } },
446 .vse64v => .{ .opcode = .STORE_FP, .data = .{ .vecls = .{ .width = .@"64", .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 } } },
447468
448469 // JALR
449470
......@@ -516,11 +537,15 @@ pub const Mnemonic = enum {
516537 .amomaxud => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .D, .funct5 = 0b11100 } } },
517538
518539 // OP_V
519 .vsetivli => .{ .opcode = .OP_V, .data = .{ .f = .{ .funct3 = 0b111 } } },
520 .vsetvli => .{ .opcode = .OP_V, .data = .{ .f = .{ .funct3 = 0b111 } } },
521 .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 } } },
523 .vadcvx => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b010000, .funct3 = .OPMVV } } },
540 .vsetivli => .{ .opcode = .OP_V, .data = .{ .f = .{ .funct3 = 0b111 } } },
541 .vsetvli => .{ .opcode = .OP_V, .data = .{ .f = .{ .funct3 = 0b111 } } },
542 .vaddvv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b000000, .funct3 = .OPIVV } } },
543 .vsubvv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b000010, .funct3 = .OPIVV } } },
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 } } },
524549
525550 // zig fmt: on
526551 };
......@@ -663,13 +688,23 @@ pub const InstEnc = enum {
663688 .fsgnjxs,
664689 .fsgnjxd,
665690
691 .vle8v,
692 .vle16v,
666693 .vle32v,
667694 .vle64v,
695
696 .vse8v,
697 .vse16v,
668698 .vse32v,
669699 .vse64v,
700
701 .vsoxei8v,
702
670703 .vaddvv,
671 .vadcxv,
672 .vadcvx,
704 .vsubvv,
705 .vadcvv,
706 .vmvvx,
707 .vslidedownvx,
673708 => .R,
674709
675710 .ecall,
src/arch/riscv64/Lower.zig+13-19
......@@ -98,12 +98,8 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index, options: struct {
9898 .dword => .fld,
9999 },
100100 .vector => switch (src_size) {
101 .byte,
102 .hword,
103 => return lower.fail(
104 "TODO: lowerMir pseudo_load_rm support {s} vector",
105 .{@tagName(src_size)},
106 ),
101 .byte => .vle8v,
102 .hword => .vle32v,
107103 .word => .vle32v,
108104 .dword => .vle64v,
109105 },
......@@ -118,10 +114,11 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index, options: struct {
118114 });
119115 },
120116 .vector => {
117 assert(frame_loc.disp == 0);
121118 try lower.emit(tag, &.{
122119 .{ .reg = rm.r },
123120 .{ .reg = frame_loc.base },
124 .{ .reg = .x0 },
121 .{ .reg = .zero },
125122 });
126123 },
127124 }
......@@ -146,12 +143,8 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index, options: struct {
146143 .dword => .fsd,
147144 },
148145 .vector => switch (dest_size) {
149 .byte,
150 .hword,
151 => return lower.fail(
152 "TODO: lowerMir pseudo_load_rm support {s} vector",
153 .{@tagName(dest_size)},
154 ),
146 .byte => .vse8v,
147 .hword => .vse16v,
155148 .word => .vse32v,
156149 .dword => .vse64v,
157150 },
......@@ -166,10 +159,11 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index, options: struct {
166159 });
167160 },
168161 .vector => {
162 assert(frame_loc.disp == 0);
169163 try lower.emit(tag, &.{
170 .{ .reg = frame_loc.base },
171164 .{ .reg = rm.r },
172 .{ .reg = .x0 },
165 .{ .reg = frame_loc.base },
166 .{ .reg = .zero },
173167 });
174168 },
175169 }
......@@ -204,20 +198,20 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index, options: struct {
204198 });
205199 },
206200 .vector => {
207 try lower.emit(.vadcxv, &.{
201 try lower.emit(.vmvvx, &.{
208202 .{ .reg = rr.rd },
209203 .{ .reg = rr.rs },
210 .{ .reg = .zero },
204 .{ .reg = .x0 },
211205 });
212206 },
213207 .float => return lower.fail("TODO: lowerMir pseudo_mv int -> {s}", .{@tagName(dst_class)}),
214208 },
215209 .vector => switch (dst_class) {
216210 .int => {
217 try lower.emit(.vadcvx, &.{
211 try lower.emit(.vadcvv, &.{
218212 .{ .reg = rr.rd },
219 .{ .reg = rr.rs },
220213 .{ .reg = .zero },
214 .{ .reg = rr.rs },
221215 });
222216 },
223217 .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 {
142142 vsetivli,
143143 vsetvl,
144144 vaddvv,
145 vsubvv,
146 vslidedownvx,
145147
146148 // A Extension Instructions
147149 amo,