diff options
| author | joachimschmidt557 <joachim.schmidt557@outlook.com> | 2020-12-28 18:17:22 +0100 |
|---|---|---|
| committer | joachimschmidt557 <joachim.schmidt557@outlook.com> | 2021-01-01 12:22:16 +0100 |
| commit | 85e1b47c40c023d8a3d75fadaeeb643a361bbc4d (patch) | |
| tree | 1b578d78315792ff73fa7abb3be3287260987ab1 /src/codegen.zig | |
| parent | 4d2919a1eed3a916f87cc5f838c9cd2b23ddef70 (diff) | |
| download | zig-85e1b47c40c023d8a3d75fadaeeb643a361bbc4d.tar.gz zig-85e1b47c40c023d8a3d75fadaeeb643a361bbc4d.zip | |
stage2 ARM: implement genCondBr for compare_flags
Diffstat (limited to 'src/codegen.zig')
| -rw-r--r-- | src/codegen.zig | 45 |
1 files changed, 42 insertions, 3 deletions
diff --git a/src/codegen.zig b/src/codegen.zig index a0e7968b97..4a02a8ffc0 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -1277,11 +1277,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { switch (op) { .add => { - // TODO runtime safety checks (overflow) writeInt(u32, try self.code.addManyAsArray(4), Instruction.add(.al, dst_reg, dst_reg, operand).toU32()); }, .sub => { - // TODO runtime safety checks (underflow) if (lhs_is_dest) { writeInt(u32, try self.code.addManyAsArray(4), Instruction.sub(.al, dst_reg, dst_reg, operand).toU32()); } else { @@ -1297,6 +1295,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { .not, .xor => { writeInt(u32, try self.code.addManyAsArray(4), Instruction.eor(.al, dst_reg, dst_reg, operand).toU32()); }, + .cmp_eq => { + writeInt(u32, try self.code.addManyAsArray(4), Instruction.cmp(.al, dst_reg, operand).toU32()); + }, else => unreachable, // not a binary instruction } } @@ -1957,6 +1958,20 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { .unsigned => MCValue{ .compare_flags_unsigned = op }, }; }, + .arm, .armeb => { + const lhs = try self.resolveInst(inst.lhs); + const rhs = try self.resolveInst(inst.rhs); + + const src_mcv = rhs; + const dst_mcv = if (lhs != .register) try self.copyToNewRegister(&inst.base, lhs) else lhs; + + try self.genArmBinOpCode(inst.base.src, dst_mcv.register, src_mcv, true, .cmp_eq); + const info = inst.lhs.ty.intInfo(self.target.*); + return switch (info.signedness) { + .signed => MCValue{ .compare_flags_signed = op }, + .unsigned => MCValue{ .compare_flags_unsigned = op }, + }; + }, else => return self.fail(inst.base.src, "TODO implement cmp for {}", .{self.target.cpu.arch}), } } @@ -2022,6 +2037,30 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { }, .arm, .armeb => reloc: { const condition: Condition = switch (cond) { + .compare_flags_signed => |cmp_op| blk: { + // Here we map to the opposite condition because the jump is to the false branch. + const condition: Condition = switch (cmp_op) { + .gte => .lt, + .gt => .le, + .neq => .eq, + .lt => .ge, + .lte => .gt, + .eq => .ne, + }; + break :blk condition; + }, + .compare_flags_unsigned => |cmp_op| blk: { + // Here we map to the opposite condition because the jump is to the false branch. + const condition: Condition = switch (cmp_op) { + .gte => .cc, + .gt => .ls, + .neq => .eq, + .lt => .cs, + .lte => .hi, + .eq => .ne, + }; + break :blk condition; + }, .register => |reg| blk: { // cmp reg, 1 // bne ... @@ -2253,7 +2292,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { .arm_branch => |info| { switch (arch) { .arm, .armeb => { - const amt = self.code.items.len - (info.pos + 4); + const amt = @intCast(i32, self.code.items.len) - @intCast(i32, info.pos + 8); if (math.cast(i26, amt)) |delta| { writeInt(u32, self.code.items[info.pos..][0..4], Instruction.b(info.cond, delta).toU32()); } else |_| { |
