| ... | ... | @@ -1540,14 +1540,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1540 | 1540 | } |
| 1541 | 1541 | |
| 1542 | 1542 | fn genCondBr(self: *Self, inst: *ir.Inst.CondBr) !MCValue { |
| 1543 | | // TODO Rework this so that the arch-independent logic isn't buried and duplicated. |
| 1544 | | switch (arch) { |
| 1545 | | .x86_64 => { |
| 1543 | const cond = try self.resolveInst(inst.condition); |
| 1544 | |
| 1545 | // TODO deal with liveness / deaths condbr's then_entry_deaths and else_entry_deaths |
| 1546 | const reloc: Reloc = switch (arch) { |
| 1547 | .i386, .x86_64 => reloc: { |
| 1546 | 1548 | try self.code.ensureCapacity(self.code.items.len + 6); |
| 1547 | 1549 | |
| 1548 | | const cond = try self.resolveInst(inst.condition); |
| 1549 | | switch (cond) { |
| 1550 | | .compare_flags_signed => |cmp_op| { |
| 1550 | const opcode: u8 = switch (cond) { |
| 1551 | .compare_flags_signed => |cmp_op| blk: { |
| 1551 | 1552 | // Here we map to the opposite opcode because the jump is to the false branch. |
| 1552 | 1553 | const opcode: u8 = switch (cmp_op) { |
| 1553 | 1554 | .gte => 0x8c, |
| ... | ... | @@ -1557,9 +1558,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1557 | 1558 | .lte => 0x8f, |
| 1558 | 1559 | .eq => 0x85, |
| 1559 | 1560 | }; |
| 1560 | | return self.genX86CondBr(inst, opcode); |
| 1561 | break :blk opcode; |
| 1561 | 1562 | }, |
| 1562 | | .compare_flags_unsigned => |cmp_op| { |
| 1563 | .compare_flags_unsigned => |cmp_op| blk: { |
| 1563 | 1564 | // Here we map to the opposite opcode because the jump is to the false branch. |
| 1564 | 1565 | const opcode: u8 = switch (cmp_op) { |
| 1565 | 1566 | .gte => 0x82, |
| ... | ... | @@ -1569,9 +1570,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1569 | 1570 | .lte => 0x87, |
| 1570 | 1571 | .eq => 0x85, |
| 1571 | 1572 | }; |
| 1572 | | return self.genX86CondBr(inst, opcode); |
| 1573 | break :blk opcode; |
| 1573 | 1574 | }, |
| 1574 | | .register => |reg| { |
| 1575 | .register => |reg| blk: { |
| 1575 | 1576 | // test reg, 1 |
| 1576 | 1577 | // TODO detect al, ax, eax |
| 1577 | 1578 | try self.code.ensureCapacity(self.code.items.len + 4); |
| ... | ... | @@ -1583,20 +1584,17 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1583 | 1584 | @as(u8, 0xC0) | (0 << 3) | @truncate(u3, reg.id()), |
| 1584 | 1585 | 0x01, |
| 1585 | 1586 | }); |
| 1586 | | return self.genX86CondBr(inst, 0x84); |
| 1587 | break :blk 0x84; |
| 1587 | 1588 | }, |
| 1588 | 1589 | else => return self.fail(inst.base.src, "TODO implement condbr {} when condition is {}", .{ self.target.cpu.arch, @tagName(cond) }), |
| 1589 | | } |
| 1590 | }; |
| 1591 | self.code.appendSliceAssumeCapacity(&[_]u8{ 0x0f, opcode }); |
| 1592 | const reloc = Reloc{ .rel32 = self.code.items.len }; |
| 1593 | self.code.items.len += 4; |
| 1594 | break :reloc reloc; |
| 1590 | 1595 | }, |
| 1591 | | else => return self.fail(inst.base.src, "TODO implement condbr for {}", .{self.target.cpu.arch}), |
| 1592 | | } |
| 1593 | | } |
| 1594 | | |
| 1595 | | fn genX86CondBr(self: *Self, inst: *ir.Inst.CondBr, opcode: u8) !MCValue { |
| 1596 | | // TODO deal with liveness / deaths condbr's then_entry_deaths and else_entry_deaths |
| 1597 | | self.code.appendSliceAssumeCapacity(&[_]u8{ 0x0f, opcode }); |
| 1598 | | const reloc = Reloc{ .rel32 = self.code.items.len }; |
| 1599 | | self.code.items.len += 4; |
| 1596 | else => return self.fail(inst.base.src, "TODO implement condbr {}", .{ self.target.cpu.arch }), |
| 1597 | }; |
| 1600 | 1598 | try self.genBody(inst.then_body); |
| 1601 | 1599 | try self.performReloc(inst.base.src, reloc); |
| 1602 | 1600 | try self.genBody(inst.else_body); |