Skip to content

Commit bfef1dd

Browse files
committed
@l and friends adjust their value depending the context used in.
For ori, they are unsigned, for addi, signed. Create a new target expression type to handle this and evaluate Fixups accordingly. llvm-svn: 215315
1 parent 16055e7 commit bfef1dd

File tree

6 files changed

+163
-41
lines changed

6 files changed

+163
-41
lines changed

llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp

Lines changed: 92 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ struct PPCOperand : public MCParsedAsmOperand {
297297
enum KindTy {
298298
Token,
299299
Immediate,
300+
ContextImmediate,
300301
Expression,
301302
TLSRegister
302303
} Kind;
@@ -341,6 +342,7 @@ struct PPCOperand : public MCParsedAsmOperand {
341342
Tok = o.Tok;
342343
break;
343344
case Immediate:
345+
case ContextImmediate:
344346
Imm = o.Imm;
345347
break;
346348
case Expression:
@@ -365,6 +367,16 @@ struct PPCOperand : public MCParsedAsmOperand {
365367
assert(Kind == Immediate && "Invalid access!");
366368
return Imm.Val;
367369
}
370+
int64_t getImmS16Context() const {
371+
assert((Kind == Immediate || Kind == ContextImmediate) && "Invalid access!");
372+
if (Kind == Immediate)
373+
return Imm.Val;
374+
return static_cast<int16_t>(Imm.Val);
375+
}
376+
int64_t getImmU16Context() const {
377+
assert((Kind == Immediate || Kind == ContextImmediate) && "Invalid access!");
378+
return Imm.Val;
379+
}
368380

369381
const MCExpr *getExpr() const {
370382
assert(Kind == Expression && "Invalid access!");
@@ -422,15 +434,42 @@ struct PPCOperand : public MCParsedAsmOperand {
422434
bool isU8ImmX8() const { return Kind == Immediate &&
423435
isUInt<8>(getImm()) &&
424436
(getImm() & 7) == 0; }
425-
bool isU16Imm() const { return Kind == Expression ||
426-
(Kind == Immediate && isUInt<16>(getImm())); }
427-
bool isS16Imm() const { return Kind == Expression ||
428-
(Kind == Immediate && isInt<16>(getImm())); }
437+
bool isU16Imm() const {
438+
switch (Kind) {
439+
case Expression:
440+
return true;
441+
case Immediate:
442+
case ContextImmediate:
443+
return isUInt<16>(getImmU16Context());
444+
default:
445+
return false;
446+
}
447+
}
448+
bool isS16Imm() const {
449+
switch (Kind) {
450+
case Expression:
451+
return true;
452+
case Immediate:
453+
case ContextImmediate:
454+
return isInt<16>(getImmS16Context());
455+
default:
456+
return false;
457+
}
458+
}
429459
bool isS16ImmX4() const { return Kind == Expression ||
430460
(Kind == Immediate && isInt<16>(getImm()) &&
431461
(getImm() & 3) == 0); }
432-
bool isS17Imm() const { return Kind == Expression ||
433-
(Kind == Immediate && isInt<17>(getImm())); }
462+
bool isS17Imm() const {
463+
switch (Kind) {
464+
case Expression:
465+
return true;
466+
case Immediate:
467+
case ContextImmediate:
468+
return isInt<17>(getImmS16Context());
469+
default:
470+
return false;
471+
}
472+
}
434473
bool isTLSReg() const { return Kind == TLSRegister; }
435474
bool isDirectBr() const {
436475
if (Kind == Expression)
@@ -553,6 +592,36 @@ struct PPCOperand : public MCParsedAsmOperand {
553592
Inst.addOperand(MCOperand::CreateExpr(getExpr()));
554593
}
555594

595+
void addS16ImmOperands(MCInst &Inst, unsigned N) const {
596+
assert(N == 1 && "Invalid number of operands!");
597+
switch (Kind) {
598+
case Immediate:
599+
Inst.addOperand(MCOperand::CreateImm(getImm()));
600+
break;
601+
case ContextImmediate:
602+
Inst.addOperand(MCOperand::CreateImm(getImmS16Context()));
603+
break;
604+
default:
605+
Inst.addOperand(MCOperand::CreateExpr(getExpr()));
606+
break;
607+
}
608+
}
609+
610+
void addU16ImmOperands(MCInst &Inst, unsigned N) const {
611+
assert(N == 1 && "Invalid number of operands!");
612+
switch (Kind) {
613+
case Immediate:
614+
Inst.addOperand(MCOperand::CreateImm(getImm()));
615+
break;
616+
case ContextImmediate:
617+
Inst.addOperand(MCOperand::CreateImm(getImmU16Context()));
618+
break;
619+
default:
620+
Inst.addOperand(MCOperand::CreateExpr(getExpr()));
621+
break;
622+
}
623+
}
624+
556625
void addBranchTargetOperands(MCInst &Inst, unsigned N) const {
557626
assert(N == 1 && "Invalid number of operands!");
558627
if (Kind == Immediate)
@@ -633,6 +702,16 @@ struct PPCOperand : public MCParsedAsmOperand {
633702
return Op;
634703
}
635704

705+
static std::unique_ptr<PPCOperand>
706+
CreateContextImm(int64_t Val, SMLoc S, SMLoc E, bool IsPPC64) {
707+
auto Op = make_unique<PPCOperand>(ContextImmediate);
708+
Op->Imm.Val = Val;
709+
Op->StartLoc = S;
710+
Op->EndLoc = E;
711+
Op->IsPPC64 = IsPPC64;
712+
return Op;
713+
}
714+
636715
static std::unique_ptr<PPCOperand>
637716
CreateFromMCExpr(const MCExpr *Val, SMLoc S, SMLoc E, bool IsPPC64) {
638717
if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val))
@@ -642,6 +721,12 @@ struct PPCOperand : public MCParsedAsmOperand {
642721
if (SRE->getKind() == MCSymbolRefExpr::VK_PPC_TLS)
643722
return CreateTLSReg(SRE, S, E, IsPPC64);
644723

724+
if (const PPCMCExpr *TE = dyn_cast<PPCMCExpr>(Val)) {
725+
int64_t Res;
726+
if (TE->EvaluateAsConstant(Res))
727+
return CreateContextImm(Res, S, E, IsPPC64);
728+
}
729+
645730
return CreateExpr(Val, S, E, IsPPC64);
646731
}
647732
};
@@ -654,6 +739,7 @@ void PPCOperand::print(raw_ostream &OS) const {
654739
OS << "'" << getToken() << "'";
655740
break;
656741
case Immediate:
742+
case ContextImmediate:
657743
OS << getImm();
658744
break;
659745
case Expression:

llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//
88
//===----------------------------------------------------------------------===//
99

10+
#include "PPCFixupKinds.h"
1011
#include "PPCMCExpr.h"
1112
#include "llvm/MC/MCAsmInfo.h"
1213
#include "llvm/MC/MCAssembler.h"
@@ -51,6 +52,43 @@ void PPCMCExpr::PrintImpl(raw_ostream &OS) const {
5152
}
5253
}
5354

55+
bool
56+
PPCMCExpr::EvaluateAsConstant(int64_t &Res) const {
57+
MCValue Value;
58+
59+
if (!getSubExpr()->EvaluateAsRelocatable(Value, nullptr, nullptr))
60+
return false;
61+
62+
if (!Value.isAbsolute())
63+
return false;
64+
65+
Res = EvaluateAsInt64(Value.getConstant());
66+
return true;
67+
}
68+
69+
int64_t
70+
PPCMCExpr::EvaluateAsInt64(int64_t Value) const {
71+
switch (Kind) {
72+
case VK_PPC_LO:
73+
return Value & 0xffff;
74+
case VK_PPC_HI:
75+
return (Value >> 16) & 0xffff;
76+
case VK_PPC_HA:
77+
return ((Value + 0x8000) >> 16) & 0xffff;
78+
case VK_PPC_HIGHER:
79+
return (Value >> 32) & 0xffff;
80+
case VK_PPC_HIGHERA:
81+
return ((Value + 0x8000) >> 32) & 0xffff;
82+
case VK_PPC_HIGHEST:
83+
return (Value >> 48) & 0xffff;
84+
case VK_PPC_HIGHESTA:
85+
return ((Value + 0x8000) >> 48) & 0xffff;
86+
case VK_PPC_None:
87+
break;
88+
}
89+
llvm_unreachable("Invalid kind!");
90+
}
91+
5492
bool
5593
PPCMCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
5694
const MCAsmLayout *Layout,
@@ -61,32 +99,10 @@ PPCMCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
6199
return false;
62100

63101
if (Value.isAbsolute()) {
64-
int64_t Result = Value.getConstant();
65-
switch (Kind) {
66-
default:
67-
llvm_unreachable("Invalid kind!");
68-
case VK_PPC_LO:
69-
Result = Result & 0xffff;
70-
break;
71-
case VK_PPC_HI:
72-
Result = (Result >> 16) & 0xffff;
73-
break;
74-
case VK_PPC_HA:
75-
Result = ((Result + 0x8000) >> 16) & 0xffff;
76-
break;
77-
case VK_PPC_HIGHER:
78-
Result = (Result >> 32) & 0xffff;
79-
break;
80-
case VK_PPC_HIGHERA:
81-
Result = ((Result + 0x8000) >> 32) & 0xffff;
82-
break;
83-
case VK_PPC_HIGHEST:
84-
Result = (Result >> 48) & 0xffff;
85-
break;
86-
case VK_PPC_HIGHESTA:
87-
Result = ((Result + 0x8000) >> 48) & 0xffff;
88-
break;
89-
}
102+
int64_t Result = EvaluateAsInt64(Value.getConstant());
103+
if ((Fixup == nullptr || (unsigned)Fixup->getKind() != PPC::fixup_ppc_half16) &&
104+
(Result >= 0x8000))
105+
return false;
90106
Res = MCValue::get(Result);
91107
} else {
92108
if (!Layout)

llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ class PPCMCExpr : public MCTargetExpr {
3434
const MCExpr *Expr;
3535
bool IsDarwin;
3636

37+
int64_t EvaluateAsInt64(int64_t Value) const;
38+
3739
explicit PPCMCExpr(VariantKind _Kind, const MCExpr *_Expr,
3840
bool _IsDarwin)
3941
: Kind(_Kind), Expr(_Expr), IsDarwin(_IsDarwin) {}
@@ -88,6 +90,8 @@ class PPCMCExpr : public MCTargetExpr {
8890
// There are no TLS PPCMCExprs at the moment.
8991
void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override {}
9092

93+
bool EvaluateAsConstant(int64_t &Res) const;
94+
9195
static bool classof(const MCExpr *E) {
9296
return E->getKind() == MCExpr::Target;
9397
}

llvm/lib/Target/PowerPC/PPCInstrInfo.td

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ def u6imm : Operand<i32> {
458458
}
459459
def PPCS16ImmAsmOperand : AsmOperandClass {
460460
let Name = "S16Imm"; let PredicateMethod = "isS16Imm";
461-
let RenderMethod = "addImmOperands";
461+
let RenderMethod = "addS16ImmOperands";
462462
}
463463
def s16imm : Operand<i32> {
464464
let PrintMethod = "printS16ImmOperand";
@@ -468,7 +468,7 @@ def s16imm : Operand<i32> {
468468
}
469469
def PPCU16ImmAsmOperand : AsmOperandClass {
470470
let Name = "U16Imm"; let PredicateMethod = "isU16Imm";
471-
let RenderMethod = "addImmOperands";
471+
let RenderMethod = "addU16ImmOperands";
472472
}
473473
def u16imm : Operand<i32> {
474474
let PrintMethod = "printU16ImmOperand";
@@ -478,7 +478,7 @@ def u16imm : Operand<i32> {
478478
}
479479
def PPCS17ImmAsmOperand : AsmOperandClass {
480480
let Name = "S17Imm"; let PredicateMethod = "isS17Imm";
481-
let RenderMethod = "addImmOperands";
481+
let RenderMethod = "addS16ImmOperands";
482482
}
483483
def s17imm : Operand<i32> {
484484
// This operand type is used for addis/lis to allow the assembler parser
@@ -554,7 +554,7 @@ def ptr_rc_idx : Operand<iPTR>, PointerLikeRegClass<0> {
554554

555555
def PPCDispRIOperand : AsmOperandClass {
556556
let Name = "DispRI"; let PredicateMethod = "isS16Imm";
557-
let RenderMethod = "addImmOperands";
557+
let RenderMethod = "addS16ImmOperands";
558558
}
559559
def dispRI : Operand<iPTR> {
560560
let ParserMatchClass = PPCDispRIOperand;

llvm/test/MC/PowerPC/ppc64-fixup-apply.s

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ subis 1, 1, target4-target3@ha
2727

2828
addi 1, 1, target5+0x8000@l
2929
addis 1, 1, target5+0x8000@ha
30+
ori 1, 1, target5+0x8000@l
31+
oris 1, 1, target5+0x8000@ha
3032

3133
.set target5, 0x10000001
3234

@@ -68,7 +70,7 @@ addis 1, 1, target7@highesta
6870
# CHECK-NEXT: ]
6971
# CHECK-NEXT: Address: 0x0
7072
# CHECK-NEXT: Offset:
71-
# CHECK-NEXT: Size: 64
73+
# CHECK-NEXT: Size: 72
7274
# CHECK-NEXT: Link: 0
7375
# CHECK-NEXT: Info: 0
7476
# CHECK-NEXT: AddressAlignment: 4
@@ -78,10 +80,12 @@ addis 1, 1, target7@highesta
7880
# CHECK-LE-NEXT: 0000: 34122138 3412213C 78562138 3412213C
7981
# CHECK-BE-NEXT: 0010: 38214444 3C211111 38218001 3C211001
8082
# CHECK-LE-NEXT: 0010: 44442138 1111213C 01802138 0110213C
81-
# CHECK-BE-NEXT: 0020: 38210008 3C210000 38214321 3C214321
82-
# CHECK-LE-NEXT: 0020: 08002138 0000213C 21432138 2143213C
83-
# CHECK-BE-NEXT: 0030: 3821FFFF 3C211234 38210000 3C211235
84-
# CHECK-LE-NEXT: 0030: FFFF2138 3412213C 00002138 3512213C
83+
# CHECK-BE-NEXT: 0020: 60218001 64211001 38210008 3C210000
84+
# CHECK-LE-NEXT: 0020: 01802160 01102164 08002138 0000213C
85+
# CHECK-BE-NEXT: 0030: 38214321 3C214321 3821FFFF 3C211234
86+
# CHECK-LE-NEXT: 0030: 21432138 2143213C FFFF2138 3412213C
87+
# CHECK-BE-NEXT: 0040: 38210000 3C211235
88+
# CHECK-LE-NEXT: 0040: 00002138 3512213C
8589
# CHECK-NEXT: )
8690
# CHECK-NEXT: }
8791

llvm/test/MC/PowerPC/ppc64-fixups.s

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,18 @@ base:
687687
# CHECK-BE: ori 1, 2, 2 # encoding: [0x60,0x41,0x00,0x02]
688688
# CHECK-LE: ori 1, 2, 2 # encoding: [0x02,0x00,0x41,0x60]
689689
ori 1, 2, 131071@ha
690+
# CHECK-BE: addi 1, 2, -1 # encoding: [0x38,0x22,0xff,0xff]
691+
# CHECK-LE: addi 1, 2, -1 # encoding: [0xff,0xff,0x22,0x38]
692+
addi 1, 2, 131071@l
693+
# CHECK-BE: addi 1, 2, 1 # encoding: [0x38,0x22,0x00,0x01]
694+
# CHECK-LE: addi 1, 2, 1 # encoding: [0x01,0x00,0x22,0x38]
695+
addi 1, 2, 131071@h
696+
# CHECK-BE: addi 1, 2, 2 # encoding: [0x38,0x22,0x00,0x02]
697+
# CHECK-LE: addi 1, 2, 2 # encoding: [0x02,0x00,0x22,0x38]
698+
addi 1, 2, 131071@ha
699+
# CHECK-BE: addis 1, 2, -4096 # encoding: [0x3c,0x22,0xf0,0x00]
700+
# CHECK-LE: addis 1, 2, -4096 # encoding: [0x00,0xf0,0x22,0x3c]
701+
addis 1, 2, 0xf0000000@h
690702

691703
# Data relocs
692704
# llvm-mc does not show any "encoding" string for data, so we just check the relocs

0 commit comments

Comments
 (0)