| author | |
| committer | |
| log | e3121accacaa2b9debaa60e0d4e8188de0b6a2f4 |
| tree | efd10cf4f4f674ed2773bddfcf2c17cad9c4d8fa |
| parent | f2a5d0bf94897554e25e889dc1c6c4c7fc6c1217 |
| signature |
4 files changed, 186 insertions(+), 40 deletions(-)
src/arch/aarch64/CodeGen.zig+81-23| ... | @@ -950,10 +950,69 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -950,10 +950,69 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { |
| 950 | switch (operand_ty.zigTypeTag()) { | 950 | switch (operand_ty.zigTypeTag()) { |
| 951 | .Bool => { | 951 | .Bool => { |
| 952 | // TODO convert this to mvn + and | 952 | // TODO convert this to mvn + and |
| 953 | const dest = try self.binOp(.xor, null, operand, .{ .immediate = 1 }, operand_ty, Type.bool); | 953 | const op_reg = switch (operand) { |
| 954 | break :result dest; | 954 | .register => |r| r, |
| 955 | else => try self.copyToTmpRegister(operand_ty, operand), | ||
| 956 | }; | ||
| 957 | self.register_manager.freezeRegs(&.{op_reg}); | ||
| 958 | defer self.register_manager.unfreezeRegs(&.{op_reg}); | ||
| 959 | |||
| 960 | const dest_reg = blk: { | ||
| 961 | if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) { | ||
| 962 | break :blk op_reg; | ||
| 963 | } | ||
| 964 | |||
| 965 | break :blk try self.register_manager.allocReg(null); | ||
| 966 | }; | ||
| 967 | |||
| 968 | _ = try self.addInst(.{ | ||
| 969 | .tag = .eor_immediate, | ||
| 970 | .data = .{ .rr_bitmask = .{ | ||
| 971 | .rd = dest_reg, | ||
| 972 | .rn = op_reg, | ||
| 973 | .imms = 0b000000, | ||
| 974 | .immr = 0b000000, | ||
| 975 | .n = 0b1, | ||
| 976 | } }, | ||
| 977 | }); | ||
| 978 | |||
| 979 | break :result MCValue{ .register = dest_reg }; | ||
| 980 | }, | ||
| 981 | .Vector => return self.fail("TODO bitwise not for vectors", .{}), | ||
| 982 | .Int => { | ||
| 983 | const int_info = operand_ty.intInfo(self.target.*); | ||
| 984 | if (int_info.bits <= 64) { | ||
| 985 | const op_reg = switch (operand) { | ||
| 986 | .register => |r| r, | ||
| 987 | else => try self.copyToTmpRegister(operand_ty, operand), | ||
| 988 | }; | ||
| 989 | self.register_manager.freezeRegs(&.{op_reg}); | ||
| 990 | defer self.register_manager.unfreezeRegs(&.{op_reg}); | ||
| 991 | |||
| 992 | const dest_reg = blk: { | ||
| 993 | if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) { | ||
| 994 | break :blk op_reg; | ||
| 995 | } | ||
| 996 | |||
| 997 | break :blk try self.register_manager.allocReg(null); | ||
| 998 | }; | ||
| 999 | |||
| 1000 | _ = try self.addInst(.{ | ||
| 1001 | .tag = .mvn, | ||
| 1002 | .data = .{ .rr_imm6_shift = .{ | ||
| 1003 | .rd = dest_reg, | ||
| 1004 | .rm = op_reg, | ||
| 1005 | .imm6 = 0, | ||
| 1006 | .shift = .lsl, | ||
| 1007 | } }, | ||
| 1008 | }); | ||
| 1009 | |||
| 1010 | break :result MCValue{ .register = dest_reg }; | ||
| 1011 | } else { | ||
| 1012 | return self.fail("TODO AArch64 not on integers > u64/i64", .{}); | ||
| 1013 | } | ||
| 955 | }, | 1014 | }, |
| 956 | else => return self.fail("TODO bitwise not", .{}), | 1015 | else => unreachable, |
| 957 | } | 1016 | } |
| 958 | }, | 1017 | }, |
| 959 | } | 1018 | } |
| ... | @@ -1259,15 +1318,13 @@ fn binOp( | ... | @@ -1259,15 +1318,13 @@ fn binOp( |
| 1259 | } | 1318 | } |
| 1260 | }, | 1319 | }, |
| 1261 | // Bitwise operations on integers | 1320 | // Bitwise operations on integers |
| 1262 | .xor => { | 1321 | .bit_and, |
| 1322 | .bit_or, | ||
| 1323 | .xor, | ||
| 1324 | => { | ||
| 1263 | switch (lhs_ty.zigTypeTag()) { | 1325 | switch (lhs_ty.zigTypeTag()) { |
| 1264 | .Vector => return self.fail("TODO binary operations on vectors", .{}), | 1326 | .Vector => return self.fail("TODO binary operations on vectors", .{}), |
| 1265 | .Int => return self.fail("TODO binary operations on vectors", .{}), | 1327 | .Int => return self.fail("TODO binary operations on integers", .{}), |
| 1266 | .Bool => { | ||
| 1267 | assert(lhs_ty.eql(rhs_ty)); | ||
| 1268 | // TODO boolean operations with immediates | ||
| 1269 | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); | ||
| 1270 | }, | ||
| 1271 | else => unreachable, | 1328 | else => unreachable, |
| 1272 | } | 1329 | } |
| 1273 | }, | 1330 | }, |
| ... | @@ -3136,11 +3193,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -3136,11 +3193,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3136 | 4, 8 => .str_stack, | 3193 | 4, 8 => .str_stack, |
| 3137 | else => unreachable, // unexpected abi size | 3194 | else => unreachable, // unexpected abi size |
| 3138 | }; | 3195 | }; |
| 3139 | const rt: Register = switch (abi_size) { | 3196 | const rt = registerAlias(reg, abi_size); |
| 3140 | 1, 2, 4 => reg.to32(), | ||
| 3141 | 8 => reg.to64(), | ||
| 3142 | else => unreachable, // unexpected abi size | ||
| 3143 | }; | ||
| 3144 | 3197 | ||
| 3145 | _ = try self.addInst(.{ | 3198 | _ = try self.addInst(.{ |
| 3146 | .tag = tag, | 3199 | .tag = tag, |
| ... | @@ -3622,7 +3675,6 @@ fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue { | ... | @@ -3622,7 +3675,6 @@ fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue { |
| 3622 | fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { | 3675 | fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { |
| 3623 | if (typed_value.val.isUndef()) | 3676 | if (typed_value.val.isUndef()) |
| 3624 | return MCValue{ .undef = {} }; | 3677 | return MCValue{ .undef = {} }; |
| 3625 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); | ||
| 3626 | 3678 | ||
| 3627 | if (typed_value.val.castTag(.decl_ref)) |payload| { | 3679 | if (typed_value.val.castTag(.decl_ref)) |payload| { |
| 3628 | return self.lowerDeclRef(typed_value, payload.data); | 3680 | return self.lowerDeclRef(typed_value, payload.data); |
| ... | @@ -3652,13 +3704,19 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { | ... | @@ -3652,13 +3704,19 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { |
| 3652 | }, | 3704 | }, |
| 3653 | .Int => { | 3705 | .Int => { |
| 3654 | const info = typed_value.ty.intInfo(self.target.*); | 3706 | const info = typed_value.ty.intInfo(self.target.*); |
| 3655 | if (info.bits <= ptr_bits and info.signedness == .signed) { | 3707 | if (info.bits <= 64) { |
| 3656 | return MCValue{ .immediate = @bitCast(u64, typed_value.val.toSignedInt()) }; | 3708 | const unsigned = switch (info.signedness) { |
| 3657 | } | 3709 | .signed => blk: { |
| 3658 | if (info.bits > ptr_bits or info.signedness == .signed) { | 3710 | const signed = typed_value.val.toSignedInt(); |
| 3659 | return self.fail("TODO const int bigger than ptr and signed int", .{}); | 3711 | break :blk @bitCast(u64, signed); |
| 3712 | }, | ||
| 3713 | .unsigned => typed_value.val.toUnsignedInt(), | ||
| 3714 | }; | ||
| 3715 | |||
| 3716 | return MCValue{ .immediate = unsigned }; | ||
| 3717 | } else { | ||
| 3718 | return self.lowerUnnamedConst(typed_value); | ||
| 3660 | } | 3719 | } |
| 3661 | return MCValue{ .immediate = typed_value.val.toUnsignedInt() }; | ||
| 3662 | }, | 3720 | }, |
| 3663 | .Bool => { | 3721 | .Bool => { |
| 3664 | return MCValue{ .immediate = @boolToInt(typed_value.val.toBool()) }; | 3722 | return MCValue{ .immediate = @boolToInt(typed_value.val.toBool()) }; |
| ... | @@ -3875,7 +3933,7 @@ fn parseRegName(name: []const u8) ?Register { | ... | @@ -3875,7 +3933,7 @@ fn parseRegName(name: []const u8) ?Register { |
| 3875 | return std.meta.stringToEnum(Register, name); | 3933 | return std.meta.stringToEnum(Register, name); |
| 3876 | } | 3934 | } |
| 3877 | 3935 | ||
| 3878 | fn registerAlias(reg: Register, size_bytes: u32) Register { | 3936 | fn registerAlias(reg: Register, size_bytes: u64) Register { |
| 3879 | if (size_bytes == 0) { | 3937 | if (size_bytes == 0) { |
| 3880 | unreachable; // should be comptime known | 3938 | unreachable; // should be comptime known |
| 3881 | } else if (size_bytes <= 4) { | 3939 | } else if (size_bytes <= 4) { |
src/arch/aarch64/Emit.zig+20-3| ... | @@ -95,6 +95,8 @@ pub fn emitMir( | ... | @@ -95,6 +95,8 @@ pub fn emitMir( |
| 95 | 95 | ||
| 96 | .call_extern => try emit.mirCallExtern(inst), | 96 | .call_extern => try emit.mirCallExtern(inst), |
| 97 | 97 | ||
| 98 | .eor_immediate => try emit.mirLogicalImmediate(inst), | ||
| 99 | |||
| 98 | .add_shifted_register => try emit.mirAddSubtractShiftedRegister(inst), | 100 | .add_shifted_register => try emit.mirAddSubtractShiftedRegister(inst), |
| 99 | .cmp_shifted_register => try emit.mirAddSubtractShiftedRegister(inst), | 101 | .cmp_shifted_register => try emit.mirAddSubtractShiftedRegister(inst), |
| 100 | .sub_shifted_register => try emit.mirAddSubtractShiftedRegister(inst), | 102 | .sub_shifted_register => try emit.mirAddSubtractShiftedRegister(inst), |
| ... | @@ -605,6 +607,21 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) !void { | ... | @@ -605,6 +607,21 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 605 | } | 607 | } |
| 606 | } | 608 | } |
| 607 | 609 | ||
| 610 | fn mirLogicalImmediate(emit: *Emit, inst: Mir.Inst.Index) !void { | ||
| 611 | const tag = emit.mir.instructions.items(.tag)[inst]; | ||
| 612 | const rr_bitmask = emit.mir.instructions.items(.data)[inst].rr_bitmask; | ||
| 613 | const rd = rr_bitmask.rd; | ||
| 614 | const rn = rr_bitmask.rn; | ||
| 615 | const imms = rr_bitmask.imms; | ||
| 616 | const immr = rr_bitmask.immr; | ||
| 617 | const n = rr_bitmask.n; | ||
| 618 | |||
| 619 | switch (tag) { | ||
| 620 | .eor_immediate => try emit.writeInstruction(Instruction.eorImmediate(rd, rn, imms, immr, n)), | ||
| 621 | else => unreachable, | ||
| 622 | } | ||
| 623 | } | ||
| 624 | |||
| 608 | fn mirAddSubtractShiftedRegister(emit: *Emit, inst: Mir.Inst.Index) !void { | 625 | fn mirAddSubtractShiftedRegister(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 609 | const tag = emit.mir.instructions.items(.tag)[inst]; | 626 | const tag = emit.mir.instructions.items(.tag)[inst]; |
| 610 | const rrr_imm6_shift = emit.mir.instructions.items(.data)[inst].rrr_imm6_shift; | 627 | const rrr_imm6_shift = emit.mir.instructions.items(.data)[inst].rrr_imm6_shift; |
| ... | @@ -643,7 +660,7 @@ fn mirLogicalShiftedRegister(emit: *Emit, inst: Mir.Inst.Index) !void { | ... | @@ -643,7 +660,7 @@ fn mirLogicalShiftedRegister(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 643 | const imm6 = rrr_imm6_logical_shift.imm6; | 660 | const imm6 = rrr_imm6_logical_shift.imm6; |
| 644 | 661 | ||
| 645 | switch (tag) { | 662 | switch (tag) { |
| 646 | .eor_shifted_register => try emit.writeInstruction(Instruction.eor(rd, rn, rm, shift, imm6)), | 663 | .eor_shifted_register => try emit.writeInstruction(Instruction.eorShiftedRegister(rd, rn, rm, shift, imm6)), |
| 647 | else => unreachable, | 664 | else => unreachable, |
| 648 | } | 665 | } |
| 649 | } | 666 | } |
| ... | @@ -844,7 +861,7 @@ fn mirMoveRegister(emit: *Emit, inst: Mir.Inst.Index) !void { | ... | @@ -844,7 +861,7 @@ fn mirMoveRegister(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 844 | switch (tag) { | 861 | switch (tag) { |
| 845 | .mov_register => { | 862 | .mov_register => { |
| 846 | const rr = emit.mir.instructions.items(.data)[inst].rr; | 863 | const rr = emit.mir.instructions.items(.data)[inst].rr; |
| 847 | try emit.writeInstruction(Instruction.orr(rr.rd, .xzr, rr.rn, .lsl, 0)); | 864 | try emit.writeInstruction(Instruction.orrShiftedRegister(rr.rd, .xzr, rr.rn, .lsl, 0)); |
| 848 | }, | 865 | }, |
| 849 | .mov_to_from_sp => { | 866 | .mov_to_from_sp => { |
| 850 | const rr = emit.mir.instructions.items(.data)[inst].rr; | 867 | const rr = emit.mir.instructions.items(.data)[inst].rr; |
| ... | @@ -852,7 +869,7 @@ fn mirMoveRegister(emit: *Emit, inst: Mir.Inst.Index) !void { | ... | @@ -852,7 +869,7 @@ fn mirMoveRegister(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 852 | }, | 869 | }, |
| 853 | .mvn => { | 870 | .mvn => { |
| 854 | const rr_imm6_shift = emit.mir.instructions.items(.data)[inst].rr_imm6_shift; | 871 | const rr_imm6_shift = emit.mir.instructions.items(.data)[inst].rr_imm6_shift; |
| 855 | try emit.writeInstruction(Instruction.orn(rr_imm6_shift.rd, .xzr, rr_imm6_shift.rm, .lsl, 0)); | 872 | try emit.writeInstruction(Instruction.ornShiftedRegister(rr_imm6_shift.rd, .xzr, rr_imm6_shift.rm, rr_imm6_shift.shift, rr_imm6_shift.imm6)); |
| 856 | }, | 873 | }, |
| 857 | else => unreachable, | 874 | else => unreachable, |
| 858 | } | 875 | } |
src/arch/aarch64/Mir.zig+15-2| ... | @@ -54,6 +54,8 @@ pub const Inst = struct { | ... | @@ -54,6 +54,8 @@ pub const Inst = struct { |
| 54 | dbg_epilogue_begin, | 54 | dbg_epilogue_begin, |
| 55 | /// Pseudo-instruction: Update debug line | 55 | /// Pseudo-instruction: Update debug line |
| 56 | dbg_line, | 56 | dbg_line, |
| 57 | /// Bitwise Exclusive OR (immediate) | ||
| 58 | eor_immediate, | ||
| 57 | /// Bitwise Exclusive OR (shifted register) | 59 | /// Bitwise Exclusive OR (shifted register) |
| 58 | eor_shifted_register, | 60 | eor_shifted_register, |
| 59 | /// Loads the contents into a register | 61 | /// Loads the contents into a register |
| ... | @@ -231,14 +233,25 @@ pub const Inst = struct { | ... | @@ -231,14 +233,25 @@ pub const Inst = struct { |
| 231 | imm12: u12, | 233 | imm12: u12, |
| 232 | sh: u1 = 0, | 234 | sh: u1 = 0, |
| 233 | }, | 235 | }, |
| 234 | /// Two registers and a shift (shift type and 6-bit amount) | 236 | /// Two registers and a shift (logical instruction version) |
| 237 | /// (shift type and 6-bit amount) | ||
| 235 | /// | 238 | /// |
| 236 | /// Used by e.g. mvn | 239 | /// Used by e.g. mvn |
| 237 | rr_imm6_shift: struct { | 240 | rr_imm6_shift: struct { |
| 238 | rd: Register, | 241 | rd: Register, |
| 239 | rm: Register, | 242 | rm: Register, |
| 240 | imm6: u6, | 243 | imm6: u6, |
| 241 | shift: bits.Instruction.AddSubtractShiftedRegisterShift, | 244 | shift: bits.Instruction.LogicalShiftedRegisterShift, |
| 245 | }, | ||
| 246 | /// Two registers and a bitmask immediate | ||
| 247 | /// | ||
| 248 | /// Used by e.g. eor_immediate | ||
| 249 | rr_bitmask: struct { | ||
| 250 | rd: Register, | ||
| 251 | rn: Register, | ||
| 252 | imms: u6, | ||
| 253 | immr: u6, | ||
| 254 | n: u1, | ||
| 242 | }, | 255 | }, |
| 243 | /// Two registers | 256 | /// Two registers |
| 244 | /// | 257 | /// |
src/arch/aarch64/bits.zig+70-12| ... | @@ -323,6 +323,16 @@ pub const Instruction = union(enum) { | ... | @@ -323,6 +323,16 @@ pub const Instruction = union(enum) { |
| 323 | op: u1, | 323 | op: u1, |
| 324 | sf: u1, | 324 | sf: u1, |
| 325 | }, | 325 | }, |
| 326 | logical_immediate: packed struct { | ||
| 327 | rd: u5, | ||
| 328 | rn: u5, | ||
| 329 | imms: u6, | ||
| 330 | immr: u6, | ||
| 331 | n: u1, | ||
| 332 | fixed: u6 = 0b100100, | ||
| 333 | opc: u2, | ||
| 334 | sf: u1, | ||
| 335 | }, | ||
| 326 | add_subtract_shifted_register: packed struct { | 336 | add_subtract_shifted_register: packed struct { |
| 327 | rd: u5, | 337 | rd: u5, |
| 328 | rn: u5, | 338 | rn: u5, |
| ... | @@ -487,6 +497,7 @@ pub const Instruction = union(enum) { | ... | @@ -487,6 +497,7 @@ pub const Instruction = union(enum) { |
| 487 | .no_operation => |v| @bitCast(u32, v), | 497 | .no_operation => |v| @bitCast(u32, v), |
| 488 | .logical_shifted_register => |v| @bitCast(u32, v), | 498 | .logical_shifted_register => |v| @bitCast(u32, v), |
| 489 | .add_subtract_immediate => |v| @bitCast(u32, v), | 499 | .add_subtract_immediate => |v| @bitCast(u32, v), |
| 500 | .logical_immediate => |v| @bitCast(u32, v), | ||
| 490 | .add_subtract_shifted_register => |v| @bitCast(u32, v), | 501 | .add_subtract_shifted_register => |v| @bitCast(u32, v), |
| 491 | // TODO once packed structs work, this can be refactored | 502 | // TODO once packed structs work, this can be refactored |
| 492 | .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), | 503 | .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), |
| ... | @@ -900,6 +911,31 @@ pub const Instruction = union(enum) { | ... | @@ -900,6 +911,31 @@ pub const Instruction = union(enum) { |
| 900 | }; | 911 | }; |
| 901 | } | 912 | } |
| 902 | 913 | ||
| 914 | fn logicalImmediate( | ||
| 915 | opc: u2, | ||
| 916 | rd: Register, | ||
| 917 | rn: Register, | ||
| 918 | imms: u6, | ||
| 919 | immr: u6, | ||
| 920 | n: u1, | ||
| 921 | ) Instruction { | ||
| 922 | return Instruction{ | ||
| 923 | .logical_immediate = .{ | ||
| 924 | .rd = rd.enc(), | ||
| 925 | .rn = rn.enc(), | ||
| 926 | .imms = imms, | ||
| 927 | .immr = immr, | ||
| 928 | .n = n, | ||
| 929 | .opc = opc, | ||
| 930 | .sf = switch (rd.size()) { | ||
| 931 | 32 => 0b0, | ||
| 932 | 64 => 0b1, | ||
| 933 | else => unreachable, // unexpected register size | ||
| 934 | }, | ||
| 935 | }, | ||
| 936 | }; | ||
| 937 | } | ||
| 938 | |||
| 903 | pub const AddSubtractShiftedRegisterShift = enum(u2) { lsl, lsr, asr, _ }; | 939 | pub const AddSubtractShiftedRegisterShift = enum(u2) { lsl, lsr, asr, _ }; |
| 904 | 940 | ||
| 905 | fn addSubtractShiftedRegister( | 941 | fn addSubtractShiftedRegister( |
| ... | @@ -1173,7 +1209,7 @@ pub const Instruction = union(enum) { | ... | @@ -1173,7 +1209,7 @@ pub const Instruction = union(enum) { |
| 1173 | 1209 | ||
| 1174 | // Logical (shifted register) | 1210 | // Logical (shifted register) |
| 1175 | 1211 | ||
| 1176 | pub fn @"and"( | 1212 | pub fn andShiftedRegister( |
| 1177 | rd: Register, | 1213 | rd: Register, |
| 1178 | rn: Register, | 1214 | rn: Register, |
| 1179 | rm: Register, | 1215 | rm: Register, |
| ... | @@ -1183,7 +1219,7 @@ pub const Instruction = union(enum) { | ... | @@ -1183,7 +1219,7 @@ pub const Instruction = union(enum) { |
| 1183 | return logicalShiftedRegister(0b00, 0b0, rd, rn, rm, shift, amount); | 1219 | return logicalShiftedRegister(0b00, 0b0, rd, rn, rm, shift, amount); |
| 1184 | } | 1220 | } |
| 1185 | 1221 | ||
| 1186 | pub fn bic( | 1222 | pub fn bicShiftedRegister( |
| 1187 | rd: Register, | 1223 | rd: Register, |
| 1188 | rn: Register, | 1224 | rn: Register, |
| 1189 | rm: Register, | 1225 | rm: Register, |
| ... | @@ -1193,7 +1229,7 @@ pub const Instruction = union(enum) { | ... | @@ -1193,7 +1229,7 @@ pub const Instruction = union(enum) { |
| 1193 | return logicalShiftedRegister(0b00, 0b1, rd, rn, rm, shift, amount); | 1229 | return logicalShiftedRegister(0b00, 0b1, rd, rn, rm, shift, amount); |
| 1194 | } | 1230 | } |
| 1195 | 1231 | ||
| 1196 | pub fn orr( | 1232 | pub fn orrShiftedRegister( |
| 1197 | rd: Register, | 1233 | rd: Register, |
| 1198 | rn: Register, | 1234 | rn: Register, |
| 1199 | rm: Register, | 1235 | rm: Register, |
| ... | @@ -1203,7 +1239,7 @@ pub const Instruction = union(enum) { | ... | @@ -1203,7 +1239,7 @@ pub const Instruction = union(enum) { |
| 1203 | return logicalShiftedRegister(0b01, 0b0, rd, rn, rm, shift, amount); | 1239 | return logicalShiftedRegister(0b01, 0b0, rd, rn, rm, shift, amount); |
| 1204 | } | 1240 | } |
| 1205 | 1241 | ||
| 1206 | pub fn orn( | 1242 | pub fn ornShiftedRegister( |
| 1207 | rd: Register, | 1243 | rd: Register, |
| 1208 | rn: Register, | 1244 | rn: Register, |
| 1209 | rm: Register, | 1245 | rm: Register, |
| ... | @@ -1213,7 +1249,7 @@ pub const Instruction = union(enum) { | ... | @@ -1213,7 +1249,7 @@ pub const Instruction = union(enum) { |
| 1213 | return logicalShiftedRegister(0b01, 0b1, rd, rn, rm, shift, amount); | 1249 | return logicalShiftedRegister(0b01, 0b1, rd, rn, rm, shift, amount); |
| 1214 | } | 1250 | } |
| 1215 | 1251 | ||
| 1216 | pub fn eor( | 1252 | pub fn eorShiftedRegister( |
| 1217 | rd: Register, | 1253 | rd: Register, |
| 1218 | rn: Register, | 1254 | rn: Register, |
| 1219 | rm: Register, | 1255 | rm: Register, |
| ... | @@ -1223,7 +1259,7 @@ pub const Instruction = union(enum) { | ... | @@ -1223,7 +1259,7 @@ pub const Instruction = union(enum) { |
| 1223 | return logicalShiftedRegister(0b10, 0b0, rd, rn, rm, shift, amount); | 1259 | return logicalShiftedRegister(0b10, 0b0, rd, rn, rm, shift, amount); |
| 1224 | } | 1260 | } |
| 1225 | 1261 | ||
| 1226 | pub fn eon( | 1262 | pub fn eonShiftedRegister( |
| 1227 | rd: Register, | 1263 | rd: Register, |
| 1228 | rn: Register, | 1264 | rn: Register, |
| 1229 | rm: Register, | 1265 | rm: Register, |
| ... | @@ -1233,7 +1269,7 @@ pub const Instruction = union(enum) { | ... | @@ -1233,7 +1269,7 @@ pub const Instruction = union(enum) { |
| 1233 | return logicalShiftedRegister(0b10, 0b1, rd, rn, rm, shift, amount); | 1269 | return logicalShiftedRegister(0b10, 0b1, rd, rn, rm, shift, amount); |
| 1234 | } | 1270 | } |
| 1235 | 1271 | ||
| 1236 | pub fn ands( | 1272 | pub fn andsShiftedRegister( |
| 1237 | rd: Register, | 1273 | rd: Register, |
| 1238 | rn: Register, | 1274 | rn: Register, |
| 1239 | rm: Register, | 1275 | rm: Register, |
| ... | @@ -1243,7 +1279,7 @@ pub const Instruction = union(enum) { | ... | @@ -1243,7 +1279,7 @@ pub const Instruction = union(enum) { |
| 1243 | return logicalShiftedRegister(0b11, 0b0, rd, rn, rm, shift, amount); | 1279 | return logicalShiftedRegister(0b11, 0b0, rd, rn, rm, shift, amount); |
| 1244 | } | 1280 | } |
| 1245 | 1281 | ||
| 1246 | pub fn bics( | 1282 | pub fn bicsShiftedRegister( |
| 1247 | rd: Register, | 1283 | rd: Register, |
| 1248 | rn: Register, | 1284 | rn: Register, |
| 1249 | rm: Register, | 1285 | rm: Register, |
| ... | @@ -1271,6 +1307,24 @@ pub const Instruction = union(enum) { | ... | @@ -1271,6 +1307,24 @@ pub const Instruction = union(enum) { |
| 1271 | return addSubtractImmediate(0b1, 0b1, rd, rn, imm, shift); | 1307 | return addSubtractImmediate(0b1, 0b1, rd, rn, imm, shift); |
| 1272 | } | 1308 | } |
| 1273 | 1309 | ||
| 1310 | // Logical (immediate) | ||
| 1311 | |||
| 1312 | pub fn andImmediate(rd: Register, rn: Register, imms: u6, immr: u6, n: u1) Instruction { | ||
| 1313 | return logicalImmediate(0b00, rd, rn, imms, immr, n); | ||
| 1314 | } | ||
| 1315 | |||
| 1316 | pub fn orrImmediate(rd: Register, rn: Register, imms: u6, immr: u6, n: u1) Instruction { | ||
| 1317 | return logicalImmediate(0b01, rd, rn, imms, immr, n); | ||
| 1318 | } | ||
| 1319 | |||
| 1320 | pub fn eorImmediate(rd: Register, rn: Register, imms: u6, immr: u6, n: u1) Instruction { | ||
| 1321 | return logicalImmediate(0b10, rd, rn, imms, immr, n); | ||
| 1322 | } | ||
| 1323 | |||
| 1324 | pub fn andsImmediate(rd: Register, rn: Register, imms: u6, immr: u6, n: u1) Instruction { | ||
| 1325 | return logicalImmediate(0b11, rd, rn, imms, immr, n); | ||
| 1326 | } | ||
| 1327 | |||
| 1274 | // Add/subtract (shifted register) | 1328 | // Add/subtract (shifted register) |
| 1275 | 1329 | ||
| 1276 | pub fn addShiftedRegister( | 1330 | pub fn addShiftedRegister( |
| ... | @@ -1378,11 +1432,11 @@ test "serialize instructions" { | ... | @@ -1378,11 +1432,11 @@ test "serialize instructions" { |
| 1378 | 1432 | ||
| 1379 | const testcases = [_]Testcase{ | 1433 | const testcases = [_]Testcase{ |
| 1380 | .{ // orr x0, xzr, x1 | 1434 | .{ // orr x0, xzr, x1 |
| 1381 | .inst = Instruction.orr(.x0, .xzr, .x1, .lsl, 0), | 1435 | .inst = Instruction.orrShiftedRegister(.x0, .xzr, .x1, .lsl, 0), |
| 1382 | .expected = 0b1_01_01010_00_0_00001_000000_11111_00000, | 1436 | .expected = 0b1_01_01010_00_0_00001_000000_11111_00000, |
| 1383 | }, | 1437 | }, |
| 1384 | .{ // orn x0, xzr, x1 | 1438 | .{ // orn x0, xzr, x1 |
| 1385 | .inst = Instruction.orn(.x0, .xzr, .x1, .lsl, 0), | 1439 | .inst = Instruction.ornShiftedRegister(.x0, .xzr, .x1, .lsl, 0), |
| 1386 | .expected = 0b1_01_01010_00_1_00001_000000_11111_00000, | 1440 | .expected = 0b1_01_01010_00_1_00001_000000_11111_00000, |
| 1387 | }, | 1441 | }, |
| 1388 | .{ // movz x1, #4 | 1442 | .{ // movz x1, #4 |
| ... | @@ -1502,11 +1556,11 @@ test "serialize instructions" { | ... | @@ -1502,11 +1556,11 @@ test "serialize instructions" { |
| 1502 | .expected = 0b10_101_0_001_1_0000010_00010_11111_00001, | 1556 | .expected = 0b10_101_0_001_1_0000010_00010_11111_00001, |
| 1503 | }, | 1557 | }, |
| 1504 | .{ // and x0, x4, x2 | 1558 | .{ // and x0, x4, x2 |
| 1505 | .inst = Instruction.@"and"(.x0, .x4, .x2, .lsl, 0), | 1559 | .inst = Instruction.andShiftedRegister(.x0, .x4, .x2, .lsl, 0), |
| 1506 | .expected = 0b1_00_01010_00_0_00010_000000_00100_00000, | 1560 | .expected = 0b1_00_01010_00_0_00010_000000_00100_00000, |
| 1507 | }, | 1561 | }, |
| 1508 | .{ // and x0, x4, x2, lsl #0x8 | 1562 | .{ // and x0, x4, x2, lsl #0x8 |
| 1509 | .inst = Instruction.@"and"(.x0, .x4, .x2, .lsl, 0x8), | 1563 | .inst = Instruction.andShiftedRegister(.x0, .x4, .x2, .lsl, 0x8), |
| 1510 | .expected = 0b1_00_01010_00_0_00010_001000_00100_00000, | 1564 | .expected = 0b1_00_01010_00_0_00010_001000_00100_00000, |
| 1511 | }, | 1565 | }, |
| 1512 | .{ // add x0, x10, #10 | 1566 | .{ // add x0, x10, #10 |
| ... | @@ -1537,6 +1591,10 @@ test "serialize instructions" { | ... | @@ -1537,6 +1591,10 @@ test "serialize instructions" { |
| 1537 | .inst = Instruction.mul(.x1, .x4, .x9), | 1591 | .inst = Instruction.mul(.x1, .x4, .x9), |
| 1538 | .expected = 0b1_00_11011_000_01001_0_11111_00100_00001, | 1592 | .expected = 0b1_00_11011_000_01001_0_11111_00100_00001, |
| 1539 | }, | 1593 | }, |
| 1594 | .{ // eor x3, x5, #1 | ||
| 1595 | .inst = Instruction.eorImmediate(.x3, .x5, 0b000000, 0b000000, 0b1), | ||
| 1596 | .expected = 0b1_10_100100_1_000000_000000_00101_00011, | ||
| 1597 | }, | ||
| 1540 | }; | 1598 | }; |
| 1541 | 1599 | ||
| 1542 | for (testcases) |case| { | 1600 | for (testcases) |case| { |