Skip to content

Commit c9d9fd5

Browse files
stage2 ARM: add inline memcpy to genSetStack
1 parent 91969ad commit c9d9fd5

File tree

1 file changed

+116
-15
lines changed

1 file changed

+116
-15
lines changed

src/arch/arm/CodeGen.zig

Lines changed: 116 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -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

3378+
fn 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+
3410+
fn 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.
33793476
fn 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
},

0 commit comments

Comments
 (0)