|
24 | 24 | #include "AllocaInst.h" |
25 | 25 | #include "BasicBlock.h" |
26 | 26 | #include "BinaryInst.h" |
| 27 | +#include "MulModInst.h" |
27 | 28 | #include "BranchInst.h" |
28 | 29 | #include "CallInst.h" |
29 | 30 | #include "ConstFloat.h" |
@@ -504,6 +505,7 @@ InstSelectorRiscV64::InstSelectorRiscV64( |
504 | 505 | translatorHandlers[IRInstOperator::IRINST_OP_MUL_I] = &InstSelectorRiscV64::translate_mul; |
505 | 506 | translatorHandlers[IRInstOperator::IRINST_OP_DIV_I] = &InstSelectorRiscV64::translate_div; |
506 | 507 | translatorHandlers[IRInstOperator::IRINST_OP_MOD_I] = &InstSelectorRiscV64::translate_mod; |
| 508 | + translatorHandlers[IRInstOperator::IRINST_OP_MULMOD_I] = &InstSelectorRiscV64::translate_mulmod; |
507 | 509 | translatorHandlers[IRInstOperator::IRINST_OP_SHL_I] = &InstSelectorRiscV64::translate_shl; |
508 | 510 | translatorHandlers[IRInstOperator::IRINST_OP_ASHR_I] = &InstSelectorRiscV64::translate_ashr; |
509 | 511 | translatorHandlers[IRInstOperator::IRINST_OP_LSHR_I] = &InstSelectorRiscV64::translate_lshr; |
@@ -1410,6 +1412,51 @@ void InstSelectorRiscV64::translate_mod(Instruction * inst) |
1410 | 1412 | translate_binary(inst, "remw"); |
1411 | 1413 | } |
1412 | 1414 |
|
| 1415 | +/// @brief 翻译宽乘取模指令 (i64)a*b % m |
| 1416 | +/// |
| 1417 | +/// 两个 i32 操作数以有符号扩展形式驻留 64 位寄存器,用 64 位 mul 得到精确的 |
| 1418 | +/// 64 位积(调用点守卫保证 0<=a<m、b>=0,积非负且 < 2^61 不溢出),再对正常量 |
| 1419 | +/// 取有符号 64 位余数。余数落在 [0, m) 内,可直接当作已符号扩展的 i32 使用 |
| 1420 | +void InstSelectorRiscV64::translate_mulmod(Instruction * inst) |
| 1421 | +{ |
| 1422 | + auto * mulmod = dynamic_cast<MulModInst *>(inst); |
| 1423 | + if (mulmod == nullptr) { |
| 1424 | + return; |
| 1425 | + } |
| 1426 | + const int32_t modulus = mulmod->getModulus(); |
| 1427 | + |
| 1428 | + int dstReg = getResultReg(inst); |
| 1429 | + LocalTempManager::Lease dstLease; |
| 1430 | + if (dstReg < 0) { |
| 1431 | + dstLease = tempMgr.borrow(inst); |
| 1432 | + dstReg = dstLease.reg(); |
| 1433 | + } |
| 1434 | + |
| 1435 | + OperandReg lhs = loadOperand(mulmod->getA(), inst, dstReg); |
| 1436 | + const int rhsPreferredReg = lhs.reg != dstReg ? dstReg : -1; |
| 1437 | + OperandReg rhs = loadOperand(mulmod->getB(), inst, rhsPreferredReg < 0 ? dstReg : -1, rhsPreferredReg); |
| 1438 | + |
| 1439 | + // 64 位无截断乘法 |
| 1440 | + iloc.inst("mul", |
| 1441 | + PlatformRiscV64::regName[dstReg], |
| 1442 | + PlatformRiscV64::regName[lhs.reg], |
| 1443 | + PlatformRiscV64::regName[rhs.reg]); |
| 1444 | + |
| 1445 | + releaseOperand(rhs); |
| 1446 | + releaseOperand(lhs); |
| 1447 | + |
| 1448 | + // 对常量取 64 位有符号余数 |
| 1449 | + auto modTmp = tempMgr.borrowExcluding(inst, {dstReg}); |
| 1450 | + iloc.load_imm(modTmp.reg(), modulus); |
| 1451 | + iloc.inst("rem", |
| 1452 | + PlatformRiscV64::regName[dstReg], |
| 1453 | + PlatformRiscV64::regName[dstReg], |
| 1454 | + PlatformRiscV64::regName[modTmp.reg()]); |
| 1455 | + modTmp.release(); |
| 1456 | + |
| 1457 | + storeResult(inst, dstReg, inst); |
| 1458 | +} |
| 1459 | + |
1413 | 1460 | /// @brief 翻译逻辑左移指令(shl) |
1414 | 1461 | void InstSelectorRiscV64::translate_shl(Instruction * inst) |
1415 | 1462 | { |
|
0 commit comments