view mc-code-powerpc.c @ 93:8f5d61239b93

*** empty log message ***
author kono
date Sun, 09 Mar 2003 18:31:00 +0900
parents e7f8515ba882
children 185d2cc6a3a9
line wrap: on
line source

/* Micro-C Code Generatation Part for Power PC (Mac OS X) */
/* $Id$ */

#define EXTERN extern
#include "mc.h"
#include "mc-code.h"
#include "mc-codegen.h"

#define TEXT_EMIT_MODE 0
#define DATA_EMIT_MODE 1
#define RODATA_EMIT_MODE 2

static void data_mode(char *name);
static void init_ptr_cache();
static void ld_indexx(int byte, int n, int xreg);
static void local_table(void);
static void shift(char *op, int reg);
static void use_register(int virt, int real, int move);
static void use_register_var(int i);

static int output_mode = TEXT_EMIT_MODE;
static int data_alignment = 0;

static int code_disp_label;
static int func_disp_label;

/*
                                           -16  -8 local2   <-- r30
                                           -12  -4 local1
                                            -8  8  arg3
                                            -4  4  arg2
                                             0  0  arg1
         local2     -20 4                    0    (r5)
         local1 <-- -16 0 local variable     0    (r4)
                    -12  <- disp_offset          %ebp
        r30 (sp)     -8
                      0   <- r1
        r1  (fp)      8   <- arg_offset
          arg1        8 0
          arg2       12 4
            see enter/enter1/leave           see code_enter

     r0    link register
     r30   stack pointer
     r31   0
     r1    frame pointer
 */
int arg_offset = 8;
int disp_offset = -12;
int func_disp_offset = -12;
int code_disp_offset = 0;
int jump_offset = 0;

int size_of_int = 4;
int size_of_float = 4;
int size_of_double = 8;
int size_of_longlong = 8;
int endian = 0;
int MAX_REGISTER=30;         /* PowerPCのレジスタを10個まで使う*/
int REAL_MAX_REGISTER=32;    /* PowerPCのレジスタが32ということ*/
int MAX_REGISTGER_VAR=30-10;    
int MAX_FREGISTER=30;

#define REG_fp   1
#define REG_sp   30
#define REG_VAR_BASE 30
#define REG_ARG_BASE 3 
#define REG_ARG_MAX  10 
#define FREG_ARG_BASE 1 
#define FREG_ARG_MAX  13 

int reg_sp=REG_sp;

static char *reg_name[] = {
    "r0","r1","r2","r3","r4","r5","r6","r7","r8","r9",
    "r10","r11","r12","r13","r14","r15","r16","r17","r18","r19",
    "r20","r21","r22","r23","r24","r25","r26","r27","r28","r29",
    "r30","r31"
}; 

static char *freg_name[] = {
    "f0","f1","f2","f3","f4","f5","f6","f7","f8","f9",
    "f10","f11","f12","f13","f14","f15","f16","f17","f18","f19",
    "f20","f21","f22","f23","f24","f25","f26","f27","f28","f29",
    "f30","f31"
}; 

static char *creg_name[] = {
    "cr0","cr1","cr2","cr3","cr4","cr5","cr6","cr7"
}; 

void
code_init(void)
{
    arg_offset = 8;
    func_disp_offset = -12;
    disp_offset = -12;
    size_of_int = 4;
    endian = 1;
}

#define register_name(i) reg_name[i]

void
gexpr_code_init(void){
    regv[creg]=0;
}

int virtual(int real);
char * fload(int d);
int code_d1(double d);
int code_d2(double d);


int 
get_register(void)
{    /* 使われていないレジスタを調べる */
    int i;
    for(i=0;i<MAX_REGISTER;i++) {
	if (! regs[i]) {    /* 使われていないなら */
	    regs[i]=1;      /* そのレジスタを使うことを宣言し */
	    return i;       /* その場所を表す番号を返す */
	}
    }
    return -1;    /* 空いている場所がないなら、それを表す -1 を返す */
}

int
pop_register(void)
{     /* レジスタから値を取り出す */
    return reg_stack[--reg_sp];
}

int
stack_used(void) {
    return reg_stack[--reg_sp]<0;
}

void
emit_pop_free(int xreg)
{
    if (xreg==dreg) {
        regv[dreg]=0;
    } else if (xreg!=-1) {
        free_register(xreg);
    }
}

void 
free_register(int i) {    /* いらなくなったレジスタを開放 */
    regv[i]=regs[i]=0;
}

int
register_full(void)
{
    int i;
    for(i=0;i<MAX_REGISTER;i++) {
	if (! regs[i]) { 
	    return 0;  
	}
    }
    return 1;    
}

int
free_register_count(void)
{
    int i,count;
    count = 0;
    for(i=0;i<MAX_REGISTER;i++) {
	if (! regs[i] && ! regv[i]) count++;
    }
    return count;    
}

void
free_all_register(void)
{
    int i;
    for(i=0;i<MAX_REGISTER;i++) {
	regs[i]=regv[i]=0;
    }
    creg = get_register();
    dreg = get_register();
    return;
}

void
use_register_var(int i) {
    regv[i]=1;
}

void
set_register_var() {
}

void
code_arg_register(int args)
{
    NMTBL *n;
    if (args) {
	/* process in reverse order */
        n = (NMTBL*)caddr(args);
        if(n->sc==REGISTER) {
            if ((n->dsp = get_register_var()) <0) {
                error(-1); return;
            }
            use_register_var(n->dsp); /* it has now value in it */
        }
	code_arg_register(cadr(args));
    }
}


void
register_usage(char *s)
{
    int i;
    if (chk) return;
    printf("# %d: %s:",lineno,s);
    printf(" creg=%s dreg=%s ",register_name(creg),register_name(dreg));
    for(i=0;i<MAX_REGISTER;i++) {
	printf("%d",regs[i]);
    }
    printf(":");
    for(i=0;i<MAX_REGISTER;i++) {
	printf("%d",regv[i]);
    }
#if 0
    printf(" regs_stack",register_name(creg),register_name(dreg));
    for(i=reg_sp;i>=0;i--) {
	if(reg_stack[i]>=0)
	    printf(" %s",register_name(reg_stack[i],0));
    }
#endif
    printf("\n");
}

void 
gexpr_init(void)
{
    while(reg_sp > 0) {
	free_register(reg_stack[--reg_sp]);
    }
    text_mode();
    gexpr_code_init();
    register_usage("gexpr_init");
}


void 
emit_init(void)
{
    int i;
    for(i=0;i<MAX_REGISTER;i++) { regs[i]=0; regv[i]=0;rname[i]=i;}
    free_all_register();
    init_ptr_cache();
    reg_sp = 0;
    text_mode();
}

int
register_var(int r) {
    return virtual(REG_VAR_BASE-r);
}

int
get_register_var(void)
{
    int i;
    for(i=0;i<MAX_REGISTGER_VAR;i++) {
	if (REG_VAR_BASE-i<=REG_ARG_MAX)
	    return -1;
        if (! regs[REG_VAR_BASE-i]) {    /* 使われていないなら */
            regs[REG_VAR_BASE-i]=1;      /* そのレジスタを使うことを宣言し */
            regv[REG_VAR_BASE-i]=0;
            return i;                    /* その場所を表す番号を返す */
        }
    }
    return -1;
}

void 
emit_push(void)
{
    int new_reg;
    new_reg = get_register();
    if(new_reg<0) {                     /* もうレジスタがない */
	if (reg_sp>=MAX_MAX) error(-1);
	reg_stack[reg_sp++] =  -1;
	printf("\tstwu %s,-%d(%s)\n",register_name(creg),
             size_of_int,register_name(reg_sp));
	/* creg is used soon, don't regv[creg]=0 */
    } else {
	reg_stack[reg_sp++] = creg;     /* push するかわりにレジスタを使う */
	creg = new_reg;
	regv[creg]=1;
    }
}

int
emit_pop(int type)
{
    int xreg;
    if ((xreg=pop_register())==-1) {
	xreg=get_register();
	if(!xreg) error(-1);
	printf("\tlwz %s,(%s)\n",register_name(xreg),register_name(reg_sp));
	printf("\taddis %s,%s,%d\n",
                 register_name(reg_sp),register_name(reg_sp),size_of_int);
	regv[xreg]=1;
    } 
    return xreg;
}

static char *code_base;

#define MAX_PTR_CACHE 10

int ptr_cache=0;

void
init_ptr_cache()
{
    int i;
    for(i=0;i<MAX_PTR_CACHE;i++) {
	ptr_cache=glist3(0,ptr_cache,0);
    }
}

int
clear_ptr_cache()
{
    int ptcptr=ptr_cache;
    while(ptcptr) {
	if(car(ptcptr))
	    free_register(caddr(ptcptr));
	car(ptcptr)=0;
	caddr(ptcptr)=0;
	ptcptr=cadr(ptcptr);
    }
}


int
get_ptr_cache(char *name)
{
    int r;
    int ptcptr=ptr_cache;
    int cache;
    int i = 0;
    int g = (int)name;
    int p,p1;

    while(ptcptr) {
	if(car(ptcptr)==g) return caddr(ptcptr);
	p1=p; p=ptcptr;
	ptcptr=cadr(ptcptr);
    }
    cadr(p1)=0;            /* remove the last one */
    cadr(p) = ptr_cache;   /* connect current queue to the last one */
    ptr_cache = p;         /* now the last one is the top */
    if (!caddr(p)) {
	if((r=get_register())) 
	    caddr(p)=r;
	else
	    r=creg;
    }
    rrn = register_name(r);
    printf("\taddis %s,r31,ha16(L_%s$non_lazy_ptr-%s)\n",
	     rrn,(char *)g,code_base);
    printf("\tlzw %s,lo16(L_%s$non_lazy_ptr-%s)(%s)\n",
	     rrn,(char *)g,code_base,rrn);
    return r;
}

void
code_label(int labelno)
{
    clear_ptr_cache();
    printf("_%d:\n",labelno);
}

void
code_gvar(int e1) {
    int r;
    r = get_ptr_cache((char*)caddr(e1));
    if(r!=creg)
	printf("\tmr %s,%s\n",register_name(creg),register_name(r));
    return;
}

void
code_rgvar(int e1) {
    printf("\tlwz %s,(%s)\n",register_name(creg),
                             register_name(get_ptr_cache((char*)caddr(e1))));
}

void
code_crgvar(e1){
    printf("\tlbz %s,(%s)\n",register_name(creg),
                             register_name(get_ptr_cache((char*)caddr(e1))));
    printf("\textsb %s,%s\n",register_name(creg),register_name(creg));
}

void
code_lvar(int e2) {
    printf("\tla %s,%d(r1),%s\n",register_name(creg),e2);
}


void
code_register(int e2) {
    if (creg!=e2)
	printf("\tmr %s,%s\n",register_name(creg),register_name(e2));
}


void
code_rlvar(int e2) {
    printf("\tlwz %s,%d(r1),%s\n",register_name(creg),e2);
}


void
code_crlvar(int e2) {
    printf("\tlbz %s,%d(r1),%s\n",register_name(creg),e2);
    printf("\textsb %s,%s\n",register_name(creg),register_name(creg));
}


void
code_fname(char *e2) {
    int r;
    r = get_ptr_cache(e2);
    if(r!=creg)
	printf("\tmr %s,%s\n",register_name(creg),register_name(e2));
    return;
}


void
code_const(int e2) {
    char *crn = register_name(creg);
    if (-32768<e2&&e2<32768)
	printf("\tli %s,%d\n",crn,e2);
    else {
	printf("\tlis %s,ha16(%d)\n",crn,e2);
	printf("\taddi %s,%s,lo16(%d)\n",crn,crn,e2);
    }
}


void
code_neg() {
    printf("\tneg %s,%s\n", register_name(creg), register_name(creg));
}


void
code_not() {
    printf("\tnor %s,%s,%s\n", 
	register_name(creg), register_name(creg),register_name(creg));
}


void
code_lnot() {
    printf("\tsubfic r0,%s,0\n", register_name(creg));
    printf("\tadde %s,r0,%s\n", register_name(creg),register_name(creg));
}

void
code_preinc(int e1,int e2) {
    char *xrn,*drn;
    int i,dreg;
    if (car(e2)==REGISTER) {
	printf("\taddi %s,%s,%d\n", register_name(cadr(e2)));
	printf("\tmr %s,%s\n",register_name(cadr(creg)),register_name(e2));
	return;
    } 
    g_expr(e2);
    xrn = register_name(creg);
    dreg=get_register(); if (!dreg) error(-1);
    drn = register_name(dreg);
    printf("\tlwz %s,(%s)\n",drn,xrn);
    printf("\taddi %s,%s,%d\n",drn,drn,caddr(e1));
    printf("\tstw %s,(%s)\n",drn,xrn);
    i=creg;creg=dreg;dreg=i;
    regv[creg=1];
    free_register(dreg);
}


void
code_postinc(int e1,int e2) {
    char *xrn,*crn,*nrn;
    int dreg,nreg;
    if (car(e2)==REGISTER) {
	printf("\tmr %s,%s\n",register_name(creg),register_name(cadr(e2)));
	printf("\taddi %s,%s,%d\n", 
	    register_name(cadr(e2)),register_name(cadr(e2)));
	return;
    } 
    g_expr(e2);
    dreg=get_register(); if (!dreg) error(-1);
    xrn = register_name(dreg);
    nreg=get_register(); if (!nreg) error(-1);
    nrn = register_name(nreg);
    printf("\tlwz %s,(%s)\n",xrn,crn);
    printf("\taddi %s,%s,%d\n",nrn,xrn,caddr(e1));
    printf("\tstw %s,(%s)\n",nrn,crn);
    i=creg;creg=dreg;dreg=i; 
    free_register(nreg);
    free_register(dreg);
    regv[creg]=1;
}


void
code_cpostinc(int e1,int e2) {
    char *xrn,*crn;
    int i,nreg,dreg;
    if (car(e2)==REGISTER) {
	printf("\tlbz %s,(%s)\n",register_name(creg),register_name(cadr(e2)));
	printf("\textsb %s,%s\n",register_name(creg),register_name(creg));
	printf("\taddi %s,%s,%d\n", 
	    register_name(cadr(e2)),register_name(cadr(e2)),caddr(e1));
	return;
    } 
    g_expr(e2);
    crn = register_name(creg);
    dreg=get_register(); if (!dreg) error(-1);
    xrn = register_name(dreg);
    nreg=get_register(); if (!nreg) error(-1);
    nrn = register_name(nreg);
    printf("\tlwz %s,(%s)\n",xrn,crn);
    printf("\tlbz %s,(%s)\n",nrn,xrn);
    printf("\textsb %s,%s\n",nrn,nrn);
    printf("\taddi %s,%s,%d\n", xrn,xrn);
    printf("\tstw %s,(%s)\n",xrn,crn);
    i=creg;creg=nreg;nreg=i; 
    free_register(nreg);
    free_register(dreg);
    regv[creg]=1;
}


void
code_cpreinc(int e1,int e2) {
    char *xrn,*crn;
    int i,nreg,dreg;
    if (car(e2)==REGISTER) {
	printf("\tlbzu %s,%d(%s)\n",register_name(creg),caddr(e1),register_name(cadr(e2)));
	printf("\textsb %s,%s\n",register_name(creg),register_name(creg));
	return;
    } 
    g_expr(e2);
    crn = register_name(creg);
    dreg=get_register(); if (!dreg) error(-1);
    xrn = register_name(dreg);
    nreg=get_register(); if (!nreg) error(-1);
    nrn = register_name(nreg);
    printf("\tlwz %s,(%s)\n",xrn,crn);
    printf("\tlbzu %s,%d(%s)\n",nrn,caddr(e1),xrn);
    printf("\tstw %s,(%s)\n",xrn,crn);
    printf("\textsb %s,%s\n",nrn,nrn);
    i=creg;creg=nreg;nreg=i; 
    free_register(nreg);
    free_register(dreg);
    regv[creg]=1;
}


void
code_cpostdec(int e1,int e2) {
    char *xrn,*crn;
    int i,nreg,dreg;
    if (car(e2)==REGISTER) {
	crn=register_name(creg);
	xrn=register_name(cadr(e2));
	printf("\tlbz %s,(%s)\n",crn,xrn);
	printf("\taddi %s,%s,%d\n",xrn,xrn,caddr(e1));
	printf("\textsb %s,%s\n",crn,crn);
	return;
    } 
    g_expr(e2);
    crn = register_name(creg);
    dreg=get_register(); if (!dreg) error(-1);
    xrn = register_name(dreg);
    nreg=get_register(); if (!nreg) error(-1);
    nrn = register_name(nreg);
    printf("\tlwz %s,(%s)\n",xrn,crn);
    printf("\tlbz %s,(%s)\n",nrn,xrn);
    printf("\taddi %s,%s,%d\n",xrn,xrn,caddr(e1));
    printf("\tstw %s,(%s)\n",xrn,crn);
    printf("\textsb %s,%s\n",nrn,nrn);
    i=creg;creg=nreg;nreg=i; 
    free_register(nreg);
    free_register(dreg);
    regv[creg]=1;
}


void
code_cpredec(int e1,int e2) {
    char *xrn,*crn;
    int i,nreg,dreg;
    if (car(e2)==REGISTER) {
	crn=register_name(creg);
	xrn=register_name(cadr(e2));
	printf("\tlbzu %s,%d(%s)\n",crn,caddr(e1),xrn);
	printf("\textsb %s,%s\n",crn,crn);
	return;
    } 
    g_expr(e2);
    crn = register_name(creg);
    dreg=get_register(); if (!dreg) error(-1);
    xrn = register_name(dreg);
    nreg=get_register(); if (!nreg) error(-1);
    nrn = register_name(nreg);
    printf("\tlwz %s,(%s)\n",xrn,crn);
    printf("\tlbzu %s,%d(%s)\n",nrn,caddr(e1),xrn);
    printf("\tstw %s,(%s)\n",xrn,crn);
    printf("\textsb %s,%s\n",nrn,nrn);
    i=creg;creg=nreg;nreg=i; 
    free_register(nreg);
    free_register(dreg);
    regv[creg]=1;
}


void
code_return() {
    int r;
    printf("\taddis %s,r31,ha16(_%d-%s)\n",crn,retcont,code_base);
    printf("\tla %s,lo16(_%d-%s)(%s)\n",crn,retcont,code_base,crn);
}


void
code_environment() {
    printf("\tmr %s,r1\n",register_name(creg));
}


void
code_bool(int e1) {
    char *xrn;
    int e2,e3;
    b_expr(e1,1,e2=fwdlabel(),1);  /* including > < ... */
    xrn = register_name(creg);
    printf("\tli %s,0\n",xrn);
    jmp(e3=fwdlabel());
    fwddef(e2);
    printf("\tli %s,1\n",xrn);
    fwddef(e3);
}

char *
code_gt(int cond) {
    return (cond?"gt":"le");
}

char *
code_ugt(int cond) {
    return (cond?"gt":"le");
}

char *
code_ge(int cond) {
    return (cond?"ge":"lt");
}

char *
code_uge(int cond) {
    return (cond?"ge":"lt");
}

char *
code_eq(int cond) {
    return (cond?"eq":"ne");
}

void
code_cmp_crgvar(int e1) {
    int r;
    char *crn = register_name(creg);
    r = get_ptr_cache((char *)caddr(e1));
    printf("\tlbz %s,(%s)\n",crn,register_name(r));
    printf("\tcmpwi cr0,%s,0\n",crn);
}


void
code_cmp_crlvar(int e1) {
    char *crn = register_name(creg);
    printf("\tlbz %s,%d(r1)\n",crn,e1);
    printf("\tcmpwi cr0,%s,0\n",crn);
}


void
code_cmp_rgvar(int e1) {
    int r;
    char *crn = register_name(creg);
    r = get_ptr_cache((char *)caddr(e1));
    printf("\tlwz %s,(%s)\n",crn,register_name(r));
    code_cmp_register(creg);
}


void
code_cmp_rlvar(int e1) {
    char *crn = register_name(creg);
    printf("\tlwz %s,%d(r1)\n",crn,e1);
    code_cmp_register(creg);
}


void
code_cmp_register(int e2) {
    printf("\tcmpwi cr0,%s,0\n",register_name(e2));
}


void
ascii(char *s)
{
    printf("\t.ascii \"");
    while(*s) {
	if (*s=='\n')
	    printf("%cn",92);
	else if (*s<' ')
	    printf("%c%03o",92,*s);
	else if (*s==34)
	    printf("%c%c",92,34);
	else 
	    printf("%c",*s);
	s++;
    }
    printf("\\0%c\n",34);
}

void
string(int e1)
{
    char *s;
    int i,lb;

    s=(char *)cadr(e1);
    printf(".data\t.cstring\n\t.align 2\n");
    lb=fwdlabel();
    printf("_%d:\n",lb);
    ascii(s);
    if (output_mode==TEXT_EMIT_MODE) {
	printf(".text\n");
    } else {
	text_mode();
    }
    printf("\taddis %s,r31,ha16(_%d-%s)\n",crn,lb,code_base);
    printf("\tla %s,lo16(_%d-%s)(%s)\n",crn,lb,code_base,crn);
}

#define MAX_COPY_LEN 20

void 
emit_copy(int from,int  to,int length,int offset,int value,int det)
{
    char *frn =	register_name(from);
    char *trn =	register_name(to);
    char *drn;
    int fix = 0;
    char *bcopy = "bcopy";
    int dreg = get_regiter(); if (!dreg) error(-1);
    drn	 = register_name(dreg);

    /* length <0 means upward direction copy */
    switch (length) {
    case 0:	break;
    case 1: case -1:
	printf("\tlbz %s,%d(%s)\n",drn,offset,frn);
	printf("\tstb %s,%d(%s)\n",drn,offset,trn);
	break;
    case 2: case -2:
	printf("\tlhz %s,%d(%s)\n",drn,offset,frn);
	printf("\tsth %s,%d(%s)\n",drn,offset,trn);
	break;
    case 4: case -4:
	printf("\tlwz %s,%d(%s)\n",drn,offset,frn);
	printf("\tstw %s,%d(%s)\n",drn,offset,trn);
	break;
    default:
	if (-MAX_COPY_LEN<length && length <0) {
	    for(;length<=4;length+=4,offset-=4)
		emit_copy(from,to,4,offset,0,det);
	    for(;length<=2;length+=2,offset-=2)
		emit_copy(from,to,2,offset,0,det);
	    if(length>0)
		emit_copy(from,to,length,offset,0,det);
	    break;
	} else if (length <=MAX_COPY_LEN) {
	    for(;length>=4;length-=4,offset+=4)
		emit_copy(from,to,4,offset,0,det);
	    for(;length>=2;length-=2,offset+=2)
		emit_copy(from,to,2,offset,0,det);
	    if(length>0)
		emit_copy(from,to,length,offset,0,det);
	    break;
	}
	if (det) {
	    printf("\tli r5,%d\n",length);
	    printf("\tmr r4,%s\n",trn);
	    printf("\tmr r3,%s\n",frn);
	    printf("\tbl L_%s$stub\n",bcopy);
	    regist_extern_function(bcopy);
	    break;
	}
    }
    if (value) {
    /* creg must point top of the destination data */
    /* this code is necessary for the value of assignment or function call */
    /* otherwise we don't need this */
	if (fix) printf("\taddi %s,%s,%d\n",trn,trn,fix);
	if(creg!=to) {
	    free_register(creg); creg=to;
	}
    }
    free_register(dreg);
    regv[from]=regv[to]=regv[dreg]=0;
    regv[creg]=1;
}

int
struct_push(int e4,int t) 
{
    int length,save,count;
    int dreg; char *drn,*crn,*srn;
    g_expr(e4);
    length=size(t); 
    if(length%size_of_int) {
	length += size_of_int - (length%size_of_int);
    }
    dreg = get_regiter(); if (!dreg) error(-1);
    drn = register_name(dreg);
    crn = register_name(dreg);
    srn = register_name(reg_sp);
    for(count=0;length<MAX_COPY_LEN;count++,length-=size_of_int) {
	if (length==0) {
	    free_register(dreg);
	    return count;
	} else {
	    printf("\tlwz %s,%d(%s)\n",drn,length-size_of_int,crn);
	    printf("\tstwu %s,%d(%s)\n",drn,-size_of_int,srn);
	}
    }
    printf("\taddis %s,%s,ha16(%d)\n",srn,srn,length);
    printf("\taddi %s,%s,lo16(%d)\n",srn,srn,length);
    /* downward direction copy */
    printf("\tmr %s,%s\n",drn,srn);
    emit_copy(creg,dreg,length,0,0,1);
    /* we have value in creg, it may be changed */
    if (dreg!=creg) free_register(dreg);
    return length/size_of_int;
}

int
arg_offset(int arg)
{
}

void
function(int e1)
{
    int e2,e3,e4,e5,nargs,t;
    int reg_arg,freg_arg;
    NMTBL *n;
    e2 = cadr(e1);
    nargs = 0;
    reg_arg = REG_ARG_BASE;
    freg_arg = FREG_ARG_BASE;
    for (e3 = caddr(e1); e3; e3 = cadr(e3)) {	
	t=caddr(e3);
	n=(NMTBL *)(e5=(cadr(e4 = car(e3))));
	if(scalar(t)) {
	    g_expr(e4);
	    if (reg_arg<REG_ARG_MAX)
		printf("\tmr %s,%s\n",register_name(reg_arg),
                                register_name(creg));
	    else {
		printf("\tstw %s,%d(r1)\n",register_name(creg),
                                arg_offset(nargs));
	    }
	    nargs ++ ; reg_arg++;
	} else if (t==DOUBLE||t==FLOAT) {
	    g_expr(e4);
	    nargs += size_of_double/size_of_int;
	    if (fregv[freg_arg])
		save_freg(freg_arg);
	    fregv[freg_arg]=1;
	    if (freg_arg<FREG_ARG_MAX)
		printf("\tmr %s,%s\n",register_name(reg_arg++),
                                register_name(freg));
	    else if(t==DOUBLE) {
		printf("\tstfd %s,%d(r1)\n",register_name(freg),
                                arg_offset(nargs));
		nargs+=size_of_double/size_of_int; 
	    } else {
		printf("\tstfs %s,%d(r1)\n",register_name(freg),
                                arg_offset(nargs));
		nargs+=size_of_float/size_of_int; 
	    }
	    freg_arg++;
	    continue;
	} else if (car(t)==STRUCT||car(t)==UNION) {
	    nargs += struct_push(e4,t);
	    continue;
	} else {
	    error(TYERR);
	}
	++nargs;
    }
    if (car(e2) == FNAME) {	
	n=(NMTBL *)cadr(e2);
	regv[creg]=0;
    } else {	
	g_expr(e2);
	regv[creg]=1;
    }

    if (car(e2) == FNAME) {	
	printf("\tbl\tL_%s$stub\n",n->nm);
    } else {
	jmp=get_tmp_register();
        jrn = register_name(jmp);
	printf("\tmr %s,%s\n",jrn,crn);
        printf("\tmtctr %s\n",jrn);
        printf("\tbctrl\n");
	free_register(jmp);
    }
    regv[creg]=1;
    clear_ptr_cache();
}

void
code_frame_pointer(int e3) {
    printf("\tmovl %s,r1\n",register_name(e3));
}


void
code_fix_frame_pointer(int disp_offset) {
    printf("\tla r1,%d(r1)\n",disp_offset);
}

void
code_jmp(char *s) {
    printf("\tb L_%s$stub\n",s);
}


void
code_indirect_jmp(int e2) {
    printf("\tmtctr %s\n",register_name(e2));
    printf("\tbctr\n");
}

void
rindirect(int e1)   /* *(p +5 ) */
{
    char *op,*crn;
    int e2,e3,byte;
    e3 = cadr(e2 = cadr(e1));
    g_expr(e2);
    crn=register_name(creg);
    switch (car(e1)) {
    case FRINDIRECT: case DRINDIRECT:
	printf("\t%s %s,(%s)\n",fload(car(e1)==DRINDIRECT),
	    register_name(freg),crn);
	regv[creg]=0; regv[freg]=1;
	break;
    case CRINDIRECT: 
	printf("\tlbz %s,(%s)\n",crn,crn);
	printf("\textsb %s,%s\n",crn,crn);
	break;
    case RINDIRECT:
	printf("\tlwz %s,(%s)\n",crn,crn);
	break;
    }
}

void
code_assign_gvar(int e2,int byte) {
    int r;
    char *crn,*rrn;
    r = get_ptr_cache((char*)caddr(e2));
    rrn=register_name(r);
    crn=register_name(creg);
    if (byte) {
	printf("\tstb %s,(%s)\n",crn,rrn);
    } else {
	printf("\tstw %s,(%s)\n",crn,rrn);
    }
}

void
code_assign_lvar(int e2,int byte) {
    char *crn;
    crn=register_name(creg);
    if (byte) {
	printf("\tstb %s,%d(r1)\n",crn,e2);
    } else {
	printf("\tstw %s,%d(r1)\n",crn,e2);
    }
}

void
code_assign_register(int e2,int byte) {
    printf("\tmr %s,%s\n",register_name(e2),register_name(creg));
}

void
code_assign(int e2,int byte) {
    char *drn=register_name(dreg);
    if (byte) {
	printf("\tstb %s,(%s)\n",crn,drn);
    } else {
	printf("\tstw %s,(%s)\n",crn,drn);
    }
}


void
code_register_assop(int e2,int op,int byte) {
    int reg;
    int xreg = creg;
    creg = reg = e2;
    tosop(op,xreg);
    creg = xreg;
    printf("\tmr %s,%s\n",register_name(creg),register_name(reg));
}


void
code_assop(int op,int byte) {
    char *xrn,*crn,*drn;
    int xreg;
    int edx = get_register(); if(!edx) error(-1);
    xrn = register_name(xreg = emit_pop(0));       /* pop e3 value */
    regv[xreg]=regs[xreg]=1;
    printf("\tmovl %s,%s  # assop \n",register_name(creg),register_name(edx));
    regv[edx]=1;
    ld_indexx(byte,0,edx);
    tosop(op,xreg);
    crn = register_name(creg);
    drn = register_name(edx);
    if (byte) {
	printf("\tstb %s,(%s)\n",crn,drn);
    } else {
	printf("\tstw %s,(%s)\n",crn,drn);
    }
    free_register(edx);
    emit_pop_free(xreg);
}


void
tosop(int op,int oreg)
{
    int dx;
    char *orn,*crn;

    switch(op) {
    case LSHIFT:
    case ULSHIFT:
	shift("slw",oreg);
	return;
    case RSHIFT:
	shift("srw",oreg);
	return;
    case URSHIFT:
	shift("sraw",oreg);
	return;
    }
    orn = register_name(oreg);
    crn = register_name(creg);
    switch(op) {
    case ADD:
	printf("\tadd %s,%s,%s\n",crn,orn,crn);
	break;
    case SUB:
	printf("\tsub %s,%s,%s\n",crn,orn,crn);
	break;
    case BAND: 
	printf("\tand %s,%s,%s\n",crn,orn,crn);
	break;
    case EOR: 
	printf("\txor %s,%s,%s\n",crn,orn,crn);
	break;
    case BOR:
	printf("\torl %s,%s,%s\n",crn,orn,crn);
	break;
    case MUL:
    case UMUL:
	printf("\t%mullw %s,%s,%s\n",crn,orn,crn);
	break;
    case DIV:
	printf("\t%divw %s,%s,%s\n",crn,orn,crn);
	break;
    case UDIV:
	printf("\t%divwu %s,%s,%s\n",crn,orn,crn);
	break;
    case MOD:
	dx=get_register();
	drn = register_name(drn);
	printf("\t%divwu %s,%s,%s\n",drn,orn,crn);
	printf("\t%mullw %s,%s,%s\n",drn,drn,crn);
	printf("\t%subf %s,%s,%s\n",drn,drn,orn);
	free_register(creg);
	creg=dx;
	break;
    case UMOD:
	dx=get_register();
	drn = register_name(drn);
	printf("\t%divwu %s,%s,%s\n",drn,orn,crn);
	printf("\t%mullw %s,%s,%s\n",drn,drn,crn);
	printf("\t%subf %s,%s,%s\n",drn,drn,orn);
	free_register(creg);
	creg=dx;
	break;
    }
    if(oreg!=cre) free_register(oreg);
}


void
shift(char *op, int reg)
{
    char *crn = register_name(creg);
    char *rrn = register_name(reg);
    printf("\t%s %s,%s,%s\n",op,crn,rrn,crn);
}

void
ld_indexx(int byte, int n, int xreg)
{	
    char *op;

    if (byte) {
	printf("\tlbz %s,%d(%s),%s\n",register_name(creg),n,
	    register_name(xreg));
	printf("\textsb %s,%s\n",crn,crn);
    } else 
	printf("\tlwz %s,%d(%s),%s\n",register_name(creg),n,
	    register_name(xreg));
}

void
cmpdimm(int e, int csreg)
{
    /* used in dosiwtch() */
    if(chk) return;
    printf("\tcmpw cr0,%s,%d\n",register_name(csreg),e);
}

void
code_opening(char *filename)
{
    printf("\t.file \"%s\"\n",filename);
    printf("\t.version\t\"01.01\"\n");
    /* printf("gcc2_compiled.:\n"); */
    printf(".text\n");
}

void
code_closing()
{
    global_table();
    printf("\t.ident \"Micro-C compiled\"\n");
}

void
rexpr(int e1, int l1, char *s)
{       
    g_expr(list3(CMP,cadr(e1),caddr(e1)));
    printf("\tb%s cr0,_%d\n",s,l1);
}


void
jcond(int l, char cond)
{       
    if (chk) return;
    printf("\tb%s cr0,_%d\n",cond?"ne":"eq",l);
}

void
jmp(int l)
{       
    control=0;
    if (chk) return;
    printf("\tb\t_%d\n",l);
}

void
gen_comment(char *s)
{
    if (chk) return;
    printf("## %s",s);
}


void
code_enter(char *name)
{
    printf("\t.align 4\n");
    if (stmode!=STATIC)
	printf(".globl %s\n",name);
    printf("\t.type\t%s,@function\n",name);
    printf("%s:\n",name);
}


void
code_enter1(int args)
{
    code_disp_label=fwdlabel();
    printf("\tlea _%d(%%ebp),%%esp\n",code_disp_label);

    printf("## args %d disp %d code_arg_offset=%d code_disp_offset=%d\n",args,disp,code_arg_offset,code_disp_offset); 
}

void
code_leave(char *name)
{
    disp&= -size_of_int;
    printf("\t.set _%d,%d\n",code_disp_label,disp+code_disp_offset);
    printf("_%d:\n",labelno);
    printf("\t.size\t%s,_%d-%s\n",name,labelno,name);
    local_table();
    labelno++;
    free_all_register();
}

void
enter(char *name)
{
    printf("\t.align 2\n");
    if (stmode!=STATIC)
	printf(".globl %s\n",name);
    printf("%s:\n",name);
    printf("\t.type\t%s,@function\n",name);
    printf("\tpushl %%ebp\n");
    printf("\tmovl %%esp,%%ebp\n");
    printf("\tpushl %%ebx\n");
    printf("\tpushl %%esi\n");
    printf("\tpushl %%edi\n");
}

void
enter1()
{
    func_disp_label=fwdlabel();
    printf("\tlea _%d(%%ebp),%%esp\n",func_disp_label); 
    /* if(disp) printf("\tsubl $%d,%%esp\n",-disp); */
}

void
leave(int control, char *name)
{
    if (control)
	use_register(creg,REG_EAX,1);
    if (retcont) {
	if (control)
	    jmp(retlabel);
	fwddef(retcont);
	use_register(creg,REG_EAX,0);
	printf("\tmovl %s,%s\n",reg_name[REG_ESI],register_name(creg));
	/* printf("\tleave\n"); */
    }
    fwddef(retlabel);
    /* use_register(creg,REG_EAX,0); too late */
    /* if(disp) printf("\taddl $%d,%%esp\n",-disp);  */
    disp &= -size_of_int;

    printf("\tlea %d(%%ebp),%%esp\n",disp_offset);
    printf("\tpopl %%edi\n");
    printf("\tpopl %%esi\n");
    printf("\tpopl %%ebx\n");
    printf("\tleave\n");
    printf("\tret\n");
    printf("\t.set _%d,%d\n",func_disp_label,disp+disp_offset);
    printf("_%d:\n",labelno);
    printf("\t.size\t%s,_%d-%s\n",name,labelno,name);
    local_table();
    labelno++;
    free_all_register();
}


void
code_set_fixed_creg(int mode) {
    creg=11;
}

void
gen_gdecl(char *n, int gpc)
{
    /*
    if (stmode!=STATIC)
	printf(".globl %s\n",n); 
     */
}

void 
align(int t)
{
    if (t!=CHAR) {
	if (data_alignment & 1)
	    printf("\t.align 2\n");
	data_alignment = 0;
    }
}

void
emit_data(int e, int t, NMTBL *n)
{
    int l;
    double d;
    float f;
    char *name;
    name = n->nm; 
    if(mode!=GDECL)  { 
	error(-1); return;
    }
    if (chk) return;
    if (n->dsp != -1) {
	n->dsp = -1;   /* initiallized flag */
	printf(".globl\t%s\n",name);
	data_mode(name);
	align(t);
	printf("%s:\n",name); 
    } else {
	data_mode(0);
    }
    if(car(e)==CONST) {       
	if (t==CHAR) {
	    printf("\t.byte %d\n",cadr(e));
	    if (data_alignment>0)
		data_alignment++;
	    gpc += 1;
	} else if (t==SHORT) {
	    printf("\t.word %d\n",cadr(e));
	    if (data_alignment>0) data_alignment++;
	    gpc += 2;
	} else {
	    printf("\t.long %d\n",cadr(e));
	    gpc += size_of_int;
	}
    } else if(t==DOUBLE) {       
	d = dcadr(e);
	printf("\t.long\t0x%x,0x%x\n",code_d1(d),code_d2(d));
    } else if(t==FLOAT) {       
	f = dcadr(e);
	printf("\t.long\t0x%x\n",*(int *)&f);
    } else if(t!=CHAR) {       
	gpc += size_of_int;
	if(car(e)==ADDRESS&&car(cadr(e))==GVAR) {
	    printf("\t.long %s\n",(char *)caddr(cadr(e)));
	} else if(car(e)==FNAME) {
	    printf("\t.long %s\n",((NMTBL *)cadr(e))->nm);
	} else if(car(e)==STRING) {       
	    if (car(n->ty)!=ARRAY || cadr(n->ty)!=CHAR) {
		l = fwdlabel();
		printf("\t.long _%d\n",l);
		printf(".section\t.rodata\n");
		printf("_%d:\n",l);
		output_mode = RODATA_EMIT_MODE;
	    }
	    ascii((char *)cadr(e));
	} else error(TYERR);
    }
}

void
emit_data_closing(NMTBL *n)
{
    int lb;
    if (chk) return;
    if (mode==GDECL) {
	data_mode(0);
	lb=fwdlabel();
	printf("_%d:\n",lb);
	printf("\t.size\t%s,_%d-%s\n",n->nm,lb,n->nm);
    }
}

void
global_table(void)
{
    NMTBL *n;
    int init;
    init=0;
    for(n=ntable;n < &ntable[GSYMS];n++) {
	if (n->sc == GVAR && n->dsp != -1) {
	    /* n->dsp = -1 means initialized global */
	    if (init==0) {
		data_mode(0);
		init=1;
	    }
	    printf(".comm %s,%d\n",n->nm,size(n->ty));
	}
    }
}

void
local_table(void)
{
    NMTBL *n;
    int init;
    init=0;
    /* static local variables */
    for(n=ntable+GSYMS;n < &ntable[GSYMS+LSYMS];n++) {
	if (n->sc == GVAR) {
	    if (init==0) {
		data_mode(0);
		init=1;
	    }
	    printf(".lcomm %s,%d\n",n->nm,size(n->ty));
	}
    }
}

void
text_mode(void)
{
    if (output_mode!=TEXT_EMIT_MODE) {
	printf(".text\n");
	printf("\t.align 2\n");
	output_mode = TEXT_EMIT_MODE;
    }
}

void
data_mode(char *name)
{
    if (output_mode!=DATA_EMIT_MODE) {
	printf(".data\n");
	output_mode = DATA_EMIT_MODE;
    }
    if (name)
	printf("\t.type\t%s,@object\n",name);
}

int
lvar(int l)
{
    if (fnptr->sc==CODE) {
	return l+code_disp_offset;
    } else if (l<0) {
	return l+disp_offset;
    } else {
	return l+arg_offset;
    }
}

/* floating point */


char *
fstore(int d)
{
    return (d?"stfd":"stfs");
}

char *
fload(int d)
{
    return d?"lfd":"lfs";
}

void code_dassign_gvar(int e2,int d)
{ 
    int r;
    r = get_ptr_cache((char*)caddr(e1));
    printf("\t%s %s,(%s)\n",fstore(d),register_name(freg),register_name(r));
}

void code_dassign_lvar(int e2,int d)
{ 
    printf("\t%s %s,%d(r1)\n",fstore(d),register_name(creg),e2);
}

void code_dassign(int e2,int d)
{ 
    printf("\t%s %s,(%s)\n",fstore(d),register_name(creg),register_name(e2));
}

static double d0 = 1.0;

int
code_d1(double d)
{
    int *i = (int *)&d0; int *j = (int *)&d;
    return (i[1] == 0x3ff00000)?j[0]:j[1];
}

int
code_d2(double d)
{
    int *i = (int *)&d0; int *j = (int *)&d;
    return (i[1] == 0x3ff00000)?j[1]:j[0];
}

void code_dconst(int e2)
{ 
    int lb;
    double d = dcadr(e2);
    int r;
    char *rrn;
    rrn = register_name((r=get_register()));

    if (d==0.0) {
	printf("\tfldz\n"); return;
    }
    if (d==1.0) {
	printf("\tfld1\n"); return;
    }
    printf(" \t.section\t.rodata\n\t.align 8\n");
    lb=fwdlabel();
    printf("_%d:\n",lb);
    printf("\t.long\t0x%x,0x%x\n",code_d1(d),code_d2(d));
    if (output_mode==TEXT_EMIT_MODE) {
	printf(".text\n");
    } else {
	text_mode();
    }
    printf("\taddis %s,r31,ha16(_%d-%s)\n",rrn,lb,code_base);
    printf("\tla %s,lo16(_%d-%s)(%s)\n",rrn,lb,code_base,rrn);
    printf("\tlfd %s,%(s)\n",register_name(freg),rrn);
    free_register(r);
}

void code_dneg()
{ 
    char *frn = register_name(freg);
    printf("\tfneg %s,%s\n",freg);
}

void code_d2i()
{ 
    char *frn = register_name(freg);
    disp-=size_of_double;
    printf("\tfctiwz  %s,%s\n",frn,frn);
    printf("\tstfd  %s,%d(r1)\n",disp);
    printf("\tlwz  %s,%d(r1)\n",crn,disp+size_of_double-size_of_int);
    fregs[freg]=0;
    regs[creg]=1;
}

static int i2d_lib_used=0;
static char *i2d_lib[] = {
".data",
".literal8",
"        .align 3",
"__i2dLC0:",
"        .long   1127219200",
"        .long   -2147483648",
".text",
"        .align 2",
"i2d:",
"        mflr r0",
"        bcl 20,31,__i2dL1$pb",
"__i2dL1$pb:",
"        mflr r10",
"        mtlr r0",
"        xoris r3,r3,0x8000",
"        stw r3,-28(r1)",
"        lis r0,0x4330",
"        stw r0,-32(r1)",
"        lfd f0,-32(r1)",
"        addis r9,r10,ha16(__i2dLC0-__i2dL1$pb)",
"        lfd f1,lo16(__i2dLC0-__i2dL1$pb)(r9)",
"        fsub f1,f0,f1",
"        blr",
0
};

void code_i2d()
{ 
    d2u_lib_used=1;
    char *frn = register_name(freg);
    char *crn = register_name(creg);
    printf("\tmr r3,%s\n",crn);
    printf("\tbl i2d_\n");
    printf("\tfmr %s,f1\n",frn);
    fregs[freg]=1;
    regs[creg]=0;
}

static int d2u_lib_used=0;
static char *d2u_lib[] = {
".literal8",
"        .align 3",
"__d2uLC0:",
"        .long   1105199104",
"        .long   0",
".text",
"        .align 2",
"d2u:",
"        mflr r0",
"        bcl 20,31,__d2uL1$pb",
"__d2uL1$pb:",
"        mflr r10",
"        mtlr r0",
"        addis r9,r10,ha16(__d2uLC0-__d2uL1$pb)",
"        lfd f0,lo16(__d2uLC0-__d2uL1$pb)(r9)",
"        fcmpu cr0,f1,f0",
"        cror 2,1,2",
"        beq- cr0,__d2uL2",
"        fctiwz f0,f1",
"        stfd f0,-32(r1)",
"        lwz r3,-28(r1)",
"        blr",
"__d2uL2:",
"        addis r9,r10,ha16(__d2uLC0-__d2uL1$pb)",
"        lfd f0,lo16(__d2uLC0-__d2uL1$pb)(r9)",
"        fsub f0,f1,f0",
"        fctiwz f0,f0",
"        stfd f0,-24(r1)",
"        lwz r3,-20(r1)",
"        xoris r3,r3,0x8000",
"        blr",
0
};

void code_d2u()
{ 
    d2u_lib_used=1;
    char *frn = register_name(freg);
    char *crn = register_name(creg);
    printf("\tfmr f1,%s\n",frn);
    printf("\tbl d2u\n");
    printf("\tmr %s,r3\n",crn);
    fregs[freg]=1;
    regs[creg]=0;
}

static int u2d_lib_used=0;
static char *u2d_lib[] = {
".data",
".literal8",
"        .align 3",
"__u2dLC1:",
"        .long   1127219200",
"        .long   0",
".text",
"        .align 2",
"u2d:",
"        mflr r0",
"        bcl 20,31,__u2dL2$pb",
"__u2dL2$pb:",
"        mflr r10",
"        mtlr r0",
"        stw r3,-28(r1)",
"        lis r0,0x4330",
"        stw r0,-32(r1)",
"        lfd f0,-32(r1)",
"        addis r9,r10,ha16(__u2dLC1-__u2dL2$pb)",
"        lfd f1,lo16(__u2dLC1-__u2dL2$pb)(r9)",
"        fsub f1,f0,f1",
"        blr",
0
};

void code_u2d()
{ 
    u2d_lib_used=1;
    char *frn = register_name(freg);
    char *crn = register_name(creg);
    printf("\tmr r3,%s\n",crn);
    printf("\tbl u2d\n");
    printf("\tfmr %s,f1\n",frn);
    fregs[freg]=1;
    regs[creg]=0;
}

void code_drgvar(int e2,int d)
{ 
    int r;
    r = get_ptr_cache((char*)caddr(e1));
    printf("\t%s %s,(%s)\n",fload(d),register_name(freg),register_name(r));
}


void code_drlvar(int e2,int d)
{ 
    printf("\t%s %s,%d(r1)\n",fload(d),register_name(freg),e2);
}

void code_cmp_drgvar(int e2)
{ 
    int r;
    char *frn=register_name(freg);
    int g=get_fregister();
    char *grn=register_name(g);
    r = get_ptr_cache((char*)caddr(e1));
    printf("\t%s,(%s)\n",fload(d),grn,register_name(r));
    printf("\tfcmpu cr0,%s,%s\n",frn,grn);
    free_fregister(g);
}

void code_cmp_drlvar(int e2)
{ 
    printf("\tfcmpu %d(%%ebp)\n",e2);
    char *frn=register_name(freg);
    int g=get_fregister();
    char *grn=register_name(g);
    printf("\t%s,%d(r1)\n",fload(d),grn,e2);
    printf("\tfcmpu cr0,%s,%s\n",frn,grn);
    free_fregister(g);
}

void dtosop(int op,int e1)
{ 
    char *opn;
    char *frn=register_name(freg);
    char *grn=register_name(e1);
    switch(op) {
    case DADD: opn="fadd"; break;
    case DSUB: opn="fadd"; break;
    case DDIV: opn="fadd"; break;
    case DMUL: opn="fadd"; break;
    case DCMP: 
	printf("\tfcompu cr0,%s,%s\n",opn,frn,grn);
	fgree_register(e1);
	break;
    case DCMPGE: 
	printf("\tfcompu cr7,%s,%s\n",opn,frn,grn);
	fgree_register(e1);
	break;
    }
    printf("\t%s %s,%s,%s\n",opn,frn,frn,grn);
    fgree_register(e1);
}

void
code_dassop(int op,int d) {
    /* we have lvalue in creg, applied floating value is in freg */
    char *frn=register_name(freg);
    int  e1=get_fregister();
    char *grn=register_name(e1);
    char *crn=register_name(creg);

    printf("\t%s %s,(%s)\n",fload(d),grn,crn);
    dtosop(op,e1);
    printf("\t%s %s,(%s)\n",fstore(d),frn,crn);
}

static int use_float_one=0;

void
code_dpreinc(int e1,int e2,int d) {
    char *frn;
    char *crn;
    int  g;
    char *grn,*drn;
    int r;
    r = get_ptr_cache("float_one");
    use_float_one=1;

    g_expr(e2);

    crn=register_name(creg);
    frn=register_name(freg);
    drn=register_name(r);
    grn=register_name(g);

    printf("\t%s %s,(%s)\n",fload(d),frn,crn);
    printf("\tfls %s,(%s)\n",grn,drn);
    if (caddr(e1)>0)
	printf("\tfadd %s,%s,%s\n",frn,frn,grn);
    else
	printf("\tfsub %s,%s,%s\n",frn,frn,grn);
    printf("\t%s %s,(%s)\n",fstore(d),frn,crn);
}

void
code_dpostinc(int e1,int e2,int d) {
    char *frn;
    char *crn;
    int  g;
    char *grn,*drn;
    int r;
    r = get_ptr_cache("float_one");
    use_float_one=1;

    g_expr(e2);

    crn=register_name(creg);
    frn=register_name(freg);
    drn=register_name(r);
    grn=register_name(g);

    printf("\t%s %s,(%s)\n",fload(d),frn,crn);
    printf("\tfls %s,(%s)\n",grn,drn);
    if (caddr(e1)>0)
	printf("\tfadd %s,%s,%s\n",grn,frn,grn);
    else
	printf("\tfsub %s,%s,%s\n",grn,frn,grn);
    printf("\t%s %s,(%s)\n",fstore(d),grn,crn);
}

void
drexpr(int e1, int e2,int l1, int op)
{       
    g_expr(list3(((op==DOP+GE)?DCMPGE:DCMP),e1,e2));
    switch(op) {
	case DOP+GE:
	    printf("\tcror 2,29,30\n");
	    printf("\tbeq\tcr0,_%d\n",l1);
	    break;
	case DOP+GT:
	    printf("\tbgt\tcr0,_%d\n",l1);
	    break;
	case DOP+EQ:
	    printf("\tbeq\tcr0,_%d\n",l1);
	    break;
	case DOP+NEQ:
	    printf("\tbne\tcr0,_%d\n",l1);
	    break;
    }
}

int dpop_register()
{ 
    return 1;
}

int emit_dpop(int e1)
{ 
    return 1;
}

void emit_dpop_free(int e1)
{ 
}

void emit_dpush()
{ 
}

/* end */