mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-31 08:16:47 +00:00 
			
		
		
		
	git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@73982 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			223 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			223 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //===- MC-X86Specific.cpp - X86-Specific code for MC ----------------------===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| //
 | |
| // This file implements X86-specific parsing, encoding and decoding stuff for
 | |
| // MC.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "AsmParser.h"
 | |
| #include "llvm/MC/MCInst.h"
 | |
| using namespace llvm;
 | |
| 
 | |
| /// X86Operand - Instances of this class represent one X86 machine instruction.
 | |
| struct AsmParser::X86Operand {
 | |
|   enum {
 | |
|     Register,
 | |
|     Immediate,
 | |
|     Memory
 | |
|   } Kind;
 | |
|   
 | |
|   union {
 | |
|     struct {
 | |
|       unsigned RegNo;
 | |
|     } Reg;
 | |
| 
 | |
|     struct {
 | |
|       // FIXME: Should be a general expression.
 | |
|       int64_t Val;
 | |
|     } Imm;
 | |
|     
 | |
|     struct {
 | |
|       unsigned SegReg;
 | |
|       int64_t Disp;     // FIXME: Should be a general expression.
 | |
|       unsigned BaseReg;
 | |
|       unsigned Scale;
 | |
|       unsigned ScaleReg;
 | |
|     } Mem;
 | |
|   };
 | |
|   
 | |
|   static X86Operand CreateReg(unsigned RegNo) {
 | |
|     X86Operand Res;
 | |
|     Res.Kind = Register;
 | |
|     Res.Reg.RegNo = RegNo;
 | |
|     return Res;
 | |
|   }
 | |
|   static X86Operand CreateImm(int64_t Val) {
 | |
|     X86Operand Res;
 | |
|     Res.Kind = Immediate;
 | |
|     Res.Imm.Val = Val;
 | |
|     return Res;
 | |
|   }
 | |
|   static X86Operand CreateMem(unsigned SegReg, int64_t Disp, unsigned BaseReg,
 | |
|                               unsigned Scale, unsigned ScaleReg) {
 | |
|     X86Operand Res;
 | |
|     Res.Kind = Memory;
 | |
|     Res.Mem.SegReg   = SegReg;
 | |
|     Res.Mem.Disp     = Disp;
 | |
|     Res.Mem.BaseReg  = BaseReg;
 | |
|     Res.Mem.Scale    = Scale;
 | |
|     Res.Mem.ScaleReg = ScaleReg;
 | |
|     return Res;
 | |
|   }
 | |
|   
 | |
|   void AddToMCInst(MCInst &I) {
 | |
|     // FIXME: Add in x86 order here.
 | |
|   }
 | |
| };
 | |
| 
 | |
| bool AsmParser::ParseX86Operand(X86Operand &Op) {
 | |
|   switch (Lexer.getKind()) {
 | |
|   default:
 | |
|     return ParseX86MemOperand(Op);
 | |
|   case asmtok::Register:
 | |
|     // FIXME: Decode reg #.
 | |
|     // FIXME: if a segment register, this could either be just the seg reg, or
 | |
|     // the start of a memory operand.
 | |
|     Op = X86Operand::CreateReg(123);
 | |
|     Lexer.Lex(); // Eat register.
 | |
|     return false;
 | |
|   case asmtok::Dollar: {
 | |
|     // $42 -> immediate.
 | |
|     Lexer.Lex();
 | |
|     int64_t Val;
 | |
|     if (ParseExpression(Val))
 | |
|       return TokError("expected integer constant");
 | |
|     Op = X86Operand::CreateReg(Val);
 | |
|     return false;
 | |
|   case asmtok::Star:
 | |
|     Lexer.Lex(); // Eat the star.
 | |
|     
 | |
|     if (Lexer.is(asmtok::Register)) {
 | |
|       Op = X86Operand::CreateReg(123);
 | |
|       Lexer.Lex(); // Eat register.
 | |
|     } else if (ParseX86MemOperand(Op))
 | |
|       return true;
 | |
| 
 | |
|     // FIXME: Note that these are 'dereferenced' so that clients know the '*' is
 | |
|     // there.
 | |
|     return false;
 | |
|   }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /// ParseX86MemOperand: segment: disp(basereg, indexreg, scale)
 | |
| bool AsmParser::ParseX86MemOperand(X86Operand &Op) {
 | |
|   // FIXME: If SegReg ':'  (e.g. %gs:), eat and remember.
 | |
|   unsigned SegReg = 0;
 | |
|   
 | |
|   // We have to disambiguate a parenthesized expression "(4+5)" from the start
 | |
|   // of a memory operand with a missing displacement "(%ebx)" or "(,%eax)".  The
 | |
|   // only way to do this without lookahead is to eat the ( and see what is after
 | |
|   // it.
 | |
|   int64_t Disp = 0;
 | |
|   if (Lexer.isNot(asmtok::LParen)) {
 | |
|     if (ParseExpression(Disp)) return true;
 | |
|     
 | |
|     // After parsing the base expression we could either have a parenthesized
 | |
|     // memory address or not.  If not, return now.  If so, eat the (.
 | |
|     if (Lexer.isNot(asmtok::LParen)) {
 | |
|       Op = X86Operand::CreateMem(SegReg, Disp, 0, 0, 0);
 | |
|       return false;
 | |
|     }
 | |
|     
 | |
|     // Eat the '('.
 | |
|     Lexer.Lex();
 | |
|   } else {
 | |
|     // Okay, we have a '('.  We don't know if this is an expression or not, but
 | |
|     // so we have to eat the ( to see beyond it.
 | |
|     Lexer.Lex(); // Eat the '('.
 | |
|     
 | |
|     if (Lexer.is(asmtok::Register) || Lexer.is(asmtok::Comma)) {
 | |
|       // Nothing to do here, fall into the code below with the '(' part of the
 | |
|       // memory operand consumed.
 | |
|     } else {
 | |
|       // It must be an parenthesized expression, parse it now.
 | |
|       if (ParseParenExpr(Disp) ||
 | |
|           ParseBinOpRHS(1, Disp))
 | |
|         return true;
 | |
|       
 | |
|       // After parsing the base expression we could either have a parenthesized
 | |
|       // memory address or not.  If not, return now.  If so, eat the (.
 | |
|       if (Lexer.isNot(asmtok::LParen)) {
 | |
|         Op = X86Operand::CreateMem(SegReg, Disp, 0, 0, 0);
 | |
|         return false;
 | |
|       }
 | |
|       
 | |
|       // Eat the '('.
 | |
|       Lexer.Lex();
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   // If we reached here, then we just ate the ( of the memory operand.  Process
 | |
|   // the rest of the memory operand.
 | |
|   unsigned BaseReg = 0, ScaleReg = 0, Scale = 0;
 | |
|   
 | |
|   if (Lexer.is(asmtok::Register)) {
 | |
|     BaseReg = 123; // FIXME: decode reg #
 | |
|     Lexer.Lex();  // eat the register.
 | |
|   }
 | |
|   
 | |
|   if (Lexer.is(asmtok::Comma)) {
 | |
|     Lexer.Lex(); // eat the comma.
 | |
|     
 | |
|     if (Lexer.is(asmtok::Register)) {
 | |
|       ScaleReg = 123; // FIXME: decode reg #
 | |
|       Lexer.Lex();  // eat the register.
 | |
|       Scale = 1;      // If not specified, the scale defaults to 1.
 | |
|     }
 | |
|     
 | |
|     if (Lexer.is(asmtok::Comma)) {
 | |
|       Lexer.Lex(); // eat the comma.
 | |
| 
 | |
|       // If present, get and validate scale amount.
 | |
|       if (Lexer.is(asmtok::IntVal)) {
 | |
|         int64_t ScaleVal = Lexer.getCurIntVal();
 | |
|         if (ScaleVal != 1 && ScaleVal != 2 && ScaleVal != 4 && ScaleVal != 8)
 | |
|           return TokError("scale factor in address must be 1, 2, 4 or 8");
 | |
|         Lexer.Lex();  // eat the scale.
 | |
|         Scale = (unsigned)ScaleVal;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   // Ok, we've eaten the memory operand, verify we have a ')' and eat it too.
 | |
|   if (Lexer.isNot(asmtok::RParen))
 | |
|     return TokError("unexpected token in memory operand");
 | |
|   Lexer.Lex(); // Eat the ')'.
 | |
|   
 | |
|   Op = X86Operand::CreateMem(SegReg, Disp, BaseReg, Scale, ScaleReg);
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| /// ParseX86InstOperands - Parse the operands of an X86 instruction and return
 | |
| /// them as the operands of an MCInst.
 | |
| bool AsmParser::ParseX86InstOperands(MCInst &Inst) {
 | |
|   // If no operands are present, just return.
 | |
|   if (Lexer.is(asmtok::EndOfStatement))
 | |
|     return false;
 | |
| 
 | |
|   // Read the first operand.
 | |
|   X86Operand Op;
 | |
|   if (ParseX86Operand(Op))
 | |
|     return true;
 | |
|   Op.AddToMCInst(Inst);
 | |
|   
 | |
|   while (Lexer.is(asmtok::Comma)) {
 | |
|     Lexer.Lex();  // Eat the comma.
 | |
|     
 | |
|     // Parse and remember the operand.
 | |
|     Op = X86Operand();
 | |
|     if (ParseX86Operand(Op))
 | |
|       return true;
 | |
|     Op.AddToMCInst(Inst);
 | |
|   }
 | |
|   return false;
 | |
| }
 |