xref: /openbsd-src/gnu/llvm/llvm/lib/Target/Mips/MipsLoongson2FBTBFix.cpp (revision e73ff4e669dda94395f3f3df1c98f51838c775d0)
1 //===- MipsLoongson2FBTBFix.cpp -------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "Mips.h"
10 #include "MipsTargetMachine.h"
11 #include "llvm/CodeGen/MachineFunctionPass.h"
12 #include "llvm/CodeGen/Passes.h"
13 
14 using namespace llvm;
15 
16 namespace {
17 
18 class MipsLoongson2FBTBFix : public MachineFunctionPass {
19 public:
20   static char ID;
21 
MipsLoongson2FBTBFix()22   MipsLoongson2FBTBFix() : MachineFunctionPass(ID) {
23     initializeMipsLoongson2FBTBFixPass(*PassRegistry::getPassRegistry());
24   }
25 
26   bool runOnMachineFunction(MachineFunction &MF) override;
27 
getPassName() const28   StringRef getPassName() const override {
29     return "Loongson 2F BTB erratum workaround pass";
30   }
31 
32 private:
33   bool runOnBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB);
34 };
35 
36 } // end of anonymous namespace
37 
38 char MipsLoongson2FBTBFix::ID = 0;
39 
40 INITIALIZE_PASS(MipsLoongson2FBTBFix, "loongson2f-btb-fix-pass",
41                 "Mips Loongson 2F BTB erratum workaround", false, false)
42 
createMipsLoongson2FBTBFix()43 FunctionPass *llvm::createMipsLoongson2FBTBFix() {
44   return new MipsLoongson2FBTBFix();
45 }
46 
runOnMachineFunction(MachineFunction & MF)47 bool MipsLoongson2FBTBFix::runOnMachineFunction(MachineFunction &MF) {
48   bool Changed = false;
49 
50   for (auto &MBB : MF) {
51     Changed |= runOnBasicBlock(MF, MBB);
52   }
53   return Changed;
54 }
55 
runOnBasicBlock(MachineFunction & MF,MachineBasicBlock & MBB)56 bool MipsLoongson2FBTBFix::runOnBasicBlock(
57     MachineFunction &MF, MachineBasicBlock &MBB) {
58   MachineRegisterInfo &MRI = MF.getRegInfo();
59   const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
60   bool Changed = false;
61 
62   for (auto &MI : MBB) {
63     if (!MI.isCall() && !MI.isIndirectBranch() && !MI.isReturn())
64       continue;
65 
66     // Skip calls that are not through a register.
67     if (MI.isCall()) {
68       if (MI.getNumOperands() == 0)
69         continue;
70       const MachineOperand &MO = MI.getOperand(0);
71       if (!MO.isReg())
72         continue;
73     }
74 
75     Changed = true;
76 
77     DebugLoc MBBDL = MI.getDebugLoc();
78     Register TempReg = MRI.createVirtualRegister(&Mips::GPR64RegClass);
79 
80     // li $TempReg, COP_0_BTB_CLEAR | COP_0_RAS_DISABLE
81     BuildMI(MBB, MI, MBBDL, TII->get(Mips::ORi), TempReg)
82         .addReg(Mips::ZERO)
83         .addImm(3);
84     // dmtc0 $TempReg, COP_0_DIAG
85     BuildMI(MBB, MI, MBBDL, TII->get(Mips::DMTC0))
86         .addReg(Mips::COP022)
87         .addReg(TempReg)
88         .addImm(0);
89   }
90   return Changed;
91 }
92