authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2020-11-08 20:21:36+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-11-11 14:34:53+01:00
logaa9df72f714c0bd3c8653ea0c5431d43543b6f6f
tree8e56b9d769d2364e97ba23807b6350226b121b3c
parent4c8f69241a70d8eac76b288a5c6a2d586696534f

stage2 AArch64: MoveWideImmediate instructions + test coverage


1 files changed, 51 insertions(+), 25 deletions(-)

src/codegen/aarch64.zig+51-25
......@@ -195,12 +195,12 @@ test "FloatingPointRegister.toX" {
195195
196196/// Represents an instruction in the AArch64 instruction set
197197pub const Instruction = union(enum) {
198 MoveWideWithZero: packed struct {
198 MoveWideImmediate: packed struct {
199199 rd: u5,
200200 imm16: u16,
201201 hw: u2,
202202 fixed: u6 = 0b100101,
203 opc: u2 = 0b10,
203 opc: u2,
204204 sf: u1,
205205 },
206206 ExceptionGeneration: packed struct {
......@@ -226,7 +226,7 @@ pub const Instruction = union(enum) {
226226
227227 pub fn toU32(self: Instruction) u32 {
228228 return switch (self) {
229 .MoveWideWithZero => |v| @bitCast(u32, v),
229 .MoveWideImmediate => |v| @bitCast(u32, v),
230230 .ExceptionGeneration => |v| @bitCast(u32, v),
231231 .UnconditionalBranchRegister => |v| @bitCast(u32, v),
232232 .UnconditionalBranchImmediate => |v| @bitCast(u32, v),
......@@ -235,24 +235,33 @@ pub const Instruction = union(enum) {
235235
236236 // Helper functions for assembly syntax functions
237237
238 fn moveWideWithZero(rd: Register, imm16: u16, shift: u2) Instruction {
238 fn moveWideImmediate(
239 opc: u2,
240 rd: Register,
241 imm16: u16,
242 shift: u6,
243 ) Instruction {
239244 switch (rd.size()) {
240245 32 => {
246 assert(shift % 16 == 0 and shift <= 16);
241247 return Instruction{
242 .MoveWideWithZero = .{
248 .MoveWideImmediate = .{
243249 .rd = rd.id(),
244250 .imm16 = imm16,
245 .hw = 0b01 & shift, // TODO shift should be an enum
251 .hw = @intCast(u2, shift / 16),
252 .opc = opc,
246253 .sf = 0,
247254 },
248255 };
249256 },
250257 64 => {
258 assert(shift % 16 == 0 and shift <= 48);
251259 return Instruction{
252 .MoveWideWithZero = .{
260 .MoveWideImmediate = .{
253261 .rd = rd.id(),
254262 .imm16 = imm16,
255 .hw = shift,
263 .hw = @intCast(u2, shift / 16),
264 .opc = opc,
256265 .sf = 1,
257266 },
258267 };
......@@ -284,6 +293,8 @@ pub const Instruction = union(enum) {
284293 rn: Register,
285294 op4: u5,
286295 ) Instruction {
296 assert(rn.size() == 64);
297
287298 return Instruction{
288299 .UnconditionalBranchRegister = .{
289300 .op4 = op4,
......@@ -301,16 +312,24 @@ pub const Instruction = union(enum) {
301312 ) Instruction {
302313 return Instruction{
303314 .UnconditionalBranchImmediate = .{
304 .imm26 = @bitCast(u26, @intCast(i26, imm26 >> 2)),
315 .imm26 = @bitCast(u26, @intCast(i26, offset >> 2)),
305316 .op = op,
306317 },
307318 };
308319 }
309320
310 // movz
321 // Move wide (immediate)
322
323 pub fn movn(rd: Register, imm16: u16, shift: u6) Instruction {
324 return moveWideImmediate(0b00, rd, imm16, shift);
325 }
326
327 pub fn movz(rd: Register, imm16: u16, shift: u6) Instruction {
328 return moveWideImmediate(0b10, rd, imm16, shift);
329 }
311330
312 pub fn movz(rd: Register, imm16: u16, shift: u2) Instruction {
313 return moveWideWithZero(rd, imm16, shift);
331 pub fn movk(rd: Register, imm16: u16, shift: u6) Instruction {
332 return moveWideImmediate(0b11, rd, imm16, shift);
314333 }
315334
316335 // Exception generation
......@@ -338,7 +357,6 @@ pub const Instruction = union(enum) {
338357 // Unconditional branch (register)
339358
340359 pub fn br(rn: Register) Instruction {
341 assert(rn.size() == 64);
342360 return unconditionalBranchRegister(0b0000, 0b11111, 0b000000, rn, 0b00000);
343361 }
344362
......@@ -368,28 +386,20 @@ test "serialize instructions" {
368386 };
369387
370388 const testcases = [_]Testcase{
371 .{ // svc #0
372 .inst = Instruction.svc(0),
373 .expected = 0b1101_0100_000_0000000000000000_00001,
374 },
375 .{ // svc #0x80 ; typical on Darwin
376 .inst = Instruction.svc(0x80),
377 .expected = 0b1101_0100_000_0000000010000000_00001,
378 },
379389 .{ // movz x1 #4
380390 .inst = Instruction.movz(.x1, 4, 0),
381391 .expected = 0b1_10_100101_00_0000000000000100_00001,
382392 },
383393 .{ // movz x1, #4, lsl 16
384 .inst = Instruction.movz(.x1, 4, 1),
394 .inst = Instruction.movz(.x1, 4, 16),
385395 .expected = 0b1_10_100101_01_0000000000000100_00001,
386396 },
387397 .{ // movz x1, #4, lsl 32
388 .inst = Instruction.movz(.x1, 4, 2),
398 .inst = Instruction.movz(.x1, 4, 32),
389399 .expected = 0b1_10_100101_10_0000000000000100_00001,
390400 },
391401 .{ // movz x1, #4, lsl 48
392 .inst = Instruction.movz(.x1, 4, 3),
402 .inst = Instruction.movz(.x1, 4, 48),
393403 .expected = 0b1_10_100101_11_0000000000000100_00001,
394404 },
395405 .{ // movz w1, #4
......@@ -397,9 +407,25 @@ test "serialize instructions" {
397407 .expected = 0b0_10_100101_00_0000000000000100_00001,
398408 },
399409 .{ // movz w1, #4, lsl 16
400 .inst = Instruction.movz(.w1, 4, 1),
410 .inst = Instruction.movz(.w1, 4, 16),
401411 .expected = 0b0_10_100101_01_0000000000000100_00001,
402412 },
413 .{ // svc #0
414 .inst = Instruction.svc(0),
415 .expected = 0b1101_0100_000_0000000000000000_00001,
416 },
417 .{ // svc #0x80 ; typical on Darwin
418 .inst = Instruction.svc(0x80),
419 .expected = 0b1101_0100_000_0000000010000000_00001,
420 },
421 .{ // ret
422 .inst = Instruction.ret(null),
423 .expected = 0b1101_011_00_10_11111_0000_00_11110_00000,
424 },
425 .{ // bl #0x10
426 .inst = Instruction.bl(0x10),
427 .expected = 0b1_00101_00_0000_0000_0000_0000_0000_0100,
428 },
403429 };
404430
405431 for (testcases) |case| {