diff --git a/src/backend/RISCv64/RISCv64ISel.cpp b/src/backend/RISCv64/RISCv64ISel.cpp index 21e8e3c..a92171f 100644 --- a/src/backend/RISCv64/RISCv64ISel.cpp +++ b/src/backend/RISCv64/RISCv64ISel.cpp @@ -745,12 +745,83 @@ void RISCv64ISel::selectNode(DAGNode* node) { CurMBB->addInstruction(std::move(instr)); break; } - case Instruction::kFtoI: { // 浮点 to 整数 (使用硬件指令进行向零截断) - // 直接生成一条带有 rtz 舍入模式的转换指令 - auto instr = std::make_unique(RVOpcodes::FCVT_W_S_RTZ); - instr->addOperand(std::make_unique(dest_vreg)); // 目标是整数vreg - instr->addOperand(std::make_unique(src_vreg)); // 源是浮点vreg - CurMBB->addInstruction(std::move(instr)); + case Instruction::kFtoI: { // 浮点 to 整数 (带向下取整) + // 目标:实现 floor(x) 的效果, C/C++中浮点转整数是截断(truncate) + // 对于正数,floor(x) == truncate(x) + // RISC-V的 fcvt.w.s 默认是“四舍五入到偶数” + // 我们需要手动实现截断逻辑 + // 逻辑: + // temp_i = fcvt.w.s(x) // 四舍五入 + // temp_f = fcvt.s.w(temp_i) // 转回浮点 + // if (x < temp_f) { // 如果原数更小,说明被“五入”了 + // result = temp_i - 1 + // } else { + // result = temp_i + // } + + auto temp_i_vreg = getNewVReg(Type::getIntType()); + auto temp_f_vreg = getNewVReg(Type::getFloatType()); + auto cmp_vreg = getNewVReg(Type::getIntType()); + + // 1. fcvt.w.s temp_i_vreg, src_vreg + auto fcvt_w = std::make_unique(RVOpcodes::FCVT_W_S); + fcvt_w->addOperand(std::make_unique(temp_i_vreg)); + fcvt_w->addOperand(std::make_unique(src_vreg)); + CurMBB->addInstruction(std::move(fcvt_w)); + + // 2. fcvt.s.w temp_f_vreg, temp_i_vreg + auto fcvt_s = std::make_unique(RVOpcodes::FCVT_S_W); + fcvt_s->addOperand(std::make_unique(temp_f_vreg)); + fcvt_s->addOperand(std::make_unique(temp_i_vreg)); + CurMBB->addInstruction(std::move(fcvt_s)); + + // 3. flt.s cmp_vreg, src_vreg, temp_f_vreg + auto flt = std::make_unique(RVOpcodes::FLT_S); + flt->addOperand(std::make_unique(cmp_vreg)); + flt->addOperand(std::make_unique(src_vreg)); + flt->addOperand(std::make_unique(temp_f_vreg)); + CurMBB->addInstruction(std::move(flt)); + + // 创建标签 + int unique_id = this->local_label_counter++; + std::string rounded_up_label = MFunc->getName() + "_ftoi_rounded_up_" + std::to_string(unique_id); + std::string done_label = MFunc->getName() + "_ftoi_done_" + std::to_string(unique_id); + + // 4. bne cmp_vreg, x0, rounded_up_label + auto bne = std::make_unique(RVOpcodes::BNE); + bne->addOperand(std::make_unique(cmp_vreg)); + bne->addOperand(std::make_unique(PhysicalReg::ZERO)); + bne->addOperand(std::make_unique(rounded_up_label)); + CurMBB->addInstruction(std::move(bne)); + + // 5. else 分支: mv dest_vreg, temp_i_vreg + auto mv = std::make_unique(RVOpcodes::MV); + mv->addOperand(std::make_unique(dest_vreg)); + mv->addOperand(std::make_unique(temp_i_vreg)); + CurMBB->addInstruction(std::move(mv)); + + // 6. j done_label + auto j = std::make_unique(RVOpcodes::J); + j->addOperand(std::make_unique(done_label)); + CurMBB->addInstruction(std::move(j)); + + // 7. rounded_up_label: + auto label_up = std::make_unique(RVOpcodes::LABEL); + label_up->addOperand(std::make_unique(rounded_up_label)); + CurMBB->addInstruction(std::move(label_up)); + + // 8. addiw dest_vreg, temp_i_vreg, -1 + auto addi = std::make_unique(RVOpcodes::ADDIW); + addi->addOperand(std::make_unique(dest_vreg)); + addi->addOperand(std::make_unique(temp_i_vreg)); + addi->addOperand(std::make_unique(-1)); + CurMBB->addInstruction(std::move(addi)); + + // 9. done_label: + auto label_done = std::make_unique(RVOpcodes::LABEL); + label_done->addOperand(std::make_unique(done_label)); + CurMBB->addInstruction(std::move(label_done)); + break; } case Instruction::kFNeg: { // 浮点取负