1#include <stdio.h>2#include <stdlib.h>3#include <string.h>45#include <scc/cstd.h>6#include <scc/scc.h>78#include "../cc2.h"9#include "arch.h"1011#define ADDR_LEN (INTIDENTSIZ+64)1213enum segment {14 CODESEG,15 DATASEG,16 BSSSEG,17 NOSEG18};1920static void src(void), dst(void), bin(void), lit(void), jmp(void);2122static struct opdata {23 void (*fun)(void);24 char *txt;25} optbl[] = {26 [ASPUSH] = {.fun = src, .txt = "push"},27 [ASPOP] = {.fun = dst, .txt = "pop"},2829 [ASRET] = {.fun = lit, .txt = "ret"},30 [ASJP] = {.fun = jmp, .txt = "jp"},31 [ASJP] = {.fun = jmp, .txt = "jr"},32 [ASBRANCH] = {0},3334 [ASMOV] = {.fun = bin, .txt = "ld"},35 [ASEXHL] = {.fun = bin, .txt = "ex"},3637 [ASADD] = {.fun = bin, .txt = "add"},38 [ASLD] = {.fun = bin, .txt = "ld"},39};4041static int curseg = NOSEG;42static unsigned long offpar, offvar;4344static void45segment(int seg)46{47 static char *txt[] = {48 [CODESEG] = "\t.text\n",49 [DATASEG] = "\t.data\n",50 [BSSSEG] = "\t.bss\n",51 };5253 if (seg == curseg)54 return;55 fputs(txt[seg], stdout);56 curseg = seg;57}5859static char *60symname(Symbol *sym)61{62 static char name[ADDR_LEN];6364 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 }7475 sprintf(name, ".%d", sym->numid);7677 return name;78}7980static void81label(Symbol *sym)82{83 int seg;84 char *name = symname(sym);8586 if (sym->type.flags & FUNF)87 seg = CODESEG;88 else if (sym->type.flags & INITF)89 seg = DATASEG;90 else91 seg = BSSSEG;92 segment(seg);9394 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 }102103 printf("%s:\n", name);104}105106static void107emitconst(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}123124static void125emittree(Node *np)126{127 if (!np)128 return;129130 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}153154static void155size2asm(Type *tp)156{157 char *s;158159 /*160 * In z80 we can ignore the alignment161 */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}182183void184deftype(Type *tp)185{186}187188void189defglobal(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}197198void199data(Node *np)200{201 size2asm(&np->type);202 emittree(np);203 putchar('\n');204}205206void207writeout(void)208{209 label(curfun);210211 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}219220void221endinit(void)222{223}224225static char *226addr2txt(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];247248 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}268269static void270lit(void)271{272 struct opdata *p = &optbl[pc->op];273274 printf("\t%s\n", p->txt);275}276277static void278bin(void)279{280 struct opdata *p = &optbl[pc->op];281 char to[ADDR_LEN], from[ADDR_LEN];282283 strcpy(from, addr2txt(&pc->from1));284 strcpy(to, addr2txt(&pc->to));285 printf("\t%s\t%s,%s\n", p->txt, from, to);286}287288static void289src(void)290{291 struct opdata *p = &optbl[pc->op];292 char from[ADDR_LEN];293294 strcpy(from, addr2txt(&pc->from1));295 printf("\t%s\t%s\n", p->txt, from);296}297298static void299dst(void)300{301 struct opdata *p = &optbl[pc->op];302 char to[ADDR_LEN];303304 strcpy(to, addr2txt(&pc->to));305 printf("\t%s\t%s\n", p->txt, to);306}307308static void309jmp(void)310{311 struct opdata *p = &optbl[pc->op];312313 printf("\t%s\t%s\n", p->txt, addr2txt(&pc->from1));314}