diff options
Diffstat (limited to 'llvm/lib/Target/Sparc')
-rw-r--r-- | llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp | 8 | ||||
-rw-r--r-- | llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp | 47 | ||||
-rw-r--r-- | llvm/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp | 22 | ||||
-rw-r--r-- | llvm/lib/Target/Sparc/Sparc.h | 35 | ||||
-rw-r--r-- | llvm/lib/Target/Sparc/SparcInstrAliases.td | 117 | ||||
-rw-r--r-- | llvm/lib/Target/Sparc/SparcInstrInfo.cpp | 22 | ||||
-rw-r--r-- | llvm/lib/Target/Sparc/SparcInstrInfo.td | 14 |
7 files changed, 223 insertions, 42 deletions
diff --git a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp index 94f1e67f588..37410c9dcd8 100644 --- a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +++ b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp @@ -636,8 +636,12 @@ bool SparcAsmParser::ParseInstruction(ParseInstructionInfo &Info, return Error(Loc, "unexpected token"); } - while (getLexer().is(AsmToken::Comma)) { - Parser.Lex(); // Eat the comma. + while (getLexer().is(AsmToken::Comma) || getLexer().is(AsmToken::Plus)) { + if (getLexer().is(AsmToken::Plus)) { + // Plus tokens are significant in software_traps (p83, sparcv8.pdf). We must capture them. + Operands.push_back(SparcOperand::CreateToken("+", Parser.getTok().getLoc())); + } + Parser.Lex(); // Eat the comma or plus. // Parse and remember the operand. if (parseOperand(Operands, Name) != MatchOperand_Success) { SMLoc Loc = getLexer().getLoc(); diff --git a/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp b/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp index 44d35764003..1dea379e14e 100644 --- a/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp +++ b/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp @@ -311,6 +311,8 @@ static DecodeStatus DecodeReturn(MCInst &MI, unsigned insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeSWAP(MCInst &Inst, unsigned insn, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeTRAP(MCInst &Inst, unsigned insn, uint64_t Address, + const void *Decoder); #include "SparcGenDisassemblerTables.inc" @@ -346,6 +348,18 @@ DecodeStatus SparcDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, return MCDisassembler::Fail; // Calling the auto-generated decoder function. + + if (STI.getFeatureBits()[Sparc::FeatureV9]) + { + Result = decodeInstruction(DecoderTableSparcV932, Instr, Insn, Address, this, STI); + } + else + { + Result = decodeInstruction(DecoderTableSparcV832, Instr, Insn, Address, this, STI); + } + if (Result != MCDisassembler::Fail) + return Result; + Result = decodeInstruction(DecoderTableSparc32, Instr, Insn, Address, this, STI); @@ -619,3 +633,36 @@ static DecodeStatus DecodeSWAP(MCInst &MI, unsigned insn, uint64_t Address, return MCDisassembler::Success; } + +static DecodeStatus DecodeTRAP(MCInst &MI, unsigned insn, uint64_t Address, + const void *Decoder) { + + unsigned rs1 = fieldFromInstruction(insn, 14, 5); + unsigned isImm = fieldFromInstruction(insn, 13, 1); + unsigned cc =fieldFromInstruction(insn, 25, 4); + unsigned rs2 = 0; + unsigned imm7 = 0; + if (isImm) + imm7 = fieldFromInstruction(insn, 0, 7); + else + rs2 = fieldFromInstruction(insn, 0, 5); + + // Decode RS1. + DecodeStatus status = DecodeIntRegsRegisterClass(MI, rs1, Address, Decoder); + if (status != MCDisassembler::Success) + return status; + + // Decode RS1 | IMM7. + if (isImm) + MI.addOperand(MCOperand::createImm(imm7)); + else { + status = DecodeIntRegsRegisterClass(MI, rs2, Address, Decoder); + if (status != MCDisassembler::Success) + return status; + } + + // Decode CC + MI.addOperand(MCOperand::createImm(cc)); + + return MCDisassembler::Success; +} diff --git a/llvm/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp b/llvm/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp index 5d714fe4da9..554f32745f8 100644 --- a/llvm/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp +++ b/llvm/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp @@ -115,8 +115,21 @@ void SparcInstPrinter::printOperand(const MCInst *MI, int opNum, } if (MO.isImm()) { - O << (int)MO.getImm(); - return; + switch (MI->getOpcode()) { + default: + O << (int)MO.getImm(); + return; + + case SP::TICCri: // Fall through + case SP::TICCrr: // Fall through + case SP::TRAPri: // Fall through + case SP::TRAPrr: // Fall through + case SP::TXCCri: // Fall through + case SP::TXCCrr: // Fall through + // Only seven-bit values up to 127. + O << ((int) MO.getImm() & 0x7f); + return; + } } assert(MO.isExpr() && "Unknown operand kind in printOperand"); @@ -166,6 +179,11 @@ void SparcInstPrinter::printCCOperand(const MCInst *MI, int opNum, // Make sure CC is a fp conditional flag. CC = (CC < 16) ? (CC + 16) : CC; break; + case SP::CBCOND: + case SP::CBCONDA: + // Make sure CC is a cp conditional flag. + CC = (CC < 32) ? (CC + 32) : CC; + break; } O << SPARCCondCodeToString((SPCC::CondCodes)CC); } diff --git a/llvm/lib/Target/Sparc/Sparc.h b/llvm/lib/Target/Sparc/Sparc.h index 96378d522dc..0a8272d8929 100644 --- a/llvm/lib/Target/Sparc/Sparc.h +++ b/llvm/lib/Target/Sparc/Sparc.h @@ -72,7 +72,24 @@ namespace llvm { FCC_UGE = 12+16, // Unordered or Greater or Equal FCC_LE = 13+16, // Less or Equal FCC_ULE = 14+16, // Unordered or Less or Equal - FCC_O = 15+16 // Ordered + FCC_O = 15+16, // Ordered + + CPCC_A = 8+32, // Always + CPCC_N = 0+32, // Never + CPCC_3 = 7+32, + CPCC_2 = 6+32, + CPCC_23 = 5+32, + CPCC_1 = 4+32, + CPCC_13 = 3+32, + CPCC_12 = 2+32, + CPCC_123 = 1+32, + CPCC_0 = 9+32, + CPCC_03 = 10+32, + CPCC_02 = 11+32, + CPCC_023 = 12+32, + CPCC_01 = 13+32, + CPCC_013 = 14+32, + CPCC_012 = 15+32 }; } @@ -110,6 +127,22 @@ namespace llvm { case SPCC::FCC_LE: return "le"; case SPCC::FCC_ULE: return "ule"; case SPCC::FCC_O: return "o"; + case SPCC::CPCC_A: return "a"; + case SPCC::CPCC_N: return "n"; + case SPCC::CPCC_3: return "3"; + case SPCC::CPCC_2: return "2"; + case SPCC::CPCC_23: return "23"; + case SPCC::CPCC_1: return "1"; + case SPCC::CPCC_13: return "13"; + case SPCC::CPCC_12: return "12"; + case SPCC::CPCC_123: return "123"; + case SPCC::CPCC_0: return "0"; + case SPCC::CPCC_03: return "03"; + case SPCC::CPCC_02: return "02"; + case SPCC::CPCC_023: return "023"; + case SPCC::CPCC_01: return "01"; + case SPCC::CPCC_013: return "013"; + case SPCC::CPCC_012: return "012"; } llvm_unreachable("Invalid cond code"); } diff --git a/llvm/lib/Target/Sparc/SparcInstrAliases.td b/llvm/lib/Target/Sparc/SparcInstrAliases.td index 361d21440a9..df570cea8da 100644 --- a/llvm/lib/Target/Sparc/SparcInstrAliases.td +++ b/llvm/lib/Target/Sparc/SparcInstrAliases.td @@ -136,59 +136,68 @@ multiclass int_cond_alias<string cond, int condVal> { (FMOVQ_XCC QFPRegs:$rd, QFPRegs:$rs2, condVal)>, Requires<[Is64Bit, HasHardQuad]>; - // t<cond> %icc, rs1 + rs2 - def : InstAlias<!strconcat(!strconcat("t", cond), " %icc, $rs1 + $rs2"), - (TICCrr IntRegs:$rs1, IntRegs:$rs2, condVal)>, - Requires<[HasV9]>; - // t<cond> %icc, rs => t<cond> %icc, G0 + rs def : InstAlias<!strconcat(!strconcat("t", cond), " %icc, $rs2"), (TICCrr G0, IntRegs:$rs2, condVal)>, Requires<[HasV9]>; - - // t<cond> %xcc, rs1 + rs2 - def : InstAlias<!strconcat(!strconcat("t", cond), " %xcc, $rs1 + $rs2"), - (TXCCrr IntRegs:$rs1, IntRegs:$rs2, condVal)>, + // t<cond> %icc, rs1 + rs2 + def : InstAlias<!strconcat(!strconcat("t", cond), " %icc, $rs1 + $rs2"), + (TICCrr IntRegs:$rs1, IntRegs:$rs2, condVal)>, Requires<[HasV9]>; + // t<cond> %xcc, rs => t<cond> %xcc, G0 + rs def : InstAlias<!strconcat(!strconcat("t", cond), " %xcc, $rs2"), (TXCCrr G0, IntRegs:$rs2, condVal)>, Requires<[HasV9]>; + // t<cond> %xcc, rs1 + rs2 + def : InstAlias<!strconcat(!strconcat("t", cond), " %xcc, $rs1 + $rs2"), + (TXCCrr IntRegs:$rs1, IntRegs:$rs2, condVal)>, + Requires<[HasV9]>; - // t<cond> rs1 + rs2 => t<cond> %icc, rs1 + rs2 - def : InstAlias<!strconcat(!strconcat("t", cond), " $rs1 + $rs2"), - (TICCrr IntRegs:$rs1, IntRegs:$rs2, condVal)>; // t<cond> rs=> t<cond> %icc, G0 + rs2 - def : InstAlias<!strconcat(!strconcat("t", cond), " $rs2"), - (TICCrr G0, IntRegs:$rs2, condVal)>; + //def : InstAlias<!strconcat(!strconcat("t", cond), " $rs2"), + // (TICCrr G0, IntRegs:$rs2, condVal)>, + // Requires<[HasV9]>; + + // t<cond> rs1 + rs2 => t<cond> %icc, rs1 + rs2 + //def : InstAlias<!strconcat(!strconcat("t", cond), " $rs1 + $rs2"), + // (TICCrr IntRegs:$rs1, IntRegs:$rs2, condVal)>, + // Requires<[HasV9]>; - // t<cond> %icc, rs1 + imm - def : InstAlias<!strconcat(!strconcat("t", cond), " %icc, $rs1 + $imm"), - (TICCri IntRegs:$rs1, i32imm:$imm, condVal)>, - Requires<[HasV9]>; // t<cond> %icc, imm => t<cond> %icc, G0 + imm def : InstAlias<!strconcat(!strconcat("t", cond), " %icc, $imm"), (TICCri G0, i32imm:$imm, condVal)>, Requires<[HasV9]>; - // t<cond> %xcc, rs1 + imm - def : InstAlias<!strconcat(!strconcat("t", cond), " %xcc, $rs1 + $imm"), - (TXCCri IntRegs:$rs1, i32imm:$imm, condVal)>, + // t<cond> %icc, rs1 + imm + def : InstAlias<!strconcat(!strconcat("t", cond), " %icc, $rs1 + $imm"), + (TICCri IntRegs:$rs1, i32imm:$imm, condVal)>, Requires<[HasV9]>; // t<cond> %xcc, imm => t<cond> %xcc, G0 + imm def : InstAlias<!strconcat(!strconcat("t", cond), " %xcc, $imm"), (TXCCri G0, i32imm:$imm, condVal)>, Requires<[HasV9]>; + // t<cond> %xcc, rs1 + imm + def : InstAlias<!strconcat(!strconcat("t", cond), " %xcc, $rs1 + $imm"), + (TXCCri IntRegs:$rs1, i32imm:$imm, condVal)>, + Requires<[HasV9]>; + + // t<cond> imm => t<cond> G0 + imm + def : InstAlias<!strconcat(!strconcat("t", cond), " $imm"), + (TRAPri G0, i32imm:$imm, condVal)>; - // t<cond> rs1 + imm => t<cond> %icc, rs1 + imm + // t<cond> rs1 + imm => t<cond> rs1 + imm def : InstAlias<!strconcat(!strconcat("t", cond), " $rs1 + $imm"), - (TICCri IntRegs:$rs1, i32imm:$imm, condVal)>; + (TRAPri IntRegs:$rs1, i32imm:$imm, condVal)>; - // t<cond> imm => t<cond> %icc, G0 + imm - def : InstAlias<!strconcat(!strconcat("t", cond), " $imm"), - (TICCri G0, i32imm:$imm, condVal)>; + // t<cond> rs1 => t<cond> G0 + rs1 + def : InstAlias<!strconcat(!strconcat("t", cond), " $rs1"), + (TRAPrr G0, IntRegs:$rs1, condVal)>; + // t<cond> rs1 + rs2 + def : InstAlias<!strconcat(!strconcat("t", cond), " $rs1 + $rs2"), + (TRAPrr IntRegs:$rs1, IntRegs:$rs2, condVal)>; } @@ -244,14 +253,23 @@ multiclass fp_cond_alias<string cond, int condVal> { Requires<[HasV9, HasHardQuad]>; } + +// Instruction aliases for co-processor conditional branches. +multiclass cp_cond_alias<string cond, int condVal> { + + // cb<cond> $imm + def : InstAlias<!strconcat(!strconcat("cb", cond), " $imm"), + (CBCOND brtarget:$imm, condVal), 0>; + + // cb<cond>,a $imm + def : InstAlias<!strconcat(!strconcat("cb", cond), ",a $imm"), + (CBCONDA brtarget:$imm, condVal), 0>; +} + defm : int_cond_alias<"a", 0b1000>; -defm : int_cond_alias<"", 0b1000>; // same as a; gnu asm, not in manual defm : int_cond_alias<"n", 0b0000>; defm : int_cond_alias<"ne", 0b1001>; -defm : int_cond_alias<"nz", 0b1001>; // same as ne defm : int_cond_alias<"e", 0b0001>; -defm : int_cond_alias<"eq", 0b0001>; // same as e -defm : int_cond_alias<"z", 0b0001>; // same as e defm : int_cond_alias<"g", 0b1010>; defm : int_cond_alias<"le", 0b0010>; defm : int_cond_alias<"ge", 0b1011>; @@ -259,16 +277,21 @@ defm : int_cond_alias<"l", 0b0011>; defm : int_cond_alias<"gu", 0b1100>; defm : int_cond_alias<"leu", 0b0100>; defm : int_cond_alias<"cc", 0b1101>; -defm : int_cond_alias<"geu", 0b1101>; // same as cc defm : int_cond_alias<"cs", 0b0101>; -defm : int_cond_alias<"lu", 0b0101>; // same as cs defm : int_cond_alias<"pos", 0b1110>; defm : int_cond_alias<"neg", 0b0110>; defm : int_cond_alias<"vc", 0b1111>; defm : int_cond_alias<"vs", 0b0111>; - +let EmitPriority = 0 in +{ + defm : int_cond_alias<"", 0b1000>; // same as a; gnu asm, not in manual + defm : int_cond_alias<"nz", 0b1001>; // same as ne + defm : int_cond_alias<"eq", 0b0001>; // same as e + defm : int_cond_alias<"z", 0b0001>; // same as e + defm : int_cond_alias<"geu", 0b1101>; // same as cc + defm : int_cond_alias<"lu", 0b0101>; // same as cs +} defm : fp_cond_alias<"a", 0b1000>; -defm : fp_cond_alias<"", 0b1000>; // same as a; gnu asm, not in manual defm : fp_cond_alias<"n", 0b0000>; defm : fp_cond_alias<"u", 0b0111>; defm : fp_cond_alias<"g", 0b0110>; @@ -277,15 +300,37 @@ defm : fp_cond_alias<"l", 0b0100>; defm : fp_cond_alias<"ul", 0b0011>; defm : fp_cond_alias<"lg", 0b0010>; defm : fp_cond_alias<"ne", 0b0001>; -defm : fp_cond_alias<"nz", 0b0001>; // same as ne defm : fp_cond_alias<"e", 0b1001>; -defm : fp_cond_alias<"z", 0b1001>; // same as e defm : fp_cond_alias<"ue", 0b1010>; defm : fp_cond_alias<"ge", 0b1011>; defm : fp_cond_alias<"uge", 0b1100>; defm : fp_cond_alias<"le", 0b1101>; defm : fp_cond_alias<"ule", 0b1110>; defm : fp_cond_alias<"o", 0b1111>; +let EmitPriority = 0 in +{ + defm : fp_cond_alias<"", 0b1000>; // same as a; gnu asm, not in manual + defm : fp_cond_alias<"nz", 0b0001>; // same as ne + defm : fp_cond_alias<"z", 0b1001>; // same as e +} + +defm : cp_cond_alias<"a", 0b1000>; +defm : cp_cond_alias<"n", 0b0000>; +defm : cp_cond_alias<"3", 0b0111>; +defm : cp_cond_alias<"2", 0b0110>; +defm : cp_cond_alias<"23", 0b0101>; +defm : cp_cond_alias<"1", 0b0100>; +defm : cp_cond_alias<"13", 0b0011>; +defm : cp_cond_alias<"12", 0b0010>; +defm : cp_cond_alias<"123", 0b0001>; +defm : cp_cond_alias<"0", 0b1001>; +defm : cp_cond_alias<"03", 0b1010>; +defm : cp_cond_alias<"02", 0b1011>; +defm : cp_cond_alias<"023", 0b1100>; +defm : cp_cond_alias<"01", 0b1101>; +defm : cp_cond_alias<"013", 0b1110>; +defm : cp_cond_alias<"012", 0b1111>; +let EmitPriority = 0 in defm : cp_cond_alias<"", 0b1000>; // same as a; gnu asm, not in manual // Section A.3 Synthetic Instructions diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.cpp b/llvm/lib/Target/Sparc/SparcInstrInfo.cpp index 0a123185ca6..28b81b608b3 100644 --- a/llvm/lib/Target/Sparc/SparcInstrInfo.cpp +++ b/llvm/lib/Target/Sparc/SparcInstrInfo.cpp @@ -119,6 +119,28 @@ static SPCC::CondCodes GetOppositeBranchCondition(SPCC::CondCodes CC) case SPCC::FCC_UE: return SPCC::FCC_LG; case SPCC::FCC_NE: return SPCC::FCC_E; case SPCC::FCC_E: return SPCC::FCC_NE; + + case SPCC::CPCC_A: return SPCC::CPCC_N; + case SPCC::CPCC_N: return SPCC::CPCC_A; + case SPCC::CPCC_3: // Fall through + case SPCC::CPCC_2: // Fall through + case SPCC::CPCC_23: // Fall through + case SPCC::CPCC_1: // Fall through + case SPCC::CPCC_13: // Fall through + case SPCC::CPCC_12: // Fall through + case SPCC::CPCC_123: // Fall through + case SPCC::CPCC_0: // Fall through + case SPCC::CPCC_03: // Fall through + case SPCC::CPCC_02: // Fall through + case SPCC::CPCC_023: // Fall through + case SPCC::CPCC_01: // Fall through + case SPCC::CPCC_013: // Fall through + case SPCC::CPCC_012: + // "Opposite" code is not meaningful, as we don't know + // what the CoProc condition means here. The cond-code will + // only be used in inline assembler, so this code should + // not be reached in a normal compilation pass. + llvm_unreachable("Meaningless inversion of co-processor cond code"); } llvm_unreachable("Invalid cond code"); } diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.td b/llvm/lib/Target/Sparc/SparcInstrInfo.td index de111246f62..269c9631f95 100644 --- a/llvm/lib/Target/Sparc/SparcInstrInfo.td +++ b/llvm/lib/Target/Sparc/SparcInstrInfo.td @@ -891,6 +891,17 @@ let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, // Section B.27 - Trap on Integer Condition Codes Instruction +// conditional branch class: +let DecoderNamespace = "SparcV8", DecoderMethod = "DecodeTRAP", hasSideEffects = 1, Uses = [ICC], cc = 0b00 in +{ + def TRAPrr : TRAPSPrr<0b111010, (outs), (ins IntRegs:$rs1, IntRegs:$rs2, + CCOp:$cond), + "t$cond $rs1 + $rs2", []>; + def TRAPri : TRAPSPri<0b111010, (outs), (ins IntRegs:$rs1, i32imm:$imm, + CCOp:$cond), + "t$cond $rs1 + $imm", []>; +} + multiclass TRAP<string regStr> { def rr : TRAPSPrr<0b111010, (outs), (ins IntRegs:$rs1, IntRegs:$rs2, CCOp:$cond), @@ -900,9 +911,10 @@ multiclass TRAP<string regStr> { !strconcat(!strconcat("t$cond ", regStr), ", $rs1 + $imm"), []>; } -let hasSideEffects = 1, Uses = [ICC], cc = 0b00 in +let DecoderNamespace = "SparcV9", DecoderMethod = "DecodeTRAP", Predicates = [HasV9], hasSideEffects = 1, Uses = [ICC], cc = 0b00 in defm TICC : TRAP<"%icc">; + let isBarrier = 1, isTerminator = 1, rd = 0b01000, rs1 = 0, simm13 = 5 in def TA5 : F3_2<0b10, 0b111010, (outs), (ins), "ta 5", [(trap)]>; |