@@ -128,18 +128,11 @@ const MCValue = union(enum) {
128
128
register : Register ,
129
129
/// The value is a tuple { wrapped: u32, overflow: u1 } where
130
130
/// wrapped is stored in the register and the overflow bit is
131
- /// stored in the C flag of the CPSR.
131
+ /// stored in the C (signed) or V (unsigned) flag of the CPSR.
132
132
///
133
133
/// This MCValue is only generated by a add_with_overflow or
134
- /// sub_with_overflow instruction operating on u32.
135
- register_c_flag : Register ,
136
- /// The value is a tuple { wrapped: i32, overflow: u1 } where
137
- /// wrapped is stored in the register and the overflow bit is
138
- /// stored in the V flag of the CPSR.
139
- ///
140
- /// This MCValue is only generated by a add_with_overflow or
141
- /// sub_with_overflow instruction operating on i32.
142
- register_v_flag : Register ,
134
+ /// sub_with_overflow instruction operating on 32- or 64-bit values.
135
+ register_with_overflow : struct { reg : Register , flag : bits .Instruction .Condition },
143
136
/// The value is in memory at a hard-coded address.
144
137
///
145
138
/// If the type is a pointer, it means the pointer address is at
@@ -760,10 +753,8 @@ fn processDeath(self: *Self, inst: Air.Inst.Index) void {
760
753
.register = > | reg | {
761
754
self .register_manager .freeReg (reg );
762
755
},
763
- .register_c_flag ,
764
- .register_v_flag ,
765
- = > | reg | {
766
- self .register_manager .freeReg (reg );
756
+ .register_with_overflow = > | rwo | {
757
+ self .register_manager .freeReg (rwo .reg );
767
758
self .compare_flags_inst = null ;
768
759
},
769
760
.compare_flags_signed , .compare_flags_unsigned = > {
@@ -905,10 +896,8 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void
905
896
log .debug ("spilling {d} to stack mcv {any}" , .{ inst , stack_mcv });
906
897
const reg_mcv = self .getResolvedInstValue (inst );
907
898
switch (reg_mcv ) {
908
- .register ,
909
- .register_c_flag ,
910
- .register_v_flag ,
911
- = > | r | assert (reg .id () == r .id ()),
899
+ .register = > | r | assert (reg .id () == r .id ()),
900
+ .register_with_overflow = > | rwo | assert (rwo .reg .id () == reg .id ()),
912
901
else = > unreachable , // not a register
913
902
}
914
903
const branch = & self .branch_stack .items [self .branch_stack .items .len - 1 ];
@@ -925,9 +914,7 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void {
925
914
.compare_flags_signed ,
926
915
.compare_flags_unsigned ,
927
916
= > try self .allocRegOrMem (inst_to_save , true ),
928
- .register_c_flag ,
929
- .register_v_flag ,
930
- = > try self .allocRegOrMem (inst_to_save , false ),
917
+ .register_with_overflow = > try self .allocRegOrMem (inst_to_save , false ),
931
918
else = > unreachable , // mcv doesn't occupy the compare flags
932
919
};
933
920
@@ -942,9 +929,7 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void {
942
929
// TODO consolidate with register manager and spillInstruction
943
930
// this call should really belong in the register manager!
944
931
switch (mcv ) {
945
- .register_c_flag ,
946
- .register_v_flag ,
947
- = > | reg | self .register_manager .freeReg (reg ),
932
+ .register_with_overflow = > | rwo | self .register_manager .freeReg (rwo .reg ),
948
933
else = > {},
949
934
}
950
935
}
@@ -1932,14 +1917,18 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
1932
1917
}
1933
1918
};
1934
1919
1935
- if (tag == .sub_with_overflow ) {
1936
- break :result MCValue { .register_v_flag = dest .register };
1937
- }
1938
-
1939
- switch (int_info .signedness ) {
1940
- .unsigned = > break :result MCValue { .register_c_flag = dest .register },
1941
- .signed = > break :result MCValue { .register_v_flag = dest .register },
1942
- }
1920
+ const flag : bits.Instruction.Condition = switch (int_info .signedness ) {
1921
+ .unsigned = > switch (tag ) {
1922
+ .add_with_overflow = > bits .Instruction .Condition .cs ,
1923
+ .sub_with_overflow = > bits .Instruction .Condition .cc ,
1924
+ else = > unreachable ,
1925
+ },
1926
+ .signed = > .vs ,
1927
+ };
1928
+ break :result MCValue { .register_with_overflow = .{
1929
+ .reg = dest .register ,
1930
+ .flag = flag ,
1931
+ } };
1943
1932
},
1944
1933
else = > return self .fail ("TODO overflow operations on integers > u32/i32" , .{}),
1945
1934
}
@@ -2648,8 +2637,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2648
2637
.dead = > unreachable ,
2649
2638
.compare_flags_unsigned ,
2650
2639
.compare_flags_signed ,
2651
- .register_c_flag ,
2652
- .register_v_flag ,
2640
+ .register_with_overflow ,
2653
2641
= > unreachable , // cannot hold an address
2654
2642
.immediate = > | imm | try self .setRegOrMem (elem_ty , dst_mcv , .{ .memory = imm }),
2655
2643
.ptr_stack_offset = > | off | try self .setRegOrMem (elem_ty , dst_mcv , .{ .stack_offset = off }),
@@ -2871,8 +2859,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
2871
2859
.dead = > unreachable ,
2872
2860
.compare_flags_unsigned ,
2873
2861
.compare_flags_signed ,
2874
- .register_c_flag ,
2875
- .register_v_flag ,
2862
+ .register_with_overflow ,
2876
2863
= > unreachable , // cannot hold an address
2877
2864
.immediate = > | imm | {
2878
2865
try self .setRegOrMem (value_ty , .{ .memory = imm }, value );
@@ -2993,13 +2980,11 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
2993
2980
.memory = > | addr | {
2994
2981
break :result MCValue { .memory = addr + struct_field_offset };
2995
2982
},
2996
- .register_c_flag ,
2997
- .register_v_flag ,
2998
- = > | reg | {
2983
+ .register_with_overflow = > | rwo | {
2999
2984
switch (index ) {
3000
2985
0 = > {
3001
2986
// get wrapped value: return register
3002
- break :result MCValue { .register = reg };
2987
+ break :result MCValue { .register = rwo . reg };
3003
2988
},
3004
2989
1 = > {
3005
2990
// TODO return special MCValue condition flags
@@ -3008,17 +2993,11 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
3008
2993
const raw_dest_reg = try self .register_manager .allocReg (null , gp );
3009
2994
const dest_reg = raw_dest_reg .to32 ();
3010
2995
3011
- // C flag: cset reg, cs
3012
- // V flag: cset reg, vs
3013
2996
_ = try self .addInst (.{
3014
2997
.tag = .cset ,
3015
2998
.data = .{ .r_cond = .{
3016
2999
.rd = dest_reg ,
3017
- .cond = switch (mcv ) {
3018
- .register_c_flag = > .cs ,
3019
- .register_v_flag = > .vs ,
3020
- else = > unreachable ,
3021
- },
3000
+ .cond = rwo .flag ,
3022
3001
} },
3023
3002
});
3024
3003
@@ -4073,14 +4052,12 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
4073
4052
else = > return self .fail ("TODO implement storing other types abi_size={}" , .{abi_size }),
4074
4053
}
4075
4054
},
4076
- .register_c_flag ,
4077
- .register_v_flag ,
4078
- = > | reg | {
4079
- const reg_lock = self .register_manager .lockReg (reg );
4055
+ .register_with_overflow = > | rwo | {
4056
+ const reg_lock = self .register_manager .lockReg (rwo .reg );
4080
4057
defer if (reg_lock ) | locked_reg | self .register_manager .unlockReg (locked_reg );
4081
4058
4082
4059
const wrapped_ty = ty .structFieldType (0 );
4083
- try self .genSetStack (wrapped_ty , stack_offset , .{ .register = reg });
4060
+ try self .genSetStack (wrapped_ty , stack_offset , .{ .register = rwo . reg });
4084
4061
4085
4062
const overflow_bit_ty = ty .structFieldType (1 );
4086
4063
const overflow_bit_offset = @intCast (u32 , ty .structFieldOffset (1 , self .target .* ));
@@ -4090,17 +4067,11 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
4090
4067
@intCast (u32 , overflow_bit_ty .abiSize (self .target .* )),
4091
4068
);
4092
4069
4093
- // C flag: cset reg, cs
4094
- // V flag: cset reg, vs
4095
4070
_ = try self .addInst (.{
4096
4071
.tag = .cset ,
4097
4072
.data = .{ .r_cond = .{
4098
4073
.rd = cond_reg ,
4099
- .cond = switch (mcv ) {
4100
- .register_c_flag = > .cs ,
4101
- .register_v_flag = > .vs ,
4102
- else = > unreachable ,
4103
- },
4074
+ .cond = rwo .flag ,
4104
4075
} },
4105
4076
});
4106
4077
@@ -4270,9 +4241,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
4270
4241
.data = .{ .rr = .{ .rd = reg , .rn = src_reg } },
4271
4242
});
4272
4243
},
4273
- .register_c_flag ,
4274
- .register_v_flag ,
4275
- = > unreachable , // doesn't fit into a register
4244
+ .register_with_overflow = > unreachable , // doesn't fit into a register
4276
4245
.got_load ,
4277
4246
.direct_load ,
4278
4247
= > | sym_index | {
0 commit comments