| 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 | 950 | switch (operand_ty.zigTypeTag()) { |
| 951 | 951 | .Bool => { |
| 952 | 952 | // TODO convert this to mvn + and |
| 953 | const dest = try self.binOp(.xor, null, operand, .{ .immediate = 1 }, operand_ty, Type.bool); | |
| 954 | break :result dest; | |
| 953 | const op_reg = switch (operand) { | |
| 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 | 1318 | } |
| 1260 | 1319 | }, |
| 1261 | 1320 | // Bitwise operations on integers |
| 1262 | .xor => { | |
| 1321 | .bit_and, | |
| 1322 | .bit_or, | |
| 1323 | .xor, | |
| 1324 | => { | |
| 1263 | 1325 | switch (lhs_ty.zigTypeTag()) { |
| 1264 | 1326 | .Vector => return self.fail("TODO binary operations on vectors", .{}), |
| 1265 | .Int => return self.fail("TODO binary operations on vectors", .{}), | |
| 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 | }, | |
| 1327 | .Int => return self.fail("TODO binary operations on integers", .{}), | |
| 1271 | 1328 | else => unreachable, |
| 1272 | 1329 | } |
| 1273 | 1330 | }, |
| ... | ... | @@ -3136,11 +3193,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3136 | 3193 | 4, 8 => .str_stack, |
| 3137 | 3194 | else => unreachable, // unexpected abi size |
| 3138 | 3195 | }; |
| 3139 | const rt: Register = switch (abi_size) { | |
| 3140 | 1, 2, 4 => reg.to32(), | |
| 3141 | 8 => reg.to64(), | |
| 3142 | else => unreachable, // unexpected abi size | |
| 3143 | }; | |
| 3196 | const rt = registerAlias(reg, abi_size); | |
| 3144 | 3197 | |
| 3145 | 3198 | _ = try self.addInst(.{ |
| 3146 | 3199 | .tag = tag, |
| ... | ... | @@ -3622,7 +3675,6 @@ fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue { |
| 3622 | 3675 | fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { |
| 3623 | 3676 | if (typed_value.val.isUndef()) |
| 3624 | 3677 | return MCValue{ .undef = {} }; |
| 3625 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); | |
| 3626 | 3678 | |
| 3627 | 3679 | if (typed_value.val.castTag(.decl_ref)) |payload| { |
| 3628 | 3680 | return self.lowerDeclRef(typed_value, payload.data); |
| ... | ... | @@ -3652,13 +3704,19 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { |
| 3652 | 3704 | }, |
| 3653 | 3705 | .Int => { |
| 3654 | 3706 | const info = typed_value.ty.intInfo(self.target.*); |
| 3655 | if (info.bits <= ptr_bits and info.signedness == .signed) { | |
| 3656 | return MCValue{ .immediate = @bitCast(u64, typed_value.val.toSignedInt()) }; | |
| 3657 | } | |
| 3658 | if (info.bits > ptr_bits or info.signedness == .signed) { | |
| 3659 | return self.fail("TODO const int bigger than ptr and signed int", .{}); | |
| 3707 | if (info.bits <= 64) { | |
| 3708 | const unsigned = switch (info.signedness) { | |
| 3709 | .signed => blk: { | |
| 3710 | const signed = typed_value.val.toSignedInt(); | |
| 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 | 3721 | .Bool => { |
| 3664 | 3722 | return MCValue{ .immediate = @boolToInt(typed_value.val.toBool()) }; |
| ... | ... | @@ -3875,7 +3933,7 @@ fn parseRegName(name: []const u8) ?Register { |
| 3875 | 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 | 3937 | if (size_bytes == 0) { |
| 3880 | 3938 | unreachable; // should be comptime known |
| 3881 | 3939 | } else if (size_bytes <= 4) { |
src/arch/aarch64/Emit.zig+20-3| ... | ... | @@ -95,6 +95,8 @@ pub fn emitMir( |
| 95 | 95 | |
| 96 | 96 | .call_extern => try emit.mirCallExtern(inst), |
| 97 | 97 | |
| 98 | .eor_immediate => try emit.mirLogicalImmediate(inst), | |
| 99 | ||
| 98 | 100 | .add_shifted_register => try emit.mirAddSubtractShiftedRegister(inst), |
| 99 | 101 | .cmp_shifted_register => try emit.mirAddSubtractShiftedRegister(inst), |
| 100 | 102 | .sub_shifted_register => try emit.mirAddSubtractShiftedRegister(inst), |
| ... | ... | @@ -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 | 625 | fn mirAddSubtractShiftedRegister(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 609 | 626 | const tag = emit.mir.instructions.items(.tag)[inst]; |
| 610 | 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 | 660 | const imm6 = rrr_imm6_logical_shift.imm6; |
| 644 | 661 | |
| 645 | 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 | 664 | else => unreachable, |
| 648 | 665 | } |
| 649 | 666 | } |
| ... | ... | @@ -844,7 +861,7 @@ fn mirMoveRegister(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 844 | 861 | switch (tag) { |
| 845 | 862 | .mov_register => { |
| 846 | 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 | 866 | .mov_to_from_sp => { |
| 850 | 867 | const rr = emit.mir.instructions.items(.data)[inst].rr; |
| ... | ... | @@ -852,7 +869,7 @@ fn mirMoveRegister(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 852 | 869 | }, |
| 853 | 870 | .mvn => { |
| 854 | 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 | 874 | else => unreachable, |
| 858 | 875 | } |
src/arch/aarch64/Mir.zig+15-2| ... | ... | @@ -54,6 +54,8 @@ pub const Inst = struct { |
| 54 | 54 | dbg_epilogue_begin, |
| 55 | 55 | /// Pseudo-instruction: Update debug line |
| 56 | 56 | dbg_line, |
| 57 | /// Bitwise Exclusive OR (immediate) | |
| 58 | eor_immediate, | |
| 57 | 59 | /// Bitwise Exclusive OR (shifted register) |
| 58 | 60 | eor_shifted_register, |
| 59 | 61 | /// Loads the contents into a register |
| ... | ... | @@ -231,14 +233,25 @@ pub const Inst = struct { |
| 231 | 233 | imm12: u12, |
| 232 | 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 | 239 | /// Used by e.g. mvn |
| 237 | 240 | rr_imm6_shift: struct { |
| 238 | 241 | rd: Register, |
| 239 | 242 | rm: Register, |
| 240 | 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 | 256 | /// Two registers |
| 244 | 257 | /// |
src/arch/aarch64/bits.zig+70-12| ... | ... | @@ -323,6 +323,16 @@ pub const Instruction = union(enum) { |
| 323 | 323 | op: u1, |
| 324 | 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 | 336 | add_subtract_shifted_register: packed struct { |
| 327 | 337 | rd: u5, |
| 328 | 338 | rn: u5, |
| ... | ... | @@ -487,6 +497,7 @@ pub const Instruction = union(enum) { |
| 487 | 497 | .no_operation => |v| @bitCast(u32, v), |
| 488 | 498 | .logical_shifted_register => |v| @bitCast(u32, v), |
| 489 | 499 | .add_subtract_immediate => |v| @bitCast(u32, v), |
| 500 | .logical_immediate => |v| @bitCast(u32, v), | |
| 490 | 501 | .add_subtract_shifted_register => |v| @bitCast(u32, v), |
| 491 | 502 | // TODO once packed structs work, this can be refactored |
| 492 | 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 | 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 | 939 | pub const AddSubtractShiftedRegisterShift = enum(u2) { lsl, lsr, asr, _ }; |
| 904 | 940 | |
| 905 | 941 | fn addSubtractShiftedRegister( |
| ... | ... | @@ -1173,7 +1209,7 @@ pub const Instruction = union(enum) { |
| 1173 | 1209 | |
| 1174 | 1210 | // Logical (shifted register) |
| 1175 | 1211 | |
| 1176 | pub fn @"and"( | |
| 1212 | pub fn andShiftedRegister( | |
| 1177 | 1213 | rd: Register, |
| 1178 | 1214 | rn: Register, |
| 1179 | 1215 | rm: Register, |
| ... | ... | @@ -1183,7 +1219,7 @@ pub const Instruction = union(enum) { |
| 1183 | 1219 | return logicalShiftedRegister(0b00, 0b0, rd, rn, rm, shift, amount); |
| 1184 | 1220 | } |
| 1185 | 1221 | |
| 1186 | pub fn bic( | |
| 1222 | pub fn bicShiftedRegister( | |
| 1187 | 1223 | rd: Register, |
| 1188 | 1224 | rn: Register, |
| 1189 | 1225 | rm: Register, |
| ... | ... | @@ -1193,7 +1229,7 @@ pub const Instruction = union(enum) { |
| 1193 | 1229 | return logicalShiftedRegister(0b00, 0b1, rd, rn, rm, shift, amount); |
| 1194 | 1230 | } |
| 1195 | 1231 | |
| 1196 | pub fn orr( | |
| 1232 | pub fn orrShiftedRegister( | |
| 1197 | 1233 | rd: Register, |
| 1198 | 1234 | rn: Register, |
| 1199 | 1235 | rm: Register, |
| ... | ... | @@ -1203,7 +1239,7 @@ pub const Instruction = union(enum) { |
| 1203 | 1239 | return logicalShiftedRegister(0b01, 0b0, rd, rn, rm, shift, amount); |
| 1204 | 1240 | } |
| 1205 | 1241 | |
| 1206 | pub fn orn( | |
| 1242 | pub fn ornShiftedRegister( | |
| 1207 | 1243 | rd: Register, |
| 1208 | 1244 | rn: Register, |
| 1209 | 1245 | rm: Register, |
| ... | ... | @@ -1213,7 +1249,7 @@ pub const Instruction = union(enum) { |
| 1213 | 1249 | return logicalShiftedRegister(0b01, 0b1, rd, rn, rm, shift, amount); |
| 1214 | 1250 | } |
| 1215 | 1251 | |
| 1216 | pub fn eor( | |
| 1252 | pub fn eorShiftedRegister( | |
| 1217 | 1253 | rd: Register, |
| 1218 | 1254 | rn: Register, |
| 1219 | 1255 | rm: Register, |
| ... | ... | @@ -1223,7 +1259,7 @@ pub const Instruction = union(enum) { |
| 1223 | 1259 | return logicalShiftedRegister(0b10, 0b0, rd, rn, rm, shift, amount); |
| 1224 | 1260 | } |
| 1225 | 1261 | |
| 1226 | pub fn eon( | |
| 1262 | pub fn eonShiftedRegister( | |
| 1227 | 1263 | rd: Register, |
| 1228 | 1264 | rn: Register, |
| 1229 | 1265 | rm: Register, |
| ... | ... | @@ -1233,7 +1269,7 @@ pub const Instruction = union(enum) { |
| 1233 | 1269 | return logicalShiftedRegister(0b10, 0b1, rd, rn, rm, shift, amount); |
| 1234 | 1270 | } |
| 1235 | 1271 | |
| 1236 | pub fn ands( | |
| 1272 | pub fn andsShiftedRegister( | |
| 1237 | 1273 | rd: Register, |
| 1238 | 1274 | rn: Register, |
| 1239 | 1275 | rm: Register, |
| ... | ... | @@ -1243,7 +1279,7 @@ pub const Instruction = union(enum) { |
| 1243 | 1279 | return logicalShiftedRegister(0b11, 0b0, rd, rn, rm, shift, amount); |
| 1244 | 1280 | } |
| 1245 | 1281 | |
| 1246 | pub fn bics( | |
| 1282 | pub fn bicsShiftedRegister( | |
| 1247 | 1283 | rd: Register, |
| 1248 | 1284 | rn: Register, |
| 1249 | 1285 | rm: Register, |
| ... | ... | @@ -1271,6 +1307,24 @@ pub const Instruction = union(enum) { |
| 1271 | 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 | 1328 | // Add/subtract (shifted register) |
| 1275 | 1329 | |
| 1276 | 1330 | pub fn addShiftedRegister( |
| ... | ... | @@ -1378,11 +1432,11 @@ test "serialize instructions" { |
| 1378 | 1432 | |
| 1379 | 1433 | const testcases = [_]Testcase{ |
| 1380 | 1434 | .{ // orr x0, xzr, x1 |
| 1381 | .inst = Instruction.orr(.x0, .xzr, .x1, .lsl, 0), | |
| 1435 | .inst = Instruction.orrShiftedRegister(.x0, .xzr, .x1, .lsl, 0), | |
| 1382 | 1436 | .expected = 0b1_01_01010_00_0_00001_000000_11111_00000, |
| 1383 | 1437 | }, |
| 1384 | 1438 | .{ // orn x0, xzr, x1 |
| 1385 | .inst = Instruction.orn(.x0, .xzr, .x1, .lsl, 0), | |
| 1439 | .inst = Instruction.ornShiftedRegister(.x0, .xzr, .x1, .lsl, 0), | |
| 1386 | 1440 | .expected = 0b1_01_01010_00_1_00001_000000_11111_00000, |
| 1387 | 1441 | }, |
| 1388 | 1442 | .{ // movz x1, #4 |
| ... | ... | @@ -1502,11 +1556,11 @@ test "serialize instructions" { |
| 1502 | 1556 | .expected = 0b10_101_0_001_1_0000010_00010_11111_00001, |
| 1503 | 1557 | }, |
| 1504 | 1558 | .{ // and x0, x4, x2 |
| 1505 | .inst = Instruction.@"and"(.x0, .x4, .x2, .lsl, 0), | |
| 1559 | .inst = Instruction.andShiftedRegister(.x0, .x4, .x2, .lsl, 0), | |
| 1506 | 1560 | .expected = 0b1_00_01010_00_0_00010_000000_00100_00000, |
| 1507 | 1561 | }, |
| 1508 | 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 | 1564 | .expected = 0b1_00_01010_00_0_00010_001000_00100_00000, |
| 1511 | 1565 | }, |
| 1512 | 1566 | .{ // add x0, x10, #10 |
| ... | ... | @@ -1537,6 +1591,10 @@ test "serialize instructions" { |
| 1537 | 1591 | .inst = Instruction.mul(.x1, .x4, .x9), |
| 1538 | 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 | 1600 | for (testcases) |case| { |