authorgravatar for eleanor@eleanor-nb.comEleanor Bartle <eleanor@eleanor-nb.com> 2020-08-18 14:30:00+10:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-08-18 00:30:00-04:00
logfa8935426b425110a89c6a2008013c500b7a3a79
treec36c70a2a595b33e2b393e523fdbe4aae7a80b22
parent3cc1f8b62477c37c938863cba0ec0409e4c9c0be
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Cleaned up RISC-V instruction creation, added 32-bit immediates (#6077)

* Implemented all R-type arithmetic/logical instructions * Implemented all I-type arithmetic/logical instructions * Implemented all load and store instructions * Implemented all of RV64I except FENCE

2 files changed, 387 insertions(+), 99 deletions(-)

src-self-hosted/codegen.zig+12-56
...@@ -1113,11 +1113,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1113,11 +1113,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1113 try self.code.append(0xcc); // int31113 try self.code.append(0xcc); // int3
1114 },1114 },
1115 .riscv64 => {1115 .riscv64 => {
1116 const full = @bitCast(u32, instructions.CallBreak{1116 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.ebreak.toU32());
1117 .mode = @enumToInt(instructions.CallBreak.Mode.ebreak),
1118 });
1119
1120 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), full);
1121 },1117 },
1122 else => return self.fail(src, "TODO implement @breakpoint() for {}", .{self.target.cpu.arch}),1118 else => return self.fail(src, "TODO implement @breakpoint() for {}", .{self.target.cpu.arch}),
1123 }1119 }
...@@ -1193,12 +1189,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1193,12 +1189,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1193 const got_addr = @intCast(u32, got.p_vaddr + func.owner_decl.link.elf.offset_table_index * ptr_bytes);1189 const got_addr = @intCast(u32, got.p_vaddr + func.owner_decl.link.elf.offset_table_index * ptr_bytes);
11941190
1195 try self.genSetReg(inst.base.src, .ra, .{ .memory = got_addr });1191 try self.genSetReg(inst.base.src, .ra, .{ .memory = got_addr });
1196 const jalr = instructions.Jalr{1192 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.jalr(.ra, 0, .ra).toU32());
1197 .rd = Register.ra.id(),
1198 .rs1 = Register.ra.id(),
1199 .offset = 0,
1200 };
1201 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), @bitCast(u32, jalr));
1202 } else {1193 } else {
1203 return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{});1194 return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{});
1204 }1195 }
...@@ -1255,12 +1246,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1255,12 +1246,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1255 try self.exitlude_jump_relocs.append(self.gpa, self.code.items.len - 4);1246 try self.exitlude_jump_relocs.append(self.gpa, self.code.items.len - 4);
1256 },1247 },
1257 .riscv64 => {1248 .riscv64 => {
1258 const jalr = instructions.Jalr{1249 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.jalr(.zero, 0, .ra).toU32());
1259 .rd = Register.zero.id(),
1260 .rs1 = Register.ra.id(),
1261 .offset = 0,
1262 };
1263 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), @bitCast(u32, jalr));
1264 },1250 },
1265 else => return self.fail(src, "TODO implement return for {}", .{self.target.cpu.arch}),1251 else => return self.fail(src, "TODO implement return for {}", .{self.target.cpu.arch}),
1266 }1252 }
...@@ -1512,11 +1498,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1512,11 +1498,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1512 }1498 }
15131499
1514 if (mem.eql(u8, inst.asm_source, "ecall")) {1500 if (mem.eql(u8, inst.asm_source, "ecall")) {
1515 const full = @bitCast(u32, instructions.CallBreak{1501 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.ecall.toU32());
1516 .mode = @enumToInt(instructions.CallBreak.Mode.ecall),
1517 });
1518
1519 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), full);
1520 } else {1502 } else {
1521 return self.fail(inst.base.src, "TODO implement support for more riscv64 assembly instructions", .{});1503 return self.fail(inst.base.src, "TODO implement support for more riscv64 assembly instructions", .{});
1522 }1504 }
...@@ -1723,36 +1705,17 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1723,36 +1705,17 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1723 .immediate => |unsigned_x| {1705 .immediate => |unsigned_x| {
1724 const x = @bitCast(i64, unsigned_x);1706 const x = @bitCast(i64, unsigned_x);
1725 if (math.minInt(i12) <= x and x <= math.maxInt(i12)) {1707 if (math.minInt(i12) <= x and x <= math.maxInt(i12)) {
1726 const instruction = @bitCast(u32, instructions.Addi{1708 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.addi(reg, .zero, @truncate(i12, x)).toU32());
1727 .mode = @enumToInt(instructions.Addi.Mode.addi),
1728 .imm = @truncate(i12, x),
1729 .rs1 = Register.zero.id(),
1730 .rd = reg.id(),
1731 });
1732
1733 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), instruction);
1734 return;1709 return;
1735 }1710 }
1736 if (math.minInt(i32) <= x and x <= math.maxInt(i32)) {1711 if (math.minInt(i32) <= x and x <= math.maxInt(i32)) {
1737 const split = @bitCast(packed struct {1712 const lo12 = @truncate(i12, x);
1738 low12: i12,1713 const carry: i32 = if (lo12 < 0) 1 else 0;
1739 up20: i20,1714 const hi20 = @truncate(i20, (x >> 12) +% carry);
1740 }, @truncate(i32, x));
1741 if (split.low12 < 0) return self.fail(src, "TODO support riscv64 genSetReg i32 immediates with 12th bit set to 1", .{});
1742
1743 const lui = @bitCast(u32, instructions.Lui{
1744 .imm = split.up20,
1745 .rd = reg.id(),
1746 });
1747 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), lui);
17481715
1749 const addi = @bitCast(u32, instructions.Addi{1716 // TODO: add test case for 32-bit immediate
1750 .mode = @enumToInt(instructions.Addi.Mode.addi),1717 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.lui(reg, hi20).toU32());
1751 .imm = @truncate(i12, split.low12),1718 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.addi(reg, reg, lo12).toU32());
1752 .rs1 = reg.id(),
1753 .rd = reg.id(),
1754 });
1755 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), addi);
1756 return;1719 return;
1757 }1720 }
1758 // li rd, immediate1721 // li rd, immediate
...@@ -1764,14 +1727,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1764,14 +1727,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1764 // If the type is a pointer, it means the pointer address is at this memory location.1727 // If the type is a pointer, it means the pointer address is at this memory location.
1765 try self.genSetReg(src, reg, .{ .immediate = addr });1728 try self.genSetReg(src, reg, .{ .immediate = addr });
17661729
1767 const ld = @bitCast(u32, instructions.Load{1730 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.ld(reg, 0, reg).toU32());
1768 .mode = @enumToInt(instructions.Load.Mode.ld),
1769 .rs1 = reg.id(),
1770 .rd = reg.id(),
1771 .offset = 0,
1772 });
1773
1774 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), ld);
1775 // LOAD imm=[i12 offset = 0], rs1 =1731 // LOAD imm=[i12 offset = 0], rs1 =
17761732
1777 // return self.fail("TODO implement genSetReg memory for riscv64");1733 // return self.fail("TODO implement genSetReg memory for riscv64");
src-self-hosted/codegen/riscv64.zig+375-43
...@@ -1,50 +1,387 @@...@@ -1,50 +1,387 @@
1const std = @import("std");1const std = @import("std");
2const DW = std.dwarf;2const DW = std.dwarf;
33
4pub const instructions = struct {4// TODO: this is only tagged to facilitate the monstrosity.
5 pub const CallBreak = packed struct {5// Once packed structs work make it packed.
6 pub const Mode = packed enum(u12) { ecall, ebreak };6pub const Instruction = union(enum) {
7 opcode: u7 = 0b1110011,7 R: packed struct {
8 unused1: u5 = 0,8 opcode: u7,
9 unused2: u3 = 0,
10 unused3: u5 = 0,
11 mode: u12, //: Mode
12 };
13 // I-type
14 pub const Addi = packed struct {
15 pub const Mode = packed enum(u3) { addi = 0b000, slti = 0b010, sltiu = 0b011, xori = 0b100, ori = 0b110, andi = 0b111 };
16 opcode: u7 = 0b0010011,
17 rd: u5,9 rd: u5,
18 mode: u3, //: Mode10 funct3: u3,
19 rs1: u5,11 rs1: u5,
20 imm: i12,12 rs2: u5,
21 };13 funct7: u7,
22 pub const Lui = packed struct {14 },
23 opcode: u7 = 0b0110111,15 I: packed struct {
16 opcode: u7,
24 rd: u5,17 rd: u5,
25 imm: i20,18 funct3: u3,
26 };
27 // I_type
28 pub const Load = packed struct {
29 pub const Mode = packed enum(u3) { ld = 0b011, lwu = 0b110 };
30 opcode: u7 = 0b0000011,
31 rd: u5,
32 mode: u3, //: Mode
33 rs1: u5,19 rs1: u5,
34 offset: i12,20 imm0_11: u12,
35 };21 },
36 // I-type22 S: packed struct {
37 pub const Jalr = packed struct {23 opcode: u7,
38 opcode: u7 = 0b1100111,24 imm0_4: u5,
39 rd: u5,25 funct3: u3,
40 mode: u3 = 0,26 rs1: u5,
27 rs2: u5,
28 imm5_11: u7,
29 },
30 B: packed struct {
31 opcode: u7,
32 imm11: u1,
33 imm1_4: u4,
34 funct3: u3,
41 rs1: u5,35 rs1: u5,
42 offset: i12,36 rs2: u5,
43 };37 imm5_10: u6,
38 imm12: u1,
39 },
40 U: packed struct {
41 opcode: u7,
42 rd: u5,
43 imm12_31: u20,
44 },
45 J: packed struct {
46 opcode: u7,
47 rd: u5,
48 imm12_19: u8,
49 imm11: u1,
50 imm1_10: u10,
51 imm20: u1,
52 },
53
54 // TODO: once packed structs work we can remove this monstrosity.
55 pub fn toU32(self: Instruction) u32 {
56 return switch (self) {
57 .R => |v| @bitCast(u32, v),
58 .I => |v| @bitCast(u32, v),
59 .S => |v| @bitCast(u32, v),
60 .B => |v| @intCast(u32, v.opcode) + (@intCast(u32, v.imm11) << 7) + (@intCast(u32, v.imm1_4) << 8) + (@intCast(u32, v.funct3) << 12) + (@intCast(u32, v.rs1) << 15) + (@intCast(u32, v.rs2) << 20) + (@intCast(u32, v.imm5_10) << 25) + (@intCast(u32, v.imm12) << 31),
61 .U => |v| @bitCast(u32, v),
62 .J => |v| @bitCast(u32, v),
63 };
64 }
65
66 fn rType(op: u7, fn3: u3, fn7: u7, rd: Register, r1: Register, r2: Register) Instruction {
67 return Instruction{
68 .R = .{
69 .opcode = op,
70 .funct3 = fn3,
71 .funct7 = fn7,
72 .rd = @enumToInt(rd),
73 .rs1 = @enumToInt(r1),
74 .rs2 = @enumToInt(r2),
75 },
76 };
77 }
78
79 // RISC-V is all signed all the time -- convert immediates to unsigned for processing
80 fn iType(op: u7, fn3: u3, rd: Register, r1: Register, imm: i12) Instruction {
81 const umm = @bitCast(u12, imm);
82
83 return Instruction{
84 .I = .{
85 .opcode = op,
86 .funct3 = fn3,
87 .rd = @enumToInt(rd),
88 .rs1 = @enumToInt(r1),
89 .imm0_11 = umm,
90 },
91 };
92 }
93
94 fn sType(op: u7, fn3: u3, r1: Register, r2: Register, imm: i12) Instruction {
95 const umm = @bitCast(u12, imm);
96
97 return Instruction{
98 .S = .{
99 .opcode = op,
100 .funct3 = fn3,
101 .rs1 = @enumToInt(r1),
102 .rs2 = @enumToInt(r2),
103 .imm0_4 = @truncate(u5, umm),
104 .imm5_11 = @truncate(u7, umm >> 5),
105 },
106 };
107 }
108
109 // Use significance value rather than bit value, same for J-type
110 // -- less burden on callsite, bonus semantic checking
111 fn bType(op: u7, fn3: u3, r1: Register, r2: Register, imm: i13) Instruction {
112 const umm = @bitCast(u13, imm);
113 if (umm % 2 != 0) @panic("Internal error: misaligned branch target");
114
115 return Instruction{
116 .B = .{
117 .opcode = op,
118 .funct3 = fn3,
119 .rs1 = @enumToInt(r1),
120 .rs2 = @enumToInt(r2),
121 .imm1_4 = @truncate(u4, umm >> 1),
122 .imm5_10 = @truncate(u6, umm >> 5),
123 .imm11 = @truncate(u1, umm >> 11),
124 .imm12 = @truncate(u1, umm >> 12),
125 },
126 };
127 }
128
129 // We have to extract the 20 bits anyway -- let's not make it more painful
130 fn uType(op: u7, rd: Register, imm: i20) Instruction {
131 const umm = @bitCast(u20, imm);
132
133 return Instruction{
134 .U = .{
135 .opcode = op,
136 .rd = @enumToInt(rd),
137 .imm12_31 = umm,
138 },
139 };
140 }
141
142 fn jType(op: u7, rd: Register, imm: i21) Instruction {
143 const umm = @bitcast(u21, imm);
144 if (umm % 2 != 0) @panic("Internal error: misaligned jump target");
145
146 return Instruction{
147 .J = .{
148 .opcode = op,
149 .rd = @enumToInt(rd),
150 .imm1_10 = @truncate(u10, umm >> 1),
151 .imm11 = @truncate(u1, umm >> 1),
152 .imm12_19 = @truncate(u8, umm >> 12),
153 .imm20 = @truncate(u1, umm >> 20),
154 },
155 };
156 }
157
158 // The meat and potatoes. Arguments are in the order in which they would appear in assembly code.
159
160 // Arithmetic/Logical, Register-Register
161
162 pub fn add(rd: Register, r1: Register, r2: Register) Instruction {
163 return rType(0b0110011, 0b000, 0b0000000, rd, r1, r2);
164 }
165
166 pub fn sub(rd: Register, r1: Register, r2: Register) Instruction {
167 return rType(0b0110011, 0b000, 0b0100000, rd, r1, r2);
168 }
169
170 pub fn @"and"(rd: Register, r1: Register, r2: Register) Instruction {
171 return rType(0b0110011, 0b111, 0b0000000, rd, r1, r2);
172 }
173
174 pub fn @"or"(rd: Register, r1: Register, r2: Register) Instruction {
175 return rType(0b0110011, 0b110, 0b0000000, rd, r1, r2);
176 }
177
178 pub fn xor(rd: Register, r1: Register, r2: Register) Instruction {
179 return rType(0b0110011, 0b100, 0b0000000, rd, r1, r2);
180 }
181
182 pub fn sll(rd: Register, r1: Register, r2: Register) Instruction {
183 return rType(0b0110011, 0b001, 0b0000000, rd, r1, r2);
184 }
185
186 pub fn srl(rd: Register, r1: Register, r2: Register) Instruction {
187 return rType(0b0110011, 0b101, 0b0000000, rd, r1, r2);
188 }
189
190 pub fn sra(rd: Register, r1: Register, r2: Register) Instruction {
191 return rType(0b0110011, 0b101, 0b0100000, rd, r1, r2);
192 }
193
194 pub fn slt(rd: Register, r1: Register, r2: Register) Instruction {
195 return rType(0b0110011, 0b010, 0b0000000, rd, r1, r2);
196 }
197
198 pub fn sltu(rd: Register, r1: Register, r2: Register) Instruction {
199 return rType(0b0110011, 0b011, 0b0000000, rd, r1, r2);
200 }
201
202 // Arithmetic/Logical, Register-Register (32-bit)
203
204 pub fn addw(rd: Register, r1: Register, r2: Register) Instruction {
205 return rType(0b0111011, 0b000, rd, r1, r2);
206 }
207
208 pub fn subw(rd: Register, r1: Register, r2: Register) Instruction {
209 return rType(0b0111011, 0b000, 0b0100000, rd, r1, r2);
210 }
211
212 pub fn sllw(rd: Register, r1: Register, r2: Register) Instruction {
213 return rType(0b0111011, 0b001, 0b0000000, rd, r1, r2);
214 }
215
216 pub fn srlw(rd: Register, r1: Register, r2: Register) Instruction {
217 return rType(0b0111011, 0b101, 0b0000000, rd, r1, r2);
218 }
219
220 pub fn sraw(rd: Register, r1: Register, r2: Register) Instruction {
221 return rType(0b0111011, 0b101, 0b0100000, rd, r1, r2);
222 }
223
224 // Arithmetic/Logical, Register-Immediate
225
226 pub fn addi(rd: Register, r1: Register, imm: i12) Instruction {
227 return iType(0b0010011, 0b000, rd, r1, imm);
228 }
229
230 pub fn andi(rd: Register, r1: Register, imm: i12) Instruction {
231 return iType(0b0010011, 0b111, rd, r1, imm);
232 }
233
234 pub fn ori(rd: Register, r1: Register, imm: i12) Instruction {
235 return iType(0b0010011, 0b110, rd, r1, imm);
236 }
237
238 pub fn xori(rd: Register, r1: Register, imm: i12) Instruction {
239 return iType(0b0010011, 0b100, rd, r1, imm);
240 }
241
242 pub fn slli(rd: Register, r1: Register, shamt: u6) Instruction {
243 return iType(0b0010011, 0b001, rd, r1, shamt);
244 }
245
246 pub fn srli(rd: Register, r1: Register, shamt: u6) Instruction {
247 return iType(0b0010011, 0b101, rd, r1, shamt);
248 }
249
250 pub fn srai(rd: Register, r1: Register, shamt: u6) Instruction {
251 return iType(0b0010011, 0b101, rd, r1, (1 << 10) + shamt);
252 }
253
254 pub fn slti(rd: Register, r1: Register, imm: i12) Instruction {
255 return iType(0b0010011, 0b010, rd, r1, imm);
256 }
257
258 pub fn sltiu(rd: Register, r1: Register, imm: u12) Instruction {
259 return iType(0b0010011, 0b011, rd, r1, @bitCast(i12, imm));
260 }
261
262 // Arithmetic/Logical, Register-Immediate (32-bit)
263
264 pub fn addiw(rd: Register, r1: Register, imm: i12) Instruction {
265 return iType(0b0011011, 0b000, rd, r1, imm);
266 }
267
268 pub fn slliw(rd: Register, r1: Register, shamt: u5) Instruction {
269 return iType(0b0011011, 0b001, rd, r1, shamt);
270 }
271
272 pub fn srliw(rd: Register, r1: Register, shamt: u5) Instruction {
273 return iType(0b0011011, 0b101, rd, r1, shamt);
274 }
275
276 pub fn sraiw(rd: Register, r1: Register, shamt: u5) Instruction {
277 return iType(0b0011011, 0b101, rd, r1, (1 << 10) + shamt);
278 }
279
280 // Upper Immediate
281
282 pub fn lui(rd: Register, imm: i20) Instruction {
283 return uType(0b0110111, rd, imm);
284 }
285
286 pub fn auipc(rd: Register, imm: i20) Instruction {
287 return uType(0b0010111, rd, imm);
288 }
289
290 // Load
291
292 pub fn ld(rd: Register, offset: i12, base: Register) Instruction {
293 return iType(0b0000011, 0b011, rd, base, offset);
294 }
295
296 pub fn lw(rd: Register, offset: i12, base: Register) Instruction {
297 return iType(0b0000011, 0b010, rd, base, offset);
298 }
299
300 pub fn lwu(rd: Register, offset: i12, base: Register) Instruction {
301 return iType(0b0000011, 0b110, rd, base, offset);
302 }
303
304 pub fn lh(rd: Register, offset: i12, base: Register) Instruction {
305 return iType(0b0000011, 0b001, rd, base, offset);
306 }
307
308 pub fn lhu(rd: Register, offset: i12, base: Register) Instruction {
309 return iType(0b0000011, 0b101, rd, base, offset);
310 }
311
312 pub fn lb(rd: Register, offset: i12, base: Register) Instruction {
313 return iType(0b0000011, 0b000, rd, base, offset);
314 }
315
316 pub fn lbu(rd: Register, offset: i12, base: Register) Instruction {
317 return iType(0b0000011, 0b100, rd, base, offset);
318 }
319
320 // Store
321
322 pub fn sd(rs: Register, offset: i12, base: Register) Instruction {
323 return sType(0b0100011, 0b011, base, rs, offset);
324 }
325
326 pub fn sw(rs: Register, offset: i12, base: Register) Instruction {
327 return sType(0b0100011, 0b010, base, rs, offset);
328 }
329
330 pub fn sh(rs: Register, offset: i12, base: Register) Instruction {
331 return sType(0b0100011, 0b001, base, rs, offset);
332 }
333
334 pub fn sb(rs: Register, offset: i12, base: Register) Instruction {
335 return sType(0b0100011, 0b000, base, rs, offset);
336 }
337
338 // Fence
339 // TODO: implement fence
340
341 // Branch
342
343 pub fn beq(r1: Register, r2: Register, offset: u13) Instruction {
344 return bType(0b1100011, 0b000, r1, r2, offset);
345 }
346
347 pub fn bne(r1: Register, r2: Register, offset: u13) Instruction {
348 return bType(0b1100011, 0b001, r1, r2, offset);
349 }
350
351 pub fn blt(r1: Register, r2: Register, offset: u13) Instruction {
352 return bType(0b1100011, 0b100, r1, r2, offset);
353 }
354
355 pub fn bge(r1: Register, r2: Register, offset: u13) Instruction {
356 return bType(0b1100011, 0b101, r1, r2, offset);
357 }
358
359 pub fn bltu(r1: Register, r2: Register, offset: u13) Instruction {
360 return bType(0b1100011, 0b110, r1, r2, offset);
361 }
362
363 pub fn bgeu(r1: Register, r2: Register, offset: u13) Instruction {
364 return bType(0b1100011, 0b111, r1, r2, offset);
365 }
366
367 // Jump
368
369 pub fn jal(link: Register, offset: i21) Instruction {
370 return jType(0b1101111, link, offset);
371 }
372
373 pub fn jalr(link: Register, offset: i12, base: Register) Instruction {
374 return iType(0b1100111, 0b000, link, base, offset);
375 }
376
377 // System
378
379 pub const ecall = iType(0b1110011, 0b000, .zero, .zero, 0x000);
380 pub const ebreak = iType(0b1110011, 0b000, .zero, .zero, 0x001);
44};381};
45382
46// zig fmt: off383// zig fmt: off
47pub const RawRegister = enum(u8) {384pub const RawRegister = enum(u5) {
48 x0, x1, x2, x3, x4, x5, x6, x7,385 x0, x1, x2, x3, x4, x5, x6, x7,
49 x8, x9, x10, x11, x12, x13, x14, x15,386 x8, x9, x10, x11, x12, x13, x14, x15,
50 x16, x17, x18, x19, x20, x21, x22, x23,387 x16, x17, x18, x19, x20, x21, x22, x23,
...@@ -55,7 +392,7 @@ pub const RawRegister = enum(u8) {...@@ -55,7 +392,7 @@ pub const RawRegister = enum(u8) {
55 }392 }
56};393};
57394
58pub const Register = enum(u8) {395pub const Register = enum(u5) {
59 // 64 bit registers396 // 64 bit registers
60 zero, // zero397 zero, // zero
61 ra, // return address. caller saved398 ra, // return address. caller saved
...@@ -76,11 +413,6 @@ pub const Register = enum(u8) {...@@ -76,11 +413,6 @@ pub const Register = enum(u8) {
76 return null;413 return null;
77 }414 }
78415
79 /// Returns the register's id.
80 pub fn id(self: @This()) u5 {
81 return @truncate(u5, @enumToInt(self));
82 }
83
84 /// Returns the index into `callee_preserved_regs`.416 /// Returns the index into `callee_preserved_regs`.
85 pub fn allocIndex(self: Register) ?u4 {417 pub fn allocIndex(self: Register) ?u4 {
86 inline for(callee_preserved_regs) |cpreg, i| {418 inline for(callee_preserved_regs) |cpreg, i| {
...@@ -90,7 +422,7 @@ pub const Register = enum(u8) {...@@ -90,7 +422,7 @@ pub const Register = enum(u8) {
90 }422 }
91423
92 pub fn dwarfLocOp(reg: Register) u8 {424 pub fn dwarfLocOp(reg: Register) u8 {
93 return @enumToInt(reg) + DW.OP_reg0;425 return @as(u8, @enumToInt(reg)) + DW.OP_reg0;
94 }426 }
95};427};
96428