Add a new .cap pseudo function to the assembler that allows to check for
certain capabilities of the CPU or target system.
This commit is contained in:
90
src/common/capability.c
Normal file
90
src/common/capability.c
Normal file
@@ -0,0 +1,90 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* capability.c */
|
||||
/* */
|
||||
/* Handle CPU or target capabilities */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2026, Kugelfuhr */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* ca65 */
|
||||
#include "capability.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* List of dot keywords with the corresponding ids. */
|
||||
/* CAUTION: table must be sorted for bsearch. */
|
||||
struct Capability {
|
||||
const char* Key;
|
||||
capability_t Cap;
|
||||
} Capabilities [] = {
|
||||
/* BEGIN SORTED.SH */
|
||||
{ "CPU_HAS_BRA8", CAP_CPU_HAS_BRA8 },
|
||||
{ "CPU_HAS_INA", CAP_CPU_HAS_INA },
|
||||
{ "CPU_HAS_PUSHXY", CAP_CPU_HAS_PUSHXY },
|
||||
{ "CPU_HAS_STZ", CAP_CPU_HAS_STZ },
|
||||
{ "CPU_HAS_ZPIND", CAP_CPU_HAS_ZPIND },
|
||||
/* END SORTED.SH */
|
||||
};
|
||||
#define CAP_TABLE_SIZE (sizeof (Capabilities) / sizeof (Capabilities [0]))
|
||||
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static int CmpCapability (const void* K1, const void* K2)
|
||||
/* Compare function for the capability search */
|
||||
{
|
||||
return strcmp (((struct Capability*)K1)->Key, ((struct Capability*)K2)->Key);
|
||||
}
|
||||
|
||||
|
||||
|
||||
capability_t FindCapability (const char* Name)
|
||||
/* Find the capability with the given name. Returns CAP_INVALID if there is no
|
||||
** capability with the given name and a capability code >= 0 instead. The
|
||||
** capability name is expected in upper case.
|
||||
*/
|
||||
{
|
||||
const struct Capability K = { Name, 0 };
|
||||
const struct Capability* C = bsearch (&K, Capabilities, CAP_TABLE_SIZE,
|
||||
sizeof (Capabilities [0]),
|
||||
CmpCapability);
|
||||
return (C == 0)? CAP_INVALID : C->Cap;
|
||||
}
|
||||
78
src/common/capability.h
Normal file
78
src/common/capability.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* capability.h */
|
||||
/* */
|
||||
/* Handle CPU or target capabilities */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2026, Kugelfuhr */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef CAPABILITY_H
|
||||
#define CAPABILITY_H
|
||||
|
||||
|
||||
|
||||
/* common */
|
||||
#include "strbuf.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Numeric codes for capabilities */
|
||||
enum capability_t {
|
||||
CAP_INVALID = -1,
|
||||
CAP_CPU_HAS_BRA8 = 0, /* CPU has a BRA 8-bit instruction */
|
||||
CAP_CPU_HAS_INA = 1, /* CPU has DEA/INA */
|
||||
CAP_CPU_HAS_PUSHXY = 2, /* CPU has PHX/PHY/PLX/PLY */
|
||||
CAP_CPU_HAS_ZPIND = 3, /* CPU has "(zp)" mode (no offset) */
|
||||
CAP_CPU_HAS_STZ = 4, /* CPU has "store zero" (!) instruction */
|
||||
};
|
||||
typedef enum capability_t capability_t;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
capability_t FindCapability (const char* Name);
|
||||
/* Find the capability with the given name. Returns CAP_INVALID if there is no
|
||||
** capability with the given name and a capability code >= 0 instead. The
|
||||
** capability name is expected in upper case.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* End of capability.h */
|
||||
|
||||
#endif
|
||||
@@ -33,6 +33,8 @@
|
||||
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* common */
|
||||
#include "addrsize.h"
|
||||
#include "check.h"
|
||||
@@ -90,6 +92,77 @@ const unsigned CPUIsets[CPU_COUNT] = {
|
||||
CPU_ISET_65CE02 | CPU_ISET_6502 | CPU_ISET_65C02,
|
||||
};
|
||||
|
||||
/* Defines for capabilities. Currently the entries are uint32_ts but the table
|
||||
** is deliberately hidden from the outside so it can be extended to 64 bit or
|
||||
** even more.
|
||||
*/
|
||||
#define CAP_NONE UINT32_C (0)
|
||||
#define CAP_6502 UINT32_C (0)
|
||||
#define CAP_6502X UINT32_C (0)
|
||||
#define CAP_6502DTV UINT32_C (0)
|
||||
#define CAP_65SC02 \
|
||||
((UINT32_C (1) << CAP_CPU_HAS_BRA8) | \
|
||||
(UINT32_C (1) << CAP_CPU_HAS_INA) | \
|
||||
(UINT32_C (1) << CAP_CPU_HAS_PUSHXY) | \
|
||||
(UINT32_C (1) << CAP_CPU_HAS_ZPIND) | \
|
||||
(UINT32_C (1) << CAP_CPU_HAS_STZ))
|
||||
#define CAP_65C02 \
|
||||
((UINT32_C (1) << CAP_CPU_HAS_BRA8) | \
|
||||
(UINT32_C (1) << CAP_CPU_HAS_INA) | \
|
||||
(UINT32_C (1) << CAP_CPU_HAS_PUSHXY) | \
|
||||
(UINT32_C (1) << CAP_CPU_HAS_ZPIND) | \
|
||||
(UINT32_C (1) << CAP_CPU_HAS_STZ))
|
||||
#define CAP_65816 \
|
||||
((UINT32_C (1) << CAP_CPU_HAS_BRA8) | \
|
||||
(UINT32_C (1) << CAP_CPU_HAS_INA) | \
|
||||
(UINT32_C (1) << CAP_CPU_HAS_PUSHXY) | \
|
||||
(UINT32_C (1) << CAP_CPU_HAS_ZPIND) | \
|
||||
(UINT32_C (1) << CAP_CPU_HAS_STZ))
|
||||
#define CAP_SWEET16 UINT32_C (0)
|
||||
#define CAP_HUC6280 \
|
||||
((UINT32_C (1) << CAP_CPU_HAS_BRA8) | \
|
||||
(UINT32_C (1) << CAP_CPU_HAS_INA) | \
|
||||
(UINT32_C (1) << CAP_CPU_HAS_PUSHXY) | \
|
||||
(UINT32_C (1) << CAP_CPU_HAS_ZPIND) | \
|
||||
(UINT32_C (1) << CAP_CPU_HAS_STZ))
|
||||
#define CAP_M740 \
|
||||
((UINT32_C (1) << CAP_CPU_HAS_BRA8) | \
|
||||
(UINT32_C (1) << CAP_CPU_HAS_INA))
|
||||
#define CAP_4510 \
|
||||
((UINT32_C (1) << CAP_CPU_HAS_BRA8) | \
|
||||
(UINT32_C (1) << CAP_CPU_HAS_INA) | \
|
||||
(UINT32_C (1) << CAP_CPU_HAS_PUSHXY))
|
||||
#define CAP_45GS02 \
|
||||
((UINT32_C (1) << CAP_CPU_HAS_BRA8) | \
|
||||
(UINT32_C (1) << CAP_CPU_HAS_INA) | \
|
||||
(UINT32_C (1) << CAP_CPU_HAS_PUSHXY))
|
||||
#define CAP_W65C02 \
|
||||
((UINT32_C (1) << CAP_CPU_HAS_BRA8) | \
|
||||
(UINT32_C (1) << CAP_CPU_HAS_INA) | \
|
||||
(UINT32_C (1) << CAP_CPU_HAS_PUSHXY))
|
||||
#define CAP_65CE02 \
|
||||
((UINT32_C (1) << CAP_CPU_HAS_BRA8) | \
|
||||
(UINT32_C (1) << CAP_CPU_HAS_INA) | \
|
||||
(UINT32_C (1) << CAP_CPU_HAS_PUSHXY))
|
||||
|
||||
/* Table containing one capability entry per CPU */
|
||||
static const uint64_t CPUCaps[CPU_COUNT] = {
|
||||
CAP_NONE, /* CPU_NONE */
|
||||
CAP_6502, /* CPU_6502 */
|
||||
CAP_6502X, /* CPU_6502X */
|
||||
CAP_6502DTV, /* CPU_6502DTV */
|
||||
CAP_65SC02, /* CPU_65SC02 */
|
||||
CAP_65C02, /* CPU_65C02 */
|
||||
CAP_65816, /* CPU_65816 */
|
||||
CAP_SWEET16, /* CPU_SWEET16 */
|
||||
CAP_HUC6280, /* CPU_HUC6280 */
|
||||
CAP_M740, /* CPU_M740 */
|
||||
CAP_4510, /* CPU_4510 */
|
||||
CAP_45GS02, /* CPU_45GS02 */
|
||||
CAP_W65C02, /* CPU_W65C02 */
|
||||
CAP_65CE02, /* CPU_65CE02 */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -148,3 +221,12 @@ cpu_t FindCPU (const char* Name)
|
||||
/* Not found */
|
||||
return CPU_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int CPUHasCap (capability_t Cap)
|
||||
/* Check if the current CPU has the given capability */
|
||||
{
|
||||
PRECONDITION (CPU >= 0 && CPU < CPU_COUNT);
|
||||
return (CPUCaps[CPU] & (UINT32_C (1) << Cap)) != 0;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,11 @@
|
||||
|
||||
|
||||
|
||||
/* common */
|
||||
#include "capability.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
@@ -107,6 +112,9 @@ cpu_t FindCPU (const char* Name);
|
||||
** the given name is no valid target.
|
||||
*/
|
||||
|
||||
int CPUHasCap (capability_t Cap);
|
||||
/* Check if the current CPU has the given capability */
|
||||
|
||||
|
||||
|
||||
/* End of cpu.h */
|
||||
|
||||
Reference in New Issue
Block a user