From 99e98551bf8719764f9345ce856118f3f1a9c441 Mon Sep 17 00:00:00 2001 From: Jack Carter Date: Wed, 20 Feb 2013 23:11:17 +0000 Subject: [PATCH] ELF symbol table field st_other support, excluding visibility bits. Mips specific standalone assembler directive "set at". This directive changes the general purpose register that the assembler will use when given the symbolic register name $at. This does not include negative testing. That will come in a future patch. A side affect of this patch recognizes the different GPR register names for temporaries between old abi and new abi so a test case for that is included. Contributer: Vladimir Medic git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@175686 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 175 ++++++++++---------- test/MC/Mips/mips_directives.s | 27 +-- test/MC/Mips/nabi-regs.s | 36 ++++ test/MC/Mips/set-at-directive.s | 132 +++++++++++++++ 4 files changed, 269 insertions(+), 101 deletions(-) create mode 100644 test/MC/Mips/nabi-regs.s create mode 100644 test/MC/Mips/set-at-directive.s diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 2fa514f7fbd..088589fbfb1 100644 --- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -147,6 +147,8 @@ class MipsAsmParser : public MCTargetAsmParser { int matchRegisterName(StringRef Symbol, bool is64BitReg); + int matchCPURegisterName(StringRef Symbol); + int matchRegisterByNumber(unsigned RegNum, unsigned RegClass); void setFpFormat(FpFormatTy Format) { @@ -163,7 +165,7 @@ class MipsAsmParser : public MCTargetAsmParser { unsigned getReg(int RC,int RegNo); - unsigned getATReg(); + int getATReg(); public: MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser) : MCTargetAsmParser(), STI(sti), Parser(parser) { @@ -192,7 +194,7 @@ public: Kind_HW64Regs, Kind_FGR32Regs, Kind_FGR64Regs, - Kind_AFGR32Regs, + Kind_AFGR64Regs, Kind_CCRRegs }; @@ -574,84 +576,72 @@ MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, return true; } +int MipsAsmParser::matchCPURegisterName(StringRef Name) { + int CC; + + if (Name == "at") + return getATReg(); + + CC = StringSwitch(Name) + .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()) + CC = StringSwitch(Name) + .Case("a4", 8) + .Case("a5", 9) + .Case("a6", 10) + .Case("a7", 11) + .Case("kt0", 26) + .Case("kt1", 27) + .Case("s8", 30) + .Default(-1); + + return CC; +} int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) { - int CC; - if (!is64BitReg) - CC = StringSwitch(Name) - .Case("zero", Mips::ZERO) - .Case("a0", Mips::A0) - .Case("a1", Mips::A1) - .Case("a2", Mips::A2) - .Case("a3", Mips::A3) - .Case("v0", Mips::V0) - .Case("v1", Mips::V1) - .Case("s0", Mips::S0) - .Case("s1", Mips::S1) - .Case("s2", Mips::S2) - .Case("s3", Mips::S3) - .Case("s4", Mips::S4) - .Case("s5", Mips::S5) - .Case("s6", Mips::S6) - .Case("s7", Mips::S7) - .Case("k0", Mips::K0) - .Case("k1", Mips::K1) - .Case("sp", Mips::SP) - .Case("fp", Mips::FP) - .Case("gp", Mips::GP) - .Case("ra", Mips::RA) - .Case("t0", Mips::T0) - .Case("t1", Mips::T1) - .Case("t2", Mips::T2) - .Case("t3", Mips::T3) - .Case("t4", Mips::T4) - .Case("t5", Mips::T5) - .Case("t6", Mips::T6) - .Case("t7", Mips::T7) - .Case("t8", Mips::T8) - .Case("t9", Mips::T9) - .Case("at", Mips::AT) - .Case("fcc0", Mips::FCC0) - .Default(-1); - else - CC = StringSwitch(Name) - .Case("zero", Mips::ZERO_64) - .Case("at", Mips::AT_64) - .Case("v0", Mips::V0_64) - .Case("v1", Mips::V1_64) - .Case("a0", Mips::A0_64) - .Case("a1", Mips::A1_64) - .Case("a2", Mips::A2_64) - .Case("a3", Mips::A3_64) - .Case("a4", Mips::T0_64) - .Case("a5", Mips::T1_64) - .Case("a6", Mips::T2_64) - .Case("a7", Mips::T3_64) - .Case("t4", Mips::T4_64) - .Case("t5", Mips::T5_64) - .Case("t6", Mips::T6_64) - .Case("t7", Mips::T7_64) - .Case("s0", Mips::S0_64) - .Case("s1", Mips::S1_64) - .Case("s2", Mips::S2_64) - .Case("s3", Mips::S3_64) - .Case("s4", Mips::S4_64) - .Case("s5", Mips::S5_64) - .Case("s6", Mips::S6_64) - .Case("s7", Mips::S7_64) - .Case("t8", Mips::T8_64) - .Case("t9", Mips::T9_64) - .Case("kt0", Mips::K0_64) - .Case("kt1", Mips::K1_64) - .Case("gp", Mips::GP_64) - .Case("sp", Mips::SP_64) - .Case("fp", Mips::FP_64) - .Case("s8", Mips::FP_64) - .Case("ra", Mips::RA_64) - .Default(-1); - + int CC; + CC = matchCPURegisterName(Name); if (CC != -1) - return CC; + return matchRegisterByNumber(CC,is64BitReg?Mips::CPU64RegsRegClassID: + Mips::CPURegsRegClassID); if (Name[0] == 'f') { StringRef NumString = Name.substr(1); @@ -715,12 +705,8 @@ bool MipsAssemblerOptions::setATReg(unsigned Reg) { return true; } -unsigned MipsAsmParser::getATReg() { - unsigned Reg = Options.getATRegNum(); - if (isMips64()) - return getReg(Mips::CPU64RegsRegClassID,Reg); - - return getReg(Mips::CPURegsRegClassID,Reg); +int MipsAsmParser::getATReg() { + return Options.getATRegNum(); } unsigned MipsAsmParser::getReg(int RC,int RegNo) { @@ -1239,16 +1225,18 @@ parseMathOperation(StringRef Name, SMLoc NameLoc, bool MipsAsmParser:: ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, SmallVectorImpl &Operands) { + StringRef Mnemonic; // floating point instructions: should register be treated as double? if (requestsDoubleOperand(Name)) { setFpFormat(FP_FORMAT_D); Operands.push_back(MipsOperand::CreateToken(Name, NameLoc)); + Mnemonic = Name; } else { setDefaultFpFormat(); // Create the leading tokens for the mnemonic, split by '.' characters. size_t Start = 0, Next = Name.find('.'); - StringRef Mnemonic = Name.slice(Start, Next); + Mnemonic = Name.slice(Start, Next); Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc)); @@ -1288,7 +1276,7 @@ ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, // Read the remaining operands. if (getLexer().isNot(AsmToken::EndOfStatement)) { // Read the first operand. - if (ParseOperand(Operands, Name)) { + if (ParseOperand(Operands, Mnemonic)) { SMLoc Loc = getLexer().getLoc(); Parser.eatToEndOfStatement(); return Error(Loc, "unexpected token in argument list"); @@ -1341,6 +1329,7 @@ bool MipsAsmParser::parseSetAtDirective() { // line can be // .set at - defaults to $1 // or .set at=$reg + int AtRegNo; getParser().Lex(); if (getLexer().is(AsmToken::EndOfStatement)) { Options.setATReg(1); @@ -1353,12 +1342,22 @@ bool MipsAsmParser::parseSetAtDirective() { return false; } Parser.Lex(); // eat '$' - if (getLexer().isNot(AsmToken::Integer)) { + const AsmToken &Reg = Parser.getTok(); + if (Reg.is(AsmToken::Identifier)) { + AtRegNo = matchCPURegisterName(Reg.getIdentifier()); + } else if (Reg.is(AsmToken::Integer)) { + AtRegNo = Reg.getIntVal(); + } else { reportParseError("unexpected token in statement"); return false; } - const AsmToken &Reg = Parser.getTok(); - if (!Options.setATReg(Reg.getIntVal())) { + + if ( AtRegNo < 1 || AtRegNo > 31) { + reportParseError("unexpected token in statement"); + return false; + } + + if (!Options.setATReg(AtRegNo)) { reportParseError("unexpected token in statement"); return false; } diff --git a/test/MC/Mips/mips_directives.s b/test/MC/Mips/mips_directives.s index 5026b385e82..d0a3beaeeaa 100644 --- a/test/MC/Mips/mips_directives.s +++ b/test/MC/Mips/mips_directives.s @@ -2,18 +2,19 @@ #this test produces no output so there isS no FileCheck call $BB0_2: .ent directives_test - .frame $sp,0,$ra - .mask 0x00000000,0 - .fmask 0x00000000,0 - .set noreorder - .set nomacro - .set noat + .frame $sp,0,$ra + .mask 0x00000000,0 + .fmask 0x00000000,0 + .set noreorder + .set nomacro + .set noat $JTI0_0: - .gpword ($BB0_2) - .word 0x77fffffc + .gpword ($BB0_2) + .word 0x77fffffc # CHECK: $JTI0_0: -# CHECK-NEXT: .4byte 2013265916 - .set at=$12 - .set macro - .set reorder - .end directives_test +# CHECK-NEXT: .4byte 2013265916 + .set at=$12 + .set macro + .set reorder + .set at=$a0 + .end directives_test diff --git a/test/MC/Mips/nabi-regs.s b/test/MC/Mips/nabi-regs.s new file mode 100644 index 00000000000..9371208a2a9 --- /dev/null +++ b/test/MC/Mips/nabi-regs.s @@ -0,0 +1,36 @@ +# OABI (o32, o64) have a different symbolic register +# set for the A and T registers because the NABI allows +# for 4 more register parameters (A registers) offsetting +# the T registers. +# +# For now just check N64 +# RUN: llvm-mc %s -triple=mipsel-unknown-linux -show-encoding \ +# RUN: -mcpu=mips64r2 -arch=mips64 | \ +# RUN: FileCheck %s + +# CHECK: .section __TEXT,__text,regular,pure_instructions + .text +foo: + +# CHECK: add $16, $16, $4 # encoding: [0x02,0x04,0x80,0x20] + add $s0,$s0,$a0 +# CHECK: add $16, $16, $6 # encoding: [0x02,0x06,0x80,0x20] + add $s0,$s0,$a2 +# CHECK: add $16, $16, $7 # encoding: [0x02,0x07,0x80,0x20] + add $s0,$s0,$a3 +# CHECK: add $16, $16, $8 # encoding: [0x02,0x08,0x80,0x20] + add $s0,$s0,$a4 +# CHECK: add $16, $16, $9 # encoding: [0x02,0x09,0x80,0x20] + add $s0,$s0,$a5 +# CHECK: add $16, $16, $10 # encoding: [0x02,0x0a,0x80,0x20] + add $s0,$s0,$a6 +# CHECK: add $16, $16, $11 # encoding: [0x02,0x0b,0x80,0x20] + add $s0,$s0,$a7 +# CHECK: add $16, $16, $12 # encoding: [0x02,0x0c,0x80,0x20] + add $s0,$s0,$t0 +# CHECK: add $16, $16, $13 # encoding: [0x02,0x0d,0x80,0x20] + add $s0,$s0,$t1 +# CHECK: add $16, $16, $14 # encoding: [0x02,0x0e,0x80,0x20] + add $s0,$s0,$t2 +# CHECK: add $16, $16, $15 # encoding: [0x02,0x0f,0x80,0x20] + add $s0,$s0,$t3 diff --git a/test/MC/Mips/set-at-directive.s b/test/MC/Mips/set-at-directive.s new file mode 100644 index 00000000000..98a3a35b542 --- /dev/null +++ b/test/MC/Mips/set-at-directive.s @@ -0,0 +1,132 @@ +# RUN: llvm-mc %s -triple=mipsel-unknown-linux -show-encoding -mcpu=mips32r2 | \ +# RUN: FileCheck %s +# Check that the assembler can handle the documented syntax +# for ".set at" and set the correct value. + +# CHECK: .section __TEXT,__text,regular,pure_instructions + .text +foo: +# CHECK: jr $1 # encoding: [0x08,0x00,0x20,0x00] + .set at=$1 + jr $at + nop +# CHECK: jr $2 # encoding: [0x08,0x00,0x40,0x00] + .set at=$2 + jr $at + nop +# CHECK: jr $3 # encoding: [0x08,0x00,0x60,0x00] + .set at=$3 + jr $at + nop +# CHECK: jr $4 # encoding: [0x08,0x00,0x80,0x00] + .set at=$a0 + jr $at + nop +# CHECK: jr $5 # encoding: [0x08,0x00,0xa0,0x00] + .set at=$a1 + jr $at + nop +# CHECK: jr $6 # encoding: [0x08,0x00,0xc0,0x00] + .set at=$a2 + jr $at + nop +# CHECK: jr $7 # encoding: [0x08,0x00,0xe0,0x00] + .set at=$a3 + jr $at + nop +# CHECK: jr $8 # encoding: [0x08,0x00,0x00,0x01] + .set at=$8 + jr $at + nop +# CHECK: jr $9 # encoding: [0x08,0x00,0x20,0x01] + .set at=$9 + jr $at + nop +# CHECK: jr $10 # encoding: [0x08,0x00,0x40,0x01] + .set at=$10 + jr $at + nop +# CHECK: jr $11 # encoding: [0x08,0x00,0x60,0x01] + .set at=$11 + jr $at + nop +# CHECK: jr $12 # encoding: [0x08,0x00,0x80,0x01] + .set at=$12 + jr $at + nop +# CHECK: jr $13 # encoding: [0x08,0x00,0xa0,0x01] + .set at=$13 + jr $at + nop +# CHECK: jr $14 # encoding: [0x08,0x00,0xc0,0x01] + .set at=$14 + jr $at + nop +# CHECK: jr $15 # encoding: [0x08,0x00,0xe0,0x01] + .set at=$15 + jr $at + nop +# CHECK: jr $16 # encoding: [0x08,0x00,0x00,0x02] + .set at=$s0 + jr $at + nop +# CHECK: jr $17 # encoding: [0x08,0x00,0x20,0x02] + .set at=$s1 + jr $at + nop +# CHECK: jr $18 # encoding: [0x08,0x00,0x40,0x02] + .set at=$s2 + jr $at + nop +# CHECK: jr $19 # encoding: [0x08,0x00,0x60,0x02] + .set at=$s3 + jr $at + nop +# CHECK: jr $20 # encoding: [0x08,0x00,0x80,0x02] + .set at=$s4 + jr $at + nop +# CHECK: jr $21 # encoding: [0x08,0x00,0xa0,0x02] + .set at=$s5 + jr $at + nop +# CHECK: jr $22 # encoding: [0x08,0x00,0xc0,0x02] + .set at=$s6 + jr $at + nop +# CHECK: jr $23 # encoding: [0x08,0x00,0xe0,0x02] + .set at=$s7 + jr $at + nop +# CHECK: jr $24 # encoding: [0x08,0x00,0x00,0x03] + .set at=$24 + jr $at + nop +# CHECK: jr $25 # encoding: [0x08,0x00,0x20,0x03] + .set at=$25 + jr $at + nop +# CHECK: jr $26 # encoding: [0x08,0x00,0x40,0x03] + .set at=$26 + jr $at + nop +# CHECK: jr $27 # encoding: [0x08,0x00,0x60,0x03] + .set at=$27 + jr $at + nop +# CHECK: jr $gp # encoding: [0x08,0x00,0x80,0x03] + .set at=$gp + jr $at + nop +# CHECK: jr $fp # encoding: [0x08,0x00,0xc0,0x03] + .set at=$fp + jr $at + nop +# CHECK: jr $sp # encoding: [0x08,0x00,0xa0,0x03] + .set at=$sp + jr $at + nop +# CHECK: jr $ra # encoding: [0x08,0x00,0xe0,0x03] + .set at=$ra + jr $at + nop