authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-05-21 19:06:05+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-05-21 22:15:04+02:00
log9747303d16dfca61316a292d1e05ac901191e3a3
treea2375efaac6a04c5eb43d6bbf09bf8d633ce8d2a
parent1f5b0c11563d9ee0a284b708c7ca092da0a0b9ef

stage2 ARM: Introduce MCValue.cpsr_flags

MCValue.cpsr_flags replaces MCValue.compare_flags_{signed,unsigned}. This simplifies a lot of stuff and enables an MCValue to represent only the overflow bits in the CPU (previously, it was only possible to represent a register + the overflow bits).

1 files changed, 83 insertions(+), 122 deletions(-)

src/arch/arm/CodeGen.zig+83-122
...@@ -96,7 +96,7 @@ register_manager: RegisterManager = .{},...@@ -96,7 +96,7 @@ register_manager: RegisterManager = .{},
96/// Maps offset to what is stored there.96/// Maps offset to what is stored there.
97stack: std.AutoHashMapUnmanaged(u32, StackAllocation) = .{},97stack: std.AutoHashMapUnmanaged(u32, StackAllocation) = .{},
98/// Tracks the current instruction allocated to the compare flags98/// Tracks the current instruction allocated to the compare flags
99compare_flags_inst: ?Air.Inst.Index = null,99cpsr_flags_inst: ?Air.Inst.Index = null,
100100
101/// Offset from the stack base, representing the end of the stack frame.101/// Offset from the stack base, representing the end of the stack frame.
102max_end_stack: u32 = 0,102max_end_stack: u32 = 0,
...@@ -159,12 +159,11 @@ const MCValue = union(enum) {...@@ -159,12 +159,11 @@ const MCValue = union(enum) {
159 /// The value is a pointer to one of the stack variables (payload159 /// The value is a pointer to one of the stack variables (payload
160 /// is stack offset).160 /// is stack offset).
161 ptr_stack_offset: u32,161 ptr_stack_offset: u32,
162 /// The value is in the compare flags assuming an unsigned162 /// The value resides in the N, Z, C, V flags of the Current
163 /// operation, with this operator applied on top of it.163 /// Program Status Register (CPSR). The value is 1 (if the type is
164 compare_flags_unsigned: math.CompareOperator,164 /// u1) or true (if the type in bool) iff the specified condition
165 /// The value is in the compare flags assuming a signed operation,165 /// is true.
166 /// with this operator applied on top of it.166 cpsr_flags: Condition,
167 compare_flags_signed: math.CompareOperator,
168 /// The value is a function argument passed via the stack.167 /// The value is a function argument passed via the stack.
169 stack_argument_offset: u32,168 stack_argument_offset: u32,
170169
...@@ -190,8 +189,7 @@ const MCValue = union(enum) {...@@ -190,8 +189,7 @@ const MCValue = union(enum) {
190189
191 .immediate,190 .immediate,
192 .memory,191 .memory,
193 .compare_flags_unsigned,192 .cpsr_flags,
194 .compare_flags_signed,
195 .ptr_stack_offset,193 .ptr_stack_offset,
196 .undef,194 .undef,
197 .stack_argument_offset,195 .stack_argument_offset,
...@@ -768,10 +766,10 @@ fn processDeath(self: *Self, inst: Air.Inst.Index) void {...@@ -768,10 +766,10 @@ fn processDeath(self: *Self, inst: Air.Inst.Index) void {
768 .register_v_flag,766 .register_v_flag,
769 => |reg| {767 => |reg| {
770 self.register_manager.freeReg(reg);768 self.register_manager.freeReg(reg);
771 self.compare_flags_inst = null;769 self.cpsr_flags_inst = null;
772 },770 },
773 .compare_flags_signed, .compare_flags_unsigned => {771 .cpsr_flags => {
774 self.compare_flags_inst = null;772 self.cpsr_flags_inst = null;
775 },773 },
776 else => {}, // TODO process stack allocation death774 else => {}, // TODO process stack allocation death
777 }775 }
...@@ -903,12 +901,10 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void...@@ -903,12 +901,10 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void
903/// Save the current instruction stored in the compare flags if901/// Save the current instruction stored in the compare flags if
904/// occupied902/// occupied
905fn spillCompareFlagsIfOccupied(self: *Self) !void {903fn spillCompareFlagsIfOccupied(self: *Self) !void {
906 if (self.compare_flags_inst) |inst_to_save| {904 if (self.cpsr_flags_inst) |inst_to_save| {
907 const mcv = self.getResolvedInstValue(inst_to_save);905 const mcv = self.getResolvedInstValue(inst_to_save);
908 const new_mcv = switch (mcv) {906 const new_mcv = switch (mcv) {
909 .compare_flags_signed,907 .cpsr_flags => try self.allocRegOrMem(inst_to_save, true),
910 .compare_flags_unsigned,
911 => try self.allocRegOrMem(inst_to_save, true),
912 .register_c_flag,908 .register_c_flag,
913 .register_v_flag,909 .register_v_flag,
914 => try self.allocRegOrMem(inst_to_save, false),910 => try self.allocRegOrMem(inst_to_save, false),
...@@ -921,7 +917,7 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void {...@@ -921,7 +917,7 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void {
921 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];917 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
922 try branch.inst_table.put(self.gpa, inst_to_save, new_mcv);918 try branch.inst_table.put(self.gpa, inst_to_save, new_mcv);
923919
924 self.compare_flags_inst = null;920 self.cpsr_flags_inst = null;
925921
926 // TODO consolidate with register manager and spillInstruction922 // TODO consolidate with register manager and spillInstruction
927 // this call should really belong in the register manager!923 // this call should really belong in the register manager!
...@@ -1111,32 +1107,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {...@@ -1111,32 +1107,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
1111 switch (operand) {1107 switch (operand) {
1112 .dead => unreachable,1108 .dead => unreachable,
1113 .unreach => unreachable,1109 .unreach => unreachable,
1114 .compare_flags_unsigned => |op| {1110 .cpsr_flags => |cond| break :result MCValue{ .cpsr_flags = cond.negate() },
1115 const r = MCValue{
1116 .compare_flags_unsigned = switch (op) {
1117 .gte => .lt,
1118 .gt => .lte,
1119 .neq => .eq,
1120 .lt => .gte,
1121 .lte => .gt,
1122 .eq => .neq,
1123 },
1124 };
1125 break :result r;
1126 },
1127 .compare_flags_signed => |op| {
1128 const r = MCValue{
1129 .compare_flags_signed = switch (op) {
1130 .gte => .lt,
1131 .gt => .lte,
1132 .neq => .eq,
1133 .lt => .gte,
1134 .lte => .gt,
1135 .eq => .neq,
1136 },
1137 };
1138 break :result r;
1139 },
1140 else => {1111 else => {
1141 switch (operand_ty.zigTypeTag()) {1112 switch (operand_ty.zigTypeTag()) {
1142 .Bool => {1113 .Bool => {
...@@ -1425,7 +1396,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1425,7 +1396,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
1425 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);1396 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);
14261397
1427 try self.spillCompareFlagsIfOccupied();1398 try self.spillCompareFlagsIfOccupied();
1428 self.compare_flags_inst = null;1399 self.cpsr_flags_inst = null;
14291400
1430 const base_tag: Air.Inst.Tag = switch (tag) {1401 const base_tag: Air.Inst.Tag = switch (tag) {
1431 .add_with_overflow => .add,1402 .add_with_overflow => .add,
...@@ -1448,7 +1419,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1448,7 +1419,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
1448 _ = try self.binOp(.cmp_eq, dest, .{ .register = truncated_reg }, Type.usize, Type.usize, null);1419 _ = try self.binOp(.cmp_eq, dest, .{ .register = truncated_reg }, Type.usize, Type.usize, null);
14491420
1450 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });1421 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });
1451 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .compare_flags_unsigned = .neq });1422 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .cpsr_flags = .ne });
14521423
1453 break :result MCValue{ .stack_offset = stack_offset };1424 break :result MCValue{ .stack_offset = stack_offset };
1454 } else if (int_info.bits == 32) {1425 } else if (int_info.bits == 32) {
...@@ -1474,7 +1445,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1474,7 +1445,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
1474 };1445 };
14751446
1476 try self.spillCompareFlagsIfOccupied();1447 try self.spillCompareFlagsIfOccupied();
1477 self.compare_flags_inst = inst;1448 self.cpsr_flags_inst = inst;
14781449
1479 const dest = blk: {1450 const dest = blk: {
1480 if (rhs_immediate_ok) {1451 if (rhs_immediate_ok) {
...@@ -1530,7 +1501,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1530,7 +1501,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1530 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);1501 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);
15311502
1532 try self.spillCompareFlagsIfOccupied();1503 try self.spillCompareFlagsIfOccupied();
1533 self.compare_flags_inst = null;1504 self.cpsr_flags_inst = null;
15341505
1535 const base_tag: Mir.Inst.Tag = switch (int_info.signedness) {1506 const base_tag: Mir.Inst.Tag = switch (int_info.signedness) {
1536 .signed => .smulbb,1507 .signed => .smulbb,
...@@ -1553,14 +1524,14 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1553,14 +1524,14 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1553 _ = try self.binOp(.cmp_eq, dest, .{ .register = truncated_reg }, Type.usize, Type.usize, null);1524 _ = try self.binOp(.cmp_eq, dest, .{ .register = truncated_reg }, Type.usize, Type.usize, null);
15541525
1555 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });1526 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });
1556 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .compare_flags_unsigned = .neq });1527 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .cpsr_flags = .ne });
15571528
1558 break :result MCValue{ .stack_offset = stack_offset };1529 break :result MCValue{ .stack_offset = stack_offset };
1559 } else if (int_info.bits <= 32) {1530 } else if (int_info.bits <= 32) {
1560 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);1531 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);
15611532
1562 try self.spillCompareFlagsIfOccupied();1533 try self.spillCompareFlagsIfOccupied();
1563 self.compare_flags_inst = null;1534 self.cpsr_flags_inst = null;
15641535
1565 const base_tag: Mir.Inst.Tag = switch (int_info.signedness) {1536 const base_tag: Mir.Inst.Tag = switch (int_info.signedness) {
1566 .signed => .smull,1537 .signed => .smull,
...@@ -1704,7 +1675,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1704,7 +1675,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1704 defer if (lhs_lock) |reg| self.register_manager.unlockReg(reg);1675 defer if (lhs_lock) |reg| self.register_manager.unlockReg(reg);
17051676
1706 try self.spillCompareFlagsIfOccupied();1677 try self.spillCompareFlagsIfOccupied();
1707 self.compare_flags_inst = null;1678 self.cpsr_flags_inst = null;
17081679
1709 // lsl dest, lhs, rhs1680 // lsl dest, lhs, rhs
1710 const dest = try self.binOp(.shl, lhs, rhs, lhs_ty, rhs_ty, null);1681 const dest = try self.binOp(.shl, lhs, rhs, lhs_ty, rhs_ty, null);
...@@ -1719,7 +1690,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1719,7 +1690,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1719 _ = try self.binOp(.cmp_eq, lhs, reconstructed, lhs_ty, lhs_ty, null);1690 _ = try self.binOp(.cmp_eq, lhs, reconstructed, lhs_ty, lhs_ty, null);
17201691
1721 try self.genSetStack(lhs_ty, stack_offset, dest);1692 try self.genSetStack(lhs_ty, stack_offset, dest);
1722 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .compare_flags_unsigned = .neq });1693 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .cpsr_flags = .ne });
17231694
1724 break :result MCValue{ .stack_offset = stack_offset };1695 break :result MCValue{ .stack_offset = stack_offset };
1725 } else {1696 } else {
...@@ -2213,8 +2184,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -2213,8 +2184,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2213 .undef => unreachable,2184 .undef => unreachable,
2214 .unreach => unreachable,2185 .unreach => unreachable,
2215 .dead => unreachable,2186 .dead => unreachable,
2216 .compare_flags_unsigned,2187 .cpsr_flags,
2217 .compare_flags_signed,
2218 .register_c_flag,2188 .register_c_flag,
2219 .register_v_flag,2189 .register_v_flag,
2220 => unreachable, // cannot hold an address2190 => unreachable, // cannot hold an address
...@@ -2227,7 +2197,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -2227,7 +2197,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2227 switch (dst_mcv) {2197 switch (dst_mcv) {
2228 .dead => unreachable,2198 .dead => unreachable,
2229 .undef => unreachable,2199 .undef => unreachable,
2230 .compare_flags_signed, .compare_flags_unsigned => unreachable,2200 .cpsr_flags => unreachable,
2231 .register => |dst_reg| {2201 .register => |dst_reg| {
2232 try self.genLdrRegister(dst_reg, reg, elem_ty);2202 try self.genLdrRegister(dst_reg, reg, elem_ty);
2233 },2203 },
...@@ -2314,8 +2284,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -2314,8 +2284,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
2314 .undef => unreachable,2284 .undef => unreachable,
2315 .unreach => unreachable,2285 .unreach => unreachable,
2316 .dead => unreachable,2286 .dead => unreachable,
2317 .compare_flags_unsigned,2287 .cpsr_flags,
2318 .compare_flags_signed,
2319 .register_c_flag,2288 .register_c_flag,
2320 .register_v_flag,2289 .register_v_flag,
2321 => unreachable, // cannot hold an address2290 => unreachable, // cannot hold an address
...@@ -2484,37 +2453,48 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2484,37 +2453,48 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
2484 break :result MCValue{ .register = reg };2453 break :result MCValue{ .register = reg };
2485 },2454 },
2486 1 => {2455 1 => {
2487 // get overflow bit: set register to C flag2456 // get overflow bit: return C or V flag
2488 // resp. V flag2457 if (self.liveness.operandDies(inst, 0)) {
2489 const dest_reg = try self.register_manager.allocReg(null, gp);2458 self.cpsr_flags_inst = inst;
24902459
2491 // mov reg, #02460 const cond: Condition = switch (mcv) {
2492 _ = try self.addInst(.{
2493 .tag = .mov,
2494 .data = .{ .rr_op = .{
2495 .rd = dest_reg,
2496 .rn = .r0,
2497 .op = Instruction.Operand.fromU32(0).?,
2498 } },
2499 });
2500
2501 // C flag: movcs reg, #1
2502 // V flag: movvs reg, #1
2503 _ = try self.addInst(.{
2504 .tag = .mov,
2505 .cond = switch (mcv) {
2506 .register_c_flag => .cs,2461 .register_c_flag => .cs,
2507 .register_v_flag => .vs,2462 .register_v_flag => .vs,
2508 else => unreachable,2463 else => unreachable,
2509 },2464 };
2510 .data = .{ .rr_op = .{
2511 .rd = dest_reg,
2512 .rn = .r0,
2513 .op = Instruction.Operand.fromU32(1).?,
2514 } },
2515 });
25162465
2517 break :result MCValue{ .register = dest_reg };2466 break :result MCValue{ .cpsr_flags = cond };
2467 } else {
2468 const dest_reg = try self.register_manager.allocReg(null, gp);
2469
2470 // mov reg, #0
2471 _ = try self.addInst(.{
2472 .tag = .mov,
2473 .data = .{ .rr_op = .{
2474 .rd = dest_reg,
2475 .rn = .r0,
2476 .op = Instruction.Operand.fromU32(0).?,
2477 } },
2478 });
2479
2480 // C flag: movcs reg, #1
2481 // V flag: movvs reg, #1
2482 _ = try self.addInst(.{
2483 .tag = .mov,
2484 .cond = switch (mcv) {
2485 .register_c_flag => .cs,
2486 .register_v_flag => .vs,
2487 else => unreachable,
2488 },
2489 .data = .{ .rr_op = .{
2490 .rd = dest_reg,
2491 .rn = .r0,
2492 .op = Instruction.Operand.fromU32(1).?,
2493 } },
2494 });
2495
2496 break :result MCValue{ .register = dest_reg };
2497 }
2518 },2498 },
2519 else => unreachable,2499 else => unreachable,
2520 }2500 }
...@@ -3602,7 +3582,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -3602,7 +3582,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
3602 const int_info = int_ty.intInfo(self.target.*);3582 const int_info = int_ty.intInfo(self.target.*);
3603 if (int_info.bits <= 32) {3583 if (int_info.bits <= 32) {
3604 try self.spillCompareFlagsIfOccupied();3584 try self.spillCompareFlagsIfOccupied();
3605 self.compare_flags_inst = inst;3585 self.cpsr_flags_inst = inst;
36063586
3607 _ = try self.binOp(.cmp_eq, lhs, rhs, int_ty, int_ty, BinOpMetadata{3587 _ = try self.binOp(.cmp_eq, lhs, rhs, int_ty, int_ty, BinOpMetadata{
3608 .lhs = bin_op.lhs,3588 .lhs = bin_op.lhs,
...@@ -3611,8 +3591,8 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -3611,8 +3591,8 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
3611 });3591 });
36123592
3613 break :result switch (int_info.signedness) {3593 break :result switch (int_info.signedness) {
3614 .signed => MCValue{ .compare_flags_signed = op },3594 .signed => MCValue{ .cpsr_flags = Condition.fromCompareOperatorSigned(op) },
3615 .unsigned => MCValue{ .compare_flags_unsigned = op },3595 .unsigned => MCValue{ .cpsr_flags = Condition.fromCompareOperatorUnsigned(op) },
3616 };3596 };
3617 } else {3597 } else {
3618 return self.fail("TODO ARM cmp for ints > 32 bits", .{});3598 return self.fail("TODO ARM cmp for ints > 32 bits", .{});
...@@ -3673,28 +3653,19 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {...@@ -3673,28 +3653,19 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
36733653
3674fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {3654fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
3675 const pl_op = self.air.instructions.items(.data)[inst].pl_op;3655 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
3676 const cond = try self.resolveInst(pl_op.operand);3656 const cond_inst = try self.resolveInst(pl_op.operand);
3677 const extra = self.air.extraData(Air.CondBr, pl_op.payload);3657 const extra = self.air.extraData(Air.CondBr, pl_op.payload);
3678 const then_body = self.air.extra[extra.end..][0..extra.data.then_body_len];3658 const then_body = self.air.extra[extra.end..][0..extra.data.then_body_len];
3679 const else_body = self.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len];3659 const else_body = self.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len];
3680 const liveness_condbr = self.liveness.getCondBr(inst);3660 const liveness_condbr = self.liveness.getCondBr(inst);
36813661
3682 const reloc: Mir.Inst.Index = reloc: {3662 const reloc: Mir.Inst.Index = reloc: {
3683 const condition: Condition = switch (cond) {3663 const condition: Condition = switch (cond_inst) {
3684 .compare_flags_signed => |cmp_op| blk: {3664 .cpsr_flags => |cond| cond.negate(),
3685 // Here we map to the opposite condition because the jump is to the false branch.
3686 const condition = Condition.fromCompareOperatorSigned(cmp_op);
3687 break :blk condition.negate();
3688 },
3689 .compare_flags_unsigned => |cmp_op| blk: {
3690 // Here we map to the opposite condition because the jump is to the false branch.
3691 const condition = Condition.fromCompareOperatorUnsigned(cmp_op);
3692 break :blk condition.negate();
3693 },
3694 else => blk: {3665 else => blk: {
3695 const reg = switch (cond) {3666 const reg = switch (cond_inst) {
3696 .register => |r| r,3667 .register => |r| r,
3697 else => try self.copyToTmpRegister(Type.bool, cond),3668 else => try self.copyToTmpRegister(Type.bool, cond_inst),
3698 };3669 };
36993670
3700 try self.spillCompareFlagsIfOccupied();3671 try self.spillCompareFlagsIfOccupied();
...@@ -3739,7 +3710,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3739,7 +3710,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
3739 var parent_stack = try self.stack.clone(self.gpa);3710 var parent_stack = try self.stack.clone(self.gpa);
3740 defer parent_stack.deinit(self.gpa);3711 defer parent_stack.deinit(self.gpa);
3741 const parent_registers = self.register_manager.registers;3712 const parent_registers = self.register_manager.registers;
3742 const parent_compare_flags_inst = self.compare_flags_inst;3713 const parent_cpsr_flags_inst = self.cpsr_flags_inst;
37433714
3744 try self.branch_stack.append(.{});3715 try self.branch_stack.append(.{});
3745 errdefer {3716 errdefer {
...@@ -3758,7 +3729,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3758,7 +3729,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
3758 defer saved_then_branch.deinit(self.gpa);3729 defer saved_then_branch.deinit(self.gpa);
37593730
3760 self.register_manager.registers = parent_registers;3731 self.register_manager.registers = parent_registers;
3761 self.compare_flags_inst = parent_compare_flags_inst;3732 self.cpsr_flags_inst = parent_cpsr_flags_inst;
37623733
3763 self.stack.deinit(self.gpa);3734 self.stack.deinit(self.gpa);
3764 self.stack = parent_stack;3735 self.stack = parent_stack;
...@@ -3876,7 +3847,7 @@ fn isNull(self: *Self, ty: Type, operand: MCValue) !MCValue {...@@ -3876,7 +3847,7 @@ fn isNull(self: *Self, ty: Type, operand: MCValue) !MCValue {
3876 } },3847 } },
3877 });3848 });
38783849
3879 return MCValue{ .compare_flags_unsigned = .eq };3850 return MCValue{ .cpsr_flags = .eq };
3880 } else {3851 } else {
3881 return self.fail("TODO implement non-pointer optionals", .{});3852 return self.fail("TODO implement non-pointer optionals", .{});
3882 }3853 }
...@@ -3884,9 +3855,9 @@ fn isNull(self: *Self, ty: Type, operand: MCValue) !MCValue {...@@ -3884,9 +3855,9 @@ fn isNull(self: *Self, ty: Type, operand: MCValue) !MCValue {
38843855
3885fn isNonNull(self: *Self, ty: Type, operand: MCValue) !MCValue {3856fn isNonNull(self: *Self, ty: Type, operand: MCValue) !MCValue {
3886 const is_null_result = try self.isNull(ty, operand);3857 const is_null_result = try self.isNull(ty, operand);
3887 assert(is_null_result.compare_flags_unsigned == .eq);3858 assert(is_null_result.cpsr_flags == .eq);
38883859
3889 return MCValue{ .compare_flags_unsigned = .neq };3860 return MCValue{ .cpsr_flags = .ne };
3890}3861}
38913862
3892fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {3863fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
...@@ -3899,15 +3870,15 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {...@@ -3899,15 +3870,15 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
38993870
3900 const error_mcv = try self.errUnionErr(operand, ty);3871 const error_mcv = try self.errUnionErr(operand, ty);
3901 _ = try self.binOp(.cmp_eq, error_mcv, .{ .immediate = 0 }, error_int_type, error_int_type, null);3872 _ = try self.binOp(.cmp_eq, error_mcv, .{ .immediate = 0 }, error_int_type, error_int_type, null);
3902 return MCValue{ .compare_flags_unsigned = .gt };3873 return MCValue{ .cpsr_flags = .hi };
3903}3874}
39043875
3905fn isNonErr(self: *Self, ty: Type, operand: MCValue) !MCValue {3876fn isNonErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
3906 const is_err_result = try self.isErr(ty, operand);3877 const is_err_result = try self.isErr(ty, operand);
3907 switch (is_err_result) {3878 switch (is_err_result) {
3908 .compare_flags_unsigned => |op| {3879 .cpsr_flags => |cond| {
3909 assert(op == .gt);3880 assert(cond == .hi);
3910 return MCValue{ .compare_flags_unsigned = .lte };3881 return MCValue{ .cpsr_flags = cond.negate() };
3911 },3882 },
3912 .immediate => |imm| {3883 .immediate => |imm| {
3913 assert(imm == 0);3884 assert(imm == 0);
...@@ -3921,7 +3892,7 @@ fn airIsNull(self: *Self, inst: Air.Inst.Index) !void {...@@ -3921,7 +3892,7 @@ fn airIsNull(self: *Self, inst: Air.Inst.Index) !void {
3921 const un_op = self.air.instructions.items(.data)[inst].un_op;3892 const un_op = self.air.instructions.items(.data)[inst].un_op;
39223893
3923 try self.spillCompareFlagsIfOccupied();3894 try self.spillCompareFlagsIfOccupied();
3924 self.compare_flags_inst = inst;3895 self.cpsr_flags_inst = inst;
39253896
3926 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {3897 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
3927 const operand = try self.resolveInst(un_op);3898 const operand = try self.resolveInst(un_op);
...@@ -4298,8 +4269,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -4298,8 +4269,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
4298 else => return self.fail("TODO implement memset", .{}),4269 else => return self.fail("TODO implement memset", .{}),
4299 }4270 }
4300 },4271 },
4301 .compare_flags_unsigned,4272 .cpsr_flags,
4302 .compare_flags_signed,
4303 .immediate,4273 .immediate,
4304 .ptr_stack_offset,4274 .ptr_stack_offset,
4305 => {4275 => {
...@@ -4469,15 +4439,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -4469,15 +4439,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
4469 } },4439 } },
4470 });4440 });
4471 },4441 },
4472 .compare_flags_unsigned,4442 .cpsr_flags => |condition| {
4473 .compare_flags_signed,
4474 => |op| {
4475 const condition = switch (mcv) {
4476 .compare_flags_unsigned => Condition.fromCompareOperatorUnsigned(op),
4477 .compare_flags_signed => Condition.fromCompareOperatorSigned(op),
4478 else => unreachable,
4479 };
4480
4481 const zero = Instruction.Operand.imm(0, 0);4443 const zero = Instruction.Operand.imm(0, 0);
4482 const one = Instruction.Operand.imm(1, 0);4444 const one = Instruction.Operand.imm(1, 0);
44834445
...@@ -4826,8 +4788,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I...@@ -4826,8 +4788,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
4826 try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg);4788 try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg);
4827 }4789 }
4828 },4790 },
4829 .compare_flags_unsigned,4791 .cpsr_flags,
4830 .compare_flags_signed,
4831 .immediate,4792 .immediate,
4832 .ptr_stack_offset,4793 .ptr_stack_offset,
4833 => {4794 => {