URL
https://opencores.org/ocsvn/rf6809/rf6809/trunk
Subversion Repositories rf6809
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 17 to Rev 18
- ↔ Reverse comparison
Rev 17 → Rev 18
/rf6809/trunk/software/vbcc/datatypes/dt12f.c
0,0 → 1,6
from) |
{ |
DTTTYPE to; |
to=(from.a[0]&255)|((from.a[1]&15)<<8); |
return to; |
} |
/rf6809/trunk/software/vbcc/datatypes/dt12t.c
0,0 → 1,7
from) |
{ |
DTFTYPE to; |
to.a[0]=from&255; |
to.a[1]=(from>>8)&15; |
return to; |
} |
/rf6809/trunk/software/vbcc/datatypes/dt24f.c
0,0 → 1,6
from) |
{ |
DTTTYPE to; |
to=(from.a[0]&255)|((from.a[1]&255)<<8)|((from.a[2]&255)<<16); |
return to; |
} |
/rf6809/trunk/software/vbcc/datatypes/dt24t.c
0,0 → 1,9
from) |
{ |
DTFTYPE to; |
to.a[0]=from&255; |
to.a[1]=(from>>8)&255; |
to.a[2]=(from>>16)&255; |
to.a[3]=(from&0x800000)?255:0; |
return to; |
} |
/rf6809/trunk/software/vbcc/datatypes/dt48f.c
0,0 → 1,8
from) |
{ |
DTTTYPE to; |
to=(from.a[0]&255LL)|((from.a[1]&255LL)<<8LL)|((from.a[2]&255LL)<<16LL)| |
((from.a[3]&255LL)<<24LL)|((from.a[4]&255LL)<<32LL)|((from.a[5]&255LL)<<40LL); |
return to; |
} |
|
/rf6809/trunk/software/vbcc/datatypes/dt48t.c
0,0 → 1,13
from) |
{ |
DTFTYPE to; |
to.a[0]=from&255LL; |
to.a[1]=(from>>8LL)&255LL; |
to.a[2]=(from>>16LL)&255LL; |
to.a[3]=(from>>24LL)&255LL; |
to.a[4]=(from>>32LL)&255LL; |
to.a[5]=(from>>40LL)&255LL; |
to.a[6]=(from&0x800000000000LL)?255LL:0LL; |
to.a[7]=(from&0x800000000000LL)?255LL:0LL; |
return to; |
} |
/rf6809/trunk/software/vbcc/datatypes/dtconv.h
0,0 → 1,23
"S12BS","S16BSLE","dt12f.c","dt12t.c",2, |
"S12BU","S16BULE","dt12f.c","dt12t.c",2, |
"S24BS","S32BSLE","dt24f.c","dt24t.c",4, |
"S24BU","S32BULE","dt24f.c","dt24t.c",4, |
"S48BS","S64BSLE","dt48f.c","dt48t.c",8, |
"S48BU","S64BULE","dt48f.c","dt48t.c",8, |
"S16BSBE","S16BSLE","dtswap16f.c","dtswap16t.c",2, |
"S16BUBE","S16BULE","dtswap16f.c","dtswap16t.c",2, |
"S32BSBE","S32BSLE","dtswap32f.c","dtswap32t.c",4, |
"S32BUBE","S32BULE","dtswap32f.c","dtswap32t.c",4, |
"S64BSBE","S64BSLE","dtswap64f.c","dtswap64t.c",8, |
"S64BUBE","S64BULE","dtswap64f.c","dtswap64t.c",8, |
"S32BIEEEBE","S32BIEEELE","dtswap32f.c","dtswap32t.c",4, |
"S64BIEEEBE","S64BIEEELE","dtswap64f.c","dtswap64t.c",8, |
"S16BSLE","S16BSBE","dtswap16f.c","dtswap16t.c",2, |
"S16BULE","S16BUBE","dtswap16f.c","dtswap16t.c",2, |
"S32BSLE","S32BSBE","dtswap32f.c","dtswap32t.c",4, |
"S32BULE","S32BUBE","dtswap32f.c","dtswap32t.c",4, |
"S64BSLE","S64BSBE","dtswap64f.c","dtswap64t.c",8, |
"S64BULE","S64BUBE","dtswap64f.c","dtswap64t.c",8, |
"S32BIEEELE","S32BIEEEBE","dtswap32f.c","dtswap32t.c",4, |
"S64BIEEELE","S64BIEEEBE","dtswap64f.c","dtswap64t.c",8, |
|
/rf6809/trunk/software/vbcc/machines/hc12/machine.c
0,0 → 1,3808
/* Code generator for Motorola 68hc12 microcontrollers. */ |
|
/*TODO: |
regs_modified bei struct-copy |
savings verfeinern |
4-Byte Copy |
[static] testen |
peephole-Pass um ALLOCREGs zu entfernen |
ACC_IND (Achtung?) |
|
banked |
bit |
long long, float, double, long double |
|
*/ |
|
#include "supp.h" |
#include "vbc.h" /* nicht schoen, aber ... */ |
|
static char FILE_[]=__FILE__; |
|
#include "dwarf2.c" |
|
/* Public data that MUST be there. */ |
|
/* Name and copyright. */ |
char cg_copyright[]="vbcc code-generator for 6809/6803/68hc12 V0.2 (c) in 2000-2022 by Volker Barthelmann"; |
|
/* Commandline-flags the code-generator accepts */ |
int g_flags[MAXGF]={VALFLAG,VALFLAG,0,0, |
0,0,0,0, |
0,0}; |
char *g_flags_name[MAXGF]={"cpu","fpu","no-delayed-popping","const-in-data", |
"merge-constants","no-peephole","mem-cse","acc-glob", |
"pcrel","drel","no-char-addi2p","nodx","nou"}; |
union ppi g_flags_val[MAXGF]; |
|
/* Typenames (needed because of HAVE_EXT_TYPES). */ |
char *typname[]={"strange","bit","char","short","int","long","long long", |
"float","double","long double","void", |
"near-pointer","far-pointer","huge-pointer", |
"array","struct","union","enum","function"}; |
|
int bitsperbyte = 8; |
int bytemask = 0xff; |
int dbl_bytemask = 0xffff; |
|
/* Alignment-requirements for all types in bytes. */ |
zmax align[MAX_TYPE+1]; |
|
/* Alignment that is sufficient for every object. */ |
zmax maxalign; |
|
/* CHAR_BIT of the target machine. */ |
zmax char_bit; |
|
/* Sizes of all elementary types in bytes. */ |
zmax sizetab[MAX_TYPE+1]; |
|
/* Minimum and Maximum values each type can have. */ |
/* Must be initialized in init_cg(). */ |
zmax t_min[MAX_TYPE+1]; |
zumax t_max[MAX_TYPE+1]; |
zumax tu_max[MAX_TYPE+1]; |
|
/* Names of all registers. */ |
char *regnames[]={"noreg","d","x","y","sp","u","d/x"}; |
|
/* The Size of each register in bytes. */ |
zmax regsize[MAXR+1]; |
|
/* Type which can store each register. */ |
struct Typ *regtype[MAXR+1]; |
|
/* regsa[reg]!=0 if a certain register is allocated and should */ |
/* not be used by the compiler pass. */ |
int regsa[MAXR+1]; |
|
/* Specifies which registers may be scratched by functions. */ |
int regscratch[MAXR+1]={0,1,1,0,1,0}; |
|
int reg_prio[MAXR+1]={0,0,1,1,0,0}; |
|
struct reg_handle empty_reg_handle={0}; |
|
/* Names of target-specific variable attributes. */ |
char *g_attr_name[]={"__interrupt","__dpage","__far",0}; |
#define INTERRUPT 1 |
#define DPAGE 2 |
#define FAR 4 |
|
int MINADDI2P=CHAR; |
|
/****************************************/ |
/* Some private data and functions. */ |
/****************************************/ |
|
static long malign[MAX_TYPE+1]= {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; |
static long msizetab[MAX_TYPE+1]={0,1,1,2,2,4,4,4,4,4,0,2,4,4,0,0,0,2,0}; |
|
struct Typ ityp={SHORT},ltyp={LONG}; |
|
#define DATA 0 |
#define BSS 1 |
#define CODE 2 |
#define RODATA 3 |
#define SPECIAL 4 |
|
static int section=-1,newobj,scnt,pushed_acc; |
static char *codename="\t.text\n", |
*dataname="\t.data\n", |
*bssname="\t.section\t.bss\n", |
*rodataname="\t.section\t.rodata\n"; |
|
#define IMM_IND 1 |
#define VAR_IND 2 |
#define POST_INC 3 |
#define POST_DEC 4 |
#define PRE_INC 5 |
#define PRE_DEC 6 |
#define ACC_IND 7 |
#define KONSTINC 8 |
|
/* (user)stack-pointer, pointer-tmp, int-tmp; reserved for compiler */ |
static int acc=1,ix=2,iy=3,sp=4,iu=5,dx=6; |
static void pr(FILE *,struct IC *); |
static void function_top(FILE *,struct Var *,long); |
static void function_bottom(FILE *f,struct Var *,long); |
|
static char *marray[]={"__section(x,y)=__vattr(\"section(\"#x\",\"#y\")\")", |
"__HC12__", |
"__SIZE_T_INT=1", |
"__direct=__vattr(\"section(\\\"dpage\\\")\")", |
0}; |
|
#define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG) |
#define isconst(x) ((p->x.flags&(KONST|DREFOBJ))==KONST) |
|
static long loff,roff,stackoffset,notpopped,dontpop,maxpushed,stack; |
|
static char *x_t[]={"?","","b","","","","","","","","","","","","","",""}; |
static char *ccs[]={"eq","ne","lt","ge","le","gt"}; |
static char *uccs[]={"eq","ne","lo","hs","ls","hi"}; |
static char *logicals[]={"ora","eor","and"}; |
static char *dct[]={"",".bit",".byte",".2byte",".2byte",".4byte",".8byte",".4byte",".8byte",".8byte", |
"(void)",".2byte",".34byte",".34byte"}; |
static char *idprefix="",*labprefix=".l"; |
static int exit_label,have_frame; |
static char *ret; |
static int stackchecklabel; |
static int frame_used,stack_valid; |
static int CPU=6812; |
static int pcrel,drel; |
static int skip_rel; |
static char *jsrinst="jsr"; |
static char *jmpinst="jmp"; |
static int nodx,nou; |
int switchsubs; |
|
static int cc_t; |
static struct obj *cc; |
|
static struct obj mobj; |
|
#define STR_NEAR "near" |
#define STR_FAR "far" |
#define STR_HUGE "huge" |
#define STR_BADDR "baddr" |
|
#define ISNULL() (zmeqto(vmax,l2zm(0L))&&zumeqto(vumax,ul2zum(0UL))&&zldeqto(vldouble,d2zld(0.0))) |
#define ISLWORD(t) ((t&NQ)==LONG||(t&NQ)==FPOINTER||(t&NQ)==HPOINTER||(t&NQ)==FLOAT) |
#define ISHWORD(t) ((t&NQ)==INT||(t&NQ)==SHORT||(t&NQ)==NPOINTER) |
#define ISCHWORD(t) ((t&NQ)==CHAR||ISHWORD(t)) |
#define ISSTATIC(v) ((v)->storage_class==EXTERN||(v)->storage_class==STATIC) |
#define ISBADDR(v) ((v)->vtyp->attr&&strstr(STR_BADDR,(v)->vtyp->attr)) |
/*FIXME*/ |
#define ISFAR(v) ((v)->vtyp->attr&&(strstr(STR_FAR,(v)->vtyp->attr)||strstr(STR_HUGE,(v)->vtyp->attr))) |
|
#define ISACC(x) ((x)==acc) |
#define ISX(x) ((x)==ix) |
#define ISY(x) ((x)==iy) |
#define ISU(x) ((x)==iu) |
#define ISIDX(x) (ISX(x)||ISY(x)||(ISU(x)&&CPU!=6812)) |
#define ISRACC(x) (isreg(x)&&ISACC(p->x.reg)) |
#define ISRX(x) (isreg(x)&&ISX(p->x.reg)) |
#define ISRY(x) (isreg(x)&&ISY(p->x.reg)) |
#define ISRU(x) (isreg(x)&&ISU(p->x.reg)) |
#define ISRIDX(x) (isreg(x)&&ISIDX(p->x.reg)) |
|
#define CPUOPT ((g_flags[0]&USEDFLAG)?g_flags_val[0].l:6812) |
|
#define SPUSH(x) (CPU==6812?"\tpsh" x "\n":"\tpshs\t" x "\n") |
#define SPUSHD (CPU==6812?"\tpshd\n":"\tpshs\tb,a\n") |
#define SPULL(x) (CPU==6812?"\tpul" x "\n":"\tpuls\t" x "\n") |
#define SPULLD (CPU==6812?"\tpuld\n":"\tpuls\ta,b\n") |
#define SCMP(x) (CPU==6812?"\tcp" x "\t":"\tcmp" x "\t") |
#define SEX (CPU==6812?"\tsex\tb,d\n":"\tsex\n") |
|
#define SGN16(x) (zm2l(zi2zm(zm2zi(l2zm((long)(x)))))) |
|
enum peepf { NEEDSAME = 1, REMOVE1ST = 2, ALLOWSFX = 4}; |
struct peeps {char *s1,*s2,*r;enum peepf flags;}; |
|
static int check_sfx(char *s) |
{ |
if(!*s) return 0; |
s+=strlen(s)-1; |
if(*s=='+'||*s=='-') return 1; |
if(*s!='s'&&*s!='x'&&*s!='y'&&*s!='u') return 0; |
s--; |
if(*s!=',') return 0; |
s--; |
if(*s=='+'||*s=='-') return 1; |
return 0; |
} |
|
static int setszflag(char *op,char r) |
{ |
static char *zb[]={"adcb","addb","andb","aslb","asrb","clrb","comb","decb","eorb","incb", |
"ldab","ldb","lslb","lsrb","negb","orb","orab","rolb","rorb","sbcb", |
"stb","stab","subb","tstb"}; |
static char *zd[]={"addd","ldd","sex","std","subd"}; |
|
int i; |
|
if(r=='b'){ |
for(i=0;i<sizeof(zb)/sizeof(*zb);i++) |
if(!strcmp(op,zb[i])) |
return 1; |
} |
if(r=='d'){ |
for(i=0;i<sizeof(zd)/sizeof(*zd);i++) |
if(!strcmp(op,zd[i])) |
return 1; |
} |
if(r=='x'&&(!strcmp(op,"leax")||!strcmp(op,"ldx"))) return 1; |
if(r=='y'&&(!strcmp(op,"leay")||!strcmp(op,"ldy"))) return 1; |
if(CPU==6812){ |
if(r=='x'&&(!strcmp(op,"dex")||!strcmp(op,"inx"))) return 1; |
if(r=='y'&&(!strcmp(op,"dey")||!strcmp(op,"iny"))) return 1; |
} |
return 0; |
} |
|
int emit_peephole(void) |
{ |
int entries,i,j,v1,v2; |
char *asmline[EMIT_BUF_DEPTH]; |
char buf1[1024],buf2[1024]; |
char op1[8],op2[8]; |
|
|
/* TODO: adapt better */ |
static struct peeps elim[]={ |
"lda","sta",0,NEEDSAME, |
"ldb","stb",0,NEEDSAME, |
"ldaa","staa",0,NEEDSAME, |
"ldab","stab",0,NEEDSAME, |
"ldd","std",0,NEEDSAME, |
"ldx","stx",0,NEEDSAME, |
"ldy","sty",0,NEEDSAME, |
"ldu","stu",0,NEEDSAME, |
"sta","sta",0,NEEDSAME, |
"stb","stb",0,NEEDSAME, |
"staa","staa",0,NEEDSAME, |
"stab","stab",0,NEEDSAME, |
"std","std",0,NEEDSAME, |
"stx","stx",0,NEEDSAME, |
"sty","sty",0,NEEDSAME, |
"stu","stu",0,NEEDSAME, |
"sta","lda",0,NEEDSAME, |
"stb","ldb",0,NEEDSAME, |
"staa","ldaa",0,NEEDSAME, |
"stab","ldab",0,NEEDSAME, |
"std","ldd",0,NEEDSAME, |
"stx","ldx",0,NEEDSAME, |
"sty","ldy",0,NEEDSAME, |
"stu","ldu",0,NEEDSAME, |
#if 0 |
"lda","lda",0,REMOVE1ST, |
"ldaa","ldaa",0,REMOVE1ST, |
"ldab","ldab",0,REMOVE1ST, |
"ldb","ldb",0,REMOVE1ST, |
"ldd","ldd",0,REMOVE1ST, |
"ldx","ldx",0,REMOVE1ST, |
"ldy","ldy",0,REMOVE1ST, |
"ldu","ldu",0,REMOVE1ST, |
"lda","pla",0,REMOVE1ST, |
"lda","txa",0,REMOVE1ST, |
"lda","tya",0,REMOVE1ST, |
"ldx","tax",0,REMOVE1ST, |
"ldy","tay",0,REMOVE1ST, |
"tay","ldy",0,REMOVE1ST, |
"tax","ldx",0,REMOVE1ST, |
"txa","lda",0,REMOVE1ST, |
"tya","lda",0,REMOVE1ST, |
#endif |
}; |
|
|
i=emit_l; |
if(emit_f==0) |
entries=i-emit_f+1; |
else |
entries=EMIT_BUF_DEPTH; |
asmline[0]=emit_buffer[i]; |
if(sscanf(asmline[0]," %6s %999s",op1,buf1)==2&&!strcmp(op1,"cmpb")&&!strcmp(buf1,"#0")) |
strcpy(asmline[0],"\ttstb\n"); |
if(sscanf(asmline[0]," %6s %999s",op1,buf1)==2&&!strcmp(op1,"cmpd")&&!strcmp(buf1,"#0")) |
strcpy(asmline[0],"\tsubd\t#0\n"); |
|
if(entries>=2){ |
i--; |
if(i<0) i=EMIT_BUF_DEPTH-1; |
asmline[1]=emit_buffer[i]; |
|
for(j=0;j<sizeof(elim)/sizeof(elim[0]);j++){ |
if(elim[j].flags&NEEDSAME){ |
if(sscanf(asmline[0]," %6s %999s",op2,buf2)==2&& |
sscanf(asmline[1]," %6s %999s",op1,buf1)==2&& |
!strcmp(op1,elim[j].s1)&&!strcmp(op2,elim[j].s2)&& |
!strcmp(buf1,buf2)){ |
if(!check_sfx(buf1)&&!check_sfx(buf2)){ |
if(elim[j].r){ |
strcpy(asmline[0],elim[j].r); |
}else{ |
if(elim[j].flags&REMOVE1ST) |
strcpy(asmline[1],asmline[0]); |
remove_asm(); |
} |
return 1; |
} |
} |
}else{ |
*buf1=0;*buf2=0; |
if(sscanf(asmline[1]," %6s %999s",op1,buf1)>=1&& |
sscanf(asmline[0]," %6s %999s",op2,buf2)>=1&& |
!strcmp(op1,elim[j].s1)&&!strcmp(op2,elim[j].s2)){ |
if((elim[j].flags&ALLOWSFX)||(!check_sfx(buf1)&&!check_sfx(buf2))){ |
if(elim[j].flags&REMOVE1ST) |
strcpy(asmline[1],asmline[0]); |
remove_asm(); |
return 1; |
} |
} |
} |
} |
|
if(!strcmp(asmline[0],"\trts\n")&&sscanf(asmline[1]," %6s %999s",op1,buf1)==2&&!strcmp(op1,"puls")){ |
sprintf(asmline[1]+strlen(asmline[1])-1,",pc\n"); |
remove_asm(); |
return 1; |
} |
|
if(!strcmp(asmline[0],"\tstb\t0,s\n")&&!strcmp(asmline[1],"\tleas\t-1,s\n")){ |
strcpy(asmline[1],"\tpshs\tb\n"); |
remove_asm(); |
return 1; |
} |
|
if(!strcmp(asmline[0],"\tstd\t0,s\n")&&!strcmp(asmline[1],"\tleas\t-2,s\n")){ |
strcpy(asmline[1],"\tpshs\tb,a\n"); |
remove_asm(); |
return 1; |
} |
|
if(!strcmp(asmline[0],"\tldb\t0,s\n")&&!strcmp(asmline[1],"\tpshs\tb\n")){ |
remove_asm(); |
return 1; |
} |
|
if(!strcmp(asmline[0],"\tldd\t0,s\n")&&!strcmp(asmline[1],"\tpshs\tb,a\n")){ |
remove_asm(); |
return 1; |
} |
|
if(!strcmp(asmline[0],"\tpshs\tb,a\n")&&!strcmp(asmline[1],"\tpuls\ta,b\n")){ |
strcpy(asmline[1],"\tldd\t0,s\n"); |
remove_asm(); |
return 1; |
} |
|
if(sscanf(asmline[1]," ldd %999s",op1)>=1&&sscanf(asmline[0]," ldd %999s",op2)>=1){ |
if(!((op2[0]=='a'||op2[0]=='b'||op2[0]=='d')&&op2[1]==',')){ |
strcpy(asmline[1],asmline[0]); |
remove_asm(); |
return 1; |
} |
} |
|
if(!strcmp(asmline[0],"\ttfr\tx,d\n")&&!strcmp(asmline[1],"\ttfr\td,x\n")){ |
remove_asm(); |
return 1; |
} |
if(!strcmp(asmline[0],"\ttfr\ty,d\n")&&!strcmp(asmline[1],"\ttfr\td,y\n")){ |
remove_asm(); |
return 1; |
} |
if(!strcmp(asmline[0],"\tstd\t0,sp\n")&&!strcmp(asmline[1],"\tpshd\n")){ |
remove_asm(); |
return 1; |
} |
if(!strcmp(asmline[0],"\tldd\t0,sp\n")&&!strcmp(asmline[1],"\tpshd\n")){ |
remove_asm(); |
return 1; |
} |
|
if(sscanf(asmline[0]," leas %d,s",&v1)==1&&sscanf(asmline[1]," leas %d,s",&v2)==1){ |
sprintf(asmline[1],"\tleas\t%ld,s\n",SGN16(v1+v2)); |
remove_asm(); |
return 1; |
} |
|
if(CPU!=6812&&sscanf(asmline[0]," tfr %c,%c",buf1,buf2)==2){ |
if((*buf1=='x'||*buf1=='y'||*buf1=='u'||*buf1=='s')&& |
(*buf2=='x'||*buf2=='y'||*buf2=='u'||*buf2=='s')){ |
sprintf(asmline[0],"\tlea%c\t,%c\n",*buf2,*buf1); |
} |
} |
if(CPU==6812&&(!strcmp(asmline[1],"\tdex\n")||!strcmp(asmline[1],"\tdey\n")||!strcmp(asmline[1],"\tsubd\t#1\n"))&& |
(!strncmp(asmline[0],"\tbne\t",5)||!strncmp(asmline[0],"\tbeq\t",5))){ |
char r=asmline[1][3]; |
if(r=='b') r='d'; |
strcpy(asmline[1],"\td"); |
strncpy(asmline[1]+2,asmline[0]+1,4); |
asmline[1][6]=r;asmline[1][7]=','; |
strcpy(asmline[1]+8,asmline[0]+5); |
remove_asm(); |
return 1; |
} |
if(CPU==6812&&(!strcmp(asmline[1],"\tinx\n")||!strcmp(asmline[1],"\tiny\n")||!strcmp(asmline[1],"\taddd\t#1\n"))&& |
(!strncmp(asmline[0],"\tbne\t",5)||!strncmp(asmline[0],"\tbeq\t",5))){ |
char r=asmline[1][3]; |
strcpy(asmline[1],"\ti"); |
strncpy(asmline[1]+2,asmline[0]+1,4); |
asmline[1][6]=r;asmline[1][7]=','; |
strcpy(asmline[1]+8,asmline[0]+5); |
remove_asm(); |
return 1; |
} |
} |
if(entries>=3){ |
i--; |
if(i<0) i=EMIT_BUF_DEPTH-1; |
asmline[2]=emit_buffer[i]; |
if(sscanf(asmline[0]," %6s %999s",op1,buf1)==2){ |
if(!strcmp(op1,"beq")||!strcmp(op1,"bne")){ |
if(!strcmp(asmline[1],"\ttstb\n")||!strcmp(asmline[1],"\tcpb\t#0\n")){ |
if(sscanf(asmline[2]," %6s %999s",op2,buf2)>=1&& |
setszflag(op2,'b')){ |
strcpy(asmline[1],asmline[0]); |
remove_asm(); |
return 1; |
} |
} |
if(sscanf(asmline[1]," %6s %999s",op2,buf2)==2&& |
(!strcmp(op2,"subd")||!strcmp(op2,"cpd"))&&!strcmp(buf2,"#0")){ |
if(sscanf(asmline[2]," %6s %999s",op2,buf2)>=1&& |
setszflag(op2,'d')){ |
strcpy(asmline[1],asmline[0]); |
remove_asm(); |
return 1; |
} |
} |
if(sscanf(asmline[1]," %6s %999s",op2,buf2)==2&& |
!strcmp(op2,(CPU==6812)?"cpx":"cmpx")&&!strcmp(buf2,"#0")){ |
if(sscanf(asmline[2]," %6s %999s",op2,buf2)>=1&& |
setszflag(op2,'x')){ |
strcpy(asmline[1],asmline[0]); |
remove_asm(); |
return 1; |
} |
} |
if(sscanf(asmline[1]," %6s %999s",op2,buf2)==2&& |
!strcmp(op2,(CPU==6812)?"cpy":"cmpy")&&!strcmp(buf2,"#0")){ |
if(sscanf(asmline[2]," %6s %999s",op2,buf2)>=1&& |
setszflag(op2,'y')){ |
strcpy(asmline[1],asmline[0]); |
remove_asm(); |
return 1; |
} |
} |
} |
} |
} |
return 0; |
} |
|
static int special_section(FILE *f,struct Var *v) |
{ |
char *sec; |
if(v->tattr&DPAGE){ |
emit(f,"\t.section\t.dpage\n"); |
}else{ |
if(!v->vattr) return 0; |
sec=strstr(v->vattr,"section("); |
if(!sec) return 0; |
sec+=strlen("section("); |
emit(f,"\t.section\t"); |
while(*sec&&*sec!=')') emit_char(f,*sec++); |
emit(f,"\n"); |
} |
if(f) section=SPECIAL; |
return 1; |
} |
|
static struct fpconstlist { |
struct fpconstlist *next; |
int label,typ; |
union atyps val; |
} *firstfpc; |
|
static int addfpconst(struct obj *o,int t) |
{ |
struct fpconstlist *p=firstfpc; |
t&=NQ; |
if(g_flags[4]&USEDFLAG){ |
for(p=firstfpc;p;p=p->next){ |
if(t==p->typ){ |
eval_const(&p->val,t); |
if(t==FLOAT&&zldeqto(vldouble,zf2zld(o->val.vfloat))) return p->label; |
if(t==DOUBLE&&zldeqto(vldouble,zd2zld(o->val.vdouble))) return p->label; |
if(t==LDOUBLE&&zldeqto(vldouble,o->val.vldouble)) return p->label; |
} |
} |
} |
p=mymalloc(sizeof(struct fpconstlist)); |
p->next=firstfpc; |
p->label=++label; |
p->typ=t; |
p->val=o->val; |
firstfpc=p; |
return p->label; |
} |
|
int pointer_type(struct Typ *p) |
{ |
if(!p) ierror(0); |
while((p->flags&NQ)==ARRAY) p=p->next; |
if((p->flags&NQ)==FUNKT) { |
if(p->attr) |
if(strstr(p->attr,STR_FAR)) return FPOINTER; |
if (p->flags&FAR) |
return FPOINTER; |
return NPOINTER; /*FIXME: banked*/ |
} |
if(p->attr){ |
if(strstr(p->attr,STR_HUGE)) return HPOINTER; |
if(strstr(p->attr,STR_FAR)) return FPOINTER; |
if(strstr(p->attr,STR_NEAR)) return NPOINTER; |
} |
/*FIXME*/ |
return NPOINTER; |
} |
static long voff(struct obj *p) |
{ |
if(zm2l(p->v->offset)<0) |
return loff-zm2l(p->v->offset)+zm2l(p->val.vmax)-stackoffset+1; |
else |
return zm2l(p->v->offset)+zm2l(p->val.vmax)-stackoffset; |
} |
|
static void emit_obj(FILE *f,struct obj *p,int t) |
/* Gibt Objekt auf Bildschirm aus */ |
{ |
if(p->am){ |
int flags=p->am->flags; |
if(flags==ACC_IND){ |
emit(f,"%s,%s",regnames[acc],regnames[p->am->base]); |
return; |
} |
if(flags==KONSTINC){ |
eval_const(&p->val,p->am->base); |
if((t&NQ)==CHAR){ |
vumax=zumrshift(vumax,bitsperbyte*3-bitsperbyte*p->am->offset); |
vumax=zumand(vumax,ul2zum(tu_max[CHAR])); |
}else{ |
vumax=zumrshift(vumax,bitsperbyte*2-bitsperbyte*p->am->offset); |
vumax=zumand(vumax,ul2zum(tu_max[SHORT])); |
} |
emit(f,"#%lu",zum2ul(vumax)); |
return; |
} |
if(flags<POST_INC||flags>PRE_DEC||CPU==6812) |
emit(f,"%ld",p->am->offset&tu_max[SHORT]); |
if(p->am->v){ |
if(p->am->v->storage_class==STATIC) |
emit(f,"+%s%ld",labprefix,zm2l(p->am->v->offset)); |
else |
emit(f,"+(%s%s)",idprefix,p->am->v->identifier); |
} |
emit(f,","); |
if(flags==PRE_INC){ |
emit(f,"+"); |
if(p->am->offset==2&&CPU!=6812) emit(f,"+"); |
}else if(flags==PRE_DEC){ |
emit(f,"-"); |
if(p->am->offset==2&&CPU!=6812) emit(f,"-"); |
} |
emit(f,"%s",regnames[p->am->base]); |
if(flags==POST_INC){ |
emit(f,"+"); |
if(p->am->offset==2&&CPU!=6812) emit(f,"+"); |
}else if(flags==POST_DEC){ |
emit(f,"-"); |
if(p->am->offset==2&&CPU!=6812) emit(f,"-"); |
} |
return; |
} |
if((p->flags&(KONST|DREFOBJ))==(KONST|DREFOBJ)){ |
emitval(f,&p->val,p->dtyp&NU); |
return; |
} |
if(p->flags&VARADR) emit(f,"#"); |
if((p->flags&(DREFOBJ|REG))==(DREFOBJ|REG)) emit(f,"0,"); |
if((p->flags&(DREFOBJ|REG))==DREFOBJ) emit(f,"["); |
if((p->flags&(VAR|REG))==VAR){ |
if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER){ |
emit(f,"%ld,%s",voff(p),regnames[sp]); |
}else{ |
if(!zmeqto(l2zm(0L),p->val.vmax)){ |
emit(f,"%ld",zm2l(zi2zm(zm2zi(p->val.vmax)))); |
emit(f,"+"); |
} |
if(p->v->storage_class==STATIC){ |
emit(f,"%s%ld",labprefix,zm2l(p->v->offset)); |
}else{ |
emit(f,"(%s%s)",idprefix,p->v->identifier); |
} |
if(pcrel&&!(p->flags&VARADR)&&ISFUNC(p->v->vtyp->flags)) |
emit(f,",pc"); |
if(drel&&!(p->flags&VARADR)&&!ISFUNC(p->v->vtyp->flags)){ |
if(CPU==6812) ierror(0); |
emit(f,",%s",regnames[iu]); |
} |
} |
} |
if(p->flags®){ |
if(ISACC(p->reg)&&(t&NQ)==CHAR) |
emit(f,"b"); |
else |
emit(f,"%s",regnames[p->reg]); |
} |
if(p->flags&KONST){ |
if(ISFLOAT(t)){ |
emit(f,"%s%d",labprefix,addfpconst(p,t)); |
}else{ |
emit(f,"#");emitval(f,&p->val,t&NU); |
} |
} |
if((p->flags&(DREFOBJ|REG))==DREFOBJ){ |
if(p->v->storage_class==EXTERN||p->v->storage_class==STATIC){ |
if(is_const(p->v->vtyp)){ |
if(!pcrel&&CPU==6812) emit(f,",pc"); |
}else{ |
if(!drel&&CPU==6812) emit(f,",pc"); |
} |
} |
emit(f,"]"); |
} |
} |
|
static void dwarf2_print_frame_location(FILE *f,struct Var *v) |
{ |
/*FIXME: needs a location list and correct register translation */ |
struct obj o; |
o.flags=REG; |
o.reg=sp; |
o.val.vmax=l2zm(0L); |
o.v=0; |
dwarf2_print_location(f,&o); |
} |
static int dwarf2_regnumber(int r) |
{ |
/*FIXME: always returns D as accumulator, even if byte size */ |
static int dwarf_regs[MAXR+1]={-1,3,7,8,15}; |
return dwarf_regs[r]; |
} |
static zmax dwarf2_fboffset(struct Var *v) |
{ |
/*FIXME*/ |
if(!v||(v->storage_class!=AUTO&&v->storage_class!=REGISTER)) ierror(0); |
if(!zmleq(l2zm(0L),v->offset)) |
return l2zm((long)(loff-zm2l(v->offset))); |
else |
return v->offset; |
} |
|
/* test operand for mov instruction */ |
static int mov_op(struct obj *o) |
{ |
long off; |
if(CPU!=6812) return 0; |
if(o->am){ |
int f=o->am->flags; |
if(f==POST_INC||f==PRE_INC||f==POST_DEC||f==PRE_DEC||f==ACC_IND) |
return 1; |
if(f==IMM_IND){ |
if(o->am->v) return 0; |
off=o->am->offset; |
if(off>=-256&&off<=255) |
return 1; |
else |
return 0; |
} |
ierror(0); |
} |
if(o->flags&(KONST|VARADR)) return 1; |
if((o->flags&(REG|DREFOBJ))==(REG|DREFOBJ)) return 1; |
if((o->flags&(VAR|REG|DREFOBJ))==VAR){ |
if(o->v->storage_class==STATIC||o->v->storage_class==EXTERN) |
return 1; |
off=voff(o); |
if(off>=-256&&off<=255) |
return 1; |
else |
return 0; |
} |
return 0; |
} |
|
/* add an offset to an object describing a memory address */ |
static void inc_addr(struct obj *o,long val,int t) |
{ |
if(o->am){ |
int f=o->am->flags; |
if(f==IMM_IND||f==KONSTINC) |
o->am->offset+=val; |
else if(f==POST_INC||f==POST_DEC||f==PRE_INC||f==PRE_DEC){ |
struct AddressingMode *old=o->am; |
o->am=mymalloc(sizeof(*o->am)); |
o->am->flags=IMM_IND; |
o->am->base=old->base; |
o->am->v=0; |
if(f==POST_DEC) o->am->offset=old->offset-val; |
else if(f==POST_INC) o->am->offset=-old->offset+val; |
else if(f==PRE_DEC) o->am->offset=val; |
else o->am->offset=-val; |
}else |
ierror(0); |
}else if(o->flags&DREFOBJ){ |
struct AddressingMode *am; |
o->am=am=mymalloc(sizeof(*am)); |
am->flags=IMM_IND; |
if(!o->reg) ierror(0); |
am->base=o->reg; |
am->offset=zm2l(val); |
am->v=0; |
}else if(o->flags&KONST){ |
struct AddressingMode *am; |
if(o->am) ierror(0); |
o->am=am=mymalloc(sizeof(*am)); |
am->flags=KONSTINC; |
am->offset=zm2l(val); |
am->base=t; |
}else{ |
o->val.vmax=zmadd(o->val.vmax,val); |
} |
} |
|
/* pushed on the stack by a callee, no pop needed */ |
static void callee_push(long l) |
{ |
if(l-stackoffset>stack) |
stack=l-stackoffset; |
} |
static void push(long l) |
{ |
stackoffset-=l; |
if(stackoffset<maxpushed) maxpushed=stackoffset; |
if(-maxpushed>stack) stack=-maxpushed; |
} |
static void pop(long l) |
{ |
stackoffset+=l; |
} |
static void gen_pop(FILE *f,long l) |
{ |
if(l==0) return; |
if(l==1&&CPU==6812){ |
emit(f,"\tins\n"); |
#if 0 /* might clobber return register */ |
}else if(l==2&&!regs[acc]){ |
emit(f,SPULLD); |
BSET(regs_modified,acc); |
}else if(l==2&&!regs[ix]){ |
emit(f,SPULL("x")); |
BSET(regs_modified,ix); |
}else if(l==2&&!regs[iy]){ |
emit(f,SPULL("y")); |
BSET(regs_modified,iy); |
#endif |
}else{ |
emit(f,"\tleas\t%u,%s\n",SGN16(l),regnames[sp]); |
} |
pop(l); |
} |
static void pr(FILE *f,struct IC *p) |
{ |
int r; |
if(pushed_acc){ |
emit(f,SPULLD); |
pop(2); |
pushed_acc=0; |
} |
for(r=MAXR;r>=1;r--){ |
if(regs[r]&8){ |
emit(f,"\t%s%s\n",CPU==6812?"pul":"puls\t",regnames[r]); |
pop(2); |
} |
regs[r]&=~12; |
} |
} |
static void function_top(FILE *f,struct Var *v,long offset) |
/* erzeugt Funktionskopf */ |
{ |
int i; |
emit(f,"# offset=%ld\n",offset); |
have_frame=0;stack_valid=1;stack=0; |
if(!special_section(f,v)&§ion!=CODE){emit(f,codename);if(f) section=CODE;} |
if(v->storage_class==EXTERN){ |
if((v->flags&(INLINEFUNC|INLINEEXT))!=INLINEFUNC) |
emit(f,"\t.global\t%s%s\n",idprefix,v->identifier); |
emit(f,"%s%s:\n",idprefix,v->identifier); |
}else{ |
emit(f,"%s%ld:\n",labprefix,zm2l(v->offset)); |
} |
roff=0; |
for(i=MAXR;i>0;i--){ |
if(regused[i]&&!regscratch[i]&&!regsa[i]){ |
have_frame=1; |
loff+=2; |
roff+=2; |
if(i==iy) emit(f,SPUSH("y")); |
else if(i==iu){ |
if(CPU!=6812&®used[iy]){ |
emit(f,"\tpshs\tu,y\n"); |
loff+=2;roff+=2;i=iy; |
}else |
emit(f,SPUSH("u")); |
}else |
ierror(0); |
} |
} |
if(stack_check){ |
stackchecklabel=++label; |
emit(f,"\tldy\t#%s%d\n",labprefix,stackchecklabel); |
/* FIXME: banked */ |
emit(f,"\t%s\t%s__stack_check\n",jsrinst,idprefix); |
} |
if(offset){ |
if(CPU==6812&&offset==1) |
emit(f,SPUSH("b")); |
else if(CPU==6812&&offset==2) |
emit(f,SPUSHD); |
else |
emit(f,"\tleas\t%ld,%s\n",SGN16(-offset),regnames[sp]); |
have_frame=1; |
} |
} |
static void function_bottom(FILE *f,struct Var *v,long offset) |
/* erzeugt Funktionsende */ |
{ |
int i; |
offset-=roff; |
if(offset){ |
if(offset==1&&CPU==6812) |
emit(f,"\tins\n"); |
else if(offset==2&&CPU==6812&&!zmeqto(szof(v->vtyp->next),l2zm(4L))) |
emit(f,SPULL("x")); |
else if(offset==2&&CPU==6812&®used[iy]) |
emit(f,SPULL("y")); |
else |
emit(f,"\tleas\t%ld,%s\n",SGN16(offset),regnames[sp]); |
} |
for(i=1;i<=MAXR;i++){ |
if(regused[i]&&!regscratch[i]&&!regsa[i]){ |
have_frame=1; |
if(i==iy){ |
if(CPU!=6812&®used[iu]&&!regscratch[iu]&&!regsa[iu]){ |
emit(f,"\tpuls\tu,y\n"); |
i=iu; |
}else |
emit(f,SPULL("y")); |
}else if(i==iu) emit(f,SPULL("u")); |
else |
ierror(0); |
} |
} |
if(ret) emit(f,"\t%s\n",ret); |
if(v->storage_class==EXTERN){ |
emit(f,"\t.type\t%s%s,@function\n",idprefix,v->identifier); |
emit(f,"\t.size\t%s%s,$-%s%s\n",idprefix,v->identifier,idprefix,v->identifier); |
}else{ |
emit(f,"\t.type\t%s%ld,@function\n",labprefix,zm2l(v->offset)); |
emit(f,"\t.size\t%s%ld,$-%s%ld\n",labprefix,zm2l(v->offset),labprefix,zm2l(v->offset)); |
} |
if(stack_check) |
emit(f,"\t.equ\t%s%d,%ld\n",labprefix,stackchecklabel,offset-maxpushed); |
if(stack_valid){ |
if(!v->fi) v->fi=new_fi(); |
v->fi->flags|=ALL_STACK; |
v->fi->stack1=l2zm(stack+offset); |
emit(f,"# stacksize=%ld\n",stack+offset); |
emit(f,"\t.equ\t%s__stack_%s,%ld\n",idprefix,v->identifier,stack+offset); |
} |
} |
static int compare_objects(struct obj *o1,struct obj *o2) |
{ |
if(o1->flags==o2->flags&&o1->am==o2->am){ |
if(!(o1->flags&VAR)||(o1->v==o2->v&&zmeqto(o1->val.vmax,o2->val.vmax))){ |
if(!(o1->flags®)||o1->reg==o2->reg){ |
return 1; |
} |
} |
} |
return 0; |
} |
|
/*FIXME*/ |
static void clear_ext_ic(struct ext_ic *p) |
{ |
p->flags=0; |
p->r=0; |
p->offset=0; |
} |
static long pof2(zumax x) |
/* Yields log2(x)+1 oder 0. */ |
{ |
zumax p;int ln=1; |
p=ul2zum(1L); |
while(ln<=32&&zumleq(p,x)){ |
if(zumeqto(x,p)) return ln; |
ln++;p=zumadd(p,p); |
} |
return 0; |
} |
static void peephole(struct IC *p) |
{ |
int c,c2,r,t;struct IC *p2; |
struct AddressingMode *am; |
zmax incmin,incmax; |
if(CPU==6812){ |
incmin=l2zm(-8L); |
incmax=l2zm(8L); |
}else{ |
incmin=l2zm(-2L); |
incmax=l2zm(2L); |
} |
frame_used=0; |
for(;p;p=p->next){ |
c=p->code; |
if(!frame_used){ |
if((p->q1.flags&(REG|VAR))==VAR&&!ISSTATIC(p->q1.v)) frame_used=1; |
if((p->q2.flags&(REG|VAR))==VAR&&!ISSTATIC(p->q2.v)) frame_used=1; |
if((p->z.flags&(REG|VAR))==VAR&&!ISSTATIC(p->z.v)) frame_used=1; |
} |
/* letztes Label merken */ |
if(c!=FREEREG&&c!=ALLOCREG&&(c!=SETRETURN||!isreg(q1)||p->q1.reg!=p->z.reg)) exit_label=0; |
if(c==LABEL) exit_label=p->typf; |
#if 0 |
/* and x,#const;bne/beq, FIXME */ |
if(c==AND&&isconst(q2)&&isreg(z)){ |
long bit; |
eval_const(&p->q2.val,p->typf); |
if(bit=pof2(vumax)){ |
struct IC *cmp=0;int fr=0; |
for(p2=p->next;p2;p2=p2->next){ |
c2=p2->code; |
if(c2==TEST){ |
if((p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==p->z.reg){ |
cmp=p2;continue; |
} |
} |
if(c2==COMPARE&&(p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==p->z.reg&&(p2->q2.flags&(KONST|DREFOBJ))==KONST){ |
eval_const(&p2->q2.val,p2->typf); |
if(ISNULL()){ |
cmp=p2;continue; |
} |
break; |
} |
if(c2==FREEREG&&p2->q1.reg==p->z.reg) {fr++;continue;} |
if((c2==BNE||c2==BEQ)&&cmp&&fr==1){ |
p->ext.flags=EXT_IC_BTST; |
p2->ext.flags=EXT_IC_BTST; |
p2->ext.offset=bit-1; |
cmp->code=NOP; |
cmp->q1.flags=cmp->q2.flags=cmp->z.flags=0; |
break; |
} |
if(((p2->q1.flags®)&&p2->q1.reg==p->z.reg)||((p2->q2.flags®)&&p2->q2.reg==p->z.reg)||((p2->z.flags®)&&p2->z.reg==p->z.reg)) break; |
if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break; |
} |
} |
} |
#endif |
/* Try d,idx */ |
if(c==ADDI2P&&ISRACC(q2)&&ISRIDX(z)&&(ISRIDX(q1)||p->q2.reg!=p->z.reg)){ |
int base,idx;struct obj *o; |
r=p->z.reg;idx=p->q2.reg; |
if(isreg(q1)) base=p->q1.reg; else base=r; |
o=0; |
for(p2=p->next;p2;p2=p2->next){ |
c2=p2->code; |
if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break; |
if(c2!=FREEREG&&(p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r) break; |
if(c2!=FREEREG&&(p2->q2.flags&(REG|DREFOBJ))==REG&&p2->q2.reg==r) break; |
if((p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg==idx&&idx!=r) break; |
|
if(c2!=CALL&&(c2<LABEL||c2>BRA)/*&&c2!=ADDRESS*/){ |
if(!p2->q1.am&&(p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r){ |
if(o||!ISCHWORD(q1typ(p2))) break; |
o=&p2->q1; |
} |
if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){ |
break; /*TODO: check what is possible */ |
if(o||!ISCHWORD(q2typ(p2))) break; |
o=&p2->q2; |
} |
if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){ |
break; /*TODO: check what is possible */ |
if(o||!ISCHWORD(ztyp(p2))) break; |
o=&p2->z; |
} |
} |
if(c2==FREEREG||(p2->z.flags&(REG|DREFOBJ))==REG){ |
int m; |
if(c2==FREEREG) |
m=p2->q1.reg; |
else |
m=p2->z.reg; |
if(m==r){ |
if(o){ |
o->am=am=mymalloc(sizeof(*am)); |
am->flags=ACC_IND; |
am->base=base; |
if(idx!=acc) ierror(0); |
am->offset=idx; |
if(isreg(q1)){ |
p->code=c=NOP;p->q1.flags=p->q2.flags=p->z.flags=0; |
}else{ |
p->code=c=ASSIGN;p->q2.flags=0; |
p->typf=p->typf2;p->q2.val.vmax=sizetab[p->typf2&NQ]; |
} |
} |
break; |
} |
if(c2!=FREEREG&&m==base) break; |
continue; |
} |
/* better no instructions between, accu used too much */ |
if(c2!=FREEREG&&c2!=ALLOCREG&&!o) break; |
} |
} |
/* POST_INC/DEC in q1 */ |
if(!p->q1.am&&(p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)){ |
r=p->q1.reg; t=q1typ(p); |
if(ISCHWORD(t)&&ISIDX(r)&&(!(p->q2.flags®)||p->q2.reg!=r)&&(!(p->z.flags®)||p->z.reg!=r)){ |
for(p2=p->next;p2;p2=p2->next){ |
c2=p2->code; |
if((c2==ADD||c2==ADDI2P||(CPU==6812&&(c2==SUB||c2==SUBIFP)))&&(p2->q1.flags&(REG|DREFOBJ))==REG&&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r&&p2->z.reg==r&&(p2->q2.flags&(KONST|DREFOBJ))==KONST){ |
eval_const(&p2->q2.val,p2->typf2); |
if(c2==SUB||c2==SUBIFP) vmax=zmsub(l2zm(0L),vmax); |
if(zmleq(vmax,incmax)&&zmleq(incmin,vmax)){ |
p2->code=NOP; |
p2->q1.flags=p2->q2.flags=p2->z.flags=0; |
p->q1.am=mymalloc(sizeof(*am)); |
p->q1.am->base=r; |
p->q1.am->v=0; |
if(zmleq(vmax,l2zm(0L))){ |
p->q1.am->flags=POST_DEC; |
p->q1.am->offset=-zm2l(vmax); |
}else{ |
p->q1.am->flags=POST_INC; |
p->q1.am->offset=zm2l(vmax); |
} |
}else break; |
} |
if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break; |
if(((p2->q1.flags®)&&p2->q1.reg==r)||((p2->q2.flags®)&&p2->q2.reg==r)||((p2->z.flags®)&&p2->z.reg==r)) break; |
} |
} |
} |
/* POST_INC/DEC in q2 */ |
if(!p->q2.am&&(p->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)){ |
r=p->q2.reg; t=q2typ(p); |
if(ISCHWORD(t)&&ISIDX(r)&&(!(p->q1.flags®)||p->q1.reg!=r)&&(!(p->z.flags®)||p->z.reg!=r)){ |
for(p2=p->next;p2;p2=p2->next){ |
c2=p2->code; |
if((c2==ADD||c2==ADDI2P||(CPU==6812&&(c2==SUB||c2==SUBIFP)))&&(p2->q1.flags&(REG|DREFOBJ))==REG&&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r&&p2->z.reg==r&&(p2->q2.flags&(KONST|DREFOBJ))==KONST){ |
eval_const(&p2->q2.val,p2->typf2); |
if(c2==SUB||c2==SUBIFP) vmax=zmsub(l2zm(0L),vmax); |
if(zmleq(vmax,incmax)&&zmleq(incmin,vmax)){ |
p2->code=NOP; |
p2->q1.flags=p2->q2.flags=p2->z.flags=0; |
p->q2.am=mymalloc(sizeof(*am)); |
p->q2.am->base=r; |
p->q2.am->v=0; |
if(zmleq(vmax,l2zm(0L))){ |
p->q2.am->flags=POST_DEC; |
p->q2.am->offset=-zm2l(vmax); |
}else{ |
p->q2.am->flags=POST_INC; |
p->q2.am->offset=zm2l(vmax); |
} |
}else break; |
} |
if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break; |
if(((p2->q1.flags®)&&p2->q1.reg==r)||((p2->q2.flags®)&&p2->q2.reg==r)||((p2->z.flags®)&&p2->z.reg==r)) break; |
} |
} |
} |
/* POST_INC/DEC in z */ |
if(!p->z.am&&(p->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)){ |
r=p->z.reg; t=ztyp(p); |
if(ISCHWORD(t)&&ISIDX(r)&&(!(p->q1.flags®)||p->q1.reg!=r)&&(!(p->q2.flags®)||p->q2.reg!=r)){ |
for(p2=p->next;p2;p2=p2->next){ |
c2=p2->code; |
if((c2==ADD||c2==ADDI2P||(CPU==6812&&(c2==SUB||c2==SUBIFP)))&&(p2->q1.flags&(REG|DREFOBJ))==REG&&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r&&p2->z.reg==r&&(p2->q2.flags&(KONST|DREFOBJ))==KONST){ |
eval_const(&p2->q2.val,p2->typf2); |
if(c2==SUB||c2==SUBIFP) vmax=zmsub(l2zm(0L),vmax); |
if(zmleq(vmax,incmax)&&zmleq(incmin,vmax)){ |
p2->code=NOP; |
p2->q1.flags=p2->q2.flags=p2->z.flags=0; |
p->z.am=mymalloc(sizeof(*am)); |
p->z.am->base=r; |
p->z.am->v=0; |
if(zmleq(vmax,l2zm(0L))){ |
p->z.am->flags=POST_DEC; |
p->z.am->offset=-zm2l(vmax); |
}else{ |
p->z.am->flags=POST_INC; |
p->z.am->offset=zm2l(vmax); |
} |
}else break; |
} |
if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break; |
if(((p2->q1.flags®)&&p2->q1.reg==r)||((p2->q2.flags®)&&p2->q2.reg==r)||((p2->z.flags®)&&p2->z.reg==r)) break; |
} |
} |
} |
|
/* R,#c */ |
if((c==ADDI2P||c==SUBIFP)&&ISHWORD(p->typf)&&((p->typf2&NQ)==NPOINTER||(p->typf2&NQ)==FPOINTER)&&isreg(z)&&((p->q2.flags&(KONST|DREFOBJ))==KONST||(!drel&&(p->q1.flags&VARADR)))){ |
int base;zmax of;struct obj *o;struct Var *v; |
if(p->q1.flags&VARADR){ |
v=p->q1.v; |
of=p->q1.val.vmax; |
r=p->z.reg; |
if(isreg(q2)&&ISIDX(p->q2.reg)) |
base=p->q2.reg; |
else |
base=r; |
}else{ |
eval_const(&p->q2.val,p->typf); |
if(c==SUBIFP) of=zmsub(l2zm(0L),vmax); else of=vmax; |
v=0; |
r=p->z.reg; |
if(isreg(q1)&&ISIDX(p->q1.reg)) base=p->q1.reg; else base=r; |
} |
o=0; |
for(p2=p->next;p2;p2=p2->next){ |
c2=p2->code; |
if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break; |
if(c2!=FREEREG&&(p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r) break; |
if(c2!=FREEREG&&(p2->q2.flags&(REG|DREFOBJ))==REG&&p2->q2.reg==r) break; |
if(c2!=CALL&&(c2<LABEL||c2>BRA)/*&&c2!=ADDRESS*/){ |
if(!p2->q1.am&&(p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r){ |
if(o||!ISHWORD(q1typ(p2))) break; |
o=&p2->q1; |
} |
if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){ |
if(o||!ISHWORD(q2typ(p2))) break; |
o=&p2->q2; |
} |
if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){ |
if(o||!ISHWORD(ztyp(p2))) break; |
o=&p2->z; |
} |
} |
if(c2==FREEREG||(p2->z.flags&(REG|DREFOBJ))==REG){ |
int m; |
if(c2==FREEREG) |
m=p2->q1.reg; |
else |
m=p2->z.reg; |
if(m==r){ |
if(o){ |
o->am=am=mymalloc(sizeof(*am)); |
am->flags=IMM_IND; |
am->base=base; |
am->offset=zm2l(of); |
am->v=v; |
if(!v){ |
if(isreg(q1)&&ISIDX(p->q1.reg)){ |
p->code=c=NOP;p->q1.flags=p->q2.flags=p->z.flags=0; |
}else{ |
p->code=c=ASSIGN;p->q2.flags=0; |
p->typf=p->typf2;p->q2.val.vmax=sizetab[p->typf2&NQ]; |
} |
}else{ |
if(isreg(q2)&&ISIDX(p->q2.reg)){ |
p->code=c=NOP;p->q1.flags=p->q2.flags=p->z.flags=0; |
}else{ |
p->code=c=ASSIGN;p->q1=p->q2;p->q2.flags=0; |
p->q2.val.vmax=sizetab[p->typf&NQ]; |
} |
} |
} |
break; |
} |
if(/*get_reg!! c2!=FREEREG&&*/m==base) break; |
continue; |
} |
} |
} |
} |
} |
|
static struct obj *cam(int flags,int base,long offset,struct Var *v) |
/* Initializes an addressing-mode structure and returns a pointer to */ |
/* that object. Will not survive a second call! */ |
{ |
static struct obj obj; |
static struct AddressingMode am; |
obj.am=&am; |
am.flags=flags; |
am.base=base; |
am.offset=offset; |
am.v=v; |
return &obj; |
} |
|
static void get_acc(FILE *f,struct IC *p) |
{ |
if(regs[acc]){ |
if(p->q2.am) |
if(p->q2.am->flags==ACC_IND) ierror(0); |
else |
if((p->q2.flags®)&&ISACC(p->q2.reg)) ierror(0); |
if(p->z.am) |
if(p->z.am->flags==ACC_IND) ierror(0); |
else |
if((p->z.flags®)&&ISACC(p->z.reg)) ierror(0); |
if(regs[acc]){ |
emit(f,SPUSHD); |
push(2); |
pushed_acc=1; |
} |
} |
} |
static int get_idx(FILE *f,IC *p) |
{ |
int r; |
for(r=1;r<=MAXR;r++){ |
if(ISIDX(r)){ |
if(!regs[r]){ |
regs[r]|=4; |
return r; |
} |
} |
} |
for(r=1;r<=MAXR;r++){ |
if(ISIDX(r)){ |
if((!(p->q1.flags®)||p->q1.reg!=r)&& |
(!(p->q2.flags®)||p->q2.reg!=r)&& |
(!(p->z.flags®)||p->z.reg!=r)){ |
emit(f,"\t%s%s\n",CPU==6812?"psh":"pshs\t",regnames[r]); |
regs[r]|=8; |
push(2); |
return r; |
} |
} |
} |
ierror(0); |
} |
static int get_reg(FILE *f,struct IC *p,int t) |
{ |
int reg; |
if(!regs[acc]) |
reg=acc; |
else if(ISHWORD(t)&&!regs[ix]) |
reg=ix; |
#if 0 |
else if(ISHWORD(t)&&!regs[iy]) |
reg=iy; |
#endif |
else{ |
get_acc(f,p); |
reg=acc; |
} |
BSET(regs_modified,reg); |
return reg; |
} |
static void load_reg(FILE *f,int r,struct obj *o,int t) |
{ |
if(!o->am){ |
if((o->flags&(REG|DREFOBJ))==REG){ |
if(o->reg==r) return; |
emit(f,"\ttfr\t%s,%s\n",regnames[o->reg],regnames[r]); |
return; |
} |
if(r==acc&&(o->flags&(KONST|DREFOBJ))==KONST){ |
eval_const(&o->val,t); |
if(zmeqto(vmax,l2zm(0L))&&zumeqto(vumax,ul2zum(0UL))){ |
if(CPU!=6812&&!optsize) |
emit(f,"\tldd\t#0\n"); |
else |
emit(f,"\tclra\n\tclrb\n"); |
cc=o;cc_t=t; |
return; |
} |
} |
} |
if(o->flags&VARADR){ |
char *base=0; |
if(pcrel&&ISFUNC(o->v->vtyp->flags)) |
base="pc"; |
if(drel&&!ISFUNC(o->v->vtyp->flags)) |
base=regnames[iu]; |
if(base&&!skip_rel){ |
if(ISACC(r)) |
emit(f,"\ttfr\t%s,d\n",base); |
if(ISIDX(r)) |
emit(f,"\tlea%s\t",regnames[r]); |
else{ |
if(*base=='p') emit(f,"%s%d:\n",labprefix,++label); |
emit(f,"\taddd\t#"); |
} |
emitzm(f,o->val.vmax); |
emit(f,"+"); |
if(o->v->storage_class==EXTERN) |
emit(f,"%s%s",idprefix,o->v->identifier); |
else |
emit(f,"%s%ld",labprefix,zm2l(o->v->offset)); |
if(ISIDX(r)) |
emit(f,",%s",base); |
else if(*base=='p') |
emit(f,"-%s%d",labprefix,label); |
emit(f,"\n"); |
cc=o;cc_t=t; |
return; |
} |
skip_rel=0; |
} |
emit(f,"\tld%s\t",(r==acc&&(t&NQ)==CHAR)?(CPU==6812?"ab":"b"):regnames[r]); |
emit_obj(f,o,t);emit(f,"\n"); |
cc=o;cc_t=t; |
} |
static void store_reg(FILE *f,int r,struct obj *o,int t) |
{ |
if((o->flags&(REG|DREFOBJ))==REG){ |
if(o->reg==r) return; |
emit(f,"\ttfr\t%s,%s\n",regnames[r],regnames[o->reg]); |
}else{ |
if(r==acc&&(t&NQ)==CHAR) |
emit(f,"\tst%s\t",(CPU==6812)?"ab":"b"); |
else |
emit(f,"\tst%s\t",regnames[r]); |
emit_obj(f,o,t);emit(f,"\n"); |
cc=o;cc_t=t; |
} |
} |
static void load_addr(FILE *f,int r,struct obj *o) |
{ |
if(o->am){ |
if(o->am->flags==IMM_IND){ |
if(o->am->base==r&&o->am->offset==0&&!o->am->v) return; |
if(ISIDX(r)){ |
emit(f,"\tlea%s\t",regnames[r]); |
emit_obj(f,o,0); |
emit(f,"\n"); |
}else{ |
if(r!=acc) ierror(0); |
emit(f,"\ttfr\t%s,%s\n",regnames[o->am->base],regnames[r]); |
emit(f,"\taddd\t#%ld\n",o->am->offset); |
if(o->am->v){ |
if(o->am->v->storage_class==STATIC) |
emit(f,"+%s%ld",labprefix,zm2l(o->am->v->offset)); |
else |
emit(f,"+%s%s",idprefix,o->am->v->identifier); |
} |
emit(f,"\n"); |
cc=0; |
} |
return; |
} |
ierror(0); |
} |
if(o->flags&DREFOBJ){ |
o->flags&=~DREFOBJ; |
load_reg(f,r,o,o->dtyp); |
o->flags|=DREFOBJ; |
return; |
} |
if((o->flags&(VAR|VARADR))==VAR){ |
if(o->v->storage_class==STATIC||o->v->storage_class==EXTERN){ |
o->flags|=VARADR; |
load_reg(f,r,o,POINTER_TYPE(o->v->vtyp)); |
o->flags&=~VARADR; |
return; |
} |
if(voff(o)==0){ |
emit(f,"\ttfr\t%s,%s\n",regnames[sp],regnames[r]); |
return; |
} |
if(ISIDX(r)){ |
emit(f,"\tlea%s\t",regnames[r]); |
emit_obj(f,o,0); |
emit(f,"\n"); |
}else{ |
if(r!=acc) ierror(0); |
emit(f,"\ttfr\t%s,%s\n",regnames[sp],regnames[r]); |
emit(f,"\taddd\t#%ld\n",voff(o)); |
cc=0; |
} |
return; |
} |
ierror(0); |
} |
|
static int scratchreg(int r,struct IC *p) |
{ |
int c; |
while(1){ |
p=p->next; |
if(!p||((c=p->code)==FREEREG&&p->q1.reg==r)) return 1; |
if(c==CALL||(c>=BEQ&&c<=BRA)) return 0; |
if((p->q1.flags®)&&p->q1.reg==r) return 0; |
if((p->q2.flags®)&&p->q2.reg==r) return 0; |
if((p->z.flags®)&&p->z.reg==r) return 0; |
} |
} |
|
/****************************************/ |
/* End of private fata and functions. */ |
/****************************************/ |
|
|
int init_cg(void) |
/* Does necessary initializations for the code-generator. Gets called */ |
/* once at the beginning and should return 0 in case of problems. */ |
{ |
int i; |
|
CPU=CPUOPT; |
|
if (CPU==680912) { |
bitsperbyte = 12; |
bytemask = 0xfff; |
dbl_bytemask = 0xffffff; |
} |
|
/* Initialize some values which cannot be statically initialized */ |
/* because they are stored in the target's arithmetic. */ |
maxalign=l2zm(1L); |
char_bit=l2zm((long)bitsperbyte); |
for(i=0;i<=MAX_TYPE;i++){ |
sizetab[i]=l2zm(msizetab[i]); |
align[i]=l2zm(malign[i]); |
} |
for(i=1;i<=iu;i++){ |
regsize[i]=l2zm(2L);regtype[i]=&ityp; |
} |
regsize[dx]=l2zm(4L);regtype[i]=<yp; |
|
/* Initialize the min/max-settings. Note that the types of the */ |
/* host system may be different from the target system and you may */ |
/* only use the smallest maximum values ANSI guarantees if you */ |
/* want to be portable. */ |
/* That's the reason for the subtraction in t_min[INT]. Long could */ |
/* be unable to represent -2147483648 on the host system. */ |
if (CPU==680912) { |
t_min[CHAR]=l2zm(-2048L); |
t_min[SHORT]=l2zm(-8388608L); |
t_min[INT]=t_min[SHORT]; |
t_min[LONG]=zmsub(l2zm(0x800000000000LL),l2zm(1L)); |
t_min[LLONG]=zmlshift(l2zm(1L),l2zm(63L)); |
t_min[MAXINT]=t_min(LLONG); |
t_max[CHAR]=ul2zum(2047L); |
t_max[SHORT]=ul2zum(8388607UL); |
t_max[INT]=t_max[SHORT]; |
t_max[LONG]=ul2zum(0x7fffffffffffULL); |
t_max[LLONG]=zumrshift(zumkompl(ul2zum(0UL)),ul2zum(1UL)); |
t_max[MAXINT]=t_max(LLONG); |
tu_max[CHAR]=ul2zum(4095UL); |
tu_max[SHORT]=ul2zum(16777215UL); |
tu_max[INT]=tu_max[SHORT]; |
tu_max[LONG]=ul2zum(0xffffffffffffULL); |
tu_max[LLONG]=zumkompl(ul2zum(0UL)); |
tu_max[MAXINT]=t_max(UNSIGNED|LLONG); |
} |
else { |
t_min[CHAR]=l2zm(-128L); |
t_min[SHORT]=l2zm(-32768L); |
t_min[INT]=t_min[SHORT]; |
t_min[LONG]=zmsub(l2zm(-2147483647L),l2zm(1L)); |
t_min[LLONG]=zmlshift(l2zm(1L),l2zm(63L)); |
t_min[MAXINT]=t_min(LLONG); |
t_max[CHAR]=ul2zum(127L); |
t_max[SHORT]=ul2zum(32767UL); |
t_max[INT]=t_max[SHORT]; |
t_max[LONG]=ul2zum(2147483647UL); |
t_max[LLONG]=zumrshift(zumkompl(ul2zum(0UL)),ul2zum(1UL)); |
t_max[MAXINT]=t_max(LLONG); |
tu_max[CHAR]=ul2zum(255UL); |
tu_max[SHORT]=ul2zum(65535UL); |
tu_max[INT]=tu_max[SHORT]; |
tu_max[LONG]=ul2zum(4294967295UL); |
tu_max[LLONG]=zumkompl(ul2zum(0UL)); |
tu_max[MAXINT]=t_max(UNSIGNED|LLONG); |
} |
|
if(g_flags[9]&USEDFLAG) drel=1; |
if(g_flags[10]&USEDFLAG) MINADDI2P=SHORT; |
if(g_flags[11]&USEDFLAG) nodx=1; |
if(g_flags[12]&USEDFLAG) nou=1; |
|
if(CPU==6812) switchsubs=1; |
|
/* Reserve a few registers for use by the code-generator. */ |
regsa[sp]=REGSA_NEVER; |
regscratch[sp]=0; |
|
if(CPU==6812||drel||nou){ |
regsa[iu]=REGSA_NEVER; |
regscratch[iu]=0; |
} |
|
if(CPU!=6812){ |
regnames[sp]="s"; |
logicals[0]="or"; |
} |
|
if(!(g_flags[6]&USEDFLAG)){ |
extern int static_cse,dref_cse; |
static_cse=0; |
dref_cse=0; |
} |
|
if(!(g_flags[7]&USEDFLAG)){ |
regsa[acc]=REGSA_TEMPS; |
regsa[dx]=REGSA_TEMPS; |
} |
|
if(g_flags[8]&USEDFLAG){ |
pcrel=1; |
jsrinst="lbsr"; |
jmpinst="lbra"; |
rodataname="\t.data\n"; |
} |
|
if(CPU==6809) |
marray[1]="__6809__"; |
if(CPU==6309) |
marray[1]="__6309__"; |
if(CPU==680912) |
marray[1]="__680912__"; |
target_macros=marray; |
|
|
declare_builtin("__mulint16",INT,INT,acc,INT,0,1,0); |
declare_builtin("__divint16",INT,INT,ix,INT,acc,1,0); |
declare_builtin("__divuint16",UNSIGNED|INT,UNSIGNED|INT,ix,UNSIGNED|INT,acc,1,0); |
declare_builtin("__modint16",INT,INT,ix,INT,acc,1,0); |
declare_builtin("__moduint16",UNSIGNED|INT,UNSIGNED|INT,ix,UNSIGNED|INT,acc,1,0); |
|
|
/* TODO: set argument registers */ |
declare_builtin("__mulint32",LONG,LONG,0,LONG,0,1,0); |
declare_builtin("__addint32",LONG,LONG,0,LONG,0,1,0); |
declare_builtin("__subint32",LONG,LONG,0,LONG,0,1,0); |
declare_builtin("__andint32",LONG,LONG,0,LONG,0,1,0); |
declare_builtin("__orint32",LONG,LONG,0,LONG,0,1,0); |
declare_builtin("__eorint32",LONG,LONG,0,LONG,0,1,0); |
declare_builtin("__negint32",LONG,LONG,0,0,0,1,0); |
declare_builtin("__lslint32",LONG,LONG,0,INT,0,1,0); |
|
declare_builtin("__divint32",LONG,LONG,0,LONG,0,1,0); |
declare_builtin("__divuint32",UNSIGNED|LONG,UNSIGNED|LONG,0,UNSIGNED|LONG,0,1,0); |
declare_builtin("__modint32",LONG,LONG,0,LONG,0,1,0); |
declare_builtin("__moduint32",UNSIGNED|LONG,UNSIGNED|LONG,0,UNSIGNED|LONG,0,1,0); |
declare_builtin("__lsrsint32",LONG,LONG,0,INT,0,1,0); |
declare_builtin("__lsruint32",UNSIGNED|LONG,UNSIGNED|LONG,0,INT,0,1,0); |
declare_builtin("__cmpsint32",INT,LONG,0,LONG,0,1,0); |
declare_builtin("__cmpuint32",INT,UNSIGNED|LONG,0,UNSIGNED|LONG,0,1,0); |
declare_builtin("__sint32toflt32",FLOAT,LONG,0,0,0,1,0); |
declare_builtin("__uint32toflt32",FLOAT,UNSIGNED|LONG,0,0,0,1,0); |
declare_builtin("__sint32toflt64",DOUBLE,LONG,0,0,0,1,0); |
declare_builtin("__uint32toflt64",DOUBLE,UNSIGNED|LONG,0,0,0,1,0); |
declare_builtin("__flt32tosint32",LONG,FLOAT,0,0,0,1,0); |
declare_builtin("__flt32touint32",UNSIGNED|LONG,FLOAT,0,0,0,1,0); |
declare_builtin("__flt64tosint32",LONG,DOUBLE,0,0,0,1,0); |
declare_builtin("__flt64touint32",UNSIGNED|LONG,DOUBLE,0,0,0,1,0); |
|
|
|
declare_builtin("__mulint64",LLONG,LLONG,0,LLONG,0,1,0); |
declare_builtin("__addint64",LLONG,LLONG,0,LLONG,0,1,0); |
declare_builtin("__subint64",LLONG,LLONG,0,LLONG,0,1,0); |
declare_builtin("__andint64",LLONG,LLONG,0,LLONG,0,1,0); |
declare_builtin("__orint64",LLONG,LLONG,0,LLONG,0,1,0); |
declare_builtin("__eorint64",LLONG,LLONG,0,LLONG,0,1,0); |
declare_builtin("__negint64",LLONG,LLONG,0,0,0,1,0); |
declare_builtin("__lslint64",LLONG,LLONG,0,INT,0,1,0); |
|
declare_builtin("__divsint64",LLONG,LLONG,0,LLONG,0,1,0); |
declare_builtin("__divuint64",UNSIGNED|LLONG,UNSIGNED|LLONG,0,UNSIGNED|LLONG,0,1,0); |
declare_builtin("__modsint64",LLONG,LLONG,0,LLONG,0,1,0); |
declare_builtin("__moduint64",UNSIGNED|LLONG,UNSIGNED|LLONG,0,UNSIGNED|LLONG,0,1,0); |
declare_builtin("__lsrsint64",LLONG,LLONG,0,INT,0,1,0); |
declare_builtin("__lsruint64",UNSIGNED|LLONG,UNSIGNED|LLONG,0,INT,0,1,0); |
declare_builtin("__cmpsint64",INT,LLONG,0,LLONG,0,1,0); |
declare_builtin("__cmpuint64",INT,UNSIGNED|LLONG,0,UNSIGNED|LLONG,0,1,0); |
declare_builtin("__sint64toflt32",FLOAT,LLONG,0,0,0,1,0); |
declare_builtin("__uint64toflt32",FLOAT,UNSIGNED|LLONG,0,0,0,1,0); |
declare_builtin("__sint64toflt64",DOUBLE,LLONG,0,0,0,1,0); |
declare_builtin("__uint64toflt64",DOUBLE,UNSIGNED|LLONG,0,0,0,1,0); |
declare_builtin("__flt32tosint64",LLONG,FLOAT,0,0,0,1,0); |
declare_builtin("__flt32touint64",UNSIGNED|LLONG,FLOAT,0,0,0,1,0); |
declare_builtin("__flt64tosint64",LLONG,DOUBLE,0,0,0,1,0); |
declare_builtin("__flt64touint64",UNSIGNED|LLONG,DOUBLE,0,0,0,1,0); |
|
declare_builtin("__flt32toflt64",DOUBLE,FLOAT,0,0,0,1,0); |
declare_builtin("__flt64toflt32",FLOAT,DOUBLE,0,0,0,1,0); |
|
|
declare_builtin("__addflt32",FLOAT,FLOAT,0,FLOAT,0,1,0); |
declare_builtin("__subflt32",FLOAT,FLOAT,0,FLOAT,0,1,0); |
declare_builtin("__mulflt32",FLOAT,FLOAT,0,FLOAT,0,1,0); |
declare_builtin("__divflt32",FLOAT,FLOAT,0,FLOAT,0,1,0); |
declare_builtin("__negflt32",FLOAT,FLOAT,0,FLOAT,0,1,0); |
declare_builtin("__cmpflt32",INT,FLOAT,0,FLOAT,0,1,0); |
|
declare_builtin("__addflt64",DOUBLE,DOUBLE,0,DOUBLE,0,1,0); |
declare_builtin("__subflt64",DOUBLE,DOUBLE,0,DOUBLE,0,1,0); |
declare_builtin("__mulflt64",DOUBLE,DOUBLE,0,DOUBLE,0,1,0); |
declare_builtin("__divflt64",DOUBLE,DOUBLE,0,DOUBLE,0,1,0); |
declare_builtin("__negflt64",DOUBLE,DOUBLE,0,DOUBLE,0,1,0); |
declare_builtin("__cmpflt64",INT,DOUBLE,0,DOUBLE,0,1,0); |
|
|
return 1; |
} |
|
int freturn(struct Typ *t) |
/* Returns the register in which variables of type t are returned. */ |
/* If the value cannot be returned in a register returns 0. */ |
{ |
int f=t->flags&NQ; |
if(ISSCALAR(f)){ |
if(ISHWORD(f)||f==CHAR) |
return acc; |
else if(ISLWORD(f)) |
return dx; |
} |
return 0; |
} |
|
int regok(int r,int t,int mode) |
/* Returns 0 if register r cannot store variables of */ |
/* type t. If t==POINTER and mode!=0 then it returns */ |
/* non-zero only if the register can store a pointer */ |
/* and dereference a pointer to mode. */ |
{ |
if(!ISSCALAR(t)) return 0; |
if(r==dx){ |
if(ISLWORD(t)&&(optflags&2)&&!nodx) return 1; |
return 0; |
} |
if(mode==-1){ |
if(ISHWORD(t)) return 1; |
if((t&NQ)==CHAR&&ISACC(r)) return 1; |
}else{ |
if(ISIDX(r)){ |
if(ISPOINTER(t)&&ISHWORD(t)) |
return 1; |
} |
if(ISACC(r)){ |
if((t&NQ)==CHAR) |
return 1; |
if(ISINT(t)&&ISHWORD(t)) |
return 1; |
} |
} |
return 0; |
} |
|
int reg_pair(int r,struct rpair *p) |
/* Returns 0 if the register is no register pair. If r */ |
/* is a register pair non-zero will be returned and the */ |
/* structure pointed to p will be filled with the two */ |
/* elements. */ |
{ |
if(r==dx){ |
p->r1=acc; |
p->r2=ix; |
return 1; |
} |
return 0; |
} |
|
int cost_savings(struct IC *p,int r,struct obj *o) |
{ |
/*FIXME*/ |
int c=p->code; |
if(r==dx){ |
if(c==GETRETURN||c==SETRETURN||c==PUSH||c==ASSIGN) return 8; |
return INT_MIN; |
} |
if(o->flags&VKONST){ |
struct obj *co=&o->v->cobj; |
if(o->flags&DREFOBJ) |
return 0; |
if(o==&p->q1&&p->code==ASSIGN&&((p->z.flags&DREFOBJ)||p->z.v->storage_class==STATIC||p->z.v->storage_class==EXTERN)){ |
return 2; |
} |
return 0; |
} |
if((o->flags&DREFOBJ)){ |
if(!ISIDX(r)) return INT_MIN; |
if(p->q2.flags&&o!=&p->z) |
return 6; |
else |
return 6; |
}else if(c==GETRETURN&&p->q1.reg==r){ |
return 4; |
}else if(c==SETRETURN&&p->z.reg==r){ |
return 4; |
}else if(c==CONVERT&&((p->typf&NQ)==CHAR||(p->typf2&NQ)==CHAR)&®ok(r,CHAR,0)){ |
return 3; |
} |
if(o==&p->z&&r==acc){ |
if(c==SUB||c==SUBIFP||c==SUBPFP||c==AND||c==OR||c==XOR) |
return 6; |
if((c==ADD||c==ADDI2P)&&!(p->q1.flags&(KONST|VKONST))&&!(p->q2.flags&(KONST|VKONST))) |
return 4; |
if(c==MULT) return 5; |
if(c==ASSIGN&&(p->q1.flags&KONST)){ |
eval_const(&p->q1.val,p->typf); |
if(zmeqto(vmax,l2zm(0L))&&zumeqto(vumax,ul2zum(0UL))) |
return 3; |
} |
} |
#if 1 |
if((o==&p->q2/*||o==&p->z*/)&&!(o->flags&DREFOBJ)&&!ISACC(o->reg)&&(c==MULT||c==DIV||c==MOD)) |
return INT_MIN; |
#endif |
if(c==COMPARE||c==TEST){ |
if(r==ix) return 3; |
if(r==iy) return 2; |
if(r==iu) return 1; |
} |
return 2; |
} |
|
int dangerous_IC(struct IC *p) |
/* Returns zero if the IC p can be safely executed */ |
/* without danger of exceptions or similar things. */ |
/* vbcc may generate code in which non-dangerous ICs */ |
/* are sometimes executed although control-flow may */ |
/* never reach them (mainly when moving computations */ |
/* out of loops). */ |
/* Typical ICs that generate exceptions on some */ |
/* machines are: */ |
/* - accesses via pointers */ |
/* - division/modulo */ |
/* - overflow on signed integer/floats */ |
{ |
int c=p->code; |
if((p->q1.flags&DREFOBJ)||(p->q2.flags&DREFOBJ)||(p->z.flags&DREFOBJ)) |
return 1; |
if((c==DIV||c==MOD)&&!isconst(q2)) |
return 1; |
return 0; |
} |
|
/* Return name of library function, if this node should be |
implemented via libcall. */ |
char *use_libcall(int c,int t,int t2) |
{ |
static char fname[16]; |
char *ret=0; |
|
if(c==COMPARE){ |
if((t&NQ)==LLONG||ISFLOAT(t)){ |
sprintf(fname,"__cmp%s%s%ld",(t&UNSIGNED)?"u":"s",ISFLOAT(t)?"flt":"int",zm2l(sizetab[t&NQ])*8); |
ret=fname; |
} |
}else{ |
t&=NU; |
t2&=NU; |
if(t==LDOUBLE) t=DOUBLE; |
if(t2==LDOUBLE) t2=DOUBLE; |
if(c==CONVERT){ |
if(t==t2) return 0; |
if(t==FLOAT&&t2==DOUBLE) return "__flt64toflt32"; |
if(t==DOUBLE&&t2==FLOAT) return "__flt32toflt64"; |
|
if(ISFLOAT(t)){ |
sprintf(fname,"__%cint%ldtoflt%d",(t2&UNSIGNED)?'u':'s',zm2l(sizetab[t2&NQ])*8,(t==FLOAT)?32:64); |
ret=fname; |
} |
if(ISFLOAT(t2)){ |
sprintf(fname,"__flt%dto%cint%ld",((t2&NU)==FLOAT)?32:64,(t&UNSIGNED)?'u':'s',zm2l(sizetab[t&NQ])*8); |
ret=fname; |
} |
} |
if((t&NQ)==LLONG||ISFLOAT(t)){ |
if((c>=LSHIFT&&c<=MOD)||(c>=OR&&c<=AND)||c==KOMPLEMENT||c==MINUS){ |
if(t==(UNSIGNED|LLONG)&&(c==DIV||c==MOD||c==RSHIFT)){ |
sprintf(fname,"__%suint64",ename[c]); |
ret=fname; |
}else if((t&NQ)==LLONG){ |
sprintf(fname,"__%sint64",ename[c]); |
ret=fname; |
}else if(t==(UNSIGNED|LONG)&&(c==DIV||c==MOD||c==RSHIFT)){ |
sprintf(fname,"__%suint32",ename[c]); |
ret=fname; |
}else if((t&NQ)==LONG){ |
sprintf(fname,"__%sint32",ename[c]); |
ret=fname; |
}else{ |
sprintf(fname,"__%s%s%s%ld",ename[c],(c!=MULT&&(t&UNSIGNED))?"u":"",ISFLOAT(t)?"flt":"int",zm2l(sizetab[t&NQ])*8); |
ret=fname; |
} |
} |
} |
if((c==MULT&&(CPU==6809||(t&NQ)==LONG))||c==DIV||c==MOD){ |
sprintf(fname,"__%s%s%s%ld",ename[c],(c!=MULT&&(t&UNSIGNED))?"u":"",ISFLOAT(t)?"flt":"int",zm2l(sizetab[t&NQ])*8); |
ret=fname; |
} |
} |
|
return ret; |
} |
|
|
|
int must_convert(int o,int t,int const_expr) |
/* Returns zero if code for converting np to type t */ |
/* can be omitted. */ |
{ |
int op=o&NQ,tp=t&NQ; |
if(op==tp) return 0; |
if(ISHWORD(op)&&ISHWORD(tp)) return 0; |
if(ISFLOAT(op)||ISFLOAT(tp)) return 1; |
if(ISLWORD(op)&&ISLWORD(tp)) return 0; |
return 1; |
} |
|
void gen_ds(FILE *f,zmax size,struct Typ *t) |
/* This function has to create <size> bytes of storage */ |
/* initialized with zero. */ |
{ |
if(newobj&§ion!=SPECIAL) |
emit(f,"%ld\n",zm2l(size)); |
else |
emit(f,"\t.space\t%ld\n",zm2l(size)); |
newobj=0; |
} |
|
void gen_align(FILE *f,zmax align) |
/* This function has to make sure the next data is */ |
/* aligned to multiples of <align> bytes. */ |
{ |
/* nothing to do */ |
} |
|
void gen_var_head(FILE *f,struct Var *v) |
/* This function has to create the head of a variable */ |
/* definition, i.e. the label and information for */ |
/* linkage etc. */ |
{ |
int constflag; |
if(v->clist) constflag=is_const(v->vtyp); |
if(v->storage_class==STATIC){ |
if(ISFUNC(v->vtyp->flags)) return; |
if(v->tattr&DPAGE) |
emit(f,"\t.direct\t%s%ld\n",labprefix,zm2l(v->offset)); |
if(!special_section(f,v)){ |
if(v->clist&&(!constflag||(g_flags[3]&USEDFLAG))&§ion!=DATA){ |
emit(f,dataname);if(f) section=DATA; |
} |
if(v->clist&&constflag&&!(g_flags[3]&USEDFLAG)&§ion!=RODATA){ |
emit(f,rodataname);if(f) section=RODATA; |
} |
if(!v->clist&§ion!=BSS){ |
emit(f,bssname);if(f) section=BSS; |
} |
} |
emit(f,"\t.type\t%s%ld,@object\n",labprefix,zm2l(v->offset)); |
emit(f,"\t.size\t%s%ld,%ld\n",labprefix,zm2l(v->offset),zm2l(szof(v->vtyp))); |
if(v->clist||section==SPECIAL) |
emit(f,"%s%ld:\n",labprefix,zm2l(v->offset)); |
else |
emit(f,"\t.lcomm\t%s%ld,",labprefix,zm2l(v->offset)); |
newobj=1; |
} |
if(v->storage_class==EXTERN){ |
if(v->flags&(DEFINED|TENTATIVE)){ |
emit(f,"\t.global\t%s%s\n",idprefix,v->identifier); |
if(v->tattr&DPAGE) |
emit(f,"\t.direct\t%s%s\n",idprefix,v->identifier); |
if(!special_section(f,v)){ |
if(v->clist&&(!constflag||(g_flags[3]&USEDFLAG))&§ion!=DATA){ |
emit(f,dataname);if(f) section=DATA; |
} |
if(v->clist&&constflag&&!(g_flags[3]&USEDFLAG)&§ion!=RODATA){ |
emit(f,rodataname);if(f) section=RODATA; |
} |
if(!v->clist&§ion!=BSS){ |
emit(f,bssname);if(f) section=BSS; |
} |
} |
emit(f,"\t.type\t%s%s,@object\n",idprefix,v->identifier); |
emit(f,"\t.size\t%s%s,%ld\n",idprefix,v->identifier,zm2l(szof(v->vtyp))); |
if(v->clist||section==SPECIAL) |
emit(f,"%s%s:\n",idprefix,v->identifier); |
else |
emit(f,"\t.global\t%s%s\n\t.lcomm\t%s%s,",idprefix,v->identifier,idprefix,v->identifier); |
newobj=1; |
} |
} |
} |
|
void gen_dc(FILE *f,int t,struct const_list *p) |
/* This function has to create static storage */ |
/* initialized with const-list p. */ |
{ |
emit(f,"\t%s\t",dct[t&NQ]); |
if(!p->tree){ |
if(ISFLOAT(t)){ |
/* auch wieder nicht sehr schoen und IEEE noetig */ |
unsigned char *ip; |
ip=(unsigned char *)&p->val.vdouble; |
emit(f,"0x%02x%02x%02x%02x",ip[3],ip[2],ip[1],ip[0]); |
if((t&NQ)==DOUBLE||(t&NQ)==LDOUBLE){ |
emit(f,",0x%02x%02x%02x%02x",ip[7],ip[6],ip[5],ip[4]); |
} |
}else{ |
emitval(f,&p->val,(t&NU)|UNSIGNED); |
} |
}else{ |
int m=p->tree->o.flags,md=drel,mp=pcrel; |
p->tree->o.flags&=~VARADR; |
drel=0;pcrel=0; |
emit_obj(f,&p->tree->o,t&NU); |
p->tree->o.flags=m; |
drel=md;pcrel=mp; |
} |
emit(f,"\n");newobj=0; |
} |
|
|
static void preload(FILE *f,IC *p) |
{ |
int t,r; |
|
if((p->typf&VOLATILE)||(p->typf2&VOLATILE)|| |
((p->q1.flags&DREFOBJ)&&(p->q1.dtyp&(VOLATILE|PVOLATILE)))|| |
((p->q2.flags&DREFOBJ)&&(p->q2.dtyp&(VOLATILE|PVOLATILE)))|| |
((p->z.flags&DREFOBJ)&&(p->z.dtyp&(VOLATILE|PVOLATILE)))) |
emit(f,"; volatile barrier\n"); |
|
t=q1typ(p); |
if(!p->q1.am&&(p->q1.flags&(REG|DREFOBJ|KONST))==DREFOBJ&&ISLWORD(t)){ |
r=get_idx(f,p); |
p->q1.flags&=~DREFOBJ; |
load_reg(f,r,&p->q1,INT); |
p->q1.flags|=(REG|DREFOBJ); |
p->q1.reg=r; |
} |
t=q2typ(p); |
if(!p->q2.am&&(p->q2.flags&(REG|DREFOBJ|KONST))==DREFOBJ&&ISLWORD(t)){ |
r=get_idx(f,p); |
p->q2.flags&=~DREFOBJ; |
load_reg(f,r,&p->q2,INT); |
p->q2.flags|=(REG|DREFOBJ); |
p->q2.reg=r; |
}else if(isreg(z)&&(((p->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p->q2.reg==p->z.reg)||(p->q2.am&&p->q2.am->base==p->z.reg))){ |
r=get_idx(f,p); |
p->q2.flags&=~DREFOBJ; |
load_reg(f,r,&p->q2,INT); |
p->q2.flags|=(REG|DREFOBJ); |
p->q2.reg=r; |
} |
t=ztyp(p); |
if(!p->z.am&&(p->z.flags&(REG|DREFOBJ|KONST))==DREFOBJ&&ISLWORD(t)){ |
r=get_idx(f,p); |
p->z .flags&=~DREFOBJ; |
load_reg(f,r,&p->z ,INT); |
p->z .flags|=(REG|DREFOBJ); |
p->z .reg=r; |
} |
} |
|
/* The main code-generation routine. */ |
/* f is the stream the code should be written to. */ |
/* p is a pointer to a doubly linked list of ICs */ |
/* containing the function body to generate code for. */ |
/* v is a pointer to the function. */ |
/* offset is the size of the stackframe the function */ |
/* needs for local variables. */ |
void gen_code(FILE *f,struct IC *fp,struct Var *v,zmax offset) |
{ |
int c,t,lastcomp=0,reg,short_add,bit_reverse,need_return=0; |
struct obj *bit_obj;char *bit_reg; |
static int idone; |
struct obj o; |
IC *p,*p2; |
if(v->tattr&INTERRUPT) |
ret="rti"; |
else if (v->tattr&FAR) |
ret="rtf"; |
else |
ret="rts"; /*FIXME: banked */ |
if(DEBUG&1) printf("gen_code()\n"); |
for(p=fp;p;p=p->next) clear_ext_ic(&p->ext); |
emit(f,"#off1=%ld\n",zm2l(offset)); |
if(!(g_flags[5]&USEDFLAG)){ |
peephole(fp); |
if(!frame_used) offset=l2zm(0L); |
} |
for(c=1;c<=MAXR;c++) regs[c]=(regsa[c]==REGSA_NEVER)?1:0; |
for(c=1;c<=MAXR;c++){ |
if(regscratch[c]&&(regsa[c]||regused[c])){ |
BSET(regs_modified,c); |
} |
} |
t=0; |
for(p=fp;p;p=p->next){ |
c=p->code; |
if(c==ALLOCREG){ regs[p->q1.reg]=1; if(p->q1.reg==dx) regs[acc]=regs[ix]=1;} |
if(c==FREEREG){ regs[p->q1.reg]=0; if(p->q1.reg==dx) regs[acc]=regs[ix]=0;} |
if((c==LSHIFT||c==RSHIFT)&&(p->typf&NQ)>=LONG) regused[iy]=1; |
if(c==PUSH&&(p->q1.flags&(REG|DREFOBJ))!=REG){ |
if(zmeqto(p->q2.val.vmax,Z1)){ |
if(regs[acc]) t=(t>2)?t:2; |
}else if(zmeqto(p->q2.val.vmax,l2zm(2L))){ |
if(regs[acc]&®s[ix]&®s[iy]&&(CPU==6812||regs[iu])) t=(t>2)?t:2; |
}else if(zmeqto(p->q2.val.vmax,l2zm(4L))){ |
if(regs[acc]) t=(t>2)?t:2; |
}else{ |
/* TODO: finer check */ |
if(drel||!regsa[iu]) |
t=(t>8)?t:8; |
else |
t=(t>6)?t:6; |
} |
} |
} |
emit(f,"#toff=%d\n",t); |
loff=zm2l(offset)+t; |
function_top(f,v,loff); |
stackoffset=notpopped=dontpop=maxpushed=0; |
for(p=fp;p;pr(f,p),p=p->next){ |
c=p->code;t=p->typf; |
if(debug_info) |
dwarf2_line_info(f,p); |
short_add=0; |
if(c==NOP) continue; |
if(c==ALLOCREG){ |
regs[p->q1.reg]=1; |
if(p->q1.reg==dx) regs[acc]=regs[ix]=1; |
continue; |
} |
if(c==FREEREG){ |
regs[p->q1.reg]=0; |
if(p->q1.reg==dx) regs[acc]=regs[ix]=0; |
continue; |
} |
if(notpopped&&!dontpop){ |
int flag=0; |
if(c==LABEL||c==COMPARE||c==TEST||c==BRA){ |
gen_pop(f,notpopped); |
notpopped=0; |
} |
} |
if(c==LABEL) {cc=0;emit(f,"%s%d:\n",labprefix,t);continue;} |
if(c>=BEQ&&c<=BGT&&t==exit_label) need_return=1; |
if(c==BRA){ |
if(p->typf==exit_label&&!have_frame){ |
emit(f,"\t%s\n",ret); |
}else{ |
if(t==exit_label) need_return=1; |
emit(f,"\tbra\t%s%d\n",labprefix,t); |
} |
cc=0;continue; |
} |
if(c>=BEQ&&c<BRA){ |
if((lastcomp&UNSIGNED)||ISPOINTER(lastcomp)) |
emit(f,"\tb%s\t%s%d\n",uccs[c-BEQ],labprefix,t); |
else |
emit(f,"\tb%s\t%s%d\n",ccs[c-BEQ],labprefix,t); |
continue; |
} |
if(c==MOVETOREG){ |
load_reg(f,p->z.reg,&p->q1,SHORT); |
continue; |
} |
if(c==MOVEFROMREG){ |
store_reg(f,p->q1.reg,&p->z,SHORT); |
continue; |
} |
|
/*if(ISFLOAT(t)) {pric2(stdout,p);ierror(0);}*/ |
|
if((t&NQ)==BIT){ |
ierror(0); |
} |
|
if(c==CONVERT&&ISLWORD(t)&&ISLWORD(p->typf2)){ |
p->code=c=ASSIGN; |
p->q2.val.vmax=l2zm(4L); |
} |
|
if((p->q2.flags®)&&ISACC(p->q2.reg)&&(c==ADD||c==MULT||c==AND||c==OR||c==XOR)){ |
obj o=p->q1; |
p->q1=p->q2; |
p->q2=o; |
} |
|
if(c==TEST){ |
lastcomp=t; |
p->code=c=COMPARE; |
gval.vmax=l2zm(0L); |
p->q2.flags=KONST; |
eval_const(&gval,MAXINT); |
insert_const(&p->q2.val,t); |
} |
|
if(c==SUBPFP){ |
p->code=c=SUB; |
p->typf=t=(UNSIGNED|INT); |
} |
|
|
|
if((c==ASSIGN||c==PUSH)&&zmeqto(p->q2.val.vmax,l2zm(4L))) |
p->typf=t=LONG; |
|
preload(f,p); |
|
if(c==ADDI2P||c==SUBIFP){ |
if((p->typf2&NQ)!=HPOINTER){ |
if(p->q2.flags&KONST){ |
eval_const(&p->q2.val,p->typf); |
insert_const(&p->q2.val,p->typf2); |
p->typf=t=(UNSIGNED|SHORT); |
}else{ |
if(ISLWORD(t)) inc_addr(&p->q2,2,t); |
if((t&NQ)==CHAR) short_add=t; |
p->typf=t=(UNSIGNED|SHORT); |
} |
}else if(ISHWORD(t)){ |
if((t&NQ)==LLONG) |
inc_addr(&p->q2,4,t); |
else if((t&NQ)!=LONG) |
short_add=t; |
p->typf=t=(UNSIGNED|LONG); |
} |
p->code=c=(c==ADDI2P)?ADD:SUB; |
} |
|
if(c==COMPARE&&ISLWORD(t)){ |
IC *branch=p->next; |
int r; |
while(branch&&branch->code==FREEREG) branch=branch->next; |
if(!branch) ierror(0); |
c=branch->code; |
if(c<BEQ||c>BGT) ierror(0); |
if(!regs[ix]) |
r=ix; |
else |
r=get_reg(f,p,INT); |
|
if(c==BEQ||c==BNE){ |
inc_addr(&p->q1,0,t); |
inc_addr(&p->q2,0,t); |
load_reg(f,r,&p->q1,INT); |
emit(f,"\t%s%s\t",CPU==6812?"cp":"cmp",regnames[r]); |
emit_obj(f,&p->q2,INT); |
emit(f,"\n"); |
if(pushed_acc) emit(f,SPULLD); |
emit(f,"\tbne\t%s%d\n",labprefix,c==BEQ?++label:branch->typf); |
if(pushed_acc) emit(f,SPUSHD); |
inc_addr(&p->q1,2,t); |
inc_addr(&p->q2,2,t); |
load_reg(f,r,&p->q1,INT); |
emit(f,"\t%s%s\t",CPU==6812?"cp":"cmp",regnames[r]); |
emit_obj(f,&p->q2,INT); |
emit(f,"\n"); |
pr(f,p); |
if(c==BEQ){ |
emit(f,"\tbeq\t%s%d\n",labprefix,branch->typf); |
emit(f,"%s%d:\n",labprefix,label); |
}else |
emit(f,"\tbne\t%s%d\n",labprefix,branch->typf); |
}else{ |
inc_addr(&p->q1,0,t); |
inc_addr(&p->q2,0,t); |
load_reg(f,r,&p->q1,INT); |
emit(f,"\t%s%s\t",CPU==6812?"cp":"cmp",regnames[r]); |
emit_obj(f,&p->q2,INT); |
emit(f,"\n"); |
label++; |
if(pushed_acc) emit(f,SPULLD); |
if(t&UNSIGNED){ |
if(c==BLT||c==BGT) |
emit(f,"\tb%s\t%s%d\n",(c==BLT)?"lo":"hi",labprefix,branch->typf); |
else |
emit(f,"\tb%s\t%s%d\n",(c==BGE)?"lo":"hi",labprefix,label); |
}else{ |
if(c==BLT||c==BGT) |
emit(f,"\tb%s\t%s%d\n",(c==BLT)?"lt":"gt",labprefix,branch->typf); |
else |
emit(f,"\tb%s\t%s%d\n",(c==BGE)?"lt":"gt",labprefix,label); |
} |
emit(f,"\tbne\t%s%d\n",labprefix,(c==BLT||c==BGT)?label:branch->typf); |
if(pushed_acc) emit(f,SPUSHD); |
inc_addr(&p->q1,2,t); |
inc_addr(&p->q2,2,t); |
load_reg(f,r,&p->q1,INT); |
emit(f,"\t%s%s\t",CPU==6812?"cp":"cmp",regnames[r]); |
emit_obj(f,&p->q2,INT); |
emit(f,"\n"); |
pr(f,p); |
emit(f,"\tb%s\t%s%d\n",uccs[c-BEQ],labprefix,branch->typf); |
emit(f,"%s%d:\n",labprefix,label); |
} |
branch->code=NOP; |
continue; |
} |
|
if(ISLWORD(t)&&(c==LSHIFT||c==RSHIFT)){ |
int cnt=-1000,i,r=0; |
int px=0,py=0,pa=0; |
if(isconst(q2)){ |
eval_const(&p->q2.val,p->typf2); |
cnt=(int)zm2l(vmax); |
if(cnt==1&&compare_objects(&p->q1,&p->z)){ |
if(c==LSHIFT) |
emit(f,"\tlsl\t"); |
else |
emit(f,"\t%s\t",(t&UNSIGNED)?"lsr":"asr"); |
inc_addr(&p->z,c==LSHIFT?3:0,t); |
emit_obj(f,&p->z,t); |
emit(f,"\n"); |
emit(f,"\t%s\t",(c==LSHIFT)?"rol":"ror"); |
inc_addr(&p->z,c==LSHIFT?-1:1,t); |
emit_obj(f,&p->z,t); |
emit(f,"\n"); |
emit(f,"\t%s\t",(c==LSHIFT)?"rol":"ror"); |
inc_addr(&p->z,c==LSHIFT?-1:1,t); |
emit_obj(f,&p->z,t); |
emit(f,"\n"); |
emit(f,"\t%s\t",(c==LSHIFT)?"rol":"ror"); |
inc_addr(&p->z,c==LSHIFT?-1:1,t); |
emit_obj(f,&p->z,t); |
emit(f,"\n"); |
continue; |
} |
} |
inc_addr(&p->q1,2,t); |
inc_addr(&p->z,2,t); |
|
if(ISRACC(q2)||(regs[acc]&&!scratchreg(acc,p))){ |
emit(f,SPUSHD); |
push(2); |
pa=1; |
} |
|
if(cnt<0||(optsize&&cnt>1)||(cnt>3&&!optspeed)){ |
if(regs[ix]&&!scratchreg(ix,p)) {px=1;emit(f,SPUSH("x"));push(2);} |
if(regs[iy]&&!scratchreg(iy,p)) {py=1;emit(f,SPUSH("y"));push(2);} |
} |
|
if(!compare_objects(&p->q1,&p->z)){ |
load_reg(f,acc,&p->q1,INT); |
store_reg(f,acc,&p->z,INT); |
} |
inc_addr(&p->q1,-2,t); |
inc_addr(&p->z,-2,t); |
load_reg(f,acc,&p->q1,INT); |
if(cnt<0||(optsize&&cnt>1)||(cnt>3&&!optspeed)){ |
if((p->q2.flags®)&&p->q2.reg==ix){ |
if((p->z.flags®)&&p->z.reg==iy) ierror(0); |
}else |
load_addr(f,ix,&p->z); |
if(ISRACC(q2)){ |
if(scratchreg(acc,p)&&(px+py==0)){ |
emit(f,SPULL("y")); |
pop(2);pa=0; |
}else |
emit(f,"\tldy\t%d,%s\n",(px+py)*2,regnames[sp]); |
}else |
load_reg(f,iy,&p->q2,p->typf2); /*TODO: types!=INT?? */ |
if((p->q2.flags®)&&p->q2.reg==ix) |
load_addr(f,ix,&p->z); |
if(c==LSHIFT) |
emit(f,"\t%s\t%s__lsll\n",jsrinst,idprefix); |
else |
emit(f,"\t%s\t%s__%s\n",jsrinst,idprefix,(t&UNSIGNED)?"lsrl":"asrl"); |
if(py) {emit(f,SPULL("y"));pop(2);} |
if(px) {emit(f,SPULL("x"));pop(2);} |
}else{ |
inc_addr(&p->z,c==LSHIFT?3:2,t); |
for(i=0;i<cnt;i++){ |
if(c==LSHIFT){ |
emit(f,"\tlsl\t"); |
emit_obj(f,&p->z,CHAR); |
emit(f,"\n"); |
inc_addr(&p->z,-1,t); |
emit(f,"\trol\t"); |
emit_obj(f,&p->z,CHAR); |
emit(f,"\n"); |
inc_addr(&p->z,1,t); |
emit(f,"\trolb\n"); |
emit(f,"\trola\n"); |
}else{ |
emit(f,"\t%s\n",(t&UNSIGNED)?"lsra":"asra"); |
emit(f,"\trorb\n"); |
emit(f,"\tror\t"); |
emit_obj(f,&p->z,CHAR); |
emit(f,"\n"); |
inc_addr(&p->z,1,t); |
emit(f,"\tror\t"); |
emit_obj(f,&p->z,CHAR); |
emit(f,"\n"); |
inc_addr(&p->z,-1,t); |
} |
} |
inc_addr(&p->z,c==LSHIFT?-3:-2,t); |
store_reg(f,acc,&p->z,INT); |
} |
if(pa) {emit(f,SPULLD);pop(2);} |
continue; |
} |
|
if(ISLWORD(t)&&c!=GETRETURN&&c!=SETRETURN&&c!=COMPARE&&c!=CONVERT&&c!=ADDRESS){ |
if(c==PUSH&&isreg(q1)&&p->q1.reg==dx){ |
if(CPU==6812){ |
emit(f,"\tpshd\n"); |
emit(f,"\tpshx\n"); |
}else{ |
//emit(f,"\tpshs\ta,b,x\n"); |
emit(f,"\tpshs\tb,a\n"); |
emit(f,"\tpshs\tx\n"); |
} |
push(4); |
continue; |
} |
if(c==ASSIGN&&isreg(q1)&&p->q1.reg==dx){ |
inc_addr(&p->z,2,t); |
store_reg(f,ix,&p->z,INT); |
inc_addr(&p->z,-2,t); |
store_reg(f,acc,&p->z,INT); |
continue; |
} |
if(c==ASSIGN&&isreg(z)&&p->z.reg==dx){ |
inc_addr(&p->q1,2,t); |
load_reg(f,ix,&p->q1,INT); |
inc_addr(&p->q1,-2,t); |
load_reg(f,acc,&p->q1,INT); |
continue; |
} |
if(c==PUSH){ |
if(regs[acc]) emit(f,"\tstd\t%ld,%s\n",loff-roff-2-stackoffset,regnames[sp]); |
}else |
get_acc(f,p); |
/*TODO: acc in IC, constants */ |
inc_addr(&p->q1,2,t); |
if(c==MINUS){ |
if(CPU!=6812&&!optsize) |
emit(f,"\tldd\t#0\n"); |
else |
emit(f,"\tclra\n\tclrb\n"); |
}else |
load_reg(f,acc,&p->q1,INT); |
if(c==ADD||c==SUB){ |
inc_addr(&p->q2,2,t); |
emit(f,"\t%s\t",c==ADD?"addd":"subd"); |
emit_obj(f,&p->q2,INT); |
emit(f,"\n"); |
}else if(c==ASSIGN||c==PUSH){ |
}else if(c==MINUS){ |
emit(f,"\tsubd\t"); |
emit_obj(f,&p->q1,INT); |
emit(f,"\n"); |
}else if(c==KOMPLEMENT){ |
emit(f,"\tcoma\n"); |
emit(f,"\tcomb\n"); |
}else{ |
if(c==AND) |
emit(f,"\tandb\t"); |
else if(c==OR) |
emit(f,"\tor%sb\t",CPU==6812?"a":""); |
else if(c==XOR) |
emit(f,"\teorb\t"); |
inc_addr(&p->q2,3,t); |
emit_obj(f,&p->q2,CHAR); |
emit(f,"\n"); |
if(c==AND) |
emit(f,"\tanda\t"); |
else if(c==OR) |
emit(f,"\tor%sa\t",CPU==6812?"a":""); |
else if(c==XOR) |
emit(f,"\teora\t"); |
inc_addr(&p->q2,-1,t); |
emit_obj(f,&p->q2,CHAR); |
emit(f,"\n"); |
} |
if(c==PUSH){ |
if(CPU==6812) |
emit(f,"\tpshd\n"); |
else |
emit(f,"\tpshs\tb,a\n"); |
push(2);dontpop+=2; |
}else{ |
inc_addr(&p->z,2,t); |
store_reg(f,acc,&p->z,INT); |
} |
inc_addr(&p->q1,-2,t); |
if(c==MINUS) |
emit(f,"\tldd\t#0\n"); |
else |
load_reg(f,acc,&p->q1,INT); |
if(c==ADD) |
emit(f,"\tadcb\t"); |
else if(c==SUB) |
emit(f,"\tsbcb\t"); |
else if(c==AND) |
emit(f,"\tandb\t"); |
else if(c==OR) |
emit(f,"\tor%sb\t",CPU==6812?"a":""); |
else if(c==XOR) |
emit(f,"\teorb\t"); |
else if(c==KOMPLEMENT) |
emit(f,"\tcomb\n"); |
else if(c==MINUS){ |
inc_addr(&p->q1,1,t); |
emit(f,"\tsbcb\t"); |
emit_obj(f,&p->q1,CHAR); |
emit(f,"\n"); |
} |
if(p->q2.flags){ |
inc_addr(&p->q2,-1,t); |
emit_obj(f,&p->q2,CHAR); |
emit(f,"\n"); |
} |
if(c==ADD) |
emit(f,"\tadca\t"); |
else if(c==SUB) |
emit(f,"\tsbca\t"); |
else if(c==AND) |
emit(f,"\tanda\t"); |
else if(c==OR) |
emit(f,"\tor%sa\t",CPU==6812?"a":""); |
else if(c==XOR) |
emit(f,"\teora\t"); |
else if(c==KOMPLEMENT) |
emit(f,"\tcoma\n"); |
else if(c==MINUS){ |
inc_addr(&p->q1,-1,t); |
emit(f,"\tsbca\t"); |
emit_obj(f,&p->q1,CHAR); |
emit(f,"\n"); |
} |
if(p->q2.flags){ |
inc_addr(&p->q2,-1,t); |
emit_obj(f,&p->q2,CHAR); |
emit(f,"\n"); |
} |
if(c==PUSH){ |
if(CPU==6812) |
emit(f,"\tpshd\n"); |
else |
emit(f,"\tpshs\tb,a\n"); |
push(2);dontpop+=2; |
if(regs[acc]) emit(f,"\tldd\t%ld,%s\n",loff-roff-2-stackoffset,regnames[sp]); |
}else{ |
inc_addr(&p->z,-2,t); |
store_reg(f,acc,&p->z,INT); |
} |
continue; |
} |
|
|
if(c==COMPARE){ |
int vadr; |
if(drel&&(p->q1.flags&VARADR)&&!ISFUNC(p->q1.v->vtyp->flags)) vadr=1; |
else if(drel&&(p->q2.flags&VARADR)&&!ISFUNC(p->q2.v->vtyp->flags)) vadr=2; |
else if(pcrel&&(p->q1.flags&VARADR)&&ISFUNC(p->q1.v->vtyp->flags)) vadr=1; |
else if(pcrel&&(p->q2.flags&VARADR)&&ISFUNC(p->q2.v->vtyp->flags)) vadr=2; |
else vadr=0; |
if(vadr!=1&&(vadr==2||isconst(q1)||ISRACC(q2))){ |
struct IC *p2; |
o=p->q1;p->q1=p->q2;p->q2=o; |
p2=p->next; |
while(p2&&p2->code==FREEREG) p2=p2->next; |
if(!p2||p2->code<BEQ||p2->code>BGT) ierror(0); |
if(p2->code==BLT) p2->code=BGT; |
else if(p2->code==BGT) p2->code=BLT; |
else if(p2->code==BLE) p2->code=BGE; |
else if(p2->code==BGE) p2->code=BLE; |
} |
/* case with two relative addresses */ |
if(drel&&(p->q2.flags&VARADR)&&!ISFUNC(p->q2.v->vtyp->flags)) skip_rel=1; |
if(pcrel&&(p->q2.flags&VARADR)&&ISFUNC(p->q2.v->vtyp->flags)) skip_rel=1; |
} |
#if 0 |
/* TODO: fix cc */ |
if(c==COMPARE&&isconst(q2)){ |
eval_const(&p->q2.val,t); |
if(ISNULL()){ |
if(cc&&(cc_t&NU)==(t&NU)&&compare_objects(cc,&p->q1)){ |
lastcomp=t;continue; |
} |
} |
} |
#endif |
|
if(!short_add) |
switch_IC(p); |
|
if(c==CONVERT){ |
int to=p->typf2&NU; |
if(to==INT) to=SHORT; |
if(to==(UNSIGNED|INT)||to==NPOINTER) to=(UNSIGNED|SHORT); |
if(to==FPOINTER||to==HPOINTER) to=(UNSIGNED|LONG); |
if((t&NU)==INT) t=SHORT; |
if((t&NU)==(UNSIGNED|INT)||(t&NU)==NPOINTER) t=(UNSIGNED|SHORT); |
if((t&NQ)==FPOINTER||(t&NQ)==HPOINTER) t=(UNSIGNED|LONG); |
/*if((t&NQ)>=LONG||(to&NQ)>=LONG) ierror(0);*/ |
if((to&NQ)<=LONG&&(t&NQ)<=LONG){ |
if((to&NQ)<(t&NQ)){ |
if(ISLWORD(t)){ |
get_acc(f,p); |
load_reg(f,acc,&p->q1,to); |
if((to&NU)==CHAR) |
emit(f,SEX); |
else if((to&NU)==(UNSIGNED|CHAR)) |
emit(f,"\tclra\n"); |
inc_addr(&p->z,2,t); |
store_reg(f,acc,&p->z,INT); |
inc_addr(&p->z,-2,t); |
if(to&UNSIGNED){ |
emit(f,"\tclra\n\tclrb\n"); |
}else{ |
if(CPU==6812) |
emit(f,"\texg\ta,b\n"); |
else |
emit(f,"\ttfr\ta,b\n"); |
emit(f,SEX); |
emit(f,"\ttfr\ta,b\n"); |
} |
store_reg(f,acc,&p->z,INT); |
continue; |
} |
/*emit(f,"#conv RACC=%d, regs=%d scratch=%d\n",(int)ISRACC(z),regs[acc],scratchreg(acc,p));*/ |
if(!ISRACC(z)) |
get_acc(f,p); |
load_reg(f,acc,&p->q1,to); |
if(to&UNSIGNED) |
emit(f,"\tclra\n"); |
else |
emit(f,SEX); |
store_reg(f,acc,&p->z,t); |
cc=&p->z;cc_t=t; |
continue; |
}else if((to&NQ)>(t&NQ)){ |
if(!ISRACC(z)&&!ISRACC(q1)) |
get_acc(f,p); |
if(ISLWORD(to)) |
inc_addr(&p->q1,2,to); |
load_reg(f,acc,&p->q1,to); |
store_reg(f,acc,&p->z,t); |
continue; |
}else{ |
c=ASSIGN; |
p->q2.val.vmax=sizetab[t&NQ]; |
} |
} |
} |
if(c==KOMPLEMENT){ |
cc=0; |
if(compare_objects(&p->q1,&p->z)&&!isreg(q1)&&(p->q1.flags&(REG|DREFOBJ))!=DREFOBJ&&(!p->q1.am||p->q1.am->flags!=ACC_IND)){ |
emit(f,"\tcom\t"); |
emit_obj(f,&p->z,t); |
emit(f,"\n"); |
if(ISHWORD(t)){ |
mobj=p->z; |
inc_addr(&mobj,1,t); |
emit(f,"\tcom\t"); |
emit_obj(f,&mobj,INT); |
emit(f,"\n"); |
} |
continue; |
} |
if((!isreg(z)||p->z.reg!=acc)&®s[acc]&&!scratchreg(acc,p)) |
get_acc(f,p); |
load_reg(f,acc,&p->q1,t); |
emit(f,"\tcoma\n\tcomb\n"); |
store_reg(f,acc,&p->z,t); |
continue; |
} |
if(c==MINUS){ |
if((!isreg(z)||p->z.reg!=acc)&®s[acc]&&!scratchreg(acc,p)) |
get_acc(f,p); |
if(isreg(q1)){ |
load_reg(f,acc,&p->q1,t); |
emit(f,"\tnega\n\tnegb\n\tsbca\t#0\n"); |
}else{ |
if(CPU!=6812&&!optsize) |
emit(f,"\tldd\t#0\n"); |
else |
emit(f,"\tclra\n\tclrb\n"); |
emit(f,"\tsubd\t"); |
emit_obj(f,&p->q1,t); |
emit(f,"\n"); |
} |
cc=&p->z;cc_t=t; |
store_reg(f,acc,&p->z,t); |
continue; |
} |
if(c==SETRETURN){ |
if(isreg(q1)&&p->q1.reg==p->z.reg) continue; |
if(p->z.reg){ |
if(ISLWORD(t)){ |
inc_addr(&p->q1,0,t); |
load_reg(f,ix,&p->q1,INT); |
BSET(regs_modified,ix); |
inc_addr(&p->q1,2,t); |
} |
load_reg(f,acc,&p->q1,t); |
BSET(regs_modified,acc); |
|
} |
continue; |
} |
if(c==GETRETURN){ |
if(isreg(z)&&p->z.reg==p->q1.reg) continue; |
if(p->q1.reg){ |
if(ISLWORD(t)){ |
store_reg(f,ix,&p->z,INT); |
BSET(regs_modified,ix); |
inc_addr(&p->z,2,t); |
} |
store_reg(f,acc,&p->z,(t&NQ)==CHAR?t:INT); |
} |
continue; |
} |
if(c==CALL){ |
int reg,jmp=0; |
cc=0; |
if(!calc_regs(p,f!=0)&&v->fi) v->fi->flags&=~ALL_REGS; |
if((p->q1.flags&(VAR|DREFOBJ))==VAR&&!strcmp("__va_start",p->q1.v->identifier)){ |
long of=va_offset(v)+loff+2; |
emit(f,"\ttfr\t%s,d\n",regnames[sp]); |
if(of) emit(f,"\taddd\t#%ld\n",of); |
continue; |
} |
if((p->q1.flags&VAR)&&p->q1.v->fi&&p->q1.v->fi->inline_asm){ |
emit_inline_asm(f,p->q1.v->fi->inline_asm); |
jmp=1; |
}else{ |
if(stackoffset==0&&!have_frame&&!strcmp(ret,"rts")){ |
struct IC *p2; |
jmp=1; |
for(p2=p->next;p2;p2=p2->next){ |
if(p2->code!=FREEREG&&p2->code!=ALLOCREG&&p2->code!=LABEL){ |
jmp=0;break; |
} |
} |
} |
if(p->q1.flags&DREFOBJ){ |
/*FIXME: test this*/ |
if(jmp) |
emit(f,"\tjmp\t"); |
else |
emit(f,"\tjsr\t"); |
if (p->q1.v->tattr&FAR) |
emit(f,"\tfar\t"); |
emit_obj(f,&p->q1,t); |
emit(f,"\n"); |
}else{ |
if(jmp){ |
emit(f,"\t%s\t",jmpinst); /*emit(f,"\tbra\t");*/ |
/*if(!need_return) ret=0;*/ /*TODO: works with optimizer? */ |
}else{ |
emit(f,"\t%s\t",jsrinst); /*emit(f,"\tbsr\t");*/ |
} |
if (p->q1.v->tattr&FAR) |
emit(f,"\tfar\t"); |
if(pcrel){ |
pcrel=0; |
emit_obj(f,&p->q1,t); |
pcrel=1; |
}else |
emit_obj(f,&p->q1,t); |
emit(f,"\n"); |
} |
} |
if(stack_valid){ |
int i; |
if(p->call_cnt<=0){ |
err_ic=p;if(f) error(320); |
stack_valid=0; |
} |
for(i=0;stack_valid&&i<p->call_cnt;i++){ |
if(p->call_list[i].v->fi&&(p->call_list[i].v->fi->flags&ALL_STACK)){ |
/*FIXME: size of return addr depends on mode */ |
if(!jmp) push(2); |
callee_push(zm2l(p->call_list[i].v->fi->stack1)); |
if(!jmp) pop(2); |
}else{ |
err_ic=p;if(f) error(317,p->call_list[i].v->identifier); |
stack_valid=0; |
} |
} |
} |
if(!zmeqto(l2zm(0L),p->q2.val.vmax)){ |
notpopped+=zm2l(p->q2.val.vmax); |
dontpop-=zm2l(p->q2.val.vmax); |
if(!(g_flags[2]&USEDFLAG)&&stackoffset==-notpopped){ |
/* Entfernen der Parameter verzoegern */ |
}else{ |
gen_pop(f,zm2l(p->q2.val.vmax)); |
notpopped-=zm2l(p->q2.val.vmax); |
} |
} |
continue; |
} |
if(c==ASSIGN||c==PUSH){ |
if(c==PUSH) dontpop+=zm2l(p->q2.val.vmax); |
if(!zmleq(p->q2.val.vmax,l2zm(2L))){ |
unsigned long size;int qr=0,zr=0,cr=0,px=0,py=0,pu=0,pd=0,lq=0,lz=0; |
size=zm2l(p->q2.val.vmax); |
if(c==ASSIGN){ |
if(!p->z.am&&(p->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&ISIDX(p->z.reg)){ |
zr=p->z.reg;lz=1; |
} |
} |
if(!p->q1.am&&(p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&ISIDX(p->q1.reg)&&p->q1.reg!=zr){ |
qr=p->q1.reg;lq=1; |
} |
if(!qr){ |
if(zr==ix) qr=iy; |
else if(zr==iy||zr==iu) qr=ix; |
else{qr=ix;zr=iy;} |
}else if(!zr){ |
if(qr==ix) zr=iy; else zr=ix; |
} |
if(CPU!=6812){ |
if(qr!=iu&&zr!=iu) cr=iu; |
if(qr!=ix&&zr!=ix) cr=ix; |
if(qr!=iy&&zr!=iy) cr=iy; |
if(!cr) ierror(0); |
} |
if(c==PUSH){ |
emit(f,"\tleas\t%ld,%s\n",SGN16(-size),regnames[sp]); |
push(size); |
} |
if(CPU!=6812&&(drel||!regused[iu]||(regs[iu]&&!scratchreg(iu,p)))){ |
if(c==PUSH) |
emit(f,"\tstu\t%ld,%s\n",loff-roff-8-stackoffset,regnames[sp]); |
else{ |
emit(f,SPUSH("u")); |
push(2); |
} |
pu=1; |
} |
if(!regused[iy]||(regs[iy]&&!scratchreg(iy,p))){ |
if(c==PUSH) |
emit(f,"\tsty\t%ld,%s\n",loff-roff-4-stackoffset,regnames[sp]); |
else{ |
emit(f,SPUSH("y")); |
push(2); |
} |
py=1; |
} |
if(regs[ix]&&!scratchreg(ix,p)){ |
if(c==PUSH) |
emit(f,"\tstx\t%ld,%s\n",loff-roff-2-stackoffset,regnames[sp]); |
else{ |
emit(f,SPUSH("x")); |
push(2); |
} |
px=1; |
} |
if(!lq) load_addr(f,qr,&p->q1); |
if(c==PUSH) |
emit(f,"\ttfr\t%s,%s\n",regnames[sp],regnames[zr]); |
else |
if(!lz) load_addr(f,zr,&p->z); |
if(size<=6||(size<=16&&!optsize)){ |
if(CPU!=6812){ |
if(!scratchreg(acc,p)){ |
if(c==PUSH) |
emit(f,"\tstd\t%ld,%s\n",loff-roff-6-stackoffset,regnames[sp]); |
else{ |
emit(f,SPUSHD); |
push(2); |
} |
pd=2; |
} |
} |
while(size>2){ |
if(CPU==6812) |
emit(f,"\tmovw\t2,%s+,2,%s+\n",regnames[qr],regnames[zr]); |
else |
emit(f,"\tldd\t,%s++\n\tstd\t,%s++\n",regnames[qr],regnames[zr]); |
size-=2; |
} |
if(CPU==6812) |
emit(f,"\tmov%c\t0,%s,0,%s\n",size==2?'w':'b',regnames[qr],regnames[zr]); |
else |
emit(f,"\tld%c\t,%s\n\tst%c\t,%s\n",size==2?'d':'b',regnames[qr],size==2?'d':'b',regnames[zr]); |
}else{ |
int l=++label,cnt=(int)(optsize?size:size/8); |
if(regs[acc]&&!scratchreg(acc,p)){ |
if(c==PUSH) |
emit(f,"\tst%c\t%ld,%s\n",(CPU!=6812&&cnt<=bytemask)?'b':'d',loff-roff-6-stackoffset,regnames[sp]); |
else{ |
if(CPU!=6812&&cnt<=bytemask){ |
emit(f,SPUSH("b")); |
push(1); |
}else{ |
emit(f,SPUSHD); |
push(2); |
} |
} |
pd=(CPU!=6812&&cnt<=bytemask)?1:2; |
} |
if(CPU!=6812&&cnt<=bytemask) |
emit(f,"\tldb\t#%lu\n",cnt); |
else |
emit(f,"\tldd\t#%lu\n",cnt); |
cc=0; |
#if 0 |
if(CPU!=6812&&((!regsa[iu]&®s[iu])||drel)){ |
if(c==PUSH){ |
emit(f,"\tstu\t%ld,%s\n",loff-roff-8-stackoffset,regnames[sp]); |
}else{ |
emit(f,SPUSH("u"));push(2); |
} |
} |
#endif |
emit(f,"%s%d:\n",labprefix,l); |
if(CPU==6812){ |
if(optsize){ |
emit(f,"\tmovb\t2,%s+,2,%s+\n",regnames[qr],regnames[zr]); |
}else{ |
emit(f,"\tmovw\t2,%s+,2,%s+\n",regnames[qr],regnames[zr]); |
emit(f,"\tmovw\t2,%s+,2,%s+\n",regnames[qr],regnames[zr]); |
emit(f,"\tmovw\t2,%s+,2,%s+\n",regnames[qr],regnames[zr]); |
emit(f,"\tmovw\t2,%s+,2,%s+\n",regnames[qr],regnames[zr]); |
size=size&7; |
} |
emit(f,"\tdbne\td,%s%d\n",labprefix,l); |
}else{ |
if(optsize){ |
emit(f,"\tld%s\t,%s+\n\tst%s\t,%s+\n",regnames[cr],regnames[qr],regnames[cr],regnames[zr]); |
size&=1; |
}else{ |
emit(f,"\tld%s\t,%s++\n\tst%s\t,%s++\n",regnames[cr],regnames[qr],regnames[cr],regnames[zr]); |
emit(f,"\tld%s\t,%s++\n\tst%s\t,%s++\n",regnames[cr],regnames[qr],regnames[cr],regnames[zr]); |
emit(f,"\tld%s\t,%s++\n\tst%s\t,%s++\n",regnames[cr],regnames[qr],regnames[cr],regnames[zr]); |
emit(f,"\tld%s\t,%s++\n\tst%s\t,%s++\n",regnames[cr],regnames[qr],regnames[cr],regnames[zr]); |
size&=7; |
} |
if(cnt<=bytemask) |
emit(f,"\tdecb\n"); |
else |
emit(f,"\tsubd\t#1\n"); |
emit(f,"\tbne\t%s%d\n",labprefix,l); |
} |
#if 0 |
if(CPU!=6812&&((!regsa[iu]&®s[iu])||drel)){ |
if(c==PUSH){ |
emit(f,"\tldu\t%ld,%s\n",loff-roff-8-stackoffset,regnames[sp]); |
}else{ |
emit(f,SPULL("u"));pop(2); |
} |
} |
#endif |
while(size>=2){ |
if(CPU==6812) |
emit(f,"\tmovw\t2,%s+,2,%s+\n",regnames[qr],regnames[zr]); |
else |
emit(f,"\tldd\t,%s++\n\tstd\t,%s++\n",regnames[qr],regnames[zr]); |
size-=2; |
} |
if(size){ |
if(CPU==6812) |
emit(f,"\tmovb\t0,%s,0,%s\n",regnames[qr],regnames[zr]); |
else |
emit(f,"\tldb\t,%s\n\tstb\t,%s\n",regnames[qr],regnames[zr]); |
} |
} |
if(pd){ |
if(c==PUSH) |
emit(f,"\tld%c\t%ld,%s\n",(pd==1)?'b':'d',loff-roff-6-stackoffset,regnames[sp]); |
else{ |
if(pd==1){ |
emit(f,SPULL("b")); |
pop(1); |
}else{ |
emit(f,SPULLD); |
pop(2); |
} |
} |
} |
if(px){ |
if(c==PUSH) |
emit(f,"\tldx\t%ld,%s\n",loff-roff-2-stackoffset,regnames[sp]); |
else{ |
emit(f,SPULL("x")); |
pop(2); |
} |
} |
if(py){ |
if(c==PUSH) |
emit(f,"\tldy\t%ld,%s\n",loff-roff-4-stackoffset,regnames[sp]); |
else{ |
emit(f,SPULL("y")); |
pop(2); |
} |
} |
if(pu){ |
if(c==PUSH) |
emit(f,"\tldu\t%ld,%s\n",loff-roff-8-stackoffset,regnames[sp]); |
else{ |
emit(f,SPULL("u")); |
pop(2); |
} |
} |
continue; |
} |
if(!ISSCALAR(t)) t=zmeqto(p->q2.val.vmax,l2zm(1L))?CHAR:INT; |
if((t&NQ)==CHAR&&!zmeqto(p->q2.val.vmax,l2zm(1L))) t=INT; |
if(mov_op(&p->q1)&&(c==PUSH||mov_op(&p->z))){ |
emit(f,"\tmov%c\t",ISHWORD(t)?'w':'b'); |
emit_obj(f,&p->q1,t); |
if(c==ASSIGN){ |
emit(f,","); |
emit_obj(f,&p->z,t); |
emit(f,"\n"); |
}else{ |
emit(f,",%d,-%s\n",ISHWORD(t)?2:1,regnames[sp]); |
push(ISHWORD(t)?2:1); |
} |
continue; |
} |
if(((regs[acc]&®s[ix])||(t&NQ)==CHAR)&&(p->q1.flags&KONST)&&!isreg(z)){ |
eval_const(&p->q1.val,t); |
if(zmeqto(vmax,l2zm(0L))&&zumeqto(vumax,ul2zum(0UL))&&((p->z.flags&(REG|DREFOBJ))!=DREFOBJ||(t&NQ)==CHAR)&&(!p->z.am||p->z.am->flags!=ACC_IND||(t&NQ)==CHAR)){ |
emit(f,"\tclr\t"); |
if(c==ASSIGN){ |
emit_obj(f,&p->z,t);emit(f,"\n"); |
}else{ |
emit(f,CPU==6812?"1,-sp\n":",-s\n"); |
push(1); |
} |
if(!ISHWORD(t)) continue; |
emit(f,"\tclr\t"); |
if(c==ASSIGN){ |
mobj=p->z; |
inc_addr(&mobj,1,t); |
emit_obj(f,&mobj,t);emit(f,"\n"); |
}else{ |
emit(f,CPU==6812?"1,-sp\n":",-s\n"); |
push(1); |
} |
continue; |
} |
|
} |
if(c==PUSH){ |
int st=0; |
if(isreg(q1)){ |
reg=p->q1.reg; |
}else{ |
if((t&NQ)==CHAR||!regs[acc]||scratchreg(acc,p)) reg=acc; |
else if(!regs[ix]||scratchreg(ix,p)) reg=ix; |
else if(regused[iy]&&(!regs[iy]||scratchreg(iy,p))) reg=iy; |
else if(regused[iu]&&!drel&&CPU!=6812&&(!regs[iu]||scratchreg(iu,p))) reg=iu; |
else reg=acc; |
if(regs[reg]&&!scratchreg(reg,p)){ |
st=1; |
emit(f,"\tst%s\t%ld,%s\n",regnames[reg],(long)loff-roff-2-stackoffset,regnames[sp]); |
} |
load_reg(f,reg,&p->q1,t); |
} |
if((t&NQ)==CHAR) |
emit(f,SPUSH("b")); |
else if(reg==ix) |
emit(f,SPUSH("x")); |
else if(reg==iy) |
emit(f,SPUSH("y")); |
else if(reg==iu) |
emit(f,SPUSH("u")); |
else |
emit(f,SPUSHD); |
push(zm2l(p->q2.val.vmax)); |
if(st) |
emit(f,"\tld%s\t%ld,%s\n",regnames[reg],(long)loff-roff-2-stackoffset,regnames[sp]); |
continue; |
} |
if(c==ASSIGN){ |
if(isreg(q1)&&isreg(z)){ |
if(p->q1.reg!=p->z.reg) |
emit(f,"\ttfr\t%s,%s\n",regnames[p->q1.reg],regnames[p->z.reg]); |
}else if(isreg(q1)){ |
store_reg(f,p->q1.reg,&p->z,t); |
}else if(isreg(z)){ |
load_reg(f,p->z.reg,&p->q1,t); |
}else{ |
reg=get_reg(f,p,t); |
load_reg(f,reg,&p->q1,t); |
store_reg(f,reg,&p->z,t); |
} |
continue; |
} |
ierror(0); |
} |
if(c==ADDRESS){ |
int px=0; |
if(isreg(z)){ |
reg=p->z.reg; |
}else if(!regs[ix]){ |
reg=ix; |
}else if(!regs[iy]){ |
reg=iy; |
}else{ |
/*FIXME: test if x used in q1 */ |
px=1; |
emit(f,SPUSH("x")); |
reg=ix; |
push(2); |
} |
load_addr(f,reg,&p->q1); |
if(!(p->z.flags®)||p->z.reg!=reg) |
store_reg(f,reg,&p->z,p->typf2); |
if(px){ |
emit(f,SPULL("x")); |
pop(2); |
} |
continue; |
} |
|
if((c==MULT||c==DIV||(c==MOD&&(p->typf&UNSIGNED)))&&isconst(q2)){ |
long ln; |
eval_const(&p->q2.val,t); |
if(zmleq(l2zm(0L),vmax)&&zumleq(ul2zum(0UL),vumax)){ |
if((ln=pof2(vumax))&&ln<5){ |
if(c==MOD){ |
vmax=zmsub(vmax,l2zm(1L)); |
c=p->code=c=AND; |
}else{ |
vmax=l2zm(ln-1); |
if(c==DIV) p->code=c=RSHIFT; else p->code=c=LSHIFT; |
} |
c=p->code; |
gval.vmax=vmax; |
eval_const(&gval,MAXINT); |
if(c==AND){ |
insert_const(&p->q2.val,t); |
}else{ |
insert_const(&p->q2.val,t); |
p->typf2=INT; |
} |
} |
} |
} |
if(c==MOD||c==DIV){ |
ierror(0); |
continue; |
} |
|
|
if((c==ADD||c==SUB)&&(p->q2.flags&(KONST|DREFOBJ))==KONST&&(p->q1.flags&(REG|DREFOBJ))!=REG&&(p->q1.flags&(REG|DREFOBJ))!=DREFOBJ&&!p->q1.am&&!p->z.am&&compare_objects(&p->q1,&p->z)){ |
eval_const(&p->q2.val,t); |
if(c==SUB) vmax=zmsub(Z0,vmax); |
if((t&NQ)==CHAR&&zmeqto(vmax,Z1)){ |
emit(f,"\tinc\t"); |
emit_obj(f,&p->z,t); |
emit(f,"\n"); |
continue; |
}else if((t&NQ)==CHAR&&zmeqto(vmax,l2zm(-1L))){ |
emit(f,"\tdec\t"); |
emit_obj(f,&p->z,t); |
emit(f,"\n"); |
continue; |
}else if(((t&NQ)==SHORT||(t&NQ)==INT)&&zmeqto(vmax,l2zm(1L))){ |
inc_addr(&p->z,1,t); |
emit(f,"\tinc\t"); |
emit_obj(f,&p->z,t); |
emit(f,"\n"); |
emit(f,"\tbne\t%s%d\n",labprefix,++label); |
inc_addr(&p->z,-1,t); |
emit(f,"\tinc\t"); |
emit_obj(f,&p->z,t); |
emit(f,"\n"); |
emit(f,"%s%d:\n",labprefix,label); |
continue; |
}else if(regs[acc]&&((t&NQ)==SHORT||(t&NQ)==INT)&&zmeqto(vmax,l2zm(-1L))){ |
inc_addr(&p->z,1,t); |
emit(f,"\ttst\t"); |
emit_obj(f,&p->z,t); |
emit(f,"\n"); |
emit(f,"\tbne\t%s%d\n",labprefix,++label); |
inc_addr(&p->z,-1,t); |
emit(f,"\tdec\t"); |
emit_obj(f,&p->z,t); |
emit(f,"\n"); |
emit(f,"%s%d:\n",labprefix,label); |
inc_addr(&p->z,1,t); |
emit(f,"\tdec\t"); |
emit_obj(f,&p->z,t); |
emit(f,"\n"); |
continue; |
} |
} |
|
if((c>=LSHIFT&&c<=MOD)||c==ADDI2P||c==SUBIFP||c==SUBPFP||(c>=OR&&c<=AND)||c==COMPARE){ |
char *s; |
/*FIXME: nicht immer besser*/ |
if(ISLWORD(t)&&c==LSHIFT&&isconst(q2)){ |
eval_const(&p->q2.val,t); |
if(zm2l(vmax)==1){ |
p->code=c=ADD; |
p->q2=p->q1; |
} |
} |
if((c==ADD||c==ADDI2P||c==MULT||(c>=OR&&c<=AND))&&isreg(q2)&&!isreg(q1)&&!short_add){ |
o=p->q1;p->q1=p->q2;p->q2=o; |
} |
if((c==ADD||c==MULT||(c>=OR&&c<=AND))&&isreg(q2)&&p->q2.reg==acc&&!short_add){ |
o=p->q1;p->q1=p->q2;p->q2=o; |
} |
if(c==MULT||c==MOD){ |
if((!isreg(z)||p->z.reg!=acc)&®s[acc]&&!scratchreg(acc,p)) |
get_acc(f,p); |
reg=acc; |
/*FIXME: y bzw. x-Register*/ |
}else if(c==LSHIFT||c==RSHIFT||c==AND||c==OR||c==XOR){ |
if((!isreg(z)||p->z.reg!=acc)&®s[acc]&&!scratchreg(acc,p)) |
get_acc(f,p); |
reg=acc; |
}else if(c==DIV){ |
reg=ix; |
ierror(0); |
}else if(isreg(z)){ |
reg=p->z.reg; |
}else if(isreg(q1)&&(c==COMPARE||scratchreg(p->q1.reg,p))){ |
reg=p->q1.reg; |
}else{ |
if(c==ADD||c==SUB||c==ADDI2P||c==SUBIFP||c==COMPARE){ |
if(ISRACC(q2)) |
reg=acc; |
else |
reg=get_reg(f,p,t); |
}else{ |
get_acc(f,p); |
reg=acc; |
} |
} |
if(c==ADD||c==ADDI2P||c==SUB||c==SUBIFP){ |
int opdone=0; |
if(isreg(q1)){ |
if(ISIDX(reg)&&ISIDX(p->q1.reg)&&isconst(q2)){ |
eval_const(&p->q2.val,short_add?short_add:q2typ(p)); |
if(CPU==6812&&p->q1.reg==reg&&zmeqto(vmax,l2zm(1L))&&zumeqto(vumax,ul2zum(1UL))){ |
emit(f,"\t%s%s\n",c==SUB?"de":"in",regnames[reg]); |
/*FIXME: condition-codes for bne/beq could be used */ |
}else{ |
emit(f,"\tlea%s\t%ld,%s\n",regnames[reg],c==SUB?SGN16(-zm2l(vmax)):SGN16(zm2l(vmax)),regnames[p->q1.reg]); |
} |
opdone=1; |
}else if((c==ADD||c==ADDI2P)&&ISIDX(reg)&&ISIDX(p->q1.reg)&&ISRACC(q2)){ |
emit(f,"\tlea%s\t%s,%s\n",regnames[reg],((t&NQ)==CHAR||(short_add&NQ)==CHAR)?"b":"d",regnames[p->q1.reg]); |
opdone=1; |
}else if((c==ADD||c==ADDI2P)&&ISIDX(reg)&&ISACC(p->q1.reg)&&ISRIDX(q2)){ |
emit(f,"\tlea%s\t%s,%s\n",regnames[reg],(t&NQ)==CHAR?"b":"d",regnames[p->q2.reg]); |
opdone=1; |
}else if((c==ADD||c==ADDI2P)&&p->q1.reg==acc&&ISIDX(reg)&&!short_add){ |
load_reg(f,reg,&p->q2,t); |
emit(f,"\tlea%s\t%s,%s\n",regnames[reg],(t&NQ)==CHAR?"b":"d",regnames[reg]); |
opdone=1; |
}else if((c==ADD||c==ADDI2P)&&p->q1.reg==acc&&ISIDX(reg)&&(short_add&NU)==(UNSIGNED|CHAR)&&scratchreg(acc,p)){ |
emit(f,"\taddb\t"); |
emit_obj(f,&p->q2,short_add); |
emit(f,"\n"); |
emit(f,"\tadca\t#0\n"); |
emit(f,"\ttfr\td,y\n"); |
opdone=1; |
}else if((c==ADD||c==ADDI2P)&&ISACC(p->q1.reg)&&ISRACC(z)&&isreg(q2)&&ISIDX(p->q2.reg)){ |
if(!scratchreg(p->q2.reg,p)) emit(f,"\texg\t%s,%s\n",regnames[acc],regnames[p->q2.reg]); |
emit(f,"\tlea%s\t%s,%s\n",regnames[p->q2.reg],regnames[acc],regnames[p->q2.reg]); |
emit(f,"\texg\t%s,%s\n",regnames[acc],regnames[p->q2.reg]); |
opdone=1; |
}else if(p->q1.reg!=reg){ |
if(c==ADD||c==ADDI2P||!ISRACC(q2)) |
emit(f,"\ttfr\t%s,%s\n",regnames[p->q1.reg],regnames[reg]); |
} |
}else if(short_add&&c==SUB&®==acc&&!(short_add&UNSIGNED)){ |
load_reg(f,reg,&p->q2,short_add); |
emit(f,"\tclra\n"); |
emit(f,"\tnegb\n"); |
emit(f,"\tsbca\t#0\n"); |
emit(f,"\taddd\t"); |
emit_obj(f,&p->q1,t); |
emit(f,"\n"); |
store_reg(f,reg,&p->z,ztyp(p)); |
continue; |
}else if(short_add&&c==ADD&®==acc){ |
load_reg(f,reg,&p->q2,short_add); |
if(short_add&UNSIGNED) |
emit(f,"\tclra\n"); |
else |
emit(f,SEX); |
emit(f,"\taddd\t"); |
emit_obj(f,&p->q1,t); |
emit(f,"\n"); |
store_reg(f,reg,&p->z,ztyp(p)); |
continue; |
}else{ |
if(!ISRACC(q2)) |
load_reg(f,reg,&p->q1,q1typ(p)); |
} |
if(!opdone){ |
if(reg==acc){ |
if(ISRACC(q2)){ |
if(!ISRACC(z)) get_acc(f,p); |
if(c==ADD||c==ADDI2P){ |
if(short_add){ |
if(short_add&UNSIGNED) |
emit(f,"\tclra\n"); |
else |
emit(f,SEX); |
emit(f,"\taddd\t"); |
emit_obj(f,&p->q1,t); |
emit(f,"\n"); |
}else{ |
if(CPU==6812) |
emit(f,"\tasld\n"); /* only cases with q1=q2=acc should remain */ |
else{ |
emit(f,"\taslb\n"); |
if((t&NQ)!=CHAR) |
emit(f,"\trola\n"); |
} |
} |
}else{ |
if(short_add){ |
if(short_add&UNSIGNED) |
emit(f,"\tld%sa\t#255\n",(CPU==6812)?"a":""); |
else{ |
emit(f,SEX); |
emit(f,"\tnega\n"); |
} |
emit(f,"\tnegb\n\tsbca\t#0\n"); |
}else if((t&NQ)!=CHAR){ |
emit(f,"\tnega\n\tnegb\n\tsbca\t#0\n"); |
}else{ |
emit(f,"\tnegb\n"); |
} |
|
if(ISRIDX(q1)){ |
emit(f,"\t%s%s\n",CPU==6812?"psh":"pshs\t",regnames[p->q1.reg]); |
emit(f,"\taddd\t%s\n",CPU==6812?"1,s+":",s++"); |
}else{ |
emit(f,"\taddd\t"); |
emit_obj(f,&p->q1,t); |
emit(f,"\n"); |
} |
} |
}else{ |
if(ISRIDX(q2)){ |
if(CPU==6812) |
emit(f,"\tpsh%s\n",regnames[p->q2.reg]); |
else |
emit(f,"\tpshs\t%s\n",regnames[p->q2.reg]); |
push(2);pop(2); |
if(CPU==6812) |
emit(f,"\t%sd\t2,%s+\n",(c==ADD||c==ADDI2P)?"add":"sub",regnames[sp]); |
else |
emit(f,"\t%sd\t,%s++\n",(c==ADD||c==ADDI2P)?"add":"sub",regnames[sp]); |
}else{ |
emit(f,"\t%s%s\t",(c==ADD||c==ADDI2P)?"add":"sub",(short_add||(t&NQ)==CHAR)?"b":"d"); |
emit_obj(f,&p->q2,short_add?short_add:t);emit(f,"\n"); |
if(short_add){ |
if(short_add&UNSIGNED) |
emit(f,"\t%s\t#0\n",c==ADD?"adca":"sbca"); |
else |
ierror(0); |
} |
if(drel&&(p->q2.flags&VARADR)){ |
if(CPU==6812) ierror(0); |
emit(f,"\tpshs\t%s\n",regnames[iu]);push(2); |
emit(f,"\t%sd\t,%s++\n",(c==ADD||c==ADDI2P)?"add":"sub",regnames[sp]); |
pop(2); |
} |
} |
} |
cc=&p->z;cc_t=t; |
}else{ |
if(isconst(q2)){ |
long l; |
eval_const(&p->q2.val,short_add?short_add:t); |
l=zm2l(vmax); |
if(c==SUB) l=-l; |
/*FIXME: condition-codes for bne/beq could be used */ |
if(l==1&®==ix&&CPU==6812){ |
emit(f,"\tinx\n"); |
}else if(l==1&®==iy&&CPU==6812){ |
emit(f,"\tiny\n"); |
}else if(l==-1&®==ix&&CPU==6812){ |
emit(f,"\tdex\n"); |
}else if(l==-1&®==iy&&CPU==6812){ |
emit(f,"\tdey\n"); |
}else{ |
emit(f,"\tlea%s\t%ld,%s\n",regnames[reg],SGN16(l),regnames[reg]); |
} |
}else{ |
if(c!=ADD&&c!=ADDI2P){ |
if(!ISRACC(q2)){ |
if(!scratchreg(acc,p)) |
get_acc(f,p); |
load_reg(f,acc,&p->q2,t); |
if((t&NQ)!=CHAR){ |
emit(f,"\tnega\n\tnegb\n\tsbca\t#0\n"); |
}else{ |
emit(f,"\tnegb\n"); |
} |
/*load_reg(f,reg,&p->q1,t);*/ |
}else{ |
get_acc(f,p); |
load_reg(f,reg,&p->q1,t); |
if((t&NQ)==CHAR) |
emit(f,"\tnegb\n"); |
else |
emit(f,"\tnega\n\tnegb\n\tsbca\t#0\n"); |
} |
}else if(!ISRACC(q2)){ |
get_acc(f,p); |
if(short_add){ |
load_reg(f,acc,&p->q2,short_add); |
if(short_add&UNSIGNED){ |
if(reg==ix){ |
emit(f,"\tabx\n"); |
store_reg(f,reg,&p->z,ztyp(p)); |
continue; |
}else{ |
emit(f,"\tclra\n"); |
} |
}else |
t=CHAR; |
}else |
load_reg(f,acc,&p->q2,t); |
}else{ |
load_reg(f,reg,&p->q1,t); |
if(short_add&UNSIGNED) |
emit(f,"\tclra\n"); |
emit(f,"\tlea%s\t%s,%s\n",regnames[reg],((t&NU)==CHAR||(short_add&NU)==CHAR)?"b":"d",regnames[reg]); |
store_reg(f,reg,&p->z,ztyp(p)); |
continue; |
} |
emit(f,"\tlea%s\t%s,%s\n",regnames[reg],(t&NQ)==CHAR?"b":"d",regnames[reg]); |
} |
} |
} |
store_reg(f,reg,&p->z,ztyp(p)); |
continue; |
} |
if(c!=LSHIFT&&c!=RSHIFT) |
load_reg(f,reg,&p->q1,t); |
if(c==MULT){ |
if(CPU==6812){ |
int py=0; |
if(reg!=acc) ierror(reg); |
if(!ISRY(q2)&®s[iy]){ |
emit(f,"\tpshy\n"); |
push(2); |
py=1; |
} |
load_reg(f,iy,&p->q2,t); |
emit(f,"\temul\n"); |
if(py){ |
emit(f,SPULL("y")); |
pop(2); |
} |
store_reg(f,acc,&p->z,t); |
continue; |
}else |
ierror(0); |
} |
if(c==LSHIFT||c==RSHIFT){ |
if(isconst(q2)){ |
int l,oldl; |
load_reg(f,acc,&p->q1,t); |
eval_const(&p->q2.val,t); |
oldl=l=zm2l(vmax); |
if(l>=24){ |
if(CPU!=6812&&!optsize) |
emit(f,"\tldd\t#0\n"); |
else |
emit(f,"\tclra\n\tclrb\n"); |
l=0; |
} |
if(l>=8){ |
if(c==LSHIFT) |
emit(f,"\t%s\n\tclrb\n",(CPU==6812)?"tba":"tfr\tb,a"); |
else{ |
if(t&UNSIGNED) |
emit(f,"\ttfr\ta,b\n\tclra\n"); |
else{ |
emit(f,"\ttfr\ta,b\n"); |
emit(f,SEX); |
} |
} |
l-=8; |
} |
while(l--){ |
if(c==RSHIFT){ |
if(t&UNSIGNED){ |
if((t&NQ)==CHAR) |
emit(f,"\tlsrb\n"); |
else |
emit(f,CPU==6809?"\tlsra\n\trorb\n":"\tlsrd\n"); |
}else{ |
if(oldl>12||(t&NQ)==CHAR) |
emit(f,"\tasrb\n"); |
else |
emit(f,"\tasra\n\trorb\n"); |
} |
}else{ |
if((t&NQ)==CHAR) |
emit(f,"\taslb\n"); |
else |
emit(f,CPU==6809?"\taslb\n\trola\n":"\tasld\n"); |
} |
} |
}else{ |
int px;char *s; |
if(regs[ix]&&!scratchreg(ix,p)&&(!isreg(z)||p->z.reg!=ix)){ |
emit(f,SPUSH("x")); |
push(2);px=1; |
}else |
px=0; |
if((p->typf2&NQ)==CHAR){ |
load_reg(f,acc,&p->q2,p->typf2); |
emit(f,(p->typf2&UNSIGNED)?"\tclra\n":SEX); |
emit(f,"\ttfr\td,x\n"); |
}else |
load_reg(f,ix,&p->q2,t); |
load_reg(f,acc,&p->q1,p->typf); |
if((t&NQ)==CHAR) |
emit(f,(p->typf2&UNSIGNED)?"\tclra\n":SEX); |
if(c==LSHIFT) s="lsl"; |
else if(t&UNSIGNED) s="lsr"; |
else s="asr"; |
emit(f,"\t.global\t%s__%s\n",idprefix,s); |
emit(f,"\t%s\t%s__%s\n",jsrinst,idprefix,s); |
if(px){ |
emit(f,SPULL("x")); |
/*emit(f,"\tpul%s\n",regnames[ix]);*/ |
pop(2); |
} |
} |
cc=0; |
store_reg(f,acc,&p->z,t); |
continue; |
} |
if(c>=OR&&c<=AND){ |
s=logicals[c-OR]; |
if(p->q2.am&&p->q2.am->flags==ACC_IND){ |
mobj=p->q1;p->q1=p->q2;p->q2=mobj; |
} |
if(p->q2.flags&KONST){ |
unsigned long l,h; |
eval_const(&p->q2.val,t); |
l=zum2ul(vumax); |
if((t&NQ)!=CHAR){ |
h=(l>>bitsperbyte)&bytemask; |
if(c==AND&&h==0) |
emit(f,"\tclra\n"); |
else if(c==XOR&&h==bytemask) |
emit(f,"\tcoma\n"); |
else if((c==AND&&h!=bytemask)||(c==OR&&h!=0)||(c==XOR&&h!=0)) |
emit(f,"\t%sa\t#%lu\n",s,h); |
} |
h=l&bytemask; |
if(c==AND&&h==0) |
emit(f,"\tclrb\n"); |
else if(c==XOR&&h==bytemask) |
emit(f,"\tcomb\n"); |
else if((c==AND&&h!=bytemask)||(c==OR&&h!=0)||(c==XOR&&h!=0)) |
emit(f,"\t%sb\t#%lu\n",s,h); |
}else{ |
if(isreg(q2)){ |
if(p->q2.reg==acc){ |
if(c==XOR){ |
emit(f,"\tclrb\n"); |
if((t&NQ)!=CHAR) emit(f,"\tclra\n"); |
} |
}else{ |
if((t&NQ)==CHAR){ |
emit(f,SPUSH("a")); |
push(1); |
emit(f,"\t%sa\t%s,%s+\n",s,CPU==6812?"1":"",regnames[sp]); |
pop(1); |
}else{ |
emit(f,"\t%s%s\n",(CPU==6812)?"psh":"pshs\t",regnames[p->q2.reg]); |
push(2); |
emit(f,"\t%sa\t%s,%s+\n",s,CPU==6812?"1":"",regnames[sp]); |
emit(f,"\t%sb\t%s,%s+\n",s,CPU==6812?"1":"",regnames[sp]); |
pop(2); |
} |
} |
}else if((p->q2.flags&(REG|DREFOBJ))==DREFOBJ&&(t&NQ)!=CHAR){ |
int xr=0; |
if(!regs[ix]) xr=ix; |
else if(!regs[iy]) xr=iy; |
else{ |
xr=ix; |
emit(f,"\t%s%s\n",(CPU==6812)?"psh":"pshs\t",regnames[xr]); |
push(2); |
|
} |
BSET(regs_modified,xr); |
load_addr(f,xr,&p->q2); |
if((t&NQ)==CHAR) |
emit(f,"\t%sb\t0,%s\n",s,regnames[xr]); |
else{ |
emit(f,"\t%sa\t0,%s\n",s,regnames[xr]); |
emit(f,"\t%sb\t1,%s\n",s,regnames[xr]); |
} |
if(regs[ix]&&xr==ix){ |
emit(f,SPULL("x")); |
pop(2); |
} |
}else{ |
emit(f,"\t%sb\t",s); |
if((t&NQ)!=CHAR) inc_addr(&p->q2,1,t); |
emit_obj(f,&p->q2,t); |
emit(f,"\n"); |
if((t&NQ)!=CHAR){ |
inc_addr(&p->q2,-1,t); |
emit(f,"\t%sa\t",s); |
emit_obj(f,&p->q2,t); |
emit(f,"\n"); |
} |
} |
} |
cc=0; |
store_reg(f,reg,&p->z,t); |
continue; |
}else if(c==COMPARE){ |
lastcomp=t; |
if(isreg(q2)){ |
emit(f,"\t%s%s\n",(CPU==6812)?"psh":"pshs\t",regnames[p->q2.reg]); |
push(2); |
} |
if(reg==acc){ |
if((t&NQ)==CHAR) |
emit(f,"\tcmpb\t"); |
else |
emit(f,SCMP("d")); |
}else if(reg==ix){ |
emit(f,SCMP("x")); |
}else if(reg==iy){ |
emit(f,SCMP("y")); |
}else if(reg==iu){ |
emit(f,SCMP("u")); |
}else |
ierror(0); |
if(isreg(q2)){ |
if(CPU==6812) |
emit(f,"2,%s+\n",regnames[sp]); |
else |
emit(f,",%s++\n",regnames[sp]); |
pop(2); |
}else{ |
emit_obj(f,&p->q2,t);emit(f,"\n"); |
} |
continue; |
} |
ierror(0); |
} |
pric2(stdout,p); |
ierror(0); |
} |
if(notpopped){ |
gen_pop(f,notpopped); |
notpopped=0; |
} |
function_bottom(f,v,loff); |
if(debug_info){ |
emit(f,"%s%d:\n",labprefix,++label); |
dwarf2_function(f,v,label); |
if(f) section=-1; |
} |
} |
|
int shortcut(int c,int t) |
{ |
if(c==COMPARE||c==ADD||c==SUB||c==AND||c==OR||c==XOR) return 1; |
if((c==LSHIFT||c==RSHIFT)&&ISCHWORD(t&NQ)) return 1; |
return 0; |
} |
|
void cleanup_cg(FILE *f) |
{ |
struct fpconstlist *p; |
unsigned char *ip; |
if(f&&stack_check) |
emit(f,"\t.global\t%s__stack_check\n",idprefix); |
while(p=firstfpc){ |
if(f){ |
if(section!=RODATA){ |
emit(f,rodataname);if(f) section=RODATA; |
} |
emit(f,"%s%d\n\t%s\t",labprefix,p->label,dct[LONG]); |
ip=(unsigned char *)&p->val.vdouble; |
emit(f,"0x%02x%02x%02x%02x",ip[0],ip[1],ip[2],ip[3]); |
if((p->typ&NQ)==DOUBLE||(p->typ&NQ)==LDOUBLE){ |
emit(f,",0x%02x%02x%02x%02x",ip[4],ip[5],ip[6],ip[7]); |
} |
emit(f,"\n"); |
} |
firstfpc=p->next; |
free(p); |
} |
} |
|
int reg_parm(struct reg_handle *p,struct Typ *t,int mode,struct Typ *fkt) |
{ |
if(p->gpr) return 0; |
if(ISSCALAR(t->flags)&&!ISFLOAT(t->flags)&&!ISLWORD(t->flags)){ |
p->gpr=1; |
return acc; |
} |
return 0; |
} |
|
void insert_const(union atyps *p,int t) |
/* Traegt Konstante in entprechendes Feld ein. */ |
{ |
if(!p) ierror(0); |
t&=NU; |
if(t==BIT) {if(zmeqto(zc2zm(vchar),l2zm(0L))) p->vchar=zm2zc(l2zm(0L)); else p->vchar=zm2zc(l2zm(1L));return;} |
if(t==CHAR) {p->vchar=vchar;return;} |
if(t==SHORT) {p->vshort=vshort;return;} |
if(t==INT) {p->vint=vint;return;} |
if(t==LONG) {p->vlong=vlong;return;} |
if(t==LLONG) {p->vllong=vllong;return;} |
if(t==MAXINT) {p->vmax=vmax;return;} |
if(t==(UNSIGNED|BIT)) {if(zumeqto(zuc2zum(vuchar),ul2zum(0UL))) p->vuchar=zum2zuc(ul2zum(0UL)); else p->vuchar=zum2zuc(ul2zum(1UL));return;} |
if(t==(UNSIGNED|CHAR)) {p->vuchar=vuchar;return;} |
if(t==(UNSIGNED|SHORT)) {p->vushort=vushort;return;} |
if(t==(UNSIGNED|INT)) {p->vuint=vuint;return;} |
if(t==(UNSIGNED|LONG)) {p->vulong=vulong;return;} |
if(t==(UNSIGNED|LLONG)) {p->vullong=vullong;return;} |
if(t==(UNSIGNED|MAXINT)) {p->vumax=vumax;return;} |
if(t==FLOAT) {p->vfloat=vfloat;return;} |
if(t==DOUBLE) {p->vdouble=vdouble;return;} |
if(t==LDOUBLE) {p->vldouble=vldouble;return;} |
if(t==NPOINTER) {p->vuint=vuint;return;} |
if(t==FPOINTER||t==HPOINTER) {p->vulong=vulong;return;} |
} |
void eval_const(union atyps *p,int t) |
/* Weist bestimmten globalen Variablen Wert einer CEXPR zu. */ |
{ |
int f=t&NQ; |
if(!p) ierror(0); |
if(f==MAXINT||(f>=BIT&&f<=LLONG)){ |
if(!(t&UNSIGNED)){ |
if(f==BIT){ |
if(zmeqto(zc2zm(p->vchar),l2zm(0L))) vmax=l2zm(0L); else vmax=l2zm(1L); |
}else if(f==CHAR) vmax=zc2zm(p->vchar); |
else if(f==SHORT)vmax=zs2zm(p->vshort); |
else if(f==INT) vmax=zi2zm(p->vint); |
else if(f==LONG) vmax=zl2zm(p->vlong); |
else if(f==LLONG) vmax=zll2zm(p->vllong); |
else if(f==MAXINT) vmax=p->vmax; |
else ierror(0); |
vumax=zm2zum(vmax); |
vldouble=zm2zld(vmax); |
}else{ |
if(f==BIT){ |
if(zumeqto(zuc2zum(p->vuchar),ul2zum(0UL))) vumax=ul2zum(0UL); else vumax=ul2zum(1UL); |
}else if(f==CHAR) vumax=zuc2zum(p->vuchar); |
else if(f==SHORT)vumax=zus2zum(p->vushort); |
else if(f==INT) vumax=zui2zum(p->vuint); |
else if(f==LONG) vumax=zul2zum(p->vulong); |
else if(f==LLONG) vumax=zull2zum(p->vullong); |
else if(f==MAXINT) vumax=p->vumax; |
else ierror(0); |
vmax=zum2zm(vumax); |
vldouble=zum2zld(vumax); |
} |
}else{ |
if(ISPOINTER(f)){ |
if(f==NPOINTER) |
vumax=zui2zum(p->vuint); |
else |
vumax=zul2zum(p->vulong); |
vmax=zum2zm(vumax);vldouble=zum2zld(vumax); |
}else{ |
if(f==FLOAT) vldouble=zf2zld(p->vfloat); |
else if(f==DOUBLE) vldouble=zd2zld(p->vdouble); |
else vldouble=p->vldouble; |
vmax=zld2zm(vldouble); |
vumax=zld2zum(vldouble); |
} |
} |
vfloat=zld2zf(vldouble); |
vdouble=zld2zd(vldouble); |
vuchar=zum2zuc(vumax); |
vushort=zum2zus(vumax); |
vuint=zum2zui(vumax); |
vulong=zum2zul(vumax); |
vullong=zum2zull(vumax); |
vchar=zm2zc(vmax); |
vshort=zm2zs(vmax); |
vint=zm2zi(vmax); |
vlong=zm2zl(vmax); |
vllong=zm2zll(vmax); |
} |
void printval(FILE *f,union atyps *p,int t) |
/* Gibt atyps aus. */ |
{ |
t&=NU; |
if(t==BIT){vmax=zc2zm(p->vchar);fprintf(f,"B%d",!zmeqto(vmax,l2zm(0L)));} |
if(t==(UNSIGNED|BIT)){vumax=zuc2zum(p->vuchar);fprintf(f,"UB%d",!zumeqto(vmax,ul2zum(0UL)));} |
if(t==CHAR){vmax=zc2zm(p->vchar);printzm(f,vmax);} |
if(t==(UNSIGNED|CHAR)){fprintf(f,"UC");vumax=zuc2zum(p->vuchar);printzum(f,vumax);} |
if(t==SHORT){fprintf(f,"S");vmax=zs2zm(p->vshort);printzm(f,vmax);} |
if(t==(UNSIGNED|SHORT)){fprintf(f,"US");vumax=zus2zum(p->vushort);printzum(f,vumax);} |
if(t==FLOAT){fprintf(f,"F");vldouble=zf2zld(p->vfloat);printzld(f,vldouble);} |
if(t==DOUBLE){fprintf(f,"D");vldouble=zd2zld(p->vdouble);printzld(f,vldouble);} |
if(t==LDOUBLE){fprintf(f,"LD");printzld(f,p->vldouble);} |
if(t==INT){fprintf(f,"I");vmax=zi2zm(p->vint);printzm(f,vmax);} |
if(t==(UNSIGNED|INT)||t==NPOINTER){fprintf(f,"UI");vumax=zui2zum(p->vuint);printzum(f,vumax);} |
if(t==LONG){fprintf(f,"L");vmax=zl2zm(p->vlong);printzm(f,vmax);} |
if(t==(UNSIGNED|LONG)||t==FPOINTER||t==HPOINTER){fprintf(f,"UL");vumax=zul2zum(p->vulong);printzum(f,vumax);} |
if(t==LLONG){fprintf(f,"LL");vmax=zll2zm(p->vllong);printzm(f,vmax);} |
if(t==(UNSIGNED|LLONG)){fprintf(f,"ULL");vumax=zull2zum(p->vullong);printzum(f,vumax);} |
if(t==MAXINT) printzm(f,p->vmax); |
if(t==(UNSIGNED|MAXINT)) printzum(f,p->vumax); |
} |
void emitval(FILE *f,union atyps *p,int t) |
{ |
t&=NU; |
if((t&NQ)==NPOINTER) t=(UNSIGNED|INT); |
if(t==BIT){vmax=zc2zm(p->vchar);emit(f,"%d",!zmeqto(vmax,l2zm(0L)));} |
if(t==(UNSIGNED|BIT)){vumax=zuc2zum(p->vuchar);emit(f,"%d",!zumeqto(vmax,ul2zum(0UL)));} |
if(t==CHAR){vmax=zc2zm(p->vchar);emitzm(f,vmax);} |
if(t==(UNSIGNED|CHAR)){vumax=zuc2zum(p->vuchar);emitzum(f,vumax);} |
if(t==SHORT){vmax=zs2zm(p->vshort);emitzm(f,vmax);} |
if(t==(UNSIGNED|SHORT)){vumax=zus2zum(p->vushort);emitzum(f,vumax);} |
if(t==FLOAT){vldouble=zf2zld(p->vfloat);emitzld(f,vldouble);} |
if(t==DOUBLE){vldouble=zd2zld(p->vdouble);emitzld(f,vldouble);} |
if(t==LDOUBLE){emitzld(f,p->vldouble);} |
if(t==INT){vmax=zi2zm(p->vint);emitzm(f,vmax);} |
if(t==(UNSIGNED|INT)||t==NPOINTER){vumax=zui2zum(p->vuint);emitzum(f,vumax);} |
if(t==LONG){vmax=zl2zm(p->vlong);emitzm(f,vmax);} |
if(t==(UNSIGNED|LONG)||t==FPOINTER||t==HPOINTER){vumax=zul2zum(p->vulong);emitzum(f,vumax);} |
if(t==LLONG){vmax=zll2zm(p->vllong);emitzm(f,vmax);} |
if(t==(UNSIGNED|LLONG)){vumax=zull2zum(p->vullong);emitzum(f,vumax);} |
if(t==MAXINT) emitzm(f,p->vmax); |
if(t==(UNSIGNED|MAXINT)) emitzum(f,p->vumax); |
} |
|
void conv_typ(struct Typ *p) |
/* Erzeugt extended types in einem Typ. */ |
{ |
char *attr; |
while(p){ |
if(ISPOINTER(p->flags)){ |
p->flags=((p->flags&~NU)|POINTER_TYPE(p->next)); |
if(attr=p->next->attr){ |
if(strstr(attr,STR_NEAR)) |
p->flags=((p->flags&~NU)|NPOINTER); |
if(strstr(attr,STR_FAR)) |
p->flags=((p->flags&~NU)|FPOINTER); |
if(strstr(attr,STR_HUGE)) |
p->flags=((p->flags&~NU)|HPOINTER); |
} |
} |
if(ISINT(p->flags)&&(attr=p->attr)&&strstr(attr,"bit")) |
p->flags=((p->flags&~NU)|BIT); |
p=p->next; |
} |
} |
|
void init_db(FILE *f) |
{ |
dwarf2_setup(sizetab[HPOINTER],".byte",".2byte",".4byte",".4byte",labprefix,idprefix,".section"); |
dwarf2_print_comp_unit_header(f); |
} |
void cleanup_db(FILE *f) |
{ |
dwarf2_cleanup(f); |
if(f) section=-1; |
} |
/rf6809/trunk/software/vbcc/machines/hc12/machine.dt
0,0 → 1,18
S12BS |
S12BU |
S24BS |
S24BU |
S48BS |
S48BU |
S16BSBE S16BSLE |
S16BUBE S16BULE |
S32BSBE S32BSLE |
S32BUBE S32BULE |
S64BSBE S64BSLE |
S64BUBE S64BULE |
S32BIEEEBE |
S64BIEEEBE |
S64BIEEEBE |
S32BUBE S32BULE |
|
|
/rf6809/trunk/software/vbcc/README.md
0,0 → 1,4
|
These files are for a backend to VBCC supporting the 12-bit version of the 6809. |
To generate code for the 12-bit version the cpu must be specified as CPU=680912 |
|