Skip to content

Commit 927a763

Browse files
stage2 ARM: Add stm, ldm variants and misc. additions
1 parent 0534f66 commit 927a763

File tree

2 files changed

+84
-13
lines changed

2 files changed

+84
-13
lines changed

src-self-hosted/codegen.zig

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,35 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
569569
try self.dbgSetEpilogueBegin();
570570
}
571571
},
572+
.arm => {
573+
const cc = self.fn_type.fnCallingConvention();
574+
if (cc != .Naked) {
575+
// push {fp, lr}
576+
// mov fp, sp
577+
// sub sp, sp, #reloc
578+
// mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.mov(.al, .fp, Instruction.Operand.reg(.sp, Instruction.Operand.Shift.none)).toU32());
579+
// const backpatch_reloc = try self.code.addManyAsArray(4);
580+
581+
try self.dbgSetPrologueEnd();
582+
583+
try self.genBody(self.mod_fn.analysis.success);
584+
585+
// Backpatch stack offset
586+
// const stack_end = self.max_end_stack;
587+
// const aligned_stack_end = mem.alignForward(stack_end, self.stack_align);
588+
// mem.writeIntLittle(u32, backpatch_reloc, Instruction.sub(.al, .sp, .sp, Instruction.Operand.imm()));
589+
590+
try self.dbgSetEpilogueBegin();
591+
592+
// mov sp, fp
593+
// pop {fp, pc}
594+
mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.mov(.al, .sp, Instruction.Operand.reg(.fp, Instruction.Operand.Shift.none)).toU32());
595+
} else {
596+
try self.dbgSetPrologueEnd();
597+
try self.genBody(self.mod_fn.analysis.success);
598+
try self.dbgSetEpilogueBegin();
599+
}
600+
},
572601
else => {
573602
try self.dbgSetPrologueEnd();
574603
try self.genBody(self.mod_fn.analysis.success);
@@ -1503,13 +1532,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
15031532
else
15041533
unreachable;
15051534

1506-
// TODO only works with leaf functions
1507-
// at the moment, which works fine for
1508-
// Hello World, but not for real code
1509-
// of course. Add pushing lr to stack
1510-
// and popping after call
15111535
try self.genSetReg(inst.base.src, .lr, .{ .memory = got_addr });
15121536

1537+
// TODO: add Instruction.supportedOn
1538+
// function for ARM
15131539
if (Target.arm.featureSetHas(self.target.cpu.features, .has_v5t)) {
15141540
mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.blx(.al, .lr).toU32());
15151541
} else {
@@ -1635,6 +1661,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
16351661
},
16361662
.arm => {
16371663
mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.bx(.al, .lr).toU32());
1664+
// // Just add space for an instruction, patch this later
1665+
// try self.code.resize(self.code.items.len + 4);
1666+
// try self.exitlude_jump_relocs.append(self.gpa, self.code.items.len - 4);
16381667
},
16391668
else => return self.fail(src, "TODO implement return for {}", .{self.target.cpu.arch}),
16401669
}
@@ -2770,6 +2799,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
27702799
} else {
27712800
return self.fail(src, "TODO MCValues with multiple registers", .{});
27722801
}
2802+
} else if (ncrn < 4 and nsaa == 0) {
2803+
return self.fail(src, "TODO MCValues split between registers and stack", .{});
27732804
} else {
27742805
ncrn = 4;
27752806
if (ty.abiAlignment(self.target.*) == 8) {

src-self-hosted/codegen/arm.zig

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -446,15 +446,15 @@ pub const Instruction = union(enum) {
446446
pre_post: u1,
447447
up_down: u1,
448448
psr_or_user: u1,
449-
write_back: u1,
449+
write_back: bool,
450450
load_store: u1,
451451
) Instruction {
452452
return Instruction{
453453
.BlockDataTransfer = .{
454454
.register_list = @bitCast(u16, reg_list),
455455
.rn = rn.id(),
456456
.load_store = load_store,
457-
.write_back = write_back,
457+
.write_back = if (write_back) 1 else 0,
458458
.psr_or_user = psr_or_user,
459459
.up_down = up_down,
460460
.pre_post = pre_post,
@@ -644,14 +644,50 @@ pub const Instruction = union(enum) {
644644

645645
// Block data transfer
646646

647-
pub fn ldm(cond: Condition, rn: Register, reg_list: RegisterList) Instruction {
648-
return blockDataTransfer(cond, rn, reg_list, 1, 0, 0, 0, 1);
647+
pub fn ldmda(cond: Condition, rn: Register, write_back: bool, reg_list: RegisterList) Instruction {
648+
return blockDataTransfer(cond, rn, reg_list, 0, 0, 0, write_back, 1);
649649
}
650650

651-
pub fn stm(cond: Condition, rn: Register, reg_list: RegisterList) Instruction {
652-
return blockDataTransfer(cond, rn, reg_list, 1, 0, 0, 0, 0);
651+
pub fn ldmdb(cond: Condition, rn: Register, write_back: bool, reg_list: RegisterList) Instruction {
652+
return blockDataTransfer(cond, rn, reg_list, 1, 0, 0, write_back, 1);
653+
}
654+
655+
pub fn ldmib(cond: Condition, rn: Register, write_back: bool, reg_list: RegisterList) Instruction {
656+
return blockDataTransfer(cond, rn, reg_list, 1, 1, 0, write_back, 1);
657+
}
658+
659+
pub fn ldmia(cond: Condition, rn: Register, write_back: bool, reg_list: RegisterList) Instruction {
660+
return blockDataTransfer(cond, rn, reg_list, 0, 1, 0, write_back, 1);
661+
}
662+
663+
pub const ldmfa = ldmda;
664+
pub const ldmea = ldmdb;
665+
pub const ldmed = ldmib;
666+
pub const ldmfd = ldmia;
667+
pub const ldm = ldmia;
668+
669+
pub fn stmda(cond: Condition, rn: Register, write_back: bool, reg_list: RegisterList) Instruction {
670+
return blockDataTransfer(cond, rn, reg_list, 0, 0, 0, write_back, 0);
653671
}
654672

673+
pub fn stmdb(cond: Condition, rn: Register, write_back: bool, reg_list: RegisterList) Instruction {
674+
return blockDataTransfer(cond, rn, reg_list, 1, 0, 0, write_back, 0);
675+
}
676+
677+
pub fn stmib(cond: Condition, rn: Register, write_back: bool, reg_list: RegisterList) Instruction {
678+
return blockDataTransfer(cond, rn, reg_list, 1, 1, 0, write_back, 0);
679+
}
680+
681+
pub fn stmia(cond: Condition, rn: Register, write_back: bool, reg_list: RegisterList) Instruction {
682+
return blockDataTransfer(cond, rn, reg_list, 0, 1, 0, write_back, 0);
683+
}
684+
685+
pub const stmed = stmda;
686+
pub const stmfd = stmdb;
687+
pub const stmfa = stmib;
688+
pub const stmea = stmia;
689+
pub const stm = stmia;
690+
655691
// Branch
656692

657693
pub fn b(cond: Condition, offset: i24) Instruction {
@@ -738,10 +774,14 @@ test "serialize instructions" {
738774
.inst = Instruction.bkpt(42),
739775
.expected = 0b1110_0001_0010_000000000010_0111_1010,
740776
},
741-
.{ // stmfd r9, {r0}
742-
.inst = Instruction.stm(.al, .r9, .{ .r0 = true }),
777+
.{ // stmdb r9, {r0}
778+
.inst = Instruction.stmdb(.al, .r9, false, .{ .r0 = true }),
743779
.expected = 0b1110_100_1_0_0_0_0_1001_0000000000000001,
744780
},
781+
.{ // ldmea r4!, {r2, r5}
782+
.inst = Instruction.ldmea(.al, .r4, true, .{ .r2 = true, .r5 = true }),
783+
.expected = 0b1110_100_1_0_0_1_1_0100_0000000000100100,
784+
},
745785
};
746786

747787
for (testcases) |case| {

0 commit comments

Comments
 (0)