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 };...@@ -192,7 +192,7 @@ pub const c_abi_int_return_regs = [_]Register{ .r0, .r1 };
192192
193/// Represents an instruction in the ARM instruction set architecture193/// Represents an instruction in the ARM instruction set architecture
194pub const Instruction = union(enum) {194pub const Instruction = union(enum) {
195 DataProcessing: packed struct {195 data_processing: packed struct {
196 // Note to self: The order of the fields top-to-bottom is196 // Note to self: The order of the fields top-to-bottom is
197 // right-to-left in the actual 32-bit int representation197 // right-to-left in the actual 32-bit int representation
198 op2: u12,198 op2: u12,
...@@ -204,7 +204,7 @@ pub const Instruction = union(enum) {...@@ -204,7 +204,7 @@ pub const Instruction = union(enum) {
204 fixed: u2 = 0b00,204 fixed: u2 = 0b00,
205 cond: u4,205 cond: u4,
206 },206 },
207 Multiply: packed struct {207 multiply: packed struct {
208 rn: u4,208 rn: u4,
209 fixed_1: u4 = 0b1001,209 fixed_1: u4 = 0b1001,
210 rm: u4,210 rm: u4,
...@@ -215,7 +215,7 @@ pub const Instruction = union(enum) {...@@ -215,7 +215,7 @@ pub const Instruction = union(enum) {
215 fixed_2: u6 = 0b000000,215 fixed_2: u6 = 0b000000,
216 cond: u4,216 cond: u4,
217 },217 },
218 MultiplyLong: packed struct {218 multiply_long: packed struct {
219 rn: u4,219 rn: u4,
220 fixed_1: u4 = 0b1001,220 fixed_1: u4 = 0b1001,
221 rm: u4,221 rm: u4,
...@@ -227,7 +227,17 @@ pub const Instruction = union(enum) {...@@ -227,7 +227,17 @@ pub const Instruction = union(enum) {
227 fixed_2: u5 = 0b00001,227 fixed_2: u5 = 0b00001,
228 cond: u4,228 cond: u4,
229 },229 },
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 {
231 offset: u12,241 offset: u12,
232 rd: u4,242 rd: u4,
233 rn: u4,243 rn: u4,
...@@ -240,7 +250,7 @@ pub const Instruction = union(enum) {...@@ -240,7 +250,7 @@ pub const Instruction = union(enum) {
240 fixed: u2 = 0b01,250 fixed: u2 = 0b01,
241 cond: u4,251 cond: u4,
242 },252 },
243 ExtraLoadStore: packed struct {253 extra_load_store: packed struct {
244 imm4l: u4,254 imm4l: u4,
245 fixed_1: u1 = 0b1,255 fixed_1: u1 = 0b1,
246 op2: u2,256 op2: u2,
...@@ -256,7 +266,7 @@ pub const Instruction = union(enum) {...@@ -256,7 +266,7 @@ pub const Instruction = union(enum) {
256 fixed_3: u3 = 0b000,266 fixed_3: u3 = 0b000,
257 cond: u4,267 cond: u4,
258 },268 },
259 BlockDataTransfer: packed struct {269 block_data_transfer: packed struct {
260 register_list: u16,270 register_list: u16,
261 rn: u4,271 rn: u4,
262 load_store: u1,272 load_store: u1,
...@@ -267,25 +277,25 @@ pub const Instruction = union(enum) {...@@ -267,25 +277,25 @@ pub const Instruction = union(enum) {
267 fixed: u3 = 0b100,277 fixed: u3 = 0b100,
268 cond: u4,278 cond: u4,
269 },279 },
270 Branch: packed struct {280 branch: packed struct {
271 offset: u24,281 offset: u24,
272 link: u1,282 link: u1,
273 fixed: u3 = 0b101,283 fixed: u3 = 0b101,
274 cond: u4,284 cond: u4,
275 },285 },
276 BranchExchange: packed struct {286 branch_exchange: packed struct {
277 rn: u4,287 rn: u4,
278 fixed_1: u1 = 0b1,288 fixed_1: u1 = 0b1,
279 link: u1,289 link: u1,
280 fixed_2: u22 = 0b0001_0010_1111_1111_1111_00,290 fixed_2: u22 = 0b0001_0010_1111_1111_1111_00,
281 cond: u4,291 cond: u4,
282 },292 },
283 SupervisorCall: packed struct {293 supervisor_call: packed struct {
284 comment: u24,294 comment: u24,
285 fixed: u4 = 0b1111,295 fixed: u4 = 0b1111,
286 cond: u4,296 cond: u4,
287 },297 },
288 Breakpoint: packed struct {298 breakpoint: packed struct {
289 imm4: u4,299 imm4: u4,
290 fixed_1: u4 = 0b0111,300 fixed_1: u4 = 0b0111,
291 imm12: u12,301 imm12: u12,
...@@ -293,7 +303,7 @@ pub const Instruction = union(enum) {...@@ -293,7 +303,7 @@ pub const Instruction = union(enum) {
293 },303 },
294304
295 /// Represents the possible operations which can be performed by a305 /// Represents the possible operations which can be performed by a
296 /// DataProcessing instruction306 /// Data Processing instruction
297 const Opcode = enum(u4) {307 const Opcode = enum(u4) {
298 // Rd := Op1 AND Op2308 // Rd := Op1 AND Op2
299 @"and",309 @"and",
...@@ -530,16 +540,17 @@ pub const Instruction = union(enum) {...@@ -530,16 +540,17 @@ pub const Instruction = union(enum) {
530540
531 pub fn toU32(self: Instruction) u32 {541 pub fn toU32(self: Instruction) u32 {
532 return switch (self) {542 return switch (self) {
533 .DataProcessing => |v| @bitCast(u32, v),543 .data_processing => |v| @bitCast(u32, v),
534 .Multiply => |v| @bitCast(u32, v),544 .multiply => |v| @bitCast(u32, v),
535 .MultiplyLong => |v| @bitCast(u32, v),545 .multiply_long => |v| @bitCast(u32, v),
536 .SingleDataTransfer => |v| @bitCast(u32, v),546 .integer_saturating_arithmetic => |v| @bitCast(u32, v),
537 .ExtraLoadStore => |v| @bitCast(u32, v),547 .single_data_transfer => |v| @bitCast(u32, v),
538 .BlockDataTransfer => |v| @bitCast(u32, v),548 .extra_load_store => |v| @bitCast(u32, v),
539 .Branch => |v| @bitCast(u32, v),549 .block_data_transfer => |v| @bitCast(u32, v),
540 .BranchExchange => |v| @bitCast(u32, v),550 .branch => |v| @bitCast(u32, v),
541 .SupervisorCall => |v| @bitCast(u32, v),551 .branch_exchange => |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),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),
543 };554 };
544 }555 }
545556
...@@ -554,7 +565,7 @@ pub const Instruction = union(enum) {...@@ -554,7 +565,7 @@ pub const Instruction = union(enum) {
554 op2: Operand,565 op2: Operand,
555 ) Instruction {566 ) Instruction {
556 return Instruction{567 return Instruction{
557 .DataProcessing = .{568 .data_processing = .{
558 .cond = @enumToInt(cond),569 .cond = @enumToInt(cond),
559 .i = @boolToInt(op2 == .Immediate),570 .i = @boolToInt(op2 == .Immediate),
560 .opcode = @enumToInt(opcode),571 .opcode = @enumToInt(opcode),
...@@ -573,7 +584,7 @@ pub const Instruction = union(enum) {...@@ -573,7 +584,7 @@ pub const Instruction = union(enum) {
573 top: bool,584 top: bool,
574 ) Instruction {585 ) Instruction {
575 return Instruction{586 return Instruction{
576 .DataProcessing = .{587 .data_processing = .{
577 .cond = @enumToInt(cond),588 .cond = @enumToInt(cond),
578 .i = 1,589 .i = 1,
579 .opcode = if (top) 0b1010 else 0b1000,590 .opcode = if (top) 0b1010 else 0b1000,
...@@ -594,7 +605,7 @@ pub const Instruction = union(enum) {...@@ -594,7 +605,7 @@ pub const Instruction = union(enum) {
594 ra: ?Register,605 ra: ?Register,
595 ) Instruction {606 ) Instruction {
596 return Instruction{607 return Instruction{
597 .Multiply = .{608 .multiply = .{
598 .cond = @enumToInt(cond),609 .cond = @enumToInt(cond),
599 .accumulate = @boolToInt(ra != null),610 .accumulate = @boolToInt(ra != null),
600 .set_cond = set_cond,611 .set_cond = set_cond,
...@@ -617,7 +628,7 @@ pub const Instruction = union(enum) {...@@ -617,7 +628,7 @@ pub const Instruction = union(enum) {
617 rn: Register,628 rn: Register,
618 ) Instruction {629 ) Instruction {
619 return Instruction{630 return Instruction{
620 .MultiplyLong = .{631 .multiply_long = .{
621 .cond = @enumToInt(cond),632 .cond = @enumToInt(cond),
622 .unsigned = signed,633 .unsigned = signed,
623 .accumulate = accumulate,634 .accumulate = accumulate,
...@@ -630,6 +641,24 @@ pub const Instruction = union(enum) {...@@ -630,6 +641,24 @@ pub const Instruction = union(enum) {
630 };641 };
631 }642 }
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
633 fn singleDataTransfer(662 fn singleDataTransfer(
634 cond: Condition,663 cond: Condition,
635 rd: Register,664 rd: Register,
...@@ -642,7 +671,7 @@ pub const Instruction = union(enum) {...@@ -642,7 +671,7 @@ pub const Instruction = union(enum) {
642 load_store: u1,671 load_store: u1,
643 ) Instruction {672 ) Instruction {
644 return Instruction{673 return Instruction{
645 .SingleDataTransfer = .{674 .single_data_transfer = .{
646 .cond = @enumToInt(cond),675 .cond = @enumToInt(cond),
647 .rn = rn.id(),676 .rn = rn.id(),
648 .rd = rd.id(),677 .rd = rd.id(),
...@@ -678,7 +707,7 @@ pub const Instruction = union(enum) {...@@ -678,7 +707,7 @@ pub const Instruction = union(enum) {
678 };707 };
679708
680 return Instruction{709 return Instruction{
681 .ExtraLoadStore = .{710 .extra_load_store = .{
682 .imm4l = imm4l,711 .imm4l = imm4l,
683 .op2 = op2,712 .op2 = op2,
684 .imm4h = imm4h,713 .imm4h = imm4h,
...@@ -705,7 +734,7 @@ pub const Instruction = union(enum) {...@@ -705,7 +734,7 @@ pub const Instruction = union(enum) {
705 load_store: u1,734 load_store: u1,
706 ) Instruction {735 ) Instruction {
707 return Instruction{736 return Instruction{
708 .BlockDataTransfer = .{737 .block_data_transfer = .{
709 .register_list = @bitCast(u16, reg_list),738 .register_list = @bitCast(u16, reg_list),
710 .rn = rn.id(),739 .rn = rn.id(),
711 .load_store = load_store,740 .load_store = load_store,
...@@ -720,7 +749,7 @@ pub const Instruction = union(enum) {...@@ -720,7 +749,7 @@ pub const Instruction = union(enum) {
720749
721 fn branch(cond: Condition, offset: i26, link: u1) Instruction {750 fn branch(cond: Condition, offset: i26, link: u1) Instruction {
722 return Instruction{751 return Instruction{
723 .Branch = .{752 .branch = .{
724 .cond = @enumToInt(cond),753 .cond = @enumToInt(cond),
725 .link = link,754 .link = link,
726 .offset = @bitCast(u24, @intCast(i24, offset >> 2)),755 .offset = @bitCast(u24, @intCast(i24, offset >> 2)),
...@@ -730,7 +759,7 @@ pub const Instruction = union(enum) {...@@ -730,7 +759,7 @@ pub const Instruction = union(enum) {
730759
731 fn branchExchange(cond: Condition, rn: Register, link: u1) Instruction {760 fn branchExchange(cond: Condition, rn: Register, link: u1) Instruction {
732 return Instruction{761 return Instruction{
733 .BranchExchange = .{762 .branch_exchange = .{
734 .cond = @enumToInt(cond),763 .cond = @enumToInt(cond),
735 .link = link,764 .link = link,
736 .rn = rn.id(),765 .rn = rn.id(),
...@@ -740,7 +769,7 @@ pub const Instruction = union(enum) {...@@ -740,7 +769,7 @@ pub const Instruction = union(enum) {
740769
741 fn supervisorCall(cond: Condition, comment: u24) Instruction {770 fn supervisorCall(cond: Condition, comment: u24) Instruction {
742 return Instruction{771 return Instruction{
743 .SupervisorCall = .{772 .supervisor_call = .{
744 .cond = @enumToInt(cond),773 .cond = @enumToInt(cond),
745 .comment = comment,774 .comment = comment,
746 },775 },
...@@ -749,7 +778,7 @@ pub const Instruction = union(enum) {...@@ -749,7 +778,7 @@ pub const Instruction = union(enum) {
749778
750 fn breakpoint(imm: u16) Instruction {779 fn breakpoint(imm: u16) Instruction {
751 return Instruction{780 return Instruction{
752 .Breakpoint = .{781 .breakpoint = .{
753 .imm12 = @truncate(u12, imm >> 4),782 .imm12 = @truncate(u12, imm >> 4),
754 .imm4 = @truncate(u4, imm),783 .imm4 = @truncate(u4, imm),
755 },784 },
...@@ -873,6 +902,24 @@ pub const Instruction = union(enum) {...@@ -873,6 +902,24 @@ pub const Instruction = union(enum) {
873 return dataProcessing(cond, .mvn, 1, rd, .r0, op2);902 return dataProcessing(cond, .mvn, 1, rd, .r0, op2);
874 }903 }
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
876 // movw and movt923 // movw and movt
877924
878 pub fn movw(cond: Condition, rd: Register, imm: u16) Instruction {925 pub fn movw(cond: Condition, rd: Register, imm: u16) Instruction {
...@@ -887,7 +934,7 @@ pub const Instruction = union(enum) {...@@ -887,7 +934,7 @@ pub const Instruction = union(enum) {
887934
888 pub fn mrs(cond: Condition, rd: Register, psr: Psr) Instruction {935 pub fn mrs(cond: Condition, rd: Register, psr: Psr) Instruction {
889 return Instruction{936 return Instruction{
890 .DataProcessing = .{937 .data_processing = .{
891 .cond = @enumToInt(cond),938 .cond = @enumToInt(cond),
892 .i = 0,939 .i = 0,
893 .opcode = if (psr == .spsr) 0b1010 else 0b1000,940 .opcode = if (psr == .spsr) 0b1010 else 0b1000,
...@@ -901,7 +948,7 @@ pub const Instruction = union(enum) {...@@ -901,7 +948,7 @@ pub const Instruction = union(enum) {
901948
902 pub fn msr(cond: Condition, psr: Psr, op: Operand) Instruction {949 pub fn msr(cond: Condition, psr: Psr, op: Operand) Instruction {
903 return Instruction{950 return Instruction{
904 .DataProcessing = .{951 .data_processing = .{
905 .cond = @enumToInt(cond),952 .cond = @enumToInt(cond),
906 .i = 0,953 .i = 0,
907 .opcode = if (psr == .spsr) 0b1011 else 0b1001,954 .opcode = if (psr == .spsr) 0b1011 else 0b1001,
...@@ -1294,6 +1341,10 @@ test "serialize instructions" {...@@ -1294,6 +1341,10 @@ test "serialize instructions" {
1294 .inst = Instruction.ldmea(.al, .r4, true, .{ .r2 = true, .r5 = true }),1341 .inst = Instruction.ldmea(.al, .r4, true, .{ .r2 = true, .r5 = true }),
1295 .expected = 0b1110_100_1_0_0_1_1_0100_0000000000100100,1342 .expected = 0b1110_100_1_0_0_1_1_0100_0000000000100100,
1296 },1343 },
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 },
1297 };1348 };
12981349
1299 for (testcases) |case| {1350 for (testcases) |case| {