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...@@ -2286,16 +2286,17 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2286 .register_c_flag,2286 .register_c_flag,
2287 .register_v_flag,2287 .register_v_flag,
2288 => unreachable, // cannot hold an address2288 => unreachable, // cannot hold an address
2289 .immediate => |imm| try self.setRegOrMem(elem_ty, dst_mcv, .{ .memory = imm }),2289 .immediate => |imm| {
2290 .ptr_stack_offset => |off| try self.setRegOrMem(elem_ty, dst_mcv, .{ .stack_offset = off }),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 },
2291 .register => |reg| {2295 .register => |reg| {
2292 const reg_lock = self.register_manager.lockReg(reg);2296 const reg_lock = self.register_manager.lockReg(reg);
2293 defer if (reg_lock) |reg_locked| self.register_manager.unlockReg(reg_locked);2297 defer if (reg_lock) |reg_locked| self.register_manager.unlockReg(reg_locked);
22942298
2295 switch (dst_mcv) {2299 switch (dst_mcv) {
2296 .dead => unreachable,
2297 .undef => unreachable,
2298 .cpsr_flags => unreachable,
2299 .register => |dst_reg| {2300 .register => |dst_reg| {
2300 try self.genLdrRegister(dst_reg, reg, elem_ty);2301 try self.genLdrRegister(dst_reg, reg, elem_ty);
2301 },2302 },
...@@ -2331,7 +2332,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -2331,7 +2332,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2331 try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg);2332 try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg);
2332 }2333 }
2333 },2334 },
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
2335 }2336 }
2336 },2337 },
2337 .memory,2338 .memory,
...@@ -2428,7 +2429,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -2428,7 +2429,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
2428 // sub src_reg, fp, #off2429 // sub src_reg, fp, #off
2429 try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off });2430 try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off });
2430 },2431 },
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) }),
2432 .stack_argument_offset => |off| {2433 .stack_argument_offset => |off| {
2433 _ = try self.addInst(.{2434 _ = try self.addInst(.{
2434 .tag = .ldr_ptr_stack_argument,2435 .tag = .ldr_ptr_stack_argument,
...@@ -3374,6 +3375,102 @@ fn genInlineMemcpy(...@@ -3374,6 +3375,102 @@ fn genInlineMemcpy(
3374 // end:3375 // end:
3375}3376}
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
3377/// Adds a Type to the .debug_info at the current position. The bytes will be populated later,3474/// Adds a Type to the .debug_info at the current position. The bytes will be populated later,
3378/// after codegen for this symbol is done.3475/// after codegen for this symbol is done.
3379fn addDbgInfoTypeReloc(self: *Self, ty: Type) error{OutOfMemory}!void {3476fn addDbgInfoTypeReloc(self: *Self, ty: Type) error{OutOfMemory}!void {
...@@ -4652,11 +4749,15 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -4652,11 +4749,15 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
4652 if (!self.wantSafety())4749 if (!self.wantSafety())
4653 return; // The already existing value will do just fine.4750 return; // The already existing value will do just fine.
4654 // TODO Upgrade this to a memset call when we have that available.4751 // TODO Upgrade this to a memset call when we have that available.
4655 switch (ty.abiSize(self.target.*)) {4752 switch (abi_size) {
4656 1 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaa }),4753 1 => try self.genSetStack(ty, stack_offset, .{ .immediate = 0xaa }),
4657 2 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }),4754 2 => try self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }),
4658 4 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }),4755 4 => try self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }),
4659 else => return self.fail("TODO implement memset", .{}),4756 else => try self.genInlineMemset(
4757 .{ .ptr_stack_offset = stack_offset },
4758 .{ .immediate = 0xaa },
4759 .{ .immediate = abi_size },
4760 ),
4660 }4761 }
4661 },4762 },
4662 .cpsr_flags,4763 .cpsr_flags,
...@@ -5068,9 +5169,9 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I...@@ -5068,9 +5169,9 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
5068 return; // The already existing value will do just fine.5169 return; // The already existing value will do just fine.
5069 // TODO Upgrade this to a memset call when we have that available.5170 // TODO Upgrade this to a memset call when we have that available.
5070 switch (abi_size) {5171 switch (abi_size) {
5071 1 => return self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaa }),5172 1 => try self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaa }),
5072 2 => return self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaaaa }),5173 2 => try self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaaaa }),
5073 4 => return self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }),5174 4 => try self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }),
5074 else => return self.fail("TODO implement memset", .{}),5175 else => return self.fail("TODO implement memset", .{}),
5075 }5176 }
5076 },5177 },