authorgravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-07-21 01:36:26-07:00
committergravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-07-26 04:05:43-07:00
log64c6473443722c933ece642b0c2cfbd74b2638bd
tree251a9acb71da4312882ac5591316423d6b45c5ed
parent45443f9c37101da1721ccbef5a29b7536f7db3a5
signature Commit is signed but in an unrecognized format.

riscv: implement `add_sat` and `ptr_slice_len_ptr`

this is enough to use the basic functions of an ArrayList!

1 files changed, 115 insertions(+), 13 deletions(-)

src/arch/riscv64/CodeGen.zig+115-13
......@@ -1321,6 +1321,8 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
13211321 .sub,
13221322 .sub_wrap,
13231323
1324 .add_sat,
1325
13241326 .mul,
13251327 .mul_wrap,
13261328 .div_trunc,
......@@ -1372,7 +1374,6 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
13721374 .shl_with_overflow => try func.airShlWithOverflow(inst),
13731375
13741376
1375 .add_sat => try func.airAddSat(inst),
13761377 .sub_sat => try func.airSubSat(inst),
13771378 .mul_sat => try func.airMulSat(inst),
13781379 .shl_sat => try func.airShlSat(inst),
......@@ -1578,7 +1579,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
15781579 for (tracking.getRegs()) |reg| {
15791580 if (RegisterManager.indexOfRegIntoTracked(reg).? == index) break;
15801581 } else return std.debug.panic(
1581 \\%{} takes up these regs: {any}, however these regs {any}, don't use it
1582 \\%{} takes up these regs: {any}, however this regs {any}, don't use it
15821583 , .{ tracked_inst, tracking.getRegs(), RegisterManager.regAtTrackedIndex(@intCast(index)) });
15831584 }
15841585 }
......@@ -2532,6 +2533,57 @@ fn genBinOp(
25322533 }
25332534 },
25342535
2536 .add_sat,
2537 => {
2538 if (bit_size != 64 or !is_unsigned)
2539 return func.fail("TODO: genBinOp ty: {}", .{lhs_ty.fmt(pt)});
2540
2541 const tmp_reg = try func.copyToTmpRegister(rhs_ty, .{ .register = rhs_reg });
2542 const tmp_lock = func.register_manager.lockRegAssumeUnused(tmp_reg);
2543 defer func.register_manager.unlockReg(tmp_lock);
2544
2545 _ = try func.addInst(.{
2546 .tag = .add,
2547 .ops = .rrr,
2548 .data = .{ .r_type = .{
2549 .rd = tmp_reg,
2550 .rs1 = rhs_reg,
2551 .rs2 = lhs_reg,
2552 } },
2553 });
2554
2555 _ = try func.addInst(.{
2556 .tag = .sltu,
2557 .ops = .rrr,
2558 .data = .{ .r_type = .{
2559 .rd = dst_reg,
2560 .rs1 = tmp_reg,
2561 .rs2 = lhs_reg,
2562 } },
2563 });
2564
2565 // neg dst_reg, dst_reg
2566 _ = try func.addInst(.{
2567 .tag = .sub,
2568 .ops = .rrr,
2569 .data = .{ .r_type = .{
2570 .rd = dst_reg,
2571 .rs1 = .zero,
2572 .rs2 = dst_reg,
2573 } },
2574 });
2575
2576 _ = try func.addInst(.{
2577 .tag = .@"or",
2578 .ops = .rrr,
2579 .data = .{ .r_type = .{
2580 .rd = dst_reg,
2581 .rs1 = dst_reg,
2582 .rs2 = tmp_reg,
2583 } },
2584 });
2585 },
2586
25352587 .ptr_add,
25362588 .ptr_sub,
25372589 => {
......@@ -3096,12 +3148,6 @@ fn airShlWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
30963148 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
30973149}
30983150
3099fn airAddSat(func: *Func, inst: Air.Inst.Index) !void {
3100 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
3101 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airAddSat", .{});
3102 return func.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
3103}
3104
31053151fn airSubSat(func: *Func, inst: Air.Inst.Index) !void {
31063152 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
31073153 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement airSubSat", .{});
......@@ -3495,7 +3541,16 @@ fn airSliceLen(func: *Func, inst: Air.Inst.Index) !void {
34953541
34963542fn airPtrSliceLenPtr(func: *Func, inst: Air.Inst.Index) !void {
34973543 const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3498 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement ptr_slice_len_ptr for {}", .{func.target.cpu.arch});
3544 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
3545 const src_mcv = try func.resolveInst(ty_op.operand);
3546
3547 const dst_reg, const dst_lock = try func.allocReg(.int);
3548 defer func.register_manager.unlockReg(dst_lock);
3549 const dst_mcv: MCValue = .{ .register = dst_reg };
3550
3551 try func.genCopy(Type.u64, dst_mcv, src_mcv.offset(8));
3552 break :result dst_mcv;
3553 };
34993554 return func.finishAir(inst, result, .{ ty_op.operand, .none, .none });
35003555}
35013556
......@@ -5838,6 +5893,17 @@ fn genInlineMemcpy(
58385893 try func.genSetReg(Type.usize, src, src_ptr);
58395894 try func.genSetReg(Type.usize, dst, dst_ptr);
58405895
5896 // if count is 0, there's nothing to copy
5897 _ = try func.addInst(.{
5898 .tag = .beq,
5899 .ops = .rr_inst,
5900 .data = .{ .b_type = .{
5901 .rs1 = count,
5902 .rs2 = .zero,
5903 .inst = @intCast(func.mir_instructions.len + 9),
5904 } },
5905 });
5906
58415907 // lb tmp, 0(src)
58425908 const first_inst = try func.addInst(.{
58435909 .tag = .lb,
......@@ -6145,7 +6211,9 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
61456211 } },
61466212 });
61476213 },
6148 .register_pair => return func.fail("genSetReg should we allow reg -> reg_pair?", .{}),
6214 // useful in cases like slice_ptr, which can easily reuse the operand
6215 // but we need to get only the pointer out.
6216 .register_pair => |pair| try func.genSetReg(ty, reg, .{ .register = pair[0] }),
61496217 .load_frame => |frame| {
61506218 if (reg.class() == .vector) {
61516219 // vectors don't support an offset memory load so we need to put the true
......@@ -6507,7 +6575,7 @@ fn airBitCast(func: *Func, inst: Air.Inst.Index) !void {
65076575 const src_lock = if (src_mcv.getReg()) |reg| func.register_manager.lockReg(reg) else null;
65086576 defer if (src_lock) |lock| func.register_manager.unlockReg(lock);
65096577
6510 const dst_mcv = if (dst_ty.abiSize(pt) <= src_ty.abiSize(pt) and
6578 const dst_mcv = if (dst_ty.abiSize(pt) <= src_ty.abiSize(pt) and src_mcv != .register_pair and
65116579 func.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: {
65126580 const dst_mcv = try func.allocRegOrMem(dst_ty, inst, true);
65136581 try func.genCopy(switch (math.order(dst_ty.abiSize(pt), src_ty.abiSize(pt))) {
......@@ -6827,8 +6895,42 @@ fn airMemset(func: *Func, inst: Air.Inst.Index, safety: bool) !void {
68276895}
68286896
68296897fn airMemcpy(func: *Func, inst: Air.Inst.Index) !void {
6830 _ = inst;
6831 return func.fail("TODO implement airMemcpy for {}", .{func.target.cpu.arch});
6898 const pt = func.pt;
6899 const zcu = pt.zcu;
6900 const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
6901
6902 const dst_ptr = try func.resolveInst(bin_op.lhs);
6903 const src_ptr = try func.resolveInst(bin_op.rhs);
6904
6905 const dst_ty = func.typeOf(bin_op.lhs);
6906
6907 const len_mcv: MCValue = switch (dst_ty.ptrSize(zcu)) {
6908 .Slice => len: {
6909 const len_reg, const len_lock = try func.allocReg(.int);
6910 defer func.register_manager.unlockReg(len_lock);
6911
6912 const elem_size = dst_ty.childType(zcu).abiSize(pt);
6913 try func.genBinOp(
6914 .mul,
6915 .{ .immediate = elem_size },
6916 Type.u64,
6917 dst_ptr.address().offset(8).deref(),
6918 Type.u64,
6919 len_reg,
6920 );
6921 break :len .{ .register = len_reg };
6922 },
6923 else => |size| return func.fail("TODO: airMemcpy size {s}", .{@tagName(size)}),
6924 };
6925 const len_lock: ?RegisterLock = switch (len_mcv) {
6926 .register => |reg| func.register_manager.lockRegAssumeUnused(reg),
6927 else => null,
6928 };
6929 defer if (len_lock) |lock| func.register_manager.unlockReg(lock);
6930
6931 try func.genInlineMemcpy(dst_ptr, src_ptr, len_mcv);
6932
6933 return func.finishAir(inst, .unreach, .{ bin_op.lhs, bin_op.rhs, .none });
68326934}
68336935
68346936fn airTagName(func: *Func, inst: Air.Inst.Index) !void {