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" {...@@ -195,12 +195,12 @@ test "FloatingPointRegister.toX" {
195195
196/// Represents an instruction in the AArch64 instruction set196/// Represents an instruction in the AArch64 instruction set
197pub const Instruction = union(enum) {197pub const Instruction = union(enum) {
198 MoveWideWithZero: packed struct {198 MoveWideImmediate: packed struct {
199 rd: u5,199 rd: u5,
200 imm16: u16,200 imm16: u16,
201 hw: u2,201 hw: u2,
202 fixed: u6 = 0b100101,202 fixed: u6 = 0b100101,
203 opc: u2 = 0b10,203 opc: u2,
204 sf: u1,204 sf: u1,
205 },205 },
206 ExceptionGeneration: packed struct {206 ExceptionGeneration: packed struct {
...@@ -226,7 +226,7 @@ pub const Instruction = union(enum) {...@@ -226,7 +226,7 @@ pub const Instruction = union(enum) {
226226
227 pub fn toU32(self: Instruction) u32 {227 pub fn toU32(self: Instruction) u32 {
228 return switch (self) {228 return switch (self) {
229 .MoveWideWithZero => |v| @bitCast(u32, v),229 .MoveWideImmediate => |v| @bitCast(u32, v),
230 .ExceptionGeneration => |v| @bitCast(u32, v),230 .ExceptionGeneration => |v| @bitCast(u32, v),
231 .UnconditionalBranchRegister => |v| @bitCast(u32, v),231 .UnconditionalBranchRegister => |v| @bitCast(u32, v),
232 .UnconditionalBranchImmediate => |v| @bitCast(u32, v),232 .UnconditionalBranchImmediate => |v| @bitCast(u32, v),
...@@ -235,24 +235,33 @@ pub const Instruction = union(enum) {...@@ -235,24 +235,33 @@ pub const Instruction = union(enum) {
235235
236 // Helper functions for assembly syntax functions236 // 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 {
239 switch (rd.size()) {244 switch (rd.size()) {
240 32 => {245 32 => {
246 assert(shift % 16 == 0 and shift <= 16);
241 return Instruction{247 return Instruction{
242 .MoveWideWithZero = .{248 .MoveWideImmediate = .{
243 .rd = rd.id(),249 .rd = rd.id(),
244 .imm16 = imm16,250 .imm16 = imm16,
245 .hw = 0b01 & shift, // TODO shift should be an enum251 .hw = @intCast(u2, shift / 16),
252 .opc = opc,
246 .sf = 0,253 .sf = 0,
247 },254 },
248 };255 };
249 },256 },
250 64 => {257 64 => {
258 assert(shift % 16 == 0 and shift <= 48);
251 return Instruction{259 return Instruction{
252 .MoveWideWithZero = .{260 .MoveWideImmediate = .{
253 .rd = rd.id(),261 .rd = rd.id(),
254 .imm16 = imm16,262 .imm16 = imm16,
255 .hw = shift,263 .hw = @intCast(u2, shift / 16),
264 .opc = opc,
256 .sf = 1,265 .sf = 1,
257 },266 },
258 };267 };
...@@ -284,6 +293,8 @@ pub const Instruction = union(enum) {...@@ -284,6 +293,8 @@ pub const Instruction = union(enum) {
284 rn: Register,293 rn: Register,
285 op4: u5,294 op4: u5,
286 ) Instruction {295 ) Instruction {
296 assert(rn.size() == 64);
297
287 return Instruction{298 return Instruction{
288 .UnconditionalBranchRegister = .{299 .UnconditionalBranchRegister = .{
289 .op4 = op4,300 .op4 = op4,
...@@ -301,16 +312,24 @@ pub const Instruction = union(enum) {...@@ -301,16 +312,24 @@ pub const Instruction = union(enum) {
301 ) Instruction {312 ) Instruction {
302 return Instruction{313 return Instruction{
303 .UnconditionalBranchImmediate = .{314 .UnconditionalBranchImmediate = .{
304 .imm26 = @bitCast(u26, @intCast(i26, imm26 >> 2)),315 .imm26 = @bitCast(u26, @intCast(i26, offset >> 2)),
305 .op = op,316 .op = op,
306 },317 },
307 };318 };
308 }319 }
309320
310 // movz321 // 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 {331 pub fn movk(rd: Register, imm16: u16, shift: u6) Instruction {
313 return moveWideWithZero(rd, imm16, shift);332 return moveWideImmediate(0b11, rd, imm16, shift);
314 }333 }
315334
316 // Exception generation335 // Exception generation
...@@ -338,7 +357,6 @@ pub const Instruction = union(enum) {...@@ -338,7 +357,6 @@ pub const Instruction = union(enum) {
338 // Unconditional branch (register)357 // Unconditional branch (register)
339358
340 pub fn br(rn: Register) Instruction {359 pub fn br(rn: Register) Instruction {
341 assert(rn.size() == 64);
342 return unconditionalBranchRegister(0b0000, 0b11111, 0b000000, rn, 0b00000);360 return unconditionalBranchRegister(0b0000, 0b11111, 0b000000, rn, 0b00000);
343 }361 }
344362
...@@ -368,28 +386,20 @@ test "serialize instructions" {...@@ -368,28 +386,20 @@ test "serialize instructions" {
368 };386 };
369387
370 const testcases = [_]Testcase{388 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 },
379 .{ // movz x1 #4389 .{ // movz x1 #4
380 .inst = Instruction.movz(.x1, 4, 0),390 .inst = Instruction.movz(.x1, 4, 0),
381 .expected = 0b1_10_100101_00_0000000000000100_00001,391 .expected = 0b1_10_100101_00_0000000000000100_00001,
382 },392 },
383 .{ // movz x1, #4, lsl 16393 .{ // movz x1, #4, lsl 16
384 .inst = Instruction.movz(.x1, 4, 1),394 .inst = Instruction.movz(.x1, 4, 16),
385 .expected = 0b1_10_100101_01_0000000000000100_00001,395 .expected = 0b1_10_100101_01_0000000000000100_00001,
386 },396 },
387 .{ // movz x1, #4, lsl 32397 .{ // movz x1, #4, lsl 32
388 .inst = Instruction.movz(.x1, 4, 2),398 .inst = Instruction.movz(.x1, 4, 32),
389 .expected = 0b1_10_100101_10_0000000000000100_00001,399 .expected = 0b1_10_100101_10_0000000000000100_00001,
390 },400 },
391 .{ // movz x1, #4, lsl 48401 .{ // movz x1, #4, lsl 48
392 .inst = Instruction.movz(.x1, 4, 3),402 .inst = Instruction.movz(.x1, 4, 48),
393 .expected = 0b1_10_100101_11_0000000000000100_00001,403 .expected = 0b1_10_100101_11_0000000000000100_00001,
394 },404 },
395 .{ // movz w1, #4405 .{ // movz w1, #4
...@@ -397,9 +407,25 @@ test "serialize instructions" {...@@ -397,9 +407,25 @@ test "serialize instructions" {
397 .expected = 0b0_10_100101_00_0000000000000100_00001,407 .expected = 0b0_10_100101_00_0000000000000100_00001,
398 },408 },
399 .{ // movz w1, #4, lsl 16409 .{ // movz w1, #4, lsl 16
400 .inst = Instruction.movz(.w1, 4, 1),410 .inst = Instruction.movz(.w1, 4, 16),
401 .expected = 0b0_10_100101_01_0000000000000100_00001,411 .expected = 0b0_10_100101_01_0000000000000100_00001,
402 },412 },
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 },
403 };429 };
404430
405 for (testcases) |case| {431 for (testcases) |case| {