| ... | ... | @@ -1277,11 +1277,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1277 | 1277 | |
| 1278 | 1278 | switch (op) { |
| 1279 | 1279 | .add => { |
| 1280 | | // TODO runtime safety checks (overflow) |
| 1281 | 1280 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.add(.al, dst_reg, dst_reg, operand).toU32()); |
| 1282 | 1281 | }, |
| 1283 | 1282 | .sub => { |
| 1284 | | // TODO runtime safety checks (underflow) |
| 1285 | 1283 | if (lhs_is_dest) { |
| 1286 | 1284 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.sub(.al, dst_reg, dst_reg, operand).toU32()); |
| 1287 | 1285 | } else { |
| ... | ... | @@ -1297,6 +1295,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1297 | 1295 | .not, .xor => { |
| 1298 | 1296 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.eor(.al, dst_reg, dst_reg, operand).toU32()); |
| 1299 | 1297 | }, |
| 1298 | .cmp_eq => { |
| 1299 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.cmp(.al, dst_reg, operand).toU32()); |
| 1300 | }, |
| 1300 | 1301 | else => unreachable, // not a binary instruction |
| 1301 | 1302 | } |
| 1302 | 1303 | } |
| ... | ... | @@ -1957,6 +1958,20 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1957 | 1958 | .unsigned => MCValue{ .compare_flags_unsigned = op }, |
| 1958 | 1959 | }; |
| 1959 | 1960 | }, |
| 1961 | .arm, .armeb => { |
| 1962 | const lhs = try self.resolveInst(inst.lhs); |
| 1963 | const rhs = try self.resolveInst(inst.rhs); |
| 1964 | |
| 1965 | const src_mcv = rhs; |
| 1966 | const dst_mcv = if (lhs != .register) try self.copyToNewRegister(&inst.base, lhs) else lhs; |
| 1967 | |
| 1968 | try self.genArmBinOpCode(inst.base.src, dst_mcv.register, src_mcv, true, .cmp_eq); |
| 1969 | const info = inst.lhs.ty.intInfo(self.target.*); |
| 1970 | return switch (info.signedness) { |
| 1971 | .signed => MCValue{ .compare_flags_signed = op }, |
| 1972 | .unsigned => MCValue{ .compare_flags_unsigned = op }, |
| 1973 | }; |
| 1974 | }, |
| 1960 | 1975 | else => return self.fail(inst.base.src, "TODO implement cmp for {}", .{self.target.cpu.arch}), |
| 1961 | 1976 | } |
| 1962 | 1977 | } |
| ... | ... | @@ -2022,6 +2037,30 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2022 | 2037 | }, |
| 2023 | 2038 | .arm, .armeb => reloc: { |
| 2024 | 2039 | const condition: Condition = switch (cond) { |
| 2040 | .compare_flags_signed => |cmp_op| blk: { |
| 2041 | // Here we map to the opposite condition because the jump is to the false branch. |
| 2042 | const condition: Condition = switch (cmp_op) { |
| 2043 | .gte => .lt, |
| 2044 | .gt => .le, |
| 2045 | .neq => .eq, |
| 2046 | .lt => .ge, |
| 2047 | .lte => .gt, |
| 2048 | .eq => .ne, |
| 2049 | }; |
| 2050 | break :blk condition; |
| 2051 | }, |
| 2052 | .compare_flags_unsigned => |cmp_op| blk: { |
| 2053 | // Here we map to the opposite condition because the jump is to the false branch. |
| 2054 | const condition: Condition = switch (cmp_op) { |
| 2055 | .gte => .cc, |
| 2056 | .gt => .ls, |
| 2057 | .neq => .eq, |
| 2058 | .lt => .cs, |
| 2059 | .lte => .hi, |
| 2060 | .eq => .ne, |
| 2061 | }; |
| 2062 | break :blk condition; |
| 2063 | }, |
| 2025 | 2064 | .register => |reg| blk: { |
| 2026 | 2065 | // cmp reg, 1 |
| 2027 | 2066 | // bne ... |
| ... | ... | @@ -2253,7 +2292,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2253 | 2292 | .arm_branch => |info| { |
| 2254 | 2293 | switch (arch) { |
| 2255 | 2294 | .arm, .armeb => { |
| 2256 | | const amt = self.code.items.len - (info.pos + 4); |
| 2295 | const amt = @intCast(i32, self.code.items.len) - @intCast(i32, info.pos + 8); |
| 2257 | 2296 | if (math.cast(i26, amt)) |delta| { |
| 2258 | 2297 | writeInt(u32, self.code.items[info.pos..][0..4], Instruction.b(info.cond, delta).toU32()); |
| 2259 | 2298 | } else |_| { |