view s-code-sparc.c @ 24:aecd80408312 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Wed, 26 Oct 2022 17:37:18 +0900
parents e5c8532ab38d
children
line wrap: on
line source

/*
    Very Simple Code Generator for Sun SPARC
	$Id$
 */

#include "s-compile.h"

int  label = 0;
char *comments = "#####";

static
char *reg_name[] = {
    "%g0","%g1","%g2","%g3","%g4","%g5","%g6","%g7",
    "%i0","%i1","%i2","%i3","%i4","%i5","%i6","%i7",
    "%l0","%l1","%l2","%l3","%l4","%l5","%l6","%l7",
    "%o0","%o1","%o2","%o3","%o4","%o5","%o6","%o7"
};
#define O0RN 24
#define MAX_REGISTER 32

static int  current_register;
static char reg_stack[MAX_REGISTER];
static int  reg_sp;
static char *crn;  /* current register name */
static char *lrn;  /* last register name */

static char regs[MAX_REGISTER];

static int
get_register() {
    int i;
    for(i=0;i<MAX_REGISTER;i++) {
	if (! regs[i]) {
	    regs[i]=1;
	    return i;
	}
    }
    error("Expression too complex (register overflow)");
    return -1;
}

static void
free_register(i) {
    regs[i]=0;
}

/* simple version
static char *
pop_register() {
    int i;
    i = reg_stack[--reg_sp];
    regs[i]=0;
    lrn = reg_name[i];
    return crn;
}
 */

static char *
pop_register() {
    int i,j;

    j = current_register;
    i = reg_stack[--reg_sp];
    lrn = reg_name[i];

    free_register(j);

    current_register = i;
    crn = reg_name[i];
    return reg_name[j];
}

static
char *intro[] = {
    "gcc2_compiled.:\n",
    "___gnu_compiled_c:\n",
    ".text\n",
    "        .align 4\n",
    "        .global _main\n",
    "        .proc   04\n",
    "_main:\n",
    "        !#PROLOGUE# 0\n",
    "        save %sp,-104,%sp\n",
    "        !#PROLOGUE# 1\n",
    "        call ___main,0\n",
    "        nop\n",
    NULL
};

static
char *ending[] = {
    "        mov 0,%i0\n",
    "L1:\n",
    "        ret\n",
    "        restore\n",
    "        .align 8\n",
    "LC0:\n",
    "        .ascii \"0x%08x = %d\\12\\0\"\n",
    "        .align 4\n",
    "        .global _print\n",
    "        .proc   04\n",
    "_print:\n",
    "        !#PROLOGUE# 0\n",
    "        save %sp,-104,%sp\n",
    "        !#PROLOGUE# 1\n",
    "        st %i0,[%fp+68]\n",
    "        sethi %hi(LC0),%o1\n",
    "        or %o1,%lo(LC0),%o0\n",
    "        ld [%fp+68],%o1\n",
    "        ld [%fp+68],%o2\n",
    "        call _printf,0\n",
    "        nop\n",
    "L2:\n",
    "        ret\n",
    "        restore\n",
    "        .common _variable,256,\"bss\"\n",
    NULL
};

void
emit_push()
{
    reg_stack[reg_sp++] =  current_register;
    lrn = reg_name[current_register];
    current_register = get_register();
    crn = reg_name[current_register];
}

void
emit_compare() 
{
    char *orn;
    orn = pop_register();
    printf("\tcmp %s,%s\n",lrn,orn);
    printf("\tbg,a LL%d\n",label);
    printf("\tmov   1,%s\n",crn);
    printf("\tmov   0,%s\n",crn);
    printf("LL%d:\n",label);
    label++;
}

void
emit_store(assign)
int assign;
{
    printf("\tsethi %%hi(_variable+%d),%%g2\n",assign*4);
    printf("\tst %s,[%%g2+%%lo(_variable+%d)]\n",crn,assign*4);
}

static
char *opcode[] = {
    "",
    "sub",
    "add",
    "mul",
    "div",
    "",
    "",
    "",
    "",
    "sub",
    "div",
};

void
emit_calc(enum opcode op)
{
    char *orn;
    orn = pop_register();
    if(op==O_MUL) {
	printf("\tmov %s,%%o1\n",lrn);
	printf("\tcall .umul,0\n");
	printf("\tmov %s,%%o0\n",orn);
	printf("\tmov %%o0,%s\n",crn);
    } else if(op==O_DIV) {
	printf("\tmov %s,%%o0\n",lrn);
	printf("\tcall .div,0\n");
	printf("\tmov %s,%%o1\n",orn);
	printf("\tmov %%o0,%s\n",crn);
    } else if(op==O_DIV_R) {
	printf("\tmov %s,%%o0\n",orn);
	printf("\tcall .div,0\n");
	printf("\tmov %s,%%o1\n",lrn);
	printf("\tmov %%o0,%s\n",crn);
    } else if(op==O_SUB) {
	printf("\t%s %s,%s,%s\n", opcode[op], lrn, orn, crn);
    } else {
	printf("\t%s %s,%s,%s\n", opcode[op], orn, lrn, crn);
    }
}

void
emit_value(d) 
int d;
{
    if(-4096 < d && d < 4096) {
	printf("\tmov %d,%s\n",d,crn);
    } else {
	printf("\tsethi %%hi(%d),%s\n",d,crn);
	printf("\tor %s,%%lo(%d),%s\n",crn,d,crn);
    }
}

void
emit_load(assign)
int assign;
{
    printf("\tsethi %%hi(_variable+%d),%%g2\n",assign*4);
    printf("\tld [%%g2+%%lo(_variable+%d)],%s\n",assign*4,crn);
}

void
emit_comment()
{
    if (before < ptr) {
	putchar('#'); putchar('#'); putchar(' ');
	while (before < ptr) {
	    if(*before && *before!='\n') {
		putchar(*before);
	    }
	    before++;
	}
	putchar('\n');
    }
}

void
emit_print()
{
    printf("\tcall _print,0\n");
    if(current_register!=O0RN) {
	printf("\tmov %s,%%o0\n",crn);
    } else {
	printf("\tnop\n");
    }
}

void
emit_intro()
{
    char **iptr;
    int i;
    for(iptr=intro;*iptr;iptr++) {
	printf("%s",*iptr);
    }
    for(i=0;i<MAX_REGISTER;i++) regs[i]=0;
    regs[0]=regs[1]=regs[2]=regs[24]=regs[25]=
       regs[8+6]=regs[16+6]=1;   /* already used */
    current_register = get_register();
    regs[current_register] = 1;
    crn = reg_name[current_register];
    reg_sp = 0;
}

void
emit_ending()
{
    char **iptr;
    for(iptr=ending;*iptr;iptr++) {
	printf("%s",*iptr);
    }
}


/* end */