| author | |
| committer | |
| log | 61b8d42d5cd35a4b57802bb4f394eca2cb935bd1 |
| tree | 72f9d3a867cfb11d50d186188d4aa21fbe49af32 |
| parent | 81183365852e7f871500a3f71810ae3b468f0027 |
| parent | 458011f21fda961055a0fd7d280e33824c63c446 |
| signature |
Stage2 AArch64: Fix genSetStack2 files changed, 88 insertions(+), 10 deletions(-)
src/codegen.zig+26-10| ... | @@ -641,20 +641,33 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -641,20 +641,33 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 641 | const cc = self.fn_type.fnCallingConvention(); | 641 | const cc = self.fn_type.fnCallingConvention(); |
| 642 | if (cc != .Naked) { | 642 | if (cc != .Naked) { |
| 643 | // TODO Finish function prologue and epilogue for aarch64. | 643 | // TODO Finish function prologue and epilogue for aarch64. |
| 644 | // Reserve the stack for local variables, etc. | ||
| 645 | 644 | ||
| 646 | // stp fp, lr, [sp, #-16]! | 645 | // stp fp, lr, [sp, #-16]! |
| 646 | // mov fp, sp | ||
| 647 | // sub sp, sp, #reloc | ||
| 647 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.stp( | 648 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.stp( |
| 648 | .x29, | 649 | .x29, |
| 649 | .x30, | 650 | .x30, |
| 650 | Register.sp, | 651 | Register.sp, |
| 651 | Instruction.LoadStorePairOffset.pre_index(-16), | 652 | Instruction.LoadStorePairOffset.pre_index(-16), |
| 652 | ).toU32()); | 653 | ).toU32()); |
| 654 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.add(.x29, .xzr, 0, false).toU32()); | ||
| 655 | const backpatch_reloc = self.code.items.len; | ||
| 656 | try self.code.resize(backpatch_reloc + 4); | ||
| 653 | 657 | ||
| 654 | try self.dbgSetPrologueEnd(); | 658 | try self.dbgSetPrologueEnd(); |
| 655 | 659 | ||
| 656 | try self.genBody(self.mod_fn.body); | 660 | try self.genBody(self.mod_fn.body); |
| 657 | 661 | ||
| 662 | // Backpatch stack offset | ||
| 663 | const stack_end = self.max_end_stack; | ||
| 664 | const aligned_stack_end = mem.alignForward(stack_end, self.stack_align); | ||
| 665 | if (math.cast(u12, aligned_stack_end)) |size| { | ||
| 666 | writeInt(u32, self.code.items[backpatch_reloc..][0..4], Instruction.sub(.xzr, .xzr, size, false).toU32()); | ||
| 667 | } else |_| { | ||
| 668 | return self.failSymbol("TODO AArch64: allow larger stacks", .{}); | ||
| 669 | } | ||
| 670 | |||
| 658 | try self.dbgSetEpilogueBegin(); | 671 | try self.dbgSetEpilogueBegin(); |
| 659 | 672 | ||
| 660 | // exitlude jumps | 673 | // exitlude jumps |
| ... | @@ -690,6 +703,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -690,6 +703,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 690 | Register.sp, | 703 | Register.sp, |
| 691 | Instruction.LoadStorePairOffset.post_index(16), | 704 | Instruction.LoadStorePairOffset.post_index(16), |
| 692 | ).toU32()); | 705 | ).toU32()); |
| 706 | // add sp, sp, #stack_size | ||
| 707 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.add(.xzr, .xzr, @intCast(u12, aligned_stack_end), false).toU32()); | ||
| 693 | // ret lr | 708 | // ret lr |
| 694 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.ret(null).toU32()); | 709 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.ret(null).toU32()); |
| 695 | } else { | 710 | } else { |
| ... | @@ -2685,9 +2700,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -2685,9 +2700,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2685 | 2700 | ||
| 2686 | switch (abi_size) { | 2701 | switch (abi_size) { |
| 2687 | 1, 4 => { | 2702 | 1, 4 => { |
| 2688 | const offset = if (adj_off <= math.maxInt(u12)) blk: { | 2703 | const offset = if (math.cast(u12, adj_off)) |imm| blk: { |
| 2689 | break :blk Instruction.Offset.imm(@intCast(u12, adj_off)); | 2704 | break :blk Instruction.Offset.imm(imm); |
| 2690 | } else Instruction.Offset.reg(try self.copyToTmpRegister(src, MCValue{ .immediate = adj_off }), 0); | 2705 | } else |_| Instruction.Offset.reg(try self.copyToTmpRegister(src, MCValue{ .immediate = adj_off }), 0); |
| 2691 | const str = switch (abi_size) { | 2706 | const str = switch (abi_size) { |
| 2692 | 1 => Instruction.strb, | 2707 | 1 => Instruction.strb, |
| 2693 | 4 => Instruction.str, | 2708 | 4 => Instruction.str, |
| ... | @@ -2848,12 +2863,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -2848,12 +2863,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2848 | 2863 | ||
| 2849 | switch (abi_size) { | 2864 | switch (abi_size) { |
| 2850 | 4, 8 => { | 2865 | 4, 8 => { |
| 2851 | const offset = if (adj_off <= math.maxInt(u12)) blk: { | 2866 | const offset = if (math.cast(i9, adj_off)) |imm| |
| 2852 | break :blk Instruction.LoadStoreOffset.imm(@intCast(u12, adj_off)); | 2867 | Instruction.LoadStoreOffset.imm_post_index(-imm) |
| 2853 | } else Instruction.LoadStoreOffset.reg(try self.copyToTmpRegister(src, MCValue{ .immediate = adj_off })); | 2868 | else |_| |
| 2854 | const rn: Register = switch (abi_size) { | 2869 | Instruction.LoadStoreOffset.reg(try self.copyToTmpRegister(src, MCValue{ .immediate = adj_off })); |
| 2855 | 4 => .w29, | 2870 | const rn: Register = switch (arch) { |
| 2856 | 8 => .x29, | 2871 | .aarch64, .aarch64_be => .x29, |
| 2872 | .aarch64_32 => .w29, | ||
| 2857 | else => unreachable, | 2873 | else => unreachable, |
| 2858 | }; | 2874 | }; |
| 2859 | 2875 |
src/codegen/aarch64.zig+62| ... | @@ -274,6 +274,16 @@ pub const Instruction = union(enum) { | ... | @@ -274,6 +274,16 @@ pub const Instruction = union(enum) { |
| 274 | opc: u2, | 274 | opc: u2, |
| 275 | sf: u1, | 275 | sf: u1, |
| 276 | }, | 276 | }, |
| 277 | AddSubtractImmediate: packed struct { | ||
| 278 | rd: u5, | ||
| 279 | rn: u5, | ||
| 280 | imm12: u12, | ||
| 281 | sh: u1, | ||
| 282 | fixed: u6 = 0b100010, | ||
| 283 | s: u1, | ||
| 284 | op: u1, | ||
| 285 | sf: u1, | ||
| 286 | }, | ||
| 277 | 287 | ||
| 278 | pub const Shift = struct { | 288 | pub const Shift = struct { |
| 279 | shift: Type = .lsl, | 289 | shift: Type = .lsl, |
| ... | @@ -304,6 +314,7 @@ pub const Instruction = union(enum) { | ... | @@ -304,6 +314,7 @@ pub const Instruction = union(enum) { |
| 304 | .UnconditionalBranchImmediate => |v| @bitCast(u32, v), | 314 | .UnconditionalBranchImmediate => |v| @bitCast(u32, v), |
| 305 | .NoOperation => |v| @bitCast(u32, v), | 315 | .NoOperation => |v| @bitCast(u32, v), |
| 306 | .LogicalShiftedRegister => |v| @bitCast(u32, v), | 316 | .LogicalShiftedRegister => |v| @bitCast(u32, v), |
| 317 | .AddSubtractImmediate => |v| @bitCast(u32, v), | ||
| 307 | }; | 318 | }; |
| 308 | } | 319 | } |
| 309 | 320 | ||
| ... | @@ -671,6 +682,31 @@ pub const Instruction = union(enum) { | ... | @@ -671,6 +682,31 @@ pub const Instruction = union(enum) { |
| 671 | } | 682 | } |
| 672 | } | 683 | } |
| 673 | 684 | ||
| 685 | fn addSubtractImmediate( | ||
| 686 | op: u1, | ||
| 687 | s: u1, | ||
| 688 | rd: Register, | ||
| 689 | rn: Register, | ||
| 690 | imm12: u12, | ||
| 691 | shift: bool, | ||
| 692 | ) Instruction { | ||
| 693 | return Instruction{ | ||
| 694 | .AddSubtractImmediate = .{ | ||
| 695 | .rd = rd.id(), | ||
| 696 | .rn = rn.id(), | ||
| 697 | .imm12 = imm12, | ||
| 698 | .sh = @boolToInt(shift), | ||
| 699 | .s = s, | ||
| 700 | .op = op, | ||
| 701 | .sf = switch (rd.size()) { | ||
| 702 | 32 => 0b0, | ||
| 703 | 64 => 0b1, | ||
| 704 | else => unreachable, // unexpected register size | ||
| 705 | }, | ||
| 706 | }, | ||
| 707 | }; | ||
| 708 | } | ||
| 709 | |||
| 674 | // Helper functions for assembly syntax functions | 710 | // Helper functions for assembly syntax functions |
| 675 | 711 | ||
| 676 | // Move wide (immediate) | 712 | // Move wide (immediate) |
| ... | @@ -850,6 +886,24 @@ pub const Instruction = union(enum) { | ... | @@ -850,6 +886,24 @@ pub const Instruction = union(enum) { |
| 850 | pub fn bics(rd: Register, rn: Register, rm: Register, shift: Shift) Instruction { | 886 | pub fn bics(rd: Register, rn: Register, rm: Register, shift: Shift) Instruction { |
| 851 | return logicalShiftedRegister(0b11, 0b1, shift, rd, rn, rm); | 887 | return logicalShiftedRegister(0b11, 0b1, shift, rd, rn, rm); |
| 852 | } | 888 | } |
| 889 | |||
| 890 | // Add/subtract (immediate) | ||
| 891 | |||
| 892 | pub fn add(rd: Register, rn: Register, imm: u12, shift: bool) Instruction { | ||
| 893 | return addSubtractImmediate(0b0, 0b0, rd, rn, imm, shift); | ||
| 894 | } | ||
| 895 | |||
| 896 | pub fn adds(rd: Register, rn: Register, imm: u12, shift: bool) Instruction { | ||
| 897 | return addSubtractImmediate(0b0, 0b1, rd, rn, imm, shift); | ||
| 898 | } | ||
| 899 | |||
| 900 | pub fn sub(rd: Register, rn: Register, imm: u12, shift: bool) Instruction { | ||
| 901 | return addSubtractImmediate(0b1, 0b0, rd, rn, imm, shift); | ||
| 902 | } | ||
| 903 | |||
| 904 | pub fn subs(rd: Register, rn: Register, imm: u12, shift: bool) Instruction { | ||
| 905 | return addSubtractImmediate(0b1, 0b1, rd, rn, imm, shift); | ||
| 906 | } | ||
| 853 | }; | 907 | }; |
| 854 | 908 | ||
| 855 | test "" { | 909 | test "" { |
| ... | @@ -979,6 +1033,14 @@ test "serialize instructions" { | ... | @@ -979,6 +1033,14 @@ test "serialize instructions" { |
| 979 | .inst = Instruction.@"and"(.x0, .x4, .x2, .{ .shift = .lsl, .amount = 0x8 }), | 1033 | .inst = Instruction.@"and"(.x0, .x4, .x2, .{ .shift = .lsl, .amount = 0x8 }), |
| 980 | .expected = 0b1_00_01010_00_0_00010_001000_00100_00000, | 1034 | .expected = 0b1_00_01010_00_0_00010_001000_00100_00000, |
| 981 | }, | 1035 | }, |
| 1036 | .{ // add x0, x10, #10 | ||
| 1037 | .inst = Instruction.add(.x0, .x10, 10, false), | ||
| 1038 | .expected = 0b1_0_0_100010_0_0000_0000_1010_01010_00000, | ||
| 1039 | }, | ||
| 1040 | .{ // subs x0, x5, #11, lsl #12 | ||
| 1041 | .inst = Instruction.subs(.x0, .x5, 11, true), | ||
| 1042 | .expected = 0b1_1_1_100010_1_0000_0000_1011_00101_00000, | ||
| 1043 | }, | ||
| 982 | }; | 1044 | }; |
| 983 | 1045 | ||
| 984 | for (testcases) |case| { | 1046 | for (testcases) |case| { |