| ... | @@ -1401,19 +1401,26 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1401,19 +1401,26 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 1401 | | 1401 | |
| 1402 | fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { | 1402 | fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { |
| 1403 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 1403 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 1404 | const lhs = try self.resolveInst(bin_op.lhs); | | |
| 1405 | const rhs = try self.resolveInst(bin_op.rhs); | | |
| 1406 | const lhs_ty = self.air.typeOf(bin_op.lhs); | 1404 | const lhs_ty = self.air.typeOf(bin_op.lhs); |
| 1407 | const rhs_ty = self.air.typeOf(bin_op.rhs); | 1405 | const rhs_ty = self.air.typeOf(bin_op.rhs); |
| 1408 | | 1406 | |
| 1409 | const result: MCValue = if (self.liveness.isUnused(inst)) | 1407 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1410 | .dead | 1408 | const lhs_bind: ReadArg.Bind = .{ .inst = bin_op.lhs }; |
| 1411 | else | 1409 | const rhs_bind: ReadArg.Bind = .{ .inst = bin_op.rhs }; |
| 1412 | try self.binOp(tag, lhs, rhs, lhs_ty, rhs_ty, BinOpMetadata{ | 1410 | const lhs = try self.resolveInst(bin_op.lhs); |
| 1413 | .lhs = bin_op.lhs, | 1411 | const rhs = try self.resolveInst(bin_op.rhs); |
| 1414 | .rhs = bin_op.rhs, | 1412 | |
| 1415 | .inst = inst, | 1413 | switch (tag) { |
| 1416 | }); | 1414 | .add, |
| | 1415 | .sub, |
| | 1416 | => break :result try self.addSub(tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst), |
| | 1417 | else => break :result try self.binOp(tag, lhs, rhs, lhs_ty, rhs_ty, BinOpMetadata{ |
| | 1418 | .lhs = bin_op.lhs, |
| | 1419 | .rhs = bin_op.rhs, |
| | 1420 | .inst = inst, |
| | 1421 | }), |
| | 1422 | } |
| | 1423 | }; |
| 1417 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 1424 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1418 | } | 1425 | } |
| 1419 | | 1426 | |
| ... | @@ -1459,8 +1466,8 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1459,8 +1466,8 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1459 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 1466 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 1460 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; | 1467 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 1461 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 1468 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1462 | const lhs = try self.resolveInst(extra.lhs); | 1469 | const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs }; |
| 1463 | const rhs = try self.resolveInst(extra.rhs); | 1470 | const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs }; |
| 1464 | const lhs_ty = self.air.typeOf(extra.lhs); | 1471 | const lhs_ty = self.air.typeOf(extra.lhs); |
| 1465 | const rhs_ty = self.air.typeOf(extra.rhs); | 1472 | const rhs_ty = self.air.typeOf(extra.rhs); |
| 1466 | | 1473 | |
| ... | @@ -1485,7 +1492,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1485,7 +1492,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1485 | .sub_with_overflow => .sub, | 1492 | .sub_with_overflow => .sub, |
| 1486 | else => unreachable, | 1493 | else => unreachable, |
| 1487 | }; | 1494 | }; |
| 1488 | const dest = try self.binOp(base_tag, lhs, rhs, lhs_ty, rhs_ty, null); | 1495 | const dest = try self.addSub(base_tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, null); |
| 1489 | const dest_reg = dest.register; | 1496 | const dest_reg = dest.register; |
| 1490 | const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg); | 1497 | const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg); |
| 1491 | defer self.register_manager.unlockReg(dest_reg_lock); | 1498 | defer self.register_manager.unlockReg(dest_reg_lock); |
| ... | @@ -1511,6 +1518,9 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1511,6 +1518,9 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1511 | | 1518 | |
| 1512 | break :result MCValue{ .stack_offset = stack_offset }; | 1519 | break :result MCValue{ .stack_offset = stack_offset }; |
| 1513 | } else if (int_info.bits == 32) { | 1520 | } else if (int_info.bits == 32) { |
| | 1521 | const lhs = try self.resolveInst(extra.lhs); |
| | 1522 | const rhs = try self.resolveInst(extra.rhs); |
| | 1523 | |
| 1514 | // Only say yes if the operation is | 1524 | // Only say yes if the operation is |
| 1515 | // commutative, i.e. we can swap both of the | 1525 | // commutative, i.e. we can swap both of the |
| 1516 | // operands | 1526 | // operands |
| ... | @@ -2600,26 +2610,10 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde | ... | @@ -2600,26 +2610,10 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde |
| 2600 | break :result MCValue{ .ptr_stack_offset = off - struct_field_offset }; | 2610 | break :result MCValue{ .ptr_stack_offset = off - struct_field_offset }; |
| 2601 | }, | 2611 | }, |
| 2602 | else => { | 2612 | else => { |
| 2603 | const offset_reg = try self.copyToTmpRegister(ptr_ty, .{ | 2613 | const lhs_bind: ReadArg.Bind = .{ .mcv = mcv }; |
| 2604 | .immediate = struct_field_offset, | 2614 | const rhs_bind: ReadArg.Bind = .{ .mcv = .{ .immediate = struct_field_offset } }; |
| 2605 | }); | | |
| 2606 | const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg); | | |
| 2607 | defer self.register_manager.unlockReg(offset_reg_lock); | | |
| 2608 | | | |
| 2609 | const addr_reg = try self.copyToTmpRegister(ptr_ty, mcv); | | |
| 2610 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); | | |
| 2611 | defer self.register_manager.unlockReg(addr_reg_lock); | | |
| 2612 | | 2615 | |
| 2613 | const dest = try self.binOp( | 2616 | break :result try self.addSub(.add, lhs_bind, rhs_bind, Type.usize, Type.usize, null); |
| 2614 | .add, | | |
| 2615 | .{ .register = addr_reg }, | | |
| 2616 | .{ .register = offset_reg }, | | |
| 2617 | Type.usize, | | |
| 2618 | Type.usize, | | |
| 2619 | null, | | |
| 2620 | ); | | |
| 2621 | | | |
| 2622 | break :result dest; | | |
| 2623 | }, | 2617 | }, |
| 2624 | } | 2618 | } |
| 2625 | }; | 2619 | }; |
| ... | @@ -2708,6 +2702,25 @@ const ReadArg = struct { | ... | @@ -2708,6 +2702,25 @@ const ReadArg = struct { |
| 2708 | .mcv => |mcv| mcv, | 2702 | .mcv => |mcv| mcv, |
| 2709 | }; | 2703 | }; |
| 2710 | } | 2704 | } |
| | 2705 | |
| | 2706 | fn resolveToImmediate(bind: Bind, function: *Self) InnerError!?u32 { |
| | 2707 | switch (bind) { |
| | 2708 | .inst => |inst| { |
| | 2709 | // TODO resolve independently of inst_table |
| | 2710 | const mcv = try function.resolveInst(inst); |
| | 2711 | switch (mcv) { |
| | 2712 | .immediate => |imm| return imm, |
| | 2713 | else => return null, |
| | 2714 | } |
| | 2715 | }, |
| | 2716 | .mcv => |mcv| { |
| | 2717 | switch (mcv) { |
| | 2718 | .immediate => |imm| return imm, |
| | 2719 | else => return null, |
| | 2720 | } |
| | 2721 | }, |
| | 2722 | } |
| | 2723 | } |
| 2711 | }; | 2724 | }; |
| 2712 | }; | 2725 | }; |
| 2713 | | 2726 | |
| ... | @@ -3057,6 +3070,136 @@ fn binOpImmediate( | ... | @@ -3057,6 +3070,136 @@ fn binOpImmediate( |
| 3057 | return MCValue{ .register = dest_reg }; | 3070 | return MCValue{ .register = dest_reg }; |
| 3058 | } | 3071 | } |
| 3059 | | 3072 | |
| | 3073 | /// TODO |
| | 3074 | fn binOpRegisterNew( |
| | 3075 | self: *Self, |
| | 3076 | mir_tag: Mir.Inst.Tag, |
| | 3077 | lhs_bind: ReadArg.Bind, |
| | 3078 | rhs_bind: ReadArg.Bind, |
| | 3079 | lhs_ty: Type, |
| | 3080 | rhs_ty: Type, |
| | 3081 | maybe_inst: ?Air.Inst.Index, |
| | 3082 | ) !MCValue { |
| | 3083 | var lhs_reg: Register = undefined; |
| | 3084 | var rhs_reg: Register = undefined; |
| | 3085 | var dest_reg: Register = undefined; |
| | 3086 | |
| | 3087 | const read_args = [_]ReadArg{ |
| | 3088 | .{ .ty = lhs_ty, .bind = lhs_bind, .class = gp, .reg = &lhs_reg }, |
| | 3089 | .{ .ty = rhs_ty, .bind = rhs_bind, .class = gp, .reg = &rhs_reg }, |
| | 3090 | }; |
| | 3091 | const write_args = [_]WriteArg{ |
| | 3092 | .{ .ty = lhs_ty, .bind = .none, .class = gp, .reg = &dest_reg }, |
| | 3093 | }; |
| | 3094 | try self.allocRegs( |
| | 3095 | &read_args, |
| | 3096 | &write_args, |
| | 3097 | if (maybe_inst) |inst| .{ |
| | 3098 | .corresponding_inst = inst, |
| | 3099 | .operand_mapping = &.{ 0, 1 }, |
| | 3100 | } else null, |
| | 3101 | ); |
| | 3102 | |
| | 3103 | const mir_data: Mir.Inst.Data = switch (mir_tag) { |
| | 3104 | .add, |
| | 3105 | .adds, |
| | 3106 | .sub, |
| | 3107 | .subs, |
| | 3108 | .@"and", |
| | 3109 | .orr, |
| | 3110 | .eor, |
| | 3111 | => .{ .rr_op = .{ |
| | 3112 | .rd = dest_reg, |
| | 3113 | .rn = lhs_reg, |
| | 3114 | .op = Instruction.Operand.reg(rhs_reg, Instruction.Operand.Shift.none), |
| | 3115 | } }, |
| | 3116 | .lsl, |
| | 3117 | .asr, |
| | 3118 | .lsr, |
| | 3119 | => .{ .rr_shift = .{ |
| | 3120 | .rd = dest_reg, |
| | 3121 | .rm = lhs_reg, |
| | 3122 | .shift_amount = Instruction.ShiftAmount.reg(rhs_reg), |
| | 3123 | } }, |
| | 3124 | .mul, |
| | 3125 | .smulbb, |
| | 3126 | => .{ .rrr = .{ |
| | 3127 | .rd = dest_reg, |
| | 3128 | .rn = lhs_reg, |
| | 3129 | .rm = rhs_reg, |
| | 3130 | } }, |
| | 3131 | else => unreachable, |
| | 3132 | }; |
| | 3133 | |
| | 3134 | _ = try self.addInst(.{ |
| | 3135 | .tag = mir_tag, |
| | 3136 | .data = mir_data, |
| | 3137 | }); |
| | 3138 | |
| | 3139 | return MCValue{ .register = dest_reg }; |
| | 3140 | } |
| | 3141 | |
| | 3142 | /// TODO |
| | 3143 | fn binOpImmediateNew( |
| | 3144 | self: *Self, |
| | 3145 | mir_tag: Mir.Inst.Tag, |
| | 3146 | lhs_bind: ReadArg.Bind, |
| | 3147 | rhs_immediate: u32, |
| | 3148 | lhs_ty: Type, |
| | 3149 | lhs_and_rhs_swapped: bool, |
| | 3150 | maybe_inst: ?Air.Inst.Index, |
| | 3151 | ) !MCValue { |
| | 3152 | var lhs_reg: Register = undefined; |
| | 3153 | var dest_reg: Register = undefined; |
| | 3154 | |
| | 3155 | const read_args = [_]ReadArg{ |
| | 3156 | .{ .ty = lhs_ty, .bind = lhs_bind, .class = gp, .reg = &lhs_reg }, |
| | 3157 | }; |
| | 3158 | const write_args = [_]WriteArg{ |
| | 3159 | .{ .ty = lhs_ty, .bind = .none, .class = gp, .reg = &dest_reg }, |
| | 3160 | }; |
| | 3161 | const operand_mapping: []const Liveness.OperandInt = if (lhs_and_rhs_swapped) &.{1} else &.{0}; |
| | 3162 | try self.allocRegs( |
| | 3163 | &read_args, |
| | 3164 | &write_args, |
| | 3165 | if (maybe_inst) |inst| .{ |
| | 3166 | .corresponding_inst = inst, |
| | 3167 | .operand_mapping = operand_mapping, |
| | 3168 | } else null, |
| | 3169 | ); |
| | 3170 | |
| | 3171 | const mir_data: Mir.Inst.Data = switch (mir_tag) { |
| | 3172 | .add, |
| | 3173 | .adds, |
| | 3174 | .sub, |
| | 3175 | .subs, |
| | 3176 | .@"and", |
| | 3177 | .orr, |
| | 3178 | .eor, |
| | 3179 | => .{ .rr_op = .{ |
| | 3180 | .rd = dest_reg, |
| | 3181 | .rn = lhs_reg, |
| | 3182 | .op = Instruction.Operand.fromU32(rhs_immediate).?, |
| | 3183 | } }, |
| | 3184 | .lsl, |
| | 3185 | .asr, |
| | 3186 | .lsr, |
| | 3187 | => .{ .rr_shift = .{ |
| | 3188 | .rd = dest_reg, |
| | 3189 | .rm = lhs_reg, |
| | 3190 | .shift_amount = Instruction.ShiftAmount.imm(@intCast(u5, rhs_immediate)), |
| | 3191 | } }, |
| | 3192 | else => unreachable, |
| | 3193 | }; |
| | 3194 | |
| | 3195 | _ = try self.addInst(.{ |
| | 3196 | .tag = mir_tag, |
| | 3197 | .data = mir_data, |
| | 3198 | }); |
| | 3199 | |
| | 3200 | return MCValue{ .register = dest_reg }; |
| | 3201 | } |
| | 3202 | |
| 3060 | const BinOpMetadata = struct { | 3203 | const BinOpMetadata = struct { |
| 3061 | inst: Air.Inst.Index, | 3204 | inst: Air.Inst.Index, |
| 3062 | lhs: Air.Inst.Ref, | 3205 | lhs: Air.Inst.Ref, |
| ... | @@ -3085,53 +3228,6 @@ fn binOp( | ... | @@ -3085,53 +3228,6 @@ fn binOp( |
| 3085 | metadata: ?BinOpMetadata, | 3228 | metadata: ?BinOpMetadata, |
| 3086 | ) InnerError!MCValue { | 3229 | ) InnerError!MCValue { |
| 3087 | switch (tag) { | 3230 | switch (tag) { |
| 3088 | .add, | | |
| 3089 | .sub, | | |
| 3090 | => { | | |
| 3091 | switch (lhs_ty.zigTypeTag()) { | | |
| 3092 | .Float => return self.fail("TODO ARM binary operations on floats", .{}), | | |
| 3093 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), | | |
| 3094 | .Int => { | | |
| 3095 | const mod = self.bin_file.options.module.?; | | |
| 3096 | assert(lhs_ty.eql(rhs_ty, mod)); | | |
| 3097 | const int_info = lhs_ty.intInfo(self.target.*); | | |
| 3098 | if (int_info.bits <= 32) { | | |
| 3099 | // Only say yes if the operation is | | |
| 3100 | // commutative, i.e. we can swap both of the | | |
| 3101 | // operands | | |
| 3102 | const lhs_immediate_ok = switch (tag) { | | |
| 3103 | .add => lhs == .immediate and Instruction.Operand.fromU32(lhs.immediate) != null, | | |
| 3104 | .sub => false, | | |
| 3105 | else => unreachable, | | |
| 3106 | }; | | |
| 3107 | const rhs_immediate_ok = switch (tag) { | | |
| 3108 | .add, | | |
| 3109 | .sub, | | |
| 3110 | => rhs == .immediate and Instruction.Operand.fromU32(rhs.immediate) != null, | | |
| 3111 | else => unreachable, | | |
| 3112 | }; | | |
| 3113 | | | |
| 3114 | const mir_tag: Mir.Inst.Tag = switch (tag) { | | |
| 3115 | .add => .add, | | |
| 3116 | .sub => .sub, | | |
| 3117 | else => unreachable, | | |
| 3118 | }; | | |
| 3119 | | | |
| 3120 | if (rhs_immediate_ok) { | | |
| 3121 | return try self.binOpImmediate(mir_tag, lhs, rhs, lhs_ty, false, metadata); | | |
| 3122 | } else if (lhs_immediate_ok) { | | |
| 3123 | // swap lhs and rhs | | |
| 3124 | return try self.binOpImmediate(mir_tag, rhs, lhs, rhs_ty, true, metadata); | | |
| 3125 | } else { | | |
| 3126 | return try self.binOpRegister(mir_tag, lhs, rhs, lhs_ty, rhs_ty, metadata); | | |
| 3127 | } | | |
| 3128 | } else { | | |
| 3129 | return self.fail("TODO ARM binary operations on integers > u32/i32", .{}); | | |
| 3130 | } | | |
| 3131 | }, | | |
| 3132 | else => unreachable, | | |
| 3133 | } | | |
| 3134 | }, | | |
| 3135 | .mul => { | 3231 | .mul => { |
| 3136 | switch (lhs_ty.zigTypeTag()) { | 3232 | switch (lhs_ty.zigTypeTag()) { |
| 3137 | .Float => return self.fail("TODO ARM binary operations on floats", .{}), | 3233 | .Float => return self.fail("TODO ARM binary operations on floats", .{}), |
| ... | @@ -3278,8 +3374,18 @@ fn binOp( | ... | @@ -3278,8 +3374,18 @@ fn binOp( |
| 3278 | else => unreachable, | 3374 | else => unreachable, |
| 3279 | }; | 3375 | }; |
| 3280 | | 3376 | |
| | 3377 | const lhs_bind = if (metadata) |md| |
| | 3378 | ReadArg.Bind{ .inst = md.lhs } |
| | 3379 | else |
| | 3380 | ReadArg.Bind{ .mcv = lhs }; |
| | 3381 | const rhs_bind = if (metadata) |md| |
| | 3382 | ReadArg.Bind{ .inst = md.rhs } |
| | 3383 | else |
| | 3384 | ReadArg.Bind{ .mcv = rhs }; |
| | 3385 | |
| 3281 | // Generate an add/sub/mul | 3386 | // Generate an add/sub/mul |
| 3282 | const result = try self.binOp(base_tag, lhs, rhs, lhs_ty, rhs_ty, metadata); | 3387 | const maybe_inst: ?Air.Inst.Index = if (metadata) |md| md.inst else null; |
| | 3388 | const result = try self.addSub(base_tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst); |
| 3283 | | 3389 | |
| 3284 | // Truncate if necessary | 3390 | // Truncate if necessary |
| 3285 | switch (lhs_ty.zigTypeTag()) { | 3391 | switch (lhs_ty.zigTypeTag()) { |
| ... | @@ -3463,6 +3569,63 @@ fn binOp( | ... | @@ -3463,6 +3569,63 @@ fn binOp( |
| 3463 | } | 3569 | } |
| 3464 | } | 3570 | } |
| 3465 | | 3571 | |
| | 3572 | fn addSub( |
| | 3573 | self: *Self, |
| | 3574 | tag: Air.Inst.Tag, |
| | 3575 | lhs_bind: ReadArg.Bind, |
| | 3576 | rhs_bind: ReadArg.Bind, |
| | 3577 | lhs_ty: Type, |
| | 3578 | rhs_ty: Type, |
| | 3579 | maybe_inst: ?Air.Inst.Index, |
| | 3580 | ) InnerError!MCValue { |
| | 3581 | switch (lhs_ty.zigTypeTag()) { |
| | 3582 | .Float => return self.fail("TODO ARM binary operations on floats", .{}), |
| | 3583 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), |
| | 3584 | .Int => { |
| | 3585 | const mod = self.bin_file.options.module.?; |
| | 3586 | assert(lhs_ty.eql(rhs_ty, mod)); |
| | 3587 | const int_info = lhs_ty.intInfo(self.target.*); |
| | 3588 | if (int_info.bits <= 32) { |
| | 3589 | const lhs_immediate = try lhs_bind.resolveToImmediate(self); |
| | 3590 | const rhs_immediate = try rhs_bind.resolveToImmediate(self); |
| | 3591 | |
| | 3592 | // Only say yes if the operation is |
| | 3593 | // commutative, i.e. we can swap both of the |
| | 3594 | // operands |
| | 3595 | const lhs_immediate_ok = switch (tag) { |
| | 3596 | .add => if (lhs_immediate) |imm| Instruction.Operand.fromU32(imm) != null else false, |
| | 3597 | .sub => false, |
| | 3598 | else => unreachable, |
| | 3599 | }; |
| | 3600 | const rhs_immediate_ok = switch (tag) { |
| | 3601 | .add, |
| | 3602 | .sub, |
| | 3603 | => if (rhs_immediate) |imm| Instruction.Operand.fromU32(imm) != null else false, |
| | 3604 | else => unreachable, |
| | 3605 | }; |
| | 3606 | |
| | 3607 | const mir_tag: Mir.Inst.Tag = switch (tag) { |
| | 3608 | .add => .add, |
| | 3609 | .sub => .sub, |
| | 3610 | else => unreachable, |
| | 3611 | }; |
| | 3612 | |
| | 3613 | if (rhs_immediate_ok) { |
| | 3614 | return try self.binOpImmediateNew(mir_tag, lhs_bind, rhs_immediate.?, lhs_ty, false, maybe_inst); |
| | 3615 | } else if (lhs_immediate_ok) { |
| | 3616 | // swap lhs and rhs |
| | 3617 | return try self.binOpImmediateNew(mir_tag, rhs_bind, lhs_immediate.?, rhs_ty, true, maybe_inst); |
| | 3618 | } else { |
| | 3619 | return try self.binOpRegisterNew(mir_tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst); |
| | 3620 | } |
| | 3621 | } else { |
| | 3622 | return self.fail("TODO ARM binary operations on integers > u32/i32", .{}); |
| | 3623 | } |
| | 3624 | }, |
| | 3625 | else => unreachable, |
| | 3626 | } |
| | 3627 | } |
| | 3628 | |
| 3466 | fn genLdrRegister(self: *Self, dest_reg: Register, addr_reg: Register, ty: Type) !void { | 3629 | fn genLdrRegister(self: *Self, dest_reg: Register, addr_reg: Register, ty: Type) !void { |
| 3467 | const abi_size = ty.abiSize(self.target.*); | 3630 | const abi_size = ty.abiSize(self.target.*); |
| 3468 | | 3631 | |
| ... | @@ -4138,8 +4301,8 @@ fn cmp( | ... | @@ -4138,8 +4301,8 @@ fn cmp( |
| 4138 | var lhs_reg: Register = undefined; | 4301 | var lhs_reg: Register = undefined; |
| 4139 | var rhs_reg: Register = undefined; | 4302 | var rhs_reg: Register = undefined; |
| 4140 | | 4303 | |
| 4141 | const rhs_mcv = try rhs.resolveToMcv(self); | 4304 | const rhs_immediate = try rhs.resolveToImmediate(self); |
| 4142 | const rhs_immediate_ok = rhs_mcv == .immediate and Instruction.Operand.fromU32(rhs_mcv.immediate) != null; | 4305 | const rhs_immediate_ok = if (rhs_immediate) |imm| Instruction.Operand.fromU32(imm) != null else false; |
| 4143 | | 4306 | |
| 4144 | if (rhs_immediate_ok) { | 4307 | if (rhs_immediate_ok) { |
| 4145 | const read_args = [_]ReadArg{ | 4308 | const read_args = [_]ReadArg{ |
| ... | @@ -4155,7 +4318,7 @@ fn cmp( | ... | @@ -4155,7 +4318,7 @@ fn cmp( |
| 4155 | .tag = .cmp, | 4318 | .tag = .cmp, |
| 4156 | .data = .{ .r_op_cmp = .{ | 4319 | .data = .{ .r_op_cmp = .{ |
| 4157 | .rn = lhs_reg, | 4320 | .rn = lhs_reg, |
| 4158 | .op = Instruction.Operand.fromU32(rhs_mcv.immediate).?, | 4321 | .op = Instruction.Operand.fromU32(rhs_immediate.?).?, |
| 4159 | } }, | 4322 | } }, |
| 4160 | }); | 4323 | }); |
| 4161 | } else { | 4324 | } else { |