1 /*-------------------------------------------------------------------------
2 main.c - m6502 specific general function
4 Copyright (C) 2003, Erik Petrich
6 Hacked for the MOS6502:
7 Copyright (C) 2020, Steven Hugg hugg@fasterlight.com
8 Copyright (C) 2021-2023, Gabriele Gorla
10 This program is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 -------------------------------------------------------------------------*/
29 #include "dbuf_string.h"
33 #define OPTION_SMALL_MODEL "--model-small"
34 #define OPTION_LARGE_MODEL "--model-large"
35 //#define OPTION_XDATA_OVR "--xdata-overlay"
36 #define OPTION_XDATA_SPILL "--no-zp-spill"
37 //#define OPTION_CODE_SEG "--codeseg"
38 //#define OPTION_CONST_SEG "--constseg"
39 //#define OPTION_DATA_SEG "--dataseg"
40 #define OPTION_NO_STD_CRT0 "--no-std-crt0"
42 extern char * iComments2
;
43 extern DEBUGFILE dwarf2DebugFile
;
44 extern int dwarf2FinalizeFile(FILE *);
46 static OPTION mos6502_options
[] = {
47 {0, OPTION_SMALL_MODEL
, NULL
, "8-bit address space for data"},
48 {0, OPTION_LARGE_MODEL
, NULL
, "16-bit address space for data (default)"},
49 // {0, OPTION_XDATA_OVR, &options.xdata_overlay, "place overlay segment in 16-bit address space"},
50 {0, OPTION_XDATA_SPILL
, &options
.xdata_spill
, "place register spills in 16-bit address space"},
51 // {0, OPTION_CODE_SEG, &options.code_seg, "<name> use this name for the code segment", CLAT_STRING},
52 // {0, OPTION_CONST_SEG, &options.const_seg, "<name> use this name for the const segment", CLAT_STRING},
53 // {0, OPTION_DATA_SEG, &options.data_seg, "<name> use this name for the data segment", CLAT_STRING},
54 {0, OPTION_NO_STD_CRT0
, &options
.no_std_crt0
, "Do not link default crt0.rel"},
60 // Determine if we can put parameters in registers
64 struct sym_link
*ftype
;
69 static char _m6502_defaultRules
[] =
74 static char _m65c02_defaultRules
[] =
79 MOS6502_OPTS mos6502_opts
;
81 /* list of key words used by m6502 */
82 static char *m6502_keywords
[] = {
100 void m6502_assignRegisters (ebbIndex
*);
105 mos6502_opts
.sub
= SUB_MOS6502
;
106 asm_addTree (&asm_asxxxx_mapping
);
112 mos6502_opts
.sub
= SUB_MOS65C02
;
113 asm_addTree (&asm_asxxxx_mapping
);
117 m6502_reset_regparm (struct sym_link
*ftype
)
120 _G
.regparam
.ftype
= ftype
;
124 m6502_regparm (sym_link
*l
, bool reentrant
)
126 if (IFFUNC_HASVARARGS (_G
.regparam
.ftype
))
132 int size
= getSize(l
);
134 /* If they fit completely, the first two bytes of parameters can go */
135 /* into A and X, otherwise, they go on the stack. Examples: */
136 /* foo(char p1) A <- p1 */
137 /* foo(char p1, char p2) A <- p1, X <- p2 */
138 /* foo(char p1, char p2, char p3) A <- p1, X <- p2, stack <- p3 */
139 /* foo(int p1) XA <- p1 */
140 /* foo(long p1) stack <- p1 */
141 /* foo(char p1, int p2) A <- p1, stack <- p2 */
142 /* foo(int p1, char p2) XA <- p1, stack <- p2 */
144 if (_G
.regparam
.n
>=2)
147 if ((_G
.regparam
.n
+size
)>2)
153 _G
.regparam
.n
+= size
;
154 return 1+_G
.regparam
.n
-size
;
158 m6502_parseOptions (int *pargc
, char **argv
, int *i
)
164 m6502_finaliseOptions (void)
166 if (options
.noXinitOpt
)
169 if (options
.model
== MODEL_LARGE
)
171 port
->mem
.default_local_map
= xdata
;
172 port
->mem
.default_globl_map
= xdata
;
176 port
->mem
.default_local_map
= data
;
177 port
->mem
.default_globl_map
= data
;
180 istack
->ptrType
= FPOINTER
;
184 m6502_setDefaultOptions (void)
187 options
.stackAuto
= 0;
188 // options.intlong_rent = 1;
189 // options.float_rent = 1;
190 // options.noRegParams = 0;
191 options
.code_loc
= 0x8000;
192 options
.data_loc
= 0x0001; /* Zero page, We can't use the byte at address zero in C, since NULL pointers have special meaning */
193 options
.xdata_loc
= 0x0200; /* immediately following stack */
194 options
.stack_loc
= 0x01ff;
196 options
.omitFramePtr
= 1; /* no frame pointer (we use SP */
197 /* offsets instead) */
198 options
.out_fmt
= 'i'; /* Default output format is ihx */
199 // options.xdata_overlay = 0; /* Overlay in ZP */
200 options
.xdata_spill
= 0; /* Spill in ZP */
204 m6502_getRegName (const struct reg_info
*reg
)
212 m6502_genAssemblerStart (FILE * of
)
214 fprintf(of
, ";; Ordering of segments for the linker.\n");
215 tfprintf (of
, "\t!area\n", DATA_NAME
);
216 tfprintf (of
, "\t!area\n", OVERLAY_NAME
);
217 // if (options.xdata_overlay==0)
218 // tfprintf (of, "\t!area (PAG, OVR)\n", OVERLAY_NAME);
220 tfprintf (of
, "\t!area\n", HOME_NAME
);
221 tfprintf (of
, "\t!area\n", STATIC_NAME
);
222 tfprintf (of
, "\t!area\n", "GSFINAL");
223 tfprintf (of
, "\t!area\n", CODE_NAME
);
224 tfprintf (of
, "\t!area\n", CONST_NAME
);
225 tfprintf (of
, "\t!area\n", XINIT_NAME
);
227 tfprintf (of
, "\t!area\n", "_DATA");
228 tfprintf (of
, "\t!area\n", XIDATA_NAME
);
229 // if(options.xdata_overlay)
230 // tfprintf (of, "\t!area (OVR)\n", OVERLAY_NAME);
231 tfprintf (of
, "\t!area\n", XDATA_NAME
);
233 if (!options
.noOptsdccInAsm
)
235 fprintf (of
, "\t.optsdcc -m%s", port
->target
);
241 m65c02_genAssemblerStart (FILE * of
)
243 fprintf(of
, "\t.r65c02\n\n");
244 m6502_genAssemblerStart (of
);
248 m6502_genAssemblerEnd (FILE * of
)
250 if (options
.out_fmt
== 'E' && options
.debug
)
252 dwarf2FinalizeFile (of
);
256 /* Generate interrupt vector table. */
258 m6502_genIVT (struct dbuf_s
* oBuf
, symbol
** interrupts
, int maxInterrupts
)
260 dbuf_printf (oBuf
, "\t.area\tCODEIVT (ABS)\n");
261 dbuf_printf (oBuf
, "\t.org\t0xFFFA\n");
263 wassertl(maxInterrupts
<= 2, "Too many interrupt vectors");
264 if (maxInterrupts
> 1 && interrupts
[1])
265 dbuf_printf (oBuf
, "\t.dw\t%s\n", interrupts
[1]->rname
);
267 dbuf_printf (oBuf
, "\t.dw\t0xffff\n");
268 dbuf_printf (oBuf
, "\t.dw\t%s", "__sdcc_gs_init_startup\n");
269 if (maxInterrupts
> 0 && interrupts
[0])
270 dbuf_printf (oBuf
, "\t.dw\t%s\n", interrupts
[0]->rname
);
272 dbuf_printf (oBuf
, "\t.dw\t0xffff\n");
277 /* Generate code to copy XINIT to XISEG */
278 static void m6502_genXINIT (FILE * of
)
280 // This is not called but it must be defined to avoid
281 // SDCCmem.c line 445 from putting DATA into BSS and
282 // then generating code to fill it in.
285 /* Do CSE estimation */
286 static bool cseCostEstimation (iCode
*ic
, iCode
*pdic
)
288 operand
*result
= IC_RESULT(ic
);
289 sym_link
*result_type
= operandType(result
);
291 /* if it is a pointer then return ok for now */
292 if (IC_RESULT(ic
) && IS_PTR(result_type
)) return 1;
294 if (ic
->op
== ADDRESS_OF
)
297 /* if bitwise | add & subtract then no since m6502 is pretty good at it
298 so we will cse only if they are local (i.e. both ic & pdic belong to
299 the same basic block */
300 if (IS_BITWISE_OP(ic
) || ic
->op
== '+' || ic
->op
== '-')
302 /* then if they are the same Basic block then ok */
303 if (ic
->eBBlockNum
== pdic
->eBBlockNum
)
309 /* for others it is cheaper to do the cse */
313 /* Indicate which extended bit operations this port supports */
315 hasExtBitOp (int op
, sym_link
*left
, int right
)
324 unsigned int lbits
= bitsForType (left
);
325 if (lbits
> (unsigned)port
->support
.shift
*8)
327 if (right
% lbits
== 1 || right
% lbits
== lbits
- 1)
335 /* Indicate the expense of an access to an output storage class */
337 oclsExpense (struct memmap
*oclass
)
339 if (IN_DIRSPACE (oclass
)) /* direct addressing mode is fastest */
341 if (IN_FARSPACE (oclass
)) /* extended addressing mode is almost at fast */
343 if (oclass
== istack
) /* stack is the slowest */
346 return 0; /* anything we missed */
349 /*----------------------------------------------------------------------*/
350 /* m6502_dwarfRegNum - return the DWARF register number for a register. */
351 /* These are defined for the M6502 in "Motorola 8- and 16-bit Embedded */
352 /* Application Binary Interface (M8/16EABI)" */
353 /*----------------------------------------------------------------------*/
355 m6502_dwarfRegNum (const struct reg_info
*reg
)
359 case A_IDX
: return 0;
360 case Y_IDX
: return 1;
361 case X_IDX
: return 2;
362 case CND_IDX
: return 17;
363 case SP_IDX
: return 15;
369 _hasNativeMulFor (iCode
*ic
, sym_link
*left
, sym_link
*right
)
374 typedef struct asmLineNode
381 newAsmLineNode (void)
385 aln
= Safe_alloc ( sizeof (asmLineNode
));
402 /* These must be kept sorted by opcode name */
403 static m6502opcodedata m6502opcodeDataTable
[] =
405 {".db", M6502OP_INH
, -1, 0 }, // used by the code generator only in the jump table
406 {"adc", M6502OP_REG
, A_IDX
, 0xc3 },
407 {"and", M6502OP_REG
, A_IDX
, 0x82 },
408 {"asl", M6502OP_RMW
, -1, 0x83 },
409 {"bbr", M6502OP_BBR
, -1, 0 }, // Rockwell and WDC only
410 {"bbs", M6502OP_BBR
, -1, 0 }, // Rockwell and WDC only
411 {"bcc", M6502OP_BR
, -1, 0 },
412 {"bcs", M6502OP_BR
, -1, 0 },
413 {"beq", M6502OP_BR
, -1, 0 },
414 {"bit", M6502OP_CMP
, -1, 0xc2 },
415 {"bmi", M6502OP_BR
, -1, 0 },
416 {"bne", M6502OP_BR
, -1, 0 },
417 {"bpl", M6502OP_BR
, -1, 0 },
418 {"bra", M6502OP_BR
, -1, 0 }, // 65C02 only
419 {"brk", M6502OP_INH
, -1, 0 },
420 {"bvc", M6502OP_BR
, -1, 0 },
421 {"bvs", M6502OP_BR
, -1, 0 },
422 {"clc", M6502OP_INH
, -1, 0x01 },
423 {"cld", M6502OP_INH
, -1, 0x08 },
424 {"cli", M6502OP_INH
, -1, 0x04 },
425 {"clv", M6502OP_INH
, -1, 0x40 },
426 {"cmp", M6502OP_CMP
, -1, 0xc3 },
427 {"cpx", M6502OP_CMP
, -1, 0xc3 },
428 {"cpy", M6502OP_CMP
, -1, 0xc3 },
429 {"dec", M6502OP_RMW
, -1, 0x82 },
430 {"dex", M6502OP_IDD
, X_IDX
, 0x82 },
431 {"dey", M6502OP_IDD
, Y_IDX
, 0x82 },
432 {"eor", M6502OP_REG
, A_IDX
, 0x82 },
433 {"inc", M6502OP_RMW
, -1, 0x82 },
434 {"inx", M6502OP_IDI
, X_IDX
, 0x82 },
435 {"iny", M6502OP_IDI
, Y_IDX
, 0x82 },
436 {"jmp", M6502OP_JMP
, -1, 0 },
437 {"jsr", M6502OP_JMP
, -1, 0 },
438 {"lda", M6502OP_LD
, A_IDX
, 0x82 },
439 {"ldx", M6502OP_LD
, X_IDX
, 0x82 },
440 {"ldy", M6502OP_LD
, Y_IDX
, 0x82 },
441 {"lsr", M6502OP_RMW
, -1, 0x83 },
442 {"nop", M6502OP_INH
, -1, 0 },
443 {"ora", M6502OP_REG
, A_IDX
, 0x82 },
444 {"pha", M6502OP_SPH
, -1, 0 },
445 {"php", M6502OP_SPH
, -1, 0 },
446 {"phx", M6502OP_SPH
, -1, 0 }, // 65C02 only
447 {"phy", M6502OP_SPH
, -1, 0 }, // 65C02 only
448 {"pla", M6502OP_SPL
, A_IDX
, 0x82 },
449 {"plp", M6502OP_SPL
, -1, 0xdf },
450 {"plx", M6502OP_SPL
, X_IDX
, 0x82 }, // 65C02 only
451 {"ply", M6502OP_SPL
, Y_IDX
, 0x82 }, // 65C02 only
452 {"rmb", M6502OP_REG
, -1, 0 }, // Rockwell and WDC only
453 {"rol", M6502OP_RMW
, -1, 0x83 },
454 {"ror", M6502OP_RMW
, -1, 0x83 },
455 {"rti", M6502OP_INH
, -1, 0xdf },
456 {"rts", M6502OP_INH
, -1, 0 },
457 {"sbc", M6502OP_REG
, A_IDX
, 0xc3 },
458 {"sec", M6502OP_INH
, -1, 0x01 },
459 {"sed", M6502OP_INH
, -1, 0x08 },
460 {"sei", M6502OP_INH
, -1, 0x04 },
461 {"smb", M6502OP_REG
, -1, 0 }, // Rockwell and WDC only
462 {"sta", M6502OP_ST
, -1, 0 },
463 {"stp", M6502OP_INH
, -1, 0 }, // WDC only
464 {"stx", M6502OP_ST
, -1, 0 },
465 {"sty", M6502OP_ST
, -1, 0 },
466 {"stz", M6502OP_ST
, -1, 0 }, // 65C02 only
467 {"tax", M6502OP_INH
, X_IDX
, 0x82 },
468 {"tay", M6502OP_INH
, Y_IDX
, 0x82 },
469 {"trb", M6502OP_REG
, -1, 0 }, // 65C02 only
470 {"tsb", M6502OP_REG
, -1, 0 }, // 65C02 only
471 {"tsx", M6502OP_INH
, X_IDX
, 0x82 },
472 {"txa", M6502OP_INH
, A_IDX
, 0x82 },
473 {"txs", M6502OP_INH
, -1, 0 },
474 {"tya", M6502OP_INH
, A_IDX
, 0x82 },
475 {"wai", M6502OP_INH
, -1, 0 } // WDC only
479 m6502_opcodeCompare (const void *key
, const void *member
)
481 return strncmp((const char *)key
, ((m6502opcodedata
*)member
)->name
,3);
485 const m6502opcodedata
*m6502_getOpcodeData (const char *inst
)
487 return bsearch (inst
, m6502opcodeDataTable
,
488 sizeof(m6502opcodeDataTable
)/sizeof(m6502opcodedata
),
489 sizeof(m6502opcodedata
), m6502_opcodeCompare
);
493 m6502_opcodeSize (const m6502opcodedata
*opcode
, const char *arg
)
495 switch (opcode
->type
)
497 case M6502OP_INH
: /* Inherent addressing mode */
504 case M6502OP_BR
: /* Branch (1 byte signed offset) */
507 case M6502OP_BBR
: /* Branch on bit (1 byte signed offset) */
510 case M6502OP_RMW
: /* read/modify/write instructions */
511 if (!strcmp(arg
, "a")) /* accumulator */
513 if (arg
[0] == '*') /* Zero page */
515 return 3; /* absolute */
517 case M6502OP_REG
: /* standard instruction */
521 if (arg
[0] == '#') /* Immediate addressing mode */
523 if (arg
[0] == '*') /* Zero page */
525 if (arg
[0] == '[') /* indirect */
527 return 3; /* Otherwise, must be extended addressing mode */
533 werror (E_INTERNAL_ERROR
, __FILE__
, __LINE__
, "unknown instruction type in m6502_opcodeSize");
538 /*--------------------------------------------------------------------*/
539 /* Given an instruction and its first two operands, compute the */
540 /* instruction size. There are a few cases where it's too complicated */
541 /* to distinguish between an 8-bit offset and 16-bit offset; in these */
542 /* cases we conservatively assume the 16-bit offset size. */
543 /*--------------------------------------------------------------------*/
545 m6502_instructionSize (const char *inst
, const char *op1
, const char *op2
)
547 const m6502opcodedata
*opcode
= m6502_getOpcodeData(inst
);
552 // printf("op: %s - %s - %s\n",inst,op1, op2);
554 return m6502_opcodeSize(opcode
, op1
);
559 m6502_asmLineNodeFromLineNode (lineNode
*ln
)
561 asmLineNode
*aln
= newAsmLineNode();
562 char *op
, op1
[256], op2
[256];
569 while (*p
&& isspace(*p
)) p
++;
570 for (op
= inst
, opsize
=1; *p
; p
++)
572 if (isspace(*p
) || *p
== ';' || *p
== ':' || *p
== '=')
575 if (opsize
< sizeof(inst
))
576 *op
++ = tolower(*p
), opsize
++;
580 if (*p
== ':' || *p
== '=')
583 while (*p
&& isspace(*p
)) p
++;
591 aln
->size
= m6502_instructionSize(inst
, op1
, op2
);
595 for (op
= op1
, opsize
=1; *p
&& *p
!= ',' && *p
!= ';'; p
++)
597 if (!isspace(*p
) && opsize
< sizeof(op1
))
598 *op
++ = tolower(*p
), opsize
++;
607 aln
->size
= m6502_instructionSize(inst
, op1
, op2
);
611 for (op
= op2
, opsize
=1; *p
&& *p
!= ',' && *p
!= ';' ; p
++)
613 if (!isspace(*p
) && opsize
< sizeof(op2
))
614 *op
++ = tolower(*p
), opsize
++;
618 aln
->size
= m6502_instructionSize(inst
, op1
, op2
);
624 m6502_getInstructionSize (lineNode
*line
)
627 line
->aln
= (asmLineNodeBase
*) m6502_asmLineNodeFromLineNode (line
);
629 return line
->aln
->size
;
637 if (options
.stackAuto
)
638 return "mos65c02-stack-auto";
644 if (options
.stackAuto
)
645 return "mos6502-stack-auto";
651 /** $1 is always the basename.
652 $2 is always the output file.
654 $l is the list of extra options that should be there somewhere...
655 $L is the list of extra options that should be passed on the command line...
656 MUST be terminated with a NULL.
658 static const char *_linkCmd
[] =
660 "sdld6808", "-nf", "$1", "$L", NULL
663 /* $3 is replaced by assembler.debug_opts resp. port->assembler.plain_opts */
664 static const char *_asmCmd
[] =
666 "sdas6500", "$l", "$3", "$2", "$1.asm", NULL
669 static const char *const _crt
[] = { "crt0.rel", NULL
, };
670 static const char * const _libs_m6502
[] = { "mos6502", NULL
, };
671 static const char * const _libs_m65c02
[] = { "mos65c02", NULL
, };
678 "MOS 6502", /* Target name */
679 NULL
, /* Processor name */
682 false, /* Emit glue around main */
683 MODEL_SMALL
| MODEL_LARGE
,
690 "-plosgffwy", /* Options with debug */
691 "-plosgffw", /* Options without debug */
694 NULL
/* no do_assemble function */
700 ".rel", /* object file extension */
701 1, /* need linker script */
703 _libs_m6502
, /* libs */
705 { /* Peephole optimizer */
707 m6502_getInstructionSize
,
718 /* Sizes: char, short, int, long, long long, ptr, fptr, gptr, bit, float, max */
719 // TODO: banked func ptr and bit-precise integers
730 0, /* banked func ptr */
733 64, /* bit-precise integer types up to _BitInt (64) */
735 /* tags for generic pointers */
736 { 0x00, 0x00, 0x00, 0x00 }, /* far, near, xstack, code */
738 "XSEG", /* xstack_name */
739 "STACK", /* istack_name */
741 "ZP (PAG)", /* data */
746 "RSEG (ABS)", /* reg */
747 "GSINIT", /* static initialization */
748 "OSEG (PAG, OVR)", /* overlay */
749 "GSFINAL", /* gsfinal */
751 "DATA", /* initialized xdata */
752 "XINIT", /* a code copy of DATA */
753 "RODATA", /* const_name */
754 "CABS (ABS)", /* cabs_name - const absolute data */
755 "DABS (ABS)", /* xabs_name - absolute xdata */
756 NULL
, /* iabs_name */
757 NULL
, // name of segment for initialized variables
758 NULL
, // name of segment for copies of initialized variables in code space
759 NULL
, // default location for auto vars
760 NULL
, // default location for globl vars
761 1, /* CODE is read-only */
762 false, // doesn't matter, as port has no __sfr anyway
763 1 /* No fancy alignments supported. */
765 { NULL
, NULL
}, /* No extra areas */
766 0, /* default ABI revision */
767 { /* stack information */
768 -1, /* stack grows down */
769 0, /* bank_overhead (switch between register banks) */
770 6, /* isr overhead */
771 2, /* call overhead */
772 0, /* reent_overhead */
773 0, /* banked_overhead (switch between code banks) */
774 1, /* sp points to next free stack location */
777 5, /* shifts up to 5 use support routines */
778 false, /* do not use support routine for int x int -> long multiplication */
779 false, /* do not use support routine for unsigned long x unsigned char -> unsigned long long multiplication */
782 m6502_emitDebuggerSymbol
,
796 2, /* sizeofElement */
797 {8,16,32}, /* sizeofMatchJump[] */
798 {8,16,32}, /* sizeofRangeCompare[] */
799 5, /* sizeofSubtract */
800 10, /* sizeofDispatch */
807 m6502_finaliseOptions
,
808 m6502_setDefaultOptions
,
809 m6502_assignRegisters
,
814 m6502_genAssemblerStart
, /* genAssemblerStart */
815 m6502_genAssemblerEnd
, /* genAssemblerEnd */
817 m6502_genXINIT
, /* genXINIT code */
818 0, /* genInitStartup */
821 NULL
, /* process_pragma */
822 NULL
, /* getMangledFunctionName */
823 _hasNativeMulFor
, /* hasNativeMulFor */
824 hasExtBitOp
, /* hasExtBitOp */
825 oclsExpense
, /* oclsExpense */
826 true, /* use_dw_for_init */
827 true, /* little endian */
830 1, /* transform <= to ! > */
831 1, /* transform >= to ! < */
832 1, /* transform != to !(a == b) */
834 false, /* No array initializer support. */
835 cseCostEstimation
, /* CSE cost estimation */
836 NULL
, /* no builtin functions */
837 GPOINTER
, /* treat unqualified pointers as "generic" pointers */
838 1, /* reset labelKey to 1 */
839 1, /* globals & local statics allowed */
840 3, /* Number of registers handled in the tree-decomposition-based register allocator in SDCCralloc.hpp */
848 "WDC 65C02", /* Target name */
849 NULL
, /* Processor name */
852 false, /* Emit glue around main */
853 MODEL_SMALL
| MODEL_LARGE
,
855 0, /* model == target */
860 "-plosgffwy", /* Options with debug */
861 "-plosgffw", /* Options without debug */
864 NULL
/* no do_assemble function */
873 _libs_m65c02
, /* libs */
875 { /* Peephole optimizer */
876 _m65c02_defaultRules
,
877 m6502_getInstructionSize
,
888 /* Sizes: char, short, int, long, long long, ptr, fptr, gptr, bit, float, max */
899 0, /* banked func ptr */
902 64, /* bit-precise integer types up to _BitInt (64) */
904 /* tags for generic pointers */
905 { 0x00, 0x00, 0x00, 0x00 }, /* far, near, xstack, code */
907 "XSEG", // xstack_name
908 "STACK", // istack_name
916 "GSINIT", // static initialization
917 "OSEG (PAG, OVR)", // overlay
918 "GSFINAL", // gsfinal
920 "DATA", // initialized xdata
921 "XINIT", // a code copy of DATA
922 "RODATA", // const_name - const data (code or not)
923 "CABS (ABS)", // cabs_name - const absolute data (code or not)
924 "DABS (ABS)", // xabs_name - absolute xdata
925 NULL
, // iabs_name - absolute data
926 NULL
, // name of segment for initialized variables
927 NULL
, // name of segment for copies of initialized variables in code space
928 NULL
, // default location for auto vars
929 NULL
, // default location for globl vars
930 1, // code space read-only 1=yes
931 false, // doesn't matter, as port has no __sfr anyway
932 1 // No fancy alignments supported.
937 -1, /* direction (-1 = stack grows down) */
938 0, /* bank_overhead (switch between register banks) */
939 4, /* isr_overhead */
940 2, /* call_overhead */
941 0, /* reent_overhead */
942 0, /* banked_overhead (switch between code banks) */
943 1 /* sp is offset by 1 from last item pushed */
946 5, // Shifts up to 5 use support routines.
947 false, // Do not use support routine for int x int -> long multiplication.
948 false, // Do not use support routine for unsigned long x unsigned char -> unsigned long long multiplication.
951 m6502_emitDebuggerSymbol
,
965 2, /* sizeofElement */
966 {8,16,32}, /* sizeofMatchJump[] */
967 {8,16,32}, /* sizeofRangeCompare[] */
968 5, /* sizeofSubtract */
969 10, /* sizeofDispatch */
976 m6502_finaliseOptions
,
977 m6502_setDefaultOptions
,
978 m6502_assignRegisters
,
983 m65c02_genAssemblerStart
, /* genAssemblerStart */
984 m6502_genAssemblerEnd
, /* genAssemblerEnd */
987 0, /* genInitStartup */
990 0, /* process_pragma */
991 NULL
, /* getMangledFunctionName */
992 _hasNativeMulFor
, /* hasNativeMulFor */
993 hasExtBitOp
, /* hasExtBitOp */
994 oclsExpense
, /* oclsExpense */
995 true, /* use_dw_for_init */
996 true, /* little endian */
999 1, /* transform <= to ! > */
1000 1, /* transform >= to ! < */
1001 1, /* transform != to !(a == b) */
1003 false, /* No array initializer support. */
1004 cseCostEstimation
, /* CSE cost estimation */
1005 NULL
, /* no builtin functions */
1006 GPOINTER
, /* treat unqualified pointers as "generic" pointers */
1007 1, /* reset labelKey to 1 */
1008 1, /* globals & local statics allowed */
1009 3, /* Number of registers handled in the tree-decomposition-based register allocator in SDCCralloc.hpp */