Add macros to check for CPU type and supported instruction set.

This commit is contained in:
Kugel Fuhr
2025-06-12 14:42:38 +02:00
parent ccdc5b9fea
commit ace81bd36a
2 changed files with 172 additions and 2 deletions

View File

@@ -1154,6 +1154,96 @@ The compiler defines several macros at startup:
<item><tt/__CC65_STD_CC65__/
</itemize>
<label id="macro-CPU">
<tag><tt>__CPU__</tt></tag>
This macro contains a bitset that allows to check if a specific instruction
set is supported. For example, the 65C02 CPU supports all instructions of the
65SC02. So testing for the instruction set of the 65SC02 using the following
check will succeed for both CPUs (and also for the 65816 and HUC6280).
<tscreen><verb>
#if (__CPU__ & __CPU_ISET_65SC02__)
</verb></tscreen>
This is much simpler and more future proof than checking for specific CPUs.
The compiler defines a set of constants named <tt/__CPU_ISET_xxx/ to do the
checks. The <tt/__CPU__/ variable is usually derived from the target system
given, but can be changed using the <tt/<ref id="option--cpu" name="--cpu">/
command line option.
<tag><tt>__CPU_6502__</tt></tag>
This macro is defined if the code is compiled for a 6502 CPU.
<tag><tt>__CPU_6502X__</tt></tag>
This macro is defined if the code is compiled for a 6502 CPU with invalid
opcodes.
<tag><tt>__CPU_6502DTV__</tt></tag>
This macro is defined if the code is compiled for a DTV CPU.
<tag><tt>__CPU_65SC02__</tt></tag>
This macro is defined if the code is compiled for a 65SC02 CPU.
<tag><tt>__CPU_65C02__</tt></tag>
This macro is defined if the code is compiled for a 65C02 CPU.
<tag><tt>__CPU_65816__</tt></tag>
This macro is defined if the code is compiled for a 65816 CPU.
<tag><tt>__CPU_HUC6280__</tt></tag>
This macro is defined if the code is compiled for a HUC6280 CPU.
<tag><tt>__CPU_ISET_6502__</tt></tag>
This macro expands to a numeric constant that can be used to check the
<tt/<ref id="macro-CPU" name="__CPU__">/ macro for the instruction set
of the 6502 CPU.
<tag><tt>__CPU_ISET_6502X__</tt></tag>
This macro expands to a numeric constant that can be used to check the
<tt/<ref id="macro-CPU" name="__CPU__">/ macro for the instruction set
of the 6502X CPU.
<tag><tt>__CPU_ISET_6502DTV__</tt></tag>
This macro expands to a numeric constant that can be used to check the
<tt/<ref id="macro-CPU" name="__CPU__">/ macro for the instruction set
of the 6502DTV CPU.
<tag><tt>__CPU_ISET_65SC02__</tt></tag>
This macro expands to a numeric constant that can be used to check the
<tt/<ref id="macro-CPU" name="__CPU__">/ macro for the instruction set
of the 65SC02 CPU.
<tag><tt>__CPU_ISET_65C02__</tt></tag>
This macro expands to a numeric constant that can be used to check the
<tt/<ref id="macro-CPU" name="__CPU__">/ macro for the instruction set
of the 65C02 CPU.
<tag><tt>__CPU_ISET_65816__</tt></tag>
This macro expands to a numeric constant that can be used to check the
<tt/<ref id="macro-CPU" name="__CPU__">/ macro for the instruction set
of the 65816 CPU.
<tag><tt>__CPU_ISET_HUC6280__</tt></tag>
This macro expands to a numeric constant that can be used to check the
<tt/<ref id="macro-CPU" name="__CPU__">/ macro for the instruction set
of the HUC6280 CPU.
<tag><tt>__CX16__</tt></tag>
This macro is defined if the target is the Commander X16 (-t cx16).

View File

@@ -317,6 +317,81 @@ static void SetSys (const char* Sys)
static void DefineCpuMacros (void)
/* Define macros for the target CPU */
{
const char* CPUName;
/* Note: The list of CPUs handled here must match the one checked in
** OptCPU().
*/
switch (CPU) {
/* The following ones are legal CPUs as far as the assembler is
** concerned but are ruled out earlier in the compiler, so this
** function should never see them.
*/
case CPU_NONE:
case CPU_SWEET16:
case CPU_M740:
case CPU_4510:
case CPU_UNKNOWN:
CPUName = (CPU == CPU_UNKNOWN)? "unknown" : CPUNames[CPU];
Internal ("Invalid CPU \"%s\"", CPUName);
break;
case CPU_6502:
DefineNumericMacro ("__CPU_6502__", 1);
break;
case CPU_6502X:
DefineNumericMacro ("__CPU_6502X__", 1);
break;
case CPU_6502DTV:
DefineNumericMacro ("__CPU_6502DTV__", 1);
break;
case CPU_65SC02:
DefineNumericMacro ("__CPU_65SC02__", 1);
break;
case CPU_65C02:
DefineNumericMacro ("__CPU_65C02__", 1);
break;
case CPU_65816:
DefineNumericMacro ("__CPU_65816__", 1);
break;
case CPU_HUC6280:
DefineNumericMacro ("__CPU_HUC6280__", 1);
break;
default:
FAIL ("Unexpected value in switch");
break;
}
/* Define the macros for instruction sets. We only include the ones for
** the available CPUs.
*/
DefineNumericMacro ("__CPU_ISET_6502__", CPU_ISET_6502);
DefineNumericMacro ("__CPU_ISET_6502X__", CPU_ISET_6502X);
DefineNumericMacro ("__CPU_ISET_6502DTV__", CPU_ISET_6502DTV);
DefineNumericMacro ("__CPU_ISET_65SC02__", CPU_ISET_65SC02);
DefineNumericMacro ("__CPU_ISET_65C02__", CPU_ISET_65C02);
DefineNumericMacro ("__CPU_ISET_65816__", CPU_ISET_65816);
DefineNumericMacro ("__CPU_ISET_HUC6280__", CPU_ISET_HUC6280);
/* Now define the macro that contains the bit set with the available
** cpu instructions.
*/
DefineNumericMacro ("__CPU__", CPUIsets[CPU]);
}
static void FileNameOption (const char* Opt, const char* Arg, StrBuf* Name)
/* Handle an option that remembers a file name for later */
{
@@ -477,7 +552,9 @@ static void OptCreateFullDep (const char* Opt attribute ((unused)),
static void OptCPU (const char* Opt, const char* Arg)
/* Handle the --cpu option */
{
/* Find the CPU from the given name */
/* Find the CPU from the given name. We do only accept a certain number
** of CPUs. If the list is changed, be sure to adjust SetCpuMacros().
*/
CPU = FindCPU (Arg);
if (CPU != CPU_6502 && CPU != CPU_6502X && CPU != CPU_65SC02 &&
CPU != CPU_65C02 && CPU != CPU_65816 && CPU != CPU_HUC6280 &&
@@ -1063,7 +1140,9 @@ int main (int argc, char* argv[])
/* Create the output file name if it was not explicitly given */
MakeDefaultOutputName (InputFile);
/* If no CPU given, use the default CPU for the target */
/* If no CPU given, use the default CPU for the target. Define macros that
** allow to query the CPU.
*/
if (CPU == CPU_UNKNOWN) {
if (Target != TGT_UNKNOWN) {
CPU = GetTargetProperties (Target)->DefaultCPU;
@@ -1071,6 +1150,7 @@ int main (int argc, char* argv[])
CPU = CPU_6502;
}
}
DefineCpuMacros ();
/* If no memory model was given, use the default */
if (MemoryModel == MMODEL_UNKNOWN) {