shithub: scc

ref: 5ee0c779060595407f6042414f4bf9c1165634b9
dir: /cc2/code.c/

View raw version

#include <stdarg.h>
#include <stdlib.h>
#include <inttypes.h>
#include <stdio.h>

#include "../inc/cc.h"
#include "cc2.h"

static char *regnames[] = {
	[AF] = "AF",
	[HL] = "HL", [DE] = "DE", [BC] = "BC",
	[IX] = "IX", [IY] = "IY", [SP] = "SP",
	[A]  = "A",
	[B]  = "B", [C]  = "C",
	[D]  = "D",  [E]  = "E",
	[H]  = "H",  [L]  = "L",
	[IYL]= "IYL",[IYH]= "IYH"
};

static void inst0(void), inst1(void), inst2(void);

static void (*instcode[])(void) = {
	[LDW] = inst2,
	[LDL] = inst2,
	[LDH] = inst2,
	[LDI] = inst2,
	[MOV] = inst2,
	[ADD] = inst2,
	[PUSH] = inst1,
	[POP] = inst1,
	[RET] = inst0,
	[NOP] = inst0,
	[INC] = inst1
};

static char *insttext[] = {
	[LDW] = "LD",
	[LDL] = "LD",
	[LDH] = "LD",
	[LDI] = "LD",
	[MOV] = "LD",
	[ADD] = "ADD",
	[PUSH] = "PUSH",
	[POP] = "POP",
	[RET] = "RET",
	[NOP] = "NOP",
	[INC] = "INC"
};

typedef struct inst Inst;
typedef struct addr Addr;

struct addr {
	char kind;
	union {
		uint8_t reg;
		TINT i;
		Inst *pc;
		Symbol *sym;
	} u;
};

struct inst {
	char op;
	Addr from, to;
	Inst *next;
};
Inst *prog, *pc;

Inst *
nextpc(void)
{
	Inst *new;

	new = xmalloc(sizeof(*new));
	if (!pc)
		prog = new;
	else
		pc->next = new;
	pc = new;
	pc->op = NOP;
	pc->to.kind = NONE;
	pc->from.kind = NONE;
	pc->next = NULL;
	return pc;
}

void
addr(char op, Node *np, Addr *addr)
{
	switch (addr->kind = np->op) {
	case REG:
		addr->u.reg = np->u.reg;
		break;
	case CONST:
		addr->u.i = np->u.imm;
		break;
	case AUTO:
		addr->u.i = np->u.sym->u.v.off;
		break;
	case MEM:
		addr->u.sym = np->u.sym;
		break;
	case INDEX:
		break;
	default:
		abort();
	}
}

void
code(uint8_t op, Node *to, Node *from)
{
	Inst *ip;

	ip = nextpc();
	if (from)
		addr(op, from, &ip->from);
	if (to)
		addr(op, to, &ip->to);
	ip->op = op;
}

void
writeout(void)
{
	if (!prog)
		return;

	for (pc = prog; pc; pc = pc->next)
		(*instcode[pc->op])();
}

static void
addr2txt(char op, Addr *a)
{
	Symbol *sym;
	char *fmt;

	switch (a->kind) {
	case REG:
		fputs(regnames[a->u.reg], stdout);
		break;
	case CONST:
		printf("%d", a->u.i);
		break;
	case PAR:
	case AUTO:
		printf("(IX%+d)", a->u.i);
		break;
	case INDEX:
		fputs("(HL)", stdout);
		break;
	case MEM:
		sym = a->u.sym;
		if (sym->name)
			printf((op == LDI) ? "%s" : "(%s)", sym);
		else
			printf((op == LDI) ? "T%u" : "(T%u)", sym->id);
		break;
	default:
		abort();
	}
}

static void
inst0(void)
{
	printf("\t%s\n", insttext[pc->op]);
}

static void
inst1(void)
{
	char op = pc->op;

	printf("\t%s\t", insttext[op]);
	addr2txt(op, (pc->to.kind != NONE) ? &pc->to : &pc->from);
	putchar('\n');
}

static void
inst2(void)
{
	char op = pc->op;

	printf("\t%s\t", insttext[op]);
	addr2txt(op, &pc->to);
	putchar(',');
	addr2txt(op, &pc->from);
	putchar('\n');
}