code.c - scc - simple c99 compiler
 (HTM) git clone git://git.simple-cc.org/scc
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Submodules
 (DIR) README
 (DIR) LICENSE
       ---
       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 }