| ... | @@ -1540,14 +1540,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -1540,14 +1540,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1540 | } | 1540 | } |
| 1541 | | 1541 | |
| 1542 | fn genCondBr(self: *Self, inst: *ir.Inst.CondBr) !MCValue { | 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. | 1543 | const cond = try self.resolveInst(inst.condition); |
| 1544 | switch (arch) { | 1544 | |
| 1545 | .x86_64 => { | 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 | try self.code.ensureCapacity(self.code.items.len + 6); | 1548 | try self.code.ensureCapacity(self.code.items.len + 6); |
| 1547 | | 1549 | |
| 1548 | const cond = try self.resolveInst(inst.condition); | 1550 | const opcode: u8 = switch (cond) { |
| 1549 | switch (cond) { | 1551 | .compare_flags_signed => |cmp_op| blk: { |
| 1550 | .compare_flags_signed => |cmp_op| { | | |
| 1551 | // Here we map to the opposite opcode because the jump is to the false branch. | 1552 | // Here we map to the opposite opcode because the jump is to the false branch. |
| 1552 | const opcode: u8 = switch (cmp_op) { | 1553 | const opcode: u8 = switch (cmp_op) { |
| 1553 | .gte => 0x8c, | 1554 | .gte => 0x8c, |
| ... | @@ -1557,9 +1558,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -1557,9 +1558,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1557 | .lte => 0x8f, | 1558 | .lte => 0x8f, |
| 1558 | .eq => 0x85, | 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 | // Here we map to the opposite opcode because the jump is to the false branch. | 1564 | // Here we map to the opposite opcode because the jump is to the false branch. |
| 1564 | const opcode: u8 = switch (cmp_op) { | 1565 | const opcode: u8 = switch (cmp_op) { |
| 1565 | .gte => 0x82, | 1566 | .gte => 0x82, |
| ... | @@ -1569,9 +1570,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -1569,9 +1570,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1569 | .lte => 0x87, | 1570 | .lte => 0x87, |
| 1570 | .eq => 0x85, | 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 | // test reg, 1 | 1576 | // test reg, 1 |
| 1576 | // TODO detect al, ax, eax | 1577 | // TODO detect al, ax, eax |
| 1577 | try self.code.ensureCapacity(self.code.items.len + 4); | 1578 | try self.code.ensureCapacity(self.code.items.len + 4); |
| ... | @@ -1583,20 +1584,17 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -1583,20 +1584,17 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1583 | @as(u8, 0xC0) | (0 << 3) | @truncate(u3, reg.id()), | 1584 | @as(u8, 0xC0) | (0 << 3) | @truncate(u3, reg.id()), |
| 1584 | 0x01, | 1585 | 0x01, |
| 1585 | }); | 1586 | }); |
| 1586 | return self.genX86CondBr(inst, 0x84); | 1587 | break :blk 0x84; |
| 1587 | }, | 1588 | }, |
| 1588 | else => return self.fail(inst.base.src, "TODO implement condbr {} when condition is {}", .{ self.target.cpu.arch, @tagName(cond) }), | 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}), | 1596 | else => return self.fail(inst.base.src, "TODO implement condbr {}", .{ self.target.cpu.arch }), |
| 1592 | } | 1597 | }; |
| 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; | | |
| 1600 | try self.genBody(inst.then_body); | 1598 | try self.genBody(inst.then_body); |
| 1601 | try self.performReloc(inst.base.src, reloc); | 1599 | try self.performReloc(inst.base.src, reloc); |
| 1602 | try self.genBody(inst.else_body); | 1600 | try self.genBody(inst.else_body); |