| ... | ... | @@ -1040,6 +1040,7 @@ fn binOpRegister( |
| 1040 | 1040 | const mir_tag: Mir.Inst.Tag = switch (tag) { |
| 1041 | 1041 | .add, .ptr_add => .add_shifted_register, |
| 1042 | 1042 | .sub, .ptr_sub => .sub_shifted_register, |
| 1043 | .mul => .mul, |
| 1043 | 1044 | .xor => .eor_shifted_register, |
| 1044 | 1045 | else => unreachable, |
| 1045 | 1046 | }; |
| ... | ... | @@ -1055,6 +1056,11 @@ fn binOpRegister( |
| 1055 | 1056 | .imm6 = 0, |
| 1056 | 1057 | .shift = .lsl, |
| 1057 | 1058 | } }, |
| 1059 | .mul => .{ .rrr = .{ |
| 1060 | .rd = dest_reg, |
| 1061 | .rn = lhs_reg, |
| 1062 | .rm = rhs_reg, |
| 1063 | } }, |
| 1058 | 1064 | .xor => .{ .rrr_imm6_logical_shift = .{ |
| 1059 | 1065 | .rd = dest_reg, |
| 1060 | 1066 | .rn = lhs_reg, |
| ... | ... | @@ -1221,6 +1227,24 @@ fn binOp( |
| 1221 | 1227 | else => unreachable, |
| 1222 | 1228 | } |
| 1223 | 1229 | }, |
| 1230 | .mul => { |
| 1231 | switch (lhs_ty.zigTypeTag()) { |
| 1232 | .Vector => return self.fail("TODO binary operations on vectors", .{}), |
| 1233 | .Int => { |
| 1234 | assert(lhs_ty.eql(rhs_ty)); |
| 1235 | const int_info = lhs_ty.intInfo(self.target.*); |
| 1236 | if (int_info.bits <= 64) { |
| 1237 | // TODO add optimisations for multiplication |
| 1238 | // with immediates, for example a * 2 can be |
| 1239 | // lowered to a << 1 |
| 1240 | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 1241 | } else { |
| 1242 | return self.fail("TODO ARM binary operations on integers > u32/i32", .{}); |
| 1243 | } |
| 1244 | }, |
| 1245 | else => unreachable, |
| 1246 | } |
| 1247 | }, |
| 1224 | 1248 | // Bitwise operations on integers |
| 1225 | 1249 | .xor => { |
| 1226 | 1250 | switch (lhs_ty.zigTypeTag()) { |
| ... | ... | @@ -1544,88 +1568,37 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1544 | 1568 | }; |
| 1545 | 1569 | self.register_manager.freezeRegs(&.{base_mcv.register}); |
| 1546 | 1570 | |
| 1547 | | // TODO implement optimized ldr for airSliceElemVal |
| 1548 | | const dst_mcv = try self.allocRegOrMem(inst, true); |
| 1571 | switch (elem_size) { |
| 1572 | else => { |
| 1573 | const dst_mcv = try self.allocRegOrMem(inst, true); |
| 1549 | 1574 | |
| 1550 | | const offset_mcv = try self.genMulConstant(bin_op.rhs, @intCast(u32, elem_size)); |
| 1551 | | assert(offset_mcv == .register); // result of multiplication should always be register |
| 1552 | | self.register_manager.freezeRegs(&.{offset_mcv.register}); |
| 1575 | const offset_mcv = try self.binOp( |
| 1576 | .mul, |
| 1577 | null, |
| 1578 | index_mcv, |
| 1579 | .{ .immediate = elem_size }, |
| 1580 | Type.usize, |
| 1581 | Type.usize, |
| 1582 | ); |
| 1583 | assert(offset_mcv == .register); // result of multiplication should always be register |
| 1584 | self.register_manager.freezeRegs(&.{offset_mcv.register}); |
| 1553 | 1585 | |
| 1554 | | const addr_reg = try self.register_manager.allocReg(null); |
| 1555 | | self.register_manager.freezeRegs(&.{addr_reg}); |
| 1556 | | defer self.register_manager.unfreezeRegs(&.{addr_reg}); |
| 1586 | const addr_mcv = try self.binOp(.add, null, base_mcv, offset_mcv, Type.usize, Type.usize); |
| 1557 | 1587 | |
| 1558 | | _ = try self.addInst(.{ |
| 1559 | | .tag = .add_shifted_register, |
| 1560 | | .data = .{ .rrr_imm6_shift = .{ |
| 1561 | | .rd = addr_reg, |
| 1562 | | .rn = base_mcv.register, |
| 1563 | | .rm = offset_mcv.register, |
| 1564 | | .imm6 = 0, |
| 1565 | | .shift = .lsl, |
| 1566 | | } }, |
| 1567 | | }); |
| 1588 | // At this point in time, neither the base register |
| 1589 | // nor the offset register contains any valuable data |
| 1590 | // anymore. |
| 1591 | self.register_manager.unfreezeRegs(&.{ base_mcv.register, offset_mcv.register }); |
| 1568 | 1592 | |
| 1569 | | // At this point in time, neither the base register |
| 1570 | | // nor the offset register contains any valuable data |
| 1571 | | // anymore. |
| 1572 | | self.register_manager.unfreezeRegs(&.{ base_mcv.register, offset_mcv.register }); |
| 1593 | try self.load(dst_mcv, addr_mcv, slice_ptr_field_type); |
| 1573 | 1594 | |
| 1574 | | try self.load(dst_mcv, .{ .register = addr_reg }, slice_ptr_field_type); |
| 1575 | | |
| 1576 | | break :result dst_mcv; |
| 1595 | break :result dst_mcv; |
| 1596 | }, |
| 1597 | } |
| 1577 | 1598 | }; |
| 1578 | 1599 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1579 | 1600 | } |
| 1580 | 1601 | |
| 1581 | | fn genMulConstant(self: *Self, op: Air.Inst.Ref, imm: u32) !MCValue { |
| 1582 | | const lhs = try self.resolveInst(op); |
| 1583 | | const rhs = MCValue{ .immediate = imm }; |
| 1584 | | |
| 1585 | | const lhs_is_register = lhs == .register; |
| 1586 | | |
| 1587 | | if (lhs_is_register) self.register_manager.freezeRegs(&.{lhs.register}); |
| 1588 | | defer if (lhs_is_register) self.register_manager.unfreezeRegs(&.{lhs.register}); |
| 1589 | | |
| 1590 | | // Destination must be a register |
| 1591 | | // LHS must be a register |
| 1592 | | // RHS must be a register |
| 1593 | | var dst_mcv: MCValue = undefined; |
| 1594 | | var lhs_mcv: MCValue = lhs; |
| 1595 | | var rhs_mcv: MCValue = rhs; |
| 1596 | | |
| 1597 | | // Allocate registers for operands and/or destination |
| 1598 | | // Allocate 1 or 2 registers |
| 1599 | | if (lhs_is_register) { |
| 1600 | | // Move RHS to register |
| 1601 | | dst_mcv = MCValue{ .register = try self.register_manager.allocReg(null) }; |
| 1602 | | rhs_mcv = dst_mcv; |
| 1603 | | } else { |
| 1604 | | // Move LHS and RHS to register |
| 1605 | | const regs = try self.register_manager.allocRegs(2, .{ null, null }); |
| 1606 | | lhs_mcv = MCValue{ .register = regs[0] }; |
| 1607 | | rhs_mcv = MCValue{ .register = regs[1] }; |
| 1608 | | dst_mcv = lhs_mcv; |
| 1609 | | } |
| 1610 | | |
| 1611 | | // Move the operands to the newly allocated registers |
| 1612 | | if (!lhs_is_register) { |
| 1613 | | try self.genSetReg(self.air.typeOf(op), lhs_mcv.register, lhs); |
| 1614 | | } |
| 1615 | | try self.genSetReg(Type.initTag(.usize), rhs_mcv.register, rhs); |
| 1616 | | |
| 1617 | | _ = try self.addInst(.{ |
| 1618 | | .tag = .mul, |
| 1619 | | .data = .{ .rrr = .{ |
| 1620 | | .rd = dst_mcv.register, |
| 1621 | | .rn = lhs_mcv.register, |
| 1622 | | .rm = rhs_mcv.register, |
| 1623 | | } }, |
| 1624 | | }); |
| 1625 | | |
| 1626 | | return dst_mcv; |
| 1627 | | } |
| 1628 | | |
| 1629 | 1602 | fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1630 | 1603 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 1631 | 1604 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; |