| ... | ... | @@ -11,6 +11,7 @@ const link = @import("../../link.zig"); |
| 11 | 11 | const Module = @import("../../Module.zig"); |
| 12 | 12 | const Type = @import("../../type.zig").Type; |
| 13 | 13 | const ErrorMsg = Module.ErrorMsg; |
| 14 | const Target = std.Target; |
| 14 | 15 | const assert = std.debug.assert; |
| 15 | 16 | const DW = std.dwarf; |
| 16 | 17 | const leb128 = std.leb; |
| ... | ... | @@ -93,6 +94,8 @@ pub fn emitMir( |
| 93 | 94 | .sub => try emit.mirDataProcessing(inst), |
| 94 | 95 | .subs => try emit.mirDataProcessing(inst), |
| 95 | 96 | |
| 97 | .sub_sp_scratch_r0 => try emit.mirSubStackPointer(inst), |
| 98 | |
| 96 | 99 | .asr => try emit.mirShift(inst), |
| 97 | 100 | .lsl => try emit.mirShift(inst), |
| 98 | 101 | .lsr => try emit.mirShift(inst), |
| ... | ... | @@ -190,6 +193,24 @@ fn instructionSize(emit: *Emit, inst: Mir.Inst.Index) usize { |
| 190 | 193 | .dbg_epilogue_begin, |
| 191 | 194 | .dbg_prologue_end, |
| 192 | 195 | => return 0, |
| 196 | |
| 197 | .sub_sp_scratch_r0 => { |
| 198 | const imm32 = emit.mir.instructions.items(.data)[inst].imm32; |
| 199 | |
| 200 | if (imm32 == 0) { |
| 201 | return 0 * 4; |
| 202 | } else if (Instruction.Operand.fromU32(imm32) != null) { |
| 203 | // sub |
| 204 | return 1 * 4; |
| 205 | } else if (Target.arm.featureSetHas(emit.target.cpu.features, .has_v7)) { |
| 206 | // movw; movt; sub |
| 207 | return 3 * 4; |
| 208 | } else { |
| 209 | // mov; orr; orr; orr; sub |
| 210 | return 5 * 4; |
| 211 | } |
| 212 | }, |
| 213 | |
| 193 | 214 | else => return 4, |
| 194 | 215 | } |
| 195 | 216 | } |
| ... | ... | @@ -427,6 +448,37 @@ fn mirDataProcessing(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 427 | 448 | } |
| 428 | 449 | } |
| 429 | 450 | |
| 451 | fn mirSubStackPointer(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 452 | const tag = emit.mir.instructions.items(.tag)[inst]; |
| 453 | const cond = emit.mir.instructions.items(.cond)[inst]; |
| 454 | const imm32 = emit.mir.instructions.items(.data)[inst].imm32; |
| 455 | |
| 456 | switch (tag) { |
| 457 | .sub_sp_scratch_r0 => { |
| 458 | if (imm32 == 0) return; |
| 459 | |
| 460 | const operand = Instruction.Operand.fromU32(imm32) orelse blk: { |
| 461 | const scratch: Register = .r0; |
| 462 | |
| 463 | if (Target.arm.featureSetHas(emit.target.cpu.features, .has_v7)) { |
| 464 | try emit.writeInstruction(Instruction.movw(cond, scratch, @truncate(u16, imm32))); |
| 465 | try emit.writeInstruction(Instruction.movt(cond, scratch, @truncate(u16, imm32 >> 16))); |
| 466 | } else { |
| 467 | try emit.writeInstruction(Instruction.mov(cond, scratch, Instruction.Operand.imm(@truncate(u8, imm32), 0))); |
| 468 | try emit.writeInstruction(Instruction.orr(cond, scratch, scratch, Instruction.Operand.imm(@truncate(u8, imm32 >> 8), 12))); |
| 469 | try emit.writeInstruction(Instruction.orr(cond, scratch, scratch, Instruction.Operand.imm(@truncate(u8, imm32 >> 16), 8))); |
| 470 | try emit.writeInstruction(Instruction.orr(cond, scratch, scratch, Instruction.Operand.imm(@truncate(u8, imm32 >> 24), 4))); |
| 471 | } |
| 472 | |
| 473 | break :blk Instruction.Operand.reg(scratch, Instruction.Operand.Shift.none); |
| 474 | }; |
| 475 | |
| 476 | try emit.writeInstruction(Instruction.sub(cond, .sp, .sp, operand)); |
| 477 | }, |
| 478 | else => unreachable, |
| 479 | } |
| 480 | } |
| 481 | |
| 430 | 482 | fn mirShift(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 431 | 483 | const tag = emit.mir.instructions.items(.tag)[inst]; |
| 432 | 484 | const cond = emit.mir.instructions.items(.cond)[inst]; |