authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-08-13 15:51:49+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-08-13 17:00:03+02:00
logc9d9fd53a61cbc656f543a3fa778ac4c72a58701
tree477bd5ea0405caa3f6f3e2fbfcd44951e1c78b73
parent91969ad908ebb0362eac994ba10cb23bce0a7a4c
signaturelock-open Commit is signed but in an unrecognized format.

stage2 ARM: add inline memcpy to genSetStack


1 files changed, 116 insertions(+), 15 deletions(-)

src/arch/arm/CodeGen.zig+116-15
......@@ -2286,16 +2286,17 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
22862286 .register_c_flag,
22872287 .register_v_flag,
22882288 => unreachable, // cannot hold an address
2289 .immediate => |imm| try self.setRegOrMem(elem_ty, dst_mcv, .{ .memory = imm }),
2290 .ptr_stack_offset => |off| try self.setRegOrMem(elem_ty, dst_mcv, .{ .stack_offset = off }),
2289 .immediate => |imm| {
2290 try self.setRegOrMem(elem_ty, dst_mcv, .{ .memory = imm });
2291 },
2292 .ptr_stack_offset => |off| {
2293 try self.setRegOrMem(elem_ty, dst_mcv, .{ .stack_offset = off });
2294 },
22912295 .register => |reg| {
22922296 const reg_lock = self.register_manager.lockReg(reg);
22932297 defer if (reg_lock) |reg_locked| self.register_manager.unlockReg(reg_locked);
22942298
22952299 switch (dst_mcv) {
2296 .dead => unreachable,
2297 .undef => unreachable,
2298 .cpsr_flags => unreachable,
22992300 .register => |dst_reg| {
23002301 try self.genLdrRegister(dst_reg, reg, elem_ty);
23012302 },
......@@ -2331,7 +2332,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
23312332 try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg);
23322333 }
23332334 },
2334 else => return self.fail("TODO load from register into {}", .{dst_mcv}),
2335 else => unreachable, // attempting to load into non-register or non-stack MCValue
23352336 }
23362337 },
23372338 .memory,
......@@ -2428,7 +2429,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
24282429 // sub src_reg, fp, #off
24292430 try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off });
24302431 },
2431 .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = @intCast(u32, addr) }),
2432 .memory => |addr| try self.genSetReg(ptr_ty, src_reg, .{ .immediate = @intCast(u32, addr) }),
24322433 .stack_argument_offset => |off| {
24332434 _ = try self.addInst(.{
24342435 .tag = .ldr_ptr_stack_argument,
......@@ -3374,6 +3375,102 @@ fn genInlineMemcpy(
33743375 // end:
33753376}
33763377
3378fn genInlineMemset(
3379 self: *Self,
3380 dst: MCValue,
3381 val: MCValue,
3382 len: MCValue,
3383) !void {
3384 const dst_reg = switch (dst) {
3385 .register => |r| r,
3386 else => try self.copyToTmpRegister(Type.initTag(.manyptr_u8), dst),
3387 };
3388 const dst_reg_lock = self.register_manager.lockReg(dst_reg);
3389 defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock);
3390
3391 const val_reg = switch (val) {
3392 .register => |r| r,
3393 else => try self.copyToTmpRegister(Type.initTag(.u8), val),
3394 };
3395 const val_reg_lock = self.register_manager.lockReg(val_reg);
3396 defer if (val_reg_lock) |lock| self.register_manager.unlockReg(lock);
3397
3398 const len_reg = switch (len) {
3399 .register => |r| r,
3400 else => try self.copyToTmpRegister(Type.usize, len),
3401 };
3402 const len_reg_lock = self.register_manager.lockReg(len_reg);
3403 defer if (len_reg_lock) |lock| self.register_manager.unlockReg(lock);
3404
3405 const count_reg = try self.register_manager.allocReg(null, gp);
3406
3407 try self.genInlineMemsetCode(dst_reg, val_reg, len_reg, count_reg);
3408}
3409
3410fn genInlineMemsetCode(
3411 self: *Self,
3412 dst: Register,
3413 val: Register,
3414 len: Register,
3415 count: Register,
3416) !void {
3417 // mov count, #0
3418 _ = try self.addInst(.{
3419 .tag = .mov,
3420 .data = .{ .rr_op = .{
3421 .rd = count,
3422 .rn = .r0,
3423 .op = Instruction.Operand.imm(0, 0),
3424 } },
3425 });
3426
3427 // loop:
3428 // cmp count, len
3429 _ = try self.addInst(.{
3430 .tag = .cmp,
3431 .data = .{ .rr_op = .{
3432 .rd = .r0,
3433 .rn = count,
3434 .op = Instruction.Operand.reg(len, Instruction.Operand.Shift.none),
3435 } },
3436 });
3437
3438 // bge end
3439 _ = try self.addInst(.{
3440 .tag = .b,
3441 .cond = .ge,
3442 .data = .{ .inst = @intCast(u32, self.mir_instructions.len + 4) },
3443 });
3444
3445 // strb val, [src, count]
3446 _ = try self.addInst(.{
3447 .tag = .strb,
3448 .data = .{ .rr_offset = .{
3449 .rt = val,
3450 .rn = dst,
3451 .offset = .{ .offset = Instruction.Offset.reg(count, .none) },
3452 } },
3453 });
3454
3455 // add count, count, #1
3456 _ = try self.addInst(.{
3457 .tag = .add,
3458 .data = .{ .rr_op = .{
3459 .rd = count,
3460 .rn = count,
3461 .op = Instruction.Operand.imm(1, 0),
3462 } },
3463 });
3464
3465 // b loop
3466 _ = try self.addInst(.{
3467 .tag = .b,
3468 .data = .{ .inst = @intCast(u32, self.mir_instructions.len - 4) },
3469 });
3470
3471 // end:
3472}
3473
33773474/// Adds a Type to the .debug_info at the current position. The bytes will be populated later,
33783475/// after codegen for this symbol is done.
33793476fn addDbgInfoTypeReloc(self: *Self, ty: Type) error{OutOfMemory}!void {
......@@ -4652,11 +4749,15 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
46524749 if (!self.wantSafety())
46534750 return; // The already existing value will do just fine.
46544751 // TODO Upgrade this to a memset call when we have that available.
4655 switch (ty.abiSize(self.target.*)) {
4656 1 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaa }),
4657 2 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }),
4658 4 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }),
4659 else => return self.fail("TODO implement memset", .{}),
4752 switch (abi_size) {
4753 1 => try self.genSetStack(ty, stack_offset, .{ .immediate = 0xaa }),
4754 2 => try self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }),
4755 4 => try self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }),
4756 else => try self.genInlineMemset(
4757 .{ .ptr_stack_offset = stack_offset },
4758 .{ .immediate = 0xaa },
4759 .{ .immediate = abi_size },
4760 ),
46604761 }
46614762 },
46624763 .cpsr_flags,
......@@ -5068,9 +5169,9 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
50685169 return; // The already existing value will do just fine.
50695170 // TODO Upgrade this to a memset call when we have that available.
50705171 switch (abi_size) {
5071 1 => return self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaa }),
5072 2 => return self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaaaa }),
5073 4 => return self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }),
5172 1 => try self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaa }),
5173 2 => try self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaaaa }),
5174 4 => try self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }),
50745175 else => return self.fail("TODO implement memset", .{}),
50755176 }
50765177 },