2012-02-17 16:55:11 +08:00
|
|
|
//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
|
2012-01-11 11:56:41 +08:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "MCTargetDesc/MipsMCTargetDesc.h"
|
2012-09-06 07:34:03 +08:00
|
|
|
#include "MipsRegisterInfo.h"
|
|
|
|
#include "llvm/ADT/StringSwitch.h"
|
|
|
|
#include "llvm/MC/MCContext.h"
|
|
|
|
#include "llvm/MC/MCExpr.h"
|
|
|
|
#include "llvm/MC/MCInst.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/MC/MCParser/MCAsmLexer.h"
|
|
|
|
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
|
2012-09-06 07:34:03 +08:00
|
|
|
#include "llvm/MC/MCStreamer.h"
|
|
|
|
#include "llvm/MC/MCSubtargetInfo.h"
|
|
|
|
#include "llvm/MC/MCSymbol.h"
|
2012-08-18 04:16:42 +08:00
|
|
|
#include "llvm/MC/MCTargetAsmParser.h"
|
2012-09-06 07:34:03 +08:00
|
|
|
#include "llvm/Support/TargetRegistry.h"
|
2012-01-11 11:56:41 +08:00
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
namespace {
|
2012-10-04 10:29:46 +08:00
|
|
|
class MipsAssemblerOptions {
|
|
|
|
public:
|
|
|
|
MipsAssemblerOptions():
|
|
|
|
aTReg(1), reorder(true), macro(true) {
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned getATRegNum() {return aTReg;}
|
|
|
|
bool setATReg(unsigned Reg);
|
2012-09-06 07:34:03 +08:00
|
|
|
|
2012-10-04 10:29:46 +08:00
|
|
|
bool isReorder() {return reorder;}
|
|
|
|
void setReorder() {reorder = true;}
|
|
|
|
void setNoreorder() {reorder = false;}
|
|
|
|
|
|
|
|
bool isMacro() {return macro;}
|
|
|
|
void setMacro() {macro = true;}
|
|
|
|
void setNomacro() {macro = false;}
|
|
|
|
|
|
|
|
private:
|
|
|
|
unsigned aTReg;
|
|
|
|
bool reorder;
|
|
|
|
bool macro;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace {
|
2012-01-11 11:56:41 +08:00
|
|
|
class MipsAsmParser : public MCTargetAsmParser {
|
2012-08-18 04:16:42 +08:00
|
|
|
|
2012-09-07 08:23:42 +08:00
|
|
|
enum FpFormatTy {
|
|
|
|
FP_FORMAT_NONE = -1,
|
|
|
|
FP_FORMAT_S,
|
|
|
|
FP_FORMAT_D,
|
|
|
|
FP_FORMAT_L,
|
|
|
|
FP_FORMAT_W
|
|
|
|
} FpFormat;
|
|
|
|
|
2012-09-06 07:34:03 +08:00
|
|
|
MCSubtargetInfo &STI;
|
|
|
|
MCAsmParser &Parser;
|
2012-10-06 07:55:28 +08:00
|
|
|
MipsAssemblerOptions Options;
|
2012-10-04 10:29:46 +08:00
|
|
|
|
2012-09-06 07:34:03 +08:00
|
|
|
|
2012-08-18 04:16:42 +08:00
|
|
|
#define GET_ASSEMBLER_HEADER
|
|
|
|
#include "MipsGenAsmMatcher.inc"
|
|
|
|
|
2012-10-13 08:26:04 +08:00
|
|
|
bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
|
2012-01-11 11:56:41 +08:00
|
|
|
SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
2012-10-13 08:26:04 +08:00
|
|
|
MCStreamer &Out, unsigned &ErrorInfo,
|
|
|
|
bool MatchingInlineAsm);
|
2012-01-11 11:56:41 +08:00
|
|
|
|
|
|
|
bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
|
|
|
|
|
2012-10-26 04:41:34 +08:00
|
|
|
bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
|
|
|
|
SMLoc NameLoc,
|
2012-08-18 04:16:42 +08:00
|
|
|
SmallVectorImpl<MCParsedAsmOperand*> &Operands);
|
2012-01-11 11:56:41 +08:00
|
|
|
|
2012-09-07 08:23:42 +08:00
|
|
|
bool parseMathOperation(StringRef Name, SMLoc NameLoc,
|
|
|
|
SmallVectorImpl<MCParsedAsmOperand*> &Operands);
|
|
|
|
|
2012-01-11 11:56:41 +08:00
|
|
|
bool ParseDirective(AsmToken DirectiveID);
|
|
|
|
|
2012-09-06 07:34:03 +08:00
|
|
|
MipsAsmParser::OperandMatchResultTy
|
2013-01-12 09:03:14 +08:00
|
|
|
parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
|
|
|
|
|
|
|
|
MipsAsmParser::OperandMatchResultTy
|
|
|
|
parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
|
|
|
|
|
|
|
|
MipsAsmParser::OperandMatchResultTy
|
|
|
|
parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
|
|
|
|
|
|
|
|
MipsAsmParser::OperandMatchResultTy
|
|
|
|
parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
|
|
|
|
|
|
|
|
MipsAsmParser::OperandMatchResultTy
|
|
|
|
parseHW64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
|
|
|
|
|
|
|
|
MipsAsmParser::OperandMatchResultTy
|
|
|
|
parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
|
2012-09-04 02:47:45 +08:00
|
|
|
|
2012-09-06 07:34:03 +08:00
|
|
|
bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
|
|
|
|
StringRef Mnemonic);
|
|
|
|
|
2013-01-12 09:03:14 +08:00
|
|
|
int tryParseRegister(bool is64BitReg);
|
2012-09-06 07:34:03 +08:00
|
|
|
|
|
|
|
bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
2013-01-12 09:03:14 +08:00
|
|
|
bool is64BitReg);
|
2012-09-06 07:34:03 +08:00
|
|
|
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
bool needsExpansion(MCInst &Inst);
|
|
|
|
|
|
|
|
void expandInstruction(MCInst &Inst, SMLoc IDLoc,
|
2012-10-06 08:53:28 +08:00
|
|
|
SmallVectorImpl<MCInst> &Instructions);
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
|
2012-10-06 08:53:28 +08:00
|
|
|
SmallVectorImpl<MCInst> &Instructions);
|
Initial assembler implementation of Mips load address macro
This patch provides initial implementation of load address
macro instruction for Mips. We have implemented two kinds
of expansions with their variations depending on the size
of immediate operand:
1) load address with immediate value directly:
* la d,j => addiu d,$zero,j (for -32768 <= j <= 65535)
* la d,j => lui d,hi16(j)
ori d,d,lo16(j) (for any other 32 bit value of j)
2) load load address with register offset value
* la d,j(s) => addiu d,s,j (for -32768 <= j <= 65535)
* la d,j(s) => lui d,hi16(j) (for any other 32 bit value of j)
ori d,d,lo16(j)
addu d,d,s
This patch does not cover the case when the address is loaded
from the value of the label or function.
Contributer: Vladimir Medic
llvm-svn: 165561
2012-10-10 07:29:45 +08:00
|
|
|
void expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
|
|
|
|
SmallVectorImpl<MCInst> &Instructions);
|
|
|
|
void expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
|
|
|
|
SmallVectorImpl<MCInst> &Instructions);
|
2012-10-04 10:29:46 +08:00
|
|
|
bool reportParseError(StringRef ErrorMsg);
|
|
|
|
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
bool parseMemOffset(const MCExpr *&Res);
|
2013-01-12 09:03:14 +08:00
|
|
|
bool parseRelocOperand(const MCExpr *&Res);
|
2012-10-04 10:29:46 +08:00
|
|
|
|
|
|
|
bool parseDirectiveSet();
|
|
|
|
|
|
|
|
bool parseSetAtDirective();
|
|
|
|
bool parseSetNoAtDirective();
|
|
|
|
bool parseSetMacroDirective();
|
|
|
|
bool parseSetNoMacroDirective();
|
|
|
|
bool parseSetReorderDirective();
|
|
|
|
bool parseSetNoReorderDirective();
|
|
|
|
|
2013-01-25 09:31:34 +08:00
|
|
|
bool parseDirectiveWord(unsigned Size, SMLoc L);
|
|
|
|
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
|
2012-09-07 08:23:42 +08:00
|
|
|
|
2012-09-06 07:34:03 +08:00
|
|
|
bool isMips64() const {
|
|
|
|
return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
|
|
|
|
}
|
|
|
|
|
2012-09-07 08:23:42 +08:00
|
|
|
bool isFP64() const {
|
|
|
|
return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
|
|
|
|
}
|
|
|
|
|
2013-01-12 09:03:14 +08:00
|
|
|
int matchRegisterName(StringRef Symbol, bool is64BitReg);
|
2012-09-06 07:34:03 +08:00
|
|
|
|
2013-02-21 07:11:17 +08:00
|
|
|
int matchCPURegisterName(StringRef Symbol);
|
|
|
|
|
2013-01-12 09:03:14 +08:00
|
|
|
int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
|
2012-09-06 07:34:03 +08:00
|
|
|
|
2012-09-07 08:23:42 +08:00
|
|
|
void setFpFormat(FpFormatTy Format) {
|
|
|
|
FpFormat = Format;
|
|
|
|
}
|
|
|
|
|
|
|
|
void setDefaultFpFormat();
|
|
|
|
|
|
|
|
void setFpFormat(StringRef Format);
|
|
|
|
|
|
|
|
FpFormatTy getFpFormat() {return FpFormat;}
|
|
|
|
|
|
|
|
bool requestsDoubleOperand(StringRef Mnemonic);
|
|
|
|
|
2012-09-06 07:34:03 +08:00
|
|
|
unsigned getReg(int RC,int RegNo);
|
2012-09-04 02:47:45 +08:00
|
|
|
|
2013-02-21 07:11:17 +08:00
|
|
|
int getATReg();
|
2012-01-11 11:56:41 +08:00
|
|
|
public:
|
|
|
|
MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
|
2012-09-06 07:34:03 +08:00
|
|
|
: MCTargetAsmParser(), STI(sti), Parser(parser) {
|
|
|
|
// Initialize the set of available features.
|
|
|
|
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
|
2012-01-11 11:56:41 +08:00
|
|
|
}
|
|
|
|
|
2012-09-06 07:34:03 +08:00
|
|
|
MCAsmParser &getParser() const { return Parser; }
|
|
|
|
MCAsmLexer &getLexer() const { return Parser.getLexer(); }
|
|
|
|
|
2012-01-11 11:56:41 +08:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2012-08-18 04:16:42 +08:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
/// MipsOperand - Instances of this class represent a parsed Mips machine
|
|
|
|
/// instruction.
|
|
|
|
class MipsOperand : public MCParsedAsmOperand {
|
2012-09-06 07:34:03 +08:00
|
|
|
|
2013-01-12 09:03:14 +08:00
|
|
|
public:
|
|
|
|
enum RegisterKind {
|
|
|
|
Kind_None,
|
|
|
|
Kind_CPURegs,
|
|
|
|
Kind_CPU64Regs,
|
|
|
|
Kind_HWRegs,
|
|
|
|
Kind_HW64Regs,
|
|
|
|
Kind_FGR32Regs,
|
|
|
|
Kind_FGR64Regs,
|
2013-02-21 07:11:17 +08:00
|
|
|
Kind_AFGR64Regs,
|
2013-01-12 09:03:14 +08:00
|
|
|
Kind_CCRRegs
|
|
|
|
};
|
|
|
|
|
|
|
|
private:
|
2012-08-18 04:16:42 +08:00
|
|
|
enum KindTy {
|
|
|
|
k_CondCode,
|
|
|
|
k_CoprocNum,
|
|
|
|
k_Immediate,
|
|
|
|
k_Memory,
|
|
|
|
k_PostIndexRegister,
|
|
|
|
k_Register,
|
|
|
|
k_Token
|
|
|
|
} Kind;
|
|
|
|
|
|
|
|
MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
|
2012-09-06 07:34:03 +08:00
|
|
|
|
2013-03-15 08:42:55 +08:00
|
|
|
struct Token {
|
|
|
|
const char *Data;
|
|
|
|
unsigned Length;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct RegOp {
|
|
|
|
unsigned RegNum;
|
|
|
|
RegisterKind Kind;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ImmOp {
|
|
|
|
const MCExpr *Val;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct MemOp {
|
|
|
|
unsigned Base;
|
|
|
|
const MCExpr *Off;
|
|
|
|
};
|
|
|
|
|
2012-09-06 07:34:03 +08:00
|
|
|
union {
|
2013-03-15 08:42:55 +08:00
|
|
|
struct Token Tok;
|
|
|
|
struct RegOp Reg;
|
|
|
|
struct ImmOp Imm;
|
|
|
|
struct MemOp Mem;
|
2012-09-06 07:34:03 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
SMLoc StartLoc, EndLoc;
|
|
|
|
|
2012-08-18 04:16:42 +08:00
|
|
|
public:
|
|
|
|
void addRegOperands(MCInst &Inst, unsigned N) const {
|
2012-09-06 07:34:03 +08:00
|
|
|
assert(N == 1 && "Invalid number of operands!");
|
|
|
|
Inst.addOperand(MCOperand::CreateReg(getReg()));
|
2012-08-18 04:16:42 +08:00
|
|
|
}
|
2012-09-06 07:34:03 +08:00
|
|
|
|
2012-08-18 04:16:42 +08:00
|
|
|
void addExpr(MCInst &Inst, const MCExpr *Expr) const{
|
2012-09-06 07:34:03 +08:00
|
|
|
// Add as immediate when possible. Null MCExpr = 0.
|
|
|
|
if (Expr == 0)
|
|
|
|
Inst.addOperand(MCOperand::CreateImm(0));
|
|
|
|
else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
|
|
|
|
Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
|
|
|
|
else
|
|
|
|
Inst.addOperand(MCOperand::CreateExpr(Expr));
|
2012-08-18 04:16:42 +08:00
|
|
|
}
|
2012-09-06 07:34:03 +08:00
|
|
|
|
2012-08-18 04:16:42 +08:00
|
|
|
void addImmOperands(MCInst &Inst, unsigned N) const {
|
2012-09-06 07:34:03 +08:00
|
|
|
assert(N == 1 && "Invalid number of operands!");
|
|
|
|
const MCExpr *Expr = getImm();
|
|
|
|
addExpr(Inst,Expr);
|
2012-08-18 04:16:42 +08:00
|
|
|
}
|
2012-09-06 07:34:03 +08:00
|
|
|
|
2012-08-18 04:16:42 +08:00
|
|
|
void addMemOperands(MCInst &Inst, unsigned N) const {
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
assert(N == 2 && "Invalid number of operands!");
|
|
|
|
|
|
|
|
Inst.addOperand(MCOperand::CreateReg(getMemBase()));
|
|
|
|
|
|
|
|
const MCExpr *Expr = getMemOff();
|
|
|
|
addExpr(Inst,Expr);
|
2012-08-18 04:16:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool isReg() const { return Kind == k_Register; }
|
|
|
|
bool isImm() const { return Kind == k_Immediate; }
|
|
|
|
bool isToken() const { return Kind == k_Token; }
|
|
|
|
bool isMem() const { return Kind == k_Memory; }
|
|
|
|
|
|
|
|
StringRef getToken() const {
|
|
|
|
assert(Kind == k_Token && "Invalid access!");
|
2012-09-06 07:34:03 +08:00
|
|
|
return StringRef(Tok.Data, Tok.Length);
|
2012-08-18 04:16:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
unsigned getReg() const {
|
|
|
|
assert((Kind == k_Register) && "Invalid access!");
|
2012-09-06 07:34:03 +08:00
|
|
|
return Reg.RegNum;
|
|
|
|
}
|
|
|
|
|
2013-01-12 09:03:14 +08:00
|
|
|
void setRegKind(RegisterKind RegKind) {
|
|
|
|
assert((Kind == k_Register) && "Invalid access!");
|
|
|
|
Reg.Kind = RegKind;
|
|
|
|
}
|
|
|
|
|
2012-09-06 07:34:03 +08:00
|
|
|
const MCExpr *getImm() const {
|
|
|
|
assert((Kind == k_Immediate) && "Invalid access!");
|
|
|
|
return Imm.Val;
|
|
|
|
}
|
|
|
|
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
unsigned getMemBase() const {
|
|
|
|
assert((Kind == k_Memory) && "Invalid access!");
|
|
|
|
return Mem.Base;
|
|
|
|
}
|
|
|
|
|
|
|
|
const MCExpr *getMemOff() const {
|
|
|
|
assert((Kind == k_Memory) && "Invalid access!");
|
|
|
|
return Mem.Off;
|
|
|
|
}
|
|
|
|
|
2012-09-06 07:34:03 +08:00
|
|
|
static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
|
|
|
|
MipsOperand *Op = new MipsOperand(k_Token);
|
|
|
|
Op->Tok.Data = Str.data();
|
|
|
|
Op->Tok.Length = Str.size();
|
|
|
|
Op->StartLoc = S;
|
|
|
|
Op->EndLoc = S;
|
|
|
|
return Op;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
|
|
|
|
MipsOperand *Op = new MipsOperand(k_Register);
|
|
|
|
Op->Reg.RegNum = RegNum;
|
|
|
|
Op->StartLoc = S;
|
|
|
|
Op->EndLoc = E;
|
|
|
|
return Op;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
|
|
|
|
MipsOperand *Op = new MipsOperand(k_Immediate);
|
|
|
|
Op->Imm.Val = Val;
|
|
|
|
Op->StartLoc = S;
|
|
|
|
Op->EndLoc = E;
|
|
|
|
return Op;
|
2012-08-18 04:16:42 +08:00
|
|
|
}
|
|
|
|
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off,
|
|
|
|
SMLoc S, SMLoc E) {
|
|
|
|
MipsOperand *Op = new MipsOperand(k_Memory);
|
|
|
|
Op->Mem.Base = Base;
|
|
|
|
Op->Mem.Off = Off;
|
|
|
|
Op->StartLoc = S;
|
|
|
|
Op->EndLoc = E;
|
|
|
|
return Op;
|
|
|
|
}
|
|
|
|
|
2013-01-12 09:03:14 +08:00
|
|
|
bool isCPURegsAsm() const {
|
2013-01-12 23:19:10 +08:00
|
|
|
return Kind == k_Register && Reg.Kind == Kind_CPURegs;
|
2013-01-12 09:03:14 +08:00
|
|
|
}
|
|
|
|
void addCPURegsAsmOperands(MCInst &Inst, unsigned N) const {
|
|
|
|
Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isCPU64RegsAsm() const {
|
2013-01-12 23:19:10 +08:00
|
|
|
return Kind == k_Register && Reg.Kind == Kind_CPU64Regs;
|
2013-01-12 09:03:14 +08:00
|
|
|
}
|
|
|
|
void addCPU64RegsAsmOperands(MCInst &Inst, unsigned N) const {
|
|
|
|
Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isHWRegsAsm() const {
|
|
|
|
assert((Kind == k_Register) && "Invalid access!");
|
|
|
|
return Reg.Kind == Kind_HWRegs;
|
|
|
|
}
|
|
|
|
void addHWRegsAsmOperands(MCInst &Inst, unsigned N) const {
|
|
|
|
Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isHW64RegsAsm() const {
|
|
|
|
assert((Kind == k_Register) && "Invalid access!");
|
|
|
|
return Reg.Kind == Kind_HW64Regs;
|
|
|
|
}
|
|
|
|
void addHW64RegsAsmOperands(MCInst &Inst, unsigned N) const {
|
|
|
|
Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
|
|
|
|
}
|
|
|
|
|
|
|
|
void addCCRAsmOperands(MCInst &Inst, unsigned N) const {
|
|
|
|
Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isCCRAsm() const {
|
|
|
|
assert((Kind == k_Register) && "Invalid access!");
|
|
|
|
return Reg.Kind == Kind_CCRRegs;
|
|
|
|
}
|
|
|
|
|
2012-09-06 07:34:03 +08:00
|
|
|
/// getStartLoc - Get the location of the first token of this operand.
|
|
|
|
SMLoc getStartLoc() const { return StartLoc; }
|
|
|
|
/// getEndLoc - Get the location of the last token of this operand.
|
|
|
|
SMLoc getEndLoc() const { return EndLoc; }
|
|
|
|
|
2012-08-18 04:16:42 +08:00
|
|
|
virtual void print(raw_ostream &OS) const {
|
|
|
|
llvm_unreachable("unimplemented!");
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
bool MipsAsmParser::needsExpansion(MCInst &Inst) {
|
|
|
|
|
|
|
|
switch(Inst.getOpcode()) {
|
|
|
|
case Mips::LoadImm32Reg:
|
Initial assembler implementation of Mips load address macro
This patch provides initial implementation of load address
macro instruction for Mips. We have implemented two kinds
of expansions with their variations depending on the size
of immediate operand:
1) load address with immediate value directly:
* la d,j => addiu d,$zero,j (for -32768 <= j <= 65535)
* la d,j => lui d,hi16(j)
ori d,d,lo16(j) (for any other 32 bit value of j)
2) load load address with register offset value
* la d,j(s) => addiu d,s,j (for -32768 <= j <= 65535)
* la d,j(s) => lui d,hi16(j) (for any other 32 bit value of j)
ori d,d,lo16(j)
addu d,d,s
This patch does not cover the case when the address is loaded
from the value of the label or function.
Contributer: Vladimir Medic
llvm-svn: 165561
2012-10-10 07:29:45 +08:00
|
|
|
case Mips::LoadAddr32Imm:
|
|
|
|
case Mips::LoadAddr32Reg:
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2012-10-06 08:53:28 +08:00
|
|
|
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
|
2012-10-06 08:53:28 +08:00
|
|
|
SmallVectorImpl<MCInst> &Instructions){
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
switch(Inst.getOpcode()) {
|
|
|
|
case Mips::LoadImm32Reg:
|
|
|
|
return expandLoadImm(Inst, IDLoc, Instructions);
|
Initial assembler implementation of Mips load address macro
This patch provides initial implementation of load address
macro instruction for Mips. We have implemented two kinds
of expansions with their variations depending on the size
of immediate operand:
1) load address with immediate value directly:
* la d,j => addiu d,$zero,j (for -32768 <= j <= 65535)
* la d,j => lui d,hi16(j)
ori d,d,lo16(j) (for any other 32 bit value of j)
2) load load address with register offset value
* la d,j(s) => addiu d,s,j (for -32768 <= j <= 65535)
* la d,j(s) => lui d,hi16(j) (for any other 32 bit value of j)
ori d,d,lo16(j)
addu d,d,s
This patch does not cover the case when the address is loaded
from the value of the label or function.
Contributer: Vladimir Medic
llvm-svn: 165561
2012-10-10 07:29:45 +08:00
|
|
|
case Mips::LoadAddr32Imm:
|
|
|
|
return expandLoadAddressImm(Inst,IDLoc,Instructions);
|
|
|
|
case Mips::LoadAddr32Reg:
|
|
|
|
return expandLoadAddressReg(Inst,IDLoc,Instructions);
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
}
|
|
|
|
}
|
2012-10-06 08:53:28 +08:00
|
|
|
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
|
Initial assembler implementation of Mips load address macro
This patch provides initial implementation of load address
macro instruction for Mips. We have implemented two kinds
of expansions with their variations depending on the size
of immediate operand:
1) load address with immediate value directly:
* la d,j => addiu d,$zero,j (for -32768 <= j <= 65535)
* la d,j => lui d,hi16(j)
ori d,d,lo16(j) (for any other 32 bit value of j)
2) load load address with register offset value
* la d,j(s) => addiu d,s,j (for -32768 <= j <= 65535)
* la d,j(s) => lui d,hi16(j) (for any other 32 bit value of j)
ori d,d,lo16(j)
addu d,d,s
This patch does not cover the case when the address is loaded
from the value of the label or function.
Contributer: Vladimir Medic
llvm-svn: 165561
2012-10-10 07:29:45 +08:00
|
|
|
SmallVectorImpl<MCInst> &Instructions){
|
2012-10-06 08:53:28 +08:00
|
|
|
MCInst tmpInst;
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
const MCOperand &ImmOp = Inst.getOperand(1);
|
Initial assembler implementation of Mips load address macro
This patch provides initial implementation of load address
macro instruction for Mips. We have implemented two kinds
of expansions with their variations depending on the size
of immediate operand:
1) load address with immediate value directly:
* la d,j => addiu d,$zero,j (for -32768 <= j <= 65535)
* la d,j => lui d,hi16(j)
ori d,d,lo16(j) (for any other 32 bit value of j)
2) load load address with register offset value
* la d,j(s) => addiu d,s,j (for -32768 <= j <= 65535)
* la d,j(s) => lui d,hi16(j) (for any other 32 bit value of j)
ori d,d,lo16(j)
addu d,d,s
This patch does not cover the case when the address is loaded
from the value of the label or function.
Contributer: Vladimir Medic
llvm-svn: 165561
2012-10-10 07:29:45 +08:00
|
|
|
assert(ImmOp.isImm() && "expected immediate operand kind");
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
const MCOperand &RegOp = Inst.getOperand(0);
|
|
|
|
assert(RegOp.isReg() && "expected register operand kind");
|
|
|
|
|
|
|
|
int ImmValue = ImmOp.getImm();
|
2012-10-06 08:53:28 +08:00
|
|
|
tmpInst.setLoc(IDLoc);
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
if ( 0 <= ImmValue && ImmValue <= 65535) {
|
2012-10-06 08:53:28 +08:00
|
|
|
// for 0 <= j <= 65535.
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
// li d,j => ori d,$zero,j
|
2013-01-12 09:03:14 +08:00
|
|
|
tmpInst.setOpcode(Mips::ORi);
|
2012-10-06 08:53:28 +08:00
|
|
|
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
|
|
|
tmpInst.addOperand(
|
2013-01-12 09:03:14 +08:00
|
|
|
MCOperand::CreateReg(Mips::ZERO));
|
2012-10-06 08:53:28 +08:00
|
|
|
tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
Instructions.push_back(tmpInst);
|
|
|
|
} else if ( ImmValue < 0 && ImmValue >= -32768) {
|
2012-10-06 08:53:28 +08:00
|
|
|
// for -32768 <= j < 0.
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
// li d,j => addiu d,$zero,j
|
2013-01-12 09:03:14 +08:00
|
|
|
tmpInst.setOpcode(Mips::ADDiu);
|
2012-10-06 08:53:28 +08:00
|
|
|
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
|
|
|
tmpInst.addOperand(
|
2013-01-12 09:03:14 +08:00
|
|
|
MCOperand::CreateReg(Mips::ZERO));
|
2012-10-06 08:53:28 +08:00
|
|
|
tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
Instructions.push_back(tmpInst);
|
|
|
|
} else {
|
|
|
|
// for any other value of j that is representable as a 32-bit integer.
|
|
|
|
// li d,j => lui d,hi16(j)
|
Initial assembler implementation of Mips load address macro
This patch provides initial implementation of load address
macro instruction for Mips. We have implemented two kinds
of expansions with their variations depending on the size
of immediate operand:
1) load address with immediate value directly:
* la d,j => addiu d,$zero,j (for -32768 <= j <= 65535)
* la d,j => lui d,hi16(j)
ori d,d,lo16(j) (for any other 32 bit value of j)
2) load load address with register offset value
* la d,j(s) => addiu d,s,j (for -32768 <= j <= 65535)
* la d,j(s) => lui d,hi16(j) (for any other 32 bit value of j)
ori d,d,lo16(j)
addu d,d,s
This patch does not cover the case when the address is loaded
from the value of the label or function.
Contributer: Vladimir Medic
llvm-svn: 165561
2012-10-10 07:29:45 +08:00
|
|
|
// ori d,d,lo16(j)
|
2013-01-12 09:03:14 +08:00
|
|
|
tmpInst.setOpcode(Mips::LUi);
|
2012-10-06 08:53:28 +08:00
|
|
|
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
|
|
|
tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
Instructions.push_back(tmpInst);
|
2012-10-06 08:53:28 +08:00
|
|
|
tmpInst.clear();
|
2013-01-12 09:03:14 +08:00
|
|
|
tmpInst.setOpcode(Mips::ORi);
|
2012-10-06 08:53:28 +08:00
|
|
|
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
|
|
|
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
|
|
|
tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
|
|
|
|
tmpInst.setLoc(IDLoc);
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
Instructions.push_back(tmpInst);
|
|
|
|
}
|
|
|
|
}
|
2012-10-06 08:53:28 +08:00
|
|
|
|
Initial assembler implementation of Mips load address macro
This patch provides initial implementation of load address
macro instruction for Mips. We have implemented two kinds
of expansions with their variations depending on the size
of immediate operand:
1) load address with immediate value directly:
* la d,j => addiu d,$zero,j (for -32768 <= j <= 65535)
* la d,j => lui d,hi16(j)
ori d,d,lo16(j) (for any other 32 bit value of j)
2) load load address with register offset value
* la d,j(s) => addiu d,s,j (for -32768 <= j <= 65535)
* la d,j(s) => lui d,hi16(j) (for any other 32 bit value of j)
ori d,d,lo16(j)
addu d,d,s
This patch does not cover the case when the address is loaded
from the value of the label or function.
Contributer: Vladimir Medic
llvm-svn: 165561
2012-10-10 07:29:45 +08:00
|
|
|
void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
|
|
|
|
SmallVectorImpl<MCInst> &Instructions){
|
|
|
|
MCInst tmpInst;
|
|
|
|
const MCOperand &ImmOp = Inst.getOperand(2);
|
|
|
|
assert(ImmOp.isImm() && "expected immediate operand kind");
|
|
|
|
const MCOperand &SrcRegOp = Inst.getOperand(1);
|
|
|
|
assert(SrcRegOp.isReg() && "expected register operand kind");
|
|
|
|
const MCOperand &DstRegOp = Inst.getOperand(0);
|
|
|
|
assert(DstRegOp.isReg() && "expected register operand kind");
|
|
|
|
int ImmValue = ImmOp.getImm();
|
|
|
|
if ( -32768 <= ImmValue && ImmValue <= 65535) {
|
|
|
|
//for -32768 <= j <= 65535.
|
|
|
|
//la d,j(s) => addiu d,s,j
|
2013-01-12 09:03:14 +08:00
|
|
|
tmpInst.setOpcode(Mips::ADDiu);
|
Initial assembler implementation of Mips load address macro
This patch provides initial implementation of load address
macro instruction for Mips. We have implemented two kinds
of expansions with their variations depending on the size
of immediate operand:
1) load address with immediate value directly:
* la d,j => addiu d,$zero,j (for -32768 <= j <= 65535)
* la d,j => lui d,hi16(j)
ori d,d,lo16(j) (for any other 32 bit value of j)
2) load load address with register offset value
* la d,j(s) => addiu d,s,j (for -32768 <= j <= 65535)
* la d,j(s) => lui d,hi16(j) (for any other 32 bit value of j)
ori d,d,lo16(j)
addu d,d,s
This patch does not cover the case when the address is loaded
from the value of the label or function.
Contributer: Vladimir Medic
llvm-svn: 165561
2012-10-10 07:29:45 +08:00
|
|
|
tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
|
|
|
|
tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
|
|
|
|
tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
|
|
|
|
Instructions.push_back(tmpInst);
|
|
|
|
} else {
|
|
|
|
//for any other value of j that is representable as a 32-bit integer.
|
|
|
|
//la d,j(s) => lui d,hi16(j)
|
|
|
|
// ori d,d,lo16(j)
|
|
|
|
// addu d,d,s
|
2013-01-12 09:03:14 +08:00
|
|
|
tmpInst.setOpcode(Mips::LUi);
|
Initial assembler implementation of Mips load address macro
This patch provides initial implementation of load address
macro instruction for Mips. We have implemented two kinds
of expansions with their variations depending on the size
of immediate operand:
1) load address with immediate value directly:
* la d,j => addiu d,$zero,j (for -32768 <= j <= 65535)
* la d,j => lui d,hi16(j)
ori d,d,lo16(j) (for any other 32 bit value of j)
2) load load address with register offset value
* la d,j(s) => addiu d,s,j (for -32768 <= j <= 65535)
* la d,j(s) => lui d,hi16(j) (for any other 32 bit value of j)
ori d,d,lo16(j)
addu d,d,s
This patch does not cover the case when the address is loaded
from the value of the label or function.
Contributer: Vladimir Medic
llvm-svn: 165561
2012-10-10 07:29:45 +08:00
|
|
|
tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
|
|
|
|
tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
|
|
|
|
Instructions.push_back(tmpInst);
|
|
|
|
tmpInst.clear();
|
2013-01-12 09:03:14 +08:00
|
|
|
tmpInst.setOpcode(Mips::ORi);
|
Initial assembler implementation of Mips load address macro
This patch provides initial implementation of load address
macro instruction for Mips. We have implemented two kinds
of expansions with their variations depending on the size
of immediate operand:
1) load address with immediate value directly:
* la d,j => addiu d,$zero,j (for -32768 <= j <= 65535)
* la d,j => lui d,hi16(j)
ori d,d,lo16(j) (for any other 32 bit value of j)
2) load load address with register offset value
* la d,j(s) => addiu d,s,j (for -32768 <= j <= 65535)
* la d,j(s) => lui d,hi16(j) (for any other 32 bit value of j)
ori d,d,lo16(j)
addu d,d,s
This patch does not cover the case when the address is loaded
from the value of the label or function.
Contributer: Vladimir Medic
llvm-svn: 165561
2012-10-10 07:29:45 +08:00
|
|
|
tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
|
|
|
|
tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
|
|
|
|
tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
|
|
|
|
Instructions.push_back(tmpInst);
|
|
|
|
tmpInst.clear();
|
|
|
|
tmpInst.setOpcode(Mips::ADDu);
|
|
|
|
tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
|
|
|
|
tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
|
|
|
|
tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
|
|
|
|
Instructions.push_back(tmpInst);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
|
|
|
|
SmallVectorImpl<MCInst> &Instructions){
|
|
|
|
MCInst tmpInst;
|
|
|
|
const MCOperand &ImmOp = Inst.getOperand(1);
|
|
|
|
assert(ImmOp.isImm() && "expected immediate operand kind");
|
|
|
|
const MCOperand &RegOp = Inst.getOperand(0);
|
|
|
|
assert(RegOp.isReg() && "expected register operand kind");
|
|
|
|
int ImmValue = ImmOp.getImm();
|
|
|
|
if ( -32768 <= ImmValue && ImmValue <= 65535) {
|
|
|
|
//for -32768 <= j <= 65535.
|
|
|
|
//la d,j => addiu d,$zero,j
|
|
|
|
tmpInst.setOpcode(Mips::ADDiu);
|
|
|
|
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
|
|
|
tmpInst.addOperand(
|
2013-01-12 09:03:14 +08:00
|
|
|
MCOperand::CreateReg(Mips::ZERO));
|
Initial assembler implementation of Mips load address macro
This patch provides initial implementation of load address
macro instruction for Mips. We have implemented two kinds
of expansions with their variations depending on the size
of immediate operand:
1) load address with immediate value directly:
* la d,j => addiu d,$zero,j (for -32768 <= j <= 65535)
* la d,j => lui d,hi16(j)
ori d,d,lo16(j) (for any other 32 bit value of j)
2) load load address with register offset value
* la d,j(s) => addiu d,s,j (for -32768 <= j <= 65535)
* la d,j(s) => lui d,hi16(j) (for any other 32 bit value of j)
ori d,d,lo16(j)
addu d,d,s
This patch does not cover the case when the address is loaded
from the value of the label or function.
Contributer: Vladimir Medic
llvm-svn: 165561
2012-10-10 07:29:45 +08:00
|
|
|
tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
|
|
|
|
Instructions.push_back(tmpInst);
|
|
|
|
} else {
|
|
|
|
//for any other value of j that is representable as a 32-bit integer.
|
|
|
|
//la d,j => lui d,hi16(j)
|
|
|
|
// ori d,d,lo16(j)
|
2013-01-12 09:03:14 +08:00
|
|
|
tmpInst.setOpcode(Mips::LUi);
|
Initial assembler implementation of Mips load address macro
This patch provides initial implementation of load address
macro instruction for Mips. We have implemented two kinds
of expansions with their variations depending on the size
of immediate operand:
1) load address with immediate value directly:
* la d,j => addiu d,$zero,j (for -32768 <= j <= 65535)
* la d,j => lui d,hi16(j)
ori d,d,lo16(j) (for any other 32 bit value of j)
2) load load address with register offset value
* la d,j(s) => addiu d,s,j (for -32768 <= j <= 65535)
* la d,j(s) => lui d,hi16(j) (for any other 32 bit value of j)
ori d,d,lo16(j)
addu d,d,s
This patch does not cover the case when the address is loaded
from the value of the label or function.
Contributer: Vladimir Medic
llvm-svn: 165561
2012-10-10 07:29:45 +08:00
|
|
|
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
|
|
|
tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
|
|
|
|
Instructions.push_back(tmpInst);
|
|
|
|
tmpInst.clear();
|
2013-01-12 09:03:14 +08:00
|
|
|
tmpInst.setOpcode(Mips::ORi);
|
Initial assembler implementation of Mips load address macro
This patch provides initial implementation of load address
macro instruction for Mips. We have implemented two kinds
of expansions with their variations depending on the size
of immediate operand:
1) load address with immediate value directly:
* la d,j => addiu d,$zero,j (for -32768 <= j <= 65535)
* la d,j => lui d,hi16(j)
ori d,d,lo16(j) (for any other 32 bit value of j)
2) load load address with register offset value
* la d,j(s) => addiu d,s,j (for -32768 <= j <= 65535)
* la d,j(s) => lui d,hi16(j) (for any other 32 bit value of j)
ori d,d,lo16(j)
addu d,d,s
This patch does not cover the case when the address is loaded
from the value of the label or function.
Contributer: Vladimir Medic
llvm-svn: 165561
2012-10-10 07:29:45 +08:00
|
|
|
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
|
|
|
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
|
|
|
|
tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
|
|
|
|
Instructions.push_back(tmpInst);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-11 11:56:41 +08:00
|
|
|
bool MipsAsmParser::
|
2012-10-13 08:26:04 +08:00
|
|
|
MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
|
2012-01-11 11:56:41 +08:00
|
|
|
SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
2012-10-13 08:26:04 +08:00
|
|
|
MCStreamer &Out, unsigned &ErrorInfo,
|
|
|
|
bool MatchingInlineAsm) {
|
2012-09-06 07:34:03 +08:00
|
|
|
MCInst Inst;
|
2012-10-13 06:53:36 +08:00
|
|
|
unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
|
2012-10-13 08:26:04 +08:00
|
|
|
MatchingInlineAsm);
|
2012-09-06 07:34:03 +08:00
|
|
|
|
|
|
|
switch (MatchResult) {
|
|
|
|
default: break;
|
|
|
|
case Match_Success: {
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
if (needsExpansion(Inst)) {
|
2012-10-06 08:53:28 +08:00
|
|
|
SmallVector<MCInst, 4> Instructions;
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
expandInstruction(Inst, IDLoc, Instructions);
|
|
|
|
for(unsigned i =0; i < Instructions.size(); i++){
|
2012-10-06 08:53:28 +08:00
|
|
|
Out.EmitInstruction(Instructions[i]);
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Inst.setLoc(IDLoc);
|
|
|
|
Out.EmitInstruction(Inst);
|
|
|
|
}
|
2012-09-06 07:34:03 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
case Match_MissingFeature:
|
|
|
|
Error(IDLoc, "instruction requires a CPU feature not currently enabled");
|
|
|
|
return true;
|
|
|
|
case Match_InvalidOperand: {
|
|
|
|
SMLoc ErrorLoc = IDLoc;
|
|
|
|
if (ErrorInfo != ~0U) {
|
|
|
|
if (ErrorInfo >= Operands.size())
|
|
|
|
return Error(IDLoc, "too few operands for instruction");
|
|
|
|
|
|
|
|
ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc();
|
|
|
|
if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Error(ErrorLoc, "invalid operand for instruction");
|
|
|
|
}
|
|
|
|
case Match_MnemonicFail:
|
|
|
|
return Error(IDLoc, "invalid instruction");
|
|
|
|
}
|
2012-01-11 11:56:41 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-02-21 07:11:17 +08:00
|
|
|
int MipsAsmParser::matchCPURegisterName(StringRef Name) {
|
2012-10-10 00:27:43 +08:00
|
|
|
int CC;
|
2013-02-21 07:11:17 +08:00
|
|
|
|
|
|
|
if (Name == "at")
|
|
|
|
return getATReg();
|
|
|
|
|
2012-10-10 00:27:43 +08:00
|
|
|
CC = StringSwitch<unsigned>(Name)
|
2013-02-21 07:11:17 +08:00
|
|
|
.Case("zero", 0)
|
|
|
|
.Case("a0", 4)
|
|
|
|
.Case("a1", 5)
|
|
|
|
.Case("a2", 6)
|
|
|
|
.Case("a3", 7)
|
|
|
|
.Case("v0", 2)
|
|
|
|
.Case("v1", 3)
|
|
|
|
.Case("s0", 16)
|
|
|
|
.Case("s1", 17)
|
|
|
|
.Case("s2", 18)
|
|
|
|
.Case("s3", 19)
|
|
|
|
.Case("s4", 20)
|
|
|
|
.Case("s5", 21)
|
|
|
|
.Case("s6", 22)
|
|
|
|
.Case("s7", 23)
|
|
|
|
.Case("k0", 26)
|
|
|
|
.Case("k1", 27)
|
|
|
|
.Case("sp", 29)
|
|
|
|
.Case("fp", 30)
|
|
|
|
.Case("gp", 28)
|
|
|
|
.Case("ra", 31)
|
|
|
|
.Case("t0", 8)
|
|
|
|
.Case("t1", 9)
|
|
|
|
.Case("t2", 10)
|
|
|
|
.Case("t3", 11)
|
|
|
|
.Case("t4", 12)
|
|
|
|
.Case("t5", 13)
|
|
|
|
.Case("t6", 14)
|
|
|
|
.Case("t7", 15)
|
|
|
|
.Case("t8", 24)
|
|
|
|
.Case("t9", 25)
|
|
|
|
.Default(-1);
|
|
|
|
|
|
|
|
// Although SGI documentation just cut out t0-t3 for n32/n64,
|
|
|
|
// GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
|
|
|
|
// We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
|
|
|
|
if (isMips64() && 8 <= CC && CC <= 11)
|
|
|
|
CC += 4;
|
|
|
|
|
|
|
|
if (CC == -1 && isMips64())
|
2012-10-10 00:27:43 +08:00
|
|
|
CC = StringSwitch<unsigned>(Name)
|
2013-02-21 07:11:17 +08:00
|
|
|
.Case("a4", 8)
|
|
|
|
.Case("a5", 9)
|
|
|
|
.Case("a6", 10)
|
|
|
|
.Case("a7", 11)
|
|
|
|
.Case("kt0", 26)
|
|
|
|
.Case("kt1", 27)
|
|
|
|
.Case("s8", 30)
|
2012-10-10 00:27:43 +08:00
|
|
|
.Default(-1);
|
|
|
|
|
2013-02-21 07:11:17 +08:00
|
|
|
return CC;
|
|
|
|
}
|
|
|
|
int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) {
|
|
|
|
|
|
|
|
int CC;
|
|
|
|
CC = matchCPURegisterName(Name);
|
2012-10-10 00:27:43 +08:00
|
|
|
if (CC != -1)
|
2013-02-21 07:11:17 +08:00
|
|
|
return matchRegisterByNumber(CC,is64BitReg?Mips::CPU64RegsRegClassID:
|
|
|
|
Mips::CPURegsRegClassID);
|
2012-09-06 07:34:03 +08:00
|
|
|
|
2012-09-07 08:23:42 +08:00
|
|
|
if (Name[0] == 'f') {
|
|
|
|
StringRef NumString = Name.substr(1);
|
|
|
|
unsigned IntVal;
|
|
|
|
if( NumString.getAsInteger(10, IntVal))
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
return -1; // not integer
|
2012-09-07 08:23:42 +08:00
|
|
|
if (IntVal > 31)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
FpFormatTy Format = getFpFormat();
|
|
|
|
|
|
|
|
if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
|
|
|
|
return getReg(Mips::FGR32RegClassID, IntVal);
|
|
|
|
if (Format == FP_FORMAT_D) {
|
|
|
|
if(isFP64()) {
|
|
|
|
return getReg(Mips::FGR64RegClassID, IntVal);
|
|
|
|
}
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
// only even numbers available as register pairs
|
2012-09-07 08:23:42 +08:00
|
|
|
if (( IntVal > 31) || (IntVal%2 != 0))
|
|
|
|
return -1;
|
|
|
|
return getReg(Mips::AFGR64RegClassID, IntVal/2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-06 07:34:03 +08:00
|
|
|
return -1;
|
|
|
|
}
|
2012-09-07 08:23:42 +08:00
|
|
|
void MipsAsmParser::setDefaultFpFormat() {
|
|
|
|
|
|
|
|
if (isMips64() || isFP64())
|
|
|
|
FpFormat = FP_FORMAT_D;
|
|
|
|
else
|
|
|
|
FpFormat = FP_FORMAT_S;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
|
|
|
|
|
|
|
|
bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
|
|
|
|
.Case("ldxc1", true)
|
|
|
|
.Case("ldc1", true)
|
|
|
|
.Case("sdxc1", true)
|
|
|
|
.Case("sdc1", true)
|
|
|
|
.Default(false);
|
|
|
|
|
|
|
|
return IsDouble;
|
|
|
|
}
|
|
|
|
void MipsAsmParser::setFpFormat(StringRef Format) {
|
|
|
|
|
|
|
|
FpFormat = StringSwitch<FpFormatTy>(Format.lower())
|
|
|
|
.Case(".s", FP_FORMAT_S)
|
|
|
|
.Case(".d", FP_FORMAT_D)
|
|
|
|
.Case(".l", FP_FORMAT_L)
|
|
|
|
.Case(".w", FP_FORMAT_W)
|
|
|
|
.Default(FP_FORMAT_NONE);
|
|
|
|
}
|
2012-09-06 07:34:03 +08:00
|
|
|
|
2012-10-04 10:29:46 +08:00
|
|
|
bool MipsAssemblerOptions::setATReg(unsigned Reg) {
|
|
|
|
if (Reg > 31)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
aTReg = Reg;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-02-21 07:11:17 +08:00
|
|
|
int MipsAsmParser::getATReg() {
|
|
|
|
return Options.getATRegNum();
|
2012-10-04 10:29:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
unsigned MipsAsmParser::getReg(int RC,int RegNo) {
|
2012-09-06 07:34:03 +08:00
|
|
|
return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
|
|
|
|
}
|
|
|
|
|
2013-01-12 09:03:14 +08:00
|
|
|
int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
|
2012-09-06 07:34:03 +08:00
|
|
|
|
|
|
|
if (RegNum > 31)
|
|
|
|
return -1;
|
|
|
|
|
2013-01-12 09:03:14 +08:00
|
|
|
return getReg(RegClass, RegNum);
|
2012-09-06 07:34:03 +08:00
|
|
|
}
|
|
|
|
|
2013-01-12 09:03:14 +08:00
|
|
|
int MipsAsmParser::tryParseRegister(bool is64BitReg) {
|
2012-09-06 07:34:03 +08:00
|
|
|
const AsmToken &Tok = Parser.getTok();
|
|
|
|
int RegNum = -1;
|
|
|
|
|
|
|
|
if (Tok.is(AsmToken::Identifier)) {
|
|
|
|
std::string lowerCase = Tok.getString().lower();
|
2013-01-12 09:03:14 +08:00
|
|
|
RegNum = matchRegisterName(lowerCase, is64BitReg);
|
2012-09-06 07:34:03 +08:00
|
|
|
} else if (Tok.is(AsmToken::Integer))
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
|
2013-01-12 09:03:14 +08:00
|
|
|
is64BitReg ? Mips::CPU64RegsRegClassID
|
|
|
|
: Mips::CPURegsRegClassID);
|
2012-09-06 07:34:03 +08:00
|
|
|
return RegNum;
|
|
|
|
}
|
|
|
|
|
2012-01-11 11:56:41 +08:00
|
|
|
bool MipsAsmParser::
|
2012-09-06 07:34:03 +08:00
|
|
|
tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
2013-01-12 09:03:14 +08:00
|
|
|
bool is64BitReg){
|
2012-09-06 07:34:03 +08:00
|
|
|
|
|
|
|
SMLoc S = Parser.getTok().getLoc();
|
|
|
|
int RegNo = -1;
|
2012-09-07 08:23:42 +08:00
|
|
|
|
2013-01-12 09:03:14 +08:00
|
|
|
RegNo = tryParseRegister(is64BitReg);
|
2012-09-06 07:34:03 +08:00
|
|
|
if (RegNo == -1)
|
|
|
|
return true;
|
|
|
|
|
2013-01-12 09:03:14 +08:00
|
|
|
Operands.push_back(MipsOperand::CreateReg(RegNo, S,
|
|
|
|
Parser.getTok().getLoc()));
|
2012-09-06 07:34:03 +08:00
|
|
|
Parser.Lex(); // Eat register token.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
|
|
|
|
StringRef Mnemonic) {
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
// Check if the current operand has a custom associated parser, if so, try to
|
|
|
|
// custom parse the operand, or fallback to the general approach.
|
2012-09-06 07:34:03 +08:00
|
|
|
OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
|
|
|
|
if (ResTy == MatchOperand_Success)
|
|
|
|
return false;
|
|
|
|
// If there wasn't a custom match, try the generic matcher below. Otherwise,
|
|
|
|
// there was a match, but an error occurred, in which case, just return that
|
|
|
|
// the operand parsing failed.
|
|
|
|
if (ResTy == MatchOperand_ParseFail)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
switch (getLexer().getKind()) {
|
|
|
|
default:
|
|
|
|
Error(Parser.getTok().getLoc(), "unexpected token in operand");
|
|
|
|
return true;
|
|
|
|
case AsmToken::Dollar: {
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
// parse register
|
2012-09-06 07:34:03 +08:00
|
|
|
SMLoc S = Parser.getTok().getLoc();
|
|
|
|
Parser.Lex(); // Eat dollar token.
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
// parse register operand
|
2013-01-12 09:03:14 +08:00
|
|
|
if (!tryParseRegisterOperand(Operands, isMips64())) {
|
2012-09-06 07:34:03 +08:00
|
|
|
if (getLexer().is(AsmToken::LParen)) {
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
// check if it is indexed addressing operand
|
2012-09-06 07:34:03 +08:00
|
|
|
Operands.push_back(MipsOperand::CreateToken("(", S));
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
Parser.Lex(); // eat parenthesis
|
2012-09-06 07:34:03 +08:00
|
|
|
if (getLexer().isNot(AsmToken::Dollar))
|
|
|
|
return true;
|
|
|
|
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
Parser.Lex(); // eat dollar
|
2013-01-12 09:03:14 +08:00
|
|
|
if (tryParseRegisterOperand(Operands, isMips64()))
|
2012-09-06 07:34:03 +08:00
|
|
|
return true;
|
|
|
|
|
|
|
|
if (!getLexer().is(AsmToken::RParen))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
S = Parser.getTok().getLoc();
|
|
|
|
Operands.push_back(MipsOperand::CreateToken(")", S));
|
|
|
|
Parser.Lex();
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
// maybe it is a symbol reference
|
2012-09-06 07:34:03 +08:00
|
|
|
StringRef Identifier;
|
2013-02-21 06:21:35 +08:00
|
|
|
if (Parser.parseIdentifier(Identifier))
|
2012-09-06 07:34:03 +08:00
|
|
|
return true;
|
|
|
|
|
2013-01-12 09:03:14 +08:00
|
|
|
SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
|
2012-09-06 07:34:03 +08:00
|
|
|
|
2012-09-07 17:47:42 +08:00
|
|
|
MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
|
2012-09-06 07:34:03 +08:00
|
|
|
|
|
|
|
// Otherwise create a symbol ref.
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
|
2012-09-06 07:34:03 +08:00
|
|
|
getContext());
|
|
|
|
|
|
|
|
Operands.push_back(MipsOperand::CreateImm(Res, S, E));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
case AsmToken::Identifier:
|
|
|
|
case AsmToken::LParen:
|
|
|
|
case AsmToken::Minus:
|
|
|
|
case AsmToken::Plus:
|
|
|
|
case AsmToken::Integer:
|
|
|
|
case AsmToken::String: {
|
|
|
|
// quoted label names
|
|
|
|
const MCExpr *IdVal;
|
|
|
|
SMLoc S = Parser.getTok().getLoc();
|
2013-02-21 06:21:35 +08:00
|
|
|
if (getParser().parseExpression(IdVal))
|
2012-09-06 07:34:03 +08:00
|
|
|
return true;
|
2013-01-12 09:03:14 +08:00
|
|
|
SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
|
2012-09-06 07:34:03 +08:00
|
|
|
Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
|
|
|
|
return false;
|
|
|
|
}
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
case AsmToken::Percent: {
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
// it is a symbol reference or constant expression
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
const MCExpr *IdVal;
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
SMLoc S = Parser.getTok().getLoc(); // start location of the operand
|
2013-01-12 09:03:14 +08:00
|
|
|
if (parseRelocOperand(IdVal))
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
return true;
|
|
|
|
|
2013-01-12 09:03:14 +08:00
|
|
|
SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
|
|
|
|
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
|
|
|
|
return false;
|
2012-10-04 10:29:46 +08:00
|
|
|
} // case AsmToken::Percent
|
|
|
|
} // switch(getLexer().getKind())
|
2012-01-11 11:56:41 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-01-12 09:03:14 +08:00
|
|
|
bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
|
2012-10-04 10:29:46 +08:00
|
|
|
Parser.Lex(); // eat % token
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
const AsmToken &Tok = Parser.getTok(); // get next token, operation
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
if (Tok.isNot(AsmToken::Identifier))
|
|
|
|
return true;
|
|
|
|
|
2012-09-07 17:47:42 +08:00
|
|
|
std::string Str = Tok.getIdentifier().str();
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
Parser.Lex(); // eat identifier
|
2012-10-04 10:29:46 +08:00
|
|
|
// now make expression from the rest of the operand
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
const MCExpr *IdVal;
|
2013-01-12 09:03:14 +08:00
|
|
|
SMLoc EndLoc;
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
|
|
|
|
if (getLexer().getKind() == AsmToken::LParen) {
|
|
|
|
while (1) {
|
2012-10-04 10:29:46 +08:00
|
|
|
Parser.Lex(); // eat '(' token
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
if (getLexer().getKind() == AsmToken::Percent) {
|
2012-10-04 10:29:46 +08:00
|
|
|
Parser.Lex(); // eat % token
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
const AsmToken &nextTok = Parser.getTok();
|
|
|
|
if (nextTok.isNot(AsmToken::Identifier))
|
|
|
|
return true;
|
2012-09-07 17:47:42 +08:00
|
|
|
Str += "(%";
|
|
|
|
Str += nextTok.getIdentifier();
|
2012-10-04 10:29:46 +08:00
|
|
|
Parser.Lex(); // eat identifier
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
if (getLexer().getKind() != AsmToken::LParen)
|
|
|
|
return true;
|
|
|
|
} else
|
|
|
|
break;
|
|
|
|
}
|
2013-02-21 06:21:35 +08:00
|
|
|
if (getParser().parseParenExpression(IdVal,EndLoc))
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
return true;
|
|
|
|
|
2013-01-12 09:03:14 +08:00
|
|
|
while (getLexer().getKind() == AsmToken::RParen)
|
2012-10-04 10:29:46 +08:00
|
|
|
Parser.Lex(); // eat ')' token
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
|
|
|
|
} else
|
2012-10-04 10:29:46 +08:00
|
|
|
return true; // parenthesis must follow reloc operand
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
|
2012-10-04 10:29:46 +08:00
|
|
|
// Check the type of the expression
|
2012-09-07 17:47:42 +08:00
|
|
|
if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
|
Implement methods that enable expansion of load immediate
macro instruction (li) in the assembler.
We have identified three possible expansions depending on
the size of immediate operand:
1) for 0 ≤ j ≤ 65535.
li d,j =>
ori d,$zero,j
2) for −32768 ≤ j < 0.
li d,j =>
addiu d,$zero,j
3) for any other value of j that is representable as a 32-bit integer.
li d,j =>
lui d,hi16(j)
ori d,d,lo16(j)
All of the above have been implemented in ths patch.
Contributer: Vladimir Medic
llvm-svn: 165199
2012-10-04 12:03:53 +08:00
|
|
|
// it's a constant, evaluate lo or hi value
|
2012-09-07 17:47:42 +08:00
|
|
|
int Val = MCE->getValue();
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
if (Str == "lo") {
|
|
|
|
Val = Val & 0xffff;
|
|
|
|
} else if (Str == "hi") {
|
2013-02-21 10:09:31 +08:00
|
|
|
int LoSign = Val & 0x8000;
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
Val = (Val & 0xffff0000) >> 16;
|
2013-02-21 10:09:31 +08:00
|
|
|
//lower part is treated as signed int, so if it is negative
|
|
|
|
//we must add 1 to hi part to compensate
|
|
|
|
if (LoSign)
|
|
|
|
Val++;
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
}
|
|
|
|
Res = MCConstantExpr::Create(Val, getContext());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-09-07 17:47:42 +08:00
|
|
|
if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
|
2012-10-04 10:29:46 +08:00
|
|
|
// it's a symbol, create symbolic expression from symbol
|
2012-09-07 17:47:42 +08:00
|
|
|
StringRef Symbol = MSRE->getSymbol().getName();
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
|
|
|
|
Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-09-06 07:34:03 +08:00
|
|
|
bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
|
|
|
|
SMLoc &EndLoc) {
|
|
|
|
|
|
|
|
StartLoc = Parser.getTok().getLoc();
|
2013-01-12 09:03:14 +08:00
|
|
|
RegNo = tryParseRegister(isMips64());
|
|
|
|
EndLoc = Parser.getTok().getLoc();
|
2012-09-06 07:34:03 +08:00
|
|
|
return (RegNo == (unsigned)-1);
|
|
|
|
}
|
|
|
|
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
|
2013-01-12 09:03:14 +08:00
|
|
|
|
|
|
|
SMLoc S;
|
|
|
|
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
switch(getLexer().getKind()) {
|
|
|
|
default:
|
|
|
|
return true;
|
|
|
|
case AsmToken::Integer:
|
|
|
|
case AsmToken::Minus:
|
|
|
|
case AsmToken::Plus:
|
2013-02-21 06:21:35 +08:00
|
|
|
return (getParser().parseExpression(Res));
|
2013-01-12 09:03:14 +08:00
|
|
|
case AsmToken::Percent:
|
|
|
|
return parseRelocOperand(Res);
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
case AsmToken::LParen:
|
2012-10-04 10:29:46 +08:00
|
|
|
return false; // it's probably assuming 0
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-09-06 07:34:03 +08:00
|
|
|
MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
|
|
|
|
SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
|
|
|
|
const MCExpr *IdVal = 0;
|
2013-01-12 09:03:14 +08:00
|
|
|
SMLoc S;
|
|
|
|
// first operand is the offset
|
|
|
|
S = Parser.getTok().getLoc();
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
|
|
|
|
if (parseMemOffset(IdVal))
|
|
|
|
return MatchOperand_ParseFail;
|
|
|
|
|
2012-10-04 10:29:46 +08:00
|
|
|
const AsmToken &Tok = Parser.getTok(); // get next token
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
if (Tok.isNot(AsmToken::LParen)) {
|
Initial assembler implementation of Mips load address macro
This patch provides initial implementation of load address
macro instruction for Mips. We have implemented two kinds
of expansions with their variations depending on the size
of immediate operand:
1) load address with immediate value directly:
* la d,j => addiu d,$zero,j (for -32768 <= j <= 65535)
* la d,j => lui d,hi16(j)
ori d,d,lo16(j) (for any other 32 bit value of j)
2) load load address with register offset value
* la d,j(s) => addiu d,s,j (for -32768 <= j <= 65535)
* la d,j(s) => lui d,hi16(j) (for any other 32 bit value of j)
ori d,d,lo16(j)
addu d,d,s
This patch does not cover the case when the address is loaded
from the value of the label or function.
Contributer: Vladimir Medic
llvm-svn: 165561
2012-10-10 07:29:45 +08:00
|
|
|
MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
|
|
|
|
if (Mnemonic->getToken() == "la") {
|
2013-01-12 09:03:14 +08:00
|
|
|
SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() -1);
|
Initial assembler implementation of Mips load address macro
This patch provides initial implementation of load address
macro instruction for Mips. We have implemented two kinds
of expansions with their variations depending on the size
of immediate operand:
1) load address with immediate value directly:
* la d,j => addiu d,$zero,j (for -32768 <= j <= 65535)
* la d,j => lui d,hi16(j)
ori d,d,lo16(j) (for any other 32 bit value of j)
2) load load address with register offset value
* la d,j(s) => addiu d,s,j (for -32768 <= j <= 65535)
* la d,j(s) => lui d,hi16(j) (for any other 32 bit value of j)
ori d,d,lo16(j)
addu d,d,s
This patch does not cover the case when the address is loaded
from the value of the label or function.
Contributer: Vladimir Medic
llvm-svn: 165561
2012-10-10 07:29:45 +08:00
|
|
|
Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
|
|
|
|
return MatchOperand_Success;
|
|
|
|
}
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
Error(Parser.getTok().getLoc(), "'(' expected");
|
|
|
|
return MatchOperand_ParseFail;
|
|
|
|
}
|
|
|
|
|
|
|
|
Parser.Lex(); // Eat '(' token.
|
|
|
|
|
Initial assembler implementation of Mips load address macro
This patch provides initial implementation of load address
macro instruction for Mips. We have implemented two kinds
of expansions with their variations depending on the size
of immediate operand:
1) load address with immediate value directly:
* la d,j => addiu d,$zero,j (for -32768 <= j <= 65535)
* la d,j => lui d,hi16(j)
ori d,d,lo16(j) (for any other 32 bit value of j)
2) load load address with register offset value
* la d,j(s) => addiu d,s,j (for -32768 <= j <= 65535)
* la d,j(s) => lui d,hi16(j) (for any other 32 bit value of j)
ori d,d,lo16(j)
addu d,d,s
This patch does not cover the case when the address is loaded
from the value of the label or function.
Contributer: Vladimir Medic
llvm-svn: 165561
2012-10-10 07:29:45 +08:00
|
|
|
const AsmToken &Tok1 = Parser.getTok(); // get next token
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
if (Tok1.is(AsmToken::Dollar)) {
|
|
|
|
Parser.Lex(); // Eat '$' token.
|
2013-01-12 09:03:14 +08:00
|
|
|
if (tryParseRegisterOperand(Operands, isMips64())) {
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
Error(Parser.getTok().getLoc(), "unexpected token in operand");
|
|
|
|
return MatchOperand_ParseFail;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
2012-10-04 10:29:46 +08:00
|
|
|
Error(Parser.getTok().getLoc(), "unexpected token in operand");
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
return MatchOperand_ParseFail;
|
|
|
|
}
|
|
|
|
|
2012-10-04 10:29:46 +08:00
|
|
|
const AsmToken &Tok2 = Parser.getTok(); // get next token
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
if (Tok2.isNot(AsmToken::RParen)) {
|
|
|
|
Error(Parser.getTok().getLoc(), "')' expected");
|
|
|
|
return MatchOperand_ParseFail;
|
|
|
|
}
|
|
|
|
|
2013-01-12 09:03:14 +08:00
|
|
|
SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
|
|
|
|
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
Parser.Lex(); // Eat ')' token.
|
|
|
|
|
|
|
|
if (IdVal == 0)
|
|
|
|
IdVal = MCConstantExpr::Create(0, getContext());
|
|
|
|
|
2012-10-04 10:29:46 +08:00
|
|
|
// now replace register operand with the mem operand
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
|
|
|
|
int RegNo = op->getReg();
|
2012-10-04 10:29:46 +08:00
|
|
|
// remove register from operands
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
Operands.pop_back();
|
2012-10-04 10:29:46 +08:00
|
|
|
// and add memory operand
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
|
|
|
|
delete op;
|
2012-09-06 07:34:03 +08:00
|
|
|
return MatchOperand_Success;
|
|
|
|
}
|
|
|
|
|
2013-01-12 09:03:14 +08:00
|
|
|
MipsAsmParser::OperandMatchResultTy
|
|
|
|
MipsAsmParser::parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
|
|
|
|
|
|
|
if (!isMips64())
|
|
|
|
return MatchOperand_NoMatch;
|
|
|
|
// if the first token is not '$' we have an error
|
|
|
|
if (Parser.getTok().isNot(AsmToken::Dollar))
|
|
|
|
return MatchOperand_NoMatch;
|
|
|
|
|
|
|
|
Parser.Lex(); // Eat $
|
|
|
|
if(!tryParseRegisterOperand(Operands, true)) {
|
|
|
|
// set the proper register kind
|
|
|
|
MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
|
|
|
|
op->setRegKind(MipsOperand::Kind_CPU64Regs);
|
|
|
|
return MatchOperand_Success;
|
|
|
|
}
|
|
|
|
return MatchOperand_NoMatch;
|
|
|
|
}
|
|
|
|
|
|
|
|
MipsAsmParser::OperandMatchResultTy
|
|
|
|
MipsAsmParser::parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
|
|
|
|
|
|
|
// if the first token is not '$' we have an error
|
|
|
|
if (Parser.getTok().isNot(AsmToken::Dollar))
|
|
|
|
return MatchOperand_NoMatch;
|
|
|
|
|
|
|
|
Parser.Lex(); // Eat $
|
|
|
|
if(!tryParseRegisterOperand(Operands, false)) {
|
|
|
|
// set the propper register kind
|
|
|
|
MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
|
|
|
|
op->setRegKind(MipsOperand::Kind_CPURegs);
|
|
|
|
return MatchOperand_Success;
|
|
|
|
}
|
|
|
|
return MatchOperand_NoMatch;
|
|
|
|
}
|
|
|
|
|
|
|
|
MipsAsmParser::OperandMatchResultTy
|
|
|
|
MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
|
|
|
|
2013-01-17 08:28:20 +08:00
|
|
|
if (isMips64())
|
|
|
|
return MatchOperand_NoMatch;
|
|
|
|
|
2013-01-12 09:03:14 +08:00
|
|
|
// if the first token is not '$' we have error
|
|
|
|
if (Parser.getTok().isNot(AsmToken::Dollar))
|
|
|
|
return MatchOperand_NoMatch;
|
|
|
|
SMLoc S = Parser.getTok().getLoc();
|
|
|
|
Parser.Lex(); // Eat $
|
|
|
|
|
|
|
|
const AsmToken &Tok = Parser.getTok(); // get next token
|
|
|
|
if (Tok.isNot(AsmToken::Integer))
|
|
|
|
return MatchOperand_NoMatch;
|
|
|
|
|
|
|
|
unsigned RegNum = Tok.getIntVal();
|
|
|
|
// at the moment only hwreg29 is supported
|
|
|
|
if (RegNum != 29)
|
|
|
|
return MatchOperand_ParseFail;
|
|
|
|
|
|
|
|
MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29, S,
|
|
|
|
Parser.getTok().getLoc());
|
|
|
|
op->setRegKind(MipsOperand::Kind_HWRegs);
|
|
|
|
Operands.push_back(op);
|
|
|
|
|
|
|
|
Parser.Lex(); // Eat reg number
|
|
|
|
return MatchOperand_Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
MipsAsmParser::OperandMatchResultTy
|
|
|
|
MipsAsmParser::parseHW64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
2013-01-17 08:28:20 +08:00
|
|
|
|
|
|
|
if (!isMips64())
|
|
|
|
return MatchOperand_NoMatch;
|
2013-01-12 09:03:14 +08:00
|
|
|
//if the first token is not '$' we have error
|
|
|
|
if (Parser.getTok().isNot(AsmToken::Dollar))
|
|
|
|
return MatchOperand_NoMatch;
|
|
|
|
SMLoc S = Parser.getTok().getLoc();
|
|
|
|
Parser.Lex(); // Eat $
|
|
|
|
|
|
|
|
const AsmToken &Tok = Parser.getTok(); // get next token
|
|
|
|
if (Tok.isNot(AsmToken::Integer))
|
|
|
|
return MatchOperand_NoMatch;
|
|
|
|
|
|
|
|
unsigned RegNum = Tok.getIntVal();
|
|
|
|
// at the moment only hwreg29 is supported
|
|
|
|
if (RegNum != 29)
|
|
|
|
return MatchOperand_ParseFail;
|
|
|
|
|
|
|
|
MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29_64, S,
|
|
|
|
Parser.getTok().getLoc());
|
2013-01-17 08:28:20 +08:00
|
|
|
op->setRegKind(MipsOperand::Kind_HW64Regs);
|
2013-01-12 09:03:14 +08:00
|
|
|
Operands.push_back(op);
|
|
|
|
|
|
|
|
Parser.Lex(); // Eat reg number
|
|
|
|
return MatchOperand_Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
MipsAsmParser::OperandMatchResultTy
|
|
|
|
MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
|
|
|
unsigned RegNum;
|
|
|
|
//if the first token is not '$' we have error
|
|
|
|
if (Parser.getTok().isNot(AsmToken::Dollar))
|
|
|
|
return MatchOperand_NoMatch;
|
|
|
|
SMLoc S = Parser.getTok().getLoc();
|
|
|
|
Parser.Lex(); // Eat $
|
|
|
|
|
|
|
|
const AsmToken &Tok = Parser.getTok(); // get next token
|
|
|
|
if (Tok.is(AsmToken::Integer)) {
|
|
|
|
RegNum = Tok.getIntVal();
|
|
|
|
// at the moment only fcc0 is supported
|
|
|
|
if (RegNum != 0)
|
|
|
|
return MatchOperand_ParseFail;
|
|
|
|
} else if (Tok.is(AsmToken::Identifier)) {
|
|
|
|
// at the moment only fcc0 is supported
|
|
|
|
if (Tok.getIdentifier() != "fcc0")
|
|
|
|
return MatchOperand_ParseFail;
|
|
|
|
} else
|
|
|
|
return MatchOperand_NoMatch;
|
|
|
|
|
|
|
|
MipsOperand *op = MipsOperand::CreateReg(Mips::FCC0, S,
|
|
|
|
Parser.getTok().getLoc());
|
|
|
|
op->setRegKind(MipsOperand::Kind_CCRRegs);
|
|
|
|
Operands.push_back(op);
|
|
|
|
|
|
|
|
Parser.Lex(); // Eat reg number
|
|
|
|
return MatchOperand_Success;
|
|
|
|
}
|
|
|
|
|
The Mips standalone assembler memory instruction support.
This includes sb,sc,sh,sw,lb,lw,lbu,lh,lhu,ll,lw
Test case included
Contributer: Vladimir Medic
llvm-svn: 163346
2012-09-07 04:00:02 +08:00
|
|
|
MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
|
|
|
|
|
|
|
|
MCSymbolRefExpr::VariantKind VK
|
|
|
|
= StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
|
|
|
|
.Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
|
|
|
|
.Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
|
|
|
|
.Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
|
|
|
|
.Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
|
|
|
|
.Case("got", MCSymbolRefExpr::VK_Mips_GOT)
|
|
|
|
.Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
|
|
|
|
.Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
|
|
|
|
.Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
|
|
|
|
.Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
|
|
|
|
.Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
|
|
|
|
.Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
|
|
|
|
.Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
|
|
|
|
.Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
|
|
|
|
.Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
|
|
|
|
.Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
|
|
|
|
.Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
|
|
|
|
.Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
|
|
|
|
.Default(MCSymbolRefExpr::VK_None);
|
|
|
|
|
|
|
|
return VK;
|
|
|
|
}
|
|
|
|
|
2012-09-10 19:52:14 +08:00
|
|
|
static int ConvertCcString(StringRef CondString) {
|
2012-09-07 08:23:42 +08:00
|
|
|
int CC = StringSwitch<unsigned>(CondString)
|
|
|
|
.Case(".f", 0)
|
|
|
|
.Case(".un", 1)
|
|
|
|
.Case(".eq", 2)
|
|
|
|
.Case(".ueq", 3)
|
|
|
|
.Case(".olt", 4)
|
|
|
|
.Case(".ult", 5)
|
|
|
|
.Case(".ole", 6)
|
|
|
|
.Case(".ule", 7)
|
|
|
|
.Case(".sf", 8)
|
|
|
|
.Case(".ngle", 9)
|
|
|
|
.Case(".seq", 10)
|
|
|
|
.Case(".ngl", 11)
|
|
|
|
.Case(".lt", 12)
|
|
|
|
.Case(".nge", 13)
|
|
|
|
.Case(".le", 14)
|
|
|
|
.Case(".ngt", 15)
|
|
|
|
.Default(-1);
|
|
|
|
|
|
|
|
return CC;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MipsAsmParser::
|
|
|
|
parseMathOperation(StringRef Name, SMLoc NameLoc,
|
2012-10-04 10:29:46 +08:00
|
|
|
SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
|
|
|
// split the format
|
2012-09-07 08:23:42 +08:00
|
|
|
size_t Start = Name.find('.'), Next = Name.rfind('.');
|
|
|
|
StringRef Format1 = Name.slice(Start, Next);
|
2012-10-04 10:29:46 +08:00
|
|
|
// and add the first format to the operands
|
2012-09-07 08:23:42 +08:00
|
|
|
Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
|
2012-10-04 10:29:46 +08:00
|
|
|
// now for the second format
|
2012-09-07 08:23:42 +08:00
|
|
|
StringRef Format2 = Name.slice(Next, StringRef::npos);
|
|
|
|
Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
|
|
|
|
|
2012-10-04 10:29:46 +08:00
|
|
|
// set the format for the first register
|
2012-09-07 08:23:42 +08:00
|
|
|
setFpFormat(Format1);
|
|
|
|
|
|
|
|
// Read the remaining operands.
|
|
|
|
if (getLexer().isNot(AsmToken::EndOfStatement)) {
|
|
|
|
// Read the first operand.
|
|
|
|
if (ParseOperand(Operands, Name)) {
|
|
|
|
SMLoc Loc = getLexer().getLoc();
|
2013-02-21 06:21:35 +08:00
|
|
|
Parser.eatToEndOfStatement();
|
2012-09-07 08:23:42 +08:00
|
|
|
return Error(Loc, "unexpected token in argument list");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (getLexer().isNot(AsmToken::Comma)) {
|
|
|
|
SMLoc Loc = getLexer().getLoc();
|
2013-02-21 06:21:35 +08:00
|
|
|
Parser.eatToEndOfStatement();
|
2012-09-07 08:23:42 +08:00
|
|
|
return Error(Loc, "unexpected token in argument list");
|
|
|
|
|
|
|
|
}
|
|
|
|
Parser.Lex(); // Eat the comma.
|
|
|
|
|
|
|
|
//set the format for the first register
|
|
|
|
setFpFormat(Format2);
|
|
|
|
|
|
|
|
// Parse and remember the operand.
|
|
|
|
if (ParseOperand(Operands, Name)) {
|
|
|
|
SMLoc Loc = getLexer().getLoc();
|
2013-02-21 06:21:35 +08:00
|
|
|
Parser.eatToEndOfStatement();
|
2012-09-07 08:23:42 +08:00
|
|
|
return Error(Loc, "unexpected token in argument list");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (getLexer().isNot(AsmToken::EndOfStatement)) {
|
|
|
|
SMLoc Loc = getLexer().getLoc();
|
2013-02-21 06:21:35 +08:00
|
|
|
Parser.eatToEndOfStatement();
|
2012-09-07 08:23:42 +08:00
|
|
|
return Error(Loc, "unexpected token in argument list");
|
|
|
|
}
|
|
|
|
|
|
|
|
Parser.Lex(); // Consume the EndOfStatement
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-01-11 11:56:41 +08:00
|
|
|
bool MipsAsmParser::
|
2012-10-26 04:41:34 +08:00
|
|
|
ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
|
2012-01-11 11:56:41 +08:00
|
|
|
SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
2013-02-21 07:11:17 +08:00
|
|
|
StringRef Mnemonic;
|
2012-10-04 10:29:46 +08:00
|
|
|
// floating point instructions: should register be treated as double?
|
2012-09-07 08:23:42 +08:00
|
|
|
if (requestsDoubleOperand(Name)) {
|
|
|
|
setFpFormat(FP_FORMAT_D);
|
2012-09-06 07:34:03 +08:00
|
|
|
Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
|
2013-02-21 07:11:17 +08:00
|
|
|
Mnemonic = Name;
|
2012-09-07 08:23:42 +08:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
setDefaultFpFormat();
|
|
|
|
// Create the leading tokens for the mnemonic, split by '.' characters.
|
|
|
|
size_t Start = 0, Next = Name.find('.');
|
2013-02-21 07:11:17 +08:00
|
|
|
Mnemonic = Name.slice(Start, Next);
|
2012-09-07 08:23:42 +08:00
|
|
|
|
|
|
|
Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
|
|
|
|
|
|
|
|
if (Next != StringRef::npos) {
|
2012-10-04 10:29:46 +08:00
|
|
|
// there is a format token in mnemonic
|
|
|
|
// StringRef Rest = Name.slice(Next, StringRef::npos);
|
2012-09-07 08:23:42 +08:00
|
|
|
size_t Dot = Name.find('.', Next+1);
|
|
|
|
StringRef Format = Name.slice(Next, Dot);
|
|
|
|
if (Dot == StringRef::npos) //only one '.' in a string, it's a format
|
|
|
|
Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
|
|
|
|
else {
|
|
|
|
if (Name.startswith("c.")){
|
|
|
|
// floating point compare, add '.' and immediate represent for cc
|
|
|
|
Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
|
|
|
|
int Cc = ConvertCcString(Format);
|
|
|
|
if (Cc == -1) {
|
|
|
|
return Error(NameLoc, "Invalid conditional code");
|
|
|
|
}
|
2013-01-12 09:03:14 +08:00
|
|
|
SMLoc E = SMLoc::getFromPointer(
|
|
|
|
Parser.getTok().getLoc().getPointer() -1 );
|
2012-09-07 08:23:42 +08:00
|
|
|
Operands.push_back(MipsOperand::CreateImm(
|
|
|
|
MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
|
|
|
|
} else {
|
2012-10-04 10:29:46 +08:00
|
|
|
// trunc, ceil, floor ...
|
2012-09-07 08:23:42 +08:00
|
|
|
return parseMathOperation(Name, NameLoc, Operands);
|
|
|
|
}
|
|
|
|
|
2012-10-04 10:29:46 +08:00
|
|
|
// the rest is a format
|
2012-09-07 08:23:42 +08:00
|
|
|
Format = Name.slice(Dot, StringRef::npos);
|
|
|
|
Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
|
|
|
|
}
|
|
|
|
|
|
|
|
setFpFormat(Format);
|
|
|
|
}
|
|
|
|
}
|
2012-09-06 07:34:03 +08:00
|
|
|
|
|
|
|
// Read the remaining operands.
|
|
|
|
if (getLexer().isNot(AsmToken::EndOfStatement)) {
|
|
|
|
// Read the first operand.
|
2013-02-21 07:11:17 +08:00
|
|
|
if (ParseOperand(Operands, Mnemonic)) {
|
2012-09-06 07:34:03 +08:00
|
|
|
SMLoc Loc = getLexer().getLoc();
|
2013-02-21 06:21:35 +08:00
|
|
|
Parser.eatToEndOfStatement();
|
2012-09-06 07:34:03 +08:00
|
|
|
return Error(Loc, "unexpected token in argument list");
|
|
|
|
}
|
|
|
|
|
|
|
|
while (getLexer().is(AsmToken::Comma) ) {
|
|
|
|
Parser.Lex(); // Eat the comma.
|
|
|
|
|
|
|
|
// Parse and remember the operand.
|
|
|
|
if (ParseOperand(Operands, Name)) {
|
|
|
|
SMLoc Loc = getLexer().getLoc();
|
2013-02-21 06:21:35 +08:00
|
|
|
Parser.eatToEndOfStatement();
|
2012-09-06 07:34:03 +08:00
|
|
|
return Error(Loc, "unexpected token in argument list");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (getLexer().isNot(AsmToken::EndOfStatement)) {
|
|
|
|
SMLoc Loc = getLexer().getLoc();
|
2013-02-21 06:21:35 +08:00
|
|
|
Parser.eatToEndOfStatement();
|
2012-09-06 07:34:03 +08:00
|
|
|
return Error(Loc, "unexpected token in argument list");
|
|
|
|
}
|
|
|
|
|
|
|
|
Parser.Lex(); // Consume the EndOfStatement
|
|
|
|
return false;
|
2012-01-11 11:56:41 +08:00
|
|
|
}
|
|
|
|
|
2012-10-04 10:29:46 +08:00
|
|
|
bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
|
|
|
|
SMLoc Loc = getLexer().getLoc();
|
2013-02-21 06:21:35 +08:00
|
|
|
Parser.eatToEndOfStatement();
|
2012-10-04 10:29:46 +08:00
|
|
|
return Error(Loc, ErrorMsg);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MipsAsmParser::parseSetNoAtDirective() {
|
|
|
|
// line should look like:
|
|
|
|
// .set noat
|
|
|
|
// set at reg to 0
|
2012-10-06 07:55:28 +08:00
|
|
|
Options.setATReg(0);
|
2012-10-04 10:29:46 +08:00
|
|
|
// eat noat
|
|
|
|
Parser.Lex();
|
|
|
|
// if this is not the end of the statement, report error
|
|
|
|
if (getLexer().isNot(AsmToken::EndOfStatement)) {
|
|
|
|
reportParseError("unexpected token in statement");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
Parser.Lex(); // Consume the EndOfStatement
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
bool MipsAsmParser::parseSetAtDirective() {
|
|
|
|
// line can be
|
|
|
|
// .set at - defaults to $1
|
|
|
|
// or .set at=$reg
|
2013-02-21 07:11:17 +08:00
|
|
|
int AtRegNo;
|
2012-10-04 10:29:46 +08:00
|
|
|
getParser().Lex();
|
|
|
|
if (getLexer().is(AsmToken::EndOfStatement)) {
|
2012-10-06 07:55:28 +08:00
|
|
|
Options.setATReg(1);
|
2012-10-04 10:29:46 +08:00
|
|
|
Parser.Lex(); // Consume the EndOfStatement
|
|
|
|
return false;
|
|
|
|
} else if (getLexer().is(AsmToken::Equal)) {
|
|
|
|
getParser().Lex(); //eat '='
|
|
|
|
if (getLexer().isNot(AsmToken::Dollar)) {
|
|
|
|
reportParseError("unexpected token in statement");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
Parser.Lex(); // eat '$'
|
2013-02-21 07:11:17 +08:00
|
|
|
const AsmToken &Reg = Parser.getTok();
|
|
|
|
if (Reg.is(AsmToken::Identifier)) {
|
|
|
|
AtRegNo = matchCPURegisterName(Reg.getIdentifier());
|
|
|
|
} else if (Reg.is(AsmToken::Integer)) {
|
|
|
|
AtRegNo = Reg.getIntVal();
|
|
|
|
} else {
|
2012-10-04 10:29:46 +08:00
|
|
|
reportParseError("unexpected token in statement");
|
|
|
|
return false;
|
|
|
|
}
|
2013-02-21 07:11:17 +08:00
|
|
|
|
|
|
|
if ( AtRegNo < 1 || AtRegNo > 31) {
|
|
|
|
reportParseError("unexpected token in statement");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!Options.setATReg(AtRegNo)) {
|
2012-10-04 10:29:46 +08:00
|
|
|
reportParseError("unexpected token in statement");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
getParser().Lex(); //eat reg
|
|
|
|
|
|
|
|
if (getLexer().isNot(AsmToken::EndOfStatement)) {
|
|
|
|
reportParseError("unexpected token in statement");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
Parser.Lex(); // Consume the EndOfStatement
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
reportParseError("unexpected token in statement");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MipsAsmParser::parseSetReorderDirective() {
|
|
|
|
Parser.Lex();
|
|
|
|
// if this is not the end of the statement, report error
|
|
|
|
if (getLexer().isNot(AsmToken::EndOfStatement)) {
|
|
|
|
reportParseError("unexpected token in statement");
|
|
|
|
return false;
|
|
|
|
}
|
2012-10-06 07:55:28 +08:00
|
|
|
Options.setReorder();
|
2012-10-04 10:29:46 +08:00
|
|
|
Parser.Lex(); // Consume the EndOfStatement
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MipsAsmParser::parseSetNoReorderDirective() {
|
|
|
|
Parser.Lex();
|
|
|
|
// if this is not the end of the statement, report error
|
|
|
|
if (getLexer().isNot(AsmToken::EndOfStatement)) {
|
|
|
|
reportParseError("unexpected token in statement");
|
|
|
|
return false;
|
|
|
|
}
|
2012-10-06 07:55:28 +08:00
|
|
|
Options.setNoreorder();
|
2012-10-04 10:29:46 +08:00
|
|
|
Parser.Lex(); // Consume the EndOfStatement
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MipsAsmParser::parseSetMacroDirective() {
|
|
|
|
Parser.Lex();
|
|
|
|
// if this is not the end of the statement, report error
|
|
|
|
if (getLexer().isNot(AsmToken::EndOfStatement)) {
|
|
|
|
reportParseError("unexpected token in statement");
|
|
|
|
return false;
|
|
|
|
}
|
2012-10-06 07:55:28 +08:00
|
|
|
Options.setMacro();
|
2012-10-04 10:29:46 +08:00
|
|
|
Parser.Lex(); // Consume the EndOfStatement
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MipsAsmParser::parseSetNoMacroDirective() {
|
|
|
|
Parser.Lex();
|
|
|
|
// if this is not the end of the statement, report error
|
|
|
|
if (getLexer().isNot(AsmToken::EndOfStatement)) {
|
|
|
|
reportParseError("`noreorder' must be set before `nomacro'");
|
|
|
|
return false;
|
|
|
|
}
|
2012-10-06 07:55:28 +08:00
|
|
|
if (Options.isReorder()) {
|
2012-10-04 10:29:46 +08:00
|
|
|
reportParseError("`noreorder' must be set before `nomacro'");
|
|
|
|
return false;
|
|
|
|
}
|
2012-10-06 07:55:28 +08:00
|
|
|
Options.setNomacro();
|
2012-10-04 10:29:46 +08:00
|
|
|
Parser.Lex(); // Consume the EndOfStatement
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
bool MipsAsmParser::parseDirectiveSet() {
|
|
|
|
|
|
|
|
// get next token
|
|
|
|
const AsmToken &Tok = Parser.getTok();
|
|
|
|
|
|
|
|
if (Tok.getString() == "noat") {
|
|
|
|
return parseSetNoAtDirective();
|
|
|
|
} else if (Tok.getString() == "at") {
|
|
|
|
return parseSetAtDirective();
|
|
|
|
} else if (Tok.getString() == "reorder") {
|
|
|
|
return parseSetReorderDirective();
|
|
|
|
} else if (Tok.getString() == "noreorder") {
|
|
|
|
return parseSetNoReorderDirective();
|
|
|
|
} else if (Tok.getString() == "macro") {
|
|
|
|
return parseSetMacroDirective();
|
|
|
|
} else if (Tok.getString() == "nomacro") {
|
|
|
|
return parseSetNoMacroDirective();
|
|
|
|
} else if (Tok.getString() == "nomips16") {
|
|
|
|
// ignore this directive for now
|
2013-02-21 06:21:35 +08:00
|
|
|
Parser.eatToEndOfStatement();
|
2012-10-04 10:29:46 +08:00
|
|
|
return false;
|
|
|
|
} else if (Tok.getString() == "nomicromips") {
|
|
|
|
// ignore this directive for now
|
2013-02-21 06:21:35 +08:00
|
|
|
Parser.eatToEndOfStatement();
|
2012-10-04 10:29:46 +08:00
|
|
|
return false;
|
|
|
|
}
|
2013-01-25 09:31:34 +08:00
|
|
|
|
2012-10-04 10:29:46 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-01-25 09:31:34 +08:00
|
|
|
/// parseDirectiveWord
|
|
|
|
/// ::= .word [ expression (, expression)* ]
|
|
|
|
bool MipsAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
|
|
|
|
if (getLexer().isNot(AsmToken::EndOfStatement)) {
|
|
|
|
for (;;) {
|
|
|
|
const MCExpr *Value;
|
2013-02-21 06:21:35 +08:00
|
|
|
if (getParser().parseExpression(Value))
|
2013-01-25 09:31:34 +08:00
|
|
|
return true;
|
|
|
|
|
|
|
|
getParser().getStreamer().EmitValue(Value, Size);
|
|
|
|
|
|
|
|
if (getLexer().is(AsmToken::EndOfStatement))
|
|
|
|
break;
|
|
|
|
|
|
|
|
// FIXME: Improve diagnostic.
|
|
|
|
if (getLexer().isNot(AsmToken::Comma))
|
|
|
|
return Error(L, "unexpected token in directive");
|
|
|
|
Parser.Lex();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Parser.Lex();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-10-04 10:29:46 +08:00
|
|
|
bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
|
2012-09-07 08:48:02 +08:00
|
|
|
|
2013-01-25 09:31:34 +08:00
|
|
|
StringRef IDVal = DirectiveID.getString();
|
|
|
|
|
|
|
|
if ( IDVal == ".ent") {
|
2012-10-04 10:29:46 +08:00
|
|
|
// ignore this directive for now
|
2012-09-07 08:48:02 +08:00
|
|
|
Parser.Lex();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-01-25 09:31:34 +08:00
|
|
|
if (IDVal == ".end") {
|
2012-10-04 10:29:46 +08:00
|
|
|
// ignore this directive for now
|
2012-09-07 08:48:02 +08:00
|
|
|
Parser.Lex();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-01-25 09:31:34 +08:00
|
|
|
if (IDVal == ".frame") {
|
2012-10-04 10:29:46 +08:00
|
|
|
// ignore this directive for now
|
2013-02-21 06:21:35 +08:00
|
|
|
Parser.eatToEndOfStatement();
|
2012-09-07 08:48:02 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-01-25 09:31:34 +08:00
|
|
|
if (IDVal == ".set") {
|
2012-10-04 10:29:46 +08:00
|
|
|
return parseDirectiveSet();
|
2012-09-07 08:48:02 +08:00
|
|
|
}
|
|
|
|
|
2013-01-25 09:31:34 +08:00
|
|
|
if (IDVal == ".fmask") {
|
2012-10-04 10:29:46 +08:00
|
|
|
// ignore this directive for now
|
2013-02-21 06:21:35 +08:00
|
|
|
Parser.eatToEndOfStatement();
|
2012-09-07 08:48:02 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-01-25 09:31:34 +08:00
|
|
|
if (IDVal == ".mask") {
|
2012-10-04 10:29:46 +08:00
|
|
|
// ignore this directive for now
|
2013-02-21 06:21:35 +08:00
|
|
|
Parser.eatToEndOfStatement();
|
2012-09-07 08:48:02 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-01-25 09:31:34 +08:00
|
|
|
if (IDVal == ".gpword") {
|
2012-10-04 10:29:46 +08:00
|
|
|
// ignore this directive for now
|
2013-02-21 06:21:35 +08:00
|
|
|
Parser.eatToEndOfStatement();
|
2012-09-07 08:48:02 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-01-25 09:31:34 +08:00
|
|
|
if (IDVal == ".word") {
|
|
|
|
parseDirectiveWord(4, DirectiveID.getLoc());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-01-11 11:56:41 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" void LLVMInitializeMipsAsmParser() {
|
|
|
|
RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
|
|
|
|
RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
|
|
|
|
RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
|
|
|
|
RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
|
|
|
|
}
|
2012-09-06 07:34:03 +08:00
|
|
|
|
|
|
|
#define GET_REGISTER_MATCHER
|
|
|
|
#define GET_MATCHER_IMPLEMENTATION
|
|
|
|
#include "MipsGenAsmMatcher.inc"
|