blob: c53e2f81efcf07b524352e896aa2d22cf5c43d99 [file] [log] [blame]
Chris Lattnere6c561b2009-06-23 18:41:30 +00001//===- 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"
17using namespace llvm;
18
19/// X86Operand - Instances of this class represent one X86 machine instruction.
20struct 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 {
Daniel Dunbar4967dbd2009-06-30 23:02:44 +000033 MCValue Val;
Chris Lattnere6c561b2009-06-23 18:41:30 +000034 } Imm;
35
36 struct {
37 unsigned SegReg;
Daniel Dunbar4967dbd2009-06-30 23:02:44 +000038 MCValue Disp;
Chris Lattnere6c561b2009-06-23 18:41:30 +000039 unsigned BaseReg;
Daniel Dunbar3aafe4d2009-07-02 00:51:52 +000040 unsigned IndexReg;
Chris Lattnere6c561b2009-06-23 18:41:30 +000041 unsigned Scale;
Chris Lattnere6c561b2009-06-23 18:41:30 +000042 } Mem;
43 };
44
45 static X86Operand CreateReg(unsigned RegNo) {
46 X86Operand Res;
47 Res.Kind = Register;
48 Res.Reg.RegNo = RegNo;
49 return Res;
50 }
Daniel Dunbar4967dbd2009-06-30 23:02:44 +000051 static X86Operand CreateImm(MCValue Val) {
Chris Lattnere6c561b2009-06-23 18:41:30 +000052 X86Operand Res;
53 Res.Kind = Immediate;
54 Res.Imm.Val = Val;
55 return Res;
56 }
Daniel Dunbar4967dbd2009-06-30 23:02:44 +000057 static X86Operand CreateMem(unsigned SegReg, MCValue Disp, unsigned BaseReg,
Daniel Dunbar3aafe4d2009-07-02 00:51:52 +000058 unsigned IndexReg, unsigned Scale) {
Chris Lattnere6c561b2009-06-23 18:41:30 +000059 X86Operand Res;
60 Res.Kind = Memory;
61 Res.Mem.SegReg = SegReg;
62 Res.Mem.Disp = Disp;
63 Res.Mem.BaseReg = BaseReg;
Daniel Dunbar3aafe4d2009-07-02 00:51:52 +000064 Res.Mem.IndexReg = IndexReg;
Chris Lattnere6c561b2009-06-23 18:41:30 +000065 Res.Mem.Scale = Scale;
Chris Lattnere6c561b2009-06-23 18:41:30 +000066 return Res;
67 }
Chris Lattnere6c561b2009-06-23 18:41:30 +000068};
69
70bool AsmParser::ParseX86Operand(X86Operand &Op) {
71 switch (Lexer.getKind()) {
72 default:
73 return ParseX86MemOperand(Op);
74 case asmtok::Register:
75 // FIXME: Decode reg #.
76 // FIXME: if a segment register, this could either be just the seg reg, or
77 // the start of a memory operand.
78 Op = X86Operand::CreateReg(123);
79 Lexer.Lex(); // Eat register.
80 return false;
81 case asmtok::Dollar: {
82 // $42 -> immediate.
83 Lexer.Lex();
Daniel Dunbar4967dbd2009-06-30 23:02:44 +000084 MCValue Val;
85 if (ParseRelocatableExpression(Val))
86 return true;
87 Op = X86Operand::CreateImm(Val);
Chris Lattnere6c561b2009-06-23 18:41:30 +000088 return false;
Daniel Dunbar4967dbd2009-06-30 23:02:44 +000089 }
90 case asmtok::Star: {
Chris Lattnere6c561b2009-06-23 18:41:30 +000091 Lexer.Lex(); // Eat the star.
92
93 if (Lexer.is(asmtok::Register)) {
94 Op = X86Operand::CreateReg(123);
95 Lexer.Lex(); // Eat register.
96 } else if (ParseX86MemOperand(Op))
97 return true;
98
99 // FIXME: Note that these are 'dereferenced' so that clients know the '*' is
100 // there.
101 return false;
102 }
103 }
104}
105
106/// ParseX86MemOperand: segment: disp(basereg, indexreg, scale)
107bool AsmParser::ParseX86MemOperand(X86Operand &Op) {
108 // FIXME: If SegReg ':' (e.g. %gs:), eat and remember.
109 unsigned SegReg = 0;
110
111 // We have to disambiguate a parenthesized expression "(4+5)" from the start
112 // of a memory operand with a missing displacement "(%ebx)" or "(,%eax)". The
113 // only way to do this without lookahead is to eat the ( and see what is after
114 // it.
Daniel Dunbar4967dbd2009-06-30 23:02:44 +0000115 MCValue Disp = MCValue::get(0, 0, 0);
Chris Lattnere6c561b2009-06-23 18:41:30 +0000116 if (Lexer.isNot(asmtok::LParen)) {
Daniel Dunbar4967dbd2009-06-30 23:02:44 +0000117 if (ParseRelocatableExpression(Disp)) return true;
Chris Lattnere6c561b2009-06-23 18:41:30 +0000118
119 // After parsing the base expression we could either have a parenthesized
120 // memory address or not. If not, return now. If so, eat the (.
121 if (Lexer.isNot(asmtok::LParen)) {
122 Op = X86Operand::CreateMem(SegReg, Disp, 0, 0, 0);
123 return false;
124 }
125
126 // Eat the '('.
127 Lexer.Lex();
128 } else {
129 // Okay, we have a '('. We don't know if this is an expression or not, but
130 // so we have to eat the ( to see beyond it.
131 Lexer.Lex(); // Eat the '('.
132
133 if (Lexer.is(asmtok::Register) || Lexer.is(asmtok::Comma)) {
134 // Nothing to do here, fall into the code below with the '(' part of the
135 // memory operand consumed.
136 } else {
137 // It must be an parenthesized expression, parse it now.
Daniel Dunbar4967dbd2009-06-30 23:02:44 +0000138 if (ParseRelocatableExpression(Disp))
Chris Lattnere6c561b2009-06-23 18:41:30 +0000139 return true;
140
141 // After parsing the base expression we could either have a parenthesized
142 // memory address or not. If not, return now. If so, eat the (.
143 if (Lexer.isNot(asmtok::LParen)) {
144 Op = X86Operand::CreateMem(SegReg, Disp, 0, 0, 0);
145 return false;
146 }
147
148 // Eat the '('.
149 Lexer.Lex();
150 }
151 }
152
153 // If we reached here, then we just ate the ( of the memory operand. Process
154 // the rest of the memory operand.
Daniel Dunbar3aafe4d2009-07-02 00:51:52 +0000155 unsigned BaseReg = 0, IndexReg = 0, Scale = 0;
Chris Lattnere6c561b2009-06-23 18:41:30 +0000156
157 if (Lexer.is(asmtok::Register)) {
158 BaseReg = 123; // FIXME: decode reg #
159 Lexer.Lex(); // eat the register.
160 }
161
162 if (Lexer.is(asmtok::Comma)) {
163 Lexer.Lex(); // eat the comma.
164
165 if (Lexer.is(asmtok::Register)) {
Daniel Dunbar3aafe4d2009-07-02 00:51:52 +0000166 IndexReg = 123; // FIXME: decode reg #
Chris Lattnere6c561b2009-06-23 18:41:30 +0000167 Lexer.Lex(); // eat the register.
168 Scale = 1; // If not specified, the scale defaults to 1.
169 }
170
171 if (Lexer.is(asmtok::Comma)) {
172 Lexer.Lex(); // eat the comma.
173
174 // If present, get and validate scale amount.
175 if (Lexer.is(asmtok::IntVal)) {
176 int64_t ScaleVal = Lexer.getCurIntVal();
177 if (ScaleVal != 1 && ScaleVal != 2 && ScaleVal != 4 && ScaleVal != 8)
178 return TokError("scale factor in address must be 1, 2, 4 or 8");
179 Lexer.Lex(); // eat the scale.
180 Scale = (unsigned)ScaleVal;
181 }
182 }
183 }
184
185 // Ok, we've eaten the memory operand, verify we have a ')' and eat it too.
186 if (Lexer.isNot(asmtok::RParen))
187 return TokError("unexpected token in memory operand");
188 Lexer.Lex(); // Eat the ')'.
189
Daniel Dunbar3aafe4d2009-07-02 00:51:52 +0000190 Op = X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale);
Chris Lattnere6c561b2009-06-23 18:41:30 +0000191 return false;
192}
193
Daniel Dunbard1d1e832009-06-30 23:38:38 +0000194/// MatchX86Inst - Convert a parsed instruction name and operand list into a
195/// concrete instruction.
196static bool MatchX86Inst(const char *Name,
197 llvm::SmallVector<AsmParser::X86Operand, 3> &Operands,
198 MCInst &Inst) {
199 return false;
200}
201
Chris Lattnere6c561b2009-06-23 18:41:30 +0000202/// ParseX86InstOperands - Parse the operands of an X86 instruction and return
203/// them as the operands of an MCInst.
Daniel Dunbard1d1e832009-06-30 23:38:38 +0000204bool AsmParser::ParseX86InstOperands(const char *InstName, MCInst &Inst) {
205 llvm::SmallVector<X86Operand, 3> Operands;
Chris Lattnere6c561b2009-06-23 18:41:30 +0000206
Daniel Dunbard1d1e832009-06-30 23:38:38 +0000207 if (Lexer.isNot(asmtok::EndOfStatement)) {
208 // Read the first operand.
209 Operands.push_back(X86Operand());
210 if (ParseX86Operand(Operands.back()))
Chris Lattnere6c561b2009-06-23 18:41:30 +0000211 return true;
Daniel Dunbard1d1e832009-06-30 23:38:38 +0000212
213 while (Lexer.is(asmtok::Comma)) {
214 Lexer.Lex(); // Eat the comma.
215
216 // Parse and remember the operand.
217 Operands.push_back(X86Operand());
218 if (ParseX86Operand(Operands.back()))
219 return true;
220 }
Chris Lattnere6c561b2009-06-23 18:41:30 +0000221 }
Daniel Dunbard1d1e832009-06-30 23:38:38 +0000222
223 return MatchX86Inst(InstName, Operands, Inst);
Chris Lattnere6c561b2009-06-23 18:41:30 +0000224}