authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-02-05 18:45:35+01:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-02-14 22:09:43+01:00
log82f91adbb4ef77e8a2b05da923bb1d0c9c3a8262
tree6547c70f7dcd0b903c3f9478740b342a79fb8708
parent77cf000438c8f65f089e9c64fbb881a9136f2931
signaturelock-open Commit is signed but in an unrecognized format.

stage2 AArch64: Add madd, msub, mul, mneg instructions


1 files changed, 61 insertions(+), 0 deletions(-)

src/arch/aarch64/bits.zig+61
......@@ -332,6 +332,17 @@ pub const Instruction = union(enum) {
332332 op: u1,
333333 sf: u1,
334334 },
335 data_processing_3_source: packed struct {
336 rd: u5,
337 rn: u5,
338 ra: u5,
339 o0: u1,
340 rm: u5,
341 op31: u3,
342 fixed: u5 = 0b11011,
343 op54: u2,
344 sf: u1,
345 },
335346
336347 pub const Shift = struct {
337348 shift: Type = .lsl,
......@@ -470,6 +481,7 @@ pub const Instruction = union(enum) {
470481 .conditional_branch => |v| @as(u32, v.cond) | (@as(u32, v.o0) << 4) | (@as(u32, v.imm19) << 5) | (@as(u32, v.o1) << 24) | (@as(u32, v.fixed) << 25),
471482 .compare_and_branch => |v| @as(u32, v.rt) | (@as(u32, v.imm19) << 5) | (@as(u32, v.op) << 24) | (@as(u32, v.fixed) << 25) | (@as(u32, v.sf) << 31),
472483 .conditional_select => |v| @as(u32, v.rd) | @as(u32, v.rn) << 5 | @as(u32, v.op2) << 10 | @as(u32, v.cond) << 12 | @as(u32, v.rm) << 16 | @as(u32, v.fixed) << 21 | @as(u32, v.s) << 29 | @as(u32, v.op) << 30 | @as(u32, v.sf) << 31,
484 .data_processing_3_source => |v| @bitCast(u32, v),
473485 };
474486 }
475487
......@@ -967,6 +979,33 @@ pub const Instruction = union(enum) {
967979 };
968980 }
969981
982 fn dataProcessing3Source(
983 op54: u2,
984 op31: u3,
985 o0: u1,
986 rd: Register,
987 rn: Register,
988 rm: Register,
989 ra: Register,
990 ) Instruction {
991 return Instruction{
992 .data_processing_3_source = .{
993 .rd = rd.id(),
994 .rn = rn.id(),
995 .ra = ra.id(),
996 .o0 = o0,
997 .rm = rm.id(),
998 .op31 = op31,
999 .op54 = op54,
1000 .sf = switch (rd.size()) {
1001 32 => 0b0,
1002 64 => 0b1,
1003 else => unreachable, // unexpected register size
1004 },
1005 },
1006 };
1007 }
1008
9701009 // Helper functions for assembly syntax functions
9711010
9721011 // Move wide (immediate)
......@@ -1245,6 +1284,24 @@ pub const Instruction = union(enum) {
12451284 pub fn csneg(rd: Register, rn: Register, rm: Register, cond: Condition) Instruction {
12461285 return conditionalSelect(0b01, 0b1, 0b0, rd, rn, rm, cond);
12471286 }
1287
1288 // Data processing (3 source)
1289
1290 pub fn madd(rd: Register, rn: Register, rm: Register, ra: Register) Instruction {
1291 return dataProcessing3Source(0b00, 0b000, 0b0, rd, rn, rm, ra);
1292 }
1293
1294 pub fn msub(rd: Register, rn: Register, rm: Register, ra: Register) Instruction {
1295 return dataProcessing3Source(0b00, 0b000, 0b1, rd, rn, rm, ra);
1296 }
1297
1298 pub fn mul(rd: Register, rn: Register, rm: Register) Instruction {
1299 return madd(rd, rn, rm, .xzr);
1300 }
1301
1302 pub fn mneg(rd: Register, rn: Register, rm: Register) Instruction {
1303 return msub(rd, rn, rm, .xzr);
1304 }
12481305};
12491306
12501307test {
......@@ -1414,6 +1471,10 @@ test "serialize instructions" {
14141471 .inst = Instruction.csinc(.x1, .x2, .x4, .eq),
14151472 .expected = 0b1_0_0_11010100_00100_0000_0_1_00010_00001,
14161473 },
1474 .{ // mul x1, x4, x9
1475 .inst = Instruction.mul(.x1, .x4, .x9),
1476 .expected = 0b1_00_11011_000_01001_0_11111_00100_00001,
1477 },
14171478 };
14181479
14191480 for (testcases) |case| {