Pick three bugfixes from next branch to trunk for inclusion in 4.5.0 RC2, as discusse...
[sdcc.git] / sdcc / src / mos6502 / main.c
blobe3c0bb1f6babb4a81cac15db66c1ff984fc52585
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
13 later version.
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 -------------------------------------------------------------------------*/
25 #include "common.h"
27 #include "ralloc.h"
28 #include "gen.h"
29 #include "dbuf_string.h"
30 #include "m6502.h"
31 #include "peep.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"},
55 {0, NULL }
58 static struct
60 // Determine if we can put parameters in registers
61 struct
63 int n;
64 struct sym_link *ftype;
65 } regparam;
67 _G;
69 static char _m6502_defaultRules[] =
71 #include "peeph.rul"
74 static char _m65c02_defaultRules[] =
76 #include "peeph.rul"
79 MOS6502_OPTS mos6502_opts;
81 /* list of key words used by m6502 */
82 static char *m6502_keywords[] = {
83 "at",
84 "critical",
85 "interrupt",
86 "naked",
87 "reentrant",
88 "code",
89 "data",
90 "zp",
91 "near",
92 "xdata",
93 "far",
94 // "overlay",
95 // "using",
96 // "generic",
97 NULL
100 void m6502_assignRegisters (ebbIndex *);
102 static void
103 m6502_init (void)
105 mos6502_opts.sub = SUB_MOS6502;
106 asm_addTree (&asm_asxxxx_mapping);
109 static void
110 m65c02_init (void)
112 mos6502_opts.sub = SUB_MOS65C02;
113 asm_addTree (&asm_asxxxx_mapping);
116 static void
117 m6502_reset_regparm (struct sym_link *ftype)
119 _G.regparam.n = 0;
120 _G.regparam.ftype = ftype;
123 static int
124 m6502_regparm (sym_link *l, bool reentrant)
126 if (IFFUNC_HASVARARGS (_G.regparam.ftype))
127 return 0;
129 if (IS_STRUCT (l))
130 return 0;
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)
145 return 0;
147 if ((_G.regparam.n+size)>2)
149 _G.regparam.n = 2;
150 return 0;
153 _G.regparam.n += size;
154 return 1+_G.regparam.n-size;
157 static bool
158 m6502_parseOptions (int *pargc, char **argv, int *i)
160 return false;
163 static void
164 m6502_finaliseOptions (void)
166 if (options.noXinitOpt)
167 port->genXINIT = 0;
169 if (options.model == MODEL_LARGE)
171 port->mem.default_local_map = xdata;
172 port->mem.default_globl_map = xdata;
174 else
176 port->mem.default_local_map = data;
177 port->mem.default_globl_map = data;
180 istack->ptrType = FPOINTER;
183 static void
184 m6502_setDefaultOptions (void)
186 options.nopeep = 0;
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 */
203 static const char *
204 m6502_getRegName (const struct reg_info *reg)
206 if (reg)
207 return reg->name;
208 return "err";
211 static void
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);
236 fprintf (of, "\n");
240 static void
241 m65c02_genAssemblerStart (FILE * of)
243 fprintf(of, "\t.r65c02\n\n");
244 m6502_genAssemblerStart (of);
247 static void
248 m6502_genAssemblerEnd (FILE * of)
250 if (options.out_fmt == 'E' && options.debug)
252 dwarf2FinalizeFile (of);
256 /* Generate interrupt vector table. */
257 static int
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);
266 else
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);
271 else
272 dbuf_printf (oBuf, "\t.dw\t0xffff\n");
274 return true;
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)
295 return 0;
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)
304 return 1;
305 else
306 return 0;
309 /* for others it is cheaper to do the cse */
310 return 1;
313 /* Indicate which extended bit operations this port supports */
314 static bool
315 hasExtBitOp (int op, sym_link *left, int right)
317 switch (op)
319 case GETBYTE:
320 case GETWORD:
321 return true;
322 case ROT:
324 unsigned int lbits = bitsForType (left);
325 if (lbits > (unsigned)port->support.shift*8)
326 return false;
327 if (right % lbits == 1 || right % lbits == lbits - 1)
328 return (true);
330 return false;
332 return false;
335 /* Indicate the expense of an access to an output storage class */
336 static int
337 oclsExpense (struct memmap *oclass)
339 if (IN_DIRSPACE (oclass)) /* direct addressing mode is fastest */
340 return -2;
341 if (IN_FARSPACE (oclass)) /* extended addressing mode is almost at fast */
342 return -1;
343 if (oclass == istack) /* stack is the slowest */
344 return 2;
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 /*----------------------------------------------------------------------*/
354 static int
355 m6502_dwarfRegNum (const struct reg_info *reg)
357 switch (reg->rIdx)
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;
365 return -1;
368 static bool
369 _hasNativeMulFor (iCode *ic, sym_link *left, sym_link *right)
371 return false;
374 typedef struct asmLineNode
376 int size;
378 asmLineNode;
380 static asmLineNode *
381 newAsmLineNode (void)
383 asmLineNode *aln;
385 aln = Safe_alloc ( sizeof (asmLineNode));
386 aln->size = 0;
388 return aln;
392 processor flags
393 N 0x80
394 V 0x40
395 B 0x10
396 D 0x08
397 I 0x04
398 Z 0x02
399 C 0x01
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
478 static int
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 */
498 case M6502OP_SPH:
499 case M6502OP_SPL:
500 case M6502OP_IDD:
501 case M6502OP_IDI:
502 return 1;
504 case M6502OP_BR: /* Branch (1 byte signed offset) */
505 return 2;
507 case M6502OP_BBR: /* Branch on bit (1 byte signed offset) */
508 return 3;
510 case M6502OP_RMW: /* read/modify/write instructions */
511 if (!strcmp(arg, "a")) /* accumulator */
512 return 1;
513 if (arg[0] == '*') /* Zero page */
514 return 2;
515 return 3; /* absolute */
517 case M6502OP_REG: /* standard instruction */
518 case M6502OP_CMP:
519 case M6502OP_LD:
520 case M6502OP_ST:
521 if (arg[0] == '#') /* Immediate addressing mode */
522 return 2;
523 if (arg[0] == '*') /* Zero page */
524 return 2;
525 if (arg[0] == '[') /* indirect */
526 return 2;
527 return 3; /* Otherwise, must be extended addressing mode */
529 case M6502OP_JMP:
530 return 3;
532 default:
533 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "unknown instruction type in m6502_opcodeSize");
534 return 3;
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 /*--------------------------------------------------------------------*/
544 static int
545 m6502_instructionSize (const char *inst, const char *op1, const char *op2)
547 const m6502opcodedata *opcode = m6502_getOpcodeData(inst);
549 if (!opcode)
550 return 999;
552 // printf("op: %s - %s - %s\n",inst,op1, op2);
554 return m6502_opcodeSize(opcode, op1);
558 static asmLineNode *
559 m6502_asmLineNodeFromLineNode (lineNode *ln)
561 asmLineNode *aln = newAsmLineNode();
562 char *op, op1[256], op2[256];
563 int opsize;
564 const char *p;
565 char inst[8];
567 p = ln->line;
569 while (*p && isspace(*p)) p++;
570 for (op = inst, opsize=1; *p; p++)
572 if (isspace(*p) || *p == ';' || *p == ':' || *p == '=')
573 break;
574 else
575 if (opsize < sizeof(inst))
576 *op++ = tolower(*p), opsize++;
578 *op = '\0';
580 if (*p == ':' || *p == '=')
581 return aln;
583 while (*p && isspace(*p)) p++;
584 if (*p == '=')
585 return aln;
587 if (*p==';')
589 op1[0]=0;
590 op2[0]=0;
591 aln->size = m6502_instructionSize(inst, op1, op2);
592 return aln;
595 for (op = op1, opsize=1; *p && *p != ',' && *p != ';'; p++)
597 if (!isspace(*p) && opsize < sizeof(op1))
598 *op++ = tolower(*p), opsize++;
600 *op = '\0';
602 if (*p == ',')
603 p++;
604 if (*p == ';')
606 op2[0]=0;
607 aln->size = m6502_instructionSize(inst, op1, op2);
608 return aln;
611 for (op = op2, opsize=1; *p && *p != ',' && *p != ';' ; p++)
613 if (!isspace(*p) && opsize < sizeof(op2))
614 *op++ = tolower(*p), opsize++;
616 *op = '\0';
618 aln->size = m6502_instructionSize(inst, op1, op2);
620 return aln;
623 static int
624 m6502_getInstructionSize (lineNode *line)
626 if (!line->aln)
627 line->aln = (asmLineNodeBase *) m6502_asmLineNodeFromLineNode (line);
629 return line->aln->size;
632 static const char *
633 get_model (void)
635 if (IS_MOS65C02)
637 if (options.stackAuto)
638 return "mos65c02-stack-auto";
639 else
640 return "mos65c02";
642 else
644 if (options.stackAuto)
645 return "mos6502-stack-auto";
646 else
647 return "mos6502";
651 /** $1 is always the basename.
652 $2 is always the output file.
653 $3 varies
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, };
673 /* Globals */
674 PORT mos6502_port =
676 TARGET_ID_MOS6502,
677 "mos6502",
678 "MOS 6502", /* Target name */
679 NULL, /* Processor name */
681 glue,
682 false, /* Emit glue around main */
683 MODEL_SMALL | MODEL_LARGE,
684 MODEL_LARGE,
685 get_model,
688 _asmCmd,
689 NULL,
690 "-plosgffwy", /* Options with debug */
691 "-plosgffw", /* Options without debug */
693 ".asm",
694 NULL /* no do_assemble function */
696 { /* Linker */
697 _linkCmd,
698 NULL,
699 NULL,
700 ".rel", /* object file extension */
701 1, /* need linker script */
702 _crt, /* crt */
703 _libs_m6502, /* libs */
705 { /* Peephole optimizer */
706 _m6502_defaultRules,
707 m6502_getInstructionSize,
708 NULL,
709 NULL,
710 NULL,
711 mos6502notUsed,
712 NULL,
713 mos6502notUsedFrom,
714 NULL,
715 NULL,
716 NULL,
718 /* Sizes: char, short, int, long, long long, ptr, fptr, gptr, bit, float, max */
719 // TODO: banked func ptr and bit-precise integers
721 1, /* char */
722 2, /* short */
723 2, /* int */
724 4, /* long */
725 8, /* long long */
726 2, /* near ptr */
727 2, /* far ptr */
728 2, /* generic ptr */
729 2, /* func ptr */
730 0, /* banked func ptr */
731 1, /* bit */
732 4, /* float */
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 */
740 "CODE", /* code */
741 "ZP (PAG)", /* data */
742 NULL, /* idata */
743 NULL, /* pdata */
744 "BSS", /* xdata */
745 NULL, /* bit */
746 "RSEG (ABS)", /* reg */
747 "GSINIT", /* static initialization */
748 "OSEG (PAG, OVR)", /* overlay */
749 "GSFINAL", /* gsfinal */
750 "_CODE", /* home */
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,
784 m6502_dwarfRegNum,
785 0, /* cfiSame */
786 0, /* cfiUndef */
787 4, /* addressSize */
788 14, /* regNumRet */
789 15, /* regNumSP */
790 -1, /* regNumBP */
791 1, /* offsetSP */
795 256, /* maxCount */
796 2, /* sizeofElement */
797 {8,16,32}, /* sizeofMatchJump[] */
798 {8,16,32}, /* sizeofRangeCompare[] */
799 5, /* sizeofSubtract */
800 10, /* sizeofDispatch */
802 "_",
803 m6502_init,
804 m6502_parseOptions,
805 mos6502_options,
806 NULL,
807 m6502_finaliseOptions,
808 m6502_setDefaultOptions,
809 m6502_assignRegisters,
810 m6502_getRegName,
812 NULL,
813 m6502_keywords,
814 m6502_genAssemblerStart, /* genAssemblerStart */
815 m6502_genAssemblerEnd, /* genAssemblerEnd */
816 m6502_genIVT,
817 m6502_genXINIT, /* genXINIT code */
818 0, /* genInitStartup */
819 m6502_reset_regparm,
820 m6502_regparm,
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 */
828 0, /* leave lt */
829 0, /* leave gt */
830 1, /* transform <= to ! > */
831 1, /* transform >= to ! < */
832 1, /* transform != to !(a == b) */
833 0, /* leave == */
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 */
841 PORT_MAGIC
844 PORT mos65c02_port =
846 TARGET_ID_MOS65C02,
847 "mos65c02",
848 "WDC 65C02", /* Target name */
849 NULL, /* Processor name */
851 glue,
852 false, /* Emit glue around main */
853 MODEL_SMALL | MODEL_LARGE,
854 MODEL_LARGE,
855 0, /* model == target */
858 _asmCmd,
860 "-plosgffwy", /* Options with debug */
861 "-plosgffw", /* Options without debug */
863 ".asm",
864 NULL /* no do_assemble function */
866 { /* Linker */
867 _linkCmd,
868 NULL,
869 NULL,
870 ".rel",
872 _crt, /* crt */
873 _libs_m65c02, /* libs */
875 { /* Peephole optimizer */
876 _m65c02_defaultRules,
877 m6502_getInstructionSize,
878 NULL,
879 NULL,
880 NULL,
881 mos6502notUsed,
882 NULL,
883 mos6502notUsedFrom,
884 NULL,
885 NULL,
886 NULL,
888 /* Sizes: char, short, int, long, long long, ptr, fptr, gptr, bit, float, max */
890 1, /* char */
891 2, /* short */
892 2, /* int */
893 4, /* long */
894 8, /* long long */
895 2, /* near ptr */
896 2, /* far ptr */
897 2, /* generic ptr */
898 2, /* func ptr */
899 0, /* banked func ptr */
900 1, /* bit */
901 4, /* float */
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
909 "CODE", // code
910 "ZP (PAG)", // data
911 NULL, // idata
912 NULL, // pdata
913 "BSS", // xdata
914 NULL, // bit
915 "RSEG (ABS)", // reg
916 "GSINIT", // static initialization
917 "OSEG (PAG, OVR)", // overlay
918 "GSFINAL", // gsfinal
919 "_CODE", // home
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.
934 { NULL, NULL },
935 0, // ABI revision
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,
953 m6502_dwarfRegNum,
954 NULL,
955 NULL,
956 4, /* addressSize */
957 14, /* regNumRet */
958 15, /* regNumSP */
959 -1, /* regNumBP */
960 1, /* offsetSP */
964 256, /* maxCount */
965 2, /* sizeofElement */
966 {8,16,32}, /* sizeofMatchJump[] */
967 {8,16,32}, /* sizeofRangeCompare[] */
968 5, /* sizeofSubtract */
969 10, /* sizeofDispatch */
971 "_",
972 m65c02_init,
973 m6502_parseOptions,
974 mos6502_options,
975 NULL,
976 m6502_finaliseOptions,
977 m6502_setDefaultOptions,
978 m6502_assignRegisters,
979 m6502_getRegName,
981 NULL,
982 m6502_keywords,
983 m65c02_genAssemblerStart, /* genAssemblerStart */
984 m6502_genAssemblerEnd, /* genAssemblerEnd */
985 m6502_genIVT,
986 m6502_genXINIT,
987 0, /* genInitStartup */
988 m6502_reset_regparm,
989 m6502_regparm,
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 */
997 0, /* leave lt */
998 0, /* leave gt */
999 1, /* transform <= to ! > */
1000 1, /* transform >= to ! < */
1001 1, /* transform != to !(a == b) */
1002 0, /* leave == */
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 */
1010 PORT_MAGIC