authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-07-30 23:17:15+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-08-05 20:30:51+02:00
logcf3aaceed9f2a9e1872bdd8b2cccecd1766e2419
treee43969bfb987275c48e8445b36a8d74929f9686a
parent423bef4dfc635a3ca0144cac95384984857a8519
signature Commit is signed but in an unrecognized format.

stage2 AArch64: introduce MCValue.stack_argument_offset

This new MCValue union member shares the same semantics as the MCValue type of the same name in the ARM backend.

3 files changed, 275 insertions(+), 9 deletions(-)

src/arch/aarch64/CodeGen.zig+201-9
...@@ -166,10 +166,12 @@ const MCValue = union(enum) {...@@ -166,10 +166,12 @@ const MCValue = union(enum) {
166 /// the type is u1) or true (if the type in bool) iff the166 /// the type is u1) or true (if the type in bool) iff the
167 /// specified condition is true.167 /// specified condition is true.
168 condition_flags: Condition,168 condition_flags: Condition,
169 /// The value is a function argument passed via the stack.
170 stack_argument_offset: u32,
169171
170 fn isMemory(mcv: MCValue) bool {172 fn isMemory(mcv: MCValue) bool {
171 return switch (mcv) {173 return switch (mcv) {
172 .memory, .stack_offset => true,174 .memory, .stack_offset, .stack_argument_offset => true,
173 else => false,175 else => false,
174 };176 };
175 }177 }
...@@ -192,6 +194,7 @@ const MCValue = union(enum) {...@@ -192,6 +194,7 @@ const MCValue = union(enum) {
192 .condition_flags,194 .condition_flags,
193 .ptr_stack_offset,195 .ptr_stack_offset,
194 .undef,196 .undef,
197 .stack_argument_offset,
195 => false,198 => false,
196199
197 .register,200 .register,
...@@ -337,6 +340,7 @@ pub fn generate(...@@ -337,6 +340,7 @@ pub fn generate(
337 .prev_di_line = module_fn.lbrace_line,340 .prev_di_line = module_fn.lbrace_line,
338 .prev_di_column = module_fn.lbrace_column,341 .prev_di_column = module_fn.lbrace_column,
339 .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,
340 };344 };
341 defer emit.deinit();345 defer emit.deinit();
342346
...@@ -2726,6 +2730,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -2726,6 +2730,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2726 },2730 },
2727 .memory,2731 .memory,
2728 .stack_offset,2732 .stack_offset,
2733 .stack_argument_offset,
2729 .got_load,2734 .got_load,
2730 .direct_load,2735 .direct_load,
2731 => {2736 => {
...@@ -2927,6 +2932,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -2927,6 +2932,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
2927 },2932 },
2928 .memory,2933 .memory,
2929 .stack_offset,2934 .stack_offset,
2935 .stack_argument_offset,
2930 .got_load,2936 .got_load,
2931 .direct_load,2937 .direct_load,
2932 => {2938 => {
...@@ -3009,6 +3015,9 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -3009,6 +3015,9 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
30093015
3010 switch (mcv) {3016 switch (mcv) {
3011 .dead, .unreach => unreachable,3017 .dead, .unreach => unreachable,
3018 .stack_argument_offset => |off| {
3019 break :result MCValue{ .stack_argument_offset = off - struct_field_offset };
3020 },
3012 .stack_offset => |off| {3021 .stack_offset => |off| {
3013 break :result MCValue{ .stack_offset = off - struct_field_offset };3022 break :result MCValue{ .stack_offset = off - struct_field_offset };
3014 },3023 },
...@@ -3152,12 +3161,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions....@@ -3152,12 +3161,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
3152 try self.register_manager.getReg(reg, null);3161 try self.register_manager.getReg(reg, null);
3153 try self.genSetReg(arg_ty, reg, arg_mcv);3162 try self.genSetReg(arg_ty, reg, arg_mcv);
3154 },3163 },
3155 .stack_offset => {3164 .stack_offset => unreachable,
3156 return self.fail("TODO implement calling with parameters in memory", .{});3165 .stack_argument_offset => |offset| try self.genSetStackArgument(
3157 },3166 arg_ty,
3158 .ptr_stack_offset => {3167 info.stack_byte_count - offset,
3159 return self.fail("TODO implement calling with MCValue.ptr_stack_offset arg", .{});3168 arg_mcv,
3160 },3169 ),
3161 else => unreachable,3170 else => unreachable,
3162 }3171 }
3163 }3172 }
...@@ -3884,7 +3893,7 @@ fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {...@@ -3884,7 +3893,7 @@ fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
3884 block_data.mcv = switch (operand_mcv) {3893 block_data.mcv = switch (operand_mcv) {
3885 .none, .dead, .unreach => unreachable,3894 .none, .dead, .unreach => unreachable,
3886 .register, .stack_offset, .memory => operand_mcv,3895 .register, .stack_offset, .memory => operand_mcv,
3887 .immediate, .condition_flags => blk: {3896 .immediate, .stack_argument_offset, .condition_flags => blk: {
3888 const new_mcv = try self.allocRegOrMem(block, true);3897 const new_mcv = try self.allocRegOrMem(block, true);
3889 try self.setRegOrMem(self.air.typeOfIndex(block), new_mcv, operand_mcv);3898 try self.setRegOrMem(self.air.typeOfIndex(block), new_mcv, operand_mcv);
3890 break :blk new_mcv;3899 break :blk new_mcv;
...@@ -4126,6 +4135,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -4126,6 +4135,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
4126 .got_load,4135 .got_load,
4127 .direct_load,4136 .direct_load,
4128 .memory,4137 .memory,
4138 .stack_argument_offset,
4129 .stack_offset,4139 .stack_offset,
4130 => {4140 => {
4131 switch (mcv) {4141 switch (mcv) {
...@@ -4328,6 +4338,188 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -4328,6 +4338,188 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
4328 else => unreachable,4338 else => unreachable,
4329 }4339 }
4330 },4340 },
4341 .stack_argument_offset => |off| {
4342 const abi_size = ty.abiSize(self.target.*);
4343
4344 switch (abi_size) {
4345 1, 2, 4, 8 => {
4346 const tag: Mir.Inst.Tag = switch (abi_size) {
4347 1 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsb_stack_argument else .ldrb_stack_argument,
4348 2 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsh_stack_argument else .ldrh_stack_argument,
4349 4, 8 => .ldr_stack_argument,
4350 else => unreachable, // unexpected abi size
4351 };
4352
4353 _ = try self.addInst(.{
4354 .tag = tag,
4355 .data = .{ .load_store_stack = .{
4356 .rt = reg,
4357 .offset = @intCast(u32, off),
4358 } },
4359 });
4360 },
4361 3, 5, 6, 7 => return self.fail("TODO implement genSetReg types size {}", .{abi_size}),
4362 else => unreachable,
4363 }
4364 },
4365 }
4366}
4367
4368fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void {
4369 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
4370 switch (mcv) {
4371 .dead => unreachable,
4372 .none, .unreach => return,
4373 .undef => {
4374 if (!self.wantSafety())
4375 return; // The already existing value will do just fine.
4376 // TODO Upgrade this to a memset call when we have that available.
4377 switch (ty.abiSize(self.target.*)) {
4378 1 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaa }),
4379 2 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }),
4380 4 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }),
4381 8 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaaaaaaaaaa }),
4382 else => return self.fail("TODO implement memset", .{}),
4383 }
4384 },
4385 .register => |reg| {
4386 switch (abi_size) {
4387 1, 2, 4, 8 => {
4388 const tag: Mir.Inst.Tag = switch (abi_size) {
4389 1 => .strb_immediate,
4390 2 => .strh_immediate,
4391 4, 8 => .str_immediate,
4392 else => unreachable, // unexpected abi size
4393 };
4394 const rt = registerAlias(reg, abi_size);
4395 const offset = switch (abi_size) {
4396 1 => blk: {
4397 if (math.cast(u12, stack_offset)) |imm| {
4398 break :blk Instruction.LoadStoreOffset.imm(imm);
4399 } else {
4400 return self.fail("TODO genSetStackArgument byte with larger offset", .{});
4401 }
4402 },
4403 2 => blk: {
4404 assert(std.mem.isAlignedGeneric(u32, stack_offset, 2)); // misaligned stack entry
4405 if (math.cast(u12, @divExact(stack_offset, 2))) |imm| {
4406 break :blk Instruction.LoadStoreOffset.imm(imm);
4407 } else {
4408 return self.fail("TODO getSetStackArgument halfword with larger offset", .{});
4409 }
4410 },
4411 4, 8 => blk: {
4412 const alignment = abi_size;
4413 assert(std.mem.isAlignedGeneric(u32, stack_offset, alignment)); // misaligned stack entry
4414 if (math.cast(u12, @divExact(stack_offset, alignment))) |imm| {
4415 break :blk Instruction.LoadStoreOffset.imm(imm);
4416 } else {
4417 return self.fail("TODO genSetStackArgument with larger offset", .{});
4418 }
4419 },
4420 else => unreachable,
4421 };
4422
4423 _ = try self.addInst(.{
4424 .tag = tag,
4425 .data = .{ .load_store_register_immediate = .{
4426 .rt = rt,
4427 .rn = .sp,
4428 .offset = offset.immediate,
4429 } },
4430 });
4431 },
4432 else => return self.fail("TODO genSetStackArgument other types abi_size={}", .{abi_size}),
4433 }
4434 },
4435 .register_with_overflow => {
4436 return self.fail("TODO implement genSetStack {}", .{mcv});
4437 },
4438 .got_load,
4439 .direct_load,
4440 .memory,
4441 .stack_argument_offset,
4442 .stack_offset,
4443 => {
4444 if (abi_size <= 4) {
4445 const reg = try self.copyToTmpRegister(ty, mcv);
4446 return self.genSetStackArgument(ty, stack_offset, MCValue{ .register = reg });
4447 } else {
4448 var ptr_ty_payload: Type.Payload.ElemType = .{
4449 .base = .{ .tag = .single_mut_pointer },
4450 .data = ty,
4451 };
4452 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
4453
4454 // TODO call extern memcpy
4455 const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }, gp);
4456 const regs_locks = self.register_manager.lockRegsAssumeUnused(5, regs);
4457 defer for (regs_locks) |reg| {
4458 self.register_manager.unlockReg(reg);
4459 };
4460
4461 const src_reg = regs[0];
4462 const dst_reg = regs[1];
4463 const len_reg = regs[2];
4464 const count_reg = regs[3];
4465 const tmp_reg = regs[4];
4466
4467 switch (mcv) {
4468 .stack_offset => |off| {
4469 // sub src_reg, fp, #off
4470 try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off });
4471 },
4472 .memory => |addr| try self.genSetReg(ptr_ty, src_reg, .{ .immediate = @intCast(u32, addr) }),
4473 .got_load,
4474 .direct_load,
4475 => |sym_index| {
4476 const tag: Mir.Inst.Tag = switch (mcv) {
4477 .got_load => .load_memory_ptr_got,
4478 .direct_load => .load_memory_ptr_direct,
4479 else => unreachable,
4480 };
4481 const mod = self.bin_file.options.module.?;
4482 _ = try self.addInst(.{
4483 .tag = tag,
4484 .data = .{
4485 .payload = try self.addExtra(Mir.LoadMemoryPie{
4486 .register = @enumToInt(src_reg),
4487 .atom_index = mod.declPtr(self.mod_fn.owner_decl).link.macho.sym_index,
4488 .sym_index = sym_index,
4489 }),
4490 },
4491 });
4492 },
4493 .stack_argument_offset => return self.fail("TODO load {}", .{mcv}),
4494 else => unreachable,
4495 }
4496
4497 // add dst_reg, sp, #stack_offset
4498 _ = try self.addInst(.{
4499 .tag = .add_immediate,
4500 .data = .{ .rr_imm12_sh = .{
4501 .rd = dst_reg,
4502 .rn = .sp,
4503 .imm12 = math.cast(u12, stack_offset) orelse {
4504 return self.fail("TODO load: set reg to stack offset with all possible offsets", .{});
4505 },
4506 } },
4507 });
4508
4509 // mov len, #abi_size
4510 try self.genSetReg(Type.usize, len_reg, .{ .immediate = abi_size });
4511
4512 // memcpy(src, dst, len)
4513 try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg);
4514 }
4515 },
4516 .condition_flags,
4517 .immediate,
4518 .ptr_stack_offset,
4519 => {
4520 const reg = try self.copyToTmpRegister(ty, mcv);
4521 return self.genSetStackArgument(ty, stack_offset, MCValue{ .register = reg });
4522 },
4331 }4523 }
4332}4524}
43334525
...@@ -4835,8 +5027,8 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -4835,8 +5027,8 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
4835 }5027 }
4836 }5028 }
48375029
4838 result.args[i] = .{ .stack_offset = nsaa };
4839 nsaa += param_size;5030 nsaa += param_size;
5031 result.args[i] = .{ .stack_argument_offset = nsaa };
4840 }5032 }
4841 }5033 }
48425034
src/arch/aarch64/Emit.zig+64
...@@ -27,14 +27,21 @@ code: *std.ArrayList(u8),...@@ -27,14 +27,21 @@ code: *std.ArrayList(u8),
2727
28prev_di_line: u32,28prev_di_line: u32,
29prev_di_column: u32,29prev_di_column: u32,
30
30/// Relative to the beginning of `code`.31/// Relative to the beginning of `code`.
31prev_di_pc: usize,32prev_di_pc: usize,
3233
34/// The amount of stack space consumed by all stack arguments as well
35/// as the saved callee-saved registers
36prologue_stack_space: u32,
37
33/// The branch type of every branch38/// The branch type of every branch
34branch_types: std.AutoHashMapUnmanaged(Mir.Inst.Index, BranchType) = .{},39branch_types: std.AutoHashMapUnmanaged(Mir.Inst.Index, BranchType) = .{},
40
35/// For every forward branch, maps the target instruction to a list of41/// For every forward branch, maps the target instruction to a list of
36/// branches which branch to this target instruction42/// branches which branch to this target instruction
37branch_forward_origins: std.AutoHashMapUnmanaged(Mir.Inst.Index, std.ArrayListUnmanaged(Mir.Inst.Index)) = .{},43branch_forward_origins: std.AutoHashMapUnmanaged(Mir.Inst.Index, std.ArrayListUnmanaged(Mir.Inst.Index)) = .{},
44
38/// For backward branches: stores the code offset of the target45/// For backward branches: stores the code offset of the target
39/// instruction46/// instruction
40///47///
...@@ -42,6 +49,8 @@ branch_forward_origins: std.AutoHashMapUnmanaged(Mir.Inst.Index, std.ArrayListUn...@@ -42,6 +49,8 @@ branch_forward_origins: std.AutoHashMapUnmanaged(Mir.Inst.Index, std.ArrayListUn
42/// instruction49/// instruction
43code_offset_mapping: std.AutoHashMapUnmanaged(Mir.Inst.Index, usize) = .{},50code_offset_mapping: std.AutoHashMapUnmanaged(Mir.Inst.Index, usize) = .{},
4451
52/// The final stack frame size of the function (already aligned to the
53/// respective stack alignment). Does not include prologue stack space.
45stack_size: u32,54stack_size: u32,
4655
47const InnerError = error{56const InnerError = error{
...@@ -148,6 +157,12 @@ pub fn emitMir(...@@ -148,6 +157,12 @@ pub fn emitMir(
148 .strb_stack => try emit.mirLoadStoreStack(inst),157 .strb_stack => try emit.mirLoadStoreStack(inst),
149 .strh_stack => try emit.mirLoadStoreStack(inst),158 .strh_stack => try emit.mirLoadStoreStack(inst),
150159
160 .ldr_stack_argument => try emit.mirLoadStackArgument(inst),
161 .ldrb_stack_argument => try emit.mirLoadStackArgument(inst),
162 .ldrh_stack_argument => try emit.mirLoadStackArgument(inst),
163 .ldrsb_stack_argument => try emit.mirLoadStackArgument(inst),
164 .ldrsh_stack_argument => try emit.mirLoadStackArgument(inst),
165
151 .ldr_register => try emit.mirLoadStoreRegisterRegister(inst),166 .ldr_register => try emit.mirLoadStoreRegisterRegister(inst),
152 .ldrb_register => try emit.mirLoadStoreRegisterRegister(inst),167 .ldrb_register => try emit.mirLoadStoreRegisterRegister(inst),
153 .ldrh_register => try emit.mirLoadStoreRegisterRegister(inst),168 .ldrh_register => try emit.mirLoadStoreRegisterRegister(inst),
...@@ -920,6 +935,55 @@ fn mirLoadStoreRegisterPair(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -920,6 +935,55 @@ fn mirLoadStoreRegisterPair(emit: *Emit, inst: Mir.Inst.Index) !void {
920 }935 }
921}936}
922937
938fn mirLoadStackArgument(emit: *Emit, inst: Mir.Inst.Index) !void {
939 const tag = emit.mir.instructions.items(.tag)[inst];
940 const load_store_stack = emit.mir.instructions.items(.data)[inst].load_store_stack;
941 const rt = load_store_stack.rt;
942
943 const raw_offset = emit.stack_size + emit.prologue_stack_space - load_store_stack.offset;
944 const offset = switch (tag) {
945 .ldrb_stack_argument, .ldrsb_stack_argument => blk: {
946 if (math.cast(u12, raw_offset)) |imm| {
947 break :blk Instruction.LoadStoreOffset.imm(imm);
948 } else {
949 return emit.fail("TODO load stack argument byte with larger offset", .{});
950 }
951 },
952 .ldrh_stack_argument, .ldrsh_stack_argument => blk: {
953 assert(std.mem.isAlignedGeneric(u32, raw_offset, 2)); // misaligned stack entry
954 if (math.cast(u12, @divExact(raw_offset, 2))) |imm| {
955 break :blk Instruction.LoadStoreOffset.imm(imm);
956 } else {
957 return emit.fail("TODO load stack argument halfword with larger offset", .{});
958 }
959 },
960 .ldr_stack_argument => blk: {
961 const alignment: u32 = switch (rt.size()) {
962 32 => 4,
963 64 => 8,
964 else => unreachable,
965 };
966
967 assert(std.mem.isAlignedGeneric(u32, raw_offset, alignment)); // misaligned stack entry
968 if (math.cast(u12, @divExact(raw_offset, alignment))) |imm| {
969 break :blk Instruction.LoadStoreOffset.imm(imm);
970 } else {
971 return emit.fail("TODO load stack argument with larger offset", .{});
972 }
973 },
974 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 }
985}
986
923fn mirLoadStoreStack(emit: *Emit, inst: Mir.Inst.Index) !void {987fn mirLoadStoreStack(emit: *Emit, inst: Mir.Inst.Index) !void {
924 const tag = emit.mir.instructions.items(.tag)[inst];988 const tag = emit.mir.instructions.items(.tag)[inst];
925 const load_store_stack = emit.mir.instructions.items(.data)[inst].load_store_stack;989 const load_store_stack = emit.mir.instructions.items(.data)[inst].load_store_stack;
src/arch/aarch64/Mir.zig+10
...@@ -94,18 +94,24 @@ pub const Inst = struct {...@@ -94,18 +94,24 @@ pub const Inst = struct {
94 ldp,94 ldp,
95 /// Pseudo-instruction: Load from stack95 /// Pseudo-instruction: Load from stack
96 ldr_stack,96 ldr_stack,
97 /// Pseudo-instruction: Load from stack argument
98 ldr_stack_argument,
97 /// Load Register (immediate)99 /// Load Register (immediate)
98 ldr_immediate,100 ldr_immediate,
99 /// Load Register (register)101 /// Load Register (register)
100 ldr_register,102 ldr_register,
101 /// Pseudo-instruction: Load byte from stack103 /// Pseudo-instruction: Load byte from stack
102 ldrb_stack,104 ldrb_stack,
105 /// Pseudo-instruction: Load byte from stack argument
106 ldrb_stack_argument,
103 /// Load Register Byte (immediate)107 /// Load Register Byte (immediate)
104 ldrb_immediate,108 ldrb_immediate,
105 /// Load Register Byte (register)109 /// Load Register Byte (register)
106 ldrb_register,110 ldrb_register,
107 /// Pseudo-instruction: Load halfword from stack111 /// Pseudo-instruction: Load halfword from stack
108 ldrh_stack,112 ldrh_stack,
113 /// Pseudo-instruction: Load halfword from stack argument
114 ldrh_stack_argument,
109 /// Load Register Halfword (immediate)115 /// Load Register Halfword (immediate)
110 ldrh_immediate,116 ldrh_immediate,
111 /// Load Register Halfword (register)117 /// Load Register Halfword (register)
...@@ -114,10 +120,14 @@ pub const Inst = struct {...@@ -114,10 +120,14 @@ pub const Inst = struct {
114 ldrsb_immediate,120 ldrsb_immediate,
115 /// Pseudo-instruction: Load signed byte from stack121 /// Pseudo-instruction: Load signed byte from stack
116 ldrsb_stack,122 ldrsb_stack,
123 /// Pseudo-instruction: Load signed byte from stack argument
124 ldrsb_stack_argument,
117 /// Load Register Signed Halfword (immediate)125 /// Load Register Signed Halfword (immediate)
118 ldrsh_immediate,126 ldrsh_immediate,
119 /// Pseudo-instruction: Load signed halfword from stack127 /// Pseudo-instruction: Load signed halfword from stack
120 ldrsh_stack,128 ldrsh_stack,
129 /// Pseudo-instruction: Load signed halfword from stack argument
130 ldrsh_stack_argument,
121 /// Load Register Signed Word (immediate)131 /// Load Register Signed Word (immediate)
122 ldrsw_immediate,132 ldrsw_immediate,
123 /// Logical Shift Left (immediate)133 /// Logical Shift Left (immediate)