Add new getValueAsBitsInit 'high-level' method
[oota-llvm.git] / utils / TableGen / CodeEmitterGen.cpp
1 //===- CodeEmitterGen.cpp - Code Emitter Generator ------------------------===//
2 //
3 // FIXME: Document.
4 //
5 //===----------------------------------------------------------------------===//
6
7 #include "CodeEmitterGen.h"
8 #include "Record.h"
9 #include "Support/Statistic.h"
10
11 void CodeEmitterGen::run(std::ostream &o) {
12   std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
13
14   std::string Namespace = "V9::";
15   std::string ClassName = "SparcV9CodeEmitter::";
16
17   //const std::string &Namespace = Inst->getValue("Namespace")->getName();
18   o << "unsigned " << ClassName
19     << "getBinaryCodeForInstr(MachineInstr &MI) {\n"
20     << "  unsigned Value = 0;\n"
21     << "  DEBUG(std::cerr << MI);\n"
22     << "  switch (MI.getOpcode()) {\n";
23   for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end();
24        I != E; ++I) {
25     Record *R = *I;
26     o << "    case " << Namespace << R->getName() << ": {\n"
27       << "      DEBUG(std::cerr << \"Emitting " << R->getName() << "\\n\");\n";
28
29     BitsInit *BI = R->getValueAsBitsInit("Inst");
30
31     unsigned Value = 0;
32     const std::vector<RecordVal> &Vals = R->getValues();
33
34     DEBUG(o << "      // prefilling: ");
35     // Start by filling in fixed values...
36     for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) {
37       if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(e-i-1))) {
38         Value |= B->getValue() << (e-i-1);
39         DEBUG(o << B->getValue());
40       } else {
41         DEBUG(o << "0");
42       }
43     }
44     DEBUG(o << "\n");
45
46     DEBUG(o << "      // " << *R->getValue("Inst") << "\n");
47     o << "      Value = " << Value << "U;\n\n";
48     
49     // Loop over all of the fields in the instruction adding in any
50     // contributions to this value (due to bit references).
51     //
52     unsigned op = 0;
53     std::map<const std::string,unsigned> OpOrder;
54     std::map<const std::string,bool> OpContinuous;
55     for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
56       if (Vals[i].getName() != "Inst" && 
57           !Vals[i].getValue()->isComplete() &&
58           /* ignore annul and predict bits since no one sets them yet */
59           Vals[i].getName() != "annul" && 
60           Vals[i].getName() != "predict")
61       {
62         o << "      // op" << op << ": " << Vals[i].getName() << "\n"
63           << "      int64_t op" << op 
64           <<" = getMachineOpValue(MI, MI.getOperand("<<op<<"));\n";
65         //<< "      MachineOperand &op" << op <<" = MI.getOperand("<<op<<");\n";
66         OpOrder[Vals[i].getName()] = op++;
67
68         // Is the operand continuous? If so, we can just mask and OR it in
69         // instead of doing it bit-by-bit, saving a lot in runtime cost.        
70         const BitsInit *InstInit = BI;
71         int beginBitInVar = -1, endBitInVar = -1,
72           beginBitInInst = -1, endBitInInst = -1;
73         bool continuous = true;
74
75         for (int bit = InstInit->getNumBits()-1; bit >= 0; --bit) {
76           if (VarBitInit *VBI =
77               dynamic_cast<VarBitInit*>(InstInit->getBit(bit))) {
78             TypedInit *TI = VBI->getVariable();
79             if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
80               // only process the current variable
81               if (VI->getName() != Vals[i].getName())
82                 continue;
83
84               if (beginBitInVar == -1)
85                 beginBitInVar = VBI->getBitNum();
86
87               if (endBitInVar == -1)
88                 endBitInVar = VBI->getBitNum();
89               else {
90                 if (endBitInVar == (int)VBI->getBitNum() + 1)
91                   endBitInVar = VBI->getBitNum();
92                 else {
93                   continuous = false;
94                   break;
95                 }
96               }
97
98               if (beginBitInInst == -1)
99                 beginBitInInst = bit;
100               if (endBitInInst == -1)
101                 endBitInInst = bit;
102               else {
103                 if (endBitInInst == bit + 1)
104                   endBitInInst = bit;
105                 else {
106                   continuous = false;
107                   break;
108                 }
109               }
110
111               // maintain same distance between bits in field and bits in
112               // instruction. if the relative distances stay the same
113               // throughout,
114               if ((beginBitInVar - (int)VBI->getBitNum()) !=
115                   (beginBitInInst - bit))
116               {
117                 continuous = false;
118                 break;
119               }
120             }
121           }
122         }
123
124         DEBUG(o << "      // Var: begin = " << beginBitInVar 
125                 << ", end = " << endBitInVar
126                 << "; Inst: begin = " << beginBitInInst
127                 << ", end = " << endBitInInst << "\n");
128
129         if (continuous) {
130           DEBUG(o << "      // continuous: op" << OpOrder[Vals[i].getName()]
131                   << "\n");
132           
133           // Mask off the right bits
134           // Low mask (ie. shift, if necessary)
135           if (endBitInVar != 0) {
136             o << "      op" << OpOrder[Vals[i].getName()]
137               << " >>= " << endBitInVar << ";\n";
138             beginBitInVar -= endBitInVar;
139             endBitInVar = 0;
140           }
141
142           // High mask
143           o << "      op" << OpOrder[Vals[i].getName()]
144             << " &= (1<<" << beginBitInVar+1 << ") - 1;\n";
145
146           // Shift the value to the correct place (according to place in instr)
147           if (endBitInInst != 0)
148             o << "      op" << OpOrder[Vals[i].getName()]
149               << " <<= " << endBitInInst << ";\n";
150
151           // Just OR in the result
152           o << "      Value |= op" << OpOrder[Vals[i].getName()] << ";\n";
153         }
154
155         // otherwise, will be taken care of in the loop below using this value:
156         OpContinuous[Vals[i].getName()] = continuous;
157       }
158     }
159
160     for (unsigned f = 0, e = Vals.size(); f != e; ++f) {
161       if (Vals[f].getPrefix()) {
162         BitsInit *FieldInitializer = (BitsInit*)Vals[f].getValue();
163
164         // Scan through the field looking for bit initializers of the current
165         // variable...
166         for (int i = FieldInitializer->getNumBits()-1; i >= 0; --i) {
167           if (BitInit *BI=dynamic_cast<BitInit*>(FieldInitializer->getBit(i)))
168           {
169             DEBUG(o << "      // bit init: f: " << f << ", i: " << i << "\n");
170           } else if (UnsetInit *UI =
171                      dynamic_cast<UnsetInit*>(FieldInitializer->getBit(i))) {
172             DEBUG(o << "      // unset init: f: " << f << ", i: " << i << "\n");
173           } else if (VarBitInit *VBI =
174                      dynamic_cast<VarBitInit*>(FieldInitializer->getBit(i))) {
175             TypedInit *TI = VBI->getVariable();
176             if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
177               // If the bits of the field are laid out consecutively in the
178               // instruction, then instead of separately ORing in bits, just
179               // mask and shift the entire field for efficiency.
180               if (OpContinuous[VI->getName()]) {
181                 // already taken care of in the loop above, thus there is no
182                 // need to individually OR in the bits
183
184                 // for debugging, output the regular version anyway, commented
185                 DEBUG(o << "      // Value |= getValueBit(op"
186                         << OpOrder[VI->getName()] << ", " << VBI->getBitNum()
187                         << ")" << " << " << i << ";\n");
188               } else {
189                 o << "      Value |= getValueBit(op" << OpOrder[VI->getName()]
190                   << ", " << VBI->getBitNum()
191                   << ")" << " << " << i << ";\n";
192               }
193             } else if (FieldInit *FI = dynamic_cast<FieldInit*>(TI)) {
194               // FIXME: implement this!
195               o << "FIELD INIT not implemented yet!\n";
196             } else {
197               o << "Error: UNIMPLEMENTED\n";
198             }
199           }
200         }
201       } else {
202         // ignore annul and predict bits since no one sets them yet
203         if (Vals[f].getName() == "annul" || Vals[f].getName() == "predict") {
204           o << "      // found " << Vals[f].getName() << "\n";
205         }
206       }
207     }
208
209     o << "      break;\n"
210       << "    }\n";
211   }
212
213   o << "  default:\n"
214     << "    DEBUG(std::cerr << \"Not supported instr: \" << MI << \"\\n\");\n"
215     << "    abort();\n"
216     << "  }\n"
217     << "  return Value;\n"
218     << "}\n";
219 }