authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-08-02 21:04:54+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-08-05 20:30:51+02:00
log65b3c27f2457f3d957d83edf13e20e41e84f6dd4
tree1416090932e7c58de9bd48658211e7ce5e5286a2
parentcf3aaceed9f2a9e1872bdd8b2cccecd1766e2419
signaturelock-open Commit is signed but in an unrecognized format.

stage2 AArch64: all arguments passed via stack from now on

Only in the Undefined calling convention, not in other calling conventions

3 files changed, 127 insertions(+), 80 deletions(-)

src/arch/aarch64/CodeGen.zig+86-54
...@@ -340,7 +340,7 @@ pub fn generate(...@@ -340,7 +340,7 @@ pub fn generate(
340 .prev_di_line = module_fn.lbrace_line,340 .prev_di_line = module_fn.lbrace_line,
341 .prev_di_column = module_fn.lbrace_column,341 .prev_di_column = module_fn.lbrace_column,
342 .stack_size = mem.alignForwardGeneric(u32, function.max_end_stack, function.stack_align),342 .stack_size = mem.alignForwardGeneric(u32, function.max_end_stack, function.stack_align),
343 .prologue_stack_space = call_info.stack_byte_count + function.saved_regs_stack_space,343 .saved_regs_stack_space = function.saved_regs_stack_space,
344 };344 };
345 defer emit.deinit();345 defer emit.deinit();
346346
...@@ -2317,6 +2317,9 @@ fn errUnionErr(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCV...@@ -2317,6 +2317,9 @@ fn errUnionErr(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCV
2317 const err_offset = @intCast(u32, errUnionErrorOffset(payload_ty, self.target.*));2317 const err_offset = @intCast(u32, errUnionErrorOffset(payload_ty, self.target.*));
2318 switch (error_union_mcv) {2318 switch (error_union_mcv) {
2319 .register => return self.fail("TODO errUnionErr for registers", .{}),2319 .register => return self.fail("TODO errUnionErr for registers", .{}),
2320 .stack_argument_offset => |off| {
2321 return MCValue{ .stack_argument_offset = off + err_offset };
2322 },
2320 .stack_offset => |off| {2323 .stack_offset => |off| {
2321 return MCValue{ .stack_offset = off - err_offset };2324 return MCValue{ .stack_offset = off - err_offset };
2322 },2325 },
...@@ -2351,6 +2354,9 @@ fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type)...@@ -2351,6 +2354,9 @@ fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type)
2351 const payload_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, self.target.*));2354 const payload_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, self.target.*));
2352 switch (error_union_mcv) {2355 switch (error_union_mcv) {
2353 .register => return self.fail("TODO errUnionPayload for registers", .{}),2356 .register => return self.fail("TODO errUnionPayload for registers", .{}),
2357 .stack_argument_offset => |off| {
2358 return MCValue{ .stack_argument_offset = off + payload_offset };
2359 },
2354 .stack_offset => |off| {2360 .stack_offset => |off| {
2355 return MCValue{ .stack_offset = off - payload_offset };2361 return MCValue{ .stack_offset = off - payload_offset };
2356 },2362 },
...@@ -3016,7 +3022,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -3016,7 +3022,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
3016 switch (mcv) {3022 switch (mcv) {
3017 .dead, .unreach => unreachable,3023 .dead, .unreach => unreachable,
3018 .stack_argument_offset => |off| {3024 .stack_argument_offset => |off| {
3019 break :result MCValue{ .stack_argument_offset = off - struct_field_offset };3025 break :result MCValue{ .stack_argument_offset = off + struct_field_offset };
3020 },3026 },
3021 .stack_offset => |off| {3027 .stack_offset => |off| {
3022 break :result MCValue{ .stack_offset = off - struct_field_offset };3028 break :result MCValue{ .stack_offset = off - struct_field_offset };
...@@ -3150,6 +3156,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions....@@ -3150,6 +3156,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
3150 // saving compare flags may require a new caller-saved register3156 // saving compare flags may require a new caller-saved register
3151 try self.spillCompareFlagsIfOccupied();3157 try self.spillCompareFlagsIfOccupied();
31523158
3159 // Make space for the arguments passed via the stack
3160 self.max_end_stack += info.stack_byte_count;
3161
3153 for (info.args) |mc_arg, arg_i| {3162 for (info.args) |mc_arg, arg_i| {
3154 const arg = args[arg_i];3163 const arg = args[arg_i];
3155 const arg_ty = self.air.typeOf(arg);3164 const arg_ty = self.air.typeOf(arg);
...@@ -3164,7 +3173,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions....@@ -3164,7 +3173,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
3164 .stack_offset => unreachable,3173 .stack_offset => unreachable,
3165 .stack_argument_offset => |offset| try self.genSetStackArgument(3174 .stack_argument_offset => |offset| try self.genSetStackArgument(
3166 arg_ty,3175 arg_ty,
3167 info.stack_byte_count - offset,3176 offset,
3168 arg_mcv,3177 arg_mcv,
3169 ),3178 ),
3170 else => unreachable,3179 else => unreachable,
...@@ -3642,40 +3651,14 @@ fn isNonNull(self: *Self, operand: MCValue) !MCValue {...@@ -3642,40 +3651,14 @@ fn isNonNull(self: *Self, operand: MCValue) !MCValue {
36423651
3643fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {3652fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
3644 const error_type = ty.errorUnionSet();3653 const error_type = ty.errorUnionSet();
3645 const payload_type = ty.errorUnionPayload();3654 const error_int_type = Type.initTag(.u16);
36463655
3647 if (error_type.errorSetIsEmpty()) {3656 if (error_type.errorSetIsEmpty()) {
3648 return MCValue{ .immediate = 0 }; // always false3657 return MCValue{ .immediate = 0 }; // always false
3649 }3658 }
36503659
3651 const err_off = errUnionErrorOffset(payload_type, self.target.*);3660 const error_mcv = try self.errUnionErr(operand, ty);
3652 switch (operand) {3661 _ = try self.binOp(.cmp_eq, error_mcv, .{ .immediate = 0 }, error_int_type, error_int_type, null);
3653 .stack_offset => |off| {
3654 const offset = off - @intCast(u32, err_off);
3655 const tmp_reg = try self.copyToTmpRegister(Type.anyerror, .{ .stack_offset = offset });
3656 _ = try self.addInst(.{
3657 .tag = .cmp_immediate,
3658 .data = .{ .r_imm12_sh = .{
3659 .rn = tmp_reg,
3660 .imm12 = 0,
3661 } },
3662 });
3663 },
3664 .register => |reg| {
3665 if (err_off > 0 or payload_type.hasRuntimeBitsIgnoreComptime()) {
3666 return self.fail("TODO implement isErr for register operand with payload bits", .{});
3667 }
3668 _ = try self.addInst(.{
3669 .tag = .cmp_immediate,
3670 .data = .{ .r_imm12_sh = .{
3671 .rn = reg,
3672 .imm12 = 0,
3673 } },
3674 });
3675 },
3676 else => return self.fail("TODO implement isErr for {}", .{operand}),
3677 }
3678
3679 return MCValue{ .condition_flags = .hi };3662 return MCValue{ .condition_flags = .hi };
3680}3663}
36813664
...@@ -4174,6 +4157,15 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -4174,6 +4157,15 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
4174 // sub src_reg, fp, #off4157 // sub src_reg, fp, #off
4175 try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off });4158 try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off });
4176 },4159 },
4160 .stack_argument_offset => |off| {
4161 _ = try self.addInst(.{
4162 .tag = .ldr_ptr_stack_argument,
4163 .data = .{ .load_store_stack = .{
4164 .rt = src_reg,
4165 .offset = off,
4166 } },
4167 });
4168 },
4177 .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = addr }),4169 .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = addr }),
4178 .got_load,4170 .got_load,
4179 .direct_load,4171 .direct_load,
...@@ -4433,7 +4425,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I...@@ -4433,7 +4425,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
4433 }4425 }
4434 },4426 },
4435 .register_with_overflow => {4427 .register_with_overflow => {
4436 return self.fail("TODO implement genSetStack {}", .{mcv});4428 return self.fail("TODO implement genSetStackArgument {}", .{mcv});
4437 },4429 },
4438 .got_load,4430 .got_load,
4439 .direct_load,4431 .direct_load,
...@@ -4469,6 +4461,15 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I...@@ -4469,6 +4461,15 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
4469 // sub src_reg, fp, #off4461 // sub src_reg, fp, #off
4470 try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off });4462 try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off });
4471 },4463 },
4464 .stack_argument_offset => |off| {
4465 _ = try self.addInst(.{
4466 .tag = .ldr_ptr_stack_argument,
4467 .data = .{ .load_store_stack = .{
4468 .rt = src_reg,
4469 .offset = off,
4470 } },
4471 });
4472 },
4472 .memory => |addr| try self.genSetReg(ptr_ty, src_reg, .{ .immediate = @intCast(u32, addr) }),4473 .memory => |addr| try self.genSetReg(ptr_ty, src_reg, .{ .immediate = @intCast(u32, addr) }),
4473 .got_load,4474 .got_load,
4474 .direct_load,4475 .direct_load,
...@@ -4490,7 +4491,6 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I...@@ -4490,7 +4491,6 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
4490 },4491 },
4491 });4492 });
4492 },4493 },
4493 .stack_argument_offset => return self.fail("TODO load {}", .{mcv}),
4494 else => unreachable,4494 else => unreachable,
4495 }4495 }
44964496
...@@ -4989,11 +4989,27 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -4989,11 +4989,27 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
4989 result.stack_align = 1;4989 result.stack_align = 1;
4990 return result;4990 return result;
4991 },4991 },
4992 .Unspecified, .C => {4992 .C => {
4993 // ARM64 Procedure Call Standard4993 // ARM64 Procedure Call Standard
4994 var ncrn: usize = 0; // Next Core Register Number4994 var ncrn: usize = 0; // Next Core Register Number
4995 var nsaa: u32 = 0; // Next stacked argument address4995 var nsaa: u32 = 0; // Next stacked argument address
49964996
4997 if (ret_ty.zigTypeTag() == .NoReturn) {
4998 result.return_value = .{ .unreach = {} };
4999 } else if (!ret_ty.hasRuntimeBitsIgnoreComptime() and !ret_ty.isError()) {
5000 result.return_value = .{ .none = {} };
5001 } else {
5002 const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*));
5003 if (ret_ty_size == 0) {
5004 assert(ret_ty.isError());
5005 result.return_value = .{ .immediate = 0 };
5006 } else if (ret_ty_size <= 8) {
5007 result.return_value = .{ .register = registerAlias(c_abi_int_return_regs[0], ret_ty_size) };
5008 } else {
5009 return self.fail("TODO support more return types for ARM backend", .{});
5010 }
5011 }
5012
4997 for (param_types) |ty, i| {5013 for (param_types) |ty, i| {
4998 const param_size = @intCast(u32, ty.abiSize(self.target.*));5014 const param_size = @intCast(u32, ty.abiSize(self.target.*));
4999 if (param_size == 0) {5015 if (param_size == 0) {
...@@ -5027,36 +5043,52 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -5027,36 +5043,52 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
5027 }5043 }
5028 }5044 }
50295045
5030 nsaa += param_size;
5031 result.args[i] = .{ .stack_argument_offset = nsaa };5046 result.args[i] = .{ .stack_argument_offset = nsaa };
5047 nsaa += param_size;
5032 }5048 }
5033 }5049 }
50345050
5035 result.stack_byte_count = nsaa;5051 result.stack_byte_count = nsaa;
5036 result.stack_align = 16;5052 result.stack_align = 16;
5037 },5053 },
5038 else => return self.fail("TODO implement function parameters for {} on aarch64", .{cc}),5054 .Unspecified => {
5039 }5055 if (ret_ty.zigTypeTag() == .NoReturn) {
50405056 result.return_value = .{ .unreach = {} };
5041 if (ret_ty.zigTypeTag() == .NoReturn) {5057 } else if (!ret_ty.hasRuntimeBitsIgnoreComptime() and !ret_ty.isError()) {
5042 result.return_value = .{ .unreach = {} };5058 result.return_value = .{ .none = {} };
5043 } else if (!ret_ty.hasRuntimeBitsIgnoreComptime() and !ret_ty.isError()) {
5044 result.return_value = .{ .none = {} };
5045 } else switch (cc) {
5046 .Naked => unreachable,
5047 .Unspecified, .C => {
5048 const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*));
5049 if (ret_ty_size == 0) {
5050 assert(ret_ty.isError());
5051 result.return_value = .{ .immediate = 0 };
5052 } else if (ret_ty_size <= 8) {
5053 result.return_value = .{ .register = registerAlias(c_abi_int_return_regs[0], ret_ty_size) };
5054 } else {5059 } else {
5055 return self.fail("TODO support more return types for ARM backend", .{});5060 const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*));
5061 if (ret_ty_size == 0) {
5062 assert(ret_ty.isError());
5063 result.return_value = .{ .immediate = 0 };
5064 } else if (ret_ty_size <= 8) {
5065 result.return_value = .{ .register = registerAlias(c_abi_int_return_regs[0], ret_ty_size) };
5066 } else {
5067 return self.fail("TODO support more return types for ARM backend", .{});
5068 }
5056 }5069 }
5070
5071 var stack_offset: u32 = 0;
5072
5073 for (param_types) |ty, i| {
5074 if (ty.abiSize(self.target.*) > 0) {
5075 const param_size = @intCast(u32, ty.abiSize(self.target.*));
5076 const param_alignment = ty.abiAlignment(self.target.*);
5077
5078 stack_offset = std.mem.alignForwardGeneric(u32, stack_offset, param_alignment);
5079 result.args[i] = .{ .stack_argument_offset = stack_offset };
5080 stack_offset += param_size;
5081 } else {
5082 result.args[i] = .{ .none = {} };
5083 }
5084 }
5085
5086 result.stack_byte_count = stack_offset;
5087 result.stack_align = 16;
5057 },5088 },
5058 else => return self.fail("TODO implement function return values for {}", .{cc}),5089 else => return self.fail("TODO implement function parameters for {} on aarch64", .{cc}),
5059 }5090 }
5091
5060 return result;5092 return result;
5061}5093}
50625094
src/arch/aarch64/Emit.zig+39-26
...@@ -31,9 +31,9 @@ prev_di_column: u32,...@@ -31,9 +31,9 @@ prev_di_column: u32,
31/// Relative to the beginning of `code`.31/// Relative to the beginning of `code`.
32prev_di_pc: usize,32prev_di_pc: usize,
3333
34/// The amount of stack space consumed by all stack arguments as well34/// The amount of stack space consumed by the saved callee-saved
35/// as the saved callee-saved registers35/// registers in bytes
36prologue_stack_space: u32,36saved_regs_stack_space: u32,
3737
38/// The branch type of every branch38/// The branch type of every branch
39branch_types: std.AutoHashMapUnmanaged(Mir.Inst.Index, BranchType) = .{},39branch_types: std.AutoHashMapUnmanaged(Mir.Inst.Index, BranchType) = .{},
...@@ -158,6 +158,7 @@ pub fn emitMir(...@@ -158,6 +158,7 @@ pub fn emitMir(
158 .strh_stack => try emit.mirLoadStoreStack(inst),158 .strh_stack => try emit.mirLoadStoreStack(inst),
159159
160 .ldr_stack_argument => try emit.mirLoadStackArgument(inst),160 .ldr_stack_argument => try emit.mirLoadStackArgument(inst),
161 .ldr_ptr_stack_argument => try emit.mirLoadStackArgument(inst),
161 .ldrb_stack_argument => try emit.mirLoadStackArgument(inst),162 .ldrb_stack_argument => try emit.mirLoadStackArgument(inst),
162 .ldrh_stack_argument => try emit.mirLoadStackArgument(inst),163 .ldrh_stack_argument => try emit.mirLoadStackArgument(inst),
163 .ldrsb_stack_argument => try emit.mirLoadStackArgument(inst),164 .ldrsb_stack_argument => try emit.mirLoadStackArgument(inst),
...@@ -940,24 +941,42 @@ fn mirLoadStackArgument(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -940,24 +941,42 @@ fn mirLoadStackArgument(emit: *Emit, inst: Mir.Inst.Index) !void {
940 const load_store_stack = emit.mir.instructions.items(.data)[inst].load_store_stack;941 const load_store_stack = emit.mir.instructions.items(.data)[inst].load_store_stack;
941 const rt = load_store_stack.rt;942 const rt = load_store_stack.rt;
942943
943 const raw_offset = emit.stack_size + emit.prologue_stack_space - load_store_stack.offset;944 const raw_offset = emit.stack_size + emit.saved_regs_stack_space + load_store_stack.offset;
944 const offset = switch (tag) {945 switch (tag) {
945 .ldrb_stack_argument, .ldrsb_stack_argument => blk: {946 .ldr_ptr_stack_argument => {
946 if (math.cast(u12, raw_offset)) |imm| {947 const offset = if (math.cast(u12, raw_offset)) |imm| imm else {
947 break :blk Instruction.LoadStoreOffset.imm(imm);948 return emit.fail("TODO load stack argument ptr with larger offset", .{});
948 } else {949 };
950
951 switch (tag) {
952 .ldr_ptr_stack_argument => try emit.writeInstruction(Instruction.add(rt, .sp, offset, false)),
953 else => unreachable,
954 }
955 },
956 .ldrb_stack_argument, .ldrsb_stack_argument => {
957 const offset = if (math.cast(u12, raw_offset)) |imm| Instruction.LoadStoreOffset.imm(imm) else {
949 return emit.fail("TODO load stack argument byte with larger offset", .{});958 return emit.fail("TODO load stack argument byte with larger offset", .{});
959 };
960
961 switch (tag) {
962 .ldrb_stack_argument => try emit.writeInstruction(Instruction.ldrb(rt, .sp, offset)),
963 .ldrsb_stack_argument => try emit.writeInstruction(Instruction.ldrsb(rt, .sp, offset)),
964 else => unreachable,
950 }965 }
951 },966 },
952 .ldrh_stack_argument, .ldrsh_stack_argument => blk: {967 .ldrh_stack_argument, .ldrsh_stack_argument => {
953 assert(std.mem.isAlignedGeneric(u32, raw_offset, 2)); // misaligned stack entry968 assert(std.mem.isAlignedGeneric(u32, raw_offset, 2)); // misaligned stack entry
954 if (math.cast(u12, @divExact(raw_offset, 2))) |imm| {969 const offset = if (math.cast(u12, @divExact(raw_offset, 2))) |imm| Instruction.LoadStoreOffset.imm(imm) else {
955 break :blk Instruction.LoadStoreOffset.imm(imm);
956 } else {
957 return emit.fail("TODO load stack argument halfword with larger offset", .{});970 return emit.fail("TODO load stack argument halfword with larger offset", .{});
971 };
972
973 switch (tag) {
974 .ldrh_stack_argument => try emit.writeInstruction(Instruction.ldrh(rt, .sp, offset)),
975 .ldrsh_stack_argument => try emit.writeInstruction(Instruction.ldrsh(rt, .sp, offset)),
976 else => unreachable,
958 }977 }
959 },978 },
960 .ldr_stack_argument => blk: {979 .ldr_stack_argument => {
961 const alignment: u32 = switch (rt.size()) {980 const alignment: u32 = switch (rt.size()) {
962 32 => 4,981 32 => 4,
963 64 => 8,982 64 => 8,
...@@ -965,22 +984,16 @@ fn mirLoadStackArgument(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -965,22 +984,16 @@ fn mirLoadStackArgument(emit: *Emit, inst: Mir.Inst.Index) !void {
965 };984 };
966985
967 assert(std.mem.isAlignedGeneric(u32, raw_offset, alignment)); // misaligned stack entry986 assert(std.mem.isAlignedGeneric(u32, raw_offset, alignment)); // misaligned stack entry
968 if (math.cast(u12, @divExact(raw_offset, alignment))) |imm| {987 const offset = if (math.cast(u12, @divExact(raw_offset, alignment))) |imm| Instruction.LoadStoreOffset.imm(imm) else {
969 break :blk Instruction.LoadStoreOffset.imm(imm);
970 } else {
971 return emit.fail("TODO load stack argument with larger offset", .{});988 return emit.fail("TODO load stack argument with larger offset", .{});
989 };
990
991 switch (tag) {
992 .ldr_stack_argument => try emit.writeInstruction(Instruction.ldr(rt, .sp, offset)),
993 else => unreachable,
972 }994 }
973 },995 },
974 else => unreachable,996 else => unreachable,
975 };
976
977 switch (tag) {
978 .ldr_stack_argument => try emit.writeInstruction(Instruction.ldr(rt, .sp, offset)),
979 .ldrb_stack_argument => try emit.writeInstruction(Instruction.ldrb(rt, .sp, offset)),
980 .ldrh_stack_argument => try emit.writeInstruction(Instruction.ldrh(rt, .sp, offset)),
981 .ldrsb_stack_argument => try emit.writeInstruction(Instruction.ldrsb(rt, .sp, offset)),
982 .ldrsh_stack_argument => try emit.writeInstruction(Instruction.ldrsh(rt, .sp, offset)),
983 else => unreachable,
984 }997 }
985}998}
986999
src/arch/aarch64/Mir.zig+2
...@@ -92,6 +92,8 @@ pub const Inst = struct {...@@ -92,6 +92,8 @@ pub const Inst = struct {
92 load_memory_ptr_direct,92 load_memory_ptr_direct,
93 /// Load Pair of Registers93 /// Load Pair of Registers
94 ldp,94 ldp,
95 /// Pseudo-instruction: Load pointer to stack argument
96 ldr_ptr_stack_argument,
95 /// Pseudo-instruction: Load from stack97 /// Pseudo-instruction: Load from stack
96 ldr_stack,98 ldr_stack,
97 /// Pseudo-instruction: Load from stack argument99 /// Pseudo-instruction: Load from stack argument