mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-13 09:33:50 +00:00
[mips][microMIPS] Implement BEQZ16 and BNEZ16 instructions
Differential Revision: http://reviews.llvm.org/D5271 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225627 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
7a95c03b1d
commit
ad017096fc
@ -1207,6 +1207,17 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
|
||||
1LL << (inMicroMipsMode() ? 1 : 2)))
|
||||
return Error(IDLoc, "branch to misaligned address");
|
||||
break;
|
||||
case Mips::BEQZ16_MM:
|
||||
case Mips::BNEZ16_MM:
|
||||
assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
|
||||
Offset = Inst.getOperand(1);
|
||||
if (!Offset.isImm())
|
||||
break; // We'll deal with this situation later on when applying fixups.
|
||||
if (!isIntN(8, Offset.getImm()))
|
||||
return Error(IDLoc, "branch target out of range");
|
||||
if (OffsetToAlignment(Offset.getImm(), 2LL))
|
||||
return Error(IDLoc, "branch to misaligned address");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -228,6 +228,13 @@ static DecodeStatus DecodeBranchTarget26(MCInst &Inst,
|
||||
uint64_t Address,
|
||||
const void *Decoder);
|
||||
|
||||
// DecodeBranchTarget7MM - Decode microMIPS branch offset, which is
|
||||
// shifted left by 1 bit.
|
||||
static DecodeStatus DecodeBranchTarget7MM(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,
|
||||
@ -1540,6 +1547,15 @@ static DecodeStatus DecodeBranchTarget26(MCInst &Inst,
|
||||
return MCDisassembler::Success;
|
||||
}
|
||||
|
||||
static DecodeStatus DecodeBranchTarget7MM(MCInst &Inst,
|
||||
unsigned Offset,
|
||||
uint64_t Address,
|
||||
const void *Decoder) {
|
||||
int32_t BranchOffset = SignExtend32<7>(Offset) << 1;
|
||||
Inst.addOperand(MCOperand::CreateImm(BranchOffset));
|
||||
return MCDisassembler::Success;
|
||||
}
|
||||
|
||||
static DecodeStatus DecodeBranchTargetMM(MCInst &Inst,
|
||||
unsigned Offset,
|
||||
uint64_t Address,
|
||||
|
@ -103,6 +103,14 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
|
||||
case Mips::fixup_MICROMIPS_26_S1:
|
||||
Value >>= 1;
|
||||
break;
|
||||
case Mips::fixup_MICROMIPS_PC7_S1:
|
||||
Value -= 4;
|
||||
// Forcing a signed division because Value can be negative.
|
||||
Value = (int64_t) Value / 2;
|
||||
// We now check if Value can be encoded as a 7-bit signed immediate.
|
||||
if (!isIntN(7, Value) && Ctx)
|
||||
Ctx->FatalError(Fixup.getLoc(), "out of range PC7 fixup");
|
||||
break;
|
||||
case Mips::fixup_MICROMIPS_PC16_S1:
|
||||
Value -= 4;
|
||||
// Forcing a signed division because Value can be negative.
|
||||
@ -271,6 +279,7 @@ getFixupKindInfo(MCFixupKind Kind) const {
|
||||
{ "fixup_MICROMIPS_HI16", 0, 16, 0 },
|
||||
{ "fixup_MICROMIPS_LO16", 0, 16, 0 },
|
||||
{ "fixup_MICROMIPS_GOT16", 0, 16, 0 },
|
||||
{ "fixup_MICROMIPS_PC7_S1", 0, 7, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_MICROMIPS_PC16_S1", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_MICROMIPS_CALL16", 0, 16, 0 },
|
||||
{ "fixup_MICROMIPS_GOT_DISP", 0, 16, 0 },
|
||||
@ -334,6 +343,7 @@ getFixupKindInfo(MCFixupKind Kind) const {
|
||||
{ "fixup_MICROMIPS_HI16", 16, 16, 0 },
|
||||
{ "fixup_MICROMIPS_LO16", 16, 16, 0 },
|
||||
{ "fixup_MICROMIPS_GOT16", 16, 16, 0 },
|
||||
{ "fixup_MICROMIPS_PC7_S1", 9, 7, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_MICROMIPS_PC16_S1",16, 16, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_MICROMIPS_CALL16", 16, 16, 0 },
|
||||
{ "fixup_MICROMIPS_GOT_DISP", 16, 16, 0 },
|
||||
|
@ -162,6 +162,9 @@ unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target,
|
||||
case Mips::fixup_MICROMIPS_GOT16:
|
||||
Type = ELF::R_MICROMIPS_GOT16;
|
||||
break;
|
||||
case Mips::fixup_MICROMIPS_PC7_S1:
|
||||
Type = ELF::R_MICROMIPS_PC7_S1;
|
||||
break;
|
||||
case Mips::fixup_MICROMIPS_PC16_S1:
|
||||
Type = ELF::R_MICROMIPS_PC16_S1;
|
||||
break;
|
||||
|
@ -158,6 +158,9 @@ namespace Mips {
|
||||
// resulting in - R_MICROMIPS_GOT16
|
||||
fixup_MICROMIPS_GOT16,
|
||||
|
||||
// resulting in - R_MICROMIPS_PC7_S1
|
||||
fixup_MICROMIPS_PC7_S1,
|
||||
|
||||
// resulting in - R_MICROMIPS_PC16_S1
|
||||
fixup_MICROMIPS_PC16_S1,
|
||||
|
||||
|
@ -220,6 +220,28 @@ getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// getBranchTarget7OpValueMM - Return binary encoding of the microMIPS branch
|
||||
/// target operand. If the machine operand requires relocation,
|
||||
/// record the relocation and return zero.
|
||||
unsigned MipsMCCodeEmitter::
|
||||
getBranchTarget7OpValueMM(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
|
||||
const MCOperand &MO = MI.getOperand(OpNo);
|
||||
|
||||
// If the destination is an immediate, divide by 2.
|
||||
if (MO.isImm()) return MO.getImm() >> 1;
|
||||
|
||||
assert(MO.isExpr() &&
|
||||
"getBranchTargetOpValueMM expects only expressions or immediates");
|
||||
|
||||
const MCExpr *Expr = MO.getExpr();
|
||||
Fixups.push_back(MCFixup::Create(0, Expr,
|
||||
MCFixupKind(Mips::fixup_MICROMIPS_PC7_S1)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// getBranchTargetOpValue - Return binary encoding of the microMIPS branch
|
||||
/// target operand. If the machine operand requires relocation,
|
||||
/// record the relocation and return zero.
|
||||
|
@ -101,6 +101,13 @@ public:
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
|
||||
// getBranchTarget7OpValue - Return binary encoding of the microMIPS branch
|
||||
// target operand. If the machine operand requires relocation,
|
||||
// record the relocation and return zero.
|
||||
unsigned getBranchTarget7OpValueMM(const MCInst &MI, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
|
||||
// getBranchTargetOpValue - Return binary encoding of the microMIPS branch
|
||||
// target operand. If the machine operand requires relocation,
|
||||
// record the relocation and return zero.
|
||||
|
@ -227,6 +227,17 @@ class BRKSDBBP16_FM_MM<bits<6> op> {
|
||||
let Inst{3-0} = code_;
|
||||
}
|
||||
|
||||
class BEQNEZ_FM_MM16<bits<6> op> {
|
||||
bits<3> rs;
|
||||
bits<7> offset;
|
||||
|
||||
bits<16> Inst;
|
||||
|
||||
let Inst{15-10} = op;
|
||||
let Inst{9-7} = rs;
|
||||
let Inst{6-0} = offset;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MicroMIPS 32-bit Instruction Formats
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -128,6 +128,13 @@ def calltarget_mm : Operand<iPTR> {
|
||||
let EncoderMethod = "getJumpTargetOpValueMM";
|
||||
}
|
||||
|
||||
def brtarget7_mm : Operand<OtherVT> {
|
||||
let EncoderMethod = "getBranchTarget7OpValueMM";
|
||||
let OperandType = "OPERAND_PCREL";
|
||||
let DecoderMethod = "DecodeBranchTarget7MM";
|
||||
let ParserMatchClass = MipsJumpTargetAsmOperand;
|
||||
}
|
||||
|
||||
def brtarget_mm : Operand<OtherVT> {
|
||||
let EncoderMethod = "getBranchTargetOpValueMM";
|
||||
let OperandType = "OPERAND_PCREL";
|
||||
@ -382,6 +389,15 @@ class BrkSdbbp16MM<string opstr> :
|
||||
!strconcat(opstr, "\t$code_"),
|
||||
[], NoItinerary, FrmOther>;
|
||||
|
||||
class CBranchZeroMM<string opstr, DAGOperand opnd, RegisterOperand RO> :
|
||||
MicroMipsInst16<(outs), (ins RO:$rs, opnd:$offset),
|
||||
!strconcat(opstr, "\t$rs, $offset"), [], IIBranch, FrmI> {
|
||||
let isBranch = 1;
|
||||
let isTerminator = 1;
|
||||
let hasDelaySlot = 1;
|
||||
let Defs = [AT];
|
||||
}
|
||||
|
||||
// MicroMIPS Jump and Link (Call) - Short Delay Slot
|
||||
let isCall = 1, hasDelaySlot = 1, Defs = [RA] in {
|
||||
class JumpLinkMM<string opstr, DAGOperand opnd> :
|
||||
@ -512,6 +528,10 @@ def JALRS16_MM : JumpLinkRegSMM16<"jalrs16", GPR32Opnd>, JALR_FM_MM16<0x0f>;
|
||||
def JRC16_MM : JumpRegCMM16<"jrc", GPR32Opnd>, JALR_FM_MM16<0x0d>;
|
||||
def JRADDIUSP : JumpRAddiuStackMM16, JRADDIUSP_FM_MM16<0x18>;
|
||||
def JR16_MM : JumpRegMM16<"jr16", GPR32Opnd>, JALR_FM_MM16<0x0c>;
|
||||
def BEQZ16_MM : CBranchZeroMM<"beqz16", brtarget7_mm, GPRMM16Opnd>,
|
||||
BEQNEZ_FM_MM16<0x23>;
|
||||
def BNEZ16_MM : CBranchZeroMM<"bnez16", brtarget7_mm, GPRMM16Opnd>,
|
||||
BEQNEZ_FM_MM16<0x2b>;
|
||||
def BREAK16_MM : BrkSdbbp16MM<"break16">, BRKSDBBP16_FM_MM<0x28>;
|
||||
def SDBBP16_MM : BrkSdbbp16MM<"sdbbp16">, BRKSDBBP16_FM_MM<0x2C>;
|
||||
|
||||
|
@ -247,6 +247,10 @@ void MipsLongBranch::replaceBranch(MachineBasicBlock &MBB, Iter Br,
|
||||
}
|
||||
|
||||
// Expand branch instructions to long branches.
|
||||
// TODO: This function has to be fixed for beqz16 and bnez16, because it
|
||||
// currently assumes that all branches have 16-bit offsets, and will produce
|
||||
// wrong code if branches whose allowed offsets are [-128, -126, ..., 126]
|
||||
// are present.
|
||||
void MipsLongBranch::expandToLongBranch(MBBInfo &I) {
|
||||
MachineBasicBlock::iterator Pos;
|
||||
MachineBasicBlock *MBB = I.Br->getParent(), *TgtMBB = getTargetMBB(*I.Br);
|
||||
|
@ -468,3 +468,9 @@
|
||||
|
||||
# CHECK: sw $4, 124($sp)
|
||||
0xc8 0x9f
|
||||
|
||||
# CHECK: beqz16 $6, 20
|
||||
0x8f 0x0a
|
||||
|
||||
# CHECK: bnez16 $6, 20
|
||||
0xaf 0x0a
|
||||
|
@ -468,3 +468,9 @@
|
||||
|
||||
# CHECK: sw $4, 124($sp)
|
||||
0x9f 0xc8
|
||||
|
||||
# CHECK: beqz16 $6, 20
|
||||
0x0a 0x8f
|
||||
|
||||
# CHECK: bnez16 $6, 20
|
||||
0x0a 0xaf
|
||||
|
@ -49,6 +49,10 @@
|
||||
# CHECK-EL: nop # encoding: [0x00,0x0c]
|
||||
# CHECK-EL: jr16 $9 # encoding: [0x89,0x45]
|
||||
# CHECK-EL: nop # encoding: [0x00,0x00,0x00,0x00]
|
||||
# CHECK-EL: beqz16 $6, 20 # encoding: [0x0a,0x8f]
|
||||
# CHECK-EL: nop # encoding: [0x00,0x00,0x00,0x00]
|
||||
# CHECK-EL: bnez16 $6, 20 # encoding: [0x0a,0xaf]
|
||||
# CHECK-EL: nop # encoding: [0x00,0x00,0x00,0x00]
|
||||
# CHECK-EL: break16 8 # encoding: [0x88,0x46]
|
||||
# CHECK-EL: sdbbp16 14 # encoding: [0xce,0x46]
|
||||
#------------------------------------------------------------------------------
|
||||
@ -94,6 +98,10 @@
|
||||
# CHECK-EB: nop # encoding: [0x0c,0x00]
|
||||
# CHECK-EB: jr16 $9 # encoding: [0x45,0x89]
|
||||
# CHECK-EB: nop # encoding: [0x00,0x00,0x00,0x00]
|
||||
# CHECK-EB: beqz16 $6, 20 # encoding: [0x8f,0x0a]
|
||||
# CHECK-EB: nop # encoding: [0x00,0x00,0x00,0x00]
|
||||
# CHECK-EB: bnez16 $6, 20 # encoding: [0xaf,0x0a]
|
||||
# CHECK-EB: nop # encoding: [0x00,0x00,0x00,0x00]
|
||||
# CHECK-EB: break16 8 # encoding: [0x46,0x88]
|
||||
# CHECK-EB: sdbbp16 14 # encoding: [0x46,0xce]
|
||||
|
||||
@ -135,5 +143,7 @@
|
||||
jraddiusp 20
|
||||
jalrs16 $9
|
||||
jr16 $9
|
||||
beqz16 $6, 20
|
||||
bnez16 $6, 20
|
||||
break16 8
|
||||
sdbbp16 14
|
||||
|
@ -126,6 +126,11 @@
|
||||
# CHECK: error: branch target out of range
|
||||
# CHECK: bc1t $fcc0, 65536
|
||||
|
||||
# CHECK: error: branch to misaligned address
|
||||
# CHECK: beqz16 $6, 31
|
||||
# CHECK: error: branch target out of range
|
||||
# CHECK: beqz16 $6, 130
|
||||
|
||||
b -65535
|
||||
b -65536
|
||||
b -65537
|
||||
@ -223,3 +228,6 @@
|
||||
bc1t $fcc0, 65534
|
||||
bc1t $fcc0, 65535
|
||||
bc1t $fcc0, 65536
|
||||
|
||||
beqz16 $6, 31
|
||||
beqz16 $6, 130
|
||||
|
27
test/MC/Mips/micromips-branch7.s
Normal file
27
test/MC/Mips/micromips-branch7.s
Normal file
@ -0,0 +1,27 @@
|
||||
# RUN: llvm-mc %s -triple=mipsel-unknown-linux -show-encoding \
|
||||
# RUN: -mattr=micromips | FileCheck %s -check-prefix=CHECK-FIXUP
|
||||
# RUN: llvm-mc %s -filetype=obj -triple=mipsel-unknown-linux \
|
||||
# RUN: -mattr=micromips | llvm-readobj -r \
|
||||
# RUN: | FileCheck %s -check-prefix=CHECK-ELF
|
||||
#------------------------------------------------------------------------------
|
||||
# Check that the assembler can handle the documented syntax
|
||||
# for relocations.
|
||||
#------------------------------------------------------------------------------
|
||||
# CHECK-FIXUP: beqz16 $6, bar # encoding: [0b0AAAAAAA,0x8f]
|
||||
# CHECK-FIXUP: # fixup A - offset: 0,
|
||||
# CHECK-FIXUP: value: bar, kind: fixup_MICROMIPS_PC7_S1
|
||||
# CHECK-FIXUP: nop # encoding: [0x00,0x00,0x00,0x00]
|
||||
# CHECK-FIXUP: bnez16 $6, bar # encoding: [0b0AAAAAAA,0xaf]
|
||||
# CHECK-FIXUP: # fixup A - offset: 0,
|
||||
# CHECK-FIXUP: value: bar, kind: fixup_MICROMIPS_PC7_S1
|
||||
# CHECK-FIXUP: nop # encoding: [0x00,0x00,0x00,0x00]
|
||||
#------------------------------------------------------------------------------
|
||||
# Check that the appropriate relocations were created.
|
||||
#------------------------------------------------------------------------------
|
||||
# CHECK-ELF: Relocations [
|
||||
# CHECK-ELF: 0x{{[0-9,A-F]+}} R_MICROMIPS_PC7_S1
|
||||
# CHECK-ELF: 0x{{[0-9,A-F]+}} R_MICROMIPS_PC7_S1
|
||||
# CHECK-ELF: ]
|
||||
|
||||
beqz16 $6, bar
|
||||
bnez16 $6, bar
|
@ -64,3 +64,5 @@
|
||||
sw16 $7, 4($10) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
|
||||
cache 256, 8($5) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range
|
||||
pref 256, 8($5) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: immediate operand value out of range
|
||||
beqz16 $9, 20 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
|
||||
bnez16 $9, 20 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
|
||||
|
Loading…
x
Reference in New Issue
Block a user