| ... | @@ -11,6 +11,7 @@ const link = @import("../../link.zig"); | ... | @@ -11,6 +11,7 @@ const link = @import("../../link.zig"); |
| 11 | const Module = @import("../../Module.zig"); | 11 | const Module = @import("../../Module.zig"); |
| 12 | const Type = @import("../../type.zig").Type; | 12 | const Type = @import("../../type.zig").Type; |
| 13 | const ErrorMsg = Module.ErrorMsg; | 13 | const ErrorMsg = Module.ErrorMsg; |
| | 14 | const Target = std.Target; |
| 14 | const assert = std.debug.assert; | 15 | const assert = std.debug.assert; |
| 15 | const DW = std.dwarf; | 16 | const DW = std.dwarf; |
| 16 | const leb128 = std.leb; | 17 | const leb128 = std.leb; |
| ... | @@ -93,6 +94,8 @@ pub fn emitMir( | ... | @@ -93,6 +94,8 @@ pub fn emitMir( |
| 93 | .sub => try emit.mirDataProcessing(inst), | 94 | .sub => try emit.mirDataProcessing(inst), |
| 94 | .subs => try emit.mirDataProcessing(inst), | 95 | .subs => try emit.mirDataProcessing(inst), |
| 95 | | 96 | |
| | 97 | .sub_sp_scratch_r0 => try emit.mirSubStackPointer(inst), |
| | 98 | |
| 96 | .asr => try emit.mirShift(inst), | 99 | .asr => try emit.mirShift(inst), |
| 97 | .lsl => try emit.mirShift(inst), | 100 | .lsl => try emit.mirShift(inst), |
| 98 | .lsr => try emit.mirShift(inst), | 101 | .lsr => try emit.mirShift(inst), |
| ... | @@ -190,6 +193,24 @@ fn instructionSize(emit: *Emit, inst: Mir.Inst.Index) usize { | ... | @@ -190,6 +193,24 @@ fn instructionSize(emit: *Emit, inst: Mir.Inst.Index) usize { |
| 190 | .dbg_epilogue_begin, | 193 | .dbg_epilogue_begin, |
| 191 | .dbg_prologue_end, | 194 | .dbg_prologue_end, |
| 192 | => return 0, | 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 | else => return 4, | 214 | else => return 4, |
| 194 | } | 215 | } |
| 195 | } | 216 | } |
| ... | @@ -427,6 +448,37 @@ fn mirDataProcessing(emit: *Emit, inst: Mir.Inst.Index) !void { | ... | @@ -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 | fn mirShift(emit: *Emit, inst: Mir.Inst.Index) !void { | 482 | fn mirShift(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 431 | const tag = emit.mir.instructions.items(.tag)[inst]; | 483 | const tag = emit.mir.instructions.items(.tag)[inst]; |
| 432 | const cond = emit.mir.instructions.items(.cond)[inst]; | 484 | const cond = emit.mir.instructions.items(.cond)[inst]; |