- Following these functions, we will add an implementation for the register names on M88k. Usually, the list of supported register names and their purposes can be found on the ABI of the specific platform of interest. Within this implementation, we’ll implement the main general-purpose registers from 0-31 and also create an array to store this information in. In terms of register aliases, note that there are no aliases for the registers that we implement currently:
const char *const M88kTargetInfo::GCCRegNames[] = {
“r0”, “r1”, “r2”, “r3”, “r4”, “r5”, “r6”, “r7”,
“r8”, “r9”, “r10”, “r11”, “r12”, “r13”, “r14”, “r15”,
“r16”, “r17”, “r18”, “r19”, “r20”, “r21”, “r22”, “r23”,
“r24”, “r25”, “r26”, “r27”, “r28”, “r29”, “r39”, “r31”};
ArrayRef M88kTargetInfo::getGCCRegNames() const {
return llvm::makeArrayRef(GCCRegNames);
}
ArrayRef M88kTargetInfo::getGCCRegAliases() const {
return std::nullopt; // No aliases.
}
- The last function we’ll implement is a function that validates the inline assembly constraints on our target. This function simply takes a character, which represents the inline assembly constraint, and handles the constraint accordingly. A few inline assembly register constraints are implemented, such as for the address, data, and floating-point registers, and a select few constraints for constants are also accounted for:
bool M88kTargetInfo::validateAsmConstraint(
const char &Name, TargetInfo::ConstraintInfo &info) const { switch (Name) {
case ‘a’: // address register
case ‘d’: // data register
case ‘f’: // floating point register
info.setAllowsRegister();
return true;
case ‘K’: // the constant 1
case ‘L’: // constant -1^20 .. 1^19
case ‘M’: // constant 1-4:
return true;
}
return false;
}
- We conclude the file by closing off the clang and targets namespaces that we initiated at the beginning of the file:
} // namespace targets
} // namespace clang
After completing the implementation for clang/lib/Basic/Targets/M88k.cpp, the following implementation of adding the M88k features group and valid CPU types within clang/include/clang/Driver/Options.td. is required.
Recall from earlier that we previously defined three valid CPU types for our M88k target: mc88000, mc88100, and mc88110. These CPU types also need to be defined in Options.td since this file is the central place that defines all options and flags that will be accepted by clang:
- First, we must add m_m88k_Features_Group, which represents a group of features that will be available to the M88k target:
def m_m88k_Features_Group: OptionGroup<“”>,
Group, DocName<“M88k”>;
- Next, we must define the three valid M88k CPU types as a feature in the M88k features group:
def m88000 : Flag<[“-“], “m88000”>, Group;
def m88100 : Flag<[“-“], “m88100”>, Group;
def m88110 : Flag<[“-“], “m88110”>, Group;
With that, we have implemented the driver integration portion for connecting the M88k target with clang.