authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2020-10-15 14:30:53+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2020-10-25 12:51:19+01:00
log0e16328636c29b4d82331744cfa1eaad1b7a8507
tree9e4efb4739962381e356020a75f3f9f99f1a4d25
parent7391087df152e0e721259cb90e31474eb46e4f86

stage2 ARM: add multiply and multiply long instructions


1 files changed, 155 insertions(+), 1 deletions(-)

src/codegen/arm.zig+155-1
......@@ -138,6 +138,29 @@ pub const Instruction = union(enum) {
138138 fixed: u2 = 0b00,
139139 cond: u4,
140140 },
141 Multiply: packed struct {
142 rn: u4,
143 fixed_1: u4 = 0b1001,
144 rm: u4,
145 ra: u4,
146 rd: u4,
147 set_cond: u1,
148 accumulate: u1,
149 fixed_2: u6 = 0b000000,
150 cond: u4,
151 },
152 MultiplyLong: packed struct {
153 rn: u4,
154 fixed_1: u4 = 0b1001,
155 rm: u4,
156 rdlo: u4,
157 rdhi: u4,
158 set_cond: u1,
159 accumulate: u1,
160 unsigned: u1,
161 fixed_2: u5 = 0b00001,
162 cond: u4,
163 },
141164 SingleDataTransfer: packed struct {
142165 offset: u12,
143166 rd: u4,
......@@ -403,6 +426,8 @@ pub const Instruction = union(enum) {
403426 pub fn toU32(self: Instruction) u32 {
404427 return switch (self) {
405428 .DataProcessing => |v| @bitCast(u32, v),
429 .Multiply => |v| @bitCast(u32, v),
430 .MultiplyLong => |v| @bitCast(u32, v),
406431 .SingleDataTransfer => |v| @bitCast(u32, v),
407432 .BlockDataTransfer => |v| @bitCast(u32, v),
408433 .Branch => |v| @bitCast(u32, v),
......@@ -454,6 +479,51 @@ pub const Instruction = union(enum) {
454479 };
455480 }
456481
482 fn multiply(
483 cond: Condition,
484 set_cond: u1,
485 rd: Register,
486 rn: Register,
487 rm: Register,
488 ra: ?Register,
489 ) Instruction {
490 return Instruction{
491 .Multiply = .{
492 .cond = @enumToInt(cond),
493 .accumulate = @boolToInt(ra != null),
494 .set_cond = set_cond,
495 .rd = rd.id(),
496 .rn = rn.id(),
497 .ra = if (ra) |reg| reg.id() else 0b0000,
498 .rm = rm.id(),
499 },
500 };
501 }
502
503 fn multiplyLong(
504 cond: Condition,
505 signed: u1,
506 accumulate: u1,
507 set_cond: u1,
508 rdhi: Register,
509 rdlo: Register,
510 rm: Register,
511 rn: Register,
512 ) Instruction {
513 return Instruction{
514 .MultiplyLong = .{
515 .cond = @enumToInt(cond),
516 .unsigned = signed,
517 .accumulate = accumulate,
518 .set_cond = set_cond,
519 .rdlo = rdlo.id(),
520 .rdhi = rdhi.id(),
521 .rn = rn.id(),
522 .rm = rm.id(),
523 },
524 };
525 }
526
457527 fn singleDataTransfer(
458528 cond: Condition,
459529 rd: Register,
......@@ -673,7 +743,83 @@ pub const Instruction = union(enum) {
673743 // PSR transfer
674744
675745 pub fn mrs(cond: Condition, rd: Register, psr: Psr) Instruction {
676 return dataProcessing(cond, if (psr == .cpsr) .tst else .cmp, 0, rd, .r15, Operand.reg(.r0, Operand.Shift.none));
746 return Instruction{
747 .DataProcessing = .{
748 .cond = @enumToInt(cond),
749 .i = 0,
750 .opcode = if (psr == .spsr) 0b1010 else 0b1000,
751 .s = 0,
752 .rn = 0b1111,
753 .rd = rd.id(),
754 .op2 = 0b0000_0000_0000,
755 },
756 };
757 }
758
759 pub fn msr(cond: Condition, psr: Psr, op: Operand) Instruction {
760 return Instruction{
761 .DataProcessing = .{
762 .cond = @enumToInt(cond),
763 .i = 0,
764 .opcode = if (psr == .spsr) 0b1011 else 0b1001,
765 .s = 0,
766 .rn = 0b1111,
767 .rd = 0b1111,
768 .op2 = op.toU12(),
769 },
770 };
771 }
772
773 // Multiply
774
775 pub fn mul(cond: Condition, rd: Register, rn: Register, rm: Register) Instruction {
776 return multiply(cond, 0, rd, rn, rm, null);
777 }
778
779 pub fn muls(cond: Condition, rd: Register, rn: Register, rm: Register) Instruction {
780 return multiply(cond, 1, rd, rn, rm, null);
781 }
782
783 pub fn mla(cond: Condition, rd: Register, rn: Register, rm: Register, ra: Register) Instruction {
784 return multiply(cond, 0, rd, rn, rm, ra);
785 }
786
787 pub fn mlas(cond: Condition, rd: Register, rn: Register, rm: Register, ra: Register) Instruction {
788 return multiply(cond, 1, rd, rn, rm, ra);
789 }
790
791 // Multiply long
792
793 pub fn umull(cond: Condition, rdlo: Register, rdhi: Register, rn: Register, rm: Register) Instruction {
794 return multiplyLong(cond, 0, 0, 0, rdhi, rdlo, rm, rn);
795 }
796
797 pub fn umulls(cond: Condition, rdlo: Register, rdhi: Register, rn: Register, rm: Register) Instruction {
798 return multiplyLong(cond, 0, 0, 1, rdhi, rdlo, rm, rn);
799 }
800
801 pub fn umlal(cond: Condition, rdlo: Register, rdhi: Register, rn: Register, rm: Register) Instruction {
802 return multiplyLong(cond, 0, 1, 0, rdhi, rdlo, rm, rn);
803 }
804
805 pub fn umlals(cond: Condition, rdlo: Register, rdhi: Register, rn: Register, rm: Register) Instruction {
806 return multiplyLong(cond, 0, 1, 1, rdhi, rdlo, rm, rn);
807 }
808
809 pub fn smull(cond: Condition, rdlo: Register, rdhi: Register, rn: Register, rm: Register) Instruction {
810 return multiplyLong(cond, 1, 0, 0, rdhi, rdlo, rm, rn);
811 }
812
813 pub fn smulls(cond: Condition, rdlo: Register, rdhi: Register, rn: Register, rm: Register) Instruction {
814 return multiplyLong(cond, 1, 0, 1, rdhi, rdlo, rm, rn);
815 }
816
817 pub fn smlal(cond: Condition, rdlo: Register, rdhi: Register, rn: Register, rm: Register) Instruction {
818 return multiplyLong(cond, 1, 1, 0, rdhi, rdlo, rm, rn);
819 }
820
821 pub fn smlals(cond: Condition, rdlo: Register, rdhi: Register, rn: Register, rm: Register) Instruction {
822 return multiplyLong(cond, 1, 1, 1, rdhi, rdlo, rm, rn);
677823 }
678824
679825 // Single data transfer
......@@ -857,6 +1003,14 @@ test "serialize instructions" {
8571003 .inst = Instruction.mrs(.al, .r5, .cpsr),
8581004 .expected = 0b1110_00010_0_001111_0101_000000000000,
8591005 },
1006 .{ // mul r0, r1, r2
1007 .inst = Instruction.mul(.al, .r0, .r1, .r2),
1008 .expected = 0b1110_000000_0_0_0000_0000_0010_1001_0001,
1009 },
1010 .{ // umlal r0, r1, r5, r6
1011 .inst = Instruction.umlal(.al, .r0, .r1, .r5, .r6),
1012 .expected = 0b1110_00001_0_1_0_0001_0000_0110_1001_0101,
1013 },
8601014 .{ // ldr r0, [r2, #42]
8611015 .inst = Instruction.ldr(.al, .r0, .r2, .{
8621016 .offset = Instruction.Offset.imm(42),