From 4d0549e3be84ae5645c1d6f4745c276e5bb69289 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Mon, 3 Nov 2008 18:38:31 +0000 Subject: [PATCH] Add binary encoding support for multiply instructions. Some blanks left to fill in, but the basics are there. llvm-svn: 58626 --- llvm/lib/Target/ARM/ARMCodeEmitter.cpp | 42 +++++++++++++++++++--- llvm/lib/Target/ARM/ARMInstrFormats.td | 22 ++++++++++++ llvm/lib/Target/ARM/ARMInstrInfo.h | 32 +++++++++-------- llvm/lib/Target/ARM/ARMInstrInfo.td | 50 +++++++++++++++----------- 4 files changed, 105 insertions(+), 41 deletions(-) diff --git a/llvm/lib/Target/ARM/ARMCodeEmitter.cpp b/llvm/lib/Target/ARM/ARMCodeEmitter.cpp index 7aca1de3878a..53385d945e91 100644 --- a/llvm/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/llvm/lib/Target/ARM/ARMCodeEmitter.cpp @@ -82,8 +82,8 @@ namespace { const TargetInstrDesc &TID, const MachineOperand &MO); - unsigned getAddrMode1SBit(const MachineInstr &MI, - const TargetInstrDesc &TID) const; + unsigned getAddrModeSBit(const MachineInstr &MI, + const TargetInstrDesc &TID) const; unsigned getAddrMode1InstrBinary(const MachineInstr &MI, const TargetInstrDesc &TID, @@ -97,6 +97,9 @@ namespace { unsigned getAddrMode4InstrBinary(const MachineInstr &MI, const TargetInstrDesc &TID, unsigned Binary); + unsigned getAddrMode6InstrBinary(const MachineInstr &MI, + const TargetInstrDesc &TID, + unsigned Binary); /// getInstrBinary - Return binary encoding for the specified /// machine instruction. @@ -432,8 +435,8 @@ unsigned ARMCodeEmitter::getMachineSoImmOpValue(const MachineInstr &MI, return Binary; } -unsigned ARMCodeEmitter::getAddrMode1SBit(const MachineInstr &MI, - const TargetInstrDesc &TID) const { +unsigned ARMCodeEmitter::getAddrModeSBit(const MachineInstr &MI, + const TargetInstrDesc &TID) const { for (unsigned i = MI.getNumOperands(), e = TID.getNumOperands(); i != e; --i){ const MachineOperand &MO = MI.getOperand(i-1); if (MO.isReg() && MO.isDef() && MO.getReg() == ARM::CPSR) @@ -449,7 +452,7 @@ unsigned ARMCodeEmitter::getAddrMode1InstrBinary(const MachineInstr &MI, Binary |= II->getPredicate(&MI) << 28; // Encode S bit if MI modifies CPSR. - Binary |= getAddrMode1SBit(MI, TID); + Binary |= getAddrModeSBit(MI, TID); // Encode register def if there is one. unsigned NumDefs = TID.getNumDefs(); @@ -618,6 +621,33 @@ unsigned ARMCodeEmitter::getAddrMode4InstrBinary(const MachineInstr &MI, return Binary; } +unsigned ARMCodeEmitter::getAddrMode6InstrBinary(const MachineInstr &MI, + const TargetInstrDesc &TID, + unsigned Binary) { + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << 28; + + // Encode S bit if MI modifies CPSR. + Binary |= getAddrModeSBit(MI, TID); + + // 32x32->64bit operations have two destination registers. The number + // of register definitions will tell us if that's what we're dealing with. + int OpIdx = 0; + if (TID.getNumDefs() == 2) + Binary |= getMachineOpValue (MI, OpIdx++) << ARMII::RegRdLoShift; + + // Encode Rd + Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdHiShift; + + // Encode Rm + Binary |= getMachineOpValue(MI, OpIdx++); + + // Encode Rs + Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRsShift; + + return Binary; +} + /// getInstrBinary - Return binary encoding for the specified /// machine instruction. unsigned ARMCodeEmitter::getInstrBinary(const MachineInstr &MI) { @@ -636,6 +666,8 @@ unsigned ARMCodeEmitter::getInstrBinary(const MachineInstr &MI) { return getAddrMode3InstrBinary(MI, TID, Binary); case ARMII::AddrMode4: return getAddrMode4InstrBinary(MI, TID, Binary); + case ARMII::AddrMode6: + return getAddrMode6InstrBinary(MI, TID, Binary); } abort(); diff --git a/llvm/lib/Target/ARM/ARMInstrFormats.td b/llvm/lib/Target/ARM/ARMInstrFormats.td index 80ffabebeef8..5a76ffa88211 100644 --- a/llvm/lib/Target/ARM/ARMInstrFormats.td +++ b/llvm/lib/Target/ARM/ARMInstrFormats.td @@ -659,6 +659,28 @@ class AXI4st opcod, dag oops, dag iops, Format f, string asm, let Inst{27-25} = 0b100; } +// addrmode6 +// Unsigned multiply, multiply-accumulate instructions. +class AI6 opcod, dag oops, dag iops, Format f, string opc, + string asm, list pattern> + : I +{ + // FIXME: bits 7-4 should be a sub-mode (for SMLAxx, SMLAWy, ...) + let Inst{7-4} = 0b1001; + let Inst{27-24} = 0b0000; + let Inst{23-20} = opcod; +} +class AsI6 opcod, dag oops, dag iops, Format f, string opc, + string asm, list pattern> + : sI +{ + // FIXME: bits 7-4 should be a sub-mode (for SMLAxx, SMLAWy, ...) + let Inst{7-4} = 0b1001; + let Inst{27-24} = 0b0000; + let Inst{23-20} = opcod; +} //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/ARM/ARMInstrInfo.h b/llvm/lib/Target/ARM/ARMInstrInfo.h index c59b03c0d178..eb6109ebf3a4 100644 --- a/llvm/lib/Target/ARM/ARMInstrInfo.h +++ b/llvm/lib/Target/ARM/ARMInstrInfo.h @@ -30,8 +30,7 @@ namespace ARMII { // Instruction Flags. //===------------------------------------------------------------------===// - // This three-bit field describes the addressing mode used. Zero is unused - // so that we can tell if we forgot to set a value. + // This four-bit field describes the addressing mode used. AddrModeMask = 0xf, AddrModeNone = 0, @@ -40,10 +39,11 @@ namespace ARMII { AddrMode3 = 3, AddrMode4 = 4, AddrMode5 = 5, - AddrModeT1 = 6, - AddrModeT2 = 7, - AddrModeT4 = 8, - AddrModeTs = 9, // i8 * 4 for pc and sp relative data + AddrMode6 = 6, + AddrModeT1 = 7, + AddrModeT2 = 8, + AddrModeT4 = 9, + AddrModeTs = 10, // i8 * 4 for pc and sp relative data // Size* - Flags to keep track of the size of an instruction. SizeShift = 4, @@ -115,15 +115,17 @@ namespace ARMII { // Field shifts - such shifts are used to set field while generating // machine instructions. - RotImmShift = 8, - RegRsShift = 8, - RegRdShift = 12, - RegRnShift = 16, - L_BitShift = 20, - S_BitShift = 20, - U_BitShift = 23, - IndexShift = 24, - I_BitShift = 25 + RotImmShift = 8, + RegRsShift = 8, + RegRdLoShift = 12, + RegRdShift = 12, + RegRdHiShift = 16, + RegRnShift = 16, + L_BitShift = 20, + S_BitShift = 20, + U_BitShift = 23, + IndexShift = 24, + I_BitShift = 25 }; } diff --git a/llvm/lib/Target/ARM/ARMInstrInfo.td b/llvm/lib/Target/ARM/ARMInstrInfo.td index 2b3a8a1e9586..d2ea2b1088a9 100644 --- a/llvm/lib/Target/ARM/ARMInstrInfo.td +++ b/llvm/lib/Target/ARM/ARMInstrInfo.td @@ -310,10 +310,11 @@ def AddrMode2 : AddrMode<2>; def AddrMode3 : AddrMode<3>; def AddrMode4 : AddrMode<4>; def AddrMode5 : AddrMode<5>; -def AddrModeT1 : AddrMode<6>; -def AddrModeT2 : AddrMode<7>; -def AddrModeT4 : AddrMode<8>; -def AddrModeTs : AddrMode<9>; +def AddrMode6 : AddrMode<6>; +def AddrModeT1 : AddrMode<7>; +def AddrModeT2 : AddrMode<8>; +def AddrModeT4 : AddrMode<9>; +def AddrModeTs : AddrMode<10>; // Instruction size. class SizeFlagVal val> { @@ -910,49 +911,53 @@ def : ARMPat<(and GPR:$src, so_imm_not:$imm), // Multiply Instructions. // -def MUL : AsI<0x0, (outs GPR:$dst), (ins GPR:$a, GPR:$b), MulFrm, - "mul", " $dst, $a, $b", - [(set GPR:$dst, (mul GPR:$a, GPR:$b))]>; +def MUL : AsI6<0b0000, (outs GPR:$dst), (ins GPR:$a, GPR:$b), MulFrm, + "mul", " $dst, $a, $b", + [(set GPR:$dst, (mul GPR:$a, GPR:$b))]>; -def MLA : AsI<0x2, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), - MulFrm, "mla", " $dst, $a, $b, $c", - [(set GPR:$dst, (add (mul GPR:$a, GPR:$b), GPR:$c))]>; +def MLA : AsI6<0b0010, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), + MulFrm, "mla", " $dst, $a, $b, $c", + [(set GPR:$dst, (add (mul GPR:$a, GPR:$b), GPR:$c))]>; // Extra precision multiplies with low / high results -def SMULL : AsI<0xC, (outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), - MulFrm, "smull", " $ldst, $hdst, $a, $b", []>; +def SMULL : AsI6<0b1100, (outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), + MulFrm, "smull", " $ldst, $hdst, $a, $b", []>; -def UMULL : AsI<0x8, (outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), - MulFrm, "umull", " $ldst, $hdst, $a, $b", []>; +def UMULL : AsI6<0b1000, (outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), + MulFrm, "umull", " $ldst, $hdst, $a, $b", []>; // Multiply + accumulate -def SMLAL : AsI<0xE, (outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), - MulFrm, "smlal", " $ldst, $hdst, $a, $b", []>; +def SMLAL : AsI6<0b1110, (outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), + MulFrm, "smlal", " $ldst, $hdst, $a, $b", []>; -def UMLAL : AsI<0xA, (outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), - MulFrm, "umlal", " $ldst, $hdst, $a, $b", []>; +def UMLAL : AsI6<0b1010, (outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), + MulFrm, "umlal", " $ldst, $hdst, $a, $b", []>; -def UMAAL : AI<0x0, (outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), MulFrm, - "umaal", " $ldst, $hdst, $a, $b", []>, - Requires<[IsARM, HasV6]>; +def UMAAL : AI6 <0b0000, (outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), + MulFrm, "umaal", " $ldst, $hdst, $a, $b", []>, + Requires<[IsARM, HasV6]>; // Most significant word multiply +// FIXME: encoding def SMMUL : AI<0x0, (outs GPR:$dst), (ins GPR:$a, GPR:$b), MulFrm, "smmul", " $dst, $a, $b", [(set GPR:$dst, (mulhs GPR:$a, GPR:$b))]>, Requires<[IsARM, HasV6]>; +// FIXME: encoding def SMMLA : AI<0x0, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), MulFrm, "smmla", " $dst, $a, $b, $c", [(set GPR:$dst, (add (mulhs GPR:$a, GPR:$b), GPR:$c))]>, Requires<[IsARM, HasV6]>; +// FIXME: encoding def SMMLS : AI<0x0, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), MulFrm, "smmls", " $dst, $a, $b, $c", [(set GPR:$dst, (sub GPR:$c, (mulhs GPR:$a, GPR:$b)))]>, Requires<[IsARM, HasV6]>; +// FIXME: encoding multiclass AI_smul { def BB : AI<0x8, (outs GPR:$dst), (ins GPR:$a, GPR:$b), MulSMUL, !strconcat(opc, "bb"), " $dst, $a, $b", @@ -992,6 +997,7 @@ multiclass AI_smul { } +// FIXME: encoding multiclass AI_smla { def BB : AI<0x8, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), MulSMLA, !strconcat(opc, "bb"), " $dst, $a, $b, $acc", @@ -1031,7 +1037,9 @@ multiclass AI_smla { Requires<[IsARM, HasV5TE]>; } +// FIXME: encoding defm SMUL : AI_smul<"smul", BinOpFrag<(mul node:$LHS, node:$RHS)>>; +// FIXME: encoding defm SMLA : AI_smla<"smla", BinOpFrag<(mul node:$LHS, node:$RHS)>>; // TODO: Halfword multiple accumulate long: SMLAL