2016-06-16 09:00:53 +08:00
|
|
|
//===-- PPCAsmParser.cpp - Parse PowerPC asm to MCInst instructions -------===//
|
2013-05-04 03:49:39 +08:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2013-06-21 00:23:52 +08:00
|
|
|
#include "MCTargetDesc/PPCMCExpr.h"
|
2016-01-27 18:01:28 +08:00
|
|
|
#include "MCTargetDesc/PPCMCTargetDesc.h"
|
2014-01-25 10:35:56 +08:00
|
|
|
#include "PPCTargetStreamer.h"
|
2014-01-07 19:48:04 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
|
|
|
#include "llvm/ADT/StringSwitch.h"
|
|
|
|
#include "llvm/ADT/Twine.h"
|
[PowerPC] ELFv2 MC support for .localentry directive
A second binutils feature needed to support ELFv2 is the .localentry
directive. In the ELFv2 ABI, functions may have two entry points:
one for calling the routine locally via "bl", and one for calling the
function via function pointer (either at the source level, or implicitly
via a PLT stub for global calls). The two entry points share a single
ELF symbol, where the ELF symbol address identifies the global entry
point address, while the local entry point is found by adding a delta
offset to the symbol address. That offset is encoded into three
platform-specific bits of the ELF symbol st_other field.
The .localentry directive instructs the assembler to set those fields
to encode a particular offset. This is typically used by a function
prologue sequence like this:
func:
addis r2, r12, (.TOC.-func)@ha
addi r2, r2, (.TOC.-func)@l
.localentry func, .-func
Note that according to the ABI, when calling the global entry point,
r12 must be set to point the global entry point address itself; while
when calling the local entry point, r2 must be set to point to the TOC
base. The two instructions between the global and local entry point in
the above example translate the first requirement into the second.
This patch implements support in the PowerPC MC streamers to emit the
.localentry directive (both into assembler and ELF object output), as
well as support in the assembler parser to parse that directive.
In addition, there is another change required in MC fixup/relocation
handling to properly deal with relocations targeting function symbols
with two entry points: When the target function is known local, the MC
layer would immediately handle the fixup by inserting the target
address -- this is wrong, since the call may need to go to the local
entry point instead. The GNU assembler handles this case by *not*
directly resolving fixups targeting functions with two entry points,
but always emits the relocation and relies on the linker to handle
this case correctly. This patch changes LLVM MC to do the same (this
is done via the processFixupValue routine).
Similarly, there are cases where the assembler would normally emit a
relocation, but "simplify" it to a relocation targeting a *section*
instead of the actual symbol. For the same reason as above, this
may be wrong when the target symbol has two entry points. The GNU
assembler again handles this case by not performing this simplification
in that case, but leaving the relocation targeting the full symbol,
which is then resolved by the linker. This patch changes LLVM MC
to do the same (via the needsRelocateWithSymbol routine).
NOTE: The method used in this patch is overly pessimistic, since the
needsRelocateWithSymbol routine currently does not have access to the
actual target symbol, and thus must always assume that it might have
two entry points. This will be improved upon by a follow-on patch
that modifies common code to pass the target symbol when calling
needsRelocateWithSymbol.
Reviewed by Hal Finkel.
llvm-svn: 213485
2014-07-21 07:06:03 +08:00
|
|
|
#include "llvm/MC/MCContext.h"
|
2013-05-04 03:49:39 +08:00
|
|
|
#include "llvm/MC/MCExpr.h"
|
|
|
|
#include "llvm/MC/MCInst.h"
|
2013-09-12 22:40:06 +08:00
|
|
|
#include "llvm/MC/MCInstrInfo.h"
|
2013-05-04 03:49:39 +08:00
|
|
|
#include "llvm/MC/MCParser/MCAsmLexer.h"
|
|
|
|
#include "llvm/MC/MCParser/MCAsmParser.h"
|
|
|
|
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
|
2016-01-27 18:01:28 +08:00
|
|
|
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
|
2014-01-07 19:48:04 +08:00
|
|
|
#include "llvm/MC/MCRegisterInfo.h"
|
|
|
|
#include "llvm/MC/MCStreamer.h"
|
|
|
|
#include "llvm/MC/MCSubtargetInfo.h"
|
2016-01-27 18:01:28 +08:00
|
|
|
#include "llvm/MC/MCSymbolELF.h"
|
2013-05-04 03:49:39 +08:00
|
|
|
#include "llvm/Support/SourceMgr.h"
|
|
|
|
#include "llvm/Support/TargetRegistry.h"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
2014-12-18 13:02:14 +08:00
|
|
|
static const MCPhysReg RRegs[32] = {
|
2013-05-04 03:49:39 +08:00
|
|
|
PPC::R0, PPC::R1, PPC::R2, PPC::R3,
|
|
|
|
PPC::R4, PPC::R5, PPC::R6, PPC::R7,
|
|
|
|
PPC::R8, PPC::R9, PPC::R10, PPC::R11,
|
|
|
|
PPC::R12, PPC::R13, PPC::R14, PPC::R15,
|
|
|
|
PPC::R16, PPC::R17, PPC::R18, PPC::R19,
|
|
|
|
PPC::R20, PPC::R21, PPC::R22, PPC::R23,
|
|
|
|
PPC::R24, PPC::R25, PPC::R26, PPC::R27,
|
|
|
|
PPC::R28, PPC::R29, PPC::R30, PPC::R31
|
|
|
|
};
|
2014-12-18 13:02:14 +08:00
|
|
|
static const MCPhysReg RRegsNoR0[32] = {
|
2013-05-04 03:49:39 +08:00
|
|
|
PPC::ZERO,
|
|
|
|
PPC::R1, PPC::R2, PPC::R3,
|
|
|
|
PPC::R4, PPC::R5, PPC::R6, PPC::R7,
|
|
|
|
PPC::R8, PPC::R9, PPC::R10, PPC::R11,
|
|
|
|
PPC::R12, PPC::R13, PPC::R14, PPC::R15,
|
|
|
|
PPC::R16, PPC::R17, PPC::R18, PPC::R19,
|
|
|
|
PPC::R20, PPC::R21, PPC::R22, PPC::R23,
|
|
|
|
PPC::R24, PPC::R25, PPC::R26, PPC::R27,
|
|
|
|
PPC::R28, PPC::R29, PPC::R30, PPC::R31
|
|
|
|
};
|
2014-12-18 13:02:14 +08:00
|
|
|
static const MCPhysReg XRegs[32] = {
|
2013-05-04 03:49:39 +08:00
|
|
|
PPC::X0, PPC::X1, PPC::X2, PPC::X3,
|
|
|
|
PPC::X4, PPC::X5, PPC::X6, PPC::X7,
|
|
|
|
PPC::X8, PPC::X9, PPC::X10, PPC::X11,
|
|
|
|
PPC::X12, PPC::X13, PPC::X14, PPC::X15,
|
|
|
|
PPC::X16, PPC::X17, PPC::X18, PPC::X19,
|
|
|
|
PPC::X20, PPC::X21, PPC::X22, PPC::X23,
|
|
|
|
PPC::X24, PPC::X25, PPC::X26, PPC::X27,
|
|
|
|
PPC::X28, PPC::X29, PPC::X30, PPC::X31
|
|
|
|
};
|
2014-12-18 13:02:14 +08:00
|
|
|
static const MCPhysReg XRegsNoX0[32] = {
|
2013-05-04 03:49:39 +08:00
|
|
|
PPC::ZERO8,
|
|
|
|
PPC::X1, PPC::X2, PPC::X3,
|
|
|
|
PPC::X4, PPC::X5, PPC::X6, PPC::X7,
|
|
|
|
PPC::X8, PPC::X9, PPC::X10, PPC::X11,
|
|
|
|
PPC::X12, PPC::X13, PPC::X14, PPC::X15,
|
|
|
|
PPC::X16, PPC::X17, PPC::X18, PPC::X19,
|
|
|
|
PPC::X20, PPC::X21, PPC::X22, PPC::X23,
|
|
|
|
PPC::X24, PPC::X25, PPC::X26, PPC::X27,
|
|
|
|
PPC::X28, PPC::X29, PPC::X30, PPC::X31
|
|
|
|
};
|
2014-12-18 13:02:14 +08:00
|
|
|
static const MCPhysReg FRegs[32] = {
|
2013-05-04 03:49:39 +08:00
|
|
|
PPC::F0, PPC::F1, PPC::F2, PPC::F3,
|
|
|
|
PPC::F4, PPC::F5, PPC::F6, PPC::F7,
|
|
|
|
PPC::F8, PPC::F9, PPC::F10, PPC::F11,
|
|
|
|
PPC::F12, PPC::F13, PPC::F14, PPC::F15,
|
|
|
|
PPC::F16, PPC::F17, PPC::F18, PPC::F19,
|
|
|
|
PPC::F20, PPC::F21, PPC::F22, PPC::F23,
|
|
|
|
PPC::F24, PPC::F25, PPC::F26, PPC::F27,
|
|
|
|
PPC::F28, PPC::F29, PPC::F30, PPC::F31
|
|
|
|
};
|
2016-10-04 14:59:23 +08:00
|
|
|
static const MCPhysReg VFRegs[32] = {
|
|
|
|
PPC::VF0, PPC::VF1, PPC::VF2, PPC::VF3,
|
|
|
|
PPC::VF4, PPC::VF5, PPC::VF6, PPC::VF7,
|
|
|
|
PPC::VF8, PPC::VF9, PPC::VF10, PPC::VF11,
|
|
|
|
PPC::VF12, PPC::VF13, PPC::VF14, PPC::VF15,
|
|
|
|
PPC::VF16, PPC::VF17, PPC::VF18, PPC::VF19,
|
|
|
|
PPC::VF20, PPC::VF21, PPC::VF22, PPC::VF23,
|
|
|
|
PPC::VF24, PPC::VF25, PPC::VF26, PPC::VF27,
|
|
|
|
PPC::VF28, PPC::VF29, PPC::VF30, PPC::VF31
|
|
|
|
};
|
2014-12-18 13:02:14 +08:00
|
|
|
static const MCPhysReg VRegs[32] = {
|
2013-05-04 03:49:39 +08:00
|
|
|
PPC::V0, PPC::V1, PPC::V2, PPC::V3,
|
|
|
|
PPC::V4, PPC::V5, PPC::V6, PPC::V7,
|
|
|
|
PPC::V8, PPC::V9, PPC::V10, PPC::V11,
|
|
|
|
PPC::V12, PPC::V13, PPC::V14, PPC::V15,
|
|
|
|
PPC::V16, PPC::V17, PPC::V18, PPC::V19,
|
|
|
|
PPC::V20, PPC::V21, PPC::V22, PPC::V23,
|
|
|
|
PPC::V24, PPC::V25, PPC::V26, PPC::V27,
|
|
|
|
PPC::V28, PPC::V29, PPC::V30, PPC::V31
|
|
|
|
};
|
2014-12-18 13:02:14 +08:00
|
|
|
static const MCPhysReg VSRegs[64] = {
|
[PowerPC] Initial support for the VSX instruction set
VSX is an ISA extension supported on the POWER7 and later cores that enhances
floating-point vector and scalar capabilities. Among other things, this adds
<2 x double> support and generally helps to reduce register pressure.
The interesting part of this ISA feature is the register configuration: there
are 64 new 128-bit vector registers, the 32 of which are super-registers of the
existing 32 scalar floating-point registers, and the second 32 of which overlap
with the 32 Altivec vector registers. This makes things like vector insertion
and extraction tricky: this can be free but only if we force a restriction to
the right register subclass when needed. A new "minipass" PPCVSXCopy takes care
of this (although it could do a more-optimal job of it; see the comment about
unnecessary copies below).
Please note that, currently, VSX is not enabled by default when targeting
anything because it is not yet ready for that. The assembler and disassembler
are fully implemented and tested. However:
- CodeGen support causes miscompiles; test-suite runtime failures:
MultiSource/Benchmarks/FreeBench/distray/distray
MultiSource/Benchmarks/McCat/08-main/main
MultiSource/Benchmarks/Olden/voronoi/voronoi
MultiSource/Benchmarks/mafft/pairlocalalign
MultiSource/Benchmarks/tramp3d-v4/tramp3d-v4
SingleSource/Benchmarks/CoyoteBench/almabench
SingleSource/Benchmarks/Misc/matmul_f64_4x4
- The lowering currently falls back to using Altivec instructions far more
than it should. Worse, there are some things that are scalarized through the
stack that shouldn't be.
- A lot of unnecessary copies make it past the optimizers, and this needs to
be fixed.
- Many more regression tests are needed.
Normally, I'd fix these things prior to committing, but there are some
students and other contributors who would like to work this, and so it makes
sense to move this development process upstream where it can be subject to the
regular code-review procedures.
llvm-svn: 203768
2014-03-13 15:58:58 +08:00
|
|
|
PPC::VSL0, PPC::VSL1, PPC::VSL2, PPC::VSL3,
|
|
|
|
PPC::VSL4, PPC::VSL5, PPC::VSL6, PPC::VSL7,
|
|
|
|
PPC::VSL8, PPC::VSL9, PPC::VSL10, PPC::VSL11,
|
|
|
|
PPC::VSL12, PPC::VSL13, PPC::VSL14, PPC::VSL15,
|
|
|
|
PPC::VSL16, PPC::VSL17, PPC::VSL18, PPC::VSL19,
|
|
|
|
PPC::VSL20, PPC::VSL21, PPC::VSL22, PPC::VSL23,
|
|
|
|
PPC::VSL24, PPC::VSL25, PPC::VSL26, PPC::VSL27,
|
|
|
|
PPC::VSL28, PPC::VSL29, PPC::VSL30, PPC::VSL31,
|
|
|
|
|
2016-10-04 14:59:23 +08:00
|
|
|
PPC::V0, PPC::V1, PPC::V2, PPC::V3,
|
|
|
|
PPC::V4, PPC::V5, PPC::V6, PPC::V7,
|
|
|
|
PPC::V8, PPC::V9, PPC::V10, PPC::V11,
|
|
|
|
PPC::V12, PPC::V13, PPC::V14, PPC::V15,
|
|
|
|
PPC::V16, PPC::V17, PPC::V18, PPC::V19,
|
|
|
|
PPC::V20, PPC::V21, PPC::V22, PPC::V23,
|
|
|
|
PPC::V24, PPC::V25, PPC::V26, PPC::V27,
|
|
|
|
PPC::V28, PPC::V29, PPC::V30, PPC::V31
|
[PowerPC] Initial support for the VSX instruction set
VSX is an ISA extension supported on the POWER7 and later cores that enhances
floating-point vector and scalar capabilities. Among other things, this adds
<2 x double> support and generally helps to reduce register pressure.
The interesting part of this ISA feature is the register configuration: there
are 64 new 128-bit vector registers, the 32 of which are super-registers of the
existing 32 scalar floating-point registers, and the second 32 of which overlap
with the 32 Altivec vector registers. This makes things like vector insertion
and extraction tricky: this can be free but only if we force a restriction to
the right register subclass when needed. A new "minipass" PPCVSXCopy takes care
of this (although it could do a more-optimal job of it; see the comment about
unnecessary copies below).
Please note that, currently, VSX is not enabled by default when targeting
anything because it is not yet ready for that. The assembler and disassembler
are fully implemented and tested. However:
- CodeGen support causes miscompiles; test-suite runtime failures:
MultiSource/Benchmarks/FreeBench/distray/distray
MultiSource/Benchmarks/McCat/08-main/main
MultiSource/Benchmarks/Olden/voronoi/voronoi
MultiSource/Benchmarks/mafft/pairlocalalign
MultiSource/Benchmarks/tramp3d-v4/tramp3d-v4
SingleSource/Benchmarks/CoyoteBench/almabench
SingleSource/Benchmarks/Misc/matmul_f64_4x4
- The lowering currently falls back to using Altivec instructions far more
than it should. Worse, there are some things that are scalarized through the
stack that shouldn't be.
- A lot of unnecessary copies make it past the optimizers, and this needs to
be fixed.
- Many more regression tests are needed.
Normally, I'd fix these things prior to committing, but there are some
students and other contributors who would like to work this, and so it makes
sense to move this development process upstream where it can be subject to the
regular code-review procedures.
llvm-svn: 203768
2014-03-13 15:58:58 +08:00
|
|
|
};
|
2014-12-18 13:02:14 +08:00
|
|
|
static const MCPhysReg VSFRegs[64] = {
|
2014-03-29 13:29:01 +08:00
|
|
|
PPC::F0, PPC::F1, PPC::F2, PPC::F3,
|
|
|
|
PPC::F4, PPC::F5, PPC::F6, PPC::F7,
|
|
|
|
PPC::F8, PPC::F9, PPC::F10, PPC::F11,
|
|
|
|
PPC::F12, PPC::F13, PPC::F14, PPC::F15,
|
|
|
|
PPC::F16, PPC::F17, PPC::F18, PPC::F19,
|
|
|
|
PPC::F20, PPC::F21, PPC::F22, PPC::F23,
|
|
|
|
PPC::F24, PPC::F25, PPC::F26, PPC::F27,
|
|
|
|
PPC::F28, PPC::F29, PPC::F30, PPC::F31,
|
|
|
|
|
|
|
|
PPC::VF0, PPC::VF1, PPC::VF2, PPC::VF3,
|
|
|
|
PPC::VF4, PPC::VF5, PPC::VF6, PPC::VF7,
|
|
|
|
PPC::VF8, PPC::VF9, PPC::VF10, PPC::VF11,
|
|
|
|
PPC::VF12, PPC::VF13, PPC::VF14, PPC::VF15,
|
|
|
|
PPC::VF16, PPC::VF17, PPC::VF18, PPC::VF19,
|
|
|
|
PPC::VF20, PPC::VF21, PPC::VF22, PPC::VF23,
|
|
|
|
PPC::VF24, PPC::VF25, PPC::VF26, PPC::VF27,
|
|
|
|
PPC::VF28, PPC::VF29, PPC::VF30, PPC::VF31
|
|
|
|
};
|
2015-05-08 02:24:05 +08:00
|
|
|
static const MCPhysReg VSSRegs[64] = {
|
|
|
|
PPC::F0, PPC::F1, PPC::F2, PPC::F3,
|
|
|
|
PPC::F4, PPC::F5, PPC::F6, PPC::F7,
|
|
|
|
PPC::F8, PPC::F9, PPC::F10, PPC::F11,
|
|
|
|
PPC::F12, PPC::F13, PPC::F14, PPC::F15,
|
|
|
|
PPC::F16, PPC::F17, PPC::F18, PPC::F19,
|
|
|
|
PPC::F20, PPC::F21, PPC::F22, PPC::F23,
|
|
|
|
PPC::F24, PPC::F25, PPC::F26, PPC::F27,
|
|
|
|
PPC::F28, PPC::F29, PPC::F30, PPC::F31,
|
|
|
|
|
|
|
|
PPC::VF0, PPC::VF1, PPC::VF2, PPC::VF3,
|
|
|
|
PPC::VF4, PPC::VF5, PPC::VF6, PPC::VF7,
|
|
|
|
PPC::VF8, PPC::VF9, PPC::VF10, PPC::VF11,
|
|
|
|
PPC::VF12, PPC::VF13, PPC::VF14, PPC::VF15,
|
|
|
|
PPC::VF16, PPC::VF17, PPC::VF18, PPC::VF19,
|
|
|
|
PPC::VF20, PPC::VF21, PPC::VF22, PPC::VF23,
|
|
|
|
PPC::VF24, PPC::VF25, PPC::VF26, PPC::VF27,
|
|
|
|
PPC::VF28, PPC::VF29, PPC::VF30, PPC::VF31
|
|
|
|
};
|
[PowerPC] Add support for the QPX vector instruction set
This adds support for the QPX vector instruction set, which is used by the
enhanced A2 cores on the IBM BG/Q supercomputers. QPX vectors are 256 bytes
wide, holding 4 double-precision floating-point values. Boolean values, modeled
here as <4 x i1> are actually also represented as floating-point values
(essentially { -1, 1 } for { false, true }). QPX shares many features with
Altivec and VSX, but is distinct from both of them. One major difference is
that, instead of adding completely-separate vector registers, QPX vector
registers are extensions of the scalar floating-point registers (lane 0 is the
corresponding scalar floating-point value). The operations supported on QPX
vectors mirrors that supported on the scalar floating-point values (with some
additional ones for permutations and logical/comparison operations).
I've been maintaining this support out-of-tree, as part of the bgclang project,
for several years. This is not the entire bgclang patch set, but is most of the
subset that can be cleanly integrated into LLVM proper at this time. Adding
this to the LLVM backend is part of my efforts to rebase bgclang to the current
LLVM trunk, but is independently useful (especially for codes that use LLVM as
a JIT in library form).
The assembler/disassembler test coverage is complete. The CodeGen test coverage
is not, but I've included some tests, and more will be added as follow-up work.
llvm-svn: 230413
2015-02-25 09:06:45 +08:00
|
|
|
static unsigned QFRegs[32] = {
|
|
|
|
PPC::QF0, PPC::QF1, PPC::QF2, PPC::QF3,
|
|
|
|
PPC::QF4, PPC::QF5, PPC::QF6, PPC::QF7,
|
|
|
|
PPC::QF8, PPC::QF9, PPC::QF10, PPC::QF11,
|
|
|
|
PPC::QF12, PPC::QF13, PPC::QF14, PPC::QF15,
|
|
|
|
PPC::QF16, PPC::QF17, PPC::QF18, PPC::QF19,
|
|
|
|
PPC::QF20, PPC::QF21, PPC::QF22, PPC::QF23,
|
|
|
|
PPC::QF24, PPC::QF25, PPC::QF26, PPC::QF27,
|
|
|
|
PPC::QF28, PPC::QF29, PPC::QF30, PPC::QF31
|
|
|
|
};
|
2014-12-18 13:02:14 +08:00
|
|
|
static const MCPhysReg CRBITRegs[32] = {
|
2013-05-04 03:49:39 +08:00
|
|
|
PPC::CR0LT, PPC::CR0GT, PPC::CR0EQ, PPC::CR0UN,
|
|
|
|
PPC::CR1LT, PPC::CR1GT, PPC::CR1EQ, PPC::CR1UN,
|
|
|
|
PPC::CR2LT, PPC::CR2GT, PPC::CR2EQ, PPC::CR2UN,
|
|
|
|
PPC::CR3LT, PPC::CR3GT, PPC::CR3EQ, PPC::CR3UN,
|
|
|
|
PPC::CR4LT, PPC::CR4GT, PPC::CR4EQ, PPC::CR4UN,
|
|
|
|
PPC::CR5LT, PPC::CR5GT, PPC::CR5EQ, PPC::CR5UN,
|
|
|
|
PPC::CR6LT, PPC::CR6GT, PPC::CR6EQ, PPC::CR6UN,
|
|
|
|
PPC::CR7LT, PPC::CR7GT, PPC::CR7EQ, PPC::CR7UN
|
|
|
|
};
|
2014-12-18 13:02:14 +08:00
|
|
|
static const MCPhysReg CRRegs[8] = {
|
2013-05-04 03:49:39 +08:00
|
|
|
PPC::CR0, PPC::CR1, PPC::CR2, PPC::CR3,
|
|
|
|
PPC::CR4, PPC::CR5, PPC::CR6, PPC::CR7
|
|
|
|
};
|
|
|
|
|
2013-07-04 22:24:00 +08:00
|
|
|
// Evaluate an expression containing condition register
|
|
|
|
// or condition register field symbols. Returns positive
|
|
|
|
// value on success, or -1 on error.
|
|
|
|
static int64_t
|
|
|
|
EvaluateCRExpr(const MCExpr *E) {
|
|
|
|
switch (E->getKind()) {
|
|
|
|
case MCExpr::Target:
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
case MCExpr::Constant: {
|
|
|
|
int64_t Res = cast<MCConstantExpr>(E)->getValue();
|
|
|
|
return Res < 0 ? -1 : Res;
|
|
|
|
}
|
|
|
|
|
|
|
|
case MCExpr::SymbolRef: {
|
|
|
|
const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E);
|
|
|
|
StringRef Name = SRE->getSymbol().getName();
|
|
|
|
|
|
|
|
if (Name == "lt") return 0;
|
|
|
|
if (Name == "gt") return 1;
|
|
|
|
if (Name == "eq") return 2;
|
|
|
|
if (Name == "so") return 3;
|
|
|
|
if (Name == "un") return 3;
|
|
|
|
|
|
|
|
if (Name == "cr0") return 0;
|
|
|
|
if (Name == "cr1") return 1;
|
|
|
|
if (Name == "cr2") return 2;
|
|
|
|
if (Name == "cr3") return 3;
|
|
|
|
if (Name == "cr4") return 4;
|
|
|
|
if (Name == "cr5") return 5;
|
|
|
|
if (Name == "cr6") return 6;
|
|
|
|
if (Name == "cr7") return 7;
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
case MCExpr::Unary:
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
case MCExpr::Binary: {
|
|
|
|
const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);
|
|
|
|
int64_t LHSVal = EvaluateCRExpr(BE->getLHS());
|
|
|
|
int64_t RHSVal = EvaluateCRExpr(BE->getRHS());
|
|
|
|
int64_t Res;
|
|
|
|
|
|
|
|
if (LHSVal < 0 || RHSVal < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
switch (BE->getOpcode()) {
|
|
|
|
default: return -1;
|
|
|
|
case MCBinaryExpr::Add: Res = LHSVal + RHSVal; break;
|
|
|
|
case MCBinaryExpr::Mul: Res = LHSVal * RHSVal; break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Res < 0 ? -1 : Res;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm_unreachable("Invalid expression kind!");
|
|
|
|
}
|
|
|
|
|
2014-12-18 13:02:14 +08:00
|
|
|
namespace {
|
|
|
|
|
2013-05-04 03:49:39 +08:00
|
|
|
struct PPCOperand;
|
|
|
|
|
|
|
|
class PPCAsmParser : public MCTargetAsmParser {
|
|
|
|
bool IsPPC64;
|
2013-12-14 21:34:02 +08:00
|
|
|
bool IsDarwin;
|
2013-05-04 03:49:39 +08:00
|
|
|
|
2014-11-11 13:18:41 +08:00
|
|
|
void Warning(SMLoc L, const Twine &Msg) { getParser().Warning(L, Msg); }
|
2013-05-04 03:49:39 +08:00
|
|
|
|
|
|
|
bool isPPC64() const { return IsPPC64; }
|
2013-12-14 21:34:02 +08:00
|
|
|
bool isDarwin() const { return IsDarwin; }
|
2013-05-04 03:49:39 +08:00
|
|
|
|
2016-12-05 22:11:03 +08:00
|
|
|
bool MatchRegisterName(unsigned &RegNo, int64_t &IntVal);
|
2013-05-04 03:49:39 +08:00
|
|
|
|
2014-04-29 15:57:37 +08:00
|
|
|
bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
|
2013-05-04 03:49:39 +08:00
|
|
|
|
2013-06-21 00:23:52 +08:00
|
|
|
const MCExpr *ExtractModifierFromExpr(const MCExpr *E,
|
|
|
|
PPCMCExpr::VariantKind &Variant);
|
[PowerPC] Revert r185476 and fix up TLS variant kinds
In the commit message to r185476 I wrote:
>The PowerPC-specific modifiers VK_PPC_TLSGD and VK_PPC_TLSLD
>correspond exactly to the generic modifiers VK_TLSGD and VK_TLSLD.
>This causes some confusion with the asm parser, since VK_PPC_TLSGD
>is output as @tlsgd, which is then read back in as VK_TLSGD.
>
>To avoid this confusion, this patch removes the PowerPC-specific
>modifiers and uses the generic modifiers throughout. (The only
>drawback is that the generic modifiers are printed in upper case
>while the usual convention on PowerPC is to use lower-case modifiers.
>But this is just a cosmetic issue.)
This was unfortunately incorrect, there is is fact another,
serious drawback to using the default VK_TLSLD/VK_TLSGD
variant kinds: using these causes ELFObjectWriter::RelocNeedsGOT
to return true, which in turn causes the ELFObjectWriter to emit
an undefined reference to _GLOBAL_OFFSET_TABLE_.
This is a problem on powerpc64, because it uses the TOC instead
of the GOT, and the linker does not provide _GLOBAL_OFFSET_TABLE_,
so the symbol remains undefined. This means shared libraries
using TLS built with the integrated assembler are currently
broken.
While the whole RelocNeedsGOT / _GLOBAL_OFFSET_TABLE_ situation
probably ought to be properly fixed at some point, for now I'm
simply reverting the r185476 commit. Now this in turn exposes
the breakage of handling @tlsgd/@tlsld in the asm parser that
this check-in was originally intended to fix.
To avoid this regression, I'm also adding a different fix for
this problem: while common code now parses @tlsgd as VK_TLSGD,
a special hack in the asm parser translates this code to the
platform-specific VK_PPC_TLSGD that the back-end now expects.
While this is not really pretty, it's self-contained and
shouldn't hurt anything else for now. One the underlying
problem is fixed, this hack can be reverted again.
llvm-svn: 185945
2013-07-10 00:41:09 +08:00
|
|
|
const MCExpr *FixupVariantKind(const MCExpr *E);
|
2013-06-21 00:23:52 +08:00
|
|
|
bool ParseExpression(const MCExpr *&EVal);
|
2013-12-14 21:34:02 +08:00
|
|
|
bool ParseDarwinExpression(const MCExpr *&EVal);
|
2013-06-21 00:23:52 +08:00
|
|
|
|
2014-06-09 00:18:35 +08:00
|
|
|
bool ParseOperand(OperandVector &Operands);
|
2013-05-04 03:49:39 +08:00
|
|
|
|
2016-12-05 22:11:03 +08:00
|
|
|
bool ParseDirectiveWord(unsigned Size, AsmToken ID);
|
|
|
|
bool ParseDirectiveTC(unsigned Size, AsmToken ID);
|
2013-07-09 18:00:34 +08:00
|
|
|
bool ParseDirectiveMachine(SMLoc L);
|
2013-12-14 21:34:02 +08:00
|
|
|
bool ParseDarwinDirectiveMachine(SMLoc L);
|
2014-07-21 06:56:57 +08:00
|
|
|
bool ParseDirectiveAbiVersion(SMLoc L);
|
[PowerPC] ELFv2 MC support for .localentry directive
A second binutils feature needed to support ELFv2 is the .localentry
directive. In the ELFv2 ABI, functions may have two entry points:
one for calling the routine locally via "bl", and one for calling the
function via function pointer (either at the source level, or implicitly
via a PLT stub for global calls). The two entry points share a single
ELF symbol, where the ELF symbol address identifies the global entry
point address, while the local entry point is found by adding a delta
offset to the symbol address. That offset is encoded into three
platform-specific bits of the ELF symbol st_other field.
The .localentry directive instructs the assembler to set those fields
to encode a particular offset. This is typically used by a function
prologue sequence like this:
func:
addis r2, r12, (.TOC.-func)@ha
addi r2, r2, (.TOC.-func)@l
.localentry func, .-func
Note that according to the ABI, when calling the global entry point,
r12 must be set to point the global entry point address itself; while
when calling the local entry point, r2 must be set to point to the TOC
base. The two instructions between the global and local entry point in
the above example translate the first requirement into the second.
This patch implements support in the PowerPC MC streamers to emit the
.localentry directive (both into assembler and ELF object output), as
well as support in the assembler parser to parse that directive.
In addition, there is another change required in MC fixup/relocation
handling to properly deal with relocations targeting function symbols
with two entry points: When the target function is known local, the MC
layer would immediately handle the fixup by inserting the target
address -- this is wrong, since the call may need to go to the local
entry point instead. The GNU assembler handles this case by *not*
directly resolving fixups targeting functions with two entry points,
but always emits the relocation and relies on the linker to handle
this case correctly. This patch changes LLVM MC to do the same (this
is done via the processFixupValue routine).
Similarly, there are cases where the assembler would normally emit a
relocation, but "simplify" it to a relocation targeting a *section*
instead of the actual symbol. For the same reason as above, this
may be wrong when the target symbol has two entry points. The GNU
assembler again handles this case by not performing this simplification
in that case, but leaving the relocation targeting the full symbol,
which is then resolved by the linker. This patch changes LLVM MC
to do the same (via the needsRelocateWithSymbol routine).
NOTE: The method used in this patch is overly pessimistic, since the
needsRelocateWithSymbol routine currently does not have access to the
actual target symbol, and thus must always assume that it might have
two entry points. This will be improved upon by a follow-on patch
that modifies common code to pass the target symbol when calling
needsRelocateWithSymbol.
Reviewed by Hal Finkel.
llvm-svn: 213485
2014-07-21 07:06:03 +08:00
|
|
|
bool ParseDirectiveLocalEntry(SMLoc L);
|
2013-05-04 03:49:39 +08:00
|
|
|
|
|
|
|
bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
|
2014-06-09 00:18:35 +08:00
|
|
|
OperandVector &Operands, MCStreamer &Out,
|
2014-08-18 19:49:42 +08:00
|
|
|
uint64_t &ErrorInfo,
|
2014-04-29 15:57:37 +08:00
|
|
|
bool MatchingInlineAsm) override;
|
2013-05-04 03:49:39 +08:00
|
|
|
|
2014-06-09 00:18:35 +08:00
|
|
|
void ProcessInstruction(MCInst &Inst, const OperandVector &Ops);
|
2013-05-04 03:50:27 +08:00
|
|
|
|
2013-05-04 03:49:39 +08:00
|
|
|
/// @name Auto-generated Match Functions
|
|
|
|
/// {
|
|
|
|
|
|
|
|
#define GET_ASSEMBLER_HEADER
|
|
|
|
#include "PPCGenAsmMatcher.inc"
|
|
|
|
|
|
|
|
/// }
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
2015-11-14 14:35:56 +08:00
|
|
|
PPCAsmParser(const MCSubtargetInfo &STI, MCAsmParser &,
|
2015-11-14 13:20:05 +08:00
|
|
|
const MCInstrInfo &MII, const MCTargetOptions &Options)
|
2017-10-11 17:17:43 +08:00
|
|
|
: MCTargetAsmParser(Options, STI, MII) {
|
2013-05-04 03:49:39 +08:00
|
|
|
// Check for 64-bit vs. 32-bit pointer mode.
|
2016-05-27 20:30:51 +08:00
|
|
|
const Triple &TheTriple = STI.getTargetTriple();
|
2015-09-16 00:17:27 +08:00
|
|
|
IsPPC64 = (TheTriple.getArch() == Triple::ppc64 ||
|
|
|
|
TheTriple.getArch() == Triple::ppc64le);
|
|
|
|
IsDarwin = TheTriple.isMacOSX();
|
2013-05-04 03:49:39 +08:00
|
|
|
// Initialize the set of available features.
|
|
|
|
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
|
|
|
|
}
|
|
|
|
|
2014-06-09 00:18:35 +08:00
|
|
|
bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
|
|
|
|
SMLoc NameLoc, OperandVector &Operands) override;
|
2013-05-04 03:49:39 +08:00
|
|
|
|
2014-04-29 15:57:37 +08:00
|
|
|
bool ParseDirective(AsmToken DirectiveID) override;
|
2013-07-08 22:49:37 +08:00
|
|
|
|
2014-06-09 00:18:35 +08:00
|
|
|
unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
|
2014-04-29 15:57:37 +08:00
|
|
|
unsigned Kind) override;
|
2013-08-28 04:23:19 +08:00
|
|
|
|
2014-04-29 15:57:37 +08:00
|
|
|
const MCExpr *applyModifierToExpr(const MCExpr *E,
|
|
|
|
MCSymbolRefExpr::VariantKind,
|
|
|
|
MCContext &Ctx) override;
|
2013-05-04 03:49:39 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/// PPCOperand - Instances of this class represent a parsed PowerPC machine
|
|
|
|
/// instruction.
|
|
|
|
struct PPCOperand : public MCParsedAsmOperand {
|
|
|
|
enum KindTy {
|
|
|
|
Token,
|
|
|
|
Immediate,
|
2014-08-10 20:41:50 +08:00
|
|
|
ContextImmediate,
|
2013-07-05 20:22:36 +08:00
|
|
|
Expression,
|
|
|
|
TLSRegister
|
2013-05-04 03:49:39 +08:00
|
|
|
} Kind;
|
|
|
|
|
|
|
|
SMLoc StartLoc, EndLoc;
|
|
|
|
bool IsPPC64;
|
|
|
|
|
|
|
|
struct TokOp {
|
|
|
|
const char *Data;
|
|
|
|
unsigned Length;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ImmOp {
|
|
|
|
int64_t Val;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ExprOp {
|
|
|
|
const MCExpr *Val;
|
2013-07-04 22:24:00 +08:00
|
|
|
int64_t CRVal; // Cached result of EvaluateCRExpr(Val)
|
2013-05-04 03:49:39 +08:00
|
|
|
};
|
|
|
|
|
2013-07-05 20:22:36 +08:00
|
|
|
struct TLSRegOp {
|
|
|
|
const MCSymbolRefExpr *Sym;
|
|
|
|
};
|
|
|
|
|
2013-05-04 03:49:39 +08:00
|
|
|
union {
|
|
|
|
struct TokOp Tok;
|
|
|
|
struct ImmOp Imm;
|
|
|
|
struct ExprOp Expr;
|
2013-07-05 20:22:36 +08:00
|
|
|
struct TLSRegOp TLSReg;
|
2013-05-04 03:49:39 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
PPCOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
|
|
|
|
public:
|
|
|
|
PPCOperand(const PPCOperand &o) : MCParsedAsmOperand() {
|
|
|
|
Kind = o.Kind;
|
|
|
|
StartLoc = o.StartLoc;
|
|
|
|
EndLoc = o.EndLoc;
|
|
|
|
IsPPC64 = o.IsPPC64;
|
|
|
|
switch (Kind) {
|
|
|
|
case Token:
|
|
|
|
Tok = o.Tok;
|
|
|
|
break;
|
|
|
|
case Immediate:
|
2014-08-10 20:41:50 +08:00
|
|
|
case ContextImmediate:
|
2013-05-04 03:49:39 +08:00
|
|
|
Imm = o.Imm;
|
|
|
|
break;
|
|
|
|
case Expression:
|
|
|
|
Expr = o.Expr;
|
|
|
|
break;
|
2013-07-05 20:22:36 +08:00
|
|
|
case TLSRegister:
|
|
|
|
TLSReg = o.TLSReg;
|
|
|
|
break;
|
2013-05-04 03:49:39 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-08 08:59:44 +08:00
|
|
|
// Disable use of sized deallocation due to overallocation of PPCOperand
|
|
|
|
// objects in CreateTokenWithStringCopy.
|
|
|
|
void operator delete(void *p) { ::operator delete(p); }
|
|
|
|
|
2013-05-04 03:49:39 +08:00
|
|
|
/// getStartLoc - Get the location of the first token of this operand.
|
2014-04-29 15:57:37 +08:00
|
|
|
SMLoc getStartLoc() const override { return StartLoc; }
|
2013-05-04 03:49:39 +08:00
|
|
|
|
|
|
|
/// getEndLoc - Get the location of the last token of this operand.
|
2016-10-11 06:49:37 +08:00
|
|
|
SMLoc getEndLoc() const override { return EndLoc; }
|
2013-05-04 03:49:39 +08:00
|
|
|
|
|
|
|
/// isPPC64 - True if this operand is for an instruction in 64-bit mode.
|
|
|
|
bool isPPC64() const { return IsPPC64; }
|
|
|
|
|
|
|
|
int64_t getImm() const {
|
|
|
|
assert(Kind == Immediate && "Invalid access!");
|
|
|
|
return Imm.Val;
|
|
|
|
}
|
2014-08-10 20:41:50 +08:00
|
|
|
int64_t getImmS16Context() const {
|
2016-06-16 09:00:53 +08:00
|
|
|
assert((Kind == Immediate || Kind == ContextImmediate) &&
|
|
|
|
"Invalid access!");
|
2014-08-10 20:41:50 +08:00
|
|
|
if (Kind == Immediate)
|
|
|
|
return Imm.Val;
|
|
|
|
return static_cast<int16_t>(Imm.Val);
|
|
|
|
}
|
|
|
|
int64_t getImmU16Context() const {
|
2016-06-16 09:00:53 +08:00
|
|
|
assert((Kind == Immediate || Kind == ContextImmediate) &&
|
|
|
|
"Invalid access!");
|
2014-08-10 20:41:50 +08:00
|
|
|
return Imm.Val;
|
|
|
|
}
|
2013-05-04 03:49:39 +08:00
|
|
|
|
|
|
|
const MCExpr *getExpr() const {
|
|
|
|
assert(Kind == Expression && "Invalid access!");
|
|
|
|
return Expr.Val;
|
|
|
|
}
|
|
|
|
|
2013-07-04 22:24:00 +08:00
|
|
|
int64_t getExprCRVal() const {
|
|
|
|
assert(Kind == Expression && "Invalid access!");
|
|
|
|
return Expr.CRVal;
|
|
|
|
}
|
|
|
|
|
2013-07-05 20:22:36 +08:00
|
|
|
const MCExpr *getTLSReg() const {
|
|
|
|
assert(Kind == TLSRegister && "Invalid access!");
|
|
|
|
return TLSReg.Sym;
|
|
|
|
}
|
|
|
|
|
2014-04-29 15:57:37 +08:00
|
|
|
unsigned getReg() const override {
|
2013-05-04 03:49:39 +08:00
|
|
|
assert(isRegNumber() && "Invalid access!");
|
|
|
|
return (unsigned) Imm.Val;
|
|
|
|
}
|
|
|
|
|
[PowerPC] Initial support for the VSX instruction set
VSX is an ISA extension supported on the POWER7 and later cores that enhances
floating-point vector and scalar capabilities. Among other things, this adds
<2 x double> support and generally helps to reduce register pressure.
The interesting part of this ISA feature is the register configuration: there
are 64 new 128-bit vector registers, the 32 of which are super-registers of the
existing 32 scalar floating-point registers, and the second 32 of which overlap
with the 32 Altivec vector registers. This makes things like vector insertion
and extraction tricky: this can be free but only if we force a restriction to
the right register subclass when needed. A new "minipass" PPCVSXCopy takes care
of this (although it could do a more-optimal job of it; see the comment about
unnecessary copies below).
Please note that, currently, VSX is not enabled by default when targeting
anything because it is not yet ready for that. The assembler and disassembler
are fully implemented and tested. However:
- CodeGen support causes miscompiles; test-suite runtime failures:
MultiSource/Benchmarks/FreeBench/distray/distray
MultiSource/Benchmarks/McCat/08-main/main
MultiSource/Benchmarks/Olden/voronoi/voronoi
MultiSource/Benchmarks/mafft/pairlocalalign
MultiSource/Benchmarks/tramp3d-v4/tramp3d-v4
SingleSource/Benchmarks/CoyoteBench/almabench
SingleSource/Benchmarks/Misc/matmul_f64_4x4
- The lowering currently falls back to using Altivec instructions far more
than it should. Worse, there are some things that are scalarized through the
stack that shouldn't be.
- A lot of unnecessary copies make it past the optimizers, and this needs to
be fixed.
- Many more regression tests are needed.
Normally, I'd fix these things prior to committing, but there are some
students and other contributors who would like to work this, and so it makes
sense to move this development process upstream where it can be subject to the
regular code-review procedures.
llvm-svn: 203768
2014-03-13 15:58:58 +08:00
|
|
|
unsigned getVSReg() const {
|
|
|
|
assert(isVSRegNumber() && "Invalid access!");
|
|
|
|
return (unsigned) Imm.Val;
|
|
|
|
}
|
|
|
|
|
2013-05-04 03:49:39 +08:00
|
|
|
unsigned getCCReg() const {
|
|
|
|
assert(isCCRegNumber() && "Invalid access!");
|
2013-07-04 22:24:00 +08:00
|
|
|
return (unsigned) (Kind == Immediate ? Imm.Val : Expr.CRVal);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned getCRBit() const {
|
|
|
|
assert(isCRBitNumber() && "Invalid access!");
|
|
|
|
return (unsigned) (Kind == Immediate ? Imm.Val : Expr.CRVal);
|
2013-05-04 03:49:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
unsigned getCRBitMask() const {
|
|
|
|
assert(isCRBitMask() && "Invalid access!");
|
2013-05-25 06:23:49 +08:00
|
|
|
return 7 - countTrailingZeros<uint64_t>(Imm.Val);
|
2013-05-04 03:49:39 +08:00
|
|
|
}
|
|
|
|
|
2014-04-29 15:57:37 +08:00
|
|
|
bool isToken() const override { return Kind == Token; }
|
2016-06-16 09:00:53 +08:00
|
|
|
bool isImm() const override {
|
|
|
|
return Kind == Immediate || Kind == Expression;
|
|
|
|
}
|
2015-03-05 04:44:33 +08:00
|
|
|
bool isU1Imm() const { return Kind == Immediate && isUInt<1>(getImm()); }
|
[PowerPC] Initial support for the VSX instruction set
VSX is an ISA extension supported on the POWER7 and later cores that enhances
floating-point vector and scalar capabilities. Among other things, this adds
<2 x double> support and generally helps to reduce register pressure.
The interesting part of this ISA feature is the register configuration: there
are 64 new 128-bit vector registers, the 32 of which are super-registers of the
existing 32 scalar floating-point registers, and the second 32 of which overlap
with the 32 Altivec vector registers. This makes things like vector insertion
and extraction tricky: this can be free but only if we force a restriction to
the right register subclass when needed. A new "minipass" PPCVSXCopy takes care
of this (although it could do a more-optimal job of it; see the comment about
unnecessary copies below).
Please note that, currently, VSX is not enabled by default when targeting
anything because it is not yet ready for that. The assembler and disassembler
are fully implemented and tested. However:
- CodeGen support causes miscompiles; test-suite runtime failures:
MultiSource/Benchmarks/FreeBench/distray/distray
MultiSource/Benchmarks/McCat/08-main/main
MultiSource/Benchmarks/Olden/voronoi/voronoi
MultiSource/Benchmarks/mafft/pairlocalalign
MultiSource/Benchmarks/tramp3d-v4/tramp3d-v4
SingleSource/Benchmarks/CoyoteBench/almabench
SingleSource/Benchmarks/Misc/matmul_f64_4x4
- The lowering currently falls back to using Altivec instructions far more
than it should. Worse, there are some things that are scalarized through the
stack that shouldn't be.
- A lot of unnecessary copies make it past the optimizers, and this needs to
be fixed.
- Many more regression tests are needed.
Normally, I'd fix these things prior to committing, but there are some
students and other contributors who would like to work this, and so it makes
sense to move this development process upstream where it can be subject to the
regular code-review procedures.
llvm-svn: 203768
2014-03-13 15:58:58 +08:00
|
|
|
bool isU2Imm() const { return Kind == Immediate && isUInt<2>(getImm()); }
|
2015-03-26 03:36:23 +08:00
|
|
|
bool isU3Imm() const { return Kind == Immediate && isUInt<3>(getImm()); }
|
2014-07-30 06:21:57 +08:00
|
|
|
bool isU4Imm() const { return Kind == Immediate && isUInt<4>(getImm()); }
|
2013-05-04 03:49:39 +08:00
|
|
|
bool isU5Imm() const { return Kind == Immediate && isUInt<5>(getImm()); }
|
|
|
|
bool isS5Imm() const { return Kind == Immediate && isInt<5>(getImm()); }
|
|
|
|
bool isU6Imm() const { return Kind == Immediate && isUInt<6>(getImm()); }
|
2014-08-09 00:43:49 +08:00
|
|
|
bool isU6ImmX2() const { return Kind == Immediate &&
|
|
|
|
isUInt<6>(getImm()) &&
|
|
|
|
(getImm() & 1) == 0; }
|
[Power9] Implement new vsx instructions: insert, extract, test data class, min/max, reverse, permute, splat
This change implements the following vsx instructions:
- Scalar Insert/Extract
xsiexpdp xsiexpqp xsxexpdp xsxsigdp xsxexpqp xsxsigqp
- Vector Insert/Extract
xviexpdp xviexpsp xvxexpdp xvxexpsp xvxsigdp xvxsigsp
xxextractuw xxinsertw
- Scalar/Vector Test Data Class
xststdcdp xststdcsp xststdcqp
xvtstdcdp xvtstdcsp
- Maximum/Minimum
xsmaxcdp xsmaxjdp
xsmincdp xsminjdp
- Vector Byte-Reverse/Permute/Splat
xxbrd xxbrh xxbrq xxbrw
xxperm xxpermr
xxspltib
30 instructions
Thanks Nemanja for invaluable discussion! Thanks Kit's great help!
Reviewers: hal, nemanja, kbarton, tjablin, amehsan
http://reviews.llvm.org/D16842
llvm-svn: 264567
2016-03-28 16:34:28 +08:00
|
|
|
bool isU7Imm() const { return Kind == Immediate && isUInt<7>(getImm()); }
|
2014-08-09 00:43:49 +08:00
|
|
|
bool isU7ImmX4() const { return Kind == Immediate &&
|
|
|
|
isUInt<7>(getImm()) &&
|
|
|
|
(getImm() & 3) == 0; }
|
[Power9] Implement new vsx instructions: insert, extract, test data class, min/max, reverse, permute, splat
This change implements the following vsx instructions:
- Scalar Insert/Extract
xsiexpdp xsiexpqp xsxexpdp xsxsigdp xsxexpqp xsxsigqp
- Vector Insert/Extract
xviexpdp xviexpsp xvxexpdp xvxexpsp xvxsigdp xvxsigsp
xxextractuw xxinsertw
- Scalar/Vector Test Data Class
xststdcdp xststdcsp xststdcqp
xvtstdcdp xvtstdcsp
- Maximum/Minimum
xsmaxcdp xsmaxjdp
xsmincdp xsminjdp
- Vector Byte-Reverse/Permute/Splat
xxbrd xxbrh xxbrq xxbrw
xxperm xxpermr
xxspltib
30 instructions
Thanks Nemanja for invaluable discussion! Thanks Kit's great help!
Reviewers: hal, nemanja, kbarton, tjablin, amehsan
http://reviews.llvm.org/D16842
llvm-svn: 264567
2016-03-28 16:34:28 +08:00
|
|
|
bool isU8Imm() const { return Kind == Immediate && isUInt<8>(getImm()); }
|
2014-08-09 00:43:49 +08:00
|
|
|
bool isU8ImmX8() const { return Kind == Immediate &&
|
|
|
|
isUInt<8>(getImm()) &&
|
|
|
|
(getImm() & 7) == 0; }
|
2016-06-16 09:00:53 +08:00
|
|
|
|
2015-05-23 00:44:10 +08:00
|
|
|
bool isU10Imm() const { return Kind == Immediate && isUInt<10>(getImm()); }
|
[PowerPC] Add support for the QPX vector instruction set
This adds support for the QPX vector instruction set, which is used by the
enhanced A2 cores on the IBM BG/Q supercomputers. QPX vectors are 256 bytes
wide, holding 4 double-precision floating-point values. Boolean values, modeled
here as <4 x i1> are actually also represented as floating-point values
(essentially { -1, 1 } for { false, true }). QPX shares many features with
Altivec and VSX, but is distinct from both of them. One major difference is
that, instead of adding completely-separate vector registers, QPX vector
registers are extensions of the scalar floating-point registers (lane 0 is the
corresponding scalar floating-point value). The operations supported on QPX
vectors mirrors that supported on the scalar floating-point values (with some
additional ones for permutations and logical/comparison operations).
I've been maintaining this support out-of-tree, as part of the bgclang project,
for several years. This is not the entire bgclang patch set, but is most of the
subset that can be cleanly integrated into LLVM proper at this time. Adding
this to the LLVM backend is part of my efforts to rebase bgclang to the current
LLVM trunk, but is independently useful (especially for codes that use LLVM as
a JIT in library form).
The assembler/disassembler test coverage is complete. The CodeGen test coverage
is not, but I've included some tests, and more will be added as follow-up work.
llvm-svn: 230413
2015-02-25 09:06:45 +08:00
|
|
|
bool isU12Imm() const { return Kind == Immediate && isUInt<12>(getImm()); }
|
2014-08-10 20:41:50 +08:00
|
|
|
bool isU16Imm() const {
|
|
|
|
switch (Kind) {
|
|
|
|
case Expression:
|
|
|
|
return true;
|
|
|
|
case Immediate:
|
|
|
|
case ContextImmediate:
|
|
|
|
return isUInt<16>(getImmU16Context());
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
bool isS16Imm() const {
|
|
|
|
switch (Kind) {
|
|
|
|
case Expression:
|
|
|
|
return true;
|
|
|
|
case Immediate:
|
|
|
|
case ContextImmediate:
|
|
|
|
return isInt<16>(getImmS16Context());
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2013-05-04 03:49:39 +08:00
|
|
|
bool isS16ImmX4() const { return Kind == Expression ||
|
|
|
|
(Kind == Immediate && isInt<16>(getImm()) &&
|
|
|
|
(getImm() & 3) == 0); }
|
2016-03-08 11:49:13 +08:00
|
|
|
bool isS16ImmX16() const { return Kind == Expression ||
|
|
|
|
(Kind == Immediate && isInt<16>(getImm()) &&
|
|
|
|
(getImm() & 15) == 0); }
|
2014-08-10 20:41:50 +08:00
|
|
|
bool isS17Imm() const {
|
|
|
|
switch (Kind) {
|
|
|
|
case Expression:
|
|
|
|
return true;
|
|
|
|
case Immediate:
|
|
|
|
case ContextImmediate:
|
|
|
|
return isInt<17>(getImmS16Context());
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2013-07-05 20:22:36 +08:00
|
|
|
bool isTLSReg() const { return Kind == TLSRegister; }
|
2014-08-09 04:57:58 +08:00
|
|
|
bool isDirectBr() const {
|
|
|
|
if (Kind == Expression)
|
|
|
|
return true;
|
|
|
|
if (Kind != Immediate)
|
|
|
|
return false;
|
|
|
|
// Operand must be 64-bit aligned, signed 27-bit immediate.
|
|
|
|
if ((getImm() & 3) != 0)
|
|
|
|
return false;
|
|
|
|
if (isInt<26>(getImm()))
|
|
|
|
return true;
|
|
|
|
if (!IsPPC64) {
|
|
|
|
// In 32-bit mode, large 32-bit quantities wrap around.
|
|
|
|
if (isUInt<32>(getImm()) && isInt<26>(static_cast<int32_t>(getImm())))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2013-06-24 19:03:33 +08:00
|
|
|
bool isCondBr() const { return Kind == Expression ||
|
|
|
|
(Kind == Immediate && isInt<16>(getImm()) &&
|
|
|
|
(getImm() & 3) == 0); }
|
2013-05-04 03:49:39 +08:00
|
|
|
bool isRegNumber() const { return Kind == Immediate && isUInt<5>(getImm()); }
|
2016-06-16 09:00:53 +08:00
|
|
|
bool isVSRegNumber() const {
|
|
|
|
return Kind == Immediate && isUInt<6>(getImm());
|
|
|
|
}
|
2013-07-04 22:24:00 +08:00
|
|
|
bool isCCRegNumber() const { return (Kind == Expression
|
|
|
|
&& isUInt<3>(getExprCRVal())) ||
|
|
|
|
(Kind == Immediate
|
|
|
|
&& isUInt<3>(getImm())); }
|
|
|
|
bool isCRBitNumber() const { return (Kind == Expression
|
|
|
|
&& isUInt<5>(getExprCRVal())) ||
|
|
|
|
(Kind == Immediate
|
|
|
|
&& isUInt<5>(getImm())); }
|
2013-05-04 03:49:39 +08:00
|
|
|
bool isCRBitMask() const { return Kind == Immediate && isUInt<8>(getImm()) &&
|
|
|
|
isPowerOf2_32(getImm()); }
|
[PowerPC] Support asm parsing for bc[l][a][+-] mnemonics
PowerPC assembly code in the wild, so it seems, has things like this:
bc+ 12, 28, .L9
This is a bit odd because the '+' here becomes part of the BO field, and the BO
field is otherwise the first operand. Nevertheless, the ISA specification does
clearly say that the +- hint syntax applies to all conditional-branch mnemonics
(that test either CTR or a condition register, although not the forms which
check both), both basic and extended, so this is supposed to be valid.
This introduces some asm-parser-only definitions which take only the upper
three bits from the specified BO value, and the lower two bits are implied by
the +- suffix (via some associated aliases).
Fixes PR23646.
llvm-svn: 280571
2016-09-03 10:31:44 +08:00
|
|
|
bool isATBitsAsHint() const { return false; }
|
2014-04-29 15:57:37 +08:00
|
|
|
bool isMem() const override { return false; }
|
|
|
|
bool isReg() const override { return false; }
|
2013-05-04 03:49:39 +08:00
|
|
|
|
|
|
|
void addRegOperands(MCInst &Inst, unsigned N) const {
|
|
|
|
llvm_unreachable("addRegOperands");
|
|
|
|
}
|
|
|
|
|
|
|
|
void addRegGPRCOperands(MCInst &Inst, unsigned N) const {
|
|
|
|
assert(N == 1 && "Invalid number of operands!");
|
2015-05-14 02:37:00 +08:00
|
|
|
Inst.addOperand(MCOperand::createReg(RRegs[getReg()]));
|
2013-05-04 03:49:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void addRegGPRCNoR0Operands(MCInst &Inst, unsigned N) const {
|
|
|
|
assert(N == 1 && "Invalid number of operands!");
|
2015-05-14 02:37:00 +08:00
|
|
|
Inst.addOperand(MCOperand::createReg(RRegsNoR0[getReg()]));
|
2013-05-04 03:49:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void addRegG8RCOperands(MCInst &Inst, unsigned N) const {
|
|
|
|
assert(N == 1 && "Invalid number of operands!");
|
2015-05-14 02:37:00 +08:00
|
|
|
Inst.addOperand(MCOperand::createReg(XRegs[getReg()]));
|
2013-05-04 03:49:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void addRegG8RCNoX0Operands(MCInst &Inst, unsigned N) const {
|
|
|
|
assert(N == 1 && "Invalid number of operands!");
|
2015-05-14 02:37:00 +08:00
|
|
|
Inst.addOperand(MCOperand::createReg(XRegsNoX0[getReg()]));
|
2013-05-04 03:49:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void addRegGxRCOperands(MCInst &Inst, unsigned N) const {
|
|
|
|
if (isPPC64())
|
|
|
|
addRegG8RCOperands(Inst, N);
|
|
|
|
else
|
|
|
|
addRegGPRCOperands(Inst, N);
|
|
|
|
}
|
|
|
|
|
|
|
|
void addRegGxRCNoR0Operands(MCInst &Inst, unsigned N) const {
|
|
|
|
if (isPPC64())
|
|
|
|
addRegG8RCNoX0Operands(Inst, N);
|
|
|
|
else
|
|
|
|
addRegGPRCNoR0Operands(Inst, N);
|
|
|
|
}
|
|
|
|
|
|
|
|
void addRegF4RCOperands(MCInst &Inst, unsigned N) const {
|
|
|
|
assert(N == 1 && "Invalid number of operands!");
|
2015-05-14 02:37:00 +08:00
|
|
|
Inst.addOperand(MCOperand::createReg(FRegs[getReg()]));
|
2013-05-04 03:49:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void addRegF8RCOperands(MCInst &Inst, unsigned N) const {
|
|
|
|
assert(N == 1 && "Invalid number of operands!");
|
2015-05-14 02:37:00 +08:00
|
|
|
Inst.addOperand(MCOperand::createReg(FRegs[getReg()]));
|
2013-05-04 03:49:39 +08:00
|
|
|
}
|
|
|
|
|
2016-10-04 14:59:23 +08:00
|
|
|
void addRegVFRCOperands(MCInst &Inst, unsigned N) const {
|
|
|
|
assert(N == 1 && "Invalid number of operands!");
|
|
|
|
Inst.addOperand(MCOperand::createReg(VFRegs[getReg()]));
|
|
|
|
}
|
|
|
|
|
2013-05-04 03:49:39 +08:00
|
|
|
void addRegVRRCOperands(MCInst &Inst, unsigned N) const {
|
|
|
|
assert(N == 1 && "Invalid number of operands!");
|
2015-05-14 02:37:00 +08:00
|
|
|
Inst.addOperand(MCOperand::createReg(VRegs[getReg()]));
|
2013-05-04 03:49:39 +08:00
|
|
|
}
|
|
|
|
|
[PowerPC] Initial support for the VSX instruction set
VSX is an ISA extension supported on the POWER7 and later cores that enhances
floating-point vector and scalar capabilities. Among other things, this adds
<2 x double> support and generally helps to reduce register pressure.
The interesting part of this ISA feature is the register configuration: there
are 64 new 128-bit vector registers, the 32 of which are super-registers of the
existing 32 scalar floating-point registers, and the second 32 of which overlap
with the 32 Altivec vector registers. This makes things like vector insertion
and extraction tricky: this can be free but only if we force a restriction to
the right register subclass when needed. A new "minipass" PPCVSXCopy takes care
of this (although it could do a more-optimal job of it; see the comment about
unnecessary copies below).
Please note that, currently, VSX is not enabled by default when targeting
anything because it is not yet ready for that. The assembler and disassembler
are fully implemented and tested. However:
- CodeGen support causes miscompiles; test-suite runtime failures:
MultiSource/Benchmarks/FreeBench/distray/distray
MultiSource/Benchmarks/McCat/08-main/main
MultiSource/Benchmarks/Olden/voronoi/voronoi
MultiSource/Benchmarks/mafft/pairlocalalign
MultiSource/Benchmarks/tramp3d-v4/tramp3d-v4
SingleSource/Benchmarks/CoyoteBench/almabench
SingleSource/Benchmarks/Misc/matmul_f64_4x4
- The lowering currently falls back to using Altivec instructions far more
than it should. Worse, there are some things that are scalarized through the
stack that shouldn't be.
- A lot of unnecessary copies make it past the optimizers, and this needs to
be fixed.
- Many more regression tests are needed.
Normally, I'd fix these things prior to committing, but there are some
students and other contributors who would like to work this, and so it makes
sense to move this development process upstream where it can be subject to the
regular code-review procedures.
llvm-svn: 203768
2014-03-13 15:58:58 +08:00
|
|
|
void addRegVSRCOperands(MCInst &Inst, unsigned N) const {
|
|
|
|
assert(N == 1 && "Invalid number of operands!");
|
2015-05-14 02:37:00 +08:00
|
|
|
Inst.addOperand(MCOperand::createReg(VSRegs[getVSReg()]));
|
[PowerPC] Initial support for the VSX instruction set
VSX is an ISA extension supported on the POWER7 and later cores that enhances
floating-point vector and scalar capabilities. Among other things, this adds
<2 x double> support and generally helps to reduce register pressure.
The interesting part of this ISA feature is the register configuration: there
are 64 new 128-bit vector registers, the 32 of which are super-registers of the
existing 32 scalar floating-point registers, and the second 32 of which overlap
with the 32 Altivec vector registers. This makes things like vector insertion
and extraction tricky: this can be free but only if we force a restriction to
the right register subclass when needed. A new "minipass" PPCVSXCopy takes care
of this (although it could do a more-optimal job of it; see the comment about
unnecessary copies below).
Please note that, currently, VSX is not enabled by default when targeting
anything because it is not yet ready for that. The assembler and disassembler
are fully implemented and tested. However:
- CodeGen support causes miscompiles; test-suite runtime failures:
MultiSource/Benchmarks/FreeBench/distray/distray
MultiSource/Benchmarks/McCat/08-main/main
MultiSource/Benchmarks/Olden/voronoi/voronoi
MultiSource/Benchmarks/mafft/pairlocalalign
MultiSource/Benchmarks/tramp3d-v4/tramp3d-v4
SingleSource/Benchmarks/CoyoteBench/almabench
SingleSource/Benchmarks/Misc/matmul_f64_4x4
- The lowering currently falls back to using Altivec instructions far more
than it should. Worse, there are some things that are scalarized through the
stack that shouldn't be.
- A lot of unnecessary copies make it past the optimizers, and this needs to
be fixed.
- Many more regression tests are needed.
Normally, I'd fix these things prior to committing, but there are some
students and other contributors who would like to work this, and so it makes
sense to move this development process upstream where it can be subject to the
regular code-review procedures.
llvm-svn: 203768
2014-03-13 15:58:58 +08:00
|
|
|
}
|
|
|
|
|
2014-03-29 13:29:01 +08:00
|
|
|
void addRegVSFRCOperands(MCInst &Inst, unsigned N) const {
|
|
|
|
assert(N == 1 && "Invalid number of operands!");
|
2015-05-14 02:37:00 +08:00
|
|
|
Inst.addOperand(MCOperand::createReg(VSFRegs[getVSReg()]));
|
2014-03-29 13:29:01 +08:00
|
|
|
}
|
|
|
|
|
2015-05-08 02:24:05 +08:00
|
|
|
void addRegVSSRCOperands(MCInst &Inst, unsigned N) const {
|
|
|
|
assert(N == 1 && "Invalid number of operands!");
|
2015-05-14 02:37:00 +08:00
|
|
|
Inst.addOperand(MCOperand::createReg(VSSRegs[getVSReg()]));
|
2015-05-08 02:24:05 +08:00
|
|
|
}
|
|
|
|
|
[PowerPC] Add support for the QPX vector instruction set
This adds support for the QPX vector instruction set, which is used by the
enhanced A2 cores on the IBM BG/Q supercomputers. QPX vectors are 256 bytes
wide, holding 4 double-precision floating-point values. Boolean values, modeled
here as <4 x i1> are actually also represented as floating-point values
(essentially { -1, 1 } for { false, true }). QPX shares many features with
Altivec and VSX, but is distinct from both of them. One major difference is
that, instead of adding completely-separate vector registers, QPX vector
registers are extensions of the scalar floating-point registers (lane 0 is the
corresponding scalar floating-point value). The operations supported on QPX
vectors mirrors that supported on the scalar floating-point values (with some
additional ones for permutations and logical/comparison operations).
I've been maintaining this support out-of-tree, as part of the bgclang project,
for several years. This is not the entire bgclang patch set, but is most of the
subset that can be cleanly integrated into LLVM proper at this time. Adding
this to the LLVM backend is part of my efforts to rebase bgclang to the current
LLVM trunk, but is independently useful (especially for codes that use LLVM as
a JIT in library form).
The assembler/disassembler test coverage is complete. The CodeGen test coverage
is not, but I've included some tests, and more will be added as follow-up work.
llvm-svn: 230413
2015-02-25 09:06:45 +08:00
|
|
|
void addRegQFRCOperands(MCInst &Inst, unsigned N) const {
|
|
|
|
assert(N == 1 && "Invalid number of operands!");
|
2015-05-14 02:37:00 +08:00
|
|
|
Inst.addOperand(MCOperand::createReg(QFRegs[getReg()]));
|
[PowerPC] Add support for the QPX vector instruction set
This adds support for the QPX vector instruction set, which is used by the
enhanced A2 cores on the IBM BG/Q supercomputers. QPX vectors are 256 bytes
wide, holding 4 double-precision floating-point values. Boolean values, modeled
here as <4 x i1> are actually also represented as floating-point values
(essentially { -1, 1 } for { false, true }). QPX shares many features with
Altivec and VSX, but is distinct from both of them. One major difference is
that, instead of adding completely-separate vector registers, QPX vector
registers are extensions of the scalar floating-point registers (lane 0 is the
corresponding scalar floating-point value). The operations supported on QPX
vectors mirrors that supported on the scalar floating-point values (with some
additional ones for permutations and logical/comparison operations).
I've been maintaining this support out-of-tree, as part of the bgclang project,
for several years. This is not the entire bgclang patch set, but is most of the
subset that can be cleanly integrated into LLVM proper at this time. Adding
this to the LLVM backend is part of my efforts to rebase bgclang to the current
LLVM trunk, but is independently useful (especially for codes that use LLVM as
a JIT in library form).
The assembler/disassembler test coverage is complete. The CodeGen test coverage
is not, but I've included some tests, and more will be added as follow-up work.
llvm-svn: 230413
2015-02-25 09:06:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void addRegQSRCOperands(MCInst &Inst, unsigned N) const {
|
|
|
|
assert(N == 1 && "Invalid number of operands!");
|
2015-05-14 02:37:00 +08:00
|
|
|
Inst.addOperand(MCOperand::createReg(QFRegs[getReg()]));
|
[PowerPC] Add support for the QPX vector instruction set
This adds support for the QPX vector instruction set, which is used by the
enhanced A2 cores on the IBM BG/Q supercomputers. QPX vectors are 256 bytes
wide, holding 4 double-precision floating-point values. Boolean values, modeled
here as <4 x i1> are actually also represented as floating-point values
(essentially { -1, 1 } for { false, true }). QPX shares many features with
Altivec and VSX, but is distinct from both of them. One major difference is
that, instead of adding completely-separate vector registers, QPX vector
registers are extensions of the scalar floating-point registers (lane 0 is the
corresponding scalar floating-point value). The operations supported on QPX
vectors mirrors that supported on the scalar floating-point values (with some
additional ones for permutations and logical/comparison operations).
I've been maintaining this support out-of-tree, as part of the bgclang project,
for several years. This is not the entire bgclang patch set, but is most of the
subset that can be cleanly integrated into LLVM proper at this time. Adding
this to the LLVM backend is part of my efforts to rebase bgclang to the current
LLVM trunk, but is independently useful (especially for codes that use LLVM as
a JIT in library form).
The assembler/disassembler test coverage is complete. The CodeGen test coverage
is not, but I've included some tests, and more will be added as follow-up work.
llvm-svn: 230413
2015-02-25 09:06:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void addRegQBRCOperands(MCInst &Inst, unsigned N) const {
|
|
|
|
assert(N == 1 && "Invalid number of operands!");
|
2015-05-14 02:37:00 +08:00
|
|
|
Inst.addOperand(MCOperand::createReg(QFRegs[getReg()]));
|
[PowerPC] Add support for the QPX vector instruction set
This adds support for the QPX vector instruction set, which is used by the
enhanced A2 cores on the IBM BG/Q supercomputers. QPX vectors are 256 bytes
wide, holding 4 double-precision floating-point values. Boolean values, modeled
here as <4 x i1> are actually also represented as floating-point values
(essentially { -1, 1 } for { false, true }). QPX shares many features with
Altivec and VSX, but is distinct from both of them. One major difference is
that, instead of adding completely-separate vector registers, QPX vector
registers are extensions of the scalar floating-point registers (lane 0 is the
corresponding scalar floating-point value). The operations supported on QPX
vectors mirrors that supported on the scalar floating-point values (with some
additional ones for permutations and logical/comparison operations).
I've been maintaining this support out-of-tree, as part of the bgclang project,
for several years. This is not the entire bgclang patch set, but is most of the
subset that can be cleanly integrated into LLVM proper at this time. Adding
this to the LLVM backend is part of my efforts to rebase bgclang to the current
LLVM trunk, but is independently useful (especially for codes that use LLVM as
a JIT in library form).
The assembler/disassembler test coverage is complete. The CodeGen test coverage
is not, but I've included some tests, and more will be added as follow-up work.
llvm-svn: 230413
2015-02-25 09:06:45 +08:00
|
|
|
}
|
|
|
|
|
2013-05-04 03:49:39 +08:00
|
|
|
void addRegCRBITRCOperands(MCInst &Inst, unsigned N) const {
|
|
|
|
assert(N == 1 && "Invalid number of operands!");
|
2015-05-14 02:37:00 +08:00
|
|
|
Inst.addOperand(MCOperand::createReg(CRBITRegs[getCRBit()]));
|
2013-05-04 03:49:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void addRegCRRCOperands(MCInst &Inst, unsigned N) const {
|
|
|
|
assert(N == 1 && "Invalid number of operands!");
|
2015-05-14 02:37:00 +08:00
|
|
|
Inst.addOperand(MCOperand::createReg(CRRegs[getCCReg()]));
|
2013-05-04 03:49:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void addCRBitMaskOperands(MCInst &Inst, unsigned N) const {
|
|
|
|
assert(N == 1 && "Invalid number of operands!");
|
2015-05-14 02:37:00 +08:00
|
|
|
Inst.addOperand(MCOperand::createReg(CRRegs[getCRBitMask()]));
|
2013-05-04 03:49:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void addImmOperands(MCInst &Inst, unsigned N) const {
|
|
|
|
assert(N == 1 && "Invalid number of operands!");
|
|
|
|
if (Kind == Immediate)
|
2015-05-14 02:37:00 +08:00
|
|
|
Inst.addOperand(MCOperand::createImm(getImm()));
|
2013-05-04 03:49:39 +08:00
|
|
|
else
|
2015-05-14 02:37:00 +08:00
|
|
|
Inst.addOperand(MCOperand::createExpr(getExpr()));
|
2013-05-04 03:49:39 +08:00
|
|
|
}
|
|
|
|
|
2014-08-10 20:41:50 +08:00
|
|
|
void addS16ImmOperands(MCInst &Inst, unsigned N) const {
|
|
|
|
assert(N == 1 && "Invalid number of operands!");
|
|
|
|
switch (Kind) {
|
|
|
|
case Immediate:
|
2015-05-14 02:37:00 +08:00
|
|
|
Inst.addOperand(MCOperand::createImm(getImm()));
|
2014-08-10 20:41:50 +08:00
|
|
|
break;
|
|
|
|
case ContextImmediate:
|
2015-05-14 02:37:00 +08:00
|
|
|
Inst.addOperand(MCOperand::createImm(getImmS16Context()));
|
2014-08-10 20:41:50 +08:00
|
|
|
break;
|
|
|
|
default:
|
2015-05-14 02:37:00 +08:00
|
|
|
Inst.addOperand(MCOperand::createExpr(getExpr()));
|
2014-08-10 20:41:50 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void addU16ImmOperands(MCInst &Inst, unsigned N) const {
|
|
|
|
assert(N == 1 && "Invalid number of operands!");
|
|
|
|
switch (Kind) {
|
|
|
|
case Immediate:
|
2015-05-14 02:37:00 +08:00
|
|
|
Inst.addOperand(MCOperand::createImm(getImm()));
|
2014-08-10 20:41:50 +08:00
|
|
|
break;
|
|
|
|
case ContextImmediate:
|
2015-05-14 02:37:00 +08:00
|
|
|
Inst.addOperand(MCOperand::createImm(getImmU16Context()));
|
2014-08-10 20:41:50 +08:00
|
|
|
break;
|
|
|
|
default:
|
2015-05-14 02:37:00 +08:00
|
|
|
Inst.addOperand(MCOperand::createExpr(getExpr()));
|
2014-08-10 20:41:50 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-24 19:03:33 +08:00
|
|
|
void addBranchTargetOperands(MCInst &Inst, unsigned N) const {
|
|
|
|
assert(N == 1 && "Invalid number of operands!");
|
|
|
|
if (Kind == Immediate)
|
2015-05-14 02:37:00 +08:00
|
|
|
Inst.addOperand(MCOperand::createImm(getImm() / 4));
|
2013-06-24 19:03:33 +08:00
|
|
|
else
|
2015-05-14 02:37:00 +08:00
|
|
|
Inst.addOperand(MCOperand::createExpr(getExpr()));
|
2013-06-24 19:03:33 +08:00
|
|
|
}
|
|
|
|
|
2013-07-05 20:22:36 +08:00
|
|
|
void addTLSRegOperands(MCInst &Inst, unsigned N) const {
|
|
|
|
assert(N == 1 && "Invalid number of operands!");
|
2015-05-14 02:37:00 +08:00
|
|
|
Inst.addOperand(MCOperand::createExpr(getTLSReg()));
|
2013-07-05 20:22:36 +08:00
|
|
|
}
|
|
|
|
|
2013-05-04 03:49:39 +08:00
|
|
|
StringRef getToken() const {
|
|
|
|
assert(Kind == Token && "Invalid access!");
|
|
|
|
return StringRef(Tok.Data, Tok.Length);
|
|
|
|
}
|
|
|
|
|
2014-04-29 15:57:37 +08:00
|
|
|
void print(raw_ostream &OS) const override;
|
2013-05-04 03:49:39 +08:00
|
|
|
|
2014-06-09 00:18:35 +08:00
|
|
|
static std::unique_ptr<PPCOperand> CreateToken(StringRef Str, SMLoc S,
|
|
|
|
bool IsPPC64) {
|
|
|
|
auto Op = make_unique<PPCOperand>(Token);
|
2013-05-04 03:49:39 +08:00
|
|
|
Op->Tok.Data = Str.data();
|
|
|
|
Op->Tok.Length = Str.size();
|
|
|
|
Op->StartLoc = S;
|
|
|
|
Op->EndLoc = S;
|
|
|
|
Op->IsPPC64 = IsPPC64;
|
|
|
|
return Op;
|
|
|
|
}
|
|
|
|
|
2014-06-09 00:18:35 +08:00
|
|
|
static std::unique_ptr<PPCOperand>
|
|
|
|
CreateTokenWithStringCopy(StringRef Str, SMLoc S, bool IsPPC64) {
|
2013-08-04 06:43:29 +08:00
|
|
|
// Allocate extra memory for the string and copy it.
|
2014-06-09 00:18:35 +08:00
|
|
|
// FIXME: This is incorrect, Operands are owned by unique_ptr with a default
|
|
|
|
// deleter which will destroy them by simply using "delete", not correctly
|
|
|
|
// calling operator delete on this extra memory after calling the dtor
|
|
|
|
// explicitly.
|
2013-08-04 06:43:29 +08:00
|
|
|
void *Mem = ::operator new(sizeof(PPCOperand) + Str.size());
|
2014-06-09 00:18:35 +08:00
|
|
|
std::unique_ptr<PPCOperand> Op(new (Mem) PPCOperand(Token));
|
2014-08-15 19:05:45 +08:00
|
|
|
Op->Tok.Data = reinterpret_cast<const char *>(Op.get() + 1);
|
2013-08-04 06:43:29 +08:00
|
|
|
Op->Tok.Length = Str.size();
|
2014-08-15 19:05:45 +08:00
|
|
|
std::memcpy(const_cast<char *>(Op->Tok.Data), Str.data(), Str.size());
|
2013-08-04 06:43:29 +08:00
|
|
|
Op->StartLoc = S;
|
|
|
|
Op->EndLoc = S;
|
|
|
|
Op->IsPPC64 = IsPPC64;
|
|
|
|
return Op;
|
|
|
|
}
|
|
|
|
|
2014-06-09 00:18:35 +08:00
|
|
|
static std::unique_ptr<PPCOperand> CreateImm(int64_t Val, SMLoc S, SMLoc E,
|
|
|
|
bool IsPPC64) {
|
|
|
|
auto Op = make_unique<PPCOperand>(Immediate);
|
2013-05-04 03:49:39 +08:00
|
|
|
Op->Imm.Val = Val;
|
|
|
|
Op->StartLoc = S;
|
|
|
|
Op->EndLoc = E;
|
|
|
|
Op->IsPPC64 = IsPPC64;
|
|
|
|
return Op;
|
|
|
|
}
|
|
|
|
|
2014-06-09 00:18:35 +08:00
|
|
|
static std::unique_ptr<PPCOperand> CreateExpr(const MCExpr *Val, SMLoc S,
|
|
|
|
SMLoc E, bool IsPPC64) {
|
|
|
|
auto Op = make_unique<PPCOperand>(Expression);
|
2013-05-04 03:49:39 +08:00
|
|
|
Op->Expr.Val = Val;
|
2013-07-04 22:24:00 +08:00
|
|
|
Op->Expr.CRVal = EvaluateCRExpr(Val);
|
2013-05-04 03:49:39 +08:00
|
|
|
Op->StartLoc = S;
|
|
|
|
Op->EndLoc = E;
|
|
|
|
Op->IsPPC64 = IsPPC64;
|
|
|
|
return Op;
|
|
|
|
}
|
2013-07-05 20:22:36 +08:00
|
|
|
|
2014-06-09 00:18:35 +08:00
|
|
|
static std::unique_ptr<PPCOperand>
|
|
|
|
CreateTLSReg(const MCSymbolRefExpr *Sym, SMLoc S, SMLoc E, bool IsPPC64) {
|
|
|
|
auto Op = make_unique<PPCOperand>(TLSRegister);
|
2013-07-05 20:22:36 +08:00
|
|
|
Op->TLSReg.Sym = Sym;
|
|
|
|
Op->StartLoc = S;
|
|
|
|
Op->EndLoc = E;
|
|
|
|
Op->IsPPC64 = IsPPC64;
|
|
|
|
return Op;
|
|
|
|
}
|
|
|
|
|
2014-08-10 20:41:50 +08:00
|
|
|
static std::unique_ptr<PPCOperand>
|
|
|
|
CreateContextImm(int64_t Val, SMLoc S, SMLoc E, bool IsPPC64) {
|
|
|
|
auto Op = make_unique<PPCOperand>(ContextImmediate);
|
|
|
|
Op->Imm.Val = Val;
|
|
|
|
Op->StartLoc = S;
|
|
|
|
Op->EndLoc = E;
|
|
|
|
Op->IsPPC64 = IsPPC64;
|
|
|
|
return Op;
|
|
|
|
}
|
|
|
|
|
2014-06-09 00:18:35 +08:00
|
|
|
static std::unique_ptr<PPCOperand>
|
|
|
|
CreateFromMCExpr(const MCExpr *Val, SMLoc S, SMLoc E, bool IsPPC64) {
|
2013-07-05 20:22:36 +08:00
|
|
|
if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val))
|
|
|
|
return CreateImm(CE->getValue(), S, E, IsPPC64);
|
|
|
|
|
|
|
|
if (const MCSymbolRefExpr *SRE = dyn_cast<MCSymbolRefExpr>(Val))
|
|
|
|
if (SRE->getKind() == MCSymbolRefExpr::VK_PPC_TLS)
|
|
|
|
return CreateTLSReg(SRE, S, E, IsPPC64);
|
|
|
|
|
2014-08-10 20:41:50 +08:00
|
|
|
if (const PPCMCExpr *TE = dyn_cast<PPCMCExpr>(Val)) {
|
|
|
|
int64_t Res;
|
2015-05-30 09:25:56 +08:00
|
|
|
if (TE->evaluateAsConstant(Res))
|
2014-08-10 20:41:50 +08:00
|
|
|
return CreateContextImm(Res, S, E, IsPPC64);
|
|
|
|
}
|
|
|
|
|
2013-07-05 20:22:36 +08:00
|
|
|
return CreateExpr(Val, S, E, IsPPC64);
|
|
|
|
}
|
2013-05-04 03:49:39 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
} // end anonymous namespace.
|
|
|
|
|
|
|
|
void PPCOperand::print(raw_ostream &OS) const {
|
|
|
|
switch (Kind) {
|
|
|
|
case Token:
|
|
|
|
OS << "'" << getToken() << "'";
|
|
|
|
break;
|
|
|
|
case Immediate:
|
2014-08-10 20:41:50 +08:00
|
|
|
case ContextImmediate:
|
2013-05-04 03:49:39 +08:00
|
|
|
OS << getImm();
|
|
|
|
break;
|
|
|
|
case Expression:
|
2015-05-27 21:05:42 +08:00
|
|
|
OS << *getExpr();
|
2013-05-04 03:49:39 +08:00
|
|
|
break;
|
2013-07-05 20:22:36 +08:00
|
|
|
case TLSRegister:
|
2015-05-27 21:05:42 +08:00
|
|
|
OS << *getTLSReg();
|
2013-07-05 20:22:36 +08:00
|
|
|
break;
|
2013-05-04 03:49:39 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-10 01:10:26 +08:00
|
|
|
static void
|
|
|
|
addNegOperand(MCInst &Inst, MCOperand &Op, MCContext &Ctx) {
|
|
|
|
if (Op.isImm()) {
|
2015-05-14 02:37:00 +08:00
|
|
|
Inst.addOperand(MCOperand::createImm(-Op.getImm()));
|
2014-08-10 01:10:26 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
const MCExpr *Expr = Op.getExpr();
|
|
|
|
if (const MCUnaryExpr *UnExpr = dyn_cast<MCUnaryExpr>(Expr)) {
|
|
|
|
if (UnExpr->getOpcode() == MCUnaryExpr::Minus) {
|
2015-05-14 02:37:00 +08:00
|
|
|
Inst.addOperand(MCOperand::createExpr(UnExpr->getSubExpr()));
|
2014-08-10 01:10:26 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else if (const MCBinaryExpr *BinExpr = dyn_cast<MCBinaryExpr>(Expr)) {
|
|
|
|
if (BinExpr->getOpcode() == MCBinaryExpr::Sub) {
|
2015-05-30 09:25:56 +08:00
|
|
|
const MCExpr *NE = MCBinaryExpr::createSub(BinExpr->getRHS(),
|
2014-08-10 01:10:26 +08:00
|
|
|
BinExpr->getLHS(), Ctx);
|
2015-05-14 02:37:00 +08:00
|
|
|
Inst.addOperand(MCOperand::createExpr(NE));
|
2014-08-10 01:10:26 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2015-05-30 09:25:56 +08:00
|
|
|
Inst.addOperand(MCOperand::createExpr(MCUnaryExpr::createMinus(Expr, Ctx)));
|
2014-08-10 01:10:26 +08:00
|
|
|
}
|
|
|
|
|
2014-06-09 00:18:35 +08:00
|
|
|
void PPCAsmParser::ProcessInstruction(MCInst &Inst,
|
|
|
|
const OperandVector &Operands) {
|
2013-06-25 21:17:41 +08:00
|
|
|
int Opcode = Inst.getOpcode();
|
|
|
|
switch (Opcode) {
|
2015-04-24 06:47:57 +08:00
|
|
|
case PPC::DCBTx:
|
|
|
|
case PPC::DCBTT:
|
|
|
|
case PPC::DCBTSTx:
|
|
|
|
case PPC::DCBTSTT: {
|
|
|
|
MCInst TmpInst;
|
|
|
|
TmpInst.setOpcode((Opcode == PPC::DCBTx || Opcode == PPC::DCBTT) ?
|
|
|
|
PPC::DCBT : PPC::DCBTST);
|
2015-05-14 02:37:00 +08:00
|
|
|
TmpInst.addOperand(MCOperand::createImm(
|
2015-04-24 06:47:57 +08:00
|
|
|
(Opcode == PPC::DCBTx || Opcode == PPC::DCBTSTx) ? 0 : 16));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case PPC::DCBTCT:
|
|
|
|
case PPC::DCBTDS: {
|
|
|
|
MCInst TmpInst;
|
|
|
|
TmpInst.setOpcode(PPC::DCBT);
|
|
|
|
TmpInst.addOperand(Inst.getOperand(2));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case PPC::DCBTSTCT:
|
|
|
|
case PPC::DCBTSTDS: {
|
|
|
|
MCInst TmpInst;
|
|
|
|
TmpInst.setOpcode(PPC::DCBTST);
|
|
|
|
TmpInst.addOperand(Inst.getOperand(2));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
2016-09-03 07:41:54 +08:00
|
|
|
case PPC::DCBFx:
|
|
|
|
case PPC::DCBFL:
|
|
|
|
case PPC::DCBFLP: {
|
|
|
|
int L = 0;
|
|
|
|
if (Opcode == PPC::DCBFL)
|
|
|
|
L = 1;
|
|
|
|
else if (Opcode == PPC::DCBFLP)
|
|
|
|
L = 3;
|
|
|
|
|
|
|
|
MCInst TmpInst;
|
|
|
|
TmpInst.setOpcode(PPC::DCBF);
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(L));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
2013-06-25 02:08:03 +08:00
|
|
|
case PPC::LAx: {
|
|
|
|
MCInst TmpInst;
|
|
|
|
TmpInst.setOpcode(PPC::LA);
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(2));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
2013-06-25 21:16:48 +08:00
|
|
|
case PPC::SUBI: {
|
|
|
|
MCInst TmpInst;
|
|
|
|
TmpInst.setOpcode(PPC::ADDI);
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
2014-08-10 01:10:26 +08:00
|
|
|
addNegOperand(TmpInst, Inst.getOperand(2), getContext());
|
2013-06-25 21:16:48 +08:00
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case PPC::SUBIS: {
|
|
|
|
MCInst TmpInst;
|
|
|
|
TmpInst.setOpcode(PPC::ADDIS);
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
2014-08-10 01:10:26 +08:00
|
|
|
addNegOperand(TmpInst, Inst.getOperand(2), getContext());
|
2013-06-25 21:16:48 +08:00
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case PPC::SUBIC: {
|
|
|
|
MCInst TmpInst;
|
|
|
|
TmpInst.setOpcode(PPC::ADDIC);
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
2014-08-10 01:10:26 +08:00
|
|
|
addNegOperand(TmpInst, Inst.getOperand(2), getContext());
|
2013-06-25 21:16:48 +08:00
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case PPC::SUBICo: {
|
|
|
|
MCInst TmpInst;
|
|
|
|
TmpInst.setOpcode(PPC::ADDICo);
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
2014-08-10 01:10:26 +08:00
|
|
|
addNegOperand(TmpInst, Inst.getOperand(2), getContext());
|
2013-06-25 21:16:48 +08:00
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
2013-06-25 21:17:41 +08:00
|
|
|
case PPC::EXTLWI:
|
|
|
|
case PPC::EXTLWIo: {
|
2013-05-04 03:50:27 +08:00
|
|
|
MCInst TmpInst;
|
|
|
|
int64_t N = Inst.getOperand(2).getImm();
|
2013-06-25 21:17:41 +08:00
|
|
|
int64_t B = Inst.getOperand(3).getImm();
|
|
|
|
TmpInst.setOpcode(Opcode == PPC::EXTLWI? PPC::RLWINM : PPC::RLWINMo);
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
2015-05-14 02:37:00 +08:00
|
|
|
TmpInst.addOperand(MCOperand::createImm(B));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(0));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(N - 1));
|
2013-06-25 21:17:41 +08:00
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case PPC::EXTRWI:
|
|
|
|
case PPC::EXTRWIo: {
|
|
|
|
MCInst TmpInst;
|
|
|
|
int64_t N = Inst.getOperand(2).getImm();
|
|
|
|
int64_t B = Inst.getOperand(3).getImm();
|
|
|
|
TmpInst.setOpcode(Opcode == PPC::EXTRWI? PPC::RLWINM : PPC::RLWINMo);
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
2015-05-14 02:37:00 +08:00
|
|
|
TmpInst.addOperand(MCOperand::createImm(B + N));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(32 - N));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(31));
|
2013-06-25 21:17:41 +08:00
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case PPC::INSLWI:
|
|
|
|
case PPC::INSLWIo: {
|
|
|
|
MCInst TmpInst;
|
|
|
|
int64_t N = Inst.getOperand(2).getImm();
|
|
|
|
int64_t B = Inst.getOperand(3).getImm();
|
|
|
|
TmpInst.setOpcode(Opcode == PPC::INSLWI? PPC::RLWIMI : PPC::RLWIMIo);
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
2015-05-14 02:37:00 +08:00
|
|
|
TmpInst.addOperand(MCOperand::createImm(32 - B));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(B));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm((B + N) - 1));
|
2013-06-25 21:17:41 +08:00
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case PPC::INSRWI:
|
|
|
|
case PPC::INSRWIo: {
|
|
|
|
MCInst TmpInst;
|
|
|
|
int64_t N = Inst.getOperand(2).getImm();
|
|
|
|
int64_t B = Inst.getOperand(3).getImm();
|
|
|
|
TmpInst.setOpcode(Opcode == PPC::INSRWI? PPC::RLWIMI : PPC::RLWIMIo);
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
2015-05-14 02:37:00 +08:00
|
|
|
TmpInst.addOperand(MCOperand::createImm(32 - (B + N)));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(B));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm((B + N) - 1));
|
2013-06-25 21:17:41 +08:00
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case PPC::ROTRWI:
|
|
|
|
case PPC::ROTRWIo: {
|
|
|
|
MCInst TmpInst;
|
|
|
|
int64_t N = Inst.getOperand(2).getImm();
|
|
|
|
TmpInst.setOpcode(Opcode == PPC::ROTRWI? PPC::RLWINM : PPC::RLWINMo);
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
2015-05-14 02:37:00 +08:00
|
|
|
TmpInst.addOperand(MCOperand::createImm(32 - N));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(0));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(31));
|
2013-06-25 21:17:41 +08:00
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case PPC::SLWI:
|
|
|
|
case PPC::SLWIo: {
|
|
|
|
MCInst TmpInst;
|
|
|
|
int64_t N = Inst.getOperand(2).getImm();
|
|
|
|
TmpInst.setOpcode(Opcode == PPC::SLWI? PPC::RLWINM : PPC::RLWINMo);
|
2013-05-04 03:50:27 +08:00
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
2015-05-14 02:37:00 +08:00
|
|
|
TmpInst.addOperand(MCOperand::createImm(N));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(0));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(31 - N));
|
2013-05-04 03:50:27 +08:00
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
2013-06-25 21:17:41 +08:00
|
|
|
case PPC::SRWI:
|
|
|
|
case PPC::SRWIo: {
|
2013-05-04 03:50:27 +08:00
|
|
|
MCInst TmpInst;
|
|
|
|
int64_t N = Inst.getOperand(2).getImm();
|
2013-06-25 21:17:41 +08:00
|
|
|
TmpInst.setOpcode(Opcode == PPC::SRWI? PPC::RLWINM : PPC::RLWINMo);
|
2013-05-04 03:50:27 +08:00
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
2015-05-14 02:37:00 +08:00
|
|
|
TmpInst.addOperand(MCOperand::createImm(32 - N));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(N));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(31));
|
2013-05-04 03:50:27 +08:00
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
2013-06-25 21:17:41 +08:00
|
|
|
case PPC::CLRRWI:
|
|
|
|
case PPC::CLRRWIo: {
|
2013-05-04 03:50:27 +08:00
|
|
|
MCInst TmpInst;
|
|
|
|
int64_t N = Inst.getOperand(2).getImm();
|
2013-06-25 21:17:41 +08:00
|
|
|
TmpInst.setOpcode(Opcode == PPC::CLRRWI? PPC::RLWINM : PPC::RLWINMo);
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
2015-05-14 02:37:00 +08:00
|
|
|
TmpInst.addOperand(MCOperand::createImm(0));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(0));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(31 - N));
|
2013-06-25 21:17:41 +08:00
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case PPC::CLRLSLWI:
|
|
|
|
case PPC::CLRLSLWIo: {
|
|
|
|
MCInst TmpInst;
|
|
|
|
int64_t B = Inst.getOperand(2).getImm();
|
|
|
|
int64_t N = Inst.getOperand(3).getImm();
|
|
|
|
TmpInst.setOpcode(Opcode == PPC::CLRLSLWI? PPC::RLWINM : PPC::RLWINMo);
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
2015-05-14 02:37:00 +08:00
|
|
|
TmpInst.addOperand(MCOperand::createImm(N));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(B - N));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(31 - N));
|
2013-06-25 21:17:41 +08:00
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case PPC::EXTLDI:
|
|
|
|
case PPC::EXTLDIo: {
|
|
|
|
MCInst TmpInst;
|
|
|
|
int64_t N = Inst.getOperand(2).getImm();
|
|
|
|
int64_t B = Inst.getOperand(3).getImm();
|
|
|
|
TmpInst.setOpcode(Opcode == PPC::EXTLDI? PPC::RLDICR : PPC::RLDICRo);
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
2015-05-14 02:37:00 +08:00
|
|
|
TmpInst.addOperand(MCOperand::createImm(B));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(N - 1));
|
2013-06-25 21:17:41 +08:00
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case PPC::EXTRDI:
|
|
|
|
case PPC::EXTRDIo: {
|
|
|
|
MCInst TmpInst;
|
|
|
|
int64_t N = Inst.getOperand(2).getImm();
|
|
|
|
int64_t B = Inst.getOperand(3).getImm();
|
|
|
|
TmpInst.setOpcode(Opcode == PPC::EXTRDI? PPC::RLDICL : PPC::RLDICLo);
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
2015-05-14 02:37:00 +08:00
|
|
|
TmpInst.addOperand(MCOperand::createImm(B + N));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(64 - N));
|
2013-06-25 21:17:41 +08:00
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case PPC::INSRDI:
|
|
|
|
case PPC::INSRDIo: {
|
|
|
|
MCInst TmpInst;
|
|
|
|
int64_t N = Inst.getOperand(2).getImm();
|
|
|
|
int64_t B = Inst.getOperand(3).getImm();
|
|
|
|
TmpInst.setOpcode(Opcode == PPC::INSRDI? PPC::RLDIMI : PPC::RLDIMIo);
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
2015-05-14 02:37:00 +08:00
|
|
|
TmpInst.addOperand(MCOperand::createImm(64 - (B + N)));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(B));
|
2013-06-25 21:17:41 +08:00
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case PPC::ROTRDI:
|
|
|
|
case PPC::ROTRDIo: {
|
|
|
|
MCInst TmpInst;
|
|
|
|
int64_t N = Inst.getOperand(2).getImm();
|
|
|
|
TmpInst.setOpcode(Opcode == PPC::ROTRDI? PPC::RLDICL : PPC::RLDICLo);
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
2015-05-14 02:37:00 +08:00
|
|
|
TmpInst.addOperand(MCOperand::createImm(64 - N));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(0));
|
2013-06-25 21:17:41 +08:00
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case PPC::SLDI:
|
|
|
|
case PPC::SLDIo: {
|
|
|
|
MCInst TmpInst;
|
|
|
|
int64_t N = Inst.getOperand(2).getImm();
|
|
|
|
TmpInst.setOpcode(Opcode == PPC::SLDI? PPC::RLDICR : PPC::RLDICRo);
|
2013-05-04 03:50:27 +08:00
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
2015-05-14 02:37:00 +08:00
|
|
|
TmpInst.addOperand(MCOperand::createImm(N));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(63 - N));
|
2013-05-04 03:50:27 +08:00
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
2017-09-19 23:22:36 +08:00
|
|
|
case PPC::SUBPCIS: {
|
|
|
|
MCInst TmpInst;
|
|
|
|
int64_t N = Inst.getOperand(1).getImm();
|
|
|
|
TmpInst.setOpcode(PPC::ADDPCIS);
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(-N));
|
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
2013-06-25 21:17:41 +08:00
|
|
|
case PPC::SRDI:
|
|
|
|
case PPC::SRDIo: {
|
2013-05-04 03:50:27 +08:00
|
|
|
MCInst TmpInst;
|
|
|
|
int64_t N = Inst.getOperand(2).getImm();
|
2013-06-25 21:17:41 +08:00
|
|
|
TmpInst.setOpcode(Opcode == PPC::SRDI? PPC::RLDICL : PPC::RLDICLo);
|
2013-05-04 03:50:27 +08:00
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
2015-05-14 02:37:00 +08:00
|
|
|
TmpInst.addOperand(MCOperand::createImm(64 - N));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(N));
|
2013-05-04 03:50:27 +08:00
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
2013-06-25 21:17:41 +08:00
|
|
|
case PPC::CLRRDI:
|
|
|
|
case PPC::CLRRDIo: {
|
|
|
|
MCInst TmpInst;
|
|
|
|
int64_t N = Inst.getOperand(2).getImm();
|
|
|
|
TmpInst.setOpcode(Opcode == PPC::CLRRDI? PPC::RLDICR : PPC::RLDICRo);
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
2015-05-14 02:37:00 +08:00
|
|
|
TmpInst.addOperand(MCOperand::createImm(0));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(63 - N));
|
2013-06-25 21:17:41 +08:00
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case PPC::CLRLSLDI:
|
|
|
|
case PPC::CLRLSLDIo: {
|
|
|
|
MCInst TmpInst;
|
|
|
|
int64_t B = Inst.getOperand(2).getImm();
|
|
|
|
int64_t N = Inst.getOperand(3).getImm();
|
|
|
|
TmpInst.setOpcode(Opcode == PPC::CLRLSLDI? PPC::RLDIC : PPC::RLDICo);
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
2015-05-14 02:37:00 +08:00
|
|
|
TmpInst.addOperand(MCOperand::createImm(N));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(B - N));
|
2013-06-25 21:17:41 +08:00
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
2015-03-29 03:42:41 +08:00
|
|
|
case PPC::RLWINMbm:
|
|
|
|
case PPC::RLWINMobm: {
|
|
|
|
unsigned MB, ME;
|
|
|
|
int64_t BM = Inst.getOperand(3).getImm();
|
|
|
|
if (!isRunOfOnes(BM, MB, ME))
|
|
|
|
break;
|
|
|
|
|
|
|
|
MCInst TmpInst;
|
|
|
|
TmpInst.setOpcode(Opcode == PPC::RLWINMbm ? PPC::RLWINM : PPC::RLWINMo);
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(2));
|
2015-05-14 02:37:00 +08:00
|
|
|
TmpInst.addOperand(MCOperand::createImm(MB));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(ME));
|
2015-03-29 03:42:41 +08:00
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case PPC::RLWIMIbm:
|
|
|
|
case PPC::RLWIMIobm: {
|
|
|
|
unsigned MB, ME;
|
|
|
|
int64_t BM = Inst.getOperand(3).getImm();
|
|
|
|
if (!isRunOfOnes(BM, MB, ME))
|
|
|
|
break;
|
|
|
|
|
|
|
|
MCInst TmpInst;
|
|
|
|
TmpInst.setOpcode(Opcode == PPC::RLWIMIbm ? PPC::RLWIMI : PPC::RLWIMIo);
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0)); // The tied operand.
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(2));
|
2015-05-14 02:37:00 +08:00
|
|
|
TmpInst.addOperand(MCOperand::createImm(MB));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(ME));
|
2015-03-29 03:42:41 +08:00
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case PPC::RLWNMbm:
|
|
|
|
case PPC::RLWNMobm: {
|
|
|
|
unsigned MB, ME;
|
|
|
|
int64_t BM = Inst.getOperand(3).getImm();
|
|
|
|
if (!isRunOfOnes(BM, MB, ME))
|
|
|
|
break;
|
|
|
|
|
|
|
|
MCInst TmpInst;
|
|
|
|
TmpInst.setOpcode(Opcode == PPC::RLWNMbm ? PPC::RLWNM : PPC::RLWNMo);
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(2));
|
2015-05-14 02:37:00 +08:00
|
|
|
TmpInst.addOperand(MCOperand::createImm(MB));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(ME));
|
2015-03-29 03:42:41 +08:00
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
2015-06-17 00:01:15 +08:00
|
|
|
case PPC::MFTB: {
|
2015-11-14 13:20:05 +08:00
|
|
|
if (getSTI().getFeatureBits()[PPC::FeatureMFTB]) {
|
2015-06-17 00:01:15 +08:00
|
|
|
assert(Inst.getNumOperands() == 2 && "Expecting two operands");
|
|
|
|
Inst.setOpcode(PPC::MFSPR);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2016-04-06 09:46:45 +08:00
|
|
|
case PPC::CP_COPYx:
|
|
|
|
case PPC::CP_COPY_FIRST: {
|
|
|
|
MCInst TmpInst;
|
|
|
|
TmpInst.setOpcode(PPC::CP_COPY);
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(Opcode == PPC::CP_COPYx ? 0 : 1));
|
|
|
|
|
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case PPC::CP_PASTEx :
|
|
|
|
case PPC::CP_PASTE_LAST: {
|
|
|
|
MCInst TmpInst;
|
|
|
|
TmpInst.setOpcode(Opcode == PPC::CP_PASTEx ?
|
|
|
|
PPC::CP_PASTE : PPC::CP_PASTEo);
|
|
|
|
TmpInst.addOperand(Inst.getOperand(0));
|
|
|
|
TmpInst.addOperand(Inst.getOperand(1));
|
|
|
|
TmpInst.addOperand(MCOperand::createImm(Opcode == PPC::CP_PASTEx ? 0 : 1));
|
|
|
|
|
|
|
|
Inst = TmpInst;
|
|
|
|
break;
|
|
|
|
}
|
2013-05-04 03:50:27 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-09 00:18:35 +08:00
|
|
|
bool PPCAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
|
|
|
|
OperandVector &Operands,
|
2014-08-18 19:49:42 +08:00
|
|
|
MCStreamer &Out, uint64_t &ErrorInfo,
|
2014-06-09 00:18:35 +08:00
|
|
|
bool MatchingInlineAsm) {
|
2013-05-04 03:49:39 +08:00
|
|
|
MCInst Inst;
|
|
|
|
|
2015-06-30 20:32:53 +08:00
|
|
|
switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
|
2013-05-04 03:49:39 +08:00
|
|
|
case Match_Success:
|
2013-05-04 03:50:27 +08:00
|
|
|
// Post-process instructions (typically extended mnemonics)
|
|
|
|
ProcessInstruction(Inst, Operands);
|
2013-05-04 03:49:39 +08:00
|
|
|
Inst.setLoc(IDLoc);
|
2015-11-14 13:20:05 +08:00
|
|
|
Out.EmitInstruction(Inst, getSTI());
|
2013-05-04 03:49:39 +08:00
|
|
|
return false;
|
|
|
|
case Match_MissingFeature:
|
|
|
|
return Error(IDLoc, "instruction use requires an option to be enabled");
|
|
|
|
case Match_MnemonicFail:
|
2015-01-03 16:16:34 +08:00
|
|
|
return Error(IDLoc, "unrecognized instruction mnemonic");
|
2013-05-04 03:49:39 +08:00
|
|
|
case Match_InvalidOperand: {
|
|
|
|
SMLoc ErrorLoc = IDLoc;
|
2014-08-18 19:49:42 +08:00
|
|
|
if (ErrorInfo != ~0ULL) {
|
2013-05-04 03:49:39 +08:00
|
|
|
if (ErrorInfo >= Operands.size())
|
|
|
|
return Error(IDLoc, "too few operands for instruction");
|
|
|
|
|
2014-06-09 00:18:35 +08:00
|
|
|
ErrorLoc = ((PPCOperand &)*Operands[ErrorInfo]).getStartLoc();
|
2013-05-04 03:49:39 +08:00
|
|
|
if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Error(ErrorLoc, "invalid operand for instruction");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm_unreachable("Implement any new match types added!");
|
|
|
|
}
|
|
|
|
|
2016-12-05 22:11:03 +08:00
|
|
|
bool PPCAsmParser::MatchRegisterName(unsigned &RegNo, int64_t &IntVal) {
|
|
|
|
if (getParser().getTok().is(AsmToken::Identifier)) {
|
|
|
|
StringRef Name = getParser().getTok().getString();
|
2013-05-06 19:16:57 +08:00
|
|
|
if (Name.equals_lower("lr")) {
|
2013-05-04 03:49:39 +08:00
|
|
|
RegNo = isPPC64()? PPC::LR8 : PPC::LR;
|
|
|
|
IntVal = 8;
|
2013-05-06 19:16:57 +08:00
|
|
|
} else if (Name.equals_lower("ctr")) {
|
2013-05-04 03:49:39 +08:00
|
|
|
RegNo = isPPC64()? PPC::CTR8 : PPC::CTR;
|
|
|
|
IntVal = 9;
|
Cleanup PPC Altivec registers in CSR lists and improve VRSAVE handling
There are a couple of (small) related changes here:
1. The printed name of the VRSAVE register has been changed from VRsave to
vrsave in order to match the name accepted by GNU binutils.
2. Support for parsing vrsave has been added to the asm parser (it seems that
there was no test case specifically covering this code, so I've added one).
3. The list of Altivec registers, which was common to all calling conventions,
has been separated out. This allows us to define the base CSR lists, and then
lists for each ABI with Altivec included. This allows SjLj, for example, to
work correctly on non-Altivec targets without using unnatural definitions of
the NoRegs CSR list.
4. VRSAVE is now always reserved on non-Darwin targets and all Altivec
registers are reserved when Altivec is disabled.
With these changes, it is now possible to compile a function containing
__builtin_unwind_init() on Linux/PPC64 with debugging information. This did not
work previously because GNU binutils assumes that all .cfi_offset offsets will
be 8-byte aligned on PPC64 (and errors out if you provide a non-8-byte-aligned
offset). This is not true for the vrsave register, however, because this
register is used only on Darwin, GCC does not bother printing a .cfi_offset
entry for it (even though there is a slot in the stack frame for it as
specified by the ABI). This change allows us to do the same: we will also not
print .cfi_offset directives for vrsave.
llvm-svn: 185409
2013-07-02 11:39:34 +08:00
|
|
|
} else if (Name.equals_lower("vrsave")) {
|
|
|
|
RegNo = PPC::VRSAVE;
|
|
|
|
IntVal = 256;
|
2013-11-01 03:59:55 +08:00
|
|
|
} else if (Name.startswith_lower("r") &&
|
2013-05-04 03:49:39 +08:00
|
|
|
!Name.substr(1).getAsInteger(10, IntVal) && IntVal < 32) {
|
|
|
|
RegNo = isPPC64()? XRegs[IntVal] : RRegs[IntVal];
|
2013-11-01 03:59:55 +08:00
|
|
|
} else if (Name.startswith_lower("f") &&
|
2013-05-04 03:49:39 +08:00
|
|
|
!Name.substr(1).getAsInteger(10, IntVal) && IntVal < 32) {
|
|
|
|
RegNo = FRegs[IntVal];
|
2015-04-24 07:16:22 +08:00
|
|
|
} else if (Name.startswith_lower("vs") &&
|
|
|
|
!Name.substr(2).getAsInteger(10, IntVal) && IntVal < 64) {
|
|
|
|
RegNo = VSRegs[IntVal];
|
2013-11-01 03:59:55 +08:00
|
|
|
} else if (Name.startswith_lower("v") &&
|
2013-05-04 03:49:39 +08:00
|
|
|
!Name.substr(1).getAsInteger(10, IntVal) && IntVal < 32) {
|
|
|
|
RegNo = VRegs[IntVal];
|
2015-04-24 07:16:22 +08:00
|
|
|
} else if (Name.startswith_lower("q") &&
|
|
|
|
!Name.substr(1).getAsInteger(10, IntVal) && IntVal < 32) {
|
|
|
|
RegNo = QFRegs[IntVal];
|
2013-11-01 03:59:55 +08:00
|
|
|
} else if (Name.startswith_lower("cr") &&
|
2013-05-04 03:49:39 +08:00
|
|
|
!Name.substr(2).getAsInteger(10, IntVal) && IntVal < 8) {
|
|
|
|
RegNo = CRRegs[IntVal];
|
2016-12-05 22:11:03 +08:00
|
|
|
} else
|
|
|
|
return true;
|
|
|
|
getParser().Lex();
|
|
|
|
return false;
|
2013-05-04 03:49:39 +08:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PPCAsmParser::
|
|
|
|
ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) {
|
2016-12-05 22:11:03 +08:00
|
|
|
const AsmToken &Tok = getParser().getTok();
|
2013-05-04 03:49:39 +08:00
|
|
|
StartLoc = Tok.getLoc();
|
|
|
|
EndLoc = Tok.getEndLoc();
|
|
|
|
RegNo = 0;
|
|
|
|
int64_t IntVal;
|
2016-12-05 22:11:03 +08:00
|
|
|
if (MatchRegisterName(RegNo, IntVal))
|
|
|
|
return TokError("invalid register name");
|
|
|
|
return false;
|
2013-05-04 03:49:39 +08:00
|
|
|
}
|
|
|
|
|
2013-06-25 09:14:20 +08:00
|
|
|
/// Extract \code @l/@ha \endcode modifier from expression. Recursively scan
|
2013-06-21 22:42:49 +08:00
|
|
|
/// the expression and check for VK_PPC_LO/HI/HA
|
2013-06-21 00:23:52 +08:00
|
|
|
/// symbol variants. If all symbols with modifier use the same
|
|
|
|
/// variant, return the corresponding PPCMCExpr::VariantKind,
|
|
|
|
/// and a modified expression using the default symbol variant.
|
|
|
|
/// Otherwise, return NULL.
|
|
|
|
const MCExpr *PPCAsmParser::
|
|
|
|
ExtractModifierFromExpr(const MCExpr *E,
|
|
|
|
PPCMCExpr::VariantKind &Variant) {
|
|
|
|
MCContext &Context = getParser().getContext();
|
|
|
|
Variant = PPCMCExpr::VK_PPC_None;
|
|
|
|
|
|
|
|
switch (E->getKind()) {
|
|
|
|
case MCExpr::Target:
|
|
|
|
case MCExpr::Constant:
|
2014-04-25 13:30:21 +08:00
|
|
|
return nullptr;
|
2013-06-21 00:23:52 +08:00
|
|
|
|
|
|
|
case MCExpr::SymbolRef: {
|
|
|
|
const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E);
|
|
|
|
|
|
|
|
switch (SRE->getKind()) {
|
2013-06-21 22:42:20 +08:00
|
|
|
case MCSymbolRefExpr::VK_PPC_LO:
|
|
|
|
Variant = PPCMCExpr::VK_PPC_LO;
|
2013-06-21 00:23:52 +08:00
|
|
|
break;
|
2013-06-21 22:42:49 +08:00
|
|
|
case MCSymbolRefExpr::VK_PPC_HI:
|
|
|
|
Variant = PPCMCExpr::VK_PPC_HI;
|
|
|
|
break;
|
2013-06-21 22:42:20 +08:00
|
|
|
case MCSymbolRefExpr::VK_PPC_HA:
|
|
|
|
Variant = PPCMCExpr::VK_PPC_HA;
|
2013-06-21 00:23:52 +08:00
|
|
|
break;
|
2013-06-21 22:43:42 +08:00
|
|
|
case MCSymbolRefExpr::VK_PPC_HIGHER:
|
|
|
|
Variant = PPCMCExpr::VK_PPC_HIGHER;
|
|
|
|
break;
|
|
|
|
case MCSymbolRefExpr::VK_PPC_HIGHERA:
|
|
|
|
Variant = PPCMCExpr::VK_PPC_HIGHERA;
|
|
|
|
break;
|
|
|
|
case MCSymbolRefExpr::VK_PPC_HIGHEST:
|
|
|
|
Variant = PPCMCExpr::VK_PPC_HIGHEST;
|
|
|
|
break;
|
|
|
|
case MCSymbolRefExpr::VK_PPC_HIGHESTA:
|
|
|
|
Variant = PPCMCExpr::VK_PPC_HIGHESTA;
|
|
|
|
break;
|
2013-06-21 00:23:52 +08:00
|
|
|
default:
|
2014-04-25 13:30:21 +08:00
|
|
|
return nullptr;
|
2013-06-21 00:23:52 +08:00
|
|
|
}
|
|
|
|
|
2015-05-30 09:25:56 +08:00
|
|
|
return MCSymbolRefExpr::create(&SRE->getSymbol(), Context);
|
2013-06-21 00:23:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
case MCExpr::Unary: {
|
|
|
|
const MCUnaryExpr *UE = cast<MCUnaryExpr>(E);
|
|
|
|
const MCExpr *Sub = ExtractModifierFromExpr(UE->getSubExpr(), Variant);
|
|
|
|
if (!Sub)
|
2014-04-25 13:30:21 +08:00
|
|
|
return nullptr;
|
2015-05-30 09:25:56 +08:00
|
|
|
return MCUnaryExpr::create(UE->getOpcode(), Sub, Context);
|
2013-06-21 00:23:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
case MCExpr::Binary: {
|
|
|
|
const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);
|
|
|
|
PPCMCExpr::VariantKind LHSVariant, RHSVariant;
|
|
|
|
const MCExpr *LHS = ExtractModifierFromExpr(BE->getLHS(), LHSVariant);
|
|
|
|
const MCExpr *RHS = ExtractModifierFromExpr(BE->getRHS(), RHSVariant);
|
|
|
|
|
|
|
|
if (!LHS && !RHS)
|
2014-04-25 13:30:21 +08:00
|
|
|
return nullptr;
|
2013-06-21 00:23:52 +08:00
|
|
|
|
|
|
|
if (!LHS) LHS = BE->getLHS();
|
|
|
|
if (!RHS) RHS = BE->getRHS();
|
|
|
|
|
|
|
|
if (LHSVariant == PPCMCExpr::VK_PPC_None)
|
|
|
|
Variant = RHSVariant;
|
|
|
|
else if (RHSVariant == PPCMCExpr::VK_PPC_None)
|
|
|
|
Variant = LHSVariant;
|
|
|
|
else if (LHSVariant == RHSVariant)
|
|
|
|
Variant = LHSVariant;
|
|
|
|
else
|
2014-04-25 13:30:21 +08:00
|
|
|
return nullptr;
|
2013-06-21 00:23:52 +08:00
|
|
|
|
2015-05-30 09:25:56 +08:00
|
|
|
return MCBinaryExpr::create(BE->getOpcode(), LHS, RHS, Context);
|
2013-06-21 00:23:52 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm_unreachable("Invalid expression kind!");
|
|
|
|
}
|
|
|
|
|
[PowerPC] Revert r185476 and fix up TLS variant kinds
In the commit message to r185476 I wrote:
>The PowerPC-specific modifiers VK_PPC_TLSGD and VK_PPC_TLSLD
>correspond exactly to the generic modifiers VK_TLSGD and VK_TLSLD.
>This causes some confusion with the asm parser, since VK_PPC_TLSGD
>is output as @tlsgd, which is then read back in as VK_TLSGD.
>
>To avoid this confusion, this patch removes the PowerPC-specific
>modifiers and uses the generic modifiers throughout. (The only
>drawback is that the generic modifiers are printed in upper case
>while the usual convention on PowerPC is to use lower-case modifiers.
>But this is just a cosmetic issue.)
This was unfortunately incorrect, there is is fact another,
serious drawback to using the default VK_TLSLD/VK_TLSGD
variant kinds: using these causes ELFObjectWriter::RelocNeedsGOT
to return true, which in turn causes the ELFObjectWriter to emit
an undefined reference to _GLOBAL_OFFSET_TABLE_.
This is a problem on powerpc64, because it uses the TOC instead
of the GOT, and the linker does not provide _GLOBAL_OFFSET_TABLE_,
so the symbol remains undefined. This means shared libraries
using TLS built with the integrated assembler are currently
broken.
While the whole RelocNeedsGOT / _GLOBAL_OFFSET_TABLE_ situation
probably ought to be properly fixed at some point, for now I'm
simply reverting the r185476 commit. Now this in turn exposes
the breakage of handling @tlsgd/@tlsld in the asm parser that
this check-in was originally intended to fix.
To avoid this regression, I'm also adding a different fix for
this problem: while common code now parses @tlsgd as VK_TLSGD,
a special hack in the asm parser translates this code to the
platform-specific VK_PPC_TLSGD that the back-end now expects.
While this is not really pretty, it's self-contained and
shouldn't hurt anything else for now. One the underlying
problem is fixed, this hack can be reverted again.
llvm-svn: 185945
2013-07-10 00:41:09 +08:00
|
|
|
/// Find all VK_TLSGD/VK_TLSLD symbol references in expression and replace
|
|
|
|
/// them by VK_PPC_TLSGD/VK_PPC_TLSLD. This is necessary to avoid having
|
|
|
|
/// _GLOBAL_OFFSET_TABLE_ created via ELFObjectWriter::RelocNeedsGOT.
|
|
|
|
/// FIXME: This is a hack.
|
|
|
|
const MCExpr *PPCAsmParser::
|
|
|
|
FixupVariantKind(const MCExpr *E) {
|
|
|
|
MCContext &Context = getParser().getContext();
|
|
|
|
|
|
|
|
switch (E->getKind()) {
|
|
|
|
case MCExpr::Target:
|
|
|
|
case MCExpr::Constant:
|
|
|
|
return E;
|
|
|
|
|
|
|
|
case MCExpr::SymbolRef: {
|
|
|
|
const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E);
|
|
|
|
MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
|
|
|
|
|
|
|
|
switch (SRE->getKind()) {
|
|
|
|
case MCSymbolRefExpr::VK_TLSGD:
|
|
|
|
Variant = MCSymbolRefExpr::VK_PPC_TLSGD;
|
|
|
|
break;
|
|
|
|
case MCSymbolRefExpr::VK_TLSLD:
|
|
|
|
Variant = MCSymbolRefExpr::VK_PPC_TLSLD;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return E;
|
|
|
|
}
|
2015-05-30 09:25:56 +08:00
|
|
|
return MCSymbolRefExpr::create(&SRE->getSymbol(), Variant, Context);
|
[PowerPC] Revert r185476 and fix up TLS variant kinds
In the commit message to r185476 I wrote:
>The PowerPC-specific modifiers VK_PPC_TLSGD and VK_PPC_TLSLD
>correspond exactly to the generic modifiers VK_TLSGD and VK_TLSLD.
>This causes some confusion with the asm parser, since VK_PPC_TLSGD
>is output as @tlsgd, which is then read back in as VK_TLSGD.
>
>To avoid this confusion, this patch removes the PowerPC-specific
>modifiers and uses the generic modifiers throughout. (The only
>drawback is that the generic modifiers are printed in upper case
>while the usual convention on PowerPC is to use lower-case modifiers.
>But this is just a cosmetic issue.)
This was unfortunately incorrect, there is is fact another,
serious drawback to using the default VK_TLSLD/VK_TLSGD
variant kinds: using these causes ELFObjectWriter::RelocNeedsGOT
to return true, which in turn causes the ELFObjectWriter to emit
an undefined reference to _GLOBAL_OFFSET_TABLE_.
This is a problem on powerpc64, because it uses the TOC instead
of the GOT, and the linker does not provide _GLOBAL_OFFSET_TABLE_,
so the symbol remains undefined. This means shared libraries
using TLS built with the integrated assembler are currently
broken.
While the whole RelocNeedsGOT / _GLOBAL_OFFSET_TABLE_ situation
probably ought to be properly fixed at some point, for now I'm
simply reverting the r185476 commit. Now this in turn exposes
the breakage of handling @tlsgd/@tlsld in the asm parser that
this check-in was originally intended to fix.
To avoid this regression, I'm also adding a different fix for
this problem: while common code now parses @tlsgd as VK_TLSGD,
a special hack in the asm parser translates this code to the
platform-specific VK_PPC_TLSGD that the back-end now expects.
While this is not really pretty, it's self-contained and
shouldn't hurt anything else for now. One the underlying
problem is fixed, this hack can be reverted again.
llvm-svn: 185945
2013-07-10 00:41:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
case MCExpr::Unary: {
|
|
|
|
const MCUnaryExpr *UE = cast<MCUnaryExpr>(E);
|
|
|
|
const MCExpr *Sub = FixupVariantKind(UE->getSubExpr());
|
|
|
|
if (Sub == UE->getSubExpr())
|
|
|
|
return E;
|
2015-05-30 09:25:56 +08:00
|
|
|
return MCUnaryExpr::create(UE->getOpcode(), Sub, Context);
|
[PowerPC] Revert r185476 and fix up TLS variant kinds
In the commit message to r185476 I wrote:
>The PowerPC-specific modifiers VK_PPC_TLSGD and VK_PPC_TLSLD
>correspond exactly to the generic modifiers VK_TLSGD and VK_TLSLD.
>This causes some confusion with the asm parser, since VK_PPC_TLSGD
>is output as @tlsgd, which is then read back in as VK_TLSGD.
>
>To avoid this confusion, this patch removes the PowerPC-specific
>modifiers and uses the generic modifiers throughout. (The only
>drawback is that the generic modifiers are printed in upper case
>while the usual convention on PowerPC is to use lower-case modifiers.
>But this is just a cosmetic issue.)
This was unfortunately incorrect, there is is fact another,
serious drawback to using the default VK_TLSLD/VK_TLSGD
variant kinds: using these causes ELFObjectWriter::RelocNeedsGOT
to return true, which in turn causes the ELFObjectWriter to emit
an undefined reference to _GLOBAL_OFFSET_TABLE_.
This is a problem on powerpc64, because it uses the TOC instead
of the GOT, and the linker does not provide _GLOBAL_OFFSET_TABLE_,
so the symbol remains undefined. This means shared libraries
using TLS built with the integrated assembler are currently
broken.
While the whole RelocNeedsGOT / _GLOBAL_OFFSET_TABLE_ situation
probably ought to be properly fixed at some point, for now I'm
simply reverting the r185476 commit. Now this in turn exposes
the breakage of handling @tlsgd/@tlsld in the asm parser that
this check-in was originally intended to fix.
To avoid this regression, I'm also adding a different fix for
this problem: while common code now parses @tlsgd as VK_TLSGD,
a special hack in the asm parser translates this code to the
platform-specific VK_PPC_TLSGD that the back-end now expects.
While this is not really pretty, it's self-contained and
shouldn't hurt anything else for now. One the underlying
problem is fixed, this hack can be reverted again.
llvm-svn: 185945
2013-07-10 00:41:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
case MCExpr::Binary: {
|
|
|
|
const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);
|
|
|
|
const MCExpr *LHS = FixupVariantKind(BE->getLHS());
|
|
|
|
const MCExpr *RHS = FixupVariantKind(BE->getRHS());
|
|
|
|
if (LHS == BE->getLHS() && RHS == BE->getRHS())
|
|
|
|
return E;
|
2015-05-30 09:25:56 +08:00
|
|
|
return MCBinaryExpr::create(BE->getOpcode(), LHS, RHS, Context);
|
[PowerPC] Revert r185476 and fix up TLS variant kinds
In the commit message to r185476 I wrote:
>The PowerPC-specific modifiers VK_PPC_TLSGD and VK_PPC_TLSLD
>correspond exactly to the generic modifiers VK_TLSGD and VK_TLSLD.
>This causes some confusion with the asm parser, since VK_PPC_TLSGD
>is output as @tlsgd, which is then read back in as VK_TLSGD.
>
>To avoid this confusion, this patch removes the PowerPC-specific
>modifiers and uses the generic modifiers throughout. (The only
>drawback is that the generic modifiers are printed in upper case
>while the usual convention on PowerPC is to use lower-case modifiers.
>But this is just a cosmetic issue.)
This was unfortunately incorrect, there is is fact another,
serious drawback to using the default VK_TLSLD/VK_TLSGD
variant kinds: using these causes ELFObjectWriter::RelocNeedsGOT
to return true, which in turn causes the ELFObjectWriter to emit
an undefined reference to _GLOBAL_OFFSET_TABLE_.
This is a problem on powerpc64, because it uses the TOC instead
of the GOT, and the linker does not provide _GLOBAL_OFFSET_TABLE_,
so the symbol remains undefined. This means shared libraries
using TLS built with the integrated assembler are currently
broken.
While the whole RelocNeedsGOT / _GLOBAL_OFFSET_TABLE_ situation
probably ought to be properly fixed at some point, for now I'm
simply reverting the r185476 commit. Now this in turn exposes
the breakage of handling @tlsgd/@tlsld in the asm parser that
this check-in was originally intended to fix.
To avoid this regression, I'm also adding a different fix for
this problem: while common code now parses @tlsgd as VK_TLSGD,
a special hack in the asm parser translates this code to the
platform-specific VK_PPC_TLSGD that the back-end now expects.
While this is not really pretty, it's self-contained and
shouldn't hurt anything else for now. One the underlying
problem is fixed, this hack can be reverted again.
llvm-svn: 185945
2013-07-10 00:41:09 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm_unreachable("Invalid expression kind!");
|
|
|
|
}
|
|
|
|
|
2013-12-14 21:34:02 +08:00
|
|
|
/// ParseExpression. This differs from the default "parseExpression" in that
|
|
|
|
/// it handles modifiers.
|
2013-06-21 00:23:52 +08:00
|
|
|
bool PPCAsmParser::
|
|
|
|
ParseExpression(const MCExpr *&EVal) {
|
2013-12-14 21:34:02 +08:00
|
|
|
|
|
|
|
if (isDarwin())
|
|
|
|
return ParseDarwinExpression(EVal);
|
|
|
|
|
|
|
|
// (ELF Platforms)
|
|
|
|
// Handle \code @l/@ha \endcode
|
2013-06-21 00:23:52 +08:00
|
|
|
if (getParser().parseExpression(EVal))
|
|
|
|
return true;
|
|
|
|
|
[PowerPC] Revert r185476 and fix up TLS variant kinds
In the commit message to r185476 I wrote:
>The PowerPC-specific modifiers VK_PPC_TLSGD and VK_PPC_TLSLD
>correspond exactly to the generic modifiers VK_TLSGD and VK_TLSLD.
>This causes some confusion with the asm parser, since VK_PPC_TLSGD
>is output as @tlsgd, which is then read back in as VK_TLSGD.
>
>To avoid this confusion, this patch removes the PowerPC-specific
>modifiers and uses the generic modifiers throughout. (The only
>drawback is that the generic modifiers are printed in upper case
>while the usual convention on PowerPC is to use lower-case modifiers.
>But this is just a cosmetic issue.)
This was unfortunately incorrect, there is is fact another,
serious drawback to using the default VK_TLSLD/VK_TLSGD
variant kinds: using these causes ELFObjectWriter::RelocNeedsGOT
to return true, which in turn causes the ELFObjectWriter to emit
an undefined reference to _GLOBAL_OFFSET_TABLE_.
This is a problem on powerpc64, because it uses the TOC instead
of the GOT, and the linker does not provide _GLOBAL_OFFSET_TABLE_,
so the symbol remains undefined. This means shared libraries
using TLS built with the integrated assembler are currently
broken.
While the whole RelocNeedsGOT / _GLOBAL_OFFSET_TABLE_ situation
probably ought to be properly fixed at some point, for now I'm
simply reverting the r185476 commit. Now this in turn exposes
the breakage of handling @tlsgd/@tlsld in the asm parser that
this check-in was originally intended to fix.
To avoid this regression, I'm also adding a different fix for
this problem: while common code now parses @tlsgd as VK_TLSGD,
a special hack in the asm parser translates this code to the
platform-specific VK_PPC_TLSGD that the back-end now expects.
While this is not really pretty, it's self-contained and
shouldn't hurt anything else for now. One the underlying
problem is fixed, this hack can be reverted again.
llvm-svn: 185945
2013-07-10 00:41:09 +08:00
|
|
|
EVal = FixupVariantKind(EVal);
|
|
|
|
|
2013-06-21 00:23:52 +08:00
|
|
|
PPCMCExpr::VariantKind Variant;
|
|
|
|
const MCExpr *E = ExtractModifierFromExpr(EVal, Variant);
|
|
|
|
if (E)
|
2015-05-30 09:25:56 +08:00
|
|
|
EVal = PPCMCExpr::create(Variant, E, false, getParser().getContext());
|
2013-06-21 00:23:52 +08:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-12-14 21:34:02 +08:00
|
|
|
/// ParseDarwinExpression. (MachO Platforms)
|
|
|
|
/// This differs from the default "parseExpression" in that it handles detection
|
|
|
|
/// of the \code hi16(), ha16() and lo16() \endcode modifiers. At present,
|
|
|
|
/// parseExpression() doesn't recognise the modifiers when in the Darwin/MachO
|
2016-06-16 09:00:53 +08:00
|
|
|
/// syntax form so it is done here. TODO: Determine if there is merit in
|
|
|
|
/// arranging for this to be done at a higher level.
|
2013-12-14 21:34:02 +08:00
|
|
|
bool PPCAsmParser::
|
|
|
|
ParseDarwinExpression(const MCExpr *&EVal) {
|
2014-11-11 13:18:41 +08:00
|
|
|
MCAsmParser &Parser = getParser();
|
2013-12-14 21:34:02 +08:00
|
|
|
PPCMCExpr::VariantKind Variant = PPCMCExpr::VK_PPC_None;
|
|
|
|
switch (getLexer().getKind()) {
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
case AsmToken::Identifier:
|
|
|
|
// Compiler-generated Darwin identifiers begin with L,l,_ or "; thus
|
|
|
|
// something starting with any other char should be part of the
|
|
|
|
// asm syntax. If handwritten asm includes an identifier like lo16,
|
|
|
|
// then all bets are off - but no-one would do that, right?
|
|
|
|
StringRef poss = Parser.getTok().getString();
|
|
|
|
if (poss.equals_lower("lo16")) {
|
|
|
|
Variant = PPCMCExpr::VK_PPC_LO;
|
|
|
|
} else if (poss.equals_lower("hi16")) {
|
|
|
|
Variant = PPCMCExpr::VK_PPC_HI;
|
|
|
|
} else if (poss.equals_lower("ha16")) {
|
|
|
|
Variant = PPCMCExpr::VK_PPC_HA;
|
|
|
|
}
|
|
|
|
if (Variant != PPCMCExpr::VK_PPC_None) {
|
|
|
|
Parser.Lex(); // Eat the xx16
|
|
|
|
if (getLexer().isNot(AsmToken::LParen))
|
|
|
|
return Error(Parser.getTok().getLoc(), "expected '('");
|
|
|
|
Parser.Lex(); // Eat the '('
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (getParser().parseExpression(EVal))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (Variant != PPCMCExpr::VK_PPC_None) {
|
|
|
|
if (getLexer().isNot(AsmToken::RParen))
|
|
|
|
return Error(Parser.getTok().getLoc(), "expected ')'");
|
|
|
|
Parser.Lex(); // Eat the ')'
|
2015-05-30 09:25:56 +08:00
|
|
|
EVal = PPCMCExpr::create(Variant, EVal, false, getParser().getContext());
|
2013-12-14 21:34:02 +08:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ParseOperand
|
|
|
|
/// This handles registers in the form 'NN', '%rNN' for ELF platforms and
|
|
|
|
/// rNN for MachO.
|
2014-06-09 00:18:35 +08:00
|
|
|
bool PPCAsmParser::ParseOperand(OperandVector &Operands) {
|
2014-11-11 13:18:41 +08:00
|
|
|
MCAsmParser &Parser = getParser();
|
2013-05-04 03:49:39 +08:00
|
|
|
SMLoc S = Parser.getTok().getLoc();
|
|
|
|
SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
|
|
|
|
const MCExpr *EVal;
|
|
|
|
|
|
|
|
// Attempt to parse the next token as an immediate
|
|
|
|
switch (getLexer().getKind()) {
|
|
|
|
// Special handling for register names. These are interpreted
|
|
|
|
// as immediates corresponding to the register number.
|
|
|
|
case AsmToken::Percent:
|
|
|
|
Parser.Lex(); // Eat the '%'.
|
|
|
|
unsigned RegNo;
|
|
|
|
int64_t IntVal;
|
2016-12-05 22:11:03 +08:00
|
|
|
if (MatchRegisterName(RegNo, IntVal))
|
|
|
|
return Error(S, "invalid register name");
|
|
|
|
|
|
|
|
Operands.push_back(PPCOperand::CreateImm(IntVal, S, E, isPPC64()));
|
|
|
|
return false;
|
2013-05-04 03:49:39 +08:00
|
|
|
|
2013-12-14 21:34:02 +08:00
|
|
|
case AsmToken::Identifier:
|
2016-12-05 22:11:03 +08:00
|
|
|
case AsmToken::LParen:
|
|
|
|
case AsmToken::Plus:
|
|
|
|
case AsmToken::Minus:
|
|
|
|
case AsmToken::Integer:
|
|
|
|
case AsmToken::Dot:
|
|
|
|
case AsmToken::Dollar:
|
|
|
|
case AsmToken::Exclaim:
|
|
|
|
case AsmToken::Tilde:
|
2013-12-14 21:34:02 +08:00
|
|
|
// Note that non-register-name identifiers from the compiler will begin
|
|
|
|
// with '_', 'L'/'l' or '"'. Of course, handwritten asm could include
|
|
|
|
// identifiers like r31foo - so we fall through in the event that parsing
|
|
|
|
// a register name fails.
|
|
|
|
if (isDarwin()) {
|
|
|
|
unsigned RegNo;
|
|
|
|
int64_t IntVal;
|
2016-12-05 22:11:03 +08:00
|
|
|
if (!MatchRegisterName(RegNo, IntVal)) {
|
2014-06-09 00:18:35 +08:00
|
|
|
Operands.push_back(PPCOperand::CreateImm(IntVal, S, E, isPPC64()));
|
2013-12-14 21:34:02 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2016-12-05 22:11:03 +08:00
|
|
|
// All other expressions
|
|
|
|
|
2013-06-21 00:23:52 +08:00
|
|
|
if (!ParseExpression(EVal))
|
2013-05-04 03:49:39 +08:00
|
|
|
break;
|
2016-12-05 22:11:03 +08:00
|
|
|
// Fall-through
|
|
|
|
LLVM_FALLTHROUGH;
|
2013-05-04 03:49:39 +08:00
|
|
|
default:
|
|
|
|
return Error(S, "unknown operand");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Push the parsed operand into the list of operands
|
2014-06-09 00:18:35 +08:00
|
|
|
Operands.push_back(PPCOperand::CreateFromMCExpr(EVal, S, E, isPPC64()));
|
2013-05-04 03:49:39 +08:00
|
|
|
|
2013-07-03 05:31:59 +08:00
|
|
|
// Check whether this is a TLS call expression
|
|
|
|
bool TLSCall = false;
|
|
|
|
if (const MCSymbolRefExpr *Ref = dyn_cast<MCSymbolRefExpr>(EVal))
|
|
|
|
TLSCall = Ref->getSymbol().getName() == "__tls_get_addr";
|
|
|
|
|
|
|
|
if (TLSCall && getLexer().is(AsmToken::LParen)) {
|
|
|
|
const MCExpr *TLSSym;
|
|
|
|
|
|
|
|
Parser.Lex(); // Eat the '('.
|
|
|
|
S = Parser.getTok().getLoc();
|
|
|
|
if (ParseExpression(TLSSym))
|
|
|
|
return Error(S, "invalid TLS call expression");
|
|
|
|
if (getLexer().isNot(AsmToken::RParen))
|
|
|
|
return Error(Parser.getTok().getLoc(), "missing ')'");
|
|
|
|
E = Parser.getTok().getLoc();
|
|
|
|
Parser.Lex(); // Eat the ')'.
|
|
|
|
|
2014-06-09 00:18:35 +08:00
|
|
|
Operands.push_back(PPCOperand::CreateFromMCExpr(TLSSym, S, E, isPPC64()));
|
2013-07-03 05:31:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, check for D-form memory operands
|
|
|
|
if (!TLSCall && getLexer().is(AsmToken::LParen)) {
|
2013-05-04 03:49:39 +08:00
|
|
|
Parser.Lex(); // Eat the '('.
|
|
|
|
S = Parser.getTok().getLoc();
|
|
|
|
|
|
|
|
int64_t IntVal;
|
|
|
|
switch (getLexer().getKind()) {
|
|
|
|
case AsmToken::Percent:
|
|
|
|
Parser.Lex(); // Eat the '%'.
|
|
|
|
unsigned RegNo;
|
2016-12-05 22:11:03 +08:00
|
|
|
if (MatchRegisterName(RegNo, IntVal))
|
2013-05-04 03:49:39 +08:00
|
|
|
return Error(S, "invalid register name");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AsmToken::Integer:
|
2016-12-05 22:11:03 +08:00
|
|
|
if (isDarwin())
|
2013-12-14 21:34:02 +08:00
|
|
|
return Error(S, "unexpected integer value");
|
2016-12-05 22:11:03 +08:00
|
|
|
else if (getParser().parseAbsoluteExpression(IntVal) || IntVal < 0 ||
|
|
|
|
IntVal > 31)
|
|
|
|
return Error(S, "invalid register number");
|
2013-05-04 03:49:39 +08:00
|
|
|
break;
|
2013-12-14 21:34:02 +08:00
|
|
|
case AsmToken::Identifier:
|
|
|
|
if (isDarwin()) {
|
|
|
|
unsigned RegNo;
|
2016-12-05 22:11:03 +08:00
|
|
|
if (!MatchRegisterName(RegNo, IntVal)) {
|
2013-12-14 21:34:02 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2016-08-17 13:10:15 +08:00
|
|
|
LLVM_FALLTHROUGH;
|
2013-12-14 21:34:02 +08:00
|
|
|
|
2013-05-04 03:49:39 +08:00
|
|
|
default:
|
|
|
|
return Error(S, "invalid memory operand");
|
|
|
|
}
|
|
|
|
|
|
|
|
E = Parser.getTok().getLoc();
|
2016-12-05 22:11:03 +08:00
|
|
|
if (parseToken(AsmToken::RParen, "missing ')'"))
|
|
|
|
return true;
|
2014-06-09 00:18:35 +08:00
|
|
|
Operands.push_back(PPCOperand::CreateImm(IntVal, S, E, isPPC64()));
|
2013-05-04 03:49:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Parse an instruction mnemonic followed by its operands.
|
2014-06-09 00:18:35 +08:00
|
|
|
bool PPCAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
|
|
|
|
SMLoc NameLoc, OperandVector &Operands) {
|
2013-05-04 03:49:39 +08:00
|
|
|
// The first operand is the token for the instruction name.
|
2013-06-25 00:52:04 +08:00
|
|
|
// If the next character is a '+' or '-', we need to add it to the
|
|
|
|
// instruction name, to match what TableGen is doing.
|
2013-08-04 06:43:29 +08:00
|
|
|
std::string NewOpcode;
|
2016-12-05 22:11:03 +08:00
|
|
|
if (parseOptionalToken(AsmToken::Plus)) {
|
2013-08-04 06:43:29 +08:00
|
|
|
NewOpcode = Name;
|
|
|
|
NewOpcode += '+';
|
|
|
|
Name = NewOpcode;
|
2013-06-25 00:52:04 +08:00
|
|
|
}
|
2016-12-05 22:11:03 +08:00
|
|
|
if (parseOptionalToken(AsmToken::Minus)) {
|
2013-08-04 06:43:29 +08:00
|
|
|
NewOpcode = Name;
|
|
|
|
NewOpcode += '-';
|
|
|
|
Name = NewOpcode;
|
2013-06-25 00:52:04 +08:00
|
|
|
}
|
2013-05-04 03:49:39 +08:00
|
|
|
// If the instruction ends in a '.', we need to create a separate
|
|
|
|
// token for it, to match what TableGen is doing.
|
|
|
|
size_t Dot = Name.find('.');
|
|
|
|
StringRef Mnemonic = Name.slice(0, Dot);
|
2013-08-04 06:43:29 +08:00
|
|
|
if (!NewOpcode.empty()) // Underlying memory for Name is volatile.
|
|
|
|
Operands.push_back(
|
|
|
|
PPCOperand::CreateTokenWithStringCopy(Mnemonic, NameLoc, isPPC64()));
|
|
|
|
else
|
|
|
|
Operands.push_back(PPCOperand::CreateToken(Mnemonic, NameLoc, isPPC64()));
|
2013-05-04 03:49:39 +08:00
|
|
|
if (Dot != StringRef::npos) {
|
|
|
|
SMLoc DotLoc = SMLoc::getFromPointer(NameLoc.getPointer() + Dot);
|
|
|
|
StringRef DotStr = Name.slice(Dot, StringRef::npos);
|
2013-08-04 06:43:29 +08:00
|
|
|
if (!NewOpcode.empty()) // Underlying memory for Name is volatile.
|
|
|
|
Operands.push_back(
|
|
|
|
PPCOperand::CreateTokenWithStringCopy(DotStr, DotLoc, isPPC64()));
|
|
|
|
else
|
|
|
|
Operands.push_back(PPCOperand::CreateToken(DotStr, DotLoc, isPPC64()));
|
2013-05-04 03:49:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// If there are no more operands then finish
|
2016-12-05 22:11:03 +08:00
|
|
|
if (parseOptionalToken(AsmToken::EndOfStatement))
|
2013-05-04 03:49:39 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// Parse the first operand
|
|
|
|
if (ParseOperand(Operands))
|
|
|
|
return true;
|
|
|
|
|
2016-12-05 22:11:03 +08:00
|
|
|
while (!parseOptionalToken(AsmToken::EndOfStatement)) {
|
|
|
|
if (parseToken(AsmToken::Comma) || ParseOperand(Operands))
|
2013-05-04 03:49:39 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-04-24 06:47:57 +08:00
|
|
|
// We'll now deal with an unfortunate special case: the syntax for the dcbt
|
|
|
|
// and dcbtst instructions differs for server vs. embedded cores.
|
|
|
|
// The syntax for dcbt is:
|
|
|
|
// dcbt ra, rb, th [server]
|
|
|
|
// dcbt th, ra, rb [embedded]
|
|
|
|
// where th can be omitted when it is 0. dcbtst is the same. We take the
|
|
|
|
// server form to be the default, so swap the operands if we're parsing for
|
|
|
|
// an embedded core (they'll be swapped again upon printing).
|
2015-11-14 13:20:05 +08:00
|
|
|
if (getSTI().getFeatureBits()[PPC::FeatureBookE] &&
|
2015-04-24 06:47:57 +08:00
|
|
|
Operands.size() == 4 &&
|
|
|
|
(Name == "dcbt" || Name == "dcbtst")) {
|
|
|
|
std::swap(Operands[1], Operands[3]);
|
|
|
|
std::swap(Operands[2], Operands[1]);
|
|
|
|
}
|
|
|
|
|
2013-05-04 03:49:39 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ParseDirective parses the PPC specific directives
|
|
|
|
bool PPCAsmParser::ParseDirective(AsmToken DirectiveID) {
|
|
|
|
StringRef IDVal = DirectiveID.getIdentifier();
|
2016-12-05 22:11:03 +08:00
|
|
|
if (isDarwin()) {
|
2013-12-14 21:34:02 +08:00
|
|
|
if (IDVal == ".machine")
|
2016-12-05 22:11:03 +08:00
|
|
|
ParseDarwinDirectiveMachine(DirectiveID.getLoc());
|
|
|
|
else
|
|
|
|
return true;
|
|
|
|
} else if (IDVal == ".word")
|
|
|
|
ParseDirectiveWord(2, DirectiveID);
|
|
|
|
else if (IDVal == ".llong")
|
|
|
|
ParseDirectiveWord(8, DirectiveID);
|
|
|
|
else if (IDVal == ".tc")
|
|
|
|
ParseDirectiveTC(isPPC64() ? 8 : 4, DirectiveID);
|
|
|
|
else if (IDVal == ".machine")
|
|
|
|
ParseDirectiveMachine(DirectiveID.getLoc());
|
|
|
|
else if (IDVal == ".abiversion")
|
|
|
|
ParseDirectiveAbiVersion(DirectiveID.getLoc());
|
|
|
|
else if (IDVal == ".localentry")
|
|
|
|
ParseDirectiveLocalEntry(DirectiveID.getLoc());
|
|
|
|
else
|
|
|
|
return true;
|
|
|
|
return false;
|
2013-05-04 03:49:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// ParseDirectiveWord
|
|
|
|
/// ::= .word [ expression (, expression)* ]
|
2016-12-05 22:11:03 +08:00
|
|
|
bool PPCAsmParser::ParseDirectiveWord(unsigned Size, AsmToken ID) {
|
|
|
|
auto parseOp = [&]() -> bool {
|
|
|
|
const MCExpr *Value;
|
|
|
|
SMLoc ExprLoc = getParser().getTok().getLoc();
|
|
|
|
if (getParser().parseExpression(Value))
|
|
|
|
return true;
|
|
|
|
if (const auto *MCE = dyn_cast<MCConstantExpr>(Value)) {
|
|
|
|
assert(Size <= 8 && "Invalid size");
|
|
|
|
uint64_t IntValue = MCE->getValue();
|
|
|
|
if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
|
|
|
|
return Error(ExprLoc, "literal value out of range for '" +
|
|
|
|
ID.getIdentifier() + "' directive");
|
|
|
|
getStreamer().EmitIntValue(IntValue, Size);
|
|
|
|
} else
|
|
|
|
getStreamer().EmitValue(Value, Size, ExprLoc);
|
|
|
|
return false;
|
|
|
|
};
|
2013-05-04 03:49:39 +08:00
|
|
|
|
2016-12-05 22:11:03 +08:00
|
|
|
if (parseMany(parseOp))
|
|
|
|
return addErrorSuffix(" in '" + ID.getIdentifier() + "' directive");
|
2013-05-04 03:49:39 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ParseDirectiveTC
|
|
|
|
/// ::= .tc [ symbol (, expression)* ]
|
2016-12-05 22:11:03 +08:00
|
|
|
bool PPCAsmParser::ParseDirectiveTC(unsigned Size, AsmToken ID) {
|
2014-11-11 13:18:41 +08:00
|
|
|
MCAsmParser &Parser = getParser();
|
2013-05-04 03:49:39 +08:00
|
|
|
// Skip TC symbol, which is only used with XCOFF.
|
|
|
|
while (getLexer().isNot(AsmToken::EndOfStatement)
|
|
|
|
&& getLexer().isNot(AsmToken::Comma))
|
|
|
|
Parser.Lex();
|
2016-12-05 22:11:03 +08:00
|
|
|
if (parseToken(AsmToken::Comma))
|
|
|
|
return addErrorSuffix(" in '.tc' directive");
|
2013-05-04 03:49:39 +08:00
|
|
|
|
|
|
|
// Align to word size.
|
|
|
|
getParser().getStreamer().EmitValueToAlignment(Size);
|
|
|
|
|
|
|
|
// Emit expressions.
|
2016-12-05 22:11:03 +08:00
|
|
|
return ParseDirectiveWord(Size, ID);
|
2013-05-04 03:49:39 +08:00
|
|
|
}
|
|
|
|
|
2013-12-14 21:34:02 +08:00
|
|
|
/// ParseDirectiveMachine (ELF platforms)
|
2013-07-09 18:00:34 +08:00
|
|
|
/// ::= .machine [ cpu | "push" | "pop" ]
|
|
|
|
bool PPCAsmParser::ParseDirectiveMachine(SMLoc L) {
|
2014-11-11 13:18:41 +08:00
|
|
|
MCAsmParser &Parser = getParser();
|
2016-12-05 22:11:03 +08:00
|
|
|
if (Parser.getTok().isNot(AsmToken::Identifier) &&
|
|
|
|
Parser.getTok().isNot(AsmToken::String))
|
|
|
|
return Error(L, "unexpected token in '.machine' directive");
|
2013-07-09 18:00:34 +08:00
|
|
|
|
|
|
|
StringRef CPU = Parser.getTok().getIdentifier();
|
|
|
|
|
|
|
|
// FIXME: Right now, the parser always allows any available
|
|
|
|
// instruction, so the .machine directive is not useful.
|
|
|
|
// Implement ".machine any" (by doing nothing) for the benefit
|
|
|
|
// of existing assembler code. Likewise, we can then implement
|
|
|
|
// ".machine push" and ".machine pop" as no-op.
|
2016-12-05 22:11:03 +08:00
|
|
|
if (CPU != "any" && CPU != "push" && CPU != "pop")
|
|
|
|
return TokError("unrecognized machine type");
|
|
|
|
|
|
|
|
Parser.Lex();
|
|
|
|
|
|
|
|
if (parseToken(AsmToken::EndOfStatement))
|
|
|
|
return addErrorSuffix(" in '.machine' directive");
|
2013-07-09 18:00:34 +08:00
|
|
|
|
2014-01-25 10:35:56 +08:00
|
|
|
PPCTargetStreamer &TStreamer =
|
|
|
|
*static_cast<PPCTargetStreamer *>(
|
|
|
|
getParser().getStreamer().getTargetStreamer());
|
|
|
|
TStreamer.emitMachine(CPU);
|
2013-07-09 18:00:34 +08:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-12-14 21:34:02 +08:00
|
|
|
/// ParseDarwinDirectiveMachine (Mach-o platforms)
|
|
|
|
/// ::= .machine cpu-identifier
|
|
|
|
bool PPCAsmParser::ParseDarwinDirectiveMachine(SMLoc L) {
|
2014-11-11 13:18:41 +08:00
|
|
|
MCAsmParser &Parser = getParser();
|
2016-12-05 22:11:03 +08:00
|
|
|
if (Parser.getTok().isNot(AsmToken::Identifier) &&
|
|
|
|
Parser.getTok().isNot(AsmToken::String))
|
|
|
|
return Error(L, "unexpected token in directive");
|
2013-12-14 21:34:02 +08:00
|
|
|
|
|
|
|
StringRef CPU = Parser.getTok().getIdentifier();
|
|
|
|
Parser.Lex();
|
|
|
|
|
|
|
|
// FIXME: this is only the 'default' set of cpu variants.
|
|
|
|
// However we don't act on this information at present, this is simply
|
|
|
|
// allowing parsing to proceed with minimal sanity checking.
|
2016-12-05 22:11:03 +08:00
|
|
|
if (check(CPU != "ppc7400" && CPU != "ppc" && CPU != "ppc64", L,
|
|
|
|
"unrecognized cpu type") ||
|
|
|
|
check(isPPC64() && (CPU == "ppc7400" || CPU == "ppc"), L,
|
|
|
|
"wrong cpu type specified for 64bit") ||
|
|
|
|
check(!isPPC64() && CPU == "ppc64", L,
|
|
|
|
"wrong cpu type specified for 32bit") ||
|
|
|
|
parseToken(AsmToken::EndOfStatement))
|
|
|
|
return addErrorSuffix(" in '.machine' directive");
|
2013-12-14 21:34:02 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-07-21 06:56:57 +08:00
|
|
|
/// ParseDirectiveAbiVersion
|
|
|
|
/// ::= .abiversion constant-expression
|
|
|
|
bool PPCAsmParser::ParseDirectiveAbiVersion(SMLoc L) {
|
|
|
|
int64_t AbiVersion;
|
2016-12-05 22:11:03 +08:00
|
|
|
if (check(getParser().parseAbsoluteExpression(AbiVersion), L,
|
|
|
|
"expected constant expression") ||
|
|
|
|
parseToken(AsmToken::EndOfStatement))
|
|
|
|
return addErrorSuffix(" in '.abiversion' directive");
|
2014-07-21 06:56:57 +08:00
|
|
|
|
|
|
|
PPCTargetStreamer &TStreamer =
|
|
|
|
*static_cast<PPCTargetStreamer *>(
|
|
|
|
getParser().getStreamer().getTargetStreamer());
|
|
|
|
TStreamer.emitAbiVersion(AbiVersion);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
[PowerPC] ELFv2 MC support for .localentry directive
A second binutils feature needed to support ELFv2 is the .localentry
directive. In the ELFv2 ABI, functions may have two entry points:
one for calling the routine locally via "bl", and one for calling the
function via function pointer (either at the source level, or implicitly
via a PLT stub for global calls). The two entry points share a single
ELF symbol, where the ELF symbol address identifies the global entry
point address, while the local entry point is found by adding a delta
offset to the symbol address. That offset is encoded into three
platform-specific bits of the ELF symbol st_other field.
The .localentry directive instructs the assembler to set those fields
to encode a particular offset. This is typically used by a function
prologue sequence like this:
func:
addis r2, r12, (.TOC.-func)@ha
addi r2, r2, (.TOC.-func)@l
.localentry func, .-func
Note that according to the ABI, when calling the global entry point,
r12 must be set to point the global entry point address itself; while
when calling the local entry point, r2 must be set to point to the TOC
base. The two instructions between the global and local entry point in
the above example translate the first requirement into the second.
This patch implements support in the PowerPC MC streamers to emit the
.localentry directive (both into assembler and ELF object output), as
well as support in the assembler parser to parse that directive.
In addition, there is another change required in MC fixup/relocation
handling to properly deal with relocations targeting function symbols
with two entry points: When the target function is known local, the MC
layer would immediately handle the fixup by inserting the target
address -- this is wrong, since the call may need to go to the local
entry point instead. The GNU assembler handles this case by *not*
directly resolving fixups targeting functions with two entry points,
but always emits the relocation and relies on the linker to handle
this case correctly. This patch changes LLVM MC to do the same (this
is done via the processFixupValue routine).
Similarly, there are cases where the assembler would normally emit a
relocation, but "simplify" it to a relocation targeting a *section*
instead of the actual symbol. For the same reason as above, this
may be wrong when the target symbol has two entry points. The GNU
assembler again handles this case by not performing this simplification
in that case, but leaving the relocation targeting the full symbol,
which is then resolved by the linker. This patch changes LLVM MC
to do the same (via the needsRelocateWithSymbol routine).
NOTE: The method used in this patch is overly pessimistic, since the
needsRelocateWithSymbol routine currently does not have access to the
actual target symbol, and thus must always assume that it might have
two entry points. This will be improved upon by a follow-on patch
that modifies common code to pass the target symbol when calling
needsRelocateWithSymbol.
Reviewed by Hal Finkel.
llvm-svn: 213485
2014-07-21 07:06:03 +08:00
|
|
|
/// ParseDirectiveLocalEntry
|
|
|
|
/// ::= .localentry symbol, expression
|
|
|
|
bool PPCAsmParser::ParseDirectiveLocalEntry(SMLoc L) {
|
|
|
|
StringRef Name;
|
2016-12-05 22:11:03 +08:00
|
|
|
if (getParser().parseIdentifier(Name))
|
|
|
|
return Error(L, "expected identifier in '.localentry' directive");
|
[PowerPC] ELFv2 MC support for .localentry directive
A second binutils feature needed to support ELFv2 is the .localentry
directive. In the ELFv2 ABI, functions may have two entry points:
one for calling the routine locally via "bl", and one for calling the
function via function pointer (either at the source level, or implicitly
via a PLT stub for global calls). The two entry points share a single
ELF symbol, where the ELF symbol address identifies the global entry
point address, while the local entry point is found by adding a delta
offset to the symbol address. That offset is encoded into three
platform-specific bits of the ELF symbol st_other field.
The .localentry directive instructs the assembler to set those fields
to encode a particular offset. This is typically used by a function
prologue sequence like this:
func:
addis r2, r12, (.TOC.-func)@ha
addi r2, r2, (.TOC.-func)@l
.localentry func, .-func
Note that according to the ABI, when calling the global entry point,
r12 must be set to point the global entry point address itself; while
when calling the local entry point, r2 must be set to point to the TOC
base. The two instructions between the global and local entry point in
the above example translate the first requirement into the second.
This patch implements support in the PowerPC MC streamers to emit the
.localentry directive (both into assembler and ELF object output), as
well as support in the assembler parser to parse that directive.
In addition, there is another change required in MC fixup/relocation
handling to properly deal with relocations targeting function symbols
with two entry points: When the target function is known local, the MC
layer would immediately handle the fixup by inserting the target
address -- this is wrong, since the call may need to go to the local
entry point instead. The GNU assembler handles this case by *not*
directly resolving fixups targeting functions with two entry points,
but always emits the relocation and relies on the linker to handle
this case correctly. This patch changes LLVM MC to do the same (this
is done via the processFixupValue routine).
Similarly, there are cases where the assembler would normally emit a
relocation, but "simplify" it to a relocation targeting a *section*
instead of the actual symbol. For the same reason as above, this
may be wrong when the target symbol has two entry points. The GNU
assembler again handles this case by not performing this simplification
in that case, but leaving the relocation targeting the full symbol,
which is then resolved by the linker. This patch changes LLVM MC
to do the same (via the needsRelocateWithSymbol routine).
NOTE: The method used in this patch is overly pessimistic, since the
needsRelocateWithSymbol routine currently does not have access to the
actual target symbol, and thus must always assume that it might have
two entry points. This will be improved upon by a follow-on patch
that modifies common code to pass the target symbol when calling
needsRelocateWithSymbol.
Reviewed by Hal Finkel.
llvm-svn: 213485
2014-07-21 07:06:03 +08:00
|
|
|
|
2016-12-05 22:11:03 +08:00
|
|
|
MCSymbolELF *Sym = cast<MCSymbolELF>(getContext().getOrCreateSymbol(Name));
|
[PowerPC] ELFv2 MC support for .localentry directive
A second binutils feature needed to support ELFv2 is the .localentry
directive. In the ELFv2 ABI, functions may have two entry points:
one for calling the routine locally via "bl", and one for calling the
function via function pointer (either at the source level, or implicitly
via a PLT stub for global calls). The two entry points share a single
ELF symbol, where the ELF symbol address identifies the global entry
point address, while the local entry point is found by adding a delta
offset to the symbol address. That offset is encoded into three
platform-specific bits of the ELF symbol st_other field.
The .localentry directive instructs the assembler to set those fields
to encode a particular offset. This is typically used by a function
prologue sequence like this:
func:
addis r2, r12, (.TOC.-func)@ha
addi r2, r2, (.TOC.-func)@l
.localentry func, .-func
Note that according to the ABI, when calling the global entry point,
r12 must be set to point the global entry point address itself; while
when calling the local entry point, r2 must be set to point to the TOC
base. The two instructions between the global and local entry point in
the above example translate the first requirement into the second.
This patch implements support in the PowerPC MC streamers to emit the
.localentry directive (both into assembler and ELF object output), as
well as support in the assembler parser to parse that directive.
In addition, there is another change required in MC fixup/relocation
handling to properly deal with relocations targeting function symbols
with two entry points: When the target function is known local, the MC
layer would immediately handle the fixup by inserting the target
address -- this is wrong, since the call may need to go to the local
entry point instead. The GNU assembler handles this case by *not*
directly resolving fixups targeting functions with two entry points,
but always emits the relocation and relies on the linker to handle
this case correctly. This patch changes LLVM MC to do the same (this
is done via the processFixupValue routine).
Similarly, there are cases where the assembler would normally emit a
relocation, but "simplify" it to a relocation targeting a *section*
instead of the actual symbol. For the same reason as above, this
may be wrong when the target symbol has two entry points. The GNU
assembler again handles this case by not performing this simplification
in that case, but leaving the relocation targeting the full symbol,
which is then resolved by the linker. This patch changes LLVM MC
to do the same (via the needsRelocateWithSymbol routine).
NOTE: The method used in this patch is overly pessimistic, since the
needsRelocateWithSymbol routine currently does not have access to the
actual target symbol, and thus must always assume that it might have
two entry points. This will be improved upon by a follow-on patch
that modifies common code to pass the target symbol when calling
needsRelocateWithSymbol.
Reviewed by Hal Finkel.
llvm-svn: 213485
2014-07-21 07:06:03 +08:00
|
|
|
const MCExpr *Expr;
|
|
|
|
|
2016-12-05 22:11:03 +08:00
|
|
|
if (parseToken(AsmToken::Comma) ||
|
|
|
|
check(getParser().parseExpression(Expr), L, "expected expression") ||
|
|
|
|
parseToken(AsmToken::EndOfStatement))
|
|
|
|
return addErrorSuffix(" in '.localentry' directive");
|
[PowerPC] ELFv2 MC support for .localentry directive
A second binutils feature needed to support ELFv2 is the .localentry
directive. In the ELFv2 ABI, functions may have two entry points:
one for calling the routine locally via "bl", and one for calling the
function via function pointer (either at the source level, or implicitly
via a PLT stub for global calls). The two entry points share a single
ELF symbol, where the ELF symbol address identifies the global entry
point address, while the local entry point is found by adding a delta
offset to the symbol address. That offset is encoded into three
platform-specific bits of the ELF symbol st_other field.
The .localentry directive instructs the assembler to set those fields
to encode a particular offset. This is typically used by a function
prologue sequence like this:
func:
addis r2, r12, (.TOC.-func)@ha
addi r2, r2, (.TOC.-func)@l
.localentry func, .-func
Note that according to the ABI, when calling the global entry point,
r12 must be set to point the global entry point address itself; while
when calling the local entry point, r2 must be set to point to the TOC
base. The two instructions between the global and local entry point in
the above example translate the first requirement into the second.
This patch implements support in the PowerPC MC streamers to emit the
.localentry directive (both into assembler and ELF object output), as
well as support in the assembler parser to parse that directive.
In addition, there is another change required in MC fixup/relocation
handling to properly deal with relocations targeting function symbols
with two entry points: When the target function is known local, the MC
layer would immediately handle the fixup by inserting the target
address -- this is wrong, since the call may need to go to the local
entry point instead. The GNU assembler handles this case by *not*
directly resolving fixups targeting functions with two entry points,
but always emits the relocation and relies on the linker to handle
this case correctly. This patch changes LLVM MC to do the same (this
is done via the processFixupValue routine).
Similarly, there are cases where the assembler would normally emit a
relocation, but "simplify" it to a relocation targeting a *section*
instead of the actual symbol. For the same reason as above, this
may be wrong when the target symbol has two entry points. The GNU
assembler again handles this case by not performing this simplification
in that case, but leaving the relocation targeting the full symbol,
which is then resolved by the linker. This patch changes LLVM MC
to do the same (via the needsRelocateWithSymbol routine).
NOTE: The method used in this patch is overly pessimistic, since the
needsRelocateWithSymbol routine currently does not have access to the
actual target symbol, and thus must always assume that it might have
two entry points. This will be improved upon by a follow-on patch
that modifies common code to pass the target symbol when calling
needsRelocateWithSymbol.
Reviewed by Hal Finkel.
llvm-svn: 213485
2014-07-21 07:06:03 +08:00
|
|
|
|
|
|
|
PPCTargetStreamer &TStreamer =
|
|
|
|
*static_cast<PPCTargetStreamer *>(
|
|
|
|
getParser().getStreamer().getTargetStreamer());
|
|
|
|
TStreamer.emitLocalEntry(Sym, Expr);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-05-04 03:49:39 +08:00
|
|
|
/// Force static initialization.
|
|
|
|
extern "C" void LLVMInitializePowerPCAsmParser() {
|
2016-10-10 07:00:34 +08:00
|
|
|
RegisterMCAsmParser<PPCAsmParser> A(getThePPC32Target());
|
|
|
|
RegisterMCAsmParser<PPCAsmParser> B(getThePPC64Target());
|
|
|
|
RegisterMCAsmParser<PPCAsmParser> C(getThePPC64LETarget());
|
2013-05-04 03:49:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#define GET_REGISTER_MATCHER
|
|
|
|
#define GET_MATCHER_IMPLEMENTATION
|
|
|
|
#include "PPCGenAsmMatcher.inc"
|
2013-07-08 22:49:37 +08:00
|
|
|
|
|
|
|
// Define this matcher function after the auto-generated include so we
|
|
|
|
// have the match class enum definitions.
|
2014-06-09 00:18:35 +08:00
|
|
|
unsigned PPCAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
|
2013-07-08 22:49:37 +08:00
|
|
|
unsigned Kind) {
|
|
|
|
// If the kind is a token for a literal immediate, check if our asm
|
|
|
|
// operand matches. This is for InstAliases which have a fixed-value
|
|
|
|
// immediate in the syntax.
|
|
|
|
int64_t ImmVal;
|
|
|
|
switch (Kind) {
|
|
|
|
case MCK_0: ImmVal = 0; break;
|
|
|
|
case MCK_1: ImmVal = 1; break;
|
2013-09-13 01:50:54 +08:00
|
|
|
case MCK_2: ImmVal = 2; break;
|
|
|
|
case MCK_3: ImmVal = 3; break;
|
2014-07-30 17:24:37 +08:00
|
|
|
case MCK_4: ImmVal = 4; break;
|
|
|
|
case MCK_5: ImmVal = 5; break;
|
|
|
|
case MCK_6: ImmVal = 6; break;
|
|
|
|
case MCK_7: ImmVal = 7; break;
|
2013-07-08 22:49:37 +08:00
|
|
|
default: return Match_InvalidOperand;
|
|
|
|
}
|
|
|
|
|
2014-06-09 00:18:35 +08:00
|
|
|
PPCOperand &Op = static_cast<PPCOperand &>(AsmOp);
|
|
|
|
if (Op.isImm() && Op.getImm() == ImmVal)
|
2013-07-08 22:49:37 +08:00
|
|
|
return Match_Success;
|
|
|
|
|
|
|
|
return Match_InvalidOperand;
|
|
|
|
}
|
|
|
|
|
2013-08-28 04:23:19 +08:00
|
|
|
const MCExpr *
|
|
|
|
PPCAsmParser::applyModifierToExpr(const MCExpr *E,
|
|
|
|
MCSymbolRefExpr::VariantKind Variant,
|
|
|
|
MCContext &Ctx) {
|
|
|
|
switch (Variant) {
|
|
|
|
case MCSymbolRefExpr::VK_PPC_LO:
|
2015-05-30 09:25:56 +08:00
|
|
|
return PPCMCExpr::create(PPCMCExpr::VK_PPC_LO, E, false, Ctx);
|
2013-08-28 04:23:19 +08:00
|
|
|
case MCSymbolRefExpr::VK_PPC_HI:
|
2015-05-30 09:25:56 +08:00
|
|
|
return PPCMCExpr::create(PPCMCExpr::VK_PPC_HI, E, false, Ctx);
|
2013-08-28 04:23:19 +08:00
|
|
|
case MCSymbolRefExpr::VK_PPC_HA:
|
2015-05-30 09:25:56 +08:00
|
|
|
return PPCMCExpr::create(PPCMCExpr::VK_PPC_HA, E, false, Ctx);
|
2013-08-28 04:23:19 +08:00
|
|
|
case MCSymbolRefExpr::VK_PPC_HIGHER:
|
2015-05-30 09:25:56 +08:00
|
|
|
return PPCMCExpr::create(PPCMCExpr::VK_PPC_HIGHER, E, false, Ctx);
|
2013-08-28 04:23:19 +08:00
|
|
|
case MCSymbolRefExpr::VK_PPC_HIGHERA:
|
2015-05-30 09:25:56 +08:00
|
|
|
return PPCMCExpr::create(PPCMCExpr::VK_PPC_HIGHERA, E, false, Ctx);
|
2013-08-28 04:23:19 +08:00
|
|
|
case MCSymbolRefExpr::VK_PPC_HIGHEST:
|
2015-05-30 09:25:56 +08:00
|
|
|
return PPCMCExpr::create(PPCMCExpr::VK_PPC_HIGHEST, E, false, Ctx);
|
2013-08-28 04:23:19 +08:00
|
|
|
case MCSymbolRefExpr::VK_PPC_HIGHESTA:
|
2015-05-30 09:25:56 +08:00
|
|
|
return PPCMCExpr::create(PPCMCExpr::VK_PPC_HIGHESTA, E, false, Ctx);
|
2013-08-28 04:23:19 +08:00
|
|
|
default:
|
2014-04-25 13:30:21 +08:00
|
|
|
return nullptr;
|
2013-08-28 04:23:19 +08:00
|
|
|
}
|
|
|
|
}
|