authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2021-08-25 20:37:40+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-08-26 14:42:28+02:00
log04cafd81377b9c57006a28407b0d97bc1164345e
treede0bcb59a1e7a01d2125a536732df8d63b20dc3f
parent9c95f38a7c1defc7f63a4815bfc2d76a5f9f83f6

stage2 ARM: Add qadd, qsub, qdadd, qdsub instructions

These are integer saturating arithmetic instructions

1 files changed, 85 insertions(+), 34 deletions(-)

src/codegen/arm.zig+85-34
......@@ -192,7 +192,7 @@ pub const c_abi_int_return_regs = [_]Register{ .r0, .r1 };
192192
193193/// Represents an instruction in the ARM instruction set architecture
194194pub const Instruction = union(enum) {
195 DataProcessing: packed struct {
195 data_processing: packed struct {
196196 // Note to self: The order of the fields top-to-bottom is
197197 // right-to-left in the actual 32-bit int representation
198198 op2: u12,
......@@ -204,7 +204,7 @@ pub const Instruction = union(enum) {
204204 fixed: u2 = 0b00,
205205 cond: u4,
206206 },
207 Multiply: packed struct {
207 multiply: packed struct {
208208 rn: u4,
209209 fixed_1: u4 = 0b1001,
210210 rm: u4,
......@@ -215,7 +215,7 @@ pub const Instruction = union(enum) {
215215 fixed_2: u6 = 0b000000,
216216 cond: u4,
217217 },
218 MultiplyLong: packed struct {
218 multiply_long: packed struct {
219219 rn: u4,
220220 fixed_1: u4 = 0b1001,
221221 rm: u4,
......@@ -227,7 +227,17 @@ pub const Instruction = union(enum) {
227227 fixed_2: u5 = 0b00001,
228228 cond: u4,
229229 },
230 SingleDataTransfer: packed struct {
230 integer_saturating_arithmetic: packed struct {
231 rm: u4,
232 fixed_1: u8 = 0b0000_0101,
233 rd: u4,
234 rn: u4,
235 fixed_2: u1 = 0b0,
236 opc: u2,
237 fixed_3: u5 = 0b00010,
238 cond: u4,
239 },
240 single_data_transfer: packed struct {
231241 offset: u12,
232242 rd: u4,
233243 rn: u4,
......@@ -240,7 +250,7 @@ pub const Instruction = union(enum) {
240250 fixed: u2 = 0b01,
241251 cond: u4,
242252 },
243 ExtraLoadStore: packed struct {
253 extra_load_store: packed struct {
244254 imm4l: u4,
245255 fixed_1: u1 = 0b1,
246256 op2: u2,
......@@ -256,7 +266,7 @@ pub const Instruction = union(enum) {
256266 fixed_3: u3 = 0b000,
257267 cond: u4,
258268 },
259 BlockDataTransfer: packed struct {
269 block_data_transfer: packed struct {
260270 register_list: u16,
261271 rn: u4,
262272 load_store: u1,
......@@ -267,25 +277,25 @@ pub const Instruction = union(enum) {
267277 fixed: u3 = 0b100,
268278 cond: u4,
269279 },
270 Branch: packed struct {
280 branch: packed struct {
271281 offset: u24,
272282 link: u1,
273283 fixed: u3 = 0b101,
274284 cond: u4,
275285 },
276 BranchExchange: packed struct {
286 branch_exchange: packed struct {
277287 rn: u4,
278288 fixed_1: u1 = 0b1,
279289 link: u1,
280290 fixed_2: u22 = 0b0001_0010_1111_1111_1111_00,
281291 cond: u4,
282292 },
283 SupervisorCall: packed struct {
293 supervisor_call: packed struct {
284294 comment: u24,
285295 fixed: u4 = 0b1111,
286296 cond: u4,
287297 },
288 Breakpoint: packed struct {
298 breakpoint: packed struct {
289299 imm4: u4,
290300 fixed_1: u4 = 0b0111,
291301 imm12: u12,
......@@ -293,7 +303,7 @@ pub const Instruction = union(enum) {
293303 },
294304
295305 /// Represents the possible operations which can be performed by a
296 /// DataProcessing instruction
306 /// Data Processing instruction
297307 const Opcode = enum(u4) {
298308 // Rd := Op1 AND Op2
299309 @"and",
......@@ -530,16 +540,17 @@ pub const Instruction = union(enum) {
530540
531541 pub fn toU32(self: Instruction) u32 {
532542 return switch (self) {
533 .DataProcessing => |v| @bitCast(u32, v),
534 .Multiply => |v| @bitCast(u32, v),
535 .MultiplyLong => |v| @bitCast(u32, v),
536 .SingleDataTransfer => |v| @bitCast(u32, v),
537 .ExtraLoadStore => |v| @bitCast(u32, v),
538 .BlockDataTransfer => |v| @bitCast(u32, v),
539 .Branch => |v| @bitCast(u32, v),
540 .BranchExchange => |v| @bitCast(u32, v),
541 .SupervisorCall => |v| @bitCast(u32, v),
542 .Breakpoint => |v| @intCast(u32, v.imm4) | (@intCast(u32, v.fixed_1) << 4) | (@intCast(u32, v.imm12) << 8) | (@intCast(u32, v.fixed_2_and_cond) << 20),
543 .data_processing => |v| @bitCast(u32, v),
544 .multiply => |v| @bitCast(u32, v),
545 .multiply_long => |v| @bitCast(u32, v),
546 .integer_saturating_arithmetic => |v| @bitCast(u32, v),
547 .single_data_transfer => |v| @bitCast(u32, v),
548 .extra_load_store => |v| @bitCast(u32, v),
549 .block_data_transfer => |v| @bitCast(u32, v),
550 .branch => |v| @bitCast(u32, v),
551 .branch_exchange => |v| @bitCast(u32, v),
552 .supervisor_call => |v| @bitCast(u32, v),
553 .breakpoint => |v| @intCast(u32, v.imm4) | (@intCast(u32, v.fixed_1) << 4) | (@intCast(u32, v.imm12) << 8) | (@intCast(u32, v.fixed_2_and_cond) << 20),
543554 };
544555 }
545556
......@@ -554,7 +565,7 @@ pub const Instruction = union(enum) {
554565 op2: Operand,
555566 ) Instruction {
556567 return Instruction{
557 .DataProcessing = .{
568 .data_processing = .{
558569 .cond = @enumToInt(cond),
559570 .i = @boolToInt(op2 == .Immediate),
560571 .opcode = @enumToInt(opcode),
......@@ -573,7 +584,7 @@ pub const Instruction = union(enum) {
573584 top: bool,
574585 ) Instruction {
575586 return Instruction{
576 .DataProcessing = .{
587 .data_processing = .{
577588 .cond = @enumToInt(cond),
578589 .i = 1,
579590 .opcode = if (top) 0b1010 else 0b1000,
......@@ -594,7 +605,7 @@ pub const Instruction = union(enum) {
594605 ra: ?Register,
595606 ) Instruction {
596607 return Instruction{
597 .Multiply = .{
608 .multiply = .{
598609 .cond = @enumToInt(cond),
599610 .accumulate = @boolToInt(ra != null),
600611 .set_cond = set_cond,
......@@ -617,7 +628,7 @@ pub const Instruction = union(enum) {
617628 rn: Register,
618629 ) Instruction {
619630 return Instruction{
620 .MultiplyLong = .{
631 .multiply_long = .{
621632 .cond = @enumToInt(cond),
622633 .unsigned = signed,
623634 .accumulate = accumulate,
......@@ -630,6 +641,24 @@ pub const Instruction = union(enum) {
630641 };
631642 }
632643
644 fn integerSaturationArithmetic(
645 cond: Condition,
646 rd: Register,
647 rm: Register,
648 rn: Register,
649 opc: u2,
650 ) Instruction {
651 return Instruction{
652 .integer_saturating_arithmetic = .{
653 .rm = rm.id(),
654 .rd = rd.id(),
655 .rn = rn.id(),
656 .opc = opc,
657 .cond = @enumToInt(cond),
658 },
659 };
660 }
661
633662 fn singleDataTransfer(
634663 cond: Condition,
635664 rd: Register,
......@@ -642,7 +671,7 @@ pub const Instruction = union(enum) {
642671 load_store: u1,
643672 ) Instruction {
644673 return Instruction{
645 .SingleDataTransfer = .{
674 .single_data_transfer = .{
646675 .cond = @enumToInt(cond),
647676 .rn = rn.id(),
648677 .rd = rd.id(),
......@@ -678,7 +707,7 @@ pub const Instruction = union(enum) {
678707 };
679708
680709 return Instruction{
681 .ExtraLoadStore = .{
710 .extra_load_store = .{
682711 .imm4l = imm4l,
683712 .op2 = op2,
684713 .imm4h = imm4h,
......@@ -705,7 +734,7 @@ pub const Instruction = union(enum) {
705734 load_store: u1,
706735 ) Instruction {
707736 return Instruction{
708 .BlockDataTransfer = .{
737 .block_data_transfer = .{
709738 .register_list = @bitCast(u16, reg_list),
710739 .rn = rn.id(),
711740 .load_store = load_store,
......@@ -720,7 +749,7 @@ pub const Instruction = union(enum) {
720749
721750 fn branch(cond: Condition, offset: i26, link: u1) Instruction {
722751 return Instruction{
723 .Branch = .{
752 .branch = .{
724753 .cond = @enumToInt(cond),
725754 .link = link,
726755 .offset = @bitCast(u24, @intCast(i24, offset >> 2)),
......@@ -730,7 +759,7 @@ pub const Instruction = union(enum) {
730759
731760 fn branchExchange(cond: Condition, rn: Register, link: u1) Instruction {
732761 return Instruction{
733 .BranchExchange = .{
762 .branch_exchange = .{
734763 .cond = @enumToInt(cond),
735764 .link = link,
736765 .rn = rn.id(),
......@@ -740,7 +769,7 @@ pub const Instruction = union(enum) {
740769
741770 fn supervisorCall(cond: Condition, comment: u24) Instruction {
742771 return Instruction{
743 .SupervisorCall = .{
772 .supervisor_call = .{
744773 .cond = @enumToInt(cond),
745774 .comment = comment,
746775 },
......@@ -749,7 +778,7 @@ pub const Instruction = union(enum) {
749778
750779 fn breakpoint(imm: u16) Instruction {
751780 return Instruction{
752 .Breakpoint = .{
781 .breakpoint = .{
753782 .imm12 = @truncate(u12, imm >> 4),
754783 .imm4 = @truncate(u4, imm),
755784 },
......@@ -873,6 +902,24 @@ pub const Instruction = union(enum) {
873902 return dataProcessing(cond, .mvn, 1, rd, .r0, op2);
874903 }
875904
905 // Integer Saturating Arithmetic
906
907 pub fn qadd(cond: Condition, rd: Register, rm: Register, rn: Register) Instruction {
908 return integerSaturationArithmetic(cond, rd, rm, rn, 0b00);
909 }
910
911 pub fn qsub(cond: Condition, rd: Register, rm: Register, rn: Register) Instruction {
912 return integerSaturationArithmetic(cond, rd, rm, rn, 0b01);
913 }
914
915 pub fn qdadd(cond: Condition, rd: Register, rm: Register, rn: Register) Instruction {
916 return integerSaturationArithmetic(cond, rd, rm, rn, 0b10);
917 }
918
919 pub fn qdsub(cond: Condition, rd: Register, rm: Register, rn: Register) Instruction {
920 return integerSaturationArithmetic(cond, rd, rm, rn, 0b11);
921 }
922
876923 // movw and movt
877924
878925 pub fn movw(cond: Condition, rd: Register, imm: u16) Instruction {
......@@ -887,7 +934,7 @@ pub const Instruction = union(enum) {
887934
888935 pub fn mrs(cond: Condition, rd: Register, psr: Psr) Instruction {
889936 return Instruction{
890 .DataProcessing = .{
937 .data_processing = .{
891938 .cond = @enumToInt(cond),
892939 .i = 0,
893940 .opcode = if (psr == .spsr) 0b1010 else 0b1000,
......@@ -901,7 +948,7 @@ pub const Instruction = union(enum) {
901948
902949 pub fn msr(cond: Condition, psr: Psr, op: Operand) Instruction {
903950 return Instruction{
904 .DataProcessing = .{
951 .data_processing = .{
905952 .cond = @enumToInt(cond),
906953 .i = 0,
907954 .opcode = if (psr == .spsr) 0b1011 else 0b1001,
......@@ -1294,6 +1341,10 @@ test "serialize instructions" {
12941341 .inst = Instruction.ldmea(.al, .r4, true, .{ .r2 = true, .r5 = true }),
12951342 .expected = 0b1110_100_1_0_0_1_1_0100_0000000000100100,
12961343 },
1344 .{ // qadd r0, r7, r8
1345 .inst = Instruction.qadd(.al, .r0, .r7, .r8),
1346 .expected = 0b1110_00010_00_0_1000_0000_0000_0101_0111,
1347 },
12971348 };
12981349
12991350 for (testcases) |case| {