| ... | ... | @@ -1193,7 +1193,7 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 1193 | 1193 | /// Asserts that generating an instruction of that form is possible. |
| 1194 | 1194 | fn binOpRegister( |
| 1195 | 1195 | self: *Self, |
| 1196 | | tag: Air.Inst.Tag, |
| 1196 | mir_tag: Mir.Inst.Tag, |
| 1197 | 1197 | maybe_inst: ?Air.Inst.Index, |
| 1198 | 1198 | lhs: MCValue, |
| 1199 | 1199 | rhs: MCValue, |
| ... | ... | @@ -1256,38 +1256,9 @@ fn binOpRegister( |
| 1256 | 1256 | if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs); |
| 1257 | 1257 | if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs); |
| 1258 | 1258 | |
| 1259 | | const mir_tag: Mir.Inst.Tag = switch (tag) { |
| 1260 | | .add, |
| 1261 | | .ptr_add, |
| 1262 | | => .add_shifted_register, |
| 1263 | | .sub, |
| 1264 | | .ptr_sub, |
| 1265 | | => .sub_shifted_register, |
| 1266 | | .cmp_eq => .cmp_shifted_register, |
| 1267 | | .mul => .mul, |
| 1268 | | .bit_and, |
| 1269 | | .bool_and, |
| 1270 | | => .and_shifted_register, |
| 1271 | | .bit_or, |
| 1272 | | .bool_or, |
| 1273 | | => .orr_shifted_register, |
| 1274 | | .shl, |
| 1275 | | .shl_exact, |
| 1276 | | => .lsl_register, |
| 1277 | | .shr, |
| 1278 | | .shr_exact, |
| 1279 | | => switch (lhs_ty.intInfo(self.target.*).signedness) { |
| 1280 | | .signed => Mir.Inst.Tag.asr_register, |
| 1281 | | .unsigned => Mir.Inst.Tag.lsr_register, |
| 1282 | | }, |
| 1283 | | .xor => .eor_shifted_register, |
| 1284 | | else => unreachable, |
| 1285 | | }; |
| 1286 | | const mir_data: Mir.Inst.Data = switch (tag) { |
| 1287 | | .add, |
| 1288 | | .sub, |
| 1289 | | .ptr_add, |
| 1290 | | .ptr_sub, |
| 1259 | const mir_data: Mir.Inst.Data = switch (mir_tag) { |
| 1260 | .add_shifted_register, |
| 1261 | .sub_shifted_register, |
| 1291 | 1262 | => .{ .rrr_imm6_shift = .{ |
| 1292 | 1263 | .rd = dest_reg, |
| 1293 | 1264 | .rn = lhs_reg, |
| ... | ... | @@ -1295,27 +1266,24 @@ fn binOpRegister( |
| 1295 | 1266 | .imm6 = 0, |
| 1296 | 1267 | .shift = .lsl, |
| 1297 | 1268 | } }, |
| 1298 | | .cmp_eq => .{ .rr_imm6_shift = .{ |
| 1269 | .cmp_shifted_register => .{ .rr_imm6_shift = .{ |
| 1299 | 1270 | .rn = lhs_reg, |
| 1300 | 1271 | .rm = rhs_reg, |
| 1301 | 1272 | .imm6 = 0, |
| 1302 | 1273 | .shift = .lsl, |
| 1303 | 1274 | } }, |
| 1304 | 1275 | .mul, |
| 1305 | | .shl, |
| 1306 | | .shl_exact, |
| 1307 | | .shr, |
| 1308 | | .shr_exact, |
| 1276 | .lsl_register, |
| 1277 | .asr_register, |
| 1278 | .lsr_register, |
| 1309 | 1279 | => .{ .rrr = .{ |
| 1310 | 1280 | .rd = dest_reg, |
| 1311 | 1281 | .rn = lhs_reg, |
| 1312 | 1282 | .rm = rhs_reg, |
| 1313 | 1283 | } }, |
| 1314 | | .bit_and, |
| 1315 | | .bool_and, |
| 1316 | | .bit_or, |
| 1317 | | .bool_or, |
| 1318 | | .xor, |
| 1284 | .and_shifted_register, |
| 1285 | .orr_shifted_register, |
| 1286 | .eor_shifted_register, |
| 1319 | 1287 | => .{ .rrr_imm6_logical_shift = .{ |
| 1320 | 1288 | .rd = dest_reg, |
| 1321 | 1289 | .rn = lhs_reg, |
| ... | ... | @@ -1348,7 +1316,7 @@ fn binOpRegister( |
| 1348 | 1316 | /// Asserts that generating an instruction of that form is possible. |
| 1349 | 1317 | fn binOpImmediate( |
| 1350 | 1318 | self: *Self, |
| 1351 | | tag: Air.Inst.Tag, |
| 1319 | mir_tag: Mir.Inst.Tag, |
| 1352 | 1320 | maybe_inst: ?Air.Inst.Index, |
| 1353 | 1321 | lhs: MCValue, |
| 1354 | 1322 | rhs: MCValue, |
| ... | ... | @@ -1379,8 +1347,8 @@ fn binOpImmediate( |
| 1379 | 1347 | }; |
| 1380 | 1348 | defer self.register_manager.unfreezeRegs(&.{lhs_reg}); |
| 1381 | 1349 | |
| 1382 | | const dest_reg = switch (tag) { |
| 1383 | | .cmp_eq => undefined, // cmp has no destination register |
| 1350 | const dest_reg = switch (mir_tag) { |
| 1351 | .cmp_immediate => undefined, // cmp has no destination register |
| 1384 | 1352 | else => if (maybe_inst) |inst| blk: { |
| 1385 | 1353 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 1386 | 1354 | |
| ... | ... | @@ -1400,39 +1368,23 @@ fn binOpImmediate( |
| 1400 | 1368 | |
| 1401 | 1369 | if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs); |
| 1402 | 1370 | |
| 1403 | | const mir_tag: Mir.Inst.Tag = switch (tag) { |
| 1404 | | .add => .add_immediate, |
| 1405 | | .sub => .sub_immediate, |
| 1406 | | .shl, |
| 1407 | | .shl_exact, |
| 1408 | | => .lsl_immediate, |
| 1409 | | .shr, |
| 1410 | | .shr_exact, |
| 1411 | | => switch (lhs_ty.intInfo(self.target.*).signedness) { |
| 1412 | | .signed => Mir.Inst.Tag.asr_immediate, |
| 1413 | | .unsigned => Mir.Inst.Tag.lsr_immediate, |
| 1414 | | }, |
| 1415 | | .cmp_eq => .cmp_immediate, |
| 1416 | | else => unreachable, |
| 1417 | | }; |
| 1418 | | const mir_data: Mir.Inst.Data = switch (tag) { |
| 1419 | | .add, |
| 1420 | | .sub, |
| 1371 | const mir_data: Mir.Inst.Data = switch (mir_tag) { |
| 1372 | .add_immediate, |
| 1373 | .sub_immediate, |
| 1421 | 1374 | => .{ .rr_imm12_sh = .{ |
| 1422 | 1375 | .rd = dest_reg, |
| 1423 | 1376 | .rn = lhs_reg, |
| 1424 | 1377 | .imm12 = @intCast(u12, rhs.immediate), |
| 1425 | 1378 | } }, |
| 1426 | | .shl, |
| 1427 | | .shl_exact, |
| 1428 | | .shr, |
| 1429 | | .shr_exact, |
| 1379 | .lsl_immediate, |
| 1380 | .asr_immediate, |
| 1381 | .lsr_immediate, |
| 1430 | 1382 | => .{ .rr_shift = .{ |
| 1431 | 1383 | .rd = dest_reg, |
| 1432 | 1384 | .rn = lhs_reg, |
| 1433 | 1385 | .shift = @intCast(u6, rhs.immediate), |
| 1434 | 1386 | } }, |
| 1435 | | .cmp_eq => .{ .r_imm12_sh = .{ |
| 1387 | .cmp_immediate => .{ .r_imm12_sh = .{ |
| 1436 | 1388 | .rn = lhs_reg, |
| 1437 | 1389 | .imm12 = @intCast(u12, rhs.immediate), |
| 1438 | 1390 | } }, |
| ... | ... | @@ -1470,7 +1422,6 @@ fn binOp( |
| 1470 | 1422 | ) InnerError!MCValue { |
| 1471 | 1423 | const target = self.target.*; |
| 1472 | 1424 | switch (tag) { |
| 1473 | | // Arithmetic operations on integers and floats |
| 1474 | 1425 | .add, |
| 1475 | 1426 | .sub, |
| 1476 | 1427 | .cmp_eq, |
| ... | ... | @@ -1498,13 +1449,26 @@ fn binOp( |
| 1498 | 1449 | else => unreachable, |
| 1499 | 1450 | }; |
| 1500 | 1451 | |
| 1452 | const mir_tag_register: Mir.Inst.Tag = switch (tag) { |
| 1453 | .add => .add_shifted_register, |
| 1454 | .sub => .sub_shifted_register, |
| 1455 | .cmp_eq => .cmp_shifted_register, |
| 1456 | else => unreachable, |
| 1457 | }; |
| 1458 | const mir_tag_immediate: Mir.Inst.Tag = switch (tag) { |
| 1459 | .add => .add_immediate, |
| 1460 | .sub => .sub_immediate, |
| 1461 | .cmp_eq => .cmp_immediate, |
| 1462 | else => unreachable, |
| 1463 | }; |
| 1464 | |
| 1501 | 1465 | if (rhs_immediate_ok) { |
| 1502 | | return try self.binOpImmediate(tag, maybe_inst, lhs, rhs, lhs_ty, false); |
| 1466 | return try self.binOpImmediate(mir_tag_immediate, maybe_inst, lhs, rhs, lhs_ty, false); |
| 1503 | 1467 | } else if (lhs_immediate_ok) { |
| 1504 | 1468 | // swap lhs and rhs |
| 1505 | | return try self.binOpImmediate(tag, maybe_inst, rhs, lhs, rhs_ty, true); |
| 1469 | return try self.binOpImmediate(mir_tag_immediate, maybe_inst, rhs, lhs, rhs_ty, true); |
| 1506 | 1470 | } else { |
| 1507 | | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 1471 | return try self.binOpRegister(mir_tag_register, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 1508 | 1472 | } |
| 1509 | 1473 | } else { |
| 1510 | 1474 | return self.fail("TODO binary operations on int with bits > 64", .{}); |
| ... | ... | @@ -1523,7 +1487,7 @@ fn binOp( |
| 1523 | 1487 | // TODO add optimisations for multiplication |
| 1524 | 1488 | // with immediates, for example a * 2 can be |
| 1525 | 1489 | // lowered to a << 1 |
| 1526 | | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 1490 | return try self.binOpRegister(.mul, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 1527 | 1491 | } else { |
| 1528 | 1492 | return self.fail("TODO binary operations on int with bits > 64", .{}); |
| 1529 | 1493 | } |
| ... | ... | @@ -1564,7 +1528,6 @@ fn binOp( |
| 1564 | 1528 | else => unreachable, |
| 1565 | 1529 | } |
| 1566 | 1530 | }, |
| 1567 | | // Bitwise operations on integers |
| 1568 | 1531 | .bit_and, |
| 1569 | 1532 | .bit_or, |
| 1570 | 1533 | .xor, |
| ... | ... | @@ -1576,7 +1539,14 @@ fn binOp( |
| 1576 | 1539 | const int_info = lhs_ty.intInfo(self.target.*); |
| 1577 | 1540 | if (int_info.bits <= 64) { |
| 1578 | 1541 | // TODO implement bitwise operations with immediates |
| 1579 | | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 1542 | const mir_tag: Mir.Inst.Tag = switch (tag) { |
| 1543 | .bit_and => .and_shifted_register, |
| 1544 | .bit_or => .orr_shifted_register, |
| 1545 | .xor => .eor_shifted_register, |
| 1546 | else => unreachable, |
| 1547 | }; |
| 1548 | |
| 1549 | return try self.binOpRegister(mir_tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 1580 | 1550 | } else { |
| 1581 | 1551 | return self.fail("TODO binary operations on int with bits > 64", .{}); |
| 1582 | 1552 | } |
| ... | ... | @@ -1594,10 +1564,27 @@ fn binOp( |
| 1594 | 1564 | if (int_info.bits <= 64) { |
| 1595 | 1565 | const rhs_immediate_ok = rhs == .immediate; |
| 1596 | 1566 | |
| 1567 | const mir_tag_register: Mir.Inst.Tag = switch (tag) { |
| 1568 | .shl => .lsl_register, |
| 1569 | .shr => switch (lhs_ty.intInfo(self.target.*).signedness) { |
| 1570 | .signed => Mir.Inst.Tag.asr_register, |
| 1571 | .unsigned => Mir.Inst.Tag.lsr_register, |
| 1572 | }, |
| 1573 | else => unreachable, |
| 1574 | }; |
| 1575 | const mir_tag_immediate: Mir.Inst.Tag = switch (tag) { |
| 1576 | .shl => .lsl_immediate, |
| 1577 | .shr => switch (lhs_ty.intInfo(self.target.*).signedness) { |
| 1578 | .signed => Mir.Inst.Tag.asr_immediate, |
| 1579 | .unsigned => Mir.Inst.Tag.lsr_immediate, |
| 1580 | }, |
| 1581 | else => unreachable, |
| 1582 | }; |
| 1583 | |
| 1597 | 1584 | if (rhs_immediate_ok) { |
| 1598 | | return try self.binOpImmediate(tag, maybe_inst, lhs, rhs, lhs_ty, false); |
| 1585 | return try self.binOpImmediate(mir_tag_immediate, maybe_inst, lhs, rhs, lhs_ty, false); |
| 1599 | 1586 | } else { |
| 1600 | | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 1587 | return try self.binOpRegister(mir_tag_register, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 1601 | 1588 | } |
| 1602 | 1589 | } else { |
| 1603 | 1590 | return self.fail("TODO binary operations on int with bits > 64", .{}); |
| ... | ... | @@ -1614,7 +1601,13 @@ fn binOp( |
| 1614 | 1601 | assert(lhs != .immediate); // should have been handled by Sema |
| 1615 | 1602 | assert(rhs != .immediate); // should have been handled by Sema |
| 1616 | 1603 | |
| 1617 | | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 1604 | const mir_tag_register: Mir.Inst.Tag = switch (tag) { |
| 1605 | .bool_and => .and_shifted_register, |
| 1606 | .bool_or => .orr_shifted_register, |
| 1607 | else => unreachable, |
| 1608 | }; |
| 1609 | |
| 1610 | return try self.binOpRegister(mir_tag_register, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 1618 | 1611 | }, |
| 1619 | 1612 | else => unreachable, |
| 1620 | 1613 | } |
| ... | ... | @@ -1632,9 +1625,9 @@ fn binOp( |
| 1632 | 1625 | const elem_size = elem_ty.abiSize(self.target.*); |
| 1633 | 1626 | |
| 1634 | 1627 | if (elem_size == 1) { |
| 1635 | | const base_tag: Air.Inst.Tag = switch (tag) { |
| 1636 | | .ptr_add => .add, |
| 1637 | | .ptr_sub => .sub, |
| 1628 | const base_tag: Mir.Inst.Tag = switch (tag) { |
| 1629 | .ptr_add => .add_shifted_register, |
| 1630 | .ptr_sub => .sub_shifted_register, |
| 1638 | 1631 | else => unreachable, |
| 1639 | 1632 | }; |
| 1640 | 1633 | |