| ... | ... | @@ -150,6 +150,7 @@ pub fn emitMir( |
| 150 | 150 | .ldp => try emit.mirLoadStoreRegisterPair(inst), |
| 151 | 151 | .stp => try emit.mirLoadStoreRegisterPair(inst), |
| 152 | 152 | |
| 153 | .ldr_ptr_stack => try emit.mirLoadStoreStack(inst), |
| 153 | 154 | .ldr_stack => try emit.mirLoadStoreStack(inst), |
| 154 | 155 | .ldrb_stack => try emit.mirLoadStoreStack(inst), |
| 155 | 156 | .ldrh_stack => try emit.mirLoadStoreStack(inst), |
| ... | ... | @@ -159,8 +160,8 @@ pub fn emitMir( |
| 159 | 160 | .strb_stack => try emit.mirLoadStoreStack(inst), |
| 160 | 161 | .strh_stack => try emit.mirLoadStoreStack(inst), |
| 161 | 162 | |
| 162 | | .ldr_stack_argument => try emit.mirLoadStackArgument(inst), |
| 163 | 163 | .ldr_ptr_stack_argument => try emit.mirLoadStackArgument(inst), |
| 164 | .ldr_stack_argument => try emit.mirLoadStackArgument(inst), |
| 164 | 165 | .ldrb_stack_argument => try emit.mirLoadStackArgument(inst), |
| 165 | 166 | .ldrh_stack_argument => try emit.mirLoadStackArgument(inst), |
| 166 | 167 | .ldrsb_stack_argument => try emit.mirLoadStackArgument(inst), |
| ... | ... | @@ -1003,23 +1004,43 @@ fn mirLoadStoreStack(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 1003 | 1004 | const rt = load_store_stack.rt; |
| 1004 | 1005 | |
| 1005 | 1006 | const raw_offset = emit.stack_size - load_store_stack.offset; |
| 1006 | | const offset = switch (tag) { |
| 1007 | | .ldrb_stack, .ldrsb_stack, .strb_stack => blk: { |
| 1008 | | if (math.cast(u12, raw_offset)) |imm| { |
| 1009 | | break :blk Instruction.LoadStoreOffset.imm(imm); |
| 1010 | | } else { |
| 1007 | switch (tag) { |
| 1008 | .ldr_ptr_stack => { |
| 1009 | const offset = if (math.cast(u12, raw_offset)) |imm| imm else { |
| 1010 | return emit.fail("TODO load stack argument ptr with larger offset", .{}); |
| 1011 | }; |
| 1012 | |
| 1013 | switch (tag) { |
| 1014 | .ldr_ptr_stack => try emit.writeInstruction(Instruction.add(rt, .sp, offset, false)), |
| 1015 | else => unreachable, |
| 1016 | } |
| 1017 | }, |
| 1018 | .ldrb_stack, .ldrsb_stack, .strb_stack => { |
| 1019 | const offset = if (math.cast(u12, raw_offset)) |imm| Instruction.LoadStoreOffset.imm(imm) else { |
| 1011 | 1020 | return emit.fail("TODO load/store stack byte with larger offset", .{}); |
| 1021 | }; |
| 1022 | |
| 1023 | switch (tag) { |
| 1024 | .ldrb_stack => try emit.writeInstruction(Instruction.ldrb(rt, .sp, offset)), |
| 1025 | .ldrsb_stack => try emit.writeInstruction(Instruction.ldrsb(rt, .sp, offset)), |
| 1026 | .strb_stack => try emit.writeInstruction(Instruction.strb(rt, .sp, offset)), |
| 1027 | else => unreachable, |
| 1012 | 1028 | } |
| 1013 | 1029 | }, |
| 1014 | | .ldrh_stack, .ldrsh_stack, .strh_stack => blk: { |
| 1030 | .ldrh_stack, .ldrsh_stack, .strh_stack => { |
| 1015 | 1031 | assert(std.mem.isAlignedGeneric(u32, raw_offset, 2)); // misaligned stack entry |
| 1016 | | if (math.cast(u12, @divExact(raw_offset, 2))) |imm| { |
| 1017 | | break :blk Instruction.LoadStoreOffset.imm(imm); |
| 1018 | | } else { |
| 1032 | const offset = if (math.cast(u12, @divExact(raw_offset, 2))) |imm| Instruction.LoadStoreOffset.imm(imm) else { |
| 1019 | 1033 | return emit.fail("TODO load/store stack halfword with larger offset", .{}); |
| 1034 | }; |
| 1035 | |
| 1036 | switch (tag) { |
| 1037 | .ldrh_stack => try emit.writeInstruction(Instruction.ldrh(rt, .sp, offset)), |
| 1038 | .ldrsh_stack => try emit.writeInstruction(Instruction.ldrsh(rt, .sp, offset)), |
| 1039 | .strh_stack => try emit.writeInstruction(Instruction.strh(rt, .sp, offset)), |
| 1040 | else => unreachable, |
| 1020 | 1041 | } |
| 1021 | 1042 | }, |
| 1022 | | .ldr_stack, .str_stack => blk: { |
| 1043 | .ldr_stack, .str_stack => { |
| 1023 | 1044 | const alignment: u32 = switch (rt.size()) { |
| 1024 | 1045 | 32 => 4, |
| 1025 | 1046 | 64 => 8, |
| ... | ... | @@ -1027,25 +1048,17 @@ fn mirLoadStoreStack(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 1027 | 1048 | }; |
| 1028 | 1049 | |
| 1029 | 1050 | assert(std.mem.isAlignedGeneric(u32, raw_offset, alignment)); // misaligned stack entry |
| 1030 | | if (math.cast(u12, @divExact(raw_offset, alignment))) |imm| { |
| 1031 | | break :blk Instruction.LoadStoreOffset.imm(imm); |
| 1032 | | } else { |
| 1051 | const offset = if (math.cast(u12, @divExact(raw_offset, alignment))) |imm| Instruction.LoadStoreOffset.imm(imm) else { |
| 1033 | 1052 | return emit.fail("TODO load/store stack with larger offset", .{}); |
| 1053 | }; |
| 1054 | |
| 1055 | switch (tag) { |
| 1056 | .ldr_stack => try emit.writeInstruction(Instruction.ldr(rt, .sp, offset)), |
| 1057 | .str_stack => try emit.writeInstruction(Instruction.str(rt, .sp, offset)), |
| 1058 | else => unreachable, |
| 1034 | 1059 | } |
| 1035 | 1060 | }, |
| 1036 | 1061 | else => unreachable, |
| 1037 | | }; |
| 1038 | | |
| 1039 | | switch (tag) { |
| 1040 | | .ldr_stack => try emit.writeInstruction(Instruction.ldr(rt, .sp, offset)), |
| 1041 | | .ldrb_stack => try emit.writeInstruction(Instruction.ldrb(rt, .sp, offset)), |
| 1042 | | .ldrh_stack => try emit.writeInstruction(Instruction.ldrh(rt, .sp, offset)), |
| 1043 | | .ldrsb_stack => try emit.writeInstruction(Instruction.ldrsb(rt, .sp, offset)), |
| 1044 | | .ldrsh_stack => try emit.writeInstruction(Instruction.ldrsh(rt, .sp, offset)), |
| 1045 | | .str_stack => try emit.writeInstruction(Instruction.str(rt, .sp, offset)), |
| 1046 | | .strb_stack => try emit.writeInstruction(Instruction.strb(rt, .sp, offset)), |
| 1047 | | .strh_stack => try emit.writeInstruction(Instruction.strh(rt, .sp, offset)), |
| 1048 | | else => unreachable, |
| 1049 | 1062 | } |
| 1050 | 1063 | } |
| 1051 | 1064 | |