refactor a bunch of X86 specific stuff out to its own file.
[oota-llvm.git] / tools / llvm-mc / MC-X86Specific.cpp
1 //===- MC-X86Specific.cpp - X86-Specific code for MC ----------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements X86-specific parsing, encoding and decoding stuff for
11 // MC.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "AsmParser.h"
16 #include "llvm/MC/MCInst.h"
17 using namespace llvm;
18
19 /// X86Operand - Instances of this class represent one X86 machine instruction.
20 struct AsmParser::X86Operand {
21   enum {
22     Register,
23     Immediate,
24     Memory
25   } Kind;
26   
27   union {
28     struct {
29       unsigned RegNo;
30     } Reg;
31
32     struct {
33       // FIXME: Should be a general expression.
34       int64_t Val;
35     } Imm;
36     
37     struct {
38       unsigned SegReg;
39       int64_t Disp;     // FIXME: Should be a general expression.
40       unsigned BaseReg;
41       unsigned Scale;
42       unsigned ScaleReg;
43     } Mem;
44   };
45   
46   static X86Operand CreateReg(unsigned RegNo) {
47     X86Operand Res;
48     Res.Kind = Register;
49     Res.Reg.RegNo = RegNo;
50     return Res;
51   }
52   static X86Operand CreateImm(int64_t Val) {
53     X86Operand Res;
54     Res.Kind = Immediate;
55     Res.Imm.Val = Val;
56     return Res;
57   }
58   static X86Operand CreateMem(unsigned SegReg, int64_t Disp, unsigned BaseReg,
59                               unsigned Scale, unsigned ScaleReg) {
60     X86Operand Res;
61     Res.Kind = Memory;
62     Res.Mem.SegReg   = SegReg;
63     Res.Mem.Disp     = Disp;
64     Res.Mem.BaseReg  = BaseReg;
65     Res.Mem.Scale    = Scale;
66     Res.Mem.ScaleReg = ScaleReg;
67     return Res;
68   }
69   
70   void AddToMCInst(MCInst &I) {
71     // FIXME: Add in x86 order here.
72   }
73 };
74
75 bool AsmParser::ParseX86Operand(X86Operand &Op) {
76   switch (Lexer.getKind()) {
77   default:
78     return ParseX86MemOperand(Op);
79   case asmtok::Register:
80     // FIXME: Decode reg #.
81     // FIXME: if a segment register, this could either be just the seg reg, or
82     // the start of a memory operand.
83     Op = X86Operand::CreateReg(123);
84     Lexer.Lex(); // Eat register.
85     return false;
86   case asmtok::Dollar: {
87     // $42 -> immediate.
88     Lexer.Lex();
89     int64_t Val;
90     if (ParseExpression(Val))
91       return TokError("expected integer constant");
92     Op = X86Operand::CreateReg(Val);
93     return false;
94   case asmtok::Star:
95     Lexer.Lex(); // Eat the star.
96     
97     if (Lexer.is(asmtok::Register)) {
98       Op = X86Operand::CreateReg(123);
99       Lexer.Lex(); // Eat register.
100     } else if (ParseX86MemOperand(Op))
101       return true;
102
103     // FIXME: Note that these are 'dereferenced' so that clients know the '*' is
104     // there.
105     return false;
106   }
107   }
108 }
109
110 /// ParseX86MemOperand: segment: disp(basereg, indexreg, scale)
111 bool AsmParser::ParseX86MemOperand(X86Operand &Op) {
112   // FIXME: If SegReg ':'  (e.g. %gs:), eat and remember.
113   unsigned SegReg = 0;
114   
115   // We have to disambiguate a parenthesized expression "(4+5)" from the start
116   // of a memory operand with a missing displacement "(%ebx)" or "(,%eax)".  The
117   // only way to do this without lookahead is to eat the ( and see what is after
118   // it.
119   int64_t Disp = 0;
120   if (Lexer.isNot(asmtok::LParen)) {
121     if (ParseExpression(Disp)) return true;
122     
123     // After parsing the base expression we could either have a parenthesized
124     // memory address or not.  If not, return now.  If so, eat the (.
125     if (Lexer.isNot(asmtok::LParen)) {
126       Op = X86Operand::CreateMem(SegReg, Disp, 0, 0, 0);
127       return false;
128     }
129     
130     // Eat the '('.
131     Lexer.Lex();
132   } else {
133     // Okay, we have a '('.  We don't know if this is an expression or not, but
134     // so we have to eat the ( to see beyond it.
135     Lexer.Lex(); // Eat the '('.
136     
137     if (Lexer.is(asmtok::Register) || Lexer.is(asmtok::Comma)) {
138       // Nothing to do here, fall into the code below with the '(' part of the
139       // memory operand consumed.
140     } else {
141       // It must be an parenthesized expression, parse it now.
142       if (ParseParenExpr(Disp) ||
143           ParseBinOpRHS(1, Disp))
144         return true;
145       
146       // After parsing the base expression we could either have a parenthesized
147       // memory address or not.  If not, return now.  If so, eat the (.
148       if (Lexer.isNot(asmtok::LParen)) {
149         Op = X86Operand::CreateMem(SegReg, Disp, 0, 0, 0);
150         return false;
151       }
152       
153       // Eat the '('.
154       Lexer.Lex();
155     }
156   }
157   
158   // If we reached here, then we just ate the ( of the memory operand.  Process
159   // the rest of the memory operand.
160   unsigned BaseReg = 0, ScaleReg = 0, Scale = 0;
161   
162   if (Lexer.is(asmtok::Register)) {
163     BaseReg = 123; // FIXME: decode reg #
164     Lexer.Lex();  // eat the register.
165   }
166   
167   if (Lexer.is(asmtok::Comma)) {
168     Lexer.Lex(); // eat the comma.
169     
170     if (Lexer.is(asmtok::Register)) {
171       ScaleReg = 123; // FIXME: decode reg #
172       Lexer.Lex();  // eat the register.
173       Scale = 1;      // If not specified, the scale defaults to 1.
174     }
175     
176     if (Lexer.is(asmtok::Comma)) {
177       Lexer.Lex(); // eat the comma.
178
179       // If present, get and validate scale amount.
180       if (Lexer.is(asmtok::IntVal)) {
181         int64_t ScaleVal = Lexer.getCurIntVal();
182         if (ScaleVal != 1 && ScaleVal != 2 && ScaleVal != 4 && ScaleVal != 8)
183           return TokError("scale factor in address must be 1, 2, 4 or 8");
184         Lexer.Lex();  // eat the scale.
185         Scale = (unsigned)ScaleVal;
186       }
187     }
188   }
189   
190   // Ok, we've eaten the memory operand, verify we have a ')' and eat it too.
191   if (Lexer.isNot(asmtok::RParen))
192     return TokError("unexpected token in memory operand");
193   Lexer.Lex(); // Eat the ')'.
194   
195   Op = X86Operand::CreateMem(SegReg, Disp, BaseReg, Scale, ScaleReg);
196   return false;
197 }
198
199 /// ParseX86InstOperands - Parse the operands of an X86 instruction and return
200 /// them as the operands of an MCInst.
201 bool AsmParser::ParseX86InstOperands(MCInst &Inst) {
202   // If no operands are present, just return.
203   if (Lexer.is(asmtok::EndOfStatement))
204     return false;
205
206   // Read the first operand.
207   X86Operand Op;
208   if (ParseX86Operand(Op))
209     return true;
210   Op.AddToMCInst(Inst);
211   
212   while (Lexer.is(asmtok::Comma)) {
213     Lexer.Lex();  // Eat the comma.
214     
215     // Parse and remember the operand.
216     Op = X86Operand();
217     if (ParseX86Operand(Op))
218       return true;
219     Op.AddToMCInst(Inst);
220   }
221   return false;
222 }