From b8c3bcbbfafc221b9d330ab67af49df3a74b45a0 Mon Sep 17 00:00:00 2001 From: Zoran Jovanovic Date: Fri, 16 May 2014 11:03:45 +0000 Subject: [PATCH] [mips][mips64r6] Add compact branch instructions Differential Revision: http://reviews.llvm.org/D3691 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@208974 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Mips/Disassembler/MipsDisassembler.cpp | 30 +++++ .../Mips/MCTargetDesc/MipsMCCodeEmitter.cpp | 40 +++++++ .../Mips/MCTargetDesc/MipsMCCodeEmitter.h | 14 +++ lib/Target/Mips/Mips32r6InstrFormats.td | 36 ++++++ lib/Target/Mips/Mips32r6InstrInfo.td | 109 ++++++++++++++++-- lib/Target/Mips/MipsCodeEmitter.cpp | 17 +++ test/MC/Mips/mips32r6/valid.s | 10 ++ test/MC/Mips/mips64r6/valid.s | 10 ++ 8 files changed, 256 insertions(+), 10 deletions(-) diff --git a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp index 958712602b4..21abe6c5857 100644 --- a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -205,6 +205,16 @@ static DecodeStatus DecodeJumpTarget(MCInst &Inst, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeBranchTarget21(MCInst &Inst, + unsigned Offset, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeBranchTarget26(MCInst &Inst, + unsigned Offset, + uint64_t Address, + const void *Decoder); + // DecodeBranchTargetMM - Decode microMIPS branch offset, which is // shifted left by 1 bit. static DecodeStatus DecodeBranchTargetMM(MCInst &Inst, @@ -856,6 +866,26 @@ static DecodeStatus DecodeJumpTarget(MCInst &Inst, return MCDisassembler::Success; } +static DecodeStatus DecodeBranchTarget21(MCInst &Inst, + unsigned Offset, + uint64_t Address, + const void *Decoder) { + int32_t BranchOffset = SignExtend32<21>(Offset) << 2; + + Inst.addOperand(MCOperand::CreateImm(BranchOffset)); + return MCDisassembler::Success; +} + +static DecodeStatus DecodeBranchTarget26(MCInst &Inst, + unsigned Offset, + uint64_t Address, + const void *Decoder) { + int32_t BranchOffset = SignExtend32<26>(Offset) << 2; + + Inst.addOperand(MCOperand::CreateImm(BranchOffset)); + return MCDisassembler::Success; +} + static DecodeStatus DecodeBranchTargetMM(MCInst &Inst, unsigned Offset, uint64_t Address, diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index 538a0cda9be..fc516188c3c 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -242,6 +242,46 @@ getBranchTargetOpValueMM(const MCInst &MI, unsigned OpNo, return 0; } +/// getBranchTarget21OpValue - Return binary encoding of the branch +/// target operand. If the machine operand requires relocation, +/// record the relocation and return zero. +unsigned MipsMCCodeEmitter:: +getBranchTarget21OpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + + const MCOperand &MO = MI.getOperand(OpNo); + + // If the destination is an immediate, divide by 4. + if (MO.isImm()) return MO.getImm() >> 2; + + assert(MO.isExpr() && + "getBranchTarget21OpValue expects only expressions or immediates"); + + // TODO: Push 21 PC fixup. + return 0; +} + +/// getBranchTarget26OpValue - Return binary encoding of the branch +/// target operand. If the machine operand requires relocation, +/// record the relocation and return zero. +unsigned MipsMCCodeEmitter:: +getBranchTarget26OpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + + const MCOperand &MO = MI.getOperand(OpNo); + + // If the destination is an immediate, divide by 4. + if (MO.isImm()) return MO.getImm() >> 2; + + assert(MO.isExpr() && + "getBranchTarget26OpValue expects only expressions or immediates"); + + // TODO: Push 26 PC fixup. + return 0; +} + /// getJumpTargetOpValue - Return binary encoding of the jump /// target operand. If the machine operand requires relocation, /// record the relocation and return zero. diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h index 735b0e43bbd..e99146e8015 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h +++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h @@ -88,6 +88,20 @@ public: SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + // getBranchTarget21OpValue - Return binary encoding of the branch + // offset operand. If the machine operand requires relocation, + // record the relocation and return zero. + unsigned getBranchTarget21OpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + // getBranchTarget26OpValue - Return binary encoding of the branch + // offset operand. If the machine operand requires relocation, + // record the relocation and return zero. + unsigned getBranchTarget26OpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + // getMachineOpValue - Return binary encoding of operand. If the machin // operand requires relocation, record the relocation and return zero. unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, diff --git a/lib/Target/Mips/Mips32r6InstrFormats.td b/lib/Target/Mips/Mips32r6InstrFormats.td index 4d49ca1812e..0f78eea18c0 100644 --- a/lib/Target/Mips/Mips32r6InstrFormats.td +++ b/lib/Target/Mips/Mips32r6InstrFormats.td @@ -191,6 +191,42 @@ class SPECIAL_3R_FM mulop, bits<6> funct> : MipsR6Inst { let Inst{5-0} = funct; } +class CMP_BRANCH_OFF16_FM funct> : MipsR6Inst { + bits<5> rs; + bits<5> rt; + bits<16> offset; + + bits<32> Inst; + + let Inst{31-26} = funct; + let Inst{25-21} = rs; + let Inst{20-16} = rt; + let Inst{15-0} = offset; +} + +class CMP_BRANCH_RT_OFF16_FM funct> : CMP_BRANCH_OFF16_FM { + let Inst{25-21} = 0b00000; +} + +class CMP_BRANCH_OFF21_FM funct> : MipsR6Inst { + bits<5> rs; + bits<21> offset; + + bits<32> Inst; + + let Inst{31-26} = funct; + let Inst{25-21} = rs; + let Inst{20-0} = offset; +} + +class BRANCH_OFF26_FM funct> : MipsR6Inst { + bits<32> Inst; + bits<26> offset; + + let Inst{31-26} = funct; + let Inst{25-0} = offset; +} + class SPECIAL3_ALIGN_FM : MipsR6Inst { bits<5> rd; bits<5> rs; diff --git a/lib/Target/Mips/Mips32r6InstrInfo.td b/lib/Target/Mips/Mips32r6InstrInfo.td index 9c57ed6c7ab..f37fd30461e 100644 --- a/lib/Target/Mips/Mips32r6InstrInfo.td +++ b/lib/Target/Mips/Mips32r6InstrInfo.td @@ -52,6 +52,20 @@ include "Mips32r6InstrFormats.td" // Removed: teqi, tgei, tgeiu, tlti, tltiu, tnei // Rencoded: [ls][wd]c2 +def brtarget21 : Operand { + let EncoderMethod = "getBranchTarget21OpValue"; + let OperandType = "OPERAND_PCREL"; + let DecoderMethod = "DecodeBranchTarget21"; + let ParserMatchClass = MipsJumpTargetAsmOperand; +} + +def brtarget26 : Operand { + let EncoderMethod = "getBranchTarget26OpValue"; + let OperandType = "OPERAND_PCREL"; + let DecoderMethod = "DecodeBranchTarget26"; + let ParserMatchClass = MipsJumpTargetAsmOperand; +} + //===----------------------------------------------------------------------===// // // Instruction Encodings @@ -63,6 +77,21 @@ class ALIGN_ENC : SPECIAL3_ALIGN_FM; class ALUIPC_ENC : PCREL16_FM; class AUI_ENC : AUI_FM; class AUIPC_ENC : PCREL16_FM; + +class BALC_ENC : BRANCH_OFF26_FM<0b111010>; +class BC_ENC : BRANCH_OFF26_FM<0b110010>; +class BEQC_ENC : CMP_BRANCH_OFF16_FM<0b001000>; +class BNEC_ENC : CMP_BRANCH_OFF16_FM<0b011000>; + +class BLTZC_ENC : CMP_BRANCH_OFF16_FM<0b010111>; +class BGEZC_ENC : CMP_BRANCH_OFF16_FM<0b010110>; + +class BLEZC_ENC : CMP_BRANCH_RT_OFF16_FM<0b010110>; +class BGTZC_ENC : CMP_BRANCH_RT_OFF16_FM<0b010111>; + +class BEQZC_ENC : CMP_BRANCH_OFF21_FM<0b110110>; +class BNEZC_ENC : CMP_BRANCH_OFF21_FM<0b111110>; + class BITSWAP_ENC : SPECIAL3_2R_FM; class DIV_ENC : SPECIAL_3R_FM<0b00010, 0b011010>; class DIVU_ENC : SPECIAL_3R_FM<0b00010, 0b011011>; @@ -215,6 +244,66 @@ class AUI_DESC_BASE { class AUI_DESC : AUI_DESC_BASE<"aui", GPR32Opnd>; +class BRANCH_DESC_BASE { + bit isBranch = 1; + bit isTerminator = 1; + bit hasDelaySlot = 0; +} + +class BC_DESC_BASE : BRANCH_DESC_BASE { + dag InOperandList = (ins opnd:$offset); + dag OutOperandList = (outs); + string AsmString = !strconcat(instr_asm, "\t$offset"); + bit isBarrier = 1; +} + +class CMP_BC_DESC_BASE : BRANCH_DESC_BASE { + dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt, opnd:$offset); + dag OutOperandList = (outs); + string AsmString = !strconcat(instr_asm, "\t$rs, $rt, $offset"); + list Defs = [AT]; +} + +class CMP_CBR_EQNE_Z_DESC_BASE : BRANCH_DESC_BASE { + dag InOperandList = (ins GPROpnd:$rs, opnd:$offset); + dag OutOperandList = (outs); + string AsmString = !strconcat(instr_asm, "\t$rs, $offset"); + list Defs = [AT]; +} + +class CMP_CBR_RT_Z_DESC_BASE : BRANCH_DESC_BASE { + dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt, opnd:$offset); + dag OutOperandList = (outs); + string AsmString = !strconcat(instr_asm, "\t$rt, $offset"); + list Defs = [AT]; +} + +class BALC_DESC : BC_DESC_BASE<"balc", brtarget26> { + bit isCall = 1; + list Defs = [RA]; +} + +class BC_DESC : BC_DESC_BASE<"bc", brtarget26>; +class BEQC_DESC : CMP_BC_DESC_BASE<"beqc", brtarget, GPR32Opnd>; +class BNEC_DESC : CMP_BC_DESC_BASE<"bnec", brtarget, GPR32Opnd>; + +class BLTZC_DESC : CMP_CBR_RT_Z_DESC_BASE<"bltzc", brtarget, GPR32Opnd> { + string Constraints = "$rs = $rt"; +} + +class BGEZC_DESC : CMP_CBR_RT_Z_DESC_BASE<"bgezc", brtarget, GPR32Opnd> { + string Constraints = "$rs = $rt"; +} + +class BLEZC_DESC : CMP_CBR_RT_Z_DESC_BASE<"blezc", brtarget, GPR32Opnd>; +class BGTZC_DESC : CMP_CBR_RT_Z_DESC_BASE<"bgtzc", brtarget, GPR32Opnd>; + +class BEQZC_DESC : CMP_CBR_EQNE_Z_DESC_BASE<"beqzc", brtarget21, GPR32Opnd>; +class BNEZC_DESC : CMP_CBR_EQNE_Z_DESC_BASE<"bnezc", brtarget21, GPR32Opnd>; + class BITSWAP_DESC_BASE { dag OutOperandList = (outs GPROpnd:$rd); dag InOperandList = (ins GPROpnd:$rt); @@ -316,31 +405,31 @@ def ALIGN : ALIGN_ENC, ALIGN_DESC, ISA_MIPS32R6; def ALUIPC : ALUIPC_ENC, ALUIPC_DESC, ISA_MIPS32R6; def AUI : AUI_ENC, AUI_DESC, ISA_MIPS32R6; def AUIPC : AUIPC_ENC, AUIPC_DESC, ISA_MIPS32R6; -def BALC; +def BALC : BALC_ENC, BALC_DESC, ISA_MIPS32R6; def BC1EQZ; def BC1NEZ; def BC2EQZ; def BC2NEZ; -def BC; -def BEQC; +def BC : BC_ENC, BC_DESC, ISA_MIPS32R6; +def BEQC : BEQC_ENC, BEQC_DESC, ISA_MIPS32R6; def BEQZALC; -def BEQZC; +def BEQZC : BEQZC_ENC, BEQZC_DESC, ISA_MIPS32R6; def BGEC; // Also aliased to blec with operands swapped def BGEUC; // Also aliased to bleuc with operands swapped def BGEZALC; -def BGEZC; +def BGEZC : BGEZC_ENC, BGEZC_DESC, ISA_MIPS32R6; def BGTZALC; -def BGTZC; +def BGTZC : BGTZC_ENC, BGTZC_DESC, ISA_MIPS32R6; def BITSWAP : BITSWAP_ENC, BITSWAP_DESC, ISA_MIPS32R6; def BLEZALC; -def BLEZC; +def BLEZC : BLEZC_ENC, BLEZC_DESC, ISA_MIPS32R6; def BLTC; // Also aliased to bgtc with operands swapped def BLTUC; // Also aliased to bgtuc with operands swapped def BLTZALC; -def BLTZC; -def BNEC; +def BLTZC : BLTZC_ENC, BLTZC_DESC, ISA_MIPS32R6; +def BNEC : BNEC_ENC, BNEC_DESC, ISA_MIPS32R6; def BNEZALC; -def BNEZC; +def BNEZC : BNEZC_ENC, BNEZC_DESC, ISA_MIPS32R6; def BNVC; def BOVC; def CLASS_D : CLASS_D_ENC, CLASS_D_DESC, ISA_MIPS32R6; diff --git a/lib/Target/Mips/MipsCodeEmitter.cpp b/lib/Target/Mips/MipsCodeEmitter.cpp index d13a4661f33..ebbcd0cdb8e 100644 --- a/lib/Target/Mips/MipsCodeEmitter.cpp +++ b/lib/Target/Mips/MipsCodeEmitter.cpp @@ -110,6 +110,11 @@ private: unsigned getBranchTargetOpValueMM(const MachineInstr &MI, unsigned OpNo) const; + unsigned getBranchTarget21OpValue(const MachineInstr &MI, + unsigned OpNo) const; + unsigned getBranchTarget26OpValue(const MachineInstr &MI, + unsigned OpNo) const; + unsigned getBranchTargetOpValue(const MachineInstr &MI, unsigned OpNo) const; unsigned getMemEncoding(const MachineInstr &MI, unsigned OpNo) const; unsigned getMemEncodingMMImm12(const MachineInstr &MI, unsigned OpNo) const; @@ -203,6 +208,18 @@ unsigned MipsCodeEmitter::getBranchTargetOpValueMM(const MachineInstr &MI, return 0; } +unsigned MipsCodeEmitter::getBranchTarget21OpValue(const MachineInstr &MI, + unsigned OpNo) const { + llvm_unreachable("Unimplemented function."); + return 0; +} + +unsigned MipsCodeEmitter::getBranchTarget26OpValue(const MachineInstr &MI, + unsigned OpNo) const { + llvm_unreachable("Unimplemented function."); + return 0; +} + unsigned MipsCodeEmitter::getBranchTargetOpValue(const MachineInstr &MI, unsigned OpNo) const { MachineOperand MO = MI.getOperand(OpNo); diff --git a/test/MC/Mips/mips32r6/valid.s b/test/MC/Mips/mips32r6/valid.s index b83cbe1a4d7..6f94ad3cc14 100644 --- a/test/MC/Mips/mips32r6/valid.s +++ b/test/MC/Mips/mips32r6/valid.s @@ -9,6 +9,16 @@ aluipc $3, 56 # CHECK: aluipc $3, 56 # encoding: [0xec,0x7f,0x00,0x38] aui $3,$2,-23 # CHECK: aui $3, $2, -23 # encoding: [0x3c,0x62,0xff,0xe9] auipc $3, -1 # CHECK: auipc $3, -1 # encoding: [0xec,0x7e,0xff,0xff] + balc 14572256 # CHECK: balc 14572256 # encoding: [0xe8,0x37,0x96,0xb8] + bc 14572256 # CHECK: bc 14572256 # encoding: [0xc8,0x37,0x96,0xb8] + beqc $5, $6, 256 # CHECK: beqc $5, $6, 256 # encoding: [0x20,0xa6,0x00,0x40] + bnec $5, $6, 256 # CHECK: bnec $5, $6, 256 # encoding: [0x60,0xa6,0x00,0x40] + beqzc $5, 72256 # CHECK: beqzc $5, 72256 # encoding: [0xd8,0xa0,0x46,0x90] + bnezc $5, 72256 # CHECK: bnezc $5, 72256 # encoding: [0xf8,0xa0,0x46,0x90] + bltzc $5, 256 # CHECK: bltzc $5, 256 # encoding: [0x5c,0xa5,0x00,0x40] + bgezc $5, 256 # CHECK: bgezc $5, 256 # encoding: [0x58,0xa5,0x00,0x40] + blezc $5, 256 # CHECK: blezc $5, 256 # encoding: [0x58,0x05,0x00,0x40] + bgtzc $5, 256 # CHECK: bgtzc $5, 256 # encoding: [0x5c,0x05,0x00,0x40] bitswap $4, $2 # CHECK: bitswap $4, $2 # encoding: [0x7c,0x02,0x20,0x20] cmp.f.s $f2,$f3,$f4 # CHECK: cmp.f.s $f2, $f3, $f4 # encoding: [0x46,0x84,0x18,0x80] cmp.f.d $f2,$f3,$f4 # CHECK: cmp.f.d $f2, $f3, $f4 # encoding: [0x46,0xa4,0x18,0x80] diff --git a/test/MC/Mips/mips64r6/valid.s b/test/MC/Mips/mips64r6/valid.s index 1551e5f3422..f341df65427 100644 --- a/test/MC/Mips/mips64r6/valid.s +++ b/test/MC/Mips/mips64r6/valid.s @@ -9,6 +9,16 @@ aluipc $3, 56 # CHECK: aluipc $3, 56 # encoding: [0xec,0x7f,0x00,0x38] aui $3,$2,-23 # CHECK: aui $3, $2, -23 # encoding: [0x3c,0x62,0xff,0xe9] auipc $3, -1 # CHECK: auipc $3, -1 # encoding: [0xec,0x7e,0xff,0xff] + balc 14572256 # CHECK: balc 14572256 # encoding: [0xe8,0x37,0x96,0xb8] + bc 14572256 # CHECK: bc 14572256 # encoding: [0xc8,0x37,0x96,0xb8] + beqc $5, $6, 256 # CHECK: beqc $5, $6, 256 # encoding: [0x20,0xa6,0x00,0x40] + bnec $5, $6, 256 # CHECK: bnec $5, $6, 256 # encoding: [0x60,0xa6,0x00,0x40] + beqzc $5, 72256 # CHECK: beqzc $5, 72256 # encoding: [0xd8,0xa0,0x46,0x90] + bnezc $5, 72256 # CHECK: bnezc $5, 72256 # encoding: [0xf8,0xa0,0x46,0x90] + bltzc $5, 256 # CHECK: bltzc $5, 256 # encoding: [0x5c,0xa5,0x00,0x40] + bgezc $5, 256 # CHECK: bgezc $5, 256 # encoding: [0x58,0xa5,0x00,0x40] + blezc $5, 256 # CHECK: blezc $5, 256 # encoding: [0x58,0x05,0x00,0x40] + bgtzc $5, 256 # CHECK: bgtzc $5, 256 # encoding: [0x5c,0x05,0x00,0x40] bitswap $4, $2 # CHECK: bitswap $4, $2 # encoding: [0x7c,0x02,0x20,0x20] cmp.f.s $f2,$f3,$f4 # CHECK: cmp.f.s $f2, $f3, $f4 # encoding: [0x46,0x84,0x18,0x80] cmp.f.d $f2,$f3,$f4 # CHECK: cmp.f.d $f2, $f3, $f4 # encoding: [0x46,0xa4,0x18,0x80] -- 2.34.1