code.c (4580B)
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 #include <scc/cstd.h> 6 #include <scc/scc.h> 7 8 #include "../cc2.h" 9 #include "arch.h" 10 11 #define ADDR_LEN (INTIDENTSIZ+64) 12 13 enum segment { 14 CODESEG, 15 DATASEG, 16 BSSSEG, 17 NOSEG 18 }; 19 20 static void src(void), dst(void), bin(void), lit(void), jmp(void); 21 22 static struct opdata { 23 void (*fun)(void); 24 char *txt; 25 } optbl[] = { 26 [ASPUSH] = {.fun = src, .txt = "push"}, 27 [ASPOP] = {.fun = dst, .txt = "pop"}, 28 29 [ASRET] = {.fun = lit, .txt = "ret"}, 30 [ASJP] = {.fun = jmp, .txt = "jp"}, 31 [ASJP] = {.fun = jmp, .txt = "jr"}, 32 [ASBRANCH] = {0}, 33 34 [ASMOV] = {.fun = bin, .txt = "ld"}, 35 [ASEXHL] = {.fun = bin, .txt = "ex"}, 36 37 [ASADD] = {.fun = bin, .txt = "add"}, 38 [ASLD] = {.fun = bin, .txt = "ld"}, 39 }; 40 41 static int curseg = NOSEG; 42 static unsigned long offpar, offvar; 43 44 static void 45 segment(int seg) 46 { 47 static char *txt[] = { 48 [CODESEG] = "\t.text\n", 49 [DATASEG] = "\t.data\n", 50 [BSSSEG] = "\t.bss\n", 51 }; 52 53 if (seg == curseg) 54 return; 55 fputs(txt[seg], stdout); 56 curseg = seg; 57 } 58 59 static char * 60 symname(Symbol *sym) 61 { 62 static char name[ADDR_LEN]; 63 64 if (sym->name) { 65 switch (sym->kind) { 66 case SGLOB: 67 case SEXTRN: 68 snprintf(name, sizeof(name), "_%s", sym->name); 69 return name; 70 case SPRIV: 71 return sym->name; 72 } 73 } 74 75 sprintf(name, ".%d", sym->numid); 76 77 return name; 78 } 79 80 static void 81 label(Symbol *sym) 82 { 83 int seg; 84 char *name = symname(sym); 85 86 if (sym->type.flags & FUNF) 87 seg = CODESEG; 88 else if (sym->type.flags & INITF) 89 seg = DATASEG; 90 else 91 seg = BSSSEG; 92 segment(seg); 93 94 switch (sym->kind) { 95 case SEXTRN: 96 printf("\t.extrn\t%s\n", name); 97 return; 98 case SGLOB: 99 printf("\t.globl\t%s\n", name); 100 break; 101 } 102 103 printf("%s:\n", name); 104 } 105 106 static void 107 emitconst(Node *np) 108 { 109 switch (np->type.size) { 110 case 1: 111 printf("%d", (int) np->u.i & 0xFF); 112 break; 113 case 2: 114 printf("%d", (int) np->u.i & 0xFFFF); 115 break; 116 case 4: 117 printf("%ld", (long) np->u.i & 0xFFFFFFFF); 118 break; 119 default: 120 abort(); 121 } 122 } 123 124 static void 125 emittree(Node *np) 126 { 127 if (!np) 128 return; 129 130 switch (np->op) { 131 case OSTRING: 132 pprint(np->u.s); 133 free(np->u.s); 134 np->u.s = NULL; 135 break; 136 case OCONST: 137 emitconst(np); 138 break; 139 case OADDR: 140 emittree(np->left); 141 break; 142 case OLABEL: 143 case OMEM: 144 fputs(symname(np->u.sym), stdout); 145 break; 146 default: 147 emittree(np->left); 148 printf(" %c ", np->op); 149 emittree(np->right); 150 break; 151 } 152 } 153 154 static void 155 size2asm(Type *tp) 156 { 157 char *s; 158 159 /* 160 * In z80 we can ignore the alignment 161 */ 162 if (tp->flags & STRF) { 163 s = "\tDB\t"; 164 } else { 165 switch (tp->size) { 166 case 1: 167 s = "\tDB\t"; 168 break; 169 case 2: 170 s = "\tDW\t"; 171 break; 172 case 4: 173 s = "\tDD\t"; 174 break; 175 default: 176 s = "\tDS\t%lu,"; 177 break; 178 } 179 } 180 printf(s, tp->size); 181 } 182 183 void 184 deftype(Type *tp) 185 { 186 } 187 188 void 189 defglobal(Symbol *sym) 190 { 191 label(sym); 192 if (sym->kind == SEXTRN || (sym->type.flags & INITF)) 193 return; 194 size2asm(&sym->type); 195 puts("0"); 196 } 197 198 void 199 data(Node *np) 200 { 201 size2asm(&np->type); 202 emittree(np); 203 putchar('\n'); 204 } 205 206 void 207 writeout(void) 208 { 209 label(curfun); 210 211 for (pc = prog; pc; pc = pc->next) { 212 if (pc->label) 213 printf("%s:\n", symname(pc->label)); 214 if (pc->op == ASLABEL) 215 continue; 216 (*optbl[pc->op].fun)(); 217 } 218 } 219 220 void 221 endinit(void) 222 { 223 } 224 225 static char * 226 addr2txt(Addr *a) 227 { 228 static char *regnames[] = { 229 [A] = "a", 230 [B] = "b", 231 [C] = "c", 232 [D] = "d", 233 [E] = "e", 234 [H] = "h", 235 [L] = "l", 236 [IYL] = "iyl", 237 [IYH] = "iyh", 238 [AF] = "af", 239 [HL] = "hl", 240 [DE] = "de", 241 [BC] = "bc", 242 [IY] = "iy", 243 [SP] = "sp", 244 [IX] = "ix", 245 }; 246 static char addr[INTIDENTSIZ+1]; 247 248 switch (a->kind) { 249 case SREG: 250 return regnames[a->u.reg]; 251 case SINDEX: 252 sprintf(addr,"%ld(ix)", a->u.off); 253 return addr; 254 case SLABEL: 255 case STMP: 256 case SGLOB: 257 case SEXTRN: 258 case SPRIV: 259 case SLOCAL: 260 return symname(a->u.sym); 261 case SCONST: 262 sprintf(addr, "%lld", a->u.i); 263 return addr; 264 default: 265 abort(); 266 } 267 } 268 269 static void 270 lit(void) 271 { 272 struct opdata *p = &optbl[pc->op]; 273 274 printf("\t%s\n", p->txt); 275 } 276 277 static void 278 bin(void) 279 { 280 struct opdata *p = &optbl[pc->op]; 281 char to[ADDR_LEN], from[ADDR_LEN]; 282 283 strcpy(from, addr2txt(&pc->from1)); 284 strcpy(to, addr2txt(&pc->to)); 285 printf("\t%s\t%s,%s\n", p->txt, from, to); 286 } 287 288 static void 289 src(void) 290 { 291 struct opdata *p = &optbl[pc->op]; 292 char from[ADDR_LEN]; 293 294 strcpy(from, addr2txt(&pc->from1)); 295 printf("\t%s\t%s\n", p->txt, from); 296 } 297 298 static void 299 dst(void) 300 { 301 struct opdata *p = &optbl[pc->op]; 302 char to[ADDR_LEN]; 303 304 strcpy(to, addr2txt(&pc->to)); 305 printf("\t%s\t%s\n", p->txt, to); 306 } 307 308 static void 309 jmp(void) 310 { 311 struct opdata *p = &optbl[pc->op]; 312 313 printf("\t%s\t%s\n", p->txt, addr2txt(&pc->from1)); 314 }