authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2021-12-29 15:23:04+01:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2021-12-30 14:24:03+01:00
logac7fa95af471304c270a4ae1da4fe074610854d1
tree6ae1867eb424b44f193d13b649a1b1914f3fc429
parentbaec07cfcd11ab51b3cec1fde66db1a084d7a97f
signaturelock-open Commit is signed but in an unrecognized format.

stage2 ARM: add genArmInlineMemcpy for copying types with size > 4


1 files changed, 178 insertions(+), 5 deletions(-)

src/arch/arm/CodeGen.zig+178-5
......@@ -1261,7 +1261,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
12611261 break :result MCValue{ .register = dst_reg };
12621262 } else {
12631263 const dst_mcv = try self.allocRegOrMem(inst, false);
1264 const addr_reg = try self.register_manager.allocReg(inst, &.{ base_mcv.register, offset_mcv.register });
1264 const addr_reg = try self.register_manager.allocReg(null, &.{ base_mcv.register, offset_mcv.register });
12651265
12661266 try self.genArmBinOpCode(addr_reg, base_mcv, offset_mcv, false, .add, .unsigned);
12671267 try self.load(dst_mcv, .{ .register = addr_reg }, slice_ptr_field_type);
......@@ -1401,7 +1401,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
14011401 },
14021402 .stack_offset => |off| {
14031403 if (elem_ty.abiSize(self.target.*) <= 4) {
1404 const tmp_reg = try self.register_manager.allocReg(null, &.{});
1404 const tmp_reg = try self.register_manager.allocReg(null, &.{reg});
14051405 try self.load(.{ .register = tmp_reg }, ptr, ptr_ty);
14061406 try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg });
14071407 } else if (elem_ty.abiSize(self.target.*) == 8) {
......@@ -1412,7 +1412,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
14121412 // larger
14131413
14141414 const usize_ty = Type.initTag(.usize);
1415 const tmp_regs = try self.register_manager.allocRegs(2, .{ null, null }, &.{});
1415 const tmp_regs = try self.register_manager.allocRegs(2, .{ null, null }, &.{reg});
14161416 _ = try self.addInst(.{
14171417 .tag = .ldr,
14181418 .cond = .al,
......@@ -1434,7 +1434,46 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
14341434 try self.genSetStack(usize_ty, off, MCValue{ .register = tmp_regs[0] });
14351435 try self.genSetStack(usize_ty, off + 4, MCValue{ .register = tmp_regs[1] });
14361436 } else {
1437 return self.fail("TODO implement memcpy", .{});
1437 // TODO optimize the register allocation
1438 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null }, &.{reg});
1439 const src_reg = reg;
1440 const dst_reg = regs[0];
1441 const len_reg = regs[1];
1442 const count_reg = regs[2];
1443 const tmp_reg = regs[3];
1444
1445 // sub dst_reg, fp, #off
1446 const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*));
1447 const adj_off = off + elem_size;
1448 const offset_op: Instruction.Operand = if (Instruction.Operand.fromU32(adj_off)) |x| x else {
1449 return self.fail("TODO load: set reg to stack offset with all possible offsets", .{});
1450 };
1451 _ = try self.addInst(.{
1452 .tag = .sub,
1453 .cond = .al,
1454 .data = .{ .rr_op = .{
1455 .rd = dst_reg,
1456 .rn = .fp,
1457 .op = offset_op,
1458 } },
1459 });
1460
1461 // mov len, #elem_size
1462 const len_op: Instruction.Operand = if (Instruction.Operand.fromU32(elem_size)) |x| x else {
1463 return self.fail("TODO load: set reg to elem_size with all possible sizes", .{});
1464 };
1465 _ = try self.addInst(.{
1466 .tag = .mov,
1467 .cond = .al,
1468 .data = .{ .rr_op = .{
1469 .rd = len_reg,
1470 .rn = .r0,
1471 .op = len_op,
1472 } },
1473 });
1474
1475 // memcpy(src, dst, len)
1476 try self.genArmInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg);
14381477 }
14391478 },
14401479 else => return self.fail("TODO load from register into {}", .{dst_mcv}),
......@@ -1975,6 +2014,87 @@ fn genArmMulConstant(self: *Self, inst: Air.Inst.Index, op: Air.Inst.Ref, op_ind
19752014 return dst_mcv;
19762015}
19772016
2017fn genArmInlineMemcpy(
2018 self: *Self,
2019 src: Register,
2020 dst: Register,
2021 len: Register,
2022 count: Register,
2023 tmp: Register,
2024) !void {
2025 // mov count, #0
2026 _ = try self.addInst(.{
2027 .tag = .mov,
2028 .cond = .al,
2029 .data = .{ .rr_op = .{
2030 .rd = count,
2031 .rn = .r0,
2032 .op = Instruction.Operand.imm(0, 0),
2033 } },
2034 });
2035
2036 // loop:
2037 // cmp count, len
2038 _ = try self.addInst(.{
2039 .tag = .cmp,
2040 .cond = .al,
2041 .data = .{ .rr_op = .{
2042 .rd = .r0,
2043 .rn = count,
2044 .op = Instruction.Operand.reg(len, Instruction.Operand.Shift.none),
2045 } },
2046 });
2047
2048 // bge end
2049 _ = try self.addInst(.{
2050 .tag = .b,
2051 .cond = .ge,
2052 .data = .{ .inst = @intCast(u32, self.mir_instructions.len + 5) },
2053 });
2054
2055 // ldrb tmp, [src, count]
2056 _ = try self.addInst(.{
2057 .tag = .ldrb,
2058 .cond = .al,
2059 .data = .{ .rr_offset = .{
2060 .rt = tmp,
2061 .rn = src,
2062 .offset = .{ .offset = Instruction.Offset.reg(count, 0) },
2063 } },
2064 });
2065
2066 // strb tmp, [src, count]
2067 _ = try self.addInst(.{
2068 .tag = .strb,
2069 .cond = .al,
2070 .data = .{ .rr_offset = .{
2071 .rt = tmp,
2072 .rn = dst,
2073 .offset = .{ .offset = Instruction.Offset.reg(count, 0) },
2074 } },
2075 });
2076
2077 // add count, count, #1
2078 _ = try self.addInst(.{
2079 .tag = .add,
2080 .cond = .al,
2081 .data = .{ .rr_op = .{
2082 .rd = count,
2083 .rn = count,
2084 .op = Instruction.Operand.imm(1, 0),
2085 } },
2086 });
2087
2088 // b loop
2089 _ = try self.addInst(.{
2090 .tag = .b,
2091 .cond = .al,
2092 .data = .{ .inst = @intCast(u32, self.mir_instructions.len - 5) },
2093 });
2094
2095 // end:
2096}
2097
19782098fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, mcv: MCValue) !void {
19792099 const ty_str = self.air.instructions.items(.data)[inst].ty_str;
19802100 const zir = &self.mod_fn.owner_decl.getFileScope().zir;
......@@ -3002,7 +3122,60 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
30023122 const reg = try self.copyToTmpRegister(ty, mcv);
30033123 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
30043124 } else {
3005 return self.fail("TODO implement memcpy", .{});
3125 // TODO optimize the register allocation
3126 const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }, &.{});
3127 const src_reg = regs[0];
3128 const dst_reg = regs[2];
3129 const len_reg = regs[2];
3130 const count_reg = regs[3];
3131 const tmp_reg = regs[4];
3132
3133 // add src_reg, fp, #off
3134 const src_offset_op: Instruction.Operand = if (Instruction.Operand.fromU32(off)) |x| x else {
3135 return self.fail("TODO load: set reg to stack offset with all possible offsets", .{});
3136 };
3137 _ = try self.addInst(.{
3138 .tag = .add,
3139 .cond = .al,
3140 .data = .{ .rr_op = .{
3141 .rd = src_reg,
3142 .rn = .fp,
3143 .op = src_offset_op,
3144 } },
3145 });
3146
3147 // sub dst_reg, fp, #stack_offset
3148 const adj_stack_offset = stack_offset + @intCast(u32, ty.abiSize(self.target.*));
3149 const dst_offset_op: Instruction.Operand = if (Instruction.Operand.fromU32(adj_stack_offset)) |x| x else {
3150 return self.fail("TODO load: set reg to stack offset with all possible offsets", .{});
3151 };
3152 _ = try self.addInst(.{
3153 .tag = .sub,
3154 .cond = .al,
3155 .data = .{ .rr_op = .{
3156 .rd = dst_reg,
3157 .rn = .fp,
3158 .op = dst_offset_op,
3159 } },
3160 });
3161
3162 // mov len, #elem_size
3163 const elem_size = @intCast(u32, ty.abiSize(self.target.*));
3164 const len_op: Instruction.Operand = if (Instruction.Operand.fromU32(elem_size)) |x| x else {
3165 return self.fail("TODO load: set reg to elem_size with all possible sizes", .{});
3166 };
3167 _ = try self.addInst(.{
3168 .tag = .mov,
3169 .cond = .al,
3170 .data = .{ .rr_op = .{
3171 .rd = len_reg,
3172 .rn = .r0,
3173 .op = len_op,
3174 } },
3175 });
3176
3177 // memcpy(src, dst, len)
3178 try self.genArmInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg);
30063179 }
30073180 },
30083181 }