lib/choir/src/backends/aarch64/registers/model.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

  1 const std = @import("std");
  2 
  3 pub const Encoded = enum(u5) {
  4     _,
  5 
  6     pub fn fromInt(val: u5) Encoded {
  7         return @fromBackingInt(@intCast(val));
  8     }
  9 
 10     pub fn toInt(self: Encoded) u5 {
 11         return @backingInt(self);
 12     }
 13 };
 14 
 15 pub const GPR = enum(u5) {
 16     x0 = 0,
 17     x1 = 1,
 18     x2 = 2,
 19     x3 = 3,
 20     x4 = 4,
 21     x5 = 5,
 22     x6 = 6,
 23     x7 = 7,
 24     x8 = 8,
 25     x9 = 9,
 26     x10 = 10,
 27     x11 = 11,
 28     x12 = 12,
 29     x13 = 13,
 30     x14 = 14,
 31     x15 = 15,
 32     x16 = 16,
 33     x17 = 17,
 34     x18 = 18,
 35     x19 = 19,
 36     x20 = 20,
 37     x21 = 21,
 38     x22 = 22,
 39     x23 = 23,
 40     x24 = 24,
 41     x25 = 25,
 42     x26 = 26,
 43     x27 = 27,
 44     x28 = 28,
 45     x29 = 29,
 46     x30 = 30,
 47 
 48     pub const fp = GPR.x29;
 49     pub const lr = GPR.x30;
 50 
 51     pub const arg0 = GPR.x0;
 52     pub const arg1 = GPR.x1;
 53     pub const arg2 = GPR.x2;
 54     pub const arg3 = GPR.x3;
 55     pub const arg4 = GPR.x4;
 56     pub const arg5 = GPR.x5;
 57     pub const arg6 = GPR.x6;
 58     pub const arg7 = GPR.x7;
 59 
 60     pub const ret = GPR.x0;
 61 
 62     pub fn encode(self: GPR) Encoded {
 63         return @fromBackingInt(@intCast(@backingInt(self)));
 64     }
 65 
 66     pub fn isCallerSaved(self: GPR) bool {
 67         const n = @backingInt(self);
 68         return n <= 17;
 69     }
 70 
 71     pub fn isCalleeSaved(self: GPR) bool {
 72         const n = @backingInt(self);
 73         return n >= 19 and n <= 28;
 74     }
 75 
 76     pub fn isArgument(self: GPR) bool {
 77         const n = @backingInt(self);
 78         return n <= 7;
 79     }
 80 
 81     pub fn toW(self: GPR) []const u8 {
 82         const names = [_][]const u8{
 83             "w0",  "w1",  "w2",  "w3",  "w4",  "w5",  "w6",  "w7",
 84             "w8",  "w9",  "w10", "w11", "w12", "w13", "w14", "w15",
 85             "w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23",
 86             "w24", "w25", "w26", "w27", "w28", "w29", "w30",
 87         };
 88         return names[@backingInt(self)];
 89     }
 90 
 91     pub fn toX(self: GPR) []const u8 {
 92         const names = [_][]const u8{
 93             "x0",  "x1",  "x2",  "x3",  "x4",  "x5",  "x6",  "x7",
 94             "x8",  "x9",  "x10", "x11", "x12", "x13", "x14", "x15",
 95             "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
 96             "x24", "x25", "x26", "x27", "x28", "x29", "x30",
 97         };
 98         return names[@backingInt(self)];
 99     }
100 };
101 
102 pub const SP = struct {
103     pub const encoded: Encoded = @fromBackingInt(@intCast(31));
104 };
105 
106 pub const ZR = struct {
107     pub const encoded: Encoded = @fromBackingInt(@intCast(31));
108 };
109 
110 pub const FPR = enum(u5) {
111     v0 = 0,
112     v1 = 1,
113     v2 = 2,
114     v3 = 3,
115     v4 = 4,
116     v5 = 5,
117     v6 = 6,
118     v7 = 7,
119     v8 = 8,
120     v9 = 9,
121     v10 = 10,
122     v11 = 11,
123     v12 = 12,
124     v13 = 13,
125     v14 = 14,
126     v15 = 15,
127     v16 = 16,
128     v17 = 17,
129     v18 = 18,
130     v19 = 19,
131     v20 = 20,
132     v21 = 21,
133     v22 = 22,
134     v23 = 23,
135     v24 = 24,
136     v25 = 25,
137     v26 = 26,
138     v27 = 27,
139     v28 = 28,
140     v29 = 29,
141     v30 = 30,
142     v31 = 31,
143 
144     pub const arg0 = FPR.v0;
145     pub const arg1 = FPR.v1;
146     pub const arg2 = FPR.v2;
147     pub const arg3 = FPR.v3;
148     pub const arg4 = FPR.v4;
149     pub const arg5 = FPR.v5;
150     pub const arg6 = FPR.v6;
151     pub const arg7 = FPR.v7;
152 
153     pub const ret = FPR.v0;
154 
155     pub fn encode(self: FPR) Encoded {
156         return @fromBackingInt(@intCast(@backingInt(self)));
157     }
158 
159     pub fn isCallerSaved(self: FPR) bool {
160         const n = @backingInt(self);
161         return n <= 7 or n >= 16;
162     }
163 
164     pub fn isCalleeSaved(self: FPR) bool {
165         const n = @backingInt(self);
166         return n >= 8 and n <= 15;
167     }
168 
169     pub fn isArgument(self: FPR) bool {
170         const n = @backingInt(self);
171         return n <= 7;
172     }
173 
174     pub fn toS(self: FPR) []const u8 {
175         const names = [_][]const u8{
176             "s0",  "s1",  "s2",  "s3",  "s4",  "s5",  "s6",  "s7",
177             "s8",  "s9",  "s10", "s11", "s12", "s13", "s14", "s15",
178             "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
179             "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
180         };
181         return names[@backingInt(self)];
182     }
183 
184     pub fn toD(self: FPR) []const u8 {
185         const names = [_][]const u8{
186             "d0",  "d1",  "d2",  "d3",  "d4",  "d5",  "d6",  "d7",
187             "d8",  "d9",  "d10", "d11", "d12", "d13", "d14", "d15",
188             "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
189             "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
190         };
191         return names[@backingInt(self)];
192     }
193 };
194 
195 pub const GPRSize = enum(u1) {
196     w = 0,
197     x = 1,
198 
199     pub fn bits(self: GPRSize) u8 {
200         return switch (self) {
201             .w => 32,
202             .x => 64,
203         };
204     }
205 };
206 
207 pub const FPRSize = enum(u2) {
208     s = 0b00,
209     d = 0b01,
210     h = 0b11,
211 
212     pub fn bits(self: FPRSize) u8 {
213         return switch (self) {
214             .h => 16,
215             .s => 32,
216             .d => 64,
217         };
218     }
219 };
220 
221 pub const Register = union(enum) {
222     gpr: GPR,
223     fpr: FPR,
224     sp,
225     zr,
226 
227     pub fn encode(self: Register) Encoded {
228         return switch (self) {
229             .gpr => |r| r.encode(),
230             .fpr => |r| r.encode(),
231             .sp => SP.encoded,
232             .zr => ZR.encoded,
233         };
234     }
235 };
236 
237 pub const allocatable_gprs = [_]GPR{
238     .x0,  .x1,  .x2,  .x3,  .x4,  .x5,  .x6,  .x7,
239     .x8,  .x9,  .x10, .x11, .x12, .x13, .x14, .x15,
240     .x19, .x20, .x21, .x22, .x23, .x24, .x25, .x26,
241     .x27, .x28,
242 };
243 
244 pub const callee_saved_gprs = [_]GPR{
245     .x19, .x20, .x21, .x22, .x23, .x24, .x25, .x26, .x27, .x28,
246 };
247 
248 pub const allocatable_fprs = [_]FPR{
249     .v0,  .v1,  .v2,  .v3,  .v4,  .v5,  .v6,  .v7,
250     .v8,  .v9,  .v10, .v11, .v12, .v13, .v14, .v15,
251     .v16, .v17, .v18, .v19, .v20, .v21, .v22, .v23,
252     .v24, .v25, .v26, .v27, .v28, .v29, .v30, .v31,
253 };
254 
255 pub const callee_saved_fprs = [_]FPR{
256     .v8, .v9, .v10, .v11, .v12, .v13, .v14, .v15,
257 };
258 
259 test "GPR encoding" {
260     const testing = std.testing;
261     try testing.expectEqual(@as(u5, 0), GPR.x0.encode().toInt());
262     try testing.expectEqual(@as(u5, 29), GPR.fp.encode().toInt());
263     try testing.expectEqual(@as(u5, 30), GPR.lr.encode().toInt());
264 }
265 
266 test "GPR classification" {
267     const testing = std.testing;
268     try testing.expect(GPR.x0.isCallerSaved());
269     try testing.expect(GPR.x0.isArgument());
270     try testing.expect(!GPR.x0.isCalleeSaved());
271 
272     try testing.expect(GPR.x19.isCalleeSaved());
273     try testing.expect(!GPR.x19.isCallerSaved());
274     try testing.expect(!GPR.x19.isArgument());
275 }
276 
277 test "FPR encoding" {
278     const testing = std.testing;
279     try testing.expectEqual(@as(u5, 0), FPR.v0.encode().toInt());
280     try testing.expectEqual(@as(u5, 31), FPR.v31.encode().toInt());
281 }
282 
283 test "FPR classification" {
284     const testing = std.testing;
285     try testing.expect(FPR.v0.isCallerSaved());
286     try testing.expect(FPR.v0.isArgument());
287 
288     try testing.expect(FPR.v8.isCalleeSaved());
289     try testing.expect(!FPR.v8.isCallerSaved());
290 }