aboutsummaryrefslogtreecommitdiff
path: root/src/arch/aarch64/Emit.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/aarch64/Emit.zig')
-rw-r--r--src/arch/aarch64/Emit.zig40
1 files changed, 40 insertions, 0 deletions
diff --git a/src/arch/aarch64/Emit.zig b/src/arch/aarch64/Emit.zig
index 077330f0ca..ac731636bd 100644
--- a/src/arch/aarch64/Emit.zig
+++ b/src/arch/aarch64/Emit.zig
@@ -162,6 +162,17 @@ pub fn emitMir(
.push_regs => try emit.mirPushPopRegs(inst),
.pop_regs => try emit.mirPushPopRegs(inst),
+
+ .sbfx,
+ .ubfx,
+ => try emit.mirBitfieldExtract(inst),
+
+ .sxtb,
+ .sxth,
+ .sxtw,
+ .uxtb,
+ .uxth,
+ => try emit.mirExtend(inst),
}
}
}
@@ -1050,3 +1061,32 @@ fn mirPushPopRegs(emit: *Emit, inst: Mir.Inst.Index) !void {
else => unreachable,
}
}
+
+fn mirBitfieldExtract(emit: *Emit, inst: Mir.Inst.Index) !void {
+ const tag = emit.mir.instructions.items(.tag)[inst];
+ const rr_lsb_width = emit.mir.instructions.items(.data)[inst].rr_lsb_width;
+ const rd = rr_lsb_width.rd;
+ const rn = rr_lsb_width.rn;
+ const lsb = rr_lsb_width.lsb;
+ const width = rr_lsb_width.width;
+
+ switch (tag) {
+ .sbfx => try emit.writeInstruction(Instruction.sbfx(rd, rn, lsb, width)),
+ .ubfx => try emit.writeInstruction(Instruction.ubfx(rd, rn, lsb, width)),
+ else => unreachable,
+ }
+}
+
+fn mirExtend(emit: *Emit, inst: Mir.Inst.Index) !void {
+ const tag = emit.mir.instructions.items(.tag)[inst];
+ const rr = emit.mir.instructions.items(.data)[inst].rr;
+
+ switch (tag) {
+ .sxtb => try emit.writeInstruction(Instruction.sxtb(rr.rd, rr.rn)),
+ .sxth => try emit.writeInstruction(Instruction.sxth(rr.rd, rr.rn)),
+ .sxtw => try emit.writeInstruction(Instruction.sxtw(rr.rd, rr.rn)),
+ .uxtb => try emit.writeInstruction(Instruction.uxtb(rr.rd, rr.rn)),
+ .uxth => try emit.writeInstruction(Instruction.uxth(rr.rd, rr.rn)),
+ else => unreachable,
+ }
+}