32#define DEBUG_TYPE "hexagon-asm-backend"
35 (
"mno-fixup",
cl::desc(
"Disable fixing up resolved relocations for Hexagon"));
44 std::unique_ptr <MCInstrInfo> MCII;
45 std::unique_ptr <MCInst *> RelaxTarget;
47 unsigned MaxPacketSize;
61 HexagonAsmBackend(
const Target &
T,
const Triple &TT, uint8_t OSABI,
65 Extender(nullptr), MaxPacketSize(HexagonMCInstrInfo::
packetSize(CPU)) {}
67 std::unique_ptr<MCObjectTargetWriter>
68 createObjectTargetWriter()
const override {
72 void setExtender(MCContext &
Context)
const {
73 if (Extender ==
nullptr)
74 const_cast<HexagonAsmBackend *
>(
this)->Extender =
Context.createMCInst();
77 MCInst *takeExtender()
const {
78 assert(Extender !=
nullptr);
79 MCInst *
Result = Extender;
80 const_cast<HexagonAsmBackend *
>(
this)->Extender =
nullptr;
84 MCFixupKindInfo getFixupKindInfo(
MCFixupKind Kind)
const override {
91 {
"fixup_Hexagon_B22_PCREL", 0, 32, 0 },
92 {
"fixup_Hexagon_B15_PCREL", 0, 32, 0 },
93 {
"fixup_Hexagon_B7_PCREL", 0, 32, 0 },
94 {
"fixup_Hexagon_LO16", 0, 32, 0 },
95 {
"fixup_Hexagon_HI16", 0, 32, 0 },
96 {
"fixup_Hexagon_32", 0, 32, 0 },
97 {
"fixup_Hexagon_16", 0, 32, 0 },
98 {
"fixup_Hexagon_8", 0, 32, 0 },
99 {
"fixup_Hexagon_GPREL16_0", 0, 32, 0 },
100 {
"fixup_Hexagon_GPREL16_1", 0, 32, 0 },
101 {
"fixup_Hexagon_GPREL16_2", 0, 32, 0 },
102 {
"fixup_Hexagon_GPREL16_3", 0, 32, 0 },
103 {
"fixup_Hexagon_HL16", 0, 32, 0 },
104 {
"fixup_Hexagon_B13_PCREL", 0, 32, 0 },
105 {
"fixup_Hexagon_B9_PCREL", 0, 32, 0 },
106 {
"fixup_Hexagon_B32_PCREL_X", 0, 32, 0 },
107 {
"fixup_Hexagon_32_6_X", 0, 32, 0 },
108 {
"fixup_Hexagon_B22_PCREL_X", 0, 32, 0 },
109 {
"fixup_Hexagon_B15_PCREL_X", 0, 32, 0 },
110 {
"fixup_Hexagon_B13_PCREL_X", 0, 32, 0 },
111 {
"fixup_Hexagon_B9_PCREL_X", 0, 32, 0 },
112 {
"fixup_Hexagon_B7_PCREL_X", 0, 32, 0 },
113 {
"fixup_Hexagon_16_X", 0, 32, 0 },
114 {
"fixup_Hexagon_12_X", 0, 32, 0 },
115 {
"fixup_Hexagon_11_X", 0, 32, 0 },
116 {
"fixup_Hexagon_10_X", 0, 32, 0 },
117 {
"fixup_Hexagon_9_X", 0, 32, 0 },
118 {
"fixup_Hexagon_8_X", 0, 32, 0 },
119 {
"fixup_Hexagon_7_X", 0, 32, 0 },
120 {
"fixup_Hexagon_6_X", 0, 32, 0 },
121 {
"fixup_Hexagon_32_PCREL", 0, 32, 0 },
122 {
"fixup_Hexagon_COPY", 0, 32, 0 },
123 {
"fixup_Hexagon_GLOB_DAT", 0, 32, 0 },
124 {
"fixup_Hexagon_JMP_SLOT", 0, 32, 0 },
125 {
"fixup_Hexagon_RELATIVE", 0, 32, 0 },
126 {
"fixup_Hexagon_PLT_B22_PCREL", 0, 32, 0 },
127 {
"fixup_Hexagon_GOTREL_LO16", 0, 32, 0 },
128 {
"fixup_Hexagon_GOTREL_HI16", 0, 32, 0 },
129 {
"fixup_Hexagon_GOTREL_32", 0, 32, 0 },
130 {
"fixup_Hexagon_GOT_LO16", 0, 32, 0 },
131 {
"fixup_Hexagon_GOT_HI16", 0, 32, 0 },
132 {
"fixup_Hexagon_GOT_32", 0, 32, 0 },
133 {
"fixup_Hexagon_GOT_16", 0, 32, 0 },
134 {
"fixup_Hexagon_DTPMOD_32", 0, 32, 0 },
135 {
"fixup_Hexagon_DTPREL_LO16", 0, 32, 0 },
136 {
"fixup_Hexagon_DTPREL_HI16", 0, 32, 0 },
137 {
"fixup_Hexagon_DTPREL_32", 0, 32, 0 },
138 {
"fixup_Hexagon_DTPREL_16", 0, 32, 0 },
139 {
"fixup_Hexagon_GD_PLT_B22_PCREL",0, 32, 0 },
140 {
"fixup_Hexagon_LD_PLT_B22_PCREL",0, 32, 0 },
141 {
"fixup_Hexagon_GD_GOT_LO16", 0, 32, 0 },
142 {
"fixup_Hexagon_GD_GOT_HI16", 0, 32, 0 },
143 {
"fixup_Hexagon_GD_GOT_32", 0, 32, 0 },
144 {
"fixup_Hexagon_GD_GOT_16", 0, 32, 0 },
145 {
"fixup_Hexagon_LD_GOT_LO16", 0, 32, 0 },
146 {
"fixup_Hexagon_LD_GOT_HI16", 0, 32, 0 },
147 {
"fixup_Hexagon_LD_GOT_32", 0, 32, 0 },
148 {
"fixup_Hexagon_LD_GOT_16", 0, 32, 0 },
149 {
"fixup_Hexagon_IE_LO16", 0, 32, 0 },
150 {
"fixup_Hexagon_IE_HI16", 0, 32, 0 },
151 {
"fixup_Hexagon_IE_32", 0, 32, 0 },
152 {
"fixup_Hexagon_IE_16", 0, 32, 0 },
153 {
"fixup_Hexagon_IE_GOT_LO16", 0, 32, 0 },
154 {
"fixup_Hexagon_IE_GOT_HI16", 0, 32, 0 },
155 {
"fixup_Hexagon_IE_GOT_32", 0, 32, 0 },
156 {
"fixup_Hexagon_IE_GOT_16", 0, 32, 0 },
157 {
"fixup_Hexagon_TPREL_LO16", 0, 32, 0 },
158 {
"fixup_Hexagon_TPREL_HI16", 0, 32, 0 },
159 {
"fixup_Hexagon_TPREL_32", 0, 32, 0 },
160 {
"fixup_Hexagon_TPREL_16", 0, 32, 0 },
161 {
"fixup_Hexagon_6_PCREL_X", 0, 32, 0 },
162 {
"fixup_Hexagon_GOTREL_32_6_X", 0, 32, 0 },
163 {
"fixup_Hexagon_GOTREL_16_X", 0, 32, 0 },
164 {
"fixup_Hexagon_GOTREL_11_X", 0, 32, 0 },
165 {
"fixup_Hexagon_GOT_32_6_X", 0, 32, 0 },
166 {
"fixup_Hexagon_GOT_16_X", 0, 32, 0 },
167 {
"fixup_Hexagon_GOT_11_X", 0, 32, 0 },
168 {
"fixup_Hexagon_DTPREL_32_6_X", 0, 32, 0 },
169 {
"fixup_Hexagon_DTPREL_16_X", 0, 32, 0 },
170 {
"fixup_Hexagon_DTPREL_11_X", 0, 32, 0 },
171 {
"fixup_Hexagon_GD_GOT_32_6_X", 0, 32, 0 },
172 {
"fixup_Hexagon_GD_GOT_16_X", 0, 32, 0 },
173 {
"fixup_Hexagon_GD_GOT_11_X", 0, 32, 0 },
174 {
"fixup_Hexagon_LD_GOT_32_6_X", 0, 32, 0 },
175 {
"fixup_Hexagon_LD_GOT_16_X", 0, 32, 0 },
176 {
"fixup_Hexagon_LD_GOT_11_X", 0, 32, 0 },
177 {
"fixup_Hexagon_IE_32_6_X", 0, 32, 0 },
178 {
"fixup_Hexagon_IE_16_X", 0, 32, 0 },
179 {
"fixup_Hexagon_IE_GOT_32_6_X", 0, 32, 0 },
180 {
"fixup_Hexagon_IE_GOT_16_X", 0, 32, 0 },
181 {
"fixup_Hexagon_IE_GOT_11_X", 0, 32, 0 },
182 {
"fixup_Hexagon_TPREL_32_6_X", 0, 32, 0 },
183 {
"fixup_Hexagon_TPREL_16_X", 0, 32, 0 },
184 {
"fixup_Hexagon_TPREL_11_X", 0, 32, 0 },
185 {
"fixup_Hexagon_GD_PLT_B22_PCREL_X", 0, 32, 0 },
186 {
"fixup_Hexagon_GD_PLT_B32_PCREL_X", 0, 32, 0 },
187 {
"fixup_Hexagon_LD_PLT_B22_PCREL_X", 0, 32, 0 },
188 {
"fixup_Hexagon_LD_PLT_B32_PCREL_X", 0, 32, 0 },
202 switch(
Fixup.getKind()) {
356 switch((
unsigned)Kind) {
385 void HandleFixupError(
const int bits,
const int align_bits,
386 const int64_t FixupValue,
const char *fixupStr)
const {
391 std::stringstream errStr;
392 errStr <<
"\nError: value " <<
398 " when resolving " <<
404 void applyFixup(
const MCFragment &,
const MCFixup &,
const MCValue &,
405 uint8_t *
Data, uint64_t FixupValue,
bool IsResolved)
override;
407 bool isInstRelaxable(MCInst
const &HMI)
const {
409 bool Relaxable =
false;
420 MCOperand
const &Operand =
430 const MCSubtargetInfo &STI)
const override {
432 RelaxedMCB.setOpcode(Opcode);
439 bool fixupNeedsRelaxationAdvanced(
const MCFragment &
F,
const MCFixup &
Fixup,
440 const MCValue &, uint64_t
Value,
441 bool Resolved)
const override {
442 MCInst
const &MCB = RelaxedMCB;
445 *RelaxTarget =
nullptr;
448 bool Relaxable = isInstRelaxable(MCI);
449 if (Relaxable ==
false)
453 switch (
Fixup.getKind()) {
478 int64_t sValue =
Value;
481 switch ((
unsigned)Kind) {
499 bool isFarAway = -maxValue > sValue || sValue > maxValue - 1;
513 void relaxInstruction(MCInst &Inst,
514 const MCSubtargetInfo &STI)
const override {
516 "Hexagon relaxInstruction only works on bundles");
524 MCInst &CrntHMI =
const_cast<MCInst &
>(*
I.getInst());
527 if (*RelaxTarget == &CrntHMI) {
530 "No room to insert extender for relaxation");
532 MCInst *HMIx = takeExtender();
537 *RelaxTarget =
nullptr;
543 Inst = std::move(Res);
545 assert(Update &&
"Didn't find relaxation target");
548 bool writeNopData(raw_ostream &OS, uint64_t
Count,
549 const MCSubtargetInfo *STI)
const override {
550 static const uint32_t Nopcode = 0x7f000000,
551 ParseIn = 0x00004000,
552 ParseEnd = 0x0000c000;
555 LLVM_DEBUG(
dbgs() <<
"Alignment not a multiple of the instruction size:"
572 bool finishLayout(
const MCAssembler &Asm)
const override {
574 for (MCSection &Sec : Asm) {
576 for (MCFragment &
F : Sec)
578 for (
size_t J = 0,
E = Frags.
size(); J !=
E; ++J) {
579 switch (Frags[J]->getKind()) {
583 auto Size =
Asm.computeFragmentSize(*Frags[J]);
586 switch (Frags[K]->getKind()) {
596 auto &RF = *Frags[
K];
600 Asm.symbols(), [&Asm, &RF, &Inst](MCSymbol
const &sym) {
602 const bool HasOffset = Asm.getSymbolOffset(sym, Offset);
603 const unsigned PacketSizeBytes =
604 HexagonMCInstrInfo::bundleSize(Inst) *
606 const bool OffsetPastSym =
607 Offset <= (Asm.getFragmentOffset(RF) + PacketSizeBytes);
608 return !sym.isVariable() && Offset != 0 && HasOffset &&
611 if (WouldTraverseLabel) {
618 MCInst *Nop =
Context.createMCInst();
622 if (!HexagonMCChecker(
624 *
Context.getRegisterInfo(),
false)
634 ReplaceInstruction(
Asm.getEmitter(), RF, Inst);
652 uint64_t FixupValue,
bool IsResolved) {
655 maybeAddReloc(
F,
Fixup, Target, FixupValue, IsResolved);
670 "Invalid fixup offset!");
675 int sValue = (int)
Value;
677 switch ((
unsigned)Kind) {
683 HandleFixupError(7, 2, (int64_t)FixupValue,
"B7_PCREL");
686 InstMask = 0x00001f18;
687 Reloc = (((
Value >> 2) & 0x1f) << 8) |
688 ((
Value & 0x3) << 3);
693 HandleFixupError(9, 2, (int64_t)FixupValue,
"B9_PCREL");
696 InstMask = 0x003000fe;
697 Reloc = (((
Value >> 7) & 0x3) << 20) |
698 ((
Value & 0x7f) << 1);
704 if (!(
isIntN(13, sValue)))
705 HandleFixupError(13, 2, (int64_t)FixupValue,
"B13_PCREL");
708 InstMask = 0x00202ffe;
709 Reloc = (((
Value >> 12) & 0x1) << 21) |
710 (((
Value >> 11) & 0x1) << 13) |
711 ((
Value & 0x7ff) << 1);
715 if (!(
isIntN(15, sValue)))
716 HandleFixupError(15, 2, (int64_t)FixupValue,
"B15_PCREL");
719 InstMask = 0x00df20fe;
720 Reloc = (((
Value >> 13) & 0x3) << 22) |
721 (((
Value >> 8) & 0x1f) << 16) |
722 (((
Value >> 7) & 0x1) << 13) |
723 ((
Value & 0x7f) << 1);
727 if (!(
isIntN(22, sValue)))
728 HandleFixupError(22, 2, (int64_t)FixupValue,
"B22_PCREL");
731 InstMask = 0x01ff3ffe;
732 Reloc = (((
Value >> 13) & 0x1ff) << 16) |
733 ((
Value & 0x1fff) << 1);
737 InstMask = 0x0fff3fff;
738 Reloc = (((
Value >> 14) & 0xfff) << 16) |
746 InstMask = 0xffffffff;
751 LLVM_DEBUG(
dbgs() <<
"Name=" << getFixupKindInfo(Kind).Name <<
"("
752 << (
unsigned)Kind <<
")\n");
754 uint32_t OldData = 0;
for (
unsigned i = 0; i < NumBytes; i++) OldData |=
755 (InstAddr[i] << (i * 8)) & (0xff << (i * 8));
758 <<
": Size=" <<
F.getSize() <<
": OInst=0x";
764 for (
unsigned i = 0; i < NumBytes; i++) {
765 InstAddr[i] &= uint8_t(~InstMask >> (i * 8)) & 0xff;
766 InstAddr[i] |= uint8_t(Reloc >> (i * 8)) & 0xff;
770 for (
unsigned i = 0; i < NumBytes; i++) NewData |=
771 (InstAddr[i] << (i * 8)) & (0xff << (i * 8));
784 return new HexagonAsmBackend(
T, TT, OSABI, CPUString);
static unsigned getFixupKindNumBytes(unsigned Kind)
The number of bytes the fixup may change.
static uint64_t adjustFixupValue(const MCFixup &Fixup, const MCValue &Target, uint64_t Value, MCContext &Ctx, const Triple &TheTriple, bool IsResolved)
static bool shouldForceRelocation(const MCFixup &Fixup)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static cl::opt< bool > DisableFixup("mno-fixup", cl::desc("Disable fixing up resolved relocations for Hexagon"))
Definition for classes that emit Hexagon machine code from MCInsts.
#define HEXAGON_INSTR_SIZE
#define HEXAGON_PACKET_SIZE
mir Rename Register Operands
PowerPC TLS Dynamic Call Fixup
static MCInstrInfo * createMCInstrInfo()
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
int64_t getSExtValue() const
Get sign extended value.
Generic interface to target specific assembler backends.
virtual MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const
Get information on a fixup kind.
MCCodeEmitter - Generic instruction encoding interface.
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
LLVM_ABI void setVarFixups(ArrayRef< MCFixup > Fixups)
LLVM_ABI void setVarContents(ArrayRef< char > Contents)
const MCSubtargetInfo * getSubtargetInfo() const
Retrieve the MCSubTargetInfo in effect when the instruction was encoded.
void setInst(const MCInst &Inst)
Instances of this class represent a single low-level machine instruction.
unsigned getOpcode() const
void addOperand(const MCOperand Op)
void setOpcode(unsigned Op)
const MCOperand & getOperand(unsigned i) const
bool isBranch() const
Returns true if this is a conditional, unconditional, or indirect branch.
static MCOperand createImm(int64_t Val)
const MCExpr * getExpr() const
static MCOperand createInst(const MCInst *Val)
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Generic base class for all target subtargets.
const Triple & getTargetTriple() const
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
raw_ostream & write_hex(unsigned long long N)
Output N in hexadecimal, without any prefix or padding.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
size_t bundleSize(MCInst const &MCI)
unsigned short getExtendableOp(MCInstrInfo const &MCII, MCInst const &MCI)
bool mustNotExtend(MCExpr const &Expr)
MCInstrDesc const & getDesc(MCInstrInfo const &MCII, MCInst const &MCI)
iterator_range< Hexagon::PacketIterator > bundleInstructions(MCInstrInfo const &MCII, MCInst const &MCI)
bool isBundle(MCInst const &MCI)
bool isExtendable(MCInstrInfo const &MCII, MCInst const &MCI)
unsigned getType(MCInstrInfo const &MCII, MCInst const &MCI)
Return the Hexagon ISA class for the insn.
MCInst const & instruction(MCInst const &MCB, size_t Index)
MCOperand const & getExtendableOperand(MCInstrInfo const &MCII, MCInst const &MCI)
unsigned packetSize(StringRef CPU)
MCInst deriveExtender(MCInstrInfo const &MCII, MCInst const &Inst, MCOperand const &MO)
StringRef selectHexagonCPU(StringRef CPU)
@ fixup_Hexagon_LD_PLT_B32_PCREL_X
@ fixup_Hexagon_GPREL16_3
@ fixup_Hexagon_GD_GOT_HI16
@ fixup_Hexagon_IE_GOT_16_X
@ fixup_Hexagon_LD_PLT_B22_PCREL
@ fixup_Hexagon_TPREL_32_6_X
@ fixup_Hexagon_TPREL_16_X
@ fixup_Hexagon_B7_PCREL_X
@ fixup_Hexagon_B13_PCREL
@ fixup_Hexagon_DTPREL_HI16
@ fixup_Hexagon_DTPMOD_32
@ fixup_Hexagon_IE_GOT_LO16
@ fixup_Hexagon_LD_PLT_B22_PCREL_X
@ fixup_Hexagon_GD_GOT_32_6_X
@ fixup_Hexagon_LD_GOT_HI16
@ fixup_Hexagon_B13_PCREL_X
@ fixup_Hexagon_GOTREL_HI16
@ fixup_Hexagon_IE_GOT_32_6_X
@ fixup_Hexagon_GD_GOT_16
@ fixup_Hexagon_PLT_B22_PCREL
@ fixup_Hexagon_B32_PCREL_X
@ fixup_Hexagon_GD_GOT_16_X
@ fixup_Hexagon_GD_GOT_11_X
@ fixup_Hexagon_DTPREL_32_6_X
@ fixup_Hexagon_GD_GOT_LO16
@ fixup_Hexagon_GD_PLT_B32_PCREL_X
@ fixup_Hexagon_DTPREL_16
@ fixup_Hexagon_DTPREL_11_X
@ fixup_Hexagon_GPREL16_2
@ fixup_Hexagon_GPREL16_1
@ fixup_Hexagon_DTPREL_32
@ fixup_Hexagon_GOTREL_32
@ fixup_Hexagon_DTPREL_LO16
@ fixup_Hexagon_LD_GOT_16_X
@ fixup_Hexagon_B15_PCREL
@ fixup_Hexagon_LD_GOT_16
@ fixup_Hexagon_GPREL16_0
@ fixup_Hexagon_6_PCREL_X
@ fixup_Hexagon_GD_GOT_32
@ fixup_Hexagon_GD_PLT_B22_PCREL_X
@ fixup_Hexagon_GD_PLT_B22_PCREL
@ fixup_Hexagon_IE_GOT_32
@ fixup_Hexagon_B22_PCREL
@ fixup_Hexagon_TPREL_LO16
@ fixup_Hexagon_TPREL_HI16
@ fixup_Hexagon_LD_GOT_32_6_X
@ fixup_Hexagon_IE_GOT_16
@ fixup_Hexagon_LD_GOT_LO16
@ fixup_Hexagon_TPREL_11_X
@ fixup_Hexagon_GOTREL_LO16
@ fixup_Hexagon_IE_GOT_HI16
@ fixup_Hexagon_GOT_32_6_X
@ fixup_Hexagon_LD_GOT_11_X
@ fixup_Hexagon_GOTREL_11_X
@ fixup_Hexagon_DTPREL_16_X
@ fixup_Hexagon_B15_PCREL_X
@ fixup_Hexagon_B22_PCREL_X
@ fixup_Hexagon_IE_32_6_X
@ fixup_Hexagon_IE_GOT_11_X
@ fixup_Hexagon_LD_GOT_32
@ fixup_Hexagon_GOTREL_32_6_X
@ fixup_Hexagon_B9_PCREL_X
@ fixup_Hexagon_GOTREL_16_X
Error applyFixup(LinkGraph &G, Block &B, const Edge &E, const ArmConfig &ArmCfg)
Apply fixup expression for edge to block content.
Context & getContext() const
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
bool HexagonMCShuffle(MCContext &Context, bool ReportErrors, MCInstrInfo const &MCII, MCSubtargetInfo const &STI, MCInst &MCB)
std::unique_ptr< MCObjectTargetWriter > createHexagonELFObjectWriter(uint8_t OSABI, StringRef CPU)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
uint16_t MCFixupKind
Extensible enumeration to represent the type of a fixup.
MCAsmBackend * createHexagonAsmBackend(const Target &T, const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionAddr VTableAddr Count
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
@ FK_Data_1
A one-byte fixup.
@ FK_Data_4
A four-byte fixup.
@ FK_Data_2
A two-byte fixup.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.