scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

code.c (15519B)


      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 static void binary(void), unary(void), store(void), jmp(void), ret(void),
     14             branch(void), call(void), ecall(void), param(void),
     15             asalloc(void), form2local(void), blit(void), vastart(void),
     16             vaarg(void);
     17 
     18 static struct opdata {
     19 	void (*fun)(void);
     20 	char *txt;
     21 	char letter;
     22 } optbl [] = {
     23 	[ASLDSB]  =  {.fun = unary,  .txt = "loadsb", .letter = 'w'},
     24 	[ASLDUB]  =  {.fun = unary,  .txt = "loadub", .letter = 'w'},
     25 	[ASLDSH]  =  {.fun = unary,  .txt = "loadsh", .letter = 'w'},
     26 	[ASLDUH]  =  {.fun = unary,  .txt = "loaduh", .letter = 'w'},
     27 	[ASLDSW]  =  {.fun = unary,  .txt = "loadsw", .letter = 'w'},
     28 	[ASLDUW]  =  {.fun = unary,  .txt = "loaduw", .letter = 'w'},
     29 	[ASLDL]   =  {.fun = unary,  .txt = "loadl", .letter = 'l'},
     30 	[ASLDS]   =  {.fun = unary,  .txt = "loads", .letter = 's'},
     31 	[ASLDD]   =  {.fun = unary,  .txt = "loadd", .letter = 'd'},
     32 
     33 	[ASCOPYB] =  {.fun = unary,  .txt = "copy", .letter = 'b'},
     34 	[ASCOPYH] =  {.fun = unary,  .txt = "copy", .letter = 'h'},
     35 	[ASCOPYW] =  {.fun = unary,  .txt = "copy", .letter = 'w'},
     36 	[ASCOPYL] =  {.fun = unary,  .txt = "copy", .letter = 'l'},
     37 	[ASCOPYS] =  {.fun = unary,  .txt = "copy", .letter = 's'},
     38 	[ASCOPYD] =  {.fun = unary,  .txt = "copy", .letter = 'd'},
     39 
     40 	[ASSTB]   =  {.fun = store,  .txt = "store", .letter = 'b'},
     41 	[ASSTH]   =  {.fun = store,  .txt = "store", .letter = 'h'},
     42 	[ASSTW]   =  {.fun = store,  .txt = "store", .letter = 'w'},
     43 	[ASSTL]   =  {.fun = store,  .txt = "store", .letter = 'l'},
     44 	[ASSTM]   =  {.fun = blit},
     45 	[ASSTS]   =  {.fun = store,  .txt = "store", .letter = 's'},
     46 	[ASSTD]   =  {.fun = store,  .txt = "store", .letter = 'd'},
     47 
     48 	[ASADDW]  =  {.fun = binary, .txt = "add", .letter = 'w'},
     49 	[ASSUBW]  =  {.fun = binary, .txt = "sub", .letter = 'w'},
     50 	[ASMULW]  =  {.fun = binary, .txt = "mul", .letter = 'w'},
     51 	[ASMODW]  =  {.fun = binary, .txt = "rem", .letter = 'w'},
     52 	[ASUMODW] =  {.fun = binary, .txt = "urem", .letter = 'w'},
     53 	[ASDIVW]  =  {.fun = binary, .txt = "div", .letter = 'w'},
     54 	[ASUDIVW] =  {.fun = binary, .txt = "udiv", .letter = 'w'},
     55 	[ASSHLW]  =  {.fun = binary, .txt = "shl", .letter = 'w'},
     56 	[ASSHRW]  =  {.fun = binary, .txt = "sar", .letter = 'w'},
     57 	[ASUSHRW] =  {.fun = binary, .txt = "shr", .letter = 'w'},
     58 	[ASLTW]   =  {.fun = binary, .txt = "csltw", .letter = 'w'},
     59 	[ASULTW]  =  {.fun = binary, .txt = "cultw", .letter = 'w'},
     60 	[ASGTW]   =  {.fun = binary, .txt = "csgtw", .letter = 'w'},
     61 	[ASUGTW]  =  {.fun = binary, .txt = "cugtw", .letter = 'w'},
     62 	[ASLEW]   =  {.fun = binary, .txt = "cslew", .letter = 'w'},
     63 	[ASULEW]  =  {.fun = binary, .txt = "culew", .letter = 'w'},
     64 	[ASGEW]   =  {.fun = binary, .txt = "csgew", .letter = 'w'},
     65 	[ASUGEW]  =  {.fun = binary, .txt = "cugew", .letter = 'w'},
     66 	[ASEQW]   =  {.fun = binary, .txt = "ceqw", .letter = 'w'},
     67 	[ASNEW]   =  {.fun = binary, .txt = "cnew", .letter = 'w'},
     68 	[ASBANDW] =  {.fun = binary, .txt = "and", .letter = 'w'},
     69 	[ASBORW]  =  {.fun = binary, .txt = "or", .letter = 'w'},
     70 	[ASBXORW] =  {.fun = binary, .txt = "xor", .letter = 'w'},
     71 
     72 	[ASADDL]  =  {.fun = binary, .txt = "add", .letter = 'l'},
     73 	[ASSUBL]  =  {.fun = binary, .txt = "sub", .letter = 'l'},
     74 	[ASMULL]  =  {.fun = binary, .txt = "mul", .letter = 'l'},
     75 	[ASMODL]  =  {.fun = binary, .txt = "rem", .letter = 'l'},
     76 	[ASUMODL] =  {.fun = binary, .txt = "urem", .letter = 'l'},
     77 	[ASDIVL]  =  {.fun = binary, .txt = "div", .letter = 'l'},
     78 	[ASUDIVL] =  {.fun = binary, .txt = "udiv", .letter = 'l'},
     79 	[ASSHLL]  =  {.fun = binary, .txt = "shl", .letter = 'l'},
     80 	[ASSHRL]  =  {.fun = binary, .txt = "sar", .letter = 'l'},
     81 	[ASUSHRL] =  {.fun = binary, .txt = "shr", .letter = 'l'},
     82 	[ASLTL]   =  {.fun = binary, .txt = "csltl", .letter = 'w'},
     83 	[ASULTL]  =  {.fun = binary, .txt = "cultl", .letter = 'w'},
     84 	[ASGTL]   =  {.fun = binary, .txt = "csgtl", .letter = 'w'},
     85 	[ASUGTL]  =  {.fun = binary, .txt = "cugtl", .letter = 'w'},
     86 	[ASLEL]   =  {.fun = binary, .txt = "cslel", .letter = 'w'},
     87 	[ASULEL]  =  {.fun = binary, .txt = "culel", .letter = 'w'},
     88 	[ASGEL]   =  {.fun = binary, .txt = "csgel", .letter = 'w'},
     89 	[ASUGEL]  =  {.fun = binary, .txt = "cugel", .letter = 'w'},
     90 	[ASEQL]   =  {.fun = binary, .txt = "ceql", .letter = 'w'},
     91 	[ASNEL]   =  {.fun = binary, .txt = "cnel", .letter = 'w'},
     92 	[ASBANDL] =  {.fun = binary, .txt = "and", .letter = 'l'},
     93 	[ASBORL]  =  {.fun = binary, .txt = "or", .letter = 'l'},
     94 	[ASBXORL] =  {.fun = binary, .txt = "xor", .letter = 'l'},
     95 
     96 	[ASADDS]  =  {.fun = binary, .txt = "add", .letter = 's'},
     97 	[ASSUBS]  =  {.fun = binary, .txt = "sub", .letter = 's'},
     98 	[ASMULS]  =  {.fun = binary, .txt = "mul", .letter = 's'},
     99 	[ASDIVS]  =  {.fun = binary, .txt = "div", .letter = 's'},
    100 	[ASLTS]   =  {.fun = binary, .txt = "clts", .letter = 'w'},
    101 	[ASGTS]   =  {.fun = binary, .txt = "cgts", .letter = 'w'},
    102 	[ASLES]   =  {.fun = binary, .txt = "cles", .letter = 'w'},
    103 	[ASGES]   =  {.fun = binary, .txt = "cges", .letter = 'w'},
    104 	[ASEQS]   =  {.fun = binary, .txt = "ceqs", .letter = 'w'},
    105 	[ASNES]   =  {.fun = binary, .txt = "cnes", .letter = 'w'},
    106 
    107 	[ASADDD]  =  {.fun = binary, .txt = "add", .letter = 'd'},
    108 	[ASSUBD]  =  {.fun = binary, .txt = "sub", .letter = 'd'},
    109 	[ASMULD]  =  {.fun = binary, .txt = "mul", .letter = 'd'},
    110 	[ASDIVD]  =  {.fun = binary, .txt = "div", .letter = 'd'},
    111 	[ASLTD]   =  {.fun = binary, .txt = "cltd", .letter = 'w'},
    112 	[ASGTD]   =  {.fun = binary, .txt = "cgtd", .letter = 'w'},
    113 	[ASLED]   =  {.fun = binary, .txt = "cled", .letter = 'w'},
    114 	[ASGED]   =  {.fun = binary, .txt = "cged", .letter = 'w'},
    115 	[ASEQD]   =  {.fun = binary, .txt = "ceqd", .letter = 'w'},
    116 	[ASNED]   =  {.fun = binary, .txt = "cned", .letter = 'w'},
    117 
    118 	[ASEXTBW] =  {.fun = unary, .txt = "extsb", .letter = 'w'},
    119 	[ASUEXTBW]=  {.fun = unary, .txt = "extub", .letter = 'w'},
    120 	[ASEXTBL] =  {.fun = unary, .txt = "extsb", .letter = 'l'},
    121 	[ASUEXTBL]=  {.fun = unary, .txt = "extub", .letter = 'l'},
    122 	[ASEXTHW] =  {.fun = unary, .txt = "extsh", .letter = 'w'},
    123 	[ASUEXTHW]=  {.fun = unary, .txt = "extuh", .letter = 'w'},
    124 	[ASEXTHL] =  {.fun = unary, .txt = "extsh", .letter = 'l'},
    125 	[ASUEXTHL]=  {.fun = unary, .txt = "extuh", .letter = 'l'},
    126 	[ASEXTWL] =  {.fun = unary, .txt = "extsw", .letter = 'l'},
    127 	[ASUEXTWL]=  {.fun = unary, .txt = "extuw", .letter = 'l'},
    128 
    129 	[ASSTOL] = {.fun = unary, .txt = "stosi", .letter = 'l'},
    130 	[ASSTOUL] = {.fun = unary, .txt = "stoui", .letter = 'l'},
    131 	[ASSTOW] = {.fun = unary, .txt = "stosi", .letter = 'w'},
    132 	[ASSTOUW] = {.fun = unary, .txt = "stoui", .letter = 'w'},
    133 	[ASDTOL] = {.fun = unary, .txt = "dtosi", .letter = 'l'},
    134 	[ASDTOUL] = {.fun = unary, .txt = "dtoui", .letter = 'l'},
    135 	[ASDTOW] = {.fun = unary, .txt = "dtosi", .letter = 'w'},
    136 	[ASDTOUW] = {.fun = unary, .txt = "dtoui", .letter = 'w'},
    137 
    138 	[ASSWTOD] = {.fun = unary, .txt = "swtof", .letter = 'd'},
    139 	[ASUWTOD] = {.fun = unary, .txt = "uwtof", .letter = 'd'},
    140 	[ASSWTOS] = {.fun = unary, .txt = "swtof", .letter = 's'},
    141 	[ASUWTOS] = {.fun = unary, .txt = "uwtof", .letter = 's'},
    142 	[ASSLTOD] = {.fun = unary, .txt = "sltof", .letter = 'd'},
    143 	[ASULTOD] = {.fun = unary, .txt = "ultof", .letter = 'd'},
    144 	[ASSLTOS] = {.fun = unary, .txt = "sltof", .letter = 's'},
    145 	[ASULTOS] = {.fun = unary, .txt = "ultof", .letter = 's'},
    146 
    147 	[ASEXTS] = {.fun = unary, .txt = "exts", .letter = 'd'},
    148 	[ASTRUNCD] = {.fun = unary, .txt = "truncd", .letter = 's'},
    149 
    150 	[ASNEGL] = {.fun = unary, .txt = "neg", .letter ='l'},
    151 	[ASNEGW] = {.fun = unary, .txt = "neg", .letter ='w'},
    152 	[ASNEGS] = {.fun = unary, .txt = "neg", .letter ='s'},
    153 	[ASNEGD] = {.fun = unary, .txt = "neg", .letter ='d'},
    154 
    155 	[ASBRANCH] = {.fun = branch},
    156 	[ASJMP]  = {.fun = jmp},
    157 	[ASRET]  = {.fun = ret},
    158 	[ASCALL] = {.fun = call},
    159 	[ASCALLE] = {.fun = ecall, .txt = ")"},
    160 	[ASCALLEX] = {.fun = ecall, .txt = ", ...)"},
    161 	[ASPAR] = {.fun = param, .txt = "%s %s, "},
    162 	[ASPARE] = {.fun = param, .txt = "%s %s"},
    163 	[ASALLOC] = {.fun = asalloc},
    164 	[ASFORM] = {.fun = form2local},
    165 
    166 	[ASVSTAR] = {.fun = vastart},
    167 	[ASVARG] = {.fun = vaarg},
    168 };
    169 
    170 static char buff[ADDR_LEN];
    171 /*
    172  * : is for user-defined Aggregate Types
    173  * $ is for globals (represented by a pointer)
    174  * % is for function-scope temporaries
    175  * @ is for block labels
    176  */
    177 static char
    178 sigil(Symbol *sym)
    179 {
    180 	switch (sym->kind) {
    181 	case SEXTRN:
    182 	case SGLOB:
    183 	case SPRIV:
    184 	case SLOCAL:
    185 		return '$';
    186 	case SAUTO:
    187 	case STMP:
    188 		return '%';
    189 	case SLABEL:
    190 		return '@';
    191 	default:
    192 		abort();
    193 	}
    194 }
    195 
    196 static char *
    197 symname(Symbol *sym)
    198 {
    199 	char c = sigil(sym);
    200 
    201 	if (sym->name) {
    202 		switch (sym->kind) {
    203 		case SEXTRN:
    204 		case SGLOB:
    205 			sprintf(buff, "%c%s", c, sym->name);
    206 			return buff;
    207 		case SLOCAL:
    208 		case SPRIV:
    209 		case SAUTO:
    210 			sprintf(buff, "%c%s.L%u", c, sym->name, sym->id);
    211 			return buff;
    212 		default:
    213 			abort();
    214 		}
    215 	}
    216 	sprintf(buff, "%c.L%u", c, sym->numid);
    217 
    218 	return buff;
    219 }
    220 
    221 static void
    222 emitconst(Node *np)
    223 {
    224 	switch (np->type.size) {
    225 	case 1:
    226 		printf("%d", (int) np->u.i & 0xFF);
    227 		break;
    228 	case 2:
    229 		printf("%d", (int) np->u.i & 0xFFFF);
    230 		break;
    231 	case 4:
    232 		printf("%ld", (long) np->u.i & 0xFFFFFFFF);
    233 		break;
    234         case 8:
    235                 printf("%lld", (long long) np->u.i);
    236                 break;
    237 	default:
    238 		abort();
    239 	}
    240 }
    241 
    242 static void
    243 emittree(Node *np)
    244 {
    245 	if (!np)
    246 		return;
    247 
    248 	switch (np->op) {
    249 	case OSTRING:
    250 		pprint(np->u.s);
    251 		free(np->u.s);
    252 		np->u.s = NULL;
    253 		break;
    254 	case OCONST:
    255 		emitconst(np);
    256 		break;
    257 	case OADDR:
    258 		emittree(np->left);
    259 		break;
    260 	case OMEM:
    261 		fputs(symname(np->u.sym), stdout);
    262 		break;
    263 	default:
    264 		emittree(np->left);
    265 		printf(" %c ", np->op);
    266 		emittree(np->right);
    267 		break;
    268 	}
    269 }
    270 
    271 static char *
    272 size2asm(Type *tp)
    273 {
    274         static char spec[ADDR_LEN];
    275 
    276 	if (tp->flags & STRF) {
    277 		return "b";
    278 	} else if (tp->flags & INTF) {
    279 		switch (tp->size) {
    280 		case 1:
    281 			return "b";
    282 		case 2:
    283 			return "h";
    284 		case 4:
    285 			return "w";
    286 		case 8:
    287 			return "l";
    288 		}
    289 	} else if (tp->flags & FLOATF) {
    290 		if (tp->size == 4)
    291 			return "s";
    292 		else if (tp->size == 8)
    293 			return "d";
    294 	}
    295 
    296 	abort();
    297 }
    298 
    299 void
    300 defglobal(Symbol *sym)
    301 {
    302 	Type *tp = &sym->type;
    303 
    304 	if (sym->kind == SEXTRN)
    305 		return;
    306 	if (sym->kind == SGLOB)
    307 		fputs("export ", stdout);
    308 	if ((tp->flags & INITF) == 0)
    309 		fputs("common ", stdout);
    310 
    311 	printf("data %s = align %d {\n",
    312 	       symname(sym),
    313 	       tp->align);
    314 	if ((tp->flags & INITF) == 0)
    315 		printf("\tz\t%lu\n}\n", tp->size);
    316 }
    317 
    318 void
    319 defpar(Symbol *sym)
    320 {
    321 	if (sym->kind == SREG)
    322 		sym->kind = SAUTO;
    323 	sym->type.flags |= PARF;
    324 }
    325 
    326 void
    327 defvar(Symbol *sym)
    328 {
    329 	if (sym->kind == SREG)
    330 		sym->kind = SAUTO;
    331 }
    332 
    333 void
    334 data(Node *np)
    335 {
    336 	printf("\t%s\t", size2asm(&np->type));
    337 	emittree(np);
    338 	putchar(',');
    339 	putchar('\n');
    340 }
    341 
    342 static char *
    343 size2stack(Type *tp)
    344 {
    345 	static char spec[ADDR_LEN];
    346 
    347 	if (tp->flags & INTF) {
    348 		switch (tp->size) {
    349 		case 1:
    350 		case 2:
    351 		case 4:
    352 			return "w";
    353 		case 8:
    354 			return "l";
    355 		}
    356 	} else if (tp->flags & FLOATF) {
    357 		if (tp->size == 4)
    358 			return "s";
    359 		else if (tp->size == 8)
    360 			return "d";
    361 	} else if (tp->flags & (ARRF|AGGRF)) {
    362 		sprintf(spec, ":.%u", tp->id);
    363 		return spec;
    364 	} else if (tp->size == 0) {
    365 		return "w";
    366 	}
    367 	abort();
    368 }
    369 
    370 void
    371 deftype(Type *tp)
    372 {
    373 	printf("type :.%u = align %d { %lu }\n",
    374 	       tp->id, tp->align, tp->size);
    375 }
    376 
    377 static void
    378 getbblocks(void)
    379 {
    380 	Inst *i;
    381 
    382 	if (!prog)
    383 		return;
    384 
    385 	prog->flags |= BBENTRY;
    386 	for (pc = prog; pc; pc = pc->next) {
    387 		switch (pc->op) {
    388 		case ASBRANCH:
    389 			i = pc->from2.u.sym->u.inst;
    390 			i->flags |= BBENTRY;
    391 		case ASJMP:
    392 			i = pc->from1.u.sym->u.inst;
    393 			i->flags |= BBENTRY;
    394 		case ASRET:
    395 			if (pc->next)
    396 				pc->next->flags |= BBENTRY;
    397 			break;
    398 		}
    399 	}
    400 }
    401 
    402 void
    403 writeout(void)
    404 {
    405 	Symbol *p;
    406 	Type *tp;
    407 	char *sep;
    408 	int haslabel = 0;
    409 
    410 	getbblocks();
    411 
    412 	if (curfun->kind == SGLOB)
    413 		fputs("export ", stdout);
    414 	printf("function %s %s(", size2stack(&curfun->rtype), symname(curfun));
    415 
    416 	/* declare formal parameters */
    417 	sep = "";
    418 	for (p = locals; p; p = p->next) {
    419 		if ((p->type.flags & PARF) == 0)
    420 			continue;
    421 		printf("%s%s %s%s",
    422 		       sep, size2stack(&p->type),
    423 		       symname(p),
    424 		       (p->type.flags & AGGRF) ? "" : ".val");
    425 		sep = ",";
    426 	}
    427 	printf("%s)\n{\n", (curfun->type.flags&ELLIPS) ? ", ..." : "");
    428 
    429 	/* emit assembler instructions */
    430 	for (pc = prog; pc; pc = pc->next) {
    431 		if (pc->label) {
    432 			haslabel = 1;
    433 			printf("%s\n", symname(pc->label));
    434 		}
    435 		if (pc->op == ASLABEL)
    436 			continue;
    437 		if (pc->flags&BBENTRY && !haslabel)
    438 			printf("%s\n", symname(newlabel()));
    439 		(*optbl[pc->op].fun)();
    440 		if (!pc->label)
    441 			haslabel = 0;
    442 	}
    443 
    444 	puts("}");
    445 }
    446 
    447 static char *
    448 addr2txt(Addr *a)
    449 {
    450 	switch (a->kind) {
    451 	case SCONST:
    452 		sprintf(buff, "%llu", (unsigned long long) a->u.i);
    453 		return buff;
    454 	case SAUTO:
    455 	case SLABEL:
    456 	case STMP:
    457 	case SGLOB:
    458 	case SEXTRN:
    459 	case SPRIV:
    460 	case SLOCAL:
    461 		return symname(a->u.sym);
    462 	default:
    463 		abort();
    464 	}
    465 }
    466 
    467 static void
    468 binary(void)
    469 {
    470 	struct opdata *p = &optbl[pc->op];
    471 	char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN];
    472 
    473 	strcpy(to, addr2txt(&pc->to));
    474 	strcpy(from1, addr2txt(&pc->from1));
    475 	strcpy(from2, addr2txt(&pc->from2));
    476 	printf("\t%s =%c\t%s\t%s,%s\n", to, p->letter, p->txt, from1, from2);
    477 }
    478 
    479 static void
    480 blit(void)
    481 {
    482 	Type *tp = &pc->to.u.sym->type;
    483 	char to[ADDR_LEN], from[ADDR_LEN];
    484 
    485 	strcpy(to, addr2txt(&pc->to));
    486 	strcpy(from, addr2txt(&pc->from1));
    487 	printf("\t\tblit\t%s,%s,%lu\n", from, to, tp->size);
    488 }
    489 
    490 static void
    491 store(void)
    492 {
    493 	struct opdata *p = &optbl[pc->op];
    494 	char to[ADDR_LEN], from[ADDR_LEN];
    495 
    496 	strcpy(to, addr2txt(&pc->to));
    497 	strcpy(from, addr2txt(&pc->from1));
    498 	printf("\t\t%s%c\t%s,%s\n", p->txt, p->letter, from, to);
    499 }
    500 
    501 static void
    502 unary(void)
    503 {
    504 	struct opdata *p = &optbl[pc->op];
    505 	char to[ADDR_LEN], from[ADDR_LEN];
    506 
    507 	strcpy(to, addr2txt(&pc->to));
    508 	strcpy(from, addr2txt(&pc->from1));
    509 	printf("\t%s =%c\t%s\t%s\n", to, p->letter, p->txt, from);
    510 }
    511 
    512 static void
    513 call(void)
    514 {
    515 	char to[ADDR_LEN], from[ADDR_LEN];
    516 	Symbol *sym = pc->to.u.sym;
    517 
    518 	strcpy(to, addr2txt(&pc->to));
    519 	strcpy(from, addr2txt(&pc->from1));
    520 	printf("\t%s =%s\tcall\t%s(",
    521 	       to, size2stack(&sym->type), from);
    522 }
    523 
    524 static void
    525 param(void)
    526 {
    527 	Symbol *sym = pc->from2.u.sym;
    528 
    529 	printf(optbl[pc->op].txt,
    530 	       size2stack(&sym->type), addr2txt(&pc->from1));
    531 }
    532 
    533 static void
    534 ecall(void)
    535 {
    536 	struct opdata *p = &optbl[pc->op];
    537 
    538 	puts(p->txt);
    539 }
    540 
    541 static void
    542 ret(void)
    543 {
    544 	if (pc->from1.kind == SNONE)
    545 		puts("\t\tret");
    546 	else
    547 		printf("\t\tret\t%s\n", addr2txt(&pc->from1));
    548 }
    549 
    550 static void
    551 jmp(void)
    552 {
    553 	printf("\t\tjmp\t%s\n", addr2txt(&pc->from1));
    554 }
    555 
    556 static void
    557 branch(void)
    558 {
    559 	char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN];
    560 
    561 	strcpy(to, addr2txt(&pc->to));
    562 	strcpy(from1, addr2txt(&pc->from1));
    563 	strcpy(from2, addr2txt(&pc->from2));
    564 	printf("\t\tjnz\t%s,%s,%s\n", to, from1, from2);
    565 }
    566 
    567 static void
    568 vastart(void)
    569 {
    570 	printf("\t\tvastart %s\n", addr2txt(&pc->from1));
    571 }
    572 
    573 static void
    574 vaarg(void)
    575 {
    576 	Symbol *sym = pc->to.u.sym;
    577 	Type *tp = &sym->type;
    578 	char to[ADDR_LEN], from[ADDR_LEN];
    579 
    580 	strcpy(to, addr2txt(&pc->to));
    581 	strcpy(from, addr2txt(&pc->from1));
    582 	printf("\t\t%s =%s vaarg %s\n", to, size2asm(tp), from);
    583 }
    584 
    585 static void
    586 asalloc(void)
    587 {
    588 	Symbol *sym = pc->to.u.sym;
    589 	Type *tp = &sym->type;
    590 	extern Type ptrtype;
    591 
    592 	printf("\t%s =%s\talloc%d\t%lu\n",
    593 	       symname(sym), size2asm(&ptrtype), tp->align+3 & ~3, tp->size);
    594 }
    595 
    596 static void
    597 form2local(void)
    598 {
    599 	Symbol *sym = pc->to.u.sym;
    600 	Type *tp = &sym->type;
    601 	char *name = symname(sym);
    602 
    603 	printf("\t\tstore%s\t%s.val,%s\n", size2asm(tp), name, name);
    604 }
    605 
    606 void
    607 endinit(void)
    608 {
    609 	puts("}");
    610 }