aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/arm.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-08-20 19:05:05 -0400
committerGitHub <noreply@github.com>2021-08-20 19:05:05 -0400
commita2438357e1f0f3853886a128f272cd27c714b176 (patch)
treef5b200eedeee3aab50b0bfe69e50e2e1a72bb8eb /src/codegen/arm.zig
parent0cd361219c107bce48f2d7b44c6f3dd05ea6ccf4 (diff)
parent224fe49be23c44095d39297a4986782bd19ce8b2 (diff)
downloadzig-a2438357e1f0f3853886a128f272cd27c714b176.tar.gz
zig-a2438357e1f0f3853886a128f272cd27c714b176.zip
Merge pull request #9597 from joachimschmidt557/stage2-arm-bitshift
stage2 ARM: implement bitshifts
Diffstat (limited to 'src/codegen/arm.zig')
-rw-r--r--src/codegen/arm.zig87
1 files changed, 87 insertions, 0 deletions
diff --git a/src/codegen/arm.zig b/src/codegen/arm.zig
index 891a9e100b..d30479e1f1 100644
--- a/src/codegen/arm.zig
+++ b/src/codegen/arm.zig
@@ -1142,6 +1142,79 @@ pub const Instruction = union(enum) {
return stmdb(cond, .sp, true, @bitCast(RegisterList, register_list));
}
}
+
+ pub const ShiftAmount = union(enum) {
+ immediate: u5,
+ register: Register,
+
+ pub fn imm(immediate: u5) ShiftAmount {
+ return .{
+ .immediate = immediate,
+ };
+ }
+
+ pub fn reg(register: Register) ShiftAmount {
+ return .{
+ .register = register,
+ };
+ }
+ };
+
+ pub fn lsl(cond: Condition, rd: Register, rm: Register, shift: ShiftAmount) Instruction {
+ return switch (shift) {
+ .immediate => |imm| mov(cond, rd, Operand.reg(rm, Operand.Shift.imm(imm, .logical_left))),
+ .register => |reg| mov(cond, rd, Operand.reg(rm, Operand.Shift.reg(reg, .logical_left))),
+ };
+ }
+
+ pub fn lsr(cond: Condition, rd: Register, rm: Register, shift: ShiftAmount) Instruction {
+ return switch (shift) {
+ .immediate => |imm| mov(cond, rd, Operand.reg(rm, Operand.Shift.imm(imm, .logical_right))),
+ .register => |reg| mov(cond, rd, Operand.reg(rm, Operand.Shift.reg(reg, .logical_right))),
+ };
+ }
+
+ pub fn asr(cond: Condition, rd: Register, rm: Register, shift: ShiftAmount) Instruction {
+ return switch (shift) {
+ .immediate => |imm| mov(cond, rd, Operand.reg(rm, Operand.Shift.imm(imm, .arithmetic_right))),
+ .register => |reg| mov(cond, rd, Operand.reg(rm, Operand.Shift.reg(reg, .arithmetic_right))),
+ };
+ }
+
+ pub fn ror(cond: Condition, rd: Register, rm: Register, shift: ShiftAmount) Instruction {
+ return switch (shift) {
+ .immediate => |imm| mov(cond, rd, Operand.reg(rm, Operand.Shift.imm(imm, .rotate_right))),
+ .register => |reg| mov(cond, rd, Operand.reg(rm, Operand.Shift.reg(reg, .rotate_right))),
+ };
+ }
+
+ pub fn lsls(cond: Condition, rd: Register, rm: Register, shift: ShiftAmount) Instruction {
+ return switch (shift) {
+ .immediate => |imm| movs(cond, rd, Operand.reg(rm, Operand.Shift.imm(imm, .logical_left))),
+ .register => |reg| movs(cond, rd, Operand.reg(rm, Operand.Shift.reg(reg, .logical_left))),
+ };
+ }
+
+ pub fn lsrs(cond: Condition, rd: Register, rm: Register, shift: ShiftAmount) Instruction {
+ return switch (shift) {
+ .immediate => |imm| movs(cond, rd, Operand.reg(rm, Operand.Shift.imm(imm, .logical_right))),
+ .register => |reg| movs(cond, rd, Operand.reg(rm, Operand.Shift.reg(reg, .logical_right))),
+ };
+ }
+
+ pub fn asrs(cond: Condition, rd: Register, rm: Register, shift: ShiftAmount) Instruction {
+ return switch (shift) {
+ .immediate => |imm| movs(cond, rd, Operand.reg(rm, Operand.Shift.imm(imm, .arithmetic_right))),
+ .register => |reg| movs(cond, rd, Operand.reg(rm, Operand.Shift.reg(reg, .arithmetic_right))),
+ };
+ }
+
+ pub fn rors(cond: Condition, rd: Register, rm: Register, shift: ShiftAmount) Instruction {
+ return switch (shift) {
+ .immediate => |imm| movs(cond, rd, Operand.reg(rm, Operand.Shift.imm(imm, .rotate_right))),
+ .register => |reg| movs(cond, rd, Operand.reg(rm, Operand.Shift.reg(reg, .rotate_right))),
+ };
+ }
};
test "serialize instructions" {
@@ -1262,6 +1335,20 @@ test "aliases" {
.actual = Instruction.push(.al, .{ .r0, .r2 }),
.expected = Instruction.stmdb(.al, .sp, true, .{ .r0 = true, .r2 = true }),
},
+ .{ // lsl r4, r5, #5
+ .actual = Instruction.lsl(.al, .r4, .r5, Instruction.ShiftAmount.imm(5)),
+ .expected = Instruction.mov(.al, .r4, Instruction.Operand.reg(
+ .r5,
+ Instruction.Operand.Shift.imm(5, .logical_left),
+ )),
+ },
+ .{ // asrs r1, r1, r3
+ .actual = Instruction.asrs(.al, .r1, .r1, Instruction.ShiftAmount.reg(.r3)),
+ .expected = Instruction.movs(.al, .r1, Instruction.Operand.reg(
+ .r1,
+ Instruction.Operand.Shift.reg(.r3, .arithmetic_right),
+ )),
+ },
};
for (testcases) |case| {