authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-02-01 20:26:23+01:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-02-14 22:09:43+01:00
log77cf000438c8f65f089e9c64fbb881a9136f2931
tree3ee9587288b52cd62e5b9d945c0d3ccb6f8a0b46
parent0d16e908fbb93cdaee80bc2514f76a09736bfa04
signaturelock-open Commit is signed but in an unrecognized format.

stage2 AArch64: implement loading from register


2 files changed, 137 insertions(+), 3 deletions(-)

src/arch/aarch64/CodeGen.zig+136-2
...@@ -1301,8 +1301,64 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -1301,8 +1301,64 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
1301 .embedded_in_code => {1301 .embedded_in_code => {
1302 return self.fail("TODO implement loading from MCValue.embedded_in_code", .{});1302 return self.fail("TODO implement loading from MCValue.embedded_in_code", .{});
1303 },1303 },
1304 .register => {1304 .register => |addr_reg| {
1305 return self.fail("TODO implement loading from MCValue.register for {}", .{self.target.cpu.arch});1305 self.register_manager.freezeRegs(&.{addr_reg});
1306 defer self.register_manager.unfreezeRegs(&.{addr_reg});
1307
1308 switch (dst_mcv) {
1309 .dead => unreachable,
1310 .undef => unreachable,
1311 .compare_flags_signed, .compare_flags_unsigned => unreachable,
1312 .embedded_in_code => unreachable,
1313 .stack_offset => |off| {
1314 if (elem_ty.abiSize(self.target.*) <= 8) {
1315 const tmp_reg = try self.register_manager.allocReg(null);
1316 self.register_manager.freezeRegs(&.{tmp_reg});
1317 defer self.register_manager.unfreezeRegs(&.{tmp_reg});
1318
1319 try self.load(.{ .register = tmp_reg }, ptr, ptr_ty);
1320 try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg });
1321 } else {
1322 // TODO optimize the register allocation
1323 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null });
1324 self.register_manager.freezeRegs(&regs);
1325 defer self.register_manager.unfreezeRegs(&regs);
1326
1327 const src_reg = addr_reg;
1328 const dst_reg = regs[0];
1329 const len_reg = regs[1];
1330 const count_reg = regs[2];
1331 const tmp_reg = regs[3];
1332
1333 // sub dst_reg, fp, #off
1334 const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*));
1335 const adj_off = off + elem_size;
1336 const offset = math.cast(u12, adj_off) catch return self.fail("TODO load: larger stack offsets", .{});
1337 _ = try self.addInst(.{
1338 .tag = .sub_immediate,
1339 .data = .{ .rr_imm12_sh = .{
1340 .rd = dst_reg,
1341 .rn = .x29,
1342 .imm12 = offset,
1343 } },
1344 });
1345
1346 // mov len, #elem_size
1347 const len_imm = math.cast(u16, elem_size) catch return self.fail("TODO load: larger stack offsets", .{});
1348 _ = try self.addInst(.{
1349 .tag = .movk,
1350 .data = .{ .r_imm16_sh = .{
1351 .rd = len_reg,
1352 .imm16 = len_imm,
1353 } },
1354 });
1355
1356 // memcpy(src, dst, len)
1357 try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg);
1358 }
1359 },
1360 else => return self.fail("TODO load from register into {}", .{dst_mcv}),
1361 }
1306 },1362 },
1307 .memory,1363 .memory,
1308 .stack_offset,1364 .stack_offset,
...@@ -1317,6 +1373,84 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -1317,6 +1373,84 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
1317 }1373 }
1318}1374}
13191375
1376fn genInlineMemcpy(
1377 self: *Self,
1378 src: Register,
1379 dst: Register,
1380 len: Register,
1381 count: Register,
1382 tmp: Register,
1383) !void {
1384 // movk count, #0
1385 _ = try self.addInst(.{
1386 .tag = .movk,
1387 .data = .{ .r_imm16_sh = .{
1388 .rd = count,
1389 .imm16 = 0,
1390 } },
1391 });
1392
1393 // loop:
1394 // cmp count, len
1395 _ = try self.addInst(.{
1396 .tag = .cmp_shifted_register,
1397 .data = .{ .rrr_imm6_shift = .{
1398 .rd = .xzr,
1399 .rn = count,
1400 .rm = len,
1401 .imm6 = 0,
1402 .shift = .lsl,
1403 } },
1404 });
1405
1406 // bge end
1407 _ = try self.addInst(.{
1408 .tag = .b_cond,
1409 .data = .{ .inst_cond = .{
1410 .inst = @intCast(u32, self.mir_instructions.len + 5),
1411 .cond = .ge,
1412 } },
1413 });
1414
1415 // ldrb tmp, [src, count]
1416 _ = try self.addInst(.{
1417 .tag = .ldrb_register,
1418 .data = .{ .load_store_register_register = .{
1419 .rt = tmp,
1420 .rn = src,
1421 .offset = Instruction.LoadStoreOffset.reg(count).register,
1422 } },
1423 });
1424
1425 // strb tmp, [dest, count]
1426 _ = try self.addInst(.{
1427 .tag = .strb_register,
1428 .data = .{ .load_store_register_register = .{
1429 .rt = tmp,
1430 .rn = dst,
1431 .offset = Instruction.LoadStoreOffset.reg(count).register,
1432 } },
1433 });
1434
1435 // add count, count, #1
1436 _ = try self.addInst(.{
1437 .tag = .add_immediate,
1438 .data = .{ .rr_imm12_sh = .{
1439 .rd = count,
1440 .rn = count,
1441 .imm12 = 1,
1442 } },
1443 });
1444
1445 // b loop
1446 _ = try self.addInst(.{
1447 .tag = .b,
1448 .data = .{ .inst = @intCast(u32, self.mir_instructions.len - 5) },
1449 });
1450
1451 // end:
1452}
1453
1320fn airLoad(self: *Self, inst: Air.Inst.Index) !void {1454fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
1321 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1455 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1322 const elem_ty = self.air.typeOfIndex(inst);1456 const elem_ty = self.air.typeOfIndex(inst);
src/arch/aarch64/Mir.zig+1-1
...@@ -224,7 +224,7 @@ pub const Inst = struct {...@@ -224,7 +224,7 @@ pub const Inst = struct {
224 },224 },
225 /// A registers and a stack offset225 /// A registers and a stack offset
226 ///226 ///
227 /// Used by e.g. str_register227 /// Used by e.g. str_stack
228 load_store_stack: struct {228 load_store_stack: struct {
229 rt: Register,229 rt: Register,
230 offset: u32,230 offset: u32,