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