Merge branch 'master' into c_sp
This commit is contained in:
3
.github/workflows/build-on-pull-request.yml
vendored
3
.github/workflows/build-on-pull-request.yml
vendored
@@ -27,6 +27,9 @@ jobs:
|
|||||||
- name: Build the tools.
|
- name: Build the tools.
|
||||||
shell: bash
|
shell: bash
|
||||||
run: make -j2 bin USER_CFLAGS=-Werror
|
run: make -j2 bin USER_CFLAGS=-Werror
|
||||||
|
- name: Build the dbginfo example
|
||||||
|
shell: bash
|
||||||
|
run: make -j2 -C src test
|
||||||
- name: Build the utilities.
|
- name: Build the utilities.
|
||||||
shell: bash
|
shell: bash
|
||||||
run: make -j2 util
|
run: make -j2 util
|
||||||
|
|||||||
1
Makefile
1
Makefile
@@ -50,6 +50,7 @@ test:
|
|||||||
# GNU "check" target, which runs all tests
|
# GNU "check" target, which runs all tests
|
||||||
check:
|
check:
|
||||||
@$(MAKE) -C .github/checks checkstyle --no-print-directory
|
@$(MAKE) -C .github/checks checkstyle --no-print-directory
|
||||||
|
@$(MAKE) -C src test --no-print-directory
|
||||||
@$(MAKE) test
|
@$(MAKE) test
|
||||||
@$(MAKE) -C targettest platforms --no-print-directory
|
@$(MAKE) -C targettest platforms --no-print-directory
|
||||||
@$(MAKE) -C samples platforms --no-print-directory
|
@$(MAKE) -C samples platforms --no-print-directory
|
||||||
|
|||||||
@@ -1154,6 +1154,96 @@ The compiler defines several macros at startup:
|
|||||||
<item><tt/__CC65_STD_CC65__/
|
<item><tt/__CC65_STD_CC65__/
|
||||||
</itemize>
|
</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>
|
<tag><tt>__CX16__</tt></tag>
|
||||||
|
|
||||||
This macro is defined if the target is the Commander X16 (-t cx16).
|
This macro is defined if the target is the Commander X16 (-t cx16).
|
||||||
|
|||||||
@@ -40,6 +40,20 @@
|
|||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#if (__CPU__ & __CPU_ISET_65SC02__)
|
||||||
|
/* Always inline, three bytes is not more than a jsr */
|
||||||
|
|
||||||
|
#define ntohs(x) \
|
||||||
|
( \
|
||||||
|
__AX__=(x), \
|
||||||
|
asm("phx"), \
|
||||||
|
asm("tax"), \
|
||||||
|
asm("pla"), \
|
||||||
|
__AX__ \
|
||||||
|
)
|
||||||
|
#define htons(x) ntohs(x)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
#if (__OPT_i__ < 200)
|
#if (__OPT_i__ < 200)
|
||||||
int __fastcall__ ntohs (int val);
|
int __fastcall__ ntohs (int val);
|
||||||
@@ -56,12 +70,12 @@ int __fastcall__ htons (int val);
|
|||||||
)
|
)
|
||||||
#define htons(x) ntohs(x)
|
#define htons(x) ntohs(x)
|
||||||
|
|
||||||
#endif
|
#endif /* __OPT_i__ < 200 */
|
||||||
|
|
||||||
|
#endif /* __CPU__ & __CPU_ISET_65SC02__ */
|
||||||
|
|
||||||
long __fastcall__ ntohl (long val);
|
long __fastcall__ ntohl (long val);
|
||||||
long __fastcall__ htonl (long val);
|
long __fastcall__ htonl (long val);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* End of arpa/inet.h */
|
/* End of arpa/inet.h */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
15
src/Makefile
15
src/Makefile
@@ -168,4 +168,19 @@ $(eval $(call OBJS_template,common))
|
|||||||
|
|
||||||
$(foreach prog,$(PROGS),$(eval $(call PROG_template,$(prog))))
|
$(foreach prog,$(PROGS),$(eval $(call PROG_template,$(prog))))
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: dbginfo dbgsh test
|
||||||
|
|
||||||
|
test: dbginfo dbgsh
|
||||||
|
|
||||||
|
$(eval $(call OBJS_template,dbginfo))
|
||||||
|
|
||||||
|
dbginfo: $(dbginfo_OBJS)
|
||||||
|
|
||||||
|
../wrk/dbgsh$(EXE_SUFFIX): $(dbginfo_OBJS) ../wrk/common/common.a
|
||||||
|
$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
|
||||||
|
|
||||||
|
dbgsh: ../wrk/dbgsh$(EXE_SUFFIX)
|
||||||
|
|
||||||
|
|
||||||
-include $(DEPS)
|
-include $(DEPS)
|
||||||
|
|||||||
@@ -169,6 +169,7 @@ static const struct {
|
|||||||
unsigned Count;
|
unsigned Count;
|
||||||
InsDesc Ins[56];
|
InsDesc Ins[56];
|
||||||
} InsTab6502 = {
|
} InsTab6502 = {
|
||||||
|
/* CAUTION: table must be sorted for bsearch */
|
||||||
sizeof (InsTab6502.Ins) / sizeof (InsTab6502.Ins[0]),
|
sizeof (InsTab6502.Ins) / sizeof (InsTab6502.Ins[0]),
|
||||||
{
|
{
|
||||||
{ "ADC", 0x080A26C, 0x60, 0, PutAll },
|
{ "ADC", 0x080A26C, 0x60, 0, PutAll },
|
||||||
@@ -235,6 +236,7 @@ static const struct {
|
|||||||
unsigned Count;
|
unsigned Count;
|
||||||
InsDesc Ins[75];
|
InsDesc Ins[75];
|
||||||
} InsTab6502X = {
|
} InsTab6502X = {
|
||||||
|
/* CAUTION: table must be sorted for bsearch */
|
||||||
sizeof (InsTab6502X.Ins) / sizeof (InsTab6502X.Ins[0]),
|
sizeof (InsTab6502X.Ins) / sizeof (InsTab6502X.Ins[0]),
|
||||||
{
|
{
|
||||||
{ "ADC", 0x080A26C, 0x60, 0, PutAll },
|
{ "ADC", 0x080A26C, 0x60, 0, PutAll },
|
||||||
@@ -324,6 +326,7 @@ static const struct {
|
|||||||
unsigned Count;
|
unsigned Count;
|
||||||
InsDesc Ins[71];
|
InsDesc Ins[71];
|
||||||
} InsTab6502DTV = {
|
} InsTab6502DTV = {
|
||||||
|
/* CAUTION: table must be sorted for bsearch */
|
||||||
sizeof (InsTab6502DTV.Ins) / sizeof (InsTab6502DTV.Ins[0]),
|
sizeof (InsTab6502DTV.Ins) / sizeof (InsTab6502DTV.Ins[0]),
|
||||||
{
|
{
|
||||||
{ "ADC", 0x080A26C, 0x60, 0, PutAll },
|
{ "ADC", 0x080A26C, 0x60, 0, PutAll },
|
||||||
@@ -405,6 +408,7 @@ static const struct {
|
|||||||
unsigned Count;
|
unsigned Count;
|
||||||
InsDesc Ins[66];
|
InsDesc Ins[66];
|
||||||
} InsTab65SC02 = {
|
} InsTab65SC02 = {
|
||||||
|
/* CAUTION: table must be sorted for bsearch */
|
||||||
sizeof (InsTab65SC02.Ins) / sizeof (InsTab65SC02.Ins[0]),
|
sizeof (InsTab65SC02.Ins) / sizeof (InsTab65SC02.Ins[0]),
|
||||||
{
|
{
|
||||||
{ "ADC", 0x080A66C, 0x60, 0, PutAll },
|
{ "ADC", 0x080A66C, 0x60, 0, PutAll },
|
||||||
@@ -481,6 +485,7 @@ static const struct {
|
|||||||
unsigned Count;
|
unsigned Count;
|
||||||
InsDesc Ins[100];
|
InsDesc Ins[100];
|
||||||
} InsTab65C02 = {
|
} InsTab65C02 = {
|
||||||
|
/* CAUTION: table must be sorted for bsearch */
|
||||||
sizeof (InsTab65C02.Ins) / sizeof (InsTab65C02.Ins[0]),
|
sizeof (InsTab65C02.Ins) / sizeof (InsTab65C02.Ins[0]),
|
||||||
{
|
{
|
||||||
{ "ADC", 0x080A66C, 0x60, 0, PutAll },
|
{ "ADC", 0x080A66C, 0x60, 0, PutAll },
|
||||||
@@ -591,6 +596,7 @@ static const struct {
|
|||||||
unsigned Count;
|
unsigned Count;
|
||||||
InsDesc Ins[133];
|
InsDesc Ins[133];
|
||||||
} InsTab4510 = {
|
} InsTab4510 = {
|
||||||
|
/* CAUTION: table must be sorted for bsearch */
|
||||||
sizeof (InsTab4510.Ins) / sizeof (InsTab4510.Ins[0]),
|
sizeof (InsTab4510.Ins) / sizeof (InsTab4510.Ins[0]),
|
||||||
{
|
{
|
||||||
{ "ADC", 0x080A66C, 0x60, 0, PutAll },
|
{ "ADC", 0x080A66C, 0x60, 0, PutAll },
|
||||||
@@ -734,6 +740,7 @@ static const struct {
|
|||||||
unsigned Count;
|
unsigned Count;
|
||||||
InsDesc Ins[100];
|
InsDesc Ins[100];
|
||||||
} InsTab65816 = {
|
} InsTab65816 = {
|
||||||
|
/* CAUTION: table must be sorted for bsearch */
|
||||||
sizeof (InsTab65816.Ins) / sizeof (InsTab65816.Ins[0]),
|
sizeof (InsTab65816.Ins) / sizeof (InsTab65816.Ins[0]),
|
||||||
{
|
{
|
||||||
{ "ADC", 0x0b8f6fc, 0x60, 0, PutAll },
|
{ "ADC", 0x0b8f6fc, 0x60, 0, PutAll },
|
||||||
@@ -844,6 +851,7 @@ static const struct {
|
|||||||
unsigned Count;
|
unsigned Count;
|
||||||
InsDesc Ins[26];
|
InsDesc Ins[26];
|
||||||
} InsTabSweet16 = {
|
} InsTabSweet16 = {
|
||||||
|
/* CAUTION: table must be sorted for bsearch */
|
||||||
sizeof (InsTabSweet16.Ins) / sizeof (InsTabSweet16.Ins[0]),
|
sizeof (InsTabSweet16.Ins) / sizeof (InsTabSweet16.Ins[0]),
|
||||||
{
|
{
|
||||||
{ "ADD", AMSW16_REG, 0xA0, 0, PutSweet16 },
|
{ "ADD", AMSW16_REG, 0xA0, 0, PutSweet16 },
|
||||||
@@ -880,6 +888,7 @@ static const struct {
|
|||||||
unsigned Count;
|
unsigned Count;
|
||||||
InsDesc Ins[135];
|
InsDesc Ins[135];
|
||||||
} InsTabHuC6280 = {
|
} InsTabHuC6280 = {
|
||||||
|
/* CAUTION: table must be sorted for bsearch */
|
||||||
sizeof (InsTabHuC6280.Ins) / sizeof (InsTabHuC6280.Ins[0]),
|
sizeof (InsTabHuC6280.Ins) / sizeof (InsTabHuC6280.Ins[0]),
|
||||||
{
|
{
|
||||||
{ "ADC", 0x080A66C, 0x60, 0, PutAll },
|
{ "ADC", 0x080A66C, 0x60, 0, PutAll },
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ static int C = 0; /* Current input character */
|
|||||||
int ForcedEnd = 0;
|
int ForcedEnd = 0;
|
||||||
|
|
||||||
/* List of dot keywords with the corresponding tokens */
|
/* List of dot keywords with the corresponding tokens */
|
||||||
|
/* CAUTION: table must be sorted for bsearch */
|
||||||
struct DotKeyword {
|
struct DotKeyword {
|
||||||
const char* Key; /* MUST be first field */
|
const char* Key; /* MUST be first field */
|
||||||
token_t Tok;
|
token_t Tok;
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ struct FuncInfo {
|
|||||||
** routines are marked to use only the A register. The remainder is ignored
|
** routines are marked to use only the A register. The remainder is ignored
|
||||||
** anyway.
|
** anyway.
|
||||||
*/
|
*/
|
||||||
/* MUST BE SORTED BY NAME !!! */
|
/* CAUTION: table must be sorted for bsearch */
|
||||||
static const FuncInfo FuncInfoTable[] = {
|
static const FuncInfo FuncInfoTable[] = {
|
||||||
{ "addeq0sp", SLV_TOP | REG_AX, PSTATE_ALL | REG_AXY },
|
{ "addeq0sp", SLV_TOP | REG_AX, PSTATE_ALL | REG_AXY },
|
||||||
{ "addeqysp", SLV_IND | REG_AXY, PSTATE_ALL | REG_AXY },
|
{ "addeqysp", SLV_IND | REG_AXY, PSTATE_ALL | REG_AXY },
|
||||||
@@ -191,12 +191,12 @@ static const FuncInfo FuncInfoTable[] = {
|
|||||||
{ "ldeaxysp", SLV_IND | REG_Y, PSTATE_ALL | REG_EAXY },
|
{ "ldeaxysp", SLV_IND | REG_Y, PSTATE_ALL | REG_EAXY },
|
||||||
{ "leaa0sp", REG_SP | REG_A, PSTATE_ALL | REG_AX },
|
{ "leaa0sp", REG_SP | REG_A, PSTATE_ALL | REG_AX },
|
||||||
{ "leaaxsp", REG_SP | REG_AX, PSTATE_ALL | REG_AX },
|
{ "leaaxsp", REG_SP | REG_AX, PSTATE_ALL | REG_AX },
|
||||||
{ "leave00", REG_SP, PSTATE_ALL | REG_SP | REG_AXY },
|
|
||||||
{ "leave0", REG_SP, PSTATE_ALL | REG_SP | REG_XY },
|
|
||||||
{ "leave", REG_SP, PSTATE_ALL | REG_SP | REG_Y },
|
{ "leave", REG_SP, PSTATE_ALL | REG_SP | REG_Y },
|
||||||
{ "leavey00", REG_SP, PSTATE_ALL | REG_SP | REG_AXY },
|
{ "leave0", REG_SP, PSTATE_ALL | REG_SP | REG_XY },
|
||||||
{ "leavey0", REG_SP, PSTATE_ALL | REG_SP | REG_XY },
|
{ "leave00", REG_SP, PSTATE_ALL | REG_SP | REG_AXY },
|
||||||
{ "leavey", REG_SP | REG_Y, PSTATE_ALL | REG_SP | REG_Y },
|
{ "leavey", REG_SP | REG_Y, PSTATE_ALL | REG_SP | REG_Y },
|
||||||
|
{ "leavey0", REG_SP, PSTATE_ALL | REG_SP | REG_XY },
|
||||||
|
{ "leavey00", REG_SP, PSTATE_ALL | REG_SP | REG_AXY },
|
||||||
{ "lsubeq", REG_EAXY | REG_PTR1_LO, PSTATE_ALL | REG_EAXY | REG_PTR1_HI },
|
{ "lsubeq", REG_EAXY | REG_PTR1_LO, PSTATE_ALL | REG_EAXY | REG_PTR1_HI },
|
||||||
{ "lsubeq0sp", SLV_TOP | REG_EAX, PSTATE_ALL | REG_EAXY },
|
{ "lsubeq0sp", SLV_TOP | REG_EAX, PSTATE_ALL | REG_EAXY },
|
||||||
{ "lsubeq1", REG_Y | REG_PTR1_LO, PSTATE_ALL | REG_EAXY | REG_PTR1_HI },
|
{ "lsubeq1", REG_Y | REG_PTR1_LO, PSTATE_ALL | REG_EAXY | REG_PTR1_HI },
|
||||||
@@ -381,7 +381,7 @@ static const FuncInfo FuncInfoTable[] = {
|
|||||||
#define FuncInfoCount (sizeof(FuncInfoTable) / sizeof(FuncInfoTable[0]))
|
#define FuncInfoCount (sizeof(FuncInfoTable) / sizeof(FuncInfoTable[0]))
|
||||||
|
|
||||||
/* Table with names of zero page locations used by the compiler */
|
/* Table with names of zero page locations used by the compiler */
|
||||||
/* MUST BE SORTED BY NAME !!! */
|
/* CAUTION: table must be sorted for bsearch */
|
||||||
static const ZPInfo ZPInfoTable[] = {
|
static const ZPInfo ZPInfoTable[] = {
|
||||||
{ 0, "c_sp", 2, REG_SP_LO, REG_SP },
|
{ 0, "c_sp", 2, REG_SP_LO, REG_SP },
|
||||||
{ 0, "c_sp+1", 1, REG_SP_HI, REG_SP },
|
{ 0, "c_sp+1", 1, REG_SP_HI, REG_SP },
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ struct OptFunc {
|
|||||||
|
|
||||||
|
|
||||||
/* A list of all the function descriptions */
|
/* A list of all the function descriptions */
|
||||||
|
/* CAUTION: should be sorted by "name" */
|
||||||
static OptFunc DOpt65C02BitOps = { Opt65C02BitOps, "Opt65C02BitOps", 66, 0, 0, 0, 0, 0 };
|
static OptFunc DOpt65C02BitOps = { Opt65C02BitOps, "Opt65C02BitOps", 66, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOpt65C02Ind = { Opt65C02Ind, "Opt65C02Ind", 100, 0, 0, 0, 0, 0 };
|
static OptFunc DOpt65C02Ind = { Opt65C02Ind, "Opt65C02Ind", 100, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOpt65C02Stores = { Opt65C02Stores, "Opt65C02Stores", 100, 0, 0, 0, 0, 0 };
|
static OptFunc DOpt65C02Stores = { Opt65C02Stores, "Opt65C02Stores", 100, 0, 0, 0, 0, 0 };
|
||||||
@@ -152,18 +153,13 @@ static OptFunc DOptJumpTarget3 = { OptJumpTarget3, "OptJumpTarget3", 100, 0,
|
|||||||
static OptFunc DOptLoad1 = { OptLoad1, "OptLoad1", 100, 0, 0, 0, 0, 0 };
|
static OptFunc DOptLoad1 = { OptLoad1, "OptLoad1", 100, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptLoad2 = { OptLoad2, "OptLoad2", 200, 0, 0, 0, 0, 0 };
|
static OptFunc DOptLoad2 = { OptLoad2, "OptLoad2", 200, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptLoad3 = { OptLoad3, "OptLoad3", 0, 0, 0, 0, 0, 0 };
|
static OptFunc DOptLoad3 = { OptLoad3, "OptLoad3", 0, 0, 0, 0, 0, 0 };
|
||||||
|
static OptFunc DOptLoadStoreLoad= { OptLoadStoreLoad,"OptLoadStoreLoad", 0, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptLongAssign = { OptLongAssign, "OptLongAssign", 100, 0, 0, 0, 0, 0 };
|
static OptFunc DOptLongAssign = { OptLongAssign, "OptLongAssign", 100, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptLongCopy = { OptLongCopy, "OptLongCopy", 100, 0, 0, 0, 0, 0 };
|
static OptFunc DOptLongCopy = { OptLongCopy, "OptLongCopy", 100, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptNegAX1 = { OptNegAX1, "OptNegAX1", 165, 0, 0, 0, 0, 0 };
|
static OptFunc DOptNegAX1 = { OptNegAX1, "OptNegAX1", 165, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptNegAX2 = { OptNegAX2, "OptNegAX2", 200, 0, 0, 0, 0, 0 };
|
static OptFunc DOptNegAX2 = { OptNegAX2, "OptNegAX2", 200, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptPrecalc = { OptPrecalc, "OptPrecalc", 100, 0, 0, 0, 0, 0 };
|
static OptFunc DOptPrecalc = { OptPrecalc, "OptPrecalc", 100, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptPtrLoad1 = { OptPtrLoad1, "OptPtrLoad1", 100, 0, 0, 0, 0, 0 };
|
static OptFunc DOptPtrLoad1 = { OptPtrLoad1, "OptPtrLoad1", 100, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptPtrLoad2 = { OptPtrLoad2, "OptPtrLoad2", 100, 0, 0, 0, 0, 0 };
|
|
||||||
static OptFunc DOptPtrLoad3 = { OptPtrLoad3, "OptPtrLoad3", 100, 0, 0, 0, 0, 0 };
|
|
||||||
static OptFunc DOptPtrLoad4 = { OptPtrLoad4, "OptPtrLoad4", 100, 0, 0, 0, 0, 0 };
|
|
||||||
static OptFunc DOptPtrLoad5 = { OptPtrLoad5, "OptPtrLoad5", 50, 0, 0, 0, 0, 0 };
|
|
||||||
static OptFunc DOptPtrLoad6 = { OptPtrLoad6, "OptPtrLoad6", 60, 0, 0, 0, 0, 0 };
|
|
||||||
static OptFunc DOptPtrLoad7 = { OptPtrLoad7, "OptPtrLoad7", 140, 0, 0, 0, 0, 0 };
|
|
||||||
static OptFunc DOptPtrLoad11 = { OptPtrLoad11, "OptPtrLoad11", 92, 0, 0, 0, 0, 0 };
|
static OptFunc DOptPtrLoad11 = { OptPtrLoad11, "OptPtrLoad11", 92, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptPtrLoad12 = { OptPtrLoad12, "OptPtrLoad12", 50, 0, 0, 0, 0, 0 };
|
static OptFunc DOptPtrLoad12 = { OptPtrLoad12, "OptPtrLoad12", 50, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptPtrLoad13 = { OptPtrLoad13, "OptPtrLoad13", 65, 0, 0, 0, 0, 0 };
|
static OptFunc DOptPtrLoad13 = { OptPtrLoad13, "OptPtrLoad13", 65, 0, 0, 0, 0, 0 };
|
||||||
@@ -173,6 +169,12 @@ static OptFunc DOptPtrLoad16 = { OptPtrLoad16, "OptPtrLoad16", 100, 0,
|
|||||||
static OptFunc DOptPtrLoad17 = { OptPtrLoad17, "OptPtrLoad17", 190, 0, 0, 0, 0, 0 };
|
static OptFunc DOptPtrLoad17 = { OptPtrLoad17, "OptPtrLoad17", 190, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptPtrLoad18 = { OptPtrLoad18, "OptPtrLoad18", 100, 0, 0, 0, 0, 0 };
|
static OptFunc DOptPtrLoad18 = { OptPtrLoad18, "OptPtrLoad18", 100, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptPtrLoad19 = { OptPtrLoad19, "OptPtrLoad19", 65, 0, 0, 0, 0, 0 };
|
static OptFunc DOptPtrLoad19 = { OptPtrLoad19, "OptPtrLoad19", 65, 0, 0, 0, 0, 0 };
|
||||||
|
static OptFunc DOptPtrLoad2 = { OptPtrLoad2, "OptPtrLoad2", 100, 0, 0, 0, 0, 0 };
|
||||||
|
static OptFunc DOptPtrLoad3 = { OptPtrLoad3, "OptPtrLoad3", 100, 0, 0, 0, 0, 0 };
|
||||||
|
static OptFunc DOptPtrLoad4 = { OptPtrLoad4, "OptPtrLoad4", 100, 0, 0, 0, 0, 0 };
|
||||||
|
static OptFunc DOptPtrLoad5 = { OptPtrLoad5, "OptPtrLoad5", 50, 0, 0, 0, 0, 0 };
|
||||||
|
static OptFunc DOptPtrLoad6 = { OptPtrLoad6, "OptPtrLoad6", 60, 0, 0, 0, 0, 0 };
|
||||||
|
static OptFunc DOptPtrLoad7 = { OptPtrLoad7, "OptPtrLoad7", 140, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptPtrStore1 = { OptPtrStore1, "OptPtrStore1", 65, 0, 0, 0, 0, 0 };
|
static OptFunc DOptPtrStore1 = { OptPtrStore1, "OptPtrStore1", 65, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptPtrStore2 = { OptPtrStore2, "OptPtrStore2", 65, 0, 0, 0, 0, 0 };
|
static OptFunc DOptPtrStore2 = { OptPtrStore2, "OptPtrStore2", 65, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptPtrStore3 = { OptPtrStore3, "OptPtrStore3", 100, 0, 0, 0, 0, 0 };
|
static OptFunc DOptPtrStore3 = { OptPtrStore3, "OptPtrStore3", 100, 0, 0, 0, 0, 0 };
|
||||||
@@ -202,7 +204,6 @@ static OptFunc DOptStore3 = { OptStore3, "OptStore3", 120, 0,
|
|||||||
static OptFunc DOptStore4 = { OptStore4, "OptStore4", 50, 0, 0, 0, 0, 0 };
|
static OptFunc DOptStore4 = { OptStore4, "OptStore4", 50, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptStore5 = { OptStore5, "OptStore5", 100, 0, 0, 0, 0, 0 };
|
static OptFunc DOptStore5 = { OptStore5, "OptStore5", 100, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptStoreLoad = { OptStoreLoad, "OptStoreLoad", 0, 0, 0, 0, 0, 0 };
|
static OptFunc DOptStoreLoad = { OptStoreLoad, "OptStoreLoad", 0, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptLoadStoreLoad= { OptLoadStoreLoad,"OptLoadStoreLoad", 0, 0, 0, 0, 0, 0 };
|
|
||||||
static OptFunc DOptSub1 = { OptSub1, "OptSub1", 100, 0, 0, 0, 0, 0 };
|
static OptFunc DOptSub1 = { OptSub1, "OptSub1", 100, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptSub2 = { OptSub2, "OptSub2", 100, 0, 0, 0, 0, 0 };
|
static OptFunc DOptSub2 = { OptSub2, "OptSub2", 100, 0, 0, 0, 0, 0 };
|
||||||
static OptFunc DOptSub3 = { OptSub3, "OptSub3", 100, 0, 0, 0, 0, 0 };
|
static OptFunc DOptSub3 = { OptSub3, "OptSub3", 100, 0, 0, 0, 0, 0 };
|
||||||
@@ -217,6 +218,7 @@ static OptFunc DOptUnusedStores = { OptUnusedStores, "OptUnusedStores", 0, 0,
|
|||||||
|
|
||||||
|
|
||||||
/* Table containing all the steps in alphabetical order */
|
/* Table containing all the steps in alphabetical order */
|
||||||
|
/* CAUTION: table must be sorted for bsearch */
|
||||||
static OptFunc* OptFuncs[] = {
|
static OptFunc* OptFuncs[] = {
|
||||||
&DOpt65C02BitOps,
|
&DOpt65C02BitOps,
|
||||||
&DOpt65C02Ind,
|
&DOpt65C02Ind,
|
||||||
@@ -268,6 +270,7 @@ static OptFunc* OptFuncs[] = {
|
|||||||
&DOptLoad1,
|
&DOptLoad1,
|
||||||
&DOptLoad2,
|
&DOptLoad2,
|
||||||
&DOptLoad3,
|
&DOptLoad3,
|
||||||
|
&DOptLoadStoreLoad,
|
||||||
&DOptLongAssign,
|
&DOptLongAssign,
|
||||||
&DOptLongCopy,
|
&DOptLongCopy,
|
||||||
&DOptNegAX1,
|
&DOptNegAX1,
|
||||||
@@ -318,7 +321,6 @@ static OptFunc* OptFuncs[] = {
|
|||||||
&DOptStore4,
|
&DOptStore4,
|
||||||
&DOptStore5,
|
&DOptStore5,
|
||||||
&DOptStoreLoad,
|
&DOptStoreLoad,
|
||||||
&DOptLoadStoreLoad,
|
|
||||||
&DOptSub1,
|
&DOptSub1,
|
||||||
&DOptSub2,
|
&DOptSub2,
|
||||||
&DOptSub3,
|
&DOptSub3,
|
||||||
|
|||||||
@@ -1225,6 +1225,10 @@ static int CmpHarmless (const void* Key, const void* Entry)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* CAUTION: table must be sorted for bsearch */
|
||||||
|
static const char* const Tab[] = {
|
||||||
|
"_abs",
|
||||||
|
};
|
||||||
|
|
||||||
int HarmlessCall (const CodeEntry* E, int PushedBytes)
|
int HarmlessCall (const CodeEntry* E, int PushedBytes)
|
||||||
/* Check if this is a call to a harmless subroutine that will not interrupt
|
/* Check if this is a call to a harmless subroutine that will not interrupt
|
||||||
@@ -1252,10 +1256,6 @@ int HarmlessCall (const CodeEntry* E, int PushedBytes)
|
|||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
static const char* const Tab[] = {
|
|
||||||
"_abs",
|
|
||||||
};
|
|
||||||
|
|
||||||
void* R = bsearch (E->Arg,
|
void* R = bsearch (E->Arg,
|
||||||
Tab,
|
Tab,
|
||||||
sizeof (Tab) / sizeof (Tab[0]),
|
sizeof (Tab) / sizeof (Tab[0]),
|
||||||
|
|||||||
@@ -1464,6 +1464,7 @@ static unsigned Opt_a_tosxor (StackOpData* D)
|
|||||||
|
|
||||||
/* The first column of these two tables must be sorted in lexical order */
|
/* The first column of these two tables must be sorted in lexical order */
|
||||||
|
|
||||||
|
/* CAUTION: table must be sorted for bsearch */
|
||||||
static const OptFuncDesc FuncTable[] = {
|
static const OptFuncDesc FuncTable[] = {
|
||||||
{ "___bzero", Opt___bzero, REG_NONE, OP_X_ZERO | OP_A_KNOWN },
|
{ "___bzero", Opt___bzero, REG_NONE, OP_X_ZERO | OP_A_KNOWN },
|
||||||
{ "staspidx", Opt_staspidx, REG_NONE, OP_NONE },
|
{ "staspidx", Opt_staspidx, REG_NONE, OP_NONE },
|
||||||
@@ -1487,6 +1488,7 @@ static const OptFuncDesc FuncTable[] = {
|
|||||||
{ "tosxorax", Opt_tosxorax, REG_NONE, OP_NONE },
|
{ "tosxorax", Opt_tosxorax, REG_NONE, OP_NONE },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* CAUTION: table must be sorted for bsearch */
|
||||||
static const OptFuncDesc FuncRegATable[] = {
|
static const OptFuncDesc FuncRegATable[] = {
|
||||||
{ "tosandax", Opt_a_tosand, REG_NONE, OP_RHS_REMOVE_DIRECT | OP_RHS_LOAD_DIRECT },
|
{ "tosandax", Opt_a_tosand, REG_NONE, OP_RHS_REMOVE_DIRECT | OP_RHS_LOAD_DIRECT },
|
||||||
{ "toseqax", Opt_a_toseq, REG_NONE, OP_NONE },
|
{ "toseqax", Opt_a_toseq, REG_NONE, OP_NONE },
|
||||||
|
|||||||
@@ -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)
|
static void FileNameOption (const char* Opt, const char* Arg, StrBuf* Name)
|
||||||
/* Handle an option that remembers a file name for later */
|
/* 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)
|
static void OptCPU (const char* Opt, const char* Arg)
|
||||||
/* Handle the --cpu option */
|
/* 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);
|
CPU = FindCPU (Arg);
|
||||||
if (CPU != CPU_6502 && CPU != CPU_6502X && CPU != CPU_65SC02 &&
|
if (CPU != CPU_6502 && CPU != CPU_6502X && CPU != CPU_65SC02 &&
|
||||||
CPU != CPU_65C02 && CPU != CPU_65816 && CPU != CPU_HUC6280 &&
|
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 */
|
/* Create the output file name if it was not explicitly given */
|
||||||
MakeDefaultOutputName (InputFile);
|
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 (CPU == CPU_UNKNOWN) {
|
||||||
if (Target != TGT_UNKNOWN) {
|
if (Target != TGT_UNKNOWN) {
|
||||||
CPU = GetTargetProperties (Target)->DefaultCPU;
|
CPU = GetTargetProperties (Target)->DefaultCPU;
|
||||||
@@ -1071,6 +1150,7 @@ int main (int argc, char* argv[])
|
|||||||
CPU = CPU_6502;
|
CPU = CPU_6502;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
DefineCpuMacros ();
|
||||||
|
|
||||||
/* If no memory model was given, use the default */
|
/* If no memory model was given, use the default */
|
||||||
if (MemoryModel == MMODEL_UNKNOWN) {
|
if (MemoryModel == MMODEL_UNKNOWN) {
|
||||||
|
|||||||
@@ -55,6 +55,7 @@
|
|||||||
|
|
||||||
|
|
||||||
/* Opcode description table */
|
/* Opcode description table */
|
||||||
|
/* CAUTION: table must be sorted by mnemonic for bsearch */
|
||||||
const OPCDesc OPCTable[OP65_COUNT] = {
|
const OPCDesc OPCTable[OP65_COUNT] = {
|
||||||
|
|
||||||
/* 65XX opcodes */
|
/* 65XX opcodes */
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ typedef enum {
|
|||||||
} pragma_t;
|
} pragma_t;
|
||||||
|
|
||||||
/* Pragma table */
|
/* Pragma table */
|
||||||
|
/* CAUTION: table must be sorted for bsearch */
|
||||||
static const struct Pragma {
|
static const struct Pragma {
|
||||||
const char* Key; /* Keyword */
|
const char* Key; /* Keyword */
|
||||||
pragma_t Tok; /* Token */
|
pragma_t Tok; /* Token */
|
||||||
@@ -433,12 +434,7 @@ static void ApplySegNamePragma (pragma_t Token, int PushPop, const char* Name, u
|
|||||||
SetSegAddrSize (Name, AddrSize);
|
SetSegAddrSize (Name, AddrSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BSS variables are output at the end of the compilation. Don't
|
g_segname (Seg);
|
||||||
** bother to change their segment, now.
|
|
||||||
*/
|
|
||||||
if (Seg != SEG_BSS) {
|
|
||||||
g_segname (Seg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -216,6 +216,7 @@ typedef enum {
|
|||||||
|
|
||||||
|
|
||||||
/* Preprocessor directive tokens mapping table */
|
/* Preprocessor directive tokens mapping table */
|
||||||
|
/* CAUTION: table must be sorted for bsearch */
|
||||||
static const struct PPDType {
|
static const struct PPDType {
|
||||||
const char* Tok; /* Token */
|
const char* Tok; /* Token */
|
||||||
ppdirective_t Type; /* Type */
|
ppdirective_t Type; /* Type */
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Token table */
|
/* Token table */
|
||||||
|
/* CAUTION: table must be sorted for bsearch */
|
||||||
static const struct Keyword {
|
static const struct Keyword {
|
||||||
char* Key; /* Keyword name */
|
char* Key; /* Keyword name */
|
||||||
unsigned char Tok; /* The token */
|
unsigned char Tok; /* The token */
|
||||||
|
|||||||
@@ -78,8 +78,8 @@ static void StdFunc_strlen (FuncDesc*, ExprDesc*);
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Table with all known functions and their handlers. Must be sorted
|
/* Table with all known functions and their handlers.
|
||||||
** alphabetically!
|
** CAUTION: table must be alphabetically sorted for bsearch
|
||||||
*/
|
*/
|
||||||
static struct StdFuncDesc {
|
static struct StdFuncDesc {
|
||||||
const char* Name;
|
const char* Name;
|
||||||
@@ -90,7 +90,6 @@ static struct StdFuncDesc {
|
|||||||
{ "strcmp", StdFunc_strcmp },
|
{ "strcmp", StdFunc_strcmp },
|
||||||
{ "strcpy", StdFunc_strcpy },
|
{ "strcpy", StdFunc_strcpy },
|
||||||
{ "strlen", StdFunc_strlen },
|
{ "strlen", StdFunc_strlen },
|
||||||
|
|
||||||
};
|
};
|
||||||
#define FUNC_COUNT (sizeof (StdFuncs) / sizeof (StdFuncs[0]))
|
#define FUNC_COUNT (sizeof (StdFuncs) / sizeof (StdFuncs[0]))
|
||||||
|
|
||||||
|
|||||||
@@ -122,6 +122,11 @@ static int DoAssemble = 1;
|
|||||||
/* The name of the output file, NULL if none given */
|
/* The name of the output file, NULL if none given */
|
||||||
static const char* OutputName = 0;
|
static const char* OutputName = 0;
|
||||||
|
|
||||||
|
/* The path part of the output file, NULL if none given
|
||||||
|
** or the OutputName is just a filename with no path
|
||||||
|
** information. */
|
||||||
|
static char *OutputDirectory = 0;
|
||||||
|
|
||||||
/* The name of the linker configuration file if given */
|
/* The name of the linker configuration file if given */
|
||||||
static const char* LinkerConfig = 0;
|
static const char* LinkerConfig = 0;
|
||||||
|
|
||||||
@@ -555,7 +560,7 @@ static void AssembleFile (const char* File, const char* TmpFile, unsigned ArgCou
|
|||||||
if (TmpFile) {
|
if (TmpFile) {
|
||||||
ObjName = MakeFilename (TmpFile, ".o");
|
ObjName = MakeFilename (TmpFile, ".o");
|
||||||
} else {
|
} else {
|
||||||
ObjName = MakeTmpFilename (".o");
|
ObjName = MakeTmpFilename (OutputDirectory, File, ".o");
|
||||||
}
|
}
|
||||||
CmdSetOutput (&CA65, ObjName);
|
CmdSetOutput (&CA65, ObjName);
|
||||||
CmdAddFile (&LD65, ObjName);
|
CmdAddFile (&LD65, ObjName);
|
||||||
@@ -684,7 +689,7 @@ static void Compile (const char* File)
|
|||||||
|
|
||||||
if (DoAssemble) {
|
if (DoAssemble) {
|
||||||
/* set a temporary output file name */
|
/* set a temporary output file name */
|
||||||
TmpFile = MakeTmpFilename(".s");
|
TmpFile = MakeTmpFilename(OutputDirectory, File, ".s");
|
||||||
CmdSetOutput (&CC65, TmpFile);
|
CmdSetOutput (&CC65, TmpFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -729,7 +734,7 @@ static void CompileRes (const char* File)
|
|||||||
** BEFORE adding the file
|
** BEFORE adding the file
|
||||||
*/
|
*/
|
||||||
if (DoAssemble && DoLink) {
|
if (DoAssemble && DoLink) {
|
||||||
AsmName = MakeTmpFilename(".s");
|
AsmName = MakeTmpFilename(OutputDirectory, File, ".s");
|
||||||
CmdSetAsmOutput(&GRC, AsmName);
|
CmdSetAsmOutput(&GRC, AsmName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1623,6 +1628,7 @@ int main (int argc, char* argv [])
|
|||||||
case 'o':
|
case 'o':
|
||||||
/* Name the output file */
|
/* Name the output file */
|
||||||
OutputName = GetArg (&I, 2);
|
OutputName = GetArg (&I, 2);
|
||||||
|
OutputDirectory = GetFileDirectory(OutputName);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'r':
|
case 'r':
|
||||||
@@ -1713,6 +1719,9 @@ int main (int argc, char* argv [])
|
|||||||
}
|
}
|
||||||
|
|
||||||
RemoveTempFiles ();
|
RemoveTempFiles ();
|
||||||
|
if (OutputDirectory != NULL) {
|
||||||
|
xfree(OutputDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
/* Return an apropriate exit code */
|
/* Return an apropriate exit code */
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
|||||||
@@ -48,6 +48,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* CAUTION: table must be sorted for bsearch */
|
||||||
static const FileId TypeTable[] = {
|
static const FileId TypeTable[] = {
|
||||||
/* Upper case stuff for obsolete operating systems */
|
/* Upper case stuff for obsolete operating systems */
|
||||||
{ "A", FILETYPE_LIB },
|
{ "A", FILETYPE_LIB },
|
||||||
|
|||||||
@@ -33,8 +33,17 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# include <process.h>
|
||||||
|
#else
|
||||||
|
# include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "fname.h"
|
#include "fname.h"
|
||||||
@@ -93,7 +102,28 @@ const char* FindName (const char* Path)
|
|||||||
return Path + Len;
|
return Path + Len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *GetFileDirectory (const char* File)
|
||||||
|
/* Return a copy of the path part of a File, or NULL if there is none. */
|
||||||
|
{
|
||||||
|
char *Out, *P;
|
||||||
|
|
||||||
|
if (File == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Out = xmalloc (strlen (File) + 1);
|
||||||
|
strcpy(Out, File);
|
||||||
|
|
||||||
|
P = (char *)FindName (Out);
|
||||||
|
if (P == Out) {
|
||||||
|
/* This is a simple filename. */
|
||||||
|
xfree (Out);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
*P = '\0';
|
||||||
|
|
||||||
|
return Out;
|
||||||
|
}
|
||||||
|
|
||||||
char* MakeFilename (const char* Origin, const char* Ext)
|
char* MakeFilename (const char* Origin, const char* Ext)
|
||||||
/* Make a new file name from Origin and Ext. If Origin has an extension, it
|
/* Make a new file name from Origin and Ext. If Origin has an extension, it
|
||||||
@@ -119,35 +149,22 @@ char* MakeFilename (const char* Origin, const char* Ext)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
char* MakeTmpFilename (const char* Ext)
|
char* MakeTmpFilename (const char *Directory, const char *Origin, const char* Ext)
|
||||||
/* Make a new temporary file name from Ext. tmpnam(3) is called
|
/* Make a new temporary file name from Origin and Ext.
|
||||||
** and Ext is appended to generate the filename.
|
|
||||||
** The result is placed in a malloc'ed buffer and returned.
|
** The result is placed in a malloc'ed buffer and returned.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
char* Out;
|
char* Out;
|
||||||
char Buffer[L_tmpnam * 2]; /* a lazy way to ensure we have space for Ext */
|
size_t Len = 0;
|
||||||
|
|
||||||
/*
|
/* Allocate template */
|
||||||
** gcc emits the following warning here:
|
if (Directory != NULL) {
|
||||||
**
|
Len = strlen (Directory);
|
||||||
** warning: the use of `tmpnam' is dangerous, better use `mkstemp'
|
}
|
||||||
**
|
Len += strlen (Origin) + strlen (".2147483648") + strlen (Ext) + 1;
|
||||||
** however, mkstemp actually opens a file, which we do not want.
|
Out = xmalloc (Len);
|
||||||
** tmpfile() is unsuitable for the same reason.
|
|
||||||
**
|
|
||||||
** we could write our own version, but then we would have to struggle
|
|
||||||
** with supporting multiple build environments.
|
|
||||||
**
|
|
||||||
** tmpnam(3) is safe here, because ca65 / cc65 / ld65 will simply clobber
|
|
||||||
** an existing file, or exit if with an error if they are unable to.
|
|
||||||
**
|
|
||||||
** gcc will also complain, if you don't use the return value from tmpnam(3)
|
|
||||||
*/
|
|
||||||
strcat(tmpnam(Buffer), Ext);
|
|
||||||
|
|
||||||
Out = xmalloc (strlen (Buffer) + 1);
|
|
||||||
strcpy (Out, Buffer);
|
|
||||||
|
|
||||||
|
snprintf (Out, Len, "%s%s.%u%s", (Directory != NULL ? Directory : ""),
|
||||||
|
FindName(Origin), getpid(), Ext);
|
||||||
return Out;
|
return Out;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,9 @@ const char* FindName (const char* Path);
|
|||||||
** the file, the function returns Path as name.
|
** the file, the function returns Path as name.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
char *GetFileDirectory (const char* File);
|
||||||
|
/* Return a copy of the path part of a File, or NULL if there is none. */
|
||||||
|
|
||||||
char* MakeFilename (const char* Origin, const char* Ext);
|
char* MakeFilename (const char* Origin, const char* Ext);
|
||||||
/* Make a new file name from Origin and Ext. If Origin has an extension, it
|
/* Make a new file name from Origin and Ext. If Origin has an extension, it
|
||||||
** is removed and Ext is appended. If Origin has no extension, Ext is simply
|
** is removed and Ext is appended. If Origin has no extension, Ext is simply
|
||||||
@@ -59,9 +62,10 @@ char* MakeFilename (const char* Origin, const char* Ext);
|
|||||||
** The function may be used to create "foo.o" from "foo.s".
|
** The function may be used to create "foo.o" from "foo.s".
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char* MakeTmpFilename (const char* Ext);
|
char* MakeTmpFilename (const char *Directory, const char *Origin, const char* Ext);
|
||||||
/* Make a new temporary file name from Ext. tmpnam(3) is called
|
/* Make a new temporary file name from Directory, Origin, and Ext.
|
||||||
** and Ext is appended to generate the filename.
|
** A temporary path is generated from the Directory,
|
||||||
|
** the Origin filename, the compiler's PID and the Extension.
|
||||||
** The result is placed in a malloc'ed buffer and returned.
|
** The result is placed in a malloc'ed buffer and returned.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -138,8 +138,9 @@ struct TargetEntry {
|
|||||||
target_t Id; /* Target ID */
|
target_t Id; /* Target ID */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Table that maps target names to IDs. Sorted alphabetically for bsearch().
|
/* Table that maps target names to IDs.
|
||||||
** Allows multiple entries for one target ID (target name aliases).
|
** Allows multiple entries for one target ID (target name aliases).
|
||||||
|
** CAUTION: must be alphabetically for bsearch().
|
||||||
*/
|
*/
|
||||||
static const TargetEntry TargetMap[] = {
|
static const TargetEntry TargetMap[] = {
|
||||||
{ "apple2", TGT_APPLE2 },
|
{ "apple2", TGT_APPLE2 },
|
||||||
|
|||||||
@@ -2523,6 +2523,7 @@ static void NextChar (InputData* D)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* CAUTION: table must be sorted for bsearch */
|
||||||
static void NextToken (InputData* D)
|
static void NextToken (InputData* D)
|
||||||
/* Read the next token from the input stream */
|
/* Read the next token from the input stream */
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -61,7 +61,8 @@ struct ConverterMapEntry {
|
|||||||
StrBuf* (*ConvertFunc) (const Bitmap*, const Collection*);
|
StrBuf* (*ConvertFunc) (const Bitmap*, const Collection*);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Converter table, alphabetically sorted */
|
/* Converter table */
|
||||||
|
/* CAUTION: table must be alphabetically sorted for bsearch */
|
||||||
static const ConverterMapEntry ConverterMap[] = {
|
static const ConverterMapEntry ConverterMap[] = {
|
||||||
{ "geos-bitmap", GenGeosBitmap },
|
{ "geos-bitmap", GenGeosBitmap },
|
||||||
{ "geos-icon", GenGeosIcon },
|
{ "geos-icon", GenGeosIcon },
|
||||||
|
|||||||
@@ -69,7 +69,8 @@ static InputFormatDesc InputFormatTable[ifCount] = {
|
|||||||
{ ReadPCXFile },
|
{ ReadPCXFile },
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Table that maps extensions to input formats. Must be sorted alphabetically */
|
/* Table that maps extensions to input formats. */
|
||||||
|
/* CAUTION: table must be alphabetically sorted for bsearch */
|
||||||
static const FileId FormatTable[] = {
|
static const FileId FormatTable[] = {
|
||||||
/* Upper case stuff for obsolete operating systems */
|
/* Upper case stuff for obsolete operating systems */
|
||||||
{ "PCX", ifPCX },
|
{ "PCX", ifPCX },
|
||||||
|
|||||||
@@ -78,7 +78,8 @@ static OutputFormatDesc OutputFormatTable[ofCount] = {
|
|||||||
{ WriteCFile },
|
{ WriteCFile },
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Table that maps extensions to Output formats. Must be sorted alphabetically */
|
/* Table that maps extensions to Output formats. */
|
||||||
|
/* CAUTION: table must be alphabetically sorted for bsearch */
|
||||||
static const FileId FormatTable[] = {
|
static const FileId FormatTable[] = {
|
||||||
/* Upper case stuff for obsolete operating systems */
|
/* Upper case stuff for obsolete operating systems */
|
||||||
{ "A", ofAsm },
|
{ "A", ofAsm },
|
||||||
|
|||||||
@@ -56,7 +56,8 @@ struct PaletteMapEntry {
|
|||||||
StrBuf* (*PaletteFunc) (const Bitmap*, const Collection*);
|
StrBuf* (*PaletteFunc) (const Bitmap*, const Collection*);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Converter table, alphabetically sorted */
|
/* Converter table */
|
||||||
|
/* CAUTION: table must be alphabetically sorted for bsearch */
|
||||||
static const PaletteMapEntry PaletteMap[] = {
|
static const PaletteMapEntry PaletteMap[] = {
|
||||||
{ "lynx-palette", GenLynxPalette },
|
{ "lynx-palette", GenLynxPalette },
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -47,10 +47,11 @@ _Pragma _Pragma (
|
|||||||
#pragma bss-name("BSS")
|
#pragma bss-name("BSS")
|
||||||
{
|
{
|
||||||
extern int y;
|
extern int y;
|
||||||
#pragma bss-name("BSS2")
|
#pragma bss-name("BSS") // used to be BSS2, but fix for #2608 means
|
||||||
|
// that now causes ld65 to fail, so we use BSS instead
|
||||||
static
|
static
|
||||||
#pragma zpsym ("y")
|
#pragma zpsym ("y")
|
||||||
int x; // TODO: currently in "BSS", but supposed to be in "BSS2"?
|
int x;
|
||||||
x = 0;
|
x = 0;
|
||||||
|
|
||||||
if (memcmp(str, "aBC", 3))
|
if (memcmp(str, "aBC", 3))
|
||||||
|
|||||||
40
test/val/bug2608.c
Normal file
40
test/val/bug2608.c
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
|
||||||
|
/* bug #2608: "zp_bss" is placed in BSS and NOT placed in ZEROPAGE as expected. */
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
int is_zeropage(void *p)
|
||||||
|
{
|
||||||
|
if (/*(p >= ((void*)0)) &&*/
|
||||||
|
(p <= ((void*)0xff))) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void foo(void) {
|
||||||
|
#pragma bss-name(push,"ZEROPAGE")
|
||||||
|
#pragma data-name(push,"ZEROPAGE")
|
||||||
|
static int zp_data = 5;
|
||||||
|
static char zp_bss;
|
||||||
|
#pragma bss-name(pop)
|
||||||
|
#pragma data-name(pop)
|
||||||
|
printf("zp_data at 0x%04x (%szp)\n", &zp_data, is_zeropage(&zp_data) ? "" : "NOT ");
|
||||||
|
printf("zp_bss at 0x%04x (%szp)\n", &zp_bss, is_zeropage(&zp_bss) ? "" : "NOT ");
|
||||||
|
if (!is_zeropage(&zp_data)) {
|
||||||
|
err++;
|
||||||
|
}
|
||||||
|
if (!is_zeropage(&zp_bss)) {
|
||||||
|
err++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
foo();
|
||||||
|
printf("errors: %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user