PulkoMandy | 17fc759 | 2022-07-28 18:27:54 +0200 | [diff] [blame^] | 1 | /* MEGA65 / 45GS02 backend for vbcc |
| 2 | (c) Volker Barthelmann 2020 |
| 3 | (c) Paul Gardner-Stephen 2020 |
| 4 | |
| 5 | */ |
| 6 | |
| 7 | /* built-time configurable options: */ |
| 8 | #define NUM_GPRS 32 |
| 9 | #define NUM_PAIRS (NUM_GPRS/2) |
| 10 | #define NUM_BIG 4 |
| 11 | #define NUM_BIGP (NUM_BIG/2) |
| 12 | #define FIXED_SP 1 |
| 13 | |
| 14 | #include "dt.h" |
| 15 | |
| 16 | #undef CHAR |
| 17 | #undef SHORT |
| 18 | #undef INT |
| 19 | #undef LONG |
| 20 | #undef LLONG |
| 21 | #undef FLOAT |
| 22 | #undef DOUBLE |
| 23 | #undef LDOUBLE |
| 24 | #undef VOID |
| 25 | #undef POINTER |
| 26 | #undef ARRAY |
| 27 | #undef STRUCT |
| 28 | #undef UNION |
| 29 | #undef ENUM |
| 30 | #undef FUNKT |
| 31 | #undef BOOL |
| 32 | #undef MAXINT |
| 33 | #undef MAX_TYPE |
| 34 | |
| 35 | #define CHAR 1 |
| 36 | #define SHORT 2 |
| 37 | #define INT 3 |
| 38 | #define LONG 4 |
| 39 | #define LLONG 5 |
| 40 | #define FLOAT 6 |
| 41 | #define DOUBLE 7 |
| 42 | #define LDOUBLE 8 |
| 43 | #define VOID 9 |
| 44 | #define POINTER 10 |
| 45 | #define FPOINTER 11 |
| 46 | #define HPOINTER 12 |
| 47 | #define ARRAY 13 |
| 48 | #define STRUCT 14 |
| 49 | #define UNION 15 |
| 50 | #define ENUM 16 |
| 51 | #define FUNKT 17 |
| 52 | #define BOOL 18 |
| 53 | |
| 54 | #define MAXINT 19 |
| 55 | |
| 56 | #define MAX_TYPE MAXINT |
| 57 | |
| 58 | |
| 59 | #define POINTER_TYPE(x) pointer_type(x) |
| 60 | #define POINTER_VARADR(x) pointer_varadr(x) |
| 61 | extern int pointer_type(); |
| 62 | extern int pointer_varadr(); |
| 63 | #define ISPOINTER(x) ((x&NQ)>=POINTER&&(x&NQ)<=HPOINTER) |
| 64 | #define ISSCALAR(x) ((x&NQ)>=CHAR&&(x&NQ)<=HPOINTER) |
| 65 | #define ISINT(x) ((x&NQ)>=CHAR&&(x&NQ)<=LLONG) |
| 66 | #define PTRDIFF_T(x) ((x)==HPOINTER?LONG:INT) |
| 67 | |
| 68 | typedef zllong zmax; |
| 69 | typedef zullong zumax; |
| 70 | |
| 71 | union atyps{ |
| 72 | zchar vchar; |
| 73 | zuchar vuchar; |
| 74 | zshort vshort; |
| 75 | zushort vushort; |
| 76 | zint vint; |
| 77 | zuint vuint; |
| 78 | zlong vlong; |
| 79 | zulong vulong; |
| 80 | zllong vllong; |
| 81 | zullong vullong; |
| 82 | zmax vmax; |
| 83 | zumax vumax; |
| 84 | zfloat vfloat; |
| 85 | zdouble vdouble; |
| 86 | zldouble vldouble; |
| 87 | }; |
| 88 | |
| 89 | |
| 90 | /* internally used by the backend */ |
| 91 | #define FIRST_GPR 10 |
| 92 | #define LAST_GPR (FIRST_GPR+NUM_GPRS-1) |
| 93 | #define FIRST_PAIR (LAST_GPR+1) |
| 94 | #define LAST_PAIR (FIRST_PAIR+NUM_PAIRS-1) |
| 95 | #define FIRST_BIG (LAST_PAIR+1) |
| 96 | #define LAST_BIG (FIRST_BIG+NUM_BIG-1) |
| 97 | #define FIRST_BIGP (LAST_BIG+1) |
| 98 | #define LAST_BIGP (FIRST_BIGP+NUM_BIGP-1) |
| 99 | |
| 100 | /* This struct can be used to implement machine-specific */ |
| 101 | /* addressing-modes. */ |
| 102 | /* Currently possible are (const,gpr) and (gpr,gpr) */ |
| 103 | struct AddressingMode{ |
| 104 | int flags; |
| 105 | int base; |
| 106 | int idx; |
| 107 | long offset; |
| 108 | void *v; |
| 109 | }; |
| 110 | |
| 111 | /* The number of registers of the target machine. */ |
| 112 | #define MAXR LAST_BIGP |
| 113 | |
| 114 | /* Number of commandline-options the code-generator accepts. */ |
| 115 | #define MAXGF 20 |
| 116 | |
| 117 | /* If this is set to zero vbcc will not generate ICs where the */ |
| 118 | /* target operand is the same as the 2nd source operand. */ |
| 119 | /* This can sometimes simplify the code-generator, but usually */ |
| 120 | /* the code is better if the code-generator allows it. */ |
| 121 | #define USEQ2ASZ 1 |
| 122 | |
| 123 | /* This specifies the smallest integer type that can be added to a */ |
| 124 | /* pointer. */ |
| 125 | #define MINADDI2P CHAR |
| 126 | |
| 127 | /* If the bytes of an integer are ordered most significant byte */ |
| 128 | /* byte first and then decreasing set BIGENDIAN to 1. */ |
| 129 | #define BIGENDIAN 0 |
| 130 | |
| 131 | /* If the bytes of an integer are ordered lest significant byte */ |
| 132 | /* byte first and then increasing set LITTLEENDIAN to 1. */ |
| 133 | #define LITTLEENDIAN 1 |
| 134 | |
| 135 | /* Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive. */ |
| 136 | |
| 137 | /* If switch-statements should be generated as a sequence of */ |
| 138 | /* SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1. */ |
| 139 | /* This can yield better code on some machines. */ |
| 140 | #define SWITCHSUBS 0 |
| 141 | |
| 142 | /* In optimizing compilation certain library memcpy/strcpy-calls */ |
| 143 | /* with length known at compile-time will be inlined using an */ |
| 144 | /* ASSIGN-IC if the size is less or equal to INLINEMEMCPY. */ |
| 145 | /* The type used for the ASSIGN-IC will be UNSIGNED|CHAR. */ |
| 146 | #define INLINEMEMCPY 1024 |
| 147 | |
| 148 | /* Parameters are sometimes passed in registers without __reg. */ |
| 149 | #define HAVE_REGPARMS 1 |
| 150 | |
| 151 | /* Parameters on the stack should be pushed in order rather than */ |
| 152 | /* in reverse order. */ |
| 153 | #define ORDERED_PUSH FIXED_SP |
| 154 | |
| 155 | /* Structure for reg_parm(). */ |
| 156 | struct reg_handle{ |
| 157 | int regs; |
| 158 | int bregs; |
| 159 | }; |
| 160 | |
| 161 | /* We have some target-specific variable attributes. */ |
| 162 | #define HAVE_TARGET_ATTRIBUTES |
| 163 | |
| 164 | /* We have target-specific pragmas */ |
| 165 | #define HAVE_TARGET_PRAGMAS |
| 166 | |
| 167 | /* We keep track of all registers modified by a function. */ |
| 168 | #define HAVE_REGS_MODIFIED 1 |
| 169 | |
| 170 | /* We have a implement our own cost-functions to adapt |
| 171 | register-allocation */ |
| 172 | #define HAVE_TARGET_RALLOC 1 |
| 173 | #define cost_move_reg(x,y) 3 |
| 174 | // MEGA65 CPU has one wait-state on reads when CPU is at full speed |
| 175 | #define cost_load_reg(x,y) 5 |
| 176 | #define cost_save_reg(x,y) 4 |
| 177 | #define cost_pushpop_reg(x) 6 |
| 178 | |
| 179 | /* size of buffer for asm-output, this can be used to do |
| 180 | peephole-optimizations of the generated assembly-output */ |
| 181 | #define EMIT_BUF_LEN 1024 /* should be enough */ |
| 182 | /* number of asm-output lines buffered */ |
| 183 | #define EMIT_BUF_DEPTH 8 |
| 184 | |
| 185 | /* We have no asm_peephole to optimize assembly-output */ |
| 186 | #define HAVE_TARGET_PEEPHOLE 1 |
| 187 | |
| 188 | /* we do not have a mark_eff_ics function, this is used to prevent |
| 189 | optimizations on code which can already be implemented by efficient |
| 190 | assembly */ |
| 191 | #undef HAVE_TARGET_EFF_IC |
| 192 | |
| 193 | /* we have additional types */ |
| 194 | #define HAVE_EXT_TYPES |
| 195 | #define HAVE_TGT_PRINTVAL |
| 196 | |
| 197 | /* we do not need extra elements in the IC */ |
| 198 | #undef HAVE_EXT_IC |
| 199 | |
| 200 | /* we do not use unsigned int as size_t (but unsigned long, the default) */ |
| 201 | #define HAVE_INT_SIZET 1 |
| 202 | |
| 203 | /* we do not need register-pairs */ |
| 204 | #define HAVE_REGPAIRS 1 |
| 205 | |
| 206 | |
| 207 | /* do not create CONVERT ICs from integers smaller than int to floats */ |
| 208 | #define MIN_INT_TO_FLOAT_TYPE INT |
| 209 | |
| 210 | /* do not create CONVERT ICs from floats to ints smaller than int */ |
| 211 | #define MIN_FLOAT_TO_INT_TYPE INT |
| 212 | |
| 213 | /* do not create CONVERT_ICs from floats to unsigned integers */ |
| 214 | #define AVOID_FLOAT_TO_UNSIGNED 0 |
| 215 | |
| 216 | /* do not create CONVERT_ICs from unsigned integers to floats */ |
| 217 | #define AVOID_UNSIGNED_TO_FLOAT 0 |
| 218 | |
| 219 | /* convert multiplications/division by powers of two to shifts */ |
| 220 | #define HAVE_POF2OPT 1 |
| 221 | |
| 222 | /* We use builtin libcalls for some operations */ |
| 223 | #define HAVE_LIBCALLS 1 |
| 224 | |
| 225 | /* Use char for return of comparison libcalls */ |
| 226 | #define LIBCALL_CMPTYPE CHAR |
| 227 | |
| 228 | /* We prefer BNE rather than BGT. */ |
| 229 | #define HAVE_WANTBNE 1 |
| 230 | |
| 231 | #define BESTCOPYT CHAR |
| 232 | |
| 233 | #define HAVE_AOS4 1 |
| 234 | |
| 235 | #define CHARCONV(x) cbmconv(x) |
| 236 | unsigned char cbmconv(unsigned char); |
| 237 | |
| 238 | #define ALLOCVLA_REG FIRST_PAIR |
| 239 | #define ALLOCVLA_INLINEASM "\tlda\tsp\n"\ |
| 240 | "\tsec\n"\ |
| 241 | "\tsbc\tr0\n"\ |
| 242 | "\tsta\tsp\n"\ |
| 243 | "\tlda\tsp+1\n"\ |
| 244 | "\tsbc\tr1\n"\ |
| 245 | "\tsta\tsp+1\n"\ |
| 246 | "\tlda\tsp\n"\ |
| 247 | "\tclc\n"\ |
| 248 | "\tldx\tsp+1\n"\ |
| 249 | "\tadc\t#___fo\n"\ |
| 250 | "\tbcc\t*+3\n"\ |
| 251 | "\tinx\n" |
| 252 | |
| 253 | #define FREEVLA_REG FIRST_PAIR |
| 254 | #define FREEVLA_INLINEASM "\tlda\tr0\n"\ |
| 255 | "\tsta\tsp\n"\ |
| 256 | "\tlda\tr1\n"\ |
| 257 | "\tsta\tsp+1\n" |
| 258 | |
| 259 | #define OLDSPVLA_INLINEASM "\tlda\tsp+1\n"\ |
| 260 | "\ttax\n"\ |
| 261 | "\tlda\tsp" |
| 262 | |
| 263 | #define FPVLA_REG (LAST_PAIR-2) |
| 264 | |
| 265 | #define HAVE_TARGET_VARHOOK_POST 1 |
| 266 | |
| 267 | #define HAVE_DECIDE_REVERSE 1 |
| 268 | |
| 269 | #define HAVE_TARGET_EFF_IC 1 |