Import VBCC source snapshot (29/04/2022)
diff --git a/machines/6502/compress.c b/machines/6502/compress.c
new file mode 100644
index 0000000..9295229
--- /dev/null
+++ b/machines/6502/compress.c
@@ -0,0 +1,127 @@
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "vcpr.h"
+
+
+const char tg_copyright[]="6502 code compressor V0.1 (c) 2020 by Volker Barthelmann";
+
+char *inst[]={
+  "lda","ldx","sta","stx","ldy","sty","ldz","stz","ldq","stq",
+  "adc","sbc","and","ora","eor","adcq","sbcq","andq","oraq","eorq",
+  "bne","beq","bcc","bcs","bvs","bvc","bpl","bmi","bra",
+  "clc","sec",
+  /*"pla","pha",*/
+  "txa","tax","tya","tay","tza","taz",
+  "inc","dec","dex","inx","iny","dey","inz","dez","inw","dew","push",
+  /*"rts","rti",*/"jsr","jmp",
+  "cmp","cpx","cpy",
+  "asl","lsr","ror","rol","asw","aslq","lsrq","asr","asrq"
+};
+
+int minsave=5;
+
+void parse_line(char *s,line *p)
+{
+  int l,i;
+  static int secok=0;
+  char buf[16],buf2[16],*e;
+
+  if(sscanf(s," %8s %8s",buf,buf2)==2&&!strcmp(buf,"section")){
+    if(!strcmp(buf2,"text"))
+      secok=1;
+    else
+      secok=0;
+    p->flags=BARRIER;
+    return;
+  }
+
+  if(sscanf(s,"l%d:",&l)==1){
+    p->flags|=LABDEF;
+    p->l1=l;
+    p->size=0;
+    if(!secok) p->flags|=BARRIER;
+    return;
+  }
+
+  if(!secok){
+    p->flags|=BARRIER;
+    return;
+  }
+
+  if(!isspace((unsigned char)*s)){
+    p->flags=BARRIER;
+    return;
+  }
+  while(isspace((unsigned char)*s))
+    s++;
+  for(e=s;isalpha((unsigned char)*e);e++);
+
+  for(i=0;i<sizeof(inst)/sizeof(inst[0]);i++){
+    if(!strncmp(s,inst[i],e-s)){
+      int quad=0;
+      if(e[-1]=='q') quad=2;
+      while(isspace((unsigned char)*e)) e++;
+      if(*e==0){
+	p->size=1;
+	return;
+      }
+      if(*e=='[') p->size++;
+      p->size=2;
+      p->size+=quad;
+      if(sscanf(e,"l%d",&l)==1){
+	p->flags|=LABUSE;
+	p->l1=l;
+      }
+      if(*s=='b'||!strncmp(s,"jmp",3)){
+	p->flags|=BRANCH;
+      }
+      return;
+    }
+  }
+  p->flags=BARRIER;
+}
+
+static int nlab;
+
+#define SECTION "\tsection\ttext\n"
+
+void add_header(line *after)
+{
+  nlab=new_label();
+  line *new;
+  new=new_line();
+  new->flags=LABDEF;
+  new->l1=nlab;
+  new->code=mymalloc(16); /* TODO */
+  sprintf(new->code,"x%d:\n",nlab);
+  insert_line(after,new);
+  new=new_line();
+  new->flags=BARRIER;
+  new->code=mymalloc(strlen(SECTION)+1);
+  strcpy(new->code,SECTION);
+  insert_line(after,new);
+}
+
+void add_ret(line *after)
+{
+  line *new=new_line();
+  new->size=1;
+  new->flags=BARRIER;
+  new->code=mymalloc(8); /*TODO*/
+  strcpy(new->code,"\trts\n");
+  insert_line(after,new);
+}
+
+void add_jsr(line *after)
+{
+  line *new=new_line();
+  new->flags=LABUSE;
+  new->size=3;
+  new->l1=nlab;
+  new->code=mymalloc(24); /* TODO */
+  sprintf(new->code,"\tjsr\tx%d\n",nlab);
+  insert_line(after,new);
+}
diff --git a/machines/6502/machine.c b/machines/6502/machine.c
new file mode 100755
index 0000000..c8e14b6
--- /dev/null
+++ b/machines/6502/machine.c
@@ -0,0 +1,6029 @@
+/*  6502 backend for vbcc
+    (c) Volker Barthelmann 2020
+
+*/                                                                             
+
+#include "supp.h"
+#include "vbc.h"
+
+#include <math.h>
+
+static char FILE_[]=__FILE__;
+
+/*  Public data that MUST be there.                             */
+
+/* Name and copyright. */
+char cg_copyright[]="vbcc 6502 code-generator V0.5 (c) in 2022 by Volker Barthelmann";
+
+/*  Commandline-flags the code-generator accepts:
+    0: just a flag
+    VALFLAG: a value must be specified
+    STRINGFLAG: a string can be specified
+    FUNCFLAG: a function will be called
+    apart from FUNCFLAG, all other versions can only be specified once */
+int g_flags[MAXGF]={0,0,
+		    VALFLAG,0,0,
+		    0,0,
+		    VALFLAG,VALFLAG,0,0,
+		    VALFLAG,0,0,0,
+		    0,0,0,
+		    0,0,0,0,0,0};
+
+/* the flag-name, do not use names beginning with l, L, I, D or U, because
+   they collide with the frontend */
+char *g_flags_name[MAXGF]={"std-syntax","no-rax",
+			   "volatile-regs","ieee","no-peephole",
+			   "cbmascii","softstack",
+			   "reg-args","int-args","mainargs","no-bank-vars",
+			   "common-banknr","btmp-zpage","oldfp","large",
+			   "glob-acc","avoid-bank-switch","manual-banking",
+			   "atascii","65c02","nox","mega65","ce02","c02",
+			   "div-bug","m65io"};
+
+/* the results of parsing the command-line-flags will be stored here */
+union ppi g_flags_val[MAXGF];
+
+/*  Alignment-requirements for all types in bytes.              */
+zmax align[MAX_TYPE+1];
+
+/*  Alignment that is sufficient for every object.              */
+zmax maxalign;
+
+/*  CHAR_BIT for the target machine.                            */
+zmax char_bit;
+
+/*  sizes of the basic 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. will be initialized in init_cg(),
+    register number 0 is invalid, valid registers start at 1 */
+char *regnames[MAXR+1];
+
+/*  The Size of each register in bytes.                         */
+zmax regsize[MAXR+1];
+
+/*  a 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];
+
+/* specifies the priority for the register-allocator, if the same
+   estimated cost-saving can be obtained by several registers, the
+   one with the highest priority will be used */
+int reg_prio[MAXR+1];
+
+/* an empty reg-handle representing initial state */
+struct reg_handle empty_reg_handle={0,0};
+
+/* Names of target-specific variable attributes.                */
+char *g_attr_name[]={"__interrupt","__zpage","__nocpr",0};
+
+#define INTERRUPT 1
+#define ZPAGE 2
+#define NOCOMPRESS 4
+
+/****************************************/
+/*  Private data and functions.         */
+/****************************************/
+
+#define STDSYNTAX  (g_flags[0]&USEDFLAG)
+#define NORAX      (g_flags[1]&USEDFLAG)
+#define VOL_GPRS   ((g_flags[2]&USEDFLAG)?g_flags_val[2].l:NUM_GPRS/2)
+#define IEEE       (g_flags[3]&USEDFLAG)
+#define NOPEEP     (g_flags[4]&USEDFLAG)
+#define CBMASCII   (g_flags[5]&USEDFLAG)
+#define SOFTSTACK  (g_flags[6]&USEDFLAG)
+#define GPR_ARGS   ((g_flags[7]&USEDFLAG)?g_flags_val[7].l:8)
+#define MAINARGS   (g_flags[9]&USEDFLAG)
+#define NOBANKVARS (g_flags[10]&USEDFLAG)
+#define COMMONBANK ((g_flags[11]&USEDFLAG)?g_flags_val[11].l:0)
+#define BIGZPAGE   (g_flags[12]&USEDFLAG)
+#define OLDFP      (g_flags[13]&USEDFLAG)
+#define LARGE      (g_flags[14]&USEDFLAG)
+#define GLOBACC    (g_flags[15]&USEDFLAG)
+#define NOSWITCH   (g_flags[16]&USEDFLAG)
+#define NOBANKING  (g_flags[17]&USEDFLAG)
+#define ATASCII    (g_flags[18]&USEDFLAG)
+#define C02        (g_flags[19]&USEDFLAG)
+#define NOX        (g_flags[20]&USEDFLAG)
+#define MEGA65     (g_flags[21]&USEDFLAG)
+#define CE02       (g_flags[22]&USEDFLAG)
+#define C02ALT     (g_flags[23]&USEDFLAG)
+#define DIVBUG     (g_flags[24]&USEDFLAG)
+#define M65IO      (g_flags[25]&USEDFLAG)
+
+
+
+#define STR_NEAR "near"
+#define STR_FAR "far"
+#define STR_HUGE "huge"
+
+#define PLA (-1)
+#define JMPIND (-2)
+
+static void function_top(FILE *,struct Var *,long);
+static void function_bottom(FILE *f,struct Var *,long);
+
+#define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
+#define isacc(x) (isreg(x)&&(p->x.reg==ra||p->x.reg==rax))
+#define isconst(x) ((p->x.flags&(KONST|DREFOBJ))==KONST)
+
+#define iszpage(o) (((o)->flags&(REG|DREFOBJ))==REG||(((o)->flags&(VAR|DREFOBJ))==VAR&&(o)->v->tattr&ZPAGE))
+
+#define isptr(r) ((r)>=FIRST_PAIR&&(r)<=LAST_PAIR)
+
+static int q1reg,q2reg,zreg;
+
+static char *ccs[]={"eq","ne","lt","ge","le","gt",""};
+static char *logicals[]={"ora","eor","and"};
+static char *arithmetics[]={"slw","srw","adc","sbc","mullw","divw","mod"};
+
+/* alignment of basic data-types, used to initialize align[] */
+static long malign[MAX_TYPE+1]=  {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+/* sizes of basic data-types, used to initialize sizetab[] */
+static long msizetab[MAX_TYPE+1]={1,1,2,2,4,8,4,4,4,0,2,3,3,0,0,0,1,0};
+static char *mregnames[MAXR+1+4];
+
+/* Typenames (needed because of HAVE_EXT_TYPES). */
+char *typname[]={"strange","char","short","int","long","long long",
+                 "float","double","long double","void",
+                 "near-pointer","far-pointer","huge-pointer",
+                 "array","struct","union","enum","function"};
+
+
+/* used to initialize regtyp[] */
+static struct Typ ityp={INT},ctyp={CHAR},ftyp={FLOAT},lltyp={LLONG};
+
+/* macros defined by the backend */
+static char *marray[]={"__section(x)=__vattr(\"section(\"#x\")\")",
+		       "__6502__",
+		       "__SIZE_T_INT",
+		       "__bank(x)=__vattr(\"bank(\"#x\")\")",
+                       "__far=__attr(\"far\")",
+                       "__near=__attr(\"near\")",
+                       "__huge=__attr(\"huge\")",
+		       0};
+
+/* special registers */
+static int ra=1, rx=2, ry=3, sp1=4,sp2=5,sp=6,fp,fp1,fp2;
+static int t4=LAST_GPR,t3=LAST_GPR-1,t2=LAST_GPR-2,t1=LAST_GPR-3;
+static int rax=7;
+static int yval;
+#define NOVAL 1000
+
+#define REGDUMMY1 MAXR+1
+#define REGDUMMY2 MAXR+2
+#define REGDUMMY3 MAXR+3
+
+static int t1,t2,f1,f2; /*tODO: remove*/
+
+static int pushedacc,pushedx,nopeep,cbmascii,atascii,ieee;
+static int storedacc,storedx;
+static int c02,m65,ce02,zzero,noy;
+static int divbug;
+static int m65io;
+static int manbank;
+static char *jmpinst;
+static int pass;
+static int libsave;
+static struct rpair rp2;
+static int cbank;
+static Var bankv;
+static int bankvoffset;
+static int bankcnum;
+static obj zstore;
+static int zstoreflag;
+static int hasretval;
+
+#define SECLEN 128
+char *use_sec;
+int use_bank=-1;
+
+#define dt(t) (((t)&UNSIGNED)?udt[(t)&NQ]:sdt[(t)&NQ])
+static char *sdt[MAX_TYPE+1]={"??","c","s","i","l","ll","f","d","ld","v","p"};
+static char *udt[MAX_TYPE+1]={"??","uc","us","ui","ul","ull","f","d","ld","v","p"};
+
+/* perhaps provide version with 8bit int? */
+#define ISCHAR(t) ((t&NQ)==CHAR)
+#define ISSHORT(t) ((t&NQ)==SHORT||(t&NQ)==INT||(t&NQ)==POINTER)
+#define ISFPOINTER(t) ((t&NQ)==FPOINTER)
+#define ISLONG(t) ((t&NQ)==LONG)
+#define ISLLONG(t) ((t&NQ)==LLONG)
+
+#define ISIDX(r) (r==rx)
+#define ISRIDX(op) (isreg(op)&&ISIDX(p->op.reg))
+#define ISPREG(op) (isreg(op)&&isptr(p->op.reg))
+
+#define LONGM65(c) ((c)==ASSIGN||(c)==PUSH||(c)==GETRETURN||(c)==SETRETURN||((c)>=LSHIFT&&(c)<=MOD)||((c)>=OR&&(c)<=AND))
+
+/* am */
+#define IMM_IND 1
+#define GPR_IND 2
+#define ABS_IND 3
+
+/* sections */
+#define DATA 0
+#define BSS 1
+#define CODE 2
+#define RODATA 3
+#define SPECIAL 4
+
+static long stack;
+static int stack_valid;
+static int section=-1,newobj;
+static char *codename="\tsection\ttext",
+  *dataname="\tsection\tdata",
+  *bssname="\tsection\tbss",
+  *rodataname="\tsection\trodata";
+
+/* return-instruction */
+static char *ret;
+
+/* label at the end of the function (if any) */
+static int exit_label;
+
+/* assembly-prefixes for labels and external identifiers */
+static char *labprefix="l",*idprefix="_";
+
+/* variables to calculate the size and partitioning of the stack-frame
+   in the case of FIXED_SP */
+static long frameoffset,pushed,maxpushed,framesize;
+
+static long localsize,rsavesize,rscnt,argsize;
+
+static void emit_obj(FILE *f,struct obj *p,int t);
+
+/* calculate the actual current offset of an object relativ to the
+   stack-pointer; we use a layout like this:
+   ------------------------------------------------
+   | arguments to this function                   |
+   ------------------------------------------------
+   | caller-save registers [size=rsavesize]       |
+   ------------------------------------------------
+   | local variables [size=localsize]             |
+   ------------------------------------------------
+   | arguments to called functions [size=argsize] |
+   ------------------------------------------------
+   All sizes will be aligned as necessary.
+   In the case of FIXED_SP, the stack-pointer will be adjusted at
+   function-entry to leave enough space for the arguments and have it
+   aligned to 16 bytes. Therefore, when calling a function, the
+   stack-pointer is always aligned to 16 bytes.
+   For a moving stack-pointer, the stack-pointer will usually point
+   to the bottom of the area for local variables, but will move while
+   arguments are put on the stack.
+
+   This is just an example layout. Other layouts are also possible.
+*/
+
+#define bank(x) bankx((x),manbank)
+#define sbank(x) bankx((x),0)
+
+static int bankx(Var *v,int nobank)
+{
+  char *s=v->vattr;
+  int n,r;
+  if(!nobank&&s&&(s=strstr(s,"bank("))){
+    if(sscanf(s+5,"%i",&n)==1)
+      return n;
+  }
+  return -1;
+}
+
+static void ebank(FILE *f,int b)
+{
+  if(b>=0) emit(f,"%d",b);
+  emit(f,"\n");
+}
+
+static long real_offset(struct obj *o)
+{
+  long off=zm2l(o->v->offset);
+  if(off<0){
+    /* function parameter */
+    off=localsize+rsavesize-off-zm2l(maxalign);
+  }
+
+  off+=argsize;
+  off+=zm2l(o->val.vmax);
+  return off;
+}
+
+/*  Initializes an addressing-mode structure and returns a pointer to
+    that object. Will not survive a second call! */
+static struct obj *cam(int flags,int base,long offset)
+{
+  static struct obj obj;
+  static struct AddressingMode am;
+  obj.am=&am;
+  am.flags=flags;
+  am.base=base;
+  am.offset=offset;
+  return &obj;
+}
+
+/* changes to a special section, used for __section() */
+static int special_section(FILE *f,struct Var *v)
+{
+  char *sec;
+  if(v->tattr&ZPAGE){
+    emit(f,"\tsection\tzpage\n");
+  }else{
+    if(!v->vattr) return 0;
+    sec=strstr(v->vattr,"section(");
+    if(!sec) return 0;
+    sec+=strlen("section(");
+    emit(f,"\tsection\t");
+    while(*sec&&*sec!=')') emit_char(f,*sec++);
+    emit(f,"\n");
+  }
+  if(f) section=SPECIAL;
+  return 1;
+}
+
+
+
+#define chk_coll(x) do{if((x)==r||(x)==r1||(x)==r2) return 0;	\
+    if(reg_pair((x),&rp)&&(rp.r1==r||rp.r2==r)) return 0;}while(0)
+
+static int scratch(IC *p,int r,int isnext)
+{
+  int r1,r2;
+  if(!p) return 1;
+  if(reg_pair(r,&rp)){
+    r1=rp.r1;
+    r2=rp.r2;
+  }else{
+    r1=0;
+    r2=0;
+  }
+  if(!isnext&&isreg(z)&&p->z.reg==r){
+    if(!(p->q2.flags&REG))
+      return 1;
+    if(p->q2.reg==r||p->q2.reg==r1||p->q2.reg==r2)
+      return 0;
+    if(reg_pair(p->q2.reg,&rp))
+      if(rp.r1==r||rp.r2==r)
+	return 0;
+    return 1;
+  }
+  while(p){
+    if(p->code==LABEL||p->code==CALL)
+      return 0;
+    if(p->code>=BEQ&&p->code<=BRA)
+      return 0;
+    if(p->code==FREEREG||p->code==ALLOCREG){
+      if(p->q1.reg==r)
+	return 1;
+      if(reg_pair(p->q1.reg,&rp)&&(rp.r1==r||rp.r2==r))
+	return 1;
+    }
+    if(p->q1.am){
+      chk_coll(p->q1.am->base);
+      if(p->q1.am->flags!=IMM_IND) chk_coll(p->q1.am->idx);
+    }
+    if(p->q2.am){
+      chk_coll(p->q2.am->base);
+      if(p->q2.am->flags!=IMM_IND) chk_coll(p->q2.am->idx);
+    }
+    if(p->z.am){
+      chk_coll(p->z.am->base);
+      if(p->z.am->flags!=IMM_IND) chk_coll(p->z.am->idx);
+    }
+    if(p->q1.flags&REG) chk_coll(p->q1.reg);
+    if(p->q2.flags&REG) chk_coll(p->q2.reg);
+    if(p->z.flags&REG){
+      if(p->z.flags&DREFOBJ)
+	chk_coll(p->z.reg);
+      else{
+	if(p->z.reg==r)
+	  return 1;
+	if(reg_pair(p->z.reg,&rp)&&(rp.r1==r||rp.r2==r))
+	  return 1;
+      }
+    }
+
+    p=p->next;
+  }
+  return 1;
+}
+
+static int rsavecur;
+static int in_isr;
+
+static int get_reg(FILE *f,IC *p,int t)
+{
+  int r,r1,r2,pass,flag;
+
+  for(pass=0;pass<5;pass++){
+    for(r=MAXR;r>sp;r--){
+      if(reg_pair(r,&rp)){
+	r1=rp.r1;
+	r2=rp.r2;
+      }else{
+	r1=0;
+	r2=0;
+      }
+      if((pass==0||pass==3)&&(!regscratch[r]||in_isr))
+	continue;
+      if(pass<3){
+	if(regs[r]) continue;
+	if(r1&&(regs[r1]||regs[r2])) continue;
+      }
+      if(pass==2&&!(regs[r]&4))
+	continue;
+      if(p->q1.flags&REG){
+	if(p->q1.reg==r||p->q1.reg==r1||p->q1.reg==r2) continue;
+	if(r1==0&&reg_pair(p->q1.reg,&rp)&&(rp.r1==r||rp.r2==r)) continue;
+      }
+      if(p->q2.flags&REG){
+	if(p->q2.reg==r||p->q2.reg==r1||p->q2.reg==r2) continue;
+	if(r1==0&&reg_pair(p->q2.reg,&rp)&&(rp.r1==r||rp.r2==r)) continue;
+      }
+      if(p->z.flags&REG){
+	if(p->z.reg==r||p->z.reg==r1||p->z.reg==r2) continue;
+	if(r1==0&&reg_pair(p->z.reg,&rp)&&(rp.r1==r||rp.r2==r)) continue;
+      }
+      if(regok(r,t,1)){
+	flag=8;
+	if(regs[r]){
+	  flag|=2;
+	  if(p->code==COMPARE||p->code==TEST)
+	    ierror(0);
+	  if(regs[ra]){
+	    emit(f,"\ttay\n");
+	    yval=NOVAL;
+	  }
+	  if(r1){
+	    emit(f,"\tlda\t%s\n",mregnames[r1]);
+	    emit(f,"\tpha\n");
+	    emit(f,"\tlda\t%s\n",mregnames[r2]);
+	    emit(f,"\tpha\n");
+	  }else{
+	    emit(f,"\tlda\t%s\n",mregnames[r]);
+	    emit(f,"\tpha\n");
+	  }
+	  if(regs[ra])
+	    emit(f,"\ttya\n");
+	}
+	if(r1){
+	  regs[r1]|=flag;
+	  regs[r2]|=flag;
+	}
+	regs[r]|=flag;
+	regused[r]=1;
+	regused[r1]=1;
+	regused[r2]=1;
+	/*emit(f,"; p=%p r=%s\n",(void*)p,mregnames[r]);*/
+	return r;
+      }
+    }
+  }
+  pric2(stdout,p);
+  ierror(0);
+}
+
+static void get_acc(FILE *f, IC *p,int t)
+{
+  int r;
+  if(isacc(z)) return;
+  t&=NQ;
+  if(ISCHAR(t)){
+    if(1/*!isreg(q1)||(p->q1.reg!=ra&&p->q1.reg!=rax)*/){
+      if((regs[ra]||regs[rax])&&!scratch(p,ra,0)&&!pushedacc){
+	if(storedacc)
+	  pushedacc=storedacc;
+	else if(optsize||(regs[t1]&&regs[t2]&&regs[t3]&&regs[t4])){
+	  emit(f,"\tpha\n");
+	  pushedacc=-1;
+	}else{
+	  r=get_reg(f,p,CHAR);
+	  emit(f,"\tsta\t%s\n",mregnames[r]);
+	  pushedacc=r;
+	}
+      }
+    }
+  }else{
+    if(1/*!isreg(q1)||p->q1.reg!=rax*/){
+      if((regs[ra]||regs[rax])&&(!scratch(p,ra,0)||!scratch(p,rax,0))&&!pushedacc){
+	if(!storedacc){
+	  r=get_reg(f,p,CHAR);
+	  emit(f,"\tsta\t%s\n",mregnames[r]);
+	  pushedacc=r;
+	}else
+	  pushedacc=storedacc;
+      }
+      if((regs[rx]||regs[rax])&&!scratch(p,rax,0)&&!pushedx){
+	if(!storedx){
+	  r=get_reg(f,p,CHAR);
+	  emit(f,"\tstx\t%s\n",mregnames[r]);
+	  pushedx=r;
+	}else
+	  pushedx=storedx;
+      }
+    }
+  }
+}
+
+static int cmp_get_acc(FILE *f,IC *p,IC *branch)
+{
+  if(!regs[ra]&&!regs[rax])
+    return 0;
+  if(branch==0&&pushedacc)
+    return 0;
+  if(branch&&isreg(q1)&&(p->q1.reg==ra||p->q1.reg==rax))
+    if(branch->code==BEQ||branch->code==BNE||(p->typf&UNSIGNED))
+      return 0;
+  if(scratch(p,ra,0))
+    return 0;
+  if(!regs[rx]&&!regs[rax]){
+    emit(f,"\ttax\n");
+    pushedacc=rx;
+  }
+  emit(f,"\tpha\n");
+  pushedacc=-1;
+  return pushedacc;
+}
+
+static void reload_acc_opt(FILE *f,IC *p)
+{
+  if(pushedacc==0) return;
+  if(pushedacc>0){
+    while(p){
+      if(p->code!=FREEREG) break;
+      if(p->q1.reg==ra||p->q1.reg==rax){
+	pushedacc=0;
+	return;
+      }
+      p=p->next;
+    }
+  }
+  if(pushedacc==-1)
+    emit(f,"\tpla\n");
+  else if(pushedacc==rx)
+    emit(f,"\ttxa\n");
+  else if(pushedacc==ry)
+    emit(f,"\ttya\n");
+  else if(pushedacc){
+    emit(f,"\tlda\t%s\n",mregnames[pushedacc]);
+    regs[pushedacc]&=~8;
+  }
+  pushedacc=0;
+}
+
+static void reload_acc(FILE *f)
+{
+  reload_acc_opt(f,0);
+}
+
+static void push(int i)
+{
+  pushed-=i;
+  if(pushed<maxpushed)
+    maxpushed=pushed;
+}
+
+static void pop(int i)
+{
+  pushed+=i;
+  if(pushed>0) ierror(0);
+}
+
+static int indirect(obj *o)
+{
+  if(o->am){
+    if(o->am->flags==ABS_IND&&o->am->idx==rx)
+      return 0;
+    else
+      return 1;
+  }
+  if((o->flags&(DREFOBJ|KONST))==DREFOBJ)
+    return 1;
+  if((o->flags&(REG|VAR))!=VAR){
+    if((o->flags&REG)&&(o->reg==ra||ISIDX(o->reg)||o->reg==rax))
+      return 1;
+    return 0;
+  }
+  if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)
+    return 1;
+  return 0;
+}
+
+void convfloat(void)
+{
+}  
+
+void sety(FILE *f,int val)
+{
+  if(yval==val)
+    return;
+  if(val-yval==1)
+    emit(f,"\tiny\n");
+  else if(yval-val==1)
+    emit(f,"\tdey\n");
+  else{
+    emit(f,"\tldy\t#%d\n",val);
+    if(val<0||val>255)
+      ierror(0);
+  }
+  yval=val;
+}
+
+static void cnv_fp(void)
+{
+  double d,mant;
+  int exp;
+  unsigned long t;
+
+  if(ieee){
+    vfloat=zld2zf(vldouble);
+    memcpy((void*)&vmax,(void*)&vfloat,4);
+  }else{
+    d=zld2d(vldouble);
+    mant=frexp(d,&exp);
+    exp=(exp+127)&255;
+    t=((unsigned long)(mant*8388608))&0xffffff;
+    t|=((long)exp)<<24;
+    
+    t=((t&0xff)<<24)|((t&0xff00)<<8)|((t&0xff0000)>>8)|((t&0xff000000)>>24);
+    vmax=l2zm((long)t);
+    if(mant==0&&d==0) vmax=Z0;
+  }
+}
+
+static void emit_ieee(FILE *f,union atyps *p,int t)
+{
+  unsigned char *ip=(unsigned char *)&p->vdouble;
+  emit(f,"0x%02x%02x,0x%02x%02x",ip[1],ip[0],ip[3],ip[2]);
+  if(t==DOUBLE||t==LDOUBLE)
+    emit(f,",0x%02x%02x,0x%02x%02x",ip[5],ip[4],ip[7],ip[6]);
+  emit(f,"\n");
+}
+
+static void emit_lobyte(FILE *f,obj *o,int t)
+{
+  if(o->flags&KONST){
+    if(o->flags&DREFOBJ){
+      eval_const(&o->val,o->dtyp);
+       emit(f,"%d",zm2l(vmax));
+    }else{
+      eval_const(&o->val,t);
+      if(ISFLOAT(t)) cnv_fp();
+      emit(f,"#%d",zm2l(vmax)&255);
+    }
+  }else if(o->flags&VARADR){
+    emit(f,"#<(");
+    emit_obj(f,o,t);
+    emit(f,")");
+  }else if((o->flags&(REG|DREFOBJ))==REG){
+    if(!reg_pair(o->reg,&rp))
+      emit(f,"%s",mregnames[o->reg]);
+    else
+      emit(f,"%s",mregnames[rp.r1]);
+  }else{
+    if(zzero&&(o->flags&(DREFOBJ|KONST))==DREFOBJ) noy=1;
+    emit_obj(f,o,t);
+    noy=0;
+  }
+}
+
+static void emit_hibyte(FILE *f,obj *o,int t)
+{
+  if(o->flags&KONST){
+    if(o->flags&DREFOBJ){
+      eval_const(&o->val,o->dtyp);
+      emit(f,"%d",zm2l(vmax)+1);
+    }else{
+      eval_const(&o->val,t);
+      if(ISFLOAT(t)) cnv_fp();
+      emit(f,"#%d",(zm2l(vmax)>>8)&255);
+    }
+  }else if(o->flags&VARADR){
+    emit(f,"#>(");
+    emit_obj(f,o,t);
+    emit(f,")");
+  }else if((o->flags&(REG|DREFOBJ))==REG){
+    if(o->reg>=FIRST_BIG&&o->reg<=LAST_BIGP){
+      emit(f,"%s+1",mregnames[o->reg]);
+    }else{
+      if(!reg_pair(o->reg,&rp))
+	ierror(0);
+      emit(f,"%s",mregnames[rp.r2]);
+    }
+  }else{
+    if(o->flags&VARADR)
+      emit(f,"#");
+    if(!(o->flags&DREFOBJ))
+      o->val.vmax=zmadd(o->val.vmax,Z1);
+    emit_obj(f,o,t);
+    if(!(o->flags&DREFOBJ))
+      o->val.vmax=zmsub(o->val.vmax,Z1);
+  }
+}
+
+static void emit_byte3(FILE *f,obj *o,int t)
+{
+  if(o->flags&KONST){
+    if(o->flags&DREFOBJ){
+      eval_const(&o->val,o->dtyp);
+      emit(f,"%d",zm2l(vmax)+2);
+    }else{
+      eval_const(&o->val,t);
+      if(ISFLOAT(t)) cnv_fp();
+      emit(f,"#%d",(zm2l(vmax)>>16)&255);
+    }
+  }else if((o->flags&(REG|DREFOBJ))==REG){
+    emit(f,"%s+2",mregnames[o->reg]);
+  }else if(o->flags&VARADR){
+    emit(f,"#%d",bank(o->v));
+  }else{
+    if(!(o->flags&DREFOBJ))
+      o->val.vmax=zmadd(o->val.vmax,l2zm(2L));
+    emit_obj(f,o,t);
+    if(!(o->flags&DREFOBJ))
+      o->val.vmax=zmsub(o->val.vmax,l2zm(2L));
+  }
+}
+
+static void emit_byte4(FILE *f,obj *o,int t)
+{
+  if(o->flags&KONST){
+    if(o->flags&DREFOBJ){
+      eval_const(&o->val,o->dtyp);
+      emit(f,"%d",zm2l(vmax)+3);
+    }else{
+      eval_const(&o->val,t);
+      if(ISFLOAT(t)) cnv_fp();
+      emit(f,"#%d",(zm2l(vmax)>>24)&255);
+    }
+  }else if((o->flags&(REG|DREFOBJ))==REG){
+    emit(f,"%s+3",mregnames[o->reg]);
+  }else{
+    if(!(o->flags&DREFOBJ))
+      o->val.vmax=zmadd(o->val.vmax,l2zm(3L));
+    emit_obj(f,o,t);
+    if(!(o->flags&DREFOBJ))
+      o->val.vmax=zmsub(o->val.vmax,l2zm(3L));
+  }
+}
+
+static void ldq_offset(FILE *f,obj *o)
+{
+  if(o->am){
+    if(o->am->flags==IMM_IND)
+      emit(f,"\tldz\t#%ld\n",o->am->offset);
+    else if(o->am->flags==GPR_IND||o->am->flags==ABS_IND){
+      if(o->am->idx==ra)
+	emit(f,"\ttaz\n");
+      else{
+	if(ISIDX(o->am->idx)){
+	  if(o->am->flags==GPR_IND){
+	    emit(f,"\tpha\n");
+	    emit(f,"\tt%sa\n",mregnames[o->am->idx]);
+	    emit(f,"\ttaz\n");
+	    emit(f,"\tpla\n");
+	  }
+	}else
+	  emit(f,"\tldz\t%s\n",mregnames[o->am->idx]);
+      }
+    }else
+      ierror(0);
+  }else if((o->flags&(DREFOBJ|KONST))==DREFOBJ){
+    /*if(!zzero)*/ emit(f,"\tldz\t#0\n");
+  }else if((o->flags&(VAR|REG|VARADR))==VAR&&(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)){
+    emit(f,"\tldz\t#%ld\n",real_offset(o));
+  }
+}
+
+static void do_amload(FILE *f,obj *o)
+{
+  if(o->am->flags==GPR_IND||o->am->flags==ABS_IND){
+    if(o->am->idx==ra)
+      emit(f,"\ttay\n");
+    else{
+      if(ISIDX(o->am->idx)){
+	if(o->am->flags==GPR_IND){
+	  emit(f,"\tpha\n");
+	  emit(f,"\tt%sa\n",mregnames[o->am->idx]);
+	  emit(f,"\ttay\n");
+	  emit(f,"\tpla\n");
+	}
+      }else{
+	if(o->am->idx==ra)
+	  emit(f,"\ttay\n");
+	else
+	  emit(f,"\tldy\t%s\n",mregnames[o->am->idx]);
+      }
+    }
+  }else
+    ierror(0);
+}
+static void do_lobyte(FILE *f,char *s,obj *o,int type)
+{
+  if(o->am){
+    if(o->am->flags==IMM_IND)
+      sety(f,o->am->offset);
+    else{
+      do_amload(f,o);
+      yval=NOVAL;
+    }
+  }else if((o->flags&(DREFOBJ|KONST))==DREFOBJ){
+    if(!zzero) sety(f,0);
+  }else if((o->flags&(VAR|REG|VARADR))==VAR&&(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)){
+    sety(f,(int)real_offset(o));
+  }
+  emit(f,"\t%s\t",s);
+  emit_lobyte(f,o,type);
+  emit(f,"\n");
+}
+
+static void do_hibyte(FILE *f,char *s,obj *o,int type)
+{
+  int ami=0;
+  if(o->am){
+    if(o->am->flags==IMM_IND)
+      sety(f,o->am->offset+1);
+    else{
+      do_amload(f,o);
+      if(o->am->flags==GPR_IND){
+	emit(f,"\tiny\n");
+      }else{
+	o->am->offset++;ami=1;
+      }
+      yval=NOVAL;
+    }
+  }else  if((o->flags&(DREFOBJ|KONST))==DREFOBJ){
+    sety(f,1);
+  }else if((o->flags&(VAR|REG|VARADR))==VAR&&(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)){
+    sety(f,(int)real_offset(o)+1);
+  }
+  emit(f,"\t%s\t",s);
+  emit_hibyte(f,o,type);
+  emit(f,"\n");
+  if(ami) o->am->offset--;
+}
+
+static void do_byte3(FILE *f,char *s,obj *o,int type)
+{
+  int ami=0;
+  if(o->am){
+    if(o->am->flags==IMM_IND)
+      sety(f,o->am->offset+2);
+    else{
+      do_amload(f,o);
+      if(o->am->flags==GPR_IND){
+	emit(f,"\tiny\n\tiny\n");
+      }else{
+	o->am->offset+=2;ami=1;
+      }
+      yval=NOVAL;
+    }
+  }else  if((o->flags&(DREFOBJ|KONST))==DREFOBJ){
+    sety(f,2);
+  }else if((o->flags&(VAR|REG|VARADR))==VAR&&(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)){
+    sety(f,(int)real_offset(o)+2);
+  }
+  emit(f,"\t%s\t",s);
+  emit_byte3(f,o,type);
+  emit(f,"\n");
+  if(ami) o->am->offset-=2;
+}
+
+static void do_byte4(FILE *f,char *s,obj *o,int type)
+{
+  int ami=0;
+  if(o->am){
+    if(o->am->flags==IMM_IND)
+      sety(f,o->am->offset+3);
+    else{
+      do_amload(f,o);
+      if(o->am->flags==GPR_IND){
+	emit(f,"\tiny\n\tiny\n\tiny\n");
+      }else{
+	o->am->offset+=3;ami=1;
+      }
+      yval=NOVAL;
+    }
+  }else  if((o->flags&(DREFOBJ|KONST))==DREFOBJ){
+    sety(f,3);
+  }else if((o->flags&(VAR|REG|VARADR))==VAR&&(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)){
+    sety(f,(int)real_offset(o)+3);
+  }
+  emit(f,"\t%s\t",s);
+  emit_byte4(f,o,type);
+  emit(f,"\n");
+  if(ami) o->am->offset-=3;
+}
+
+static void load_lobyte(FILE *f,obj *o,int t)
+{
+  if((o->flags&(REG|DREFOBJ))==REG){
+    if(o->reg==ra||o->reg==rax)
+      return;
+    if(o->reg==rx){
+      emit(f,"\ttxa\n");
+      return;
+    }
+  }
+  do_lobyte(f,"lda",o,t);
+}
+
+static void load_hibyte(FILE *f,obj *o,int t)
+{
+  if((o->flags&REG)&&(o->reg==rx||o->reg==rax))
+    emit(f,"\ttxa\n");
+  else
+    do_hibyte(f,"lda",o,t);
+}
+
+static void store_lobyte(FILE *f,obj *o,int t)
+{
+  if((o->flags&(REG|DREFOBJ))==REG){
+    if(o->reg==ra||o->reg==rax)
+      return;
+    if(o->reg==rx){
+      emit(f,"\ttax\n");
+      return;
+    }
+  }
+  do_lobyte(f,"sta",o,t);
+}
+
+static void store_hibyte(FILE *f,obj *o,int t)
+{
+  if((o->flags&REG)&&(o->reg==rx||o->reg==rax))
+    emit(f,"\ttax\n");
+  else
+    do_hibyte(f,"sta",o,t);
+}
+
+static void load_acc(FILE *f,obj *o,int type)
+{
+  if((o->flags&REG)&&(o->reg==ra||o->reg==rax))
+    return;
+  if(!ISCHAR(type)){
+    if(indirect(o)){
+      do_hibyte(f,"lda",o,type);
+      emit(f,"\ttax\n");
+    }else
+      do_hibyte(f,"ldx",o,type);
+  }
+  if((o->flags&(REG|DREFOBJ))==REG&&o->reg==rx)
+    emit(f,"\ttxa\n");
+  else
+    do_lobyte(f,"lda",o,type);
+}
+
+static void store_acc(FILE *f,obj *o,int type)
+{
+  if((o->flags&(DREFOBJ|KONST))==DREFOBJ&&((!(o->flags&REG))||!isptr(o->reg))){
+    ierror(0);
+  }
+  if((o->flags&REG)&&(o->reg==ra||o->reg==rax))
+    return;
+  if((o->flags&REG)&&o->reg==rx){
+    emit(f,"\ttax\n");
+    return;
+  }
+  store_lobyte(f,o,type);
+  if(!ISCHAR(type)){
+    if(indirect(o)){
+      /*TODO: save accu */
+      emit(f,"\ttxa\n");
+      store_hibyte(f,o,type);
+    }else
+      do_hibyte(f,"stx",o,type);
+  }
+}
+
+static void load_reg(FILE *f,int r,struct obj *o,int type)
+{
+  static obj ro;
+  if(ISIDX(r)&&!indirect(o)){
+    static char ldr[4]="ldr";
+    ldr[2]=mregnames[r][0];
+    do_lobyte(f,ldr,o,type);
+    return;
+  }
+  ro.flags=REG;
+  ro.reg=r;
+  load_lobyte(f,o,type);
+  store_lobyte(f,&ro,type);
+  if(!ISCHAR(type)){
+    load_hibyte(f,o,type);
+    store_hibyte(f,&ro,type);
+  }
+}
+
+static void store_reg(FILE *f,int r,struct obj *o,int type)
+{
+  static obj ro;
+  if(ISIDX(r)){
+    if((o->flags&(REG|DREFOBJ))==REG){
+      if(o->reg==r)
+	return;
+      if(o->reg==ra){
+	emit(f,"\tt%sa\n",mregnames[r]);
+	return;
+      }
+    }
+    if(!indirect(o)){
+      static char str[4]="str";
+      str[2]=mregnames[r][0];
+      do_lobyte(f,str,o,type);
+      return;
+    }
+  }
+  ro.flags=REG;
+  ro.reg=r;
+  if(r!=ra&&r!=rax)
+    load_acc(f,&ro,type);
+  store_acc(f,o,type);
+}
+
+static struct fpconstlist {
+  struct fpconstlist *next;
+  int label;
+  int t;
+  union atyps val;
+} *firstfpc;
+
+static int addfpconst(struct obj *o,int t)
+{
+  struct fpconstlist *p=firstfpc;
+  t&=NQ;
+  if(t==LDOUBLE) t=DOUBLE;
+  for(p=firstfpc;p;p=p->next){
+    if(t==p->t){
+      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==LONG&&zmeqto(vmax,zl2zm(o->val.vlong))) return p->label;
+      if(t==LLONG&&zmeqto(vmax,zll2zm(o->val.vllong))) return p->label;
+    }
+  }
+  p=mymalloc(sizeof(struct fpconstlist));
+  p->next=firstfpc;
+  p->t=t;
+  p->label=++label;
+  p->val=o->val;
+  firstfpc=p;
+  return p->label;
+}
+
+/* generate code to load the address of a local variable into register r */
+static void load_laddr(FILE *f,int r,struct obj *o)
+{
+  long l=real_offset(o);
+  /* assumes acc is available */
+  if(!reg_pair(r,&rp)) ierror(0);
+  emit(f,"\tlda\t%s\n",mregnames[fp]);
+  if(l!=0)
+    emit(f,"\tclc\n");
+  if(l&255)
+    emit(f,"\tadc\t#%ld\n",l&255);
+  emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
+  emit(f,"\tlda\t%s\n",mregnames[fp2]);
+  if(l!=0)
+    emit(f,"\tadc\t#%ld\n",(l>>8)&255);
+  emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
+}
+
+/* generate code to load the address of a variable into register r */
+static void load_address(FILE *f,int r,struct obj *o,int t)
+{
+  if(o->flags&DREFOBJ){
+    o->flags&=~DREFOBJ;
+    load_reg(f,r,o,POINTER);
+    o->flags|=DREFOBJ;
+  }else if((o->flags&(REG|DREFOBJ))==REG){
+    if(!reg_pair(r,&rp)) ierror(0);
+    emit(f,"\tlda\t#>%s\n",mregnames[o->reg]);
+    emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
+    emit(f,"\tlda\t#<%s\n",mregnames[o->reg]);
+    emit(f,"\tsta\t%s\n",mregnames[rp.r1]);    
+  }else if(o->flags&VAR){
+    if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER){
+      load_laddr(f,r,o);
+    }else{
+      o->flags|=VARADR;
+      load_reg(f,r,o,POINTER);
+      o->flags&=~VARADR;
+    }
+  }else if((o->flags&(KONST|DREFOBJ))==KONST){
+    int l=addfpconst(o,t);
+    if(!ieee) ierror(0);
+    if(!reg_pair(r,&rp)) ierror(0);
+    emit(f,"\tlda\t#>%s%d\n",labprefix,l);
+    emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
+    emit(f,"\tlda\t#<%s%d\n",labprefix,l);
+    emit(f,"\tsta\t%s\n",mregnames[rp.r1]);    
+  }else
+    ierror(0);
+}
+
+
+/*  Yields log2(x)+1 or 0. */
+static long pof2(zumax x)
+{
+  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 incmem(FILE *f,obj *o,int t,int op,int x)
+{
+  int i,idx=0;
+  char *s;
+  if(ce02&&ISSHORT(t)){
+    if(((o->flags&(REG|DREFOBJ))==REG&&(op==ADD||op==SUB))||
+       (op==LSHIFT&&!indirect(o)&&!o->am)){
+      do{
+	emit(f,"\t%s\t%s\n",op==ADD?"inw":(op==SUB?"dew":"asw"),mregnames[o->reg]);
+      }while(--x);
+      return;
+    }
+  }
+  if((o->flags&(REG|DREFOBJ))==REG&&ISIDX(o->reg)){
+    static char buf[4]="   ";
+    idx=1;s=buf;
+    if(op==ADD){s[0]='i';s[1]='n';}else{s[0]='d';s[1]='e';}
+    s[2]=mregnames[o->reg][0];
+  }else if(op==ADD)
+    s="inc";
+  else if(op==SUB)
+    s="dec";
+  else if(op==LSHIFT)
+    s="asl";
+  else if(op==RSHIFT&&(t&UNSIGNED))
+    s="lsr";
+  else if(op==RSHIFT){
+    s="cmp\t#128\n\tror";
+  }else
+    ierror(0);
+  if(ISCHAR(t)){
+    for(i=0;i<x;i++){
+      if(idx){
+	emit(f,"\t%s\n",s);
+      }else{
+	emit(f,"\t%s\t",s);
+	emit_obj(f,o,t);
+	emit(f,"\n");
+      }
+    }
+  }else{
+    for(i=0;i<x;i++){
+      if(op==SUB){
+	if(m65&&ISLONG(t)){
+	  emit(f,"\tdeq\t");
+	  emit_obj(f,o,t);
+	  emit(f,"\n");
+	}else if(ce02&&iszpage(o)){
+	  emit(f,"\tdew\n");
+	}else{
+	  /* caller mus make sure accu is available */
+	  load_lobyte(f,o,t);
+	  emit(f,"\tbne\t%s%d\n",labprefix,++label);
+	  emit(f,"\tdec\t");
+	  emit_hibyte(f,o,t);
+	  emit(f,"\n");
+	  if(ISLONG(t)){
+	    ierror(0);
+	  }
+	  emit(f,"%s%d:\n",labprefix,label);
+	  emit(f,"\tdec\t");
+	  emit_lobyte(f,o,t);
+	  emit(f,"\n");
+	}
+      }else if(op==ADD){
+	if(!optspeed&&m65&&ISLONG(t)){
+	  emit(f,"\tinq\t");
+	  emit_obj(f,o,t);
+	  emit(f,"\n");
+	}else if(!optspeed&&ce02&&iszpage(o)){
+	  emit(f,"\tinw\t");
+	  emit_lobyte(f,o,t);
+	  emit(f,"\n");
+	  if(ISLONG(t)){
+	    emit(f,"\tbne\t%s%d\n",labprefix,++label);
+	    emit(f,"\tinw\t");
+	    emit_byte3(f,o,t);
+	    emit(f,"\n");
+	    emit(f,"%s%d:\n",labprefix,label);
+	  }
+	}else{
+	  emit(f,"\t%s\t",s);
+	  emit_lobyte(f,o,t);
+	  emit(f,"\n");
+	  emit(f,"\tbne\t%s%d\n",labprefix,++label);
+	  emit(f,"\t%s\t",s);
+	  emit_hibyte(f,o,t);
+	  emit(f,"\n");
+	  if(ISLONG(t)){
+	    emit(f,"\tbne\t%s%d\n",labprefix,label);
+	    emit(f,"\t%s\t",s);
+	    emit_byte3(f,o,t);
+	    emit(f,"\n");
+	    emit(f,"\tbne\t%s%d\n",labprefix,label);
+	    emit(f,"\t%s\t",s);
+	    emit_byte4(f,o,t);
+	    emit(f,"\n");
+	  }
+	  emit(f,"%s%d:\n",labprefix,label);
+	}
+      }else if(op==LSHIFT){
+	if(ce02&&!indirect(o)&&!o->am){
+	  emit(f,"\tasw\t");
+	  emit_obj(f,o,t);
+	  emit(f,"\n");
+	}else{
+	  emit(f,"\tasl\t");
+	  emit_lobyte(f,o,t);
+	  emit(f,"\n");
+	  emit(f,"\trol\t");
+	  emit_hibyte(f,o,t);
+	  emit(f,"\n");
+	}
+	if(ISLONG(t)){
+	  do_byte3(f,"rol",o,t);
+	  do_byte4(f,"rol",o,t);
+	}
+      }else if(op==RSHIFT&&(t&UNSIGNED)){
+	/*emit(f,"\tclc\n");
+	  emit(f,"\tror\t");*/
+	if(ISLONG(t)){
+	  do_byte4(f,"lsr",o,t);
+	  do_byte3(f,"ror",o,t);
+	  do_hibyte(f,"ror",o,t);
+	}else
+	  do_hibyte(f,"lsr",o,t);
+	do_lobyte(f,"ror",o,t);
+      }else if(op==RSHIFT){
+	if(ce02){
+	  emit(f,"\tasr\t");
+	}else{
+	  if(ISLONG(t))
+	    do_byte4(f,"lda",o,t);
+	  else
+	    load_hibyte(f,o,t);
+	  emit(f,"\tcmp\t#128\n");
+	  emit(f,"\tror\t");
+	}
+	if(ISLONG(t))
+	  emit_byte4(f,o,t);
+	else
+	  emit_hibyte(f,o,t);
+	emit(f,"\n");
+	if(ISLONG(t)){
+	  do_byte3(f,"ror",o,t);
+	  do_hibyte(f,"ror",o,t);
+	}
+	do_lobyte(f,"ror",o,t);
+      }else{
+	printf("op=%d\n",op);
+	ierror(0);
+      }
+    }
+  }
+}
+
+static void preload_obj(FILE *f,IC *p,obj *o)
+{
+  int r,pa=0,px=0,longm65=0;long of;
+
+  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");
+
+
+  if(m65){
+    int t;
+    if(o==&p->q1)
+      t=q1typ(p);
+    else{
+      if(o==&p->q2) t=q2typ(p);
+      else if(o==&p->z) t=ztyp(p);
+      else ierror(0);
+      if(ISLONG(t)&&LONGM65(p->code)) longm65=1;
+    }
+  }
+
+  if((o->flags&(VAR|REG))==VAR&&(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)&&(((of=real_offset(o))+zm2l(szof(o->v->vtyp))>255)||longm65)){
+    r=get_reg(f,p,POINTER);
+    if(o->flags&DREFOBJ){
+      if(p->code==GETRETURN&&(p->q1.reg==ra||p->q1.reg==rax)){
+	emit(f,"\tsta\t%s\n",mregnames[t1]);
+	emit(f,"\tstx\t%s\n",mregnames[t2]);
+	pa=px=1;
+      }else
+	get_acc(f,p,INT);
+    }else{
+      if(p->code==GETRETURN&&(p->q1.reg==ra||p->q1.reg==rax)){
+	emit(f,"\tsta\t%s\n",mregnames[t1]);
+	pa=1;
+      }else
+	cmp_get_acc(f,p,0);
+    }
+    if(!reg_pair(r,&rp)) ierror(0);
+    emit(f,"\tlda\t%s\n",mregnames[fp1]);
+    emit(f,"\tclc\n");
+    if(of&0xff)
+      emit(f,"\tadc\t#%ld\n",of&0xff);
+    emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
+    emit(f,"\tlda\t%s\n",mregnames[fp2]);
+    if(1/*of&0xff00*/)
+      emit(f,"\tadc\t#%ld\n",(of>>8)&0xff);
+    emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
+    o->flags|=REG;
+    o->reg=r;
+    if(o->flags&DREFOBJ){
+      if(!zzero) sety(f,0);
+      emit(f,"\tlda\t(%s)%s\n",mregnames[r],zzero?"":",y");
+      emit(f,"\ttxa\n");
+      sety(f,1);
+      emit(f,"\tlda\t(%s),y\n",mregnames[r]);
+      emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
+      emit(f,"\tstx\t%s\n",mregnames[rp.r1]);
+    }else{
+      o->flags|=DREFOBJ;
+      o->dtyp=POINTER;
+    }
+    if(pa){ emit(f,"\tlda\t%s\n",mregnames[t1]); pa=0;}
+    if(px){ emit(f,"\tldx\t%s\n",mregnames[t2]); px=0;}
+  }
+
+  if((o->flags&(DREFOBJ|KONST))==DREFOBJ&&(!(o->flags&REG)||!isptr(o->reg))&&(!(o->flags&VAR)||!(o->v->tattr&ZPAGE))&&!ISFPOINTER(o->dtyp)){
+    if(p->code==GETRETURN&&(p->q1.reg==ra||p->q1.reg==rax)){
+      emit(f,"\tsta\t%s\n",mregnames[t1]);
+      pa=1;
+    }else
+      cmp_get_acc(f,p,0);
+    r=get_reg(f,p,POINTER);
+    o->flags&=~DREFOBJ;
+    load_reg(f,r,o,POINTER);
+    o->flags|=REG|DREFOBJ;
+    o->reg=r;
+    if(pa){ emit(f,"\tlda\t%s\n",mregnames[t1]); pa=0;}
+  }
+}
+
+static void far_copy(FILE *f,IC *p)
+{
+  int b;long l;
+  get_acc(f,p,INT);
+  if(p->code==PUSH){
+    if(!reg_pair(LAST_PAIR,&rp)) ierror(0);
+    emit(f,"\tlda\t%s\n",mregnames[sp]);
+    if(pushed) emit(f,"\tclc\n");
+    if(pushed&0xff) emit(f,"\tadc\t#%d\n",(pushed&0xff));
+    emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
+    emit(f,"\tlda\t%s+1\n",mregnames[sp]);
+    if(pushed) emit(f,"\tadc\t#%d\n",((pushed>>8)&0xff));
+    emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
+    pushed+=zm2l(p->q2.val.vmax);
+    emit(f,"\tldx\t#%d\n",bankcnum);
+  }else if(p->z.flags&DREFOBJ){
+    if(!reg_pair(LAST_PAIR,&rp)) ierror(0);
+    p->z.flags&=~DREFOBJ;
+    load_lobyte(f,&p->z,FPOINTER);
+    emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
+    load_hibyte(f,&p->z,FPOINTER);
+    emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
+    if(indirect(&p->z)){
+      do_byte3(f,"lda",&p->z,FPOINTER);
+      emit(f,"\ttax\n");
+    }else
+      do_byte3(f,"ldx",&p->z,FPOINTER);
+  }else{
+    load_address(f,LAST_PAIR,&p->z,POINTER);
+    b=bank(p->z.v);
+    emit(f,"\tldx\t#%d\n",b>=0?b:bankcnum);
+  }
+  if(p->q1.flags&DREFOBJ){
+    if(!reg_pair(LAST_PAIR-1,&rp)) ierror(0);
+    p->q1.flags&=~DREFOBJ;
+    load_lobyte(f,&p->q1,FPOINTER);
+    emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
+    load_hibyte(f,&p->q1,FPOINTER);
+    emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
+    if(indirect(&p->q1)){
+      do_byte3(f,"lda",&p->q1,FPOINTER);
+      emit(f,"\ttay\n");
+    }else
+      do_byte3(f,"ldy",&p->q1,FPOINTER);
+  }else{
+    load_address(f,LAST_PAIR-1,&p->q1,POINTER);
+    b=bank(p->q1.v);
+    sety(f,b>=0?b:bankcnum);
+  }
+  l=zm2l(p->q2.val.vmax);
+  emit(f,"\tlda\t#%d\n",(l>>8)&0xff);
+  emit(f,"\tsta\t%s__bankcopy_len+1\n",idprefix);
+  emit(f,"\tlda\t#%d\n",(l)&0xff);
+  emit(f,"\tsta\t%s__bankcopy_len\n",idprefix);
+  emit(f,"\tlda\t#%d\n",cbank>=0?cbank:bankcnum);
+  emit(f,"\tjsr\t%s__bankcopy\n",idprefix);
+  yval=NOVAL;
+}
+
+static void load_far(FILE *f,IC *p,obj *o,int t)
+{
+  int pushed=0;
+  if(!(o->flags&DREFOBJ)) ierror(0);
+  o->flags&=~DREFOBJ;
+  t&=NQ;
+  if(zmeqto(sizetab[t],Z0)) return;
+  /*get_acc(f,p,INT);*/
+  if(pushedacc==t3||pushedacc==t4) ierror(0);
+  if(pushedx==t3||pushedx==t4) ierror(0);
+  if(regs[ra]||regs[rax]){
+    if(isacc(q1)||isacc(q2)||!isacc(z)){
+      pushed=1;
+      emit(f,"\tpha\n");
+      if(regs[rax]) emit(f,"\ttxa\n\tpha\n");
+    }
+  }
+  load_reg(f,LAST_PAIR,o,POINTER);
+  if(!indirect(o))
+    do_byte3(f,"ldy",o,CHAR);
+  else{
+    do_byte3(f,"lda",o,CHAR);
+    emit(f,"\ttay\n");
+  }
+  emit(f,"\tldx\t#%d\n",bankvoffset);
+  emit(f,"\tlda\t#%d\n",cbank>=0?cbank:bankcnum);
+  emit(f,"\tjsr\t%s__bankload%d\n",idprefix,(int)zm2l(sizetab[t]));
+  yval=NOVAL;
+  o->flags=VAR;
+  o->v=&bankv;
+  o->val.vmax=l2zm((long)bankvoffset);
+  bankvoffset+=zm2l(sizetab[t]);
+  if(pushed){
+    if(regs[rax]) emit(f,"\tpla\n\ttax\n");
+    emit(f,"\tpla\n");
+  }
+}
+
+static void load_banked(FILE *f,IC *p,obj *o,int t)
+{
+  int pushed=0,m;
+  if(o->flags&DREFOBJ) t=o->dtyp;
+  t&=NQ;
+  if(zmeqto(sizetab[t],Z0)) return;
+  /*get_acc(f,p,INT);*/
+  if(pushedacc==t3||pushedacc==t4) ierror(0);
+  if(pushedx==t3||pushedx==t4) ierror(0);
+  if(regs[ra]||regs[rax]){
+    if(isacc(q1)||isacc(q2)||!isacc(z)){
+      pushed=1;
+      emit(f,"\tpha\n");
+      if(regs[rax]||regs[rx]) emit(f,"\ttxa\n\tpha\n");
+    }
+  }
+  m=o->flags;
+  o->flags&=~DREFOBJ;
+  load_address(f,LAST_PAIR,o,POINTER);
+  o->flags=m;
+  emit(f,"\tldx\t#%d\n",bankvoffset);
+  emit(f,"\tlda\t#%d\n",cbank>=0?cbank:bankcnum);
+  sety(f,bank(o->v));
+  emit(f,"\tjsr\t%s__bankload%d\n",idprefix,(int)zm2l(sizetab[t]));
+  yval=NOVAL;
+  o->v=&bankv;
+  o->val.vmax=l2zm((long)bankvoffset);
+  bankvoffset+=zm2l(sizetab[t]);
+  if(pushed){
+    if(regs[rax]||regs[rx]) emit(f,"\tpla\n\ttax\n");
+    emit(f,"\tpla\n");
+  }
+}
+
+static void preload(FILE *f,IC *p)
+{
+  int r,mra=regs[ra],mrax=regs[rax];
+  int bq1=-1,bq2=-1,bz=-1,sb=-1,zbuf=0;
+
+  if(((p->q1.flags&DREFOBJ)&&p->q1.am&&(p->q1.am->flags==GPR_IND||p->q1.am->flags==ABS_IND)&&p->q1.am->idx==ra)||
+     ((p->q2.flags&DREFOBJ)&&p->q2.am&&(p->q2.am->flags==GPR_IND||p->q2.am->flags==ABS_IND)&&p->q2.am->idx==ra)||
+     ((p->z.flags&DREFOBJ)&&p->z.am&&(p->z.am->flags==GPR_IND||p->z.am->flags==ABS_IND)&&p->z.am->idx==ra)
+     ){
+    if(pushedacc>0)
+      r=pushedacc;
+    else{
+      r=get_reg(f,p,CHAR);
+      emit(f,"\tsta\t%s\n",mregnames[r]);
+    }
+    pushedacc=r;
+    if((p->q1.flags&DREFOBJ)&&p->q1.am&&(p->q1.am->flags==GPR_IND||p->q1.am->flags==ABS_IND)&&p->q1.am->idx==ra)
+      p->q1.am->idx=r;
+    if((p->q2.flags&DREFOBJ)&&p->q2.am&&(p->q2.am->flags==GPR_IND||p->q2.am->flags==ABS_IND)&&p->q2.am->idx==ra)
+      p->q2.am->idx=r;
+    if((p->z.flags&DREFOBJ)&&p->z.am&&(p->z.am->flags==GPR_IND||p->z.am->flags==ABS_IND)&&p->z.am->idx==ra)
+      p->z.am->idx=r;
+  }
+
+  if(p->code==GETRETURN&&p->q1.reg==ra&&!regs[ra])
+    regs[ra]=1;
+
+  if(p->code==GETRETURN&&p->q1.reg==rax&&!regs[rax])
+    regs[rax]=1;
+
+  bankvoffset=0;
+
+  if(!NOBANKVARS){
+    if((p->q1.flags&(VAR|VARADR))==VAR) bq1=bank(p->q1.v);
+    if((p->q2.flags&(VAR|VARADR))==VAR) bq2=bank(p->q2.v);
+    if((p->z.flags&(VAR|VARADR))==VAR) bz=bank(p->z.v);
+
+    if((p->q1.flags&(VAR|VARADR))==(VAR|VARADR)){
+      r=bank(p->q1.v);
+      /*if(r>=0&&r!=cbank) ierror(0);*/
+    }
+    
+    if((p->code==ASSIGN||p->code==PUSH)&&!zmleq(p->q2.val.vmax,l2zm(4L))){
+      if(p->q1.flags&DREFOBJ) preload_obj(f,p,&p->q1);
+      if(p->z.flags&DREFOBJ) preload_obj(f,p,&p->z);
+      return;
+    }
+
+    if(p->code!=CALL){
+      /* TODO: some optimizations possible */
+      if(bq1>=0&&bq1!=cbank){
+	if(cbank<0&&!NOSWITCH)
+	  sb=bq1;
+	else
+	  load_banked(f,p,&p->q1,q1typ(p));
+      }
+      if(bq2>=0&&bq2!=cbank){
+	if((bq2==sb||(cbank<0&&sb<0))&&!NOSWITCH)
+	  sb=bq2;
+	else
+	  load_banked(f,p,&p->q2,q2typ(p));
+      }
+      if(bz>=0&&bz!=cbank&&(p->z.flags&DREFOBJ)){
+	if((bz==sb||(cbank<0&&sb<0))||!NOSWITCH)
+	  sb=bz;
+	else
+	  load_banked(f,p,&p->z,ztyp(p));
+      }
+      
+      if(sb>=0){
+	if(NOSWITCH) ierror(0);
+	sety(f,sb);
+	emit(f,"\tjsr\t%s__bankswitch\n",idprefix);
+	yval=NOVAL;
+      }
+    }
+  }
+
+  if((p->q1.flags&DREFOBJ)&&ISFPOINTER(p->q1.dtyp)&&p->code!=CALL) load_far(f,p,&p->q1,q1typ(p));
+  if((p->q2.flags&DREFOBJ)&&ISFPOINTER(p->q2.dtyp)) load_far(f,p,&p->q2,q2typ(p));
+
+  if(isacc(q2)){
+    static obj o;
+    int t=q2typ(p);
+    r=get_reg(f,p,t);
+    o.flags=REG;
+    o.reg=r;
+    store_acc(f,&o,t);
+    p->q2.reg=r;
+    if(!pushedacc){
+      if((t&NQ)==CHAR)
+	storedacc=r;
+      else{
+	if(!reg_pair(r,&rp)) ierror(0);
+	storedacc=rp.r1;
+	storedx=rp.r2;
+      }
+    }
+  }
+
+  if((p->code==ADDI2P||p->code==SUBIFP)&&ISRIDX(q2)){
+    static obj o;
+    if(p->q2.reg==rx){
+      if(pushedx>0) r=pushedx;
+      else if(storedx>0) r=storedx;
+      else r=get_reg(f,p,CHAR);
+    }else
+      r=get_reg(f,p,CHAR);
+    o.flags=REG;
+    o.reg=r;
+    store_reg(f,p->q2.reg,&o,CHAR);
+    p->q2.reg=r;
+    storedx=r;
+  }
+
+  if(p->code!=ADDRESS){
+    preload_obj(f,p,&p->q1);
+    if((p->q1.flags&(DREFOBJ|VAR|REG))==(DREFOBJ|VAR|REG)&&
+       (p->q2.flags&(DREFOBJ|VAR|REG))==(DREFOBJ|VAR)&&
+       p->q1.v==p->q2.v){
+      p->q2.flags|=REG;
+      p->q2.reg=p->q1.reg;
+    }
+    if((p->q1.flags&(DREFOBJ|VAR|REG))==(DREFOBJ|VAR|REG)&&
+       (p->z.flags&(DREFOBJ|VAR|REG))==(DREFOBJ|VAR)&&
+       p->q1.v==p->z.v){
+      p->z.flags|=REG;
+      p->z.reg=p->q1.reg;
+    }
+  }
+
+  preload_obj(f,p,&p->q2);
+  if((p->q2.flags&(DREFOBJ|VAR|REG))==(DREFOBJ|VAR|REG)&&
+     (p->z.flags&(DREFOBJ|VAR|REG))==(DREFOBJ|VAR)&&
+     p->q2.v==p->z.v){
+    p->z.flags|=REG;
+    p->z.reg=p->q2.reg;
+  }
+
+
+  if((p->z.flags&DREFOBJ)&&ISFPOINTER(p->z.dtyp)) zbuf=1;
+  if((p->z.flags&(VAR|DREFOBJ))==VAR){
+    bz=bank(p->z.v);
+    if(bz>=0&&bz!=cbank) zbuf=1;
+  }
+  
+  if(zbuf&&!NOBANKVARS){
+    zstore=p->z;
+    p->z.flags=VAR;
+    p->z.v=&bankv;
+    p->z.val.vmax=l2zm((long)bankvoffset);
+    zstoreflag=1;
+    /*bankvoffset+=zm2l(sizetab[p->typf&NQ]);*/
+  }else{
+    preload_obj(f,p,&p->z);
+
+    if(isreg(z)){
+      r=0;
+      if(p->q1.am&&p->q1.am->base==p->z.reg){
+	r=get_reg(f,p,POINTER);
+	cmp_get_acc(f,p,0);
+	if(!reg_pair(p->q1.am->base,&rp)) ierror(0);
+	if(!reg_pair(r,&rp2)) ierror(0);
+	emit(f,"\tlda\t%s\n",mregnames[rp.r1]);
+	emit(f,"\tsta\t%s\n",mregnames[rp2.r1]);
+	emit(f,"\tlda\t%s\n",mregnames[rp.r2]);
+	emit(f,"\tsta\t%s\n",mregnames[rp2.r2]);
+	p->q1.am->base=p->q1.reg=r;
+      }else if(!p->q1.am&&(p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p->q1.reg==p->z.reg){
+	r=get_reg(f,p,POINTER);
+	cmp_get_acc(f,p,0);
+	if(!reg_pair(p->z.reg,&rp)) ierror(0);
+	if(!reg_pair(r,&rp2)) ierror(0);
+	emit(f,"\tlda\t%s\n",mregnames[rp.r1]);
+	emit(f,"\tsta\t%s\n",mregnames[rp2.r1]);
+	emit(f,"\tlda\t%s\n",mregnames[rp.r2]);
+	emit(f,"\tsta\t%s\n",mregnames[rp2.r2]);
+	p->q1.reg=r;
+      }
+      if(p->q2.am&&p->q2.am->base==p->z.reg){
+	if(r==0){
+	  r=get_reg(f,p,POINTER);
+	  cmp_get_acc(f,p,0);
+	  if(!reg_pair(p->q2.am->base,&rp)) ierror(0);
+	  if(!reg_pair(r,&rp2)) ierror(0);
+	  emit(f,"\tlda\t%s\n",mregnames[rp.r1]);
+	  emit(f,"\tsta\t%s\n",mregnames[rp2.r1]);
+	  emit(f,"\tlda\t%s\n",mregnames[rp.r2]);
+	  emit(f,"\tsta\t%s\n",mregnames[rp2.r2]);
+	}
+	p->q2.am->base=p->q2.reg=r;
+      }else if(!p->q2.am&&(p->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p->q2.reg==p->z.reg){
+	if(r==0){
+	  r=get_reg(f,p,POINTER);
+	  cmp_get_acc(f,p,0);
+	  if(!reg_pair(p->z.reg,&rp)) ierror(0);
+	  if(!reg_pair(r,&rp2)) ierror(0);
+	  emit(f,"\tlda\t%s\n",mregnames[rp.r1]);
+	  emit(f,"\tsta\t%s\n",mregnames[rp2.r1]);
+	  emit(f,"\tlda\t%s\n",mregnames[rp.r2]);
+	  emit(f,"\tsta\t%s\n",mregnames[rp2.r2]);
+	}
+	p->q2.reg=r;
+      }
+    }
+    if(isacc(z)){
+      if(isacc(q2)){
+	if(p->q2.reg==rax){
+	  r=get_reg(f,p,INT);
+	  if(!reg_pair(r,&rp)) ierror(0);
+	  emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
+	  emit(f,"\tstx\t%s\n",mregnames[rp.r2]);
+	  storedacc=rp.r1;
+	  storedx=rp.r2;
+	}else{
+	  r=get_reg(f,p,CHAR);
+	  emit(f,"\tsta\t%s\n",mregnames[r]);
+	  storedacc=r;
+	}
+	p->q2.reg=r;
+	if(isacc(q1))
+	  p->q1.reg=r;
+      }
+    }
+  }     
+ 
+  reload_acc(f);
+
+  regs[ra]=mra;
+  regs[rax]=mrax;
+}
+
+
+/* compare if two objects are the same */
+static int compare_objects(struct obj *o1,struct obj *o2)
+{
+  if((o1->flags&(REG|DREFOBJ))==REG&&(o2->flags&(REG|DREFOBJ))==REG&&o1->reg==o2->reg)
+    return 1;
+  if(o1->flags==o2->flags){
+    if(o1->am){
+      if(o2->am){
+	if(o1->am->flags!=o2->am->flags||o1->am->base!=o2->am->base||
+	   o1->am->idx!=o2->am->idx||o1->am->offset!=o2->am->offset)
+	  return 0;
+	else
+	  return 1;
+      }else
+	return 0;
+    }else if(o2->am)
+      return 0;
+    if(!(o1->flags&VAR)||(o1->v==o2->v&&zmeqto(o1->val.vmax,o2->val.vmax))){
+      if(!(o1->flags&REG)||o1->reg==o2->reg){
+        return 1;
+      }
+    }
+  }
+  return 0;
+}
+
+/* save the result (in zreg) into p->z */
+void save_result(FILE *f,struct IC *p)
+{
+  ierror(0);
+}
+
+/* prints an object */
+static void emit_obj(FILE *f,struct obj *p,int t)
+{
+  if(p->am){
+    if(p->am->flags==IMM_IND)
+      emit(f,"(%s),y ;am(%ld)",mregnames[p->am->base],p->am->offset);
+    else if(p->am->flags==GPR_IND)
+      emit(f,"(%s),y ;am(%s)",mregnames[p->am->base],mregnames[p->am->idx]);
+    else if(p->am->flags==ABS_IND){
+      emit(f,"%ld",p->am->offset);
+      if(p->am->v){
+	Var *v=p->am->v;
+	if(v->storage_class==EXTERN)
+	  emit(f,"+%s%s",idprefix,v->identifier);
+	else
+	  emit(f,"+%s%ld",labprefix,zm2l(v->offset));
+      }
+      if(ISIDX(p->am->idx))
+	emit(f,",%s ;am(%s)",mregnames[p->am->idx],mregnames[p->am->idx]);
+      else
+	emit(f,",y ;am(%s)",mregnames[p->am->idx]);
+    }else
+      ierror(0);
+    return;
+  }
+  if((p->flags&(KONST|DREFOBJ))==(KONST|DREFOBJ)){
+    emitval(f,&p->val,p->dtyp&NU);
+    return;
+  }
+  if(p->flags&DREFOBJ) emit(f,"(");
+  if(p->flags&REG){
+    emit(f,"%s",mregnames[p->reg]);
+  }else if(p->flags&VAR) {
+    if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER)
+      emit(f,"(%s),%s",mregnames[fp],noy==2?"z":"y");
+    else{
+      if(!zmeqto(l2zm(0L),p->val.vmax)){emitval(f,&p->val,MAXINT);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(p->flags&KONST){
+    if(/*ieee&&((t&NQ)==DOUBLE||(t&NQ)==LDOUBLE)*/ISFLOAT(t))
+      emit(f,"%s%d",labprefix,addfpconst(p,t));
+    else
+      emitval(f,&p->val,t&NU);
+  }
+  if(p->flags&DREFOBJ) emit(f,")%s",noy==0?",y":(noy==1?"":",z"));
+}
+
+/*  Test if there is a sequence of FREEREGs containing FREEREG reg.
+    Used by peephole. */
+static int exists_freereg(struct IC *p,int reg)
+{
+  while(p&&(p->code==FREEREG||p->code==ALLOCREG)){
+    if(p->code==FREEREG&&p->q1.reg==reg) return 1;
+    p=p->next;
+  }
+  return 0;
+}
+
+/* search for possible addressing-modes */
+static void peephole(struct IC *p)
+{
+  int c,c2,r;struct IC *p2,*free_base,*use;struct AddressingMode *am;
+
+  for(;p;p=p->next){
+    c=p->code;
+    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;
+
+    /* Try const(reg) */
+    if((c==ADDI2P||c==SUBIFP)&&ISPREG(z)&&(p->q2.flags&(KONST|DREFOBJ))==KONST&&!ISFPOINTER(p->typf2)){
+      int base;zmax of;struct obj *o;IC *dub=0;
+      eval_const(&p->q2.val,p->typf);
+      if(c==SUBIFP) of=zmsub(l2zm(0L),vmax); else of=vmax;
+      if(zmleq(Z0,of)&&zmleq(of,l2zm(255L))){
+	r=p->z.reg;
+	if(isreg(q1)&&isptr(p->q1.reg)) base=p->q1.reg; else base=r;
+	o=0;free_base=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.reg==p->z.reg) free_base=p2;
+	  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*/){
+	    int t,mc;
+	    if((c2==ASSIGN|c2==PUSH)&&(p2->typf&NQ)==CHAR&&!zmeqto(p2->q2.val.vmax,Z1))
+	      mc=1;
+	    else
+	      mc=0;
+	    if(!o&&(c2==ADD||c2==SUB||c2==AND||c2==OR||c2==XOR)&&/*(p2->typf&NQ)==CHAR&&*/!p2->q1.am&&!p2->z.am&&
+	       (p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&
+	       p2->q1.flags==p2->z.flags&&p2->q1.reg==r&&p2->z.reg==r){
+	      o=&p2->q1;use=p2;
+	      dub=p2;
+	      continue;
+	    }
+	    if(!p2->q1.am&&(p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r){
+	      if(o||mc) break;
+	      t=q1typ(p2)&NQ;
+	      if(t>POINTER||ISFLOAT(t)) break;
+	      if(m65&&ISLONG(t)) break;
+	      o=&p2->q1;use=p2;
+	    }
+	    if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
+	      if(o||mc) break;
+	      t=q2typ(p2)&NQ;
+	      if(t>POINTER||ISFLOAT(t)) break;
+	      if(m65&&ISLONG(t)) break;
+	      o=&p2->q2;use=p2;
+	    }
+	    if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
+	      if(o||mc) break;
+	      t=ztyp(p2)&NQ;
+	      if(t>POINTER||ISFLOAT(t)) break;
+	      if(m65&&ISLONG(t)) break;
+	      o=&p2->z;use=p2;
+	    }
+	  }
+	  if(c2==FREEREG||(p2->z.flags&(REG|DREFOBJ))==REG){
+	    int m;
+	    if(c2==FREEREG)
+	      m=p2->q1.reg;
+	    else{
+	      m=p2->z.reg;
+	      if(o==&p->q1||o==&p->q2) break;
+	    }
+	    if(m==r){
+	      if(o){
+		o->am=am=mymalloc(sizeof(*am));
+		am->flags=IMM_IND;
+		am->base=base;
+		am->offset=(int)zm2l(of);
+		if(ISPREG(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];
+		}
+	      }
+	      if(dub){
+		dub->z=*o;
+		dub->z.am=mymalloc(sizeof(*am));
+		*dub->z.am=*o->am;
+	      }
+	      if(free_base) move_IC(use,free_base);
+	      break;
+	    }
+	    if(c2!=FREEREG&&m==base) break;
+	    continue;
+	  }
+        }
+      }
+    }
+    /* Try reg,reg */
+    if(c==ADDI2P&&(p->typf&NU)==(UNSIGNED|CHAR)&&!ISFPOINTER(p->typf2)&&isreg(q2)/*&&p->q2.reg!=ra*/&&ISPREG(z)&&(ISPREG(q1)||p->q2.reg!=p->z.reg)){
+      int base,idx,ind;struct obj *o;IC *free_idx,*dub=0;
+      r=p->z.reg;idx=p->q2.reg;
+      if(ISPREG(q1)) base=p->q1.reg; else base=r;
+      if((p->q1.flags&VARADR)||(p->q1.flags&(KONST|DREFOBJ))==KONST)
+	ind=0;
+      else
+	ind=1;
+      o=0;free_base=free_idx=use=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.reg==p->z.reg) free_base=p2;
+	if(c2==FREEREG&&p2->q1.reg==p->q2.reg) free_idx=p2;
+        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&&idx!=r){
+	  if(p2->z.reg==idx) break;
+	  if(reg_pair(p2->z.reg,&rp)){
+	    if(rp.r1==idx) break;
+	    if(rp.r2==idx) break;
+	  }
+	}
+
+        if(c2!=CALL&&(c2<LABEL||c2>BRA)/*&&c2!=ADDRESS*/){
+	  if(!o&&(c2==ADD||c2==SUB||c2==AND||c2==OR||c2==XOR)&&/*(p2->typf&NQ)==CHAR&&*/!p2->q1.am&&!p2->z.am&&
+	     (p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&
+	     p2->q1.flags==p2->z.flags&&p2->q1.reg==r&&p2->z.reg==r){
+	    o=&p2->q1;use=p2;
+	    dub=p2;
+	    continue;
+	  }
+          if(!p2->q1.am&&(p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r){
+            if(o||(ind&&(q1typ(p2)&NQ)!=CHAR)) break;
+	    if(ieee&&ISFLOAT(q1typ(p2))) break;
+            o=&p2->q1;use=p2;
+          }
+          if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
+            if(o||(ind&&(q2typ(p2)&NQ)!=CHAR)) break;
+	    if(ieee&&ISFLOAT(q2typ(p2))) break;
+            o=&p2->q2;use=p2;
+          }
+          if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
+            if(o||(ind&&(ztyp(p2)&NQ)!=CHAR)) break;
+	    if(ieee&&ISFLOAT(ztyp(p2))) break;
+            o=&p2->z;use=p2;
+          }
+        }
+	
+        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->idx=idx;
+	      if(ind){
+		am->flags=GPR_IND;
+		am->base=base;
+		if(ISPREG(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];
+		}
+	      }else{
+		am->flags=ABS_IND;
+		am->base=0;
+		eval_const(&p->q1.val,MAXINT);
+		am->offset=zm2l(vmax);
+		if(p->q1.flags&VARADR)
+		  am->v=p->q1.v;
+		else
+		  am->v=0;
+		p->code=c=NOP;p->q1.flags=p->q2.flags=p->z.flags=0;
+	      }
+	      if(dub){
+		dub->z=*o;
+		dub->z.am=mymalloc(sizeof(*am));
+		*dub->z.am=*o->am;
+	      }
+	      if(free_idx) move_IC(use,free_idx);
+	      if(free_base) move_IC(use,free_base);
+            }
+            break;
+          }
+          if(c2!=FREEREG&&m==base) break;
+          continue;
+        }
+      }
+    }
+  }
+}
+
+static void pr(FILE *f,struct IC *p)
+{
+  int r;
+
+  if(zstoreflag){
+    int off;
+    if(p->z.flags!=VAR||p->z.v!=&bankv) ierror(0);
+    off=(int)zm2l(p->z.val.vmax);
+    p->z=zstore;
+    get_acc(f,p,INT);
+    if(zstore.flags&DREFOBJ){
+      if(!ISFPOINTER(zstore.dtyp)) ierror(0);
+      zstore.flags&=~DREFOBJ;
+      load_reg(f,LAST_PAIR,&zstore,POINTER);
+      if(indirect(&zstore)){
+	do_byte3(f,"lda",&zstore,FPOINTER);
+	emit(f,"\ttay\n");
+      }else
+	do_byte3(f,"ldy",&zstore,FPOINTER);
+      yval=NOVAL;
+    }else{
+      load_address(f,LAST_PAIR,&zstore,p->typf);
+      r=bank(zstore.v);
+      sety(f,r>=0?r:bankcnum);
+    }
+    emit(f,"\tldx\t#%d\n",off);
+    emit(f,"\tlda\t#%d\n",cbank>=0?cbank:bankcnum);
+    emit(f,"\tjsr\t%s__bankstore%d\n",idprefix,(int)zm2l(sizetab[p->typf&NQ]));
+    yval=NOVAL;
+    zstoreflag=0;
+  }
+
+  for(r=1;r<=MAXR;r++){
+    if(regs[r]&8)
+      regs[r]&=~8;
+  }
+  for(r=FIRST_GPR;r<=LAST_GPR;r++){
+    int ta=0;
+    if(regs[r]&2){
+      if(regs[ra]&&!pushedacc){
+	emit(f,"\ttay\n");
+	yval=NOVAL;
+	ta=1;
+      }
+      emit(f,"\tpla\n");
+      emit(f,"\tsta\t%s\n",mregnames[r]);
+      regs[r]&=~2;
+    }
+    if(ta)
+      emit(f,"\ttya\n");
+  }
+  if(pushedx){
+    emit(f,"\tldx\t%s\n",mregnames[pushedx]);
+    pushedx=0;
+  }
+
+  reload_acc_opt(f,p->next);
+
+  storedacc=0;
+  storedx=0;
+}
+
+struct cmplist {struct cmplist *next;int from,to,mode;} *first_cmplist;
+
+static void add_cmplist(int from, int to, int mode)
+{
+  struct cmplist *new;
+  new=mymalloc(sizeof(*new));
+  new->next=first_cmplist;
+  new->from=from;
+  new->to=to;
+  new->mode=mode;
+  first_cmplist=new;
+}
+
+static void incsp(FILE *f,long of)
+{
+  if(of==0) return;
+  if(of==1||of==-1){
+    static obj o;
+    o.flags=REG;
+    o.reg=sp;
+    if(of==1)
+      incmem(f,&o,INT,ADD,1);
+    else
+      incmem(f,&o,INT,SUB,1);
+  }else if(of==256){
+    emit(f,"\tinc\t%s+1\n",mregnames[sp]);
+  }else if(of==-256){
+    emit(f,"\tdec\t%s+1\n",mregnames[sp]);
+  }else{
+    long abs;
+    if(of>0){
+      abs=of;
+      emit(f,"\tclc\n");
+    }else{
+      abs=-of;
+      emit(f,"\tsec\n");
+    }
+    if(abs&255){
+      emit(f,"\tlda\t%s\n",mregnames[sp]);
+      if(of>0){
+	emit(f,"\tadc\t#%ld\n",abs&255);
+      }else{
+	emit(f,"\tsbc\t#%ld\n",abs&255);
+      }
+      emit(f,"\tsta\t%s\n",mregnames[sp]);
+    }
+    if((abs&0xff00)==0){
+      if(of>0){
+	emit(f,"\tbcc\t%s%d\n",labprefix,++label);
+	emit(f,"\tinc\t%s+1\n",mregnames[sp]);
+	emit(f,"%s%d:\n",labprefix,label);
+      }else{
+	emit(f,"\tbcs\t%s%d\n",labprefix,++label);
+	emit(f,"\tdec\t%s+1\n",mregnames[sp]);
+	emit(f,"%s%d:\n",labprefix,label);
+      }	
+    }else{
+      emit(f,"\tlda\t%s+1\n",mregnames[sp]);
+      if(of>0)
+	emit(f,"\tadc\t#%ld\n",(abs>>8)&255);
+      else
+	emit(f,"\tsbc\t#%ld\n",(abs>>8)&255);
+      emit(f,"\tsta\t%s+1\n",mregnames[sp]);
+    }
+  }
+}
+
+/* generates the function entry code */
+static void function_top(FILE *f,struct Var *v,long offset)
+{
+  int i,r,of;
+  rsavesize=0;
+  libsave=1;
+  hasretval=0;
+
+  if(!optsize||(v->tattr&NOCOMPRESS)) emit(f,";vcprmin=10000\n");
+  if(vlas) emit(f,"___fo\tset\t%ld\n",(long)argsize);
+  r=0;
+  for(i=FIRST_GPR;i<=LAST_GPR;i++){
+    if((regused[i]&&(in_isr||!regscratch[i]))||(in_isr&&function_calls&&regscratch[i]&&!regsa[i])){
+      if(i!=LAST_GPR-VOL_GPRS+1&&r==0) libsave=0;
+      rsavesize++;
+      r=1;
+    }else{
+      if(i==LAST_GPR-VOL_GPRS+1) libsave=0;
+      r=0;
+    }
+  }
+  rscnt=rsavesize;
+  if(rscnt&&!SOFTSTACK){
+    if(optspeed||rscnt<2)
+      rsavesize=0;
+    else if(!optsize&&rscnt<=5)
+      rsavesize=0;
+  }
+
+  if(!special_section(f,v)){emit(f,codename);ebank(f,sbank(v));if(f) section=CODE;} 
+  if(v->storage_class==EXTERN){
+    if((v->flags&(INLINEFUNC|INLINEEXT))!=INLINEFUNC)
+      emit(f,"\tglobal\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));
+
+  offset=localsize+argsize+rsavesize;
+
+  if(in_isr){
+    emit(f,"\tpha\n");
+    if(c02){
+      emit(f,"\tphx\n");
+      emit(f,"\tphy\n");
+    }else{
+      emit(f,"\ttxa\n");
+      emit(f,"\tpha\n");
+      emit(f,"\ttya\n");
+      emit(f,"\tpha\n");
+    }
+    if(offset||function_calls){
+      emit(f,"\tlda\t%s\n",mregnames[sp]);
+      emit(f,"\tpha\n");
+      emit(f,"\tlda\t%s+1\n",mregnames[sp]);
+      emit(f,"\tpha\n");
+      emit(f,"\tlda\t#<(___isrstack-%ld)\n",offset);
+      emit(f,"\tsta\t%s\n",mregnames[sp]);
+      emit(f,"\tlda\t#>(___isrstack-%ld)\n",offset);
+      emit(f,"\tsta\t%s+1\n",mregnames[sp]);
+    }
+  }
+
+  if(MAINARGS&&v->storage_class==EXTERN&&!strcmp(v->identifier,"main")&&v->vtyp->exact->count>1)
+    emit(f,"\tjsr\tinitmainargs\n");
+
+  yval=NOVAL;
+  of=argsize+localsize;
+
+  if(rsavesize>0&&of+rsavesize>255){
+    offset-=rsavesize;
+    incsp(f,-rsavesize);
+    of=0;
+  }else{
+    incsp(f,-offset);
+    offset=0;
+  }
+
+
+  if(!libsave||rscnt!=rsavesize||optspeed||rscnt<=1||(rscnt<=3&&(!optsize)))
+    libsave=0;
+  
+  if(libsave){
+    sety(f,of+rsavesize-1);
+    if(0/*mask_opt*/)
+      emit(f,"\tjsr\t%s__rsave.%d+%ld\n",idprefix,(1<<(rscnt-2)),(rscnt-2)*5);
+    else
+      emit(f,"\tjsr\t%s__rsave%ld\n",idprefix,rscnt);
+    yval=of;
+  }else{
+    int last=0;
+    for(i=FIRST_GPR;i<=LAST_GPR;i++){
+      if((regused[i]&&(in_isr||!regscratch[i]))||(in_isr&&function_calls&&regscratch[i]&&!regsa[i])){
+	if(rscnt!=rsavesize){
+	  if(ce02&&last==i-1){
+	    emit(f,"\tphw\t%s\n",mregnames[last]);
+	    last=0;
+	  }else{
+	    if(!ce02){
+	      emit(f,"\tlda\t%s\n",mregnames[i]);
+	      emit(f,"\tpha\n");
+	    }else
+	      last=i;
+	  }
+	}else{
+	  sety(f,of++);
+	  emit(f,"\tlda\t%s\n",mregnames[i]);
+	  emit(f,"\tsta\t(%s),y\n",mregnames[sp]);
+	}
+      }
+    }
+    if(last){
+      emit(f,"\tlda\t%s\n",mregnames[last]);
+      emit(f,"\tpha\n");
+    }
+  }
+
+
+
+  incsp(f,-offset);
+
+  if(vlas){
+    emit(f,"\tlda\t%s\n",mregnames[sp]);
+    emit(f,"\tsta\t%s\n",mregnames[fp]);
+    emit(f,"\tlda\t%s\n",mregnames[sp2]);
+    emit(f,"\tsta\t%s\n",mregnames[fp2]);
+  }
+}
+
+/* generates the function exit code */
+static void function_bottom(FILE *f,struct Var *v,long offset)
+{
+  int i,of,ar;
+  struct cmplist *p;
+  offset=localsize+argsize+rsavesize;
+  of=argsize+localsize;
+
+  i=freturn(v->vtyp->next);
+  if(hasretval&&(i==ra||i==rax)) ar=1; else ar=0;
+
+  if(rscnt!=rsavesize){
+    if(ar&&!pushedacc){
+      pushedacc=t4;
+      emit(f,"\tsta\t%s\n",mregnames[pushedacc]);
+    }
+    for(i=LAST_GPR;i>=FIRST_GPR;i--){
+      if((regused[i]&&(in_isr||!regscratch[i]))||(in_isr&&function_calls&&regscratch[i]&&!regsa[i])){
+	emit(f,"\tpla\n");
+	emit(f,"\tsta\t%s\n",mregnames[i]);
+      }
+    }
+  }
+  if(rsavesize>0&&of+rsavesize>255){
+    if(of!=1&&ar&&!pushedacc){
+      pushedacc=t4;
+      emit(f,"\tsta\t%s\n",mregnames[pushedacc]);
+    }
+    incsp(f,of);
+    offset-=of;
+    of=0;
+  }
+  if(rsavesize>0){
+    if(ar&&!pushedacc){
+      pushedacc=t4;
+      emit(f,"\tsta\t%s\n",mregnames[pushedacc]);
+    }
+  }
+  if(rsavesize){
+    if(libsave){
+      sety(f,of+rsavesize-1);
+      if(0/*mask_opt*/)
+	emit(f,"\tjsr\t%s__rload.%d+%ld\n",idprefix,(1<<(rscnt-2)),(rscnt-2)*5);
+      else
+	emit(f,"\tjsr\t%s__rload%ld\n",idprefix,rscnt);
+      yval=of;
+    }else{
+      for(i=FIRST_GPR;i<=LAST_GPR;i++){
+	if((regused[i]&&(in_isr||!regscratch[i]))||(in_isr&&function_calls&&regscratch[i]&&!regsa[i])){
+	  sety(f,of++);
+	  emit(f,"\tlda\t(%s),y\n",mregnames[sp]);
+	  emit(f,"\tsta\t%s\n",mregnames[i]);
+	}
+      }
+    }
+  }
+  if(in_isr){
+    if(offset||function_calls){
+      emit(f,"\tpla\n");
+      emit(f,"\tsta\t%s+1\n",mregnames[sp]);
+      emit(f,"\tpla\n");
+      emit(f,"\tsta\t%s\n",mregnames[sp]);
+    }
+  }else if(offset==2&&!pushedacc){
+    emit(f,"\tinc\t%s\n",mregnames[sp]);
+    emit(f,"\tbeq\t%s%d\n",labprefix,++label);
+    emit(f,"\tinc\t%s\n",mregnames[sp]);
+    emit(f,"\tbeq\t%s%d\n",labprefix,++label);
+    reload_acc(f);
+    emit(f,ret);
+    emit(f,"%s%d:\n",labprefix,label-1);
+    emit(f,"\tinc\t%s\n",mregnames[sp]);
+    emit(f,"%s%d:\n",labprefix,label);
+    emit(f,"\tinc\t%s+1\n",mregnames[sp]);
+  }else{
+    if(offset!=0&&ar&&!pushedacc){
+      pushedacc=t4;
+      emit(f,"\tsta\t%s\n",mregnames[pushedacc]);
+    }
+    incsp(f,offset);
+  }
+
+  reload_acc(f);
+
+  if(in_isr){
+    if(c02){
+      emit(f,"\tply\n");
+      emit(f,"\tplx\n");
+    }else{
+      emit(f,"\tpla\n");
+      emit(f,"\ttay\n");
+      emit(f,"\tpla\n");
+      emit(f,"\ttax\n");
+    }
+    emit(f,"\tpla\n");
+  }
+  emit(f,ret);
+
+  for(p=first_cmplist;p;){
+    struct cmplist *m;
+    emit(f,"%s%d:\n",labprefix,p->from);
+    if(p->mode==JMPIND){
+      /* indirect call */
+      emit(f,"\tjmp\t(%s)\n",mregnames[p->to]);
+    }else{
+      pushedacc=p->mode;
+      reload_acc(f);
+      emit(f,"\t%s\t%s%d\n",jmpinst,labprefix,p->to);
+    }
+    m=p;
+    p=p->next;
+    free(m);
+  }
+  first_cmplist=0;
+  pushedacc=0;
+}
+
+/****************************************/
+/*  End of private data and functions.  */
+/****************************************/
+
+/*  Does necessary initializations for the code-generator. Gets called  */
+/*  once at the beginning and should return 0 in case of problems.      */
+int init_cg(void)
+{
+  int i;
+  /*  Initialize some values which cannot be statically initialized   */
+  /*  because they are stored in the target's arithmetic.             */
+  maxalign=l2zm(1L);
+  char_bit=l2zm(8L);
+  stackalign=l2zm(1);
+
+  if(IEEE){
+    ieee=1;
+    msizetab[DOUBLE]=msizetab[LDOUBLE]=l2zm(8L);
+  }
+
+
+  mregnames[0]=regnames[0]="noreg";
+  mregnames[REGDUMMY1]=mymalloc(MAXI+8);
+  mregnames[REGDUMMY2]=mymalloc(MAXI+8);
+  mregnames[REGDUMMY3]=mymalloc(MAXI+8);
+
+  for(i=FIRST_GPR;i<=LAST_GPR;i++){
+    regnames[i]=mymalloc(10);
+    sprintf(regnames[i],"r%d",i-FIRST_GPR);
+    mregnames[i]=regnames[i];
+    regsize[i]=l2zm(1L);
+    regtype[i]=&ctyp;
+  }
+  for(i=FIRST_PAIR;i<=LAST_PAIR;i++){
+    int sr=(i-FIRST_PAIR)*2+FIRST_GPR;
+    regnames[i]=mymalloc(10);
+    sprintf(regnames[i],"%s/%s",mregnames[sr],mregnames[sr+1]);
+    mregnames[i]=regnames[sr];
+    regsize[i]=l2zm(2L);
+    regtype[i]=&ityp;
+  }
+  for(i=FIRST_BIG;i<=LAST_BIG;i++){
+    regnames[i]=mymalloc(10);
+    sprintf(regnames[i],"btmp%d",i-FIRST_BIG);
+    mregnames[i]=regnames[i];
+    regsize[i]=msizetab[FLOAT];
+    regtype[i]=&ftyp;
+    regsa[i]=0;
+    regscratch[i]=1;
+  }
+  for(i=FIRST_BIGP;i<=LAST_BIGP;i++){
+    int sr=(i-FIRST_BIGP)*2+FIRST_BIG;
+    regnames[i]=mymalloc(20);
+    sprintf(regnames[i],"%s/%s",mregnames[sr],mregnames[sr+1]);
+    mregnames[i]=regnames[sr];
+    regsize[i]=msizetab[LLONG];
+    regtype[i]=&lltyp;
+    regsa[i]=0;
+    regscratch[i]=1;
+  }
+
+  mregnames[ra] = regnames[ra] = "a";
+  mregnames[rx] = regnames[rx] = "x";
+  mregnames[ry] = regnames[ry] = "y";
+  regsize[ra]=regsize[rx]=regsize[ry]=l2zm(1L);
+  regtype[ra]=regtype[rx]=regtype[ry]=&ctyp;
+  mregnames[sp]=regnames[sp] = "sp";
+  mregnames[sp1]=regnames[sp1] = "sp";
+  mregnames[sp2]=regnames[sp2] = "sp+1";
+
+  mregnames[rax]=regnames[rax] = "a/x";
+  regsize[rax]=regsize[sp]=l2zm(2L);
+  regtype[rax]=regtype[sp]=&ityp;
+
+  reg_prio[ra]=reg_prio[rax]=100;
+  reg_prio[rx]=50;
+
+  /*  Use multiple ccs.   */
+  multiple_ccs=0;
+
+  short_push=1;
+
+  static_cse=0;
+
+  dref_cse=1;
+
+  /*prefer_statics=1; TODO */
+
+
+  if(optsize){
+    clist_copy_stack=2;
+    clist_copy_pointer=2;
+    clist_copy_static=2;
+  }else if(optspeed){
+    clist_copy_stack=64;
+    clist_copy_pointer=64;
+    clist_copy_static=64;
+  }else{
+    clist_copy_stack=8;
+    clist_copy_pointer=8;
+    clist_copy_static=8;
+  }
+
+  /*  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.          */
+  t_min[CHAR]=l2zm(-128L);
+  t_min[SHORT]=l2zm(-32768L);
+  t_min[LONG]=zmsub(l2zm(-2147483647L),l2zm(1L));
+  t_min[INT]=t_min(SHORT);
+  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[LONG]=ul2zum(2147483647UL);
+  t_max[INT]=t_max(SHORT);
+  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[LONG]=ul2zum(4294967295UL);
+  tu_max[INT]=t_max(UNSIGNED|SHORT);
+  tu_max[LLONG]=zumkompl(ul2zum(0UL));
+  tu_max[MAXINT]=t_max(UNSIGNED|LLONG);
+  
+  /*  Reserve a few registers for use by the code-generator.      */
+  /*  This is not optimal but simple.                             */
+  regsa[ry]=regsa[sp]=regsa[sp1]=regsa[sp2]=REGSA_NEVER;
+  regsa[t1]=regsa[t2]=regsa[t3]=regsa[t4]=REGSA_NEVER;
+  regscratch[ra]=regscratch[rx]=regscratch[rax]=1;
+  if(!GLOBACC)
+    regsa[ra]=regsa[rx]=regsa[rax]=REGSA_TEMPS;
+  regsa[rx]=0;
+  regscratch[sp]=regscratch[sp1]=regscratch[sp2]=regscratch[ry]=0;
+  regscratch[t1]=regscratch[t2]=regscratch[t3]=regscratch[t4]=1;
+
+  for(i=FIRST_GPR;i<=LAST_GPR-VOL_GPRS;i++){
+    regscratch[i]=1;
+    if(i&1)
+      regscratch[FIRST_PAIR+(i-FIRST_GPR)/2]=1;
+  }
+
+  target_macros=marray;
+
+  declare_builtin("__mulint8",CHAR,CHAR,FIRST_GPR,CHAR,FIRST_GPR+1,1,0);
+  declare_builtin("__mulint16",INT,INT,FIRST_PAIR,INT,FIRST_PAIR+1,1,0);
+  declare_builtin("__muluint16",UNSIGNED|INT,UNSIGNED|INT,FIRST_PAIR,UNSIGNED|INT,FIRST_PAIR+1,1,0);
+  declare_builtin("__divuint16",UNSIGNED|INT,UNSIGNED|INT,FIRST_PAIR,UNSIGNED|INT,FIRST_PAIR+1,1,0);
+  declare_builtin("__divint16",INT,INT,FIRST_PAIR,INT,FIRST_PAIR+1,1,0);
+  declare_builtin("__modint16",INT,INT,FIRST_PAIR,INT,FIRST_PAIR+1,1,0);
+  declare_builtin("__moduint16",UNSIGNED|INT,UNSIGNED|INT,FIRST_PAIR,UNSIGNED|INT,FIRST_PAIR+1,1,0);
+  declare_builtin("__modint16wo",INT,INT,FIRST_PAIR,INT,FIRST_PAIR+1,1,0);
+  declare_builtin("__divuint16wo",UNSIGNED|INT,UNSIGNED|INT,FIRST_PAIR,UNSIGNED|INT,FIRST_PAIR+1,1,0);
+  declare_builtin("__divint16wo",INT,INT,FIRST_PAIR,INT,FIRST_PAIR+1,1,0);
+  declare_builtin("__moduint16wo",UNSIGNED|INT,UNSIGNED|INT,FIRST_PAIR,UNSIGNED|INT,FIRST_PAIR+1,1,0);
+  declare_builtin("__modint16wo",INT,INT,FIRST_PAIR,INT,FIRST_PAIR+1,1,0);
+
+  declare_builtin("__mulint32",LONG,LONG,FIRST_BIG+1,LONG,FIRST_BIG+2,1,0);
+  declare_builtin("__muluint32",UNSIGNED|LONG,UNSIGNED|LONG,FIRST_BIG+1,UNSIGNED|LONG,FIRST_BIG+2,1,0);
+  declare_builtin("__divint32",LONG,LONG,FIRST_BIG,LONG,FIRST_BIG+1,1,0);
+  declare_builtin("__divuint32",UNSIGNED|LONG,UNSIGNED|LONG,FIRST_BIG,UNSIGNED|LONG,FIRST_BIG+1,1,0);
+  declare_builtin("__modint32",LONG,LONG,FIRST_BIG,LONG,FIRST_BIG+1,1,0);
+  declare_builtin("__moduint32",UNSIGNED|LONG,UNSIGNED|LONG,FIRST_BIG,UNSIGNED|LONG,FIRST_BIG+1,1,0);
+  declare_builtin("__divint32wo",LONG,LONG,FIRST_BIG,LONG,FIRST_BIG+1,1,0);
+  declare_builtin("__divuint32wo",UNSIGNED|LONG,UNSIGNED|LONG,FIRST_BIG,UNSIGNED|LONG,FIRST_BIG+1,1,0);
+  declare_builtin("__modint32wo",LONG,LONG,FIRST_BIG,LONG,FIRST_BIG+1,1,0);
+  declare_builtin("__moduint32wo",UNSIGNED|LONG,UNSIGNED|LONG,FIRST_BIG,UNSIGNED|LONG,FIRST_BIG+1,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("__divint64",LLONG,LLONG,0,LLONG,0,1,0);
+  declare_builtin("__divuint64",UNSIGNED|LLONG,UNSIGNED|LLONG,0,UNSIGNED|LLONG,0,1,0);
+  declare_builtin("__modint64",LLONG,LLONG,0,LLONG,0,1,0);
+  declare_builtin("__moduint64",UNSIGNED|LLONG,UNSIGNED|LLONG,0,UNSIGNED|LLONG,0,1,0);
+  declare_builtin("__lsrint64",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("__sint32toflt32",FLOAT,LONG,OLDFP?0:FIRST_BIG,0,0,1,0);
+  declare_builtin("__uint32toflt32",FLOAT,UNSIGNED|LONG,OLDFP?0:FIRST_BIG,0,0,1,0);
+  declare_builtin("__flt32tosint32",LONG,FLOAT,OLDFP?0:FIRST_BIG,0,0,1,0);
+  declare_builtin("__flt32touint32",UNSIGNED|LONG,FLOAT,OLDFP?0:FIRST_BIG,0,0,1,0);
+  declare_builtin("__sint16toflt32",FLOAT,INT,FIRST_PAIR,0,0,1,0);
+  declare_builtin("__uint16toflt32",FLOAT,UNSIGNED|INT,FIRST_PAIR,0,0,1,0);
+  declare_builtin("__flt32tosint16",INT,FLOAT,OLDFP?0:FIRST_BIG,0,0,1,0);
+  declare_builtin("__flt32touint16",UNSIGNED|INT,FLOAT,OLDFP?0:FIRST_BIG,0,0,1,0);
+
+  declare_builtin("__sint32toflt64",DOUBLE,LONG,OLDFP?0:FIRST_BIG,0,0,1,0);
+  declare_builtin("__uint32toflt64",DOUBLE,UNSIGNED|LONG,OLDFP?0:FIRST_BIG,0,0,1,0);
+  declare_builtin("__flt64tosint32",LONG,DOUBLE,OLDFP?0:FIRST_BIGP,0,0,1,0);
+  declare_builtin("__flt64touint32",UNSIGNED|LONG,DOUBLE,OLDFP?0:FIRST_BIGP,0,0,1,0);
+  declare_builtin("__sint16toflt64",DOUBLE,INT,FIRST_PAIR,0,0,1,0);
+  declare_builtin("__uint16toflt64",DOUBLE,UNSIGNED|INT,FIRST_PAIR,0,0,1,0);
+  declare_builtin("__flt64tosint16",INT,DOUBLE,OLDFP?0:FIRST_BIGP,0,0,1,0);
+  declare_builtin("__flt64touint16",UNSIGNED|INT,DOUBLE,OLDFP?0:FIRST_BIGP,0,0,1,0);
+
+  declare_builtin("__flt64toflt32",FLOAT,DOUBLE,OLDFP?0:FIRST_BIGP,0,0,1,0);
+  declare_builtin("__flt32toflt64",DOUBLE,FLOAT,OLDFP?0:FIRST_BIG,0,0,1,0);
+
+  declare_builtin("__addflt32",FLOAT,FLOAT,OLDFP?0:FIRST_BIG+1,FLOAT,OLDFP?0:FIRST_BIG,1,0);
+  declare_builtin("__subflt32",FLOAT,FLOAT,OLDFP?0:FIRST_BIG+1,FLOAT,OLDFP?0:FIRST_BIG,1,0);
+  declare_builtin("__mulflt32",FLOAT,FLOAT,OLDFP?0:FIRST_BIG+1,FLOAT,OLDFP?0:FIRST_BIG,1,0);
+  declare_builtin("__divflt32",FLOAT,FLOAT,OLDFP?0:FIRST_BIG+1,FLOAT,OLDFP?0:FIRST_BIG,1,0);
+  declare_builtin("__negflt32",FLOAT,FLOAT,OLDFP?0:FIRST_BIG,0,0,1,0);
+  declare_builtin("__cmpsflt32",CHAR,FLOAT,OLDFP?0:FIRST_BIG+1,FLOAT,OLDFP?0:FIRST_BIG,1,0);
+
+#if 0
+  for(i=1;i<MAXR;i++){
+    printf("%02d %s scratch=%d ",i,regnames[i],regscratch[i]);
+    if(reg_pair(i,&rp))
+      printf("pair(%s,%s)",regnames[rp.r1],regnames[rp.r2]);
+    printf("\n");
+  }
+#endif
+
+  if(NOPEEP) nopeep=1;
+  if(CBMASCII) cbmascii=1;
+  if(ATASCII) atascii=1;
+  if(DIVBUG) divbug=1;
+  if(M65IO) m65io=1;
+  if(NOBANKING) manbank=1;
+  jmpinst="jmp";
+  if(C02||C02ALT){
+    c02=1;zzero=1;
+    jmpinst="bra";
+  }
+  if(CE02){
+    c02=1;ce02=1;
+    jmpinst="bra";
+  }
+  if(MEGA65){
+    m65=1;c02=1;ce02=1;
+    jmpinst="bra";
+  }
+
+  for(i=0;i<=MAX_TYPE;i++){
+    sizetab[i]=l2zm(msizetab[i]);
+    align[i]=l2zm(malign[i]);
+  }
+
+  bankv.storage_class=EXTERN;
+  bankv.identifier="__bankv";
+  bankv.vtyp=new_typ();
+  bankv.vtyp->flags=CHAR;
+
+  bankcnum=COMMONBANK;
+
+  return 1;
+}
+
+void init_db(FILE *f)
+{
+}
+
+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.        */
+/*  A pointer MUST be returned in a register. The code-generator    */
+/*  has to simulate a pseudo register if necessary.                 */
+{
+  int typ=t->flags&NQ;
+  if(ISSTRUCT(typ)||ISUNION(typ)||typ==VOID) 
+    return 0;
+  if(OLDFP&&ISFLOAT(typ)) return FIRST_GPR;
+  if(typ==LONG||typ==FLOAT||ISFPOINTER(typ)||(!ieee&&(typ==DOUBLE||typ==LDOUBLE)))
+    return FIRST_BIG;
+  if(typ==LLONG||(ieee&&(typ==DOUBLE||typ==LDOUBLE)))
+    return FIRST_BIGP;
+  if(zmleq(szof(t),l2zm(1L)))
+    return ra;
+  if(zmleq(szof(t),l2zm(2L))) 
+    return rax;
+  else
+    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>=FIRST_PAIR&&r<=LAST_PAIR){
+    p->r1=(r-FIRST_PAIR)*2+FIRST_GPR;
+    p->r2=p->r1+1;
+    return 1;
+  }else if(r>=FIRST_BIGP&&r<=LAST_BIGP){
+    p->r1=(r-FIRST_BIGP)*2+FIRST_BIG;
+    p->r2=p->r1+1;
+    return 1;
+  }else if(r==rax){
+    p->r1=ra;
+    p->r2=rx;
+    return 1;
+  }else if(r==sp){
+    p->r1=sp1;
+    p->r2=sp2;
+    return 1;
+  }
+  return 0;
+}
+
+/* estimate the cost-saving if object o from IC p is placed in
+   register r */
+int cost_savings(struct IC *p,int r,struct obj *o)
+{
+  int c=p->code,co;
+  if((o->flags&VAR)&&(o->v->tattr&ZPAGE)) return 0;
+  if(indirect(o)) co=5; else co=2;
+
+  /*TODO: adapt this */
+  if(o->flags&VKONST){
+    if(o!=&p->q1||p->q2.flags!=0) return 0;
+    if(r==ra||r==rax) return co;
+    if(r==rx&&(c==ASSIGN||c==PUSH)) return co-1;
+    return 0;
+  }
+
+  if(ISIDX(r)){
+    if(c==ADD||c==SUB||c==ADDI2P||c==SUBIFP||c==AND||c==OR||c==XOR){
+      if(o==&p->q2&&c!=ADDI2P) return co-4;
+      if(r==rx&&o==&p->q2&&((p->q1.flags&(VARADR|KONST|VKONST))==0||(p->q1.flags&DREFOBJ)))
+	return co-4;
+      if((c==ADD||c==SUB)&&o==&p->z&&(p->q2.flags&(KONST|DREFOBJ))==KONST){
+	eval_const(&p->q2.val,q2typ(p));
+	if(zmeqto(vmax,Z1)&&zumeqto(vumax,ZU1))
+	  return co+2;
+      }
+    }else if(c==ASSIGN||c==CONVERT){
+      if(o==&p->q1&&indirect(&p->z)) return 1;
+      if(o==&p->z&&indirect(&p->q1)) return 1;
+    }else if(c==COMPARE){
+      //if(o==&p->q1&&indirect(&p->q2)) return INT_MIN;
+      //if(o==&p->q2&&indirect(&p->q1)) return INT_MIN;
+    }else if(c==SETRETURN||c==GETRETURN||c==PUSH){
+    }else if(c==TEST){
+    }else
+      return INT_MIN;
+  }
+
+  if(c==ADDI2P&&o==&p->q1&&(p->typf&NU)==CHAR&&(r==rax))
+    return INT_MIN;
+
+
+  if(o->flags&DREFOBJ){
+    if(isptr(r))
+      return co+co+10;
+    if(r==rax)
+      return INT_MIN;
+  }
+  if(c==SETRETURN&&r==p->z.reg&&!(o->flags&DREFOBJ)) return co+2;
+  if(c==GETRETURN&&r==p->q1.reg&&!(o->flags&DREFOBJ)) return co+2;
+  if((c==ADD||c==SUB)&&o==&p->z&&p->q1.flags==p->z.flags&&p->q1.v==p->z.v&&(p->q2.flags&(KONST|DREFOBJ))==KONST){
+    eval_const(&p->q2.val,q2typ(p));
+    if(zmeqto(vmax,Z1)&&zumeqto(vumax,ZU1))
+      return co+1;
+  }
+  if(r==ra)
+    return co+2;
+  if(ISIDX(r))
+    return co+1;
+  if(r==rax)
+    return co+co+4;
+  return co;
+}
+
+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(r==0)
+    return 0;
+  if(r==rax&&NORAX)
+    return 0;
+  if(r==rx&&NOX)
+    return 0;
+  t&=NQ;
+  if(ISCHAR(t))
+    if(r==ra||(ISIDX(r)&&(optflags&2))||(r>=FIRST_GPR&&r<=LAST_GPR))
+      return 1;
+  if(ISSHORT(t)){
+    if(r==rax){
+      if(t==POINTER&&mode<0)
+	return 1;
+      if(t!=POINTER)
+	return 1;
+    }
+    if(r>=FIRST_PAIR&&r<=LAST_PAIR)
+      return 1;
+  }
+  if(r>=FIRST_BIG&&r<=LAST_BIG){
+    if(t==LONG||t==FLOAT||((t==DOUBLE||t==LDOUBLE)&&!ieee))
+      return 1;
+    if(t==FPOINTER)
+      return 1;
+  }
+  if(r>=FIRST_BIGP&&r<=LAST_BIGP){
+    if(t==LLONG||((t==DOUBLE||t==LDOUBLE)&&ieee))
+      return 1;
+  }
+  return 0;
+}
+
+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;
+}
+
+int must_convert(int o,int t,int const_expr)
+/*  Returns zero if code for converting np to type t    */
+/*  can be omitted.                                     */
+/*  On the PowerPC cpu pointers and 32bit               */
+/*  integers have the same representation and can use   */
+/*  the same registers.                                 */
+{
+  int op=o&NQ,tp=t&NQ;
+
+  if(op==tp) return 0;
+  if(ISCHAR(op)&&ISCHAR(tp)) return 0;
+  if(ISSHORT(op)&&ISSHORT(tp)) return 0;
+  if(!ieee&&ISFLOAT(op)&&ISFLOAT(tp)) return 0;
+  if(op==DOUBLE&&tp==LDOUBLE) return 0;
+  if(op==LDOUBLE&&tp==DOUBLE) 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(STDSYNTAX)
+    emit(f,"\tspace\t%ld\n",zm2l(size));
+  else
+    emit(f,"\treserve\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.              */
+{
+  if(zm2l(align)>1) emit(f,"\talign 1\n");
+}
+
+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,b=sbank(v);char *sec;
+  if(v->clist) constflag=is_const(v->vtyp);
+  if(v->storage_class==STATIC){
+    if(ISFUNC(v->vtyp->flags)) return;
+    if(v->tattr&ZPAGE)
+      emit(f,"\tzpage\t%s%ld\n",labprefix,zm2l(v->offset));
+    if(!special_section(f,v)){
+      if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))){emit(f,dataname);ebank(f,b);if(f) section=DATA;}
+      if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)){emit(f,rodataname);ebank(f,b);if(f) section=RODATA;}
+      if(!v->clist){emit(f,bssname);ebank(f,b);if(f) section=BSS;}
+    }
+    gen_align(f,falign(v->vtyp));
+    emit(f,"%s%ld:\n",labprefix,zm2l(v->offset));
+    newobj=1;
+  }
+  if(v->storage_class==EXTERN){
+    emit(f,"\t%s\t%s%s\n",(v->flags&NEEDS)?"needs":"global",idprefix,v->identifier);
+    if(v->tattr&ZPAGE)
+      emit(f,"\tzpage\t%s%s\n",idprefix,v->identifier);
+    if(v->flags&(DEFINED|TENTATIVE)){
+      if(!special_section(f,v)){
+	if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))){emit(f,dataname);ebank(f,b);if(f) section=DATA;}
+	if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)){emit(f,rodataname);ebank(f,b);if(f) section=RODATA;}
+	if(!v->clist){emit(f,bssname);ebank(f,b);if(f) section=BSS;}
+      }
+
+      gen_align(f,falign(v->vtyp));
+      emit(f,"%s%s:\n",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.                      */
+{
+  if(ISCHAR(t))
+    emit(f,"\tbyte\t");
+  else
+    emit(f,"\tword\t");
+  if(!p->tree){
+    if(ISLONG(t)||ISFLOAT(t)){
+      if(ieee&&ISFLOAT(t)){
+	emit_ieee(f,&p->val,t&NQ);
+      }else{
+	eval_const(&p->val,t&NU);
+	if(ISFLOAT(t)) cnv_fp();
+	gval.vmax=zmand(vmax,l2zm(0xffffL));
+	emitval(f,&gval,MAXINT);
+	emit(f,",");
+	gval.vmax=zmand(zmrshift(vmax,l2zm(16L)),l2zm(0xffffL));
+	emitval(f,&gval,MAXINT);
+      }
+    }else{
+      if(ISFPOINTER(t)){
+	eval_const(&p->val,t&NU);
+	emit(f,"%ld\n",(long)zm2l(vmax)&0xffff);
+	emit(f,"\tbyte\t%d\n",(int)((zm2l(vmax)>>16)&0xff));
+      }else
+	emitval(f,&p->val,t&NU);
+    }
+  }else{
+    emit_obj(f,&p->tree->o,t&NU);
+    if(ISFPOINTER(t)){
+      int b;
+      if((p->tree->o.flags&(VAR|VARADR))!=(VAR|VARADR)) ierror(0);
+      b=bank(p->tree->o.v);
+      emit(f,"\n\tbyte\t%d",b>=0?b:bankcnum);
+    }
+  }
+  emit(f,"\n");newobj=0;
+}
+
+static int handle_m65(FILE *f,IC *p)
+{
+  int t=p->typf,c=p->code,noop2=0;
+  if(c==MULT&&(ISSHORT(t)||ISCHAR(t))){
+    get_acc(f,p,INT);
+    load_acc(f,&p->q1,t);
+    if(m65io){
+      emit(f,"\tsta\t$d770\n");
+      if(ISSHORT(t)) emit(f,"\tstx\t$d771\n");
+    }else{
+      emit(f,"\tldz\t#$70\n");
+      emit(f,"\tstz\t___m65mathptr\n");
+      emit(f,"\tstq\t[___m65mathptr]\n");
+    }
+    load_acc(f,&p->q2,t);
+    if(m65io){
+      emit(f,"\tsta\t$d774\n");
+      if(ISSHORT(t)) emit(f,"\tstx\t$d775\n");
+    }
+    if(m65io){
+      emit(f,"\tlda\t$d778\n");
+      if(ISSHORT(t)) emit(f,"\tldx\t$d779\n");
+    }else{
+      emit(f,"\tldz\t#$74\n");
+      emit(f,"\tstz\t___m65mathptr\n");
+      emit(f,"\tstq\t[___m65mathptr]\n");    
+      emit(f,"\tldz\t#4\n");
+      emit(f,"\tldq\t[___m65mathptr],z\n");
+      emit(f,"\tldz\t#0\n");
+    }
+    yval=NOVAL;
+    store_acc(f,&p->z,t);
+    return 1;
+  }
+  if(ISLONG(t)&&LONGM65(c)){
+    int mnoy;
+
+    if(c==ASSIGN&&isreg(q1)&&isreg(z)&&p->q1.reg==p->z.reg) return 1;
+    if(c==GETRETURN&&isreg(z)&&p->z.reg==FIRST_BIG) return 1;
+    if(c==SETRETURN&&isreg(q1)&&p->q1.reg==FIRST_BIG) return 1;
+
+    get_acc(f,p,INT);
+
+    if(c==LSHIFT||c==RSHIFT){
+      int r,cnt=-1,mzzero;
+      
+      if((p->q2.flags&(KONST|DREFOBJ))==KONST){
+	eval_const(&p->q2.val,p->typf2);
+	cnt=(int)(zm2l(vmax));
+	cnt&=31;
+      }
+
+      if(cnt==24||cnt==16||cnt==8||(cnt>=0&&(!optsize||cnt<=2))){
+	r=0;
+      }else{
+	if(isreg(q2)&&p->q2.reg>=FIRST_GPR&&scratch(p,r,0)){
+	  r=p->q2.reg;
+	  if(reg_pair(r,&rp)) r=rp.r1;
+	}else{
+	  /* TODO: improve for x or z */
+	  load_lobyte(f,&p->q2,p->typf2);
+	  r=t1;
+	  emit(f,"\tsta\t%s\n",mregnames[r]);
+	}
+      }
+
+      mzzero=zzero;
+      zzero=0;
+      if(cnt==24||(!optsize&&cnt>=24)){
+	cnt-=24;
+	if(c==LSHIFT){
+	  if(indirect(&p->q1)){
+	    load_lobyte(f,&p->q1,t);
+	    emit(f,"\ttaz\n");
+	  }else
+	    do_lobyte(f,"ldz",&p->q1,t);
+	  emit(f,"\tlda\t#0\n");
+	  emit(f,"\ttax\n");
+	  emit(f,"\ttay\n");
+	  yval=0;
+	}else if(t&UNSIGNED){
+	  do_byte4(f,"lda",&p->q1,t);
+	  emit(f,"\tldx\t#0\n");
+	  emit(f,"\tldz\t#0\n");
+	  emit(f,"\tldy\t#0\n");
+	  yval=0;
+	}else{
+	  emit(f,"\tldx\t#0\n");
+	  emit(f,"\tldz\t#0\n");
+	  emit(f,"\tldy\t#0\n");
+	  yval=0;
+	  do_byte4(f,"lda",&p->q1,t);
+	  emit(f,"\tbpl\t%s%d\n",labprefix,++label);
+	  emit(f,"\tdex\n");
+	  if(yval==0) 
+	    emit(f,"\tdey\n");
+	  emit(f,"\tdez\n");
+	  emit(f,"%s%d:\n",labprefix,label);
+	  if(yval!=0){
+	    emit(f,"\tphx\n");
+	    emit(f,"\tply\n");
+	  }
+	}
+      }else if(cnt==16||(!optsize&&cnt>=16)){
+	cnt-=16;
+	if(c==LSHIFT){
+	  if(indirect(&p->q1)){
+	    load_hibyte(f,&p->q1,t);
+	    emit(f,"\ttaz\n");
+	    load_lobyte(f,&p->q1,t);
+	    emit(f,"\ttay\n");
+	  }else{
+	    do_lobyte(f,"ldy",&p->q1,t);
+	    do_hibyte(f,"ldz",&p->q1,t);
+	  }
+	  emit(f,"\tlda\t#0\n");
+	  emit(f,"\ttax\n");
+	}else if(t&UNSIGNED){
+	  if(indirect(&p->q1)){
+	    do_byte4(f,"lda",&p->q1,t);
+	    emit(f,"\ttax\n");
+	    do_byte3(f,"lda",&p->q1,t);
+	  }else{
+	    do_byte3(f,"lda",&p->q1,t);
+	    do_byte4(f,"ldx",&p->q1,t);
+	  }
+	  emit(f,"\tldy\t#0\n");
+	  emit(f,"\tldz\t#0\n");
+	}else{
+	  emit(f,"\tldy\t#0\n");
+	  emit(f,"\tldz\t#0\n");
+	  yval=0;
+	  if(indirect(&p->q1)){
+	    do_byte4(f,"lda",&p->q1,t);
+	    emit(f,"\ttax\n");
+	    do_byte3(f,"lda",&p->q1,t);
+	    emit(f,"\tcpx\t#0\n");
+	  }else{
+	    do_byte3(f,"lda",&p->q1,t);
+	    do_byte4(f,"ldx",&p->q1,t);
+	  }
+	  emit(f,"\tbpl\t%s%d\n",labprefix,++label);
+	  emit(f,"\tdez\n");
+	  if(yval==0)
+	    emit(f,"\tdey\n");
+	  emit(f,"%s%d:\n",labprefix,label);
+	  if(yval!=0){
+	    emit(f,"\tphz\n");
+	    emit(f,"\tply\n");
+	  }
+	}
+      }else if(cnt==8||(!optsize&&cnt>=8)){
+	cnt-=8;
+	if(c==LSHIFT){
+	  if(indirect(&p->q1)){
+	    do_byte3(f,"lda",&p->q1,t);
+	    emit(f,"\ttaz\n");
+	    load_lobyte(f,&p->q1,t);
+	    emit(f,"\ttax\n");
+	    load_hibyte(f,&p->q1,t);
+	    emit(f,"\ttay\n");
+	  }else{
+	    do_lobyte(f,"ldx",&p->q1,t);
+	    do_byte3(f,"ldz",&p->q1,t);
+	    do_hibyte(f,"ldy",&p->q1,t);
+	  }
+	  emit(f,"\tlda\t#0\n");
+	}else if(t&UNSIGNED){
+	  emit(f,"\tldz\t#0\n");
+	  if(indirect(&p->q1)){
+	    do_byte4(f,"lda",&p->q1,t);
+	    emit(f,"\tpha\n");
+	    do_byte3(f,"lda",&p->q1,t);
+	    emit(f,"\ttax\n");
+	    do_hibyte(f,"lda",&p->q1,t);
+	    emit(f,"\tply\n");
+	  }else{
+	    do_hibyte(f,"lda",&p->q1,t);
+	    do_byte3(f,"ldx",&p->q1,t);
+	    do_byte4(f,"ldy",&p->q1,t);
+	  }
+	}else{
+	  emit(f,"\tldz\t#0\n");
+	  if(indirect(&p->q1)){
+	    do_byte4(f,"lda",&p->q1,t);
+	    emit(f,"\tpha\n");
+	    do_byte3(f,"lda",&p->q1,t);
+	    emit(f,"\ttax\n");
+	    do_hibyte(f,"lda",&p->q1,t);
+	    emit(f,"\tply\n");
+	  }else{
+	    do_hibyte(f,"lda",&p->q1,t);
+	    do_byte3(f,"ldx",&p->q1,t);
+	    do_byte4(f,"ldy",&p->q1,t);
+	  }
+	  emit(f,"\tbpl\t%s%d\n",labprefix,++label);
+	  emit(f,"\tdez\n");
+	  emit(f,"%s%d:\n",labprefix,label);
+	}
+      }else{
+	mnoy=noy;
+	ldq_offset(f,&p->q1);
+	noy=2;
+	emit(f,"\tldq\t");
+	emit_obj(f,&p->q1,t);
+	emit(f,"\n");
+	noy=mnoy;
+      }
+      if(r){
+	emit(f,"\tdec\t%s\n",mregnames[r]);
+	emit(f,"\tbmi\t%s%d\n",labprefix,++label);
+	emit(f,"%s%d:\n",labprefix,++label);
+	emit(f,"\t%s\n",c==LSHIFT?"aslq":((t&UNSIGNED)?"lsrq":"asrq"));
+	emit(f,"\tdec\t%s\n",mregnames[r]);
+	emit(f,"\tbpl\t%s%d\n",labprefix,label);
+	emit(f,"%s%d:\n",labprefix,label-1);
+      }else{
+	while(--cnt>=0)
+	  emit(f,"\t%s\n",c==LSHIFT?"aslq":((t&UNSIGNED)?"lsrq":"asrq"));
+      }
+      yval=NOVAL;
+      mnoy=noy;
+      noy=1;
+      emit(f,"\tstq\t");
+      emit_obj(f,&p->z,t);
+      emit(f,"\n");
+      noy=mnoy;
+      emit(f,"\tldz\t#0\n");
+      zzero=mzzero;
+      return 1;
+    }
+
+    if(c==PUSH){
+      if(pushed){
+	emit(f,"\tlda\t%s\n",mregnames[sp]);
+	emit(f,"\tldx\t%s+1\n",mregnames[sp]);
+	emit(f,"\tclc\n");
+	emit(f,"\tadc\t#%d\n",pushed);
+	emit(f,"\tbcc\t%s%d\n",labprefix,++label);
+	emit(f,"\tinx\n");
+	emit(f,"%s%d:\n",labprefix,label);
+	emit(f,"\tsta\t%s\n",mregnames[t1]);
+	emit(f,"\tstx\t%s\n",mregnames[t2]);
+      }
+      pushed+=4;
+    }
+    if((c==MULT||c==DIV)&&!m65io){
+      emit(f,"\tlda\t#$70\n");
+      emit(f,"\tsta\t___m65mathptr\n");
+    }
+    yval=NOVAL;
+    noy=1;
+    if((p->q1.flags&(KONST|DREFOBJ))==KONST){
+      unsigned long v;
+      eval_const(&p->q1.val,q1typ(p));
+      v=zum2ul(vumax);
+      emit(f,"\tlda\t#%d\n",(int)(v&255));v>>=8;
+      emit(f,"\tldx\t#%d\n",(int)(v&255));v>>=8;
+      emit(f,"\tldy\t#%d\n",(int)(v&255));v>>=8;
+      emit(f,"\tldz\t#%d\n",(int)(v&255));
+    }else if(c==GETRETURN){
+      emit(f,"\tldq\t%s\n",mregnames[FIRST_BIG]);
+    }else{
+      noy=2;
+      ldq_offset(f,&p->q1);
+      emit(f,"\tldq\t");
+      /*TODO: VARADR */
+      if((p->q1.flags&VARADR)||(p->q1.flags&(KONST|DREFOBJ))==KONST){
+	emit(f,"%s%d",labprefix,addfpconst(&p->q1,q1typ(p)));
+      }else
+	emit_obj(f,&p->q1,t);
+      emit(f,"\n");
+      noy=1;
+    }
+    if(c==ADD){
+      if((p->q2.flags&(KONST|DREFOBJ))==KONST){
+	eval_const(&p->q2.val,t);
+	if(zmeqto(vmax,Z1)){noop2=1;emit(f,"\tinq\n");}
+	else if(zmeqto(vmax,l2zm(2L))){noop2=1;emit(f,"\tinq\n\tinq\n");}
+	else if(zmeqto(vmax,l2zm(3L))){noop2=1;emit(f,"\tinq\n\tinq\n\tinq\n");}
+	else if(zmeqto(vmax,l2zm(4L))){noop2=1;emit(f,"\tinq\n\tinq\n\tinq\n\tinq\n");}
+      }
+      if(!noop2){
+	emit(f,"\tclc\n");
+	emit(f,"\tadcq\t");
+      }
+    }else if(c==SUB){
+      if((p->q2.flags&(KONST|DREFOBJ))==KONST){
+	eval_const(&p->q2.val,t);
+	if(zmeqto(vmax,Z1)){noop2=1;emit(f,"\tdeq\n");}
+	else if(zmeqto(vmax,l2zm(2L))){noop2=1;emit(f,"\tdeq\n\tdeq\n");}
+	else if(zmeqto(vmax,l2zm(3L))){noop2=1;emit(f,"\tdeq\n\tdeq\n\tdeq\n");}
+	else if(zmeqto(vmax,l2zm(4L))){noop2=1;emit(f,"\tdeq\n\tdeq\n\tdeq\n\tdeq\n");}
+      }
+      if(!noop2){
+	emit(f,"\tsec\n");
+	emit(f,"\tsbcq\t");
+      }
+    }else if(c==OR){
+      emit(f,"\torq\t");
+    }else if(c==AND){
+      emit(f,"\tandq\t");
+    }else if(c==XOR){
+      emit(f,"\teorq\t");
+    }else if(c==MULT||c==DIV){
+      if(m65io){
+	emit(f,"\tstq\t$d770\n");
+      }else{
+	emit(f,"\tstq\t[___m65mathptr]\n");
+	emit(f,"\tlda\t#$74\n");
+	emit(f,"\tsta\t___m65mathptr\n");
+      }
+      noy=2;
+      ldq_offset(f,&p->q2);
+      emit(f,"\tldq\t");
+    }
+    if(c!=ASSIGN&&c!=PUSH&&c!=GETRETURN&&c!=SETRETURN&&!noop2){
+      if((p->q2.flags&VARADR)||(p->q2.flags&(KONST|DREFOBJ))==KONST){
+	emit(f,"%s%d",labprefix,addfpconst(&p->q2,q2typ(p)));
+      }else
+	emit_obj(f,&p->q2,t);
+      emit(f,"\n");
+    }
+    noy=1;
+    if(c==MULT||c==DIV){
+      if(m65io)
+	emit(f,"\tstq\t$d774\n");
+      else
+	emit(f,"\tstq\t[___m65mathptr]\n");
+      if(m65io){
+	if(c==DIV){
+	  /* delay */
+	  emit(f,"\tlda\t$d76c\n");
+	  emit(f,"\tlda\t$d76c\n");
+	  emit(f,"\tlda\t$d76c\n");
+	  emit(f,"\tlda\t$d76c\n");
+	  emit(f,"\tldq\t$d76c\n");
+	}else
+	  emit(f,"\tldq\t$d778\n");
+      }else{
+	if(c==DIV){
+	  emit(f,"\tlda\t#$6c\n");
+	  emit(f,"\tsta\t___m65mathptr\n");
+	  emit(f,"\tldz\t#0\n");
+	  emit(f,"\tlda\t[___m65mathptr],z\n"); /* delay for division */
+	}else
+	  emit(f,"\tldz\t#4\n");
+	emit(f,"\tldq\t[___m65mathptr],z\n");
+      }
+    }
+    emit(f,"\tstq\t");
+    if(c==PUSH)
+      emit(f,"(%s)",pushed==4?mregnames[sp]:mregnames[t1]);
+    else if(c==SETRETURN)
+      emit(f,"%s",mregnames[FIRST_BIG]);
+    else
+      emit_obj(f,&p->z,t);
+    emit(f,"\n");
+    noy=0;
+    if(zzero) 
+      emit(f,"\tldz\t#0\n");
+    else
+      ierror(0);
+    return 1;
+  }
+  return 0;
+}
+
+/*  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 *p,struct Var *v,zmax offset)
+/*  The main code-generation.                                           */
+{
+  int c,t,i;
+  struct IC *mi;
+  FILE *rf=f;
+  static char *dbgfile;
+  static int dbgline;
+
+  if(vlas){
+    fp=FPVLA_REG;
+    if(!reg_pair(fp,&rp)) ierror(0);
+    fp1=rp.r1;
+    fp2=rp.r2;
+    regused[fp]=regused[fp1]=regused[fp2]=1;
+   }else{
+    fp=sp;
+    fp1=sp1;
+    fp2=sp2;
+  }
+  argsize=0;
+  localsize=offset;
+  if(DEBUG&1) printf("gen_code()\n");
+
+  if(ce02) zzero=1; /* TODO: check what to do */
+
+  cbank=bank(v);
+
+  if(!v->fi) v->fi=new_fi();
+  v->fi->flags|=ALL_REGS;
+
+  for(mi=p;mi;mi=mi->next)
+    switch_IC(mi);
+
+  for(pass=0;pass<2;pass++){
+
+    if(DEBUG&1) printf("pass %d\n",pass);
+
+    if(pass==0){
+      f=0;
+      mi=clone_ic(p);
+    }else
+      f=rf;
+
+    for(c=1;c<=MAXR;c++) regs[c]=0; /*regsa[c];*/
+    maxpushed=0;
+
+    /*FIXME*/
+    if(v->tattr&INTERRUPT){
+      ret="\trti\n";
+      in_isr=1;
+    }else{
+      ret="\trts\n";
+      in_isr=0;
+    }
+
+    if(!nopeep) peephole(pass==0?p:mi);
+
+    function_top(f,v,localsize);
+
+    pushed=0;
+
+    yval=NOVAL;
+
+    dbgfile=0;
+    dbgline=0;
+
+    for(p=pass==0?p:mi;p;pr(f,p),p=p->next){
+
+
+
+      if(DEBUG&1) pric2(stdout,p);
+
+      if(debug_info){
+	if(p->file&&p->line){
+	  if(p->file!=dbgfile||p->line!=dbgline){
+	    dbgfile=p->file;
+	    dbgline=p->line;
+	    emit(f,"; %d \"%s\"\n",dbgline,dbgfile);
+	  }
+	}
+      }
+
+      c=p->code;t=p->typf;
+
+      if(c==NOP) {p->z.flags=0;continue;}
+      if(c==ALLOCREG){
+	regs[p->q1.reg]=1;
+	if(reg_pair(p->q1.reg,&rp)){
+	  regs[rp.r1]=1;
+	  regs[rp.r2]=1;
+	}
+	continue;
+      }
+      if(c==FREEREG){
+	regs[p->q1.reg]=0;
+	if(reg_pair(p->q1.reg,&rp)){
+	  regs[rp.r1]=0;
+	  regs[rp.r2]=0;
+	}
+	continue;
+      }
+      if(c==LABEL) {emit(f,"%s%d:\n",labprefix,t);yval=NOVAL;continue;}
+      if(c==BRA){
+	yval=NOVAL;
+	if(t==exit_label&&localsize+argsize+rsavesize+rscnt==0)
+	  emit(f,ret);
+	else
+	  emit(f,"\t%s\t%s%d\n",jmpinst,labprefix,t);
+	continue;
+      }
+      if(c>=BEQ&&c<BRA){
+	yval=NOVAL;
+	continue;
+      }
+
+      if(c==MOVETOREG){
+	p->code=c=ASSIGN;
+	p->typf=t=regtype[p->z.reg]->flags;
+	p->q2.val.vmax=sizetab[regtype[p->z.reg]->flags];
+      }
+      if(c==MOVEFROMREG){
+	p->code=c=ASSIGN;
+	p->typf=t=regtype[p->q1.reg]->flags;
+	p->q2.val.vmax=sizetab[regtype[p->q1.reg]->flags];
+      }
+      if(c==CONVERT&&ISCHAR(t)&&ISCHAR(p->typf2)){
+	p->code=c=ASSIGN;
+	p->q2.val.vmax=sizetab[CHAR];
+      }
+      if(c==CONVERT&&msizetab[t&NQ]==3&&msizetab[p->typf2&NQ]==3){
+	p->code=c=ASSIGN;
+	p->q2.val.vmax=sizetab[SHORT];
+      }
+      if(c==CONVERT&&ISSHORT(t)&&ISSHORT(p->typf2)){
+	p->code=c=ASSIGN;
+	p->q2.val.vmax=sizetab[SHORT];
+      }
+      if(c==CONVERT&&ISLONG(t)&&ISLONG(p->typf2)){
+	p->code=c=ASSIGN;
+	p->q2.val.vmax=sizetab[LONG];
+      }
+      if(c==CONVERT&&ISLLONG(t)&&ISLLONG(p->typf2)){
+	p->code=c=ASSIGN;
+	p->q2.val.vmax=sizetab[LLONG];
+      }
+      if(c==CONVERT&&ISFLOAT(t)&&ISFLOAT(p->typf2)){
+	p->code=c=ASSIGN;
+	p->q2.val.vmax=sizetab[t&NQ];
+      }
+
+
+      /* switch commutative operands if suitable */
+      if(c==ADD||c==MULT||c==AND||c==XOR||c==OR||(c==ADDI2P&&ISSHORT(t)&&!ISFPOINTER(p->typf2))){
+	if((compare_objects(&p->q2,&p->z)&&!isacc(q1))||isacc(q2)){
+	  struct obj tmp;
+	  tmp=p->q1;
+	  p->q1=p->q2;
+	  p->q2=tmp;
+	}
+      }
+
+      if(c==COMPARE&&((p->q1.flags&(KONST|DREFOBJ))==KONST||ISRIDX(q2)||(isacc(q2)&&!ISRIDX(q1)))){
+	obj tmp;IC *b;
+	tmp=p->q1;
+	p->q1=p->q2;
+	p->q2=tmp;
+	for(b=p->next;b;b=b->next){
+	  int bc;
+	  if(!b||b->code==LABEL) ierror(0);
+	  bc=b->code;
+	  if(bc==BGT){b->code=BLT;break;}
+	  if(bc==BGE){b->code=BLE;break;}
+	  if(bc==BLT){b->code=BGT;break;}
+	  if(bc==BLE){b->code=BGE;break;}
+	  if(bc==BNE||bc==BEQ) break;
+	}
+      }
+
+      c=p->code;
+      if(c==SUBPFP) c=SUB;
+      /*if(c==ADDI2P) c=ADD;*/
+      /*if(c==SUBIFP) c=SUB;*/
+
+
+      if(c==MINUS){
+	if(isacc(q1)&&isacc(z)){
+	  emit(f,"\teor\t#255\n");
+	  if(c02&&ISCHAR(t)){
+	    emit(f,"\tina\n");
+	  }else{
+	    emit(f,"\tclc\n");
+	    emit(f,"\tadc\t#1\n");
+	  }
+	  if(!ISCHAR(t)){
+	    emit(f,"\tpha\n");
+	    emit(f,"\ttxa\n");
+	    emit(f,"\teor\t#255\n");
+	    emit(f,"\tadc\t#0\n");
+	    emit(f,"\ttax\n");
+	    emit(f,"\tpla\n");
+	  }
+	  continue;
+	}
+	p->code=c=SUB;
+	p->q2=p->q1;
+	p->q1.flags=KONST;
+	p->q1.am=0;
+	gval.vmax=Z0;
+	eval_const(&gval,MAXINT);
+	insert_const(&p->q1.val,t);
+      }
+
+      preload(f,p);
+
+      if((c==ADD||c==SUB||c==ADDI2P||c==SUBIFP)&&compare_objects(&p->q1,&p->z)&&(!indirect(&p->q1)||(isreg(q1)&&ISIDX(p->q1.reg)))&&isconst(q2)&&!isacc(z)){
+	long l;
+	eval_const(&p->q2.val,q2typ(p));
+	l=zm2l(vmax);
+	if(c==ADDI2P/*&&(t2&NQ)==POINTER*/) {c=ADD;t=UNSIGNED|INT;}
+	if(c==SUBIFP/*&&(t2&NQ)==POINTER*/) {c=SUB;t=UNSIGNED|INT;}
+	if(c==SUB||c==SUBIFP) l=-l;
+	/*TODO: allow larger types */
+	if(l<3&&l>-3&&(t&NQ)<=INT){
+	  if(l<0){
+	    if(!c02||!isreg(q1)) get_acc(f,p,CHAR);
+	    incmem(f,&p->z,t,SUB,-l);
+	  }else
+	    incmem(f,&p->z,t,ADD,l);
+	  continue;
+	}
+	if(ISLONG(t)&&((m65&&labs(l)<3)||(optspeed&&l>0&&l<4)||(l>0&&l<2))){
+	  if(l<0){
+	    incmem(f,&p->z,t,SUB,-l);
+	  }else
+	    incmem(f,&p->z,t,ADD,l);
+	  continue;
+	}
+      }
+
+      if(m65&&handle_m65(f,p))
+	continue;
+
+      if(c==CONVERT){
+	int to=q1typ(p)&NU;
+	t&=NU;
+	if(ISCHAR(t)){
+	  if(!isacc(q1))
+	    get_acc(f,p,CHAR);
+	  load_lobyte(f,&p->q1,to);
+	  store_lobyte(f,&p->z,t);
+	  continue;
+	}
+	if(ISLONG(to)){
+	  if(!isacc(z))
+	    get_acc(f,p,CHAR);
+	  if(zm2l(sizetab[t&NQ])==3){
+	    do_byte3(f,"lda",&p->q1,to);
+	    do_byte3(f,"sta",&p->z,t);
+	  }
+	  if(zm2l(sizetab[t&NQ])>=2){
+	    if(isacc(z)&&!indirect(&p->q1)){
+	      do_hibyte(f,"ldx",&p->q1,to);
+	    }else{
+	      load_hibyte(f,&p->q1,to);
+	      store_hibyte(f,&p->z,t);
+	    }
+	  }
+	  load_lobyte(f,&p->q1,to);
+	  store_lobyte(f,&p->z,t);
+	  continue;
+	}
+	if(ISSHORT(to)){
+	  if((t&UNSIGNED)||ISFPOINTER(t))
+	    get_acc(f,p,CHAR);
+	  else
+	    get_acc(f,p,SHORT);
+	  load_lobyte(f,&p->q1,to);
+	  store_lobyte(f,&p->z,t);
+	  load_hibyte(f,&p->q1,to);
+	  store_hibyte(f,&p->z,t);
+	  if(ISFPOINTER(t)){
+	    int b=-1;
+	    if((p->q1.flags&(VARADR|DREFOBJ))==VARADR) b=bank(p->q1.v);
+	    emit(f,"\tlda\t#%d\n",b>=0?b:bankcnum);
+	    do_byte3(f,"sta",&p->z,t);
+	    continue;
+	  }
+	  if(to&UNSIGNED){
+	    if(zzero&&!indirect(&p->z)){
+	      do_byte3(f,"stz",&p->z,t);
+	      do_byte4(f,"stz",&p->z,t);
+	    }else{
+	      emit(f,"\tlda\t#0\n");
+	      do_byte3(f,"sta",&p->z,t);
+	      do_byte4(f,"sta",&p->z,t);
+	    }
+	  }else{
+	    emit(f,"\tldx\t#0\n");
+	    emit(f,"\tcmp\t#0\n");
+	    emit(f,"\tbpl\t%s%d\n",labprefix,++label);
+	    emit(f,"\tdex\n");
+	    emit(f,"%s%d:\n",labprefix,label);
+	    if(indirect(&p->z)){
+	      emit(f,"\ttxa\n");
+	      do_byte3(f,"sta",&p->z,t);
+	      do_byte4(f,"sta",&p->z,t);
+	    }else{
+	      do_byte3(f,"stx",&p->z,t);
+	      do_byte4(f,"stx",&p->z,t);
+	    }
+	  }
+	  continue;
+	}
+	if(ISCHAR(to)){
+	  if(to&UNSIGNED){
+	    char *s;
+	    get_acc(f,p,CHAR);
+	    if(isreg(q1)&&p->q1.reg==rx&&!indirect(&p->z)){
+	      do_lobyte(f,"stx",&p->z,CHAR);
+	    }else{
+	      load_lobyte(f,&p->q1,to);
+	      store_lobyte(f,&p->z,t);
+	    }
+	    if(isacc(z)){
+	      emit(f,"\tldx\t#0\n");
+	      continue;
+	    }
+	    if(zzero&&!indirect(&p->z))
+	      s="stz";
+	    else{
+	      emit(f,"\tlda\t#0\n");
+	      s="sta";
+	    }
+	    do_hibyte(f,s,&p->z,t);
+	    if(ISLONG(t)){
+	      do_byte3(f,s,&p->z,t);
+	      do_byte4(f,s,&p->z,t);
+	    }
+	  }else{
+	    int l=++label;
+	    get_acc(f,p,SHORT);
+	    emit(f,"\tldx\t#0\n");
+	    if(isreg(q1)&&p->q1.reg==ra)
+	      emit(f,"\tcmp\t#0\n");
+	    else
+	      load_lobyte(f,&p->q1,to);
+	    emit(f,"\tbpl\t%s%d\n",labprefix,label);
+	    emit(f,"\tdex\n");
+	    emit(f,"%s%d:\n",labprefix,label);
+	    store_lobyte(f,&p->z,t);
+	    if(indirect(&p->z)&&(!isreg(z)||p->z.reg!=rax)){
+	      emit(f,"\ttxa\n");
+	      store_hibyte(f,&p->z,t);
+	      if(ISLONG(t)){
+		do_byte3(f,"sta",&p->z,t);
+		do_byte4(f,"sta",&p->z,t);
+	      }
+	    }else{
+	      if(!isreg(z)||p->z.reg!=rax){
+		emit(f,"\tstx\t");
+		emit_hibyte(f,&p->z,t);
+		emit(f,"\n");
+	      }
+	      if(ISLONG(t)){
+		do_byte3(f,"stx",&p->z,t);
+		do_byte4(f,"stx",&p->z,t);
+	      }
+	    }
+	  }
+	  if(ISFPOINTER(t)){
+	    emit(f,"\tlda\t#%d\n",cbank>=0?cbank:bankcnum);
+	    do_byte3(f,"sta",&p->z,t);
+	  }
+	  continue;
+	}
+	if(ISFPOINTER(to)){
+	  get_acc(f,p,CHAR);
+	  if(zm2l(sizetab[t&NQ])>=3){
+	    do_byte3(f,"lda",&p->q1,to);
+	    do_byte3(f,"sta",&p->z,t);
+	  }
+	  if(zm2l(sizetab[t&NQ])>=2){
+	    load_hibyte(f,&p->q1,to);
+	    store_hibyte(f,&p->z,t);
+	  }
+	  load_lobyte(f,&p->q1,to);
+	  store_lobyte(f,&p->z,t);
+
+	  continue;
+	}
+	pric2(stdout,p);
+	ierror(0);
+      }
+
+      if(c==KOMPLEMENT){
+	get_acc(f,p,CHAR);
+	if(ISCHAR(t)){
+	  load_acc(f,&p->q1,t);
+	  emit(f,"\teor\t#-1\n");
+	  store_acc(f,&p->z,t);
+	}else{
+	  if(isacc(q1))
+	    emit(f,"\tpha\n");
+	  if(ISLONG(t)){
+	    do_byte4(f,"lda",&p->q1,t);
+	    emit(f,"\teor\t#-1\n");
+	    do_byte4(f,"sta",&p->z,t);
+	    do_byte3(f,"lda",&p->q1,t);
+	    emit(f,"\teor\t#-1\n");
+	    do_byte3(f,"sta",&p->z,t);
+	  }
+	  load_hibyte(f,&p->q1,t);
+	  emit(f,"\teor\t#-1\n");
+	  store_hibyte(f,&p->z,t);
+	  if(isacc(q1))
+	    emit(f,"\tpla\n");
+	  load_lobyte(f,&p->q1,t);
+	  emit(f,"\teor\t#-1\n");
+	  store_lobyte(f,&p->z,t);
+	}
+	continue;
+      }
+      if(c==SETRETURN){
+	hasretval=1;
+	t&=NQ;
+	if(isreg(q1)&&p->q1.reg==p->z.reg) continue;
+	if(t==LONG||t==LLONG||ISFLOAT(t)||ISFPOINTER(t)){
+	  long l=zm2l(p->q2.val.vmax);
+	  int zr=p->z.reg;
+	  //get_acc(f,p,t);
+	  if((optsize||l>4)&&!ISFPOINTER(t)){
+	    int ind=indirect(&p->q1);
+	    if(ind) load_address(f,LAST_PAIR,&p->q1,t);
+	    BSET(regused,t3);
+	    BSET(regused,t4);
+	    sety(f,l-1);
+	    emit(f,"%s%d:\n",labprefix,++label);
+	    if(ind)
+	      emit(f,"\tlda\t(%s),y\n",mregnames[LAST_PAIR]);
+	    else{
+	      emit(f,"\tlda\t");
+	      if(!ISFLOAT(t)&&(p->q1.flags&(KONST|DREFOBJ))==KONST){
+		emit(f,"%s%d",labprefix,addfpconst(&p->q1,t));
+	      }else
+		emit_obj(f,&p->q1,t);
+	      emit(f,",y\n");
+	    }
+	    emit(f,"\tsta\t%s,y\n",mregnames[zr]);
+	    emit(f,"\tdey\n");
+	    emit(f,"\tbpl\t%s%d\n",labprefix,label);
+	    yval=255;
+	  }else{
+	    if((p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)){
+	      if(p->q1.reg==zr){
+		int r=get_reg(f,p,POINTER);
+		if(r==FIRST_PAIR||r==FIRST_PAIR+1)
+		  ierror(0);
+		if(!reg_pair(r,&rp2)) ierror(0);
+		emit(f,"\tlda\t%s\n",mregnames[zr]);
+		emit(f,"\tsta\t%s\n",mregnames[rp2.r1]);
+		emit(f,"\tlda\t%s+1\n",mregnames[zr]);
+		emit(f,"\tsta\t%s\n",mregnames[rp2.r2]);
+		p->q1.reg=r;
+	      }
+	    }
+	    load_lobyte(f,&p->q1,t);
+	    emit(f,"\tsta\t%s\n",mregnames[zr]);
+	    load_hibyte(f,&p->q1,t);
+	    emit(f,"\tsta\t%s+1\n",mregnames[zr]);
+	    do_byte3(f,"lda",&p->q1,t);
+	    emit(f,"\tsta\t%s+2\n",mregnames[zr]);
+	    if(!ISFPOINTER(t)){
+	      do_byte4(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s+3\n",mregnames[zr]);
+	    }
+	    /*TODO:regused OLDFP */
+	    regused[zr]=1;
+	  }
+	  continue;
+	}
+	//get_acc(f,p,t);
+	load_acc(f,&p->q1,t);
+	regused[ra]=1;
+	regused[rx]=1;
+	continue;
+      }
+      if(c==GETRETURN){
+	t&=NQ;
+	if(isreg(z)&&p->q1.reg==p->z.reg) continue;
+	if(t==LONG||t==LLONG||ISFLOAT(t)||ISFPOINTER(t)){
+	  long l=zm2l(p->q2.val.vmax);
+	  int qr=p->q1.reg;
+	  if((optsize||l>4)&&!ISFPOINTER(t)){
+	    int ind=indirect(&p->z);
+	    if(ind) load_address(f,LAST_PAIR,&p->z,t);
+	    BSET(regused,t3);
+	    BSET(regused,t4);
+	    sety(f,l-1);
+	    emit(f,"%s%d:\n",labprefix,++label);
+	    emit(f,"\tlda\t%s,y\n",mregnames[qr]);
+	    if(ind)
+	      emit(f,"\tsta\t(%s),y\n",mregnames[LAST_PAIR]);
+	    else{
+	      emit(f,"\tsta\t");
+	      emit_obj(f,&p->z,t);
+	      emit(f,",y\n");
+	    }
+	    emit(f,"\tdey\n");
+	    emit(f,"\tbpl\t%s%d\n",labprefix,label);
+	    yval=255;
+	  }else{
+	    if((p->z.reg&(REG|DREFOBJ))==(REG|DREFOBJ)){
+	      if(p->z.reg==qr) ierror(0);
+	    }
+	    emit(f,"\tlda\t%s\n",mregnames[qr]);
+	    store_lobyte(f,&p->z,t);
+	    emit(f,"\tlda\t%s+1\n",mregnames[qr]);
+	    store_hibyte(f,&p->z,t);
+	    emit(f,"\tlda\t%s+2\n",mregnames[qr]);
+	    do_byte3(f,"sta",&p->z,t);
+	    if(!ISFPOINTER(t)){
+	      emit(f,"\tlda\t%s+3\n",mregnames[qr]);
+	      do_byte4(f,"sta",&p->z,t);
+	    }
+	  }
+	  continue;
+	}
+	if(p->q1.reg)
+	  store_acc(f,&p->z,t);
+	continue;
+      }
+      if(c==CALL){
+	int reg;
+
+	if(argsize<zm2l(p->q2.val.vmax)) argsize=zm2l(p->q2.val.vmax);
+
+	/*FIXME*/
+#if 0      
+	if(stack_valid&&(p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&(p->q1.v->fi->flags&ALL_STACK)){
+	  if(framesize+zum2ul(p->q1.v->fi->stack1)>stack)
+	    stack=framesize+zum2ul(p->q1.v->fi->stack1);
+	}else
+	  stack_valid=0;
+#endif
+	if((p->q1.flags&(VAR|DREFOBJ))==VAR&&!strcmp("__va_start",p->q1.v->identifier)){
+	  long of=va_offset(v)+localsize+rsavesize+argsize;
+	  emit(f,"\tlda\t%s\n",mregnames[fp]);
+	  if(of){
+	    emit(f,"\tclc\n");
+	    if(of&255)
+	      emit(f,"\tadc\t#%d\n",(of&255));
+	  }
+	  emit(f,"\tldx\t%s+1\n",mregnames[fp]);
+	  if(of&0xff00){
+	    emit(f,"\tpha\n");
+	    emit(f,"\ttxa\n");
+	    emit(f,"\tadc\t#%d\n",(of>>8)&255);
+	    emit(f,"\ttax\n");
+	    emit(f,"\tpla\n");
+	  }else if(of){
+	    emit(f,"\tbcc\t%s%d\n",labprefix,++label);
+	    emit(f,"\tinx\n");
+	    emit(f,"%s%d:\n",labprefix,label);
+	  }
+	  continue;
+	}
+	if((p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&p->q1.v->fi->inline_asm){
+	  emit(f,";startinline\n");
+	  emit_inline_asm(f,p->q1.v->fi->inline_asm);
+	  emit(f,";endinline\n");
+	}else if(p->q1.flags&DREFOBJ){
+	  if(ISFPOINTER(p->q1.dtyp)){
+	    p->q1.flags&=~DREFOBJ;
+	    load_reg(f,LAST_PAIR,&p->q1,POINTER);
+	    if(indirect(&p->q1)){
+	      do_byte3(f,"lda",&p->q1,FPOINTER);
+	      emit(f,"\ttay\n");
+	    }else
+	      do_byte3(f,"ldy",&p->q1,FPOINTER);
+	    emit(f,"\tlda\t#%d\n",cbank>=0?cbank:bankcnum);
+	    emit(f,"\tjsr\t%s__bankjsr\n",idprefix);
+	    yval=NOVAL;
+	  }else{
+	    if(!(p->q1.flags&REG)) ierror(0);
+	    emit(f,"\tjsr\t%s%d\n",labprefix,++label);
+	    yval=NOVAL;
+	    add_cmplist(label,p->q1.reg,JMPIND);
+	  }
+	}else{
+	  int tbank=-1;
+	  if(p->q1.flags&VAR) tbank=bank(p->q1.v);
+	  if(tbank!=cbank&&tbank>=0){
+	    if(cbank>=0){
+	      load_address(f,LAST_PAIR,&p->q1,t);
+	      sety(f,tbank);
+	      emit(f,"\tlda\t#%d\n",cbank);
+	      emit(f,"\tjsr\t%s__bankjsr\n",idprefix);
+	      yval=NOVAL;
+	      continue;
+	    }
+	    sety(f,tbank);
+	    emit(f,"\tjsr\t%s__bankswitch\n",idprefix);
+	    yval=NOVAL;
+	  }
+	  if((p->q1.flags&VAR)&&!strcmp(p->q1.v->identifier,"_fmemcpy"))
+	    emit(f,"\tlda\t#%d\n",cbank>=0?cbank:bankcnum);
+	  emit(f,"\tjsr\t");
+	  emit_obj(f,&p->q1,t);
+	  emit(f,"\n");
+	}
+	pushed-=zm2l(p->q2.val.vmax);
+	if(!calc_regs(p,f!=0)&&v->fi) v->fi->flags&=~ALL_REGS;
+	yval=NOVAL;
+	continue;
+      }
+      if(c==ASSIGN||c==PUSH){
+	if(t==0) ierror(0);
+	if((p->q1.flags&(KONST|DREFOBJ))==KONST&&(t&NQ)==LLONG){
+	  int i;
+	  eval_const(&p->q1.val,t);
+	  for(i=0;i<8;i++){
+	    emit(f,"\tlda\t#%d\n",zm2l(vmax)&255);
+	    vmax=zmrshift(vmax,l2zm(8L));
+	    if(c==PUSH||(p->z.flags&DREFOBJ)){
+	      sety(f,i+((c==PUSH)?pushed:0));
+	      emit(f,"\tsta\t(%s),y\n",(c==PUSH)?mregnames[sp]:mregnames[p->z.reg]);
+	    }else{
+	      p->z.val.vmax=zmadd(p->z.val.vmax,l2zm((long)i));
+	      emit(f,"\tsta\t");
+	      emit_lobyte(f,&p->z,t);
+	      emit(f,"\n");
+	      p->z.val.vmax=zmsub(p->z.val.vmax,l2zm((long)i));
+	    }
+	  }
+	  if(c==PUSH) pushed+=8;
+	  continue;
+	}  
+
+	if(!zmleq(p->q2.val.vmax,l2zm(4L))){
+	  long len=zm2l(p->q2.val.vmax);
+	  int r1,r2,loops,looplab;
+	  if(len>32767) ierror(0);
+	  if(!NOBANKVARS){
+	    int bq=-1,bz=-1,s=-1;
+	    if((p->q1.flags&(VAR|DREFOBJ))==VAR) bq=bank(p->q1.v);
+	    if((p->z.flags&(VAR|DREFOBJ))==VAR) bz=bank(p->z.v);
+	    if(((p->q1.flags&DREFOBJ)&&ISFPOINTER(p->q1.dtyp))||
+	       ((p->z.flags&DREFOBJ)&&ISFPOINTER(p->z.dtyp))){
+	      far_copy(f,p);
+	      continue;
+	    }
+	    if(cbank<0){
+	      if(bq>=0&&bz>=0){
+		if(bq!=bz){
+		  far_copy(f,p);
+		  continue;
+		}
+		s=bq;
+	      }else{
+		if(bq>=0) s=bq;
+		if(bz>=0) s=bz;
+	      }
+	      if(s>=0){
+		sety(f,s);
+		emit(f,"\tjsr\t%s__bankswitch\n",idprefix);
+		yval=NOVAL;
+	      }
+	    }else{
+	      if((bq>=0&&bq!=cbank)||(bz>=0&&bz!=cbank)){
+		far_copy(f,p);
+		continue;
+	      }
+	    }
+	  }
+	  get_acc(f,p,CHAR);
+	  if((p->q1.flags&(DREFOBJ|KONST))==DREFOBJ){
+	    if(p->q1.flags&REG){
+	      r1=p->q1.reg;
+	      if(!reg_pair(r1,&rp)) ierror(0);
+	      if(len>128){
+		emit(f,"\tlda\t%s\n",mregnames[rp.r1]);
+		emit(f,"\tclc\n");
+		if(len&128)
+		  emit(f,"\tadc\t#128\n");
+		emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
+		if(len>255){
+		  emit(f,"\tlda\t%s\n",mregnames[rp.r2]);
+		  emit(f,"\tadc\t#%ld\n",(len>>8)&255);
+		  emit(f,"\tsta\t%s\n",mregnames[rp.r2]);	
+		}else{
+		  emit(f,"\tbcc\t%s%d\n",labprefix,++label);
+		  emit(f,"\tinc\t%s\n",mregnames[rp.r2]);
+		  emit(f,"%s%d:\n",labprefix,label);
+		}
+	      }
+	    }else
+	      ierror(0);
+	  }else if(!indirect(&p->q1)&&len<=128&&(p->q1.flags&(DREFOBJ|KONST))!=KONST){
+	    r1=0;
+	  }else{
+	    Var *v=p->q1.v;
+	    /*if((p->q1.flags&(VARADR|VAR))!=VAR) ierror(0);*/
+	    /*printf("len=%ld %ld\n",len,len&0xff80);*/
+	    r1=get_reg(f,p,POINTER);
+	    if(len>128) p->q1.val.vmax=zmadd(p->q1.val.vmax,l2zm((len-1)&0xff80));
+	    load_address(f,r1,&p->q1,t);
+	    if(len>128) p->q1.val.vmax=zmsub(p->q1.val.vmax,l2zm((len-1)&0xff80));
+	  }
+	  if((p->z.flags&(DREFOBJ|KONST))==DREFOBJ){
+	    if(p->z.flags&REG){
+	      r2=p->z.reg;
+	      if(!reg_pair(r2,&rp)) ierror(0);
+	      if(len>128){
+		emit(f,"\tlda\t%s\n",mregnames[rp.r1]);
+		emit(f,"\tclc\n");
+		if(len&128)
+		  emit(f,"\tadc\t#128\n");
+		emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
+		if(len>255){
+		  emit(f,"\tlda\t%s\n",mregnames[rp.r2]);
+		  emit(f,"\tadc\t#%ld\n",(len>>8)&255);
+		  emit(f,"\tsta\t%s\n",mregnames[rp.r2]);	
+		}else{
+		  emit(f,"\tbcc\t%s%d\n",labprefix,++label);
+		  emit(f,"\tinc\t%s\n",mregnames[rp.r2]);
+		  emit(f,"%s%d:\n",labprefix,label);
+		}
+	      }
+	    }else
+	      ierror(0);
+	  }else if(c==PUSH){
+	    if(len<=128&&pushed==0){
+	      r2=sp;
+	    }else{
+	      r2=get_reg(f,p,POINTER);
+	      if(!reg_pair(r2,&rp)) ierror(0);
+	      emit(f,"\tlda\t%s\n",mregnames[sp]);
+	      emit(f,"\tclc\n");
+	      if(((pushed+(len&128))&255)!=0)
+		emit(f,"\tadc\t#%ld\n",(pushed+(len&128))&255);
+	      emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
+	      emit(f,"\tlda\t%s\n",mregnames[sp2]);
+	      emit(f,"\tadc\t#%ld\n",((pushed+len)>>8)&255);
+	      emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
+	    }
+	  }else if(!indirect(&p->z)&&len<=128){
+	    r2=0;
+	  }else{
+	    Var *v=p->z.v;
+	    r2=get_reg(f,p,POINTER);
+	    if(len>128) p->z.val.vmax=zmadd(p->z.val.vmax,l2zm((len-1)&0xff80));
+	    load_address(f,r2,&p->z,t);
+	    if(len>128) p->z.val.vmax=zmsub(p->z.val.vmax,l2zm((len-1)&0xff80));
+	  }
+	  if(len>128){
+	    get_acc(f,p,POINTER); /* get x */
+	    emit(f,"\tldx\t#%ld\n",(((len-128)>>7)+1)&255);
+	  }
+	  sety(f,(len-1)&127);
+	  if((optsize&&len>4)||len>8){
+	    emit(f,"%s%d:\n",labprefix,looplab=++label);
+	    if(optsize)
+	      loops=1;
+	    else{
+	      if((len&3)==0)
+		loops=4;
+	      else if((len&1)==0)
+		loops=2;
+	      else
+		loops=1;
+	    }
+	  }else
+	    loops=len;
+	  if(r1&&!reg_pair(r1,&rp)) ierror(0);
+	  if(r2&&!reg_pair(r2,&rp2)) ierror(0);
+	  for(i=0;i<loops;i++){
+	    if(r1)
+	      emit(f,"\tlda\t(%s),y\n",mregnames[rp.r1]);
+	    else{
+	      emit(f,"\tlda\t");
+	      emit_obj(f,&p->q1,t);
+	      emit(f,",y\n");
+	    }
+	    if(r2)
+	      emit(f,"\tsta\t(%s),y\n",mregnames[rp2.r1]);
+	    else{
+	      emit(f,"\tsta\t");
+	      emit_obj(f,&p->z,t);
+	      emit(f,",y\n");
+	    }
+	    emit(f,"\tdey\n");
+	  }
+	  if(loops!=len){
+	    emit(f,"\tbpl\t%s%d\n",labprefix,label);
+	  }	  
+	  if(len>128){
+	    emit(f,"\tlda\t%s\n",mregnames[rp.r1]);
+	    emit(f,"\tsec\n");
+	    emit(f,"\tsbc\t#128\n");
+	    emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
+	    emit(f,"\tbcs\t%s%d\n",labprefix,++label);
+	    emit(f,"\tdec\t%s\n",mregnames[rp.r2]);
+	    emit(f,"%s%d:\n",labprefix,label);
+	    emit(f,"\tlda\t%s\n",mregnames[rp2.r1]);
+	    emit(f,"\tsec\n");
+	    emit(f,"\tsbc\t#128\n");
+	    emit(f,"\tsta\t%s\n",mregnames[rp2.r1]);
+	    emit(f,"\tbcs\t%s%d\n",labprefix,++label);
+	    emit(f,"\tdec\t%s\n",mregnames[rp2.r2]);
+	    emit(f,"%s%d:\n",labprefix,label);
+	    emit(f,"\tldy\t#127\n");
+	    emit(f,"\tdex\n");
+	    emit(f,"\tbne\t%s%d\n",labprefix,looplab);
+	  }
+	  yval=NOVAL;
+	  if(c==PUSH)
+	    pushed+=zm2l(p->q2.val.vmax);
+	  continue;
+	}
+	if(c==PUSH){
+	  if(!scratch(p->next,ra,1))
+	    get_acc(f,p,CHAR);
+	  load_lobyte(f,&p->q1,t);
+	  if(zzero&&pushed==0){
+	    emit(f,"\tsta\t(%s)\n",mregnames[sp]);
+	  }else{
+	    sety(f,pushed);
+	    emit(f,"\tsta\t(%s),y\n",mregnames[sp]);
+	  }
+	  if(!zmleq(p->q2.val.vmax,Z1)){
+	    load_hibyte(f,&p->q1,t);
+	    sety(f,pushed+1);
+	    emit(f,"\tsta\t(%s),y\n",mregnames[sp]);
+	  }
+	  if(!zmleq(p->q2.val.vmax,l2zm(2L))){
+	    do_byte3(f,"lda",&p->q1,t);
+	    sety(f,pushed+2);
+	    emit(f,"\tsta\t(%s),y\n",mregnames[sp]);
+	  }
+	  if(!zmleq(p->q2.val.vmax,l2zm(3L))){
+	    do_byte4(f,"lda",&p->q1,t);
+	    sety(f,pushed+3);
+	    emit(f,"\tsta\t(%s),y\n",mregnames[sp]);
+	  }
+
+	  pushed+=zm2l(p->q2.val.vmax);
+	  continue;
+	}
+	if(c==ASSIGN){
+	  int c2m;unsigned long v;
+	  if(isreg(q1)&&isreg(z)&&p->q1.reg==p->z.reg) continue;
+	  if(isacc(q1)){
+	    if(p->q1.reg==rax&&indirect(&p->z)) get_acc(f,p,CHAR);
+	    store_acc(f,&p->z,t);
+	    continue;
+	  }
+	  if(zzero&&!indirect(&p->z)&&(p->q1.flags&(DREFOBJ|KONST))==KONST){
+	    eval_const(&p->q1.val,t);
+	    if(ISFLOAT(t)){
+	      cnv_fp();
+	      v=zum2ul(zm2zum(vmax));
+	    }else
+	      v=zum2ul(vumax);
+	    c2m=1;
+	  }else
+	    c2m=0;
+	  if(!c2m||v!=0)
+	    get_acc(f,p,CHAR);
+	  if(0/*ISCHAR(t)*/){
+	    load_acc(f,&p->q1,t);
+	    store_acc(f,&p->z,t);
+	  }else{
+	    if(!zmleq(p->q2.val.vmax,l2zm(3L))){
+	      if(c2m&&(v&0xFF000000)==0){
+		do_byte4(f,"stz",&p->z,t);
+	      }else{
+		do_byte4(f,"lda",&p->q1,t);
+		do_byte4(f,"sta",&p->z,t);
+	      }
+	    }
+	    if(!zmleq(p->q2.val.vmax,l2zm(2L))){
+	      if(c2m&&(v&0xFF0000)==0){
+		do_byte3(f,"stz",&p->z,t);
+	      }else{
+		do_byte3(f,"lda",&p->q1,t);
+		do_byte3(f,"sta",&p->z,t);
+	      }
+	    }
+	    if(!zmleq(p->q2.val.vmax,l2zm(1L))){
+	      if(isreg(z)&&p->z.reg==rax&&!indirect(&p->q1)){
+		do_hibyte(f,"ldx",&p->q1,t);
+	      }else if(c2m&&(v&0xFF00)==0){
+		do_hibyte(f,"stz",&p->z,t);
+	      }else{
+		load_hibyte(f,&p->q1,t);
+		store_hibyte(f,&p->z,t);
+	      }
+	    }
+	    if(c2m&&(v&0xFF)==0){
+	      do_lobyte(f,"stz",&p->z,t);
+	    }else{
+	      if(isreg(q1)&&ISIDX(p->q1.reg)){
+		store_reg(f,p->q1.reg,&p->z,CHAR);
+	      }else if(isreg(z)&&ISIDX(p->z.reg)){
+		load_reg(f,p->z.reg,&p->q1,t);
+	      }else{
+		load_lobyte(f,&p->q1,t);
+		store_lobyte(f,&p->z,t);
+	      }
+	    }
+	  }
+	}
+	continue;
+      }
+      if(c==ADDRESS){
+	long o=real_offset(&p->q1);
+	get_acc(f,p,CHAR);
+	emit(f,"\tlda\t%s\n",mregnames[fp1]);
+	if(o){
+	  emit(f,"\tclc\n");
+	  if((o&255)!=0)
+	    emit(f,"\tadc\t#%ld\n",real_offset(&p->q1)&255);
+	}
+	if(isacc(z)){
+	  if(o==0) {emit(f,"\tldx\t%s\n",mregnames[fp2]);continue;}
+	  if(o==256){emit(f,"\tldx\t%s\n\tinx\n",mregnames[fp2]);continue;}
+	  if(o==512){emit(f,"\tldx\t%s\n\tinx\n\tinx\n",mregnames[fp2]);continue;}
+	  if(o<256){++label;emit(f,"\tldx\t%s\n\tbcc\t%s%d\n\tinx\n%s%d:\n",mregnames[fp2],labprefix,label,labprefix,label);continue;}
+	  if(o<512){++label;emit(f,"\tldx\t%s\n\tinx\n\tbcc\t%s%d\n\tinx\n%s%d:\n",mregnames[fp2],labprefix,label,labprefix,label);continue;}
+	}
+	store_lobyte(f,&p->z,t);
+	if(isacc(z)) emit(f,"\tpha\n");
+	emit(f,"\tlda\t%s\n",mregnames[fp2]);
+	if(o!=0)
+	  emit(f,"\tadc\t#%ld\n",real_offset(&p->q1)>>8&255);
+	store_hibyte(f,&p->z,t);
+	if(isacc(z)) emit(f,"\tpla\n");
+	continue;
+      }
+
+      if(c==COMPARE||c==TEST){
+	IC *branch=p->next;
+	int pacc=0,bc,bout;
+	if(ISPOINTER(t)) t|=UNSIGNED;
+	while(branch){
+	  if(branch->code>=BEQ&&branch->code<BRA)
+	    break;
+	  if(branch->code!=FREEREG&&branch->code!=ALLOCREG&&branch->code!=NOP)
+	    ierror(0);
+	  branch=branch->next;
+	}
+	bc=branch->code;
+	bout=branch->typf;
+	if(c==TEST){
+	  p->q2.flags=KONST;
+	  gval.vmax=Z0;
+	  eval_const(&gval,MAXINT);
+	  insert_const(&p->q2.val,t);
+	}
+	if((t&NU)==(UNSIGNED|CHAR)&&(bc==BLE||bc==BGT)&&(p->q2.flags&(DREFOBJ|KONST))==KONST){
+	  eval_const(&p->q2.val,t);
+	  if(!zmeqto(vmax,l2zm(255L))){
+	    vmax=zmadd(vmax,Z1);
+	    gval.vmax=vmax;
+	    eval_const(&gval,t);
+	    insert_const(&p->q2.val,t);
+	    if(bc==BLE) bc=BLT; else bc=BGE;
+	    branch->code=bc;
+	  }
+	}
+	if(((t&NQ)==SHORT||(t&NQ)==INT||(t&NQ)==LONG)&&(bc==BNE||bc==BEQ)&&isconst(q2)&&!isacc(q1)){
+	  eval_const(&p->q2.val,t);
+	  if(zmeqto(vmax,Z0)&&zumeqto(vumax,ZU0)){
+	    if(pacc=cmp_get_acc(f,p,branch))
+	      bout=++label;
+	    load_lobyte(f,&p->q1,t);
+	    do_hibyte(f,"ora",&p->q1,t);
+	    if((t&NQ)==LONG){
+	      do_byte3(f,"ora",&p->q1,t);
+	      do_byte4(f,"ora",&p->q1,t);
+	    }
+	    emit(f,"\t%s\t%s%d\n",(bc==BNE)?"bne":"beq",labprefix,bout);
+	    if(pacc){
+	      reload_acc(f);
+	      add_cmplist(bout,branch->typf,pacc);
+	    }
+	    continue;
+	  }
+	}
+	if(ieee&&ISFLOAT(t)){
+	  if(!ieee) ierror(0);
+	  t&=NQ;
+	  if(regs[LAST_PAIR]) ierror(0);
+	  regs[LAST_PAIR]=1;
+	  if(regs[ra]||regs[rax])
+	    ierror(0);
+	  load_address(f,LAST_PAIR,&p->q2,t);
+	  BSET(regused,t3);
+	  BSET(regused,t4);
+	  emit(f,"\tjsr\t%s__fload%c\n",idprefix,(t==FLOAT?'s':'d'));
+	  yval=NOVAL;
+	  load_address(f,LAST_PAIR,&p->q1,t);
+	  emit(f,"\tjsr\t%s__fcmp%c\n",idprefix,(t==FLOAT?'s':'d'));
+	  yval=NOVAL;
+	  regs[LAST_PAIR]=0;
+	  if(bc==BLT||bc==BLE)
+	    emit(f,"\tbmi\t%s%d\n",labprefix,bout);
+	  else if(bc==BGT|bc==BGE)
+	    emit(f,"\tbvs\t%s%d\n",labprefix,bout);
+	  if(bc==BEQ||bc==BLE||bc==BGE)
+	    emit(f,"\tbeq\t%s%d\n",labprefix,bout);
+	  if(bc==BNE)
+	    emit(f,"\tbne\t%s%d\n",labprefix,bout);
+	  continue;
+	}
+	if(ISCHAR(t)){
+	  char *s=0;
+	  if(isreg(q1)&&ISIDX(p->q1.reg)&&!indirect(&p->q2)&&(bc==BEQ||bc==BNE||(t&UNSIGNED))){
+	    static char buf[4]="cpr";
+	    s=buf;s[2]=mregnames[p->q1.reg][0];
+	  }else{
+	    if(pacc=cmp_get_acc(f,p,branch))
+	      bout=++label;
+	    load_acc(f,&p->q1,t);
+	    if(bc==BEQ||bc==BNE||(t&UNSIGNED)){
+	      s="cmp";
+	    }else{
+	      if(bc==BLT||bc==BGE)
+		emit(f,"\tsec\n");
+	      else
+		emit(f,"\tclc\n");
+	      s="sbc";
+	    }
+	  }
+	  if(c==TEST)
+	    emit(f,"\t%s\t#0\n",s);
+	  else
+	    do_lobyte(f,s,&p->q2,t);
+	  if(bc==BEQ)
+	    emit(f,"\tbeq\t%s%d\n",labprefix,bout);
+	  else if(bc==BNE)
+	    emit(f,"\tbne\t%s%d\n",labprefix,bout);
+	  else if(t&UNSIGNED){
+	    if(bc==BLT)
+	      emit(f,"\tbcc\t%s%d\n",labprefix,bout);
+	    else if(bc==BGE)
+	      emit(f,"\tbcs\t%s%d\n",labprefix,bout);
+	    else if(bc==BLE){
+	      emit(f,"\tbcc\t%s%d\n",labprefix,bout);
+	      emit(f,"\tbeq\t%s%d\n",labprefix,bout);
+	    }else if(bc==BGT){
+	      emit(f,";\n\tbeq\t%s%d\n",labprefix,++label);
+	      emit(f,"\tbcs\t%s%d\n",labprefix,bout);
+	      emit(f,"%s%d:\n",labprefix,label);
+	    }else
+	      ierror(0);
+	  }else{
+	    emit(f,"\tbvc\t%s%d\n",labprefix,++label);
+	    emit(f,"\teor\t#128\n");
+	    emit(f,"%s%d:\n",labprefix,label);
+	    if(bc==BLT||bc==BLE)
+	      emit(f,"\tbmi\t%s%d\n",labprefix,bout);
+	    else
+	      emit(f,"\tbpl\t%s%d\n",labprefix,bout);
+	  }
+	  if(pacc){
+	    reload_acc(f);
+	    add_cmplist(bout,branch->typf,pacc);
+	  }
+	  continue;
+	}else if(bc==BEQ||bc==BNE||(t&UNSIGNED)||ISFPOINTER(t)){
+	  int in=0;
+	  if(pacc=cmp_get_acc(f,p,branch))
+	    bout=++label;
+	  if(ISLONG(t)){
+	    do_byte4(f,"lda",&p->q1,t);
+	    if(c==TEST)
+	      emit(f,"\tcmp\t#0\n");
+	    else
+	      do_byte4(f,"cmp",&p->q2,t);
+	    if(bc==BEQ)
+	      emit(f,"\tbne\t%s%d\n",labprefix,in=++label);
+	    else if(bc==BNE)
+	      emit(f,"\tbne\t%s%d\n",labprefix,bout);
+	    else if(bc==BLT||bc==BLE){
+	      emit(f,"\tbcc\t%s%d\n",labprefix,bout);
+	      emit(f,"\tbne\t%s%d\n",labprefix,in=++label);
+	    }else if(bc==BGE||bc==BGT){
+	      emit(f,"\tbcc\t%s%d\n",labprefix,in=++label);	
+	      emit(f,"\tbne\t%s%d\n",labprefix,bout);
+	    }else
+	      ierror(0);
+	  }
+	  if(ISLONG(t)||ISFPOINTER(t)){
+	    do_byte3(f,"lda",&p->q1,t);
+	    if(c==TEST)
+	      emit(f,"\tcmp\t#0\n");
+	    else
+	      do_byte3(f,"cmp",&p->q2,t);
+	    if(bc==BEQ)
+	      emit(f,"\tbne\t%s%d\n",labprefix,in?in:(in=++label));
+	    else if(bc==BNE)
+	      emit(f,"\tbne\t%s%d\n",labprefix,bout);
+	    else if(bc==BLT||bc==BLE){
+	      emit(f,"\tbcc\t%s%d\n",labprefix,bout);
+	      emit(f,"\tbne\t%s%d\n",labprefix,in?in:(in=++label));
+	    }else if(bc==BGE||bc==BGT){
+	      emit(f,"\tbcc\t%s%d\n",labprefix,in?in:(in=++label));	
+	      emit(f,"\tbne\t%s%d\n",labprefix,bout);
+	    }else
+	      ierror(0);	  
+	  }
+	  if(isacc(q1)){
+	    if(!indirect(&p->q2)){
+	      do_hibyte(f,"cpx",&p->q2,t);
+	    }else{
+	      int r=get_reg(f,p,CHAR);
+	      emit(f,"\tpha\n");
+	      load_hibyte(f,&p->q2,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r]);
+	      emit(f,"\tpla\n");
+	      emit(f,"\tcpx\t%s\n",mregnames[r]);
+	    }
+	  }else{
+	    load_hibyte(f,&p->q1,t);
+	    if(c==TEST)
+	      emit(f,"\tcmp\t#0\n");
+	    else
+	      do_hibyte(f,"cmp",&p->q2,t);
+	  }
+	  if(bc==BEQ)
+	    emit(f,"\tbne\t%s%d\n",labprefix,in?in:(in=++label));
+	  else if(bc==BNE)
+	    emit(f,"\tbne\t%s%d\n",labprefix,bout);
+	  else if(bc==BLT||bc==BLE){
+	    emit(f,"\tbcc\t%s%d\n",labprefix,bout);
+	    emit(f,"\tbne\t%s%d\n",labprefix,in?in:(in=++label));
+	  }else if(bc==BGE||bc==BGT){
+	    emit(f,"\tbcc\t%s%d\n",labprefix,in?in:(in=++label));
+	    emit(f,"\tbne\t%s%d\n",labprefix,bout);
+	  }else
+	    ierror(0);
+	  load_lobyte(f,&p->q1,t);
+	  if(c==TEST)
+	    emit(f,"\tcmp\t#0\n");
+	  else
+	    do_lobyte(f,"cmp",&p->q2,t);
+	  if(bc==BEQ)
+	    emit(f,"\tbeq\t%s%d\n",labprefix,bout);
+	  else if(bc==BNE)
+	    emit(f,"\tbne\t%s%d\n",labprefix,bout);
+	  else if(bc==BLT)
+	    emit(f,"\tbcc\t%s%d\n",labprefix,bout);
+	  else if(bc==BGE)
+	    emit(f,"\tbcs\t%s%d\n",labprefix,bout);	
+	  else if(bc==BLE){
+	    emit(f,"\tbcc\t%s%d\n",labprefix,bout);
+	    emit(f,"\tbeq\t%s%d\n",labprefix,bout);
+	  }else if(bc==BGT){
+	    emit(f,"\tbcc\t%s%d\n",labprefix,in);
+	    emit(f,"\tbne\t%s%d\n",labprefix,bout);
+	  }else
+	    ierror(0);
+	  if(in)
+	    emit(f,"%s%d:\n",labprefix,in);
+	  if(pacc){
+	    reload_acc(f);
+	    add_cmplist(bout,branch->typf,pacc);
+	  }
+	  continue;
+	}else{
+	  if(bc==BGT||bc==BLE){
+	    obj o;
+	    if(isacc(q1)){
+	      int r;
+	      if(pacc=cmp_get_acc(f,p,branch))
+		bout=++label;
+	      r=get_reg(f,p,CHAR);
+	      emit(f,"\tsta\t%s\n",mregnames[r]);
+	      load_lobyte(f,&p->q2,t);
+	      emit(f,"\tcmp\t%s\n",mregnames[r]);
+	      emit(f,"\tstx\t%s\n",mregnames[r]);
+	      load_hibyte(f,&p->q2,t);
+	      emit(f,"\tsbc\t%s\n",mregnames[r]);
+	      emit(f,"\tbvc\t%s%d\n",labprefix,++label);
+	      emit(f,"\teor\t#128\n");
+	      emit(f,"%s%d:\n",labprefix,label);
+	      if(bc==BGT)
+		emit(f,"\tbmi\t%s%d\n",labprefix,bout);
+	      else
+		emit(f,"\tbpl\t%s%d\n",labprefix,bout);
+	      if(pacc){
+		reload_acc(f);
+		add_cmplist(bout,branch->typf,pacc);
+	      }
+	      continue;
+	    }else{
+	      o=p->q1;p->q1=p->q2;p->q2=o;
+	      if(bc==BGT) bc=BLT; else bc=BGE;
+	    }
+	  }
+	  if(pacc=cmp_get_acc(f,p,branch))
+	    bout=++label;
+	  if(ISLONG(t)){
+	    load_lobyte(f,&p->q1,t);
+	    do_lobyte(f,"cmp",&p->q2,t);
+	    load_hibyte(f,&p->q1,t);
+	    do_hibyte(f,"sbc",&p->q2,t);
+	    do_byte3(f,"lda",&p->q1,t);
+	    do_byte3(f,"sbc",&p->q2,t);
+	    do_byte4(f,"lda",&p->q1,t);
+	    do_byte4(f,"sbc",&p->q2,t);
+	  }else{
+	    load_lobyte(f,&p->q1,t);
+	    do_lobyte(f,"cmp",&p->q2,t);
+	    load_hibyte(f,&p->q1,t);
+	    do_hibyte(f,"sbc",&p->q2,t);
+	  }
+	  emit(f,"\tbvc\t%s%d\n",labprefix,++label);
+	  emit(f,"\teor\t#128\n");
+	  emit(f,"%s%d:\n",labprefix,label);
+	  if(bc==BLT)
+	    emit(f,"\tbmi\t%s%d\n",labprefix,bout);
+	  else if(bc==BGE)
+	    emit(f,"\tbpl\t%s%d\n",labprefix,bout);
+	  else
+	    ierror(0);
+	  if(pacc){
+	    reload_acc(f);
+	    add_cmplist(bout,branch->typf,pacc);
+	  }
+	  continue; 
+	}
+	ierror(0);
+      }
+
+
+      if((c==ADD||c==SUB)&&ISRIDX(z)&&isconst(q2)){
+	eval_const(&p->q2.val,t);
+	if(zmeqto(vmax,l2zm(-1L))){ 
+	  vmax=Z1; vumax=ZU1; 
+	  if(c==ADD) c=SUB; else c=ADD;
+	}
+	if(zmeqto(vmax,Z1)&&zumeqto(vumax,ZU1)){
+	  if(indirect(&p->q1)){
+	    get_acc(f,p,CHAR);
+	    load_reg(f,p->z.reg,&p->q1,t);
+	  }else
+	    do_lobyte(f,"ldx",&p->q1,t);
+	  emit(f,"\t%s%s\n",(c==ADD)?"in":"de",mregnames[p->z.reg]);
+	  continue;
+	}
+      }
+
+      if((c==LSHIFT||c==RSHIFT)&&isconst(q2)&&
+	 (
+	 (isreg(q1)&&isreg(z)&&p->q1.reg==p->z.reg&&p->z.reg!=ra&&p->z.reg!=rax)||
+	 (!indirect(&p->q1)&&compare_objects(&p->q1,&p->z))
+	 )
+	 ){
+	long l;
+	eval_const(&p->q2.val,q2typ(p));
+	l=zm2l(vmax);
+	/*TODO: allow larger types */
+	if((l<3||(iszpage(&p->z)&&l<5))&&(t&NQ)<=LONG){
+	  if(c==RSHIFT&&(!c02&&!(t&UNSIGNED)))
+	    get_acc(f,p,CHAR);
+	  incmem(f,&p->z,t,c,l);
+	  continue;
+	}
+      }
+
+      if(c==LSHIFT||c==RSHIFT){
+	long l=-1,m;int loop=0,r=0,r2=0,r3=0,outl=0,same=0;
+	if(isconst(q2)){
+	  eval_const(&p->q2.val,q2typ(p));
+	  l=zm2l(vmax);
+	  loop=0;
+	}else
+	  loop=1;
+	if(l>=0&&optsize){
+	  if(c==LSHIFT&&(l&7)>6) 
+	    loop=1;
+	  else if(c==RSHIFT&&(t&UNSIGNED)&&(l&7)>3)
+	    loop=1;
+	  else if(c==RSHIFT&&!(t&UNSIGNED)&&(l&7)>2)
+	    loop=1;
+	}
+
+	if(ISLONG(t)){
+	  if(!indirect(&p->z)&&
+	     (isreg(z)||(p->z.flags&(VAR|DREFOBJ))==VAR)&&
+	     (iszpage(&p->z)||(l&7)<=2)&&
+	     (!(p->q2.flags&REG)||!(p->z.flags&REG)||p->q2.reg!=p->z.reg)&&
+	     (!(p->q2.flags&VAR)||!(p->z.flags&VAR)||p->q2.v!=p->z.v)
+	     ){
+	    if(isreg(z))
+	      strcpy(mregnames[REGDUMMY1],mregnames[p->z.reg]);
+	    else if(p->z.v->storage_class==STATIC)
+	      sprintf(mregnames[REGDUMMY1],"%s%ld",labprefix,zm2l(p->z.v->offset));
+	    else
+	      sprintf(mregnames[REGDUMMY1],"%s%s",idprefix,p->z.v->identifier);
+	    strcpy(mregnames[REGDUMMY2],mregnames[REGDUMMY1]);
+	    strcpy(mregnames[REGDUMMY3],mregnames[REGDUMMY1]);
+	    strcat(mregnames[REGDUMMY1],"+1");
+	    strcat(mregnames[REGDUMMY2],"+2");
+	    if(c!=RSHIFT||(t&UNSIGNED))
+	      strcat(mregnames[REGDUMMY3],"+3");
+	    if(c==RSHIFT&&!(t&UNSIGNED)){
+	      r=REGDUMMY2;r2=REGDUMMY1;r3=REGDUMMY3;
+	    }else{
+	      r=REGDUMMY1;r2=REGDUMMY2;r3=REGDUMMY3;
+	    }
+	    if(compare_objects(&p->q1,&p->z)) same=1;
+	  }else{
+	    r2=get_reg(f,p,CHAR);
+	    r3=get_reg(f,p,CHAR);
+	  }
+	}
+	if(!ISCHAR(t)&&r2!=REGDUMMY1&&r2!=REGDUMMY2)
+	  r=get_reg(f,p,CHAR);
+	if(ISLONG(t)){
+	  get_acc(f,p,CHAR);
+	  if(l>=24){
+	    if(c==LSHIFT){
+	      load_lobyte(f,&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r3]);
+	      emit(f,"\tlda\t#0\n");
+	      emit(f,"\tsta\t%s\n",mregnames[r]);
+	      emit(f,"\tsta\t%s\n",mregnames[r2]);
+	    }else if(c==RSHIFT&&!(t&UNSIGNED)){
+	      do_byte4(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r3]);
+	      sety(f,0);
+	      emit(f,"\tcmp\t#0\n");
+	      emit(f,"\tbpl\t%s%d\n",labprefix,++label);
+	      emit(f,"\tdey\n");
+	      emit(f,"%s%d:\n",labprefix,label);
+	      emit(f,"\tsty\t%s\n",mregnames[r]);
+	      emit(f,"\tsty\t%s\n",mregnames[r2]);
+	      emit(f,"\ttya\n");
+	      yval=NOVAL;
+	    }else{
+	      do_byte4(f,"lda",&p->q1,t);
+	      sety(f,0);
+	      emit(f,"\tsty\t%s\n",mregnames[r3]);
+	      emit(f,"\tsty\t%s\n",mregnames[r2]);
+	      emit(f,"\tsty\t%s\n",mregnames[r]);
+	    }
+	  }else if(l>=16){
+	    if(c==LSHIFT){
+	      load_lobyte(f,&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r2]);
+	      load_hibyte(f,&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r3]);
+	      emit(f,"\tlda\t#0\n");
+	      emit(f,"\tsta\t%s\n",mregnames[r]);
+	    }else if(c==RSHIFT&&!(t&UNSIGNED)){
+	      do_byte3(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r3]);
+	      do_byte4(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r2]);
+	      sety(f,0);
+	      emit(f,"\tcmp\t#0\n");
+	      emit(f,"\tbpl\t%s%d\n",labprefix,++label);
+	      emit(f,"\tdey\n");
+	      emit(f,"%s%d:\n",labprefix,label);
+	      emit(f,"\tsty\t%s\n",mregnames[r]);
+	      emit(f,"\ttya\n");
+	      yval=NOVAL;
+	    }else{
+	      do_byte4(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r]);
+	      do_byte3(f,"lda",&p->q1,t);
+	      sety(f,0);
+	      emit(f,"\tsty\t%s\n",mregnames[r2]);
+	      emit(f,"\tsty\t%s\n",mregnames[r3]);
+	    }
+	  }else if(l>=8){
+	    if(c==LSHIFT){
+	      do_byte3(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r3]);
+	      load_hibyte(f,&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r2]);
+	      load_lobyte(f,&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r]);
+	      emit(f,"\tlda\t#0\n");
+	    }else if(c==RSHIFT&&!(t&UNSIGNED)){
+	      load_hibyte(f,&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r3]);
+	      do_byte3(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r2]);
+	      do_byte4(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r]);
+	      sety(f,0);
+	      emit(f,"\tcmp\t#0\n");
+	      emit(f,"\tbpl\t%s%d\n",labprefix,++label);
+	      emit(f,"\tdey\n");
+	      emit(f,"%s%d:\n",labprefix,label);
+	      emit(f,"\ttya\n");
+	      yval=NOVAL;
+	    }else{
+	      if(same){
+		load_hibyte(f,&p->q1,t);
+		do_byte3(f,"ldy",&p->q1,t);
+		yval=NOVAL;
+		emit(f,"\tsty\t%s\n",mregnames[r]);
+		do_byte4(f,"ldy",&p->q1,t);
+		emit(f,"\tsty\t%s\n",mregnames[r2]);
+		sety(f,0);
+		emit(f,"\tsty\t%s\n",mregnames[r3]);
+	      }else{
+		emit(f,"\tlda\t#0\n");
+		emit(f,"\tsta\t%s\n",mregnames[r3]);
+		do_byte4(f,"lda",&p->q1,t);
+		emit(f,"\tsta\t%s\n",mregnames[r2]);
+		do_byte3(f,"lda",&p->q1,t);
+		emit(f,"\tsta\t%s\n",mregnames[r]);
+		load_hibyte(f,&p->q1,t);
+	      }
+	    }
+	  }else if(c==RSHIFT&&!(t&UNSIGNED)){
+	    if(!same){
+	      load_lobyte(f,&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r3]);
+	      load_hibyte(f,&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r2]);
+	      do_byte3(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r]);
+	    }
+	    do_byte4(f,"lda",&p->q1,t);
+	  }else{
+	    if(!same){
+	      do_byte4(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r3]);
+	      do_byte3(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r2]);
+	      load_hibyte(f,&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r]);
+	    }
+	    load_lobyte(f,&p->q1,t);
+	  }
+	}else
+	  get_acc(f,p,t);
+	if(!ISLONG(t)){
+	  if(l>=8){
+	    if(!ISSHORT(t)) ierror(0);
+	    if(c==LSHIFT){
+	      if(indirect(&p->q1)){
+		load_lobyte(f,&p->q1,t);
+		emit(f,"\ttax\n");
+		emit(f,"\tlda\t#0\n");
+	      }else{
+		if(isacc(q1))
+		  emit(f,"\ttax\n");
+		else
+		  do_lobyte(f,"ldx",&p->q1,t);
+		emit(f,"\tlda\t#0\n");
+	      }
+	    }else{
+	      load_hibyte(f,&p->q1,t);
+	      emit(f,"\tldx\t#0\n");
+	      if(!(t&UNSIGNED)){
+		emit(f,"\tcmp\t#0\n");
+		emit(f,"\tbpl\t%s%d\n",labprefix,++label);
+		emit(f,"\tdex\n");
+		emit(f,"%s%d:\n",labprefix,label);
+	      }
+	    }
+	  }else
+	    load_acc(f,&p->q1,t);
+	}
+	if(l>=0) l&=7;
+	m=l;
+	if(ISSHORT(t)&&(l>0||loop))
+	  emit(f,"\tstx\t%s\n",mregnames[r]);
+	if(loop){
+	  if(l>=0)
+	    sety(f,l);
+	  else{
+	    if(indirect(&p->q2)){
+	      emit(f,"\tpha\n");
+	      load_lobyte(f,&p->q2,q2typ(p));
+	      emit(f,"\ttay\n");
+	      emit(f,"\tpla\n");
+	      emit(f,"\tcpy\t#0\n");
+	    }else{
+	      emit(f,"\tldy\t");
+	      emit_lobyte(f,&p->q2,q2typ(p));
+	      emit(f,"\n");
+	    }
+	    outl=++label;
+	    emit(f,"\tbeq\t%s%d\n",labprefix,outl);
+	  }
+	  emit(f,"%s%d:\n",labprefix,++label);
+	}else{
+	  if(ISCHAR(t))
+	    l&=7;
+	  else if(ISSHORT(t))
+	    l&=15;
+	  else
+	    l&=31;
+	}
+	while(l>0||loop){
+	  if(c==LSHIFT){
+	    emit(f,"\tasl\n");
+	    if(!ISCHAR(t))
+	      emit(f,"\trol\t%s\n",mregnames[r]);
+	    if(ISLONG(t)){
+	      emit(f,"\trol\t%s\n",mregnames[r2]);
+	      emit(f,"\trol\t%s\n",mregnames[r3]);
+	    }
+	  }else if(t&UNSIGNED){
+	    emit(f,"\tlsr");
+	    if(ISLONG(t)){
+	      emit(f,"\t%s\n",mregnames[r3]);
+	      emit(f,"\tror\t%s\n",mregnames[r2]);
+	      emit(f,"\tror");
+	    }
+	    if(!ISCHAR(t)){
+	      emit(f,"\t%s\n",mregnames[r]);
+	      emit(f,"\tror");
+	    }
+	    emit(f,"\n");
+	  }else{
+	    if(ISLONG(t)){
+	      if(ce02)
+		emit(f,"\tasr\n");
+	      else{
+		emit(f,"\tcmp\t#128\n");
+		emit(f,"\tror\n");
+	      }
+	      emit(f,"\tror\t%s\n",mregnames[r]);
+	      emit(f,"\tror\t%s\n",mregnames[r2]);
+	      emit(f,"\tror\t%s\n",mregnames[r3]);
+	    }else{
+	      if(!ISCHAR(t)){
+		emit(f,"\tcpx\t#128\n");
+		emit(f,"\tror\t%s\n",mregnames[r]);
+	      }else
+		emit(f,"\tcmp\t#128\n");
+	      emit(f,"\tror\n");
+	    }
+	  }
+	  if(loop){
+	    emit(f,"\tdey\n");
+	    emit(f,"\tbne\t%s%d\n",labprefix,label);
+	    if(outl) emit(f,"%s%d:\n",labprefix,outl);
+	    yval=0;
+	    break;
+	  }
+	  l--;
+	}
+	if(ISLONG(t)){
+	  if(c==RSHIFT&&!(t&UNSIGNED)){
+	    do_byte4(f,"sta",&p->z,t);
+	    if(r!=REGDUMMY2){
+	      emit(f,"\tlda\t%s\n",mregnames[r]);
+	      do_byte3(f,"sta",&p->z,t);
+	      emit(f,"\tlda\t%s\n",mregnames[r2]);
+	      store_hibyte(f,&p->z,t);
+	      emit(f,"\tlda\t%s\n",mregnames[r3]);
+	      store_lobyte(f,&p->z,t);
+	    }
+	  }else{
+	    store_lobyte(f,&p->z,t);
+	    if(r!=REGDUMMY1){
+	      emit(f,"\tlda\t%s\n",mregnames[r]);
+	      store_hibyte(f,&p->z,t);
+	      emit(f,"\tlda\t%s\n",mregnames[r2]);
+	      do_byte3(f,"sta",&p->z,t);
+	      emit(f,"\tlda\t%s\n",mregnames[r3]);
+	      do_byte4(f,"sta",&p->z,t);
+	    }
+	  }
+	}else{
+	  if(!ISCHAR(t)&&(m>0||loop))
+	    emit(f,"\tldx\t%s\n",mregnames[r]);
+	  if(ISCHAR(t)||indirect(&p->z))
+	    store_acc(f,&p->z,t);
+	  else{
+	    store_lobyte(f,&p->z,t);
+	    if(!isreg(z)||p->z.reg!=rax){
+	      emit(f,"\tstx\t");
+	      emit_hibyte(f,&p->z,t);
+	      emit(f,"\n");
+	    }
+	  }
+	}
+	continue;
+      }
+
+      if((c>=OR&&c<=AND)||(c>=LSHIFT&&c<=MOD)||c==ADDI2P||c==SUBIFP){
+	char *s;int t2=t,pt=p->typf2;
+	if(!isacc(z)){
+	  /* TODO: check other operations */
+	  if((c==ADD||c==SUB||c==AND||c==XOR||c==OR||c==ADDI2P||c==SUBIFP)&&isacc(q1)&&scratch(p->next,ra,1))
+	    ;
+	  else{
+	    if((c==ADDI2P||c==SUBIFP)&&(p->typf2&NU)==CHAR)
+	      get_acc(f,p,INT);
+	    else
+	      get_acc(f,p,CHAR);
+	  }
+	}
+	if(c==ADDI2P||c==SUBIFP){
+	  if(c==ADDI2P) c=ADD; else c=SUB;
+	  t=UNSIGNED|INT;
+	  if((pt&NQ)==POINTER&&(p->q1.flags&(KONST|DREFOBJ))==KONST){
+	    eval_const(&p->q1.val,POINTER);
+	    insert_const(&p->q1.val,UNSIGNED|INT);
+	  }
+	}
+	if(c>=OR&&c<=AND)
+	  s=logicals[c-OR];
+	else
+	  s=arithmetics[c-LSHIFT];
+      
+	if(ISFLOAT(t)){
+	  if(!ieee) ierror(0);
+	  t&=NQ;
+	  if(regs[LAST_PAIR]) ierror(0);
+	  get_acc(f,p,INT);
+	  regs[LAST_PAIR]=1;
+	  load_address(f,LAST_PAIR,&p->q1,t);
+	  BSET(regused,t3);
+	  BSET(regused,t4);
+	  emit(f,"\tjsr\t%s__fload%c\n",idprefix,(t==FLOAT?'s':'d'));
+	  yval=NOVAL;
+	  load_address(f,LAST_PAIR,&p->q2,t);
+	  emit(f,"\tjsr\t%s__f%s%c\n",idprefix,ename[c],(t==FLOAT?'s':'d'));
+	  yval=NOVAL;
+	  load_address(f,LAST_PAIR,&p->z,t);
+	  emit(f,"\tjsr\t%s__fstore%c\n",idprefix,(t==FLOAT?'s':'d'));
+	  yval=NOVAL;
+	  regs[LAST_PAIR]=0;
+	  continue;
+	}else if(ISLONG(t)){
+	  long l;int cnst=0;
+	  if(c==ADD) emit(f,"\tclc\n");
+	  if(c==SUB) emit(f,"\tsec\n");
+	  if((p->q2.flags&(KONST|DREFOBJ))==KONST){
+	    eval_const(&p->q2.val,t);
+	    l=zm2l(vmax);
+	    cnst=1;
+	  }
+	  if(cnst&&c==AND&&(l&0xff)==0) emit(f,"\tlda\t#0\n");
+	  else if(cnst&&c==OR&&(l&0xff)==0xff) emit(f,"\tlda\t#255\n");
+	  else{
+	    load_lobyte(f,&p->q1,t);
+	    if(!(cnst&&((c==AND&&(l&0xff)==0xff)||(c==OR&&(l&0xff)==0)||(c==XOR&&(l&0xff)==0)))) do_lobyte(f,s,&p->q2,t);
+	  }
+	  store_lobyte(f,&p->z,t);
+	  if(cnst&&c==AND&&(l&0xff00)==0) emit(f,"\tlda\t#0\n");
+	  else if(cnst&&c==OR&&(l&0xff00)==0xff00) emit(f,"\tlda\t#255\n");
+	  else{
+	    load_hibyte(f,&p->q1,t);
+	    if(!(cnst&&((c==AND&&(l&0xff00)==0xff00)||(c==OR&&(l&0xff00)==0)||(c==XOR&&(l&0xff00)==0)))) do_hibyte(f,s,&p->q2,t);
+	  }
+	  store_hibyte(f,&p->z,t);
+	  if(cnst&&c==AND&&(l&0xff0000)==0) emit(f,"\tlda\t#0\n");
+	  else if(cnst&&c==OR&&(l&0xff0000)==0xff0000) emit(f,"\tlda\t#255\n");
+	  else{
+	    do_byte3(f,"lda",&p->q1,t);
+	    if(!(cnst&&((c==AND&&(l&0xff0000)==0xff0000)||(c==OR&&(l&0xff0000)==0)||(c==XOR&&(l&0xff0000)==0)))) do_byte3(f,s,&p->q2,t);
+	  }
+	  do_byte3(f,"sta",&p->z,t);
+	  if(cnst&&c==AND&&(l&0xff000000)==0) emit(f,"\tlda\t#0\n");
+	  else if(cnst&&c==OR&&(l&0xff000000)==0xff000000) emit(f,"\tlda\t#255\n");
+	  else{
+	    do_byte4(f,"lda",&p->q1,t);
+	    if(!(cnst&&((c==AND&&(l&0xff000000)==0xff000000)||(c==OR&&(l&0xff000000)==0)||(c==XOR&&(l&0xff000000)==0)))) do_byte4(f,s,&p->q2,t);
+	  }
+	  do_byte4(f,"sta",&p->z,t);
+	  continue;
+	}else if(ISCHAR(t)){
+	  load_acc(f,&p->q1,t);
+	  if(c02&&(c==ADD||c==SUB)&&(p->q2.flags&(KONST|DREFOBJ))==KONST){
+	    eval_const(&p->q2.val,t);
+	    if(zmeqto(vmax,Z1)||zmeqto(vmax,l2zm(2L))){
+	      if(zmeqto(vmax,l2zm(2L)))
+		emit(f,"\t%s\n",c==ADD?"ina":"dea");
+	      emit(f,"\t%s\n",c==ADD?"ina":"dea");
+	      store_acc(f,&p->z,t);
+	      continue;
+	    }
+	  }
+	  if(c==ADD) emit(f,"\tclc\n");
+	  if(c==SUB) emit(f,"\tsec\n");
+	  if(isreg(q2)&&ISIDX(p->q2.reg)){
+	    int r=get_reg(f,p,CHAR);
+	    emit(f,"\tst%s\t%s\n",mregnames[p->q2.reg],mregnames[r]);
+	    p->q2.flags=REG;
+	    p->q2.reg=r;
+	  }
+	  do_lobyte(f,s,&p->q2,t);
+	  store_acc(f,&p->z,t);
+	}else if(c==ADD||c==SUB){
+	  int a,r;long l=1;
+	  if(isconst(q2)){
+	    eval_const(&p->q2.val,t2);
+	    l=zm2l(vmax);
+	    if(isacc(z)&&(l&0xffff)<=768){
+	      load_acc(f,&p->q1,t);
+	      if(c==ADD){
+		if(l&0xff)
+		  emit(f,"\tclc\n\tadc\t#%d\n",(int)(l&255));
+		l&=0xffff;
+		if(l==256){emit(f,"\tinx\n");continue;}
+		if(l==512){emit(f,"\tinx\n\tinx\n");continue;}
+		if(l==768){emit(f,"\tinx\n\tinx\n\tinx\n");continue;}
+		if(l<256){++label;emit(f,"\tbcc\t%s%d\n\tinx\n%s%d:\n",labprefix,label,labprefix,label);continue;}
+		if(l<512){++label;emit(f,"\tinx\n\tbcc\t%s%d\n\tinx\n%s%d:\n",labprefix,label,labprefix,label);continue;}
+		if(l<768){++label;emit(f,"\tinx\n\tinx\n\tbcc\t%s%d\n\tinx\n%s%d:\n",labprefix,label,labprefix,label);continue;}
+	      }else{
+		if(l&0xff)
+		  emit(f,"\tsec\n\tsbc\t#%d\n",(int)(l&255));
+		l&=0xffff;
+		if(l==256){emit(f,"\tdex\n");continue;}
+		if(l==512){emit(f,"\tdex\n\tdex\n");continue;}
+		if(l==768){emit(f,"\tdex\n\tdex\n\tdex\n");continue;}
+		if(l<256){++label;emit(f,"\tbcs\t%s%d\n\tdex\n%s%d:\n",labprefix,label,labprefix,label);continue;}
+		if(l<512){++label;emit(f,"\tdex\n\tbcs\t%s%d\n\tdex\n%s%d:\n",labprefix,label,labprefix,label);continue;}
+		if(l<768){++label;emit(f,"\tdex\n\tdex\n\tbcs\t%s%d\n\tdex\n%s%d:\n",labprefix,label,labprefix,label);continue;}
+	      }
+	    }
+	    l&=0xff00;
+	  }
+	  if(isreg(z)&&p->z.reg==rax) a=1; else a=0;
+	  if((t2&NU)==CHAR&&(p->q2.flags&(KONST|DREFOBJ))!=KONST){
+	    get_acc(f,p,INT);
+	    emit(f,"\tldx\t#0\n");
+	    load_lobyte(f,&p->q2,t);
+	    emit(f,"\tbpl\t%s%d\n",labprefix,++label);
+	    emit(f,"\tdex\n");
+	    emit(f,"%s%d:\n",labprefix,label);
+	    if(c==ADD){
+	      if(c==ADD) emit(f,"\tclc\n"); else emit(f,"\tsec\n");
+	      do_lobyte(f,s,&p->q1,t);
+	      if(isacc(z))
+		emit(f,"\tpha\n");
+	      else
+		store_lobyte(f,&p->z,t);
+	      emit(f,"\ttxa\n");
+	      do_hibyte(f,s,&p->q1,t);
+	      store_hibyte(f,&p->z,t);
+	      if(ISFPOINTER(pt)&&!compare_objects(&p->q1,&p->z)){
+		do_byte3(f,"lda",&p->q1,pt);
+		do_byte3(f,"sta",&p->z,pt);
+	      }
+	      if(isacc(z))
+		emit(f,"\tpla\n");
+	      continue;
+	    }
+	    r=get_reg(f,p,CHAR);
+	    emit(f,"\tstx\t%s\n",mregnames[r]);
+	  }
+	  load_lobyte(f,&p->q1,t);
+	  if(c==ADD) emit(f,"\tclc\n"); else emit(f,"\tsec\n");
+	  do_lobyte(f,s,&p->q2,t2);
+	  store_lobyte(f,&p->z,t);
+	  if(l==0&&isreg(q1)&&isreg(z)&&p->q1.reg==p->z.reg){
+	    if(c==ADD){
+	      emit(f,"\tbcc\t%s%d\n",labprefix,++label);
+	      if(a)
+		emit(f,"\tinx\n");
+	      else{
+		/*if(!reg_pair(p->z.reg,&rp)) ierror(0);*/
+		emit(f,"\tinc\t%s+1\n",mregnames[p->z.reg]);
+	      }
+	    }else{
+	      emit(f,"\tbcs\t%s%d\n",labprefix,++label);
+	      if(a)
+		emit(f,"\tdex\n");
+	      else{
+		if(!reg_pair(p->z.reg,&rp)) ierror(0);
+		emit(f,"\tdec\t%s\n",mregnames[rp.r2]);
+	      }
+	    }
+	    emit(f,"%s%d:\n",labprefix,label);
+	  }else{
+	    if(a==1) emit(f,"\tpha\n");
+	    if((t2&NQ)==CHAR){
+	      if(t2&UNSIGNED){
+		load_hibyte(f,&p->q1,t);
+		emit(f,"\t%s\t#0\n",s);
+	      }else{
+		load_hibyte(f,&p->q1,t);
+		if((p->q2.flags&(KONST|DREFOBJ))==KONST){
+		  eval_const(&p->q2.val,t2);
+		  if(zmleq(Z0,vmax))
+		    emit(f,"\t%s\t#0\n",s);
+		  else
+		    emit(f,"\t%s\t#255\n",s);
+		}else{
+		  emit(f,"\t%s\t%s\n",s,mregnames[r]);
+		}
+	      }
+	    }else{
+	      load_hibyte(f,&p->q1,t);
+	      do_hibyte(f,s,&p->q2,t2);
+	    }
+	    store_hibyte(f,&p->z,t);
+	    if(a==1) emit(f,"\tpla\n");
+	    if(ISFPOINTER(pt)&&p->code!=SUBPFP){
+	      if(!compare_objects(&p->q1,&p->z)){
+		do_byte3(f,"lda",&p->q1,FPOINTER);
+		do_byte3(f,"sta",&p->z,FPOINTER);
+	      }
+	    }
+	  }
+	}else{
+	  long l=-1;int dello=0;
+	  if(c!=AND&&c!=OR&&c!=XOR) ierror(0);
+	  if((p->q2.flags&(KONST|DREFOBJ))==KONST){
+	    eval_const(&p->q2.val,t);
+	    l=zm2l(vmax)&0xffff;
+	  }
+	  if(l>0&&((c==AND&&(l&0xFF)==0)||(c==OR&&(l&0xFF)==0xFF))){
+	    dello=1;
+	  }else if(l>0&&((c==AND&&(l&0xFF)==0xFF)||((c==OR||c==XOR)&&(l&0xFF)==0))){
+	    if(!compare_objects(&p->q1,&p->z)){
+	      load_lobyte(f,&p->q1,t);
+	      store_lobyte(f,&p->z,t);
+	    }
+	  }else{
+	    load_lobyte(f,&p->q1,t);
+	    do_lobyte(f,s,&p->q2,t);
+	    store_lobyte(f,&p->z,t);
+	  }
+	  if(l>0&&((c==AND&&(l&0xFF00)==0)||(c==OR&&(l&0xFF00)==0xFF00))){
+	    int val=(c==AND)?0:255;
+	    if(isacc(z)){
+	      emit(f,"\tldx\t#%d\n",val);
+	    }else{
+	      emit(f,"\tlda\t#%d\n",val);
+	      store_hibyte(f,&p->z,t);
+	    }
+	  }else if(l>0&&((c==AND&&(l&0xFF00)==0xFF00)||((c==OR||c==XOR)&&(l&0xFF00)==0))){
+	    if(isacc(z)&&!indirect(&p->q1)){
+	      do_hibyte(f,"ldx",&p->q1,t);
+	    }else{
+	      if(!compare_objects(&p->q1,&p->z)){
+		if(!dello&&isacc(z))
+		  emit(f,"\tpha\n");
+		load_hibyte(f,&p->q1,t);
+		store_hibyte(f,&p->z,t);
+		if(!dello&&isacc(z))
+		  emit(f,"\tpla\n");
+	      }
+	    }
+	  }else{
+	    if(!dello&&isacc(z))
+	      emit(f,"\tpha\n");
+	    load_hibyte(f,&p->q1,t);
+	    do_hibyte(f,s,&p->q2,t);
+	    store_hibyte(f,&p->z,t);
+	    if(!dello&&isacc(z))
+	      emit(f,"\tpla\n");
+	  }
+	  if(dello){
+	    emit(f,"\tlda\t#%d\n",(c==AND)?0:255);
+	    store_lobyte(f,&p->z,t);
+	  }
+	}
+	continue;
+      }
+      pric2(stdout,p);
+      ierror(0);
+    }
+
+    function_bottom(f,v,localsize);
+    
+    for(c=1;c<=MAXR;c++){
+      if(regsa[c]||regused[c]){
+	BSET(regs_modified,c);
+      }
+    }
+
+    if(stack_valid){
+      if(!v->fi) v->fi=new_fi();
+      v->fi->flags|=ALL_STACK;
+      v->fi->stack1=stack;
+    }
+  }
+
+  free_IC(mi);
+
+  emit(f,"; stacksize=%lu%s\n",zum2ul(stack),stack_valid?"":"+??");
+}
+
+int shortcut(int code,int typ)
+{
+  if(code==COMPARE||code==MULT||code==ADD||code==SUB||code==AND||code==OR||code==XOR||code==LSHIFT||code==RSHIFT||code==MINUS||code==KOMPLEMENT||code==NEGATION)
+    return 1;
+
+  return 0;
+}
+
+static int fattr(type *p,char *s)
+{
+  if(p->attr&&strstr(p->attr,s))
+    return 1;
+  if(p->next)
+    return fattr(p->next,s);
+  else
+    return 0;
+}
+
+int reg_parm(struct reg_handle *m, struct Typ *t,int vararg,struct Typ *d)
+{
+  int f;
+
+  if(vararg)
+    return 0;
+  f=t->flags&NQ;
+  if(OLDFP&&ISFLOAT(f)) return 0;
+  if(d&&fattr(d,"__stackparms__"))
+    return 0;
+  if(d&&fattr(d,"__cc65__")){
+    m->regs++;
+    printf("arg=%d cnt=%d\n",m->regs,d->exact->count);
+    if(m->regs==d->exact->count-1){
+      if(ISCHAR(t->flags))
+	return ra;
+      if(ISSHORT(t->flags))
+	return rax;
+    }
+    return 0;
+  }
+  if(ISCHAR(f)){
+    if(!t->exact){
+      if(m->regs>=GPR_ARGS-1)
+	return 0;
+      f=FIRST_GPR+m->regs;
+      m->regs+=2;
+      return f;
+    }else{
+      if(m->regs>=GPR_ARGS)
+	return 0;
+      else
+	return FIRST_GPR+m->regs++;
+    }
+  }
+  if(ISSHORT(f)||f==POINTER){
+    if(m->regs>=GPR_ARGS-1)
+      return 0;
+    else{
+      if(m->regs&1) m->regs+=1;
+      m->regs+=2;
+      return FIRST_PAIR+m->regs/2-1;
+    }
+  }
+  if(f==FPOINTER||f==LONG||f==FLOAT||(!ieee&&(f==DOUBLE||f==LDOUBLE))){
+    if(m->bregs>=4)
+      return 0;
+    else
+      return FIRST_BIG+m->bregs++;
+  }
+  if(f==LLONG||(ieee&&(f==DOUBLE||f==LDOUBLE))){
+    if(m->bregs>=3)
+      return 0;
+    else{
+      if(m->bregs&1)  m->bregs++;
+      m->bregs+=2;
+      return FIRST_BIGP+m->bregs/2-1;
+    }
+  }
+  return 0;
+}
+
+int handle_pragma(const char *s)
+{
+  static char sec[SECLEN];
+  int i;
+  if(sscanf(s,"section %127s",sec)==1){
+    if(!strcmp(sec,"default"))
+      use_sec=0;
+    else
+      use_sec=sec;
+    return 1;
+  }
+  if(sscanf(s,"bank %d",&i)==1){
+    use_bank=i;
+    return 1;
+  }
+}
+void cleanup_cg(FILE *f)
+{
+  int i;
+  struct fpconstlist *p=firstfpc;
+
+  if(f&&p){
+    emit(f,rodataname);emit(f,"\n");
+    section=RODATA;
+  }
+  while(p=firstfpc){
+    emit(f,"%s%d:\n\tword\t",labprefix,p->label);
+    if(ieee)
+      emit_ieee(f,&p->val,p->t);
+    else{
+      int words=zm2l(sizetab[p->t&NQ])/2;
+      eval_const(&p->val,p->t);
+      if(ISFLOAT(p->t)) cnv_fp();
+      for(i=0;i<words;i++){
+	emit(f,"%ld",zm2l(vmax)&0xffff);
+	if(i<words-1){emit(f,",");vmax=zmrshift(vmax,l2zm(16L));}
+      }
+      emit(f,"\n");
+      /*emit(f,"%ld,%ld\n",zm2l(vmax)&0xffff,zm2l(zmrshift(vmax,l2zm(16L)))&0xffff);*/
+    }
+    firstfpc=p->next;
+    free(p);
+  }
+
+  emit(f,"\tzpage\t%s\n",mregnames[sp]);
+  for(i=FIRST_GPR;i<=LAST_GPR;i++)
+    emit(f,"\tzpage\t%s\n",mregnames[i]);
+  for(i=FIRST_BIG;i<=LAST_BIG;i++)
+    emit(f,"\tzpage\t%s\n",mregnames[i]);
+
+}
+void cleanup_db(FILE *f)
+{
+  if(f) section=-1;
+}
+
+static char *zops[]={
+  "adc","and","asl","bit","eor","lda","ora",
+  "tax","txa","tay","tya","sbc"};
+
+static int setszflag(char *op)
+{
+  int i;
+  for(i=0;i<sizeof(zops)/sizeof(zops[0]);i++)
+    if(!strcmp(op,zops[i]))
+      return 1;
+  return 0;
+}
+
+static char *zxops[]={
+  "tax","txa","ldx","inx","dex"};
+
+static int setszxflag(char *op)
+{
+  int i;
+  for(i=0;i<sizeof(zxops)/sizeof(zxops[0]);i++)
+    if(!strcmp(op,zxops[i]))
+      return 1;
+  return 0;
+}
+
+enum peepf { NEEDSAME = 1, REMOVE1ST = 2};
+struct peeps {char *s1,*s2,*r;enum peepf flags;};
+
+
+
+int emit_peephole(void)
+{
+  int entries,i,j;
+  char *asmline[EMIT_BUF_DEPTH];
+  char buf1[1024],buf2[1024];
+  char op1[8],op2[8];
+  static char ca[1024],cx[1024],cy[1024],cz[1024];
+  static int rm,disabled;
+
+  static struct peeps elim[]={
+    "lda","sta",0,NEEDSAME,
+    "ldx","stx",0,NEEDSAME,
+    "ldy","sty",0,NEEDSAME,
+    "ldz","stz",0,NEEDSAME,
+    "ldq","stq",0,NEEDSAME,
+    "sta","sta",0,NEEDSAME,
+    "stx","stx",0,NEEDSAME,
+    "sty","sty",0,NEEDSAME,
+    "stz","stz",0,NEEDSAME,
+    "stq","stq",0,NEEDSAME,
+    "sta","lda",0,NEEDSAME,
+    "stx","ldx",0,NEEDSAME,
+    "sty","ldy",0,NEEDSAME,
+    "stz","ldz",0,NEEDSAME,
+    "stq","ldq",0,NEEDSAME,
+    "txa","tax",0,0,
+    "tax","txa",0,0,
+    "tay","tya",0,0,
+    "tya","tay",0,0,
+    "tza","taz",0,0,
+    "taz","tza",0,0,
+    "lda","lda",0,REMOVE1ST,
+    "ldx","ldx",0,REMOVE1ST,
+    "ldy","ldy",0,REMOVE1ST,
+    "ldz","ldz",0,REMOVE1ST,
+    "ldq","ldq",0,REMOVE1ST,
+    "lda","ldq",0,REMOVE1ST,
+    "ldx","ldq",0,REMOVE1ST,
+    "ldy","ldq",0,REMOVE1ST,
+    "lda","pla",0,REMOVE1ST,
+    "ldx","plx",0,REMOVE1ST,
+    "ldy","ply",0,REMOVE1ST,
+    "ldz","plz",0,REMOVE1ST,
+    "lda","txa",0,REMOVE1ST,
+    "lda","tya",0,REMOVE1ST,
+    "lda","tza",0,REMOVE1ST,
+    "ldx","tax",0,REMOVE1ST,
+    "ldy","tay",0,REMOVE1ST,
+    "ldz","taz",0,REMOVE1ST,
+    "tay","ldy",0,REMOVE1ST,
+    "tax","ldx",0,REMOVE1ST,
+    "taz","ldz",0,REMOVE1ST,
+    "txa","lda",0,REMOVE1ST,
+    "tya","lda",0,REMOVE1ST,
+    "tza","lda",0,REMOVE1ST,
+    "lda","ldx","\ttax\n",NEEDSAME,
+    "lda","ldy","\ttay\n",NEEDSAME,
+    "lda","ldz","\ttaz\n",NEEDSAME,
+    "ldx","lda","\ttxa\n",NEEDSAME,
+    "ldy","lda","\ttya\n",NEEDSAME,
+    "ldz","lda","\ttza\n",NEEDSAME,
+    "sta","ldx","\ttax\n",NEEDSAME,
+    "sta","ldy","\ttay\n",NEEDSAME,
+    "sta","ldz","\ttaz\n",NEEDSAME,
+    "stx","lda","\ttxa\n",NEEDSAME,
+    "sty","lda","\ttya\n",NEEDSAME,
+    "stz","lda","\ttza\n",NEEDSAME, /* must be last */
+  };
+
+  if(nopeep) return 0;
+
+  /* activate optimization that is not valid for c02 */
+  if(!ce02) elim[sizeof(elim)/sizeof(elim[0])-1].r="\tlda\t#0\n";
+
+  i=emit_l;
+  if(emit_f==0)
+    entries=i-emit_f+1;
+  else
+    entries=EMIT_BUF_DEPTH;
+  asmline[0]=emit_buffer[i];
+
+  if(!strcmp(asmline[0],";startinline\n")) disabled=1;
+  if(!strcmp(asmline[0],";endinline\n")) disabled=0;
+  if(disabled) return 0;
+
+  buf1[0]=0;op1[0]=0;
+  if((j=sscanf(asmline[0]," %6s %999s",op1,buf1))>=1){
+    /*printf("a=%s x=%s y=%s z=%s\n",ca,cx,cy,cz);
+      printf("\t\t%s %s\n",op1,buf1);*/
+    if(!strcmp(op1,"lda")){
+      if(buf1[0]=='#'){
+	if(!rm&&!strcmp(buf1,ca)){remove_asm();return rm=1;}
+	if(!rm&&!strcmp(buf1,cx)){strcpy(asmline[0],"\ttxa\n");return rm=1;}
+	if(!rm&&!strcmp(buf1,cy)){strcpy(asmline[0],"\ttya\n");return rm=1;}
+	if(!rm&&!strcmp(buf1,cz)){strcpy(asmline[0],"\ttza\n");return rm=1;}
+	strcpy(ca,buf1);
+      }else ca[0]=0;
+    }else if(!strcmp(op1,"ldx")){
+      if(buf1[0]=='#'){
+	if(!rm&&!strcmp(buf1,cx)){remove_asm();return rm=1;}
+	if(!rm&&!strcmp(buf1,ca)){strcpy(asmline[0],"\ttax\n");return rm=1;}
+	strcpy(cx,buf1);
+      }else cx[0]=0;
+    }else if(!strcmp(op1,"ldy")){
+      if(buf1[0]=='#'){
+	if(!rm&&!strcmp(buf1,cy)){remove_asm();return rm=1;}
+	if(!rm&&!strcmp(buf1,ca)){strcpy(asmline[0],"\ttay\n");return rm=1;}
+	strcpy(cy,buf1);
+      }else cy[0]=0;
+    }else if(!strcmp(op1,"ldz")){
+      if(buf1[0]=='#'){
+	if(!rm&&!strcmp(buf1,cz)){remove_asm();return rm=1;}
+	if(!rm&&!strcmp(buf1,ca)){strcpy(asmline[0],"\ttaz\n");return rm=1;}
+	strcpy(cz,buf1);
+      }else cz[0]=0;
+    }else{
+      static char clobbernone[]="asw bit clc cld cli clv cmp cpx cpy dec deq dew inc inq inw nop pha php phw phz plp sec sed sei sta stq stx sty";
+      static char clobbera[]="adc and asl asr eor lsr ora pla rol ror sbc txa tya tza";
+      static char clobberx[]="dex inx tax tsx";
+      static char clobbery[]="dey iny tay";
+      static char clobberz[]="dez inz taz";
+      if(strstr(clobbernone,op1)){
+      }else if(strstr(clobbera,op1))
+	ca[0]=0;
+      else if(strstr(clobberx,op1))
+	cx[0]=0;
+      else if(strstr(clobbery,op1))
+	cy[0]=0;
+      else if(strstr(clobberz,op1))
+	cz[0]=0;
+      else
+	ca[0]=cx[0]=cy[0]=cz[0]=0;
+    }
+  }else{
+    ca[0]=cx[0]=cy[0]=cz[0]=0;
+  }
+
+  rm=0;
+
+  if(sscanf(asmline[0]," %6s %999s",op1,buf1)==2&&!strcmp(op1,"and")&&!strcmp(buf1,"#0")){
+    strcpy(asmline[0],"\tlda\t#0\n");
+    return rm=1;
+  }
+
+  if(entries>=2){
+    i--;
+    if(i<0) i=EMIT_BUF_DEPTH-1;
+    asmline[1]=emit_buffer[i];
+
+
+    if(!strcmp(asmline[0],"; volatile barrier\n")&&!strcmp(asmline[0],asmline[1])){
+      remove_asm();
+      return rm=1;
+    }
+
+    if(sscanf(asmline[0]," %6s",op1)==1&&!strcmp(op1,"rts")&&
+       sscanf(asmline[1]," %6s %999s",op2,buf2)==2&&!strcmp(op2,"jsr")){
+      sprintf(asmline[1],"\tjmp\t%s\n",buf2);
+      remove_asm();
+      return rm=1;
+    }
+
+    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(elim[j].r){
+	    strcpy(asmline[0],elim[j].r);
+	  }else{
+	    if(elim[j].flags&REMOVE1ST)
+	      strcpy(asmline[1],asmline[0]);
+	    remove_asm();
+	  }
+	  return rm=1;
+	}
+      }else{
+	if(sscanf(asmline[1]," %6s",op1)==1&&
+	   sscanf(asmline[0]," %6s",op2)==1&&
+	   !strcmp(op1,elim[j].s1)&&!strcmp(op2,elim[j].s2)){
+	  if(elim[j].flags&REMOVE1ST)
+	    strcpy(asmline[1],asmline[0]);
+	  remove_asm();
+	  return rm=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 0
+      if(!strcmp(op1,"lda")&&buf1[0]=='#'){
+	if(sscanf(asmline[1]," %6s %999s",op2,buf2)==2&&
+	   !strcmp(op2,"sta")){
+	  if(sscanf(asmline[2]," %6s %999s",op2,buf2)==2&&
+	     !strcmp(op2,"lda")&&!strcmp(buf1,buf2)){
+	    remove_asm();
+	    return rm=1;
+	  }
+	}
+      }
+#endif
+      if(!strcmp(op1,"beq")||!strcmp(op1,"bne")){
+	if(sscanf(asmline[1]," %6s %999s",op2,buf2)==2&&
+	   !strcmp(op2,"cmp")&&!strcmp(buf2,"#0")){
+	  if(sscanf(asmline[2]," %6s",op2)==1&&
+	     setszflag(op2)){
+	    strcpy(asmline[1],asmline[0]);
+	    remove_asm();
+	    return rm=1;
+	  }
+	}
+      }
+      if(!strcmp(op1,"beq")||!strcmp(op1,"bne")){
+	if(sscanf(asmline[1]," %6s %999s",op2,buf2)==2&&
+	   !strcmp(op2,"cpx")&&!strcmp(buf2,"#0")){
+	  if(sscanf(asmline[2]," %6s",op2)==1&&
+	     setszxflag(op2)){
+	    strcpy(asmline[1],asmline[0]);
+	    remove_asm();
+	    return rm=1;
+	  }
+	}
+      }
+    }
+  }
+  if(entries>=4){
+    i--;
+    if(i<0) i=EMIT_BUF_DEPTH-1;
+    asmline[3]=emit_buffer[i];
+  }
+  if(entries>=5){
+    i--;
+    if(i<0) i=EMIT_BUF_DEPTH-1;
+    asmline[4]=emit_buffer[i];
+    if(sscanf(asmline[0]," %s %s",op1,buf1)>=1){
+      if(!strcmp(op1,"lda")||!strcmp(op1,"pla")||!strcmp(op1,"txa")||!strcmp(op1,"tya")){
+	if(sscanf(asmline[1]," %s %s",op1,buf1)>=1&&!strcmp(op1,"pla")&&
+	   sscanf(asmline[2]," %s %s",op1,buf1)>=1&&!strcmp(op1,"tay")&&
+	   sscanf(asmline[3]," %s %s",op1,buf1)>=1&&!strcmp(op1,"txa")&&
+	   sscanf(asmline[4]," %s %s",op1,buf1)>=1&&!strcmp(op1,"pha")){
+	  strcpy(asmline[4],asmline[3]);
+	  strcpy(asmline[3],asmline[2]);
+	  strcpy(asmline[2],asmline[0]);
+	  remove_asm();
+	  remove_asm();
+	  return rm=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)&&!ieee)){
+      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(ISSHORT(t)&&c!=MULT&&c!=DIV&&c!=MOD&&!ISFLOAT(t2))
+      return 0;
+    if(ISLONG(t)&&c!=MULT&&c!=DIV&&c!=MOD&&!ISFLOAT(t2))
+      return 0;
+
+    if(!ieee&&ISFLOAT(t)) t=FLOAT;
+    if(t==LDOUBLE) t=DOUBLE;
+    if(t2==LDOUBLE) t2=DOUBLE;
+    if(!ieee&&ISFLOAT(t2)) t2=FLOAT;
+    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(c==MULT&&(t&NQ)==CHAR&&!m65) return "__mulint8";
+    if((t&NQ)==SHORT||(t&NQ)==INT||(t&NQ)==LONG||(t&NQ)==LLONG||(!ieee&&ISFLOAT(t))){
+      if((c>=LSHIFT&&c<=MOD)||(c>=OR&&c<=AND)||c==KOMPLEMENT||c==MINUS){
+	if(m65&&ISLONG(t)&&(c==MULT||(c==DIV&&!divbug&&(t&UNSIGNED)))) return 0;
+	if(m65&&c==MULT&&ISSHORT(t)) return 0;
+        if(t==(UNSIGNED|LLONG)&&(c==MULT||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 if(t==(UNSIGNED|INT)&&(c==DIV||c==MOD||c==RSHIFT)){
+          sprintf(fname,"__%suint16",ename[c]);
+          ret=fname;
+        }else if((t&NQ)==INT){
+          sprintf(fname,"__%sint16",ename[c]);
+          ret=fname;
+        }else{
+          sprintf(fname,"__%s%s%s%ld",ename[c],(t&UNSIGNED)?"u":"",ISFLOAT(t)?"flt":"int",zm2l(sizetab[t&NQ])*8);
+          ret=fname;
+        }
+      }
+    }
+  }
+
+  if(ret&&divbug&&(c==DIV||c==MOD)&&!ISFLOAT(t)) strcat(ret,"wo");
+
+  return ret;
+}
+
+
+int pointer_varadr(Var *v)
+{
+  int b=bank(v);
+  if(b>=0&&b!=bankcnum&&!NOBANKVARS){
+    if(cur_funcv&&bank(cur_funcv)!=b)
+      return FPOINTER;
+  }
+  return pointer_type(v->vtyp);
+}
+
+int pointer_type(struct Typ *p)
+{
+  struct Typ *merk=p;
+  if(!p) ierror(0);
+  if(LARGE) return FPOINTER;
+  while(ISARRAY(p->flags)||ISFUNC(p->flags)) p=p->next;
+  if(p->attr){
+    char *s;
+    if(strstr(p->attr,STR_HUGE)) return HPOINTER;
+    if(strstr(p->attr,STR_FAR)) return FPOINTER;
+    if(strstr(p->attr,STR_NEAR)) return POINTER;
+  }
+  return POINTER;
+}
+
+unsigned char cbmconv(unsigned char x)
+{
+  static unsigned char ctab[256]={
+    0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x14,0x09,0x0D,0x11,0x93,0x0A,0x0E,0x0F,
+    0x10,0x0B,0x12,0x13,0x08,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
+    0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
+    0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
+    0x40,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
+    0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0x5B,0xBF,0x5D,0x5E,0xA4,
+    0xAD,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
+    0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0xB3,0xDD,0xAB,0xB1,0xDF,
+    0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
+    0x90,0x91,0x92,0x0C,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
+    0xA0,0xA1,0xA2,0xA3,0x5F,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0x7D,0xAC,0x60,0xAE,0xAF,
+    0xB0,0x7E,0xB2,0x7B,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0x5C,
+    0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
+    0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0xDC,0x7C,0xDE,0x7F,
+    0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
+    0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
+  };
+
+  static unsigned char atab[]={0xfd,8,0x7f,0x9b,11,0x7d};
+
+  if(cbmascii)
+    return ctab[x&255];
+  else if(atascii&&x>=7&&x<=12)
+    return atab[x-7];
+  else
+    return x;
+}
+
+void insert_const(union atyps *p,int t)
+/*  Traegt Konstante in entprechendes Feld ein.       */
+{
+  if(!p) ierror(0);
+/*  *p = (union atyps) 0 ; /* rfi: clear unused bits */
+  t&=NU;
+  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|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==POINTER) {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>=CHAR&&f<=LLONG)){
+    if(!(t&UNSIGNED)){
+      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==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==POINTER)
+	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==CHAR){fprintf(f,"C");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==POINTER){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)
+/*  Gibt atyps aus.                                     */
+{
+  t&=NU;
+  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==POINTER){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)|POINTER);
+        if(strstr(attr,STR_FAR))
+          p->flags=((p->flags&~NU)|FPOINTER);
+        if(strstr(attr,STR_HUGE))
+          p->flags=((p->flags&~NU)|HPOINTER);
+      }
+    }
+    p=p->next;
+  }
+}
+
+void add_var_hook_post(Var *v)
+{
+  if(use_sec&&(v->storage_class==STATIC||v->storage_class==EXTERN)){
+    char buf[SECLEN+32];
+    sprintf(buf,"section(\"%s\");",use_sec);
+    add_attr(&v->vattr,buf);
+  }
+  if(use_bank>=0&&(v->storage_class==STATIC||v->storage_class==EXTERN)){
+    char buf[64];
+    /*sprintf(buf,"section(\"bank%d\");bank(%d)",use_bank,use_bank);*/
+    sprintf(buf,"bank(%d)",use_bank);
+    add_attr(&v->vattr,buf);
+  }
+}
+
+int decide_reverse(zmax v)
+{
+  if(zmeqto(v,Z1)||zmeqto(v,l2zm(2L)))
+    return 1;
+  if(optspeed)
+    if(zmeqto(v,l2zm(4L))||zmeqto(v,l2zm(8L))||zmeqto(v,l2zm(256L))||zmeqto(v,l2zm(512L)))
+      return 1;
+  
+  return 0;
+}
+
+static int is_single_eff_ic(struct IC *p)
+{
+  struct Var *v,*idx;
+  if(p->code!=ADDI2P||(p->typf2&NQ)!=POINTER)
+    return 0;
+  if(!(p->q2.flags&KONST)){
+    if((p->typf&NU)!=(UNSIGNED|CHAR))
+      return 0;
+    if((p->q2.flags&(VAR|DREFOBJ))!=VAR)
+      return 0;
+    if(p->q2.v->storage_class!=AUTO&&p->q2.v->storage_class!=REGISTER)
+      return 0;
+    idx=p->q2.v;
+  }else{
+    idx=0;
+    eval_const(&p->q2.val,p->typf);
+    /* TODO: more precise check considering data type useful? */
+    if(!zmleq(vumax,l2zm(255L)))
+      return 0;
+    return 1;
+  }
+  if(p->q1.flags&DREFOBJ)
+    return 0;
+  if((p->z.flags&(VAR|DREFOBJ))!=VAR)
+    return 0;
+  if(p->z.v->storage_class==STATIC||p->z.v->storage_class==EXTERN)
+    return 0;
+  v=p->z.v;
+  for(p=p->next;p;p=p->next){
+    int c=p->code;
+    if(c==LABEL||(c>=BEQ&&c<=BRA))
+      return 1; /* TODO: how elaborate should we test? */
+    if((p->q1.flags&VAR)&&p->q1.v==v){
+      if(p->q1.flags&DREFOBJ)
+        return 1;
+      else
+        return 0;
+    }
+    if((p->q2.flags&VAR)&&p->q2.v==v){
+      if(p->q2.flags&DREFOBJ)
+        return 1;
+      else
+        return 0;
+    }
+    if((p->z.flags&VAR)&&p->z.v==v){
+      if(p->z.flags&DREFOBJ)
+        return 1;
+      else
+        return 0;
+    }
+    if((p->z.flags&VAR)&&p->z.v==idx)
+      return 0;
+  }
+  return 0;
+}
+
+void mark_eff_ics(void)
+{
+  struct IC *p;
+  for(p=first_ic;p;p=p->next){
+    if(is_single_eff_ic(p))
+      p->flags|=EFF_IC;
+    else
+      p->flags&=~EFF_IC;
+  }
+}
diff --git a/machines/6502/machine.dt b/machines/6502/machine.dt
new file mode 100755
index 0000000..eab38c9
--- /dev/null
+++ b/machines/6502/machine.dt
@@ -0,0 +1,16 @@
+S8BS
+S8BU
+S16BSLE S16BSBE
+S16BULE S16BUBE
+S16BSLE S16BSBE
+S16BULE S16BUBE
+S32BSLE S32BSBE
+S32BULE S32BUBE
+S64BSLE S64BSBE
+S64BULE S64BUBE
+S32BIEEELE
+S64BIEEELE
+S64BIEEELE
+S16BULE S16BUBE
+
+
diff --git a/machines/6502/machine.h b/machines/6502/machine.h
new file mode 100755
index 0000000..b2c5e45
--- /dev/null
+++ b/machines/6502/machine.h
@@ -0,0 +1,267 @@
+/*  6502 backend for vbcc
+    (c) Volker Barthelmann 2020
+
+*/
+
+/* buil-time configurable options: */
+#define NUM_GPRS 32
+#define NUM_PAIRS (NUM_GPRS/2)
+#define NUM_BIG 4
+#define NUM_BIGP (NUM_BIG/2)
+#define FIXED_SP 1
+
+#include "dt.h"
+
+#undef CHAR
+#undef SHORT
+#undef INT
+#undef LONG
+#undef LLONG
+#undef FLOAT
+#undef DOUBLE
+#undef LDOUBLE
+#undef VOID
+#undef POINTER
+#undef ARRAY
+#undef STRUCT
+#undef UNION
+#undef ENUM
+#undef FUNKT
+#undef BOOL
+#undef MAXINT
+#undef MAX_TYPE
+
+#define CHAR 1
+#define SHORT 2
+#define INT 3
+#define LONG 4
+#define LLONG 5
+#define FLOAT 6
+#define DOUBLE 7
+#define LDOUBLE 8
+#define VOID 9
+#define POINTER 10
+#define FPOINTER 11
+#define HPOINTER 12
+#define ARRAY 13
+#define STRUCT 14
+#define UNION 15
+#define ENUM 16
+#define FUNKT 17
+#define BOOL 18
+
+#define MAXINT 19
+
+#define MAX_TYPE MAXINT
+
+
+#define POINTER_TYPE(x) pointer_type(x)
+#define POINTER_VARADR(x) pointer_varadr(x)
+extern int pointer_type();
+extern int pointer_varadr();
+#define ISPOINTER(x) ((x&NQ)>=POINTER&&(x&NQ)<=HPOINTER)
+#define ISSCALAR(x) ((x&NQ)>=CHAR&&(x&NQ)<=HPOINTER)
+#define ISINT(x) ((x&NQ)>=CHAR&&(x&NQ)<=LLONG)
+#define PTRDIFF_T(x) ((x)==HPOINTER?LONG:INT)
+
+typedef zllong zmax;
+typedef zullong zumax;
+
+union atyps{
+  zchar vchar;
+  zuchar vuchar;
+  zshort vshort;
+  zushort vushort;
+  zint vint;
+  zuint vuint;
+  zlong vlong;
+  zulong vulong;
+  zllong vllong;
+  zullong vullong;
+  zmax vmax;
+  zumax vumax;
+  zfloat vfloat;
+  zdouble vdouble;
+  zldouble vldouble;
+};
+
+
+/* internally used by the backend */
+#define FIRST_GPR 8
+#define LAST_GPR (FIRST_GPR+NUM_GPRS-1)
+#define FIRST_PAIR (LAST_GPR+1)
+#define LAST_PAIR (FIRST_PAIR+NUM_PAIRS-1)
+#define FIRST_BIG (LAST_PAIR+1)
+#define LAST_BIG (FIRST_BIG+NUM_BIG-1)
+#define FIRST_BIGP (LAST_BIG+1)
+#define LAST_BIGP (FIRST_BIGP+NUM_BIGP-1)
+
+/*  This struct can be used to implement machine-specific           */
+/*  addressing-modes.                                               */
+/*  Currently possible are (const,gpr) and (gpr,gpr)                */
+struct AddressingMode{
+  int flags;
+  int base;
+  int idx;
+  long offset;
+  void *v;
+};
+
+/*  The number of registers of the target machine.                  */
+#define MAXR LAST_BIGP
+
+/*  Number of commandline-options the code-generator accepts.       */
+#define MAXGF 30
+
+/*  If this is set to zero vbcc will not generate ICs where the     */
+/*  target operand is the same as the 2nd source operand.           */
+/*  This can sometimes simplify the code-generator, but usually     */
+/*  the code is better if the code-generator allows it.             */
+#define USEQ2ASZ 1
+
+/*  This specifies the smallest integer type that can be added to a */
+/*  pointer.                                                        */
+#define MINADDI2P CHAR
+
+/*  If the bytes of an integer are ordered most significant byte    */
+/*  byte first and then decreasing set BIGENDIAN to 1.              */
+#define BIGENDIAN 0
+
+/*  If the bytes of an integer are ordered lest significant byte    */
+/*  byte first and then increasing set LITTLEENDIAN to 1.           */
+#define LITTLEENDIAN 1
+
+/*  Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive.    */
+
+/*  If switch-statements should be generated as a sequence of       */
+/*  SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1.      */
+/*  This can yield better code on some machines.                    */
+#define SWITCHSUBS 0
+
+/*  In optimizing compilation certain library memcpy/strcpy-calls   */
+/*  with length known at compile-time will be inlined using an      */
+/*  ASSIGN-IC if the size is less or equal to INLINEMEMCPY.         */
+/*  The type used for the ASSIGN-IC will be UNSIGNED|CHAR.          */
+#define INLINEMEMCPY 128
+
+/*  Parameters are sometimes passed in registers without __reg.     */
+#define HAVE_REGPARMS 1
+
+/*  Parameters on the stack should be pushed in order rather than   */
+/*  in reverse order.                                               */
+#define ORDERED_PUSH FIXED_SP
+
+/*  Structure for reg_parm().                                       */
+struct reg_handle{
+  int regs;
+  int bregs;
+};
+
+/*  We have some target-specific variable attributes.               */
+#define HAVE_TARGET_ATTRIBUTES
+
+/* We have target-specific pragmas */
+#define HAVE_TARGET_PRAGMAS
+
+/*  We keep track of all registers modified by a function.          */
+#define HAVE_REGS_MODIFIED 1
+
+/* We have a implement our own cost-functions to adapt 
+   register-allocation */
+#define HAVE_TARGET_RALLOC 1
+#define cost_move_reg(x,y) 6 //6
+#define cost_load_reg(x,y) 10 //10
+#define cost_save_reg(x,y) 10 //10
+#define cost_pushpop_reg(x) 2 //12
+
+/* size of buffer for asm-output, this can be used to do
+   peephole-optimizations of the generated assembly-output */
+#define EMIT_BUF_LEN 1024 /* should be enough */
+/* number of asm-output lines buffered */
+#define EMIT_BUF_DEPTH 8
+
+/*  We have no asm_peephole to optimize assembly-output */
+#define HAVE_TARGET_PEEPHOLE 1
+
+/* we do not have a mark_eff_ics function, this is used to prevent
+   optimizations on code which can already be implemented by efficient
+   assembly */
+#undef HAVE_TARGET_EFF_IC
+
+/* we have additional types */
+#define HAVE_EXT_TYPES
+#define HAVE_TGT_PRINTVAL
+
+/* we do not need extra elements in the IC */
+#undef HAVE_EXT_IC
+
+/* we do not use unsigned int as size_t (but unsigned long, the default) */
+#define HAVE_INT_SIZET 1
+
+/* we do not need register-pairs */
+#define HAVE_REGPAIRS 1
+
+
+/* do not create CONVERT ICs from integers smaller than int to floats */
+#define MIN_INT_TO_FLOAT_TYPE INT
+
+/* do not create CONVERT ICs from floats to ints smaller than int */
+#define MIN_FLOAT_TO_INT_TYPE INT
+
+/* do not create CONVERT_ICs from floats to unsigned integers */
+#define AVOID_FLOAT_TO_UNSIGNED 0
+
+/* do not create CONVERT_ICs from unsigned integers to floats */
+#define AVOID_UNSIGNED_TO_FLOAT 0
+
+/* convert multiplications/division by powers of two to shifts */
+#define HAVE_POF2OPT 1
+
+/* We use builtin libcalls for some operations */
+#define HAVE_LIBCALLS 1
+
+/* Use char for return of comparison libcalls */
+#define LIBCALL_CMPTYPE CHAR
+
+/* We prefer BNE rather than BGT. */
+#define HAVE_WANTBNE 1
+
+#define BESTCOPYT CHAR
+
+#define HAVE_AOS4 1
+
+#define CHARCONV(x) cbmconv(x)
+unsigned char cbmconv(unsigned char);
+
+#define ALLOCVLA_REG FIRST_PAIR
+#define ALLOCVLA_INLINEASM "\tlda\tsp\n"\
+                           "\tsec\n"\
+                           "\tsbc\tr0\n"\
+                           "\tsta\tsp\n"\
+                           "\tlda\tsp+1\n"\
+                           "\tsbc\tr1\n"\
+                           "\tsta\tsp+1\n"\
+                           "\tlda\tsp\n"\
+                           "\tclc\n"\
+                           "\tldx\tsp+1\n"\
+                           "\tadc\t#___fo\n"\
+                           "\tbcc\t*+3\n"\
+                           "\tinx\n"
+
+#define FREEVLA_REG FIRST_PAIR
+#define FREEVLA_INLINEASM "\tlda\tr0\n"\
+                          "\tsta\tsp\n"\
+                          "\tlda\tr1\n"\
+                          "\tsta\tsp+1\n"
+
+#define OLDSPVLA_INLINEASM "\tlda\tsp+1\n"\
+                           "\ttax\n"\
+                           "\tlda\tsp"
+
+#define FPVLA_REG (LAST_PAIR-2)
+
+#define HAVE_TARGET_VARHOOK_POST 1
+
+#define HAVE_DECIDE_REVERSE 1
+
+#define HAVE_TARGET_EFF_IC 1
diff --git a/machines/832/addressingmodes.c b/machines/832/addressingmodes.c
new file mode 100644
index 0000000..6defe37
--- /dev/null
+++ b/machines/832/addressingmodes.c
@@ -0,0 +1,740 @@
+/* search for possible addressing-modes */
+
+/* DONE: Determine whether a given ob is disposable. */
+
+/* ToDo: Look for pairs of ICs with Z set to register,
+   followed by disposable q1 on the same register ->
+   use tmp for that register.  (Provided second IC won't trash tmp)
+   Can we avoid the passing register being allocated? */
+
+/* Look for ways to use ldidx when an IC adds to a pointer and the next one dereferences it */
+
+
+#define DEFERREDPOP_FLOWCONTROL 0
+#define DEFERREDPOP_NESTEDCALLS 1
+#define DEFERREDPOP_OK 2
+
+
+#define AM_DEBUG 0
+
+// If the obj doesn't already have an addressing mode, create one and zero it out.
+static void am_alloc(struct obj *o)
+{
+	if (!o->am) {
+		o->am = mymalloc(sizeof(struct AddressingMode));
+		memset(o->am, 0, sizeof(struct AddressingMode));
+	}
+}
+
+
+void am_deferredpop(struct IC *p)
+{
+	struct IC *p2;
+	int pushed=0;
+	int deferredpop=0;
+	int candefer=0;
+	for(;p;p=p->next)
+	{
+		switch(p->code)
+		{
+			case PUSH:
+				pushed+=pushsize(p);
+//				printf("Pushing %d bytes, %d so far\n",pushsize(p),pushed);
+				break;
+			case CALL:
+//				printf("CALL IC with pushedsize %d\n",pushedargsize(p));
+
+				am_alloc(&p->z);
+
+				/* We detected nested function calls by comparing the amount of data pushed to the 
+				   stack with this call's pushedargsize().  If they don't match we're dealing with
+                   nested calls.  If they do match, we might be able to defer stack popping. */
+				if(pushed==pushedargsize(p))
+				{
+//					printf("Checking for flow change\n");
+					p2=p->next;
+					candefer=1;
+					while(p2)
+					{
+						switch(p2->code)
+						{
+							/* If we encounter LABEL, COMPARE, TEST or a branch operation then program flow changes
+							   before the next PUSH, and we can't defer the stack pop. */
+							case LABEL:
+							case COMPARE:
+							case TEST:
+							case BLT:
+							case BGT:
+							case BLE:
+							case BGE:
+							case BEQ:
+							case BNE:
+							case BRA:
+//								printf("Flow control changed - can't defer\n");
+								p->z.am->deferredpop=DEFERREDPOP_FLOWCONTROL;
+								candefer=0;
+								p2=0;
+								break;
+							/* If we encounter another PUSH operation without a flow control change we can defer */
+							case PUSH:
+//								printf("Can defer stack popping\n");
+								p2=0;
+								break;
+							default:
+								p2=p2->next;
+								break;
+						}
+					}
+				}
+				else /* pushedargsize() and the contents of the stack differed in size - nested calls. */
+				{
+					p->z.am->deferredpop=DEFERREDPOP_NESTEDCALLS;
+//					printf("Nested call - can't defer stack popping\n");
+					candefer=0;
+				}
+
+				if(candefer)
+				{
+					p->z.am->deferredpop=DEFERREDPOP_OK;
+					deferredpop=pushedargsize(p);
+				}
+
+				pushed-=pushedargsize(p);
+				break;
+			default:
+				break;
+		}
+	}
+}
+
+
+static int is_arithmetic_bitwise(int code)
+{
+	switch(code)
+	{
+		case ADD:
+		case ADDI2P:
+		case SUB:
+		case SUBIFP:
+		case MULT:
+		case OR:
+		case XOR:
+		case AND:
+		case LSHIFT:
+		case RSHIFT:
+			return(1);
+			break;
+	}
+	return(0);
+}
+
+
+void am_conversions(struct IC *p)
+{
+	int c;
+	struct IC *p2;
+	struct IC *p3;
+	for (; p; p = p->next) {
+		c = p->code;
+		switch(c)
+		{
+			case BEQ:
+			case BNE:
+			case BLT:
+			case BLE:
+			case BGT:
+			case BGE:
+			case ALLOCREG:
+			case FREEREG:
+			case NOP:
+				break;
+			case CONVERT:
+				printf("(conversion)\n");
+				break;
+
+			default:
+				switch(q1typ(p)&NQ)
+				{
+					case CHAR:
+					case SHORT:
+						printf("IC %d, non-int operation %x, %x\n",c,q1typ(p),ztyp(p));
+					default:
+						break;
+				}
+				break;
+		}
+	}
+}
+
+// Look for 832-specific optimizations
+
+extern zmax sizetab[MAX_TYPE + 1];
+
+void am_simplify(struct IC *p)
+{
+	int c;
+	struct IC *p2;
+	struct IC *p3;
+	struct IC *prev;
+	for (; p; p = p->next) {
+		c = p->code;
+
+		p2=p->next;
+		if(!p2)
+			break;
+		p3=p2->next;
+		if(!p3)
+			break;
+
+		switch(c)
+		{
+			// Check for ADDRESS followed by push - can we merge?
+			case ADDRESS:
+				if((p->z.flags&(REG|DREFOBJ|SCRATCH))!=(REG|SCRATCH))
+					break;
+
+//				printf("Address IC candidate: zreg: %d, z flags %x\n",p->z.reg,p->z.flags);
+
+				while(p3)
+				{
+//					printf(" next op: %x, q1reg: %d, q1flags: %x, q2reg: %d, q2flags: %x\n",
+//						p2->code,p2->q1.reg,p2->q1.flags,p2->q2.reg,p2->q2.flags);
+					switch(p2->code)
+					{
+						case PUSH:
+							if((p2->q1.flags&(REG|DREFOBJ|VARADR))==REG && p2->q1.reg==p->z.reg)
+							{
+//								printf("p3 code: %x, reg: %d\n",p3->code,p3->q1.reg);
+								if(p3->code!=FREEREG || p3->q1.reg!=p->z.reg)
+									break;
+//								printf("Push: merging\n");
+								p->code=NOP;	// Don't prepare the address to a register...
+								p2->q1=p->q1;	// Push it directly.
+								p2->q1.flags|=VARADR;
+								p3=0;
+							}
+							break;
+						case FREEREG:
+							if(p2->q1.reg==p->z.reg)
+							{
+//								printf("Freereg: bailing out\n");
+								p3=0;
+							}
+							break;
+						default:
+							break;
+					}
+					// Does the IC reference the register?
+					if((p2->q1.flags&REG) && p2->q1.reg==p->z.reg)
+						p3=0;
+					else if((p2->q2.flags&REG) && p2->q2.reg==p->z.reg)
+						p3=0;
+					p2=p3;
+					if(p3)
+						p3=p3->next;
+				}
+				break;
+
+			// Check for GETRETURN followed by TEST/COMPARE of call result which is then discarded...
+			case GETRETURN:
+				if((p->z.flags&(REG|DREFOBJ|SCRATCH))!=(REG|SCRATCH))
+					break;
+
+				// FIXME - can do the same for other instructions, provided we don't need to use r0 to derive the second op.
+
+				if(p3->code!=FREEREG || p3->q1.reg!=p->z.reg)
+					break;
+
+				switch(p2->code)
+				{
+					case TEST:
+						if(p2->q1.flags&(REG|DREFOBJ)!=REG || p2->q1.reg!=p->z.reg)
+							break;
+						p->code=NOP;	// Don't bother retrieving the return value...
+						p2->q1.reg=p->q1.reg;	// Test it directly from return register.
+						break;
+					case SETRETURN:
+						if(p2->q1.flags&(REG|DREFOBJ)!=REG || p2->q1.reg!=p->z.reg)
+							break;
+						p->code=NOP;	// Don't bother retrieving the return value...
+						p2->q1.reg=p->q1.reg;
+						break;
+					case COMPARE:
+						if((p2->q1.flags&(REG|DREFOBJ))==REG && p2->q1.reg==p->z.reg)
+						{
+							// Make sure the other op is simple enough not to need r0: FIXME - can we improve this?
+//							if((p2->q2.flags&(REG|DREFOBJ))==REG || p2->q2.flags&KONST)
+//							{
+								// COMPARE is guaranteed not to touch t1 (r0).
+								p->code=NOP;	// Don't bother retrieving the return value...
+								p2->q1.reg=p->q1.reg;	// Test it directly from return register.
+//							}
+						}
+						else if((p2->q2.flags&(REG|DREFOBJ))==REG && p2->q2.reg==p->z.reg)
+						{
+//							if((p2->q1.flags&(REG|DREFOBJ))==REG || p2->q1.flags&KONST)
+//							{
+								// COMPARE is guaranteed not to touch t1 (r0).
+								p->code=NOP;	// Don't bother retrieving the return value...
+								p2->q2.reg=p->q1.reg;	// Test it directly from return register.
+//							}
+						}
+						break;
+				}
+				break;
+
+			// Loads cause automatic zero-extension so can avoid conversion
+			// in that case.  Arithmetic functions may require conversion - with the exception of AND and (unsigned) SHR,
+			// since neither can result in extra set bits in the MSBs.
+			case CONVERT:
+				if(p2->code==CONVERT)
+				{
+//					printf("Found successive Convert ICs\n");
+//					printf("p1: %x, %d, %x -> %x, p2: %x, %d, %x -> %x\n",p->z.flags,p->z.reg,q1typ(p),ztyp(p),
+//						p2->q1.flags,p2->q1.reg,q1typ(p2),ztyp(p2));
+					if((p->z.flags&(REG|DREFOBJ))==REG && ((p2->q1.flags&(REG|DREFOBJ))==REG) && p->z.reg==p2->q1.reg)
+					{
+//						printf("Register match\n");
+						if(((q1typ(p)&NQ)<(ztyp(p)&NQ)) && (q1typ(p)==ztyp(p2)))
+						{
+//							printf("Sizes match - nullifying conversion to wider type.\n");
+							p->code=NOP;
+							p2->q1=p->q1;
+						}
+					}
+				} else {
+					if (AM_DEBUG)
+						printf("Checking conversion from %d to %d, %d to %d\n",q1typ(p),ztyp(p),p->q1.reg,p->z.reg);
+					/* Eliminate conversions to wider types within a single register if the value is unsigned */
+					if((p->z.flags&(REG|DREFOBJ))==REG && ((p->q1.flags&(REG|DREFOBJ))==REG) && p->z.reg==p->q1.reg) {
+						if((q1typ(p)&UNSIGNED) && (sizetab[q1typ(p) & NQ] < sizetab[ztyp(p) & NQ])) {
+							if (AM_DEBUG)
+								printf("Eliminating unnecessary conversion\n");
+							p->code=NOP;
+						}
+					}
+				}
+//				printic(stdout,p);
+				break;
+
+			// Look for situations where an arithmetic operation will have set flags,
+			// rendering an explicit TEST unnecessary.
+			case TEST:
+				prev=p->prev;
+				if(prev)
+				{
+//					printf("TEST found, evaluating previous IC\n");
+					if(is_arithmetic_bitwise(prev->code))
+					{
+//							printf("Arithmetic / bitwise IC found\n");
+//							printf("%x, %d, %x, %d\n",prev->z.flags,prev->z.reg,p->q1.flags,p->q1.reg);
+						if((prev->z.flags&(REG|DREFOBJ))==REG && ((p->q1.flags&(REG|DREFOBJ))==REG) && prev->z.reg==p->q1.reg)
+						{
+//								printf("Register match\n");
+							p->code=NOP;
+						}
+					}
+				}
+				break;
+
+			default:
+				// Look for cases where multiple arithmetic / bitwise instructions are chained and could
+				// avoid writing to an intermediate register...
+				if(is_arithmetic_bitwise(c) && is_arithmetic_bitwise(p2->code) && p3->code==FREEREG)
+				{
+					if (AM_DEBUG)
+						printf("Evaluating pair of arithmetic ops followed by freereg...\n");
+					if(((p->z.flags&(REG|DREFOBJ))==REG) && ((p2->q1.flags&(REG|DREFOBJ))==REG) && ((p2->z.flags&(REG|DREFOBJ))==REG))
+					{
+						if (AM_DEBUG)
+							printf("Ops are all register based...\n");
+						if (AM_DEBUG)
+							printf("p1.q1: %s, p1.q2: %s, p1.z: %s  -  p2.q1: %s, p2.q2: %s, p2.z: %s\n",
+								regnames[p->q1.reg],regnames[p->q2.reg],regnames[p->z.reg],
+								regnames[p2->q1.reg],regnames[p2->q2.reg],regnames[p2->z.reg]);
+						if(p2->q1.reg==p3->q1.reg && p->z.reg==p2->q1.reg && p2->q1.reg!=p2->z.reg && p2->q2.reg!=p2->z.reg)
+						{
+							if (AM_DEBUG)
+								printf("Freereg matches - adjusting\n");
+							p->z.reg=p2->z.reg;
+							p2->q1.reg=p2->z.reg;
+						}
+					}
+					// FIXME - explore the lifetime of the register we've just avoided; can we
+					// avoid allocating / freeing it?  Won't help the code-generator but might be
+					// able to avoid saving / restoring it in the function head / tail.
+				}
+				else
+				{
+					// Look specificially for addt candidates...
+					if(c==ADD || c==ADDI2P)
+					{
+						int zr=(p->z.flags&(REG|DREFOBJ))==REG ? 1 : 0;
+
+//						printf("add %x, %x, %x, %s, %s, %s\n",p->q1.flags,p->q2.flags,p->z.flags,
+//								regnames[p->q1.reg],regnames[p->q2.reg],regnames[p->z.reg]);
+						if((p->q1.flags&(REG|DREFOBJ))==REG)
+						{
+							if(!zr || p->z.reg!=p->q1.reg)
+							{
+								if((p->q2.flags&(REG|DREFOBJ))==REG)  // reg + reg => reg
+								{
+									// All three operands are registers - are they all different?
+									if((zr || p->z.reg!=p->q2.reg) && p->q1.reg!=p->q2.reg)
+									{
+										am_alloc(&p->q1);
+										p->q1.am->type=AM_ADDT;
+										if (AM_DEBUG)
+											printf("Marked addt candidate\n");
+									}
+								}
+								if((p->q2.flags&(KONST|DREFOBJ))==KONST) // reg + const => reg
+								{
+									am_alloc(&p->q1);
+									p->q1.am->type=AM_ADDT;
+									if (AM_DEBUG)
+									{
+										printf("Marked addt candidate\n");
+										printf("Reg + Konst => Reg\n");
+									}
+								}
+							}
+						}
+					}
+				}
+				break;
+		}
+	}
+}
+
+void am_disposable(struct IC *p, struct obj *o)
+{
+	struct IC *p2;
+	int disposable = 0;
+	if (o->flags & REG) {
+		// Cover the case where q1 or q2 are the same register as z.
+		if(o!=&p->z)
+		{
+			// We're writing to the same register as we're reading from - not disposable!
+			if((p->z.flags&REG) && p->z.reg==o->reg)
+				return;
+		}
+		p2 = p->next;
+		while (p2) {
+			if (p2->code == FREEREG && p2->q1.reg == o->reg) {
+				if (AM_DEBUG)
+					printf("\t(%s disposable.)\n", regnames[o->reg]);
+				am_alloc(o);
+				o->am->disposable = 1;
+				return;
+			}
+			if (((p2->q1.flags & REG)
+			     && p2->q1.reg == o->reg)
+			    || ((p2->q2.flags & REG)
+				&& p2->q2.reg == o->reg)
+			    || ((p2->z.flags & REG)
+				&& p2->z.reg == o->reg)) {
+				//Found another instruction referencing reg - not disposable.
+				return;
+			}
+			switch (p2->code) {
+			case CALL:
+			case BEQ:
+			case BNE:
+			case BLT:
+			case BGE:
+			case BLE:
+			case BGT:
+			case BRA:
+				// Control flow changed, erring on the side of safety - not disposable.
+				return;
+				break;
+			default:
+				break;
+			}
+			p2 = p2->next;
+		}
+	}
+}
+
+struct obj *throwaway_reg(struct IC *p,int reg)
+{
+	struct obj *result=0;
+	if (AM_DEBUG)
+		printf("\tChecking IC for reg %s\n", regnames[reg]);
+	if(p) {
+		if((p->q1.flags&REG) && p->q1.reg==reg) {
+			am_disposable(p,&p->q1);
+			if(p->q1.am && p->q1.am->disposable)
+				result=&p->q1;
+		} else if((p->z.flags&REG) && p->z.reg==reg) {
+			am_disposable(p,&p->z);
+			if(p->z.am && p->z.am->disposable)
+				result=&p->z;
+		}
+	}
+	if (AM_DEBUG)
+		printf("\tReturning %x\n", result);
+	return(result);
+}
+
+
+struct IC *am_find_adjustment(struct IC *p, int reg)
+{
+	struct IC *p2 = p->next;
+	// FIXME - limit how many steps we check...
+	/* Look for a post-increment */
+	while (p2) {
+//		printf("\t\tChecking code %d\n",p2->code);
+		if (p2->code == ADDI2P) {
+//			if (AM_DEBUG)
+//				printf("\tFound Addi2p to register %s \n", regnames[p2->z.reg]);
+			if ((p2->q2.flags & KONST) && (p2->z.flags & REG)) {
+				if (p2->z.reg == reg) {
+					if (AM_DEBUG)
+						printf("\t\tAdjusting the correct register - match found\n");
+					break;
+				} else {
+					if(p2 && p2->q1.reg == reg) {	
+						if (AM_DEBUG)
+							printf("\t\tWriting to different reg - is source reg disposable?  ");
+						am_disposable(p2, &p2->q1);
+						if(p2->q1.am && p2->q1.am->disposable){
+							if (AM_DEBUG)
+								printf("yes\n");
+							break;
+						} else {
+							if (AM_DEBUG)
+								printf("no - bailing out\n");
+							p2=0;
+						}
+					} else {
+						if (AM_DEBUG)
+							printf("\t\tWrong register - keep looking\n");
+					}
+				}
+			} else {
+				if (AM_DEBUG)
+					printf("\t\tnot a constant, however - bailing out.\n");
+				p2 = 0;
+			}
+		} else if (((p2->q1.flags & (REG | DREFOBJ)) && p2->q1.reg == reg)
+			   || ((p2->q2.flags & (REG | DREFOBJ))
+			       && p2->q2.reg == reg)
+			   || ((p2->z.flags & (REG | DREFOBJ))
+			       && p2->z.reg == reg)) {
+			if (AM_DEBUG)
+				printf("\t\tFound another instruction referencing reg - bailing out\n");
+			p2 = 0;
+		} else if (p2->code>=BEQ && p2->code<=BRA) {
+			if (AM_DEBUG)
+				printf("\t\tFound a branch instruction - bailing out\n");
+			p2 = 0;
+		} else if (p2->code>=LABEL) {
+			if (AM_DEBUG)
+				printf("\t\tFound a label - bailing out\n");
+			p2 = 0;
+		}
+		if (p2)
+			p2 = p2->next;
+	}
+	if (p2)
+		return (p2);
+	if (AM_DEBUG)
+		printf("\tNo postincrements found - checking for predecrements\n");
+	/* Search for a predecrement */
+	p2 = p->prev;
+	while (p2) {
+		if (p2->code == SUBIFP) {
+			if (AM_DEBUG)
+				printf("\t\tFound subifp to register %s \n", regnames[p2->z.reg]);
+			if ((p2->q2.flags & KONST) && (p2->z.flags & REG)) {
+				if (p2 && p2->z.reg == reg) {
+					if (AM_DEBUG)
+						printf("\t\tAdjusting the correct register - match found\n");
+					break;
+				} else {
+					if(p2 && p2->q1.reg == reg) {	
+						if (AM_DEBUG)
+							printf("\t\tWriting to different reg - is source reg disposable?  ");
+						am_disposable(p2, &p2->q1);
+						if(p2->q1.am && p2->q1.am->disposable){
+							if (AM_DEBUG)
+								printf("yes\n");
+							break;
+						} else {
+							if (AM_DEBUG)
+								printf("no - bailing out\n");
+						}
+					}
+				}
+			} else {
+				if (AM_DEBUG)
+					printf("\t\tnot a constant, however - bailing out.\n");
+				p2 = 0;
+			}
+		} else if (((p2->q1.flags & (REG | DREFOBJ)) && p2->q1.reg == reg)
+			   || ((p2->q2.flags & (REG | DREFOBJ))
+			       && p2->q2.reg == reg)
+			   || ((p2->z.flags & (REG | DREFOBJ))
+			       && p2->z.reg == reg)) {
+			if (AM_DEBUG)
+				printf("\t\tFound another instruction referencing reg - bailing out\n");
+			p2 = 0;
+		}
+		// FIXME - check for control flow changes
+		if (p2)
+			p2 = p2->prev;
+	}
+	return (p2);
+}
+
+// If we have a candidate for pre/post increment/decrement, validate that we can use it,
+// and return the offset.  Zero if we can't use it.
+int am_get_adjvalue(struct IC *p, int type, int target)
+{
+	int offset = p->q2.val.vmax;
+	if (p->code == SUBIFP)
+		offset = -offset;
+	if (AM_DEBUG)
+		printf("Offset is %d, type is %d, writing to target? %s\n", offset, type & NQ, target ? "yes" : "no");
+	// Validate offset against type and CPU's capabilities.
+	switch (type & NQ) {
+	case CHAR:		// We only support postincrement for CHARs
+		if (offset != 1)
+			offset = 0;
+		if (p->code == SUBIFP)
+			offset = 0;
+		break;
+	case INT:
+	case LONG:
+	case POINTER:		// We support post-increment and predecrement for INTs/LONGs/PTRs
+//                      if(target && offset!=-4)        // We only support predec for writing.
+		if (target && ((offset != -4) && (offset != 4)))	// We now support predec and postinc for writing.
+			offset = 0;
+		if (!target && offset != 4)	// We only support postinc for reading
+			offset = 0;
+		if (p->code == ADDI2P && offset != 4)
+			offset = 0;
+		if (p->code == SUBIFP && offset != -4)
+			offset = 0;
+		break;
+	case SHORT:		// We don't support either mode for shorts or anything else.
+	default:
+		offset = 0;
+	}
+	if (AM_DEBUG)
+		printf("Validated offset is %d\n", offset);
+	return (offset);
+}
+
+void am_prepost_incdec(struct IC *p, struct obj *o)
+{
+	struct IC *p2 = 0;
+	int type;
+
+	if (o->flags & (REG) && (o->flags & DREFOBJ)) {
+		if (AM_DEBUG)
+			printf("Dereferencing register %s - searching for adjustments\n", regnames[o->reg]);
+		p2 = am_find_adjustment(p, o->reg);
+
+		if (p2)		// Did we find a candidate for postinc / predec?
+		{
+			int adj;
+			switch (p->code) {
+			case CONVERT:
+				// Are we considering q1 or z?
+				if(o==&p->z)
+					type = p->typf;
+				else
+					type = p->typf2;
+				if (AM_DEBUG)
+					printf("\tConvert operation - type is %d\n", type);
+				break;
+			default:
+				if (AM_DEBUG)
+					printf("\tRegular operation - type is %d\n", p->typf);
+				type = p->typf;
+				break;
+			}
+			adj = am_get_adjvalue(p2, type, o == &p->z);	// Validate the adjustment
+			if (adj) {
+				obj *tempob;
+				switch(p2->code)
+				{
+					case ADDI2P:
+					case SUBIFP:
+						// Are the source and destination regs the same?
+						if(p2->q1.reg==p2->z.reg) {
+							p2->code=NOP; // Nullify the manual adjustment if we can do it as an opcode side-effect
+							break;
+						}
+
+						// Check next IC to see if it's disposable, and referencing the same register:
+						if(tempob=throwaway_reg(p2->next,p2->z.reg)) {
+							if (AM_DEBUG)
+								printf("\tChangingnext IC from reg %s to reg %s\n", regnames[tempob->reg], regnames[p2->q1.reg]);
+							tempob->reg=p2->q1.reg; // Adjust the register referenced in the next IC.
+							p2->code=NOP; // Nullify the adjustment since we've aliased the register
+						}
+						else
+							p2->code=ASSIGN; // Otherwise replace it with an assign if the registers aren't equal.
+						break;
+					default:
+						p2->code = NOP;	// Nullify the manual adjustment if we can do it as an opcode side-effect
+						break;
+				}
+				am_alloc(o);
+				o->am->type = (adj > 0) ? AM_POSTINC : AM_PREDEC;
+			}
+		}
+	}
+}
+
+#define getreg(x) (x.flags&REG ? x.reg : 0)
+
+static void find_addressingmodes(struct IC *p)
+{
+	int c;
+	struct obj *o;
+	struct AddressingMode *am;
+
+	am_deferredpop(p);
+	am_simplify(p);
+//	am_conversions(p);
+
+	for (; p; p = p->next) {
+		c = p->code;
+
+		// Have to make sure that operands are different registers!
+		if ((getreg(p->q1) == getreg(p->q2))
+		    || (getreg(p->q1) == getreg(p->z))) {
+			if (getreg(p->q1))
+				if (AM_DEBUG)
+					printf("Collision between q1 and q2 or z - ignoring\n");
+		} else
+			am_prepost_incdec(p, &p->q1);
+
+		if ((getreg(p->q1) == getreg(p->q2))
+		    || (getreg(p->q2) == getreg(p->z))) {
+			if (getreg(p->q1))
+				if (AM_DEBUG)
+					printf("Collision between q2 and q1 or z - ignoring\n");
+		} else
+			am_prepost_incdec(p, &p->q2);
+
+		if ((getreg(p->q1) == getreg(p->z))
+		    || (getreg(p->q2) == getreg(p->z))) {
+			if (getreg(p->z))
+				if (AM_DEBUG)
+					printf("Collision between z and q1 or q2 - ignoring\n");
+		} else
+			am_prepost_incdec(p, &p->z);
+//		printic(stdout,p);
+
+		am_disposable(p, &p->q1);
+		am_disposable(p, &p->q2);
+		am_disposable(p, &p->z);
+	}
+}
+
diff --git a/machines/832/inlinememcpy.c b/machines/832/inlinememcpy.c
new file mode 100644
index 0000000..aa146f5
--- /dev/null
+++ b/machines/832/inlinememcpy.c
@@ -0,0 +1,262 @@
+/* FIXME - emit a memcpy function with weak linkage if -size is specified */
+
+void emit_inlinememcpy(FILE *f,struct IC *p, int t)
+{
+	int srctype=t;
+	int srcr = t1;
+	int dstr=0;
+	int cntr=0;
+	int savec=1;
+	int saved=0;
+	int wordcopy;
+	int bytecopy;
+	zmax copysize = opsize(p);
+	int unrollwords=0;
+	int unrollbytes=0;
+
+	// Can we create larger code in the interests of speed?  If so, partially unroll the copy.
+	wordcopy = copysize & ~3;
+	bytecopy = copysize - wordcopy;
+
+	if (wordcopy < 32 && !optsize)
+		unrollwords=1;
+	if (bytecopy < 5)
+		unrollbytes=1;
+
+	cleartempobj(f,t1);
+	cleartempobj(f,tmp);
+
+	// Even if a register is available we still have to save it because the current function wouldn't
+	// but the parent function may be using it.  Therefore we might as well use a hardcoded register.
+	dstr=t1+1;
+	if(p->z.flags&(REG|DREFOBJ)==REG)
+		dstr=p->z.reg;
+	// FIXME - check this logic.  If the target is a register, it may not be a scratch register.
+	if(regs[dstr]) // Scratch register - only need to save if it's in use?
+	{
+		saved=1;
+		emit(f,"\tmt\t%s\n",regnames[dstr]);
+		emit(f,"\tstdec\t%s\n",regnames[sp]);
+		pushed+=4;
+	}
+
+	cntr=t1+2;
+	if(cntr==dstr)	/* Use r1 instead of r2 if the dest pointer is in r2 already. */
+		cntr=t1+1;
+	if(cntr==srcr)  /* If cntr && srcr now clash, use r3 instead */
+		cntr=t1+3;
+
+	if((unrollwords && unrollbytes) || regs[cntr]==0)
+		savec=0;
+	else {
+		emit(f,"\tmt\t%s\n",regnames[cntr]);
+		emit(f,"\tstdec\t%s\n",regnames[sp]);
+		pushed+=4;
+	}
+
+	/* Prepare source register */
+	if ((t & NQ) == CHAR && (opsize(p) != 1)) {
+		emit(f, "\t\t\t\t\t// (char with size!=1 -> array of unknown type)\n");
+		srctype = ARRAY;	// FIXME - ugly hack
+	}
+	emit_objtoreg(f, &p->q1, srctype,srcr);
+
+	/* Prepare destination register */
+
+	emit_prepobj(f, &p->z, t, dstr, 0);
+
+	if (p->z.flags & REG) {
+		if(p->z.reg!=dstr) {// Move target register to dstr
+			emit(f, "\tmt\t%s\n", regnames[p->z.reg]);
+			emit(f, "\tmr\t%s\n", regnames[dstr]);
+		}
+	}
+
+	emit(f, "\t\t\t\t\t// Copying %d words and %d bytes to %s\n", wordcopy / 4, bytecopy,
+	     p->z.v ? p->z.v->identifier : "(null)");
+//	printf("memcpy: Copying %d words and %d bytes to %s\n", wordcopy / 4, bytecopy,
+//	     p->z.v ? p->z.v->identifier : "(null)");
+
+//	if(!p->z.v)
+//		printf("No z->v: z flags: %x\n",p->z.flags);
+
+	// Prepare the copy
+	// FIXME - we don't necessarily have a valid z->v!  If not, where does the target come from?
+	// Stack based variable?
+
+	if (unrollwords) {
+		wordcopy >>= 2;
+		if (wordcopy) {
+			emit(f, "\t\t\t\t\t// Copying %d words to %s\n", wordcopy, p->z.v ? p->z.v->identifier : "(null)");
+		}
+		while (wordcopy--) {
+			emit(f, "\tldinc\t%s\n\tstinc\t%s\n", regnames[srcr], regnames[dstr]);
+		}
+	} else if(wordcopy) {
+		emit(f, "\t\t\t\t\t// Copying %d words to %s\n", wordcopy / 4, p->z.v ? p->z.v->identifier : "(null)");
+		// Copy bytes...
+		emit_constanttotemp(f, wordcopy);
+		emit(f, "\taddt\t%s\n", regnames[dstr]);
+		emit(f, "\tmr\t%s\n", regnames[cntr]);
+		emit(f, ".cpy%swordloop%d:\n", p->z.v ? p->z.v->identifier : "null", loopid);
+		emit(f, "\tldinc\t%s\n\tstinc\t%s\n", regnames[srcr], regnames[dstr]);
+		emit(f, "\tmt\t%s\n\tcmp\t%s\n", regnames[dstr], regnames[cntr]);
+		emit(f, "\tcond\tNEQ\n");
+		emit(f, "\t\t.lipcrel\t.cpy%swordloop%d\n", p->z.v ? p->z.v->identifier : "null", loopid);
+		emit(f, "\t\tadd\t%s\n", regnames[pc]);
+	}
+
+	if (unrollbytes) {
+		if (bytecopy)
+			emit(f, "\t\t\t\t\t// Copying %d byte tail to %s\n", bytecopy,p->z.v ? p->z.v->identifier : "null");
+		while (bytecopy--)
+			emit(f, "\tldbinc\t%s\n\tstbinc\t%s\n", regnames[srcr], regnames[dstr]);
+	} else if (bytecopy) {
+		emit(f, "\t\t\t\t\t// Copying %d bytes to %s\n", bytecopy, p->z.v ? p->z.v->identifier : "null");
+		// Copy bytes...
+		emit_constanttotemp(f, bytecopy);
+		emit(f, "\taddt\t%s\n", regnames[dstr]);
+		emit(f, "\tmr\t%s\n", regnames[cntr]);
+		emit(f, ".cpy%sloop%d:\n", p->z.v ? p->z.v->identifier : "null", loopid);
+		emit(f, "\tldbinc\t%s\n\tstbinc\t%s\n", regnames[srcr], regnames[dstr]);
+		emit(f, "\tmt\t%s\n\tcmp\t%s\n", regnames[dstr], regnames[cntr]);
+		emit(f, "\tcond\tNEQ\n");
+		emit(f, "\t\t.lipcrel\t.cpy%sloop%d\n", p->z.v ? p->z.v->identifier : "null", loopid);
+		emit(f, "\t\tadd\t%s\n", regnames[pc]);
+
+	}
+	// cleanup
+	if(savec) {
+		emit(f,"\tldinc\t%s\n",regnames[sp]);
+		emit(f,"\tmr\t%s\n",regnames[cntr]);
+		pushed-=4;
+	}
+	if(saved) {
+		emit(f,"\tldinc\t%s\n",regnames[sp]);
+		emit(f,"\tmr\t%s\n",regnames[dstr]);
+		pushed-=4;
+	}
+	cleartempobj(f,t1);
+	cleartempobj(f,tmp);
+	loopid++;
+}
+
+
+/* Similar to inlinememcpy, but copies an array or struct to the stack */
+
+void emit_inlinepush(FILE *f,struct IC *p, int t)
+{
+	int srcr = t1;
+	int dstr=0;
+	int cntr=0;
+	int savec=1;
+	int saved=0;
+	int wordcopy;
+	int bytecopy;
+	zmax copysize = opsize(p);
+	int unrollwords=0;
+	int unrollbytes=0;
+
+	// Can we create larger code in the interests of speed?  If so, partially unroll the copy.
+	wordcopy = copysize & ~3;
+	bytecopy = copysize - wordcopy;
+
+	if ((wordcopy < 32 && !optsize) || (wordcopy<16))
+		unrollwords=1;
+	if (bytecopy < 5)
+		unrollbytes=1;
+
+	cleartempobj(f,t1);
+	cleartempobj(f,tmp);
+
+	// Even if a register is available we still have to save it because the current function wouldn't
+	// but the parent function may be using it.  Therefore we might as well use a hardcoded register.
+	dstr=sp;
+
+	// FIXME - don't necessarily need the counter register if the copy is small...
+
+	/* Is our source a register?  If so, set srcr accordingly */
+	if (p->q1.flags & REG) {
+		srcr=p->q1.reg;
+		cntr=t1;
+	} else
+		cntr=t1+2;
+
+	if((unrollwords && unrollbytes) || regs[cntr]==0)
+		savec=0;
+	else {
+		emit(f,"\tmt\t%s\n",regnames[cntr]);
+		emit(f,"\tstdec\t%s\n",regnames[sp]);
+		pushed+=4;
+	}
+
+	emit(f, "\t\t\t\t\t// Copying %d words and %d bytes to stack\n", wordcopy / 4, bytecopy);
+
+//	if(!p->z.v)
+//		printf("No z->v: z flags: %x\n",p->z.flags);
+
+	// Prepare the copy
+	emit_prepobj(f, &p->q1, t,srcr,0);
+
+	// Make room on the stack for the copied object
+
+	emit(f,"\t.liconst\t%d\n",pushsize(p));
+	emit(f,"\tsub\t%s\n",regnames[sp]);
+
+	if (unrollwords) {
+		wordcopy >>= 2;
+		if (wordcopy) {
+			emit(f, "\t\t\t\t\t// Copying %d words to stack\n", wordcopy);
+		}
+		while (wordcopy--) {
+			emit(f, "\tldinc\t%s\n\tstinc\t%s\n", regnames[srcr], regnames[dstr]);
+		}
+	} else {
+		emit(f, "\t\t\t\t\t// Copying %d words to stack\n", wordcopy / 4);
+		// Copy bytes...
+		emit_constanttotemp(f, wordcopy);
+		emit(f, "\taddt\t%s\n", regnames[dstr]);
+		emit(f, "\tmr\t%s\n", regnames[cntr]);
+		emit(f, ".cpystackwordloop%d:\n", loopid);
+		emit(f, "\tldinc\t%s\n\tstinc\t%s\n", regnames[srcr], regnames[dstr]);
+		emit(f, "\tmt\t%s\n\tcmp\t%s\n", regnames[dstr], regnames[cntr]);
+		emit(f, "\tcond\tNEQ\n");
+		emit(f, "\t\t.lipcrel\t.cpystackwordloop%d\n", loopid);
+		emit(f, "\t\tadd\t%s\n", regnames[pc]);
+	}
+
+	if (unrollbytes) {
+		if (bytecopy)
+			emit(f, "\t\t\t\t\t// Copying %d byte tail to stack\n", bytecopy);
+		while (bytecopy--)
+			emit(f, "\tldbinc\t%s\n\tstbinc\t%s\n", regnames[srcr], regnames[dstr]);
+	} else {
+		emit(f, "\t\t\t\t\t// Copying %d bytes to stack\n", bytecopy);
+		// Copy bytes...
+		emit_constanttotemp(f, bytecopy);
+		emit(f, "\taddt\t%s\n", regnames[dstr]);
+		emit(f, "\tmr\t%s\n", regnames[cntr]);
+		emit(f, ".cpystackloop%d:\n", loopid);
+		emit(f, "\tldbinc\t%s\n\tstbinc\t%s\n", regnames[srcr], regnames[dstr]);
+		emit(f, "\tmt\t%s\n\tcmp\t%s\n", regnames[dstr], regnames[cntr]);
+		emit(f, "\tcond\tNEQ\n");
+		emit(f, "\t\t.lipcrel\t.cpystackloop%d\n", loopid);
+		emit(f, "\t\tadd\t%s\n", regnames[pc]);
+
+	}
+	// cleanup
+
+	// Reset the stack pointer since we've been blithely post-incrementing it.
+	emit(f,"\t.liconst\t%d\n",opsize(p));
+	emit(f,"\tsub\t%s\n",regnames[sp]);
+
+	if(savec) {
+		emit(f,"\tldinc\t%s\n",regnames[sp]);
+		emit(f,"\tmr\t%s\n",regnames[cntr]);
+		pushed-=4;
+	}
+	cleartempobj(f,t1);
+	cleartempobj(f,tmp);
+	loopid++;
+}
+
diff --git a/machines/832/libcalls.c b/machines/832/libcalls.c
new file mode 100644
index 0000000..291f062
--- /dev/null
+++ b/machines/832/libcalls.c
@@ -0,0 +1,50 @@
+/* First steps towards LONG LONG and FLOAT support.
+   832 is not well suited to handling these types. */
+
+char *use_libcall(int code,int typf1, int typf2)
+{
+	char *result=0;
+//	printf("Querying libcall for %d, %d, %d\n",code,typf1,typf2);
+	switch(code)
+	{
+		case CONVERT:
+			if((typf1&NU)==LLONG && (typf2&NU)==INT)
+				return("__conv_ll_int\n");
+			if((typf1&NU)==(UNSIGNED|LLONG) && (typf2&NU)==(UNSIGNED|INT))
+				return("__conv_ull_uint\n");
+			if((typf1&NU)==INT && (typf2&NU)==LLONG)
+				return("__conv_int_ll\n");
+			if((typf1&NU)==(UNSIGNED|INT) && (typf2&NU)==(UNSIGNED|LLONG))
+				return("__conv_uint_ull\n");
+		case ADD:
+			if((typf1&NU)==LLONG)
+				return("__add_ll_ll\n");
+			if((typf1&NU)==(UNSIGNED|LLONG))
+				return("__add_ull_ull\n");
+		case MULT:
+			if((typf1&NU)==LLONG && (typf2&NU)==INT)
+				return("__mul_ll_int\n");
+			if((typf1&NU)==(UNSIGNED|LLONG) && (typf2&NU)==(UNSIGNED|INT))
+				return("__mul_ull_uint\n");
+			if((typf1&NU)==LLONG && (typf2&NU)==LLONG)
+				return("__mul_ll_ll\n");
+			if((typf1&NU)==(UNSIGNED|LLONG) && (typf2&NU)==(UNSIGNED|LLONG))
+				return("__mul_ull_ull\n");
+		default:
+			break;	
+	}
+	return(result);
+}
+
+void declare_builtins()
+{
+	declare_builtin("__conv_int_ll",INT,LLONG,0,LLONG,0,1,0);
+	declare_builtin("__conv_ull_ull",UNSIGNED|INT,UNSIGNED|LLONG,0,UNSIGNED|LLONG,0,1,0);
+	declare_builtin("__add_ll_ll",LLONG,LLONG,0,LLONG,0,1,0);
+	declare_builtin("__add_ull_ull",UNSIGNED|LLONG,UNSIGNED|LLONG,0,UNSIGNED|LLONG,0,1,0);
+	declare_builtin("__mul_ll_ll",LLONG,LLONG,0,LLONG,0,1,0);
+	declare_builtin("__mul_ull_ull",UNSIGNED|LLONG,UNSIGNED|LLONG,0,UNSIGNED|LLONG,0,1,0);
+	declare_builtin("__mul_ll_int",LLONG,LLONG,0,INT,0,1,0);
+	declare_builtin("__mul_ull_uint",UNSIGNED|LLONG,UNSIGNED|LLONG,0,UNSIGNED|INT,0,1,0);
+}
+
diff --git a/machines/832/machine.c b/machines/832/machine.c
new file mode 100644
index 0000000..03899e3
--- /dev/null
+++ b/machines/832/machine.c
@@ -0,0 +1,2420 @@
+/*  EightThirtyTwo backend for vbcc,
+	based on the generic RISC backend
+
+	The CPU targeted by this backend, and the latest version, can be found at
+    https://github.com/robinsonb5/EightThirtyTwo
+
+*/
+
+// DONE - T2 no longer used at all - frees up a register for the main code generator
+
+// DONE Update the memcpy code to save/allocate registers if needed.
+// DONE Update the div code likewise.
+
+// Complete the work on object tracking.  In particular take care of tracking an object vs
+// its address.
+// Also track via addressing-mode analysis whether or not it's valuable to save a value;
+// Values can also be saved to otherwise unused registers.  (The compiler is almost certainly
+// already smart enough to make use of unused registers for this, however!)
+
+// DONE: eliminate unnecessary register shuffling for compare.
+
+// DONE: Implement block copying
+
+// DONE: Implement division / modulo using library code.
+// DONE: Mark registers as disposable if their contents are never used beyond the current op.
+
+// Look at ways of improving code efficiency.  Look for situations where the output of one IC
+// becomes the input of another?  Would make a big difference when registers are all in use.
+
+// Minus could be optimised for the in-register case.
+
+// DONE: Do we need to reserve two temp registers?  Turns out one was sufficient, and giving
+// the code generator an extra one to play with helped a great deal.
+
+// Restrict byte and halfword storage to static and extern types, not stack-based variables.
+// (Having learned more, bytes and halfwords on the stack are fine, the complication is with
+// function parameters, which are promoted to int - thus the size modifier will be different
+// for parameters and local variables even though both live on the stack.)
+
+// DONE - Avoid moving registers for cmp and test when possible.
+
+// Condition code for test may well be already set by previous load.
+// Done for TEST, do the same for comparisons?
+
+// Deal with dereferencing in temp caching - can we avoid repeated setups in tmp, maybe using r0?
+
+
+#include "supp.h"
+
+#define DBGMSG 1
+
+static char FILE_[] = __FILE__;
+
+/*  Public data that MUST be there.                             */
+
+/* Name and copyright. */
+char cg_copyright[] =
+    "vbcc EightThirtyTwo code-generator, (c) 2019/2020 by Alastair M. Robinson\nBased on the generic RISC example backend (c) 2001 by Volker Barthelmann";
+
+/*  Commandline-flags the code-generator accepts:
+    0: just a flag
+    VALFLAG: a value must be specified
+    STRINGFLAG: a string can be specified
+    FUNCFLAG: a function will be called
+    apart from FUNCFLAG, all other versions can only be specified once */
+int g_flags[MAXGF] = { 0 };
+
+#define FLAG_PIC 0
+#define FLAG_LE 1
+#define FLAG_BE 2
+
+/* the flag-name, do not use names beginning with l, L, I, D or U, because
+   they collide with the frontend */
+/* 832-specific flags, "fpic" enables position independent code - name chosen to match gcc */
+char *g_flags_name[MAXGF] = { "fpic","el","eb" };
+
+char flag_832_bigendian;
+
+/* the results of parsing the command-line-flags will be stored here */
+union ppi g_flags_val[MAXGF] = { 0,0,0 };
+
+/*  Alignment-requirements for all types in bytes.              */
+zmax align[MAX_TYPE + 1];
+
+/*  Alignment that is sufficient for every object.              */
+zmax maxalign;
+
+/*  CHAR_BIT for the target machine.                            */
+zmax char_bit;
+
+/*  sizes of the basic 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. will be initialized in init_cg(),
+    register number 0 is invalid, valid registers start at 1 */
+char *regnames[MAXR + 1];
+
+/*  The Size of each register in bytes.                         */
+zmax regsize[MAXR + 1];
+
+/*  a 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];
+
+/* specifies the priority for the register-allocator, if the same
+   estimated cost-saving can be obtained by several registers, the
+   one with the highest priority will be used */
+int reg_prio[MAXR + 1];
+
+/* an empty reg-handle representing initial state */
+struct reg_handle empty_reg_handle = { 0, 0 };
+
+/* Names of target-specific variable attributes.                */
+char *g_attr_name[] = { "__interrupt", "__ctor", "__dtor", "__weak", 0 };
+
+/****************************************/
+/*  Private data and functions.         */
+/****************************************/
+
+#define USE_COMMONS 0
+
+/* alignment of basic data-types, used to initialize align[] */
+/* In actual fact 832 has full load/store alignment so this is negotiable based on -speed / -size flags. */
+static long malign[MAX_TYPE + 1] = { 1, 1, 2, 4, 4, 4, 4, 8, 8, 1, 4, 1, 1, 1, 4, 1 };
+
+/* sizes of basic data-types, used to initialize sizetab[] */
+static long msizetab[MAX_TYPE + 1] = { 1, 1, 2, 4, 4, 8, 4, 8, 8, 0, 4, 0, 0, 0, 4, 0 };
+
+/* used to initialize regtyp[] */
+static struct Typ ltyp = { LONG }, ldbl = {
+DOUBLE}, lchar = {
+CHAR};
+
+/* macros defined by the backend */
+static char *marray[] = { "__section(x)=__vattr(\"section(\"#x\")\")",
+	"__EIGHTTHIRTYTWO__",
+	"__constructor(pri)=__vattr(\"ctor(\"#pri\")\")",
+	"__destructor(pri)=__vattr(\"dtor(\"#pri\")\")",
+	"__weak=__vattr(\"weak\")",
+	0
+};
+
+/* special registers */
+static int pc;			/*  Program counter                     */
+static int sp;			/*  Stackpointer                        */
+static int tmp;
+static int t1, t2;		/*  temporary gprs */
+static int f1, f2, f3;		/*  temporary fprs */
+static int loopid = 0;	/* must be unique for every function in a compilation unit */
+
+
+/* sections */
+#define DATA 0
+#define BSS 1
+#define CODE 2
+#define RODATA 3
+#define SPECIAL 4
+
+//static long stack;
+static int section = -1, newobj;
+static char *codename = "\t.section\t.text";
+static char *dataname = "\t.section\t.data";
+static char *bssname = "\t.section\t.bss";
+static char *rodataname = "\t.section\t.rodata";
+static int sectionid=0;
+
+/* assembly-prefixes for labels and external identifiers */
+static char *labprefix = "l", *idprefix = "_";
+
+/* variables to keep track of the current stack-offset in the case of
+   a moving stack-pointer */
+static long pushed;
+static long notyetpopped;
+
+static long localsize, rsavesize, argsize;
+
+static int count_constantchunks(zmax v);
+static void emit_constanttotemp(FILE * f, zmax v);
+static void emit_statictotemp(FILE * f, char *lab, int suffix, int offset);
+static void emit_externtotemp(FILE * f, char *lab, int offset);
+static void emit_pcreltotemp2(FILE *f,struct obj *p);
+
+static void emit_prepobj(FILE * f, struct obj *p, int t, int reg, int offset);
+static int emit_objtoreg(FILE * f, struct obj *p, int t,int reg);
+
+/* calculate the actual current offset of an object relativ to the
+   stack-pointer; we use a layout like this:
+   ------------------------------------------------
+   | arguments to this function                   |
+   ------------------------------------------------
+   | return-address [size=4]                      |
+   ------------------------------------------------
+   | caller-save registers [size=rsavesize]       |
+   ------------------------------------------------
+   | local variables [size=localsize]             |
+   ------------------------------------------------
+   | arguments to called functions [size=argsize] |
+   ------------------------------------------------
+   All sizes will be aligned as necessary.
+   For a moving stack-pointer, the stack-pointer will usually point
+   to the bottom of the area for local variables, but will move while
+   arguments are put on the stack.
+
+   This is just an example layout. Other layouts are also possible.
+*/
+
+static long real_offset(struct obj *o)
+{
+	long off = 0;
+	if((o->flags&VAR) && isauto(o->v->storage_class))
+		off=zm2l(o->v->offset);
+//      printf("Parameter offset: %d, localsize: %d, rsavesize: %d\n",off,localsize,rsavesize);
+	if (off < 0) {
+		/* function parameter */
+		off = localsize + rsavesize + 4 - off - zm2l(maxalign);
+	}
+	off += pushed;
+	off += notyetpopped;
+	off += zm2l(o->val.vmax);
+	return off;
+}
+
+
+static int isstackparam(struct obj *o)
+{
+	int result=0;
+//	if(o->flags&VAR && o->flags&REG && o->reg==sp)
+//	if(o->flags&(VAR|DREFOBJ)==VAR)
+	if((o->flags&VAR) && !(o->flags&REG))
+	{
+		if(isauto(o->v->storage_class))
+		{
+			long off = zm2l(o->v->offset);
+			if (off < 0)
+				result=1;
+		}
+	}
+	return(result);
+}
+
+/* Convenience function to determine whether we're assigning to 0(r6)
+   and can thus use a more efficient writing sequence. */
+
+int istopstackslot(struct obj *o)
+{
+	if(!o)
+		return(0);
+	if((o->flags&(VAR|REG|DREFOBJ))==VAR && o->v)
+	{
+		if(isauto(o->v->storage_class)
+				&& real_offset(o)==0)
+			return(1);
+	}
+	return(0);
+}
+
+/* changes to a special section, used for __section() */
+static int special_section(FILE * f, struct Var *v)
+{
+	char *sec;
+	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;
+}
+
+/* Returns 1 if the symbol has weak linkage */
+static int isweak(struct Var *v)
+{
+	if (!v->vattr)
+		return 0;
+	if (strstr(v->vattr, "weak"))
+		return (1);
+	return 0;
+}
+
+/* Emits a pointer to a function in a .ctor or .dtor section for automatic setup/cleanup */
+static int ctor_dtor(FILE * f, struct Var *v)
+{
+	int dtor = 0;
+	char *sec;
+	if (!v->vattr)
+		return 0;
+	sec = strstr(v->vattr, "ctor(");
+	if (!sec) {
+		dtor = 1;
+		sec = strstr(v->vattr, "dtor(");
+	}
+	if (!sec)
+		return 0;
+	sec += strlen("ctor(");
+	emit(f, "\t%s.", dtor ? ".dtor .dtor" : ".ctor .ctor");
+	while (*sec && *sec != ')')
+		emit_char(f, *sec++);
+	emit(f, "\n\t.ref\t%s%s\n", idprefix, v->identifier);
+
+	return 1;
+}
+
+
+#define TEMP_TMP 0
+#define TEMP_T1 1
+struct tempobj
+{
+	struct obj o;
+	int reg;
+};
+struct tempobj tempobjs[2];
+
+void cleartempobj(FILE *f, int reg)
+{
+	int i;
+	if(reg==tmp) i=TEMP_TMP;
+	else if(reg==t1) i=TEMP_T1;
+	else return;
+//	emit(f,"// clearing %s\n",regnames[reg]);
+
+	tempobjs[i].reg=0;
+}
+
+void settempkonst(FILE *f,int reg,int v)
+{
+	int i;
+	if(reg==tmp) i=TEMP_TMP;
+	else if(reg==t1) i=TEMP_T1;
+	else return;
+	tempobjs[i].reg=reg;
+	tempobjs[i].o.flags=KONST;
+	tempobjs[i].o.val.vlong=v;
+//	emit(f,"// set %s to konst %d\n",regnames[reg],v);
+}
+
+
+// Add an adjustment due to postinc / predec to a cached object
+void adjtempobj(FILE *f,int reg,int offset)
+{
+	if(reg<=1)
+		tempobjs[reg].o.val.vlong+=offset;
+}
+
+
+// Store any passing value in tempobj records for optimisation.
+// FIXME - need to figure out VARADR semantics for stored objects.
+void settempobj(FILE *f,int reg,struct obj *o,int offset,int varadr)
+{
+	int i;
+	if(reg==tmp) i=TEMP_TMP;
+	else if(reg==t1) i=TEMP_T1;
+	else return;
+//	if(reg==t1)
+//		emit(f,"// Setting %s to %x (%x)\n",regnames[reg],o,o->v);
+	tempobjs[i].reg=reg;
+	tempobjs[i].o=*o;
+	tempobjs[i].o.val.vlong+=offset;	// Account for any postinc / predec
+	if(varadr)
+		tempobjs[i].o.flags|=VARADR;
+}
+
+
+// Compare a pair of struct obj* for equivalence.
+// The first object should be the "live" object, the second one the cached object."
+int matchobj(FILE *f,struct obj *o1,struct obj *o2,int varadr)
+{
+	int result=1;
+	int flg=o1->flags;
+	if(varadr)
+		flg|=VARADR;
+//	emit(f,"// comparing flags %x with %x\n",o1->flags, o2->flags);
+//	if((o1->flags&~VARADR)!=(o2->flags&~VARADR))
+	// FIXME - need to figure out VARADR semantics for stored objects.
+	emit(f,"\t\t\t\t\t\t// matchobj comparing flags %d with %d\n",flg,o2->flags);
+	if(flg!=(o2->flags))
+		return(0);
+
+//	emit(f,"// comparing regs %d with %d\n",o1->reg, o2->reg);
+	// If the register-based value is being dereferenced we would have to track
+	// the register itself being updated.  Unless the value's in tmp using a cached
+	// version isn't a win anyway.
+	if((o1->flags&(REG|DREFOBJ)==REG) && (o1->reg==o2->reg))
+		return(1);
+
+	if(o1->flags&KONST)
+	{
+//		emit(f,"\t\t\t\t\t\t// Comparing constants %x with %x\n",o1->val.vlong,o2->val.vlong);
+		if(o1->val.vlong == o2->val.vlong)
+			return(1);
+		else
+		{			// Attempt fuzzy matching...
+			int d=o1->val.vlong-o2->val.vlong;
+			// Don't bother if we need fewer than four LIs to represent the value, or if we'd need more than 1 LI for the offset.
+			if(count_constantchunks(o1->val.vlong)<4 || count_constantchunks(d)>1)
+			{
+//				emit(f,"\t\t\t\t\t\t// Gains from fuzzy matching too small, ignoring.\n");
+				return(0);
+			}
+			else
+				return(2);
+		}
+	}
+
+	if(!(o1->flags&VAR))
+		return(0); // Not a var?  Can't do any more.
+
+	if(o1->v==0 || o2->v==0)
+		return(0);
+
+	if(o1->v == o2->v && o1->val.vlong == o2->val.vlong)
+		return(1);
+
+	if(!(flg&VARADR))
+		return(0); // Can only attempt fuzzy matching if this is a varadr
+
+	if(isauto(o1->v->storage_class) && isauto(o2->v->storage_class))
+	{
+		if(DBGMSG)
+			emit(f,"\t\t\t\t\t\t//auto: flags: %x, comparing %d, %d with %d, %d\n",
+				flg,o1->v->offset,o1->val.vlong, o2->v->offset,o2->val.vlong);
+		// Can't fuzzy match between parameters and vars on stack
+		if((o1->v->offset<0 && o2->v->offset>=0) || (o1->v->offset>=0 && o2->v->offset<0))
+			return(0);
+		if(o1->v->offset==o2->v->offset && o1->val.vlong==o2->val.vlong)
+			return(1);
+		if((o1->flags&DREFOBJ) || (o2->flags&DREFOBJ))	// Can't fuzzy match if we're dereferencing.
+			return(0);
+		return(2);
+	}
+
+	if(isextern(o1->v->storage_class) && isextern(o2->v->storage_class))
+	{
+		if(DBGMSG)
+			emit(f,"\t\t\t\t\t\t//extern: comparing %d with %d\n",o1->val.vlong, o2->val.vlong);
+		if(strcmp(o1->v->identifier,o2->v->identifier))
+			return(0);
+		if(o1->val.vlong==o2->val.vlong)
+			return(1);
+		if((o1->flags&DREFOBJ) || (o2->flags&DREFOBJ))	// Can't fuzzy match if we're dereferencing.
+			return(0);
+		return(2);
+	}
+
+	return(0);
+}
+
+
+int matchoffset(struct obj *o,struct obj *o2)
+{
+	if(o->flags&KONST)
+		return(o->val.vlong-o2->val.vlong);
+	if(isextern(o->v->storage_class))
+		return(o->val.vlong-o2->val.vlong);
+	if(isauto(o->v->storage_class))
+//		return((o->val.vlong+real_offset(o))-(o2->val.vlong+real_offset(o2)));
+		return((o->val.vlong+o->v->offset)-(o2->val.vlong+o2->v->offset));
+	return(0);
+}
+
+
+void obsoletetempobj(FILE *f,int reg,struct obj *o,int varadr)
+{
+//	emit(f,"\t\t\t\t\t// Attempting to obsolete obj\n");
+	if(tempobjs[0].reg==reg && matchobj(f,o,&tempobjs[0].o,varadr))
+	{
+		emit(f,"\t\t\t\t\t\t// Obsoleting tmp\n");
+		cleartempobj(f,tmp);
+	}
+	if(tempobjs[1].reg==reg && matchobj(f,o,&tempobjs[0].o,varadr))
+	{
+		emit(f,"\t\t\t\t\t\t// Obsoleting t1\n");
+		cleartempobj(f,t1);
+	}
+}
+
+
+// Check the tempobj records to see if the value we're interested in can be found in either.
+int matchtempobj(FILE *f,struct obj *o,int varadr,int preferredreg)
+{
+	int hit=0;	// Hit will be 1 for an exact match, 2 for a near miss.
+//	return(0); // Temporarily disable matching
+	if(tempobjs[0].reg && (hit=matchobj(f,o,&tempobjs[0].o,varadr)))
+	{
+//		emit(f,"//match found - tmp\n");
+//		printf("//match found - tmp\n");
+		if(hit==1)
+			return(tempobjs[0].reg);
+		else if(hit==2)
+		{
+			int offset=matchoffset(o,&tempobjs[0].o);
+			emit(f,"\t\t\t\t\t\t// Fuzzy match found against tmp.\n");
+			if(preferredreg==tmp)
+			{
+				emit(f,"\tmr\t%s\n",regnames[t1]);
+				emit(f,"\t.liconst\t%d\n",offset);
+				emit(f,"\taddt\t%s\n",regnames[t1]);
+				settempobj(f,t1,&tempobjs[0].o,0,0);
+				settempobj(f,tmp,o,0,varadr);
+			}
+			else
+			{
+				emit(f,"\tmr\t%s\n",regnames[preferredreg]);
+				emit(f,"\t.liconst\t%d\n",offset);
+				settempkonst(f,tmp,offset);
+				emit(f,"\tadd\t%s\n",regnames[preferredreg]);
+				settempobj(f,preferredreg,o,0,varadr);
+			}
+			return(preferredreg);
+//			return(tempobjs[0].reg);
+		}
+		else
+			return(0);
+	}
+	else if(tempobjs[1].reg && (hit=matchobj(f,o,&tempobjs[1].o,varadr)))
+	{
+		// Temporarily disable t1 matching.  FIXME - keep t1 records more up-to-date.
+//		return(0);
+//		emit(f,"//match found - t1\n");
+//		printf("//match found - t1\n");
+		if(hit==1)
+			return(tempobjs[1].reg);
+		else if(hit==2)
+		{
+			int offset=matchoffset(o,&tempobjs[1].o);
+			if(DBGMSG)
+				emit(f,"\t\t\t\t\t\t//Fuzzy match found, offset: %d (varadr: %d)\n",offset,varadr);
+			// Fuzzy match against t1 - if target is t1 use add, otherwise use addt.
+			emit(f,"\t.liconst\t%d\n",offset);
+			if(preferredreg!=tempobjs[1].reg)
+			{
+				emit(f,"\taddt\t%s\n",regnames[tempobjs[1].reg]);
+				if(preferredreg!=tmp)
+					emit(f,"\tmr\t%s\n",regnames[preferredreg]);
+				settempobj(f,tmp,o,0,0);
+				settempobj(f,preferredreg,o,0,varadr);
+			}
+			else
+			{
+				emit(f,"\tadd\t%s\n",regnames[tempobjs[1].reg]);
+				settempkonst(f,tmp,offset);
+				settempobj(f,tempobjs[1].reg,o,0,varadr);
+			}
+			return(preferredreg);
+		}
+		return(0);
+	}
+	else
+		return(0);
+}
+
+
+int matchtempkonst(FILE *f,int k,int preferredreg)
+{
+//	return(0); // Temporarily disable matching
+	struct obj o;
+	o.flags=KONST;
+	o.val.vlong=k;
+	return(matchtempobj(f,&o,0,preferredreg));
+}
+
+
+/*  Generates code to store register r into memory object o. */
+
+static void store_reg(FILE * f, int r, struct obj *o, int type)
+{
+	// Need to take different types into account here.
+	if(DBGMSG)
+		emit(f, "\t\t\t\t\t\t// Store_reg to type 0x%x, flags 0x%x\n", type,o->flags);
+
+	type &= NQ;		// Filter out unsigned, etc.
+	if((type==CHAR || type==SHORT) && isstackparam(o))
+	{
+		emit(f, "\t\t\t\t\t\t// Promoting storage size of stack parameter to int\n");
+		type=INT;
+	}
+
+	switch (type) {
+	case CHAR:
+		emit_prepobj(f, o, type & NQ, tmp, 0);
+		emit(f, "\texg\t%s\n", regnames[r]);
+		emit(f, "\tstbinc\t%s\t//WARNING - pointer / reg not restored, might cause trouble!\n", regnames[r]);
+		cleartempobj(f,tmp);
+		cleartempobj(f,r);
+		break;
+	case SHORT:
+		emit_prepobj(f, o, type & NQ, tmp, 0);
+		emit(f, "\texg\t%s\n", regnames[r]);
+		emit(f, "\thlf\n\tst\t%s\n", regnames[r]);
+		cleartempobj(f,tmp);
+		cleartempobj(f,r);
+		break;
+	case INT:
+	case LONG:
+	case POINTER:
+		// if o is a reg, can store directly.
+		if ((o->flags & (REG | DREFOBJ)) == (REG | DREFOBJ)) {
+			emit(f, "\tmt\t%s\n", regnames[r]);
+			emit(f, "\tst\t%s\n", regnames[o->reg]);
+//			settempobj(f,r,o,0,0);
+			if((type&NQ)!=INT || (type & VOLATILE) || (type & PVOLATILE))
+			{
+				emit(f,"\t// Volatile, or not int - not caching\n");
+				cleartempobj(f,r);
+			}
+			else
+				settempobj(f,r,o,0,0); // FIXME - is this correct?
+			settempobj(f,tmp,o,0,0); // FIXME - is this correct?
+		} else {
+			if(o->flags & DREFOBJ) {  // Can't use the offset / stmpdec trick for dereferenced objects.
+				// FIXME, not strictly true - could use it for dereferenced constants
+				emit_prepobj(f, o, type & NQ, tmp, 0);
+				emit(f, "\texg\t%s\n", regnames[r]);
+				emit(f, "\tst\t%s\n", regnames[r]);
+				if(r==t1 || (o->am && o->am->disposable))
+					emit(f, "\t\t\t\t\t\t// WARNING - Object is disposable, not bothering to undo exg - check correctness\n");
+				else
+					emit(f, "\texg\t%s\n", regnames[r]);
+				cleartempobj(f,tmp);
+				cleartempobj(f,r);
+			}
+			else {
+				emit_prepobj(f, o, type & NQ, tmp, 4);	// stmpdec predecrements, so need to add 4!
+				emit(f, "\tstmpdec\t%s\n \t\t\t\t\t\t// WARNING - check that 4 has been added.\n", regnames[r]);
+				adjtempobj(f,tmp,-4);
+//				cleartempobj(f,tmp);
+				if((type&NQ)!=INT || (type & VOLATILE) || (type & PVOLATILE))
+				{
+					emit(f,"\t// Volatile, or not int - not caching\n");
+					cleartempobj(f,r);
+				}
+				else
+					settempobj(f,r,o,0,0); // FIXME - is this correct?
+			}
+		}
+		break;
+	case LLONG:
+		if ((o->flags & (REG | DREFOBJ)) == (REG | DREFOBJ)) {
+			emit_prepobj(f, o, type & NQ, tmp, 0);
+			printf("store_reg: storing long long to dereferenced register\n");
+			emit(f,"//FIXME - need to store 64-bits\n");
+			ierror(0);
+		}
+		else {
+			// 
+			printf("store_reg: storing long long in %s to reg\n",regnames[r]);
+			ierror(0);
+		}
+		break;		
+	default:
+		printf("store_reg: unhandled type 0x%x\n", type);
+		ierror(0);
+		break;
+	}
+}
+
+
+/*  Yields log2(x)+1 or 0. */
+static long pof2(zumax x)
+{
+	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 int availreg()
+{
+	int i;
+	for(i=FIRST_GPR+RESERVED_GPRS;i<(LAST_GPR-1);++i)
+		if(regs[i]==0)
+			return(i);
+	return(0);
+}
+
+
+static struct IC *preload(FILE *, struct IC *,int stacksubst);
+
+static void function_top(FILE *, struct Var *, long);
+static int function_bottom(FILE * f, struct Var *, long,int);
+
+#define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
+#define involvesreg(x) ((p->x.flags&(REG))==REG)
+#define isconst(x) ((p->x.flags&(KONST|DREFOBJ))==KONST)
+
+static int q1reg, q2reg, zreg;
+
+static char *ccs[] = { "EQ", "NEQ", "SLT", "GE", "LE", "SGT", "EX", "" };
+static char *logicals[] = { "or", "xor", "and" };
+
+static char *arithmetics[] = { "shl", "shr", "add", "sub", "mul", "(div)", "(mod)" };
+
+/* Does some pre-processing like fetching operands from memory to
+   registers etc. */
+static struct IC *preload(FILE * f, struct IC *p,int stacksubst)
+{
+	int r;
+
+	if(stacksubst)
+	{
+		if(istopstackslot(&p->q1))
+		{
+			p->q1.reg=sp;
+			p->q1.flags|=REG|DREFOBJ;
+		}
+
+		if(istopstackslot(&p->q2))
+		{
+			p->q2.reg=sp;
+			p->q2.flags|=REG|DREFOBJ;
+		}
+
+		if(istopstackslot(&p->z))
+		{
+			p->z.reg=sp;
+			p->z.flags|=REG|DREFOBJ;
+		}
+	}
+
+	if (involvesreg(q1))
+		q1reg = p->q1.reg;
+	else
+		q1reg = 0;
+
+	if (involvesreg(q2))
+		q2reg = p->q2.reg;
+	else
+		q2reg = 0;
+
+	if (isreg(z)) {
+		zreg = p->z.reg;
+	} else {
+		if (ISFLOAT(ztyp(p)))
+			zreg = f1;
+		else
+			zreg = t1;
+	}
+
+	return p;
+}
+
+/* Determine whether the register we're about to write to will merely be passed to SetReturn.
+   If so, return 1, and convert the SetReturn IC to NOP */
+int next_setreturn(struct IC *p,int reg)
+{
+	int result=0;
+	struct IC *p2=p->next;
+	while(p2 && p2->code==FREEREG)
+		p2=p2->next;
+	if(p2 && p2->code==SETRETURN && (p2->q1.flags&(REG|DREFOBJ))==REG && p2->q1.reg==reg)
+	{
+		p2->code=NOP;
+		result=1;
+	}
+	return(result);
+}
+
+
+int consecutiveaccess(struct IC *p,struct IC *p2)
+{
+	if(!p || !p2)
+		return(0);
+//	printf("Flags %x, %x\n",p->z.flags,p2->z.flags);
+	if(((p->z.flags&(VAR|DREFOBJ))==VAR) && ((p2->z.flags&(VAR|DREFOBJ))==VAR))
+	{
+		int result=real_offset(&p2->z)-real_offset(&p->z);
+//		printf("Got two vars\n");
+		if(strcmp(p->z.v->identifier,p2->z.v->identifier))
+			return(0);
+		if(isstatic(p->z.v->storage_class) && isstatic(p->z.v->storage_class))
+		{
+//			printf("Both static - dif %d\n",result);
+			return(result);
+		}
+		if(isextern(p->z.v->storage_class) && isextern(p->z.v->storage_class))
+		{
+//			printf("Both extern - dif %d\n",result);
+			return(result);
+		}
+	}
+	return(0);
+}
+
+/* save the result (in temp) into p->z */
+/* Guaranteed not to touch t1/t2 unless nominated */
+/* or followed by a SetReturn IC. */
+void save_temp(FILE * f, struct IC *p, int treg)
+{
+	int type = ztyp(p) & NQ;
+	if(DBGMSG)
+		emit(f, "\t\t\t\t\t\t// (save temp)");
+
+	if (isreg(z)) {
+		int target=p->z.reg;
+		if(DBGMSG)
+			emit(f, "isreg\n");
+		if(next_setreturn(p,target))
+			target=t1;
+		emit(f, "\tmr\t%s\n", regnames[target]);
+	} else {
+		if ((p->z.flags & DREFOBJ) && (p->z.flags & REG))
+			treg = p->z.reg;
+		else if(isstackparam(&p->z) && !(p->z.flags & DREFOBJ))
+			type=INT;
+
+		if(DBGMSG)
+			emit(f, "store type %x\n",type);
+
+		switch (type) {
+		case CHAR:
+			if (p->z.am && p->z.am->type == AM_POSTINC)
+			{
+				emit(f, "\tstbinc\t%s\n", regnames[treg]);
+				adjtempobj(f,treg,1);
+			}
+			else if ((p->z.am && p->z.am->disposable)
+				 || (treg == t1))
+			{
+				emit(f, "\tstbinc\t%s\n\t\t\t\t\t\t//Disposable, postinc doesn't matter.\n", regnames[treg]);
+				adjtempobj(f,treg,1);
+			}
+			else
+				emit(f, "\tbyt\n\tst\t%s\n", regnames[treg]);
+			break;
+		case SHORT:
+			emit(f, "\thlf\n\tst\t%s\n", regnames[treg]);
+			break;
+		case INT:
+		case LONG:
+		case POINTER:
+//			// Would need to adjust the pointer at the setup stage since we're predecrementing
+//			if (consecutiveaccess(p,p->next)==-4 || (p->z.am && p->z.am->type == AM_PREDEC))
+//			{
+//				emit(f, "\tstdec\t%s\n", regnames[treg]);
+//				adjtempobj(f,treg,-4);
+//			}
+			if (consecutiveaccess(p,p->next)==4 || (p->z.am && p->z.am->type == AM_POSTINC))
+			{
+				emit(f, "\tstinc\t%s\n", regnames[treg]);
+				adjtempobj(f,treg,4);
+			}
+			else
+				emit(f, "\tst\t%s\n", regnames[treg]);
+			break;
+		default:
+			printf("save_temp - type %d not yet handled\n", ztyp(p));
+			emit(f,"\t\t\t\t\t\t// FIXME - save_temp doesn't support size\n");
+			break;
+		}
+	}
+	if(DBGMSG)
+		emit(f, "\t\t\t\t\t\t//save_temp done\n");
+}
+
+/* save the result (in zreg) into p->z */
+void save_result(FILE * f, struct IC *p)
+{
+	if(DBGMSG)
+		emit(f, "\t\t\t\t\t\t// (save result) ");
+	if (isreg(z)) {
+		if(DBGMSG)
+			emit(f, "// isreg\n");
+		if (p->z.reg != zreg)
+		{
+			emit(f, "\tmt\t%s\n\tmr\t%s\n", regnames[zreg], regnames[p->z.reg]);
+			settempobj(f,tmp,&p->z,0,0);
+			settempobj(f,p->z.reg,&p->z,0,0);
+		}
+	}
+	else
+	{
+		emit(f, "// not reg\n");
+		store_reg(f,zreg,&p->z,ztyp(p));
+	}
+	return;
+}
+
+#include "addressingmodes.c"
+#include "tempregs.c"
+#include "inlinememcpy.c"
+#include "libcalls.c"
+
+/* generates the function entry code */
+static void function_top(FILE * f, struct Var *v, long offset)
+{
+	int i;
+	int regcount = 0;
+
+	cleartempobj(f,tmp);
+	cleartempobj(f,t1);
+
+	if(DBGMSG)
+	{
+		emit(f, "\t//registers used:\n");
+		for (i = FIRST_GPR+RESERVED_GPRS; i <= LAST_GPR; ++i) {
+			emit(f, "\t\t//%s: %s\n", regnames[i], regused[i] ? "yes" : "no");
+			if (regused[i] && (i >= (FIRST_GPR+SCRATCH_GPRS+RESERVED_GPRS)) && (i <= LAST_GPR - 2))
+				++regcount;
+		}
+	}
+
+// Emit ctor / dtor tables
+	ctor_dtor(f, v);
+
+	rsavesize = 0;
+	if (!special_section(f, v)) {
+		emit(f, "\t.section\t.text.%x\n", sectionid);
+		section=CODE;
+		++sectionid;
+	}
+	if (v->storage_class == EXTERN) {
+		if ((v->flags & (INLINEFUNC | INLINEEXT)) != INLINEFUNC) {
+			if (isweak(v))
+				emit(f, "\t.weak\t%s%s\n", idprefix, v->identifier);
+			else
+				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));
+
+	if (regcount < 3) {
+		emit(f, "\tstdec\t%s\n", regnames[sp]);
+		for (i = FIRST_GPR + SCRATCH_GPRS; i <= LAST_GPR - 3; ++i) {
+			if (regused[i] && !regscratch[i]) {
+				emit(f, "\tmt\t%s\n\tstdec\t%s\n", regnames[i], regnames[sp]);
+				rsavesize += 4;
+			}
+		}
+	} else {
+		emit(f, "\texg\t%s\n\tstmpdec\t%s\n", regnames[sp], regnames[sp]);
+		for (i = FIRST_GPR + SCRATCH_GPRS; i <= LAST_GPR - 3; ++i) {
+			if (regused[i] && !regscratch[i]) {
+				emit(f, "\tstmpdec\t%s\n", regnames[i]);
+				rsavesize += 4;
+			}
+		}
+		emit(f, "\texg\t%s\n", regnames[sp]);
+	}
+
+	// FIXME - Allow the stack to float, in the hope that we can use stdec to adjust it.
+
+	if ((offset == 4) && optsize)
+		emit(f, "\tstdec\tr6\t// shortest way to decrement sp by 4\n");
+	else if (offset) {
+		emit_constanttotemp(f, -offset);
+		emit(f, "\tadd\t%s\n", regnames[sp]);
+	}
+}
+
+/* generates the function exit code */
+/* Returns 1 if tail code was generated. */
+static int function_bottom(FILE * f, struct Var *v, long offset,int firsttail)
+{
+	int i;
+	int tail=0;
+
+	int regcount = 0;
+	for (i = FIRST_GPR + SCRATCH_GPRS + RESERVED_GPRS; i <= LAST_GPR - 3; ++i) {
+		if (regused[i] && !regscratch[i])
+			++regcount;
+	}
+
+	if ((offset == 4) && optsize)
+		emit(f, "\tldinc\t%s\t// shortest way to add 4 to sp\n", regnames[sp]);
+	else if (offset) {
+		emit_constanttotemp(f, -offset);	// Negative range extends one integer further than positive range.
+		emit(f, "\tsub\t%s\n", regnames[sp]);
+	}
+
+	if(optsize) // If we're optimising for size we can potentially save some bytes in the function tails.
+	{
+		if(regcount)
+		{
+			/* We have to restore some registers.  Jump into the tail code at the appropriate place. */
+			if(regcount<(5-SCRATCH_GPRS) || !firsttail)
+			{
+				emit(f,"\t.lipcrel\t.functiontail, %d\n",((5-SCRATCH_GPRS)-regcount)*2);
+				emit(f,"\tadd\t%s\n\n",regnames[pc]);
+			}
+			if(firsttail)
+			{
+				/* This is the first time we've needed to restore registers - generate tail code */
+				emit(f,".functiontail:\n");
+				for (i = LAST_GPR - 3; i >= FIRST_GPR + SCRATCH_GPRS; --i) {
+					if (!regscratch[i])
+						emit(f, "\tldinc\t%s\n\tmr\t%s\n\n", regnames[sp], regnames[i]);
+				}
+				emit(f, "\tldinc\t%s\n\tmr\t%s\n\n", regnames[sp], regnames[pc]);
+				if(f)
+					tail=1; /* Higher optimisation levels do a dummy run with null file */
+			}
+		}
+		else
+		{
+			/* Didn't need to preserve any registers, just restore PC */
+			emit(f, "\tldinc\t%s\n\tmr\t%s\n\n", regnames[sp], regnames[pc]);
+		}
+	}
+	else
+	{
+		for (i = LAST_GPR - 3; i >= FIRST_GPR + SCRATCH_GPRS; --i) {
+			if (regused[i] && !regscratch[i])
+				emit(f, "\tldinc\t%s\n\tmr\t%s\n\n", regnames[sp], regnames[i]);
+		}
+		emit(f, "\tldinc\t%s\n\tmr\t%s\n\n", regnames[sp], regnames[pc]);
+	}
+	return(tail);
+}
+
+/****************************************/
+/*  End of private data and functions.  */
+/****************************************/
+
+/*  Does necessary initializations for the code-generator. Gets called  */
+/*  once at the beginning and should return 0 in case of problems.      */
+int init_cg(void)
+{
+	int i;
+	/*  Initialize some values which cannot be statically initialized   */
+	/*  because they are stored in the target's arithmetic.             */
+	maxalign = l2zm(4L);
+	char_bit = l2zm(8L);
+	stackalign = l2zm(4);
+
+	flag_832_bigendian=0;
+	if(g_flags[FLAG_BE]&USEDFLAG)
+		flag_832_bigendian=1;
+	else if(!g_flags[FLAG_BE]&USEDFLAG)
+		printf("Neither -eb nor -el specified - defaulting to little-endian\n");
+
+#ifndef V09G
+	clist_copy_stack=0;
+	clist_copy_static=0;
+	clist_copy_pointer=0;
+#endif
+
+	// We have full load-store align, so in size mode we can pack data more tightly...
+
+	for (i = 0; i <= MAX_TYPE; i++) {
+		sizetab[i] = l2zm(msizetab[i]);
+		align[i] = optsize ? 1 : l2zm(malign[i]);
+
+// Can't align everything to 4 bytes for speed without messing up struct packing.  Is there a better way?
+//		align[i] = optspeed ? 4 : (optsize ? 1 : l2zm(malign[i]));
+//		align[i] = l2zm(malign[i]);
+	}
+
+	regnames[0] = "noreg";
+	for (i = FIRST_GPR; i <= LAST_GPR - 1; i++) {
+		regnames[i] = mymalloc(5);
+		sprintf(regnames[i], "r%d", i - FIRST_GPR);
+		regsize[i] = l2zm(4L);
+		regtype[i] = &ltyp;
+		regsa[i] = 0;
+	}
+	regnames[i] = mymalloc(5);
+	sprintf(regnames[i], "tmp");
+	regsize[i] = l2zm(4L);
+	regtype[i] = &ltyp;
+	regsa[i] = 1;
+	for (i = FIRST_FPR; i <= LAST_FPR; i++) {
+		regnames[i] = mymalloc(10);
+		sprintf(regnames[i], "fpr%d", i - FIRST_FPR);
+		regsize[i] = l2zm(8L);
+		regtype[i] = &ldbl;
+	}
+
+	/*  Use multiple ccs.   */
+	multiple_ccs = 0;
+
+	/*  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.          */
+	t_min[CHAR] = l2zm(-128L);
+	t_min[SHORT] = l2zm(-32768L);
+	t_min[INT] = zmsub(l2zm(-2147483647L), l2zm(1L));
+	t_min[LONG] = t_min(INT);
+	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] = ul2zum(2147483647UL);
+	t_max[LONG] = t_max(INT);
+	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] = ul2zum(4294967295UL);
+	tu_max[LONG] = t_max(UNSIGNED | INT);
+	tu_max[LLONG] = zumkompl(ul2zum(0UL));
+	tu_max[MAXINT] = t_max(UNSIGNED | LLONG);
+
+	/*  Reserve a few registers for use by the code-generator.      */
+	/*  This is not optimal but simple.                             */
+	tmp = FIRST_GPR + 8;
+	pc = FIRST_GPR + 7;
+	sp = FIRST_GPR + 6;
+	t1 = FIRST_GPR;		// r0, also return register.
+	t2 = FIRST_GPR + 1;
+//  f1=FIRST_FPR;
+//  f2=FIRST_FPR+1;
+
+	for (i = FIRST_GPR; i <= LAST_GPR; i++)
+		regscratch[i] = 0;
+	for (i = FIRST_FPR; i <= LAST_FPR; i++)
+		regscratch[i] = 0;
+
+	regsa[FIRST_GPR] = 1;	// Allocate the return register
+	regsa[t1] = 1;
+	regsa[t2] = 0;
+	regsa[sp] = 1;
+	regsa[pc] = 1;
+	regsa[tmp] = 1;
+	regscratch[FIRST_GPR] = 0;
+	for(i=FIRST_GPR+RESERVED_GPRS;i<(FIRST_GPR+RESERVED_GPRS+SCRATCH_GPRS);++i)
+		regscratch[i] = 1;
+	regscratch[sp] = 0;
+	regscratch[pc] = 0;
+
+	target_macros = marray;
+
+	return 1;
+}
+
+void init_db(FILE * f)
+{
+}
+
+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.        */
+/*  A pointer MUST be returned in a register. The code-generator    */
+/*  has to simulate a pseudo register if necessary.                 */
+{
+	if (ISFLOAT(t->flags))
+		return 0;
+	if (ISSTRUCT(t->flags) || ISUNION(t->flags))
+		return 0;
+	if (zmleq(szof(t), l2zm(4L)))
+		return FIRST_GPR;
+	else
+		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.                                            */
+{
+	return 0;
+}
+
+/* estimate the cost-saving if object o from IC p is placed in
+   register r */
+int cost_savings(struct IC *p, int r, struct obj *o)
+{
+	int c = p->code;
+	if(o->v && isextern(o->v->storage_class))  // Externs are particularly costly due to the ldinc r7 shuffle
+		return(o->flags & DREFOBJ ? 5 : 3);
+	if (o->flags & VKONST) {
+		if (isextern(o->flags) || isstatic(o->flags))
+			return 2;
+		else {
+			struct obj *o2 = &o->v->cobj;
+			int c = count_constantchunks(o2->val.vmax);
+			return c - 1;
+		}
+	}
+	if (o->flags & DREFOBJ)
+		return 2;
+	if (c == SETRETURN)// && r == p->z.reg && !(o->flags & DREFOBJ))
+		return 1;
+	if (c == GETRETURN)// && r == p->q1.reg && !(o->flags & DREFOBJ))
+		return 1;
+	return 1;
+}
+
+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 (r == 0)
+		return 0;
+	t &= NQ;
+	if (ISFLOAT(t) && r >= FIRST_FPR && r <= LAST_FPR)
+		return 1;
+	if (t == POINTER && r >= FIRST_GPR && r <= LAST_GPR)
+		return 1;
+	if (t >= CHAR && t <= LONG && r >= FIRST_GPR && r <= LAST_GPR)
+		return 1;
+	return 0;
+}
+
+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;
+}
+
+int must_convert(int o, int t, int const_expr)
+/*  Returns zero if code for converting np to type t    */
+/*  can be omitted.                                     */
+/*  On the PowerPC cpu pointers and 32bit               */
+/*  integers have the same representation and can use   */
+/*  the same registers.                                 */
+{
+	int op = o & NQ, tp = t & NQ;
+	if ((op == INT || op == LONG || op == POINTER)
+	    && (tp == INT || tp == LONG || tp == POINTER))
+		return 0;
+	if (op == DOUBLE && tp == LDOUBLE)
+		return 0;
+	if (op == LDOUBLE && tp == DOUBLE)
+		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 && section != SPECIAL)
+		emit(f, "%ld\n", zm2l(size));
+	else
+		emit(f, "\t.space\t%ld\n", zm2l(size));
+	newobj = 0;
+}
+
+
+/*  This function has to make sure the next data is
+    aligned to multiples of <align> bytes.
+    If the speed optimisation flag is set, always align
+    to four bytes. */
+void gen_align(FILE * f, zmax align)
+{
+	if(optspeed)
+		emit(f,"\t.align\t4\n");
+	else if (zm2l(align) > 1)
+		emit(f, "\t.align\t%d\n", align);
+}
+
+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;
+	char *sec;
+	if (v->clist)
+		constflag = is_const(v->vtyp);
+	if (v->storage_class == STATIC) {
+		if (ISFUNC(v->vtyp->flags))
+			return;
+		if (!special_section(f, v)) {
+			if (v->clist && (!constflag)) { // || (g_flags[2] & USEDFLAG))
+//			    && section != DATA) {
+				emit(f, "%s.%x\n",dataname,sectionid);
+				++sectionid;
+				if (f)
+					section = DATA;
+			}
+			if (v->clist && constflag) { // && !(g_flags[2] & USEDFLAG)
+//			    && section != RODATA) {
+				emit(f, "%s.%x\n",rodataname,sectionid);
+				++sectionid;
+				if (f)
+					section = RODATA;
+			}
+			if (!v->clist) { // && section != BSS) {
+				emit(f, "%s.%x\n",bssname,sectionid);
+				++sectionid;
+				if (f)
+					section = BSS;
+			}
+		}
+		if (v->clist || section == SPECIAL) {
+			gen_align(f, falign(v->vtyp));
+			emit(f, "%s%ld:\n", labprefix, zm2l(v->offset));
+		} else {
+			gen_align(f, falign(v->vtyp));
+			emit(f, "\t.lcomm\t%s%ld,", labprefix, zm2l(v->offset));
+		}
+		newobj = 1;
+	}
+	if (v->storage_class == EXTERN) {
+//		emit(f, "\t.global\t%s%s\n", idprefix, v->identifier);
+		if (v->flags & (DEFINED | TENTATIVE)) {
+			if (!special_section(f, v)) {
+				if (v->clist && (!constflag)) { // || (g_flags[2] & USEDFLAG))
+//				    && section != DATA) {
+					emit(f, "%s.%x\n",dataname,sectionid);
+					++sectionid;
+					if (f)
+						section = DATA;
+				}
+				if (v->clist && constflag) { // && !(g_flags[2] & USEDFLAG)
+//				    && section != RODATA) {
+					emit(f, "%s.%x\n",rodataname,sectionid);
+					++sectionid;
+					if (f)
+						section = RODATA;
+				}
+				if (!v->clist) { // && section != BSS) {
+					emit(f, "%s.%x\n",bssname,sectionid);
+					++sectionid;
+					if (f)
+						section = BSS;
+				}
+			}
+			if (v->clist || section == SPECIAL) {
+				gen_align(f, falign(v->vtyp));
+				if (isweak(v))
+					emit(f, "\t.weak\t%s%s\n", idprefix, v->identifier);
+				else
+					emit(f, "\t.global\t%s%s\n", idprefix, v->identifier);
+				emit(f, "%s%s:\n", idprefix, v->identifier);
+			} else {
+				gen_align(f, falign(v->vtyp));
+				if (isweak(v))
+					emit(f, "\t.weak\t%s%s\n", idprefix, v->identifier);
+				else {
+					emit(f, "\t.global\t%s%s\n", idprefix, v->identifier);
+					emit(f, "\t.comm\t%s%s,", 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.                      */
+{
+	if (!p->tree) {
+		switch (t & NQ) {
+		case CHAR:
+			emit(f, "\t.byte\t");
+			break;
+		case SHORT:
+			emit(f, "\t.short\t");
+			break;
+		case LONG:
+		case INT:
+		case MAXINT:
+		case POINTER:
+			emit(f, "\t.int\t");
+			break;
+		case LLONG:
+			emit(f, "//FIXME - unsupported type\n");
+			emit(f, "\t.long\t");
+//			ierror(0);
+			break;
+		default:
+			printf("gen_dc: unsupported type 0x%x\n", t);
+			ierror(0);
+		}
+		emitval(f, &p->val, t & NU);
+		emit(f, "\n");
+
+#if 0
+		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[0], ip[1], ip[2], ip[3]);
+			if ((t & NQ) != FLOAT) {
+				emit(f, ",0x%02x%02x%02x%02x", ip[4], ip[5], ip[6], ip[7]);
+			}
+		} else {
+			emitval(f, &p->val, t & NU);
+		}
+#endif
+	} else {
+		struct obj *o = &p->tree->o;
+		emit(f, "\t\t\t\t\t\t// Declaring from tree\n");
+		if (isextern(o->v->storage_class)) {
+			emit(f, "\t\t\t\t\t\t// extern (offset %d)\n", o->val.vmax);
+			if (o->val.vmax)
+				emit(f, "\t.ref\t_%s, %d\n", o->v->identifier, o->val.vmax);
+			else
+				emit(f, "\t.ref\t_%s\n", o->v->identifier);
+		} else if (isstatic(o->v->storage_class)) {
+			emit(f, "\t\t\t\t\t\t// static\n");
+			if(o->val.vlong)
+				emit(f, "\t.ref\t%s%d,%d\n", labprefix, zm2l(o->v->offset),o->val.vlong);
+			else
+				emit(f, "\t.ref\t%s%d\n", labprefix, zm2l(o->v->offset));
+		} else {
+			printf("error: GenDC (tree) - unknown storage class 0x%x!\n", o->v->storage_class);
+		}
+	}
+	newobj = 0;
+}
+
+
+/* Return 1 if any of p's operands uses predec or postinc addressing mode */
+int check_am(struct IC *p)
+{
+	if(p->q1.am && (p->q1.am->type==AM_POSTINC || p->q1.am->type==AM_PREDEC))
+		return(1);
+	if(p->q2.am && (p->q2.am->type==AM_POSTINC || p->q2.am->type==AM_PREDEC))
+		return(1);
+	if(p->z.am && (p->z.am->type==AM_POSTINC || p->z.am->type==AM_PREDEC))
+		return(1);
+	return(0);
+}
+
+/*  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 *p, struct Var *v, zmax offset)
+/*  The main code-generation.                                           */
+{
+	static int idemp = 0;
+	static int firsttail=1;
+	int reversecmp=0;
+	int c, t, i;
+	struct IC *m;
+	argsize = 0;
+	// if(DEBUG&1) 
+
+	if(!p)
+		printf("(gen_code called with null IC list?)\n");
+
+	for (c = 1; c <= MAXR; c++)
+		regs[c] = regsa[c];
+	pushed = 0;
+	notyetpopped = 0;
+
+#if 0
+	if (!idemp) {
+		sectionid = 0;
+		if (p && p->file) {
+			int v;
+			char *c = p->file;
+			idemp = 1;
+			while (v = *c++) {
+				sectionid <<= 3;
+				sectionid ^= v;
+			}
+			printf("Created section ID %x\n",sectionid);
+		}
+		else
+			printf("No sectionid created (%x, %x)\n",p,p ? p->file : 0);
+	}
+#endif
+
+	for (m = p; m; m = m->next) {
+		c = m->code;
+		t = m->typf & NU;
+		if (c == ALLOCREG) {
+			regs[m->q1.reg] = 1;
+			continue;
+		}
+		if (c == FREEREG) {
+			regs[m->q1.reg] = 0;
+			continue;
+		}
+
+		/* convert MULT/DIV/MOD with powers of two */
+		// Perversely, mul is faster than shifting on 832, so we only want to do this for div.
+		// FIXME - we can do this for signed values too.
+		if ((t & NQ) <= LONG && (m->q2.flags & (KONST | DREFOBJ)) == KONST && (t & NQ) <= LONG
+		    && (((c == DIV || c == MOD) && (t & UNSIGNED)))) {
+			eval_const(&m->q2.val, t);
+			i = pof2(vmax);
+			if (i) {
+				if (c == MOD) {
+					vmax = zmsub(vmax, l2zm(1L));
+					m->code = AND;
+				} else {
+					vmax = l2zm(i - 1);
+					if (c == DIV)
+						m->code = RSHIFT;
+					else
+						m->code = LSHIFT;
+				}
+				c = m->code;
+				gval.vmax = vmax;
+				eval_const(&gval, MAXINT);
+				if (c == AND) {	// FIXME - why?
+					insert_const(&m->q2.val, t);
+				} else {
+					insert_const(&m->q2.val, INT);
+					p->typf2 = INT;
+				}
+			}
+		}
+	}
+
+	for (c = 1; c <= MAXR; c++) {
+		if (regsa[c] || regused[c]) {
+			BSET(regs_modified, c);
+		}
+	}
+	localsize = (zm2l(offset) + 3) / 4 * 4;
+
+//    printf("\nSeeking addressing modes for function %s\n",v->identifier);
+	find_addressingmodes(p);
+
+	function_top(f, v, localsize);
+//    printf("%s:\n",v->identifier);
+
+	for (; p; p = p->next) {
+//		printic(stdout,p);
+		c = p->code;
+		t = q1typ(p);
+
+		if (c == NOP) {
+			p->z.flags = 0;
+			continue;
+		}
+		if (c == ALLOCREG) {
+			if(DBGMSG)
+				emit(f, "\t\t\t\t\t\t// allocreg %s\n", regnames[p->q1.reg]);
+			regs[p->q1.reg] = 1;
+			continue;
+		}
+		if (c == FREEREG) {
+			if(DBGMSG)
+				emit(f, "\t\t\t\t\t\t// freereg %s\n", regnames[p->q1.reg]);
+			regs[p->q1.reg] = 0;
+			continue;
+		}
+		if (c == LABEL) {
+			int i;
+			emit(f, "%s%d: # \n", labprefix, t);
+			cleartempobj(f,tmp);	// Can't carry temporary context past a label
+			cleartempobj(f,t1);
+			continue;
+		}
+
+		if (DBGMSG && p->file)
+			emit(f, "\n\t\t\t\t\t\t//%s, line %d\n", p->file, p->line);
+		if(p->q1.am && p->q1.am->disposable)
+			emit(f, "\t\t\t\t\t\t// Q1 disposable\n");
+		if(p->q2.am && p->q2.am->disposable)
+			emit(f, "\t\t\t\t\t\t// Q2 disposable\n");
+		if(p->z.am && p->z.am->disposable)
+			emit(f, "\t\t\t\t\t\t// Z disposable\n");
+
+		// OK
+		if (c == BRA) {
+			if(0) // FIXME - could duplicate function tail here.  Perhaps do it depending on number of saved registers?
+				function_bottom(f, v, localsize, 0);
+			else
+				emit_pcreltotemp(f, labprefix, t);
+			emit(f, "\tadd\t%s\n", regnames[pc]);
+			continue;
+		}
+		// OK
+		if (c >= BEQ && c < BRA) {
+			if(reversecmp)
+			{
+				switch(c)
+				{
+					case BLT:
+						c=BGT;
+						break;
+					case BLE:
+						c=BGE;
+						break;
+					case BGT:
+						c=BLT;
+						break;
+					case BGE:
+						c=BLE;
+						break;
+				}
+			}
+			emit(f, "\tcond\t%s\n",ccs[c - BEQ]);
+			if(DBGMSG)
+				emit(f, "\t\t\t\t\t\t//conditional branch %s\n",reversecmp ? "reversed" : "regular");
+			reversecmp=0;
+			emit_pcreltotemp(f, labprefix, t);	// FIXME - double-check that we shouldn't include an offset here.
+			emit(f, "\t\tadd\tr7\n");
+			continue;
+		}
+		// Investigate - but not currently seeing it used.
+		if (c == MOVETOREG) {
+			emit(f, "\t\t\t\t\t\t//CHECKME movetoreg\n");
+			emit_objtoreg(f, &p->q1, ztyp(p),zreg);
+			continue;
+		}
+		// Investigate - but not currently seeing it used.
+		if (c == MOVEFROMREG) {
+			emit(f, "\t\t\t\t\t\t//CHECKME movefromreg\n");
+			store_reg(f, p->q1.reg, &p->z, regtype[p->q1.reg]->flags);
+			continue;
+		}
+		// Reject types we can't handle - anything beyond a pointer and chars with more than 1 byte.
+//		if ((c == PUSH)
+//		    && ((t & NQ) > POINTER || ((t & NQ) == CHAR && zm2l(p->q2.val.vmax) != 1))) {
+//			printf("Pushing a type we don't yet handle: 0x%x\n", t);
+//			ierror(0);
+//		}
+
+		if ((c == ASSIGN) && ((t & NQ) > UNION)) {
+			printf("Assignment of a type we don't yet handle: 0x%x\n", t);
+			ierror(0);
+		}
+
+		// Avoid stack top slot trickery if the operation involves pushing operands to the stack
+	    if(c==DIV || c==MOD ||
+			((c==ASSIGN || c==PUSH) && ((t & NQ) > POINTER || ((t & NQ) == CHAR && zm2l(p->q2.val.vmax) != 1))))
+			p = preload(f, p, 0);	// Setup zreg, etc.
+		else
+			p = preload(f, p, 1);	// Setup zreg, etc.
+
+		c = p->code;
+
+		if (c == SUBPFP)
+			c = SUB;
+		if (c == ADDI2P)
+			c = ADD;
+		if (c == SUBIFP)
+			c = SUB;
+
+//		emit(f, "// code 0x%x, q1->v: %x\n", c,&p->q1.v);
+//		if(p->prev && matchobj(f,&p->q1,&p->prev->q1))
+//			emit(f, "// Matching objs found\n", p->prev->code,&p->prev->q1.v);
+
+		if (c == CONVERT) {
+			if(DBGMSG)
+				emit(f, "\t\t\t\t\t\t//FIXME convert\n");
+			if (ISFLOAT(q1typ(p)) || ISFLOAT(ztyp(p))) {
+				printf("Float not yet supported\n");
+				ierror(0);
+			}
+			if (sizetab[q1typ(p) & NQ] < sizetab[ztyp(p) & NQ]) {
+				int shamt = 0;
+				if(DBGMSG)
+					emit(f,"\t\t\t\t\t\t//Converting to wider type...\n");
+				switch (q1typ(p) & NU) {
+					case CHAR | UNSIGNED:
+					case SHORT | UNSIGNED:
+						if(DBGMSG)
+							emit(f,"\t\t\t\t\t\t//But unsigned, so no need to extend\n");
+
+						if(involvesreg(z)) {
+							emit_prepobj(f, &p->z, ztyp(p), zreg, 0);
+							emit_objtoreg(f, &p->q1, q1typ(p), tmp);
+							save_temp(f, p, zreg);
+							// WARNING - might need to invalidate temp objects here...
+						} else {
+							emit_objtoreg(f, &p->q1, q1typ(p), zreg);
+							save_result(f, p);
+							// WARNING - might need to invalidate temp objects here...
+						}
+						break;
+					case CHAR:
+						emit_objtoreg(f, &p->q1, q1typ(p), zreg);
+						emit_constanttotemp(f,0xffffff80);
+						emit(f,"\tadd\t%s\n",regnames[zreg]);
+						emit(f,"\txor\t%s\n",regnames[zreg]);
+						cleartempobj(f,zreg);
+						save_result(f, p);
+						break;
+					case SHORT:
+						emit_objtoreg(f, &p->q1, q1typ(p), zreg);
+						emit_constanttotemp(f,0xffff8000);
+						emit(f,"\tadd\t%s\n",regnames[zreg]);
+						emit(f,"\txor\t%s\n",regnames[zreg]);
+						cleartempobj(f,zreg);
+						save_result(f, p);
+						break;
+				}
+//				settempobj(f,zreg,&p->z,0,0);
+			} else if(sizetab[q1typ(p) & NQ] >= sizetab[ztyp(p) & NQ]) {	// Reducing the size, must mask off excess bits...
+				if(DBGMSG)
+					emit(f,"\t\t\t\t\t\t// (convert - reducing type %x to %x\n",q1typ(p),ztyp(p));
+
+				// If Z is not a register then we're storing a halfword or byte, and thus don't need to mask...
+
+				if(((p->q1.flags&(REG|DREFOBJ))==REG) && (p->z.flags&(REG|DREFOBJ))!=REG) {
+					if(p->z.flags&DREFOBJ) {	// Can't use stmpdec for dereferenced objects
+						emit_prepobj(f, &p->z, t, zreg, 0); // Need an offset
+						emit_objtoreg(f, &p->q1, q1typ(p), tmp);
+						save_temp(f,p,zreg);
+#if 0
+						emit_prepobj(f, &p->z, t, tmp, 0); // Need an offset
+						emit(f, "\texg\t%s\n", regnames[q1reg]);
+//						if(!isstackparam(&p->z) || (p->z.flags&DREFOBJ))
+							emit_sizemod(f,ztyp(p));
+						emit(f, "\tst\t%s\n", regnames[q1reg]);
+						if(p->z.am && p->z.am->disposable && p->q1.am && p->q1.am->disposable)
+							emit(f, "\t\t\t\t\t\t// Both q1 and z are disposable, not bothering to undo exg\n");
+						else
+							emit(f, "\texg\t%s\n", regnames[q1reg]);
+#endif
+					}
+					else {
+						// Use stmpdec if q1 is already in a register...
+						emit_prepobj(f, &p->z, ztyp(p), tmp, 4); // Need an offset
+						if(!isstackparam(&p->z))
+							emit_sizemod(f,ztyp(p));
+						emit(f,"\tstmpdec\t%s\n",regnames[q1reg]);
+					}
+				}
+				else { // Destination is a register - we must mask...
+					// Potential optimisation here - track which ops could have caused a value to require truncation.
+					// Also figure out what's happening next to the value.  If it's only being added, anded, ored, xored
+					// and then truncated by a write to memory we don't need to worry.
+					if(!isreg(q1) || !isreg(z) || q1reg!=zreg) // Do we just need to mask in place, or move the value first?
+					{
+						if(!isreg(z))
+							zreg=t1;
+						emit_prepobj(f, &p->z, ztyp(p), t1, 0);
+
+						emit_objtoreg(f, &p->q1, t,tmp);
+						emit(f,"\t\t\t\t\t\t//Saving to reg %s\n",regnames[zreg]);
+						save_temp(f, p, zreg);
+					}
+//					else
+					if(zreg!=sp && (p->z.flags&(DREFOBJ|REG))==REG)
+					{
+						switch(ztyp(p)&NQ) {
+							case SHORT:
+								emit_constanttotemp(f, 0xffff);
+								emit(f, "\tand\t%s\n", regnames[zreg]);
+								break;
+							case CHAR:
+								emit_constanttotemp(f, 0xff);
+								emit(f, "\tand\t%s\n", regnames[zreg]);
+								break;
+							default:
+								emit(f,"\t\t\t\t\t\t//No need to mask - same size\n");
+								break;
+						}
+					}
+				}
+			}
+			continue;
+		}
+
+		if (c == KOMPLEMENT) {
+			if(DBGMSG)
+				emit(f, "\t\t\t\t\t\t//comp\n");
+			emit_objtoreg(f, &p->q1, q1typ(p), zreg);
+			emit_constanttotemp(f,-1);
+			emit(f, "\txor\t%s\n", regnames[zreg]);
+//			cleartempobj(f,zreg);
+			save_result(f, p);
+			continue;
+		}
+		// May not need to actually load the register here - certainly check before emitting code.
+		if (c == SETRETURN) {
+			if(DBGMSG)
+				emit(f, "\t\t\t\t\t\t//setreturn\n");
+			emit_objtoreg(f, &p->q1, q1typ(p), zreg);
+			BSET(regs_modified, p->z.reg);
+			continue;
+		}
+		// Investigate - May not be needed for register mode?
+		if (c == GETRETURN) {
+			if(DBGMSG)
+				emit(f, "\t\t\t\t\t\t// (getreturn)");
+			if (p->q1.reg) {
+				zreg = p->q1.reg;
+				save_result(f, p);
+			} else {
+				if(DBGMSG)
+					emit(f, " not reg\n");
+				p->z.flags = 0;
+			}
+			continue;
+		}
+		// OK - figure out what the bvunite stuff is all about.
+		if (c == CALL) {
+			int reg;
+			if(DBGMSG)
+				emit(f, "\t\t\t\t\t\t//call\n");
+			if ((p->q1.flags & (VAR | DREFOBJ)) == VAR && p->q1.v->fi && p->q1.v->fi->inline_asm) {
+				emit_inline_asm(f, p->q1.v->fi->inline_asm);
+				cleartempobj(f,t1);
+				cleartempobj(f,tmp);
+				/* FIXME - restore stack from pushed arguments? */
+			} else {
+				/* FIXME - deal with different object types here */
+				if (p->q1.v->storage_class == STATIC) {
+					// FIXME - double-check that we shouldn't include an offset here.
+					emit_pcreltotemp2(f, &p->q1);
+					if (p->q1.flags & DREFOBJ) {
+						emit(f, "\taddt\t%s\t//Deref function pointer\n", regnames[pc]);
+						emit(f, "\tldt\n\texg\t%s\n", regnames[pc]);
+					} else
+						emit(f, "\tadd\t%s\n", regnames[pc]);
+				} else if (p->q1.v->storage_class == EXTERN) {
+					if (p->q1.flags & DREFOBJ) {	// Is this a function pointer?
+						emit_externtotemp(f, p->q1.v->identifier, p->q1.val.vmax);
+						emit(f, "\tldt\t// deref function ptr\n");
+						emit(f, "\texg\t%s\n", regnames[pc]);
+					}
+					else {
+						emit_pcreltotemp2(f, &p->q1);
+						emit(f, "\tadd\t%s\n", regnames[pc]);
+					}
+				} else {
+					emit_objtoreg(f, &p->q1, t, tmp);
+					emit(f, "\texg\t%s\n", regnames[pc]);
+				}
+
+				cleartempobj(f,tmp);
+
+				/* If we have an addressingmode, see if we're able to defer stack popping. */
+				if(p->z.am)
+				{
+					switch(p->z.am->deferredpop)
+					{
+						/* If we couldn't defer popping due to flow control changes, we need to pop any previously
+						   deferred stack entries at this point.*/
+						case DEFERREDPOP_FLOWCONTROL:
+							emit(f,"\t\t\t\t\t\t// Flow control - popping %d + %d bytes\n",pushedargsize(p),notyetpopped);
+							if(pushedargsize(p)+notyetpopped)
+							{
+								emit_constanttotemp(f, pushedargsize(p)+notyetpopped);				
+								emit(f, "\tadd\t%s\n", regnames[sp]);
+							}
+							pushed -= pushedargsize(p);
+							notyetpopped=0;
+							break;
+
+						/* If we couldn't defer popping due to nested calls then we only pop this function's stack entries. */
+						case DEFERREDPOP_NESTEDCALLS:
+							emit(f,"\t\t\t\t\t\t// Nested call - popping %d bytes\n",pushedargsize(p));
+							if(pushedargsize(p))
+							{
+								emit_constanttotemp(f, pushedargsize(p));
+								emit(f, "\tadd\t%s\n", regnames[sp]);
+							}
+							pushed -= pushedargsize(p);
+							break;
+
+						/*	Otherwise, we're OK to defer popping until later. */
+						case DEFERREDPOP_OK:
+							notyetpopped+=pushedargsize(p);
+							pushed -= pushedargsize(p);
+							emit(f,"\t\t\t\t\t\t// Deferred popping of %d bytes (%d in total)\n",pushedargsize(p),notyetpopped);
+							break;
+					}
+				}
+				else if(pushedargsize(p))
+				{
+					emit_constanttotemp(f, pushedargsize(p));
+					pushed -= pushedargsize(p);
+					emit(f, "\tadd\t%s\n", regnames[sp]);
+				}
+//				cleartempobj(f,tmp);
+				cleartempobj(f,t1);
+			}
+			 /*FIXME*/
+			if ((p->q1.flags & (VAR | DREFOBJ)) == VAR && p->q1.v->fi
+				       && (p->q1.v->fi->flags & ALL_REGS)) {
+				bvunite(regs_modified, p->q1.v->fi->regs_modified, RSIZE);
+			} else {
+				int i;
+				for (i = 1; i <= MAXR; i++) {
+					if (regscratch[i])
+						BSET(regs_modified, i);
+				}
+			}
+			continue;
+		}
+
+		if ((c == ASSIGN || c == PUSH) && t == 0) {
+			printf("Bad type for assign / push\n");
+			ierror(0);
+		}
+		// Basically OK.
+		if (c == PUSH) {
+			int matchreg;
+			if(DBGMSG)
+				emit(f, "\t\t\t\t\t\t// (a/p push)\n");
+
+			/* Handle composite types */
+		    if((t & NQ) > POINTER || ((t & NQ) == CHAR && zm2l(p->q2.val.vmax) != 1)) {
+//				if(DBGMSG)
+					emit(f,"\t\t\t\t\t\t// Pushing composite type - size %d, pushed size %d\n",opsize(p),pushsize(p));
+				emit_inlinepush(f,p,t);
+				pushed += pushsize(p);
+			}
+			else
+			{
+				/* need to take dt into account */
+				if(DBGMSG)
+					emit(f, "\t\t\t\t\t\t// a: pushed %ld, regnames[sp] %s\n", pushed, regnames[sp]);
+				switch(t&NQ)
+				{
+					case INT:
+					case LONG:
+					case POINTER:
+						emit_objtoreg(f, &p->q1, t, tmp);
+						emit(f, "\tstdec\t%s\n", regnames[sp]);
+						break;
+					default:
+						printf("Pushing unhandled type 0x%x to the stack\n",t);
+						ierror(0);
+						break;
+				}
+				pushed += pushsize(p);
+			}
+			continue;
+		}
+
+		if (c == ASSIGN) {
+			if(DBGMSG)
+				emit(f, "\t\t\t\t\t\t// (a/p assign)\n");
+			if (((t & NQ) == STRUCT) || ((t & NQ) == UNION) || ((t & NQ) == ARRAY)
+			    || ((t & NQ) == CHAR && opsize(p) != 1)) {
+				emit_inlinememcpy(f,p,t);
+			} else {
+				// Is the small speedup here worth the complexity?  (Yes, because it improves code density)
+				// Use stmpdec if q1 is already in a register and we're not using addressing modes...
+				if(!check_am(p) && ((p->q1.flags&(REG|DREFOBJ))==REG) && !(p->z.flags&REG))
+				{
+					if(p->z.flags&DREFOBJ)	// Can't use stmpdec for dereferenced objects
+					{
+						emit_prepobj(f, &p->z, t, tmp, 0);
+						emit(f, "\texg\t%s\n", regnames[q1reg]);
+						emit_sizemod(f,t);
+						emit(f, "\tst\t%s\n", regnames[q1reg]);
+						if(p->z.am && p->z.am->disposable)
+						{
+							cleartempobj(f,tmp);
+							emit(f, "\t\t\t\t\t\t// Object is disposable, not bothering to undo exg\n");
+						}
+						else
+							emit(f, "\texg\t%s\n", regnames[q1reg]);
+					}
+					else
+					{
+						emit_prepobj(f, &p->z, t, tmp, 4); // Need an offset
+						if(!isstackparam(&p->z))
+							emit_sizemod(f,t);
+						emit(f,"\tstmpdec\t%s\n",regnames[q1reg]);
+						cleartempobj(f,tmp);
+					}
+				}
+				else
+				{
+					emit_prepobj(f, &p->z, t, t1, 0);
+					emit_objtoreg(f, &p->q1, t, tmp);
+					save_temp(f, p, t1);
+				}
+			}
+			continue;
+		}
+		// Seems to work.
+		if (c == ADDRESS) {
+			if(DBGMSG)
+				emit(f, "\t\t\t\t\t\t// (address)\n");
+			if(involvesreg(z))
+			{
+				emit_prepobj(f, &p->q1, POINTER, tmp, 0);
+				save_temp(f,p,zreg);
+			}
+			else
+			{
+				emit_prepobj(f, &p->q1, POINTER, zreg, 0);
+				save_result(f, p);
+			}
+			continue;
+		}
+		// OK
+		if (c == MINUS) {
+			if(DBGMSG)
+				emit(f, "\t\t\t\t\t\t// (minus)\n");
+			emit_objtoreg(f, &p->q1, q1typ(p), zreg);
+			emit_constanttotemp(f,0);
+			emit(f, "\texg %s\n\tsub %s\n", regnames[zreg], regnames[zreg]);
+			settempobj(f,tmp,&p->q1,0,0); // Temp contains un-negated value
+			// cleartempobj(f,tmp);
+			save_result(f, p);
+			continue;
+		}
+		// Compare - #
+		// Revisit
+		if (c == TEST) {
+			if(DBGMSG)
+				emit(f, "\t\t\t\t\t\t// (test)\n");
+			if(!emit_objtoreg(f, &p->q1, t, tmp)) /* emit_objtoreg might already have set the Z flag */
+			{
+				emit(f,"\t\t\t\t// flags %x\n",p->q1.flags);
+				if ((p->q1.flags & (REG|DREFOBJ)) == REG)	// Can avoid mr if the value came from a register
+						emit(f, "\tand\t%s\n", regnames[p->q1.reg]);
+				else
+				{
+						emit(f, "\tmr\t%s\n\tand\t%s\n", regnames[t1], regnames[t1]);
+						settempobj(f,t1,&p->q1,0,0);
+				}
+//				cleartempobj(f,tmp);
+//				cleartempobj(f,t1);
+			}
+			continue;
+		}
+		// Compare
+		// Revisit
+		if (c == COMPARE) {
+			if(DBGMSG)
+			{
+					emit(f, "\t\t\t\t\t\t// (compare)");
+				if (q1typ(p) & UNSIGNED)
+					emit(f, " (q1 unsigned)");
+				else
+					emit(f, " (q1 signed)");
+				if (q2typ(p) & UNSIGNED)
+					emit(f, " (q2 unsigned)");
+				else
+					emit(f, " (q2 signed)");
+				emit(f,"\n");
+			}
+
+			// If q2 is a register but q1 isn't we could reverse the comparison, but would then have to reverse
+			// the subsequent conditional branch.
+			// FIXME - can also reverse if one value is cached
+
+			if (!isreg(q1)) {
+				if(isreg(q2)) {	// Reverse the test.
+					emit_objtoreg(f, &p->q1, t,tmp);
+					q1reg=q2reg;
+					reversecmp=1;
+				} else { // Neither object is in a register, so load q1 into t1 and q2 into tmp.
+					emit_objtoreg(f, &p->q1, t,t1);
+					cleartempobj(f,t1);
+					q1reg = t1;
+					emit_objtoreg(f, &p->q2, t,tmp);
+				}
+			}
+			else
+				emit_objtoreg(f, &p->q2, t,tmp);
+			if ((!(q1typ(p) & UNSIGNED)) && (!(q2typ(p) & UNSIGNED))) {	// If we have a mismatch of signedness we treat as unsigned.
+				int nextop=p->next->code;	// Does the sign matter for the branch being done?
+				if(nextop==FREEREG)
+					nextop=p->next->next->code;
+				if((nextop!=BEQ) && (nextop!=BNE))
+					emit(f, "\tsgn\n");	// Signed comparison
+			}
+			emit(f, "\tcmp\t%s\n", regnames[q1reg]);
+			continue;
+		}
+
+		// Division and modulo
+		if ((c == MOD) || (c == DIV)) {
+			int targetreg=zreg;
+			int doneq2=0;
+			// FIXME - do we need to use switch_IC here?
+			if(DBGMSG)
+				emit(f, "\t\t\t\t\t\t//Call division routine\n");
+
+			// determine here whether R1 and R2 really need saving - may not be in use, or may be the target register.
+			if(regs[t2] && zreg!=t2)
+			{
+				emit(f, "\tmt\t%s\n\tstdec\t%s\n", regnames[t2], regnames[sp]);
+				cleartempobj(f,tmp);
+				pushed+=4;
+			}
+			if(regs[t2+1] && zreg!=(t2+1))
+			{
+				emit(f, "\tmt\t%s\n\tstdec\t%s\n", regnames[t2 + 1], regnames[sp]);
+				cleartempobj(f,tmp);
+				pushed += 4;
+			}
+			// q1 must be written to t2, q2 must be written to t2+2
+			// if q2 starts in t2 we have to avoid overwriting it.
+
+			// If q1 is already in t2, q2 can't be, so we don't need to worry about swapping
+			if(!isreg(q1) || q1reg!=t2)
+			{
+				emit_objtoreg(f, &p->q1, t,tmp);
+
+				// Need to make sure we're not about to overwrite the other operand!
+				if(isreg(q2) && q2reg==t2)
+				{
+					emit(f,"\texg\t%s\n",regnames[t2]);
+					emit(f,"\tmr\t%s\n",regnames[t2+1]);
+					doneq2=1;
+				}
+				else
+					emit(f, "\tmr\t%s\n", regnames[t2]);
+			}
+			if(!doneq2 && (!isreg(q2) || q2reg!=t2+1))
+			{
+				emit_objtoreg(f, &p->q2, t,tmp);
+				emit(f, "\tmr\t%s\n", regnames[t2 + 1]);
+			}
+			cleartempobj(f,t1);
+			cleartempobj(f,t2);
+
+			if ((!(q1typ(p) & UNSIGNED)) && (!(q2typ(p) & UNSIGNED)))	// If we have a mismatch of signedness we treat as unsigned.
+				emit(f, "\t.lipcrel\t_div_s32bys32\n");
+			else
+				emit(f, "\t.lipcrel\t_div_u32byu32\n");
+			emit(f, "\tadd\t%s\n", regnames[pc]);
+
+			// If the next IC is SetReturn from the same register we can skip saving the result.
+			if(next_setreturn(p,zreg))
+			{
+				emit(f,"\t\t\t\t\t\t// Skipping save_result...\n");
+				targetreg=t1;
+			}
+
+			if (c == MOD)
+			{
+				if(targetreg!=t2)
+					emit(f, "\tmt\t%s\n\tmr\t%s\n", regnames[t2], regnames[zreg]);
+			}
+			else
+			{
+				if(targetreg!=t1)
+					emit(f, "\tmt\t%s\n\tmr\t%s\n", regnames[t1], regnames[zreg]);
+			}
+
+			if(regs[t2+1] && zreg!=(t2+1))
+			{
+				emit(f, "\tldinc\t%s\n\tmr\t%s\n", regnames[sp], regnames[t2+1]);
+				pushed -= 4;
+			}
+			if(regs[t2] && zreg!=t2)
+			{
+				emit(f, "\tldinc\t%s\n\tmr\t%s\n", regnames[sp], regnames[t2]);
+				pushed -= 4;
+			}
+
+			cleartempobj(f,tmp);
+			cleartempobj(f,t1);
+
+			// Target not guaranteed to be a register.
+			save_result(f, p);
+
+			continue;
+		}
+
+		// Remaining arithmetic and bitwise operations
+
+		if ((c >= OR && c <= AND) || (c >= LSHIFT && c <= MULT)) {
+			if(DBGMSG)
+				emit(f, "\t\t\t\t\t\t// (bitwise/arithmetic) ");
+			if(DBGMSG)
+				emit(f, "\t//ops: %d, %d, %d\n", q1reg, q2reg, zreg);
+			if(p->q1.am && p->q1.am->type==AM_ADDT)
+			{
+				if(DBGMSG)
+					emit(f,"\t\t\t\t\t\t//Special case - addt\n");
+				// FIXME - if q2 is already in tmp could reverse this
+				if(p->q2.flags&KONST)
+				{
+					zreg=t1;
+					emit_prepobj(f, &p->z, t, t1, 0);
+
+					emit_objtoreg(f, &p->q2, t,tmp);
+					emit(f,"\taddt\t%s\n",regnames[p->q1.reg]);
+					settempobj(f,tmp,&p->z,0,0);
+					save_temp(f, p, zreg);
+					obsoletetempobj(f,t1,&p->z,0);
+//					emit(f,"\tmr\t%s\n",regnames[p->z.reg]);
+				}
+				else
+				{
+					zreg=t1;
+					emit_prepobj(f, &p->z, t, t1, 0);
+
+					emit_objtoreg(f, &p->q1, t,tmp);
+					emit(f,"\taddt\t%s\n",regnames[p->q2.reg]);
+					settempobj(f,tmp,&p->z,0,0);
+					save_temp(f, p, zreg);
+					obsoletetempobj(f,t1,&p->z,0);
+//					emit(f,"\tmr\t%s\n",regnames[p->z.reg]);
+				}
+				continue;
+			}
+
+			if (involvesreg(q2) && q2reg == zreg) {
+//                      printf("Target register and q2 are the same!  Attempting a switch...\n");
+				if (switch_IC(p)) {
+					preload(f,p,1);	// refresh q1reg, etc after switching the IC
+				} else {
+					emit(f,
+					     "\t\t\t\t\t\t// WARNING - evading q2 and target collision - check code for correctness.\n");
+					zreg = t1;
+				}
+			}
+			if (involvesreg(q1) && q1reg == zreg)
+				emit(f,"\t\t\t\t\t\t// WARNING - q1 and target collision - check code for correctness.\n");
+
+			if (!isreg(q1) || q1reg != zreg) {
+				emit_objtoreg(f, &p->q1, t,zreg);
+//				emit(f, "\tmr\t%s\n", regnames[zreg]);	// FIXME - what happens if zreg and q1/2 are the same?
+			}
+			emit_objtoreg(f, &p->q2, t,tmp);
+			if (c >= OR && c <= AND)
+				emit(f, "\t%s\t%s\n", logicals[c - OR], regnames[zreg]);
+			else {
+				if (c == RSHIFT || c==MULT)	// Modify right shift operations with appropriate signedness...
+				{
+//					printf("q1typ: %x, q2typ: %x, ztyp: %x\n",q1typ(p),q2typ(p),ztyp(p));
+					if (!(t & UNSIGNED))
+					{
+						// Evaluate q1 - if we're dealing with a constant that doesn't have bit 31 set we don't need sgn...
+						if((!(p->typf2 & UNSIGNED) && c==RSHIFT) 
+									|| (p->q1.flags&(KONST|DREFOBJ)!=KONST)
+											|| (val2zmax(&p->q1,p->typf)&0x80000000))
+							emit(f, "\tsgn\n");
+					}
+				}
+				emit(f, "\t%s\t%s\n", arithmetics[c - LSHIFT], regnames[zreg]);
+				if(c==MULT)
+					cleartempobj(f,tmp);
+			}
+			settempobj(f,zreg,&p->z,0,0);
+			cleartempobj(f,zreg);
+			save_result(f, p);
+			continue;
+		}
+		printf("Unhandled IC\n");
+		pric2(stdout, p);
+		ierror(0);
+	}
+	if(function_bottom(f, v, localsize+notyetpopped,firsttail))
+		firsttail=0;
+}
+
+int shortcut(int code, int typ)
+{
+	// Only RSHIFT and AND are safe on 832.
+	// So far have seen shortcut requests for
+	// DIV
+	// ADD
+	// RSHIFT
+	// COMPARE
+	// SUB
+	// LSHIFT
+	// AND
+	// MULT
+	// OR
+
+//	printf("Evaluating shortcut for code %d, type %x\n",code,typ);
+	if(code==RSHIFT)
+		return(1);
+	if(code==AND)
+		return(1);
+
+	return 0;
+}
+
+int reg_parm(struct reg_handle *m, struct Typ *t, int vararg, struct Typ *d)
+{
+	int f;
+	f = t->flags & NQ;
+	if(is_varargs(d))	/* Disallow register parameters for varargs functions */
+		return(0);
+
+	if (f <= LONG || f == POINTER) {
+		if (m->gregs >= REGPARM_COUNT)
+			return 0;
+		else
+			return FIRST_GPR + 1 + m->gregs++;
+	}
+	if (ISFLOAT(f)) {
+		return(0);
+/*		if (m->fregs >= 0)
+			return 0;
+		else
+			return FIRST_FPR + 2 + m->fregs++;
+*/
+	}
+	return 0;
+}
+
+int iscomment(char *str)
+{
+	char c;
+	while(c=*str++)
+	{
+		if(!c || c=='\n' || c=='/')
+			return(1);
+		if(c!=' '&&c!='\t')
+			return(0);
+	}
+	return(1);
+}
+
+
+int emit_peephole(void)
+{
+	int i;
+	int havemr=0;
+	int havemt=0;
+	int havestore=0;
+	int haveload=0;
+	int loadidx=0;
+	i=emit_f;
+
+	while(i!=emit_l)
+	{
+		int reg,reg2;
+	    if(sscanf(emit_buffer[i],"\tmr\tr%d",&reg)==1)
+		{
+			if(havemt && reg==reg2)
+			{
+				strcpy(emit_buffer[i],"\t//mr\n");
+				return(1);
+			}
+			reg2=reg;
+			havemr=1;
+			havemt=0;
+		}
+	    else if(sscanf(emit_buffer[i],"\tmt\tr%d",&reg)==1)
+		{
+			if(havemr && reg==reg2)
+			{
+				strcpy(emit_buffer[i],"\t//mt\n");
+				return(1);
+			}
+			reg2=reg;
+			havemr=0;
+			havemt=1;
+		}
+		else if(sscanf(emit_buffer[i],"\tst\tr%d",&reg)==1)
+		{
+			havemr=havemt=0;
+			havestore=1;
+		}
+		else if(sscanf(emit_buffer[i],"\tld\tr%d",&reg2)==1 && havestore)
+		{
+			havemr=havemt=0;
+			if(reg==reg2 && reg==6) /* Only stack ops - others would be risky due to potential hardware registers. */
+			{
+				loadidx=i;
+				haveload=1;
+//				printf("Found matching load directive, r%d\n",reg);
+//				strcpy(emit_buffer[i],"\t//nop\n");
+//				return(1);
+			}
+		}
+		else if(!iscomment(emit_buffer[i])) /* Check that the next instruction isn't "cond" */
+		{
+			havemr=havemt=0;
+			if(haveload && strncmp(emit_buffer[i],"\tcond",5)) /* If not, we're OK to zero out the load */
+			{
+				strcpy(emit_buffer[loadidx],"\t//nop\n");
+				return(1);
+			}
+			else
+			{
+				havestore=haveload=0;
+			}
+		}
+		i=(i+1)%EMIT_BUF_DEPTH;
+	}
+	return 0;                                                                    
+}
+
+
+int handle_pragma(const char *s)
+{
+	return(0);
+}
+
+void cleanup_cg(FILE * f)
+{
+}
+
+void cleanup_db(FILE * f)
+{
+	if (f)
+		section = -1;
+}
diff --git a/machines/832/machine.dt b/machines/832/machine.dt
new file mode 100644
index 0000000..526c8d4
--- /dev/null
+++ b/machines/832/machine.dt
@@ -0,0 +1,16 @@
+S8BS
+S8BU
+S16BSBE S16BSLE
+S16BUBE S16BULE
+S32BSBE S32BSLE
+S32BUBE S32BULE
+S32BSBE S32BSLE
+S32BUBE S32BULE
+S64BSBE S64BSLE
+S64BUBE S64BULE
+S32BIEEEBE
+S64BIEEEBE
+S64BIEEEBE
+S32BUBE S32BULE
+
+
diff --git a/machines/832/machine.h b/machines/832/machine.h
new file mode 100644
index 0000000..43aba53
--- /dev/null
+++ b/machines/832/machine.h
@@ -0,0 +1,148 @@
+/*  EightThirtyTwo backend for vbcc.
+    Based on the "generic" backend.
+*/
+
+/* build-time configurable options: */
+#define NUM_GPRS 9
+#define SCRATCH_GPRS 2
+#define NUM_FPRS 0
+#define NUM_CCRS 0
+#define FIXED_SP 0
+
+#include "dt.h"
+
+/* Define this if you need to build with 0.9g */
+/* #define V09G */
+
+/* internally used by the backend */
+#define FIRST_GPR 1
+#define LAST_GPR (FIRST_GPR+NUM_GPRS-1)
+#define FIRST_FPR (LAST_GPR+1)
+#define LAST_FPR (FIRST_FPR+NUM_FPRS-1)
+#define RESERVED_GPRS 1
+
+/*  This struct can be used to implement machine-specific           */
+/*  addressing-modes.                                               */
+/*  Currently possible are (const,gpr) and (gpr,gpr)                */
+/*  FIXME - we can make use of ldidx here */
+enum AddressingMode_Type { AM_POSTINC=1, AM_PREDEC, AM_ADDT };
+struct AddressingMode{
+    enum AddressingMode_Type type;
+	int disposable;
+	int deferredpop;
+};
+
+/*  The number of registers of the target machine.                  */
+#define MAXR NUM_GPRS+NUM_FPRS+NUM_CCRS
+
+/*  Number of commandline-options the code-generator accepts.       */
+#define MAXGF 3
+
+/*  If this is set to zero vbcc will not generate ICs where the     */
+/*  target operand is the same as the 2nd source operand.           */
+/*  This can sometimes simplify the code-generator, but usually     */
+/*  the code is better if the code-generator allows it.             */
+#define USEQ2ASZ 1
+
+/*  This specifies the smallest integer type that can be added to a */
+/*  pointer.                                                        */
+#define MINADDI2P INT
+
+/*  If the bytes of an integer are ordered most significant byte    */
+/*  byte first and then decreasing set BIGENDIAN to 1.              */
+
+extern char flag_832_bigendian;
+#define BIGENDIAN (flag_832_bigendian)
+
+/*  If the bytes of an integer are ordered lest significant byte    */
+/*  byte first and then increasing set LITTLEENDIAN to 1.           */
+#define LITTLEENDIAN (!flag_832_bigendian)
+
+/*  Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive.    */
+
+/*  If switch-statements should be generated as a sequence of       */
+/*  SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1.      */
+/*  This can yield better code on some machines.                    */
+#define SWITCHSUBS 1
+
+/*  In optimizing compilation certain library memcpy/strcpy-calls   */
+/*  with length known at compile-time will be inlined using an      */
+/*  ASSIGN-IC if the size is less or equal to INLINEMEMCPY.         */
+/*  The type used for the ASSIGN-IC will be UNSIGNED|CHAR.          */
+#define INLINEMEMCPY 1024
+
+/*  Parameters are sometimes passed in registers without __reg.     */
+#define HAVE_REGPARMS 1
+#define REGPARM_COUNT 1
+
+/*  Parameters on the stack should be pushed in order rather than   */
+/*  in reverse order.                                               */
+// #define ORDERED_PUSH 1
+// FIXED_SP
+
+/*  Structure for reg_parm().                                       */
+struct reg_handle{
+    unsigned long gregs;
+    unsigned long fregs;
+};
+
+/*  We have some target-specific variable attributes.               */
+#define HAVE_TARGET_ATTRIBUTES
+
+/* We have target-specific pragmas */
+#define HAVE_TARGET_PRAGMAS
+
+/*  We keep track of all registers modified by a function.          */
+#define HAVE_REGS_MODIFIED 1
+
+/* We have implemented our own cost-functions to adapt 
+   register-allocation */
+#define HAVE_TARGET_RALLOC 1
+#define cost_move_reg(x,y) 1
+#define cost_load_reg(x,y) 5
+#define cost_save_reg(x,y) 5
+#define cost_pushpop_reg(x) 1
+
+/* size of buffer for asm-output, this can be used to do
+   peephole-optimizations of the generated assembly-output */
+#define EMIT_BUF_LEN 1024 /* should be enough */
+/* number of asm-output lines buffered */
+#define EMIT_BUF_DEPTH 16
+
+/*  We have no asm_peephole to optimize assembly-output */
+#define HAVE_TARGET_PEEPHOLE 1
+
+/* we do not have a mark_eff_ics function, this is used to prevent
+   optimizations on code which can already be implemented by efficient
+   assembly */
+#undef HAVE_TARGET_EFF_IC
+
+/* we only need the standard data types (no bit-types, different pointers
+   etc.) */
+#undef HAVE_EXT_TYPES
+#undef HAVE_TGT_PRINTVAL
+
+/* we do not need extra elements in the IC */
+#undef HAVE_EXT_IC
+
+/* we use unsigned int as size_t (but unsigned long, the default) */
+#define HAVE_INT_SIZET 1
+
+/* we do not need register-pairs */
+#undef HAVE_REGPAIRS
+
+/* We (will eventually) use libcalls for 64-bit and float support */
+/* Enabling this completely changes code generation - investigate. */
+#define HAVE_LIBCALLS 0
+
+/* do not create CONVERT ICs from integers smaller than int to floats */
+#define MIN_INT_TO_FLOAT_TYPE INT
+
+/* do not create CONVERT ICs from floats to ints smaller than int */
+#define MIN_FLOAT_TO_INT_TYPE INT
+
+/* do not create CONVERT_ICs from floats to unsigned integers */
+#define AVOID_FLOAT_TO_UNSIGNED 1
+
+/* do not create CONVERT_ICs from unsigned integers to floats */
+#define AVOID_UNSIGNED_TO_FLOAT 1
diff --git a/machines/832/tempregs.c b/machines/832/tempregs.c
new file mode 100644
index 0000000..c4b177f
--- /dev/null
+++ b/machines/832/tempregs.c
@@ -0,0 +1,624 @@
+/*
+To do: 
+	Peephole optimise away such constructs as mr r0, mt r0
+	| Optimise addresses of stack variables - lea's can mostly be replaced with simple adds.
+	Detect absolute moves to reg, prune any that aren't needed.
+
+	tempreg logic should be correct - now it's up to machine.c to make good use of it.
+*/
+
+zmax val2zmax(struct obj *o, int t)
+{
+	union atyps *p = &o->val;
+	t &= NU;
+	if (t == CHAR)
+		return (zc2zm(p->vchar));
+	if (t == (UNSIGNED | CHAR))
+		return (zuc2zum(p->vuchar));
+	if (t == SHORT)
+		return (zs2zm(p->vshort));
+	if (t == (UNSIGNED | SHORT))
+		return (zus2zum(p->vushort));
+
+	/*
+	   if(t==FLOAT) return(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)
+		return (zi2zm(p->vint));
+	if (t == (UNSIGNED | INT))
+		return (zui2zum(p->vuint));
+	if (t == LONG)
+		return (zl2zm(p->vlong));
+	if (t == (UNSIGNED | LONG))
+		return (zul2zum(p->vulong));
+	if (t == LLONG)
+		return (zll2zm(p->vllong));
+	if (t == (UNSIGNED | LLONG))
+		return (zull2zum(p->vullong));
+	if (t == MAXINT)
+		return (p->vmax);
+	if (t == (UNSIGNED | MAXINT))
+		return (p->vumax);
+	if (t == POINTER)
+		return (zul2zum(p->vulong));
+	printf("#FIXME - no float support yet\n");
+	ierror(0);
+}
+
+static void emit_sizemod(FILE * f, int type)
+{
+	if(DBGMSG)
+		emit(f, "\t\t\t\t\t\t//sizemod based on type 0x%x\n", type);
+	switch (type & NQ) {
+	case 0:
+		if(DBGMSG)
+			emit(f, "\t\t\t\t\t\t//sizemod type is zero (movefromreg?)");
+		break;
+	case CHAR:
+		emit(f, "\tbyt\n");
+		break;
+	case SHORT:
+		emit(f, "\thlf\n");
+		break;
+	case INT:
+	case LONG:
+	case LLONG:
+	case POINTER:
+	case FUNKT:		// Function pointers are dereferenced by calling them.
+	case STRUCT:
+	case UNION:
+	case ARRAY:
+		break;		// Structs and unions have to remain as pointers
+	default:
+		printf("emit_sizemod - type %d not handled\n", type);
+		ierror(0);
+		break;
+	}
+}
+
+
+// WARNING: Must invalidate tmp if control flow doesn't change immediately after this instruction.
+
+static void emit_pcreltotemp(FILE * f, char *lab, int suffix)
+{
+	int i;
+	if(DBGMSG)
+		emit(f, "\t\t\t\t\t\t//pcreltotemp\n");
+	emit(f, "\t.lipcrel\t%s%d\n", lab, suffix);
+//	cleartempobj(f,tmp);
+}
+
+static void emit_pcreltotemp2(FILE *f,struct obj *p)
+{
+	if(DBGMSG)
+		emit(f, "\t\t\t\t\t\t//pcreltotemp\n");
+	if (p->v->storage_class == STATIC)
+		emit(f,"\t.lipcrel\t%s%d\n",labprefix, zm2l(p->v->offset));
+	else if(p->v->storage_class == EXTERN)
+	{
+		if(p->val.vmax)
+			emit(f,"\t.lipcrel\t_%s%d\n",p->v->identifier, p->val.vmax);
+		else
+			emit(f,"\t.lipcrel\t_%s\n",p->v->identifier);
+	}
+//	cleartempobj(f,tmp);
+}
+
+// tempobj logic should be correct.
+
+static void emit_externtotemp(FILE * f, char *lab, int offset)	// FIXME - need to find a way to do this PC-relative.
+{
+#if 0
+	emit(f, "\tldinc\t%s\n", regnames[pc]);
+	if (offset)
+		emit(f, "\t.ref\t_%s, %d\n",lab, offset);
+	else
+		emit(f, "\t.ref\t_%s\n",lab);
+#else
+	if(g_flags[FLAG_PIC]&USEDFLAG)
+	{
+		if (offset)
+			emit(f, "\t.lipcrel\t_%s, %d\n",lab, offset);
+		else
+			emit(f, "\t.lipcrel\t_%s\n",lab);
+		emit(f, "\taddt\t%s\n",regnames[pc]);
+	}
+	else
+	{
+		if (offset)
+			emit(f, "\t.liabs\t_%s, %d\n",lab, offset);
+		else
+			emit(f, "\t.liabs\t_%s\n",lab);
+	}
+#endif
+	cleartempobj(f,tmp);
+}
+
+
+// tempobj logic should be correct.
+
+static void emit_statictotemp(FILE * f, char *lab, int suffix, int offset)	// FIXME - need to find a way to do this PC relative
+{
+	if(DBGMSG)
+		emit(f, "\t\t\t\t\t\t//statictotemp (FIXME - make PC-relative?)\n");
+	if(g_flags[FLAG_PIC]&USEDFLAG)
+	{
+		emit(f, "\t.lipcrel\t%s%d,%d\n", lab, suffix, offset);
+		emit(f, "\taddt\t%s\n",regnames[pc]);
+	}
+	else
+	{
+		emit(f, "\t.liabs\t%s%d,%d\n", lab, suffix, offset);
+	}
+	cleartempobj(f,tmp);
+}
+
+static int count_constantchunks(zmax v)
+{
+	int chunk = 1;
+	int v2 = (int)v;
+	while (((v2 & 0xffffffe0) != 0) && ((v2 & 0xffffffe0) != 0xffffffe0))	// Are we looking at a sign-extended 6-bit value yet?
+	{
+//               printf("%08x\n",v2);
+		v2 >>= 6;
+		++chunk;
+	}
+	return (chunk);
+}
+
+
+// tempobj logic should be correct.
+
+static void emit_constanttoreg(FILE * f, zmax v,int reg)
+{
+	int matchreg=matchtempkonst(f,v,reg);
+//	emit(f,"// matchreg %s\n",regnames[matchreg]);
+
+//	if(matchreg==tmp)
+//		return;
+//	else if(matchreg)
+//		emit(f,"\tmt\t%s\n",regnames[matchreg]);
+	if(matchreg) {
+		// Need to deal with the case where a constant is in r0 but required in tmp or vice versa.
+		if(matchreg!=reg) {
+			if(reg==tmp)
+				emit(f,"\tmt\t%s\n",regnames[matchreg]);
+			else
+				emit(f,"\tmr\t%s\n",regnames[reg]);
+			settempkonst(f,reg,v);
+		}
+	} else {
+		emit(f, "\t.liconst\t%d\n", v);
+		settempkonst(f,tmp,v);
+		if(reg!=tmp)
+		{
+			emit(f,"\tmr\t%s\n",regnames[reg]);
+			settempkonst(f,reg,v);
+		}
+	}
+}
+
+static void emit_constanttotemp(FILE * f, zmax v)
+{
+	emit_constanttoreg(f,v,tmp);
+}
+
+
+// tempobj logic should be correct.
+
+static void emit_stackvartotemp(FILE * f, zmax offset, int deref)
+{
+	if (deref) {
+		if (offset) {
+			emit_constanttotemp(f, offset);
+			emit(f, "\tldidx\t%s\n", regnames[sp]);
+		} else
+			emit(f, "\tld\t%s\n", regnames[sp]);
+	} else {
+		if (offset) {
+			emit_constanttotemp(f, offset);
+			emit(f, "\taddt\t%s\n", regnames[sp]);
+		} else
+			emit(f, "\tmt\t%s\n", regnames[sp]);
+	}
+	cleartempobj(f,tmp);
+}
+
+
+// Load the address of a target obj into reg in preparation for a store.
+// If the target is simply a register then does nothing.
+// The nominated register can be tmp or any gpr.
+// Guaranteed not to modify t1 or t2 except when nominated.
+// tempobj logic should be correct.
+
+static void emit_prepobj(FILE * f, struct obj *p, int t, int reg, int offset)
+{
+	int matchreg=0;
+
+	if(DBGMSG)
+		emit(f, "\t\t\t\t\t\t// (prepobj %s)\n ", regnames[reg]);
+
+	if (p->flags & REG) {
+		if(DBGMSG)
+			emit(f, "\t\t\t\t\t\t// reg %s - no need to prep\n", regnames[p->reg]);
+		if(p->flags & DREFOBJ)
+		{
+			if (reg == tmp)
+			{
+				emit(f, "\tmt\t%s\n", regnames[p->reg]);
+				cleartempobj(f,tmp);
+			}
+		}
+		return;
+	}
+
+	if(!offset)
+		matchreg=matchtempobj(f,p,1,t1);  // FIXME - we're hunting for varadr here.
+
+	if(matchreg)
+	{
+		if(DBGMSG)
+			emit(f,"\n\t\t\t\t\t\t// required value found in %s\n",regnames[matchreg]);
+		if(matchreg==reg)
+			return;
+		else if(matchreg==tmp) {
+			emit(f,"\tmr\t%s\n",regnames[reg]);
+			settempobj(f,reg,p,0,0);
+			return;
+		} else {
+			emit(f,"\tmt\t%s\n",regnames[matchreg]);
+			settempobj(f,tmp,p,0,0);
+			if(reg!=tmp)
+			{
+				emit(f,"\tmr\t%s\n",regnames[reg]);
+				settempobj(f,reg,p,0,0);
+			}
+			return;
+		}
+	}
+
+	if (p->flags & DREFOBJ) {
+		if (p->flags & VARADR)
+			if(DBGMSG)
+				emit(f, "\t\t\t\t\t\t//varadr AND ");
+		if(DBGMSG)
+			emit(f, "\t\t\t\t\t\t// deref\n");
+		/* Dereferencing a pointer */
+		if (p->flags & KONST) {
+			if(DBGMSG)
+				emit(f, "\t\t\t\t\t\t// const to %s\n",regnames[reg]);
+			emit_constanttoreg(f, val2zmax(p, p->dtyp) + offset,reg);
+//			if (reg != tmp)
+//				emit(f, "\tmr\t%s\n", regnames[reg]);
+			settempkonst(f,reg,val2zmax(p, p->dtyp) + offset);
+		} else if (p->flags & REG) {
+			if (reg == tmp)
+			{
+				emit(f, "\tmt\t%s\n", regnames[p->reg]);
+				cleartempobj(f,tmp);
+			}
+			else if(DBGMSG)
+				emit(f, "\t\t\t\t\t\t// reg %s - no need to prep\n", regnames[p->reg]);
+		} else if (p->flags & VAR) {
+			if(DBGMSG)
+				emit(f, "\t\t\t\t\t\t// var FIXME - deref?\n");
+			if(offset)
+			{
+				printf("emit_prepobj: Offset supplied but object is being dereferenced!\n");
+				ierror(0);
+			}
+			if (isauto(p->v->storage_class)) {
+				if(DBGMSG)
+					emit(f, "\t\t\t\t\t\t// reg - auto\n");
+				emit_stackvartotemp(f, real_offset(p) + offset, 1);
+				if (reg != tmp)
+				{
+					emit(f, "\tmr\t%s\n", regnames[reg]);
+					cleartempobj(f,reg);
+				}
+			} else if (isstatic(p->v->storage_class)) {
+				cleartempobj(f,tmp);
+				cleartempobj(f,reg);
+				if(DBGMSG)
+					emit(f, "\t\t\t\t\t\t// static\n");
+				emit(f, "\tldinc\tr7\n\t.ref\t%s%d,%d\n",
+				     labprefix, zm2l(p->v->offset), offset + p->val.vmax);
+				emit(f, "\tldt\n");
+				if (reg != tmp)
+					emit(f, "\tmr\t%s\n", regnames[reg]);
+			} else if (isextern(p->v->storage_class)) {
+				emit(f, "\t\t\t\t\t\t//Extern\n");
+				emit_externtotemp(f, p->v->identifier, p->val.vmax);
+				emit(f, "\tldt\n");
+				if (reg != tmp)
+					emit(f, "\tmr\t%s\n", regnames[reg]);
+			} else {
+				if(DBGMSG)
+					printf("// emit_prepobj (deref): - unknown storage class!\n");
+				ierror(0);
+			}
+//                              if(!zmeqto(l2zm(0L),p->val.vmax)){
+//                                      emit(f," offset ");
+//                                      emit(f," FIXME - deref?\n");
+//                                      emit_constanttotemp(f,val2zmax(f,p,LONG));
+//                                      emit(f,"\tmr\t%s\n",regnames[reg]);
+//                                      emit_pcreltotemp(f,labprefix,zm2l(p->v->offset));
+//                                      emit(f,"\tadd\t%s\n",regnames[reg]);
+//                              }
+		}
+	} else {
+		if (p->flags & REG) {
+			if(DBGMSG)
+				emit(f, "\t\t\t\t\t\t// reg %s - no need to prep\n", regnames[p->reg]);
+		} else if (p->flags & VAR) {
+			if (isauto(p->v->storage_class)) {
+				/* Set a register to point to a stack-base variable. */
+				if(DBGMSG)
+					emit(f, "\t\t\t\t\t\t// var, auto|reg\n");
+				if (p->v->storage_class == REGISTER)
+					if(DBGMSG)
+						emit(f, "\t\t\t\t\t\t// (is actually REGISTER)\n");
+				emit_stackvartotemp(f, real_offset(p) + offset, 0);
+				if (reg != tmp)
+					emit(f, "\tmr\t%s\n\n", regnames[reg]);
+			} else if (isextern(p->v->storage_class)) {
+				if(DBGMSG)
+					emit(f, "\t\t\t\t\t\t// extern (offset %d)\n", p->val.vmax);
+				emit_externtotemp(f, p->v->identifier, p->val.vmax + offset);
+				if(DBGMSG)
+					emit(f, "\t\t\t\t\t\t// extern pe %s varadr\n", p->flags & VARADR ? "is" : "not");
+				if (reg != tmp)
+					emit(f, "\tmr\t%s\n", regnames[reg]);
+			} else if (isstatic(p->v->storage_class)) {
+				if(DBGMSG)
+					emit(f, "\t\t\t\t\t\t// static\n");
+//				emit(f, "\tldinc\tr7\n\t.ref\t%s%d,%d\n",
+//				     labprefix, zm2l(p->v->offset), offset + p->val.vmax);
+				if(g_flags[FLAG_PIC]&USEDFLAG)
+				{
+					emit(f, "\t.lipcrel\t%s%d,%d\n",
+						 labprefix, zm2l(p->v->offset), offset + p->val.vmax);
+					emit(f, "\taddt\t%s\n",regnames[pc]);
+				}
+				else
+					emit(f, "\t.liabs\t%s%d,%d\n",
+						 labprefix, zm2l(p->v->offset), offset + p->val.vmax);
+				if(DBGMSG)
+					emit(f, "\t\t\t\t\t\t// static pe %s varadr\n", p->flags & VARADR ? "is" : "not");
+				if (reg != tmp)
+					emit(f, "\tmr\t%s\n", regnames[reg]);
+			} else {
+				if(DBGMSG)
+					printf("emit_prepobj: - unknown storage class!\n");
+				ierror(0);
+			}
+			settempobj(f,tmp,p,0,1);
+			settempobj(f,reg,p,0,1);
+		}
+	}
+}
+
+
+// Returns 1 if the Z flag has been set (i.e. a load has occurred)
+// Guaranteed not to modify t1 or t2.
+
+static int emit_objtoreg(FILE * f, struct obj *p, int t,int reg)
+{
+	int result=0;
+	int matchreg;
+	int elementary;
+	int postinc=0;
+	if(DBGMSG)
+		emit(f, "\t\t\t\t\t\t// (obj to %s) flags %x type %x\n",regnames[reg],p->flags,t);
+
+	/* If we're dealing with an elementary type on the stack we'll copy the actual object into
+	   a register.  If we're dealing with a composite type, or taking the address of an elementary
+	   type then instead we'll take its address into the register.  There's a subtlety to take care
+	   of with ASSIGN ICs and inline memcpy/strcpy where they type can be CHAR with a size!=1.
+	   I hack around this by overriding type in the parent fucction. */
+	if ((!(p->flags & VARADR)) && ((t & NQ) != STRUCT) && ((t & NQ) != UNION) && ((t & NQ) != ARRAY))
+		elementary=1;
+	else
+		elementary=0;
+
+	matchreg=matchtempobj(f,p,0,reg);
+
+	if ((p->flags & (REG|DREFOBJ)) == REG) {
+		settempobj(f,reg,p,0,0);
+		if(DBGMSG)
+			emit(f, "\t\t\t\t\t\t// reg %s - only match against tmp\n", regnames[p->reg]);
+		if (reg == p->reg)
+			return(0);
+		if(matchreg!=tmp)
+		{
+			emit(f,"\tmt\t%s\n",regnames[p->reg]);
+			settempobj(f,tmp,p,0,0);
+		}
+		if(reg!=tmp)
+		{
+			emit(f, "\tmr\t%s\n", regnames[reg]);
+			settempobj(f,reg,p,0,0);
+		}
+		return(0);
+	}
+
+	if(matchreg)
+	{
+		if(DBGMSG)
+			emit(f,"\n\t\t\t// required value found in %s\n",regnames[matchreg]);
+		if(matchreg==reg)
+			return(0);
+		if(matchreg!=tmp)
+		{
+			emit(f,"\tmt\t%s\n",regnames[matchreg]);
+			settempobj(f,tmp,p,0,0);
+		}
+		if(reg!=tmp)
+		{
+			emit(f,"\tmr\t%s\n",regnames[reg]);
+			settempobj(f,reg,p,0,0);
+		}
+		emit(f,"\t\t\t\t//return 0\n");
+		return(0);
+	}
+
+	// FIXME - does this have implications for structs, unions, fptrs, etc?
+	if(p->flags&VARADR)
+	{
+		emit_prepobj(f,p,t,reg,0);
+		return(0);
+	}
+	if ((p->flags & (KONST | DREFOBJ)) == (KONST | DREFOBJ)) {
+		if(DBGMSG)
+			emit(f, "\t\t\t\t\t\t// const/deref\n");
+		matchreg=matchtempkonst(f, val2zmax(p, p->dtyp),tmp);
+		if(matchreg && matchreg!=tmp) {
+			emit_sizemod(f, t);
+			emit(f,"\tld\t%s\n",regnames[matchreg]);
+		} else {
+			emit_prepobj(f, p, t, tmp, 0);
+			emit_sizemod(f, t);
+			emit(f, "\tldt\n");
+		}
+		settempobj(f,tmp,p,0,0);
+		settempobj(f,reg,p,0,0);
+		if(reg!=tmp)
+			emit(f,"\tmr\t%s\n",regnames[reg]);
+		return(1);
+	}
+
+//	printf("p->flags %x, type %d\n",p->flags,t);
+
+	if (p->flags & DREFOBJ) {
+		if(DBGMSG)
+			emit(f, "\t\t\t\t\t\t// deref \n");
+		/* Dereferencing a pointer */
+		if (p->flags & REG) {
+			switch (t & NQ) {
+			case CHAR:
+				if (p->am && p->am->type == AM_POSTINC)
+				{
+					emit(f, "\tldbinc\t%s\n", regnames[p->reg]);
+					postinc=1;
+				}
+				else if (p->am && p->am->disposable)
+					emit(f,
+					     "\tldbinc\t%s\n//Disposable, postinc doesn't matter.\n", regnames[p->reg]);
+				else
+					emit(f, "\tbyt\n\tld\t%s\n", regnames[p->reg]);
+				break;
+			case SHORT:
+				emit(f, "\thlf\n");
+				emit(f, "\tld\t%s\n", regnames[p->reg]);
+				break;
+			case INT:
+			case LONG:
+			case POINTER:
+				if (p->am && p->am->type == AM_POSTINC)
+				{
+					emit(f, "\tldinc\t%s\n", regnames[p->reg]);
+					postinc=4;
+				}
+				else
+					emit(f, "\tld\t%s\n", regnames[p->reg]);
+				break;
+			case STRUCT:
+			case UNION:
+			case ARRAY:
+			case FUNKT:	// Function pointers are dereferenced by calling them.
+				emit(f, "\tmt\t%s\n", regnames[p->reg]);
+				break;
+			default:
+				fprintf(stderr,"Objtoreg - unhandled type %d\n",t);
+				ierror(0);
+				break;
+			}
+			result=1;
+		} else {
+			emit_prepobj(f, p, t, tmp, 0);
+			// Exclusions for fptrs, structs and unions to avoid double-dereference.
+			// Included array type in these exclusions.  FIXME - is this sufficient?
+			if ((t & NQ) != FUNKT && (t & NQ) != STRUCT && (t & NQ) != UNION && (t & NQ) != ARRAY)
+			{
+				emit_sizemod(f, t);
+				emit(f, "\tldt\n");
+				result=1;
+			}
+		}
+	} else {
+		if (p->flags & REG) {
+			// Already handled in the preamble.
+			if(DBGMSG)
+				emit(f, "\t\t\t\t\t\t// reg %s\n", regnames[p->reg]);
+			emit(f, "\tmt\t%s\n", regnames[p->reg]);
+		} else if (p->flags & VAR) {
+			if (isauto(p->v->storage_class)) {
+				if(DBGMSG)
+					emit(f, "\t\t\t\t\t\t// var, auto|reg\n");
+				/* Do we need to deference? */
+				if (elementary) {
+					if (real_offset(p)) {
+						emit_constanttotemp(f, real_offset(p));
+						if(!isstackparam(p))
+							emit_sizemod(f, t);
+						emit(f, "\tldidx\t%s\n", regnames[sp]);
+					} else {
+						emit_sizemod(f, t);
+						emit(f, "\tld\t%s\n", regnames[sp]);
+					}
+					result=1;
+				} else {
+					if (real_offset(p)) {
+						emit_constanttotemp(f, real_offset(p));
+						emit(f, "\taddt\t%s\n", regnames[sp]);
+					} else {
+						emit(f, "\tmt\t%s\n", regnames[sp]);
+					}
+				}
+			} else if (isextern(p->v->storage_class)) {
+				if(DBGMSG)
+					emit(f, "\t\t\t\t\t\t// extern\n");
+				emit_externtotemp(f, p->v->identifier, p->val.vmax);
+				// Structs, unions and arrays have to remain as pointers
+				if (elementary) {
+					if(DBGMSG)
+						emit(f, "\t\t\t\t\t\t//extern deref\n");
+					emit_sizemod(f, t);
+					emit(f, "\tldt\n");
+					result=1;
+				}
+			} else if (isstatic(p->v->storage_class)) {
+				if(DBGMSG)
+					emit(f, "\t\t\t\t\t\t//static %s\n", p->flags & VARADR ? "varadr" : "not varadr");
+				emit_statictotemp(f, labprefix, zm2l(p->v->offset), p->val.vmax);
+				// Structs, unions and arrays have to remain as pointers
+				if (elementary) {
+					if(DBGMSG)
+						emit(f, "\t\t\t\t\t\t//static deref\n");
+					emit_sizemod(f, t);
+					emit(f, "\tldt\n");
+					result=1;
+				}
+			} else {
+				printf("Objtotemp: Unhandled storage class: %d\n", p->v->storage_class);
+				ierror(0);
+			}
+		} else if (p->flags & KONST) {
+			if(DBGMSG)
+				emit(f, "\t\t\t\t\t\t// const\n");
+			emit_constanttotemp(f, val2zmax(p, t));
+		} else {
+			printf("Objtotemp: unknown flags %d\n", p->flags);
+			ierror(0);
+		}
+	}
+	if(reg!=tmp)
+		emit(f,"\tmr\t%s\n",regnames[reg]);
+	settempobj(f,reg,p,-postinc,0);
+	settempobj(f,tmp,p,-postinc,0);
+	return(result);
+}
+
diff --git a/machines/alpha/machine.c b/machines/alpha/machine.c
new file mode 100755
index 0000000..c5038c0
--- /dev/null
+++ b/machines/alpha/machine.c
@@ -0,0 +1,1707 @@
+/*  Code generator for a DEC Alpha 64bit RISC cpu with 32       */
+/*  general purpose and 32 floating point registers.            */
+
+#include "supp.h"
+
+static char FILE_[]=__FILE__;
+
+#include "dwarf2.c"
+
+/*  Public data that MUST be there.                             */
+
+/* Name and copyright. */
+char cg_copyright[]="vbcc code-generator for DEC Alpha V0.3c (c) in 1997-2000 by Volker Barthelmann";
+
+/*  Commandline-flags the code-generator accepts                */
+int g_flags[MAXGF]={VALFLAG,VALFLAG,0,0,0,0,0};
+char *g_flags_name[MAXGF]={"cpu","fpu","const-in-data","sd","merge-constants","stabs","no-builtins"};
+union ppi g_flags_val[MAXGF];
+
+/*  Alignment-requirements for all types in bytes.              */
+zmax align[MAX_TYPE+1];
+
+/*  Alignment that is sufficient for every object.              */
+zmax maxalign;
+
+/*  CHAR_BIT for the target machine.                            */
+zmax char_bit;
+
+/*  Tabelle fuer die Groesse der einzelnen Typen                */
+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[MAXR+1]={"noreg",
+                        "$0","$1","$2","$3","$4","$5","$6","$7",
+                        "$8","$9","$10","$11","$12","$13","$14","$15",
+                        "$16","$17","$18","$19","$20","$21","$22","$23",
+                        "$24","$25","$26","$27","$28","$29","$30","$31",
+                        "$f0","$f1","$f2","$f3","$f4","$f5","$f6","$f7",
+                        "$f8","$f9","$f10","$f11","$f12","$f13","$f14","$f15",
+                        "$f16","$f17","$f18","$f19","$f20","$f21","$f22","$f23",
+                        "$f24","$f25","$f26","$f27","$f28","$f29","$f30","$f31"};
+
+/*  The Size of each register in bytes.                         */
+zmax regsize[MAXR+1];
+
+/*  A 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,1,1,1,1,1,1,1,0,0,0,0,0,0,0,
+                          1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,
+                          1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,
+                          1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+
+struct reg_handle empty_reg_handle={0};
+
+
+/****************************************/
+/*  Private data and functions.         */
+/****************************************/
+
+static long malign[MAX_TYPE+1]=  {1,1,2,4,8,8,4,8,8,1,8,1,1,1,4,1};
+static long msizetab[MAX_TYPE+1]={1,1,2,4,8,8,4,8,8,0,8,0,0,0,4,0};
+
+static struct Typ ltyp={LONG};
+
+static char x_t[MAX_TYPE+1]={'?','b','w','l','q','q','s','t','t','?','q'};
+
+static int sp=31;                  /*  Stackpointer                        */
+static int gp=30;                  /*  Global pointer                      */
+static int lr=27;                  /*  Link Register                       */
+static int vp=28;                  /*  Virtual frame pointer               */
+static int r31=32;                 /*  Read as zero                        */
+static int f31=64;                 /*  Read as zero                        */
+static int sd=14;                  /*  SmallDataPointer                    */
+static int t1=2,t2=3,t3=4;         /*  Temporaries used by code generator  */
+static int t4=5,t5=6;
+static int f1=34,f2=35,f3=36;      /*  Temporaries used by code generator  */
+
+#define DATA 0
+#define BSS 1
+#define CODE 2
+
+static char *marray[]={"__ALPHA__",0};
+
+static int section=-1,newobj,crsave,helpl,helps,stabs;
+static char *codename="\t.text\n",*dataname="\t.data\n",*bssname="";
+static int balign(struct obj *);
+static char *labprefix="$C",*idprefix="";
+static long framesize,frameoffset;
+static void probj2(FILE *f,struct obj *p,int t);
+
+#define ESGN 1
+#define EUNS 2
+static int st[MAXR+1];
+
+static struct fpconstlist {
+  struct fpconstlist *next;
+  int label,typ;
+  union atyps val;
+} *firstfpc;
+
+static void move_reg(FILE *f,int s,int t)
+{
+  if(t==r31||t==f31) ierror(0);
+  if(s<=32&&t>32) ierror(0);
+  if(t<=32&&s>32) ierror(0);
+  if(s==t) return;
+  if(s<=32){
+    emit(f,"\tbis\t%s,%s,%s\n",regnames[r31],regnames[s],regnames[t]);
+  }else{
+    emit(f,"\tcpys\t%s,%s,%s\n",regnames[s],regnames[s],regnames[t]);
+  }
+  st[t]=st[s];
+}
+
+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==INT&&zmeqto(vmax,zi2zm(o->val.vint))) return p->label;
+        if(t==LONG&&zmeqto(vmax,zl2zm(o->val.vlong))) return p->label;
+        if(t==LLONG&&zmeqto(vmax,zll2zm(o->val.vllong))) return p->label;
+        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;
+}
+
+#define REG_IND 1
+#define IMM_IND 2
+
+static struct obj *cam(int flags,int base,int align,long offset)
+/*  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.align=align;
+  return &obj;
+}
+
+void title(FILE *f)
+{
+  static int done;
+  extern char *inname; /*grmpf*/
+  if(!done&&f){
+    done=1;
+    emit(f,"\t.file\t\"%s\"\n",inname);
+  }
+} 
+
+static char *dct[]={"??","byte","short","long","quad","long","long","quad","??","??","??","??"};
+
+static void load_address(FILE *f,int r,struct obj *o,int typ)
+/*  Generates code to load the address of a variable into register r.   */
+{
+  if((o->flags&VAR)&&(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)){
+    long of=zm2l(o->v->offset);
+    if(of>=0)
+      of+=frameoffset+zm2l(o->val.vlong);
+    else
+      of=-of-zm2l(maxalign)+framesize+zm2l(o->val.vmax);
+    if(of>32767) ierror(0);
+    emit(f,"\tlda\t%s,%ld(%s)\n",regnames[r],of,regnames[sp]);
+  }else{
+    emit(f,"\tlda\t%s,",regnames[r]);
+    probj2(f,o,typ);emit(f,"\n");
+  }
+  st[r]=ESGN;
+}
+static void load_obj(FILE *f,int r,struct obj *o,int typ,int tmp)
+{
+  int adr,shift,al;
+  switch(typ&NQ){
+  case POINTER:
+  case LDOUBLE:
+  case DOUBLE:
+  case FLOAT:
+  case LLONG:
+  case LONG:
+  case INT:
+    emit(f,"\tld%c\t%s,",x_t[typ&NQ],regnames[r]);
+    probj2(f,o,typ);emit(f,"\n");
+    st[r]=ESGN;return;
+  case SHORT:
+    al=balign(o);
+    if(al>=0){
+      emit(f,"\tldq_u\t%s,",regnames[r]);
+      probj2(f,o,typ);emit(f,"\n");
+      shift=64-16-al*8;
+      if(shift) emit(f,"\tsll\t%s,%d,%s\n",regnames[r],shift,regnames[r]);
+      if(typ&UNSIGNED){
+        emit(f,"\tsrl\t%s,%d,%s\n",regnames[r],64-16,regnames[r]);
+        st[r]=EUNS;
+      }else{
+        emit(f,"\tsra\t%s,%d,%s\n",regnames[r],64-16,regnames[r]);
+        st[r]=ESGN;
+      }
+      return;
+    }
+    adr=0;
+    if(o->am&&o->am->offset==0)
+      adr=o->am->base;
+    else if(zmeqto(o->val.vmax,l2zm(0L)))
+      adr=o->reg;
+    if(!adr){
+      adr=tmp;load_address(f,adr,o,POINTER);
+    }
+
+    if(typ&UNSIGNED){
+      emit(f,"\tbic\t%s,6,%s\n",regnames[adr],regnames[t4]); /* ldq_u ? */
+      emit(f,"\tldq\t%s,0(%s)\n",regnames[t5],regnames[t4]);
+      emit(f,"\tbic\t%s,1,%s\n",regnames[adr],regnames[t4]);
+      emit(f,"\textwl\t%s,%s,%s\n",regnames[t5],regnames[t4],regnames[r]);
+      /*
+      emit(f,"\tbic\t%s,2,%s\n",regnames[adr],regnames[t4]);
+      emit(f,"\tand\t%s,2,%s\n",regnames[adr],regnames[t5]);
+      emit(f,"\tldq\t%s,0(%s)\n",regnames[r],regnames[t4]);
+      emit(f,"\textwh\t%s,%s,%s\n",regnames[r],regnames[t5],regnames[r]);
+      */
+      st[r]=EUNS;return;
+    }else{
+      emit(f,"\tbic\t%s,6,%s\n",regnames[adr],regnames[t4]);
+      emit(f,"\tand\t%s,6,%s\n",regnames[adr],regnames[t5]);
+      emit(f,"\tldq\t%s,0(%s)\n",regnames[r],regnames[t4]);
+      emit(f,"\tlda\t%s,2(%s)\n",regnames[t5],regnames[t5]);
+      emit(f,"\textqh\t%s,%s,%s\n",regnames[r],regnames[t5],regnames[r]);
+      emit(f,"\tsra\t%s,48,%s\n",regnames[r],regnames[r]);
+      st[r]=ESGN;return;
+    }
+  case CHAR:
+    al=balign(o);
+    if(al>=0){
+      emit(f,"\tldq_u\t%s,",regnames[r]);
+      probj2(f,o,typ);emit(f,"\n");
+      shift=64-8-al*8;
+      if(shift&&al) emit(f,"\tsll\t%s,%d,%s\n",regnames[r],shift,regnames[r]);
+      if(typ&UNSIGNED){
+        if(al==0)
+          emit(f,"\tand\t%s,255,%s\n",regnames[r],regnames[r]);
+        else
+          emit(f,"\tsrl\t%s,%d,%s\n",regnames[r],64-8,regnames[r]);
+        st[r]=EUNS;
+      }else{
+        if(al==0)
+          emit(f,"\tsextb\t%s,%s\n",regnames[r],regnames[r]);
+        else
+          emit(f,"\tsra\t%s,%d,%s\n",regnames[r],64-8,regnames[r]);
+        st[r]=ESGN;
+      }
+      return;
+    }
+    if(typ&UNSIGNED){
+      adr=0;
+      if(o->am&&o->am->offset==0)
+        adr=o->am->base;
+      else if(zmeqto(o->val.vmax,l2zm(0L)))
+        adr=o->reg;
+      if(!adr){
+        adr=tmp; load_address(f,adr,o,POINTER);
+      }
+      emit(f,"\tldq_u\t%s,0(%s)\n",regnames[r],regnames[adr]);
+      emit(f,"\textbl\t%s,%s,%s\n",regnames[r],regnames[adr],regnames[r]);
+      st[r]=EUNS;return;
+    }else{
+      emit(f,"\tldq_u\t%s,",regnames[t5]);
+      probj2(f,o,typ);emit(f,"\n\tlda\t%s,",regnames[t4]);
+      if(o->am) o->am->offset++; else o->val.vmax=zmadd(o->val.vmax,l2zm(1L));
+      probj2(f,o,typ);
+      if(o->am) o->am->offset--; else o->val.vmax=zmsub(o->val.vmax,l2zm(1L));
+      emit(f,"\n\textqh\t%s,%s,%s\n",regnames[t5],regnames[t4],regnames[t5]);
+      emit(f,"\tsra\t%s,56,%s\n",regnames[t5],regnames[r]);
+      st[r]=ESGN;return;
+    }
+  }
+  ierror(0);
+}
+static void load_reg(FILE *f,int r,struct obj *o,int typ,int tmp)
+/*  Generates code to load a memory object into register r. tmp is a    */
+/*  general purpose register which may be used. tmp can be r.           */
+{
+  typ&=NU;
+  if(o->am){
+    load_obj(f,r,o,typ,tmp);
+    return;
+  }
+  if(o->flags&KONST){
+    long l;int lab;
+    eval_const(&o->val,typ);
+    if(ISFLOAT(typ)){
+      lab=addfpconst(o,typ);
+      emit(f,"\tlda\t%s,%s%d\n",regnames[tmp],labprefix,lab);
+      emit(f,"\tld%c\t%s,0(%s)\n",x_t[typ&NQ],regnames[r],regnames[tmp]);
+      st[r]=ESGN;
+      return;
+    }
+    if(zmleq(vmax,l2zm(32767))&&zmleq(l2zm(-32768),vmax)){
+      emit(f,"\tlda\t%s,%ld(%s)\n",regnames[r],zm2l(vmax),regnames[r31]);
+    }else{
+/*       if((typ&NQ)<INT) ierror(0); */
+      lab=addfpconst(o,typ);
+      emit(f,"\tlda\t%s,%s%d\n",regnames[tmp],labprefix,lab);
+      emit(f,"\tldq\t%s,0(%s)\n",regnames[r],regnames[tmp]);
+    }
+    st[r]=ESGN;
+    return;
+  }
+  if((o->flags&VAR)&&(o->v->storage_class==EXTERN||o->v->storage_class==STATIC)){
+    if(!(o->flags&VARADR)){
+      load_address(f,tmp,o,POINTER);
+      load_obj(f,r,cam(IMM_IND,tmp,balign(o),0L),typ,tmp);
+    }else{
+      load_address(f,r,o,POINTER);
+    }
+  }else{
+    if(o->am||(o->flags&(DREFOBJ|REG))==REG){
+      if(r!=o->reg)
+        move_reg(f,o->reg,r);
+    }else{
+      if(o->flags&DREFOBJ) ierror(0);
+      load_obj(f,r,o,typ,tmp);
+    }
+  }
+}
+
+
+static void store_reg(FILE *f,int r,struct obj *o,int typ)
+/*  Generates code to store register r into memory object o.            */
+{
+  int adr,t6,t7;
+  if((o->flags&(REG|DREFOBJ))==REG) ierror(0);
+  if(r==t1){ t6=t2;t7=t3;}
+  else if(r==t2) {t6=t1;t7=t3;}
+  else {t6=t1;t7=t2;}
+  if((typ&NQ)>SHORT){
+    if((o->flags&VAR)&&(o->v->storage_class==EXTERN||o->v->storage_class==STATIC)){
+      load_address(f,t6,o,POINTER);
+      emit(f,"\tst%c\t%s,0(%s)\n",x_t[typ&NQ],regnames[r],regnames[t6]);
+      return;
+    }
+    emit(f,"\tst%c\t%s,",x_t[typ&NQ],regnames[r]);
+    probj2(f,o,typ);emit(f,"\n");
+    return;
+  }else{
+    adr=0;
+    if(o->am&&o->am->offset==0){
+      adr=o->am->base;
+      if(adr<1||adr>32) ierror(0);
+    }else if((o->flags&REG)&&zmeqto(o->val.vmax,l2zm(0L))){
+      adr=o->reg;
+      if(adr<1||adr>32) ierror(0);
+    }
+    if(!adr){
+      adr=t7; load_address(f,adr,o,POINTER);
+    }
+    if(adr<1||adr>32) ierror(0);
+    if((typ&NQ)==SHORT){
+      emit(f,"\tbic\t%s,2,%s\n",regnames[adr],regnames[t4]);
+      emit(f,"\tldl\t%s,0(%s)\n",regnames[t6],regnames[t4]);
+      emit(f,"\tand\t%s,2,%s\n",regnames[adr],regnames[t5]);
+      emit(f,"\tmskwl\t%s,%s,%s\n",regnames[t6],regnames[t5],regnames[t6]);
+      emit(f,"\tinswl\t%s,%s,%s\n",regnames[r],regnames[t5],regnames[t7]);
+      emit(f,"\tbis\t%s,%s,%s\n",regnames[t6],regnames[t7],regnames[t6]);
+      emit(f,"\tstl\t%s,0(%s)\n",regnames[t6],regnames[t4]);
+      return;
+    }else{
+      emit(f,"\tldq_u\t%s,0(%s)\n",regnames[t4],regnames[adr]);
+      emit(f,"\tmskbl\t%s,%s,%s\n",regnames[t4],regnames[adr],regnames[t4]);
+      emit(f,"\tinsbl\t%s,%s,%s\n",regnames[r],regnames[adr],regnames[t5]);
+      emit(f,"\tbis\t%s,%s,%s\n",regnames[t4],regnames[t5],regnames[t4]);
+      emit(f,"\tstq_u\t%s,0(%s)\n",regnames[t4],regnames[adr]);
+      return;
+    }
+  }
+}
+
+static void extend(FILE *f,int r)
+{
+  if(!r) return;
+  if(st[r]==ESGN) return;
+  emit(f,"\taddl\t%s,%s,%s\n",regnames[r],regnames[r31],regnames[r]);
+  st[r]=ESGN;
+}
+static void uextend(FILE *f,int r)
+{
+  if(!r) return;
+  if(st[r]==EUNS) return;
+  emit(f,"\tzapnot\t%s,15,%s\n",regnames[r],regnames[r]);
+  st[r]=EUNS;
+}
+
+static struct IC *do_refs(FILE *,struct IC *);
+static void pr(FILE *,struct IC *);
+static void function_top(FILE *,struct Var *,long,long);
+static void function_bottom(FILE *f,struct Var *,long,long);
+
+#define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
+
+static int q1reg,q2reg,zreg;
+
+static char *ccs[]={"eq","ne","lt","ge","le","gt",""};
+static char *logicals[]={"bis","xor","and"};
+static char *arithmetics[]={"sll","srl","add","sub","mul","div","rem"};
+
+static struct IC *do_refs(FILE *f,struct IC *p)
+/*  Does some pre-processing like fetching operands from memory to      */
+/*  registers etc.                                                      */
+{
+  int typ=p->typf,typ1,reg,c=p->code;
+
+  typ=q1typ(p);
+  if(ISPOINTER(typ)) typ=(UNSIGNED|LONG);
+
+  q1reg=q2reg=zreg=0;
+  if(p->q1.flags&REG) q1reg=p->q1.reg;
+  if(p->q2.flags&REG) q2reg=p->q2.reg;
+  if((p->z.flags&(REG|DREFOBJ))==REG) zreg=p->z.reg;
+
+
+  if((p->q1.flags&(KONST|DREFOBJ))==KONST){
+    eval_const(&p->q1.val,typ);
+    if(zmeqto(vmax,l2zm(0L))&&zumeqto(vumax,ul2zum(0UL))&&zldeqto(vldouble,d2zld(0.0))){
+      if(ISFLOAT(typ)) q1reg=f31; else q1reg=r31;
+    }else{
+      if(ISFLOAT(typ)) reg=f1; else reg=t1;
+      if(c==ASSIGN&&zreg) reg=zreg;
+      if(c==SETRETURN&&p->z.reg) reg=p->z.reg;
+      if((c==MOD||c==DIV)&&ISINT(typ)&&!regs[25]) reg=25; /* Linux-div */
+      if(ISFLOAT(typ)||c==DIV||c==SUB||c==ASSIGN||c==PUSH||c==SETRETURN||c==LSHIFT||c==RSHIFT||c==COMPARE){
+        load_reg(f,reg,&p->q1,typ,t1);
+        q1reg=reg;
+      }else{
+        if(ISINT(typ)){
+          if(!zumleq(vumax,ul2zum(255UL))||!zmleq(vmax,l2zm(255L))||zmleq(vmax,l2zm(-1L))){
+            load_reg(f,reg,&p->q2,typ,t1);
+            q1reg=reg;
+          }
+        }
+      }
+    }
+  }else if(c!=ADDRESS){
+    if(p->q1.flags&&!q1reg){
+      if(ISFLOAT(typ)) reg=f1; else reg=t1;
+      if((c==ASSIGN||c==CONVERT)&&zreg&&(reg-r31)*(zreg-r31)>0) reg=zreg;
+      if(c==SETRETURN&&p->z.reg) reg=p->z.reg;
+      if((p->q1.flags&DREFOBJ)||c==ADDI2P||c==SUBIFP) {typ1=POINTER;reg=t1;} else typ1=typ;
+      if(c==CALL) reg=vp;
+      if((c==MOD||c==DIV)&&ISINT(typ1)&&!regs[25]) reg=25; /* Linux-div */
+      if(ISSCALAR(typ1)){
+        int m=p->q1.flags;
+        p->q1.flags&=~DREFOBJ;
+        load_reg(f,reg,&p->q1,typ1,t1);
+        p->q1.flags=m;
+        q1reg=reg;
+      }
+    }
+    if((p->q1.flags&DREFOBJ)&&ISSCALAR(typ)){
+      if(ISFLOAT(typ)) reg=f1; else reg=t1;
+      if((c==ASSIGN||c==CONVERT)&&zreg&&regok(zreg,typ,0)) reg=zreg;
+      if(c==SETRETURN&&p->z.reg) reg=p->z.reg;
+      if((c==MOD||c==DIV)&&(typ&NQ)<=LONG&&!regs[25]) reg=25; /* Linux-div */
+      if(c==ADDI2P||c==SUBIFP)
+        load_reg(f,reg,cam(IMM_IND,q1reg,-1,0),POINTER,t1);
+      else
+        load_reg(f,reg,cam(IMM_IND,q1reg,-1,0),typ,t1);
+      q1reg=reg;
+    }
+  }
+  typ=q2typ(p);
+  if((p->q2.flags&(KONST|DREFOBJ))==KONST){
+    eval_const(&p->q2.val,typ);
+    if(zmeqto(vmax,l2zm(0L))&&zumeqto(vumax,ul2zum(0UL))&&zldeqto(vldouble,d2zld(0.0))){
+      if(ISFLOAT(typ)) q2reg=f31; else q2reg=r31;
+    }else{
+      if(ISFLOAT(typ)) reg=f2; else reg=t2;
+      if((c==MOD||c==DIV)&&ISINT(typ)&&!regs[26]) reg=26; /* Linux-div */
+      if(ISFLOAT(typ)){
+        load_reg(f,reg,&p->q2,typ,t2);
+        q2reg=reg;
+      }else{
+        if(ISINT(typ)){
+          if(!zumleq(vumax,ul2zum(255UL))||!zmleq(vmax,l2zm(255L))||zmleq(vmax,l2zm(-1L))){
+            load_reg(f,reg,&p->q2,typ,t2);
+            q2reg=reg;
+          }
+        }
+      }
+    }
+  }else{
+    if(p->q2.flags&&!q2reg){
+      if(p->q2.flags&DREFOBJ) typ1=POINTER; else typ1=typ;
+      if(ISFLOAT(typ1)) reg=f2; else reg=t2;
+      if((c==MOD||c==DIV)&&ISINT(typ1)&&!regs[26]) reg=26; /* Linux-div */
+      if(ISSCALAR(typ1)){
+        int m=p->q2.flags;
+        p->q2.flags&=~DREFOBJ;
+        load_reg(f,reg,&p->q2,typ1,t2);
+        p->q2.flags=m;
+        q2reg=reg;
+      }
+    }
+    if((p->q2.flags&DREFOBJ)&&ISSCALAR(typ)){
+      if(ISFLOAT(typ)) reg=f2; else reg=t2;
+      if((c==MOD||c==DIV)&&ISINT(typ)&&!regs[26]) reg=26; /* Linux-div */
+      load_reg(f,reg,cam(IMM_IND,q2reg,-1,0),typ,t2);
+      q2reg=reg;
+    }
+  }
+  if(p->z.flags&&!isreg(z)){
+    typ=ztyp(p);
+    if(ISFLOAT(typ)) zreg=f3; else zreg=t3;
+    if((c==MOD||c==DIV)&&ISINT(typ)&&!regs[28]) zreg=28; /* Linux-div */
+  }
+  if(q1reg){ p->q1.flags=REG; p->q1.reg=q1reg;}
+  if(q2reg){ p->q2.flags=REG; p->q2.reg=q2reg;}
+  return p;
+}
+static long pof2(zumax x)
+/*  Yields log2(x)+1 oder 0. */
+{
+    zumax p;int ln=1;
+    p=ul2zum(1L);
+    while(ln<=64&&zumleq(p,x)){
+        if(zumeqto(x,p)) return ln;
+        ln++;p=zumadd(p,p);
+    }
+    return 0;
+}
+static void pr(FILE *f,struct IC *p)
+/*  Writes the destination register to the real destination if necessary.   */
+{
+  int typ=p->typf;
+  if(p->z.flags){
+    if(p->code==ADDRESS||p->code==ADDI2P||p->code==SUBIFP) typ=POINTER;
+    if(!isreg(z)){
+      if(p->z.flags&DREFOBJ){
+        if(p->z.flags&REG){
+          store_reg(f,zreg,cam(IMM_IND,p->z.reg,-1,0),typ);
+        }else{
+          int r,m;
+          if(t1==zreg) r=t2; else r=t1;
+          m=p->z.flags;
+          p->z.flags&=~DREFOBJ;
+          load_reg(f,r,&p->z,POINTER,r);
+          p->z.flags=m;
+          store_reg(f,zreg,cam(IMM_IND,r,balign(&p->z),0),typ);
+        }
+      }else{
+        store_reg(f,zreg,&p->z,typ);
+      }
+    }else{
+      if(p->z.reg!=zreg)
+        move_reg(f,zreg,p->z.reg);
+    }
+  }
+}
+
+static void probj2(FILE *f,struct obj *p,int t)
+/*  Prints an object.                               */
+{
+  if(p->am){
+    if(p->am->flags==REG_IND) ierror(0);
+    if(p->am->flags==IMM_IND) emit(f,"%ld(%s)",p->am->offset,regnames[p->am->base]);
+    return;
+  }
+  if(p->flags&DREFOBJ) emit(f,"(");
+  if(p->flags&VAR) {
+    if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER){
+      if(p->flags&REG){
+        emit(f,"%s",regnames[p->reg]);
+      }else{
+        long of=zm2l(p->v->offset);
+        if(of>=0)
+          of+=frameoffset+zm2l(p->val.vmax);
+        else
+          of=-of-zm2l(maxalign)+framesize+zm2l(p->val.vmax);
+        if(of>32767) ierror(0);
+        emit(f,"%ld(%s)",of,regnames[sp]);
+      }
+    }else{
+      if(!zmeqto(l2zm(0L),p->val.vmax)){emitval(f,&p->val,MAXINT);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((p->flags&REG)&&!(p->flags&VAR)) emit(f,"%s",regnames[p->reg]);
+  if(p->flags&KONST){
+    emitval(f,&p->val,t&NU);
+  }
+  if(p->flags&DREFOBJ) emit(f,")");
+}
+static void dwarf2_print_frame_location(FILE *f,struct Var *v)
+{
+  struct obj o;
+  o.flags=REG;
+  /*FIXME: need correct register translation */
+  o.reg=sp;
+  o.val.vmax=l2zm(0L);
+  o.v=0;
+  dwarf2_print_location(f,&o);
+}
+static int dwarf2_regnumber(int r)
+{
+  /*FIXME: needs correct translation */
+  return r-1;
+}
+static zmax dwarf2_fboffset(struct Var *v)
+{
+  long of;
+  if(!v||(v->storage_class!=AUTO&&v->storage_class!=REGISTER)) ierror(0);
+  of=zm2l(v->offset);
+  if(of>=0)
+    of+=frameoffset;
+  else
+    of=-of-zm2l(maxalign)+framesize;
+  if(of>32767) ierror(0);
+  return l2zm(of);
+}
+static void function_top(FILE *f,struct Var *v,long offset,long maxpushed)
+/*  Generates function top.                             */
+{
+  int i;
+   emit(f,"\t.set\tnoat\n");
+  if(section!=CODE){emit(f,codename);if(f) section=CODE;}
+  emit(f,"\t.align\t3\n");
+  if(v->storage_class==EXTERN)
+    if((v->flags&(INLINEFUNC|INLINEEXT))!=INLINEFUNC)
+      emit(f,"\t.global\t%s%s\n",idprefix,v->identifier);
+  emit(f,"\t.ent\t%s%s\n",idprefix,v->identifier);
+  if(v->storage_class==STATIC)
+    emit(f,"%s%ld:\n",labprefix,zm2l(v->offset));
+  else
+    emit(f,"%s%s:\n",idprefix,v->identifier);
+  if(function_calls) emit(f,"\tldgp\t%s,0(%s)\n",regnames[gp],regnames[vp]);
+  if(v->storage_class==STATIC)
+    emit(f,"%s%ld..ng:\n",labprefix,zm2l(v->offset));
+  else  
+    emit(f,"%s%s..ng:\n",idprefix,v->identifier);
+  framesize=offset+maxpushed;
+  if(function_calls) framesize+=8; /* lr */
+  for(i=1;i<=MAXR;i++)
+    if(regused[i]&&!regscratch[i]&&!regsa[i])
+      framesize+=8;
+  framesize=((framesize+16-1)/16)*16;
+  if(framesize>32767) ierror(0);
+  if(framesize) emit(f,"\tlda\t%s,%ld(%s)\n",regnames[sp],-framesize,regnames[sp]);
+  emit(f,"\t.frame\t%s,%ld,%s,0\n",regnames[sp],framesize,regnames[lr]);
+  frameoffset=maxpushed;
+  if(function_calls){
+    emit(f,"\tstq\t%s,%ld(%s)\n",regnames[lr],frameoffset,regnames[sp]);
+    frameoffset+=8;
+  }
+  for(i=1;i<=MAXR;i++){
+    if(regused[i]&&!regscratch[i]&&!regsa[i]){
+      if(i<=32){
+        emit(f,"\tstq\t%s,%ld(%s)\n",regnames[i],frameoffset,regnames[sp]);
+      }else{
+        emit(f,"\tstt\t%s,%ld(%s)\n",regnames[i],frameoffset,regnames[sp]);
+      }
+      frameoffset+=8;
+    }
+  }
+  emit(f,"\t.mask\t0x4000000,%ld\n",-framesize);
+  emit(f,"\t.prologue\t%c\n",function_calls?'1':'0');
+}
+static void function_bottom(FILE *f,struct Var *v,long offset,long maxpushed)
+/*  Generates function bottom.                          */
+{
+  int i;
+  frameoffset=maxpushed;
+  if(function_calls){
+    emit(f,"\tldq\t%s,%ld(%s)\n",regnames[lr],frameoffset,regnames[sp]);
+    frameoffset+=8;
+  }
+  for(i=1;i<=MAXR;i++){
+    if(regused[i]&&!regscratch[i]&&!regsa[i]){
+      if(i<=32){
+        emit(f,"\tldq\t%s,%ld(%s)\n",regnames[i],frameoffset,regnames[sp]);
+      }else{
+        emit(f,"\tldt\t%s,%ld(%s)\n",regnames[i],frameoffset,regnames[sp]);
+
+      }
+      frameoffset+=8;
+    }
+  }
+  if(framesize) emit(f,"\tlda\t%s,%ld(%s)\n",regnames[sp],framesize,regnames[sp]);
+  emit(f,"\tret\t%s,(%s),1\n",regnames[r31],regnames[lr]);
+  emit(f,"\t.end\t%s%s\n",idprefix,v->identifier);
+  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);
+}
+static int balign(struct obj *o)
+/*  Liefert die unteren 3 Bits des Objekts. -1 wenn unklar. */
+{
+  int sc;
+  if(o->flags&DREFOBJ) return -1;
+  if(o->am) return o->am->align;
+  if(!(o->flags&VAR)) ierror(0);
+  sc=o->v->storage_class;
+  if(sc==EXTERN||sc==STATIC){
+    /* Alle statischen Daten werden vom cg auf 64bit alignt. */
+    return zm2l(zmand(o->val.vmax,l2zm(7L)));
+  }
+  if(sc==AUTO||sc==REGISTER){
+    zmax of=o->v->offset;
+    if(!zmleq(l2zm(0L),of))
+      of=zmsub(l2zm(0L),zmadd(of,maxalign));
+    return zm2l(zmand(zmadd(of,o->val.vmax),l2zm(7L)));
+  }
+  ierror(0);
+}
+
+/* Routinen fuer Debug-Informationen mit stabs. */
+
+static int debug_blabel,debug_elabel;
+static int debug_type(FILE *,struct Typ *);
+static void debug_init(FILE *,struct Var *);
+static void debug_exit(FILE *,struct Var *);
+static void debug_var(FILE *,struct obj *);
+static void debug_IC(FILE *,struct IC *);
+static void debug_cleanup(FILE *);
+
+static int debug_type(FILE *f,struct Typ *t)
+     /* Liefert Typindex.  */
+{
+  return t->flags&NU;
+}
+static void debug_init(FILE *f,struct Var *v)
+     /* Debug-Infos. Wird am Anfang von gen_code aufgerufen. */
+{
+  static int did_header;
+  if(!did_header){
+    emit(f,"\t.stabs \"\",100,0,0,%stext0\n",labprefix);
+    emit(f,"\t.stabs \"%s\",100,0,0,%stext0\n",filename,labprefix);
+    emit(f,"\t.text\n%stext0:\n",labprefix);if(f) section=CODE;
+    emit(f,"\t.stabs\t\"char:t%d=r1;-128;127;\",128,0,0,0\n",CHAR);
+    emit(f,"\t.stabs\t\"short:t%d=r1;-32768;32767;\",128,0,0,0\n",SHORT);
+    emit(f,"\t.stabs\t\"int:t%d=r1;-2147483648;2147483647;\",128,0,0,0\n",INT);
+    emit(f,"\t.stabs\t\"long:t%d=r1;001000000000000000000000;000777777777777777777777;\",128,0,0,0\n",LONG);
+    emit(f,"\t.stabs\t\"unsigned char:t%d=r1;0;255;\",128,0,0,0\n",UNSIGNED|CHAR);
+    emit(f,"\t.stabs\t\"unsigned short:t%d=r1;0;65535;\",128,0,0,0\n",UNSIGNED|SHORT);
+    emit(f,"\t.stabs\t\"unsigned int:t%d=r1;0;-1;\",128,0,0,0\n",UNSIGNED|INT);
+    emit(f,"\t.stabs\t\"unsigned long:t%d=r1;0;-1;\",128,0,0,0\n",UNSIGNED|LONG);
+    emit(f,"\t.stabs\t\"float:t%d=r1;4;0;\",128,0,0,0\n",FLOAT);
+    emit(f,"\t.stabs\t\"double:t%d=r1;8;0;\",128,0,0,0\n",DOUBLE);
+    emit(f,"\t.stabs\t\"void:t%d=%d;8;0;\",128,0,0,0\n",VOID,VOID);
+    did_header=1;
+  }
+  emit(f,"\t.stabs\t\"%s:F%d\",36,0,0,%s%s\n",v->identifier,debug_type(f,v->vtyp->next),idprefix,v->identifier);
+  debug_blabel=++label;debug_elabel=++label;
+}
+static void debug_exit(FILE *f,struct Var *v)
+     /* Debug-Infos. Wird am Ende von gen_code aufgerufen. */
+{
+  struct IC *p;
+  ierror(0);
+  emit(f,"\t.stabn\t192,0,0,%s%d\n",labprefix,debug_blabel);
+  emit(f,"\t.stabn\t224,0,0,%s%d\n",labprefix,debug_elabel);
+  for(p=first_ic;p;p=p->next){
+    if(p->q1.flags&VAR) debug_var(f,&p->q1);
+    if(p->q2.flags&VAR) debug_var(f,&p->q2);
+    if(p->z.flags&VAR) debug_var(f,&p->z);
+  }
+}
+static void debug_var(FILE *f,struct obj *o)
+     /* Debug-Infos fuer eine Variable ausgeben. */
+{
+  struct Var *v=o->v; int td;
+  if(!*v->identifier) return;
+  td=debug_type(f,v->vtyp);
+  if(ISFUNC(td)) return;
+  if(o->flags&REG){
+    emit(f,"\t.stabs\t\"%s:r%d\",0x40,0,0,%d\n",v->identifier,td,o->reg-1);
+    return;
+  }
+  if(v->storage_class==AUTO||v->storage_class==REGISTER){
+    long of=zm2l(v->offset);
+    if(!zmleq(l2zm(0L),v->offset)){
+      of=-of-zm2l(maxalign)+framesize;
+      emit(f,"#\toffset %ld:\n",of);
+      emit(f,"\t.stabs\t\"%s:p%d\",0x80,0,0,%ld\n",v->identifier,td,of-framesize);
+    }else{
+      of+=frameoffset;
+      emit(f,"#\toffset %ld:\n",of);
+      emit(f,"\t.stabs\t\"%s:%d\",0x80,0,0,%ld\n",v->identifier,td,of-framesize);
+    }
+    return;
+  }
+  ierror(td);
+}
+static void debug_IC(FILE *f,struct IC *p)
+     /* Debug-Infos. Wird fuer jedes IC aufgerufen. */
+{
+  static int lastline;int lab;
+  printf("%d",p->line);pric2(stdout,p);
+  if(!p->prev)
+    emit(f,"%s%d:\n",labprefix,debug_blabel);
+/*   if(p->q1.flags&VAR) debug_var(f,&p->q1); */
+/*   if(p->q2.flags&VAR) debug_var(f,&p->q2); */
+/*   if(p->z.flags&VAR) debug_var(f,&p->z); */
+  if(p->line&&p->line!=lastline){
+    lab=++label;lastline=p->line;
+    emit(f,"%s%d:\n",labprefix,lab);
+    emit(f,"\t.stabn\t68,0,%d,%s%d\n",lastline,labprefix,lab);
+  }
+  if(!p->next) emit(f,"%s%d:\n",labprefix,debug_elabel);
+}
+static void debug_cleanup(FILE *f)
+     /* Debug-Infos. Wird in cleanup_cg aufgerufen. */
+{
+}
+
+
+/****************************************/
+/*  End of private data 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;
+  /*  Initialize some values which cannot be statically initialized   */
+  /*  because they are stored in the target's arithmetic.             */
+  maxalign=l2zm(8L);
+  char_bit=l2zm(8L);
+  for(i=0;i<=MAX_TYPE;i++){
+    sizetab[i]=l2zm(msizetab[i]);
+    align[i]=l2zm(malign[i]);
+  }
+  for(i= 1;i<=32;i++) {regsize[i]=l2zm(8L);regtype[i]=&ltyp;}
+  for(i=33;i<=64;i++) {regsize[i]=l2zm(8L);regtype[i]=&ltyp;}
+
+  /*  Use multiple ccs.   */
+  multiple_ccs=0; /* not yet */
+
+  /*  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.          */
+  t_min[CHAR]=l2zm(-128L);
+  t_min[SHORT]=l2zm(-32768L);
+  t_min[INT]=zmsub(l2zm(-2147483647L),l2zm(1L));
+  t_min[LLONG]=zmlshift(l2zm(1L),l2zm(63L));
+  t_min[LONG]=t_min[LLONG];
+  t_min[MAXINT]=t_min(LLONG);
+  t_max[CHAR]=ul2zum(127L);
+  t_max[SHORT]=ul2zum(32767UL);
+  t_max[INT]=ul2zum(2147483647UL);
+  t_max[LLONG]=zumrshift(zumkompl(ul2zum(0UL)),ul2zum(1UL));
+  t_max[LONG]=t_max[LLONG];
+  t_max[MAXINT]=t_max(LLONG);
+  tu_max[CHAR]=ul2zum(255UL);
+  tu_max[SHORT]=ul2zum(65535UL);
+  tu_max[INT]=ul2zum(4294967295UL);
+  tu_max[LLONG]=zumkompl(ul2zum(0UL));
+  tu_max[LONG]=tu_max[LLONG];
+  tu_max[MAXINT]=t_max(UNSIGNED|LLONG);
+
+  /*  Reserve a few registers for use by the code-generator.      */
+  /*  This is not optimal but simple.                             */
+  regsa[t1]=regsa[t2]=regsa[t3]=regsa[t4]=regsa[t5]=1;
+  regsa[f1]=regsa[f2]=regsa[f3]=1;
+  regsa[sp]=regsa[gp]=regsa[sd]=1;
+  regsa[lr]=regsa[r31]=regsa[f31]=1;
+  regscratch[t1]=regscratch[t2]=regscratch[t3]=regscratch[t4]=regscratch[t5]=0;
+  regscratch[f1]=regscratch[f2]=regscratch[f3]=0;
+  regscratch[sp]=regscratch[gp]=regscratch[sd]=0;
+  regscratch[lr]=regscratch[r31]=regscratch[f31]=0;
+  /* reserve at - noch aendern */
+  /* regsa[29]=1;regscratch[29]=0; */
+  /* Debug stabs? */
+  stabs=(g_flags[5]&USEDFLAG);
+  target_macros=marray;
+  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.        */
+/*  A pointer MUST be returned in a register. The code-generator    */
+/*  has to simulate a pseudo register if necessary.                 */
+{
+  if(ISFLOAT(t->flags)) return 33;
+  if(ISSTRUCT(t->flags)||ISUNION(t->flags)) return 0;
+  if(zmleq(szof(t),l2zm(8L)))
+    return 1; 
+  else
+    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.                                            */
+{
+  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(r==0) return 0;
+  if(t==0) return 0;
+  if(ISFLOAT(t)){
+    if(r>=33&&r<=64)
+      return 1;
+    else
+      return 0;
+  }
+  if(ISSCALAR(t)&&r>=1&&r<=32) return 1;
+  return 0;
+}
+
+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)&&!(p->q2.flags&KONST))
+    return 1;
+  return 0;
+}
+
+int must_convert(int o,int t,int const_expr)
+/*  Returns zero if code for converting np to type t    */
+/*  can be omitted.                                     */
+/*  On the PowerPC cpu pointers and 32bit               */
+/*  integers have the same representation and can use   */
+/*  the same registers.                                 */
+{
+  int op=o&NQ,tp=t&NQ;
+  if((op==LONG||op==LLONG||op==POINTER)&&(tp==LONG||tp==LLONG||tp==POINTER)) return 0;
+  if((op==DOUBLE||op==LDOUBLE)&&(tp==DOUBLE||tp==LDOUBLE)) 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.                              */
+{
+  title(f);
+  if(newobj){
+    size=zmmult(zmdiv(zmadd(size,l2zm(7L)),l2zm(8L)),l2zm(8L));
+    emitzm(f,size);
+  }else{
+    emit(f,"\t.zero\t");
+    emitzm(f,size);
+  }
+  emit(f,"\n");
+  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.              */
+{
+  title(f);
+  if(zm2l(align)>1)
+    emit(f,"\t.align\t3\n");
+}
+
+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;
+  title(f);
+  if(v->clist) constflag=is_const(v->vtyp);
+  if(v->storage_class==STATIC){
+    if(ISFUNC(v->vtyp->flags)) return;
+    if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&&section!=DATA){emit(f,dataname);if(f) section=DATA;}
+    if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&&section!=CODE){emit(f,codename);if(f) section=CODE;}
+    if(!v->clist&&section!=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(section!=BSS)
+      emit(f,"\t.align\t3\n%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){
+    emit(f,"\t.global\t%s%s\n",idprefix,v->identifier);
+    if(v->flags&(DEFINED|TENTATIVE)){
+      if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&&section!=DATA){emit(f,dataname);if(f) section=DATA;}
+      if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&&section!=CODE){emit(f,codename);if(f) section=CODE;}
+      if(!v->clist&&section!=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(section!=BSS)
+	emit(f,"\t.align\t3\n%s%s:\n",idprefix,v->identifier);
+      else{
+	emit(f,"\t.comm\t%s%s,",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.                      */
+{
+  title(f);
+  if(ISPOINTER(t)) t=UNSIGNED|LONG;
+  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)!=FLOAT){
+        emit(f,",0x%02x%02x%02x%02x",ip[7],ip[6],ip[5],ip[4]);
+      }
+    }else{
+      emitval(f,&p->val,t&NU);
+    }
+  }else{
+    if(p->tree->o.am) ierror(9);
+    probj2(f,&p->tree->o,t&NU);
+  }
+  emit(f,"\n");newobj=0;
+}
+
+
+/*  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 *p,struct Var *v,zmax offset)
+/*  The main code-generation.                                           */
+{
+  int addbuf,c,t,cmpreg,cmpflag,wasnoreg,i,varargs=0,fixargs;struct IC *m;
+  long pushed,maxpushed;
+  if(DEBUG&1) printf("gen_code()\n");
+  if(stabs) debug_init(f,v);
+  for(c=1;c<=MAXR;c++){regs[c]=regsa[c];st[c]=ESGN;}
+  /* We do a pass over the code to retrieve some info and prepare certain optimizations */
+  addbuf=0;maxpushed=0;
+  title(f);
+  for(m=p;m;m=m->next){
+    c=m->code;t=m->typf&NU;
+    if(c==ALLOCREG) {regs[m->q1.reg]=1;continue;}
+    if(c==FREEREG) {regs[m->q1.reg]=0;continue;}
+    if(c==COMPARE&&(m->q2.flags&KONST)){
+      eval_const(&m->q2.val,t);
+      if(zmeqto(vmax,l2zm(0L))&&zumeqto(vumax,ul2zum(0UL))&&zldeqto(vldouble,d2zld(0.0))){
+        m->q2.flags=0;m->code=c=TEST;
+      }
+    }
+    if(ISINT(t)&&(m->q2.flags&KONST)&&(c==MULT||((c==DIV||c==MOD)&&(t&UNSIGNED)))){
+      eval_const(&m->q2.val,t);
+      i=pof2(vumax);
+      if(i){
+        if(c==MOD){
+          vmax=zmsub(vmax,l2zm(1L));
+          m->code=AND;
+        }else{
+          vmax=l2zm(i-1);
+          if(c==DIV) m->code=RSHIFT; else m->code=LSHIFT;
+        }
+        c=m->code;
+	gval.vmax=vmax;
+	eval_const(&gval,MAXINT);
+	if(c==AND){
+	  insert_const(&m->q2.val,t&NU);
+	}else{
+	  insert_const(&m->q2.val,INT);
+	  p->typf2=INT;
+	}
+      }
+    }
+    /* Need one stack slot for transfrring between integer and floating-point registers. */
+    t&=NQ;
+    if(c==CONVERT&&addbuf<8&&((ISFLOAT(t)&&!ISFLOAT(m->typf2))||(!ISFLOAT(t)&&ISFLOAT(p->typf2)))) addbuf=8;
+    /* May need one stack slot for inline memcpy. */
+/*     if((c==ASSIGN||c==PUSH)&&t>=POINTER&&addbuf<8) addbuf=8; */
+    /* Need additional stack slots for passing function arguments. */
+    if(c==CALL&&maxpushed<zm2l(m->q2.val.vmax)) maxpushed=zm2l(m->q2.val.vmax);
+    if(c==CALL&&(m->q1.flags&VAR)&&!strcmp(m->q1.v->identifier,"__va_start")) varargs=1;
+    /* Need up to 4 stack slots for calling div/mod-functions. */
+    if((c==DIV||c==MOD)&&ISINT(t)&&addbuf<32){
+      if(regs[25]||regs[26]||regs[28]||regs[29]) addbuf=32;
+    }
+  }
+  /* Noch nicht ok. */
+  if(varargs){
+    fixargs=0;
+    for(i=0;i<v->vtyp->exact->count;i++){
+      c=(*v->vtyp->exact->sl)[i].styp->flags;
+      if(ISPOINTER(c)) fixargs++;
+    }
+    if(fixargs<6) addbuf+=(6-fixargs)*16;
+  }
+  function_top(f,v,zm2l(offset+addbuf),maxpushed);
+  if(varargs){
+    for(i=fixargs+1;i<=6;i++){
+      emit(f,"\tstq\t%s,%ld(%s)\n",regnames[16+i],framesize-(7-i)*16,regnames[sp]);
+      emit(f,"\tstt\t%s,%ld(%s)\n",regnames[48+i],framesize-(7-i)*16+8,regnames[sp]);
+    }
+  }
+  pushed=0;
+  for(;p;pr(f,p),p=p->next){
+    if(DEBUG) pric2(stdout,p);
+    if(debug_info){
+      if(stabs) 
+	debug_IC(f,p);
+      else
+	dwarf2_line_info(f,p);
+    }
+    c=p->code;t=p->typf;
+    if(c==NOP) continue;
+    if(c==ALLOCREG) {regs[p->q1.reg]=1;continue;}
+    if(c==FREEREG) {regs[p->q1.reg]=0;continue;}
+    if(c==LABEL||(c>=BEQ&&c<=BRA)){
+      int i;
+      for(i=1;i<=32;i++)
+        if(regs[i]&&!regsa[i]) extend(f,i);
+    }
+    if(c==LABEL) {emit(f,"%s%d:\n",labprefix,t);continue;}
+    if(c==BRA) {emit(f,"\tbr\t%s%d\n",labprefix,t);continue;}
+    if(c>=BEQ&&c<BRA){
+      if(cmpflag){
+        emit(f,"\t%sb%s\t%s,%s%d\n",cmpreg<=32?"":"f",cmpflag<0?"eq":"ne",regnames[cmpreg],labprefix,t);
+      }else{
+        emit(f,"\t%sb%s\t%s,%s%d\n",cmpreg<=32?"":"f",ccs[c-BEQ],regnames[cmpreg],labprefix,t);
+      }
+      continue;
+    }
+    if(c==MOVETOREG){
+      load_reg(f,p->z.reg,&p->q1,p->z.reg<=32?LONG:DOUBLE,0);
+      p->z.flags=0;
+      continue;
+    }
+    if(c==MOVEFROMREG){
+      store_reg(f,p->q1.reg,&p->z,p->q1.reg<=32?LONG:DOUBLE);
+      p->z.flags=0;
+      continue;
+    }
+    if(ISPOINTER(t)) t=((t&~NU)|UNSIGNED|LONG);
+    if((c==ASSIGN||c==PUSH)&&(!ISSCALAR(t)||((t&NQ)==CHAR&&zm2l(p->q2.val.vmax)!=1))){
+      zmax size; struct obj loops;
+      int salign,dalign,cl,a1,a2,mr,ms;
+      size=p->q2.val.vmax;
+      salign=balign(&p->q1);
+      if(c==PUSH) dalign=0; else dalign=balign(&p->z);
+      if(salign>=0&&dalign>=0&&(salign&3)==(dalign&3)){
+        a1=t1; a2=t2;
+      }else{
+        if(!helpl) helpl=++label;
+        cl=0;mr=0;ms=0;
+        for(i=1;i<=32;i++){
+          if(i!=17&&i!=18&&i!=19&&regused[i]&&!regscratch[i]&&!regs[i]) mr=i;
+          if(regs[i]&&regscratch[i]) ms=1;
+        }
+        if(mr==0) mr=t3;
+        if(regs[17]||regs[18]||regs[19]||function_calls==0) ms=1;
+        if(ms) emit(f,"\tlda\t%s,%s%d\n",regnames[mr],labprefix,helpl);
+        if(regs[17]) emit(f,"\tstq\t%s,%d(%s)\n",regnames[17],8*cl++,regnames[mr]);
+        if(regs[18]) emit(f,"\tstq\t%s,%d(%s)\n",regnames[18],8*cl++,regnames[mr]);
+        if(regs[19]) emit(f,"\tstq\t%s,%d(%s)\n",regnames[19],8*cl++,regnames[mr]);
+        a1=18;a2=17;
+        if(p->z.am&&p->z.am->base==18) ierror(0);
+        if(!p->z.am&&(p->z.flags&REG)&&p->z.reg==18) ierror(0);
+      }
+      if(p->q1.flags&DREFOBJ){
+        p->q1.flags&=~DREFOBJ;
+        load_reg(f,a1,&p->q1,POINTER,a1);
+        p->q1.flags|=DREFOBJ;
+      }else{
+        load_address(f,a1,&p->q1,POINTER);
+      }
+      if(p->z.flags&DREFOBJ){
+        p->z.flags&=~DREFOBJ;
+        load_reg(f,a2,&p->z,POINTER,a2);
+        p->z.flags|=DREFOBJ;
+      }else{
+        if(c==PUSH){
+          emit(f,"\tlda\t%s,%ld(%s)\n",regnames[a2],pushed,regnames[sp]);
+          pushed+=zm2l(p->q2.val.vmax);
+        }else{
+          load_address(f,a2,&p->z,POINTER);
+        }
+      }
+      if(salign>=0&&dalign>=0&&(salign&3)==(dalign&3)){
+        int do64,m,s;
+        if((salign&7)==(dalign&7))
+          {do64=1;m=8;s='q';}
+        else
+          {do64=0;m=4;s='l';salign&=3;}
+        if(salign&7){
+          emit(f,"\tld%c\t%s,%d(%s)\n",s,regnames[t3],-salign,regnames[t1]);
+          emit(f,"\tld%c\t%s,%d(%s)\n",s,regnames[t4],-salign,regnames[t2]);
+          cl=(1<<salign)-1;
+          if(!zmleq(l2zm(m-salign),size)) cl+=((1<<(m-salign-zm2l(size)))-1)<<(salign+zm2l(size));
+          emit(f,"\tzap\t%s,%d,%s\n",regnames[t3],cl,regnames[t3]);
+          emit(f,"\tzapnot\t%s,%d,%s\n",regnames[t4],cl,regnames[t4]);
+          emit(f,"\tbis\t%s,%s,%s\n",regnames[t3],regnames[t4],regnames[t3]);
+          emit(f,"\tst%c\t%s,%d(%s)\n",s,regnames[t3],-salign,regnames[t2]);
+          size=zmsub(size,zm2l(m-salign));
+          salign=m-salign;
+        }else
+          salign=0;
+        loops.val.vmax=zmdiv(size,l2zm(8*m));
+        if(zmleq(l2zm(2L),loops.val.vmax)){
+          loops.flags=KONST;
+          loops.am=0;
+          load_reg(f,t3,&loops,LONG,t3);
+          cl=++label;
+          emit(f,"\t.align\t4\n%s%d:\n",labprefix,cl);
+        }
+        if(!zmeqto(loops.val.vmax,l2zm(0))){
+          for(i=0;i<8;i+=2){
+            emit(f,"\tld%c\t%s,%d(%s)\n",s,regnames[t4],salign+i*m,regnames[t1]);
+            emit(f,"\tld%c\t%s,%d(%s)\n",s,regnames[t5],salign+i*m+m,regnames[t1]);
+            emit(f,"\tst%c\t%s,%d(%s)\n",s,regnames[t4],salign+i*m,regnames[t2]);
+            emit(f,"\tst%c\t%s,%d(%s)\n",s,regnames[t5],salign+i*m+m,regnames[t2]);
+          }
+        }
+        if(zmleq(l2zm(2L),loops.val.vmax)){
+          emit(f,"\taddq\t%s,%d,%s\n",regnames[t1],8*m,regnames[t1]);
+          emit(f,"\taddq\t%s,%d,%s\n",regnames[t2],8*m,regnames[t2]);
+          emit(f,"\tsubq\t%s,1,%s\n",regnames[t3],regnames[t3]);
+          emit(f,"\tbne\t%s,%s%d\n",regnames[t3],labprefix,cl);
+        }else{
+          if(!zmeqto(loops.val.vmax,l2zm(0L)))
+            salign+=8*m;
+        }
+        size=zmand(size,l2zm(8*m-1));
+        for(i=0;i<(zm2l(size)/m/2)*2;i+=2){
+          emit(f,"\tld%c\t%s,%d(%s)\n",s,regnames[t4],salign+i*m,regnames[t1]);
+          emit(f,"\tld%c\t%s,%d(%s)\n",s,regnames[t5],salign+i*m+m,regnames[t1]);
+          emit(f,"\tst%c\t%s,%d(%s)\n",s,regnames[t4],salign+i*m,regnames[t2]);
+          emit(f,"\tst%c\t%s,%d(%s)\n",s,regnames[t5],salign+i*m+m,regnames[t2]);
+        }
+        size=zmand(size,l2zm(2*m-1));
+        if(zm2l(size)>=m){
+          emit(f,"\tld%c\t%s,%d(%s)\n",s,regnames[t4],salign+i*m,regnames[t1]);
+          emit(f,"\tst%c\t%s,%d(%s)\n",s,regnames[t4],salign+i*m,regnames[t2]);
+          size=zmsub(size,l2zm(m));i++;
+        }
+        if(zm2l(size)>0){
+          if(zm2l(size)==4){
+            emit(f,"\tldl\t%s,%d(%s)\n",regnames[t4],salign+i*m,regnames[t1]);
+            emit(f,"\tstl\t%s,%d(%s)\n",regnames[t4],salign+i*m,regnames[t2]);
+          }else{
+            emit(f,"\tld%c\t%s,%d(%s)\n",s,regnames[t4],salign+i*m,regnames[t1]);
+            emit(f,"\tld%c\t%s,%d(%s)\n",s,regnames[t5],salign+i*m,regnames[t2]);
+            cl=(1<<zm2l(size))-1;
+            emit(f,"\tzapnot\t%s,%d,%s\n",regnames[t4],cl,regnames[t4]);
+            emit(f,"\tzap\t%s,%d,%s\n",regnames[t5],cl,regnames[t5]);
+            emit(f,"\tbis\t%s,%s,%s\n",regnames[t4],regnames[t5],regnames[t4]);
+            emit(f,"\tst%c\t%s,%d(%s)\n",s,regnames[t4],salign+i*m,regnames[t2]);
+          }
+        }
+        p->z.flags=0; /* to prevent pr() from... */
+        continue;
+      }
+      for(i=1;i<=32;i++){
+        if(i!=17&&i!=18&&i!=19&&regs[i]&&regscratch[i])
+          emit(f,"\tstq\t%s,%d(%s)\n",regnames[i],8*cl++,regnames[mr]);
+      }
+      if(function_calls==0) emit(f,"\tstq\t%s,%d(%s)\n",regnames[lr],8*cl++,regnames[mr]);
+      if(cl>helps) helps=cl;
+      loops.val.vmax=size;
+      loops.flags=KONST;
+      loops.am=0;
+      load_reg(f,19,&loops,LONG,19);
+      emit(f,"\t.global\t%smemcpy\n",idprefix);
+      emit(f,"\tjsr\t%s,%smemcpy\n",regnames[lr],idprefix);
+      emit(f,"\tldgp\t%s,0(%s)\n",regnames[gp],regnames[lr]);
+      cl=0;
+      if(ms&&mr==t3) emit(f,"\tlda\t%s,%s%d\n",regnames[mr],labprefix,helpl);
+      if(regs[17]) emit(f,"\tldq\t%s,%d(%s)\n",regnames[17],8*cl++,regnames[mr]);
+      if(regs[18]) emit(f,"\tldq\t%s,%d(%s)\n",regnames[18],8*cl++,regnames[mr]);
+      if(regs[19]) emit(f,"\tldq\t%s,%d(%s)\n",regnames[19],8*cl++,regnames[mr]);
+      for(i=1;i<=32;i++){
+        if(i!=17&&i!=18&&i!=19&&regs[i]&&regscratch[i])
+          emit(f,"\tldq\t%s,%d(%s)\n",regnames[i],8*cl++,regnames[mr]);
+      }
+      if(function_calls==0) emit(f,"\tldq\t%s,%d(%s)\n",regnames[lr],8*cl++,regnames[mr]);
+      p->z.flags=0;
+      continue;
+    }
+    if(isreg(q1)) wasnoreg=1; else wasnoreg=0;
+    p=do_refs(f,p);
+    c=p->code;
+    if(c==CONVERT){
+      int to;
+      to=p->typf2&NU;
+      if(ISPOINTER(to)) to=(UNSIGNED|LONG);
+      if(ISINT(to)&&ISINT(t)){
+        if((to&NQ)>=(t&NQ)){
+          if((t&NQ)<INT){
+            if(t&UNSIGNED){
+              emit(f,"\tzapnot\t%s,%d,%s\n",regnames[q1reg],(t&NQ)==CHAR?1:3,regnames[zreg]);
+              st[zreg]=EUNS;continue;
+            }else{
+              emit(f,"\tsext%c\t%s,%s\n",(t&NQ)==CHAR?'b':'w',regnames[q1reg],regnames[zreg]);
+              st[zreg]=ESGN;continue;
+            }
+          }
+          zreg=q1reg;
+        }else if((t&NQ)==LONG||(t&NQ)==LLONG){
+          if(to&UNSIGNED)
+            uextend(f,q1reg);
+          else
+            extend(f,q1reg);
+          st[q1reg]=ESGN;
+          zreg=q1reg;
+        }else{
+          if((to&UNSIGNED)==(t&UNSIGNED)){
+            zreg=q1reg;
+          }else{
+            if(to&UNSIGNED){
+              emit(f,"\tzapnot\t%s,%d,%s\n",regnames[q1reg],(t&NQ)==CHAR?1:3,regnames[zreg]);
+              st[zreg]=EUNS;continue;
+            }else{
+              emit(f,"\tsext%c\t%s,%s\n",(t&NQ)==CHAR?'b':'w',regnames[q1reg],regnames[zreg]);
+              st[zreg]=ESGN;continue;
+            }
+          }
+        }
+        continue;
+      }
+      if(ISFLOAT(to)){
+        st[zreg]=ESGN;
+        if(ISFLOAT(t)){
+          emit(f,"\tcvt%c%c\t%s,%s\n",x_t[to&NQ],x_t[t&NQ],regnames[q1reg],regnames[zreg]);
+          continue;
+        }
+/*      if(t&UNSIGNED) ierror(0); */
+        emit(f,"\tcvttqc\t%s,%s\n",regnames[q1reg],regnames[f3]);
+/*      emit(f,"\tftoit\t%s,%s\n",regnames[q1reg],regnames[zreg]);  */
+/*      emit(f,"\t.long\t%ld\n",(0x1cl<<26)+(0x70l<<5)+(31l<<16)+((long)(q1reg-33)<<21)+zreg-1); */
+        emit(f,"\tstt\t%s,%ld(%s)\n",regnames[f3],framesize-addbuf,regnames[sp]);
+        emit(f,"\tldq\t%s,%ld(%s)\n",regnames[zreg],framesize-addbuf,regnames[sp]);
+        st[zreg]=ESGN;
+        continue;
+      }
+      if(ISFLOAT(t)){
+/*      if(to&UNSIGNED) ierror(0); */
+/*      emit(f,"\titoft\t%s,%s\n",regnames[q1reg],regnames[zreg]);  */
+        emit(f,"\tstq\t%s,%ld(%s)\n",regnames[q1reg],framesize-addbuf,regnames[sp]);
+        emit(f,"\tldt\t%s,%ld(%s)\n",regnames[zreg],framesize-addbuf,regnames[sp]);
+        emit(f,"\tcvtq%c\t%s,%s\n",x_t[t&15],regnames[zreg],regnames[zreg]);
+
+        continue;
+      }
+    }
+    if(c==KOMPLEMENT){
+      emit(f,"\tornot\t%s,%s,%s\n",regnames[r31],regnames[q1reg],regnames[zreg]);
+      if((t&NQ)==INT) st[zreg]=0; else st[zreg]=ESGN;
+      continue;
+    }
+    if(c==SETRETURN){
+      if(p->z.reg){
+        if(zreg==0) load_reg(f,p->z.reg,&p->q1,t,t3);
+        extend(f,p->z.reg);
+      }else
+        ierror(0);
+      continue;
+    }
+    if(c==GETRETURN){
+      if(p->q1.reg){
+        zreg=p->q1.reg;
+        st[zreg]=ESGN;
+      }else
+        p->z.flags=0;
+      continue;
+    }
+    if(c==CALL){
+      int reg;
+      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);
+        pushed-=zm2l(p->q2.val.vmax);
+        continue;
+      }
+      if((p->q1.flags&VAR)&&p->q1.v->storage_class==EXTERN&&!(g_flags[6]&USEDFLAG)){
+        char *s=p->q1.v->identifier;
+        if(!strcmp("abs",s)||!strcmp("labs",s)){
+          emit(f,"\tsubq\t%s,%s,%s\n",regnames[r31],regnames[17],regnames[1]);
+          emit(f,"\tcmovge\t%s,%s,%s\n",regnames[17],regnames[17],regnames[1]);
+          continue;
+        }
+        if(!strcmp("fabs",s)){
+          emit(f,"\tfabs\t%s,%s\n",regnames[17],regnames[1]);
+          continue;
+        }
+        if(!strcmp("__va_fixargs",s)){
+          emit(f,"\tlda\t%s,%d(%s)\n",regnames[1],fixargs,regnames[r31]);
+          continue;
+        }
+        if(!strcmp("__va_start",s)){
+          emit(f,"\tlda\t%s,%ld(%s)\n",regnames[1],framesize-(6-fixargs)*16,regnames[sp]);
+          continue;
+        }
+      }
+      for(reg=17;reg<=22;reg++)
+        extend(f,reg);
+      if(q1reg){
+        if(q1reg!=vp) move_reg(f,q1reg,vp);
+        emit(f,"\tjsr\t%s,(%s),0\n",regnames[lr],regnames[vp]);
+      }else{
+        emit(f,"\tjsr\t%s,",regnames[lr]);
+        probj2(f,&p->q1,t);emit(f,"\n");
+      }
+      emit(f,"\tldgp\t%s,0(%s)\n",regnames[gp],regnames[lr]);
+      pushed-=zm2l(p->q2.val.vmax);
+      continue;
+    }
+    if(c==ASSIGN||c==PUSH){
+      if(t==0) ierror(0);
+      if(q1reg){
+        if(c==PUSH){
+          extend(f,q1reg);
+          if((t&NQ)==FLOAT){
+            emit(f,"\tcvtst\t%s,%s\n",regnames[q1reg],regnames[f1]);
+            q1reg=f1;
+	    emit(f,"\tsts\t%s,%ld(%s)\n",regnames[q1reg],pushed,regnames[sp]);
+          }else{
+	    emit(f,"\tst%c\t%s,%ld(%s)\n",q1reg<=32?'q':'t',regnames[q1reg],pushed,regnames[sp]);
+	  }
+          pushed+=8;
+          continue;
+        }
+        if(c==ASSIGN) zreg=q1reg;
+        continue;
+      }else ierror(0);
+    }
+    if(c==ADDRESS){
+      load_address(f,zreg,&p->q1,POINTER);
+      continue;
+    }
+    if(c==MINUS){
+      if(ISINT(t))
+        emit(f,"\tsub%c\t%s,%s,%s\n",x_t[t&NQ],regnames[r31],regnames[q1reg],regnames[zreg]);
+      else
+        emit(f,"\tsub%c\t%s,%s,%s\n",x_t[t&NQ],regnames[f31],regnames[q1reg],regnames[zreg]);
+      st[zreg]=ESGN;
+      continue;
+    }
+    if(c==TEST){
+      if(st[q1reg]==0) extend(f,q1reg);
+      cmpreg=q1reg;
+      cmpflag=0;
+      continue;
+    }
+    if(c==COMPARE){
+      struct IC *br=p->next;
+      while(1){
+        if(br->code>=BEQ&&br->code<BRA) break;
+        if(br->code!=FREEREG) ierror(0);
+        br=br->next;
+      }
+      if(ISFLOAT(t)) cmpreg=f3; else cmpreg=t3;
+      if(br->code==BEQ||br->code==BNE){
+        if((t&NU)==(UNSIGNED|INT)){
+          if(st[q1reg]==ESGN) extend(f,q2reg);
+          else if(st[q2reg]==ESGN) extend(f,q1reg);
+          else if(st[q1reg]==EUNS) uextend(f,q2reg);
+          else if(st[q2reg]==EUNS) uextend(f,q1reg);
+          else {extend(f,q1reg);extend(f,q2reg);}
+        }
+        if((t&NU)==INT){extend(f,q1reg);extend(f,q2reg);}
+        if(ISFLOAT(t)) emit(f,"\tsub%c\t%s,",x_t[t&NQ],regnames[q1reg]);
+          else emit(f,"\tsub%c\t%s,",x_t[t&NQ],regnames[q1reg]);
+        probj2(f,&p->q2,t);emit(f,",%s\n",regnames[cmpreg]);
+        cmpflag=0;st[cmpreg]=ESGN;
+      }else{
+        char *s="";
+        if(t&UNSIGNED) s="u";
+        if((t&NU)==(UNSIGNED|INT)){uextend(f,q1reg);uextend(f,q2reg);}
+        if((t&NU)==INT){extend(f,q1reg);extend(f,q2reg);}
+        if(ISFLOAT(t)) s="t";
+        if(br->code==BLT||br->code==BGE){
+          emit(f,"\tcmp%slt\t%s,",s,regnames[q1reg]);
+          probj2(f,&p->q2,t);emit(f,",%s\n",regnames[cmpreg]);
+          if(br->code==BGE) cmpflag=-1; else cmpflag=1;
+        }else{
+          emit(f,"\tcmp%sle\t%s,",s,regnames[q1reg]);
+          probj2(f,&p->q2,t);emit(f,",%s\n",regnames[cmpreg]);
+          if(br->code==BGT) cmpflag=-1; else cmpflag=1;
+        }
+      }
+      continue;
+    }
+    if(c>=OR&&c<=AND){
+      emit(f,"\t%s\t%s,",logicals[c-OR],regnames[q1reg]);
+      probj2(f,&p->q2,t);emit(f,",%s\n",regnames[zreg]);
+      /* hier ist mehr moeglich */
+      if((t&NQ)==INT) st[zreg]=0; else st[zreg]=ESGN;
+      continue;
+    }
+    if(c>=LSHIFT&&c<=MOD){
+      int xt;
+      if(c==LSHIFT&&(p->q2.flags&KONST)){
+        eval_const(&p->q2.val,t);
+        if(zumeqto(vumax,ul2zum(1UL))){
+          emit(f,"\tadd%c\t%s,%s,%s\n",x_t[t&NQ],regnames[q1reg],regnames[q1reg],regnames[zreg]);
+          st[zreg]=ESGN;continue;
+        }
+        if(zumeqto(vumax,ul2zum(2UL))){
+          emit(f,"\ts4add%c\t%s,0,%s\n",x_t[t&NQ],regnames[q1reg],regnames[zreg]);
+          st[zreg]=ESGN;continue;
+        }
+        if(zumeqto(vumax,ul2zum(3UL))){
+          emit(f,"\ts8add%c\t%s,0,%s\n",x_t[t&NQ],regnames[q1reg],regnames[zreg]);
+          st[zreg]=ESGN;continue;
+        }
+      }
+      if(c==RSHIFT||c==LSHIFT){
+        if(c==RSHIFT){
+          if(t&UNSIGNED){
+            if((t&NQ)<LONG) uextend(f,q1reg);
+            emit(f,"\tsrl\t");
+          }else{
+            extend(f,q1reg);
+            emit(f,"\tsra\t");
+          }
+          st[zreg]=st[q1reg];
+        }else{
+          emit(f,"\tsll\t");
+          if((t&NQ)<=INT) st[zreg]=0; else st[zreg]=ESGN;
+        }
+        emit(f,"%s,",regnames[q1reg]);
+        probj2(f,&p->q2,t);emit(f,",%s\n",regnames[zreg]);
+        continue;
+      }
+      if((c==DIV||c==MOD)&&ISINT(t)){
+        /* Linux-Routinen aufrufen. q1=$24 q2=$25 z=$27 $28 scratch */
+        if(!q1reg) ierror(0);
+        if(q1reg!=25){
+          if(regs[25]) emit(f,"\tstq\t%s,%ld(%s)\n",regnames[25],framesize-addbuf,regnames[sp]);
+          move_reg(f,q1reg,25);
+        }
+        if(q2reg!=26&&regs[26]) emit(f,"\tstq\t%s,%ld(%s)\n",regnames[26],framesize-addbuf+8,regnames[sp]);
+        if(q2reg==25)
+          emit(f,"\tldq\t%s,%ld(%s)\n",regnames[26],framesize-addbuf,regnames[sp]);
+        else
+          load_reg(f,26,&p->q2,t,26);
+        if(zreg!=28&&regs[28]) emit(f,"\tstq\t%s,%ld(%s)\n",regnames[28],framesize-addbuf+16,regnames[sp]);
+        if(regs[29]) emit(f,"\tstq\t%s,%ld(%s)\n",regnames[29],framesize-addbuf+24,regnames[sp]);
+        emit(f,"\t%sq%s\t%s,%s,%s\n",arithmetics[c-LSHIFT],(t&UNSIGNED)?"u":"",regnames[25],regnames[26],regnames[28]);
+        if(zreg!=28) move_reg(f,28,zreg);
+        if(q1reg!=25&&regs[25]) emit(f,"\tldq\t%s,%ld(%s)\n",regnames[25],framesize-addbuf,regnames[sp]);
+        if(q2reg!=26&&regs[26]) emit(f,"\tldq\t%s,%ld(%s)\n",regnames[26],framesize-addbuf+8,regnames[sp]);
+        if(zreg!=28&&regs[28]) emit(f,"\tldq\t%s,%ld(%s)\n",regnames[28],framesize-addbuf+16,regnames[sp]);
+        if(regs[29]) emit(f,"\tldq\t%s,%ld(%s)\n",regnames[29],framesize-addbuf+24,regnames[sp]);
+        /* Was fuer st[zreg]? */
+        continue;
+      }
+      xt=x_t[t&NQ];
+      if((t&NQ)<INT) xt='l';
+      emit(f,"\t%s%c\t%s,",arithmetics[c-LSHIFT],xt,regnames[q1reg]);
+      probj2(f,&p->q2,t);emit(f,",%s\n",regnames[zreg]);
+      st[zreg]=ESGN;
+      continue;
+    }
+    if(c==SUBPFP){
+      emit(f,"\tsubq\t%s,%s,%s\n",regnames[q1reg],regnames[q2reg],regnames[zreg]);
+      st[zreg]=ESGN;continue;
+    }
+    if(c==ADDI2P||c==SUBIFP){
+      if(t&UNSIGNED){
+        if((t&NQ)<LONG) uextend(f,q2reg);
+      }else
+        extend(f,q2reg);
+      if(c==ADDI2P) emit(f,"\taddq\t%s,",regnames[q1reg]);
+      else emit(f,"\tsubq\t%s,",regnames[q1reg]);
+      probj2(f,&p->q2,t);
+      emit(f,",%s\n",regnames[zreg]);
+      st[zreg]=ESGN;continue;
+    }
+    ierror(0);
+  }
+  function_bottom(f,v,zm2l(offset+addbuf),maxpushed);
+  if(debug_info){
+    if(stabs){
+      debug_exit(f,v);
+    }else{
+      emit(f,"%s%d:\n",labprefix,++label);
+      dwarf2_function(f,v,label);
+      if(f) section=-1;    
+    }
+  }  
+}
+
+int shortcut(int code,int typ)
+{
+  return 0;
+}
+
+int reg_parm(struct reg_handle *m, struct Typ *t,int vararg,struct Typ *fkt)
+{
+  int f;
+  f=t->flags&NQ;
+  if(ISINT(f)||ISPOINTER(f)){
+    if(m->nextr>=6) return 0;
+    return 17+m->nextr++;
+  }
+  if(ISFLOAT(f)){
+    if(m->nextr>=6) return 0;
+    return 49+m->nextr++;
+  }
+  return 0;
+}
+void cleanup_cg(FILE *f)
+{
+  struct fpconstlist *p;
+  unsigned char *ip;
+
+  title(f);
+  if(f&&stabs) debug_cleanup(f);
+  while(p=firstfpc){
+    if(f){
+      int t=p->typ&NQ;
+      if(section!=CODE){emit(f,codename);if(f) section=CODE;}
+      emit(f,"\t.align\t3\n%s%d:\n\t",labprefix,p->label);
+      if(ISFLOAT(t)){
+        ip=(unsigned char *)&p->val.vdouble;
+        emit(f,"\t.long\t0x%02x%02x%02x%02x",ip[3],ip[2],ip[1],ip[0]);
+        if((p->typ&NQ)!=FLOAT){
+          emit(f,",0x%02x%02x%02x%02x",ip[7],ip[6],ip[5],ip[4]);
+        }
+      }else{
+        emit(f,"\t.quad\t");
+        emitval(f,&p->val,p->typ);
+      }
+      emit(f,"\n");
+    }
+    firstfpc=p->next;
+    free(p);
+  }
+  if(f&&helps) emit(f,"\t.lcomm\t%s%d,%d\n",labprefix,helpl,helps*8);
+}
+
+void init_db(FILE *f)
+{
+  if(!stabs){
+    dwarf2_setup(sizetab[POINTER],".byte",".2byte",".4byte",".8byte",labprefix,idprefix,".section");
+    dwarf2_print_comp_unit_header(f);
+  }
+} 
+void cleanup_db(FILE *f)
+{
+  if(!stabs&&f)
+    dwarf2_cleanup(f);
+  if(f) section=-1;
+}
diff --git a/machines/alpha/machine.dt b/machines/alpha/machine.dt
new file mode 100755
index 0000000..60cf0b9
--- /dev/null
+++ b/machines/alpha/machine.dt
@@ -0,0 +1,16 @@
+S8BS
+S8BU
+S16BSLE S16BSBE
+S16BULE S16BUBE
+S32BSLE S32BSBE
+S32BULE S32BUBE
+S64BSLE S64BSBE
+S64BULE S64BUBE
+S64BSLE S64BSBE
+S64BULE S64BUBE
+S32BIEEELE
+S64BIEEELE
+S64BIEEELE
+S64BULE S64BUBE
+
+
diff --git a/machines/alpha/machine.h b/machines/alpha/machine.h
new file mode 100755
index 0000000..aa05ba8
--- /dev/null
+++ b/machines/alpha/machine.h
@@ -0,0 +1,70 @@
+/*  Example of a code-generator for a DEC Alpha                     */
+
+#include "dt.h"
+
+/*  This struct can be used to implement machine-specific           */
+/*  addressing-modes.                                               */
+/*  Not used in this code-generrator.                               */
+struct AddressingMode{
+  int flags;
+  int base;
+  int align;
+  long offset;
+};
+
+/*  The number of registers of the target machine.                  */
+#define MAXR 64
+
+/*  Number of commandline-options the code-generator accepts.       */
+#define MAXGF 10
+
+/*  If this is set to zero vbcc will not generate ICs where the     */
+/*  target operand is the same as the 2nd source operand.           */
+/*  This can sometimes simplify the code-generator, but usually     */
+/*  the code is better if the code-generator allows it.             */
+#define USEQ2ASZ 1
+
+/*  This specifies the smallest integer type that can be added to a */
+/*  pointer.                                                        */
+#define MINADDI2P LONG
+
+/*  If the bytes of an integer are ordered most significant byte    */
+/*  byte first and then decreasing set BIGENDIAN to 1.              */
+#define BIGENDIAN 0
+
+/*  If the bytes of an integer are ordered lest significant byte    */
+/*  byte first and then increasing set LITTLEENDIAN to 1.           */
+#define LITTLEENDIAN 1
+
+/*  Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive.    */
+
+/*  If switch-statements should be generated as a sequence of       */
+/*  SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1.      */
+/*  This can yield better code on some machines.                    */
+#define SWITCHSUBS 1
+
+/*  In optimizing compilation certain library memcpy/strcpy-calls   */
+/*  with length known at compile-time will be inlined using an      */
+/*  ASSIGN-IC if the size is less or equal to INLINEMEMCPY.         */
+/*  The type used for the ASSIGN-IC will be UNSIGNED|CHAR.          */
+#define INLINEMEMCPY 1024
+
+/*  Parameters are sometimes passed in registers without __reg.     */
+#define HAVE_REGPARMS 1
+
+/*  Parameters on the stack should be pushed in order rather than   */
+/*  in reverse order.                                               */
+#define ORDERED_PUSH 1
+
+/*  Structure for reg_parm().                                       */
+struct reg_handle{
+    int nextr;
+};
+
+/* size of buffer for asm-output */
+#define EMIT_BUF_LEN 1024 /* should be enough */
+/* number of asm-output lines buffered */
+#define EMIT_BUF_DEPTH 4
+
+/*  We have no asm_peephole to optimize assembly-output */
+#define HAVE_TARGET_PEEPHOLE 0
diff --git a/machines/alpha/schedule.c b/machines/alpha/schedule.c
new file mode 100755
index 0000000..e19e13b
--- /dev/null
+++ b/machines/alpha/schedule.c
@@ -0,0 +1,106 @@
+#include "vsc.h"
+
+char tg_copyright[]="Alpha scheduler V0.0 (c) in 1997 by Volker Barthelmann";
+
+int sched_init(void)
+{
+  return 1;
+}
+void sched_cleanup(void)
+{
+}
+int sched_info(struct sinfo *p)
+{
+  char buf[20];int q1,q2,z,i;
+  if(sscanf(p->txt,"$C%d:",&i)==1){
+    p->label=i;
+    p->flags=LABEL;
+    return 1;
+  }
+  /* lda $r1,imm($r2) */
+  if(sscanf(p->txt,"lda $%d,%d($%d)",&z,&i,&q1)==3){
+    p->latency=1;
+    BSET(p->pipes,0);
+    BSET(p->pipes,1);
+    BSET(p->uses,q1);
+    BSET(p->modifies,z);
+    return 1;
+  }
+  /* lda $r1,... */
+  if(sscanf(p->txt,"lda $%d,",&z)==1){
+    BSET(p->pipes,0);
+    BSET(p->pipes,1);
+    BSET(p->modifies,z);
+    return 1;
+  }
+  /* op $r1,$r2,$r3 */
+  if(sscanf(p->txt,"%19s $%d,$%d,$%d",buf,&q1,&q2,&z)==4){
+    p->latency=1;
+    BSET(p->pipes,0);
+    BSET(p->pipes,1);
+    BSET(p->uses,q1);
+    BSET(p->uses,q2);
+    BSET(p->modifies,z);
+    return 1;
+  }
+  /* op $r1,$r2 */
+  if(sscanf(p->txt,"%19s $%d,$%d",buf,&q1,&z)==3){
+    p->latency=1;
+    BSET(p->pipes,0);
+    BSET(p->pipes,1);
+    BSET(p->uses,q1);
+    BSET(p->modifies,z);
+    return 1;
+  }
+  /* op $r1,imm,$r2 */
+  if(sscanf(p->txt,"%19s $%d,%d,$%d",buf,&q1,&i,&z)==4){
+    p->latency=1;
+    BSET(p->pipes,0);
+    BSET(p->pipes,1);
+    BSET(p->uses,q1);
+    BSET(p->modifies,z);
+    return 1;
+  }
+  /* op $fr1,$fr2,$fr3 */
+  if(sscanf(p->txt,"%19s $f%d,$f%d,$f%d",buf,&q1,&q2,&z)==4){
+    p->latency=1;
+    BSET(p->pipes,2);
+    BSET(p->pipes,3);
+    BSET(p->uses,q1+32);
+    BSET(p->uses,q2+32);
+    BSET(p->modifies,z+32);
+    return 1;
+  }
+  /* load/store $r1,c($r2) */
+  if(sscanf(p->txt,"%19s $%d,%d($%d)",buf,&z,&i,&q1)==4){
+    p->latency=3;
+    BSET(p->pipes,0);
+    BSET(p->uses,q1);
+    if(*buf=='l'){
+      BSET(p->pipes,1);
+      BSET(p->modifies,z);
+      BSET(p->uses,MEM);
+    }else{
+      BSET(p->uses,z);
+      BSET(p->modifies,MEM);
+    }
+    return 1;
+  }
+  /* load/store $fr1,c($r2) */
+  if(sscanf(p->txt,"%19s $f%d,%d($%d)",buf,&z,&i,&q1)==4){
+    p->latency=3;
+    BSET(p->pipes,0);
+    BSET(p->uses,q1);
+    if(*buf=='l'){
+      BSET(p->pipes,1);
+      BSET(p->modifies,z+32);
+      BSET(p->uses,MEM);
+    }else{
+      BSET(p->uses,z+32);
+      BSET(p->modifies,MEM);
+    }
+    return 1;
+  }
+  p->flags=BARRIER;
+  return 1;
+}
diff --git a/machines/alpha/schedule.h b/machines/alpha/schedule.h
new file mode 100755
index 0000000..8603727
--- /dev/null
+++ b/machines/alpha/schedule.h
@@ -0,0 +1,4 @@
+
+#define PIPES 4
+#define REGS 64
+
diff --git a/machines/arm/machine.c b/machines/arm/machine.c
new file mode 100755
index 0000000..1462bef
--- /dev/null
+++ b/machines/arm/machine.c
@@ -0,0 +1,2460 @@
+/*
+ * ARM code generator
+ * A 32-bit RISC with 16 general purpose registers.
+ * Written by Frank Wille <frank@phoenix.owl.de>
+ */
+
+#include "supp.h"
+#include "vbc.h"
+
+static char FILE_[] = __FILE__;
+
+
+/*  Public data that MUST be there.                             */
+
+/* Name and copyright. */
+char cg_copyright[] = "vbcc code-generator for ARM V0.0 (c) in 2006 by Frank Wille";
+
+/* Commandline-flags the code-generator accepts:
+   0: just a flag
+   VALFLAG: a value must be specified
+   STRINGFLAG: a string can be specified
+   FUNCFLAG: a function will be called
+   apart from FUNCFLAG, all other versions can only be specified once */
+int g_flags[MAXGF] = {
+    STRINGFLAG,STRINGFLAG,0,0,0,0,
+    0,0,0,0
+};
+
+/* the flag-name, do not use names beginning with l, L, I, D or U, because
+   they collide with the frontend */
+char *g_flags_name[MAXGF] = {
+    "cpu","fpu","little-endian","big-endian","arm","thumb",
+    "const-in-data","merge-constants","elf","use-commons"
+};
+
+/* the results of parsing the command-line-flags will be stored here */
+union ppi g_flags_val[MAXGF];
+
+/*  Alignment-requirements for all types in bytes.              */
+zmax align[MAX_TYPE+1];
+
+/*  Alignment that is sufficient for every object.              */
+zmax maxalign;
+
+/*  CHAR_BIT for the target machine.                            */
+zmax char_bit;
+
+/*  sizes of the basic 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[MAXR+1] = {
+    "noreg",
+    "r0","r1","r2","r3","r4","r5","r6","r7",
+    "r8","r9","r10","r11","r12","sp","lr","pc",
+    "s0","s1","s2","s3","s4","s5","s6","s7",
+    "s8","s9","s10","s11","s12","s13","s14","s15",
+    "cpsr",
+    "r0/r1","r2/r3","r4/r5","r6/r7","r10/r11",
+    "d0","d1","d2","d3","d4","d5","d6","d7"
+};
+
+/*  The Size of each register in bytes.                         */
+zmax regsize[MAXR+1];
+
+/*  a 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,1,1,0,0,0,0,0,0,0,0,1,0,0,0,  /* r0-r3,r12 */
+    1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,    /* vfp s0-s3 */
+    1,                                  /* cpsr */
+    1,1,0,0,0,                          /* r0/r1, r2/r3 */
+    1,1,0,0,0,0,0,0                     /* vfp d0-d1 */
+};
+
+/* specifies the priority for the register-allocator, if the same
+   estimated cost-saving can be obtained by several registers, the
+   one with the highest priority will be used */
+int reg_prio[MAXR+1] = {
+    0,10,11,12,13,2,3,4,5,6,7,8,9,14,0,1,0,
+    1,2,3,4,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,
+    10,12,2,4,8,
+    1,2,0,0,0,0,0,0
+};
+
+/* an empty reg-handle representing initial state */
+struct reg_handle empty_reg_handle = {0,0};
+
+/* Names of target-specific variable attributes.                */
+char *g_attr_name[] = {
+    "__arm","__thumb","__interrupt","__syscall",0
+};
+#define ARM 1
+#define THUMB 2
+#define INTERRUPT 4
+#define SYSCALL 8
+
+
+/****************************************/
+/*  Private data and functions.         */
+/****************************************/
+
+#define LE_MODE (g_flags[2]&USEDFLAG)
+#define BE_MODE (g_flags[3]&USEDFLAG)
+#define ARM_DEFAULT (g_flags[4]&USEDFLAG)
+#define THUMB_DEFAULT (g_flags[5]&USEDFLAG)
+#define CONST_IN_DATA (g_flags[6]&USEDFLAG)
+#define ELF_LABELS (g_flags[8]&USEDFLAG)
+#define USE_COMMONS (g_flags[9]&USEDFLAG)
+
+int arm_le_mode = 1;          /* defaults to little-endian */
+static int thumb_default = 0; /* we start in ARM mode */
+static int thumb = 0;         /* current mode */
+
+enum {
+  AAANY=0,AA2,AA3,AA3M,AA4,AA4T,AA5,AA5T,AA5TE
+};
+static int aa = AAANY;        /* ARM architecture version */
+
+/* alignment of basic data-types, used to initialize align[] */
+static long malign[MAX_TYPE+1] = {
+    1,1,2,4,4,8,4,8,8,1,4,1,1,1,4,1
+};
+/* sizes of basic data-types, used to initialize sizetab[] */
+static long msizetab[MAX_TYPE+1] = {
+    1,1,2,4,4,8,4,8,8,0,4,0,0,0,4,0
+};
+
+/* used to initialize regtyp[] */
+static struct Typ ltyp  = {LONG};
+static struct Typ lltyp = {LLONG};
+static struct Typ ftyp  = {FLOAT};
+static struct Typ dtyp  = {DOUBLE};
+
+/* macros defined by the backend */
+static char *marray[]={"__section(x,y)=__vattr(\"section(\"#x\",\"#y\")\")",
+                       "__ARM__",
+                       0};
+
+/* special registers */
+static int ip = FIRST_GPR+12;       /* inter-procedural scratch register */
+static int sp = FIRST_GPR+13;       /* stack pointer */
+static int lr = FIRST_GPR+14;       /* link register */
+static int pc = FIRST_GPR+15;       /* program counter */
+static int r0 = FIRST_GPR;
+static int r1 = FIRST_GPR+1;
+
+/* load/store instructions */
+static char *ldts[MAX_TYPE+1] = {
+    "ldr","ldrsb","ldrsh","ldr","ldr","ldr","ldr","ldr","ldr","??","ldr"};
+static char *ldtu[MAX_TYPE+1] = {
+    "ldr","ldrb","ldrh","ldr","ldr","ldr","??","??","??","??","??"};
+static char *sdts[MAX_TYPE+1] = {
+    "str","strb","strh","str","str","str","str","str","str","??","str"};
+static char *sdtu[MAX_TYPE+1] = {
+    "str","strb","strh","str","str","str","??","??","??","??","??"};
+#define ldt(t) ((t&UNSIGNED) ? ldtu[(t)&NQ] : ldts[(t)&NQ])
+#define sdt(t) ((t&UNSIGNED) ? sdtu[(t)&NQ] : sdts[(t)&NQ])
+
+static char *ldstprefix[] = {
+    "ld","st"
+};
+
+static char *dct[] = {
+    "","byte","short","word","word","word","word","word","word"
+};
+
+static char *ccs[] = {
+    "eq","ne","lt","ge","le","gt",""
+};
+
+static char *logicals[] = {
+    "orr","eor","and"
+};
+
+static char *shifts[2][2] = {
+    "lsl","asr","lsl","lsr"
+};
+
+/* sections */
+#define DATA 0
+#define BSS 1
+#define CODE 2
+#define RODATA 3
+#define SPECIAL 4
+
+#if 0
+static long stack;
+static int stack_valid;
+#endif
+static int newobj;
+static int section = -1;
+
+static char *codename = "\t.text\n";
+static char *dataname = "\t.data\n";
+static char *bssname = "";
+static char *rodataname = "\t.rodata\n";
+
+/* list of floating point constants to output at end of file */
+struct fpconstlist {
+  struct fpconstlist *next;
+  int label;
+  int typ;
+  union atyps val;
+};
+static struct fpconstlist *firstfpc = NULL;
+
+/* data reference pointers at the end of each function */
+struct DataRefPtrList {
+  struct DataRefPtrList *next;
+  int label;
+  struct Var *vptr;             /* valid, when label==0 */
+};
+static struct DataRefPtrList *dataptrs = NULL;
+static int drefptr_array_label; /* current array's label */
+
+#define isreg(x) (((x)&(REG|DREFOBJ))==REG)
+#define isconst(x) (((x)&(KONST|DREFOBJ))==KONST)
+
+static int q1reg,q2reg,zreg;
+static struct Var *current_function;
+static int icnt;                /* counts number of lines in cur. function */
+
+#define MAXCODELINES 500        /* emit data-ref. ptr array after that */
+#define MAXCOPYINSTS 4          /* max. nb. of load/store copy-instructions */
+
+/* return-instruction */
+static char *ret;
+
+/* label at the end of the function (if any) */
+static int exit_label;
+
+/* assembly-prefixes for labels and external identifiers */
+static char *labprefix="l";
+static char *idprefix="_";
+
+/* variables to calculate the size and partitioning of the stack-frame */
+static long frameoffset,pushoffs,framesize;
+static int needframe;
+static long localsize,rsavesize,argsize,rsaveoffs,maxrsaveoffs;
+
+
+
+static long real_offset(struct obj *o)
+/* calculate the actual current offset of an object relative to the
+   stack-pointer; we use a layout like this:
+   ------------------------------------------------
+   | stack-arguments to this function             |
+   ------------------------------------------------
+   | caller-save registers [size=rsavesize]       |
+   ------------------------------------------------
+   | local variables [size=localsize]             |
+   ------------------------------------------------
+   | arguments to called functions [size=argsize] |
+   ------------------------------------------------
+   All sizes will be aligned as necessary.
+   The stack-pointer will be adjusted at
+   function-entry to leave enough space for the arguments and have it
+   aligned to 16 bytes. Therefore, when calling a function, the
+   stack-pointer is always aligned to 16 bytes.
+*/
+{
+  long off = zm2l(o->v->offset);
+
+  if (off < 0) {
+    /* function parameter */
+    off = localsize + rsavesize - off - zm2l(maxalign);
+  }
+  else {
+    /* local variable */
+    off += argsize;
+    off += zm2l(o->val.vmax);
+  }
+
+  return off;
+}
+
+
+static struct obj *cam(int flags,int base,long offset)
+/*  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;
+
+#if 0
+  obj.am = &am;
+  am.flags = flags;
+  am.base = base;
+  am.offset = offset;
+#endif
+  return &obj;
+}
+
+
+static int objalign(struct obj *o)
+/* yields the object's lower two bits, 1 when unknown */
+{
+  if (o->flags & DREFOBJ)
+    return 1;
+  if (o->am)
+    ierror(0);
+  if (!(o->flags & VAR))
+    ierror(0);
+
+  if (isstatic(o->v->storage_class) || isextern(o->v->storage_class)) {
+    /* all static data should be 32-bits aligned */
+    return zm2l(zmand(o->val.vmax,l2zm(3L)));
+  }
+
+  if (isauto(o->v->storage_class)) {
+    zmax of = o->v->offset;
+
+    if (!zmleq(l2zm(0L),of))
+      of = zmsub(l2zm(0L),zmadd(of,maxalign));
+    return zm2l(zmand(zmadd(of,o->val.vmax),l2zm(3L)));
+  }
+
+  ierror(0);
+}
+
+
+static void title(FILE *f)
+/* set file symbol with input file name */
+{
+  extern char *inname;
+  static int done;
+
+  if (!done && f) {
+    done = 1;
+    emit(f,"\t.file\t\"%s\"\n",inname);
+  }
+}
+
+
+static void emitnl(FILE *f)
+/* emit a newline character */
+{
+  emit(f,"\n");
+}
+
+
+static void emit_obj(FILE *f,struct obj *p,int t)
+/* prints an object */
+{
+  if (p->flags & VAR) {
+    if (isauto(p->v->storage_class)) {
+      emit(f,"[%s,#%ld]",regnames[sp],real_offset(p));
+    }
+    else {
+      if (!zmeqto(l2zm(0L),p->val.vmax)) {
+        emitval(f,&p->val,LONG);
+        emit(f,"+");
+      }
+      if (isstatic(p->v->storage_class))
+        emit(f,"%s%ld",labprefix,zm2l(p->v->offset));
+      else
+        emit(f,"%s%s",idprefix,p->v->identifier);
+    }
+  }
+
+  if (p->flags & REG) {
+    emit(f,"%s",regnames[p->reg]);
+  }
+
+  if (p->flags & KONST) {
+    emit(f,"#");
+    emitval(f,&p->val,t&NU);
+  }
+}
+
+
+static int special_section(FILE *f,struct Var *v)
+/* changes to a special section, used for __section() */
+{
+  char *sec;
+
+  if (v->vattr) {
+    if (sec = strstr(v->vattr,"section(")) {
+      sec += strlen("section(");
+      emit(f,"\t.section\t");
+      while (*sec && *sec!=')')
+        emit_char(f,*sec++);
+      emitnl(f);
+      if (f)
+        section = SPECIAL;
+      return 1;
+    }
+  }
+  return 0;
+}
+
+
+static int addfpconst(struct obj *o,int t)
+/* return label for a float-constant, create if it didn't exist */
+{
+  struct fpconstlist *p=firstfpc;
+
+  t &= NQ;
+  if (t == LDOUBLE)
+    t = DOUBLE;
+
+  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;
+    }
+  }
+
+  p = mymalloc(sizeof(struct fpconstlist));
+  p->next = firstfpc;
+  p->label = ++label;
+  p->typ = t;
+  p->val = o->val;
+  firstfpc = p;
+
+  return p->label;
+}
+
+
+static void emit_dataptr_array(FILE *f)
+/* emit all data-reference pointers which were collected until now,
+   then reset the array */
+{
+  struct DataRefPtrList *drp,*next;
+
+  if (next = dataptrs) {
+    emit(f,"\t.align\t2\n");
+    emit(f,"%s%d:\n",labprefix,drefptr_array_label);
+
+    while (drp = next) {
+      next = drp->next;
+      emit(f,"\t.%s\t",dct[LONG]);
+      if (drp->label) {
+        emit(f,"%s%d\n",labprefix,drp->label);
+      }
+      else {
+        if (isstatic(drp->vptr->storage_class))
+          emit(f,"%s%ld\n",labprefix,zm2l(drp->vptr->offset));
+        else
+          emit(f,"%s%s\n",idprefix,drp->vptr->identifier);
+      }
+      free(drp);
+    }
+    dataptrs = NULL;
+  }
+  drefptr_array_label = 0;
+}
+
+
+static int cg_getreg(FILE *f,struct IC *ic)
+/* allocate a code generator internal general purpose register */
+{
+  /* alloc_code: 1:compiler, 2:backend, >=4:backend rsave-area offset - 4 */
+  int alloc_code = 2;
+  int i,p,r;
+
+  /* try to get a free scratch-register or a non-volatile
+     register which has to be saved anyway,
+     r12 (ip) is reserved to the backend and will be used as well,
+     r14 (lr) is available when the function builds a stack frame */
+  for (i=FIRST_GPR,p=0,r=0; i<FIRST_GPR+13; i++) {
+    if (((i==ip && regs[i]==1) ||
+         (i==lr && regs[i]==1 && needframe) ||
+         (regs[i]==0 && (regscratch[i] || regused[i]))) &&
+        reg_prio[i]+(regused[i]<<8) > p) {
+      p = reg_prio[i] + (regused[i] << 8);
+      r = i;
+    }
+  }
+  if (!r) {
+    /* seems we have to save a new non-volatile register */
+    for (i=FIRST_GPR,p=0; i<FIRST_GPR+13; i++) {
+      if (regs[i]==0 && reg_prio[i]>p) {
+        p = reg_prio[i];
+        r = i;
+      }
+    }
+  }
+  if (!r) {
+    /* no register available - save one to the stack-frame, but
+       make sure it is not used in this IC */
+    for (i=FIRST_GPR,p=0; i<FIRST_GPR+13; i++) {
+      if (regs[i]<2 && reg_prio[i]>p) {
+        if ((!isreg(ic->q1.flags) || ic->q1.reg!=i) &&
+            (!isreg(ic->q2.flags) || ic->q2.reg!=i) &&
+            (!isreg(ic->z.flags) || ic->z.reg!=i)) {
+          p = reg_prio[i];
+          r = i;
+        }
+      }
+    }
+    if (r) {
+      if (f)
+        emit(f,"\tstr\t%s,[%s,#%ld]\n",
+             regnames[r],regnames[sp],argsize+localsize+rsaveoffs);
+      rsaveoffs += 4;
+      if (rsaveoffs > maxrsaveoffs)
+        maxrsaveoffs = rsaveoffs;
+      alloc_code = rsaveoffs;
+    }
+    else
+      ierror(0);
+  }
+
+  regs[r] = alloc_code;
+  regused[r] = 1;
+  return r;
+}
+
+
+static int cg_getdpreg(FILE *f,struct IC *ic)
+/* allocate a code generator internal double precision FP register */
+{
+  int i,p,r;
+  struct rpair rp;
+
+  /* try to get a free scratch-register or a non-volatile
+     register which has to be saved anyway */
+  for (i=FIRST_DOUBLE,p=0,r=0; i<=LAST_PAIR; i++) {
+    if (regs[i]==0 && (regscratch[i] || regused[i]) &&
+        reg_prio[i]+(regused[i]<<8) > p && reg_pair(i,&rp)) {
+      if (regs[rp.r1]==0 && regs[rp.r2]==0) {
+        p = reg_prio[i] + (regused[i] << 8);
+        r = i;
+      }
+    }
+  }
+  if (!r) {
+    ierror(0); /* @@@ FIXME */
+  }
+
+  regs[r] = 2;
+  regused[r] = 1;
+  if (!reg_pair(i,&rp))
+    ierror(0);
+  regs[rp.r1] = regs[rp.r2] = 2;
+  regused[rp.r1] = regused[rp.r2] = 1;
+  return r;
+}
+
+
+static void cg_restorereg(FILE *f,int r)
+{
+  if (f) {
+    if (r <= LAST_GPR)
+      emit(f,"\tldr\t%s,[%s,#%ld]\n",
+           regnames[r],regnames[sp],argsize+localsize+regs[r]-4);
+    else
+      ierror(0);  /* @@@ FIXME */
+  }
+}
+
+
+static void cg_freereg(FILE *f,int r)
+/* free a code generator internal general purpose register */
+{
+  struct rpair rp;
+
+  if (regs[r] > 1) {
+    if (regs[r] > 2)
+      cg_restorereg(f,r);
+    regs[r] = (r==ip||r==lr) ? 1 : 0;  /* ip/lr need to stay reserved */
+  }
+  else
+    ierror(0);
+
+  if (reg_pair(r,&rp)) {
+    if (regs[rp.r1]>1 && regs[rp.r2]>1) {
+      if (regs[rp.r1] > 2)
+        cg_restorereg(f,rp.r1);
+      if (regs[rp.r2] > 2)
+        cg_restorereg(f,rp.r2);
+      regs[rp.r1] = regs[rp.r2] = 0;
+    }
+    else
+      ierror(0);
+  }
+}
+
+
+static void cg_freeall(FILE *f)
+/* reset internal register allocations */
+{
+  int i;
+
+  for (i=1; i<=MAXR; i++) {
+    if (regs[i] > 1) {
+      if (regs[i] > 2)
+        cg_restorereg(f,i);
+      regs[i] = (i==ip||i==lr) ? 1 : 0;  /* ip/lr need to stay reserved */
+    }
+  }
+  rsaveoffs = 0;
+}
+
+
+static long dataptr_offset(int label,struct obj *o)
+/* return offset into data-reference-pointer array for label l
+   or for object o (mutually exclusive) */
+{
+  long off = 0;
+  struct DataRefPtrList **olddrp = &dataptrs;
+  struct DataRefPtrList *drp = dataptrs;
+
+  if (!label) {
+    if (!(o->flags & VAR))
+      ierror(0);
+    if (!isstatic(o->v->storage_class) && !isextern(o->v->storage_class))
+      ierror(0);
+  }
+
+  /* check if a pointer to this object already exists */
+  while (drp) {
+    if (label) {
+      if (drp->label == label)
+        break;
+    }
+    else {
+      if (drp->vptr == o->v)
+        break;
+    }
+    olddrp = &drp->next;
+    drp = drp->next;
+    off += 4;
+  }
+
+  /* create a new entry if it doesn't exist */
+  if (drp == NULL) {
+    *olddrp = drp = mymalloc(sizeof(struct DataRefPtrList));
+
+    drp->next = NULL;
+    if (drp->label = label)
+      drp->vptr = NULL;
+    else
+      drp->vptr = o->v;
+  }
+
+  return off;
+}
+
+
+static void load_dataptr(FILE *f,int r,int l,struct obj *o)
+/* load data-reference-pointer array entry for label l or object o into r */
+{
+  BSET(regs_modified,r);
+
+  if (!drefptr_array_label)
+    drefptr_array_label = ++label;
+
+  emit(f,"\tldr\t%s,%s%d+%ld\n",
+       regnames[r],labprefix,drefptr_array_label,dataptr_offset(l,o));
+}
+
+
+static void ldst64(FILE *f,int store,struct rpair *rp,int base)
+/* generate a ldmia or stmia (store=1) instruction to transfer a 64-bit
+   value in register pair rp pointed to by base-register base */
+{
+  emit(f,"%smia\t%s,{%s-%s}\n",
+       ldstprefix[store],regnames[base],regnames[rp->r1],regnames[rp->r2]);
+}
+
+
+static void load_address(FILE *f,int r,struct obj *o,int type)
+/*  Generates code to load the address of a variable into register r. */
+{
+  BSET(regs_modified,r);
+
+  if (!(o->flags & VAR))
+    ierror(0);
+
+  if (isauto(o->v->storage_class))
+    emit(f,"\tadd\t%s,%s,#%ld\n",regnames[r],regnames[sp],real_offset(o));
+  else
+    load_dataptr(f,r,0,o);
+}
+
+
+static void load_regindir(FILE *f,struct IC *p,int type,
+                          int dst,int base,long off)
+/*  Load register dst of type type from [base,#off].
+    base and dst may be the same.
+    Perform size extensions as required by architecture. */
+{
+  BSET(regs_modified,dst);
+
+  if (aa >= AA4) {
+    emit(f,"\t%s\t%s,[%s,#%ld]\n",
+         ldt(type),regnames[dst],regnames[base],off);
+  }
+
+  else {
+    /* this requires more effort on older ARMs */
+    int tmp;
+
+    switch (sizetab[type&NQ]) {
+      case 1:
+        emit(f,"\tldrb\t%s,[%s,#%ld]\n",regnames[dst],regnames[base],off);
+        if (!(type & UNSIGNED)) {
+          emit(f,"\tmov\t%s,%s,lsl #24\n",regnames[dst],regnames[dst]);
+          emit(f,"\tmov\t%s,%s,asr #24\n",regnames[dst],regnames[dst]);
+        }
+        break;
+      case 2:
+        tmp = cg_getreg(f,p);
+        emit(f,"\tldrb\t%s,[%s,#%ld]\n",regnames[tmp],regnames[base],
+                                        off+1-arm_le_mode);
+        emit(f,"\tldrb\t%s,[%s,#%ld]\n",regnames[dst],regnames[base],
+                                        off+arm_le_mode);
+        if (!(type & UNSIGNED)) {
+          emit(f,"\tmov\t%s,%s,lsl #24\n",regnames[dst],regnames[dst]);
+          emit(f,"\torr\t%s,%s,%s asr #16\n",
+               regnames[dst],regnames[tmp],regnames[dst]);
+        }
+        else {
+          emit(f,"\torr\t%s,%s,%s lsl #8\n",
+               regnames[dst],regnames[tmp],regnames[dst]);
+        }
+        cg_freereg(f,tmp);
+        break;
+      case 4:
+        emit(f,"\tldr\t%s,[%s,#%ld]\n",regnames[dst],regnames[base],off);
+        break;
+      default:
+        ierror(0);
+    }
+  }
+}
+
+
+static void load_reg(FILE *f,struct IC *p,int r,struct obj *o,int type)
+/* Generates code to load a memory object into register r. */
+{
+  type &= NU;
+  BSET(regs_modified,r);
+
+  if (o->flags & KONST) {
+    /* evaluate and load a constant */
+
+    eval_const(&o->val,type);
+
+    if (ISFLOAT(type)) {
+      int lab = addfpconst(o,type);
+
+      load_dataptr(f,r,lab,NULL);
+      if (type == FLOAT)
+        load_regindir(f,p,type,r,r,0);
+      else
+        ierror(0);  /* double can only be in a register-pair */
+    }
+
+    else {
+      /* integer constant */
+      emit(f,"\tmov\t%s,",regnames[r]);
+      emit_obj(f,o,type);
+      emitnl(f);
+    }
+  }
+
+  else if (isreg(o->flags)) {
+    if (r != o->reg)
+      emit(f,"\tmov\t%s,%s\n",regnames[r],regnames[o->reg]);
+  }
+
+  else if ((o->flags & (REG|DREFOBJ)) == (REG|DREFOBJ)) {
+    load_regindir(f,p,type,r,o->reg,0);
+  }
+
+  else if (o->flags & VAR) {
+    if (isstatic(o->v->storage_class) || isextern(o->v->storage_class)) {
+      /* load from a static variable */
+      if (o->flags & VARADR) {
+        load_address(f,r,o,POINTER);
+      }
+      else {
+        load_dataptr(f,r,0,o);
+        load_regindir(f,p,type,r,r,zm2l(o->val.vmax));
+      }
+    }
+    else {
+      /* dynamic variable on stack */
+      load_regindir(f,p,type,r,sp,real_offset(o));
+    }
+  }
+
+  else
+    ierror(0);
+}
+
+
+static void store_regindir(FILE *f,struct IC *p,int type,
+                           int src,int base,long off)
+/*  Store register src of type type to [base,#off]. */
+{
+  if (aa>=AA4 || sizetab[type&NQ]!=2) {
+    emit(f,"\t%s\t%s,[%s,#%ld]\n",
+         sdt(type),regnames[src],regnames[base],off);
+  }
+
+  else {
+    /* storing halfwords requires more effort on older ARMs */
+    int tmp = cg_getreg(f,p);
+
+    emit(f,"\tstrb\t%s,[%s,#%ld]\n",regnames[src],regnames[base],
+                                    off+1-arm_le_mode);
+    emit(f,"\tmov\t%s,%s,asr #8\n",regnames[tmp],regnames[src]);
+    emit(f,"\tstrb\t%s,[%s,#%ld]\n",regnames[src],regnames[base],
+                                    off+arm_le_mode);
+    cg_freereg(f,tmp);
+  }
+}
+
+
+static void store_reg(FILE *f,struct IC *p,int r,struct obj *o,int type)
+/* Generates code to store register r into memory object o. */
+{
+  if (isreg(o->flags)) {
+    if (r != o->reg)
+      emit(f,"\tmov\t%s,%s\n",regnames[o->reg],regnames[r]);
+  }
+
+  else if ((o->flags & (REG|DREFOBJ)) == (REG|DREFOBJ)) {
+    store_regindir(f,p,type,r,o->reg,0);
+  }
+
+  else if (o->flags & VAR) {
+    if (isstatic(o->v->storage_class) || isextern(o->v->storage_class)) {
+      /* store to a static variable */
+      int tmp = cg_getreg(f,p);
+
+      load_dataptr(f,tmp,0,o);
+      store_regindir(f,p,type,r,tmp,zm2l(o->val.vmax));
+      cg_freereg(f,tmp);
+    }
+    else {
+      /* dynamic variable on stack */
+      store_regindir(f,p,type,r,sp,real_offset(o));
+    }
+  }
+
+  else
+    ierror(0);
+}
+
+
+static int load_objptr(FILE *f,struct IC *p,struct obj *o)
+/* Make sure object o can be dereferenced by a single load.
+   Return new base register, or 0 if object was not modified. */
+{
+  if ((o->flags & (REG|DREFOBJ)) == DREFOBJ) {
+    int r = cg_getreg(f,p);
+
+    load_reg(f,p,r,o,POINTER);
+    o->flags |= REG;
+    o->reg = r;
+    return r;
+  }
+
+  if ((o->flags & (VAR|REG)) == VAR) {
+    if (isstatic(o->v->storage_class) || isextern(o->v->storage_class)) {
+      int r = cg_getreg(f,p);
+
+      load_dataptr(f,r,0,o);
+      o->reg = r;
+      o->flags = REG|DREFOBJ;
+      return r;
+    }
+  }
+
+  return 0;
+}
+
+
+static void load_regpair(FILE *f,struct IC *p,struct rpair *rp,
+                         struct obj *o,int type)
+/* Generates code to load a memory object into the register pair rp.
+   tmp is a general purpose register which may be used. */
+{
+  BSET(regs_modified,rp->r1);
+  BSET(regs_modified,rp->r2);
+
+  if (o->flags & KONST) {
+    /* evaluate and load a constant */
+    eval_const(&o->val,type);
+
+    if (ISFLOAT(type)) {
+      int lab = addfpconst(o,type);
+      int tmp = cg_getreg(f,p);
+
+      load_dataptr(f,tmp,lab,NULL);
+      if (type != FLOAT)
+        ldst64(f,0,rp,tmp);
+      else
+        ierror(0);  /* have to load float in a single register */
+      cg_freereg(f,tmp);
+    }
+    else {
+      struct obj cobj;
+
+      cobj.flags = KONST;
+      cobj.val.vulong = zum2zul(zumand(vumax,ul2zum(0xffffffff))); 
+      load_reg(f,p,arm_le_mode?rp->r1:rp->r2,&cobj,UNSIGNED|LONG);
+      cobj.val.vulong = zum2zul(zumand(zumrshift(vumax,ul2zum(32UL)),
+                                       ul2zum(0xffffffff)));
+      load_reg(f,p,arm_le_mode?rp->r2:rp->r1,&cobj,UNSIGNED|LONG);
+    }
+  }
+
+  else {
+    /* make sure that object can be addressed through a register */
+    load_objptr(f,p,o);
+
+    if (isreg(o->flags)) {
+      struct rpair qrp;
+
+      if (!reg_pair(o->reg,&qrp))
+        ierror(0);
+      if (qrp.r1 != rp->r1) {
+        emit(f,"\tmov\t%s,%s\n\tmov\t%s,%s\n",regnames[rp->r1],
+             regnames[qrp.r1],regnames[rp->r2],regnames[qrp.r2]);
+      }
+    }
+    else if ((o->flags & (REG|DREFOBJ)) == (REG|DREFOBJ)) {
+      ldst64(f,0,rp,o->reg);
+    }
+    else
+      ierror(0);
+  }
+}
+
+
+static void store_regpair(FILE *f,struct IC *p,struct rpair *rp,
+                          struct obj *o,int type)
+/* Generates code to store the register pair rp into memory object o.
+   tmp is a general purpose register which may be used. */
+{
+  /* make sure that object can be addressed through a register */
+  load_objptr(f,p,o);
+
+  if (isreg(o->flags)) {
+    struct rpair zrp;
+
+    if (!reg_pair(o->reg,&zrp))
+      ierror(0);
+    if (zrp.r1 != rp->r1) {
+      emit(f,"\tmov\t%s,%s\n\tmov\t%s,%s\n",regnames[zrp.r1],
+           regnames[rp->r1],regnames[zrp.r2],regnames[rp->r2]);
+    }
+  }
+  else if ((o->flags & (REG|DREFOBJ)) == (REG|DREFOBJ)) {
+    ldst64(f,1,rp,o->reg);
+  }
+  else
+    ierror(0);
+}
+
+
+static long pof2(zumax x)
+/* yields log2(x)+1 or 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 struct IC *preload(FILE *f,struct IC *p)
+/* Does some pre-processing like fetching operands from memory to
+   registers etc. */
+/* @@@ FIXME - Is this function needed at all ??? */
+{
+#if 0
+  if (isreg(p->q1.flags))
+    q1reg = p->q1.reg;
+  else
+    q1reg = 0;
+
+  if (isreg(p->q2.flags))
+    q2reg = p->q2.reg;
+  else
+    q2reg = 0;
+#endif
+
+  if (isreg(p->z.flags)) {
+    zreg = p->z.reg;
+  }
+  else {
+    if (ISFLOAT(ztyp(p)))
+      zreg = FIRST_PAIR;  /* @@@ VFP? ->f1 */
+    else
+      zreg = cg_getreg(f,p);
+  }
+  
+#if 0  /* Better use load_objptr() when needed? */
+  if ((p->q1.flags & (REG|DREFOBJ)) == DREFOBJ) {
+    int tmp = cg_getreg(f,p);
+
+    p->q1.flags &= ~DREFOBJ;
+    load_reg(f,p,tmp,&p->q1,q1typ(p));
+    p->q1.reg = tmp;
+    p->q1.flags |= REG|DREFOBJ;
+  }
+
+  if ((p->q2.flags & (REG|DREFOBJ)) == DREFOBJ) {
+    int tmp = cg_getreg(f,p);
+
+    p->q2.flags &= ~DREFOBJ;
+    load_reg(f,p,tmp,&p->q2,q2typ(p));
+    p->q2.reg = tmp;
+    p->q2.flags |= REG|DREFOBJ;
+  }
+#endif
+
+  return p;
+}
+
+
+static void save_result(FILE *f,struct IC *p)
+/* save the result (in zreg) into p->z */
+{
+  if ((p->z.flags&(REG|DREFOBJ)) == DREFOBJ) {
+    int tmp = cg_getreg(f,p);
+
+    p->z.flags &= ~DREFOBJ;
+    load_reg(f,p,tmp,&p->z,POINTER);
+    p->z.reg = tmp;
+    p->z.flags |= REG|DREFOBJ;
+  }
+  if (isreg(p->z.flags)) {
+    if (p->z.reg != zreg)
+      emit(f,"\tmov\t%s,%s\n",regnames[p->z.reg],regnames[zreg]);
+  }
+  else {
+    store_reg(f,p,zreg,&p->z,ztyp(p));
+  }
+}
+
+
+static void registerize(FILE *f,struct IC *p,struct obj *o,int t)
+/* make sure object is loaded into a register */
+{
+  if (!(isreg(o->flags))) {
+    int r;
+
+    r = load_objptr(f,p,o);
+    if (!r)
+      r = cg_getreg(f,p);
+    if ((o->flags & (REG|DREFOBJ)) == DREFOBJ)
+      ierror(0);
+    load_reg(f,p,r,o,t);
+    o->reg = r;
+  }
+  o->flags = REG;
+}
+
+
+static void cg_memcopy(FILE *f,struct IC *p)
+/* generates code to copy an object of non-elementary type (ARRAY, STRUCT) */
+{
+  unsigned long size = opsize(p);
+  int a1 = objalign(&p->q1);
+  int a2 = (p->code==ASSIGN) ? objalign(&p->z) : 0;
+  int b = 1;
+  char *ld = ldt(CHAR);
+  char *st = sdt(CHAR);
+  unsigned long l;
+  int srcreg,dstreg,tmpreg,cntreg,ncp;
+
+  if (p->q1.flags & VAR) {
+    if (p->q1.flags & DREFOBJ) {
+      if (p->q1.v->vtyp->next &&
+          zmeqto(p->q2.val.vmax,szof(p->q1.v->vtyp->next)) && (a1&1)) {
+        a1 = zm2l(falign(p->q1.v->vtyp->next)) & 3;
+        a2 &= a1;
+      }
+    }
+    else {
+      if (zmeqto(p->q2.val.vmax,szof(p->q1.v->vtyp)) && (a1&1)) {
+        a1 = zm2l(falign(p->q1.v->vtyp)) & 3;
+        a2 &= a1;
+      }
+    }
+  }
+  if (p->z.flags & VAR) {
+    if (p->z.flags & DREFOBJ) {
+      if (p->z.v->vtyp->next &&
+          zmeqto(p->q2.val.vmax,szof(p->z.v->vtyp->next)) && (a2&1)) {
+        a2 = zm2l(falign(p->z.v->vtyp->next)) & 3;
+        a1 &= a2;
+      }
+    }
+    else {
+      if (zmeqto(p->q2.val.vmax,szof(p->z.v->vtyp)) && (a2&1)) {
+        a2 = zm2l(falign(p->z.v->vtyp)) & 3;
+        a1 &= a2;
+      }
+    }
+  } 
+
+  /* @@@ implement with ldmia/stmia */
+  if (a1>=0 && a2>=0) {
+    if (a1==0 && a2==0) {
+      /* 32-bit copy */
+      b = 4;
+      ld = ldt(LONG);
+      st = sdt(LONG);
+    }
+    else if ((a1&1)==0 && (a2&1)==0 && aa>=AA4) {
+      /* 16-bit copy for ARM-architecture 4 and better only */
+      b = 2;
+      ld = ldt(SHORT);
+      st = sdt(SHORT);
+    }
+  }
+
+  srcreg = cg_getreg(f,p);
+  BSET(regs_modified,srcreg);
+
+  if (p->q1.flags & DREFOBJ) {
+    p->q1.flags &= ~DREFOBJ;
+    if (isreg(p->q1.flags))
+      emit(f,"\tmov\t%s,%s\n",regnames[srcreg],regnames[p->q1.reg]);
+    else
+      load_reg(f,p,srcreg,&p->q1,POINTER);
+    p->q1.flags |= DREFOBJ;
+  }
+  else {
+    load_address(f,srcreg,&p->q1,POINTER);
+  }
+
+  dstreg = cg_getreg(f,p);
+  BSET(regs_modified,dstreg);
+
+  if (p->z.flags & DREFOBJ) {
+    p->z.flags &= ~DREFOBJ;
+    if (isreg(p->z.flags))
+      emit(f,"\tmov\t%s,%s\n",regnames[dstreg],regnames[p->z.reg]);
+    else
+      load_reg(f,p,dstreg,&p->z,POINTER);
+    p->z.flags |= DREFOBJ;
+  }
+  else {
+    if (p->code == PUSH) {
+      emit(f,"\tadd\t%s,%s,#%ld\n",regnames[dstreg],regnames[sp],pushoffs);
+      pushoffs += size;
+    }
+    else
+      load_address(f,dstreg,&p->z,POINTER);
+  }
+
+  tmpreg = cg_getreg(f,p);
+  BSET(regs_modified,tmpreg);
+  l = size/b;
+
+  if (l > MAXCOPYINSTS) { /* @@@ make MAXCOPYINSTS changeable by an option? */
+    cntreg = cg_getreg(f,p);
+    BSET(regs_modified,cntreg);
+    emit(f,"\tmov\t%s,#%lu\n",regnames[cntreg],l);
+    emit(f,"%s%d:\n",labprefix,++label);
+    ncp = 1;
+  }
+  else
+    ncp = l;
+  while (ncp--) {
+    emit(f,"\t%s\t%s,[%s],#%d\n",ld,regnames[tmpreg],regnames[srcreg],b);
+    emit(f,"\t%s\t%s,[%s],#%d\n",st,regnames[tmpreg],regnames[dstreg],b);
+  }
+  if (l > MAXCOPYINSTS) {
+    emit(f,"\tsubs\t%s,%s,#1\n",regnames[cntreg],regnames[cntreg]);
+    emit(f,"\tbne\t%s%d\n",labprefix,label);
+    cg_freereg(f,cntreg);
+  }
+
+  size = size % b;
+  ncp = 0;
+  if (size & 2) {
+    if (aa >= AA4) {
+      emit(f,"\t%s\t%s,[%s],#%d\n",ldt(SHORT),regnames[tmpreg],regnames[srcreg],b);
+      emit(f,"\t%s\t%s,[%s],#%d\n",sdt(SHORT),regnames[tmpreg],regnames[dstreg],b);
+    }
+    else
+      ncp = 2;
+  }
+  ncp += (size & 1);
+  while (ncp--) {
+    emit(f,"\t%s\t%s,[%s],#%d\n",ldt(CHAR),regnames[tmpreg],regnames[srcreg],b);
+    emit(f,"\t%s\t%s,[%s],#%d\n",sdt(CHAR),regnames[tmpreg],regnames[dstreg],b);
+  }
+}
+
+
+static int exists_freereg(struct IC *p,int reg)
+/*  Test if there is a sequence of FREEREGs containing FREEREG reg.
+    Used by peephole(). */
+{
+  while (p && (p->code==FREEREG || p->code==ALLOCREG)) {
+    if (p->code==FREEREG && p->q1.reg==reg)
+      return 1;
+    p=p->next;
+  }
+  return 0;
+}
+
+
+#if 0
+static void peephole(struct IC *p)
+/* search for possible addressing-modes */
+{
+  int c,c2,r;struct IC *p2;struct AddressingMode *am;
+
+  for(;p;p=p->next){
+    c=p->code;
+    if(c!=FREEREG&&c!=ALLOCREG&&(c!=SETRETURN||!isreg(p->q1.flags)||p->q1.reg!=p->z.reg)) exit_label=0;
+    if(c==LABEL) exit_label=p->typf;
+
+    /* Try const(reg) */
+    if(IMM_IND&&(c==ADDI2P||c==SUBIFP)&&isreg(p->z.flags)&&isconst(p->q2.flags)){
+      int base;zmax of;struct obj *o;
+      eval_const(&p->q2.val,p->typf);
+      if(c==SUBIFP) of=zmsub(l2zm(0L),vmax); else of=vmax;
+      if(1/*zmleq(l2zm(-32768L),vmax)&&zmleq(vmax,l2zm(32767L))*/){
+        r=p->z.reg;
+        if(isreg(p->q1.flags)) 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&&isreg(p2->q1.flags)&&p2->q1.reg==r) break;
+          if(c2!=FREEREG&&isreg(p2->q2.flags)&&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) break;
+              o=&p2->q1;
+            }
+            if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
+              if(o) break;
+              o=&p2->q2;
+            }
+            if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
+              if(o) break;
+              o=&p2->z;
+            }
+          }
+          if(c2==FREEREG||isreg(p2->z.flags)){
+            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);
+                if(isreg(p->q1.flags)){
+                  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;
+          }
+        }
+      }
+    }
+    /* Try reg,reg */
+    if(GPR_IND&&c==ADDI2P&&isreg(p->q2.flags)&&isreg(p->z.flags)&&(isreg(p->q1.flags)||p->q2.reg!=p->z.reg)){
+      int base,idx;struct obj *o;
+      r=p->z.reg;idx=p->q2.reg;
+      if(isreg(p->q1.flags)) 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&&isreg(p2->q1.flags)&&p2->q1.reg==r) break;
+        if(c2!=FREEREG&&isreg(p2->q2.flags)&&p2->q2.reg==r) break;
+        if(isreg(p2->z.flags)&&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||(q1typ(p2)&NQ)==LLONG) break;
+            o=&p2->q1;
+          }
+          if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
+            if(o||(q2typ(p2)&NQ)==LLONG) break;
+            o=&p2->q2;
+          }
+          if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
+            if(o||(ztyp(p2)&NQ)==LLONG) break;
+            o=&p2->z;
+          }
+        }
+        if(c2==FREEREG||isreg(p2->z.flags)){
+          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=GPR_IND;
+              am->base=base;
+              am->offset=idx;
+              if(isreg(p->q1.flags)){
+                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;
+        }
+      }
+    }
+  }
+}
+#endif
+
+
+static void function_top(FILE *f,struct Var *v,long offset)
+/* generates the function entry code */
+{
+  static char ret_instr[64];
+  char gprsave[32];
+  char *p;
+  int i;
+
+  title(f);
+
+  /* determine rsavesize and registers to save */
+  rsavesize = 0;
+  gprsave[0] = '\0';
+  for (i=FIRST_GPR,p=gprsave; i<=LAST_GPR; i++) {
+    if (!regsa[i] && !regscratch[i] && regused[i]) {
+      p += sprintf(p,"%s,",regnames[i]);
+      rsavesize += 4;
+    }
+  }
+
+  if (!special_section(f,v) && section!=CODE) {
+    emit(f,codename);
+    section = CODE;
+  } 
+
+  if (isextern(v->storage_class)) {
+    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));
+
+  if (rsavesize==0 && !needframe) {
+    ret = "\tmov\tpc,lr\n";
+  }
+  else {
+    rsavesize += 3*4;  /* sp,lr,pc to be saved as well */
+    emit(f,"\tstmfd\t%s!,{%s%s,%s,%s}\n",
+         regnames[sp],gprsave,regnames[sp],regnames[lr],regnames[pc]);
+    sprintf(ret_instr,"\tldmfd\t%s,{%s%s,%s}\n",
+            regnames[sp],gprsave,regnames[sp],regnames[pc]);
+    ret = ret_instr;
+    if (localsize+argsize > 0) {
+      emit(f,"\tsub\t%s,%s,#%ld\n",
+           regnames[sp],regnames[sp],localsize+argsize);
+    }
+  }
+}
+
+
+static void function_bottom(FILE *f,struct Var *v,long offset)
+/* generates the function exit code */
+{
+  if (localsize+argsize > 0) {
+    emit(f,"\tadd\t%s,%s,#%ld\n",
+         regnames[sp],regnames[sp],localsize+argsize);
+  }
+  emit(f,ret);
+  emit_dataptr_array(f);
+
+  if (isextern(v->storage_class)) {
+    emit(f,"\t.type\t%s%s,@function\n",idprefix,v->identifier);
+    emit(f,"\t.size\t%s%s,.-%s%s\n\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\n",
+         labprefix,zm2l(v->offset),labprefix,zm2l(v->offset));
+  }    
+
+  /*if(all_regs&&v->fi) v->fi->flags|=ALL_REGS;*/
+}
+
+
+/****************************************/
+/*  End of private data 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;
+
+  /*  Initialize some values which cannot be statically initialized   */
+  /*  because they are stored in the target's arithmetic.             */
+  maxalign = l2zm(8L);
+  stackalign = l2zm(4L);
+  char_bit = l2zm(8L);
+
+  for (i=0; i<=MAX_TYPE; i++) {
+    sizetab[i] = l2zm(msizetab[i]);
+    align[i] = l2zm(malign[i]);
+  }
+
+  for (i=FIRST_GPR; i<=LAST_GPR; i++) {
+    regsize[i] = l2zm(4L);
+    regtype[i] = &ltyp;
+  }
+
+  for (i=FIRST_FPR; i<=LAST_FPR; i++) {
+    regsize[i] = l2zm(8L);
+    regtype[i] = &ftyp;
+  }
+
+  for (i=FIRST_CCR; i<=LAST_CCR; i++) {
+    regsize[i] = l2zm(4L);
+    regtype[i] = &ltyp;
+  }
+
+  for (i=FIRST_PAIR; i<FIRST_DOUBLE; i++) {
+    regsize[i] = l2zm(8L);
+    regtype[i] = &lltyp;
+  }
+
+  for (i=FIRST_DOUBLE; i<=LAST_PAIR; i++) {
+    regsize[i] = l2zm(8L);
+    regtype[i] = &dtyp;
+  }
+
+  /*  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.          */
+  t_min[CHAR] = l2zm(-128L);
+  t_min[SHORT] = l2zm(-32768L);
+  t_min[INT] = zmsub(l2zm(-2147483647L),l2zm(1L));
+  t_min[LONG] = t_min(INT);
+  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] = ul2zum(2147483647UL);
+  t_max[LONG] = t_max(INT);
+  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] = ul2zum(4294967295UL);
+  tu_max[LONG] = t_max(UNSIGNED|INT);
+  tu_max[LLONG] = zumkompl(ul2zum(0UL));
+  tu_max[MAXINT] = t_max(UNSIGNED|LLONG);
+
+  /*  Reserve a few registers for use by the code-generator.      */
+  regsa[ip] = regsa[sp] = regsa[lr] = regsa[pc] = 1;
+  regscratch[ip] = regscratch[sp] = regscratch[lr] = regscratch[pc] = 0;
+
+  if (LE_MODE)
+    arm_le_mode = 1;
+  if (BE_MODE)
+    arm_le_mode = 0;
+  if (ARM_DEFAULT)
+    thumb_default = 0;
+  if (THUMB_DEFAULT)
+    thumb_default = 1;
+  if (ELF_LABELS) {
+    labprefix = ".l";
+    idprefix = "";
+  }
+
+  target_macros = marray;
+
+
+  /* TODO: set argument registers */
+  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;
+}
+
+
+void init_db(FILE *f)
+{
+}
+
+
+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.        */
+/*  A pointer MUST be returned in a register. The code-generator    */
+/*  has to simulate a pseudo register if necessary.                 */
+{
+  int tu = t->flags&NQ;
+
+  /* @@@ handle VFP */
+
+  if (tu==LLONG || tu==DOUBLE)
+    return FIRST_PAIR;
+
+  if (zmleq(szof(t),l2zm(4L)))
+    return FIRST_GPR;
+
+  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<FIRST_PAIR || r>LAST_PAIR)
+    return 0;
+
+  switch (r) {
+    case FIRST_PAIR:
+      p->r1 = FIRST_GPR;
+      p->r2 = FIRST_GPR+1;
+      return 1;
+    case FIRST_PAIR+1:
+      p->r1 = FIRST_GPR+2;
+      p->r2 = FIRST_GPR+3;
+      return 1;
+    case FIRST_PAIR+2:
+      p->r1 = FIRST_GPR+4;
+      p->r2 = FIRST_GPR+5;
+      return 1;
+    case FIRST_PAIR+3:
+      p->r1 = FIRST_GPR+6;
+      p->r2 = FIRST_GPR+7;
+      return 1;
+    case FIRST_PAIR+4:
+      p->r1 = FIRST_GPR+10;
+      p->r2 = FIRST_GPR+11;
+      return 1;
+    case FIRST_DOUBLE:
+      p->r1 = FIRST_FPR;
+      p->r2 = FIRST_FPR+1;
+      return 1;
+    case FIRST_DOUBLE+1:
+      p->r1 = FIRST_FPR+2;
+      p->r2 = FIRST_FPR+3;
+      return 1;
+    case FIRST_DOUBLE+2:
+      p->r1 = FIRST_FPR+4;
+      p->r2 = FIRST_FPR+5;
+      return 1;
+    case FIRST_DOUBLE+3:
+      p->r1 = FIRST_FPR+6;
+      p->r2 = FIRST_FPR+7;
+      return 1;
+    case FIRST_DOUBLE+4:
+      p->r1 = FIRST_FPR+8;
+      p->r2 = FIRST_FPR+9;
+      return 1;
+    case FIRST_DOUBLE+5:
+      p->r1 = FIRST_FPR+10;
+      p->r2 = FIRST_FPR+11;
+      return 1;
+    case FIRST_DOUBLE+6:
+      p->r1 = FIRST_FPR+12;
+      p->r2 = FIRST_FPR+13;
+      return 1;
+    case FIRST_DOUBLE+7:
+      p->r1 = FIRST_FPR+14;
+      p->r2 = FIRST_FPR+15;
+      return 1;
+    default:
+      ierror(0);
+  }
+
+  return 0;
+}
+
+
+int cost_savings(struct IC *p,int r,struct obj *o)
+/* estimate the cost-saving if object o from IC p is placed in */
+/* register r                                                  */
+{
+  int c = p->code;
+
+  /* @@@ FIXME */
+  if (o->flags & VKONST) {
+    if (o==&p->q1 && p->code==ASSIGN && (p->z.flags&DREFOBJ))
+      return 4;
+    else
+      return 2;
+  }
+  if (o->flags & DREFOBJ)
+    return 4;
+  if (c==SETRETURN && r==p->z.reg && !(o->flags&DREFOBJ))
+    return 3;
+  if (c==GETRETURN && r==p->q1.reg && !(o->flags&DREFOBJ))
+    return 3;
+  return 2;
+}
+
+
+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 (r==0)
+    return 0;
+
+  if (t==0 && r>=FIRST_CCR && r<=LAST_CCR)
+    return 1;
+
+  t &= NQ;
+
+  if (ISFLOAT(t)) {
+    /* @@@ handle VFP */
+    if (t==FLOAT && r>=FIRST_GPR && r<=LAST_GPR)
+      return 1;
+    else if (r>=FIRST_PAIR && r<=LAST_PAIR)
+      return 1;
+  }
+  else if (t==POINTER && r>=FIRST_GPR && r<=LAST_GPR)
+    return 1;
+  else if (t>=CHAR && t<=LONG && r>=FIRST_GPR && r<=LAST_GPR)
+    return 1;
+  else if (t==LLONG && r>=FIRST_PAIR && r<=LAST_PAIR)
+    return 1;
+
+  return 0;
+}
+
+
+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             */
+{
+  if ((p->q1.flags&DREFOBJ) || (p->q2.flags&DREFOBJ) || (p->z.flags&DREFOBJ))
+    return 1;
+  /* ARM has no division/modulo instructions */
+  return 0;
+}
+
+
+int must_convert(int o,int t,int const_expr)
+/*  Returns zero if code for converting np to type t    */
+/*  can be omitted.                                     */
+/*  On the PowerPC cpu pointers and 32bit               */
+/*  integers have the same representation and can use   */
+/*  the same registers.                                 */
+{
+  int op = o & NQ;
+  int tp = t & NQ;
+
+  if ((op==INT||op==LONG||op==POINTER) && (tp==INT||tp==LONG||tp==POINTER))
+    return 0;
+  if (op==DOUBLE && tp==LDOUBLE)
+    return 0;
+  if (op==LDOUBLE && tp==DOUBLE)
+    return 0;
+  if(op==tp)
+    return 0;
+  return 1;
+}
+
+
+char *use_libcall(int c,int t,int t2)
+/* Return name of library function, if this node should be
+   implemented via libcall. */
+{
+  static char fname[16];
+  char *ret = NULL;
+
+  if (((c==MULT && aa<AA2) ||
+       (c>MULT && c<=MOD)) && (t&NQ) <= LONG) {
+    if ((t&UNSIGNED) && (c==DIV || c==MOD))
+      sprintf(fname,"__%s",ename[c]);
+    else
+      sprintf(fname,"__%ss",ename[c]);
+    ret = fname;
+  }
+
+  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)&&(t&NU)==LLONG){
+        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{
+	  sprintf(fname,"__%s%s%s%ld",ename[c],(t&UNSIGNED)?"u":"",ISFLOAT(t)?"flt":"int",zm2l(sizetab[t&NQ])*8);
+          ret=fname;
+	}
+      }
+    }
+  }
+
+  return ret;
+}
+
+
+void gen_ds(FILE *f,zmax size,struct Typ *t)
+/*  This function has to create <size> bytes of storage */
+/*  initialized with zero.                              */
+{
+  title(f);
+
+  if (newobj && section!=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.              */
+{
+  title(f);
+
+  if (zm2l(align) > 1)
+    emit(f,"\t.align\t2\n");
+}
+
+
+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;
+  char *sec;
+
+  title(f);
+
+  if(v->clist)
+    constflag = is_const(v->vtyp);
+
+  if (isstatic(v->storage_class)) {
+    if (ISFUNC(v->vtyp->flags))
+      return;
+    if (!special_section(f,v)) {
+      if (v->clist && (!constflag || CONST_IN_DATA) && section!=DATA) {
+        emit(f,dataname);
+        if (f)
+          section = DATA;
+      }
+      if (v->clist && constflag && !CONST_IN_DATA && section!=RODATA) {
+        emit(f,rodataname);
+        if (f)
+          section = RODATA;
+      }
+      if (!v->clist && section!=BSS) {
+        emit(f,bssname);
+        if (f)
+          section = BSS;
+      }
+    }
+    if (v->clist || section==SPECIAL) {
+      gen_align(f,falign(v->vtyp));
+      emit(f,"%s%ld:\n",labprefix,zm2l(v->offset));
+    }
+    else
+      emit(f,"\t.lcomm\t%s%ld,",labprefix,zm2l(v->offset));
+    newobj = 1;
+  }
+
+  if (isextern(v->storage_class)) {
+    emit(f,"\t.globl\t%s%s\n",idprefix,v->identifier);
+    if (v->flags & (DEFINED|TENTATIVE)) {
+      if (!special_section(f,v)) {
+        if (v->clist && (!constflag || CONST_IN_DATA) && section!=DATA) {
+          emit(f,dataname);
+          if(f)
+            section = DATA;
+        }
+        if (v->clist && constflag && !CONST_IN_DATA && section!=RODATA) {
+          emit(f,rodataname);
+          if (f)
+            section = RODATA;
+        }
+        if (!v->clist && section!=BSS) {
+          emit(f,bssname);
+          if (f)
+            section = BSS;
+        }
+      }
+      if (v->clist || section==SPECIAL) {
+        gen_align(f,falign(v->vtyp));
+        emit(f,"%s%s:\n",idprefix,v->identifier);
+      }
+      else {
+        emit(f,"\t.global\t%s%s\n\t.%scomm\t%s%s,",idprefix,
+             v->identifier,(USE_COMMONS?"":"l"),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.                      */
+{
+  title(f);
+
+  if ((t&NQ) == POINTER)
+    t = UNSIGNED|LONG;
+  emit(f,"\t.%s\t",dct[t&NQ]);
+
+  if (!p->tree) {
+    if (ISFLOAT(t)) {
+      unsigned char *ip = (unsigned char *)&p->val.vdouble;
+
+      emit(f,"0x%02x%02x%02x%02x",ip[0],ip[1],ip[2],ip[3]);
+      if ((t&NQ) != FLOAT)
+        emit(f,",0x%02x%02x%02x%02x",ip[4],ip[5],ip[6],ip[7]);
+    }
+    else {
+      emitval(f,&p->val,t&NU);
+    }
+  }
+  else {
+    emit_obj(f,&p->tree->o,t&NU);
+  }
+
+  emitnl(f);
+  newobj = 0;
+}
+
+
+/*  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 *p,struct Var *v,zmax offset)
+/*  The main code-generation routine.                   */
+{
+  FILE *outfile = f;
+  struct IC *p_start = p;
+  int c,t,i,pass;
+  struct rpair rp;
+
+  if (DEBUG & 1)
+    printf("gen_code()\n");
+
+  current_function = v;
+  icnt = 0;
+  drefptr_array_label = 0;
+  argsize = 0;
+  rsavesize = 0;
+  maxrsaveoffs = 0;
+  needframe = 0;
+
+  for (c=1; c<=MAXR; c++)
+    regs[c] = regsa[c];
+
+  for (p=p_start; p; p=p->next) {
+    c = p->code;
+    t = p->typf & NU;
+
+    if (c == ALLOCREG) {
+      if (reg_pair(p->q1.reg,&rp)) {
+        regs[rp.r1] = 1;
+        regs[rp.r2] = 1;
+      }
+      regs[p->q1.reg] = 1;
+      continue;
+    }
+
+    if (c == FREEREG) {
+      if (reg_pair(p->q1.reg,&rp)) {
+        regs[rp.r1] = 0;
+        regs[rp.r2] = 0;
+      }
+      regs[p->q1.reg] = 0;
+      continue;
+    }
+
+    /* try MULT/DIV/MOD with powers of two */
+    if ((c==MULT || ((c==DIV || c==MOD) && (t&UNSIGNED))) &&
+        (t&NQ)<=LONG && isconst(p->q2.flags)) {
+      eval_const(&p->q2.val,t);
+      if (i = pof2(vmax)) {
+        if (c == MOD) {
+          vmax = zmsub(vmax,l2zm(1L));
+          p->code = AND;
+        }
+        else {
+          vmax = l2zm(i-1);
+          p->code = c==DIV ? RSHIFT : 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,INT);
+          p->typf2 = INT;
+        }
+      }
+    }
+
+    if (c == CALL) {
+      needframe = 1;
+      if (argsize < zm2l(pushedargsize(p)))
+        argsize = zm2l(pushedargsize(p));  /* set max argsize */
+    }
+  }
+
+  /*peephole(p); @@@ FIXME */
+
+  for (c=i; i<=MAXR; i++) {
+    if (regsa[i] || regused[i])
+      BSET(regs_modified,i);
+    if (!regsa[i] && !regscratch[i] && regused[i])
+      needframe = 1;
+  }
+
+  /* determine word-aligned space for local variables */
+  localsize = ((zm2l(offset) + 3) / 4) * 4;
+  if (localsize > 0)
+    needframe = 1;
+
+  for (pass=0,f=NULL; pass<2; pass++,f=outfile) {
+    struct IC my_ic;
+    struct IC *p2;
+
+    if (pass) {
+      emit_dataptr_array(NULL);  /* reset ptr-array */
+      icnt = 0;
+      function_top(f,v,argsize+localsize);
+    }
+
+    pushoffs = 0;
+
+    for (p2=p_start; p2; p2=p2->next) {
+      if (pass) {
+        p = p2;
+      }
+      else {  /* work on a copy in first pass */
+        p = &my_ic;
+        *p = *p2;
+      }
+
+      c = p->code;
+      t = p->typf;
+
+      cg_freeall(f);  /* reset internal register allocations */
+
+      if (icnt > MAXCODELINES) {
+        /* function has grown too big, emit all data-reference pointers first */
+        emit(f,"\tb\t%s%d\n",labprefix,++label);
+        emit_dataptr_array(f);
+        emit(f,"%s%d:\n",labprefix,label);
+        icnt = 0;
+      }
+
+      if (c == NOP) {
+        p->z.flags = 0;
+        continue;
+      }
+
+      if (c == ALLOCREG) {
+        if (reg_pair(p->q1.reg,&rp)) {
+          regs[rp.r1] = 1;
+          regs[rp.r2] = 1;
+        }
+        regs[p->q1.reg] = 1;
+        continue;
+      }
+
+      if (c == FREEREG) {
+        if (reg_pair(p->q1.reg,&rp)) {
+          regs[rp.r1] = 0;
+          regs[rp.r2] = 0;
+        }
+        regs[p->q1.reg] = 0;
+        continue;
+      }
+
+      if (c == LABEL) {
+        emit(f,"%s%d:\n",labprefix,t);
+        continue;
+      }
+
+      if (c == BRA) {
+        if (t==exit_label && framesize==0)
+          emit(f,ret);
+        else
+          emit(f,"\tb\t%s%d\n",labprefix,t);
+        continue;
+      }
+
+      if (c>=BEQ && c<BRA) {
+        emit(f,"\tb%s\t",ccs[c-BEQ]);
+        if (isreg(p->q1.flags)) {
+          ierror(0);  /* @@@ was ist das? */
+          emit_obj(f,&p->q1,0);
+          emit(f,",");
+        }
+        emit(f,"%s%d\n",labprefix,t);
+        continue;
+      }
+
+      if (c == MOVETOREG) {
+        if (p->z.reg>=FIRST_GPR && p->z.reg<=LAST_GPR) {
+          load_reg(f,p,p->z.reg,&p->q1,t);
+        }
+        else if (reg_pair(p->z.reg,&rp)) {
+          BSET(regs_modified,p->z.reg);
+          load_regpair(f,p,&rp,&p->q1,t);
+        }
+        else
+          ierror(0);  /* @@@ VFP registers */
+        p->z.flags = 0;
+        continue;
+      }
+
+      if (c == MOVEFROMREG) {
+        if (p->q1.reg>=FIRST_GPR && p->q1.reg<=LAST_GPR) {
+          store_reg(f,p,p->q1.reg,&p->z,t);
+        }
+        else if (reg_pair(p->q1.reg,&rp)) {
+          store_regpair(f,p,&rp,&p->z,t);
+        }
+        else
+          ierror(0);  /* @@@ VFP registers */
+        p->z.flags = 0;
+        continue;
+      }
+
+      if ((c==ASSIGN || c==PUSH) &&
+          ((t&NQ)>POINTER || ((t&NQ)==CHAR && zm2l(opsize(p))!=1))) {
+        cg_memcopy(f,p);
+        p->z.flags = 0;
+        continue;
+      }
+
+      p = preload(f,p);
+      c = p->code;
+
+      if (c == SUBPFP)
+        c = SUB;
+      else if (c == ADDI2P)
+        c = ADD;
+      else if (c == SUBIFP)
+        c = SUB;
+
+      if (c == CONVERT) {
+        if (ISFLOAT(q1typ(p)) || ISFLOAT(ztyp(p)))   /* @@@ */
+          ierror(0);
+
+        if (sizetab[q1typ(p)&NQ] < sizetab[ztyp(p)&NQ]) {
+          int sh = 0;
+
+          if ((q1typ(p)&NQ) == CHAR)
+            sh = 24;
+          else if ((q1typ(p)&NQ) == SHORT)
+            sh = 16;
+          else if (sizetab[ztyp(p)&NQ] > 4)
+            ierror(0);  /* @@@ */
+
+          if (sh) {
+            registerize(f,p,&p->q1,q1typ(p));
+            emit(f,"\tmov\t%s,%s,lsl #%d\n",regnames[zreg],regnames[p->q1.reg],sh);
+            emit(f,"\tmov\t%s,%s,%csr #%d\n",regnames[zreg],regnames[zreg],
+                                             (q1typ(p)&UNSIGNED)?'l':'a',sh);
+          }
+        }
+        save_result(f,p);
+        continue;
+      }
+
+      if (c == KOMPLEMENT) {
+        registerize(f,p,&p->q1,t);
+        emit(f,"\tmvn\t%s,%s\n",regnames[zreg],regnames[p->q1.reg]);
+        save_result(f,p);
+        continue;
+      }
+
+      if (c == SETRETURN) {
+        load_reg(f,p,p->z.reg,&p->q1,t);
+        BSET(regs_modified,p->z.reg);
+        continue;
+      }
+
+      if (c == GETRETURN) {
+        if (p->q1.reg) {  /* REG-flag is not set!? */
+          zreg = p->q1.reg;
+          save_result(f,p);
+        }
+        else
+          p->z.flags = 0;
+        continue;
+      }
+
+      if (c == CALL) {
+        if ((p->q1.flags & (VAR|DREFOBJ))==VAR &&
+            p->q1.v->fi && p->q1.v->fi->inline_asm) {
+          emit_inline_asm(f,p->q1.v->fi->inline_asm);
+        }
+        else if (p->q1.flags & DREFOBJ) {
+          int reg;
+
+          if (p->q1.flags & REG) {
+            reg = p->q1.reg;
+          }
+          else {
+            reg = cg_getreg(f,p);
+            load_reg(f,p,reg,&p->q1,POINTER);
+          }
+          emit(f,"\tmov\t%s,%s\n",regnames[lr],regnames[pc]);
+          if (aa < AA4T)
+            emit(f,"\tmov\t%s,%s\n",regnames[pc],regnames[reg]);
+          else
+            emit(f,"\tbx\t%s\n",regnames[reg]);
+        }
+        else {
+          emit(f,"\tbl\t");
+          emit_obj(f,&p->q1,t);
+          emitnl(f);
+        }
+
+        pushoffs -= zm2l(pushedargsize(p));
+
+        if ((p->q1.flags & (VAR|DREFOBJ))==VAR &&
+            p->q1.v->fi && (p->q1.v->fi->flags & ALL_REGS)) {
+          bvunite(regs_modified,p->q1.v->fi->regs_modified,RSIZE);
+        }
+        else{
+          int i;
+
+          for (i=1; i<=MAXR; i++) {
+            if (regscratch[i])
+              BSET(regs_modified,i);
+          }
+        }
+        continue;
+      }
+
+      if (c == PUSH) {
+        if (t == 0)
+          ierror(0);
+        registerize(f,p,&p->q1,t);
+        emit(f,"\tstr\t%s,[%s,#%ld]\n",
+             regnames[p->q1.reg],regnames[sp],pushoffs);
+        pushoffs += zm2l(opsize(p));
+        continue;
+      }
+
+      if (c == ASSIGN) {
+        if (t == 0)
+          ierror(0);
+        if (isreg(p->q1.flags))
+          zreg = p->q1.reg;
+        else
+          load_reg(f,p,zreg,&p->q1,t);
+        save_result(f,p);
+        continue;
+      }
+
+      if (c == ADDRESS) {
+        load_address(f,zreg,&p->q1,POINTER);
+        save_result(f,p);
+        continue;
+      }
+
+      if (c == MINUS) {
+        registerize(f,p,&p->q1,t);
+        emit(f,"\trsb\t%s,%s,#0\n",regnames[zreg],regnames[p->q1.reg]);
+        save_result(f,p);
+        continue;
+      }
+
+      if (c == TEST) {
+        registerize(f,p,&p->q1,t);
+        emit(f,"\tteq\t%s,#0\n",regnames[p->q1.reg]);
+        continue;
+      }
+
+      if (c == COMPARE) {
+        if (!isconst(p->q1.flags))
+          registerize(f,p,&p->q1,t);
+        emit(f,"\tcmp\t%s,",regnames[p->q1.reg]);
+        emit_obj(f,&p->q2,t);
+        emitnl(f);
+        continue;
+      }
+
+      if ((c>=OR && c<=AND)) {
+        registerize(f,p,&p->q1,t);
+        if (!isconst(p->q2.flags))
+          registerize(f,p,&p->q2,t);
+        emit(f,"\t%s\t%s,%s,",logicals[c-OR],regnames[zreg],
+             regnames[p->q1.reg]);
+        emit_obj(f,&p->q2,t);
+        emitnl(f);
+        save_result(f,p);
+        continue;
+      }
+
+      if (c>=LSHIFT && c<=RSHIFT) {
+        registerize(f,p,&p->q1,t);
+        if (!isconst(p->q2.flags))
+          registerize(f,p,&p->q2,t);
+        emit(f,"\tmov\t%s,%s,%s ",regnames[zreg],regnames[p->q1.reg],
+             shifts[(t&UNSIGNED)!=0][c-LSHIFT]);
+        emit_obj(f,&p->q2,t);
+        emitnl(f);
+        save_result(f,p);
+        continue;
+      }
+
+      if (c>=ADD && c<=SUB) {
+        registerize(f,p,&p->q1,t);
+        if (!isconst(p->q2.flags))
+          registerize(f,p,&p->q2,t);
+        emit(f,"\t%s\t%s,%s,",c==ADD?"add":"sub",
+             regnames[zreg],regnames[p->q1.reg]);
+        emit_obj(f,&p->q2,t);
+        emitnl(f);
+        save_result(f,p);
+        continue;
+      }
+
+      if (c==MULT && aa>=AA2 && sizetab[t&NQ]<=4) {
+        registerize(f,p,&p->q1,t);
+        registerize(f,p,&p->q2,t);
+        emit(f,"\tmul\t%s,%s,%s\n",
+             regnames[zreg],regnames[p->q1.reg],regnames[p->q2.reg]);
+        save_result(f,p);
+        continue;
+      }
+
+      if (pass) {
+        pric2(stdout,p);
+        ierror(0);
+      }
+    }
+  }
+
+  cg_freeall(f);
+  function_bottom(f,v,argsize+localsize+rsavesize);
+
+#if 0  /* @@@ wozu? */
+  if (stack_valid) {
+    if (!v->fi)
+      v->fi = new_fi();
+    v->fi->flags |= ALL_STACK;
+    v->fi->stack1 = stack;
+  }
+  emit(f,"; stacksize=%lu%s\n",zum2ul(stack),stack_valid?"":"+??");
+#endif
+}
+
+
+int shortcut(int code,int typ)
+{
+  return 0;
+}
+
+
+int reg_parm(struct reg_handle *m, struct Typ *t,int vararg,struct Typ *d)
+{
+  int f;
+
+  if (!m || !t)
+    ierror(0);
+
+  f = t->flags & NQ;
+
+  if (f<=LONG || f==POINTER) {
+    if (m->gregs >= GPR_ARGS)
+      return 0;
+    else
+      return FIRST_GPR + m->gregs++;
+  }
+
+  if (f == LLONG) {
+    if (m->gregs >= GPR_ARGS-1)
+      return 0;
+    else
+      ierror(0);  /* @@@ check ABI if odd registers are skipped!? */
+  }
+
+  if (ISFLOAT(f)) {
+#if 0 /* @@@ VFP only! */
+    if (m->fregs >= FPR_ARGS)
+      return 0;
+    else
+      return FIRST_DOUBLE + m->fregs++;
+#endif
+  }
+
+  return 0;
+}
+
+
+int emit_peephole(void)
+/* This function will not optimize anything, but just update the
+   number of lines counter, icnt, for the current function.
+   It is required to estimate if a data-reference-pointer array
+   is still reachable with a 12-bit offset. */
+{
+  int entries;
+
+  entries = emit_f ? EMIT_BUF_DEPTH : emit_l - emit_f + 1;
+  icnt += entries;
+  return 0;
+}
+
+
+int handle_pragma(const char *s)
+{
+  return 0;
+}
+
+
+void cleanup_cg(FILE *f)
+{
+}
+
+
+void cleanup_db(FILE *f)
+{
+  if (f)
+    section = -1;
+}
diff --git a/machines/arm/machine.dt b/machines/arm/machine.dt
new file mode 100755
index 0000000..47b1bfa
--- /dev/null
+++ b/machines/arm/machine.dt
@@ -0,0 +1,16 @@
+S8BS
+S8BU
+S16BSLE S16BSBE
+S16BULE S16BUBE
+S32BSLE S32BSBE
+S32BULE S32BUBE
+S32BSLE S32BSBE
+S32BULE S32BUBE
+S64BSLE S64BSBE
+S64BULE S64BUBE
+S32BIEEELE
+S64BIEEELE
+S64BIEEELE
+S32BULE S32BUBE
+
+
diff --git a/machines/arm/machine.h b/machines/arm/machine.h
new file mode 100755
index 0000000..7730379
--- /dev/null
+++ b/machines/arm/machine.h
@@ -0,0 +1,141 @@
+/*
+ * ARM code generator
+ * Written by Frank Wille <frank@phoenix.owl.de>
+ */
+
+/* built-time configurable options: */
+#define NUM_GPRS 16
+#define NUM_FPRS 16
+#define NUM_CCRS 1
+#define NUM_PAIRS 13
+
+#include "dt.h"
+
+/* internally used by the backend */
+#define FIRST_GPR 1
+#define LAST_GPR (FIRST_GPR+NUM_GPRS-1)
+#define FIRST_FPR (LAST_GPR+1)
+#define LAST_FPR (FIRST_FPR+NUM_FPRS-1)
+#define FIRST_CCR (LAST_FPR+1)
+#define LAST_CCR (FIRST_CCR+NUM_CCRS-1)
+#define FIRST_PAIR (LAST_CCR+1)
+#define FIRST_DOUBLE (FIRST_PAIR+5)
+#define LAST_PAIR (FIRST_PAIR+NUM_PAIRS-1)
+
+
+/*  This struct can be used to implement machine-specific           */
+/*  addressing-modes.                                               */
+/*  Currently possible are (const,gpr) and (gpr,gpr)                */
+struct AddressingMode{
+    int never_used;
+};
+
+/*  The number of registers of the target machine.                  */
+#define MAXR NUM_GPRS+NUM_FPRS+NUM_CCRS+NUM_PAIRS
+
+/*  Number of commandline-options the code-generator accepts.       */
+#define MAXGF 10
+
+/*  If this is set to zero vbcc will not generate ICs where the     */
+/*  target operand is the same as the 2nd source operand.           */
+/*  This can sometimes simplify the code-generator, but usually     */
+/*  the code is better if the code-generator allows it.             */
+#define USEQ2ASZ 1
+
+/*  This specifies the smallest integer type that can be added to a */
+/*  pointer.                                                        */
+#define MINADDI2P INT
+
+/*  This specifies the largest integer type that can be added to a  */
+/*  pointer.                                                        */
+#define MAXADDI2P LONG
+
+/*  If the bytes of an integer are ordered most significant byte    */
+/*  byte first and then decreasing set BIGENDIAN to 1.              */
+#define BIGENDIAN (!arm_le_mode)
+
+/*  If the bytes of an integer are ordered lest significant byte    */
+/*  byte first and then increasing set LITTLEENDIAN to 1.           */
+#define LITTLEENDIAN (arm_le_mode)
+
+extern int arm_le_mode;
+/*  Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive.    */
+
+/*  If switch-statements should be generated as a sequence of       */
+/*  SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1.      */
+/*  This can yield better code on some machines.                    */
+#define SWITCHSUBS 0
+
+/*  In optimizing compilation certain library memcpy/strcpy-calls   */
+/*  with length known at compile-time will be inlined using an      */
+/*  ASSIGN-IC if the size is less or equal to INLINEMEMCPY.         */
+/*  The type used for the ASSIGN-IC will be UNSIGNED|CHAR.          */
+#define INLINEMEMCPY 1024
+
+/*  Parameters are sometimes passed in registers without __reg.     */
+#define HAVE_REGPARMS 1
+
+/*  Parameters on the stack should be pushed in order rather than   */
+/*  in reverse order.                                               */
+#define ORDERED_PUSH 1
+
+/*  Structure for reg_parm().                                       */
+struct reg_handle{
+    unsigned long gregs;
+    unsigned long fregs;
+};
+
+/*  Number registers used for function arguments */
+#define GPR_ARGS 4
+#define FPR_ARGS 4
+
+/*  We have some target-specific variable attributes.               */
+#define HAVE_TARGET_ATTRIBUTES
+
+/* We have no target-specific pragmas */
+#undef HAVE_TARGET_PRAGMAS
+
+/*  We keep track of all registers modified by a function.          */
+#define HAVE_REGS_MODIFIED 1
+
+/* We have to implement our own cost-functions to adapt 
+   register-allocation */
+#define HAVE_TARGET_RALLOC 1
+#define cost_move_reg(x,y) 1
+#define cost_load_reg(x,y) 2
+#define cost_save_reg(x,y) 2
+#define cost_pushpop_reg(x) 3
+
+/* size of buffer for asm-output, this can be used to do
+   peephole-optimizations of the generated assembly-output */
+#define EMIT_BUF_LEN 1024 /* should be enough */
+/* number of asm-output lines buffered */
+#define EMIT_BUF_DEPTH 4
+
+/*  We have asm_peephole to optimize assembly-output */
+#define HAVE_TARGET_PEEPHOLE 1
+
+/* we do not have a mark_eff_ics function, this is used to prevent
+   optimizations on code which can already be implemented by efficient
+   assembly */
+#undef HAVE_TARGET_EFF_IC
+
+/* we only need the standard data types (no bit-types, different pointers
+   etc.) */
+#undef HAVE_EXT_TYPES
+#undef HAVE_TGT_PRINTVAL
+
+/* we do not need extra elements in the IC */
+#undef HAVE_EXT_IC
+
+/* we do not use unsigned int as size_t (but unsigned long, the default) */
+#undef HAVE_INT_SIZET
+
+/* we have register-pairs */
+#define HAVE_REGPAIRS 1
+
+#define JUMP_TABLE_DENSITY 0.8
+#define JUMP_TABLE_LENGTH 12
+
+/* We use builtin libcalls for some operations */
+#define HAVE_LIBCALLS 1
diff --git a/machines/bc16/machine.c b/machines/bc16/machine.c
new file mode 100755
index 0000000..82ab96f
--- /dev/null
+++ b/machines/bc16/machine.c
@@ -0,0 +1,1179 @@
+/*  Example backend for vbcc, it models a generic 32bit RISC or CISC
+    CPU.
+ 
+    Configurable at build-time are:
+    - number of (32bit) general-purpose-registers
+    - number of (64bit) floating-point-registers
+    - number of (8bit) condition-code-registers
+    - mechanism for stack-arguments (moving ot fixed sp)
+ 
+    It allows to select as run-time-options:
+    - two- or three-address code
+    - memory operands or load-store-architecture
+    - number of register-arguments
+    - number of caller-save-registers
+*/                                                                             
+
+#include "supp.h"
+
+static char FILE_[]=__FILE__;
+
+/*  Public data that MUST be there.                             */
+
+/* Name and copyright. */
+char cg_copyright[]="vbcc bc16 code-generator V0.1 (c) in 2021 by Volker Barthelmann";
+
+/*  Commandline-flags the code-generator accepts:
+    0: just a flag
+    VALFLAG: a value must be specified
+    STRINGFLAG: a string can be specified
+    FUNCFLAG: a function will be called
+    apart from FUNCFLAG, all other versions can only be specified once */
+int g_flags[MAXGF]={0,0,
+		    VALFLAG,VALFLAG,VALFLAG,
+		    0,0,
+		    VALFLAG,VALFLAG,0};
+
+/* the flag-name, do not use names beginning with l, L, I, D or U, because
+   they collide with the frontend */
+char *g_flags_name[MAXGF]={"three-addr","load-store",
+			   "volatile-gprs","volatile-fprs","volatile-ccrs",
+			   "imm-ind","gpr-ind",
+			   "gpr-args","fpr-args","use-commons"};
+
+/* the results of parsing the command-line-flags will be stored here */
+union ppi g_flags_val[MAXGF];
+
+/*  Alignment-requirements for all types in bytes.              */
+zmax align[MAX_TYPE+1];
+
+/*  Alignment that is sufficient for every object.              */
+zmax maxalign;
+
+/*  CHAR_BIT for the target machine.                            */
+zmax char_bit;
+
+/*  sizes of the basic 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. will be initialized in init_cg(),
+    register number 0 is invalid, valid registers start at 1 */
+char *regnames[MAXR+1];
+
+/*  The Size of each register in bytes.                         */
+zmax regsize[MAXR+1];
+
+/*  a 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];
+
+/* specifies the priority for the register-allocator, if the same
+   estimated cost-saving can be obtained by several registers, the
+   one with the highest priority will be used */
+int reg_prio[MAXR+1];
+
+/* an empty reg-handle representing initial state */
+struct reg_handle empty_reg_handle={0,0};
+
+/* Names of target-specific variable attributes.                */
+char *g_attr_name[]={"__interrupt",0};
+
+
+/****************************************/
+/*  Private data and functions.         */
+/****************************************/
+
+#define THREE_ADDR (g_flags[0]&USEDFLAG)
+#define LOAD_STORE (g_flags[1]&USEDFLAG)
+#define VOL_GPRS   ((g_flags[2]&USEDFLAG)?g_flags_val[2].l:NUM_GPRS/2)
+#define VOL_FPRS   ((g_flags[3]&USEDFLAG)?g_flags_val[3].l:NUM_FPRS/2)
+#define VOL_CCRS   ((g_flags[4]&USEDFLAG)?g_flags_val[4].l:NUM_CCRS/2)
+#define IMM_IND    ((g_flags[5]&USEDFLAG)?1:0)
+#define GPR_IND    ((g_flags[6]&USEDFLAG)?2:0)
+#define GPR_ARGS   ((g_flags[7]&USEDFLAG)?g_flags_val[7].l:0)
+#define FPR_ARGS   ((g_flags[8]&USEDFLAG)?g_flags_val[8].l:0)
+#define USE_COMMONS (g_flags[9]&USEDFLAG)
+
+
+/* alignment of basic data-types, used to initialize align[] */
+static long malign[MAX_TYPE+1]=  {1,1,2,4,4,4,4,8,8,1,4,1,1,1,4,1};
+/* sizes of basic data-types, used to initialize sizetab[] */
+static long msizetab[MAX_TYPE+1]={1,1,2,4,4,8,4,8,8,0,4,0,0,0,4,0};
+
+/* used to initialize regtyp[] */
+static struct Typ ltyp={LONG},ldbl={DOUBLE},lchar={CHAR};
+
+/* macros defined by the backend */
+static char *marray[]={"__section(x)=__vattr(\"section(\"#x\")\")",
+		       "__GENERIC__",
+		       0};
+
+/* special registers */
+static int sp;                     /*  Stackpointer                        */
+static int t1,t2,t3;               /*  temporary gprs */
+static int f1,f2,f3;               /*  temporary fprs */
+
+#define dt(t) (((t)&UNSIGNED)?udt[(t)&NQ]:sdt[(t)&NQ])
+static char *sdt[MAX_TYPE+1]={"??","c","s","i","l","ll","f","d","ld","v","p"};
+static char *udt[MAX_TYPE+1]={"??","uc","us","ui","ul","ull","f","d","ld","v","p"};
+
+/* sections */
+#define DATA 0
+#define BSS 1
+#define CODE 2
+#define RODATA 3
+#define SPECIAL 4
+
+static long stack;
+static int stack_valid;
+static int section=-1,newobj;
+static char *codename="\t.text\n",
+  *dataname="\t.data\n",
+  *bssname="",
+  *rodataname="\t.section\t.rodata\n";
+
+/* return-instruction */
+static char *ret;
+
+/* label at the end of the function (if any) */
+static int exit_label;
+
+/* assembly-prefixes for labels and external identifiers */
+static char *labprefix="l",*idprefix="_";
+
+#if FIXED_SP
+/* variables to calculate the size and partitioning of the stack-frame
+   in the case of FIXED_SP */
+static long frameoffset,pushed,maxpushed,framesize;
+#else
+/* variables to keep track of the current stack-offset in the case of
+   a moving stack-pointer */
+static long notpopped,dontpop,pushed,stackoffset,maxpushed;
+#endif
+
+static long localsize,rsavesize,argsize;
+
+static void emit_obj(FILE *f,struct obj *p,int t);
+
+/* calculate the actual current offset of an object relativ to the
+   stack-pointer; we use a layout like this:
+   ------------------------------------------------
+   | arguments to this function                   |
+   ------------------------------------------------
+   | return-address [size=4]                      |
+   ------------------------------------------------
+   | caller-save registers [size=rsavesize]       |
+   ------------------------------------------------
+   | local variables [size=localsize]             |
+   ------------------------------------------------
+   | arguments to called functions [size=argsize] |
+   ------------------------------------------------
+   All sizes will be aligned as necessary.
+   In the case of FIXED_SP, the stack-pointer will be adjusted at
+   function-entry to leave enough space for the arguments and have it
+   aligned to 16 bytes. Therefore, when calling a function, the
+   stack-pointer is always aligned to 16 bytes.
+   For a moving stack-pointer, the stack-pointer will usually point
+   to the bottom of the area for local variables, but will move while
+   arguments are put on the stack.
+
+   This is just an example layout. Other layouts are also possible.
+*/
+
+static void push(int i)
+{
+  pushed-=i;
+  if(pushed<maxpushed)
+    maxpushed=pushed;
+}
+
+static void pop(int i)
+{
+  pushed+=i;
+  if(pushed>0) ierror(0);
+}
+
+static long real_offset(struct obj *o)
+{
+  long off=zm2l(o->v->offset);
+  if(off<0){
+    /* function parameter */
+    off=localsize+rsavesize+4-off-zm2l(maxalign);
+  }
+
+#if FIXED_SP
+  off+=argsize;
+#else
+  off+=stackoffset;
+#endif
+  off+=zm2l(o->val.vmax);
+  return off;
+}
+
+/*  Initializes an addressing-mode structure and returns a pointer to
+    that object. Will not survive a second call! */
+static struct obj *cam(int flags,int base,long offset)
+{
+  static struct obj obj;
+  static struct AddressingMode am;
+  obj.am=&am;
+  am.flags=flags;
+  am.base=base;
+  am.offset=offset;
+  return &obj;
+}
+
+/* changes to a special section, used for __section() */
+static int special_section(FILE *f,struct Var *v)
+{
+  char *sec;
+  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;
+}
+
+/* generate code to load the address of a variable into register r */
+static void load_address(FILE *f,int r,struct obj *o,int type)
+/*  Generates code to load the address of a variable into register r.   */
+{
+  if(!(o->flags&VAR)) ierror(0);
+  if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER){
+    long off=real_offset(o);
+    if(THREE_ADDR){
+      emit(f,"\tadd.%s\t%s,%s,%ld\n",dt(POINTER),regnames[r],regnames[sp],off);
+    }else{
+      emit(f,"\tmov.%s\t%s,%s\n",dt(POINTER),regnames[r],regnames[sp]);
+      if(off)
+	emit(f,"\tadd.%s\t%s,%ld\n",dt(POINTER),regnames[r],off);
+    }
+  }else{
+    emit(f,"\tmov.%s\t%s,",dt(POINTER),regnames[r]);
+    emit_obj(f,o,type);
+    emit(f,"\n");
+  }
+}
+/* Generates code to load a memory object into register r. tmp is a
+   general purpose register which may be used. tmp can be r. */
+static void load_reg(FILE *f,int r,struct obj *o,int type)
+{
+  type&=NU;
+  if(o->flags&VARADR){
+    load_address(f,r,o,POINTER);
+  }else{
+    if((o->flags&(REG|DREFOBJ))==REG&&o->reg==r)
+      return;
+    emit(f,"\tmov.%s\t%s,",dt(type),regnames[r]);
+    emit_obj(f,o,type);
+    emit(f,"\n");
+  }
+}
+
+/*  Generates code to store register r into memory object o. */
+static void store_reg(FILE *f,int r,struct obj *o,int type)
+{
+  type&=NQ;
+  emit(f,"\tmov.%s\t",dt(type));
+  emit_obj(f,o,type);
+  emit(f,",%s\n",regnames[r]);
+}
+
+/*  Yields log2(x)+1 or 0. */
+static long pof2(zumax x)
+{
+  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 struct IC *preload(FILE *,struct IC *);
+
+static void function_top(FILE *,struct Var *,long);
+static void function_bottom(FILE *f,struct Var *,long);
+
+#define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
+#define isconst(x) ((p->x.flags&(KONST|DREFOBJ))==KONST)
+
+static int q1reg,q2reg,zreg;
+
+static char *ccs[]={"eq","ne","lt","ge","le","gt",""};
+static char *logicals[]={"or","xor","and"};
+static char *arithmetics[]={"slw","srw","add","sub","mullw","divw","mod"};
+
+/* compare if two objects are the same */
+static int compare_objects(struct obj *o1,struct obj *o2)
+{
+  if((o1->flags&(REG|DREFOBJ))==REG&&(o2->flags&(REG|DREFOBJ))==REG&&o1->reg==o2->reg)
+    return 1;
+  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&REG)||o1->reg==o2->reg){
+        return 1;
+      }
+    }
+  }
+  return 0;
+}
+
+/* Does some pre-processing like fetching operands from memory to
+   registers etc. */
+static struct IC *preload(FILE *f,struct IC *p)
+{
+  int r;
+
+  if(isreg(q1))
+    q1reg=p->q1.reg;
+  else
+    q1reg=0;
+
+  if(isreg(q2))
+    q2reg=p->q2.reg;
+  else
+    q2reg=0;
+
+  if(isreg(z)&&(THREE_ADDR||!compare_objects(&p->q2,&p->z))){
+    zreg=p->z.reg;
+  }else{
+    if(ISFLOAT(ztyp(p)))
+      zreg=f1;
+    else
+      zreg=t1;
+  }
+  
+  if((p->q1.flags&(DREFOBJ|REG))==DREFOBJ&&!p->q1.am){
+    p->q1.flags&=~DREFOBJ;
+    load_reg(f,t1,&p->q1,q1typ(p));
+    p->q1.reg=t1;
+    p->q1.flags|=(REG|DREFOBJ);
+  }
+  if(p->q1.flags&&LOAD_STORE&&!isreg(q1)){
+    if(p->code==ASSIGN&&isreg(z))
+      q1reg=p->z.reg;
+    else if(ISFLOAT(q1typ(p)))
+      q1reg=f1;
+    else
+      q1reg=t1;
+    load_reg(f,q1reg,&p->q1,q1typ(p));
+    p->q1.reg=q1reg;
+    p->q1.flags=REG;
+  }
+
+  if((p->q2.flags&(DREFOBJ|REG))==DREFOBJ&&!p->q2.am){
+    p->q2.flags&=~DREFOBJ;
+    load_reg(f,t1,&p->q2,q2typ(p));
+    p->q2.reg=t1;
+    p->q2.flags|=(REG|DREFOBJ);
+  }
+  if(p->q2.flags&&LOAD_STORE&&!isreg(q2)){
+    if(ISFLOAT(q2typ(p)))
+      q2reg=f2;
+    else
+      q2reg=t2;
+    load_reg(f,q2reg,&p->q2,q2typ(p));
+    p->q2.reg=q2reg;
+    p->q2.flags=REG;
+  }
+  return p;
+}
+
+/* save the result (in zreg) into p->z */
+void save_result(FILE *f,struct IC *p)
+{
+  if((p->z.flags&(REG|DREFOBJ))==DREFOBJ&&!p->z.am){
+    p->z.flags&=~DREFOBJ;
+    load_reg(f,t2,&p->z,POINTER);
+    p->z.reg=t2;
+    p->z.flags|=(REG|DREFOBJ);
+  }
+  if(isreg(z)){
+    if(p->z.reg!=zreg)
+      emit(f,"\tmov.%s\t%s,%s\n",dt(ztyp(p)),regnames[p->z.reg],regnames[zreg]);
+  }else{
+    store_reg(f,zreg,&p->z,ztyp(p));
+  }
+}
+
+/* prints an object */
+static void emit_obj(FILE *f,struct obj *p,int t)
+{
+  if(p->am){
+    if(p->am->flags&GPR_IND) emit(f,"(%s,%s)",regnames[p->am->offset],regnames[p->am->base]);
+    if(p->am->flags&IMM_IND) emit(f,"(%ld,%s)",p->am->offset,regnames[p->am->base]);
+    return;
+  }
+  if((p->flags&(KONST|DREFOBJ))==(KONST|DREFOBJ)){
+    emitval(f,&p->val,p->dtyp&NU);
+    return;
+  }
+  if(p->flags&DREFOBJ) emit(f,"(");
+  if(p->flags&REG){
+    emit(f,"%s",regnames[p->reg]);
+  }else if(p->flags&VAR) {
+    if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER)
+      emit(f,"%ld(%s)",real_offset(p),regnames[sp]);
+    else{
+      if(!zmeqto(l2zm(0L),p->val.vmax)){emitval(f,&p->val,LONG);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(p->flags&KONST){
+    emitval(f,&p->val,t&NU);
+  }
+  if(p->flags&DREFOBJ) emit(f,")");
+}
+
+/*  Test if there is a sequence of FREEREGs containing FREEREG reg.
+    Used by peephole. */
+static int exists_freereg(struct IC *p,int reg)
+{
+  while(p&&(p->code==FREEREG||p->code==ALLOCREG)){
+    if(p->code==FREEREG&&p->q1.reg==reg) return 1;
+    p=p->next;
+  }
+  return 0;
+}
+
+/* search for possible addressing-modes */
+static void peephole(struct IC *p)
+{
+  int c,c2,r;struct IC *p2;struct AddressingMode *am;
+
+  for(;p;p=p->next){
+    c=p->code;
+    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;
+
+    /* Try const(reg) */
+    if(IMM_IND&&(c==ADDI2P||c==SUBIFP)&&isreg(z)&&(p->q2.flags&(KONST|DREFOBJ))==KONST){
+      int base;zmax of;struct obj *o;
+      eval_const(&p->q2.val,p->typf);
+      if(c==SUBIFP) of=zmsub(l2zm(0L),vmax); else of=vmax;
+      if(1/*zmleq(l2zm(-32768L),vmax)&&zmleq(vmax,l2zm(32767L))*/){
+	r=p->z.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(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) break;
+	      o=&p2->q1;
+	    }
+	    if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
+	      if(o) break;
+	      o=&p2->q2;
+	    }
+	    if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
+	      if(o) 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);
+		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;
+	  }
+        }
+      }
+    }
+    /* Try reg,reg */
+    if(GPR_IND&&c==ADDI2P&&isreg(q2)&&isreg(z)&&(isreg(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||(q1typ(p2)&NQ)==LLONG) break;
+            o=&p2->q1;
+          }
+          if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
+            if(o||(q2typ(p2)&NQ)==LLONG) break;
+            o=&p2->q2;
+          }
+          if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
+            if(o||(ztyp(p2)&NQ)==LLONG) 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=GPR_IND;
+              am->base=base;
+              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;
+        }
+      }
+    }
+  }
+}
+
+/* generates the function entry code */
+static void function_top(FILE *f,struct Var *v,long offset)
+{
+  rsavesize=0;
+  if(!special_section(f,v)&&section!=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));
+}
+/* generates the function exit code */
+static void function_bottom(FILE *f,struct Var *v,long offset)
+{
+  emit(f,ret);
+}
+
+/****************************************/
+/*  End of private data and functions.  */
+/****************************************/
+
+/*  Does necessary initializations for the code-generator. Gets called  */
+/*  once at the beginning and should return 0 in case of problems.      */
+int init_cg(void)
+{
+  int i;
+  /*  Initialize some values which cannot be statically initialized   */
+  /*  because they are stored in the target's arithmetic.             */
+  maxalign=l2zm(8L);
+  char_bit=l2zm(8L);
+  stackalign=l2zm(4);
+
+  for(i=0;i<=MAX_TYPE;i++){
+    sizetab[i]=l2zm(msizetab[i]);
+    align[i]=l2zm(malign[i]);
+  }
+
+  regnames[0]="noreg";
+  for(i=FIRST_GPR;i<=LAST_GPR;i++){
+    regnames[i]=mymalloc(10);
+    sprintf(regnames[i],"gpr%d",i-FIRST_GPR);
+    regsize[i]=l2zm(4L);
+    regtype[i]=&ltyp;
+  }
+  for(i=FIRST_FPR;i<=LAST_FPR;i++){
+    regnames[i]=mymalloc(10);
+    sprintf(regnames[i],"fpr%d",i-FIRST_FPR);
+    regsize[i]=l2zm(8L);
+    regtype[i]=&ldbl;
+  }
+  for(i=FIRST_CCR;i<=LAST_CCR;i++){
+    regnames[i]=mymalloc(10);
+    sprintf(regnames[i],"ccr%d",i-FIRST_CCR);
+    regsize[i]=l2zm(1L);
+    regtype[i]=&lchar;
+  }
+
+  /*  Use multiple ccs.   */
+  multiple_ccs=0;
+
+  /*  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.          */
+  t_min[CHAR]=l2zm(-128L);
+  t_min[SHORT]=l2zm(-32768L);
+  t_min[INT]=zmsub(l2zm(-2147483647L),l2zm(1L));
+  t_min[LONG]=t_min(INT);
+  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]=ul2zum(2147483647UL);
+  t_max[LONG]=t_max(INT);
+  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]=ul2zum(4294967295UL);
+  tu_max[LONG]=t_max(UNSIGNED|INT);
+  tu_max[LLONG]=zumkompl(ul2zum(0UL));
+  tu_max[MAXINT]=t_max(UNSIGNED|LLONG);
+  
+  /*  Reserve a few registers for use by the code-generator.      */
+  /*  This is not optimal but simple.                             */
+  sp=FIRST_GPR;
+  t1=FIRST_GPR+1;
+  t2=FIRST_GPR+2;
+  f1=FIRST_FPR;
+  f2=FIRST_FPR+1;
+  regsa[t1]=regsa[t2]=1;
+  regsa[f1]=regsa[f2]=1;
+  regsa[sp]=1;
+  regscratch[t1]=regscratch[t2]=0;
+  regscratch[f1]=regscratch[f2]=0;
+  regscratch[sp]=0;
+
+  for(i=FIRST_GPR;i<=LAST_GPR-VOL_GPRS;i++)
+    regscratch[i]=1;
+  for(i=FIRST_FPR;i<=LAST_FPR-VOL_FPRS;i++)
+    regscratch[i]=1;
+  for(i=FIRST_CCR;i<=LAST_CCR-VOL_CCRS;i++)
+    regscratch[i]=1;
+
+  target_macros=marray;
+
+
+  return 1;
+}
+
+void init_db(FILE *f)
+{
+}
+
+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.        */
+/*  A pointer MUST be returned in a register. The code-generator    */
+/*  has to simulate a pseudo register if necessary.                 */
+{
+  if(ISFLOAT(t->flags)) 
+    return FIRST_FPR+2;
+  if(ISSTRUCT(t->flags)||ISUNION(t->flags)) 
+    return 0;
+  if(zmleq(szof(t),l2zm(4L))) 
+    return FIRST_GPR+3;
+  else
+    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.                                            */
+{
+  return 0;
+}
+
+/* estimate the cost-saving if object o from IC p is placed in
+   register r */
+int cost_savings(struct IC *p,int r,struct obj *o)
+{
+  int c=p->code;
+  if(o->flags&VKONST){
+    if(!LOAD_STORE)
+      return 0;
+    if(o==&p->q1&&p->code==ASSIGN&&(p->z.flags&DREFOBJ))
+      return 4;
+    else
+      return 2;
+  }
+  if(o->flags&DREFOBJ)
+    return 4;
+  if(c==SETRETURN&&r==p->z.reg&&!(o->flags&DREFOBJ)) return 3;
+  if(c==GETRETURN&&r==p->q1.reg&&!(o->flags&DREFOBJ)) return 3;
+  return 2;
+}
+
+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(r==0)
+    return 0;
+  t&=NQ;
+  if(t==0&&r>=FIRST_CCR&&r<=LAST_CCR)
+    return 1;
+  if(ISFLOAT(t)&&r>=FIRST_FPR&&r<=LAST_FPR)
+    return 1;
+  if(t==POINTER&&r>=FIRST_GPR&&r<=LAST_GPR)
+    return 1;
+  if(t>=CHAR&&t<=LONG&&r>=FIRST_GPR&&r<=LAST_GPR)
+    return 1;
+  return 0;
+}
+
+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;
+}
+
+int must_convert(int o,int t,int const_expr)
+/*  Returns zero if code for converting np to type t    */
+/*  can be omitted.                                     */
+/*  On the PowerPC cpu pointers and 32bit               */
+/*  integers have the same representation and can use   */
+/*  the same registers.                                 */
+{
+  int op=o&NQ,tp=t&NQ;
+  if((op==INT||op==LONG||op==POINTER)&&(tp==INT||tp==LONG||tp==POINTER))
+    return 0;
+  if(op==DOUBLE&&tp==LDOUBLE) return 0;
+  if(op==LDOUBLE&&tp==DOUBLE) 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&&section!=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.              */
+{
+  if(zm2l(align)>1) emit(f,"\t.align\t2\n");
+}
+
+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;char *sec;
+  if(v->clist) constflag=is_const(v->vtyp);
+  if(v->storage_class==STATIC){
+    if(ISFUNC(v->vtyp->flags)) return;
+    if(!special_section(f,v)){
+      if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&&section!=DATA){emit(f,dataname);if(f) section=DATA;}
+      if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&&section!=RODATA){emit(f,rodataname);if(f) section=RODATA;}
+      if(!v->clist&&section!=BSS){emit(f,bssname);if(f) section=BSS;}
+    }
+    if(v->clist||section==SPECIAL){
+      gen_align(f,falign(v->vtyp));
+      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){
+    emit(f,"\t.globl\t%s%s\n",idprefix,v->identifier);
+    if(v->flags&(DEFINED|TENTATIVE)){
+      if(!special_section(f,v)){
+	if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&&section!=DATA){emit(f,dataname);if(f) section=DATA;}
+	if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&&section!=RODATA){emit(f,rodataname);if(f) section=RODATA;}
+	if(!v->clist&&section!=BSS){emit(f,bssname);if(f) section=BSS;}
+      }
+      if(v->clist||section==SPECIAL){
+	gen_align(f,falign(v->vtyp));
+        emit(f,"%s%s:\n",idprefix,v->identifier);
+      }else
+        emit(f,"\t.global\t%s%s\n\t.%scomm\t%s%s,",idprefix,v->identifier,(USE_COMMONS?"":"l"),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,"\tdc.%s\t",dt(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[0],ip[1],ip[2],ip[3]);
+      if((t&NQ)!=FLOAT){
+	emit(f,",0x%02x%02x%02x%02x",ip[4],ip[5],ip[6],ip[7]);
+      }
+    }else{
+      emitval(f,&p->val,t&NU);
+    }
+  }else{
+    emit_obj(f,&p->tree->o,t&NU);
+  }
+  emit(f,"\n");newobj=0;
+}
+
+
+/*  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 *p,struct Var *v,zmax offset)
+/*  The main code-generation.                                           */
+{
+  int c,t,i;
+  struct IC *m;
+  argsize=0;
+  if(DEBUG&1) printf("gen_code()\n");
+  for(c=1;c<=MAXR;c++) regs[c]=regsa[c];
+  maxpushed=0;
+
+  /*FIXME*/
+  ret="\trts\n";
+
+  for(m=p;m;m=m->next){
+    c=m->code;t=m->typf&NU;
+    if(c==ALLOCREG) {regs[m->q1.reg]=1;continue;}
+    if(c==FREEREG) {regs[m->q1.reg]=0;continue;}
+
+    /* convert MULT/DIV/MOD with powers of two */
+    if((t&NQ)<=LONG&&(m->q2.flags&(KONST|DREFOBJ))==KONST&&(t&NQ)<=LONG&&(c==MULT||((c==DIV||c==MOD)&&(t&UNSIGNED)))){
+      eval_const(&m->q2.val,t);
+      i=pof2(vmax);
+      if(i){
+        if(c==MOD){
+          vmax=zmsub(vmax,l2zm(1L));
+          m->code=AND;
+        }else{
+          vmax=l2zm(i-1);
+          if(c==DIV) m->code=RSHIFT; else m->code=LSHIFT;
+        }
+        c=m->code;
+	gval.vmax=vmax;
+	eval_const(&gval,MAXINT);
+	if(c==AND){
+	  insert_const(&m->q2.val,t);
+	}else{
+	  insert_const(&m->q2.val,INT);
+	  p->typf2=INT;
+	}
+      }
+    }
+#if FIXED_SP
+    if(c==CALL&&argsize<zm2l(m->q2.val.vmax)) argsize=zm2l(m->q2.val.vmax);
+#endif
+  }
+  peephole(p);
+
+  for(c=1;c<=MAXR;c++){
+    if(regsa[c]||regused[c]){
+      BSET(regs_modified,c);
+    }
+  }
+
+  localsize=(zm2l(offset)+3)/4*4;
+#if FIXED_SP
+  /*FIXME: adjust localsize to get an aligned stack-frame */
+#endif
+
+  function_top(f,v,localsize);
+
+#if FIXED_SP
+  pushed=0;
+#endif
+
+  for(;p;p=p->next){
+    c=p->code;t=p->typf;
+    if(c==NOP) {p->z.flags=0;continue;}
+    if(c==ALLOCREG) {regs[p->q1.reg]=1;continue;}
+    if(c==FREEREG) {regs[p->q1.reg]=0;continue;}
+    if(c==LABEL) {emit(f,"%s%d:\n",labprefix,t);continue;}
+    if(c==BRA){
+      if(0/*t==exit_label&&framesize==0*/)
+	emit(f,ret);
+      else
+	emit(f,"\tb\t%s%d\n",labprefix,t);
+      continue;
+    }
+    if(c>=BEQ&&c<BRA){
+      emit(f,"\tb%s\t",ccs[c-BEQ]);
+      if(isreg(q1)){
+	emit_obj(f,&p->q1,0);
+	emit(f,",");
+      }
+      emit(f,"%s%d\n",labprefix,t);
+      continue;
+    }
+    if(c==MOVETOREG){
+      load_reg(f,p->z.reg,&p->q1,regtype[p->z.reg]->flags);
+      continue;
+    }
+    if(c==MOVEFROMREG){
+      store_reg(f,p->z.reg,&p->q1,regtype[p->z.reg]->flags);
+      continue;
+    }
+    if((c==ASSIGN||c==PUSH)&&((t&NQ)>POINTER||((t&NQ)==CHAR&&zm2l(p->q2.val.vmax)!=1))){
+      ierror(0);
+    }
+    /* switch commutative operands if suitable */
+    if(c==ADD||c==MULT||c==AND||c==XOR||c==OR){
+      if(compare_objects(&p->q2,&p->z)){
+	struct obj tmp;
+	tmp=p->q1;
+	p->q1=p->q2;
+	p->q2=tmp;
+      }
+    }
+
+    p=preload(f,p);
+    c=p->code;
+    if(c==SUBPFP) c=SUB;
+    if(c==ADDI2P) c=ADD;
+    if(c==SUBIFP) c=SUB;
+    if(c==CONVERT){
+      if(ISFLOAT(q1typ(p))||ISFLOAT(ztyp(p))) ierror(0);
+      if(sizetab[q1typ(p)&NQ]<sizetab[ztyp(p)&NQ]){
+	if(q1typ(p)&UNSIGNED)
+	  emit(f,"\tzext.%s\t%s\n",dt(q1typ(p)),regnames[zreg]);
+	else
+	  emit(f,"\tsext.%s\t%s\n",dt(q1typ(p)),regnames[zreg]);
+      }
+      save_result(f,p);
+      continue;
+    }
+    if(c==KOMPLEMENT){
+      load_reg(f,zreg,&p->q1,t);
+      emit(f,"\tcpl.%s\t%s\n",dt(t),regnames[zreg]);
+      save_result(f,p);
+      continue;
+    }
+    if(c==SETRETURN){
+      load_reg(f,p->z.reg,&p->q1,t);
+      BSET(regs_modified,p->z.reg);
+      continue;
+    }
+    if(c==GETRETURN){
+      if(p->q1.reg){
+        zreg=p->q1.reg;
+	save_result(f,p);
+      }else
+        p->z.flags=0;
+      continue;
+    }
+    if(c==CALL){
+      int reg;
+      /*FIXME*/
+#if 0      
+      if(stack_valid&&(p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&(p->q1.v->fi->flags&ALL_STACK)){
+	if(framesize+zum2ul(p->q1.v->fi->stack1)>stack)
+	  stack=framesize+zum2ul(p->q1.v->fi->stack1);
+      }else
+	stack_valid=0;
+#endif
+      if((p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&p->q1.v->fi->inline_asm){
+        emit_inline_asm(f,p->q1.v->fi->inline_asm);
+      }else{
+	emit(f,"\tcall\t");
+	emit_obj(f,&p->q1,t);
+	emit(f,"\n");
+      }
+      /*FIXME*/
+#if FIXED_SP
+      pushed-=zm2l(p->q2.val.vmax);
+#endif
+      if((p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&(p->q1.v->fi->flags&ALL_REGS)){
+	bvunite(regs_modified,p->q1.v->fi->regs_modified,RSIZE);
+      }else{
+	int i;
+	for(i=1;i<=MAXR;i++){
+	  if(regscratch[i]) BSET(regs_modified,i);
+	}
+      }
+      continue;
+    }
+    if(c==ASSIGN||c==PUSH){
+      if(t==0) ierror(0);
+      if(c==PUSH){
+#if FIXED_SP
+	emit(f,"\tmov.%s\t%ld(%s),",dt(t),pushed,regnames[sp]);
+	emit_obj(f,&p->q1,t);
+	emit(f,"\n");
+	pushed+=zm2l(p->q2.val.vmax);
+#else
+	emit(f,"\tpush.%s\t",dt(t));
+	emit_obj(f,&p->q1,t);
+	emit(f,"\n");
+	push(zm2l(p->q2.val.vmax));
+#endif
+	continue;
+      }
+      if(c==ASSIGN){
+	load_reg(f,zreg,&p->q1,t);
+	save_result(f,p);
+      }
+      continue;
+    }
+    if(c==ADDRESS){
+      load_address(f,zreg,&p->q1,POINTER);
+      save_result(f,p);
+      continue;
+    }
+    if(c==MINUS){
+      load_reg(f,zreg,&p->q1,t);
+      emit(f,"\tneg.%s\t%s\n",dt(t),regnames[zreg]);
+      save_result(f,p);
+      continue;
+    }
+    if(c==TEST){
+      emit(f,"\ttst.%s\t",dt(t));
+      if(multiple_ccs)
+	emit(f,"%s,",regnames[zreg]);
+      emit_obj(f,&p->q1,t);
+      emit(f,"\n");
+      if(multiple_ccs)
+	save_result(f,p);
+      continue;
+    }
+    if(c==COMPARE){
+      emit(f,"\tcmp.%s\t",dt(t));
+      if(multiple_ccs)
+	emit(f,"%s,",regnames[zreg]);
+      emit_obj(f,&p->q1,t);
+      emit(f,",");
+      emit_obj(f,&p->q2,t);
+      emit(f,"\n");
+      if(multiple_ccs)
+	save_result(f,p);
+      continue;
+    }
+    if((c>=OR&&c<=AND)||(c>=LSHIFT&&c<=MOD)){
+      if(!THREE_ADDR)
+	load_reg(f,zreg,&p->q1,t);
+      if(c>=OR&&c<=AND)
+	emit(f,"\t%s.%s\t%s,",logicals[c-OR],dt(t),regnames[zreg]);
+      else
+	emit(f,"\t%s.%s\t%s,",arithmetics[c-LSHIFT],dt(t),regnames[zreg]);
+      if(THREE_ADDR){
+	emit_obj(f,&p->q1,t);
+	emit(f,",");
+      }
+      emit_obj(f,&p->q2,t);
+      emit(f,"\n");
+      save_result(f,p);
+      continue;
+    }
+    pric2(stdout,p);
+    ierror(0);
+  }
+  function_bottom(f,v,localsize);
+  if(stack_valid){
+    if(!v->fi) v->fi=new_fi();
+    v->fi->flags|=ALL_STACK;
+    v->fi->stack1=stack;
+  }
+  emit(f,"# stacksize=%lu%s\n",zum2ul(stack),stack_valid?"":"+??");
+}
+
+int shortcut(int code,int typ)
+{
+  return 0;
+}
+
+int reg_parm(struct reg_handle *m, struct Typ *t,int vararg,struct Typ *d)
+{
+  int f;
+  f=t->flags&NQ;
+  if(f<=LONG||f==POINTER){
+    if(m->gregs>=GPR_ARGS)
+      return 0;
+    else
+      return FIRST_GPR+3+m->gregs++;
+  }
+  if(ISFLOAT(f)){
+    if(m->fregs>=FPR_ARGS)
+      return 0;
+    else
+      return FIRST_FPR+2+m->fregs++;
+  }
+  return 0;
+}
+
+int handle_pragma(const char *s)
+{
+}
+void cleanup_cg(FILE *f)
+{
+}
+void cleanup_db(FILE *f)
+{
+  if(f) section=-1;
+}
+
diff --git a/machines/bc16/machine.dt b/machines/bc16/machine.dt
new file mode 100755
index 0000000..cd2cdef
--- /dev/null
+++ b/machines/bc16/machine.dt
@@ -0,0 +1,16 @@
+S8BS
+S8BU
+S16BSBE S16BSLE
+S16BUBE S16BULE
+S16BSBE S16BSLE
+S16BUBE S16BULE
+S32BSBE S32BSLE
+S32BUBE S32BULE
+S64BSBE S64BSLE
+S64BUBE S64BULE
+S32BIEEEBE
+S64BIEEEBE
+S64BIEEEBE
+S16BUBE S16BULE
+
+
diff --git a/machines/bc16/machine.h b/machines/bc16/machine.h
new file mode 100755
index 0000000..83579be
--- /dev/null
+++ b/machines/bc16/machine.h
@@ -0,0 +1,153 @@
+/*  Example backend for vbcc, it models a generic 32bit RISC or CISC
+    CPU.
+
+    Configurable at build-time are:
+    - number of (32bit) general-purpose-registers
+    - number of (64bit) floating-point-registers
+    - number of (8bit) condition-code-registers
+    - mechanism for stack-arguments (moving ot fixed sp)
+
+    It allows to select as run-time-options:
+    - two- or three-address code
+    - memory operands or load-store-architecture
+    - number of register-arguments
+    - number of caller-save-registers
+*/
+
+/* buil-time configurable options: */
+#define NUM_GPRS 8
+#define NUM_FPRS 0
+#define NUM_CCRS 1
+#define FIXED_SP 0
+
+#include "dt.h"
+
+/* internally used by the backend */
+#define FIRST_GPR 1
+#define LAST_GPR (FIRST_GPR+NUM_GPRS-1)
+#define FIRST_FPR (LAST_GPR+1)
+#define LAST_FPR (FIRST_FPR+NUM_FPRS-1)
+#define FIRST_CCR (LAST_FPR+1)
+#define LAST_CCR (FIRST_CCR+NUM_CCRS-1)
+
+/*  This struct can be used to implement machine-specific           */
+/*  addressing-modes.                                               */
+/*  Currently possible are (const,gpr) and (gpr,gpr)                */
+struct AddressingMode{
+    int flags;
+    int base;
+    long offset;
+};
+
+/*  The number of registers of the target machine.                  */
+#define MAXR NUM_GPRS+NUM_FPRS+NUM_CCRS
+
+/*  Number of commandline-options the code-generator accepts.       */
+#define MAXGF 20
+
+/*  If this is set to zero vbcc will not generate ICs where the     */
+/*  target operand is the same as the 2nd source operand.           */
+/*  This can sometimes simplify the code-generator, but usually     */
+/*  the code is better if the code-generator allows it.             */
+#define USEQ2ASZ 1
+
+/*  This specifies the smallest integer type that can be added to a */
+/*  pointer.                                                        */
+#define MINADDI2P INT
+
+/*  If the bytes of an integer are ordered most significant byte    */
+/*  byte first and then decreasing set BIGENDIAN to 1.              */
+#define BIGENDIAN 0
+
+/*  If the bytes of an integer are ordered lest significant byte    */
+/*  byte first and then increasing set LITTLEENDIAN to 1.           */
+#define LITTLEENDIAN 1
+
+/*  Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive.    */
+
+/*  If switch-statements should be generated as a sequence of       */
+/*  SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1.      */
+/*  This can yield better code on some machines.                    */
+#define SWITCHSUBS 0
+
+/*  In optimizing compilation certain library memcpy/strcpy-calls   */
+/*  with length known at compile-time will be inlined using an      */
+/*  ASSIGN-IC if the size is less or equal to INLINEMEMCPY.         */
+/*  The type used for the ASSIGN-IC will be UNSIGNED|CHAR.          */
+#define INLINEMEMCPY 1024
+
+/*  Parameters are sometimes passed in registers without __reg.     */
+#define HAVE_REGPARMS 1
+
+/*  Parameters on the stack should be pushed in order rather than   */
+/*  in reverse order.                                               */
+#define ORDERED_PUSH FIXED_SP
+
+/*  Structure for reg_parm().                                       */
+struct reg_handle{
+    unsigned long gregs;
+    unsigned long fregs;
+};
+
+/*  We have some target-specific variable attributes.               */
+#define HAVE_TARGET_ATTRIBUTES
+
+/* We have target-specific pragmas */
+#define HAVE_TARGET_PRAGMAS
+
+/*  We keep track of all registers modified by a function.          */
+#define HAVE_REGS_MODIFIED 1
+
+/* We have a implement our own cost-functions to adapt 
+   register-allocation */
+#define HAVE_TARGET_RALLOC 1
+#define cost_move_reg(x,y) 1
+#define cost_load_reg(x,y) 2
+#define cost_save_reg(x,y) 2
+#define cost_pushpop_reg(x) 3
+
+/* size of buffer for asm-output, this can be used to do
+   peephole-optimizations of the generated assembly-output */
+#define EMIT_BUF_LEN 1024 /* should be enough */
+/* number of asm-output lines buffered */
+#define EMIT_BUF_DEPTH 4
+
+/*  We have no asm_peephole to optimize assembly-output */
+#define HAVE_TARGET_PEEPHOLE 0
+
+/* we do not have a mark_eff_ics function, this is used to prevent
+   optimizations on code which can already be implemented by efficient
+   assembly */
+#undef HAVE_TARGET_EFF_IC
+
+/* we only need the standard data types (no bit-types, different pointers
+   etc.) */
+#undef HAVE_EXT_TYPES
+#undef HAVE_TGT_PRINTVAL
+
+/* we do not need extra elements in the IC */
+#undef HAVE_EXT_IC
+
+/* we do not use unsigned int as size_t (but unsigned long, the default) */
+#undef HAVE_INT_SIZET
+
+/* we do not need register-pairs */
+#undef HAVE_REGPAIRS
+
+
+/* do not create CONVERT ICs from integers smaller than int to floats */
+#define MIN_INT_TO_FLOAT_TYPE INT
+
+/* do not create CONVERT ICs from floats to ints smaller than int */
+#define MIN_FLOAT_TO_INT_TYPE INT
+
+/* do not create CONVERT_ICs from floats to unsigned integers */
+#define AVOID_FLOAT_TO_UNSIGNED 1
+
+/* do not create CONVERT_ICs from unsigned integers to floats */
+#define AVOID_UNSIGNED_TO_FLOAT 1
+
+/* convert multiplications/division by powers of two to shifts */
+#define HAVE_POF2OPT 1
+
+#define HAVE_WANTBNE 1
diff --git a/machines/bi386/machine.c b/machines/bi386/machine.c
new file mode 100755
index 0000000..37fe7a1
--- /dev/null
+++ b/machines/bi386/machine.c
@@ -0,0 +1,1446 @@
+/*  Code generator for Intel 80386 or higher.			*/
+
+#include "supp.h"
+
+/* Was gehoert hier hin? */
+#define N_SO 128
+#define N_LSYM 128
+#define N_FUN 36
+#define N_PSYM 128
+
+static char FILE_[]=__FILE__;
+
+/*  Public data that MUST be there.				*/
+
+/* Name and copyright. */
+char cg_copyright[]="vbcc code-generator for i386/BE V0.1 (c) in 1997 by Volker Barthelmann";
+
+/*  Commandline-flags the code-generator accepts		*/
+int g_flags[MAXGF]={VALFLAG,VALFLAG,0,0,
+		    0,0,0,0,
+                    0};
+char *g_flags_name[MAXGF]={"cpu","fpu","no-delayed-popping","const-in-data",
+			   "merge-constants","elf","longalign","use-framepointer",
+                           "g"};
+union ppi g_flags_val[MAXGF];
+
+/*  Alignment-requirements for all types in bytes.		*/
+zlong align[16];
+
+/*  Alignment that is sufficient for every object.		*/
+zlong maxalign;
+
+/*  CHAR_BIT of the target machine.				*/
+zlong char_bit;
+
+/*  Sizes of all elementary types in bytes.			*/
+zlong sizetab[16];
+
+/*  Minimum and Maximum values each type can have.		*/
+/*  Must be initialized in init_cg().                           */
+zlong t_min[32];
+zulong t_max[32];
+
+/*  Names of all registers.					*/
+char *regnames[MAXR+1]={"noreg","%eax","%ecx","%edx","%ebx",
+				"%esi","%edi","%ebp","%esp",
+				"%st(0)","%st(1)","%st(2)","%st(3)",
+				"%st(4)","%st(5)","%st(6)","%st(7)"};
+
+/*  The Size of each register in bytes. 			*/
+zlong regsize[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,1,0,0,0,0,0,1,1,1,1,1,1,1,1};
+
+
+/****************************************/
+/*  Some private data and functions.	*/
+/****************************************/
+
+static long malign[16]={1,1,2,2,2,2,2,2,2,2,2,2,2,2,2};
+static long msizetab[16]={0,1,2,4,4,4,8,0,4,0,0,0,4,0};
+
+
+#define DATA 0
+#define BSS 1
+#define CODE 2
+
+static int section=-1,newobj;
+static char *codename="\t.text\n",*dataname="\t.data\n",*bssname="";
+static int is_const(struct Typ *);
+static const int ax=1,cx=2,dx=3,bx=4,si=5,di=6,bp=7,sp=8;
+static char x_t[]={'?','b','w','l','l','s','l','v','l','a','s','u','e','f','?','?'};
+static int is_const(struct Typ *);
+static void pr(FILE *,struct IC *);
+static void function_top(FILE *,struct Var *,long);
+static void function_bottom(FILE *f,struct Var *,long);
+
+#define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
+
+static long loff,stackoffset,notpopped,dontpop;
+
+static char *ccs[]={"z","nz","l","ge","le","g","mp"};
+static char *ccu[]={"z","nz","b","ae","be","a","mp"};
+static char *logicals[]={"or","xor","and"};
+static char *arithmetics[]={"sal","sar","add","sub","imul","div","mod"};
+static char *farithmetics[]={"f?","f?","fadd","fsub","fmul","fdiv","fsubr","fdivr"};
+static char *dct[]={"","byte","short","long","long","long","long","long","long"};
+static pushedsize,pushorder=2;
+static int fst[8];
+static int cxl,dil,sil;
+static char *idprefix="_",*labprefix="l";
+
+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&&zdeqto(vdouble,zf2zd(o->val.vfloat))) return(p->label);
+		if(t==DOUBLE&&zdeqto(vdouble,o->val.vdouble)) 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);
+}
+
+void title(FILE *f)
+{
+  static int done;
+  extern char *inname; /*grmpf*/
+  if(!done&&f){
+    done=1;
+    emit(f,"\t.file\t\"%s\"\n",inname);
+  }
+} 
+
+static void probj2(FILE *f,struct obj *p,int t)
+/*  Gibt Objekt auf Bildschirm aus			*/
+{
+    if((p->flags&(DREFOBJ|REG))==(DREFOBJ|REG)) fprintf(f,"(");
+    if(p->flags&VARADR) fprintf(f,"$");
+    if((p->flags&VAR)&&!(p->flags&REG)) {
+	if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER){
+	    if(p->v->offset<0) fprintf(f,"%ld(%%esp)",(long)(loff-zl2l(p->v->offset)+zl2l(p->val.vlong))-stackoffset+pushedsize);
+		else	       fprintf(f,"%ld(%%esp)",(long)(zl2l(p->v->offset)+zl2l(p->val.vlong)-stackoffset));
+	}else{
+	    if(!zleqto(l2zl(0L),p->val.vlong)){printval(f,&p->val,LONG,0);fprintf(f,"+");}
+	    if(p->v->storage_class==STATIC&&(p->v->vtyp->flags&NQ)!=FUNKT){
+		fprintf(f,"%s%ld",labprefix,zl2l(p->v->offset));
+	    }else{
+		fprintf(f,"%s%s",idprefix,p->v->identifier);
+	    }
+	}
+    }
+    if(p->flags&REG){
+	if(p->reg>8){
+	    int i;
+	    for(i=0;i<8;i++){
+		if(fst[i]==p->reg)
+		    fprintf(f,"%s",regnames[i+9]);
+	    }
+	}else{
+	    fprintf(f,"%s",regnames[p->reg]);
+	}
+    }
+    if(p->flags&KONST){
+	if((t&NQ)==FLOAT||(t&NQ)==DOUBLE){
+	    fprintf(f,"%s%d",labprefix,addfpconst(p,t));
+	}else{
+	    fprintf(f,"$");printval(f,&p->val,t&NU,0);
+	}
+    }
+    if((p->flags&(DREFOBJ|REG))==(DREFOBJ|REG)) fprintf(f,")");
+}
+static void fxch(FILE *f,int i)
+{
+    int m;
+    fprintf(f,"\tfxch\t%s\n",regnames[i+9]);
+    m=fst[0];fst[0]=fst[i];fst[i]=m;
+}
+static int freest(void)
+{
+    int i;
+    for(i=0;i<8;i++){
+	if(fst[i]<0) return(i);
+    }
+    for(i=0;i<8;i++){
+	if(fst[i]==0) return(i);
+    }
+    ierror(0);
+}
+static void fpush(FILE *f)
+{
+    int i;
+    if(fst[7]>0){
+	i=freest();
+	if(fst[i]==0) fprintf(f,"\tffree\t%s\n",regnames[i+9]);
+	fxch(f,i);fxch(f,7);
+    }
+    for(i=7;i>0;i--)
+	fst[i]=fst[i-1];
+    fst[0]=-1;
+}
+static void fpop(void)
+{
+    int i;
+/*    if(fst[0]>0&&regs[fst[0]]) ierror(0);*/
+    for(i=0;i<7;i++)
+	fst[i]=fst[i+1];
+    fst[7]=-1;
+}
+static void fload(FILE *f,struct obj *o,int t)
+{
+    fprintf(f,"\tfld");
+    if((o->flags&(REG|DREFOBJ))==REG) fprintf(f,"\t");
+	else fprintf(f,"%c\t",x_t[t&NQ]);
+    probj2(f,o,t);fprintf(f,"\n");
+    fpush(f);
+}
+static void fstore(FILE *f,struct obj *o,int t)
+{
+    int i;
+    if((o->flags&(REG|DREFOBJ))==REG){
+	for(i=0;i<8;i++)
+	    if(fst[i]==o->reg) fst[i]=-1;
+	fst[0]=o->reg;
+    }else{
+	fprintf(f,"\tfstp%c\t",x_t[t&NQ]);probj2(f,o,t);
+	fpop();fprintf(f,"\n");
+    }
+}
+static void prfst(FILE *f,char *s)
+{
+    int i;
+    if(DEBUG==0) return;
+    fprintf(f,"*\t%s\t",s);
+    for(i=0;i<8;i++){
+	if(fst[i]>=0){
+	    if(fst[i]==0) fprintf(f,"+++ ");
+	      else	  fprintf(f,"%s ",regnames[fst[i]]+3);
+	}else{
+	    fprintf(f,"--- ");
+	}
+    }
+    fprintf(f,"\n");
+}
+static void finit(void)
+{
+    int i;
+    for(i=0;i<8;i++){
+	if(regs[i+9])
+	    fst[i]=i+9;
+	else
+	    fst[i]=-1;
+    }
+}
+static void forder(FILE *f)
+{
+    int i,m,unordered;
+    prfst(f,"forder");
+    for(i=0;i<8;i++){
+	if(fst[i]==0){fprintf(f,"\tffree\t%s\n",regnames[i+9]);fst[i]=-1;}
+    }
+oloop:
+    unordered=0;
+    for(i=0;i<8;i++){
+	if(fst[i]>0&&fst[i]!=i+9&&regs[fst[i]]){unordered=1;break;}
+    }
+    if(!unordered) return;
+    if(fst[0]>=0&&regs[fst[0]]){
+	if(fst[0]!=9){
+	    fxch(f,fst[0]-9);
+	    goto oloop;
+	}else{
+	    fxch(f,freest());
+	}
+    }
+    for(i=1;i<8;i++){
+	if(fst[i]>=0&&fst[i]!=i+9&&regs[fst[i]]&&fst[i]!=9){
+	    fxch(f,i);
+	    goto oloop;
+	}
+    }
+    if(regs[9]){
+	for(i=1;i<8;i++){
+	    if(fst[i]==9){ fxch(f,i);return;}
+	}
+    }
+}
+static void pr(FILE *f,struct IC *p)
+{
+    int i;
+    for(;pushorder>2;pushorder>>=1){
+	for(i=1;i<=8;i++){
+	    if(regs[i]&pushorder){
+		fprintf(f,"\tpopl\t%s\n",regnames[i]);
+		stackoffset+=4;regs[i]&=~pushorder;
+	    }
+	}
+    }
+    for(i=1;i<=8;i++)
+	if(regs[i]&2) regs[i]&=~2;
+}
+
+/*ADA*/
+static int local_debug_line_count;
+static int local_debug_func_count;
+static char * debug_offset_func = NULL;
+
+static void emitdebugline (FILE *f, int line)
+{
+  if(g_flags[8]&USEDFLAG){
+    if (debug_offset_func && line)
+      {
+	/*
+	  Tell GDB that a new line starts here.
+	  
+	  Format: 68,0,<line>,<offset>
+	  
+	  <line> is the current line number
+	  <offset> is the offset to the current function.
+	  */
+	fprintf (f, ".stabn 68,0,%d,%sM%d-%s\n", line, labprefix, local_debug_line_count, debug_offset_func);
+	fprintf (f, "%sM%d:\n", labprefix, local_debug_line_count);
+	local_debug_line_count ++;
+    }
+  }
+}
+
+#ifndef PATH_MAX
+#   define PATH_MAX  1024
+#endif
+
+static int next_free_typeid = 32;
+
+static void begin_file (FILE *f, char *name)
+{
+    char * ptr;
+    char path[PATH_MAX];
+    int len1, len2, t;
+
+    ptr = strrchr (name, '/');
+    if (!ptr)
+	ptr = name-1;
+
+    /* Filename without path */
+    fprintf (f, "\t.file\t\"%s\"\n", ptr+1);
+    fprintf (f, "\t.version\t\"01.01\"\n");
+
+    getcwd (path, sizeof(path));
+    strcat (path, "/");
+    if (ptr != name-1)
+    {
+	len1 = strlen(path);
+	len2 = ptr-name;
+	strncpy (path+len1, name, len2);
+	path[len1+len2] = 0;
+	strcat (path, "/");
+    }
+
+    /* Emit absolute path to source file and the filename with any
+	path the user gave to the frontend */
+    fprintf (f, "\t.stabs \"%s\",%d,0,0,%stext0\n", path, N_SO, labprefix);
+    fprintf (f, "\t.stabs \"%s\",%d,0,0,%stext0\n", name, N_SO, labprefix);
+    fprintf (f, ".text\n%stext0:\n",labprefix);
+    fprintf (f, "\t.stabs  \"vbcc_compiled.\", 0x3c, 0, 0, 0\n");
+
+    /* Emit types. Format is:
+
+	"<name>:<t#1>=<r#2;min;max;>",128,0,0,0
+
+	128,0,0,0 tells GDB this is a type definition
+	<name> is the name of the symbol.
+	<t#1> is the name of the type and its number
+        <r#2;min;max;> is a range. The min and max values are in the format
+               of the type #2. min and max values for this type can be
+               omitted.
+        void is defined by <t#1=#1>.
+      */
+    for (t=CHAR; t<=LONG; t++)
+      {
+	fprintf (f, ".stabs \"%s:t%d=r%d;%ld;%ld;\",%d,0,0,0\n", typname[t],t,t==CHAR ? CHAR:INT,
+		 zl2l(t_min[t]),zl2l(t_max[t]),N_LSYM);
+	fprintf (f, ".stabs \"unsigned %s:t%d=r%d;%lu;%lu;\",%d,0,0,0\n", typname[t],
+		 t|UNSIGNED, INT,
+		 zul2ul(t_min[t|UNSIGNED]),zul2ul(t_max[t|UNSIGNED]), N_LSYM);
+      }
+ 
+    fprintf (f, ".stabs \"float:t%d=r%d;%ld;0;\",%d,0,0,0\n",
+	     FLOAT,INT,zl2l(sizetab[FLOAT]),N_LSYM);
+    fprintf (f, ".stabs \"double:t%d=r%d;%ld;0;\",%d,0,0,0\n",
+	     DOUBLE,INT,zl2l(sizetab[DOUBLE]),N_LSYM);
+    fprintf (f, ".stabs \"void:t%d=r%d\",%d,0,0,0\n",
+	     VOID,VOID,N_LSYM);
+	     
+ 
+    /*
+      fprintf (f, ".stabs \"char:t2=r2;0;127;\",128,0,0,0\n");
+      fprintf (f, ".stabs \"int:t1=r1;-2147483648;2147483647;\",128,0,0,0\n");
+      fprintf (f, ".stabs \"long int:t3=r1;-2147483648;2147483647;\",128,0,0,0\n");
+      fprintf (f, ".stabs \"unsigned int:t4=r1;0;-1;\",128,0,0,0\n");
+      fprintf (f, ".stabs \"long unsigned int:t5=r1;0;-1;\",128,0,0,0\n");
+      fprintf (f, ".stabs \"void:t19=19\",128,0,0,0\n");
+      */
+}
+
+static void debug_print_stab_type (FILE *f, struct Typ *typ)
+{
+  int t = typ->flags & NU;
+  
+  if (t <= VOID)
+    fprintf (f, "%d", t);
+  else if (t == ARRAY || t == POINTER)
+    {
+      fprintf (f, "%d=*", next_free_typeid++);
+      debug_print_stab_type (f, typ->next);
+    }
+  else
+    {
+      ierror(t);
+    }
+}
+
+
+static void function_top(FILE *f,struct Var *v,long offset)
+/*  erzeugt Funktionskopf			*/
+{
+    int i;
+    struct struct_declaration *p;
+
+    if(section!=CODE){fprintf(f,codename);section=CODE;}
+
+    /*ADA*/
+    if(g_flags[8]&USEDFLAG){ /*vb*/
+      fprintf (f, "\t.align\t16\n");
+      /* Tell GDB that a new function starts here.
+	 
+	 Format: "<name>:F<type>",36,0,<line>,<symname>
+	 
+	 <name> Is the name of the function
+	 <type> is the return type (only the number as defined above, ie.
+	        if int is t1, then this is 1).
+	 <line> The line in the source
+	 <symname> The name of the symbol as it appears in the object file.
+
+	 Right now, all functions return void.
+	 */
+
+      fprintf (f, ".stabs \"%s:F", v->identifier);
+      debug_print_stab_type (f, v->vtyp->next);
+      fprintf (f, "\",%d,0,%d,%s%s\n", N_FUN, fline, idprefix,v->identifier);
+  
+      p=v->vtyp->exact;
+      for (i=0; i<p->count; i++)
+	{
+	  if((*p->sl)[i].styp->flags==VOID) break;
+	  fprintf (f, ".stabs \"%s:p", (*p->sl)[i].identifier);
+	  debug_print_stab_type (f, (*p->sl)[i].styp);
+	  /* TODO i*4+4 is a crude method to find the offset of a parameter on
+	     the stack */
+	  fprintf (f, "\",%d,0,0,%d\n", N_PSYM, i*4+4);
+	}
+    }
+
+    if(v->storage_class==EXTERN) fprintf(f,"\t.globl\t%s%s\n",idprefix,v->identifier);
+    fprintf(f,"%s%s:\n",idprefix,v->identifier);
+
+    /*ADA*/
+    debug_offset_func=v->identifier;
+
+    for(pushedsize=0,i=1;i<sp;i++){
+	if(regused[i]&&!regscratch[i]){
+	    fprintf(f,"\tpushl\t%s\n",regnames[i]);
+	    pushedsize+=4;
+	}
+    }
+
+    if(offset) fprintf(f,"\tsubl\t$%ld,%%esp\n",offset);
+    if(g_flags[7]&USEDFLAG) fprintf(f,"\tmovl\t%s,%s\n",regnames[sp],regnames[7]);
+    if(g_flags[8]&USEDFLAG){
+      /* Tell GDB that the code of the function starts here */
+      emitdebugline (f,fline);
+      local_debug_func_count ++;
+      fprintf (f, "%sBB%d:\n", labprefix, local_debug_func_count);
+    }
+}
+static void function_bottom(FILE *f,struct Var *v,long offset)
+/*  erzeugt Funktionsende			*/
+{
+    int i;
+    forder(f);
+
+    if(g_flags[8]&USEDFLAG){
+      emitdebugline (f,fline);
+      fprintf (f, "%sBE%d:\n", labprefix, local_debug_func_count);
+    }
+
+    if(offset) fprintf(f,"\taddl\t$%ld,%%esp\n",offset);
+    for(i=sp-1;i>0;i--){
+	if(regused[i]&&!regscratch[i]){
+	    fprintf(f,"\tpopl\t%s\n",regnames[i]);
+	}
+    }
+    fprintf(f,"\tret\n");
+    
+    if(g_flags[8]&USEDFLAG){
+      fprintf (f, "%sfe%d:\n\t.size\t%s,%sfe%d-%s%s\n", labprefix, local_debug_func_count, v->identifier, labprefix, local_debug_func_count, idprefix,v->identifier);
+      /* Tell GDB the real size of the function */
+      fprintf (f, ".stabn 192,0,0,%sBB%d-%s%s\n",labprefix,local_debug_func_count, idprefix,v->identifier);
+      fprintf (f, ".stabn 224,0,0,%sBE%d-%s%s\n", labprefix, local_debug_func_count, idprefix,v->identifier);
+    }
+}
+static int is_const(struct Typ *t)
+/*  Tests if a type can be placed in the code-section.	*/
+{
+    if(!(t->flags&(CONST|STRINGCONST))){
+	do{
+	    if(t->flags&(CONST|STRINGCONST)) return(1);
+	    if((t->flags&NQ)!=ARRAY) return(0);
+	    t=t->next;
+	}while(1);
+    }else return(1);
+}
+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&&zleqto(o1->val.vlong,o2->val.vlong))){
+	    if(!(o1->flags&REG)||o1->reg==o2->reg){
+		return(1);
+	    }
+	}
+    }
+    return(0);
+}
+static int get_reg(FILE *f,struct IC *p)
+{
+    int i;
+    /*	If we can use a register which was already used by the compiler */
+    /*	or it is a sratch register then we can use it without problems. */
+    for(i=1;i<=8;i++){
+	if(!regs[i]&&(regused[i]||regscratch[i])){
+	    regs[i]=2;
+	    return(i);
+	}
+    }
+    /*	Otherwise we have to save this register.			*/
+    /*	We may not use a register which is used in this IC.		*/
+    for(i=1;i<=8;i++){
+	if(regs[i]<2
+	    &&(!(p->q1.flags&REG)||p->q1.reg!=i)
+	    &&(!(p->q2.flags&REG)||p->q2.reg!=i)
+	    &&(!(p->z.flags&REG)||p->z.reg!=i) ){
+
+	    fprintf(f,"\tpushl\t%s\n",regnames[i]);
+	    /*	Mark register as pushed (taking care of the order). */
+	    pushorder<<=1; regs[i]|=pushorder;
+	    stackoffset-=4;
+	    return(i);
+	}
+    }
+    ierror(0);
+}
+static void move(FILE *f,struct obj *q,int qr,struct obj *z,int zr,int t)
+/*  Generates code to move object q (or register qr) into object z (or  */
+/*  register zr).							*/
+{
+    if(q&&(q->flags&(REG|DREFOBJ))==REG) qr=q->reg;
+    if(z&&(z->flags&(REG|DREFOBJ))==REG) zr=z->reg;
+    if(qr&&zr){
+	if(qr!=zr)
+	    fprintf(f,"\tmovl\t%s,%s\n",regnames[qr],regnames[zr]);
+	return;
+    }
+    if(zr&&(q->flags&KONST)){
+	eval_const(&q->val,t);
+	if(zleqto(vlong,l2zl(0L))&&zuleqto(vulong,ul2zul(0UL))&&zdeqto(vdouble,d2zd(0.0))){
+	    fprintf(f,"\txorl\t%s,%s\n",regnames[zr],regnames[zr]);
+	    return;
+	}
+    }
+    fprintf(f,"\tmov%c\t",x_t[t&NQ]);
+    if(qr) fprintf(f,"%s",regnames[qr]); else probj2(f,q,t);
+    fprintf(f,",");
+    if(zr) fprintf(f,"%s",regnames[zr]); else probj2(f,z,t);
+    fprintf(f,"\n");
+}
+static long pof2(zulong x)
+/*  Yields log2(x)+1 oder 0. */
+{
+    zulong p;int ln=1;
+    p=ul2zul(1L);
+    while(zulleq(p,x)){
+	if(zuleqto(x,p)) return(ln);
+	ln++;p=zuladd(p,p);
+    }
+    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;
+
+    /*	Initialize some values which cannot be statically initialized	*/
+    /*	because they are stored in the target's arithmetic.             */
+    maxalign=l2zl(4L);
+    char_bit=l2zl(8L);
+    if(g_flags[6]&USEDFLAG){
+	for(i=SHORT;i<16;i++) malign[i]=4;
+    }
+    for(i=0;i<16;i++){
+	sizetab[i]=l2zl(msizetab[i]);
+	align[i]=l2zl(malign[i]);
+    }
+    for(i=1;i<= 8;i++) regsize[i]=l2zl(4L);
+    for(i=9;i<=16;i++) regsize[i]=l2zl(8L);
+
+    /*	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.		*/
+    t_min[UNSIGNED|CHAR]=t_min[UNSIGNED|SHORT]=t_min[UNSIGNED|INT]=t_min[UNSIGNED|LONG]=l2zl(0L);
+    t_min[CHAR]=l2zl(-128L);
+    t_min[SHORT]=l2zl(-32768L);
+    t_min[LONG]=zlsub(l2zl(-2147483647L),l2zl(1L));
+    t_min[INT]=t_min[LONG];
+    t_max[CHAR]=ul2zul(127L);
+    t_max[SHORT]=ul2zul(32767UL);
+    t_max[LONG]=ul2zul(2147483647UL);
+    t_max[INT]=t_max[LONG];
+    t_max[UNSIGNED|CHAR]=ul2zul(255UL);
+    t_max[UNSIGNED|SHORT]=ul2zul(65535UL);
+    t_max[UNSIGNED|LONG]=ul2zul(4294967295UL);
+    t_max[UNSIGNED|INT]=t_max[UNSIGNED|LONG];
+    /*	Reserve a few registers for use by the code-generator.	    */
+    /*	We only reserve the stack-pointer here. 		    */
+    regsa[sp]=1;
+    /*  If we are to use a framepointer also reserve %ebp.          */
+    if(g_flags[7]&USEDFLAG) regsa[7]=1;
+    /*	We need at least one free slot in the flaoting point stack  */
+    regsa[16]=1;regscratch[16]=0;
+    /*	Use l%d as labels and _%s as identifiers by default. If     */
+    /*	-elf is specified we use .l%d and %s instead.		    */
+    if(g_flags[5]&USEDFLAG) {labprefix=".L";idprefix="";}
+    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.	    */
+{
+    if((t->flags&NQ)==FLOAT||(t->flags&NQ)==DOUBLE) return 9;
+    if((t->flags&NQ)<=POINTER) return 1;
+    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(r==0) return(0);
+    t&=NQ;
+    if(r>8){
+	if(t==FLOAT||t==DOUBLE) return(1);
+	    else		return(0);
+    }
+    if(t==CHAR&&(r==si||r==di||r==bp)) return(0);
+    if(t<=LONG) return(1);
+    if(t==POINTER) return(1);
+    return(0);
+}
+
+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(0);
+    if((c==DIV||c==MOD)&&!(p->q2.flags&KONST))
+	return(1);
+    return(0);
+}
+
+int must_convert(np p,int t)
+/*  Returns zero if code for converting np to type t	*/
+/*  can be omitted.					*/
+/*  In this generic 32bit RISC cpu pointers and 32bit	*/
+/*  integers have the same representation and can use	*/
+/*  the same registers. 				*/
+{
+    int o=p->ntyp->flags,op=o&NQ,tp=t&NQ;
+    if(tp==POINTER&&op==POINTER) return(0);
+    if((t&UNSIGNED)&&(o&UNSIGNED)&&zleqto(sizetab[tp],sizetab[op])) return(0);
+    if((tp==INT&&op==LONG)||(tp==LONG&&op==INT)) return(0);
+
+    return(1);
+}
+
+void gen_ds(FILE *f,zlong size,struct Typ *t)
+/*  This function has to create <size> bytes of storage */
+/*  initialized with zero.				*/
+{
+  title(f);
+  if(newobj) fprintf(f,"%ld\n",zl2l(size));
+  else fprintf(f,"\t.space\t%ld\n",zl2l(size));
+  newobj=0;
+}
+
+void gen_align(FILE *f,zlong align)
+/*  This function has to make sure the next data is	*/
+/*  aligned to multiples of <align> bytes.		*/
+{
+  title(f);
+  if(!zlleq(align,l2zl(1L))) fprintf(f,"\t.align\t2\n");
+}
+
+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;
+  title(f);
+  if(v->clist) constflag=is_const(v->vtyp);
+  if(v->storage_class==STATIC){
+	if((v->vtyp->flags&NQ)==FUNKT) return;
+	if(v->clist&&(!constflag||(g_flags[3]&USEDFLAG))&&section!=DATA){fprintf(f,dataname);section=DATA;}
+	if(v->clist&&constflag&&!(g_flags[3]&USEDFLAG)&&section!=CODE){fprintf(f,codename);section=CODE;}
+	if(!v->clist&&section!=BSS){fprintf(f,bssname);section=BSS;}
+	if(section!=BSS) fprintf(f,"\t.align\t2\n%s%ld:\n",labprefix,zl2l(v->offset));
+	    else fprintf(f,"\t.lcomm\t%s%ld,",labprefix,zl2l(v->offset));
+	newobj=1;
+    }
+    if(v->storage_class==EXTERN){
+	fprintf(f,"\t.globl\t%s%s\n",idprefix,v->identifier);
+	if(v->flags&(DEFINED|TENTATIVE)){
+	    if(v->clist&&(!constflag||(g_flags[3]&USEDFLAG))&&section!=DATA){fprintf(f,dataname);section=DATA;}
+	    if(v->clist&&constflag&&!(g_flags[3]&USEDFLAG)&&section!=CODE){fprintf(f,codename);section=CODE;}
+	    if(!v->clist&&section!=BSS){fprintf(f,bssname);section=BSS;}
+	    if(section!=BSS) fprintf(f,"\t.align\t2\n%s%s:\n",idprefix,v->identifier);
+		else fprintf(f,"\t.comm\t%s%s,",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.			*/
+{
+    title(f);
+    fprintf(f,"\t.%s\t",dct[t&NQ]);
+    if(!p->tree){
+	if((t&NQ)==FLOAT||(t&NQ)==DOUBLE){
+	/*  auch wieder nicht sehr schoen und IEEE noetig   */
+	    unsigned char *ip;
+	    ip=(unsigned char *)&p->val.vdouble;
+	    fprintf(f,"0x%02x%02x%02x%02x",ip[3],ip[2],ip[1],ip[0]);
+	    if((t&NQ)==DOUBLE){
+		fprintf(f,",0x%02x%02x%02x%02x",ip[7],ip[6],ip[5],ip[4]);
+	    }
+	}else{
+	    printval(f,&p->val,t&NU,0);
+	}
+    }else{
+	int m=p->tree->o.flags;
+	p->tree->o.flags&=~VARADR;
+	probj2(f,&p->tree->o,t&NU);
+	p->tree->o.flags=m;
+    }
+    fprintf(f,"\n");newobj=0;
+}
+
+/*  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 *p,struct Var *v,zlong offset)
+{
+    int c,t,lastcomp=0,reg;
+    int lastline=-1;
+
+    if(DEBUG&1) printf("gen_code()\n");
+    for(c=1;c<=15;c++) regs[c]=regsa[c];
+    regs[16]=0;
+    loff=((zl2l(offset)+1)/2)*2;
+    title(f);
+    function_top(f,v,loff);
+    stackoffset=notpopped=dontpop=0;
+    finit();
+    for(;p;pr(f,p),p=p->next){
+	c=p->code;t=p->typf;
+	if(c==NOP) continue;
+
+/*ADA*/
+if (lastline != p->line)
+{
+    emitdebugline(f,p->line);
+    lastline = p->line;
+}
+
+	if(c==SUBPFP) c=SUB;
+	if(c==SUBIFP) c=SUB;
+	if(c==ADDI2P) c=ADD;
+	if(c==ALLOCREG){
+	    regs[p->q1.reg]=1;
+	    continue;
+	}
+	if(c==FREEREG){
+	    if(p->q1.reg>=9){
+		for(c=0;c<8;c++)
+		    if(fst[c]==p->q1.reg) fst[c]=0;
+	    }
+	    regs[p->q1.reg]=0;
+	    continue;
+	}
+	if(notpopped&&!dontpop){
+	    int flag=0;
+	    if(c==LABEL||c==COMPARE||c==TEST||c==BRA){
+		fprintf(f,"\taddl\t$%ld,%%esp\n",notpopped);
+		stackoffset+=notpopped;notpopped=0;
+	    }
+	}
+	if(c==LABEL) {forder(f);fprintf(f,"%s%d:\n",labprefix,t);continue;}
+	if(c>=BEQ&&c<=BRA){
+	    forder(f);
+	    if(lastcomp&UNSIGNED) fprintf(f,"\tj%s\t%s%d\n",ccu[c-BEQ],labprefix,t);
+		else		  fprintf(f,"\tj%s\t%s%d\n",ccs[c-BEQ],labprefix,t);
+	    continue;
+	}
+	if(c==MOVETOREG){
+	    if(p->z.reg>8){
+		for(c=0;c<8;c++){
+		    if(fst[c]==p->z.reg) fst[c]=0;
+		}
+		fload(f,&p->q1,DOUBLE);
+		fst[0]=p->z.reg;
+		continue;
+	    }
+	    move(f,&p->q1,0,0,p->z.reg,LONG);
+	    continue;
+	}
+	if(c==MOVEFROMREG){
+	    if(p->q1.reg>8){
+		if(fst[0]!=p->q1.reg){
+		    for(c=0,reg=-1;c<8;c++){
+			if(fst[c]==p->q1.reg) reg=c;
+		    }
+		    if(reg<0) ierror(0);
+		    fxch(f,reg);
+		}
+		fprintf(f,"\tfstpl\t");probj2(f,&p->z,DOUBLE);
+		fprintf(f,"\n");fpop();
+		continue;
+	    }
+	    move(f,0,p->q1.reg,&p->z,0,LONG);
+	    continue;
+	}
+	if((p->q1.flags&(DREFOBJ|REG))==DREFOBJ){
+	    reg=get_reg(f,p);
+	    move(f,&p->q1,0,0,reg,LONG);
+	    p->q1.flags|=REG;p->q1.reg=reg;
+	}
+	if((p->q2.flags&(DREFOBJ|REG))==DREFOBJ){
+	    reg=get_reg(f,p);
+	    move(f,&p->q2,0,0,reg,LONG);
+	    p->q2.flags|=REG;p->q2.reg=reg;
+	}
+	if((p->z.flags&(DREFOBJ|REG))==DREFOBJ){
+	    reg=get_reg(f,p);
+	    move(f,&p->z,0,0,reg,LONG);
+	    p->z.flags|=REG;p->z.reg=reg;
+	}
+	if(c>=CONVCHAR&&c<=CONVULONG){
+	    int to;
+	    if(c==CONVCHAR) to=CHAR;
+	    if(c==CONVUCHAR) to=(UNSIGNED|CHAR);
+	    if(c==CONVSHORT) to=SHORT;
+	    if(c==CONVUSHORT) to=(UNSIGNED|SHORT);
+	    if(c==CONVINT) to=INT;
+	    if(c==CONVUINT) to=(UNSIGNED|INT);
+	    if(c==CONVLONG) to=INT;
+	    if(c==CONVULONG) to=(UNSIGNED|INT);
+	    if(c==CONVFLOAT) to=FLOAT;
+	    if(c==CONVDOUBLE) to=DOUBLE;
+	    if(c==CONVPOINTER) to=(UNSIGNED|INT);
+	    if((t&NU)==LONG) t=INT;
+	    if((t&NU)==(UNSIGNED|LONG)||(t&NU)==POINTER) t=(UNSIGNED|INT);
+	    if((to&NQ)<=INT&&(t&NQ)<=INT){
+		if(isreg(z)) reg=p->z.reg;
+		else if(isreg(q1)) reg=p->q1.reg;
+		else reg=get_reg(f,p);
+		if((to&NQ)<=SHORT){
+		    fprintf(f,"\tmov%c%cl\t",(to&UNSIGNED)?'z':'s',x_t[to&NQ]);
+		    if(isreg(q1)){
+			if((to&NQ)==SHORT){
+			    fprintf(f,"%%%s",regnames[p->q1.reg]+2);
+			}else{
+			    fprintf(f,"%%%cl",regnames[p->q1.reg][2]);
+			}
+		    }else probj2(f,&p->q1,to);
+		    fprintf(f,",%s\n",regnames[reg]);
+		}else{
+		    move(f,&p->q1,0,0,reg,to);
+		}
+		move(f,0,reg,&p->z,0,t);
+		continue;
+	    }
+	    if((t&NQ)==FLOAT||(t&NQ)==DOUBLE){
+		if((to&NQ)==FLOAT||(to&NQ)==DOUBLE){
+		    if(isreg(q1)&&fst[0]==p->q1.reg){
+			if(isreg(z)){
+			    if(p->z.reg==fst[0]) continue;
+			    for(reg=0,c=7;c>=0;c--){
+				if(fst[c]==p->z.reg){reg=c;break;}
+				if(fst[c]<0) reg=c;
+			    }
+			    fst[reg]=p->z.reg;
+			}
+			fprintf(f,"\tfst%c\t",x_t[t&NQ]);
+			probj2(f,&p->z,t);fprintf(f,"\n");
+			continue;
+		    }
+		    fload(f,&p->q1,to);
+		    fstore(f,&p->z,t);
+		    continue;
+		}
+		if((to&NQ)<=SHORT){
+		    if(isreg(q1)){
+			reg=p->q1.reg;
+			if(to&UNSIGNED){
+			    fprintf(f,"\tandl\t$%ld,%s\n",(to&NQ)==CHAR?255L:65535L,regnames[reg]);
+			}else{
+/*			      fprintf(f,"\tc%ctl\t%s\n",x_t[to&NQ],regnames[reg]);*/
+			    if((to&NQ)==SHORT){
+				fprintf(f,"\tmovswl\t%%%s,%s\n",regnames[reg]+2,regnames[reg]);
+			    }else{
+				fprintf(f,"\tmovsbl\t%%%cl,%s\n",regnames[reg][2],regnames[reg]);
+			    }
+			}
+		    }else{
+			reg=get_reg(f,p);
+			if(to&UNSIGNED){
+			    fprintf(f,"\tmovz%cl\t",x_t[to&NQ]);
+			}else{
+			    fprintf(f,"\tmovs%cl\t",x_t[to&NQ]);
+			}
+			probj2(f,&p->q1,to);fprintf(f,",%s\n",regnames[reg]);
+		    }
+		    fprintf(f,"\tpushl\t%s\n",regnames[reg]);
+		    fprintf(f,"\tfildl\t(%s)\n\taddl\t$4,%s\n",regnames[sp],regnames[sp]);
+		}else{
+		    if(to&UNSIGNED){
+			fprintf(f,"\tpushl\t$0\n\tpushl\t");stackoffset-=4;
+			probj2(f,&p->q1,to);
+			fprintf(f,"\n\tfildq\t(%s)\n\taddl\t$8,%s\n",regnames[sp],regnames[sp]);
+			stackoffset+=4;
+		    }else{
+			if(isreg(q1)){
+			    fprintf(f,"\tpushl\t%s\n\tfildl\t(%s)\n\taddl\t$4,%s\n",regnames[p->q1.reg],regnames[sp],regnames[sp]);
+			}else{
+			    fprintf(f,"\tfildl\t");probj2(f,&p->q1,t);
+			    fprintf(f,"\n");
+			}
+		    }
+		}
+		fpush(f);
+		fstore(f,&p->z,t);
+		continue;
+	    }
+	    if((to&NQ)==FLOAT||(to&NQ)==DOUBLE){
+		if(isreg(q1)&&fst[0]==p->q1.reg){
+		    if((t&NQ)==CHAR){
+			if(isreg(z)) reg=p->z.reg; else reg=get_reg(f,p);
+			fprintf(f,"\tsubl\t$4,%s\n\tfistl\t(%s)\n\tmovsbl\t(%s),%s\n\taddl\t$4,%s\n",regnames[sp],regnames[sp],regnames[sp],regnames[reg],regnames[sp]);
+			move(f,0,reg,&p->z,0,t);
+		    }else{
+		      if(isreg(z)){
+			fprintf(f,"\tsubl\t$4,%s\n\tfistl\t(%s)\n\tmov%c\t(%s),",regnames[sp],regnames[sp],x_t[t&NQ],regnames[sp]);
+			stackoffset-=4;
+			probj2(f,&p->z,t);fprintf(f,"\n\taddl\t$4,%s\n",regnames[sp]);
+			stackoffset+=4;
+		      }else{
+			fprintf(f,"\tfist%c\t",x_t[t&NQ]);
+			probj2(f,&p->z,t);fprintf(f,"\n");
+		      }
+		    }
+		}else{
+		    fload(f,&p->q1,to);
+		    if((t&NQ)==CHAR){
+			if(isreg(z)) reg=p->z.reg; else reg=get_reg(f,p);
+			fprintf(f,"\tsubl\t$4,%s\n\tfistpl\t(%s)\n\tmovsbl\t(%s),%s\n\taddl\t$4,%s\n",regnames[sp],regnames[sp],regnames[sp],regnames[reg],regnames[sp]);
+			fpop(); move(f,0,reg,&p->z,0,t);
+		    }else{
+		      if(isreg(z)){
+			fprintf(f,"\tsubl\t$4,%s\n\tfistpl\t(%s)\n\tmov%c\t(%s),",regnames[sp],regnames[sp],x_t[t&NQ],regnames[sp]);
+			stackoffset-=4;
+			probj2(f,&p->z,t);fprintf(f,"\n\taddl\t$4,%s\n",regnames[sp]);
+			stackoffset+=4;fpop();
+		      }else{
+			fprintf(f,"\tfistp%c\t",x_t[t&NQ]);
+			probj2(f,&p->z,t);fprintf(f,"\n");fpop();
+		      }
+		    }
+		}
+		continue;
+	    }
+	    ierror(0);
+	}
+	if(c==MINUS||c==KOMPLEMENT){
+	    char *s;
+	    if((t&NQ)==FLOAT||(t&NQ)==DOUBLE){
+		if(isreg(z)&&p->z.reg==9&&isreg(q1)&&p->q1.reg==9){
+		    fprintf(f,"\tfchs\n");
+		    continue;
+		}
+		fload(f,&p->q1,t);
+		fprintf(f,"\tfchs\n");
+		fprintf(f,"\tfstp%c\t",x_t[t&NQ]);
+		probj2(f,&p->z,t);fprintf(f,"\n");
+		fpop();
+		continue;
+	    }
+	    if(c==MINUS) s="neg"; else s="not";
+	    if(compare_objects(&p->q1,&p->q2)){
+		fprintf(f,"\t%s%c\t",s,x_t[t&NQ]);
+		probj2(f,&p->z,t);fprintf(f,"\n");
+		continue;
+	    }
+	    if(isreg(z)) reg=p->z.reg; else reg=get_reg(f,p);
+	    move(f,&p->q1,0,0,reg,t);
+	    fprintf(f,"\t%s%c\t%s\n",s,x_t[t&NQ],regnames[reg]);
+	    move(f,0,reg,&p->z,0,t);
+	    continue;
+	}
+	if(c==SETRETURN){
+	    if(p->z.reg){
+		if(p->z.reg==9){
+		    if(!isreg(q1)||fst[0]!=p->q1.reg)
+			fload(f,&p->q1,t);
+		}else{
+		    move(f,&p->q1,0,0,p->z.reg,t);
+		}
+	    }
+	    continue;
+	}
+	if(c==GETRETURN){
+	    if(p->q1.reg){
+		if(p->q1.reg==9){
+		    if(!isreg(z)||fst[0]!=p->z.reg)
+			fstore(f,&p->z,t);
+		}else{
+		    move(f,0,p->q1.reg,&p->z,0,t);
+		}
+	    }
+	    continue;
+	}
+	if(c==CALL){
+	    int reg;
+	    if(p->q1.flags&DREFOBJ){
+		if(!(p->q1.flags&REG)) ierror(0);
+		fprintf(f,"\tcall\t*%s\n",regnames[p->q1.reg]);
+	    }else{
+		fprintf(f,"\tcall\t");probj2(f,&p->q1,t);
+		fprintf(f,"\n");
+	    }
+	    if(!zleqto(l2zl(0L),p->q2.val.vlong)){
+		notpopped+=zl2l(p->q2.val.vlong);
+		dontpop-=zl2l(p->q2.val.vlong);
+		if(!(g_flags[2]&USEDFLAG)&&stackoffset==-notpopped){
+		/*  Entfernen der Parameter verzoegern	*/
+		}else{
+		    fprintf(f,"\taddl\t$%ld,%%esp\n",zl2l(p->q2.val.vlong));
+		    stackoffset+=zl2l(p->q2.val.vlong);
+		    notpopped-=zl2l(p->q2.val.vlong);
+		}
+	    }
+	    continue;
+	}
+	if(c==ASSIGN||c==PUSH){
+	    if(c==PUSH) dontpop+=zl2l(p->q2.val.vlong);
+	    if((t&NQ)==FLOAT||(t&NQ)==DOUBLE){
+		if(c==ASSIGN){
+		    prfst(f,"fassign");
+		    fload(f,&p->q1,t);
+		    fstore(f,&p->z,t);
+		    continue;
+		}else if(isreg(q1)){
+		    prfst(f,"fpush");
+		    fprintf(f,"\tsubl\t$%ld,%s\n",zl2l(sizetab[t&NQ]),regnames[sp]);
+		    stackoffset-=zl2l(sizetab[t&NQ]);
+		    if(fst[0]==p->q1.reg){
+			fprintf(f,"\tfst%c\t(%s)\n",x_t[t&NQ],regnames[sp]);
+		    }else{
+			fload(f,&p->q1,t);
+			fprintf(f,"\tfstp%c\t(%s)\n",x_t[t&NQ],regnames[sp]);
+			fpop();
+		    }
+		    continue;
+		}
+	    }
+	    if((t&NQ)>POINTER||!zleqto(p->q2.val.vlong,sizetab[t&NQ])||!zlleq(p->q2.val.vlong,l2zl(4L))){
+		int mdi=di,msi=si,m=0;long l;
+		l=zl2l(p->q2.val.vlong);
+		if(regs[cx]){m|=1;if(!cxl)cxl=++label;fprintf(f,"\tmovl\t%s,%s%d\n",regnames[cx],labprefix,cxl);}
+		if(regs[msi]||!regused[msi]){m|=2;if(!sil)sil=++label;fprintf(f,"\tmovl\t%s,%s%d\n",regnames[msi],labprefix,sil);}
+		if(regs[mdi]||!regused[mdi]){m|=4;if(!dil)dil=++label;fprintf(f,"\tmovl\t%s,%s%d\n",regnames[mdi],labprefix,dil);}
+		if((p->z.flags&REG)&&p->z.reg==msi&&(p->q1.flags&REG)&&p->q1.reg==mdi){
+		    msi=di;mdi=si;
+		    m|=8;
+		}
+		if(!(p->z.flags&REG)||p->z.reg!=msi){
+		    fprintf(f,"\tleal\t");probj2(f,&p->q1,t);
+		    fprintf(f,",%s\n",regnames[msi]);
+		}
+		if(c==PUSH){
+		    fprintf(f,"\tsubl\t$%ld,%s\n\tmovl\t%s,%s\n",l,regnames[sp],regnames[sp],regnames[mdi]);
+		    stackoffset-=l;
+		}else{
+		    fprintf(f,"\tleal\t");probj2(f,&p->z,t);
+		    fprintf(f,",%s\n",regnames[mdi]);
+		}
+		if((p->z.flags&REG)&&p->z.reg==msi){
+		    fprintf(f,"\tleal\t");probj2(f,&p->q1,t);
+		    fprintf(f,",%s\n",regnames[msi]);
+		}
+		if(m&8){
+		    msi=si;mdi=di;
+		    fprintf(f,"\txch\t%s,%s\n",regnames[msi],regnames[mdi]);
+		}
+		if((t&NQ)==ARRAY||(t&NQ)==CHAR||l<4){
+		    fprintf(f,"\tmovl\t$%ld,%s\n\trep\n\tmovsb\n",l,regnames[cx]);
+		}else{
+		    if(l>=8)
+			fprintf(f,"\tmovl\t$%ld,%s\n\trep\n",l/4,regnames[cx]);
+		    fprintf(f,"\tmovsl\n");
+		    if(l%2) fprintf(f,"\tmovsw\n");
+		    if(l%1) fprintf(f,"\tmovsb\n");
+		}
+		if(m&4) fprintf(f,"\tmovl\t%s%d,%s\n",labprefix,dil,regnames[mdi]);
+		if(m&2) fprintf(f,"\tmovl\t%s%d,%s\n",labprefix,sil,regnames[msi]);
+		if(m&1) fprintf(f,"\tmovl\t%s%d,%s\n",labprefix,cxl,regnames[cx]);
+		continue;
+	    }
+	    if(t==FLOAT) t=LONG;
+	    if(c==PUSH){
+		fprintf(f,"\tpush%c\t",x_t[t&NQ]);
+		probj2(f,&p->q1,t);fprintf(f,"\n");
+		stackoffset-=zl2l(p->q2.val.vlong);
+		continue;
+	    }
+	    if(c==ASSIGN){
+		if(p->q1.flags&KONST){
+		    move(f,&p->q1,0,&p->z,0,t);
+		    continue;
+		}
+		if(isreg(z)) reg=p->z.reg;
+		else if(isreg(q1)) reg=p->q1.reg;
+		else reg=get_reg(f,p);
+		move(f,&p->q1,0,0,reg,t);
+		move(f,0,reg,&p->z,0,t);
+		continue;
+	    }
+	    ierror(0);
+	}
+	if(c==ADDRESS){
+	    if(isreg(z)) reg=p->z.reg; else reg=get_reg(f,p);
+	    fprintf(f,"\tleal\t");probj2(f,&p->q1,t);
+	    fprintf(f,",%s\n",regnames[reg]);
+	    move(f,0,reg,&p->z,0,POINTER);
+	    continue;
+	}
+	if(c==TEST){
+	    lastcomp=t;
+	    if((t&NQ)==FLOAT||(t&NQ)==DOUBLE){
+		if(isreg(q1)&&fst[0]==p->q1.reg){
+		    fprintf(f,"\tftst\n");lastcomp|=UNSIGNED;
+		    continue;
+		}else{
+		    p->code=c=COMPARE;
+		    p->q2.flags=KONST;
+		    p->q2.val.vdouble=d2zd(0.0);
+		    if((t&NQ)==FLOAT) p->q2.val.vfloat=zd2zf(p->q2.val.vdouble);
+		    /*	fall through to COMPARE */
+		}
+	    }else{
+		fprintf(f,"\tcmp%c\t$0,",x_t[t&NQ]);
+		probj2(f,&p->q1,t);fprintf(f,"\n");
+		continue;
+	    }
+	}
+	if(c==COMPARE){
+	    lastcomp=t;
+	    if(isreg(q2)||(p->q1.flags&KONST)){
+		struct IC *b=p->next;
+		struct obj o;
+		o=p->q1;p->q1=p->q2;p->q2=o;
+		while(b&&b->code==FREEREG) b=b->next;
+		if(!b) ierror(0);
+		if(b->code==BLT) b->code=BGT;
+		else if(b->code==BLE) b->code=BGE;
+		else if(b->code==BGT) b->code=BLT;
+		else if(b->code==BGE) b->code=BLE;
+	    }
+	    if((t&NQ)==FLOAT||(t&NQ)==DOUBLE){
+		prfst(f,"fcomp");
+		if(isreg(q1)&&p->q1.reg==fst[0]){
+		    fprintf(f,"\tfcom%c\t",x_t[t&NQ]);
+		    probj2(f,&p->q2,t);fprintf(f,"\n");
+		}else{
+		    fload(f,&p->q1,t);
+		    fprintf(f,"\tfcomp%c\t",x_t[t&NQ]);
+		    probj2(f,&p->q2,t);fprintf(f,"\n");
+		    fpop();
+		}
+		fprintf(f,"\tfstsw\n\tsahf\n");
+		lastcomp|=UNSIGNED;
+		continue;
+	    }
+	    if(!isreg(q1)){
+		if(!isreg(q2)){
+		    reg=get_reg(f,p);
+		    move(f,&p->q1,0,0,reg,t);
+		    p->q1.flags=REG;
+		    p->q1.reg=reg;
+		}
+	    }
+	    fprintf(f,"\tcmp%c\t",x_t[t&NQ]);
+	    probj2(f,&p->q2,t);fprintf(f,",");
+	    probj2(f,&p->q1,t);fprintf(f,"\n");
+	    continue;
+	}
+	if((t&NQ)==FLOAT||(t&NQ)==DOUBLE){
+	    char s[2];
+	    prfst(f,"fmath");
+	    if(isreg(q2)) s[0]=0; else {s[0]=x_t[t&NQ];s[1]=0;}
+	    if(isreg(z)&&isreg(q1)&&p->q1.reg==fst[0]&&p->z.reg==fst[0]){
+		fprintf(f,"\t%s%s\t",farithmetics[c-LSHIFT],s);
+		probj2(f,&p->q2,t); fprintf(f,"\n");continue;
+	    }
+	    fload(f,&p->q1,t);
+	    fprintf(f,"\t%s%s\t",farithmetics[c-LSHIFT],s);
+	    probj2(f,&p->q2,t); fprintf(f,"\n");
+	    fstore(f,&p->z,t); continue;
+	}
+	if((c==MULT||c==DIV||(c==MOD&&(p->typf&UNSIGNED)))&&(p->q2.flags&KONST)){
+	    long ln;
+	    eval_const(&p->q2.val,t);
+	    if(zlleq(l2zl(0L),vlong)&&zulleq(ul2zul(0UL),vulong)){
+		if(ln=pof2(vulong)){
+		    if(c==MOD){
+			vlong=zlsub(vlong,l2zl(1L));
+			p->code=AND;
+		    }else{
+			vlong=l2zl(ln-1);
+			if(c==DIV) p->code=RSHIFT; else p->code=LSHIFT;
+		    }
+		    c=p->code;
+		    if((t&NU)==CHAR) p->q2.val.vchar=zl2zc(vlong);
+		    if((t&NU)==SHORT) p->q2.val.vshort=zl2zs(vlong);
+		    if((t&NU)==INT) p->q2.val.vint=zl2zi(vlong);
+		    if((t&NU)==LONG) p->q2.val.vlong=vlong;
+		    vulong=zl2zul(vlong);
+		    if((t&NU)==(UNSIGNED|CHAR)) p->q2.val.vuchar=zul2zuc(vulong);
+		    if((t&NU)==(UNSIGNED|SHORT)) p->q2.val.vushort=zul2zus(vulong);
+		    if((t&NU)==(UNSIGNED|INT))  p->q2.val.vuint=zul2zui(vulong);
+		    if((t&NU)==(UNSIGNED|LONG)) p->q2.val.vulong=vulong;
+		}
+	    }
+	}
+	if(c==MOD||c==DIV){
+	    int m=0;
+	    if(regs[ax]&&(!isreg(z)||p->z.reg!=ax)){
+		fprintf(f,"\tpushl\t%s\n",regnames[ax]);
+		stackoffset-=4;m|=1;
+	    }
+	    if(regs[dx]&&(!isreg(z)||p->z.reg!=dx)){
+		fprintf(f,"\tpushl\t%s\n",regnames[dx]);
+		stackoffset-=4;m|=2;
+	    }
+	    if((p->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&(p->q2.reg==ax||p->q2.reg==dx)){
+		move(f,&p->q2,0,0,dx,t);
+		fprintf(f,"\tpushl\t%s\n",regnames[dx]);
+		m|=8;stackoffset-=4;
+	    }
+	    move(f,&p->q1,0,0,ax,t);
+	    if(p->q2.flags&KONST){
+		fprintf(f,"\tpush%c\t",x_t[t&NQ]);probj2(f,&p->q2,t);
+		fprintf(f,"\n");m|=4;stackoffset-=4;
+	    }
+	    if(t&UNSIGNED) fprintf(f,"\txorl\t%s,%s\n\tdivl\t",regnames[dx],regnames[dx]);
+		else	   fprintf(f,"\tcltd\n\tidivl\t");
+	    if((m&12)||(isreg(q2)&&p->q2.reg==dx)){
+		fprintf(f,"(%s)",regnames[sp]);
+	    }else if(isreg(q2)&&p->q2.reg==ax){
+		fprintf(f,"%s(%s)",(m&2)?"4":"",regnames[sp]);
+	    }else{
+		probj2(f,&p->q2,t);
+	    }
+	    fprintf(f,"\n");
+	    if(c==DIV) move(f,0,ax,&p->z,0,t);
+		else   move(f,0,dx,&p->z,0,t);
+	    if(m&4){ fprintf(f,"\taddl\t$%ld,%s\n",zl2l(sizetab[t&NQ]),regnames[sp]);stackoffset+=4;}
+	    if(m&8){ fprintf(f,"\tpopl\t%s\n",regnames[dx]);stackoffset+=4;}
+	    if(m&2){ fprintf(f,"\tpopl\t%s\n",regnames[dx]);stackoffset+=4;}
+	    if(m&1){ fprintf(f,"\tpopl\t%s\n",regnames[ax]);stackoffset+=4;}
+	    continue;
+	}
+	if(!(p->q2.flags&KONST)&&(c==LSHIFT||c==RSHIFT)){
+	    char *s=arithmetics[c-LSHIFT];
+	    int fl=0;
+	    if(c==RSHIFT&&(t&UNSIGNED)) s="shr";
+	    if(((p->q1.flags&REG)&&p->q1.reg==cx)||((p->z.flags&REG)&&p->z.reg==cx)
+	       ||(!compare_objects(&p->q1,&p->z)&&!isreg(q1))){
+		reg=get_reg(f,p);
+		move(f,&p->q1,0,0,reg,t);
+		move(f,&p->q2,0,0,cx,t);
+		fprintf(f,"\t%s%c\t%%cl,%s\n",s,x_t[t&NQ],regnames[reg]);
+		move(f,0,reg,&p->z,0,t);
+		continue;
+	    }else{
+		if(!isreg(q2)||p->q2.reg!=cx){
+		    if(regs[cx]){fprintf(f,"\tpushl\t%s\n",regnames[cx]);fl=1;}
+		    move(f,&p->q2,0,0,cx,t);
+		}
+		if(compare_objects(&p->q1,&p->z)){
+		    fprintf(f,"\t%s%c\t%%cl,",s,x_t[t&NQ]);
+		    probj2(f,&p->z,t);fprintf(f,"\n");
+		}else{
+		    move(f,0,p->q1.reg,&p->z,0,t);
+		    fprintf(f,"\t%s%c\t%%cl,",s,x_t[t&NQ]);
+		    probj2(f,&p->z,t);fprintf(f,"\n");
+		}
+		if(fl) fprintf(f,"\tpopl\t%s\n",regnames[cx]);
+		continue;
+	    }
+	}
+	if((c>=LSHIFT&&c<=MOD)||(c>=OR&&c<=AND)){
+	    char *s;
+	    if(c>=OR&&c<=AND) s=logicals[c-OR];
+		else s=arithmetics[c-LSHIFT];
+	    if(c==RSHIFT&&(t&UNSIGNED)) s="shr";
+	    if(c!=MULT&&compare_objects(&p->q1,&p->z)){
+		if(isreg(z)||isreg(q1)||(p->q2.flags&KONST)){
+		    if((p->q2.flags&KONST)&&(c==ADD||c==SUB)){
+			eval_const(&p->q2.val,t);
+			if(zleqto(vlong,l2zl(1L))&&zuleqto(vulong,ul2zul(1UL))&&zdeqto(vdouble,d2zd(1.0))){
+			    if(c==ADD) s="inc"; else s="dec";
+			    fprintf(f,"\t%s%c\t",s,x_t[t&NQ]);
+			    probj2(f,&p->z,t);fprintf(f,"\n");
+			    continue;
+			}
+		    }
+		    fprintf(f,"\t%s%c\t",s,x_t[t&NQ]);
+		    probj2(f,&p->q2,t);fprintf(f,",");
+		    probj2(f,&p->z,t);fprintf(f,"\n");
+		    continue;
+		}else{
+		    if(isreg(q2)) reg=p->q2.reg; else reg=get_reg(f,p);
+		    move(f,&p->q2,0,0,reg,t);
+		    fprintf(f,"\t%s%c\t%s",s,x_t[t&NQ],regnames[reg]);
+		    fprintf(f,","); probj2(f,&p->z,t);fprintf(f,"\n");
+		    continue;
+		}
+	    }
+	    if(isreg(z)) reg=p->z.reg; else reg=get_reg(f,p);
+	    move(f,&p->q1,0,0,reg,t);
+	    if((p->q2.flags&KONST)&&(c==ADD||c==SUB)){
+		eval_const(&p->q2.val,t);
+		if(zleqto(vlong,l2zl(1L))&&zuleqto(vulong,ul2zul(1UL))&&zdeqto(vdouble,d2zd(1.0))){
+		    if(c==ADD) s="inc"; else s="dec";
+		    fprintf(f,"\t%s%c\t%s\n",s,x_t[t&NQ],regnames[reg]);
+		}else{
+		    fprintf(f,"\t%s%c\t",s,x_t[t&NQ]);
+		    probj2(f,&p->q2,t);fprintf(f,",%s\n",regnames[reg]);
+		}
+	    }else{
+		fprintf(f,"\t%s%c\t",s,x_t[t&NQ]);
+		probj2(f,&p->q2,t);fprintf(f,",%s\n",regnames[reg]);
+	    }
+	    move(f,0,reg,&p->z,0,t);
+	    continue;
+	}
+	ierror(0);
+    }
+    if(notpopped){
+	fprintf(f,"\taddl\t$%ld,%%esp\n",notpopped);
+	stackoffset+=notpopped;notpopped=0;
+    }
+    function_bottom(f,v,loff);
+}
+
+int shortcut(int code,int typ)
+{
+    return(0);
+}
+
+void cleanup_cg(FILE *f)
+{
+    struct fpconstlist *p;
+    unsigned char *ip;
+
+    title(f);
+    while(p=firstfpc){
+	if(f){
+	    if(section!=CODE){fprintf(f,codename);section=CODE;}
+	    fprintf(f,"%s%d:\n\t.long\t",labprefix,p->label);
+	    ip=(unsigned char *)&p->val.vdouble;
+	    fprintf(f,"0x%02x%02x%02x%02x",ip[3],ip[2],ip[1],ip[0]);
+	    if((p->typ&NQ)==DOUBLE){
+		fprintf(f,",0x%02x%02x%02x%02x",ip[7],ip[6],ip[5],ip[4]);
+	    }
+	    fprintf(f,"\n");
+	}
+	firstfpc=p->next;
+	free(p);
+    }
+    if(f){
+	if(section!=BSS){fprintf(f,bssname);section=BSS;}
+	if(cxl) fprintf(f,"\t.lcomm\t%s%d,4\n",labprefix,cxl);
+	if(sil) fprintf(f,"\t.lcomm\t%s%d,4\n",labprefix,sil);
+	if(dil) fprintf(f,"\t.lcomm\t%s%d,4\n",labprefix,dil);
+    }
+}
diff --git a/machines/bi386/machine.dt b/machines/bi386/machine.dt
new file mode 100755
index 0000000..94451a4
--- /dev/null
+++ b/machines/bi386/machine.dt
@@ -0,0 +1,13 @@
+S8BS
+S8BU
+S16BSBE S16BSLE
+S16BUBE S16BULE
+S32BSBE S32BSLE
+S32BUBE S32BULE
+S32BSBE S32BSLE
+S32BUBE S32BULE
+S32BIEEEBE
+S64BIEEEBE
+S32BUBE S32BULE
+
+
diff --git a/machines/bi386/machine.h b/machines/bi386/machine.h
new file mode 100755
index 0000000..5970ac1
--- /dev/null
+++ b/machines/bi386/machine.h
@@ -0,0 +1,59 @@
+/*  Example of a code-generator for an Intel 386 or higher.         */
+
+#include "dt.h"
+
+#define BEI386
+
+/*  This struct can be used to implement machine-specific           */
+/*  addressing-modes.                                               */
+/*  Not used in this code-generrator.                               */
+struct AddressingMode{
+    int never_used;
+};
+
+/*  The number of registers of the target machine.                  */
+#define MAXR 16
+
+/*  Number of commandline-options the code-generator accepts.       */
+#define MAXGF 10
+
+/*  If this is set to zero vbcc will not generate ICs where the     */
+/*  target operand is the same as the 2nd source operand.           */
+/*  This can sometimes simplify the code-generator, but usually     */
+/*  the code is better if the code-generator allows it.             */
+#define USEQ2ASZ 0
+
+/*  This specifies the smallest integer type that can be added to a */
+/*  pointer.                                                        */
+#define MINADDI2P INT
+
+/*  If the bytes of an integer are ordered most significant byte    */
+/*  byte first and then decreasing set BIGENDIAN to 1.              */
+#ifdef BEI386
+#define BIGENDIAN 1
+#else
+#define BIGENDIAN 0
+#endif
+
+/*  If the bytes of an integer are ordered lest significant byte    */
+/*  byte first and then increasing set LITTLEENDIAN to 1.           */
+#ifdef BEI386
+#define LITTLEENDIAN 0
+#else
+#define LITTLEENDIAN 1
+#endif
+
+/*  Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive.    */
+
+/*  If switch-statements should be generated as a sequence of       */
+/*  SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1.      */
+/*  This can yield better code on some machines.                    */
+#define SWITCHSUBS 0
+
+/*  In optimizing compilation certain library memcpy/strcpy-calls   */
+/*  with length known at compile-time will be inlined using an      */
+/*  ASSIGN-IC if the size is less or equal to INLINEMEMCPY.         */
+/*  The type used for the ASSIGN-IC will be UNSIGNED|CHAR.          */
+#define INLINEMEMCPY 1024
+
+
diff --git a/machines/c16x/machine.c b/machines/c16x/machine.c
new file mode 100755
index 0000000..b80fd10
--- /dev/null
+++ b/machines/c16x/machine.c
@@ -0,0 +1,3728 @@
+/*  Code generator for SAB c16x microcontrollers.               */
+
+#include "supp.h"
+
+static char FILE_[]=__FILE__;
+/*  Public data that MUST be there.                             */
+
+/* Name and copyright. */
+char cg_copyright[]="vbcc code-generator for c16x V0.3 (c) in 1998-2005 by Volker Barthelmann";
+
+/*  Commandline-flags the code-generator accepts                */
+int g_flags[MAXGF]={VALFLAG,0,0,0,
+                    0,0,0,0,
+                    0};
+char *g_flags_name[MAXGF]={"cpu","int32","no-delayed-popping","const-in-data",
+                           "merge-constants","no-peephole","mtiny","mlarge",
+                           "mhuge","tasking"};
+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"};
+
+/*  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","R0","R1","R2","R3","R4","R5","R6","R7",
+		  "R8","R9","R10","R11","R12","R13","R14","R15",
+		  "R6/R7","R7/R8","R8/R9","R4/R5",
+		  "R14/R15","R13/R14","R12/R13",
+		  "R3/R4","R2/R3",
+		  "MAXR+1","MAXR+2","ZEROS","ONES"};
+
+/*  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,1,1,1,1,0,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1};
+
+int reg_prio[MAXR+1]={0,0,0,0,0,2,3,1,1,1,1,0,0,4,5,6,7,1,1,1,2,6,5,4,0,0};
+
+struct reg_handle empty_reg_handle={0};
+
+/* Names of target-specific variable attributes.                */
+char *g_attr_name[]={"__interrupt","__dpp0","__dpp1","__dpp2","__dpp3",0};
+#define INTERRUPT 1
+#define DPP0 2
+#define DPP1 4
+#define DPP2 8
+#define DPP3 16
+
+
+/****************************************/
+/*  Some private data and functions.    */
+/****************************************/
+
+static char *bregnames[]={"nobreg","RL0","RL1","RL2","RL3","RL4","RL5","RL6","RL7",
+ "e8","e9","e10","e11","e12","e13","e14","e15","e16",
+ "e17","e18","e19","e20","e21","e22"
+};
+
+static long malign[MAX_TYPE+1]=  {1,1,1,2,2,2,2,2,2,2,1,2,2,2,1,1,1,2,1};
+static long msizetab[MAX_TYPE+1]={0,1,1,2,2,4,8,4,8,8,0,2,4,4,0,0,0,2,0};
+
+struct Typ ityp={SHORT},ltyp={LONG};
+
+#define INT32 (g_flags[1]&USEDFLAG)
+#define TINY (g_flags[6]&USEDFLAG)
+#define LARGE (g_flags[7]&USEDFLAG)
+#define HUGE (g_flags[8]&USEDFLAG)
+#define TASKING (g_flags[9]&USEDFLAG)
+
+
+#define NDATA 0
+#define NBSS 1
+#define NCDATA 2
+#define FDATA 3
+#define FBSS 4
+#define FCDATA 5
+#define HDATA 6
+#define HBSS 7
+#define HCDATA 8
+#define CODE 9
+#define SPECIAL 10
+#define BITS 11
+
+#define SEG r2
+#define SOF r1
+
+#define MTMP1 MAXR+1
+#define MTMP2 MAXR+2
+#define ZEROS MAXR+3
+#define ONES  MAXR+4
+
+static int section=-1,newobj,scnt;
+static char *codename="SCODE\tSECTION CODE WORD PUBLIC 'CPROGRAM'\n",*ecode="SCODE\tends\n",
+            *ndataname="NDATA\tSECTION LDAT WORD PUBLIC\n",*endata="NDATA\tends\n",
+            *fdataname="FDATA\tSECTION LDAT WORD PUBLIC\n",*efdata="FDATA\tends\n",
+            *hdataname="HDATA\tSECTION LDAT WORD PUBLIC\n",*ehdata="HDATA\tends\n",
+            *nbssname="NBSS\tSECTION LDAT WORD PUBLIC\n",*enbss="NBSS\tends\n",
+            *fbssname="FBSS\tSECTION LDAT WORD PUBLIC\n",*efbss="FBSS\tends\n",
+            *hbssname="HBSS\tSECTION LDAT WORD PUBLIC\n",*ehbss="HBSS\tends\n",
+            *ncdataname="NCDATA\tSECTION LDAT WORD PUBLIC\n",*encdata="NCDATA\tends\n",
+            *fcdataname="FCDATA\tSECTION LDAT WORD PUBLIC\n",*efcdata="FCDATA\tends\n",
+            *hcdataname="HCDATA\tSECTION LDAT WORD PUBLIC\n",*ehcdata="HCDATA\tends\n",
+
+            *bitsname="BITS\tSECTION BIT BIT PUBLIC 'CBITS'\n",*ebits="BITS\tends\n";
+
+static char *even="\teven\n",*public="public",*comment="; ";
+
+#define IMM_IND  1
+#define VAR_IND  2
+#define POST_INC 3
+#define PRE_DEC  4
+
+static char sec_end[32];
+/* (user)stack-pointer, pointer-tmp, int-tmp; reserved for compiler */
+static const int sp=1,tp=2,ti=11,ti2=12,r4=5,r5=6,r4r5=20;
+static int tmp1,tmp2,tmp3,tmp4;
+static void pr(FILE *,struct IC *);
+static void function_top(FILE *,struct Var *,long);
+static void function_bottom(FILE *f,struct Var *,long);
+static int scratchreg(int,struct IC *);
+static struct Var nvar,fvar;
+
+static char *marray[]={0,
+                       "__far=__attr(\"far\")",
+		       "__near=__attr(\"near\")",
+		       "__huge=__attr(\"huge\")",
+		       "__bit=__attr(\"bit\") unsigned char",
+                       /*"__section(x)=__vattr(\"section(\"x\")\")",*/
+                       "__section(x,y)=__vattr(\"section(\"#x\",\"#y\")\")",
+		       "__rbank(x)=__vattr(\"rbank(\"__str(x)\")\")",
+		       "__interrupt(x)=__interrupt __vattr(\"ivec(\"__str(x)\")\")",
+		       "__sysstack(x)=__stack2(x)",
+		       "__usrstack(x)=__stack(x)",
+		       "__C16X__",
+		       "__C167__",
+		       "__ST10__",
+		       "__sfr(x)=__vattr(\"sfr(\"__str(x)\")\") extern",
+		       "__sfrbit(x,y)=__vattr(\"sfrbit(\"__str(x)\",\"__str(y)\")\") extern",
+		       "__esfr(x)=__vattr(\"sfre(\"__str(x)\")\") extern",
+		       "__esfrbit(x,y)=__vattr(\"sfrbite(\"__str(x)\",\"__str(y)\")\") extern",
+		       "__SIZE_T_INT=1",
+		       "__str(x)=#x",
+		       0};
+
+#define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
+#define isconst(x) ((p->x.flags&(KONST|DREFOBJ))==KONST)
+#define issfrv(v) (v->vattr&&strstr(v->vattr,"sfr("))
+#define issfrbitv(v) (v->vattr&&strstr(v->vattr,"sfrbit("))
+#define isesfrv(v) (v->vattr&&strstr(v->vattr,"sfre("))
+#define isesfrbitv(v) (v->vattr&&strstr(v->vattr,"sfrbite("))
+#define issfr(x) ((p->x.flags&(VAR|DREFOBJ))==VAR&&issfrv(p->x.v))
+#define issfrbit(x) ((p->x.flags&(VAR|DREFOBJ))==VAR&&issfrbitv(p->x.v))
+#define isesfr(x) ((p->x.flags&(VAR|DREFOBJ))==VAR&&isesfrv(p->x.v))
+#define isesfrbit(x) ((p->x.flags&(VAR|DREFOBJ))==VAR&&isesfrbitv(p->x.v))
+
+static long loff,sysstackoffset,usrstackoffset,notpopped,dontpop,
+  usrmaxpushed,sysmaxpushed,sysstack,usrstack;
+
+static char *x_t[]={"?","","b","","","","","","","","","","","","","",""};
+static char *ccs[]={"z","nz","lt","ge","le","gt"};
+static char *logicals[]={"or","xor","and"};
+static char *arithmetics[]={"shl","shr","add","sub","mul","div","mod"};
+static char *dct[]={"","dbit","db","dw","dw","dw","dw","dw","dw","dw",
+		    "(void)","dw","dsptr","dsptr"};
+static char *vdct[]={"",".bit",".byte",".short",".short",".short",".short",".short",".short",".short",
+		    "(void)",".short",".long",".long"};
+static int pushedsize,pushorder=2;
+static char *idprefix="_",*labprefix="l";
+static int ti2_used;
+static struct rpair qp;
+static int exit_label,have_frame,stackchecklabel,stack_valid;
+static char *ret,*call,*jump;
+static int frame_used;
+
+static char *dppprefix="___DPP_";
+static int romdpp=0,ramdpp=1;
+
+#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 ISSTATIC(v) ((v)->storage_class==EXTERN||(v)->storage_class==STATIC)
+#define ISBADDR(v) ((v)->vtyp->attr&&strstr(STR_BADDR,(v)->vtyp->attr))
+
+static int dppuse(struct Var *v,int section)
+{
+  if(v->tattr&DPP0) return 0;
+  if(v->tattr&DPP1) return 1;
+  if(v->tattr&DPP2) return 2;
+  if(v->tattr&DPP3) return 3;
+  if(section==NCDATA) return romdpp;
+  if(section==NDATA||section==NBSS) return ramdpp;
+  return -1;
+}
+
+static int ISFAR(struct Var *v)
+{
+  struct Typ *vt;
+  if(v==&nvar) return 0;
+  if(v==&fvar) return 1;
+  if(issfrv(v)||isesfrv(v)||issfrbitv(v)||isesfrbitv(v))
+    return 0;
+  vt=v->vtyp;
+  while(ISARRAY(vt->flags)) vt=vt->next;
+  if(vt->attr&&strstr(STR_NEAR,vt->attr))
+    return 0;
+  if(HUGE||LARGE)
+    return 1;
+  if(vt->attr&&(strstr(STR_FAR,vt->attr)||strstr(STR_HUGE,vt->attr)))
+    return 1;
+  return 0;
+}
+
+static int special_section(FILE *f,struct Var *v)
+{
+  char *sec,*e;
+  if(!v->vattr) return 0;
+  sec=strstr(v->vattr,"section(");
+  if(!sec) return 0;
+  sec+=strlen("section(");
+  if(f&&TASKING){
+    emit(f,sec_end);
+    e=sec_end;
+    while(*sec&&*sec!=')') {
+      *e++=*sec;
+      emit_char(f,*sec++);
+    }
+    *e=0;
+    strcat(sec_end,"\tends\n");
+    emit(f,"\tSECTION LDAT WORD PUBLIC\n");
+  }else{
+    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;
+}
+static void callee_push(long usr,long sys)
+{
+  if(usr-usrstackoffset>usrstack)
+    usrstack=usr-usrstackoffset;
+  if(sys-sysstackoffset>sysstack)
+    sysstack=sys-sysstackoffset;
+}
+static void push(long usr,long sys)
+{
+  usrstackoffset-=usr;
+  if(usrstackoffset<usrmaxpushed) 
+    usrmaxpushed=usrstackoffset;
+  if(-usrmaxpushed>usrstack) usrstack=-usrmaxpushed;
+  sysstackoffset-=sys;
+  if(sysstackoffset<sysmaxpushed) 
+    sysmaxpushed=sysstackoffset;
+  if(-sysmaxpushed>sysstack) sysstack=-sysmaxpushed;
+}
+static void pop(long usr,long sys)
+{
+  usrstackoffset+=usr;
+  sysstackoffset+=sys;
+}
+int pointer_type(struct Typ *p)
+{
+  struct Typ *merk=p;
+  if(!p) ierror(0);
+  while(ISARRAY(p->flags)||ISFUNC(p->flags)) p=p->next;
+  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;
+  }
+  if((merk->flags&NQ)==FUNKT){
+    if(TINY)
+      return NPOINTER;
+    else
+      return HPOINTER;
+  }
+  if(LARGE)
+    return FPOINTER;
+  else if(HUGE)
+    return HPOINTER;
+  else
+    return NPOINTER;
+}
+static long voff(struct obj *p)
+{
+  if(p->v->offset<0)
+    return loff-zm2l(p->v->offset)+zm2l(p->val.vmax)-usrstackoffset+pushedsize-2;
+  return zm2l(p->v->offset)+zm2l(p->val.vmax)-usrstackoffset;
+}
+static int alignment(struct obj *o)
+{
+  if(o->flags&DREFOBJ) return 1;
+  if(!(o->flags&VAR)) ierror(0);
+  if(ISSTATIC(o->v)) return zm2l(o->val.vmax)&1;
+  return voff(o)&1;
+}
+
+static int isseg;
+
+static void emit_obj(FILE *f,struct obj *p,int t)
+/*  Gibt Objekt auf Bildschirm aus                      */
+{
+  if(p->am){
+    static struct rpair bp;
+    int base;
+    if(reg_pair(p->am->base,&bp))
+      base=bp.SOF;
+    else
+      base=p->am->base;
+    if(p->am->flags==POST_INC){
+      emit(f,"[%s+]",regnames[base]);
+      return;
+    }else if(p->am->flags==PRE_DEC){
+      emit(f,"[-%s]",regnames[base]);
+      return;
+    }else{
+      emit(f,"[%s+#%ld",regnames[base],p->am->offset);
+      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,"]");
+      return;
+    }
+  }
+  if((p->flags&(KONST|DREFOBJ))==(KONST|DREFOBJ)){
+    emitval(f,&p->val,p->dtyp&NU);
+    return;
+  }
+  if((p->flags&(DREFOBJ|REG))==(DREFOBJ|REG)) emit(f,"[");
+  if(p->flags&VARADR) emit(f,"#");
+  if((p->flags&(VAR|REG))==VAR){
+    if(p->v==&nvar||p->v==&fvar){
+      if(p->v==&fvar) emit(f,"SOF ");
+      emitval(f,&p->val,p->dtyp&NU);
+      return;
+    }else if(issfrv(p->v)||isesfrv(p->v)||issfrbitv(p->v)||isesfrbitv(p->v)){
+      emit(f,"%s",p->v->identifier);
+    }else if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER){
+      if(voff(p))
+	emit(f,"[%s+#%ld]",regnames[sp],voff(p));
+      else emit(f,"[%s]",regnames[sp]);
+    }else{
+      if(!isseg&&!ISFUNC(p->v->vtyp->flags)){
+        if(ISFAR(p->v)) 
+          emit(f,"SOF ");
+        else
+          emit(f,"DPPX:");
+      }
+      isseg=0;
+      if(!zmeqto(l2zm(0L),p->val.vmax)){emitval(f,&p->val,LONG);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(p->flags&REG){
+    if(p->reg==MTMP1||p->reg==MTMP2){
+      if(!reg_pair(p->reg,&rp)) ierror(0);
+      emit(f,"%s",regnames[rp.SOF]);
+    }else{
+      emit(f,"%s",regnames[p->reg]);
+      if((t&NQ)==BIT) emit(f,".0");
+    }
+  }
+  /* sometimes we just or a REG into a KONST */
+  if((p->flags&(KONST|REG))==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|REG)) emit(f,"]");
+}
+
+static void pr(FILE *f,struct IC *p)
+{
+}
+static int switched_bank;
+static void function_top(FILE *f,struct Var *v,long offset)
+/*  erzeugt Funktionskopf                       */
+{
+  int i;char *tmp;
+  static int wrote_header;
+  if(f&&!wrote_header){
+    wrote_header=1;
+    if(!TASKING){
+      emit(f,"\t.sfr\tZEROS,0xfe,0x8e\n");
+      emit(f,"\t.sfr\tONES,0xfe,0x8f\n");
+      emit(f,"\t.sfr\tCP,0xfe,0x08\n");
+      emit(f,"\t.sfr\tMDH,0xfe,0x06\n");
+      emit(f,"\t.sfr\tMDL,0xfe,0x07\n");
+      emit(f,"\t.sfr\tPSW,0xfe,0x88\n");
+    }
+  }
+  have_frame=0;stack_valid=1;
+  pushedsize=0;
+  if(v->vattr&&(tmp=strstr(v->vattr,"ivec("))){
+    int vec;char c;int rc;
+    rc=sscanf(tmp+5,"%i%c",&vec,&c);
+    if(rc!=2||c!=')') error(324,"illegal vector number");
+    emit(f,"\t.section\t\".ivec%d\",\"axr\"\n",vec);
+    emit(f,"\t.global\tivec%d\nivec%d:\n",vec,vec);
+    if(v->storage_class==EXTERN)
+      emit(f,"\tjmps\t%s%s\n",idprefix,v->identifier);
+    else
+      emit(f,"\tjmps\t%s%ld\n",labprefix,zm2l(v->offset));
+    section=-1;
+  }
+  if(!special_section(f,v)&&section!=CODE){
+    if(f&&TASKING){
+      emit(f,sec_end);emit(f,codename);
+      section=CODE;
+      strcpy(sec_end,ecode);
+    }else
+      emit(f,codename);
+  }
+  if(TASKING){
+    if(v->storage_class==EXTERN){
+      if((v->flags&(INLINEFUNC|INLINEEXT))!=INLINEFUNC)
+	emit(f,"\tpublic\t%s%s\n",idprefix,v->identifier);
+      if(TINY)
+	emit(f,"%s%s\tproc\tnear\n",idprefix,v->identifier);
+      else
+	emit(f,"%s%s\tproc\tfar\n",idprefix,v->identifier);
+    }else{
+      if(TINY)
+	emit(f,"%s%ld\tproc\tnear\n",labprefix,zm2l(v->offset));
+      else
+	emit(f,"%s%ld\tproc\tfar\n",labprefix,zm2l(v->offset));
+    }
+  }else{
+    if(v->storage_class==EXTERN){
+      if((v->flags&(INLINEFUNC|INLINEEXT))!=INLINEFUNC)
+	emit(f,"\t.global\t%s%s\n",idprefix,v->identifier);
+      emit(f,"\t.align\t1\n%s%s:\n",idprefix,v->identifier); 
+    }else{
+      emit(f,"\t.align\t1\n%s%ld:\n",labprefix,zm2l(v->offset));  
+    }
+  }
+  if(v->vattr&&(tmp=strstr(v->vattr,"rbank("))){
+    char *p;
+    tmp+=strlen("rbank(");
+    emit(f,"\tmov\t%s",idprefix);
+    for(p=tmp;*p&&*p!=')';p++) emit_char(f,*p);
+    emit(f,",%s\n",regnames[sp]);
+    emit(f,"\tscxt\tCP,#%s",idprefix);
+    for(p=tmp;*p&&*p!=')';p++) emit_char(f,*p);
+    emit(f,"\n");
+    switched_bank=1;
+  }else
+    switched_bank=0;
+  if(v->tattr&INTERRUPT){
+    /*FIXME?*/
+    emit(f,"\tpush\tMDL\n");
+    emit(f,"\tpush\tMDH\n");
+  }
+  if(stack_check){
+    stackchecklabel=++label;
+    BSET(regs_modified,tp);
+    emit(f,"\tmov\t%s,#%s%d\n",regnames[tp],labprefix,stackchecklabel);
+    emit(f,"\t%s\t%s__stack_check\n",call,idprefix);/*FIXME:usrstack*/
+  }
+  for(i=1;i<=16;i++){
+    if(regused[i]&&!regscratch[i]&&!regsa[i]){
+      emit(f,"\tmov\t[-%s],%s\n",regnames[sp],regnames[i]);
+      push(2,0);
+      have_frame=1;pushedsize+=2;
+    }
+  }
+  if(offset){
+    emit(f,"\tsub\t%s,#%ld\n",regnames[sp],offset);
+    have_frame=1;
+  }
+}
+static void function_bottom(FILE *f,struct Var *v,long offset)
+/*  erzeugt Funktionsende                       */
+{
+  int i;
+  if(offset) emit(f,"\tadd\t%s,#%ld\n",regnames[sp],offset);
+  for(i=16;i>0;i--){
+    if(regused[i]&&!regscratch[i]&&!regsa[i]){
+      emit(f,"\tmov\t%s,[%s+]\n",regnames[i],regnames[sp]);
+      pop(2,0);
+    }
+  }
+  if(v->tattr&INTERRUPT){
+    emit(f,"\tpop\tMDH\n");
+    emit(f,"\tpop\tMDL\n");
+  }
+  if(switched_bank)
+    emit(f,"\tpop\tCP\n");
+  if(ret) emit(f,"\t%s\n",ret);
+  if(TASKING){
+    if(v->storage_class==EXTERN){
+      emit(f,"%s%s\tendp\n",idprefix,v->identifier);
+      if(!strcmp("main",v->identifier)) emit(f,"\textern\t__CSTART:far\n");
+    }else
+      emit(f,"%s%ld\tendp\n",labprefix,zm2l(v->offset));
+  }else{
+    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,"%s%d\tequ\t%ld\n",labprefix,stackchecklabel,offset+pushedsize-usrmaxpushed);
+  if(stack_valid){
+    long ustack=usrstack+offset+pushedsize,sstack=sysstack;
+    if(!v->fi) v->fi=new_fi();
+    if(v->fi->flags&ALL_STACK){
+      if(v->fi->stack1!=ustack)
+        if(f) error(319,"user-",ustack,v->fi->stack1);
+      if(v->fi->stack2!=sstack)
+        if(f) error(319,"system-",sstack,v->fi->stack2);
+    }else{
+      v->fi->flags|=ALL_STACK;
+      v->fi->stack1=ustack;
+      v->fi->stack2=sstack;
+    }
+#if 0
+    emit(f,"%s usrstacksize=%ld\n",comment,zm2l(v->fi->stack1));
+    emit(f,"%s sysstacksize=%ld\n",comment,zm2l(v->fi->stack2));
+#endif
+    if(TASKING){
+    }else{
+      emit(f,"\t.equ\t%s__ustack_%s,%ld\n",idprefix,v->identifier,zm2l(v->fi->stack1));
+      emit(f,"\t.equ\t%s__sstack_%s,%ld\n",idprefix,v->identifier,zm2l(v->fi->stack2));
+    }
+  }
+}
+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&REG)||o1->reg==o2->reg){
+	return 1;
+      }
+    }
+  }
+  return 0;
+}
+#define EXT_IC_CMPIA 1
+#define EXT_IC_BTST  2
+#define EXT_IC_CMPIB 3
+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;
+  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;
+    /* and x,#const;bne/beq */
+    if(c==AND&&isconst(q2)&&isreg(z)&&!ISLWORD(ztyp(p))){
+      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&REG)&&p2->q1.reg==p->z.reg)||((p2->q2.flags&REG)&&p2->q2.reg==p->z.reg)||((p2->z.flags&REG)&&p2->z.reg==p->z.reg)) break;
+	  if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
+	}
+      }
+    }
+    /* [Rx+] in q1 */
+    if(!p->q1.am&&(p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)){
+      r=p->q1.reg; t=q1typ(p);
+      if((!(p->q2.flags&REG)||p->q2.reg!=r)&&(!(p->z.flags&REG)||p->z.reg!=r)){
+	for(p2=p->next;p2;p2=p2->next){
+	  c2=p2->code;
+	  if((c2==ADD||(c2==ADDI2P&&(p2->typf2&NQ)!=HPOINTER))&&(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((zmeqto(vmax,l2zm(1L))&&(t&NQ)==CHAR)||(zmeqto(vmax,l2zm(2L))&&ISHWORD(t))){
+	      p2->code=NOP;
+	      p2->q1.flags=p2->q2.flags=p2->z.flags=0;
+	      p->q1.am=mymalloc(sizeof(*am));
+	      p->q1.am->flags=POST_INC;
+	      p->q1.am->base=r;
+	    }else break;
+	  }
+	  if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
+	  if(((p2->q1.flags&REG)&&p2->q1.reg==r)||((p2->q2.flags&REG)&&p2->q2.reg==r)||((p2->z.flags&REG)&&p2->z.reg==r)) break;
+	}
+      }
+    }
+    /* [Rx+] in q2 */
+    if(!p->q2.am&&(p->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)){
+      r=p->q2.reg; t=q2typ(p);
+      if((!(p->q1.flags&REG)||p->q1.reg!=r)&&(!(p->z.flags&REG)||p->z.reg!=r)){
+	for(p2=p->next;p2;p2=p2->next){
+          c2=p2->code;
+	  if((c2==ADD||(c2==ADDI2P&&(p2->typf2&NQ)!=HPOINTER))&&(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((zmeqto(vmax,l2zm(1L))&&(t&NQ)==CHAR)||(zmeqto(vmax,l2zm(2L))&&ISHWORD(t))){
+	      p2->code=NOP;
+	      p2->q1.flags=p2->q2.flags=p2->z.flags=0;
+	      p->q2.am=mymalloc(sizeof(*am));
+	      p->q2.am->flags=POST_INC;
+	      p->q2.am->base=r;
+	    }else break;
+	  }
+	  if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
+	  if(((p2->q1.flags&REG)&&p2->q1.reg==r)||((p2->q2.flags&REG)&&p2->q2.reg==r)||((p2->z.flags&REG)&&p2->z.reg==r)) break;
+	}
+      }
+    }
+    /* move x->t; add/sub x,#1/-1/2/-2-> x; test/cmp t,#0; freereg t => cmpid12 */
+    if(c==ASSIGN&&isreg(q1)&&isreg(z)&&ISHWORD(p->typf)){
+      p2=p->next;if(p2) c2=p2->code;
+      if(p2&&(c2==ADD||c2==SUB||c2==ADDI2P||c2==SUBIFP)&&(p2->q1.flags&(REG|DREFOBJ))==REG&&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==p->q1.reg&&p2->z.reg==p2->q1.reg&&(p2->q2.flags&(KONST|DREFOBJ))==KONST&&ISHWORD(p2->typf)){
+	long l;
+	eval_const(&p2->q2.val,p2->typf);
+	l=zm2l(vmax);
+	if((l==1||l==2||l==-1||l==-2)&&p2->next){
+	  struct IC *p3=p2->next;
+	  if((p3->code==TEST||(p3->code==COMPARE&&(p3->q2.flags&(KONST|DREFOBJ))==KONST))&&(p3->q1.flags&(REG|DREFOBJ))==REG&&p3->q1.reg==p->z.reg&&scratchreg(p->z.reg,p3)&&ISHWORD(p3->typf)){
+	    if(c2==SUB||c2==SUBIFP) l=-l;
+	    p3->q1=p->q1;
+	    p->code=c=NOP;
+	    p->q1.flags=p->q2.flags=p->z.flags=0;
+	    p2->code=NOP;
+	    p2->q1.flags=p2->q2.flags=p2->z.flags=0;
+	    p3->ext.flags=EXT_IC_CMPIB;
+	    p3->ext.offset=l;
+	    p3->ext.r=p->q1.reg;
+	  }
+	}
+      }
+    }
+    /* add/sub x,#1/2/-1/-2 ->x; cmp x,#c => cmpid12 x,#c+-12 */
+    if((c==ADD||c==SUB||c==ADDI2P||c==SUBIFP)&&isreg(q1)&&isreg(z)&&p->q1.reg==p->z.reg&&isconst(q2)&&ISHWORD(p->typf)&&!reg_pair(p->q1.reg,&rp)){
+      eval_const(&p->q2.val,p->typf);
+      if(zmeqto(vmax,l2zm(-1L))||zmeqto(vmax,l2zm(-2L))||zmeqto(vmax,l2zm(1L))||zmeqto(vmax,l2zm(2L))){
+	long l=zm2l(vmax);
+	if(c==SUB||c==SUBIFP) l=-l;
+	r=p->q1.reg;
+	for(p2=p->next;p2;p2=p2->next){
+	  c2=p2->code;
+	  if((p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r&&(c2==TEST||(c2==COMPARE&&(p2->q2.flags&(KONST|DREFOBJ))==KONST))&&ISHWORD(p2->typf)){
+	    unsigned long ul;
+	    eval_const(&p2->q2.val,q2typ(p2));
+	    ul=zum2ul(vumax);
+	    if(ul<65534){
+	      p2->ext.flags=EXT_IC_CMPIA;
+	      p2->ext.offset=l;
+	      p2->ext.r=r;
+	      p->code=c=NOP;
+	      p->q1.flags=p->q2.flags=p->z.flags=0;
+	    }
+	    break;
+
+	  }
+	  if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
+	  if((p2->q1.flags&REG)&&p2->q1.reg==r) break;
+	  if((p2->q2.flags&REG)&&p2->q2.reg==r) break;
+	  if((p2->z.flags&REG)&&p2->z.reg==r) break;
+	}
+      }
+    }
+    /* [Rx+#const] */
+    if((c==ADDI2P||c==SUBIFP)&&((p->typf2&NQ)==NPOINTER||(p->typf2&NQ)==FPOINTER)&&isreg(z)&&((p->q2.flags&(KONST|DREFOBJ))==KONST||(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)) 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)) 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) break;
+	    o=&p2->q1;
+	  }
+	  if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
+	    if(o) break;
+	    o=&p2->q2;
+	  }
+	  if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
+	    if(o) 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)){
+		  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)){
+		  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;
+}
+/* prints label types used by tasking assembler */
+static void emit_label_type(FILE *f,struct Var *v)
+{
+  if(TASKING){
+    if(ISFUNC(v->vtyp->flags)){
+      if(TINY)
+	emit(f,"near");
+      else
+	emit(f,"far");
+    }else{
+      if((v->vtyp->flags&NQ)==BIT)
+	emit(f,"bit");
+      else if((v->vtyp->flags&NQ)==CHAR)
+	emit(f,"byte");
+      else
+	emit(f,"word");
+    }
+  }
+}
+static void move(FILE *f,struct obj *q,int qr,struct obj *z,int zr,int t)
+/*  Generates code to move object q (or register qr) into object z (or  */
+/*  register zr). One must be a register and DREFOBJ only allowed with  */
+/*  registers.                                                          */
+{
+  long l=0;
+  t&=NQ;
+  if(q&&(q->flags&(REG|DREFOBJ))==REG) qr=q->reg;
+  if(z&&(z->flags&(REG|DREFOBJ))==REG) zr=z->reg;
+  if(qr&&qr==zr) return;
+  if((t&NQ)==BIT){
+    if(!zr&&((z->flags&(VAR|REG|DREFOBJ|VARADR))!=VAR||!ISSTATIC(z->v))) ierror(0);
+    if(q&&(q->flags&(KONST|DREFOBJ))==KONST){
+      if(z&&(z->flags&(VAR|DREFOBJ))==VAR&&isesfrbitv(z->v))
+	emit(f,"\textr\t#1\n");
+      eval_const(&q->val,BIT);
+      if(zmeqto(vmax,l2zm(0L)))
+	emit(f,"\tbclr\t");
+      else
+	emit(f,"\tbset\t");
+      if(zr) emit(f,"%s.0",regnames[zr]); else emit_obj(f,z,t);
+      emit(f,"\n");
+    }else{
+      if(!qr&&((q->flags&(VAR|REG|DREFOBJ|VARADR))!=VAR||!ISSTATIC(q->v))) ierror(0);
+      if((q->flags&(VAR|DREFOBJ))==VAR&&isesfrbitv(q->v)){
+	if(!zr&&((z->flags&(VAR|DREFOBJ))!=VAR||!isesfrbitv(z->v))){
+	  emit(f,"\textr\t#1\n");
+	  emit(f,"\tbmov\t%s.0,",regnames[ti]);
+	  if(qr) emit(f,"%s.0",regnames[qr]); else emit_obj(f,q,t);
+	  emit(f,"\n");
+	  emit(f,"\tbmov\t");
+	  if(zr) emit(f,"%s.0",regnames[zr]); else emit_obj(f,z,t);
+	  emit(f,",%s.0\n",regnames[ti]);
+	  return;
+	}else
+	  emit(f,"\textr\t#1\n");
+      }else if(z&&(z->flags&(VAR|DREFOBJ))==VAR&&isesfrbitv(z->v)){
+	if(!qr){
+	  emit(f,"\tbmov\t%s.0,",regnames[ti]);
+	  if(qr) emit(f,"%s.0",regnames[qr]); else emit_obj(f,q,t);
+	  emit(f,"\n");
+	  emit(f,"\textr\t#1\n");
+	  emit(f,"\tbmov\t");emit_obj(f,z,t);
+	  emit(f,",%s.0\n",regnames[ti]);
+	  return;
+	}else
+	  emit(f,"\textr\t#1\n");
+      }
+      emit(f,"\tbmov\t");
+      if(zr) emit(f,"%s.0",regnames[zr]); else emit_obj(f,z,t);
+      emit(f,",");
+      if(qr) emit(f,"%s.0",regnames[qr]); else emit_obj(f,q,t);
+      emit(f,"\n");
+    }
+    return;
+  }
+  if(q){
+    if(!zr) ierror(0);
+    if(q->am&&reg_pair(q->am->base,&rp)){
+      l=rp.SOF;
+      if(zr>16)
+	emit(f,"\texts\t%s,#2\n",regnames[rp.SEG]);
+      else
+	emit(f,"\texts\t%s,#1\n",regnames[rp.SEG]);
+    }else if((q->flags&DREFOBJ)&&reg_pair(q->reg,&rp)){
+      l=rp.SOF;
+      if(zr>16)
+	emit(f,"\texts\t%s,#2\n",regnames[rp.SEG]);
+      else
+	emit(f,"\texts\t%s,#1\n",regnames[rp.SEG]);
+    }else if((q->flags&(VAR|REG|VARADR))==VAR&&ISSTATIC(q->v)&&ISFAR(q->v)){
+      emit(f,"\texts\t#SEG ");
+      isseg=1;emit_obj(f,q,INT);
+      if(zr>16)
+	emit(f,",#2\n");
+      else
+	emit(f,",#1\n");
+    }
+    if(reg_pair(zr,&rp)){
+      if(q->am){
+	emit(f,"\tmov\t%s,",regnames[rp.r1]);
+	emit_obj(f,q,t);emit(f,"\n");
+	q->am->offset+=2;
+	emit(f,"\tmov\t%s,",regnames[rp.r2]);
+	emit_obj(f,q,t);emit(f,"\n");
+	q->am->offset-=2;
+	return;
+      }else if(q->flags&DREFOBJ){
+	int tmp=0;
+	if(!(q->flags&REG)) ierror(0);
+	if(!l) l=q->reg;
+	if(l==rp.r1){
+	  tmp=rp.r1;
+	  /*FIXME: tp hier immer frei? */
+	  BSET(regs_modified,tp);
+	  rp.r1=tp;
+	}
+	/*FIXME: test auf scratchreg*/
+	if(q->reg>MAXR){
+	  emit(f,"\tmov\t%s,[%s+]\n",regnames[rp.r1],regnames[l]);
+	  emit(f,"\tmov\t%s,[%s]\n",regnames[rp.r2],regnames[l]);
+	}else{
+	  emit(f,"\tmov\t%s,[%s]\n",regnames[rp.r1],regnames[l]);
+	  emit(f,"\tmov\t%s,[%s+#2]\n",regnames[rp.r2],regnames[l]);
+	}
+	if(tmp) emit(f,"\tmov\t%s,%s\n",regnames[tmp],regnames[rp.r1]);
+	return;
+      }else if(q->flags&VARADR){
+	q->flags&=~VARADR;
+	emit(f,"\tmov\t%s,#",regnames[rp.r1]);emit_obj(f,q,t);emit(f,"\n");
+	emit(f,"\tmov\t%s,#SEG ",regnames[rp.r2]);isseg=1;emit_obj(f,q,t);emit(f,"\n");
+	q->flags|=VARADR;
+	return;
+      }else if((q->flags&(KONST|DREFOBJ))==KONST){
+	long l2;
+	if(ISFLOAT(t)) ierror(0);
+	eval_const(&q->val,t);
+	l=zm2zl(zmand(vmax,l2zm(65535L)));
+	emit(f,"\tmov\t%s,#%ld\n",regnames[rp.r1],l);
+	l2=zm2l(zmrshift(vmax,l2zm(16L)));
+	if(l2==l) emit(f,"\tmov\t%s,%s\n",regnames[rp.r2],regnames[rp.r1]);
+	else emit(f,"\tmov\t%s,#%ld\n",regnames[rp.r2],l2);
+	return;
+      }else if(qr){
+	if(!reg_pair(qr,&qp)) ierror(0);
+	emit(f,"\tmov\t%s,%s\n",regnames[rp.r1],regnames[qp.r1]);
+	emit(f,"\tmov\t%s,%s\n",regnames[rp.r2],regnames[qp.r2]);
+	return;
+      }else{
+	if(!(q->flags&VAR)) ierror(0);
+	if(q->v->storage_class==AUTO||q->v->storage_class==REGISTER){
+	  l=voff(q);
+	  if(l)
+	    emit(f,"\tmov\t%s,[%s+#%ld]\n",regnames[rp.r1],regnames[sp],l);
+	  else
+	    emit(f,"\tmov\t%s,[%s]\n",regnames[rp.r1],regnames[sp]);
+	  emit(f,"\tmov\t%s,[%s+#%ld]\n",regnames[rp.r2],regnames[sp],l+2);
+	  return;
+	}else{
+	  emit(f,"\tmov\t%s,",regnames[rp.r1]);emit_obj(f,q,t);emit(f,"\n");
+	  emit(f,"\tmov\t%s,",regnames[rp.r2]);emit_obj(f,q,t);emit(f,"+2\n");
+	  return;
+	}
+      }
+      ierror(0);
+    }else{
+      emit(f,"\tmov%s\t%s,",x_t[t&NQ],(t==CHAR?bregnames[zr]:regnames[zr]));
+      if(qr&&t==CHAR)
+	emit(f,"%s",bregnames[qr]); 
+      else if(!q->am&&(q->flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&reg_pair(q->reg,&rp))
+	emit(f,"[%s]",regnames[rp.SOF]);
+      else
+	emit_obj(f,q,t);
+      emit(f,"\n");
+      return;
+    }
+  }
+  if(z){
+    if(!qr) ierror(0);
+    if(z->am&&reg_pair(z->am->base,&rp)){
+      l=rp.SOF;
+      if(qr>16)
+	emit(f,"\texts\t%s,#2\n",regnames[rp.SEG]);
+      else
+	emit(f,"\texts\t%s,#1\n",regnames[rp.SEG]);      
+    }else if((z->flags&DREFOBJ)&&reg_pair(z->reg,&rp)){
+      l=rp.SOF;
+      if(qr>16)
+	emit(f,"\texts\t%s,#2\n",regnames[rp.SEG]);
+      else
+	emit(f,"\texts\t%s,#1\n",regnames[rp.SEG]);
+    }else if((z->flags&(VAR|REG|VARADR))==VAR&&ISSTATIC(z->v)&&ISFAR(z->v)){
+      emit(f,"\texts\t#SEG ");
+      isseg=1;emit_obj(f,z,INT);
+      if(qr>16)
+	emit(f,",#2\n");
+      else
+	emit(f,",#1\n");
+    }
+    if(reg_pair(qr,&rp)){
+      if(z->am){
+	emit(f,"\tmov\t");emit_obj(f,z,t);emit(f,",%s\n",regnames[rp.r1]);
+	z->am->offset+=2;
+	emit(f,"\tmov\t");emit_obj(f,z,t);emit(f,",%s\n",regnames[rp.r2]);
+	z->am->offset-=2;
+	return;
+      }else if(z->flags&DREFOBJ){
+	if(!(z->flags&REG)) ierror(0);
+	if(!l) l=z->reg;
+	/*FIXME: test auf scratchreg statt >MAXR*/
+	if(z->reg>MAXR&&l!=rp.r2){
+	  emit(f,"\tmov\t[%s+],%s\n",regnames[l],regnames[rp.r1]);
+	  emit(f,"\tmov\t[%s],%s\n",regnames[l],regnames[rp.r2]);
+	}else{
+	  emit(f,"\tmov\t[%s],%s\n",regnames[l],regnames[rp.r1]);
+	  emit(f,"\tmov\t[%s+#2],%s\n",regnames[l],regnames[rp.r2]);
+	}
+	return;
+      }else if(zr){
+	if(!reg_pair(zr,&qp)) ierror(0);
+	emit(f,"\tmov\t%s,%s\n",regnames[qp.r1],regnames[rp.r1]);
+	emit(f,"\tmov\t%s,%s\n",regnames[qp.r2],regnames[rp.r2]);
+	return;
+      }else{
+	if(!(z->flags&VAR)) ierror(0);
+	if(z->v->storage_class==AUTO||z->v->storage_class==REGISTER){
+	  l=voff(z);
+	  if(l)
+	    emit(f,"\tmov\t[%s+#%ld],%s\n",regnames[sp],l,regnames[rp.r1]);
+	  else
+	    emit(f,"\tmov\t[%s],%s\n",regnames[sp],regnames[rp.r1]);
+	  emit(f,"\tmov\t[%s+#%ld],%s\n",regnames[sp],l+2,regnames[rp.r2]);
+	  return;
+	}else{
+	  emit(f,"\tmov\t");emit_obj(f,z,t);emit(f,",%s\n",regnames[rp.r1]);
+	  emit(f,"\tmov\t");emit_obj(f,z,t);emit(f,"+2,%s\n",regnames[rp.r2]);
+	  return;
+	}
+      }
+      ierror(0);
+    }else{
+      emit(f,"\tmov%s\t",x_t[t&NQ]);
+      if(!z->am&&(z->flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&reg_pair(z->reg,&rp))
+	emit(f,"[%s]",regnames[rp.SOF]);
+      else if(zr&&t==CHAR)
+	emit(f,"%s",bregnames[zr]);
+      else
+	emit_obj(f,z,t);
+      emit(f,",%s\n",((t==CHAR)?bregnames[qr]:regnames[qr]));
+      return;
+    }
+  }
+  /*reg->reg*/
+  if(t==CHAR){
+    emit(f,"\tmovb\t%s,%s\n",bregnames[zr],bregnames[qr]);
+  }else if(ISLWORD(t)){
+    if(!reg_pair(qr,&qp)) ierror(0);
+    if(!reg_pair(zr,&rp)) ierror(0);
+    emit(f,"\tmov\t%s,%s\n",regnames[rp.r1],regnames[qp.r1]);
+    emit(f,"\tmov\t%s,%s\n",regnames[rp.r2],regnames[qp.r2]);
+  }else{
+    emit(f,"\tmov\t%s,%s\n",regnames[zr],regnames[qr]);
+  }
+}
+
+static int get_reg(FILE *f,struct IC *p)
+{
+  int i;
+  for(i=1;i<=16;i++){
+    if(!regs[i]&&regscratch[i]){
+      BSET(regs_modified,i);
+      return i;
+    }
+  }
+  ierror(0);
+}
+
+static void save_result(FILE *f,int r,struct IC *p,int t)
+/*  Saves result in register r to object o. May use tp or ti. */ 
+{
+  if((p->z.flags&(REG|DREFOBJ))==DREFOBJ){
+    BSET(regs_modified,tp);
+    if(ISLWORD(p->z.dtyp)){
+      if(!ti2_used) tmp4=ti2; else tmp4=get_reg(f,p);
+      BSET(regs_modified,tmp3);
+      tmp3=tp;
+      p->z.flags&=~DREFOBJ;
+      move(f,&p->z,0,0,MTMP2,FPOINTER);
+      p->z.flags=(DREFOBJ|REG);
+      p->z.reg=MTMP2;
+    }else if(!(p->z.flags&KONST)){
+      int tmp=(r==tp)?ti:tp;
+      BSET(regs_modified,tmp);
+      p->z.flags&=~DREFOBJ;
+      move(f,&p->z,0,0,tmp,NPOINTER);
+      p->z.flags=(DREFOBJ|REG);
+      p->z.reg=tmp;
+    }
+  }
+  move(f,0,r,&p->z,0,t);
+}
+
+static int scratchreg(int r,struct IC *p)
+{
+  int c;
+  if(r==tp||r==ti||r==ti2||r==MTMP1||r==MTMP2)
+    return 1;
+  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&REG)&&p->q1.reg==r) return 0;
+    if((p->q2.flags&REG)&&p->q2.reg==r) return 0;
+    if((p->z.flags&REG)&&p->z.reg==r) return 0;
+  }
+}
+
+static char *longcmd(char *s)
+{
+  if(!strcmp(s,"add")) return "addc";
+  if(!strcmp(s,"sub")) return "subc";
+  /*FIXME*/
+  return s;
+}
+
+/* perform long arithmetic using library functions */
+/* the functions take arguments in r4/r5 and r10/r11 */
+/* giving the result in r4/r5 */
+/* returns , if the operation was performed, 0 if */
+/* the IC should be handled by inline-code */
+static int lib_larith(FILE *f,struct IC *p)
+{
+  int r4p,r5p,c=p->code,t=ztyp(p);char *s;
+  if(regs[r4]&&(!isreg(z)||p->z.reg==r4r5)){
+    emit(f,"\tmov\t[-%s],%s\n",regnames[sp],regnames[r4]);
+    push(2,0);
+    r4p=1;
+  }else
+    r4p=0;
+  if(regs[r5]&&(!isreg(z)||p->z.reg==r4r5)){
+    emit(f,"\tmov\t[-%s],%s\n",regnames[sp],regnames[r5]);
+    push(2,0);
+    r5p=1;
+  }else
+    r5p=0;
+  if(!p->q1.am&&(p->q1.flags&DREFOBJ)){
+    if(!(p->q1.flags&(REG))){
+      if(ISLWORD(p->q1.dtyp)){
+	tmp3=ti2;tmp4=ti;ti2_used=1;
+	BSET(regs_modified,ti);
+	BSET(regs_modified,ti2);
+	p->q1.flags&=~DREFOBJ;
+	move(f,&p->q1,0,0,MTMP2,FPOINTER);
+	p->q1.reg=MTMP2;
+	p->q1.flags=(REG|DREFOBJ);
+      }else if(!(p->q1.flags&KONST)){
+	BSET(regs_modified,ti);
+	p->q1.flags&=~DREFOBJ;
+	move(f,&p->q1,0,0,ti,NPOINTER);
+	p->q1.reg=ti;
+	p->q1.flags=(REG|DREFOBJ);
+      }
+    }
+  }
+  BSET(regs_modified,r4r5);
+  move(f,&p->q1,0,0,r4r5,q1typ(p));
+  if(!p->q2.am&&(p->q2.flags&DREFOBJ)){
+    if(!(p->q2.flags&(REG))){
+      if(ISLWORD(p->q2.dtyp)){
+	BSET(regs_modified,ti); 
+	BSET(regs_modified,ti2);
+	tmp3=ti2;tmp4=ti;ti2_used=1;
+	p->q2.flags&=~DREFOBJ;
+	move(f,&p->q2,0,0,MTMP2,FPOINTER);
+	p->q2.reg=MTMP2;
+	p->q2.flags=(REG|DREFOBJ);
+      }else if(!(p->q2.flags&KONST)){
+	BSET(regs_modified,ti);
+	p->q2.flags&=~DREFOBJ;
+	move(f,&p->q2,0,0,ti,NPOINTER);
+	p->q2.reg=ti;
+	p->q2.flags=(REG|DREFOBJ);
+      }
+    }
+  }  
+  /* ti/ti2 must be r10/r11 */
+  tmp3=ti;tmp4=ti2;ti2_used=1;
+  BSET(regs_modified,ti); 
+  BSET(regs_modified,ti2);
+  move(f,&p->q2,0,0,MTMP2,q2typ(p));
+  if(c==MULT)
+    s="_mul";
+  else if(c==DIV&&(t&UNSIGNED))
+    s="_udil";
+  else if(c==DIV&&!(t&UNSIGNED))
+    s="_sdil";
+  else if(c==MOD&&(t&UNSIGNED))
+    s="_umol";
+  else if(c==MOD&&!(t&UNSIGNED))
+    s="_smol";
+  else
+    ierror(0);
+  if(TASKING){
+    emit(f,"\textern\t%s%s:%s\n",idprefix,s,TINY?"near":"far");
+    emit(f,"\t%s\t%s%s\n",call,idprefix,s);
+  }
+  save_result(f,r4r5,p,ztyp(p));
+  if(r5p){
+    emit(f,"\tmov\t%s,[%s+]\n",regnames[r5],regnames[sp]);
+    pop(2,0);
+  }
+  if(r4p){
+    emit(f,"\tmov\t%s,[%s+]\n",regnames[r4],regnames[sp]);
+    pop(2,0);
+  }  
+  return 1;
+}
+
+/****************************************/
+/*  End of private fata and functions.  */
+/****************************************/
+
+int emit_peephole(void)
+{
+  int entries,i;long x,y,z;
+  char *asmline[EMIT_BUF_DEPTH];
+  i=emit_l;
+  if(emit_f==0)
+    entries=i-emit_f+1;
+  else
+    entries=EMIT_BUF_DEPTH;
+  asmline[0]=emit_buffer[i];
+  if(entries>=1){
+    if(sscanf(asmline[0],"\tshl\tR%ld,#%ld\n",&x,&y)==2&&(y<0||y>15)){
+      sprintf(asmline[0],"\tmov\tR%ld,#0\n",x);
+      return 1;
+    }
+    if(sscanf(asmline[0],"\tshr\tR%ld,#%ld\n",&x,&y)==2&&(y<0||y>15)){
+      sprintf(asmline[0],"\tmov\tR%ld,#0\n",x);
+      return 1;
+    }
+  }
+  if(entries>=2){
+    i--;
+    if(i<0) i=EMIT_BUF_DEPTH-1;
+    asmline[1]=emit_buffer[i];
+    if(sscanf(asmline[0],"\tadd\tR0,#%ld",&x)==1&&sscanf(asmline[1],"\tadd\tR0,#%ld",&y)==1){
+      sprintf(asmline[1],"\tadd\tR0,#%ld\n",x+y);
+      remove_asm();
+      return 1;
+    }
+    if(sscanf(asmline[1],"\tmov\tR11,#%ld",&x)==1&&sscanf(asmline[0],"\texts\tR11,#%ld",&y)==1){
+      sprintf(asmline[1],"\texts\t#%ld,#%ld\n",x,y);
+      remove_asm();
+      return 1;
+    }
+  }
+  if(entries>=3){
+    i--;
+    if(i<0) i=EMIT_BUF_DEPTH-1;
+    asmline[2]=emit_buffer[i];
+    if(sscanf(asmline[2],"\tmov\tR1,#%ld",&x)==1&&sscanf(asmline[1],"\texts\t#%ld,#1",&y)==1&&sscanf(asmline[0],"\tmov\t[R1],R%ld",&z)==1){
+      strcpy(asmline[2],asmline[1]);
+      sprintf(asmline[1],"\tmov\t%ld,R%ld\n",x,z);
+      remove_asm();
+      return 1;
+    }
+  }
+  return 0;
+}
+
+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;
+  /*  Initialize some values which cannot be statically initialized   */
+  /*  because they are stored in the target's arithmetic.             */
+  maxalign=l2zm(2L);
+  char_bit=l2zm(8L);
+  for(i=0;i<=MAX_TYPE;i++){
+    sizetab[i]=l2zm(msizetab[i]);
+    align[i]=l2zm(malign[i]);
+  }
+  for(i=1;i<=MAXR;i++){
+    if(i<=16){
+      regsize[i]=l2zm(2L);regtype[i]=&ityp;
+    }else{
+      regsize[i]=l2zm(4L);regtype[i]=&ltyp;
+    }
+  }	
+  
+  /*  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.          */
+  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);
+
+  /*  Reserve a few registers for use by the code-generator.      */
+  regsa[sp]=regsa[tp]=regsa[ti]=regsa[ti2]=1;
+  regscratch[sp]=regscratch[tp]=regscratch[ti]=regscratch[ti2]=0;
+  target_macros=marray;
+  if(TINY) marray[0]="__TINY__";
+  else if(LARGE) marray[0]="__LARGE__";
+  else if(HUGE) marray[0]="__HUGE__";
+  else marray[0]="__MEDIUM__";
+
+  if(!TASKING){
+    codename="\t.section\t.text,\"carx1\"\n";
+    ndataname="\t.section\t.ndata,\"darw1\"\n";
+    fdataname="\t.section\t.fdata,\"darw1\"\n";
+    hdataname="\t.section\t.hdata,\"darw1\"\n";
+    nbssname="\t.section\t.nbss,\"uarw1\"\n";
+    fbssname="\t.section\t.fbss,\"uarw1\"\n";
+    hbssname="\t.section\t.hbss,\"uarw1\"\n";
+    ncdataname="\t.section\t.ncdata,\"dar1\"\n";
+    fcdataname="\t.section\t.fcdata,\"dar1\"\n";
+    hcdataname="\t.section\t.hcdata,\"dar1\"\n";
+    bitsname="\t.section\t.bits,\"darw0\"\n";
+    even="\t.align\t1\n";
+    public=".global";
+    comment="; ";
+  }
+
+  nvar.storage_class=STATIC;
+  fvar.storage_class=STATIC;
+
+
+  /* TODO: set argument registers */
+  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(f==LLONG||f==DOUBLE||f==LDOUBLE)
+    return 0;
+  if(ISSCALAR(f)){
+    if(f==LONG||f==FPOINTER||f==HPOINTER)
+      return 20;
+    else
+      return 5;
+  }
+  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.                  */
+{
+  t&=NQ;
+  if(r==0) return(0);
+  if(mode>0&&!ISPOINTER(t)) return 0;
+  if(t==NPOINTER&&mode>0){
+    if(r<=4) return 1; else return 0;
+  }
+  if(t<=CHAR&&r>8) return 0;
+  if((t<LONG||t==NPOINTER)&&r<=16) return 1;
+  if(t==LONG||t==FLOAT||t==FPOINTER||t==HPOINTER){
+    if(r>16) 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<=16) return 0;
+  if(p){
+    switch(r){
+    case 17: p->r1=7;p->r2=8;break;
+    case 18: p->r1=8;p->r2=9;break;
+    case 19: p->r1=9;p->r2=10;break;
+    case 20: p->r1=5;p->r2=6;break;
+    case 21: p->r1=15;p->r2=16;break;
+    case 22: p->r1=14;p->r2=15;break;
+    case 23: p->r1=13;p->r2=14;break;
+    case 24: p->r1=4;p->r2=5;break;
+    case 25: p->r1=3;p->r2=4;break;
+	
+    /* pseudos */
+    case MTMP1: p->r1=tmp1;p->r2=tmp2;break;
+    case MTMP2: p->r1=tmp3;p->r2=tmp4;break;
+    case ZEROS: return 0;
+    case ONES: return 0;
+    default: ierror(0);
+    }
+  }
+  return 1;
+}
+
+int cost_savings(struct IC *p,int r,struct obj *o)
+{
+  int c=p->code;
+  if((o->flags&DREFOBJ)){
+    if(o->flags&VKONST) return 1;
+    if(r<=4&&p->q2.flags&&o!=&p->z)
+      return 6;
+    else
+      return 4;
+  }else if(o->flags&VKONST){
+    struct obj *co=&o->v->cobj;
+    if((p->code==ASSIGN&&(p->z.flags&DREFOBJ))||p->code==PUSH)
+      return 4;
+    if(co->flags&VARADR)
+      return 4;
+    if(o==&p->q1)
+      eval_const(&co->val,q1typ(p));
+    else
+      eval_const(&co->val,q2typ(p));
+    /*FIXME*/
+    return 0;
+  }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)&&regok(r,CHAR,0)){
+    return 3;
+  }
+  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;
+}
+
+int must_convert(int o,int t,int const_expr)
+/*  Returns zero if code for converting np to type t    */
+/*  can be omitted.                                     */
+/*  In this generic 32bit RISC cpu pointers and 32bit   */
+/*  integers have the same representation and can use   */
+/*  the same registers.                                 */
+{
+  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 0
+  emit(f,"\tds\t%ld\n",zm2l(size));
+#endif
+  /*FIXME: we currently do not use ds because of initialization */
+  long l=zm2l(size);
+  if(TASKING){
+    if(t&&(t->flags&NQ)==BIT){
+      emit(f,"\tdbit\n");
+      return;
+    }
+    /*FIXME:alignment while(size>=4) {emit(f,"\tddw\t0\n");size-=4;}*/
+    while(size--) emit(f,"\tdb\t0\n");
+  }else{
+    if(newobj&&section!=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.              */
+{
+  if(section!=BITS&&!zmleq(align,l2zm(1L)))
+    emit(f,even);
+}
+static void new_section(FILE *f,int nsec)
+{
+  if(!f||section==nsec) return;
+  if(TASKING)
+    emit(f,sec_end);
+  section=nsec;
+  if(nsec==HDATA){
+    emit(f,hdataname);
+    strcpy(sec_end,ehdata);
+  }else if(nsec==FDATA){
+    emit(f,fdataname);
+    strcpy(sec_end,efdata);
+  }else if(nsec==NDATA){
+    emit(f,ndataname);
+    strcpy(sec_end,endata);
+  }else if(nsec==HCDATA){
+    emit(f,hcdataname);
+    strcpy(sec_end,ehcdata);
+  }else if(nsec==FCDATA){
+    emit(f,fcdataname);
+    strcpy(sec_end,efcdata);
+  }else if(nsec==NCDATA){
+    emit(f,ncdataname);
+    strcpy(sec_end,encdata);
+  }else if(nsec==HBSS){
+    emit(f,hbssname);
+    strcpy(sec_end,ehbss);
+  }else if(nsec==FBSS){
+    emit(f,fbssname);
+    strcpy(sec_end,efbss);
+  }else if(nsec==NBSS){
+    emit(f,nbssname);
+    strcpy(sec_end,enbss);
+  }else if(nsec==BITS){
+    emit(f,bitsname);
+    strcpy(sec_end,ebits);
+  }
+}
+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;
+  char *attr;struct Typ *tv;
+  tv=v->vtyp;
+  while(tv->flags==ARRAY) tv=tv->next;
+  attr=tv->attr;
+  if(v->clist) constflag=is_const(v->vtyp);
+  if(v->storage_class==STATIC){
+    if(ISFUNC(v->vtyp->flags)) return;
+    if(!TASKING){
+      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(!special_section(f,v)){
+      if((v->vtyp->flags&NQ)==BIT){
+	new_section(f,BITS);
+      }else{
+	if(v->clist&&(!constflag||(g_flags[3]&USEDFLAG))){
+	  if(attr&&strstr(attr,STR_HUGE))
+	    new_section(f,HDATA);
+	  else if(attr&&strstr(attr,STR_FAR))
+	    new_section(f,FDATA);
+	  else if(attr&&strstr(attr,STR_NEAR))
+	    new_section(f,NDATA);
+	  else{
+	    if(HUGE)
+	      new_section(f,HDATA);
+	    else if(LARGE)
+	      new_section(f,FDATA);
+	    else
+	      new_section(f,NDATA);
+	  }
+	}
+	if(v->clist&&constflag&&!(g_flags[3]&USEDFLAG)){
+	  if(attr&&strstr(attr,STR_HUGE))
+	    new_section(f,HCDATA);
+	  else if(attr&&strstr(attr,STR_FAR))
+	    new_section(f,FCDATA);
+	  else if(attr&&strstr(attr,STR_NEAR))
+	    new_section(f,NCDATA);
+	  else{
+	    if(HUGE)
+	      new_section(f,HCDATA);
+	    else if(LARGE)
+	      new_section(f,FCDATA);
+	    else
+	      new_section(f,NCDATA);
+	  }
+	}
+	if(!v->clist){
+	  if(attr&&strstr(attr,STR_HUGE))
+	    new_section(f,HBSS);
+	  else if(attr&&strstr(attr,STR_FAR))
+	    new_section(f,FBSS);
+	  else if(attr&&strstr(attr,STR_NEAR))
+	    new_section(f,NBSS);
+	  else{
+	    if(HUGE)
+	      new_section(f,HBSS);
+	    else if(LARGE)
+	      new_section(f,FBSS);
+	    else
+	      new_section(f,NBSS);
+	  }
+	}
+      }
+    }
+    gen_align(f,falign(v->vtyp));
+    if(TASKING){
+      emit(f,"%s%ld\tlabel\t",labprefix,zm2l(v->offset));
+      emit_label_type(f,v);
+      emit(f,"\n");
+    }else{
+      if(dppuse(v,section)>=0)
+        emit(f,"\t.set\t%s%s%ld,%d\n",dppprefix,labprefix,zm2l(v->offset),dppuse(v,section));
+      emit(f,"%s%ld:\n",labprefix,zm2l(v->offset));
+    }
+  }
+  if(v->storage_class==EXTERN){
+    if(v->flags&(DEFINED|TENTATIVE)){
+      if(!TASKING){
+	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)));
+      }
+      emit(f,"\t%s\t%s%s\n",public,idprefix,v->identifier);
+      if(!special_section(f,v)){
+	if((v->vtyp->flags&NQ)==BIT){
+	  if(f&&section!=BITS){
+	    if(TASKING)
+	      emit(f,sec_end);
+	    strcpy(sec_end,ebits);
+	    emit(f,bitsname);
+	    section=BITS;	  
+	  }
+	}else{
+	  if(v->clist&&(!constflag||(g_flags[3]&USEDFLAG))){
+	    if(attr&&strstr(attr,STR_HUGE))
+	      new_section(f,HDATA);
+	    else if(attr&&strstr(attr,STR_FAR))
+	      new_section(f,FDATA);
+	    else if(attr&&strstr(attr,STR_NEAR))
+	      new_section(f,NDATA);
+	    else{
+	      if(HUGE)
+		new_section(f,HDATA);
+	      else if(LARGE)
+		new_section(f,FDATA);
+	      else
+		new_section(f,NDATA);
+	    }
+	  }
+	  if(v->clist&&constflag&&!(g_flags[3]&USEDFLAG)){
+	    if(attr&&strstr(attr,STR_HUGE))
+	      new_section(f,HCDATA);
+	    else if(attr&&strstr(attr,STR_FAR))
+	      new_section(f,FCDATA);
+	    else if(attr&&strstr(attr,STR_NEAR))
+	      new_section(f,NCDATA);
+	    else{
+	      if(HUGE)
+		new_section(f,HCDATA);
+	      else if(LARGE)
+		new_section(f,FCDATA);
+	      else
+		new_section(f,NCDATA);
+	    }
+	  }
+	  if(!v->clist){
+	    if(attr&&strstr(attr,STR_HUGE))
+	      new_section(f,HBSS);
+	    else if(attr&&strstr(attr,STR_FAR))
+	      new_section(f,FBSS);
+	    else if(attr&&strstr(attr,STR_NEAR))
+	      new_section(f,NBSS);
+	    else{
+	      if(HUGE)
+		new_section(f,HBSS);
+	      else if(LARGE)
+		new_section(f,FBSS);
+	      else
+		new_section(f,NBSS);
+	    }
+	  }
+	}
+      }
+      gen_align(f,falign(v->vtyp));
+      if(TASKING){
+	emit(f,"%s%s\tlabel\t",idprefix,v->identifier);
+	emit_label_type(f,v);
+	emit(f,"\n");
+      }else{
+        if(dppuse(v,section)>=0){
+          emit(f,"\t.global\t%s%s%s\n",dppprefix,idprefix,v->identifier);
+          emit(f,"\t.set\t%s%s%s,%d\n",dppprefix,idprefix,v->identifier,dppuse(v,section));
+        }
+	emit(f,"%s%s:\n",idprefix,v->identifier);
+      }
+    }else if(strcmp(v->identifier,"__va_start")&&!issfrv(v)&&!isesfrv(v)&&!issfrbitv(v)&&!isesfrbitv(v)){
+      if(TASKING){
+	emit(f,"\textern\t%s%s:",idprefix,v->identifier);
+	emit_label_type(f,v);
+	emit(f,"\n");
+      }else{
+	emit(f,"\t.global\t%s%s\n",idprefix,v->identifier);
+      }
+    }
+  }
+}
+
+void gen_dc(FILE *f,int t,struct const_list *p)
+/*  This function has to create static storage          */
+/*  initialized with const-list p.                      */
+{
+  if(ISPOINTER(t)){
+    if(p->tree)
+      emit(f,"\t%s\t",TASKING?dct[t&NQ]:vdct[t&NQ]); 
+    if(ISLWORD(t))
+      t=UNSIGNED|LONG;
+    else
+      t=UNSIGNED|SHORT;
+    if(!p->tree)
+      emit(f,"\t%s\t",TASKING?dct[t&NQ]:vdct[t&NQ]);
+  }else{
+    emit(f,"\t%s\t",TASKING?dct[t&NQ]:vdct[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{
+      if(ISLWORD(t)){
+	long l;
+	eval_const(&p->val,t);
+	l=zm2l(zmand(p->val.vmax,l2zm(65535L)));
+	emit(f,"%ld",l);
+	l=zm2l(zmand(zmrshift(p->val.vmax,l2zm(16L)),l2zm(65535L)));
+	emit(f,",%ld",l);
+      }else if((t&NQ)!=BIT)
+	/*FIXME: initialization of bits impossible */
+	emitval(f,&p->val,(t&NU)|UNSIGNED);
+    }
+  }else{
+    int m=p->tree->o.flags;
+    p->tree->o.flags&=~VARADR;
+    emit_obj(f,&p->tree->o,t&NU);
+    p->tree->o.flags=m;
+  }
+  emit(f,"\n");
+}
+
+/*  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 *p,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,*cc=0;int cc_t;
+  struct IC *p2;
+  if(TINY){
+    ret="ret";
+    call="calla\tcc_uc,";
+    jump="jmpa\tcc_uc,";
+  }else{
+    ret="rets";
+    call="calls";
+    jump="jmps\t";
+  }
+  if(v->tattr&INTERRUPT)
+    ret="reti";
+  if(DEBUG&1) printf("gen_code()\n");
+  if(!v->fi) v->fi=new_fi();
+  v->fi->flags|=ALL_REGS;
+  if(f&&TASKING&&!idone){
+    emit(f,"$EXTEND\n");
+    emit(f,"$MODEL(SMALL)\n");
+    idone=1;
+  }
+  for(p2=p;p2;p2=p2->next) clear_ext_ic(&p2->ext);
+  if(!(g_flags[5]&USEDFLAG)){
+    peephole(p);
+    if(!frame_used) offset=l2zm(0L);
+  }
+  for(c=1;c<=15;c++) regs[c]=regsa[c];
+  regs[16]=0;
+  for(c=1;c<=MAXR;c++){
+    if(regscratch[c]&&(regsa[c]||regused[c])){
+      BSET(regs_modified,c);
+    }
+  }
+  loff=((zm2l(offset)+1)/2)*2;
+  function_top(f,v,loff);
+  usrstackoffset=sysstackoffset=notpopped=dontpop=usrmaxpushed=sysmaxpushed=0;
+  sysstack=usrstack=0;
+  for(;p;pr(f,p),p=p->next){
+    if((p->q1.flags&(KONST|DREFOBJ))==(KONST|DREFOBJ)){
+      p->q1.flags=VAR;
+      p->q1.v=ISLWORD(p->q1.dtyp)?&fvar:&nvar;
+    }
+    if((p->q2.flags&(KONST|DREFOBJ))==(KONST|DREFOBJ)){
+      p->q2.flags=VAR;
+      p->q2.v=ISLWORD(p->q2.dtyp)?&fvar:&nvar;
+    }
+    if((p->z.flags&(KONST|DREFOBJ))==(KONST|DREFOBJ)){
+      p->z.flags=VAR;
+      p->z.v=ISLWORD(p->z.dtyp)?&fvar:&nvar;
+    }
+    if(!TASKING){
+      int rn,rb;char *rs;
+      if(issfr(q1)){
+	rs=strstr(p->q1.v->vattr,"sfr(");
+	sscanf(rs+4,"%i",&rn);
+	if(rn<=255) rn=0xfe00+2*rn;
+	emit(f,"\t.sfr\t%s,%d\n",p->q1.v->identifier,rn);
+      }
+      if(issfr(q2)){
+	rs=strstr(p->q2.v->vattr,"sfr(");
+	sscanf(rs+4,"%i",&rn);
+	if(rn<=255) rn=0xfe00+2*rn;
+	emit(f,"\t.sfr\t%s,%d\n",p->q2.v->identifier,rn);
+      }
+      if(issfr(z)){
+	rs=strstr(p->z.v->vattr,"sfr(");
+	sscanf(rs+4,"%i",&rn);
+	if(rn<=255) rn=0xfe00+2*rn;
+	emit(f,"\t.sfr\t%s,%d\n",p->z.v->identifier,rn);
+      }
+      if(issfrbit(q1)){
+	rs=strstr(p->q1.v->vattr,"sfrbit(");
+	sscanf(rs+7,"%i,%i",&rn,&rb);
+	if(rn<=255) rn=0xfe00+2*rn;
+	emit(f,"\t.sfr\t%s,%d,%d\n",p->q1.v->identifier,rn,rb);
+      }
+      if(issfrbit(q2)){
+	rs=strstr(p->q2.v->vattr,"sfrbit(");
+	sscanf(rs+7,"%i,%i",&rn,&rb);
+	if(rn<=255) rn=0xfe00+2*rn;
+	emit(f,"\t.sfr\t%s,%d,%d\n",p->q2.v->identifier,rn,rb);
+      }
+      if(issfrbit(z)){
+	rs=strstr(p->z.v->vattr,"sfrbit(");
+	sscanf(rs+7,"%i,%i",&rn,&rb);
+	if(rn<=255) rn=0xfe00+2*rn;
+	emit(f,"\t.sfr\t%s,%d,%d\n",p->z.v->identifier,rn,rb);
+      }
+      if(isesfr(q1)){
+	rs=strstr(p->q1.v->vattr,"sfre(");
+	sscanf(rs+5,"%i",&rn);
+	if(rn<=255) rn=0xf000+2*rn;
+	emit(f,"\t.equ\t%s,%d\n",p->q1.v->identifier,rn);
+      }
+      if(isesfr(q2)){
+	rs=strstr(p->q2.v->vattr,"sfre(");
+	sscanf(rs+5,"%i",&rn);
+	if(rn<=255) rn=0xf000+2*rn;
+	emit(f,"\t.equ\t%s,%d\n",p->q2.v->identifier,rn);
+      }
+      if(isesfr(z)){
+	rs=strstr(p->z.v->vattr,"sfre(");
+	sscanf(rs+5,"%i",&rn);
+	if(rn<=255) rn=0xf000+2*rn;
+	emit(f,"\t.equ\t%s,%d\n",p->z.v->identifier,rn);
+      }
+      if(isesfrbit(q1)){
+	rs=strstr(p->q1.v->vattr,"sfrbite(");
+	sscanf(rs+8,"%i,%i",&rn,&rb);
+	if(rn<=255) rn=0xf000+2*rn;
+	emit(f,"\t.sfr\t%s,%d,%d\n",p->q1.v->identifier,rn,rb);
+      }
+      if(isesfrbit(q2)){
+	rs=strstr(p->q2.v->vattr,"sfrbite(");
+	sscanf(rs+8,"%i,%i",&rn,&rb);
+	if(rn<=255) rn=0xf000+2*rn;
+	emit(f,"\t.sfr\t%s,%d,%d\n",p->q2.v->identifier,rn,rb);
+      }
+      if(isesfrbit(z)){
+	rs=strstr(p->z.v->vattr,"sfrbite(");
+	sscanf(rs+8,"%i,%i",&rn,&rb);
+	if(rn<=255) rn=0xf000+2*rn;
+	emit(f,"\t.sfr\t%s,%d,%d\n",p->z.v->identifier,rn,rb);
+      }      
+    }
+
+    c=p->code;t=p->typf;
+    ti2_used=0; short_add=0;
+    if(c==NOP) continue;
+    if(c==ALLOCREG){
+      regs[p->q1.reg]=1;
+      if(reg_pair(p->q1.reg,&rp)) regs[rp.r1]=regs[rp.r2]=1;
+      BSET(regs_modified,p->q1.reg);
+      continue;
+    }
+    if(c==FREEREG){
+      regs[p->q1.reg]=0;
+      if(reg_pair(p->q1.reg,&rp)) regs[rp.r1]=regs[rp.r2]=0;
+      continue;
+    }
+    if(notpopped&&!dontpop){
+      int flag=0;
+      if(c==LABEL||c==COMPARE||c==TEST||c==BRA){
+	emit(f,"\tadd\t%s,#%ld\n",regnames[sp],notpopped);
+	pop(notpopped,0);notpopped=0;cc=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,"\tjmpr\tcc_uc,%s%d\n",labprefix,t);
+      }
+      cc=0;continue;
+    }
+    if(c==BEQ||c==BNE){
+      if(p->ext.flags==EXT_IC_BTST){
+	if(bit_reg){
+	  emit(f,"\tj%sb\t%s.%ld,%s%d\n",(c==BEQ)?"n":"",bit_reg,p->ext.offset,labprefix,t);
+	}else{
+	  if(!bit_obj) ierror(0);
+	  emit(f,"\tj%sb\t",(c==BEQ)?"n":"");
+	  emit_obj(f,bit_obj,t);emit(f,".%ld,%s%d\n",p->ext.offset,labprefix,t);
+	}
+      }else if(lastcomp==BIT){
+	if(c==BEQ) bit_reverse=1-bit_reverse;
+	emit(f,"\tj%sb\t",(bit_reverse==1)?"n":"");
+	if(bit_obj)
+	  emit_obj(f,bit_obj,t);
+	else
+	  emit(f,"%s",bit_reg);
+	emit(f,",%s%d\n",labprefix,t);
+      }else
+	emit(f,"\tjmpr\tcc_%s,%s%d\n",ccs[c-BEQ],labprefix,t);
+      cc=0;continue;
+    }
+    if(c>BNE&&c<BRA){      
+      if(p->ext.flags==EXT_IC_BTST||lastcomp==BIT) ierror(0);
+      if(lastcomp&UNSIGNED) emit(f,"\tjmpr\tcc_u%s,%s%d\n",ccs[c-BEQ],labprefix,t);
+      else              emit(f,"\tjmpr\tcc_s%s,%s%d\n",ccs[c-BEQ],labprefix,t);
+      cc=0;continue;
+    }
+    if(c==MOVETOREG){
+      move(f,&p->q1,0,0,p->z.reg,SHORT);
+      cc=&p->q1;cc_t=SHORT;continue;
+    }
+    if(c==MOVEFROMREG){
+      move(f,0,p->q1.reg,&p->z,0,SHORT);
+      cc=&p->z;cc_t=SHORT;continue;
+    }
+    
+    if((t&NQ)==DOUBLE) {pric2(stdout,p);ierror(0);}
+    if((t&NQ)==BIT){
+      cc=0;
+      if(c==ASSIGN){
+	if(!isreg(z)&&((p->z.flags&(VAR|REG|DREFOBJ|VARADR))!=VAR||!ISSTATIC(p->z.v))) ierror(0);
+	move(f,&p->q1,0,&p->z,0,t);
+	continue;
+      }
+      if(c==COMPARE){
+	if(!isconst(q2)){
+	  if(!isreg(q2)&&((p->q2.flags&(VAR|REG|DREFOBJ|VARADR))!=VAR||!ISSTATIC(p->q2.v))) ierror(0);
+	  bit_reg="PSW.1";bit_obj=0;lastcomp=BIT;bit_reverse=1;
+	  if(isesfrbit(q1)){
+	    if(!isesfrbit(q2)&&!isreg(q2)){
+	      move(f,&p->q1,0,0,ti,t);
+	      emit(f,"\tbcmp\t%s.0,",regnames[ti]);
+	      emit_obj(f,&p->q2,t);emit(f,"\n");
+	      continue;
+	    }else
+	      emit(f,"\textr\t#1\n");
+	  }else if(isesfrbit(q2)){
+	    if(!isreg(q1)){
+	      move(f,&p->q2,0,0,ti,t);
+	      emit(f,"\tbcmp\t");
+	      emit_obj(f,&p->q1,t);
+	      emit(f,",%s.0\n",regnames[ti]);
+	      continue;
+	    }else
+	      emit(f,"\textr\t#1\n");
+	  }
+	  emit(f,"\tbcmp\t");emit_obj(f,&p->q1,t);
+	  emit(f,",");emit_obj(f,&p->q2,t);emit(f,"\n");
+	}else{
+	  bit_reg=0;bit_obj=&p->q1;lastcomp=BIT;
+	  eval_const(&p->q2.val,t);
+	  if(ISNULL())
+	    bit_reverse=0;
+	  else
+	    bit_reverse=1;
+	  if(isesfrbit(q1)) emit(f,"\textr\t#1\n");
+	}
+	continue;
+      }
+      if(c==TEST){
+	bit_reg=0;bit_obj=&p->q1;bit_reverse=0;lastcomp=BIT;
+	if(isesfrbit(q1)) emit(f,"\textr\t#1\n");
+	continue;
+      }
+      if(c==AND||c==OR||c==XOR){
+	char *s;
+	if(compare_objects(&p->z,&p->q2)){
+	  struct obj m;
+	  m=p->q1;p->q1=p->q2;p->q2=m;
+	}
+	if(!compare_objects(&p->q1,&p->z))
+	  move(f,&p->q1,0,&p->z,0,t);
+	/*FIXME: const, esfr etc. */
+	if(c==AND) s="band";
+	else if(c==OR) s="bor";
+	else s="bxor";
+	if(isesfrbit(q2)&&!isesfrbit(z)&&!isreg(z)){
+	  move(f,&p->q2,0,0,ti,t);
+	  emit(f,"\t%s\t",s);
+	  emit_obj(f,&p->z,t);
+	  emit(f,",%s.0\n",regnames[ti]);
+	}else if(isesfrbit(z)&&!isesfrbit(q2)&&!isreg(q2)){
+	  move(f,&p->q2,0,0,ti,t);
+	  emit(f,"\textr\t#1\n");
+	  emit(f,"\t%s\t",s);
+	  emit_obj(f,&p->z,t);
+	  emit(f,",%s.0\n",regnames[ti]);
+	}else{
+	  if(isesfrbit(z)) emit(f,"\textr\t#1\n");
+	  emit(f,"\t%s\t",s);
+	  emit_obj(f,&p->z,t);emit(f,",");
+	  emit_obj(f,&p->q2,t);emit(f,"\n");
+	}
+	continue;
+      }
+      if(c!=CONVERT) ierror(0);
+    }
+
+    if(c==TEST){
+      lastcomp=t;
+      if(p->ext.flags==EXT_IC_CMPIA){
+	if(p->ext.offset<0)
+	  emit(f,"\tsub\t%s,#%ld\n",regnames[p->ext.r],-p->ext.offset);
+	else
+	  emit(f,"\tadd\t%s,#%ld\n",regnames[p->ext.r],p->ext.offset);
+	cc=0;continue;
+      }
+      if(p->ext.flags==EXT_IC_CMPIB){
+	if(p->ext.offset<0)
+	  emit(f,"\tcmpd%ld\t%s,#0\n",-p->ext.offset,regnames[p->ext.r]);
+	else
+	  emit(f,"\tcmpi%ld\t%s,#0\n",p->ext.offset,regnames[p->ext.r]);
+	cc=0;continue;
+      }
+      if(cc&&(cc_t&NU)==(t&NU)&&compare_objects(cc,&p->q1)){
+	continue;
+      }
+      p->code=c=COMPARE;
+      gval.vmax=l2zm(0L);
+      p->q2.flags=KONST;
+      eval_const(&gval,MAXINT);
+      insert_const(&p->q2.val,t);
+    } 
+    if(c==COMPARE&&isconst(q1)){
+      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;
+    }
+    if(c==COMPARE&&p->ext.flags==EXT_IC_CMPIA){
+      long l;
+      if(!isconst(q2)) ierror(0);
+      eval_const(&p->q2.val,t);
+      l=zm2l(vmax);
+      if(p->ext.offset<0)
+	emit(f,"\tcmpd%ld\t%s,#%ld\n",-p->ext.offset,regnames[p->ext.r],l-p->ext.offset);
+      else
+	emit(f,"\tcmpi%ld\t%s,#%ld\n",p->ext.offset,regnames[p->ext.r],l-p->ext.offset);
+      cc=0;lastcomp=t;continue;
+    }
+    if(c==COMPARE&&p->ext.flags==EXT_IC_CMPIB){
+pric2(stdout,p);
+      if(p->ext.offset<0)
+	emit(f,"\tcmpd%ld\t%s,",-p->ext.offset,regnames[p->ext.r]);
+      else
+	emit(f,"\tcmpi%ld\t%s,",p->ext.offset,regnames[p->ext.r]);
+      emit_obj(f,&p->q2,t);emit(f,"\n");
+      cc=0;lastcomp=t;continue;
+    }
+    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;
+	}
+      }
+    }
+
+    if(c==SUBPFP){
+      p->code=c=SUB;
+      if((p->typf2&NQ)==NPOINTER) p->typf=t=INT;
+      else if((p->typf2&NQ)==HPOINTER) p->typf=t=LONG;
+      else ierror(0);
+      if((p->typf2&NQ)==NPOINTER){
+	cc=&p->z;cc_t=NPOINTER;
+      }else{
+	cc=0;
+      }
+    }
+
+    if(c==ADDI2P||c==SUBIFP){
+      /*if(c==ADDI2P) p->code=c=ADD; else p->code=c=SUB;*/
+      if((p->typf2&NQ)!=HPOINTER){
+	p->typf=t=(UNSIGNED|SHORT);
+	short_add=2;
+	if(isreg(q2)&&reg_pair(p->q2.reg,&rp)){
+	  /*FIXME:warning*/
+	  p->q2.reg=rp.r1;
+	}
+      }else if(ISHWORD(t)){
+	p->typf=t=(UNSIGNED|LONG);
+	short_add=1;
+      }
+      if((p->typf2&NQ)==NPOINTER){
+	cc=&p->z;cc_t=NPOINTER;
+      }else{
+	cc=0;
+      }      
+    }
+    /* try to avoid z==q2 */
+    if((c==ADD||c==AND||c==OR||c==XOR||(c==ADDI2P&&!short_add))&&compare_objects(&p->q2,&p->z)){
+      o=p->q1;p->q1=p->q2;p->q2=o;
+    }    
+    /* DREFOBJs nach q2, um evtl. op reg,[ri] zu nutzen */
+    if(c==ADD||c==MULT||c==OR||c==AND||c==XOR){
+      if(isreg(q2)&&scratchreg(p->q2.reg,p)){
+	o=p->q1;p->q1=p->q2;p->q2=o;
+      }
+      if((p->q1.flags&DREFOBJ)&&(!(p->q1.flags&REG)||p->q1.reg<=4)&&(!p->q1.am||p->q1.am->flags!=IMM_IND)){
+	if(!((p->q2.flags&DREFOBJ)&&(!p->q2.am||p->q2.am->flags!=IMM_IND))){
+	  struct obj o;
+	  o=p->q1;p->q1=p->q2;p->q2=o;
+	}
+      }
+    }
+    /*FIXME: ICs mit mehreren Typen*/
+    if(switch_IC(p)&&isreg(z)){
+      reg=p->z.reg;
+    }else if(isreg(q1)&&(!ISLWORD(t)||reg_pair(p->q1.reg,&rp))&&(scratchreg(p->q1.reg,p)||(isreg(z)&&p->z.reg==p->q1.reg)||(!ISLWORD(t)&&c==COMPARE))){
+      reg=p->q1.reg;
+    }else{
+      if(ISLWORD(ztyp(p))){
+	tmp1=ti;tmp2=ti2;ti2_used=1;
+	BSET(regs_modified,ti);
+	BSET(regs_modified,ti2);
+	reg=MTMP1;
+      }else{
+	if((t&NQ)==CHAR){
+	  BSET(regs_modified,tp);
+	  reg=tp;
+	}else{
+	  BSET(regs_modified,ti);
+	  reg=ti;
+	}
+      }
+    }
+    /* op reg,mem/const */
+    if(issfr(z)&&(c==ADD||c==SUB||c==AND||c==OR||c==XOR||c==ADDI2P)&&(compare_objects(&p->q1,&p->z)||((c!=SUB&&c!=SUBIFP)&&compare_objects(&p->q2,&p->z)))){
+      char *s;
+      if(!compare_objects(&p->q1,&p->z)){o=p->q1;p->q1=p->q2;p->q2=o;}
+      if((p->q2.flags&(KONST|DREFOBJ))==KONST||((p->q2.flags&(VAR|DREFOBJ))==VAR&&ISSTATIC(p->q2.v))){
+	if(c>=OR&&c<=AND){
+	  s=logicals[c-OR];
+	}else{
+	  if(c==ADDI2P)
+	    s=arithmetics[ADD-LSHIFT];
+	  else if(c==SUBIFP)
+	    s=arithmetics[SUB-LSHIFT];
+	  else
+	    s=arithmetics[c-LSHIFT];
+	}
+	if((p->q2.flags&VAR)&&ISFAR(p->q2.v)){
+	  emit(f,"\texts\t#SEG ");isseg=1;emit_obj(f,&p->q2,t);emit(f,",#1\n");
+	}
+	emit(f,"\t%s%s\t",s,(t&NQ)==CHAR?"b":"");
+	emit_obj(f,&p->q1,t);
+	emit(f,",");
+	emit_obj(f,&p->q2,t);
+	emit(f,"\n");
+	cc=&p->z;cc_t=t;
+	continue;
+      }
+    }
+    /* op mem,reg */
+    if((c==ADD||c==SUB||c==AND||c==OR||c==XOR||c==ADDI2P)&&(compare_objects(&p->q1,&p->z)||((c!=SUB&&c!=SUBIFP)&&compare_objects(&p->q2,&p->z)))&&(p->z.flags&(VAR|VARADR|DREFOBJ|REG))==VAR&&ISSTATIC(p->z.v)){
+      char *s;
+      if(!compare_objects(&p->q1,&p->z)){o=p->q1;p->q1=p->q2;p->q2=o;}
+      cc=&p->z;cc_t=t;
+      if(isreg(q2)){
+	reg=p->q2.reg;
+      }else if(issfr(q2)){
+	reg=0;
+      }else if(isconst(q2)){
+	eval_const(&p->q2.val,t);
+	if(ISLWORD(t)){
+	  unsigned long ul;
+	  reg=MTMP1;
+	  if((c==ADD||c==SUB||c==ADDI2P||c==SUBIFP)&&zumeqto(vumax,ul2zum(1UL))){
+	    if(c==ADD) c=SUB;
+	    else if(c==SUB) c=ADD;
+	    else if(c==ADDI2P) c=SUBIFP;
+	    else c=ADDI2P;
+	    tmp1=ONES;tmp2=ONES;
+	  }else{
+	    ul=zum2ul(zumand(vumax,ul2zum(65535UL)));
+	    if(ul==0) tmp1=ZEROS;
+	    else if(ul==0xffff) tmp1=ONES;
+	    else{
+	      BSET(regs_modified,ti);
+	      tmp1=ti;
+	      emit(f,"\tmov\t%s,#%lu\n",regnames[ti],ul);
+	    }
+	    ul=zum2ul(zumand(zumrshift(vumax,ul2zum(16UL)),ul2zum(65535UL)));
+	    if(ul==0) tmp2=ZEROS;
+	    else if(ul==0xffff) tmp2=ONES;
+	    else{
+	      BSET(regs_modified,ti2);
+	      tmp2=ti2;
+	      emit(f,"\tmov\t%s,#%lu\n",regnames[ti2],ul);
+	    }
+	  }
+	}else{
+	  long l;
+	  if(c==OR&&(l=pof2(vumax))&&ISBADDR(p->z.v)){
+	    emit(f,"\tbset\t");emit_obj(f,&p->z,t);
+	    emit(f,".%ld\n",l-1);
+	    cc=0;continue;
+	  }else if(c==AND&&(l=pof2(zumkompl(vumax)))&&ISBADDR(p->z.v)){
+	    emit(f,"\tbclr\t");emit_obj(f,&p->z,t);
+	    emit(f,".%ld\n",l-1);
+	    cc=0;continue;
+	  }else if((c==ADD||c==SUB||c==ADDI2P||c==SUBIFP)&&zumeqto(vumax,ul2zum(1UL))){
+	    if(c==ADD) c=SUB; 
+	    else if(c==SUB) c=ADD;
+	    else if(c==ADDI2P) c=SUBIFP;
+	    else c=ADDI2P;
+	    reg=ONES;
+	  }else{
+	    if(zumeqto(vumax,ul2zum(0UL))) reg=ZEROS;
+	    else if(zumeqto(vumax,ul2zum(0xffffUL))) reg=ONES;
+	    else{
+	      BSET(regs_modified,tp);
+	      reg=tp;
+	      move(f,&p->q2,0,0,reg,t);
+	    }
+	  }
+	}
+      }else{
+	/*FIXME:ones/zeros nutzen*/
+	if(ISLWORD(t)){
+	  tmp1=ti;tmp2=ti2;
+	  BSET(regs_modified,ti);
+	  BSET(regs_modified,ti2);
+	  reg=MTMP1;
+	}else{
+	  BSET(regs_modified,tp);
+	  reg=tp;
+	}
+	if((p->q2.flags&(DREFOBJ|REG))==DREFOBJ){
+	  if(ISLWORD(p->q2.dtyp)){
+	    tmp3=ti2;tmp4=ti;
+	    BSET(regs_modified,ti);
+	    BSET(regs_modified,ti2);
+	    p->q2.flags&=~DREFOBJ;
+	    move(f,&p->q2,0,0,MTMP2,HPOINTER);
+	    p->q2.flags=(REG|DREFOBJ);p->q2.reg=MTMP2;
+	  }else if(!(p->q2.flags&KONST)){
+	    BSET(regs_modified,ti);
+	    move(f,&p->q2,0,0,ti,NPOINTER);
+	    p->q2.flags=REG;p->q2.reg=ti;
+	  }
+	}
+	move(f,&p->q2,0,0,reg,t);
+      }
+      if(c>=OR&&c<=AND){
+	s=logicals[c-OR];
+      }else{
+	if(c==ADDI2P)
+	  s=arithmetics[ADD-LSHIFT];
+	else if(c==SUBIFP)
+	  s=arithmetics[SUB-LSHIFT];
+	else
+	  s=arithmetics[c-LSHIFT];
+      }
+      if(reg&&reg_pair(reg,&rp)){
+	if(ISFAR(p->z.v)){
+	  emit(f,"\texts\t#SEG ");isseg=1;emit_obj(f,&p->z,t);emit(f,",#2\n");
+	}
+	emit(f,"\t%s\t",s);
+	emit_obj(f,&p->q1,t);emit(f,",%s\n",regnames[rp.r1]);
+	s=longcmd(s);
+	p->q1.val.vmax=zmadd(p->q1.val.vmax,l2zm(2L));
+	emit(f,"\t%s\t",s);
+	emit_obj(f,&p->q1,t);emit(f,",%s\n",regnames[rp.r2]);
+	p->q1.val.vmax=zmsub(p->q1.val.vmax,l2zm(2L));
+      }else{
+	if(ISFAR(p->z.v)){
+	  emit(f,"\texts\t#SEG ");isseg=1;emit_obj(f,&p->z,t);emit(f,",#1\n");
+	}
+	emit(f,"\t%s%s\t",s,(t&NQ)==CHAR?"b":"");
+	emit_obj(f,&p->q1,t);
+	if(reg)
+	  emit(f,",%s\n",((t&NQ)==CHAR&&reg<=MAXR)?bregnames[reg]:regnames[reg]);
+	else{
+	  emit(f,",");
+	  emit_obj(f,&p->q2,t);
+	  emit(f,"\n");
+	}
+      }
+      cc=&p->z;cc_t=t;
+      continue;
+    }
+    if(p->ext.flags==EXT_IC_BTST){
+      if(isreg(q1)){bit_reg=regnames[p->q1.reg];continue;}
+      if((p->q1.flags&(VAR|VARADR|DREFOBJ|REG))==VAR&&ISSTATIC(p->q1.v)&&ISBADDR(p->q1.v)){
+	bit_reg=0;bit_obj=&p->q1;
+	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)){
+	  if(c==MOD){
+	    vmax=zmsub(vmax,l2zm(1L));
+	    p->code=AND;
+	  }else{
+	    vmax=l2zm(ln-1);
+	    if(c==DIV) p->code=RSHIFT; else p->code=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,INT);
+	    p->typf2=INT;
+	  }
+	}
+      }
+    }
+    if(ISLWORD(t)&&(c==MULT||c==DIV||c==MOD)){
+      if(lib_larith(f,p)) continue;
+    }
+
+    if(!p->q1.am&&(p->q1.flags&DREFOBJ)){
+      if(!(p->q1.flags&(REG))){
+	if(ISLWORD(p->q1.dtyp)){
+	  tmp3=ti2;tmp4=ti;ti2_used=1;
+	  BSET(regs_modified,ti);
+	  BSET(regs_modified,ti2);
+	  p->q1.flags&=~DREFOBJ;
+	  move(f,&p->q1,0,0,MTMP2,FPOINTER);
+	  p->q1.reg=MTMP2;
+	  p->q1.flags=(REG|DREFOBJ);
+	}else if(!(p->q1.flags&KONST)){
+	  BSET(regs_modified,ti);
+	  p->q1.flags&=~DREFOBJ;
+	  move(f,&p->q1,0,0,ti,NPOINTER);
+	  p->q1.reg=ti;
+	  p->q1.flags=(REG|DREFOBJ);
+	}
+      }
+      if(p->q2.flags){
+	move(f,&p->q1,0,0,reg,q2typ(p));/*FIXME*/
+	if((!isreg(q1)||p->q1.reg!=reg)&&c==COMPARE&&!ISLWORD(t)&&isconst(q2)){
+	  /* avoid cmp, if not needed */
+	  eval_const(&p->q2.val,t);
+	  if(ISNULL()){
+	    lastcomp=t;continue;
+	  }
+	}
+      }
+    }else{
+      if(p->q2.flags){
+	move(f,&p->q1,0,0,reg,q1typ(p));/*FIXME*/
+	if((!isreg(q1)||p->q1.reg!=reg)&&c==COMPARE&&!ISLWORD(t)&&isconst(q2)){
+	  /* avoid cmp, if not needed */
+	  eval_const(&p->q2.val,t);
+	  if(ISNULL()){
+	    lastcomp=t;continue;
+	  }
+	}
+      }
+    }
+    if(p->ext.flags==EXT_IC_BTST){ bit_reg=regnames[reg];continue;}
+    if(!p->q2.am&&(p->q2.flags&DREFOBJ)){
+      if(!(p->q2.flags&(REG))||p->q2.reg>4){
+	if(ISLWORD(p->q2.dtyp)){
+	  if(ti2_used) tmp4=get_reg(f,p); else tmp4=ti2;
+	  tmp3=tp;
+	  BSET(regs_modified,tmp3);
+	  BSET(regs_modified,tmp4);
+	  p->q2.flags&=~DREFOBJ;
+	  move(f,&p->q2,0,0,MTMP2,FPOINTER);
+	  p->q2.reg=MTMP2;
+	  p->q2.flags=(REG|DREFOBJ);
+	}else if(!(p->q2.flags&KONST)){
+	  BSET(regs_modified,tp);
+	  p->q2.flags&=~DREFOBJ;
+	  move(f,&p->q2,0,0,tp,NPOINTER);
+	  p->q2.flags=(REG|DREFOBJ);
+	  p->q2.reg=tp;
+	}
+      }
+    }
+    if(c==CONVERT&&!must_convert(p->typf,p->typf2,0)){
+      p->code=c=ASSIGN;
+      p->q2.val.vmax=sizetab[p->typf&NQ];
+    }
+
+    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((to&NQ)<=LONG&&(t&NQ)<=LONG){
+	if((to&NQ)<=(t&NQ)){
+	  if((to&NQ)==(t&NQ)) ierror(0);
+	  if((to&NQ)==BIT){
+	    cc=0;
+	    if((p->q1.flags&(VAR|REG|DREFOBJ|VARADR))!=VAR||!ISSTATIC(p->q1.v)) ierror(0);
+	    if(reg_pair(reg,&rp)){
+	      emit(f,"\tmov\t%s,#0\n",regnames[rp.r1]);
+	      emit(f,"\tmov\t%s,#0\n",regnames[rp.r2]);
+	      emit(f,"\tbmov\t%s.0,",regnames[rp.r1]);
+	      emit_obj(f,&p->q1,t);emit(f,"\n");
+	    }else{
+	      emit(f,"\tmov\t%s,#0\n",regnames[reg]);
+	      emit(f,"\tbmov\t%s.0,",regnames[reg]);
+	    }
+	    emit_obj(f,&p->q1,t);emit(f,"\n");
+	    save_result(f,reg,p,t);
+	    continue;
+	  }
+	  if((p->q1.flags&(VAR|REG|VARADR))==VAR&&ISSTATIC(p->q1.v)&&ISFAR(p->q1.v)){
+	    emit(f,"\texts\t#SEG ");isseg=1;emit_obj(f,&p->q1,t);
+	    emit(f,",#1\n");
+	  }
+	  qp.SEG=0;
+	  if(!p->q1.am&&(p->q1.flags&DREFOBJ)&&reg_pair(p->q1.reg,&qp))
+	    emit(f,"\texts\t%s,#1\n",regnames[qp.SEG]);
+	  if(p->q1.am&&reg_pair(p->q1.am->base,&qp))
+	    emit(f,"\texts\t%s,#1\n",regnames[qp.SEG]);
+	  if(reg_pair(reg,&rp)){
+	    cc=0;
+	    if((to&NQ)==CHAR){
+	      if(isreg(q1)||((p->q1.flags&(VAR|VARADR|DREFOBJ))==VAR&&ISSTATIC(p->q1.v))){
+		emit(f,"\tmovb%c\t%s,",(to&UNSIGNED)?'z':'s',regnames[rp.r1]);
+		if((to&NQ)==CHAR&&isreg(q1)) emit(f,"%s",bregnames[p->q1.reg]);
+		else if(qp.SEG) emit(f,"[%s]",regnames[qp.SOF]);
+		else emit_obj(f,&p->q1,to);
+		emit(f,"\n");
+	      }else{
+		BSET(regs_modified,tp);
+		emit(f,"\tmovb\t%s,",bregnames[tp]);
+		if(isreg(q1)) emit(f,"%s",bregnames[p->q1.reg]);
+		else if(!p->q1.am&&qp.SEG) emit(f,"[%s]",regnames[qp.SOF]);
+		else emit_obj(f,&p->q1,to);
+		emit(f,"\n");
+		emit(f,"\tmovb%c\t%s,%s\n",(to&UNSIGNED)?'z':'s',regnames[rp.r1],bregnames[tp]);
+	      }
+	    }else{
+	      emit(f,"\tmov\t%s,",regnames[rp.r1]);
+	      if(qp.SEG) emit(f,"[%s]",regnames[qp.SOF]);
+	      else emit_obj(f,&p->q1,to);
+	      emit(f,"\n");
+	    }
+	    if(to&UNSIGNED)
+	      emit(f,"\tmov\t%s,#0\n",regnames[rp.r2]);
+	    else
+	      emit(f,"\tmov\t%s,%s\n\tashr\t%s,#15\n",regnames[rp.r2],regnames[rp.r1],regnames[rp.r2]);
+
+	  }else{
+	    cc=&p->z;cc_t=t;
+	    if(isreg(q1)||((p->q1.flags&(VAR|VARADR|DREFOBJ))==VAR&&ISSTATIC(p->q1.v))){
+	      emit(f,"\tmovb%c\t%s,",(to&UNSIGNED)?'z':'s',regnames[reg]);
+	      if((to&NQ)==CHAR&&isreg(q1)) emit(f,"%s",bregnames[p->q1.reg]);
+	      else if(qp.SEG) emit(f,"[%s]",regnames[qp.SOF]);
+	      else emit_obj(f,&p->q1,to);
+	      emit(f,"\n");
+	    }else{
+	      BSET(regs_modified,tp);
+	      emit(f,"\tmovb\t%s,",bregnames[tp]);
+	      if(isreg(q1)) emit(f,"%s",bregnames[p->q1.reg]);
+	      else if(!p->q1.am&&qp.SEG) emit(f,"[%s]",regnames[qp.SOF]);
+	      else emit_obj(f,&p->q1,to);
+	      emit(f,"\n");
+	      emit(f,"\tmovb%c\t%s,%s\n",(to&UNSIGNED)?'z':'s',regnames[reg],bregnames[tp]);
+	    }	    
+	  }
+	  save_result(f,reg,p,t);
+	  continue;
+	}else{
+	  if((t&NQ)==BIT){
+	    if(!isreg(z)&&((p->z.flags&(VAR|REG|DREFOBJ|VARADR))!=VAR||!ISSTATIC(p->z.v))) ierror(0);
+	    if(isreg(q1)){
+	      reg=p->q1.reg;
+	    }else{
+	      if(ISLWORD(to)){
+		tmp1=ti;tmp2=ti2;
+		BSET(regs_modified,ti);
+		BSET(regs_modified,ti2);
+		reg=MTMP1;
+	      }
+	    }
+	    move(f,&p->q1,0,0,reg,to);
+	    if(reg_pair(reg,&rp)){
+	      if(isreg(q1)&&!scratchreg(reg,p)){
+		BSET(regs_modified,ti);
+		emit(f,"\tmov\t%s,%s\n",regnames[ti],regnames[rp.r1]);
+		emit(f,"\tor\t%s,%s\n",regnames[ti],regnames[rp.r2]);
+	      }else
+		emit(f,"\tor\t%s,%s\n",regnames[rp.r1],regnames[rp.r2]);
+	    }else{
+	      if(isreg(q1)) emit(f,"\tcmp%s\t%s,#0\n",(to&NQ)==CHAR?"b":"",(to&NQ)==CHAR?bregnames[reg]:regnames[reg]);
+	    }
+	    emit(f,"\tbmovn\t");
+	    if(isesfrbit(z))
+	      emit(f,"%s.0",regnames[ti]);
+	    else
+	      emit_obj(f,&p->z,t);
+	    emit(f,",PSW.3\n");
+	    if(isesfrbit(z)){
+	      emit(f,"\textr\t#1\n");
+	      emit(f,"\tbmov\t");
+	      emit_obj(f,&p->z,t);
+	      emit(f,",%s.0\n",regnames[ti]);
+	    }
+	    cc=0;continue;
+	  }
+	  cc=&p->z;cc_t=t;
+	  if(ISLWORD(to)){
+	    if(isreg(q1)) {reg_pair(p->q1.reg,&rp);p->q1.reg=rp.r1;}
+	    to=SHORT;
+	  }
+	  if(isreg(q1)&&regok(p->q1.reg,t,0)) reg=p->q1.reg;
+	  if(isreg(z)) reg=p->z.reg;
+	  if(!regok(reg,t,0)){
+	    reg=tp;
+	    BSET(regs_modified,tp);
+	  }
+	  move(f,&p->q1,0,0,reg,to);
+	  save_result(f,reg,p,t);
+	}
+	continue;
+      }
+      ierror(0);
+    }
+    if(c==MINUS||c==KOMPLEMENT){
+      move(f,&p->q1,0,0,reg,t);
+      if(reg_pair(reg,&rp)){
+	emit(f,"\t%s\t%s\n",(c==MINUS?"neg":"cpl"),regnames[rp.r1]);
+	if(c==MINUS) emit(f,"\taddc\t%s,#0\n",regnames[rp.r2]);
+	emit(f,"\t%s\t%s\n",(c==MINUS?"neg":"cpl"),regnames[rp.r2]);
+	cc=0;
+      }else{
+	emit(f,"\t%s%s\t%s\n",(c==MINUS?"neg":"cpl"),x_t[t&NQ],regnames[reg]);
+	cc=&p->z;cc_t=t;
+      }
+      save_result(f,reg,p,t);
+      continue;
+    }
+    if(c==SETRETURN){
+      if(p->z.reg){
+	move(f,&p->q1,0,0,p->z.reg,t);
+	BSET(regs_modified,p->z.reg);
+      }
+      cc=0; /* probably not needed */
+      continue;
+    }
+    if(c==GETRETURN){
+      if(p->q1.reg){
+	if(!isreg(z)||p->z.reg!=p->q1.reg){ cc=&p->z;cc_t=t;}
+	save_result(f,p->q1.reg,p,t);
+      }
+      continue;
+    }
+    if(c==CALL){
+      int reg,jmp=0;long csstack=0,custack=0;
+      cc=0;
+      if((p->q1.flags&(VAR|DREFOBJ))==VAR&&!strcmp("__va_start",p->q1.v->identifier)){
+	long va_off=loff-usrstackoffset+pushedsize+zm2l(va_offset(v));
+	emit(f,"\tmov\t%s,%s\n",regnames[r4],regnames[sp]);
+	if(va_off)
+	  emit(f,"\tadd\t%s,#%ld\n",regnames[r4],va_off);
+	BSET(regs_modified,r4);
+	if(LARGE||HUGE){
+	  emit(f,"\tmov\t%s,#0\n",regnames[r5]);
+	  BSET(regs_modified,r5);
+	}
+	continue;
+      }
+      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)){
+	    if(p->call_list[i].v->fi->stack1>custack) custack=p->call_list[i].v->fi->stack1;
+	    if(p->call_list[i].v->fi->stack2>csstack) csstack=p->call_list[i].v->fi->stack2;
+          }else{
+            err_ic=p;if(f) error(317,p->call_list[i].v->identifier);
+            stack_valid=0;
+          }
+        }
+      }
+      if(!calc_regs(p,f!=0)&&v->fi) v->fi->flags&=~ALL_REGS;
+      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);
+	callee_push(custack,csstack);
+      }else{
+	if(usrstackoffset==0&&!have_frame&&!(v->tattr&INTERRUPT)){
+	  struct IC *p2;
+	  jmp=1;
+	  for(p2=p->next;p2;p2=p2->next){
+	    if(p2->code!=FREEREG&&p2->code!=ALLOCREG&&p2->code!=LABEL&&
+	       (p2->code!=GETRETURN||(p2->z.flags&(REG|DREFOBJ))!=REG||p2->q1.reg!=p2->z.reg)&&
+	       (p2->code!=SETRETURN||(p2->q1.flags&(REG|DREFOBJ))!=REG||p2->q1.reg!=p2->z.reg)){
+	      jmp=0;break;
+	    }
+	  }
+	}
+	if(p->q1.flags&DREFOBJ){
+	  int clabel=++label;
+	  if(ISLWORD(p->q1.dtyp)){
+	    int tmp;
+	    if(!ti2_used) tmp=ti2; else tmp=tp;
+	    BSET(regs_modified,tmp);
+	    emit(f,"\tmov\t%s,#SEG %s%d\n",regnames[tmp],labprefix,clabel);
+	    emit(f,"\tpush\t%s\n",regnames[tmp]);
+	    emit(f,"\tmov\t%s,#SOF %s%d\n",regnames[tmp],labprefix,clabel);
+	    emit(f,"\tpush\t%s\n",regnames[tmp]);
+	    push(0,4);
+	  }
+	  if(!(p->q1.flags&REG)) ierror(0);
+	  reg=p->q1.reg;
+	  p->q1.flags&=~DREFOBJ;
+	  if(!ISLWORD(p->q1.dtyp)){
+	    emit(f,"\tcalli\tcc_uc,[%s]\n",regnames[reg]);
+	    push(0,2);
+	    callee_push(custack,csstack);
+	    pop(0,2);
+	  }else{
+	    if(!reg_pair(reg,&rp)) ierror(0);
+	    emit(f,"\tpush\t%s\n",regnames[rp.r2]);
+	    emit(f,"\tpush\t%s\n",regnames[rp.r1]);
+	    push(0,4);
+	    callee_push(custack,csstack);
+	    emit(f,"\trets\n");
+	    emit(f,"%s%d:\n",labprefix,clabel);
+	    pop(0,8);
+	  }
+	}else{
+	  if(jmp){
+	    emit(f,"\t%s",jump);
+	    if(!need_return) ret=TASKING?"retv":"";
+	    callee_push(custack,csstack);
+	  }else{
+	    emit(f,"\t%s\t",call);
+	    if(TINY)
+	      push(0,2);
+	    else
+	      push(0,4);
+	    callee_push(custack,csstack);
+	    if(TINY)
+	      pop(0,2);
+	    else
+	      pop(0,4);
+	  }
+	  emit_obj(f,&p->q1,t);
+	  emit(f,"\n");
+	}
+      }
+      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)&&usrstackoffset==-notpopped){
+	  /*  Entfernen der Parameter verzoegern  */
+	}else{
+	  emit(f,"\tadd\t%s,#%ld\n",regnames[sp],zm2l(p->q2.val.vmax));
+	  pop(zm2l(p->q2.val.vmax),0);
+	  notpopped-=zm2l(p->q2.val.vmax);cc=0;
+	}
+      }
+      continue;
+    }
+    if(c==ASSIGN||c==PUSH){
+      if(c==PUSH) dontpop+=zm2l(p->q2.val.vmax);
+      if(!ISSCALAR(t)||!zmeqto(p->q2.val.vmax,sizetab[t&NQ])||!zmleq(p->q2.val.vmax,l2zm(4L))){
+	int alq,alz,rq,rz;unsigned long size;
+	cc=0;
+	size=zm2l(p->q2.val.vmax);
+	/*FIXME: check for (s)huge */
+	if(malign[t&NQ]==1){
+	  alq=alignment(&p->q1);
+	  alz=alignment(&p->z);
+	}else{
+	  alq=alz=0;
+	}
+	if(size==1||(size==2&&alq==0&&alz==0)){
+	  if(c==PUSH&&zm2l(p->z.val.vmax)==1){
+	    emit(f,"\tsub\t%s,#1\n",regnames[sp]);
+	    push(1,0);size=1;
+	  }
+	  BSET(regs_modified,tp);
+	  move(f,&p->q1,0,0,tp,size==1?CHAR:SHORT);
+	  if(c==PUSH){
+	    emit(f,"\tmov\t[-%s],%s\n",regnames[sp],regnames[tp]);
+	    push(size,0);
+	  }else
+	    save_result(f,tp,p,size==1?CHAR:SHORT);
+	  continue;
+	}
+	if(size==4&&alq==0&&alz==0){
+	  tmp1=ti;tmp2=ti2;
+	  BSET(regs_modified,ti);
+	  BSET(regs_modified,ti2);
+	  move(f,&p->q1,0,0,MTMP1,LONG);
+	  if(c==PUSH){
+	    emit(f,"\tmov\t[-%s],%s\n",regnames[sp],regnames[tmp2]);
+	    emit(f,"\tmov\t[-%s],%s\n",regnames[sp],regnames[tmp1]);
+	    push(4,0);
+	  }else
+	    save_result(f,MTMP1,p,LONG);
+	  continue;
+	}
+	if(p->q1.am){
+	  if(p->q1.am->flags!=IMM_IND) ierror(0);
+	  if(!scratchreg(p->q1.am->base,p)){
+	    BSET(regs_modified,ti);
+	    emit(f,"\tmov\t%s,%s\n",regnames[ti],regnames[p->q1.am->base]);
+	    rq=ti;
+	  }else
+	    rq=p->q1.am->base;
+	  emit(f,"\tadd\t%s,#%ld",regnames[rq],p->q1.am->offset);
+	  if(p->q1.am->v){
+	    if(p->q1.am->v->storage_class==EXTERN)
+	      emit(f,"+%s%s\n",idprefix,p->q1.am->v->identifier);
+
+	    else
+	      emit(f,"+%s%ld\n",labprefix,zm2l(p->q1.am->v->offset));
+	  }
+	  emit(f,"\n");
+	}else if(p->q1.flags&REG){
+	  if(scratchreg(p->q1.reg,p)){
+	    rq=p->q1.reg;
+	  }else{
+	    BSET(regs_modified,ti);
+	    emit(f,"\tmov\t%s,%s\n",regnames[ti],regnames[p->q1.reg]);
+	    rq=ti;
+	  }
+	}else if((p->q1.flags&VAR)&&ISSTATIC(p->q1.v)){
+	  int m=p->q1.flags;
+	  rq=ti;
+	  BSET(regs_modified,ti);
+	  if(p->q1.flags&DREFOBJ)
+	    p->q1.flags&=~DREFOBJ;
+	  else
+	    p->q1.flags|=VARADR;
+	  move(f,&p->q1,0,0,ti,NPOINTER);
+	  p->q1.flags&=~VARADR;
+	}else{
+	  BSET(regs_modified,ti);
+	  rq=ti;
+	  emit(f,"\tmov\t%s,%s\n",regnames[ti],regnames[sp]);
+	  if(voff(&p->q1))
+	    emit(f,"\tadd\t%s,#%ld\n",regnames[ti],voff(&p->q1));
+	}
+	if(!p->z.flags){
+	  /* PUSH */
+	  emit(f,"\tsub\t%s,#%lu\n",regnames[sp],size);
+	  emit(f,"\tmov\t%s,%s\n",regnames[ti2],regnames[sp]);
+	  rz=ti2;
+	  push(size,0);
+	  BSET(regs_modified,ti2);
+	}else if(p->z.am){
+	  if(p->z.am->flags!=IMM_IND) ierror(0);
+	  if(!scratchreg(p->z.am->base,p)){
+	    BSET(regs_modified,ti2);
+	    emit(f,"\tmov\t%s,%s\n",regnames[ti2],regnames[p->z.am->base]);
+	    rz=ti2;
+	  }else
+	    rz=p->z.am->base;
+	  emit(f,"\tadd\t%s,#%ld",regnames[rz],p->z.am->offset);
+	  if(p->z.am->v){
+	    if(p->z.am->v->storage_class==EXTERN)
+	      emit(f,"+%s%s",idprefix,p->z.am->v->identifier);
+	    else
+	      emit(f,"%+s%ld",labprefix,zm2l(p->z.am->v->offset));
+
+	  }
+	  emit(f,"\n");
+	}else if(p->z.flags&REG){
+	  if(scratchreg(p->z.reg,p)){
+	    rz=p->z.reg;
+	  }else{
+	    BSET(regs_modified,ti2);
+	    emit(f,"\tmov\t%s,%s\n",regnames[ti2],regnames[p->z.reg]);
+	    rz=ti2;
+	  }
+	}else if(ISSTATIC(p->z.v)){
+	  int m=p->z.flags;
+	  rz=ti2;
+	  BSET(regs_modified,ti2);
+	  if(p->z.flags&DREFOBJ)
+	    p->z.flags&=~DREFOBJ;
+	  else
+	    p->z.flags|=VARADR;
+	  move(f,&p->z,0,0,ti2,NPOINTER);
+	  p->z.flags=m;
+	}else{
+	  BSET(regs_modified,ti2);
+	  rz=ti2;
+	  emit(f,"\tmov\t%s,%s\n",regnames[ti2],regnames[sp]);
+	  if(voff(&p->z))
+	    emit(f,"\tadd\t%s,#%ld\n",regnames[ti2],voff(&p->z));
+	}	
+	if(alq==0&&alz==0){
+	  if(optspeed){
+	    if((size/8)>1){ 
+	      BSET(regs_modified,tp);
+	      emit(f,"\tmov\t%s,#%lu\n",regnames[tp],size/8);
+	      emit(f,"%s%d:\n",labprefix,++label);
+	    }
+	    if(size>=8){
+	      emit(f,"\tmov\t[%s],[%s+]\n",regnames[rz],regnames[rq]);
+	      emit(f,"\tadd\t%s,#2\n",regnames[rz]);
+	      emit(f,"\tmov\t[%s],[%s+]\n",regnames[rz],regnames[rq]);
+	      emit(f,"\tadd\t%s,#2\n",regnames[rz]);	    
+	      emit(f,"\tmov\t[%s],[%s+]\n",regnames[rz],regnames[rq]);
+	      emit(f,"\tadd\t%s,#2\n",regnames[rz]);
+	      emit(f,"\tmov\t[%s],[%s+]\n",regnames[rz],regnames[rq]);
+	      emit(f,"\tadd\t%s,#2\n",regnames[rz]);	    
+	    }
+	    if((size/8)>1){
+	      emit(f,"\tsub\t%s,#1\n",regnames[tp]);
+	      emit(f,"\tjmpr\tcc_nz,%s%d\n",labprefix,label);	      
+	    }
+	    size&=7;
+	    if(size>=4){
+	      emit(f,"\tmov\t[%s],[%s+]\n",regnames[rz],regnames[rq]);
+	      emit(f,"\tadd\t%s,#2\n",regnames[rz]);
+	      emit(f,"\tmov\t[%s],[%s+]\n",regnames[rz],regnames[rq]);
+	      if(size>4) emit(f,"\tadd\t%s,#2\n",regnames[rz]);	      
+	    }
+	    size&=3;
+	    if(size>=2){
+	      emit(f,"\tmov\t[%s],[%s+]\n",regnames[rz],regnames[rq]);
+	      if(size>2) emit(f,"\tadd\t%s,#2\n",regnames[rz]);
+	    }	      
+	    if(size&1)
+	      if(size&1) emit(f,"\tmovb\t[%s],[%s]\n",regnames[rz],regnames[rq]);
+	  }else{
+	    BSET(regs_modified,tp);
+	    emit(f,"\tmov\t%s,#%lu\n",regnames[tp],size/2);
+	    emit(f,"%s%d:\n",labprefix,++label);
+	    emit(f,"\tmov\t[%s],[%s+]\n",regnames[rz],regnames[rq]);
+	    emit(f,"\tadd\t%s,#2\n",regnames[rz]);
+	    emit(f,"\tsub\t%s,#1\n",regnames[tp]);
+	    emit(f,"\tjmpr\tcc_nz,%s%d\n",labprefix,label);
+	    if(size&1) emit(f,"\tmovb\t[%s],[%s]\n",regnames[rz],regnames[rq]);
+	  }
+	}else{
+	  BSET(regs_modified,tp);
+	  emit(f,"\tmov\t%s,#%lu\n",regnames[tp],size);
+	  emit(f,"%s%d:\n",labprefix,++label);
+	  emit(f,"\tmovb\t[%s],[%s+]\n",regnames[rz],regnames[rq]);
+	  emit(f,"\tadd\t%s,#1\n",regnames[rz]);
+	  emit(f,"\tsub\t%s,#1\n",regnames[tp]);
+	  emit(f,"\tjmpr\tcc_nz,%s%d\n",labprefix,label);
+	}
+	continue;
+      }
+      /* mov [rx],[ry] ; mov [rx+],[ry] ; mov [rx],[ry+] */
+      if(!ISLWORD(t)&&(p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&(p->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&(!p->z.am||p->z.am->flags==POST_INC)&&(!p->q1.am||p->q1.am->flags==POST_INC)&&!reg_pair(p->q1.reg,&rp)&&!reg_pair(p->z.reg,&rp)){
+	emit(f,"\tmov%s\t",(t&NQ)==CHAR?"b":"");
+	emit_obj(f,&p->z,t);emit(f,",");
+	emit_obj(f,&p->q1,t);emit(f,"\n");
+	cc=&p->z;cc_t=t;continue;
+      }
+      /* mov mem,[rx]/reg */
+      if(!ISLWORD(t)&&(issfr(q1)||(p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ))&&(p->z.flags&(REG|DREFOBJ|VAR))==VAR&&!p->q1.am&&(p->z.v->storage_class==STATIC||p->z.v->storage_class==EXTERN)){
+	emit(f,"\tmov%s\t",(t&NQ)==CHAR?"b":"");
+	emit_obj(f,&p->z,t);emit(f,",");
+	emit_obj(f,&p->q1,t);emit(f,"\n");
+	cc=&p->z;cc_t=t;continue;
+      } 
+      /* mov [rx]/reg,mem */
+      if(!ISLWORD(t)&&(issfr(z)||(p->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ))&&(p->q1.flags&(REG|DREFOBJ|VAR))==VAR&&!p->z.am&&(p->q1.v->storage_class==STATIC||p->q1.v->storage_class==EXTERN)){
+	emit(f,"\tmov%s\t",(t&NQ)==CHAR?"b":"");
+	emit_obj(f,&p->z,t);emit(f,",");
+	emit_obj(f,&p->q1,t);emit(f,"\n");
+	cc=&p->z;cc_t=t;continue;
+      }     
+      /* mov reg,op */
+      if(issfr(z)&&(p->q1.flags&KONST)){
+	emit(f,"\tmov%s\t",(t&NQ)==CHAR?"b":"");
+	emit_obj(f,&p->z,t);emit(f,",");
+	emit_obj(f,&p->q1,t);emit(f,"\n");
+	cc=&p->z;cc_t=t;continue;
+      }
+
+      if(isreg(q1)){
+	reg=p->q1.reg;
+      }else if(isreg(z)){
+	reg=p->z.reg;
+      }else{
+	BSET(regs_modified,ti);
+	if(ISLWORD(t)){
+	  BSET(regs_modified,ti2);
+	  tmp1=ti;tmp2=ti2;
+	  reg=MTMP1;
+	}else
+	  reg=ti;
+      }
+      if(c==PUSH){
+	move(f,&p->q1,0,0,reg,t);
+	if(reg_pair(reg,&rp)){
+	  emit(f,"\tmov\t[-%s],%s\n",regnames[sp],regnames[rp.r2]);
+	  emit(f,"\tmov\t[-%s],%s\n",regnames[sp],regnames[rp.r1]);
+	  cc=0;
+	}else{
+	  emit(f,"\tmov%s\t[-%s],%s\n",x_t[t&NQ],regnames[sp],regnames[reg]);
+	  cc=&p->q1;cc_t=t;
+	}
+	push(zm2l(p->z.val.vmax),0);
+	continue;
+      }
+      if(c==ASSIGN){
+	if((p->z.flags&(VAR|REG|DREFOBJ))==VAR&&ISSTATIC(p->z.v)&&isconst(q1)){
+	  /*FIXME: long und ones */
+	  eval_const(&p->q1.val,t);
+	  if(ISNULL()&&!ISLWORD(t)){
+	    emit(f,"\tmov%s\t",(t&NQ)==CHAR?"b":"");emit_obj(f,&p->z,t);
+	    emit(f,",ZEROS\n");
+	    cc=&p->z;cc_t=t;continue;
+	  }
+	}
+	if((t&NQ)==CHAR&&!regok(reg,CHAR,0)){
+	  reg=tp;
+	  BSET(regs_modified,tp);
+	}
+	move(f,&p->q1,0,0,reg,t);
+	save_result(f,reg,p,t);
+	if(ISLWORD(t)){
+	  cc=0;
+	}else{
+	  cc=&p->z;cc_t=t;
+	}
+	continue;
+      }
+      ierror(0);
+    }
+    if(c==ADDRESS){
+      if(reg_pair(reg,&rp)){
+	emit(f,"\tmov\t%s,%s\n",regnames[rp.r1],regnames[sp]);
+	emit(f,"\tmov\t%s,#0\n",regnames[rp.r2]);
+	if(voff(&p->q1))
+	  emit(f,"\tadd\t%s,#%ld\n",regnames[rp.r1],voff(&p->q1)&0xffff);
+      }else{
+	emit(f,"\tmov\t%s,%s\n",regnames[reg],regnames[sp]);
+	if(voff(&p->q1)) emit(f,"\tadd\t%s,#%ld\n",regnames[reg],voff(&p->q1));
+      }
+      save_result(f,reg,p,p->typf2);
+      cc=0;
+      continue;
+    }
+
+    if(c==MOD||c==DIV){
+      if(ISLWORD(t)) ierror(0);
+      /*FIXME:suboptimal*/
+      emit(f,"\tmov\tMDL,%s\n",regnames[reg]);
+      move(f,&p->q2,0,0,reg,t);
+      emit(f,"\tdiv%s\t%s\n",(t&UNSIGNED)?"u":"",regnames[reg]);
+      if(c==MOD) 
+	emit(f,"\tmov\t%s,MDH\n",regnames[reg]);
+      else
+	emit(f,"\tmov\t%s,MDL\n",regnames[reg]);
+      save_result(f,reg,p,t);
+      cc=&p->z;cc_t=t;
+      continue;
+    }
+    if((c>=LSHIFT&&c<=MOD)||(c>=OR&&c<=AND)||c==COMPARE||c==ADDI2P||c==SUBIFP){
+      char *s;
+      /*FIXME: nicht immer besser*/
+/* rfi: better performed in LSHIFT code generation
+      if(ISLWORD(t)&&c==LSHIFT&&isconst(q2)){
+	eval_const(&p->q2.val,t);
+	if(zm2l(vmax)==1&&!p->q1.am){
+	  p->code=c=ADD;
+	  p->q2=p->q1;
+	}
+      }
+*/
+      if(ISLWORD(t)&&c==MULT) ierror(0);
+      if(ISLWORD(t)&&(c==LSHIFT||c==RSHIFT)){
+/* rfi: we now handle constant value greater than 16 in const shift generation
+	if(isconst(q2))	
+	  eval_const(&p->q2.val,q2typ(p));
+	if(!isconst(q2)||zmleq(l2zm(16L),vmax)){
+*/
+	if(!isconst(q2)){
+	  int cnt,lab1,lab2;
+	  if(isreg(q2)&&scratchreg(p->q2.reg,p)){
+	    cnt=p->q2.reg;
+	  }else{
+	    BSET(regs_modified,tp);
+	    cnt=tp;
+	    if(isreg(q2)&&reg_pair(p->q2.reg,&rp))
+	      move(f,0,rp.r1,0,tp,INT);
+	    else
+	      move(f,&p->q2,0,0,tp,INT);
+	  }
+	  if(reg_pair(cnt,&rp))
+	    cnt=rp.r1;
+	  /*move(f,&p->q1,0,0,reg,ztyp(p));*/
+	  lab1=++label;lab2=++label;
+	  if(!reg_pair(reg,&rp)) ierror(0);
+	  if(c==LSHIFT){
+	    emit(f,"\tjmpr\tcc_uc,%s%d\n",labprefix,lab2);
+	    emit(f,"%s%d:\n",labprefix,lab1);
+	    emit(f,"\tadd\t%s,%s\n",regnames[rp.r1],regnames[rp.r1]);
+	    emit(f,"\taddc\t%s,%s\n",regnames[rp.r2],regnames[rp.r2]);
+	    emit(f,"%s%d:\n",labprefix,lab2);
+/* rfi: fix off by one and handle negative shift value
+		emit(f,"\tsub\t%s,#1\n",regnames[cnt]);
+	    emit(f,"\tjmpr\tcc_ne,%s%d\n",labprefix,lab1);
+*/
+	    emit(f,"\tcmpd1\t%s,#1\n",regnames[cnt]);
+	    emit(f,"\tjmpr\tcc_sge,%s%d\n",labprefix,lab1);
+	  }else{
+	    emit(f,"\tjmpr\tcc_uc,%s%d\n",labprefix,lab2);
+	    emit(f,"%s%d:\n",labprefix,lab1);
+		emit(f,"\tshr\t%s,#1\n",regnames[rp.r1]);
+	    emit(f,"\tbmov\t%s.15,%s.0\n",regnames[rp.r1],regnames[rp.r2]);
+/* rfi: use ashr for signed shift
+		emit(f,"\tshr\t%s,#1\n",regnames[rp.r2]);
+*/
+	    emit(f,"\t%sshr\t%s,#1\n",(t&UNSIGNED)?"":"a",regnames[rp.r2]);
+	    emit(f,"%s%d:\n",labprefix,lab2);
+/* rfi: fix off by one and handle negative shift value
+		emit(f,"\tsub\t%s,#1\n",regnames[cnt]);
+	    emit(f,"\tjmpr\tcc_ne,%s%d\n",labprefix,lab1);
+*/
+	    emit(f,"\tcmpd1\t%s,#1\n",regnames[cnt]);
+	    emit(f,"\tjmpr\tcc_sge,%s%d\n",labprefix,lab1);
+	  }
+	  save_result(f,reg,p,ztyp(p));
+	  continue;
+	}
+      }
+      if(c>=OR&&c<=AND){
+	s=logicals[c-OR];
+      }else{
+	if(c==ADDI2P)
+	  s=arithmetics[ADD-LSHIFT];
+	else if(c==SUBIFP)
+	  s=arithmetics[SUB-LSHIFT];
+	else
+	  s=arithmetics[c-LSHIFT];
+      }
+      if(c==RSHIFT&&!(t&UNSIGNED)) s="ashr";
+      if(c==COMPARE){
+	lastcomp=t;
+	if(ISLWORD(t)) s="sub"; else s="cmp";
+      }
+      if((c==MULT&&!isreg(q2))){
+	BSET(regs_modified,tp);
+	move(f,&p->q2,0,0,tp,t);
+	p->q2.flags=REG;
+	p->q2.reg=tp;
+      }
+      if((c==LSHIFT||c==RSHIFT)&&!isconst(q2)&&!isreg(q2)){
+	BSET(regs_modified,tp);
+	move(f,&p->q2,0,0,tp,t);
+	p->q2.flags=REG;
+	p->q2.reg=tp;
+      }
+      if(isreg(q2)){
+	if(reg_pair(reg,&rp)){
+	  if(!reg_pair(p->q2.reg,&qp)) qp.r1=p->q2.reg;
+	  emit(f,"\t%s\t%s,%s\n",s,regnames[rp.r1],regnames[qp.r1]);
+	  s=longcmd(s);
+	  if(!short_add) emit(f,"\t%s\t%s,%s\n",s,regnames[rp.r2],regnames[qp.r2]);
+	}else{
+	  emit(f,"\t%s%s\t%s,%s\n",s,x_t[t&NQ],(t&NQ)==CHAR?bregnames[reg]:regnames[reg],(t&NQ)==CHAR?bregnames[p->q2.reg]:regnames[p->q2.reg]);
+	}	    
+      }else if(p->q2.am){
+	if(reg_pair(p->q2.am->base,&rp)){
+	  int seg=rp.SEG;
+	  if(!short_add&&reg_pair(reg,&rp))
+	    emit(f,"\texts\t%s,#3\n",regnames[seg]);
+	  else
+	    emit(f,"\texts\t%s,#1\n",regnames[seg]);
+	}
+	if(reg_pair(reg,&rp)){
+	  BSET(regs_modified,tp);
+	  emit(f,"\tmov\t%s,",regnames[tp]);emit_obj(f,&p->q2,t);emit(f,"\n");
+	  emit(f,"\t%s\t%s,%s\n",s,regnames[rp.r1],regnames[tp]);
+	  s=longcmd(s);
+	  if(!short_add){
+	    p->q2.am->offset+=2;
+	    emit(f,"\tmov\t%s,",regnames[tp]);emit_obj(f,&p->q2,t);emit(f,"\n");
+	    emit(f,"\t%s\t%s,%s\n",s,regnames[rp.r2],regnames[tp]);
+	    p->q2.am->offset-=2;
+	  }
+	}else{
+	  if(p->q2.am->flags==POST_INC&&p->q2.am->base<=4){
+	    emit(f,"\t%s%s\t%s,",s,x_t[t&NQ],(t&NQ)==CHAR?bregnames[reg]:regnames[reg]);
+	    emit_obj(f,&p->q2,t);emit(f,"\n");
+	  }else{
+	    BSET(regs_modified,tp);
+	    emit(f,"\tmov%s\t%s,",x_t[t&NQ],(t&NQ)==CHAR?bregnames[tp]:regnames[tp]);
+	    emit_obj(f,&p->q2,t);emit(f,"\n");
+	    emit(f,"\t%s%s\t%s,%s\n",s,x_t[t&NQ],(t&NQ)==CHAR?bregnames[reg]:regnames[reg],(t&NQ)==CHAR?bregnames[tp]:regnames[tp]);
+	  }
+	}
+      }else if((p->q2.flags&(VAR|VARADR|REG))==VAR&&ISSTATIC(p->q2.v)){
+	if(ISFAR(p->q2.v)){
+	  emit(f,"\texts\t#SEG ");isseg=1;emit_obj(f,&p->q2,t);
+	  emit(f,",#%d\n",(reg_pair(reg,&rp)?2:1));
+	}
+	if(reg_pair(reg,&rp)){
+	  emit(f,"\t%s\t%s,",s,regnames[rp.r1]);
+	  emit_obj(f,&p->q2,t);emit(f,"\n");
+	  s=longcmd(s);
+	  if(!short_add){
+	    emit(f,"\t%s\t%s,",s,regnames[rp.r2]);
+	    emit_obj(f,&p->q2,t);emit(f,"+2\n");
+	  }
+	}else{
+	  emit(f,"\t%s%s\t%s,",s,x_t[t&NQ],(t&NQ)==CHAR?bregnames[reg]:regnames[reg]);
+	  emit_obj(f,&p->q2,t);emit(f,"\n");
+	}
+      }else if(isconst(q2)){
+	if(ISFLOAT(t)) ierror(0);
+	if(reg_pair(reg,&rp)){
+	  long l;
+/* rfi: shift constant must be evaluated according to own type
+	  eval_const(&p->q2.val,t);
+*/
+	  eval_const(&p->q2.val,q2typ(p));
+	  if(c==RSHIFT){
+	    l=zm2l(vmax);
+/* rfi: new generation for constant right shift */
+		if( l < 0) {
+		/* TODO: we should raise a warning */
+		/* Implementation dependent: negative shift is same as null shift */
+		/* avoid shift generation */
+		} else if( l > 31) {
+		/* TODO: we should raise a warning */
+		/* Implementation dependent: same behaviour as non const shift */
+			if( t & UNSIGNED)
+				emit(f,"\tmov\t%s,#0\n",regnames[rp.r2]);
+			else
+	    		emit(f,"\t%s\t%s,#15\n",s,regnames[rp.r2]);
+
+		   	emit(f,"\tmov\t%s,%s\n",regnames[rp.r1],regnames[rp.r2]);
+		} else if( l > 15) {
+	    	emit(f,"\tmov\t%s,%s\n",regnames[rp.r1],regnames[rp.r2]);
+			if( t & UNSIGNED)
+				emit(f,"\tmov\t%s,#0\n",regnames[rp.r2]);
+			else
+	    		emit(f,"\t%s\t%s,#15\n",s,regnames[rp.r2]);
+
+			l -= 16 ;
+			if( l > 0)
+	    		emit(f,"\t%s\t%s,#%ld\n",s,regnames[rp.r1],l);
+		} else if( l == 0) {
+		/* avoid shift generation */
+		} else if( l == 1) {
+			emit(f,"\tshr\t%s,#1\n",regnames[rp.r1]);
+	    	emit(f,"\tbmov\t%s.15,%s.0\n",regnames[rp.r1],regnames[rp.r2]);
+	    	emit(f,"\t%s\t%s,#1\n",s,regnames[rp.r2]);
+		} else {
+/* rfi: warning should be raised in corresponding case (see TODO above)
+	    if(l<1||l>15) ierror(0);
+*/
+	    BSET(regs_modified,tp);
+	    emit(f,"\tmov\t%s,%s\n",regnames[tp],regnames[rp.r2]);
+	    emit(f,"\tshr\t%s,#%ld\n",regnames[rp.r1],l);
+	    emit(f,"\t%s\t%s,#%ld\n",s,regnames[rp.r2],l);
+	    emit(f,"\tshl\t%s,#%ld\n",regnames[tp],16-l);
+	    emit(f,"\tor\t%s,%s\n",regnames[rp.r1],regnames[tp]);
+		}
+	  }else if(c==LSHIFT){
+	    l=zm2l(vmax);
+/* rfi: new generation for constant left shift */
+		if( l < 0) {
+		/* TODO: we should raise a warning */
+		/* Implementation dependent: negative shift is same as null shift */
+		/* avoid shift generation */
+		} else if( l > 31) {
+		/* TODO: we should raise a warning */
+		/* Implementation dependent: same behaviour as non const shift */
+			emit(f,"\tmov\t%s,#0\n",regnames[rp.r1]);
+		   	emit(f,"\tmov\t%s,%s\n",regnames[rp.r2],regnames[rp.r1]);
+		} else if( l > 15) {
+	   		emit(f,"\tmov\t%s,%s\n",regnames[rp.r2],regnames[rp.r1]);
+	   		emit(f,"\tmov\t%s,#0\n",regnames[rp.r1]);
+			l -= 16 ;
+			if( l > 0)
+	      		emit(f,"\tshl\t%s,#%ld\n",regnames[rp.r2],l);
+		} else if( l == 0) {
+		/* avoid shift generation */
+		} else if( l == 1) {
+	      emit(f,"\tadd\t%s,%s\n",regnames[rp.r1],regnames[rp.r1]);
+	      emit(f,"\taddc\t%s,%s\n",regnames[rp.r2],regnames[rp.r2]);
+		} else
+/* rfi: warning should be raised in corresponding case (see TODO above)
+	    if(l<1||l>15) ierror(0);
+*/
+	    if(l==2){
+	      emit(f,"\tadd\t%s,%s\n",regnames[rp.r1],regnames[rp.r1]);
+	      emit(f,"\taddc\t%s,%s\n",regnames[rp.r2],regnames[rp.r2]);
+	      emit(f,"\tadd\t%s,%s\n",regnames[rp.r1],regnames[rp.r1]);
+	      emit(f,"\taddc\t%s,%s\n",regnames[rp.r2],regnames[rp.r2]);
+	    }else{
+	      BSET(regs_modified,tp);
+	      emit(f,"\tmov\t%s,%s\n",regnames[tp],regnames[rp.r1]);
+	      emit(f,"\tshl\t%s,#%ld\n",regnames[rp.r1],l);
+	      emit(f,"\tshl\t%s,#%ld\n",regnames[rp.r2],l);
+	      emit(f,"\tshr\t%s,#%ld\n",regnames[tp],16-l);
+	      emit(f,"\tor\t%s,%s\n",regnames[rp.r2],regnames[tp]);
+	    }
+	  }else{
+	    l=zm2l(zmand(vmax,l2zm(65535L)));
+	    emit(f,"\t%s\t%s,#%ld\n",s,regnames[rp.r1],l);
+	    l=zm2l(zmrshift(vmax,l2zm(16L)));
+	    s=longcmd(s);
+	    if(!short_add) emit(f,"\t%s\t%s,#%ld\n",s,regnames[rp.r2],l);
+	  }
+	}else{
+	  emit(f,"\t%s%s\t%s,",s,x_t[t&NQ],(t&NQ)==CHAR?bregnames[reg]:regnames[reg]);
+	  emit_obj(f,&p->q2,t);emit(f,"\n");
+	}
+      }else if(p->q2.flags&VARADR){
+	p->q2.flags&=~VARADR;
+	if(reg_pair(reg,&rp)){
+	  emit(f,"\t%s\t%s,#SOF ",s,regnames[rp.r1]);emit_obj(f,&p->q2,t);emit(f,"\n");
+	  s=longcmd(s);
+	  if(!short_add)
+	    emit(f,"\t%s\t%s,#SEG ",s,regnames[rp.r2]);isseg=1;emit_obj(f,&p->q2,t);emit(f,"\n");
+	}else{
+	  emit(f,"\t%s\t%s,#",s,regnames[reg]);emit_obj(f,&p->q2,t);emit(f,"\n");
+	}
+	p->q2.flags|=VARADR;
+      }else if(p->q2.flags&DREFOBJ){
+	int seg=0,sof=0;
+        /*	if(!(p->q2.flags&REG)) ierror(0);*/
+	if(reg_pair(p->q2.reg,&rp)){
+	  seg=rp.SEG;sof=rp.SOF;
+	  if(!short_add&&reg_pair(reg,&rp)){
+	    emit(f,"\texts\t%s,#2\n",regnames[seg]);
+	  }else
+	    emit(f,"\texts\t%s,#1\n",regnames[seg]);
+	}
+	if(reg_pair(reg,&rp)){
+	  if(scratchreg(p->q2.reg,p)){
+	    emit(f,"\t%s\t%s,[%s+]\n",s,regnames[rp.r1],regnames[sof?sof:p->q2.reg]);
+	    s=longcmd(s);
+	    if(!short_add) emit(f,"\t%s\t%s,[%s]\n",s,regnames[rp.r2],regnames[sof?sof:p->q2.reg]);
+	  }else{
+	    emit(f,"\t%s\t%s,[%s]\n",s,regnames[rp.r1],regnames[sof?sof:p->q2.reg]);
+	    s=longcmd(s);
+	    if(!short_add){
+	      BSET(regs_modified,tp);
+	      emit(f,"\tmov\t%s,[%s+#2]\n",regnames[tp],regnames[sof?sof:p->q2.reg]);
+	      emit(f,"\t%s\t%s,%s\n",s,regnames[rp.r2],regnames[tp]);
+	    }
+	  }
+	}else{
+	  emit(f,"\t%s%s\t%s,",s,x_t[t&NQ],(t&NQ)==CHAR?bregnames[reg]:regnames[reg]);
+	  emit_obj(f,&p->q2,t);emit(f,"\n");
+	}
+      }else if((p->q2.flags&(VAR|DREFOBJ))==VAR&&(p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER)){
+	long l=voff(&p->q2);
+	if(reg_pair(reg,&rp)){
+	  if(l){
+	    BSET(regs_modified,tp);
+	    emit(f,"\tmov\t%s,[%s+#%ld]\n",regnames[tp],regnames[sp],l);
+	    emit(f,"\t%s\t%s,%s\n",s,regnames[rp.r1],regnames[tp]);
+	  }else
+	    emit(f,"\t%s\t%s,[%s]\n",s,regnames[rp.r1],regnames[sp]);
+	  s=longcmd(s);
+	  if(!short_add){
+	    BSET(regs_modified,tp);
+	    emit(f,"\tmov\t%s,[%s+#%ld]\n",regnames[tp],regnames[sp],l+2);
+	    emit(f,"\t%s\t%s,%s\n",s,regnames[rp.r2],regnames[tp]);
+	  }
+	}else{
+	  if(l){
+	    BSET(regs_modified,tp);
+	    emit(f,"\tmov%s\t%s,[%s+#%ld]\n",x_t[t&NQ],(t&NQ)==CHAR?bregnames[tp]:regnames[tp],regnames[sp],l);
+	    emit(f,"\t%s%s\t%s,%s\n",s,x_t[t&NQ],(t&NQ)==CHAR?bregnames[reg]:regnames[reg],(t&NQ)==CHAR?bregnames[tp]:regnames[tp]);
+	  }else
+	    emit(f,"\t%s%s\t%s,[%s]\n",s,x_t[t&NQ],(t&NQ)==CHAR?bregnames[reg]:regnames[reg],regnames[sp]);
+	}
+      }else
+	ierror(0);
+      if(c==MULT) emit(f,"\tmov\t%s,MDL\n",regnames[reg]);
+      /*FIXME:signed*/
+      if(short_add==1) emit(f,"\t%s\t%s,#0\n",s,regnames[rp.r2]);
+      if(c!=COMPARE) save_result(f,reg,p,t);
+      if(!ISLWORD(t)||((c==ADD||c==SUB||c==ADDI2P||c==SUBIFP)&&!short_add)){
+	cc=&p->z;cc_t=t;
+      }else
+	cc=0;
+      continue;
+    }
+    ierror(0);
+  }
+  if(notpopped){
+    emit(f,"\tadd\t%s,#%ld\n",regnames[sp],notpopped);
+    pop(notpopped,0);notpopped=0;
+  }
+  function_bottom(f,v,loff);
+}
+
+int shortcut(int c,int t)
+{
+  if(c==COMPARE||c==AND||c==OR||c==XOR) return 1;
+  if((t&NQ)!=BIT&&(c==ADD||c==SUB)) return 1;
+  return 0;
+}
+
+void cleanup_cg(FILE *f)
+{
+  struct fpconstlist *p;
+  unsigned char *ip;
+  if(f&&stack_check){
+    emit(f,"\t%s\t%s__stack_check\n",public,idprefix);
+  }
+  while(p=firstfpc){
+    if(f){
+      new_section(f,NDATA);
+      emit(f,even);
+      emit(f,"%s%d:\n\t%s\t",labprefix,p->label,TASKING?dct[SHORT]:vdct[SHORT]);
+      ip=(unsigned char *)&p->val.vdouble;
+      emit(f,"0x%02x%02x%02x%02x",ip[3],ip[2],ip[1],ip[0]);
+      if((p->typ&NQ)==DOUBLE||(p->typ&NQ)==LDOUBLE){
+	emit(f,",0x%02x%02x%02x%02x",ip[7],ip[6],ip[5],ip[4]);
+      }
+      emit(f,"\n");
+    }
+    firstfpc=p->next;
+    free(p);
+  }
+  if(f&&TASKING) emit(f,"%s\tREGDEF R0-R15\n\tend\n",sec_end);
+}
+
+int reg_parm(struct reg_handle *p,struct Typ *t,int mode,struct Typ *fkt)
+{
+  int f=t->flags&NQ;
+  if(!ISSCALAR(f)) return 0;
+  if(p->gpr>3||mode) return 0;
+  if(f==LLONG||f==DOUBLE||f==LDOUBLE)
+    return 0;
+  else if(f==LONG||f==FPOINTER||f==HPOINTER){
+    if(p->gpr==0) {p->gpr=2;return 23;}
+    if(p->gpr==1) {p->gpr=3;return 22;}
+    if(p->gpr==2) {p->gpr=4;return 21;}
+    return 0;
+  }else
+    return 13+p->gpr++;
+}
+
+void insert_const(union atyps *p,int t)
+/*  Traegt Konstante in entprechendes Feld ein.       */
+{
+  if(!p) ierror(0);
+/*  *p = (union atyps) 0 ; /* rfi: clear unused bits */
+  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){fprintf(f,"B");vmax=zc2zm(p->vchar);fprintf(f,"%d",!zmeqto(vmax,l2zm(0L)));}
+  if(t==(UNSIGNED|BIT)){fprintf(f,"UB");vumax=zuc2zum(p->vuchar);fprintf(f,"%d",!zumeqto(vmax,ul2zum(0UL)));}
+  if(t==CHAR){fprintf(f,"C");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)
+/*  Gibt atyps aus.                                     */
+{
+  t&=NU;
+  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(vumax,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)
+{
+}
+
+void cleanup_db(FILE *f)
+{
+}
+
+char *use_libcall(int c,int t,int t2)
+{
+  static char fname[16];
+  char *ret=0,*tt;
+
+  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)&&(t&NU)==LLONG){
+        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{
+	  sprintf(fname,"__%s%s%s%ld",ename[c],(t&UNSIGNED)?"u":"",ISFLOAT(t)?"flt":"int",zm2l(sizetab[t&NQ])*8);
+          ret=fname;
+	}
+      }
+    }
+  }
+
+
+  return ret;
+}
diff --git a/machines/c16x/machine.dt b/machines/c16x/machine.dt
new file mode 100755
index 0000000..eab38c9
--- /dev/null
+++ b/machines/c16x/machine.dt
@@ -0,0 +1,16 @@
+S8BS
+S8BU
+S16BSLE S16BSBE
+S16BULE S16BUBE
+S16BSLE S16BSBE
+S16BULE S16BUBE
+S32BSLE S32BSBE
+S32BULE S32BUBE
+S64BSLE S64BSBE
+S64BULE S64BUBE
+S32BIEEELE
+S64BIEEELE
+S64BIEEELE
+S16BULE S16BUBE
+
+
diff --git a/machines/c16x/machine.h b/machines/c16x/machine.h
new file mode 100755
index 0000000..be6dbdd
--- /dev/null
+++ b/machines/c16x/machine.h
@@ -0,0 +1,184 @@
+/*  Example of a code-generator for SAB c16x 16bit microcontrollers.*/
+
+#include "dt.h"
+
+/* We have extended types! What we have to do to support them:      */
+/* - #define HAVE_EXT_TYPES
+   - #undef all standard types
+   - #define all standard types plus new types
+   - write eval_const and insert_const
+   - write typedefs for zmax and zumax
+   - write typname[]
+   - write conv_typ()
+   - optionally #define ISPOINTER, ISARITH, ISINT etc.
+   - optionally #define HAVE_TGT_PRINTVAL and write printval
+   - optionally #define POINTER_TYPE
+   - optionally #define HAVE_TGT_FALIGN and write falign
+   - optionally #define HAVE_TGT_SZOF and write szof
+   - optionally add functions for attribute-handling
+*/
+#define HAVE_EXT_TYPES 1
+
+#define HAVE_TGT_PRINTVAL
+
+#undef CHAR
+#undef SHORT
+#undef INT
+#undef LONG
+#undef LLONG
+#undef FLOAT
+#undef DOUBLE
+#undef LDOUBLE
+#undef VOID
+#undef POINTER
+#undef ARRAY
+#undef STRUCT
+#undef UNION
+#undef ENUM
+#undef FUNKT
+#undef BOOL
+#undef MAXINT
+#undef MAX_TYPE
+
+#define BIT 1
+#define CHAR 2
+#define SHORT 3
+#define INT 4
+#define LONG 5
+#define LLONG 6
+#define FLOAT 7
+#define DOUBLE 8
+#define LDOUBLE 9
+#define VOID 10
+#define NPOINTER 11
+#define FPOINTER 12
+#define HPOINTER 13
+#define ARRAY 14
+#define STRUCT 15
+#define UNION 16
+#define ENUM 17
+#define FUNKT 18
+#define BOOL 19
+
+#define MAXINT 20
+
+#define MAX_TYPE MAXINT
+
+#define POINTER_TYPE(x) pointer_type(x)
+extern int pointer_type();
+#define ISPOINTER(x) ((x&NQ)>=NPOINTER&&(x&NQ)<=HPOINTER)
+#define ISSCALAR(x) ((x&NQ)>=BIT&&(x&NQ)<=HPOINTER)
+#define ISINT(x) ((x&NQ)>=BIT&&(x&NQ)<=LLONG)
+#define PTRDIFF_T(x) ((x)==HPOINTER?LONG:INT)
+
+typedef zllong zmax;
+typedef zullong zumax;
+
+union atyps{
+  zchar vchar;
+  zuchar vuchar;
+  zshort vshort;
+  zushort vushort;
+  zint vint;
+  zuint vuint;
+  zlong vlong;
+  zulong vulong;
+  zllong vllong;
+  zullong vullong;
+  zmax vmax;
+  zumax vumax;
+  zfloat vfloat;
+  zdouble vdouble;
+  zldouble vldouble;
+};
+
+/*  This struct can be used to implement machine-specific           */
+/*  addressing-modes.                                               */
+/*  Not used in this code-generrator.                               */
+struct AddressingMode{
+    int flags;
+    int base;
+    long offset;
+    struct Var *v;
+};
+
+/* This type will be added to every IC. Can be used by the cg.      */
+#define HAVE_EXT_IC 1
+struct ext_ic {
+  int flags;
+  int r;
+  long offset;
+};
+
+/*  The number of registers of the target machine.                  */
+#define MAXR 25
+
+/*  Number of commandline-options the code-generator accepts.       */
+#define MAXGF 10
+
+/*  If this is set to zero vbcc will not generate ICs where the     */
+/*  target operand is the same as the 2nd source operand.           */
+/*  This can sometimes simplify the code-generator, but usually     */
+/*  the code is better if the code-generator allows it.             */
+#define USEQ2ASZ 1
+
+/*  This specifies the smallest integer type that can be added to a */
+/*  pointer.                                                        */
+#define MINADDI2P INT
+
+/*  If the bytes of an integer are ordered most significant byte    */
+/*  byte first and then decreasing set BIGENDIAN to 1.              */
+#define BIGENDIAN 0
+
+/*  If the bytes of an integer are ordered lest significant byte    */
+/*  byte first and then increasing set LITTLEENDIAN to 1.           */
+#define LITTLEENDIAN 1
+
+/*  Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive.    */
+
+/*  If switch-statements should be generated as a sequence of       */
+/*  SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1.      */
+/*  This can yield better code on some machines.                    */
+#define SWITCHSUBS 0
+
+/*  In optimizing compilation certain library memcpy/strcpy-calls   */
+/*  with length known at compile-time will be inlined using an      */
+/*  ASSIGN-IC if the size is less or equal to INLINEMEMCPY.         */
+/*  The type used for the ASSIGN-IC will be UNSIGNED|CHAR.          */
+#define INLINEMEMCPY 1024
+
+#define HAVE_REGPARMS 1
+
+struct reg_handle {
+  int gpr;
+};
+
+/*  We use unsigned int as size_t rather than unsigned long which   */
+/*  is the default setting.                                         */
+#define HAVE_INT_SIZET 1
+
+/*  We have register pairs.                                         */
+#define HAVE_REGPAIRS 1
+
+/*  We keep track of all registers modified by a function.          */
+#define HAVE_REGS_MODIFIED 1
+
+#define HAVE_TARGET_RALLOC 1
+#define cost_load_reg(r,v) 4
+#define cost_save_reg(r,v) 4
+#define cost_move_reg(i,j) 2
+#define cost_pushpop_reg(r) 2
+
+/* size of buffer for asm-output */
+#define EMIT_BUF_LEN 1024 /* should be enough */
+/* number of asm-output lines buffered */
+#define EMIT_BUF_DEPTH 4
+
+/*  We have asm_peephole to optimize assembly-output */
+#define HAVE_TARGET_PEEPHOLE 1
+
+/*  We have some target-specific variable attributes.               */
+#define HAVE_TARGET_ATTRIBUTES 1
+
+/* We use builtin libcalls for some operations */
+#define HAVE_LIBCALLS 1
diff --git a/machines/dv/machine.c b/machines/dv/machine.c
new file mode 100755
index 0000000..264d677
--- /dev/null
+++ b/machines/dv/machine.c
@@ -0,0 +1,1112 @@
+/*
+    Dalvik backend for vbcc
+*/                                                                             
+
+#include "supp.h"
+
+static char FILE_[]=__FILE__;
+
+/*  Public data that MUST be there.                             */
+
+/* Name and copyright. */
+char cg_copyright[]="vbcc dalvik code-generator V0.1 (c) in 2012 by Volker Barthelmann";
+
+/*  Commandline-flags the code-generator accepts:
+    0: just a flag
+    VALFLAG: a value must be specified
+    STRINGFLAG: a string can be specified
+    FUNCFLAG: a function will be called
+    apart from FUNCFLAG, all other versions can only be specified once */
+int g_flags[MAXGF]={0,0,
+		    VALFLAG,VALFLAG,VALFLAG,
+		    0,0,
+		    VALFLAG,VALFLAG,0};
+
+/* the flag-name, do not use names beginning with l, L, I, D or U, because
+   they collide with the frontend */
+char *g_flags_name[MAXGF]={"three-addr","load-store",
+			   "volatile-gprs","volatile-fprs","volatile-ccrs",
+			   "imm-ind","gpr-ind",
+			   "gpr-args","fpr-args","use-commons"};
+
+/* the results of parsing the command-line-flags will be stored here */
+union ppi g_flags_val[MAXGF];
+
+/*  Alignment-requirements for all types in bytes.              */
+zmax align[MAX_TYPE+1];
+
+/*  Alignment that is sufficient for every object.              */
+zmax maxalign;
+
+/*  CHAR_BIT for the target machine.                            */
+zmax char_bit;
+
+/*  sizes of the basic 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. will be initialized in init_cg(),
+    register number 0 is invalid, valid registers start at 1 */
+char *regnames[MAXR+1];
+
+/*  The Size of each register in bytes.                         */
+zmax regsize[MAXR+1];
+
+/*  a 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];
+
+/* specifies the priority for the register-allocator, if the same
+   estimated cost-saving can be obtained by several registers, the
+   one with the highest priority will be used */
+int reg_prio[MAXR+1];
+
+/* an empty reg-handle representing initial state */
+struct reg_handle empty_reg_handle={0,0};
+
+/* Names of target-specific variable attributes.                */
+char *g_attr_name[]={"__interrupt",0};
+
+
+/****************************************/
+/*  Private data and functions.         */
+/****************************************/
+
+#define THREE_ADDR (g_flags[0]&USEDFLAG)
+#define LOAD_STORE (g_flags[1]&USEDFLAG)
+#define VOL_GPRS   ((g_flags[2]&USEDFLAG)?g_flags_val[2].l:NUM_GPRS/2)
+#define VOL_FPRS   ((g_flags[3]&USEDFLAG)?g_flags_val[3].l:NUM_FPRS/2)
+#define VOL_CCRS   ((g_flags[4]&USEDFLAG)?g_flags_val[4].l:NUM_CCRS/2)
+#define IMM_IND    ((g_flags[5]&USEDFLAG)?1:0)
+#define GPR_IND    ((g_flags[6]&USEDFLAG)?2:0)
+#define GPR_ARGS   ((g_flags[7]&USEDFLAG)?g_flags_val[7].l:0)
+#define FPR_ARGS   ((g_flags[8]&USEDFLAG)?g_flags_val[8].l:0)
+#define USE_COMMONS (g_flags[9]&USEDFLAG)
+
+
+#ifdef DV_BYTE8
+/* alignment of basic data-types, used to initialize align[] */
+static long malign[MAX_TYPE+1]=  {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+/* sizes of basic data-types, used to initialize sizetab[] */
+static long msizetab[MAX_TYPE+1]={1,1,2,4,4,8,4,8,8,0,8,0,0,0,4,0};
+#else
+/* alignment of basic data-types, used to initialize align[] */
+static long malign[MAX_TYPE+1]=  {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+/* sizes of basic data-types, used to initialize sizetab[] */
+static long msizetab[MAX_TYPE+1]={1,1,1,1,1,2,1,2,2,0,2,0,0,0,1,0};
+#endif
+
+/* used to initialize regtyp[] */
+static struct Typ ltyp={LONG},ldbl={DOUBLE},lchar={CHAR};
+
+/* macros defined by the backend */
+static char *marray[]={"__section(x)=__vattr(\"section(\"#x\")\")",
+		       "__GENERIC__",
+		       0};
+
+/* special registers */
+static int sp;                     /*  Stackpointer                        */
+static int t1,t2,t3;               /*  temporary gprs */
+static int f1,f2,f3;               /*  temporary fprs */
+
+#define dt(t) (((t)&UNSIGNED)?udt[(t)&NQ]:sdt[(t)&NQ])
+static char *sdt[MAX_TYPE+1]={"??","c","s","i","l","ll","f","d","ld","v","p"};
+static char *udt[MAX_TYPE+1]={"??","uc","us","ui","ul","ull","f","d","ld","v","p"};
+
+/* sections */
+#define DATA 0
+#define BSS 1
+#define CODE 2
+#define RODATA 3
+#define SPECIAL 4
+
+static long stack;
+static int stack_valid;
+static int section=-1,newobj;
+static char *codename="\t.text\n",
+  *dataname="\t.data\n",
+  *bssname="",
+  *rodataname="\t.section\t.rodata\n";
+
+/* label at the end of the function (if any) */
+static int exit_label;
+
+/* assembly-prefixes for labels and external identifiers */
+static char *labprefix=":",*idprefix="";
+
+#if FIXED_SP
+/* variables to calculate the size and partitioning of the stack-frame
+   in the case of FIXED_SP */
+static long frameoffset,pushed,maxpushed,framesize;
+#else
+/* variables to keep track of the current stack-offset in the case of
+   a moving stack-pointer */
+static long notpopped,dontpop,stackoffset,maxpushed;
+#endif
+
+static long localsize,rsavesize,argsize;
+
+static void emit_obj(FILE *f,struct obj *p,int t);
+
+static long real_offset(struct obj *o)
+{
+  long off=zm2l(o->v->offset);
+  if(off<0){
+    /* function parameter */
+    ierror(0);
+  }
+
+  off+=zm2l(o->val.vmax);
+  return off;
+}
+
+/*  Initializes an addressing-mode structure and returns a pointer to
+    that object. Will not survive a second call! */
+static struct obj *cam(int flags,int base,long offset)
+{
+  static struct obj obj;
+  static struct AddressingMode am;
+  obj.am=&am;
+  am.flags=flags;
+  am.base=base;
+  am.offset=offset;
+  return &obj;
+}
+
+/* changes to a special section, used for __section() */
+static int special_section(FILE *f,struct Var *v)
+{
+  char *sec;
+  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;
+}
+
+/* generate code to load the address of a variable into register r */
+static void load_address(FILE *f,int r,struct obj *o,int type)
+/*  Generates code to load the address of a variable into register r.   */
+{
+  if(!(o->flags&VAR)) ierror(0);
+  if(!reg_pair(r,&rp)) ierror(0);
+
+  if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER){
+    long off=real_offset(o);
+    emit(f,"\tmove-int\t%s,%s\n",mregnames[rp.r2],mregnames[fp]);
+    emit(f,"\tconst-int\t%s,%ld\n",mregnames[rp.r1],loff);
+  }else{
+    emit(f,"\tconst-int\t%s,%s\n",mregnames[rp.r2],gp);
+    emit(f,"\tconst-int\t%s,",mregnames[rp.r1]);
+    emit_obj(f,o,type);
+    emit(f,"\n");
+  }
+}
+/* Generates code to load a memory object into register r. tmp is a
+   general purpose register which may be used. tmp can be r. */
+static void load_reg(FILE *f,int r,struct obj *o,int type)
+{
+  type&=NU;
+  if(o->flags&VARADR){
+    load_address(f,r,o,POINTER);
+  }else{
+    if((o->flags&(REG|DREFOBJ))==REG&&o->reg==r)
+      return;
+#ifdef DV_BYTE8
+    ierror(0);
+#else
+    ierror(0);
+#endif
+  }
+}
+
+/*  Generates code to store register r into memory object o. */
+static void store_reg(FILE *f,int r,struct obj *o,int type)
+{
+  type&=NQ;
+  emit(f,"\tmov.%s\t",dt(type));
+  emit_obj(f,o,type);
+  emit(f,",%s\n",regnames[r]);
+}
+
+/*  Yields log2(x)+1 or 0. */
+static long pof2(zumax x)
+{
+  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 struct IC *preload(FILE *,struct IC *);
+
+static void function_top(FILE *,struct Var *,long);
+static void function_bottom(FILE *f,struct Var *,long);
+
+#define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
+#define isconst(x) ((p->x.flags&(KONST|DREFOBJ))==KONST)
+
+static int q1reg,q2reg,zreg;
+
+static char *ccs[]={"eq","ne","lt","ge","le","gt",""};
+static char *logicals[]={"or","xor","and"};
+static char *arithmetics[]={"slw","srw","add","sub","mullw","divw","mod"};
+
+/* Does some pre-processing like fetching operands from memory to
+   registers etc. */
+static struct IC *preload(FILE *f,struct IC *p)
+{
+  int r;
+
+  if(isreg(q1))
+    q1reg=p->q1.reg;
+  else
+    q1reg=0;
+
+  if(isreg(q2))
+    q2reg=p->q2.reg;
+  else
+    q2reg=0;
+
+  if(isreg(z)){
+    zreg=p->z.reg;
+  }else{
+    if(ISFLOAT(ztyp(p)))
+      zreg=f1;
+    else
+      zreg=t1;
+  }
+  
+  if((p->q1.flags&(DREFOBJ|REG))==DREFOBJ&&!p->q1.am){
+    p->q1.flags&=~DREFOBJ;
+    load_reg(f,t1,&p->q1,q1typ(p));
+    p->q1.reg=t1;
+    p->q1.flags|=(REG|DREFOBJ);
+  }
+  if(p->q1.flags&&LOAD_STORE&&!isreg(q1)){
+    if(ISFLOAT(q1typ(p)))
+      q1reg=f1;
+    else
+      q1reg=t1;
+    load_reg(f,q1reg,&p->q1,q1typ(p));
+    p->q1.reg=q1reg;
+    p->q1.flags=REG;
+  }
+
+  if((p->q2.flags&(DREFOBJ|REG))==DREFOBJ&&!p->q2.am){
+    p->q2.flags&=~DREFOBJ;
+    load_reg(f,t1,&p->q2,q2typ(p));
+    p->q2.reg=t1;
+    p->q2.flags|=(REG|DREFOBJ);
+  }
+  if(p->q2.flags&&LOAD_STORE&&!isreg(q2)){
+    if(ISFLOAT(q2typ(p)))
+      q2reg=f2;
+    else
+      q2reg=t2;
+    load_reg(f,q2reg,&p->q2,q2typ(p));
+    p->q2.reg=q2reg;
+    p->q2.flags=REG;
+  }
+  return p;
+}
+
+/* save the result (in zreg) into p->z */
+void save_result(FILE *f,struct IC *p)
+{
+  if((p->z.flags&(REG|DREFOBJ))==DREFOBJ&&!p->z.am){
+    p->z.flags&=~DREFOBJ;
+    load_reg(f,t2,&p->z,POINTER);
+    p->z.reg=t2;
+    p->z.flags|=(REG|DREFOBJ);
+  }
+  if(isreg(z)){
+    if(p->z.reg!=zreg)
+      emit(f,"\tmov.%s\t%s,%s\n",dt(ztyp(p)),regnames[p->z.reg],regnames[zreg]);
+  }else{
+    store_reg(f,zreg,&p->z,ztyp(p));
+  }
+}
+
+/* prints an object */
+static void emit_obj(FILE *f,struct obj *p,int t)
+{
+  if(p->am){
+    ierror(0);
+  }
+  if((p->flags&(KONST|DREFOBJ))==(KONST|DREFOBJ)){
+    emitval(f,&p->val,p->dtyp&NU);
+    return;
+  }
+  if(p->flags&DREFOBJ) ierror(0);
+  if(p->flags&REG){
+    emit(f,"%s",regnames[p->reg]);
+  }else if(p->flags&VAR) {
+    if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER)
+      ierror(0);
+      emit(f,"%ld(%s)",real_offset(p),regnames[sp]);
+    else{
+      if(!zmeqto(l2zm(0L),p->val.vmax)){emitval(f,&p->val,LONG);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(p->flags&KONST){
+    emitval(f,&p->val,t&NU);
+  }
+  /*if(p->flags&DREFOBJ) emit(f,")");*/
+}
+
+/*  Test if there is a sequence of FREEREGs containing FREEREG reg.
+    Used by peephole. */
+static int exists_freereg(struct IC *p,int reg)
+{
+  while(p&&(p->code==FREEREG||p->code==ALLOCREG)){
+    if(p->code==FREEREG&&p->q1.reg==reg) return 1;
+    p=p->next;
+  }
+  return 0;
+}
+
+/* search for possible addressing-modes */
+static void peephole(struct IC *p)
+{
+  int c,c2,r;struct IC *p2;struct AddressingMode *am;
+
+  return;
+
+  for(;p;p=p->next){
+    c=p->code;
+    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;
+
+    /* Try const(reg) */
+    if(IMM_IND&&(c==ADDI2P||c==SUBIFP)&&isreg(z)&&(p->q2.flags&(KONST|DREFOBJ))==KONST){
+      int base;zmax of;struct obj *o;
+      eval_const(&p->q2.val,p->typf);
+      if(c==SUBIFP) of=zmsub(l2zm(0L),vmax); else of=vmax;
+      if(1/*zmleq(l2zm(-32768L),vmax)&&zmleq(vmax,l2zm(32767L))*/){
+	r=p->z.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(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) break;
+	      o=&p2->q1;
+	    }
+	    if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
+	      if(o) break;
+	      o=&p2->q2;
+	    }
+	    if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
+	      if(o) 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);
+		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;
+	  }
+        }
+      }
+    }
+    /* Try reg,reg */
+    if(GPR_IND&&c==ADDI2P&&isreg(q2)&&isreg(z)&&(isreg(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||(q1typ(p2)&NQ)==LLONG) break;
+            o=&p2->q1;
+          }
+          if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
+            if(o||(q2typ(p2)&NQ)==LLONG) break;
+            o=&p2->q2;
+          }
+          if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
+            if(o||(ztyp(p2)&NQ)==LLONG) 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=GPR_IND;
+              am->base=base;
+              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;
+        }
+      }
+    }
+  }
+}
+
+/* generates the function entry code */
+static void function_top(FILE *f,struct Var *v,long offset)
+{
+  rsavesize=0;
+  if(!special_section(f,v)&&section!=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));
+}
+/* generates the function exit code */
+static void function_bottom(FILE *f,struct Var *v,long offset)
+{
+  emit(f,ret);
+}
+
+/****************************************/
+/*  End of private data and functions.  */
+/****************************************/
+
+/*  Does necessary initializations for the code-generator. Gets called  */
+/*  once at the beginning and should return 0 in case of problems.      */
+int init_cg(void)
+{
+  int i;
+  /*  Initialize some values which cannot be statically initialized   */
+  /*  because they are stored in the target's arithmetic.             */
+  maxalign=l2zm(8L);
+  char_bit=l2zm(8L);
+  stackalign=l2zm(4);
+
+  for(i=0;i<=MAX_TYPE;i++){
+    sizetab[i]=l2zm(msizetab[i]);
+    align[i]=l2zm(malign[i]);
+  }
+
+  regnames[0]="noreg";
+  for(i=1;i<=GPRS;i++){
+    regnames[i]=mymalloc(10);
+    sprintf(regnames[i],"v%d",i-1);
+#ifdef DV_BYTE8
+    regsize[i]=l2zm(4L);
+#else
+    regsize[i]=l2zm(1L);
+#endif
+    regtype[i]=&ltyp;
+  }
+  for(i=GPRS+1;i<=GPRS+PAIRS+1;i++){
+    regnames[i]=mymalloc(10);
+    sprintf(regnames[i],"v%d/v%d",i-GPRS-1,i-GPRS);
+#ifdef DV_BYTE8
+    regsize[i]=l2zm(8L);
+#else
+    regsize[i]=l2zm(2L);
+#endif
+    regtype[i]=&llong;
+  }
+
+  /*  Use multiple ccs.   */
+  multiple_ccs=0;
+
+  /*  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.          */
+#ifdef DV_BYTE8
+  t_min[CHAR]=l2zm(-128L);
+  t_min[SHORT]=l2zm(-32768L);
+  t_max[CHAR]=ul2zum(127L);
+  t_max[SHORT]=ul2zum(32767UL);
+  tu_max[CHAR]=ul2zum(255UL);
+  tu_max[SHORT]=ul2zum(65535UL);
+#else
+  t_min[CHAR]=t_min[SHORT]=zmsub(l2zm(-2147483647L),l2zm(1L));
+  t_max[CHAR]=t_max[SHORT]=ul2zum(2147483647UL);
+  tu_max[CHAR]=tu_max[SHORT]=ul2zum(4294967295UL);
+#endif
+  t_min[INT]=zmsub(l2zm(-2147483647L),l2zm(1L));
+  t_min[LONG]=t_min(INT);
+  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]=ul2zum(2147483647UL);
+  t_max[LONG]=t_max(INT);
+  t_max[LLONG]=zumrshift(zumkompl(ul2zum(0UL)),ul2zum(1UL));
+  t_max[MAXINT]=t_max(LLONG);
+  tu_max[INT]=ul2zum(4294967295UL);
+  tu_max[LONG]=t_max(UNSIGNED|INT);
+  tu_max[LLONG]=zumkompl(ul2zum(0UL));
+  tu_max[MAXINT]=t_max(UNSIGNED|LLONG);
+  
+  /*  Reserve a few registers for use by the code-generator.      */
+  /*  This is not optimal but simple.                             */
+  sp=FIRST_GPR;
+  t1=FIRST_GPR+1;
+  t2=FIRST_GPR+2;
+  f1=FIRST_FPR;
+  f2=FIRST_FPR+1;
+  regsa[t1]=regsa[t2]=1;
+  regsa[f1]=regsa[f2]=1;
+  regsa[sp]=1;
+  regscratch[t1]=regscratch[t2]=0;
+  regscratch[f1]=regscratch[f2]=0;
+  regscratch[sp]=0;
+
+  for(i=FIRST_GPR;i<=LAST_GPR-VOL_GPRS;i++)
+    regscratch[i]=1;
+  for(i=FIRST_FPR;i<=LAST_FPR-VOL_FPRS;i++)
+    regscratch[i]=1;
+  for(i=FIRST_CCR;i<=LAST_CCR-VOL_CCRS;i++)
+    regscratch[i]=1;
+
+  target_macros=marray;
+
+
+  return 1;
+}
+
+void init_db(FILE *f)
+{
+}
+
+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.        */
+/*  A pointer MUST be returned in a register. The code-generator    */
+/*  has to simulate a pseudo register if necessary.                 */
+{
+  if(ISFLOAT(t->flags)) 
+    return FIRST_FPR+2;
+  if(ISSTRUCT(t->flags)||ISUNION(t->flags)) 
+    return 0;
+  if(zmleq(szof(t),l2zm(4L))) 
+    return FIRST_GPR+3;
+  else
+    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.                                            */
+{
+  return 0;
+}
+
+/* estimate the cost-saving if object o from IC p is placed in
+   register r */
+int cost_savings(struct IC *p,int r,struct obj *o)
+{
+  int c=p->code;
+  if(o->flags&VKONST){
+    if(!LOAD_STORE)
+      return 0;
+    if(o==&p->q1&&p->code==ASSIGN&&(p->z.flags&DREFOBJ))
+      return 4;
+    else
+      return 2;
+  }
+  if(o->flags&DREFOBJ)
+    return 4;
+  if(c==SETRETURN&&r==p->z.reg&&!(o->flags&DREFOBJ)) return 3;
+  if(c==GETRETURN&&r==p->q1.reg&&!(o->flags&DREFOBJ)) return 3;
+  return 2;
+}
+
+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(r==0)
+    return 0;
+  t&=NQ;
+  if(t==0&&r>=FIRST_CCR&&r<=LAST_CCR)
+    return 1;
+  if(ISFLOAT(t)&&r>=FIRST_FPR&&r<=LAST_FPR)
+    return 1;
+  if(t==POINTER&&r>=FIRST_GPR&&r<=LAST_GPR)
+    return 1;
+  if(t>=CHAR&&t<=LONG&&r>=FIRST_GPR&&r<=LAST_GPR)
+    return 1;
+  return 0;
+}
+
+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;
+}
+
+int must_convert(int o,int t,int const_expr)
+/*  Returns zero if code for converting np to type t    */
+/*  can be omitted.                                     */
+/*  On the PowerPC cpu pointers and 32bit               */
+/*  integers have the same representation and can use   */
+/*  the same registers.                                 */
+{
+  int op=o&NQ,tp=t&NQ;
+  if((op==INT||op==LONG||op==POINTER)&&(tp==INT||tp==LONG||tp==POINTER))
+    return 0;
+  if(op==DOUBLE&&tp==LDOUBLE) return 0;
+  if(op==LDOUBLE&&tp==DOUBLE) 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&&section!=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.              */
+{
+  if(zm2l(align)>1) emit(f,"\t.align\t2\n");
+}
+
+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;char *sec;
+  if(v->clist) constflag=is_const(v->vtyp);
+  if(v->storage_class==STATIC){
+    if(ISFUNC(v->vtyp->flags)) return;
+    if(!special_section(f,v)){
+      if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&&section!=DATA){emit(f,dataname);if(f) section=DATA;}
+      if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&&section!=RODATA){emit(f,rodataname);if(f) section=RODATA;}
+      if(!v->clist&&section!=BSS){emit(f,bssname);if(f) section=BSS;}
+    }
+    if(v->clist||section==SPECIAL){
+      gen_align(f,falign(v->vtyp));
+      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){
+    emit(f,"\t.globl\t%s%s\n",idprefix,v->identifier);
+    if(v->flags&(DEFINED|TENTATIVE)){
+      if(!special_section(f,v)){
+	if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&&section!=DATA){emit(f,dataname);if(f) section=DATA;}
+	if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&&section!=RODATA){emit(f,rodataname);if(f) section=RODATA;}
+	if(!v->clist&&section!=BSS){emit(f,bssname);if(f) section=BSS;}
+      }
+      if(v->clist||section==SPECIAL){
+	gen_align(f,falign(v->vtyp));
+        emit(f,"%s%s:\n",idprefix,v->identifier);
+      }else
+        emit(f,"\t.global\t%s%s\n\t.%scomm\t%s%s,",idprefix,v->identifier,(USE_COMMONS?"":"l"),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,"\tdc.%s\t",dt(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[0],ip[1],ip[2],ip[3]);
+      if((t&NQ)!=FLOAT){
+	emit(f,",0x%02x%02x%02x%02x",ip[4],ip[5],ip[6],ip[7]);
+      }
+    }else{
+      emitval(f,&p->val,t&NU);
+    }
+  }else{
+    emit_obj(f,&p->tree->o,t&NU);
+  }
+  emit(f,"\n");newobj=0;
+}
+
+
+/*  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 *p,struct Var *v,zmax offset)
+/*  The main code-generation.                                           */
+{
+  int c,t,i;
+  struct IC *m;
+  argsize=0;
+  if(DEBUG&1) printf("gen_code()\n");
+  for(c=1;c<=MAXR;c++) regs[c]=regsa[c];
+  maxpushed=0;
+
+  /*FIXME*/
+  ret="\trts\n";
+
+  for(m=p;m;m=m->next){
+    c=m->code;t=m->typf&NU;
+    if(c==ALLOCREG) {regs[m->q1.reg]=1;continue;}
+    if(c==FREEREG) {regs[m->q1.reg]=0;continue;}
+
+    /* convert MULT/DIV/MOD with powers of two */
+    if((t&NQ)<=LONG&&(m->q2.flags&(KONST|DREFOBJ))==KONST&&(t&NQ)<=LONG&&(c==MULT||((c==DIV||c==MOD)&&(t&UNSIGNED)))){
+      eval_const(&m->q2.val,t);
+      i=pof2(vmax);
+      if(i){
+        if(c==MOD){
+          vmax=zmsub(vmax,l2zm(1L));
+          m->code=AND;
+        }else{
+          vmax=l2zm(i-1);
+          if(c==DIV) m->code=RSHIFT; else m->code=LSHIFT;
+        }
+        c=m->code;
+	gval.vmax=vmax;
+	eval_const(&gval,MAXINT);
+	if(c==AND){
+	  insert_const(&m->q2.val,t);
+	}else{
+	  insert_const(&m->q2.val,INT);
+	  p->typf2=INT;
+	}
+      }
+    }
+#if FIXED_SP
+    if(c==CALL&&argsize<zm2l(m->q2.val.vmax)) argsize=zm2l(m->q2.val.vmax);
+#endif
+  }
+  peephole(p);
+
+  for(c=1;c<=MAXR;c++){
+    if(regsa[c]||regused[c]){
+      BSET(regs_modified,c);
+    }
+  }
+
+  localsize=(zm2l(offset)+3)/4*4;
+#if FIXED_SP
+  /*FIXME: adjust localsize to get an aligned stack-frame */
+#endif
+
+  function_top(f,v,localsize);
+
+#if FIXED_SP
+  pushed=0;
+#endif
+
+  for(;p;p=p->next){
+    c=p->code;t=p->typf;
+    if(c==NOP) {p->z.flags=0;continue;}
+    if(c==ALLOCREG) {regs[p->q1.reg]=1;continue;}
+    if(c==FREEREG) {regs[p->q1.reg]=0;continue;}
+    if(c==LABEL) {emit(f,"%s%d:\n",labprefix,t);continue;}
+    if(c==BRA){
+      if(0/*t==exit_label&&framesize==0*/)
+	emit(f,ret);
+      else
+	emit(f,"\tb\t%s%d\n",labprefix,t);
+      continue;
+    }
+    if(c>=BEQ&&c<BRA){
+      emit(f,"\tb%s\t",ccs[c-BEQ]);
+      if(isreg(q1)){
+	emit_obj(f,&p->q1,0);
+	emit(f,",");
+      }
+      emit(f,"%s%d\n",labprefix,t);
+      continue;
+    }
+    if(c==MOVETOREG){
+      load_reg(f,p->z.reg,&p->q1,regtype[p->z.reg]->flags);
+      continue;
+    }
+    if(c==MOVEFROMREG){
+      store_reg(f,p->z.reg,&p->q1,regtype[p->z.reg]->flags);
+      continue;
+    }
+    if((c==ASSIGN||c==PUSH)&&((t&NQ)>POINTER||((t&NQ)==CHAR&&zm2l(p->q2.val.vmax)!=1))){
+      ierror(0);
+    }
+    p=preload(f,p);
+    c=p->code;
+    if(c==SUBPFP) c=SUB;
+    if(c==ADDI2P) c=ADD;
+    if(c==SUBIFP) c=SUB;
+    if(c==CONVERT){
+      if(ISFLOAT(q1typ(p))||ISFLOAT(ztyp(p))) ierror(0);
+      if(sizetab[q1typ(p)&NQ]<sizetab[ztyp(p)&NQ]){
+	if(q1typ(p)&UNSIGNED)
+	  emit(f,"\tzext.%s\t%s\n",dt(q1typ(p)),regnames[zreg]);
+	else
+	  emit(f,"\tsext.%s\t%s\n",dt(q1typ(p)),regnames[zreg]);
+      }
+      save_result(f,p);
+      continue;
+    }
+    if(c==KOMPLEMENT){
+      load_reg(f,zreg,&p->q1,t);
+      emit(f,"\tcpl.%s\t%s\n",dt(t),regnames[zreg]);
+      save_result(f,p);
+      continue;
+    }
+    if(c==SETRETURN){
+      load_reg(f,p->z.reg,&p->q1,t);
+      BSET(regs_modified,p->z.reg);
+      continue;
+    }
+    if(c==GETRETURN){
+      if(p->q1.reg){
+        zreg=p->q1.reg;
+	save_result(f,p);
+      }else
+        p->z.flags=0;
+      continue;
+    }
+    if(c==CALL){
+      int reg;
+      /*FIXME*/
+#if 0      
+      if(stack_valid&&(p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&(p->q1.v->fi->flags&ALL_STACK)){
+	if(framesize+zum2ul(p->q1.v->fi->stack1)>stack)
+	  stack=framesize+zum2ul(p->q1.v->fi->stack1);
+      }else
+	stack_valid=0;
+#endif
+      if((p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&p->q1.v->fi->inline_asm){
+        emit_inline_asm(f,p->q1.v->fi->inline_asm);
+      }else{
+	emit(f,"\tcall\t");
+	emit_obj(f,&p->q1,t);
+	emit(f,"\n");
+      }
+      /*FIXME*/
+#if FIXED_SP
+      pushed-=zm2l(p->q2.val.vmax);
+#endif
+      if((p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&(p->q1.v->fi->flags&ALL_REGS)){
+	bvunite(regs_modified,p->q1.v->fi->regs_modified,RSIZE);
+      }else{
+	int i;
+	for(i=1;i<=MAXR;i++){
+	  if(regscratch[i]) BSET(regs_modified,i);
+	}
+      }
+      continue;
+    }
+    if(c==ASSIGN||c==PUSH){
+      if(t==0) ierror(0);
+      if(c==PUSH){
+#if FIXED_SP
+	emit(f,"\tmov.%s\t%ld(%s),",dt(t),pushed,regnames[sp]);
+	emit_obj(f,&p->q1,t);
+	emit(f,"\n");
+	pushed+=zm2l(p->q2.val.vmax);
+#else
+	emit(f,"\tpush.%s\t",dt(t));
+	emit_obj(f,&p->q1,t);
+	emit(f,"\n");
+	push(zm2l(p->q2.val.vmax));
+#endif
+	continue;
+      }
+      if(c==ASSIGN){
+	load_reg(f,zreg,&p->q1,t);
+	save_result(f,p);
+      }
+      continue;
+    }
+    if(c==ADDRESS){
+      load_address(f,zreg,&p->q1,POINTER);
+      save_result(f,p);
+      continue;
+    }
+    if(c==MINUS){
+      load_reg(f,zreg,&p->q1,t);
+      emit(f,"\tneg.%s\t%s\n",dt(t),regnames[zreg]);
+      save_result(f,p);
+      continue;
+    }
+    if(c==TEST){
+      emit(f,"\ttst.%s\t",dt(t));
+      if(multiple_ccs)
+	emit(f,"%s,",regnames[zreg]);
+      emit_obj(f,&p->q1,t);
+      emit(f,"\n");
+      if(multiple_ccs)
+	save_result(f,p);
+      continue;
+    }
+    if(c==COMPARE){
+      emit(f,"\tcmp.%s\t",dt(t));
+      if(multiple_ccs)
+	emit(f,"%s,",regnames[zreg]);
+      emit_obj(f,&p->q1,t);
+      emit(f,",");
+      emit_obj(f,&p->q2,t);
+      emit(f,"\n");
+      if(multiple_ccs)
+	save_result(f,p);
+      continue;
+    }
+    if((c>=OR&&c<=AND)||(c>=LSHIFT&&c<=MOD)){
+      if(!THREE_ADDR)
+	load_reg(f,zreg,&p->q1,t);
+      if(c>=OR&&c<=AND)
+	emit(f,"\t%s.%s\t%s,",logicals[c-OR],dt(t),regnames[zreg]);
+      else
+	emit(f,"\t%s.%s\t%s,",arithmetics[c-LSHIFT],dt(t),regnames[zreg]);
+      if(THREE_ADDR){
+	emit_obj(f,&p->q1,t);
+	emit(f,",");
+      }
+      emit_obj(f,&p->q2,t);
+      emit(f,"\n");
+      save_result(f,p);
+      continue;
+    }
+    pric2(stdout,p);
+    ierror(0);
+  }
+  function_bottom(f,v,localsize);
+  if(stack_valid){
+    if(!v->fi) v->fi=new_fi();
+    v->fi->flags|=ALL_STACK;
+    v->fi->stack1=stack;
+  }
+  emit(f,"# stacksize=%lu%s\n",zum2ul(stack),stack_valid?"":"+??");
+}
+
+int shortcut(int code,int typ)
+{
+  return 0;
+}
+
+int reg_parm(struct reg_handle *m, struct Typ *t,int vararg,struct Typ *d)
+{
+  int f;
+  f=t->flags&NQ;
+  if(f<=LONG||f==POINTER){
+    if(m->gregs>=GPR_ARGS)
+      return 0;
+    else
+      return FIRST_GPR+3+m->gregs++;
+  }
+  if(ISFLOAT(f)){
+    if(m->fregs>=FPR_ARGS)
+      return 0;
+    else
+      return FIRST_FPR+2+m->fregs++;
+  }
+  return 0;
+}
+
+int handle_pragma(const char *s)
+{
+}
+void cleanup_cg(FILE *f)
+{
+}
+void cleanup_db(FILE *f)
+{
+  if(f) section=-1;
+}
+
diff --git a/machines/dv/machine.dt b/machines/dv/machine.dt
new file mode 100755
index 0000000..fa79dba
--- /dev/null
+++ b/machines/dv/machine.dt
@@ -0,0 +1,16 @@
+S32BSLE
+S32BULE
+S32BSLE S32BSBE
+S32BULE S32BUBE
+S32BSLE S32BSBE
+S32BULE S32BUBE
+S32BSLE S32BSBE
+S32BULE S32BUBE
+S64BSLE S64BSBE
+S64BULE S64BUBE
+S32BIEEELE
+S64BIEEELE
+S64BIEEELE
+S64BULE S64BUBE
+
+
diff --git a/machines/dv/machine.h b/machines/dv/machine.h
new file mode 100755
index 0000000..cc49371
--- /dev/null
+++ b/machines/dv/machine.h
@@ -0,0 +1,127 @@
+/*  
+    Dalvik backend for vbcc
+*/
+
+#include "dt.h"
+
+/*  This struct can be used to implement machine-specific           */
+/*  addressing-modes.                                               */
+/*  Currently possible are (const,gpr) and (gpr,gpr)                */
+struct AddressingMode{
+    int flags;
+    int base;
+    long offset;
+};
+
+/*  The number of registers of the target machine.                  */
+#define GPRS 256
+#define PAIRS (GPRS/2)
+#define MAXR (GPRS + PAIRS)
+
+/*  Number of commandline-options the code-generator accepts.       */
+#define MAXGF 20
+
+/*  If this is set to zero vbcc will not generate ICs where the     */
+/*  target operand is the same as the 2nd source operand.           */
+/*  This can sometimes simplify the code-generator, but usually     */
+/*  the code is better if the code-generator allows it.             */
+#define USEQ2ASZ 1
+
+/*  This specifies the smallest integer type that can be added to a */
+/*  pointer.                                                        */
+#ifndef DV_BYTE8
+#define MINADDI2P CHAR
+#else
+#define MINADDI2P INT
+#endif
+
+/*  If the bytes of an integer are ordered most significant byte    */
+/*  byte first and then decreasing set BIGENDIAN to 1.              */
+#define BIGENDIAN 0
+
+/*  If the bytes of an integer are ordered lest significant byte    */
+/*  byte first and then increasing set LITTLEENDIAN to 1.           */
+#define LITTLEENDIAN 1
+
+/*  Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive.    */
+
+/*  If switch-statements should be generated as a sequence of       */
+/*  SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1.      */
+/*  This can yield better code on some machines.                    */
+#define SWITCHSUBS 0
+
+/*  In optimizing compilation certain library memcpy/strcpy-calls   */
+/*  with length known at compile-time will be inlined using an      */
+/*  ASSIGN-IC if the size is less or equal to INLINEMEMCPY.         */
+/*  The type used for the ASSIGN-IC will be UNSIGNED|CHAR.          */
+#define INLINEMEMCPY 1024
+
+/*  Parameters are sometimes passed in registers without __reg.     */
+#define HAVE_REGPARMS 1
+
+/*  Parameters on the stack should be pushed in order rather than   */
+/*  in reverse order.                                               */
+#define ORDERED_PUSH FIXED_SP
+
+/*  Structure for reg_parm().                                       */
+struct reg_handle{
+    unsigned long regs;
+};
+
+/*  We have some target-specific variable attributes.               */
+#define HAVE_TARGET_ATTRIBUTES
+
+/* We have target-specific pragmas */
+#define HAVE_TARGET_PRAGMAS
+
+/*  We keep track of all registers modified by a function.          */
+#define HAVE_REGS_MODIFIED 1
+
+/* We have a implement our own cost-functions to adapt 
+   register-allocation */
+#define HAVE_TARGET_RALLOC 1
+#define cost_move_reg(x,y) 1
+#define cost_load_reg(x,y) 2
+#define cost_save_reg(x,y) 2
+#define cost_pushpop_reg(x) 3
+
+/* size of buffer for asm-output, this can be used to do
+   peephole-optimizations of the generated assembly-output */
+#define EMIT_BUF_LEN 1024 /* should be enough */
+/* number of asm-output lines buffered */
+#define EMIT_BUF_DEPTH 4
+
+/*  We have no asm_peephole to optimize assembly-output */
+#define HAVE_TARGET_PEEPHOLE 0
+
+/* we do not have a mark_eff_ics function, this is used to prevent
+   optimizations on code which can already be implemented by efficient
+   assembly */
+#undef HAVE_TARGET_EFF_IC
+
+/* we only need the standard data types (no bit-types, different pointers
+   etc.) */
+#undef HAVE_EXT_TYPES
+#undef HAVE_TGT_PRINTVAL
+
+/* we do not need extra elements in the IC */
+#undef HAVE_EXT_IC
+
+/* we do not use unsigned int as size_t (but unsigned long, the default) */
+#undef HAVE_INT_SIZET
+
+/* we need register-pairs */
+##define HAVE_REGPAIRS
+
+
+/* do not create CONVERT ICs from integers smaller than int to floats */
+#define MIN_INT_TO_FLOAT_TYPE INT
+
+/* do not create CONVERT ICs from floats to ints smaller than int */
+#define MIN_FLOAT_TO_INT_TYPE INT
+
+/* do not create CONVERT_ICs from floats to unsigned integers */
+#define AVOID_FLOAT_TO_UNSIGNED 1
+
+/* do not create CONVERT_ICs from unsigned integers to floats */
+#define AVOID_UNSIGNED_TO_FLOAT 1
diff --git a/machines/falco16/machine.c b/machines/falco16/machine.c
new file mode 100755
index 0000000..91ada14
--- /dev/null
+++ b/machines/falco16/machine.c
@@ -0,0 +1,2470 @@
+/* 
+   FALCO16 v3
+*/                                                                             
+
+/* TO DO
+
+- If a FREEREG follows an IC for Q1, the register can be used as temporary.
+e.g if we get a = R0 + c, and there's a FREEREG R0 following the IC, we can generate
+add r0, [c]
+mov [a], r0
+instead of
+mov r1, r0
+add r1, [c]
+mov [a], r1
+
+-- floating point capability must also be implemented
+
+- data alignement doesn't work, g1 should be aligned below.
+-- Is this supposed to be handled by the assembler?
+char global = 4;
+int g1 = 5;
+
+-- conditional branching for LONG works, but temporary register handling is not ideal.
+   Register are loaded more than required.
+
+-- inline optimization must be done, e.g shift by const, mul/div by 2
+
+-- call ptr not implemented.
+
+-- register parameter passing
+
+-- 1arg operation are currently only using reg arguments
+
+-- could take advantage of [reg+ofs] addressing mode by combining IC
+
+-- IRQs should only save registers which are actually used, in case of function call all regs must be saved
+-- implement "naked" keyword for RTOS use.
+
+-- right now lib_mov is done by messing with the IC operands changing them into pointers. It is probably better to
+   use ptr_push instead of messign around with val_push.
+
+-- must update arg_push to support double, long long and such, not using more temperary registers
+
+-- compare with KONST not correct when KONST = maxint
+
+*/
+
+#include "supp.h"
+#include "vbc.h"
+
+//static char FILE_[]=__FILE__;
+
+/*  Public data that MUST be there.                             */
+
+/* Name and copyright. */
+char cg_copyright[]="falco16_v3 code generator v0.1 by Daniel Schoch";
+
+// command line
+//--------------
+/*  Commandline-flags the code-generator accepts:
+    0: just a flag
+    VALFLAG: a value must be specified
+    STRINGFLAG: a string can be specified
+    FUNCFLAG: a function will be called
+    apart from FUNCFLAG, all other versions can only be specified once */
+int g_flags[MAXGF] = {VALFLAG, VALFLAG, VALFLAG};
+
+/* the flag-name, do not use names beginning with l, L, I, D or U, because
+   they collide with the frontend */
+char *g_flags_name[MAXGF]={"regs", "rsave", "rtmp"};
+/* Description of command line options:
+regs=<val>
+DEFAULT = 6
+Specify the number of registers to use. Must be >=3 and <= 14.
+The value should match the actual CPU implementation, the default is 6.
+Values < 6 don't make much practical sense since there won't be
+enough registers available for efficient code generation.
+
+rsave=<val>
+DEFAULT = automatic
+0 <= val <= regs-rtmp
+Specify the number of non-scratch registers to use.
+Non-scratch registers are registers that are saved across
+function calls. They are used for efficient register
+variable implementation.
+
+rtmp=<val>
+DEFAULT = 0
+0 <= val <= 3
+Specify the number of temporary registers to reserve.
+Temporary registers are used by the code generator.
+In situation where there is no free register is available
+a register must be saved and restored.
+
+/* the results of parsing the command-line-flags will be stored here */
+union ppi g_flags_val[MAXGF];
+
+
+
+// data types
+//======================
+
+/*  CHAR_BIT for the target machine.                            */
+zmax char_bit;
+
+/* Typenames (needed because of HAVE_EXT_TYPES). */
+char *typname[MAX_TYPE+1];
+
+/*  Alignment-requirements for all types in bytes.              */
+zmax align[MAX_TYPE+1];
+
+/*  Alignment that is sufficient for every object.              */
+zmax maxalign;
+
+/*  sizes of the basic 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];
+
+// registers
+//==========================
+
+/*  Names of all registers. will be initialized in init_cg(),
+    register number 0 is invalid, valid registers start at 1 */
+char *regnames[MAXR+1];
+
+/*  The Size of each register in bytes.                         */
+zmax regsize[MAXR+1];
+
+/*  Specifies which registers may be scratched by functions.    */
+int regscratch[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 the priority for the register-allocator, if the same
+   estimated cost-saving can be obtained by several registers, the
+   one with the highest priority will be used */
+int reg_prio[MAXR+1];
+
+/*  a type which can store each register. */
+struct Typ *regtype[MAXR+1];
+
+/* an empty reg-handle representing initial state */
+struct reg_handle	empty_reg_handle = {0, 0};
+
+
+/****************************************/
+/*  Private data and functions.         */
+/****************************************/
+
+#define ISCOMPOSITE(t)	(ISARRAY(t) || ISSTRUCT(t) || ISUNION(t))
+
+// number of registers to use, this can be a ny value from 3 to 14.
+// A value < 6 is not recommended as it does not leave any registers for
+// efficient code generation.
+// The default is 6.
+int nregs;
+
+// register names
+#define REG_FLAGS	1
+#define REG_SP		2
+#define REG_R0		3
+#define REG_R1		4
+#define REG_R2		5
+#define REG_R3		6
+#define REG_R4		7
+#define REG_R5		8
+#define REG_R6		9
+#define REG_R7		10
+#define REG_R8		11
+#define REG_R9		12
+#define REG_R10		13
+#define REG_R11		14
+#define REG_R12		15
+#define REG_R13		16
+
+// register usage tracking system
+// Allocated by ALLOCEG IC
+#define TRACK_ALLOCREG	1
+// used by IC, not available as temporary
+#define TRACK_IC		2
+// allocated as temporary by tracker
+#define TRACK_TMP		4
+// saved 
+#define TRACK_SAVED		8
+// not usable as indicated by CPU register layout
+#define TRACK_OFFLIMITS		16
+// dedicated temporary register
+#define TRACK_DEDICATED		32
+// bits indicating register is used and cannot be used no matter what
+#define TRACK_NOGO		(TRACK_IC | TRACK_TMP | TRACK_OFFLIMITS)
+int track_status[MAXR+1];
+
+// We provide 3 slots for temporary registers.
+// In here we keep track if which slot contains which register.
+#define TRACK_SLOTS		3
+int track_slot[TRACK_SLOTS];
+
+/* used to initialize regtyp[] */
+static struct Typ ltyp = { INT };
+
+/* macros defined by the backend */
+// extended data types attribute strings
+#define EXTDATA_INTERRUPT	"interrupt"
+
+static char 		*marray[] = {
+   "__FALCO16__",
+   "__interrupt(x)=__vattr(\"interrupt(\"#x\")\")",
+   0
+};
+
+/* sections */
+#define SEC_TEXT	0		// code
+#define SEC_RODATA	1		// constant data
+#define SEC_DATA	2		// initialized data
+#define SEC_BSS		3		// data initialized to 0
+#define SEC_VECTOR	4		// irq vectors
+static int		section = -1;
+static char 		*sec_textname = "code",
+  			*sec_rodataname = "const",
+  			*sec_dataname = "idata",
+  			*sec_bssname = "zdata",
+  			*sec_vectorname = "vector";
+
+/* assembly-prefixes for labels and external identifiers */
+static char 		*label_prefix = "p";
+static char		*ident_prefix = "_";
+static int			label_count;
+
+
+// assemly data storage strings
+static char 		*dct[] = {"", "db", "dw", "dw", "dd", "dd", "dd", "dd", "dd"};
+
+
+static long		loff;
+static long		stackoffset;
+static int		newobj;
+
+
+static long pof2(zumax x)
+/*  Yields log2(x)+1 oder 0. */
+{
+   zumax	p;
+   int		ln = 1;
+    
+   p = ul2zum(1UL);
+   while (ln <= 32 && zumleq(p, x)) {
+      if (zumeqto(x, p)) return ln;
+      ln++; p = zumadd(p, p);
+   }
+   return 0;
+}
+
+static long const_get(struct obj *x, int typ, int n)
+{
+   long	       ret;
+   
+   eval_const(&x->val, typ);
+   ret = (vmax >> (n * char_bit)) & 0xffff;
+   
+   return ret;
+}   
+
+static long ofs_get(struct obj *x)
+{
+   long	    ret;
+   
+   ret = 0;
+   if (x->flags & VAR) {
+      if (x->v->offset < 0) {
+         ret = (long)(loff-(x->v->offset+2)+(x->val.vmax))-stackoffset+2;
+      } else {
+         ret = (long)((x->v->offset)+(x->val.vmax)-stackoffset);
+      }
+   }  
+   return ret;
+}
+
+
+static void emit_object(FILE *f, struct obj *x, int n, int typ)
+{
+   long		ofs;
+
+// calculate offset into stack
+   ofs = ofs_get(x);
+
+// access mode
+   eval_const(&x->val, typ);
+
+   if (x->flags & REG) {
+      if (x->flags & DREFOBJ) {
+// register pointer '[reg+ofs]'
+         emit(f, "[%s+%ld]", regnames[x->reg], n);
+      } else {
+// register 'reg'
+         emit(f, "%s", regnames[x->reg]);
+      }
+   } else if (x->flags & KONST) {
+      if (x->flags & VARADR) {
+// This is the special case for which the address of a constant must be generated.
+// KONST| VARADR is never generated by the front-end, but it's a modified
+// object by the back-end. The address of a constant is used for FLOAT/DOUBLE
+// library call operations involving a constant. An address to a constant is generated by
+// placing the constant into section SEC_RODATA and generating a pointer to
+// the object.
+// NOT COMPLETE, must have some kind of konst counter.
+// 1st nject konst into ROM section         
+         emit(f, "__KONST_");
+      } else if (x->flags & DREFOBJ) {
+// constant address, e.g. mov [123], r0
+         emit(f, "[%ld]", const_get(x, typ, n));      
+      } else {
+// regular KONST value
+         emit(f, "%ld", const_get(x, typ, n));
+      }
+   } else if (x->flags & VAR) {
+// REGULAR VARIABLE ACCESS      
+      if (isauto(x->v->storage_class)) {
+         if (x->flags & VARADR) {
+// this is a special case not generated by the front-end, it's a modified object
+// by the back end needing to generate the address of a auto variable.
+// This is used by 'ptr_push'. What eventually must be generated is
+// mov reg, sp
+// add reg, ofs+n
+// Since this is the emit_object function we only generate sp here, the
+// add reg, ofs+n must be generated by the callee.
+            emit(f, "sp");
+         } else {
+// stack based value '[sp+ofs]'      
+            emit(f, "[sp+%ld]", (long)ofs + n);
+         } 
+      } else if (isextern(x->v->storage_class)) {
+         if (x->flags & VARADR) {
+// address of global variable
+            emit(f, "%s%s+%ld", ident_prefix, (long)x->v->identifier, (long)x->val.vmax + n);
+         } else {
+// value of global '[ident+ofs]'        
+            emit(f, "[%s%s+%ld]", ident_prefix, (long)x->v->identifier, (long)x->val.vmax + n);
+         }
+      } else if (isstatic(x->v->storage_class)) {
+         if (x->flags & VARADR) {
+// address of static variable         
+            emit(f, "%s%ld+%ld", label_prefix, (long)x->v->offset, (long)x->val.vmax + n);
+         } else {
+// value of static variable         
+            emit(f, "[%s%ld+%ld]", label_prefix, (long)x->v->offset, (long)x->val.vmax + n);
+         }
+      } else terror("-- emit_object: unexpected storage class");
+   } else {   
+      terror("-- emit_object: unexpected access mode");
+   }  
+}
+
+/*
+Load a temporary ptr register to be used by the main emit_load
+function.
+returns 1, if code was generated to load the pointer.
+returns 0, if no code was necessary since no temporary ptr is required.
+*/
+static int emit_tmpptr(FILE *f, struct obj *x, int n)
+{
+   struct AddressingMode *am;
+   char		*regptr_name;
+   int		ret;
+
+   ret = 0;
+   am = x->am;
+   if (am && am->regptr) {
+      ret = 1;
+      regptr_name =  regnames[x->am->regptr];         
+      if (n == 0) {
+	 emit(f, "\tmov\t%s, ", regptr_name);
+         emit_object(f, x, 0, POINTER);
+	 emit(f, "\n");
+      } else {
+	  //  emit(f, "\tadd\t%s, %d\n", regptr_name, n);
+      }    
+   }
+   return ret;
+}
+
+
+// Generate code to perform a given operation.
+// The code generated is:
+//    op  t, s
+// typ = operand type (e.g CHAR, POINTER, INT ...)
+// n   = the offset when dealing with multi-world objects (e.g long, float)
+// EITHER t OR s MUST BE A REGISTER!
+// For the non-register operand, temporaries are used and loaded
+// according to am-data.
+static void emit_op(FILE *f, struct obj *t, struct obj *s, int typ, int n, char *op)
+{
+   long		ofs;
+   char		*mode;
+
+// calculate offset into stack
+   ofs = ofs_get(t);
+
+// determine access mode (8-bit or 16-bit instruction)
+   mode = "";
+   if (sizetab[typ&NQ] == 1) mode = ".8";
+
+   if (emit_tmpptr(f, s, n)) {
+// we use a temporary pointer and it's loaded in register s->am->regptr
+// Now we have to generate the code to load the data using the temporary pointer.      
+      emit(f, "\t%s%s\t%s, [%s+%d]\n", op, mode, regnames[t->reg], regnames[s->am->regptr], n);      
+   } else if (emit_tmpptr(f, t, n)) {
+// get value into target register
+      emit(f, "\t%s%s\t[%s+%d], %s\n", op, mode, regnames[t->am->regptr], n, regnames[s->reg]);      
+   } else {
+      emit(f, "\t%s%s\t", op, mode);
+      emit_object(f, t, n, typ);
+      emit(f, ", ");
+      emit_object(f, s, n, typ);
+      emit(f, "\n");
+   }      
+}
+
+// Generate register loading code in the following format:
+//    op  reg, x
+// Meaning it is always code generated, which loads into a register.
+// typ = operand type (e.g CHAR, POINTER, INT ...)
+// n   = the offset when dealing with multi-world objects (e.g long, float)
+static void emit_load(FILE *f, int reg, struct obj *s, int typ, int n, char *op)
+{
+   struct obj	*x;
+   int		ofs;
+
+// if target register is blank, we quit
+   if (reg == 0) return;
+
+   x = mymalloc(sizeof(struct obj));
+
+// build a target register object
+   x->flags = REG;
+   x->reg = reg;
+   x->dtyp = 0;
+   x->v = 0;
+   x->am = 0;
+
+// generate operation
+   emit_op(f, x, s, typ, n, op);
+// we have to take care of the speical case of address of auto variable
+   if ((s->flags & (VAR|VARADR)) == (VAR|VARADR)) {
+      if (isauto(s->v->storage_class)) {
+// calculate offset into stack
+         ofs = ofs_get(s) + n;
+         if (ofs) {       
+	 emit(f, "\tadd\t%s, %d\n", regnames[reg], ofs);
+         } 
+      }
+   }
+
+   myfree(x);
+}
+ 
+// Generate the following code:
+//    mov t, reg
+// typ = operand type (e.g CHAR, POINTER, INT ...)
+// n   = the offset when dealing with multi-world objects (e.g long, float)
+static void emit_store(FILE *f, struct obj *t, int reg, int typ, int n)
+{
+   struct obj	*x;
+
+// if source register is blank, we quit
+   if (reg == 0) return;
+
+   x = mymalloc(sizeof(struct obj));
+
+// build a source register object
+   x->flags = REG;
+   x->reg = reg;
+   x->dtyp = 0;
+   x->v = 0;
+   x->am = 0;
+
+// generate operation
+   emit_op(f, t, x, typ, n, "mov");
+
+   myfree(x);
+}
+
+void am_alloc(struct obj *x)
+{
+// if no object, return
+   if (x == 0) return;
+// if already allocated, return
+   if (x->am) return;
+
+   x->am = mymalloc(sizeof(struct AddressingMode));
+   x->am->regptr = 0;
+   x->am->regval[0] = 0;
+   x->am->regval[1] = 0;
+}
+
+// Compare if 2 objects are the same.
+int obj_eq(struct obj *x1, struct obj *x2)
+{
+   int		ret;
+
+// we assume the objects are equal to start with
+   ret = 1;
+
+   if (x1==0 || x2==0) {
+      ret = 0;
+   } else {
+      if (x1->flags != x2->flags) ret = 0;
+      if (x1->reg != x2->reg) ret = 0;
+   }
+
+   return ret;
+}
+
+/*
+Initialize register tracking system.
+The tracking systemis is used to keep track of what register is used and holds
+what at any given time. Depending on availability, temporary registers can be
+allocated with best efficiency.
+*/
+static void track_init(void)
+{
+   int		i;
+
+// pre-fill
+   for(i = 1; i <= MAXR; i++) {
+// clear all unnecessary bits
+      track_status[i] &= (TRACK_OFFLIMITS | TRACK_DEDICATED);
+   }
+
+// all slots are empty at the beginning.
+   for (i = 0; i < TRACK_SLOTS; i++) {
+// indicate slot is not used      
+     track_slot[i] = 0;
+   }
+}
+
+
+// Mark any register used by the IC
+static void track_obj_claim(struct obj *x)
+{
+// analyze object and flag already used registers as 'no-go'
+   if (x && (x->flags & REG)) {
+      track_status[x->reg] |= TRACK_IC;
+   }
+}
+
+/* 
+Allocate the required temporary registers
+to be able to generate code for the given IC.
+Each operand gets an 'am' datastructure, which
+is filled with the temporary registers to use.
+
+And it works like this
+z   =   q1 <op> q2
+ptr     ptr     ptr
+val     val
+
+There's only one ptr that satisfies all three operand.
+There's only one val that is used for both q1 and z.
+
+So for example in if we have q1(ptr, val) that means:
+Use register ptr to get q1 into register val.
+
+Or for z(ptr, val): Use register ptr to store register val
+to the target location.
+*/
+
+
+/*
+0. determine if we need to free previously allocated temps
+a. we do this if we got a branch or if the current IC uses any temp reg
+1. determine how many temporaries we need
+2. check if we can reuse previously reserved temps
+3. reserve temps if necessary (and make it smart, pick the ones that are not used in the next IC)
+*/
+
+static int track_alloc(FILE *f)
+{
+   int		reg;
+   int		i;
+   int		save;
+
+   reg = 0;
+   save = 0;
+// try to find a register
+// If we can't find one, there's some serious issue.
+   for (i = 1; i < MAXR+1; i++) {
+      if ((track_status[i] & (TRACK_NOGO|TRACK_ALLOCREG|TRACK_SAVED)) == TRACK_ALLOCREG) {
+// found a register, but it must be saved, keep looking maybe
+// we find a better one, only use this if we haven't found anything useful yet
+         if (reg == 0) {
+            reg = i;
+            save = 1;
+         }  
+      } else if ((track_status[i] & (TRACK_NOGO|TRACK_ALLOCREG|TRACK_SAVED)) == (TRACK_ALLOCREG|TRACK_SAVED)) {
+// found a register, it's in use by ALLOCREG, but it has already been saved
+// We use it and quit.
+         reg = i;
+	 save = 0;
+	 break;
+      } else if ((track_status[i] & (TRACK_NOGO|TRACK_ALLOCREG|TRACK_SAVED|TRACK_DEDICATED)) == 0) {
+// found an unallocated register which is not a dedicated temp, we use it
+         reg = i;
+	 save = 0;
+	 break;
+      } else if ((track_status[i] & (TRACK_NOGO|TRACK_DEDICATED)) == TRACK_DEDICATED) {
+// found a dedicated temporary, we could use it, but we try to find a better one
+         reg = i;
+	 save = 0;
+      }
+   }
+   if (reg == 0) terror("-- track_alloc: can't find temporary register");
+
+// flag register as taken
+   track_status[reg] |= TRACK_TMP;
+   emit(f, "; allocate temporary: %s\n", regnames[reg]);
+   if (save) {
+      track_status[reg] |= TRACK_SAVED;
+// find an unused storage slot
+      for (i = 0; i < TRACK_SLOTS; i++) {
+         if (!track_slot[i]) break;
+      }
+      if (i >= TRACK_SLOTS) terror("--track_alloc: out of storage slots");
+      track_slot[i] = reg;      
+      emit(f, "\tmov\t[_TSLOT+%d], %s\n", i*2, regnames[reg]);
+   }
+
+   return reg;
+}
+
+
+/*
+Temporary register tracking and assignement.
+*/
+/*
+Check if access to object x requires temporary registers.
+Allocate all required temporary registers.
+*/
+static void track_obj(FILE *f, struct obj *x, int typ)
+{
+   int		i;
+   int		reg, reg2;
+   int		need_tmpval;
+   int		size;
+
+
+// object must have 'am' structure.
+   am_alloc(x);
+
+// determine if we need to free previously allocated temporaries
+// claim registers used by object  
+   track_obj_claim(x);
+// see if one of them was allocated, and free it if necessary
+   for (i = 0; i < TRACK_SLOTS; i++) {
+      reg = track_slot[i];
+      if ((track_status[reg] & (TRACK_IC|TRACK_SAVED)) == (TRACK_IC|TRACK_SAVED)) {
+         track_status[reg] &= ~TRACK_SAVED;
+         track_slot[i] = 0;
+         emit(f, "; restore temporary\n");
+         emit(f, "\tmov\t%s, [_TSLOT+%d]\n", regnames[reg], i*2);
+      }
+   }
+
+// determine how many temporary registers we need
+   need_tmpval = 1;
+   if (x && (x->flags & (REG|DREFOBJ)) == REG) need_tmpval = 0;
+
+   if (need_tmpval) {
+// we need temporary value register, allocate one
+      reg = track_alloc(f);    
+// In case this is a 32-bit operand we need 2 temporaries
+      size = sizetab[typ&NQ];     
+      reg2 = 0;
+      if (size == 4) {
+         reg2 = track_alloc(f);
+      }
+      x->am->regval[0] = reg;
+      x->am->regval[1] = reg2;
+   }
+
+// next step is to check if pointer memory access requires a register
+   if (x && (x->flags & (DREFOBJ | VAR | REG)) == (DREFOBJ | VAR)) {
+      reg = track_alloc(f);
+      x->am->regptr = reg;
+   }
+}
+
+/*
+Check the IC for temporary register requirements.
+Allocate all required temporaries and save them if required.
+*/
+static void track_ic(FILE *f, struct IC *p) 
+{
+   struct obj	*z;
+   struct obj	*q1;
+   struct obj	*q2;
+   int		i;
+   int		reg, reg2;
+   int		need_tmpval;
+   int		size;
+   int		code;
+
+// get objects
+   z = &p->z;
+   q1 = &p->q1;
+   q2 = &p->q2;
+
+// get instruction code
+   code = p->code;
+
+// each object must have 'am' structure.
+   am_alloc(z);
+   am_alloc(q1);
+   am_alloc(q2);
+
+
+// determine if we need to free previously allocated temporaries
+// claim registers used by IC   
+   track_obj_claim(z);
+   track_obj_claim(q1);
+   track_obj_claim(q2);
+
+// see if one of them was allocated, and free it if necessary
+   for (i = 0; i < TRACK_SLOTS; i++) {
+      reg = track_slot[i];
+      if ((track_status[reg] & (TRACK_IC|TRACK_SAVED)) == (TRACK_IC|TRACK_SAVED)) {
+         track_status[reg] &= ~TRACK_SAVED;
+	 track_slot[i] = 0;
+	 emit(f, "; restore temporary\n");
+	 emit(f, "\tmov\t%s, [_TSLOT+%d]\n", regnames[reg], i*2);
+      }
+   }
+
+// determine how many temporary registers we need
+   need_tmpval = 1;
+   if (z && (z->flags & (REG|DREFOBJ)) == REG) need_tmpval = 0;
+   if (q1 && (q1->flags & (REG|DREFOBJ)) == REG) need_tmpval = 0;
+   if (q2 && (q2->flags & (REG|DREFOBJ)) == REG) need_tmpval = 0;
+
+// if target Z is NOT the same as Q1 we will always need a temporary   
+   if (code == ASSIGN || code == CONVERT) {
+      ;
+   } else if (code == COMPARE) {
+// in case of COMPARE we need a temporary if Q1 == KONST
+      if (q1 && (q1->flags & KONST) == KONST) need_tmpval = 1;
+   } else {
+      if (!obj_eq(z, q1)) {
+         need_tmpval = 1;
+      }
+   }
+
+   if (need_tmpval) {
+      reg = 0;
+// check if we can use target register as temporary
+// We can do so if Q2 is not the same as Z      
+      if (z) {   
+         if (((z->flags & (REG|DREFOBJ)) == REG) && !obj_eq(z, q2)) {
+            reg = z->reg;
+	    track_status[reg] |= TRACK_TMP;
+         } else {
+// we need temporary value register, allocate one
+            reg = track_alloc(f);
+         }
+// In case this is a 32-bit operand we need 2 temporaries
+         size = sizetab[ztyp(p)&NQ];     
+         reg2 = 0;
+         if (size >= 4) {
+            reg2 = track_alloc(f);
+         }
+         z->am->regval[0] = reg;
+         z->am->regval[1] = reg2;
+      }
+// Q1 need the same temp as Z, but maybe only 16-bit
+      if (q1) {
+         if (!reg) {
+	    reg = track_alloc(f);
+         }
+         q1->am->regval[0] = reg;
+         if (sizetab[q1typ(p)&NQ] <= 2) {
+            reg2 = 0;
+         }
+        q1->am->regval[1] = reg2;
+      }
+   }
+
+// next step is to check if pointer memory access requires a register
+   reg = 0; 
+   if (z && (z->flags & (DREFOBJ | VAR | REG)) == (DREFOBJ | VAR)) {
+      if (!reg) reg = track_alloc(f);
+      z->am->regptr = reg;
+   } 
+   if (q1 && (q1->flags & (DREFOBJ | VAR | REG)) == (DREFOBJ | VAR)) {
+      if (!reg) reg = track_alloc(f);
+      q1->am->regptr = reg;
+   } 
+   if (q2 && (q2->flags & (DREFOBJ | VAR | REG)) == (DREFOBJ | VAR)) {
+      if (!reg) reg = track_alloc(f);
+      q2->am->regptr = reg;
+   }
+
+}
+
+static void track_release(void)
+{
+   int		i;
+
+   for (i = 1; i <= MAXR; i++) {
+      track_status[i] &= ~(TRACK_TMP|TRACK_IC);
+   }
+}
+
+/*
+Restores all saved temporary registers.
+This must be executed before any branch, call
+or function exit.
+*/
+static void track_restore(FILE *f)
+{
+   int		i;
+
+   track_release();
+   for (i = 0; i < TRACK_SLOTS; i++) {
+      if (track_slot[i]) {
+         track_status[track_slot[i]] &= ~(TRACK_SAVED);
+	 emit(f, "\tmov\t%s, [_TSLOT+%d]\n", regnames[track_slot[i]], i*2);
+	 track_slot[i] = 0;
+      }
+   }
+}
+// same as above, but don't clear TRACK_SAVED and don't release the temps.
+// This is used in branch instructions.
+static void track_restore2(FILE *f)
+{
+   int		i;
+
+   for (i = 0; i < TRACK_SLOTS; i++) {
+      if (track_slot[i]) {
+	 emit(f, "\tmov\t%s, [_TSLOT+%d]\n", regnames[track_slot[i]], i*2);
+      }
+   }
+}
+
+
+
+/* generates the function entry code */
+static void cd_function_entry(FILE *f, struct Var *v, long offset)
+{
+   int		i;
+
+   if (section != SEC_TEXT) {
+      emit(f, "\n\tsection\t%s\n", sec_textname);
+      section = SEC_TEXT;
+   }
+
+   if (v->storage_class == EXTERN) emit(f,"\tpublic\t%s%s\n", ident_prefix, v->identifier);
+   emit(f,"%s%s:\n", ident_prefix,v->identifier);
+
+   if (v->vattr && strstr(v->vattr, EXTDATA_INTERRUPT)) {     
+// interrupt service routine
+      emit(f, "\tpush\tflags\n");
+      for (i = REG_R0; i < REG_R0+nregs; i++) {
+         emit(f, "\tpush\t%s\n", regnames[i]);
+      }
+   }   
+            
+// allocate required stack
+   if (offset > 0) emit(f,"\tsub\tsp, %ld\n", offset);
+
+// store non-scratch register used in function
+   for (i = 1; i <= MAXR; i++) {
+      if (!regsa[i] && !regscratch[i] && regused[i]) {
+         emit(f, "\tpush\t%s\n", regnames[i]);
+// adjust stack offset
+         stackoffset -= 2;
+      }
+   }
+}
+
+/* generates the function exit code */
+static void cg_function_exit(FILE *f, struct Var *v, long offset)
+{
+   int		i;
+
+// restore any saved temporary registers
+// I don't think this is necessary as long as we don't have global register variables.
+// What does vbcc do? Global regs?
+   track_restore(f);
+
+// restore non-scratch register used in function
+   for (i = MAXR; i >= 1; i--) {
+      if (!regsa[i] && !regscratch[i] && regused[i]) {
+         emit(f, "\tpop\t%s\n", regnames[i]);
+         stackoffset += 2;
+      }
+   }
+
+   if (offset > 0) {
+      emit(f,"\tadd\tsp, %ld\n", offset);
+   }
+   
+   if (v->vattr && strstr(v->vattr, EXTDATA_INTERRUPT)) {
+// interrupt service routine
+      for (i = REG_R0+nregs-1; i >= REG_R0; i--) {
+         emit(f, "\tpop\t%s\n", regnames[i]);
+      }
+      emit(f, "\tpop\tflags\n");
+      emit(f, "\tiret\n\n");
+   } else {   
+      emit(f, "\tret\n\n");
+   }
+}
+
+/* 
+some blurp:
+There's an IC, which contains a target(z), and 2 sources(q1 and q2).
+Macros ztyp, q1typ and q2typ return the type of the operands
+e.g. (char, int, short, double, struct, array....).
+Also contains the qualifiers UNSIGNED, CONST
+Most of the time it's the same for all operands. Exceptions are
+CONVERT or adding int to pointer.
+Using NU and NQ will remove qualifiers and only leave base type.
+
+Of interest are:
+ISPOINTER, ISINT, ISFLOAT, ISFUNC, ISSTRUCT, ISUNION, ISARRAY,
+ISSCALAR, ISARITH
+
+Each operand can be one of the following:
+----------------------------------------
+KONST			constant number
+KONST|DREFOBJ		absolute pointer
+REG			register
+VAR			variable (can be auto, register, static, extern)
+VAR|REG			a variable which was put in a register
+REG|DREFOBJ		indirect [reg]
+VAR|DREFOBJ		indirect [var]
+VAR|REG|DREFOBJ		indirect [reg], where the register is a variable
+VAR|VARADR		address of a variable
+
+Temporaries generated by the compiler don't have the VAR flag set.
+It is only a VAR if it is so in the source code.
+
+Each variable then has information regarding the storage class,
+so each VAR is on of the following:
+AUTO
+REGISTER
+STATIC
+EXTERN
+
+Macros of interest:
+isauto, isextern, isstatic.
+
+*/
+/* val_push
+Pushing the value of the object onto the stack.
+*/
+static void val_push(FILE *f, struct obj *x, int typ)
+{
+// handle required temporaries	   
+   track_obj(f, x, typ); 
+
+   emit(f, "; push val\n");
+   
+// Load Q1 into temporary register val if necessary.
+// Automatically use temporary x->am->regptr if necessary.
+   emit_load(f, x->am->regval[0], x, typ, 0, "mov");
+   emit_load(f, x->am->regval[1], x, typ, 2, "mov");
+
+// emit operation
+  if (x->am->regval[1]) {
+      emit(f, "\tpush\t%s\n", regnames[x->am->regval[1]]);
+      stackoffset -= 2;
+   }
+   if (x->am->regval[0]) {
+// operation is performed on temporaries
+      emit(f, "\tpush\t%s\n", regnames[x->am->regval[0]]);
+      stackoffset -= 2;
+    } else {
+// operation is performed directly on target (z == q1 for this to work)
+      emit(f, "\tpush\t%s\n", regnames[x->reg]);
+      stackoffset -= 2;
+   }
+
+// release temporaries
+   track_release();
+}
+/* ptr_push
+Pushing the ptr to the object onto the stack.
+In case the object is a KONST, a copy of the KONST is made
+in romsection and a pointer to the constant is pushed.
+WARNING WARNING WARNING
+This function MODIFIES the object *x.
+*/
+static void ptr_push(FILE *f, struct obj *x)
+{
+// handle required temporaries	   
+   track_obj(f, x, POINTER); 
+
+   emit(f, "; push ptr to object\n");
+   
+// modify the IC such that we can generate code from it
+
+// what we should do here is: if DREFOBJ is set, clear it. If DREFOBJ is not set, set VARADR.
+      if (x->flags & DREFOBJ) {
+         x->flags &= ~DREFOBJ;
+     } else {    
+	 x->flags |= VARADR;
+      }
+      x->dtyp = POINTER;
+
+// Load object into temporary register val if necessary.
+// Automatically use temporary x->am->regptr if necessary.
+   emit_load(f, x->am->regval[0], x, POINTER, 0, "mov");
+
+// emit operation
+   if (x->am->regval[0]) {
+// operation is performed on temporaries
+      emit(f, "\tpush\t%s\n", regnames[x->am->regval[0]]);
+      stackoffset -= 2;
+    } else {
+// operation is performed directly on target (z == q1 for this to work)
+      emit(f, "\tpush\t%s\n", regnames[x->reg]);
+      stackoffset -= 2;
+   }
+
+// release temporaries
+   track_release();
+}
+
+/*
+Get the object from the stack. It is assumed the object is
+located at [sp]. It is subsequently transfered to x
+[sp] --> x
+This function can be implemented either using 'pop' or using '[sp+xx]'.
+Either one has advantage or disadvantage, also depending on CPU
+implementation.
+*/
+void val_pop(FILE *f, struct obj *x, int typ)
+{
+   emit(f, "; pop val\n");
+
+// handle required temporaries	   
+   track_obj(f, x, typ); 
+   
+// Load [sp] value into temporary register val if necessary.
+   if (x->am->regval[0]) {
+// operation is performed on temporaries
+      emit(f, "\tpop\t%s\n", regnames[x->am->regval[0]]);
+      stackoffset += 2;
+      if (x->am->regval[1]) {
+         emit(f, "\tpop\t%s\n", regnames[x->am->regval[1]]);
+         stackoffset += 2;
+      }
+   } else {
+// operation is performed directly on target (z == q1 for this to work)
+      emit(f, "\tpop\t%s\n", regnames[x->reg]);
+      stackoffset += 2;
+   }
+
+// store to target
+   emit_store(f, x, x->am->regval[0], typ, 0);
+   emit_store(f, x, x->am->regval[1], typ, 2);
+
+// release temporaries
+   track_release();
+}
+
+/*
+Library call for ALU functions.
+*/
+static void lib_alu(FILE *f, struct IC *p, char *call)
+{
+   char		*modifier;
+   char		*dtype;
+   int		size;
+
+   // do some checking first
+   if (q1typ(p) != q2typ(p)) terror("--lib_alu: type mismatch");
+
+   modifier = "S";
+   if (q1typ(p) & UNSIGNED) {
+      modifier = "U";
+   }
+
+   switch (q1typ(p)) {
+      case CHAR: 
+         dtype = "I8"; break;
+      case SHORT:
+      case INT:
+         dtype = "I16"; break;
+      case LONG:
+         dtype = "I32"; break;
+      case FLOAT:
+         dtype = "F32"; break;
+      case DOUBLE:
+         dtype = "F64"; break;
+      default:
+         dtype = ""; break;
+         terror("--lib_alu: data type not supported");
+	 break;
+   }
+// handle required temporaries
+// temporary allocation is handled in val_push instead.
+// The idea here is to allocate all required temporaries now,
+// such that the return value can be easily grabbed.
+// This is not implemented right now due to complications.
+//   track_ic(f, p);
+
+// push the spaceholder for the result
+   size = sizetab[ztyp(p)&NQ];
+   if (size <= 2) {
+// stack is 2-byte minimum
+   if (size < 2) size = 2;
+   emit(f, "\tsub\tsp, %d\n", size);
+   stackoffset -= size;
+// Push all arguments
+   val_push(f, &p->q2, q2typ(p));
+   val_push(f, &p->q1, q1typ(p));
+   } else {
+      ptr_push(f, &p->q2);
+      ptr_push(f, &p->q1);
+   }
+   track_restore(f);
+// emit call to library function
+   emit(f, "\tcall\t_%s_%s%s\n", call, modifier, dtype);
+
+// restore stack state
+// use 2*size in case 'val_pop' actually pops,
+// use 3*size in case 'val_pop uses [sp+xx]
+    emit(f, "\tadd\tsp, %d\n", (int)2*size);
+    stackoffset += 2*size;
+
+// last step is to grab the return value
+// Return value is at [sp].
+   val_pop(f, &p->z, ztyp(p));
+
+} 
+
+
+/*
+Library call for mempry copy functions.
+*/
+static void lib_mov(FILE *f, struct IC *p)
+{
+
+// modify the IC such that we can generate code from it      
+   p->q2.flags = KONST;
+
+// Push Q2 (number of bytes to copy)
+   emit(f, "; push array size\n");
+   val_push(f, &p->q2, INT);
+// Push pointer to Q1 (source)
+   emit(f, "; push source pointer\n");
+   ptr_push(f, &p->q1);
+// push pointer to target (Z)
+   emit(f, "; push target pointer\n");
+   ptr_push(f, &p->z);
+
+   track_restore(f);
+// emit call to library function
+   emit(f, "\tcall\t_MOV\n");
+
+// stack cleanup, we should use callee clean-up
+    emit(f, "\tadd\tsp, %d\n", (int)6);
+    stackoffset += 6;
+} 
+/*
+
+*/
+static void cg_assign(FILE *f, struct IC *p)
+{
+   struct obj	*x;
+   int		typ;
+   int		size;
+
+// any struct or array goes to library function
+// anything > 4 bytes goes to library
+// size is only possible with ASSIGN, not CONVERT.
+   if (p->code == ASSIGN) {
+      size = opsize(p);
+      if (size > 4 || ISCOMPOSITE(ztyp(p))) {
+
+         lib_mov(f, p);
+         return;
+      }
+   }
+
+// handle required temporaries   
+   track_ic(f, p);
+
+   // We also get here for CONVERT, so test don't work.
+  // if (q1typ(p) != ztyp(p)) terror(0);
+   emit(f, "; mov\n");
+
+// emit operation
+   typ = q1typ(p);
+   x = &p->q1;
+   if (x->am->regval[0]) {
+// operation is performed on temporaries
+      emit_load(f, x->am->regval[0], x, typ, 0, "mov");
+      emit_load(f, x->am->regval[1], x, typ, 2, "mov");
+   } else {
+// operation is performed directly, no temporaries involved
+      emit_op(f, &p->z, x, typ, 0, "mov");
+   }
+
+// check if this is a CONVERT operation and inject sign extension
+// if necessary.
+   if (p->code == CONVERT) {
+// if Q1 is CHAR we need to blow it up to INT      
+      if (sizetab[q1typ(p) & NQ] == 1) {
+         if (typ & UNSIGNED) {
+// clear high byte            
+            if (p->z.am->regval[0]) {
+	       emit(f, "\tand\t%s, 0xff\n", regnames[p->z.am->regval[0]]);
+            } else {
+	       emit(f, "\tand\t%s, 0xff\n", regnames[p->z.reg]);
+	    }
+         } else {
+// SXT high byte
+            if (p->z.am->regval[0]) {
+               emit(f, "\tsxt.8\t%s\n", regnames[p->z.am->regval[0]]);
+            } else {
+	       emit(f, "\tsxt.8\t%s\n", regnames[p->z.reg]);
+	    }
+	 }
+      }         
+// if Z is LONG we need to blow it up from INT to LONG      
+      if (sizetab[ztyp(p) & NQ] == 4) {      
+         if (typ & UNSIGNED) {
+            emit(f, "\tmov\t%s, 0\n", regnames[p->z.am->regval[1]]);
+         } else {
+            emit(f, "\tmov\t%s, %s\n", regnames[p->z.am->regval[1]], regnames[p->z.am->regval[0]]);
+            emit(f, "\tsxt\t%s\n", regnames[p->z.am->regval[1]]);
+         } 
+      }
+   }
+// emit store if necessary
+   typ = ztyp(p);
+   x = &p->z;
+   emit_store(f, x, x->am->regval[0], typ, 0);
+   emit_store(f, x, x->am->regval[1], typ, 2);
+
+// release temporaries
+   track_release();
+}   
+
+
+static void cg_push(FILE *f, struct IC *p)
+{
+   int		size;
+
+// any object larger than 4 bytes goes to a library function
+   size = opsize(p); // might need to use pushsize here instead of opsize?
+   if (size > 4 || ISCOMPOSITE(q1typ(p))) {
+// allocate required stack
+      emit(f, "\tsub\tsp, %d\n", size);
+      stackoffset -= size;
+
+// Push Z (number of bytes to push)
+      emit(f, "; push array size\n");
+// modify z such that it becomes a KONST      
+      p->z.flags = KONST;
+      val_push(f, &p->z, INT);
+// Push pointer to Q1 (source)
+      emit(f, "; push source pointer\n");
+      ptr_push(f, &p->q1);
+
+// emit call to library function
+      emit(f, "\tcall\t_PUSH\n");
+
+// stack cleanup, we should use callee clean-up
+      emit(f, "\tadd\tsp, %d\n", (int)4);
+      stackoffset += 4;
+      return;
+   }
+// handle required temporaries of 1op instructions	   
+  // track_push(f, p); // this must go, needs to be part of val_push
+
+   val_push(f, &p->q1, q1typ(p));
+
+} 
+
+static void cg_call(FILE *f, struct IC *p) 
+{
+   long		size = pushedargsize(p);
+   long		ofs;
+   
+// calculate offset into stack
+   ofs = ofs_get(&p->q1);
+   
+   emit(f, "; call\n");
+  
+// restore any temporaries
+   track_restore(f);
+
+   if ((p->q1.flags & (VAR|DREFOBJ)) == VAR) {
+// call to label      
+      emit(f, "\tcall\t%s%s\n", ident_prefix, p->q1.v->identifier);
+   } else if ((p->q1.flags & (VAR|DREFOBJ)) == (VAR|DREFOBJ) && p->q1.dtyp == POINTER) {
+      terror("-- call:  pointer argument not yet supported");
+   } else terror("-- call: unexpected call mode\n");   
+   if (size > 0) {
+      emit(f,"\tadd\tsp, %ld\n", size);
+      stackoffset += size;
+   }    
+}
+
+
+static void cg_alu(FILE *f, struct IC *p)
+{
+   struct obj	*x;
+   int		typ;
+   int		c;
+   char		*instr1, *instr2;
+
+   c = p->code;
+   switch (c) {
+      case ADD: instr1 = "add"; instr2 = "addc"; break;
+      case SUB: instr1 = "sub"; instr2 = "subc"; break;
+      case ADDI2P: instr1 = "add"; instr2 = "addc"; break;
+      case SUBIFP: instr1 = "sub"; instr2 = "subc"; break;
+      case OR: instr1 = instr2 = "or"; break;
+      case AND: instr1 = instr2 = "and"; break;
+      case XOR: instr1 = instr2 = "xor"; break;
+      default: instr1 = "xxx"; break;
+   };   
+      
+   emit(f, "; %s\n", instr1);
+
+   // get type of argument
+   typ = ztyp(p);   
+
+// try to get z and q1 the same, if possible
+   switch_IC(p); 
+// handle required temporaries of 2op instructions	  
+   track_ic(f, p);
+
+
+   if (!ISINT(typ) && !ISPOINTER(typ)) terror("-- addsub: unexpected operands");
+ 
+// Load Q1 into temporary register val if necessary.
+// Automatically use temporary x->am->regptr if necessary.
+   x = &p->q1;
+   emit_load(f, x->am->regval[0], x, typ, 0, "mov");
+   emit_load(f, x->am->regval[1], x, typ, 2, "mov");
+
+// emit operation
+   x = &p->z;
+   if (x->am->regval[0]) {
+// operation is performed on temporaries
+      emit_load(f, x->am->regval[0], &p->q2, typ, 0, instr1);
+      emit_load(f, x->am->regval[1], &p->q2, typ, 2, instr2);
+   } else {
+// operation is performed directly on target (z == q1 for this to work)
+      emit_op(f, x, &p->q2, typ, 0, instr1);
+   }
+
+// emit store if necessary
+   x = &p->z;
+   if (x->am->regval[0]) {
+      if (((x->flags & (REG|DREFOBJ)) != REG) && x->reg != x->am->regval[0]) { 
+// only write store if target is not a register or in case it is a register it
+// is not the same as the source.
+         emit_store(f, x, x->am->regval[0], typ, 0);
+         emit_store(f, x, x->am->regval[1], typ, 2);
+      }
+   }
+// release temporaries
+   track_release();
+}                   	 
+
+
+static void cg_lshift(FILE *f, struct IC *p)
+{
+// First we check if we can take a short-cut and don't need to
+// call the library.
+// [not done]
+
+   lib_alu(f, p, "SHL");
+}  
+      
+static void cg_rshift(FILE *f, struct IC *p)
+{
+// First we check if we can take a short-cut and don't need to
+// call the library.
+// [not done]
+
+   lib_alu(f, p, "SHR");
+}        
+        
+
+static void cg_mult(FILE *f, struct IC *p)
+{
+// First we check if we can take a short-cut and don't need to
+// call the library.
+// [not done]
+
+   lib_alu(f, p, "MUL");
+}        
+
+static void cg_div(FILE *f, struct IC *p)
+{
+// First we check if we can take a short-cut and don't need to
+// call the library.
+// [not done]
+
+   lib_alu(f, p, "DIV");
+}        
+
+static void cg_mod(FILE *f, struct IC *p)
+{
+// First we check if we can take a short-cut and don't need to
+// call the library.
+// [not done]
+
+   lib_alu(f, p, "MOD");
+} 
+/*
+modify IC such that we get
+z = q1 xor 0xffff
+*/
+static void cg_komplement(FILE *f, struct IC *p)
+{
+   struct obj	*x;
+
+   emit(f, "; komplement\n");
+
+   p->code = XOR;
+
+// change q2 to const 0
+   x = &p->q2;
+   x->flags = KONST;
+   x->reg = 0;
+   x->dtyp = 0;
+// insert 0xffff
+   gval.vmax = -1;
+   eval_const(&gval, MAXINT);
+   insert_const(&x->val, ztyp(p));
+
+// transfer to alu
+   cg_alu(f, p);
+}    
+
+/*
+modify IC such that we get
+z = 0 - q1
+*/
+static void cg_minus(FILE *f, struct IC *p)
+{
+   struct obj	*x;
+
+   emit(f, "; minus\n");
+
+   p->code = SUB;
+   p->q2 = p->q1;
+
+// change q1 to const 0
+   x = &p->q1;
+   x->flags = KONST;
+   x->reg = 0;
+   x->dtyp = 0;
+// is this the right way of generating a constant?
+   gval.vmax = 0;
+   eval_const(&gval, MAXINT);
+   insert_const(&x->val, ztyp(p));
+
+// transfer to alu
+   cg_alu(f, p);
+
+}    
+
+static void cg_address(FILE *f, struct IC *p)
+{
+   struct obj	*x;
+   int		typ;
+   long		ofs;
+   int		reg;
+   
+// calculate offset into stack
+   ofs = ofs_get(&p->q1);
+
+// handle required temporaries of 1op instructions	   
+   track_ic(f, p);
+
+   emit(f, "; address\n");
+   
+// emit operation
+   typ = ztyp(p);
+   x = &p->z;
+   reg = x->reg;
+   if (x->am->regval[0]) {
+      reg = x->am->regval[0];
+   }
+// emit operation
+   emit(f, "\tmov\t%s, sp\n", regnames[reg]);
+   if (ofs != 0) emit(f, "\tadd\t%s, %ld\n", regnames[reg], ofs);
+
+// emit store if necessary
+   typ = ztyp(p);
+   x = &p->z;
+   if (x->am->regval[0]) {
+      if ((x->flags & (REG|DREFOBJ)) != REG) { 
+// only write store if target is not a register 
+         emit_store(f, x, x->am->regval[0], typ, 0);
+      }
+   }
+// release temporaries
+   track_release();
+}
+
+/*
+modify IC such that we get
+COMPARE q1, 0
+*/
+static void cg_test(FILE *f, struct IC *p)
+{
+   struct obj	*x;
+
+   emit(f, "; test\n");
+
+   p->code = COMPARE;
+
+// change q2 to const 0
+   x = &p->q2;
+   x->flags = KONST;
+   x->reg = 0;
+   x->dtyp = 0;
+// insert 0
+   gval.vmax = 0;
+   eval_const(&gval, MAXINT);
+   insert_const(&x->val, ztyp(p));
+
+}  
+
+/*
+Swap operands q1 <-> q2 of an IC. This is used by the branch IC
+to map the operation to the available comaprisons.
+*/
+static void swap_operands(struct IC *p)
+{
+   struct obj y;
+   y = p->q1;
+   p->q1 = p->q2;
+   p->q2 = y;
+}
+
+static void cg_branch_modify(struct IC *cmp, struct IC *p)
+{
+   int		c;
+   int		q2_inc;
+   int		swap;
+   int		q2_konst;  
+
+   
+// grab the branch instruction
+   c = p->code;
+   
+/*
+In case Q1 == KONST we need to swap operands, however
+this only makes a difference in case Q2 == REG.
+This whole logic here might not be necessary if the front-end
+always puts KONST in Q2. Test seem to confirm this, however for
+the time being we leave the code in.
+*/
+   if (((cmp->q1.flags & (KONST|DREFOBJ)) == KONST) && ((cmp->q2.flags & (REG|DREFOBJ)) == REG)) {
+// swap operands      
+      swap_operands(cmp);
+// modify branch condition to match operand swap
+      switch (c) {
+         case BLT: c = BGT; break;
+         case BGE: c = BLE; break;
+         case BLE: c = BGE; break;
+         case BGT: c = BLT; break;
+      }
+   }
+
+// Check if Q2 is a KONST. If it is we shouldn't swap operands.
+   q2_konst = 0;
+   if ((cmp->q2.flags & (KONST|DREFOBJ)) == KONST) {
+      q2_konst = 1;
+   }
+
+// initialize modification falgs
+   swap = 0;
+   q2_inc = 0;
+
+// decode jump and decide what modifications must be undertaken.
+   switch (c) {
+// equal ==, generate 'je'
+      case BEQ: break;
+// not equal !=, generate 'jne'      
+      case BNE: break;
+// less than '<'
+      case BLT: break;
+// greater equal '>='      
+      case BGE: break;
+// less equal '<=' 
+// This must be changed into BLT or BGE     
+      case BLE:
+	 if (q2_konst) {
+// Q2 is KONST, can't swap operands but must modify the constant
+	    c = BLT;
+	    q2_inc = 1;
+	 } else {
+// must swap operands to map to available comparison instructions
+            c = BGE;
+	    swap = 1;
+	 }   
+	 break;
+// greater than '>'
+      case BGT:
+	 if (q2_konst) {
+// Q2 is KONST, can't swap operands but must modify the constant
+	    c = BGE;
+	    q2_inc = 1;
+	 } else {
+// must swap operands to map to available comparison instructions
+            c = BLT;
+	    swap = 1;
+	 }   
+	 break;
+   }
+
+/* 
+MODIFY IC if neccessary.
+Modification looks like this:
+If q2_inc == 1, we increment KONST q2 by 1.
+If swap == 1, we swap operands.
+Either way, we replace the  exisiting condition code with the new one.
+*/
+   if (swap) swap_operands(cmp);
+   if (q2_inc) {
+// partial constant
+      struct obj *x; 
+// increment Q2
+      x = &cmp->q2;
+// not sure if this is the way I'm supposed to do this
+      eval_const(&x->val, q2typ(cmp));
+      gval.vmax = zmadd(vmax, 1);
+      eval_const(&gval, MAXINT);
+      insert_const(&x->val, q2typ(cmp));
+   }
+// insert new condition code
+   p->code = c;
+}
+
+//static void cg_branch
+
+static void cg_branch(FILE *f, struct IC *p)
+{
+   struct IC	*cmp;
+   int		c;
+// size in bytes   
+   long		size;
+   int		typ;
+   char		*sign;
+// jump target
+// The target in case the condition is satisfied
+   long		target_true;
+// the target in case the condition is violated
+   long		target_false; 
+// partial constant
+   struct obj	*x; 
+   
+      
+   if (q1typ(p) != q2typ(p)) terror(0);
+ 
+   emit(f, "; compare\n");
+   
+
+// try to find compare IC
+   cmp = p->prev;
+   while (cmp && cmp->code == FREEREG) cmp = cmp->prev;
+   if (!cmp || (cmp->code != COMPARE && cmp->code != TEST)) terror("-- cg_branch: compare not found");   
+
+   typ = q1typ(cmp);
+   size = sizetab[typ&NQ];
+
+   if (!ISINT(typ)) terror("-- cg_branch: unexpected object type");
+   
+// get jump target
+   target_true = (long)p->typf;
+   target_false = label_count++;
+
+   cg_branch_modify(cmp, p);
+
+// grab the branch instruction
+   c = p->code;
+
+// determine sign/unsigned modifier
+   sign = "s";
+   if (typ & UNSIGNED) {
+      sign = "u";
+   }
+
+// 1. step we allcoate necessay temporaries	  
+   track_ic(f, cmp);
+
+// We need to distinguish different operand sizes
+   if (size <= 2) {
+// First case takes care of CHAR and INT/SHORT
+      x = &cmp->q1;
+      emit_load(f, x->am->regval[0], x, typ, 0, "mov");
+// emit operation
+      if (x->am->regval[0]) {
+// operation is performed on temporaries
+         emit_load(f, x->am->regval[0], &cmp->q2, typ, 0, "cmp");
+      } else {
+// operation is performed directly on target (z == q1 for this to work)
+         emit_op(f, x, &cmp->q2, typ, 0, "cmp");
+      }
+// must restore temporaries here,
+      track_restore(f);
+
+      switch (c) {
+         case BLT:
+            emit(f, "\tj%sl\t%s%ld\n", sign, label_prefix, target_true);
+	    break;
+         case BGE:
+            emit(f, "\tj%sge\t%s%ld\n", sign, label_prefix, target_true);
+	    break;
+         case BEQ:
+            emit(f, "\tje\t%s%ld\n", label_prefix, target_true);
+	    break;
+         case BNE:
+            emit(f, "\tjne\t%s%ld\n", label_prefix, target_true);
+	    break;
+      }
+
+   } else if (size == 4) {
+// LONG
+      x = &cmp->q1;
+      emit_load(f, x->am->regval[0], x, typ, 0, "mov");
+      emit_load(f, x->am->regval[1], x, typ, 2, "mov");
+// emit operation
+      if (x->am->regval[1]) {
+// operation is performed on temporaries
+         emit_load(f, x->am->regval[1], &cmp->q2, typ, 2, "cmp");
+      } else {
+// operation is performed directly on target (z == q1 for this to work)
+         emit_op(f, x, &cmp->q2, typ, 2, "cmp");
+      }
+// must restore temporaries here,
+      track_restore2(f);// (but don't release)
+      switch (c) {
+         case BLT:
+            emit(f, "\tj%sl\t%s%ld\n", sign, label_prefix, target_true);
+            emit(f, "\tjne\t%sn%ld\n", label_prefix, target_false);
+	    break;
+         case BGE:
+            emit(f, "\tj%sl\t%sn%ld\n", sign, label_prefix, target_false);
+            emit(f, "\tjne\t%s%ld\n", label_prefix, target_true);
+	    break;
+         case BEQ:
+            emit(f, "\tjne\t%sn%ld\n", label_prefix, target_false);
+	    break;
+         case BNE:
+            emit(f, "\tjne\t%sn%ld\n", label_prefix, target_true);
+	    break;
+      }
+// here we have to reallocate temporary. HOWEVER if done cleverly we don't have
+// to reload it, I have to think about the whole thing a litte bit.
+  // (reload what is needed, use same temps as above)
+ emit_load(f, x->am->regval[0], x, typ, 0, "mov");
+
+      // emit operation
+      if (x->am->regval[0]) {
+// operation is performed on temporaries
+         emit_load(f, x->am->regval[0], &cmp->q2, typ, 0, "cmp");
+      } else {
+// operation is performed directly on target (z == q1 for this to work)
+         emit_op(f, x, &cmp->q2, typ, 0, "cmp");
+      }
+      track_restore(f); 
+     switch (c) {
+         case BLT:
+            emit(f, "\tjuge\t%s%ld\n", label_prefix, target_true);
+	    break;
+         case BGE:
+            emit(f, "\tjul\t%s%ld\n", label_prefix, target_true);
+	    break;
+         case BEQ:
+            emit(f, "\tje\t%s%ld\n", label_prefix, target_true);
+	    break;
+         case BNE:
+            emit(f, "\tjne\t%s%ld\n", label_prefix, target_true);
+	    break;
+      }
+              
+      
+   } else {
+      terror("branch size not supported");
+   }
+
+// emit "not taken" label
+   emit(f, "%sn%ld:\n", label_prefix, target_false);
+
+// release temporaries
+   track_release();
+}
+
+static void cg_setreturn(FILE *f, struct IC *p)
+{
+   emit(f, "; set return\n");
+   
+   if (sizetab[ztyp(p)&NQ] > regsize[p->z.reg]) terror("-- cg_setreturn: size mismatch");
+   emit_load(f, REG_R0, &p->q1, q1typ(p), 0, "mov");
+}
+
+static void cg_getreturn(FILE *f, struct IC *p)
+{
+   emit(f, "; get return\n");
+   
+   if (p->q1.reg) {
+      emit_store(f, &p->z, p->q1.reg, ztyp(p), 0);
+   }
+}
+
+static void cg_movefromreg(FILE *f, struct IC *p)
+{
+   emit_store(f, &p->z, p->q1.reg, ztyp(p), 0);
+}
+
+static void cg_movetoreg(FILE *f, struct IC *p)
+{
+   emit_load(f, p->z.reg, &p->q1, ztyp(p), 0, "mov");
+}
+
+/****************************************/
+/*  End of private data and functions.  */
+/****************************************/
+
+/*  Does necessary initializations for the code-generator. Gets called  */
+/*  once at the beginning and should return 0 in case of problems.      */
+int init_cg(void)
+{
+   int		i;
+   int		nregs;
+   int		rtmp;
+   int		rsave;
+   
+/*  Initialize some values which cannot be statically initialized   */
+ /*  because they are stored in the target's arithmetic.             */
+   maxalign = l2zm(2L);
+   char_bit = l2zm(8L);
+
+   sizetab[0] = 1; typname[0] = "strange"; align[0] = 1;
+   sizetab[CHAR] = 1; typname[CHAR] = "char"; align[CHAR] = 1;
+   sizetab[SHORT] = 2; typname[SHORT] = "short"; align[SHORT] = 2;
+   sizetab[INT] = 2; typname[INT] = "int"; align[INT] = 2;
+   sizetab[LONG] = 4; typname[LONG] = "long"; align[LONG] = 2;
+   sizetab[LLONG] = 8; typname[LLONG] = "long long"; align[LLONG] = 2;
+   sizetab[FLOAT] = 4; typname[FLOAT] = "float"; align[FLOAT] = 2;
+   sizetab[DOUBLE] = 8; typname[DOUBLE] = "double"; align[DOUBLE] = 2;
+   sizetab[LDOUBLE] = 8; typname[LDOUBLE] = "long double"; align[LDOUBLE] = 2;
+   sizetab[VOID] = 0; typname[VOID] = "void"; align[VOID] = 1;
+   sizetab[POINTER] = 2; typname[POINTER] = "pointer"; align[POINTER] = 2;
+   sizetab[ARRAY] = 0; typname[ARRAY] = "array"; align[ARRAY] = 1;
+   sizetab[STRUCT] = 0; typname[STRUCT] = "struct"; align[STRUCT] = 1;
+   sizetab[UNION] = 0; typname[UNION] = "union"; align[UNION] = 1;
+   sizetab[ENUM] = 2; typname[ENUM] = "enum"; align[ENUM] = 2;
+   sizetab[FUNKT] = 0; typname[FUNKT] = "function"; align[FUNKT] = 1;
+   sizetab[MAXINT] = 0;
+
+// fill in the default register description
+   regnames[0] = "noreg";
+   regnames[REG_R0] = "r0";
+   regnames[REG_R1] = "r1";
+   regnames[REG_R2] = "r2";
+   regnames[REG_R3] = "r3";
+   regnames[REG_R4] = "r4";   
+   regnames[REG_R5] = "r5";
+   regnames[REG_R6] = "r6";
+   regnames[REG_R7] = "r7";
+   regnames[REG_R8] = "r8";
+   regnames[REG_R9] = "r9";
+   regnames[REG_R10] = "r10";
+   regnames[REG_R11] = "r11";
+   regnames[REG_R12] = "r12";
+   regnames[REG_R13] = "r13";
+
+   for (i = 1; i < MAXR+1; i++) {
+      regsize[i] = l2zm(2L);
+      regtype[i] = &ltyp;
+      regscratch[i] = 1;
+      regsa[i] = 0;
+      reg_prio[i] = 1;
+// private register tracking system
+// Indicate register is available as temporary.
+      track_status[i] = 0;
+   }
+
+// default numbers of registers to use
+   nregs = 6;
+// check command line flags for number of registers
+   if (g_flags[0] & USEDFLAG) {
+      nregs = g_flags_val[0].l;
+   }
+   if (nregs < 3) nregs = 3;
+   if (nregs > 14) nregs = 14;  
+// limit available registers to 'nregs'
+   for (i = REG_R0+nregs; i <= REG_R13; i++) {
+      regsa[i] = 1;
+      regscratch[i] = 0;
+      track_status[i] |= TRACK_OFFLIMITS;
+   }
+
+// get the number of temporary registers to reserve
+   if (g_flags[2] & USEDFLAG) {
+      rtmp = g_flags_val[1].l;
+   } else {
+      rtmp = 0;
+      if (nregs >= 6) rtmp = 1;
+      if (nregs >= 9) rtmp = 2;
+      if (nregs >= 12) rtmp = 3;
+   }
+   if (rtmp < 0) rtmp = 0;
+   if (rtmp > 3) rtmp = 3;
+
+// remove temporary registers from code generator pool (on the top side)
+   for (i = nregs-rtmp; i < nregs; i++) {
+      regsa[REG_R0+i] = 1;
+      regscratch[REG_R0+i] = 0;
+// indicate to tracked that this is a dedicated temporary register
+      track_status[REG_R0+i] |= TRACK_DEDICATED;
+   }
+
+// get numbers of registers to save across function calls
+   if (g_flags[1] & USEDFLAG) {
+      rsave = g_flags_val[1].l;
+   } else {
+      rsave = 0;
+// automatically select 
+      if (nregs >= 6) rsave = 2;
+      if (nregs >= 10) rsave = 4;
+   }
+   if (rsave < 0) rsave = 0;
+   if (rsave > nregs-rtmp) rsave = nregs-rtmp;
+
+   for (i = 0; i < rsave; i++) {
+      regscratch[REG_R0+nregs-rtmp-rsave+i] = 0;
+   }
+   
+// SP is special
+   regnames[REG_SP] = "sp";
+   regscratch[REG_SP] = 0;
+   regsa[REG_SP] = 1;
+   track_status[REG_SP] |= TRACK_OFFLIMITS;
+// and FLAGS is special
+   regnames[REG_FLAGS] = "flags";
+   regscratch[REG_FLAGS] = 0;
+   regsa[REG_FLAGS] = 1;
+   track_status[REG_FLAGS] |= TRACK_OFFLIMITS;
+
+// print some status to the screen
+   printf("Falco16 CPU information\n");
+   printf("   GP registers: %d\n", nregs);
+   printf("   temporaries:  %d\n", rtmp);
+   printf("   saves:        %d\n", rsave);
+
+
+
+  /*  Don't use multiple ccs.   */
+  multiple_ccs = 0;
+
+  /*  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.          */
+  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]=t_max(UNSIGNED|SHORT);
+  tu_max[LONG]=ul2zum(4294967295UL);
+  tu_max[LLONG]=zumkompl(ul2zum(0UL));
+  tu_max[MAXINT]=t_max(UNSIGNED|LLONG);
+  
+
+  target_macros=marray;
+
+// local label counter
+  label_count = 0;
+
+  return 1;
+}
+
+void init_db(FILE *f)
+{
+}
+
+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.        */
+/*  A pointer MUST be returned in a register. The code-generator    */
+/*  has to simulate a pseudo register if necessary.                 */
+{
+   int	       ret;
+   int	       p;
+   
+   ret = 0;
+   p = t->flags & NQ;
+   
+   if (sizetab[p] <= regsize[REG_R0]) ret = REG_R0;
+  
+   return ret;
+}
+
+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.                                            */
+{
+  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.                  */
+{
+// simple paramtere check   
+   if(r == 0) return 0;
+
+// if floating point, we don't keep them in registers at all
+   if (ISFLOAT(t)) return 0;
+
+// Must be integer or pointer, keep them in register if possible. 
+   t &= NQ;
+   if (sizetab[t] <= regsize[r]) return 1;
+   
+   return 0;
+}
+
+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             */
+{
+
+  return 0;
+}
+
+int must_convert(int src, int dst, int const_expr)
+{
+   int		srcp = src & NQ;
+   int		dstp = dst & NQ;
+
+   if (ISINT(src) && ISINT(dst)) {
+      if (sizetab[srcp] >= sizetab[dstp]) return 0;
+     // if (sizetab[srcp] == 1 && sizetab[dstp] == 2) return 0;        
+   } else if (ISINT(src) && ISPOINTER(dst)) {
+      if (sizetab[srcp] >= sizetab[dstp]) return 0;
+     // if (sizetab[srcp] == 1 && sizetab[dstp] == 2) return 0;        
+   } else if (ISPOINTER(src) && ISINT(dst)) {
+      if (sizetab[srcp] >= sizetab[dstp]) return 0;
+    //  if (sizetab[srcp] == 1 && sizetab[dstp] == 2) return 0;        
+   } 
+   
+// no conversion when src and dst are same type   
+   if (src == dst) return 0;
+
+   
+   return 1;
+}
+
+/* Return name of library function, if this node should be
+   implemented via libcall. */
+char *use_libcall(np p)
+{
+
+/*
+   following operations go into library
+
+N - native
+L - library call (some paramters are implemented native)
+A - library call (all the time)
+X - not supported
+- - not valid (not generated by front-end)
+? - what to do?
+
+            CHAR  SHORT/INT  LONG  LLONG  FLOAT  DOUBLE  LDOUBLE
+
+CMP          N        N        N     X      ?      X       X
+OR           N        N        N     X      -      -       -
+XOR          N        N        N     X      -      -       -
+AND          N        N        N     X      -      -       -
+LSHIFT       L        L        L     X      -      -       -
+RSHIFT       L        L        L     X      -      -       -
+ADD          N        N        N     X      A      X       X
+SUB          N        N        N     X      A      X       X
+MULT         L        L        L     X      A      X       X
+DIV          L        L        L     X      A      X       X
+MOD          L        L        L     X      A      X       X
+*/
+
+   static char	fname[16];
+   char		*ret;
+   int		f;
+   char		*sign;
+   char		*dtype;
+   int		code;
+
+   if(p->flags>=EQUAL&&p->flags<=GREATEREQ){
+   extern struct Typ *arith_typ();
+    struct Typ *t=arith_typ(p->left->ntyp,p->right->ntyp);
+    f=t->flags&NU;
+    freetyp(t);
+    if((f&NQ)==LLONG){
+      sprintf(fname,"__cmp%s%sll",ename[p->flags],(f&UNSIGNED)&&p->flags!=EQUAL&&p->flags!=INEQUAL?"u":"");
+      ret=fname;
+    }else if((f&NQ)==FLOAT){
+      sprintf(fname,"__cmp%s%sf",ename[p->flags],(f&UNSIGNED)&&p->flags!=EQUAL&&p->flags!=INEQUAL?"u":"");
+      ret=fname;
+    }else if((f&NQ)==DOUBLE||(f&NQ)==LDOUBLE){
+      sprintf(fname,"__cmp%s%sd",ename[p->flags],(f&UNSIGNED)&&p->flags!=EQUAL&&p->flags!=INEQUAL?"u":"");
+      ret=fname;
+    }
+   }else{
+// get code of operation
+      code = p->flags;
+// get data type
+      f = p->ntyp->flags & NU;
+
+      sign = "s";
+      if (f & UNSIGNED) {
+         sign = "u";
+      }
+
+      switch (f & NQ) {
+         case CHAR: dtype = "i8"; break;
+         case SHORT:
+         case INT: dtype = "i16"; break;
+         case LONG: dtype = "i32"; break;
+         case FLOAT: dtype = "f32"; break;
+         case DOUBLE: dtype = "f64"; break;
+         default: dtype = ""; break;
+            terror("--use_libcall: data type not supported");
+	    break;
+      }
+// default is no function
+      ret = 0;
+      switch (code) {
+         case LSHIFT: sprintf(fname, "__shl_%s%s", sign, dtype); ret = fname; break;
+         case RSHIFT: sprintf(fname, "__shr_%s%s", sign, dtype); ret = fname; break;
+         case ADD:
+	    if (ISFLOAT(f)) { sprintf(fname, "__add_%s", dtype); ret = fname; }
+	    break;
+	 case SUB:
+	    if (ISFLOAT(f)) { sprintf(fname, "__sub_%s", dtype); ret = fname; }
+	    break;
+	 case MINUS:
+	    if (ISFLOAT(f)) { sprintf(fname, "__neg_%s", dtype); ret = fname; }
+	    break;
+	 case MULT: sprintf(fname, "__mul_%s%s", sign, dtype); ret = fname; break;
+	 case DIV:
+	    sprintf(fname, "__div_%s%s", sign, dtype); ret = fname;
+	    break;
+	 case MOD:
+	    sprintf(fname, "__mod_%s%s", sign, dtype); ret = fname;
+	    break;
+      }
+   }
+  
+   if(ret){
+/* declare function if necessary */
+      struct struct_declaration *sd;struct Typ *t;
+      if(!find_ext_var(ret)){
+         sd = mymalloc(sizeof(*sd));
+         sd->count = 0;
+         t = new_typ();
+         t->flags = FUNKT;
+         t->exact = add_sd(sd, FUNKT);
+         t->next = clone_typ(p->ntyp);
+         add_var(ret, t, EXTERN, 0);
+      }
+   }
+   return ret;
+}
+
+
+
+void gen_ds(FILE *f, zmax size, struct Typ *t)
+/*  This function has to create <size> bytes of storage */
+/*  initialized with zero.                              */
+{
+   if (newobj) {
+      emit(f, "\tdb\tdup(%ld, 0)\n", zm2l(size));
+   } else {
+      emit (f, "-- somehting's wrong\n");
+   }     
+   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.              */
+{
+   int p;
+   p = p; 
+}
+
+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 ((v->vtyp->flags&NQ) == FUNKT) return;
+      if (v->clist && (!constflag) && section != SEC_DATA) {
+         emit(f, "\n\tsection\t%s\n", sec_dataname);
+         if (f) section = SEC_DATA;
+      }
+      if (v->clist && constflag && section != SEC_RODATA) {
+         emit(f, "\n\tsection\t%s\n", sec_rodataname);
+         if (f) section = SEC_RODATA;
+      }
+      if (!v->clist && section != SEC_BSS) {
+         emit(f, "\n\tsection\t%s\n", sec_bssname);
+         if (f) section = SEC_BSS;
+      }
+      emit(f, "%s%ld:", label_prefix, zm2l(v->offset));
+
+      newobj = 1;
+   }
+   if (v->storage_class == EXTERN) {
+      if (v->flags & (DEFINED|TENTATIVE)) {
+         if (v->clist && (!constflag) && section != SEC_DATA) {
+            emit(f, "\n\tsection\t%s\n", sec_dataname);
+            if (f) section=SEC_DATA;
+         }
+         if (v->clist && constflag && section != SEC_RODATA) {
+            emit(f, "\n\tsection\t%s\n", sec_rodataname); 
+            if(f) section = SEC_RODATA;
+         }
+         if (!v->clist && section != SEC_BSS) {
+            emit(f, "\n\tsection\t%s\n", sec_bssname);
+            if (f) section = SEC_BSS;
+         }
+         emit(f, "\tpublic\t%s%s\n", ident_prefix, v->identifier);
+         emit(f, "%s%s:", ident_prefix, 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 ((t&NQ) == FLOAT || (t&NQ) == DOUBLE) {
+         emit(f, "-- floating point not supported\n");
+      } else {
+	 emitval(f, &p->val, t&NU);
+      }
+   } else {
+         emit(f, "-- gen_dc: what the hell\n");
+   }
+   emit(f, "\n");
+   newobj = 0;
+}
+
+
+/*  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 *p, struct Var *v, zmax offset)
+/*  The main code-generation.                                           */
+{
+   struct IC	*head;
+   int		c;
+  
+   if (DEBUG&1) printf("gen_code()\n");
+   
+   loff = ((zm2l(offset) + 1) / 2) * 2;
+   stackoffset = 0;
+   cd_function_entry(f, v, loff);
+   
+// initialize temporary register tracking
+   track_init();
+
+   head = p;
+   for(; p; p = p->next){
+// print: this doesn't work right, due to emit buffer
+   printic(f, p);
+   emit(f, "; stackoffset: %d\n", stackoffset);
+
+// get operation code      
+      c = p->code;
+      
+      switch (c) {
+         case NOP: 
+            break;
+            
+         case ASSIGN:
+	 case CONVERT:
+            cg_assign(f, p);
+            break; 
+         
+         case LSHIFT:
+            cg_lshift(f, p);
+            break;
+         case RSHIFT:
+            cg_rshift(f, p);
+            break;
+            
+         case ADD:
+         case ADDI2P:
+         case SUB:
+         case SUBIFP:
+         case OR:
+         case XOR:
+         case AND:
+            cg_alu(f, p);
+            break;
+         
+         case MULT:
+            cg_mult(f, p);
+            break;
+
+         case DIV:
+            cg_div(f, p);
+            break;
+
+         case MOD:
+            cg_mod(f, p);
+            break;
+         
+         case KOMPLEMENT:
+            cg_komplement(f, p);
+            break;
+
+         case MINUS:
+            cg_minus(f, p);
+            break;
+            
+         case ADDRESS:
+            cg_address(f, p);
+            break;   
+            
+         case TEST:
+// change TEST into COMPARE
+            cg_test(f, p);
+            break;
+	 
+         case COMPARE:
+// This is handled by the branch IC. Nothing to do here.
+            break;     
+               
+         case LABEL:
+// must restore all temporaries before any label
+// This is not good, as vbcc seems to be generating more labels than necessaty,
+// pretty much defeating our clever system. We must do some more processing here.
+            track_restore(f);
+            emit(f, "%s%ld:\n", label_prefix, (long)p->typf);
+            break;
+            
+         case BEQ:
+         case BNE:
+         case BLT:
+         case BGE:
+         case BLE:
+         case BGT:
+            cg_branch(f, p);
+            break;      
+         case BRA:
+// restore temporaries
+            track_restore(f);
+            emit(f, "\tjmp\t%s%ld\n", label_prefix, (long)p->typf);
+            break;
+               
+         case PUSH:
+            cg_push(f, p);
+            break;
+
+         case CALL:
+            cg_call(f, p);
+            break;
+            
+         case SETRETURN:
+            cg_setreturn(f, p);
+            break;   
+
+         case GETRETURN:
+            cg_getreturn(f, p);
+            break;
+            
+         case ALLOCREG:
+// register is being used, indicate it can only be used if saved
+            track_status[p->q1.reg] |= TRACK_ALLOCREG;
+            break;
+            
+         case FREEREG:
+// register is again free
+            track_status[p->q1.reg] &= ~(TRACK_ALLOCREG);
+            break; 
+        
+         case MOVEFROMREG:
+            cg_movefromreg(f, p);       
+	    break;
+            
+         case MOVETOREG:
+	    cg_movetoreg(f, p);
+            break;
+            
+            
+         default:
+            emit(f, "unhandled IC\n");
+      }
+      emit(f, "\n");   
+   }   
+   cg_function_exit(f, v, loff);
+
+}
+
+int shortcut(int code, int typ)
+{
+   if (sizetab[typ&NQ] > 2) return 0;
+   return 1;
+}
+
+
+void cleanup_cg(FILE *f)
+{
+}
+void cleanup_db(FILE *f)
+{
+
+}
diff --git a/machines/falco16/machine.dt b/machines/falco16/machine.dt
new file mode 100755
index 0000000..eab38c9
--- /dev/null
+++ b/machines/falco16/machine.dt
@@ -0,0 +1,16 @@
+S8BS
+S8BU
+S16BSLE S16BSBE
+S16BULE S16BUBE
+S16BSLE S16BSBE
+S16BULE S16BUBE
+S32BSLE S32BSBE
+S32BULE S32BUBE
+S64BSLE S64BSBE
+S64BULE S64BUBE
+S32BIEEELE
+S64BIEEELE
+S64BIEEELE
+S16BULE S16BUBE
+
+
diff --git a/machines/falco16/machine.h b/machines/falco16/machine.h
new file mode 100755
index 0000000..bdebc42
--- /dev/null
+++ b/machines/falco16/machine.h
@@ -0,0 +1,142 @@
+/* 
+   FALCO16 v3
+*/
+
+/*#include "supp.h"*/
+#include "dt.h"
+
+
+/*  This struct can be used to implement machine-specific           */
+/*  addressing-modes.                                               */
+struct AddressingMode {
+// register to be used as temporary pointer   
+   int			regptr;
+// register to be used as temporary value
+// We support long and float and therfore need potentially 2 registers   
+   int			regval[2];
+};
+
+/*  The number of registers of the target machine.                  */
+#define MAXR		16
+
+/*  Number of commandline-options the code-generator accepts.       */
+#define MAXGF		3
+
+/*  If this is set to zero vbcc will not generate ICs where the     */
+/*  target operand is the same as the 2nd source operand.           */
+/*  This can sometimes simplify the code-generator, but usually     */
+/*  the code is better if the code-generator allows it.             */
+#define USEQ2ASZ 1
+
+/*  This specifies the smallest integer type that can be added to a */
+/*  pointer.                                                        */
+#define MINADDI2P INT
+
+/*  If the bytes of an integer are ordered most significant byte    */
+/*  byte first and then decreasing set BIGENDIAN to 1.              */
+#define BIGENDIAN 0
+
+/*  If the bytes of an integer are ordered lest significant byte    */
+/*  byte first and then increasing set LITTLEENDIAN to 1.           */
+#define LITTLEENDIAN 1
+
+/*  Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive.    */
+
+/*  If switch-statements should be generated as a sequence of       */
+/*  SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1.      */
+/*  This can yield better code on some machines.                    */
+#define SWITCHSUBS 0
+
+/*  In optimizing compilation certain library memcpy/strcpy-calls   */
+/*  with length known at compile-time will be inlined using an      */
+/*  ASSIGN-IC if the size is less or equal to INLINEMEMCPY.         */
+/*  The type used for the ASSIGN-IC will be UNSIGNED|CHAR.          */
+#define INLINEMEMCPY 4
+
+/*  Parameter push order */
+#undef ORDERED_PUSH
+
+/*  Parameters are sometimes passed in registers without __reg.     */
+//#define HAVE_REGPARMS 1
+#undef HAVE_REGPARMS
+
+/* use library calls for some basic ICs */
+#define HAVE_LIBCALLS 1
+
+/*  Structure for reg_parm().                                       */
+struct reg_handle{
+    unsigned long gregs;
+    unsigned long fregs;
+};
+
+
+/* we do not need register-pairs */
+#undef HAVE_REGPAIRS
+
+/* select size_t. unsigned int or unsigned long, the default */
+#undef HAVE_INT_SIZET
+
+/* size of buffer for asm-output, this can be used to do
+   peephole-optimizations of the generated assembly-output */
+#define EMIT_BUF_LEN 1024 /* should be enough */
+/* number of asm-output lines buffered */
+#define EMIT_BUF_DEPTH 1
+
+/*  We have no asm_peephole to optimize assembly-output */
+#define HAVE_TARGET_PEEPHOLE 0
+
+
+/*  We have some target-specific variable attributes.               */
+#undef HAVE_TARGET_ATTRIBUTES
+
+/* We have target-specific pragmas */
+#undef HAVE_TARGET_PRAGMAS
+
+/*  We keep track of all registers modified by a function.          */
+#undef HAVE_REGS_MODIFIED
+
+/* We have a implement our own cost-functions to adapt 
+   register-allocation */
+#undef HAVE_TARGET_RALLOC
+
+
+/* we do not have a mark_eff_ics function, this is used to prevent
+   optimizations on code which can already be implemented by efficient
+   assembly */
+#undef HAVE_TARGET_EFF_IC
+
+/* we do need extra elements in the IC */
+#define HAVE_EXT_IC 1
+struct Regtmp {
+// register number   
+   int		reg;
+// must be saved before used?
+   int		save;
+};
+#define MAX_TMPREG		3
+struct ext_ic {
+// temporary ptr register to use with this IC
+   struct Regtmp	reg_tmp[MAX_TMPREG];
+};
+
+/* We have extended types! What we have to do to support them:      */
+/* - #define HAVE_EXT_TYPES
+   - #undef all standard types
+   - #define all standard types plus new types
+   - write eval_const and insert_const
+   - write typedefs for zmax and zumax
+   - define atyps union
+   - write typname[]
+   - write conv_typ()
+   - optionally #define ISPOINTER, ISARITH, ISINT etc.
+   - optionally #define HAVE_TGT_PRINTVAL and write printval
+   - optionally #define POINTER_TYPE
+   - optionally #define HAVE_TGT_FALIGN and write falign
+   - optionally #define HAVE_TGT_SZOF and write szof
+   - optionally add functions for attribute-handling
+*/
+#undef HAVE_TGT_PRINTVAL
+#undef HAVE_EXT_TYPES
+
+
+
diff --git a/machines/fire16/machine.c b/machines/fire16/machine.c
new file mode 100644
index 0000000..e838c11
--- /dev/null
+++ b/machines/fire16/machine.c
@@ -0,0 +1,2280 @@
+/*
+ * Backend for the Fire16 iCE40 SoftCore
+ * (c) 2019 by Sylvain Munaut
+ */
+
+#define DBG
+
+#include "supp.h"
+
+static char FILE_[]=__FILE__;
+/*  Public data that MUST be there.                             */
+
+/* Name and copyright. */
+char cg_copyright[]="vbcc code-generator for fire16 v0.1 (c) 2019 by Sylvain Munaut";
+
+/*  Commandline-flags the code-generator accepts                */
+char *g_flags_name[MAXGF]={"tiny-dmem", "tiny-pmem"};
+int g_flags[MAXGF]={0, 0};
+union ppi g_flags_val[MAXGF];
+
+/*  Extended type names */
+char *typname[]={"n/a", "char","short","int","long","long long",
+                 "float","double","long double","void",
+                 "dmem-pointer","pmem-pointer",
+                 "array","struct","union","enum","function"};
+
+/*  Alignment-requirements for all types in bytes.              */
+zmax align[MAX_TYPE+1];
+
+/*  Alignment that is sufficient for every object.              */
+zmax maxalign;
+
+/*  CHAR_BIT for the target machine.                            */
+zmax char_bit;
+
+/*  sizes of the basic 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. will be initialized in init_cg(),
+    register number 0 is invalid, valid registers start at 1 */
+char *regnames[MAXR+1];
+
+/*  The Size of each register in bytes.                         */
+zmax regsize[MAXR+1];
+
+/*  a 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];
+
+/* specifies the priority for the register-allocator, if the same
+   estimated cost-saving can be obtained by several registers, the
+   one with the highest priority will be used */
+int reg_prio[MAXR+1];
+
+/* an empty reg-handle representing initial state */
+struct reg_handle empty_reg_handle={0};
+
+/* Names of target-specific variable attributes.                */
+char *g_attr_name[]={0};
+
+
+/****************************************/
+/*  Private data and functions.         */
+/****************************************/
+
+/* alignment of basic data-types, used to initialize align[] */
+static long malign[MAX_TYPE+1]   = {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+/* sizes of basic data-types, used to initialize sizetab[] */
+static long msizetab[MAX_TYPE+1] = {0,1,1,1,2,4,2,4,4,1,1,1,1,1,1,1,1,1,1};
+
+/* Macros */
+static char *marray[] = {
+	"__pmem=__attr(\"pmem\")",
+	0
+};
+
+/* Register types */
+struct Typ ityp={SHORT}, ltyp={LONG};
+
+/* Registers num */
+enum {
+	R_NONE = 0,
+	R_R0, R_R1, R_R2, R_R3, R_R4, R_R5, R_R6, R_R7,
+	R_R8, R_R9, R_RA, R_RB, R_RC, R_RD, R_RE, R_RF,
+	R_S0, R_S1, R_S2, R_S3, R_S4, R_S5, R_S6, R_S7,
+	R_S8, R_S9, R_SA, R_SB, R_SC, R_SD, R_SE, R_SF,
+	R_R0P, R_R2P, R_R4P, R_R6P, R_R8_P, R_RAP, R_RCP, R_REP,
+	R_S0P, R_S2P, R_S4P, R_S6P, R_S8_P, R_SAP, R_SCP, R_SEP,
+	R_A, R_X, R_Y, R_I
+};
+
+#define isgpr(r) ((r) >= R_R0 && (r) <= R_SEP)
+
+/* Identifier prefixes */
+static const char *idprefix="_", *labprefix="l";
+
+#define isreg(x) (((x)->flags&(REG|DREFOBJ))==REG)
+#define isconst(x) (((x)->flags&(KONST|DREFOBJ))==KONST)
+
+#define ISTSHORT(t) (((t)&NQ)==CHAR || ((t)&NQ)==SHORT || ((t)&NQ)==INT || ((t)&NQ)==DPOINTER || ((t)&NQ)==PPOINTER)
+#define ISTLONG(t)  (((t)&NQ)==LONG || ((t)&NQ)==FLOAT)
+
+#define STR_PMEM "pmem"
+
+#define TINY_DMEM (g_flags[0] & USEDFLAG)
+#define TINY_PMEM (g_flags[1] & USEDFLAG)
+#define TINY_IMM(i) ( (((i) & 0xff00) == 0xff00) || (((i) & 0xff00) == 0x0000) )
+
+static char *sym_name(struct Var *var)
+{
+	static char sym[128];	/* fixme ? */
+
+	if (isstatic(var->storage_class))
+		snprintf(sym, sizeof(sym)-1, "%s%ld", labprefix, zm2l(var->offset));
+	else
+		snprintf(sym, sizeof(sym)-1, "%s%s", idprefix, var->identifier);
+
+	return sym;
+}
+
+static long const2long(struct obj *o, int dtyp)
+{
+	if (!(o->flags & KONST))
+		ierror(0);
+	eval_const(&o->val, dtyp);
+	return zm2l(vmax);
+}
+
+struct gc_state
+{
+	FILE *f;
+
+	int reg_busy[MAXR+1];	/* Track used registers */
+
+	int op_save;		/* Saved register to restore before op end */
+	long val_rv;		/* Return Value immediate (must be small enough) */
+	int reg_rv;		/* Return Value register, 0=none */
+	int reg_lw;		/* Register written in the last emitted op code */
+
+	int s_argsize;
+	int s_localsize;
+	int s_savesize;
+
+	int cmp_signed;		/* Last comparison was signed */
+	int cmp_cur_z;		/* Current state of z flag */
+};
+
+static int
+_gc_find_reg(struct gc_state *gc, int pair)
+{
+	int min, max, r;
+
+	min = pair ? R_R0P : R_R0;
+	max = pair ? R_SEP : R_SF;
+
+	/* Try for a scratch reg first */
+	for (r=min; r<=max; r++)
+		if (!gc->reg_busy[r] && !regsa[r] && regscratch[r])
+			return r;
+
+	/* Ok ... anything will do */
+	for (r=min; r<=max; r++)
+		if (!gc->reg_busy[r] && !regsa[r])
+			return r;
+
+	/* Nothing :/ */
+	return 0;
+}
+
+
+/* Stack layout: (grows toward 0)
+ *
+ *       ,------------------------------------------------,
+ *   Y   | (next available word)                          |  <- Y pointer
+ *       | arguments to called functions [size=s_argsize] |
+ *       | local variables [size=s_localsize]             |
+ *       | saved register [size=s_savesize]               |
+ *       | return-address save [size=1]                   |
+ *   Y+N | arguments to this function [size=?]            |
+ *       `------------------------------------------------'
+ */
+static long
+_gc_real_offset(struct gc_state *gc, struct Var *v, long add_offset)
+{
+	long off = zm2l(v->offset);
+
+	if (off < 0) {
+		/* function parameter */
+		off = gc->s_localsize + gc->s_savesize + 1 - (off + zm2l(maxalign));
+	}
+
+	off += gc->s_argsize;
+	off += add_offset;
+	off += 1; /* Because we point to the next available word */
+
+	return off;
+}
+
+#define _gc_emit(gc, ...) do {		\
+	(gc)->reg_lw = 0;		\
+	emit((gc)->f,  __VA_ARGS__ );	\
+} while (0)
+
+static void
+_gc_emit_nop(struct gc_state *gc)
+{
+	gc->reg_lw = 0;
+	gc->cmp_cur_z = 0;
+	emit(gc->f, "\tnop\n" );
+}
+
+/* Emit a IMM opcode prefix if the constant requires it */
+static long
+_gc_emit_imm(struct gc_state *gc, long v)
+{
+	v = v & 0xffff;
+
+	if ((v & 0xff00) == 0) {
+		return v;
+	} else if ((v & 0xff00) == 0xff00) {
+		return - ((v ^ 0xffff) + 1);
+	} else {
+		gc->reg_lw = 0;
+		emit(gc->f, "\timm\t$%d\n", (v >> 8) & 0xff);
+		return v & 0xff;
+	}
+}
+
+/* Emit movs between any register pairs and any single GPR & A */
+static void
+_gc_emit_mov(struct gc_state *gc, int dst, int src)
+{
+	if (src == dst)
+		return;
+
+	if ((src == gc->reg_lw) && isgpr(src))
+		emit(gc->f, "\tnop\n");
+
+	emit(gc->f, "\tmov\t%s, %s\n", regnames[dst], regnames[src]);
+
+	BSET(regs_modified, dst);
+
+	gc->reg_lw = isgpr(dst) ? dst : 0;
+}
+
+/* Emit opcode and checks for depencies */
+static void
+_gc_emit_alu(struct gc_state *gc, const char *opcode,
+             int dst, int src1, int src2, long imm)
+{
+	int dep1 = (src1 == gc->reg_lw) && isgpr(src1);
+	int dep2 = (src2 == gc->reg_lw) && isgpr(src2);
+	char dst_str[16], *op1_str, op2_str[16], imm_str[16];
+
+	if ((dep1 || dep2) && (src1 != R_I) && (src2 != R_I))
+		emit(gc->f, "\tnop\n");
+
+	if ((src1 == R_I) || (src2 == R_I)) {
+		imm = _gc_emit_imm(gc, imm);
+		if ((dst && (dst != R_A)) ||
+		    ((src1 != R_I) && (src1 != R_A)) ||
+		    ((src2 != R_I) && (src2 != R_A))) {
+			emit(gc->f, "\timm\t$%d\n", imm);
+			snprintf(imm_str, sizeof(imm_str)-1, "%s", regnames[R_I]);
+		} else {
+			snprintf(imm_str, sizeof(imm_str)-1, "$%ld", imm);
+		}
+	}
+
+	dst_str[0] = op2_str[0] = 0;
+	op1_str = (src1 != R_I) ? regnames[src1] : imm_str;
+	if (dst)  snprintf(dst_str, sizeof(dst_str)-1, "%s, ", regnames[dst]);
+	if (src2) snprintf(op2_str, sizeof(op2_str)-1, ", %s", (src2 != R_I) ? regnames[src2] : imm_str);
+
+	emit(gc->f, "\t%s\t%s%s%s\n", opcode, dst_str, op1_str, op2_str);
+
+	BSET(regs_modified, dst);
+
+	gc->reg_lw = isgpr(dst) ? dst : 0;
+	gc->cmp_cur_z = gc->reg_lw;
+}
+
+static void
+_gc_move_gpr(struct gc_state *gc, int dst, int src)
+{
+	struct rpair rp_src, rp_dst;
+	int ip_src, ip_dst;
+
+	if (src == dst)
+		return;
+
+	ip_dst = reg_pair(dst, &rp_dst);
+	ip_src = reg_pair(src, &rp_src);
+	if ((regsize[dst] != regsize[src]) || (ip_dst != ip_src))
+		ierror(0);	/* Shouldn't happen */
+
+	if (ip_dst) {
+		if (gc->reg_lw == rp_src.r1) {
+			_gc_emit_mov(gc, R_A, rp_src.r2);
+			_gc_emit_mov(gc, rp_dst.r2, R_A);
+			_gc_emit_mov(gc, R_A, rp_src.r1);
+			_gc_emit_mov(gc, rp_dst.r1, R_A);
+		} else {
+			_gc_emit_mov(gc, R_A, rp_src.r1);
+			_gc_emit_mov(gc, rp_dst.r1, R_A);
+			_gc_emit_mov(gc, R_A, rp_src.r2);
+			_gc_emit_mov(gc, rp_dst.r2, R_A);
+		}
+	} else {
+		/* _gc_emit_mov will handle if src or dst is R_A */
+		_gc_emit_mov(gc, R_A, src);
+		_gc_emit_mov(gc, dst, R_A);
+	}
+}
+
+static void
+_gc_store_to_mem(struct gc_state *gc, int val_reg, int dtyp,
+                 long ptr_const, int ptr_reg, struct Var *var)
+{
+	struct rpair rp;
+	char *opcode;
+	int tiny;
+	int is_pair;
+
+	if (dtyp == DPOINTER) {
+		opcode = "std";
+		tiny = TINY_DMEM;
+	} else if (dtyp == PPOINTER) {
+		opcode = "stp";
+		tiny = TINY_PMEM;
+	} else {
+		ierror(0);
+	}
+
+	is_pair = reg_pair(val_reg, &rp);
+
+	if (var)
+	{
+		/* Variable */
+		if (isauto(var->storage_class)) {
+			/* Stack variable always in data mem */
+			if (dtyp != DPOINTER)
+				ierror(1);
+
+			long sp_offset = _gc_real_offset(gc, var, ptr_const);
+
+			if (sp_offset <= 15) {
+				/* Offset is small enough for indexed Y access */
+				if (is_pair) {
+					/* 32 bit */
+					_gc_emit_mov(gc, R_A, rp.r1);
+					_gc_emit(gc, "\t%s\tA, [Y++, $%d]\n", opcode, sp_offset);
+					_gc_emit_mov(gc, R_A, rp.r2);
+					_gc_emit(gc, "\t%s\tA, [Y--, $%d]\n", opcode, sp_offset);
+				} else {
+					/* 16 bit */
+					_gc_emit_mov(gc, R_A, val_reg);
+					_gc_emit(gc, "\t%s\tA, [Y, $%d]\n", opcode, sp_offset);
+				}
+			} else {
+				/* Offset is too large ... load address in A and fall back to code below */
+				_gc_emit(gc, "\tmov\tA, Y\n");
+				_gc_emit(gc, "\tadd A, A, $%d\n", sp_offset);
+				ptr_reg = R_A;
+			}
+		} else if (isextern(var->storage_class) || isstatic(var->storage_class)) {
+			/* Symbol name */
+			char *sym = sym_name(var);
+
+			/* Make access using absolute immediate addressing */
+			if (reg_pair(val_reg, &rp)) {
+				/* 32 bit */
+				_gc_emit_mov(gc, R_A, rp.r1);
+				if (!tiny) _gc_emit(gc, "\timm\t$(hi(%s+%d))\n", sym, ptr_const);
+				_gc_emit(gc, "\t%s\tA, [$(lo(%s+%d))]\n", opcode, sym, ptr_const);
+				_gc_emit_mov(gc, R_A, rp.r2);
+				if (!tiny) _gc_emit(gc, "\timm\t$(hi(%s+%d))\n", sym, ptr_const+1);
+				_gc_emit(gc, "\t%s\tA, [$(lo(%s+%d))]\n", opcode, sym, ptr_const+1);
+			} else {
+				/* 16 bit */
+				_gc_emit_mov(gc, R_A, val_reg);
+				if (!tiny) _gc_emit(gc, "\timm\t$(hi(%s+%d))\n", sym, ptr_const);
+				_gc_emit(gc, "\t%s\tA, [$(lo(%s+%d))]\n", opcode, sym, ptr_const);
+			}
+		} else {
+			ierror(0);
+		}
+	}
+
+	if (ptr_reg)
+	{
+		/* Register pointer */
+		_gc_emit_mov(gc, R_A, ptr_reg);
+		_gc_emit_mov(gc, R_X, R_A);
+
+		if (is_pair) {
+			/* 32 bit */
+			_gc_emit_mov(gc, R_A, rp.r1);
+			_gc_emit(gc, "\t%s\tA, [X++]\n", opcode);
+			_gc_emit_mov(gc, R_A, rp.r2);
+			_gc_emit(gc, "\t%s\tA, [X--]\n", opcode);
+		} else {
+			/* 16 bit */
+			_gc_emit_mov(gc, R_A, val_reg);
+			_gc_emit(gc, "\t%s\tA, [X]\n", opcode);
+		}
+	}
+
+	if (!ptr_reg && !var)
+	{
+		/* Constant immediate pointer */
+		if (is_pair) {
+			/* 32 bit access */
+			_gc_emit_mov(gc, R_A, rp.r1);
+			_gc_emit(gc, "\t%s\tA, [$%d]\n", opcode,
+				tiny ? (ptr_const+0) : _gc_emit_imm(gc, ptr_const+0));
+			_gc_emit_mov(gc, R_A, rp.r2);
+			_gc_emit(gc, "\t%s\tA, [$%d]\n", opcode,
+				tiny ? (ptr_const+1) : _gc_emit_imm(gc, ptr_const+1));
+		} else {
+			/* 16 bit access */
+			_gc_emit_mov(gc, R_A, val_reg);
+			_gc_emit(gc, "\t%s\tA, [$%d]\n", opcode,
+				tiny ? ptr_const : _gc_emit_imm(gc, ptr_const));
+		}
+	}
+}
+
+static void
+_gc_load_from_mem(struct gc_state *gc, int val_reg, int dtyp,
+                 long ptr_const, int ptr_reg, struct Var *var)
+{
+	struct rpair rp;
+	char *opcode;
+	int tiny;
+	int is_pair;
+
+	if (dtyp == DPOINTER) {
+		opcode = "ldd";
+		tiny = TINY_DMEM;
+	} else if (dtyp == PPOINTER) {
+		opcode = "ldp";
+		tiny = TINY_PMEM;
+	} else {
+		ierror(0);
+	}
+
+	is_pair = reg_pair(val_reg, &rp);
+
+	if (var)
+	{
+		/* Variable */
+		if (isauto(var->storage_class)) {
+			/* Stack variable always in data mem */
+			if (dtyp != DPOINTER)
+				ierror(1);
+
+			long sp_offset = _gc_real_offset(gc, var, ptr_const);
+
+			if (sp_offset <= 15) {
+				/* Offset is small enough for indexed Y access */
+				if (is_pair) {
+					/* 32 bit */
+					_gc_emit(gc, "\t%s\tA, [Y++, $%d]\n", opcode, sp_offset);
+					_gc_emit_mov(gc, rp.r1, R_A);
+					_gc_emit(gc, "\t%s\tA, [Y--, $%d]\n", opcode, sp_offset);
+					_gc_emit_mov(gc, rp.r2, R_A);
+				} else {
+					/* 16 bit */
+					_gc_emit(gc, "\t%s\tA, [Y, $%d]\n", opcode, sp_offset);
+					_gc_emit_mov(gc, val_reg, R_A);
+				}
+			} else {
+				/* Offset is too large ... load address in A and fall back to code below */
+				_gc_emit(gc, "\tmov\tA, Y\n");
+				_gc_emit(gc, "\tadd A, A, $%d\n", sp_offset);
+				ptr_reg = R_A;
+			}
+		} else if (isextern(var->storage_class) || isstatic(var->storage_class)) {
+			/* Symbol name */
+			char *sym = sym_name(var);
+
+			/* Make access using absolute immediate addressing */
+			if (is_pair) {
+				/* 32 bit */
+				if (!tiny) _gc_emit(gc, "\timm\t$(hi(%s+%d))\n", sym, ptr_const);
+				_gc_emit(gc, "\t%s\tA, [$(lo(%s+%d))]\n", opcode, sym, ptr_const);
+				if (dtyp == PPOINTER) _gc_emit_nop(gc);
+				_gc_emit_mov(gc, rp.r1, R_A);
+				if (!tiny) _gc_emit(gc, "\timm\t$(hi(%s+%d))\n", sym, ptr_const+1);
+				_gc_emit(gc, "\t%s\tA, [$(lo(%s+%d))]\n", opcode, sym, ptr_const+1);
+				if (dtyp == PPOINTER) _gc_emit_nop(gc);
+				_gc_emit_mov(gc, rp.r2, R_A);
+			} else {
+				/* 16 bit */
+				if (!tiny) _gc_emit(gc, "\timm\t$(hi(%s+%d))\n", sym, ptr_const);
+				_gc_emit(gc, "\t%s\tA, [$(lo(%s+%d))]\n", opcode, sym, ptr_const);
+				if (dtyp == PPOINTER) _gc_emit_nop(gc);
+				_gc_emit_mov(gc, val_reg, R_A);
+			}
+		} else {
+			ierror(0);
+		}
+	}
+
+	if (ptr_reg)
+	{
+		/* Register pointer */
+		_gc_emit_mov(gc, R_A, ptr_reg);
+		_gc_emit_mov(gc, R_X, R_A);
+
+		if (is_pair) {
+			/* 32 bit access */
+			_gc_emit(gc, "\t%s\tA, [X++]\n", opcode);
+			if (dtyp == PPOINTER) _gc_emit_nop(gc);
+			_gc_emit_mov(gc, rp.r1, R_A);
+			_gc_emit(gc, "\t%s\tA, [X--]\n", opcode);
+			if (dtyp == PPOINTER) _gc_emit_nop(gc);
+			_gc_emit_mov(gc, rp.r2, R_A);
+		} else {
+			/* 16 bit access */
+			_gc_emit(gc, "\t%s\tA, [X]\n", opcode);
+			if (dtyp == PPOINTER) _gc_emit_nop(gc);
+			_gc_emit_mov(gc, val_reg, R_A);
+		}
+	}
+
+	if (!ptr_reg && !var)
+	{
+		/* Constant immediate pointer */
+		if (is_pair) {
+			/* 32 bit access */
+			_gc_emit(gc, "\t%s\tA, [$%d]\n", opcode,
+				tiny ? (ptr_const+0) : _gc_emit_imm(gc, ptr_const+0));
+			if (dtyp == PPOINTER) _gc_emit_nop(gc);
+			_gc_emit_mov(gc, rp.r1, R_A);
+			_gc_emit(gc, "\t%s\tA, [$%d]\n", opcode,
+				tiny ? (ptr_const+1) : _gc_emit_imm(gc, ptr_const+1));
+			if (dtyp == PPOINTER) _gc_emit_nop(gc);
+			_gc_emit_mov(gc,rp.r2, R_A);
+		} else {
+			/* 16 bit access */
+			_gc_emit(gc, "\t%s\tA, [$%d]\n", opcode,
+				tiny ? ptr_const : _gc_emit_imm(gc, ptr_const));
+			if (dtyp == PPOINTER) _gc_emit_nop(gc);
+			_gc_emit_mov(gc, val_reg, R_A);
+		}
+	}
+}
+
+/* Selects a register for the result to be computed in */
+static int
+_gc_store_sel(struct IC *p)
+{
+	int t;
+
+	/* Register destination ? */
+	if (isreg(&p->z))
+		return p->z.reg;
+
+	/* If not, use the scratch registers as temporaries */
+	/* (ideally we should find some free scratch ones and use that
+	 *  instead of having 'reserved' ones ...) */
+	t = ztyp(p) & NQ;
+	if (ISSCALAR(t) && (msizetab[t] == 1))
+		return R_RF;
+	if (ISSCALAR(t) && (msizetab[t] == 2))
+		return R_REP;
+
+	/* Couldn't find a fit ? */
+	ierror(0);
+}
+
+static void
+_gc_op_pre(struct gc_state *gc, struct IC *p, int n_op,
+           int *r_z, int *r_q1, int *r_q2, long *k)
+{
+	int is32b;
+	int t = q1typ(p) & NQ;
+	int z;
+
+	/* Init */
+	gc->op_save = 0;
+
+	/* Type */
+	if (ISSCALAR(t) && (msizetab[t] == 1))
+		is32b = 0;
+	else if (ISSCALAR(t) && (msizetab[t] == 2))
+		is32b = 1;
+	else
+		ierror(0);
+
+	/* Where to place the destination ? */
+	if (r_z && isreg(&p->z))
+		z = p->z.reg;
+	else
+		z = is32b ? R_REP : R_RF;	/* R_A is needed for the store_op */
+
+	if (r_z) *r_z = z;
+
+	/* Where can we load q1 ? */
+	if (isreg(&p->q1))
+		*r_q1 = p->q1.reg;
+	else if (isconst(&p->q1)) {
+		*r_q1 = R_I;
+		*k = const2long(&p->q1, q1typ(p));
+	} else {
+		if (isreg(&p->q2) || isconst(&p->q2) || (n_op < 2))
+			*r_q1 = R_A;
+		else
+			*r_q1 = z;
+	}
+
+	/* q2 ? */
+	if (n_op != 2)
+		return;
+
+	if (isreg(&p->q2))
+		*r_q2 = p->q2.reg;
+	else if (isconst(&p->q2)) {
+		*r_q2 = R_I;
+		*k = const2long(&p->q2, q2typ(p));
+	} else if (*r_q1 != z) {
+		*r_q2 = z;
+	} else if (!is32b) {
+		*r_q2 = (*r_q1 == R_A) ? R_RE : R_A;
+	} else if (z != R_REP) {
+		*r_q2 = R_REP;
+	} else {
+		/* At this point we have nowhere safe to load a 32b q2 :/ */
+		*r_q2 = _gc_find_reg(gc, 1);
+		if (!*r_q2)
+			*r_q2 = R_RCP;
+		gc->op_save = !regscratch[*r_q2] ? *r_q2 : 0;
+	}
+
+	if (gc->op_save) {
+		struct rpair rp;
+		reg_pair(gc->op_save, &rp);
+		_gc_emit_mov(gc, R_A, rp.r1);
+		_gc_emit(gc, "\tstd\tA, [Y--]\n");
+		_gc_emit_mov(gc, R_A, rp.r2);
+		_gc_emit(gc, "\tstd\tA, [Y--]\n");
+	}
+}
+
+static void
+_gc_op_post(struct gc_state *gc, struct IC *p)
+{
+	if (gc->op_save) {
+		struct rpair rp;
+		reg_pair(gc->op_save, &rp);
+		_gc_emit(gc, "\tldd\tA, [Y++, $1]\n");
+		_gc_emit_mov(gc, rp.r2, R_A);
+		_gc_emit(gc, "\tldd\tA, [Y++, $1]\n");
+		_gc_emit_mov(gc, rp.r1, R_A);
+	}
+
+	gc->op_save = 0;
+}
+
+/* Load an object into a register */
+static void
+_gc_load_op(struct gc_state *gc, struct obj *q, int dst, int typf)
+{
+	struct rpair rp;
+
+	/* Source already in register ? */
+	if (isreg(q))
+	{
+		_gc_move_gpr(gc, dst, q->reg);
+		return;
+	}
+
+	/* Is this a dereference ? */
+	if (q->flags & DREFOBJ)
+	{
+		long ptr_imm = 0;
+		int ptr_reg = 0;
+
+		if (q->flags & KONST) {
+			/* Constant address load */
+			ptr_imm = const2long(q, pointer_type(q->v->vtyp));
+		} else if (q->flags & REG) {
+			/* Dereference value in register */
+			ptr_reg = q->reg;
+		} else {
+			/* Load variable content */
+			ptr_reg = R_A;
+			_gc_load_from_mem(gc, R_A, pointer_type(q->v->vtyp), zm2l(zl2zm(q->val.vlong)), 0, q->v);
+		}
+
+		/* Execute dereference */
+		_gc_load_from_mem(gc, dst, q->dtyp, ptr_imm, ptr_reg, NULL);
+	}
+	else
+	{
+		if (q->flags & KONST) {
+			/* Constant load */
+			long k = const2long(q, typf);
+
+			if (reg_pair(dst, &rp)) {
+				/* 32 bit */
+				long v = k & 0xffff;
+				v = _gc_emit_imm(gc, v);
+				_gc_emit(gc, "\tmov\tA, $%d\n", v);
+				_gc_emit_mov(gc, rp.r1, R_A);
+				v = (k >> 16) & 0xffff;
+				v = _gc_emit_imm(gc, v);
+				_gc_emit(gc, "\tmov\tA, $%d\n", v);
+				_gc_emit_mov(gc, rp.r2, R_A);
+			} else {
+				/* 16 bit */
+				k = _gc_emit_imm(gc, k);
+				_gc_emit(gc, "\tmov\tA, $%d\n", k);
+				_gc_emit_mov(gc, dst, R_A);
+			}
+		} else if (q->flags & VARADR) {
+			/* Variable address load */
+			int tiny = (pointer_type(q->v->vtyp) == DPOINTER) ? TINY_DMEM : TINY_PMEM;
+			long ofs = zm2l(zl2zm(q->val.vlong));
+			char *sym = sym_name(q->v);
+
+			if (!tiny) _gc_emit(gc, "\timm\t$(hi(%s+%d))\n", sym, ofs);
+			_gc_emit(gc, "\tmov\tA, [$(lo(%s+%d))]\n", sym, ofs);
+			_gc_emit_mov(gc, dst, R_A);
+		} else if (!(q->flags & REG)) {
+			/* Variable load */
+			_gc_load_from_mem(gc, dst, pointer_type(q->v->vtyp), zm2l(zl2zm(q->val.vlong)), 0, q->v);
+		}
+	}
+}
+
+/* Store a register into its final destination */
+static void
+_gc_store_op(struct gc_state *gc, struct obj *z, int src, int typf)
+{
+	struct rpair rp;
+	int reg;
+
+	/* Register destination ? */
+	if (isreg(z))
+	{
+		_gc_move_gpr(gc, z->reg, src);
+		return;
+	}
+
+	/* Is this a dereference ? */
+	if (z->flags & DREFOBJ)
+	{
+		long ptr_imm = 0;
+		int ptr_reg = 0;
+
+		if (z->flags & KONST) {
+			/* Constant address load */
+			ptr_imm = const2long(z, pointer_type(z->v->vtyp));
+		} else if (z->flags & REG) {
+			/* Dereference value in register */
+			ptr_reg = z->reg;
+		} else {
+			/* Load variable content */
+			ptr_reg = R_A;
+			_gc_load_from_mem(gc, R_A, pointer_type(z->v->vtyp), zm2l(zl2zm(z->val.vlong)), 0, z->v);
+		}
+
+		/* Execute dereference */
+		_gc_store_to_mem(gc, src, z->dtyp, ptr_imm, ptr_reg, NULL);
+	}
+	else if (z->flags & VAR)
+	{
+		/* Variable store */
+		_gc_store_to_mem(gc, src, pointer_type(z->v->vtyp), zm2l(zl2zm(z->val.vlong)), 0, z->v);
+	}
+	else
+	{
+		/* huh ? */
+		ierror(0);
+	}
+}
+
+
+static void
+gc_func_begin(struct gc_state *gc,
+              FILE *f, struct IC *p, struct Var *v, zmax offset)
+{
+	int i;
+
+	/* Reset state */
+	memset(gc, 0x00, sizeof(struct gc_state));
+
+	gc->f = f;
+
+	/* Init register usage */
+	for (i=1; i<=MAXR; i++)
+		gc->reg_busy[i] = regsa[i];
+
+	/* Section and symbol setup */
+	if (isextern(v->storage_class))
+		emit(f, "\t.text\n%s%s:\n", idprefix, v->identifier);
+	else
+		emit(f, "\t.text\n%s%d:\n", labprefix, zm2l(v->offset));
+
+	/* Debug */
+#ifdef DBG
+	emit(gc->f, "\t; Function prologue\n");
+#endif
+
+	/* Function prologue */
+		/* Save return address */
+	emit(f, "\tmov\tA, X\n");
+	emit(f, "\tstd\tA, [Y--]\n");
+
+		/* Save all registers need saving */
+	for (i=1; i<=MAXR; i++) {
+		if (regused[i] && !regscratch[i] && !regsa[i])
+		{
+			struct rpair rp;
+			if (reg_pair(i, &rp)) {
+				if (!regused[rp.r1]) {
+					emit(f, "\tmov\tA, %s\n", regnames[rp.r1]);
+					emit(f, "\tstd\tA, [Y--]\n");
+					gc->s_savesize += 1;
+				}
+				if (!regused[rp.r2]) {
+					emit(f, "\tmov\tA, %s\n", regnames[rp.r2]);
+					emit(f, "\tstd\tA, [Y--]\n");
+					gc->s_savesize += 1;
+				}
+			} else {
+				emit(f, "\tmov\tA, %s\n", regnames[i]);
+				emit(f, "\tstd\tA, [Y--]\n");
+				gc->s_savesize += 1;
+			}
+		}
+	}
+
+		/* Adjust SP for local variables */
+	gc->s_localsize = zm2l(offset);
+
+	if (gc->s_localsize <= 2) {
+		for (i=0; i<gc->s_localsize; i++)
+			emit(f, "\tldd\tA, [Y--]\n");	/* Useless op */
+	} else {
+		emit(f, "\tmov\tA, Y\n");
+		emit(f, "\tadd\tA, A, $%d\n", -gc->s_localsize);
+		emit(f, "\tmov\tY, A\n");
+	}
+
+	/* Modifieds regs in all cases */
+	BSET(regs_modified, R_A);
+	BSET(regs_modified, R_X);
+	BSET(regs_modified, R_Y);
+}
+
+static void
+gc_func_end(struct gc_state *gc,
+            FILE *f, struct IC *p, struct Var *v, zmax offset)
+{
+	int i;
+
+	/* Debug */
+#ifdef DBG
+	emit(gc->f, "\n\t; Function epilogue\n");
+#endif
+
+	/* Function epilogue */
+		/* Re-adjust SP */
+	if (gc->s_localsize <= 2) {
+		for (i=0; i<gc->s_localsize; i++)
+			emit(f, "\tldd\tA, [Y++]\n");	/* Useless op */
+	} else {
+		emit(f, "\tmov\tA, Y\n");
+		emit(f, "\tadd\tA, A, $%d\n", gc->s_localsize);
+		emit(f, "\tmov\tY, A\n");
+	}
+
+		/* Restore saved registers */
+	for (i=MAXR; i>=1; i--) {
+		if (regused[i] && !regscratch[i] && !regsa[i])
+		{
+			struct rpair rp;
+			if (reg_pair(i, &rp)) {
+				if (!regused[rp.r2]) {
+					emit(f, "\tldd\tA, [Y++, $1]\n");
+					emit(f, "\tmov\t%s, A\n", regnames[rp.r2]);
+				}
+				if (!regused[rp.r1]) {
+					emit(f, "\tldd\tA, [Y++, $1]\n");
+					emit(f, "\tmov\t%s, A\n", regnames[rp.r1]);
+				}
+			} else {
+				emit(f, "\tldd\tA, [Y++, $1]\n");
+				emit(f, "\tmov\t%s, A\n", regnames[i]);
+			}
+		}
+	}
+
+		/* Return address */
+	emit(f, "\tldd\tA, [Y++, $1]\n");
+	emit(f, "\tmov\tX, A\n");
+
+		/* Return value */
+	emit(f, "\tbax\n");
+	if (gc->reg_rv)
+		emit(f, "\tmov\tA, %s\n", regnames[gc->reg_rv]);
+	else
+		emit(f, "\tmov\tA, $%d\n", gc->val_rv);
+
+	/* Bit of spacing */
+	emit(gc->f, "\n\n");
+}
+
+static void
+gc_func_assign(struct gc_state *gc, struct IC *node)
+{
+	/* FIXME: Only works for size=1 | size=2 ... */
+	int v_reg;
+
+	if (isreg(&node->q1)) {
+		v_reg = node->q1.reg;
+	} else {
+		v_reg = _gc_store_sel(node);
+		_gc_load_op(gc, &node->q1, v_reg, q1typ(node));
+	}
+
+	_gc_store_op(gc, &node->z, v_reg, ztyp(node));
+}
+
+static void
+gc_func_convert(struct gc_state *gc, struct IC *node)
+{
+	struct rpair rp;
+	int qt = q1typ(node) & NQ;
+	int zt = ztyp(node)  & NQ;
+	int sext = !(q1typ(node) & UNSIGNED);
+	int v_reg;
+
+	if ((zt == LONG) && (qt >= CHAR) && (qt <= INT)) {
+		/* Convert from short to long */
+		v_reg = _gc_store_sel(node);
+
+		if (!reg_pair(v_reg, &rp))
+			ierror(0);
+
+		_gc_load_op(gc, &node->q1, rp.r1, q1typ(node));
+
+		if (sext) {
+			_gc_emit_alu(gc, "rol", R_A, rp.r1, 0, 0);
+			_gc_emit_alu(gc, "and", R_A, R_A, R_I, 1);
+			_gc_emit_alu(gc, "sub", R_A, R_A, R_I, 0);
+			_gc_emit_mov(gc, rp.r2, R_A);
+		} else {
+			_gc_emit(gc, "\tmov\tA, $0\n");
+			_gc_emit_mov(gc, rp.r2, R_A);
+		}
+	} else if ((zt >= CHAR) && (zt <= INT) && (qt == LONG)) {
+		/* Convert from long to short */
+		if (isreg(&node->q1)) {
+			/* Long already in register, so get the LSB from pair and do store */
+			if (!reg_pair(node->q1.reg, &rp))
+				ierror(0);
+
+			v_reg = rp.r1;
+		} else {
+			/* Perform a load as if it was a short. Because of Little-Endian, it works */
+			v_reg = _gc_store_sel(node);
+			_gc_load_op(gc, &node->q1, v_reg, q1typ(node));
+		}
+	} else if (ISPOINTER(zt) && ISPOINTER(qt)) {
+		/* No way to convert between pointer types to different spaces ... */
+		ierror(1);
+	} else {
+		/* Shouldn't happen, all other conversions are lib_call */
+		ierror(0);
+	}
+
+	_gc_store_op(gc, &node->z, v_reg, ztyp(node));
+}
+
+static void
+gc_func_alu_2op(struct gc_state *gc, struct IC *node)
+{
+	const char *opcode, *opcode2;
+	struct rpair rpz, rp1, rp2;
+	int regz, reg1, reg2, regt;
+	long k;
+	int is32b, issub, isadd;
+
+	is32b = ISTLONG(ztyp(node));
+	isadd = (node->code == ADD) || (node->code == ADDI2P);
+	issub = (node->code == SUB) || (node->code == SUBIFP) || (node->code == SUBPFP);
+
+	/* Load operands */
+	_gc_op_pre(gc, node, 2, &regz, &reg1, &reg2, &k);
+
+	if (!isreg(&node->q1) && !isconst(&node->q1))
+		_gc_load_op(gc, &node->q1, reg1, q1typ(node));
+
+	if (!isreg(&node->q2) && !isconst(&node->q2))
+		_gc_load_op(gc, &node->q2, reg2, q2typ(node));
+
+	/* We can only have immediate in reg2. Also 'sub' is swapped vs hw */
+	if (issub) {
+		if (reg2 == R_I) {
+			node->code = ADD;
+			k = -k;
+		} else {
+			regt = reg1;
+			reg1 = reg2;
+			reg2 = regt;
+		}
+	} else if (reg1 == R_I) {
+		regt = reg1;
+		reg1 = reg2;
+		reg2 = regt;
+	}
+
+	/* Solve reg-pairs */
+	reg_pair(regz, &rpz);
+	reg_pair(reg1, &rp1);
+	reg_pair(reg2, &rp2);
+
+	if (reg2 == R_I)
+		rp2.r1 = rp2.r2 = R_I;
+
+	/* Select opcode */
+	switch (node->code) {
+	case OR:  opcode = "or";  opcode2 = "or";   break;
+	case XOR: opcode = "xor"; opcode2 = "xor";   break;
+	case AND: opcode = "and"; opcode2 = "and";   break;
+	case ADD: opcode = "add"; opcode2 = "addcy"; break;
+	case SUB: opcode = "sub"; opcode2 = "subcy"; break;
+	case ADDI2P: opcode = "add"; opcode2 = NULL; break;
+	case SUBIFP: opcode = "sub"; opcode2 = NULL; break;
+	case SUBPFP: opcode = "sub"; opcode2 = NULL; break;
+	default: ierror(0);
+	}
+
+	/* Do the operation */
+	if (is32b) {
+		if (regz == reg1) {
+			if (reg2 == R_I) {
+				/* 1 single GPR (reg1 == regz) and one immediate */
+				_gc_emit_alu(gc, opcode,  rpz.r1, rp1.r1, R_I, k & 0xffff);
+				_gc_emit_alu(gc, opcode2, rpz.r2, rp1.r2, R_I, (k >> 16) & 0xffff);
+			} else {
+				/* 2 different GPRs, reg1 == regz */
+				_gc_emit_mov(gc, R_A, rp2.r1);
+				_gc_emit_alu(gc, opcode,  rpz.r1, rp1.r1, R_A, 0);
+				_gc_emit_mov(gc, R_A, rp2.r2);
+				_gc_emit_alu(gc, opcode2, rpz.r2, rp1.r2, R_A, 0);
+			}
+		} else if (regz == reg2) {
+			/* 2 different GPRs, reg2 == regz */
+			_gc_emit_mov(gc, R_A, rp1.r1);
+			_gc_emit_alu(gc, opcode,  rpz.r1, R_A, rp2.r1, 0);
+			_gc_emit_mov(gc, R_A, rp1.r2);
+			_gc_emit_alu(gc, opcode2, rpz.r2, R_A, rp2.r2, 0);
+		} else if (reg2 == R_I) {
+			/* 2 different GPRs and one immediate */
+			_gc_emit_mov(gc, R_A, rp1.r1);
+			_gc_emit_alu(gc, opcode,  rpz.r1, R_A, rp2.r1, k & 0xffff);
+			_gc_emit_mov(gc, R_A, rp1.r2);
+			_gc_emit_alu(gc, opcode2, rpz.r2, R_A, rp2.r2, (k >> 16) & 0xffff);
+		} else {
+			/* 3 different GPRs pair */
+			_gc_emit_mov(gc, R_A, rp1.r1);
+			_gc_emit_alu(gc, opcode,  R_A, R_A, rp2.r1, 0);
+			_gc_emit_mov(gc, rpz.r1, R_A);
+			_gc_emit_mov(gc, R_A, rp1.r2);
+			_gc_emit_alu(gc, opcode2, R_A, R_A, rp2.r2, 0);
+			_gc_emit_mov(gc, rpz.r2, R_A);
+		}
+	} else {
+		/* Count GPRs */
+		int ngpr = isgpr(regz) + isgpr(reg1) + isgpr(reg2);
+
+		/* Detect INC / DEC */
+		if ((reg2 == R_I) && ((k == 1) || (k == -1)) && (isadd || issub))
+		{
+			opcode = ((k == -1) ^ (node->code == SUB)) ? "dec" : "inc";
+
+			if ((regz == reg1) || (regz == R_A) || (reg1 == R_A)) {
+				_gc_emit_alu(gc, opcode, regz, reg1, 0, 0);
+			} else {
+				_gc_emit_alu(gc, opcode, R_A, reg1, 0, 0);
+				_gc_emit_mov(gc, regz, R_A);
+			}
+		}
+
+		/* Classic ALU */
+		else if (ngpr < 2) {
+			_gc_emit_alu(gc, opcode, regz, reg1, reg2, k);
+		} else if (ngpr == 2) {
+			if (regz == R_A) {
+				_gc_emit_mov(gc, R_A, reg1);
+				_gc_emit_alu(gc, opcode, R_A, R_A, reg2, k);
+			} else if ((regz == reg1) || (regz == reg2)) {
+				_gc_emit_alu(gc, opcode, regz, reg1, reg2, k);
+			} else {
+				_gc_emit_alu(gc, opcode, R_A, reg1, reg2, k);
+				_gc_emit_mov(gc, regz, R_A);
+			}
+		} else {
+			if (regz == reg1) {
+				_gc_emit_mov(gc, R_A, reg2);
+				_gc_emit_alu(gc, opcode, regz, regz, R_A, 0);
+			} else if (regz == reg2) {
+				_gc_emit_mov(gc, R_A, reg1);
+				_gc_emit_alu(gc, opcode, regz, regz, R_A, 0);
+			} else {
+				_gc_emit_mov(gc, R_A, reg1);
+				_gc_emit_alu(gc, opcode, R_A, R_A, reg2, 0);
+				_gc_emit_mov(gc, regz, R_A);
+			}
+		}
+	}
+
+	/* Store result */
+	_gc_store_op(gc, &node->z, regz, ztyp(node));
+
+	/* Allow 'test' optimization */
+	gc->cmp_cur_z = regz;
+
+	/* Clean up */
+	_gc_op_post(gc, node);
+}
+
+static void
+gc_func_not(struct gc_state *gc, struct IC *node)
+{
+	struct rpair rp;
+	int l_reg, z_reg, is32b;
+
+	z_reg = _gc_store_sel(node);
+	is32b = reg_pair(z_reg, &rp);
+	l_reg = (is32b || (isreg(&node->q1) && (node->q1.reg != z_reg))) ? z_reg : R_A;
+
+	_gc_load_op(gc, &node->q1, l_reg, q1typ(node));
+
+	if (is32b) {
+		_gc_emit(gc, "\tmov\tA, $0xffff\n");
+		_gc_emit_alu(gc, "xor", rp.r1, rp.r1, R_A, 0);
+		_gc_emit_alu(gc, "xor", rp.r2, rp.r2, R_A, 0);
+	} else {
+		_gc_emit_alu(gc, "xor", z_reg, l_reg, R_I, 0xffff);
+	}
+
+	_gc_store_op(gc, &node->z, z_reg, ztyp(node));
+}
+
+static void
+gc_func_neg(struct gc_state *gc, struct IC *node)
+{
+	struct rpair rp;
+	int l_reg, z_reg, is32b;
+
+	z_reg = _gc_store_sel(node);
+	is32b = reg_pair(z_reg, &rp);
+	l_reg = (is32b || (isreg(&node->q1) && (node->q1.reg != z_reg))) ? z_reg : R_A;
+
+	_gc_load_op(gc, &node->q1, l_reg, q1typ(node));
+
+	if (is32b) {
+		_gc_emit(gc, "\tmov\tA, $0\n");
+		_gc_emit_alu(gc, "sub",  rp.r1, rp.r1, R_A, 0);
+		_gc_emit_alu(gc, "subcy", rp.r2, rp.r2, R_A, 0);
+	} else {
+		_gc_emit_alu(gc, "sub", z_reg, l_reg, R_I, 0);
+	}
+
+	_gc_store_op(gc, &node->z, z_reg, ztyp(node));
+}
+
+static void
+gc_func_shift(struct gc_state *gc, struct IC *node)
+{
+	/* FIXME */
+}
+
+static void
+gc_func_allocreg(struct gc_state *gc, struct IC *node)
+{
+	struct rpair rp;
+	int reg = node->q1.reg;
+
+	if (reg_pair(reg, &rp)) {
+		gc->reg_busy[rp.r1] = 1;
+		gc->reg_busy[rp.r2] = 1;
+	}
+	gc->reg_busy[reg] = 1;
+}
+
+static void
+gc_func_freereg(struct gc_state *gc, struct IC *node)
+{
+	int reg = node->q1.reg;
+	if (regsa[reg])
+		return;
+
+	if (reg_pair(reg, &rp)) {
+		gc->reg_busy[rp.r1] = 0;
+		gc->reg_busy[rp.r2] = 0;
+	}
+	gc->reg_busy[reg] = 0;
+}
+
+static void
+gc_func_cmp_test(struct gc_state *gc, struct IC *node)
+{
+	struct rpair rp1, rp2;
+	int reg1, reg2;
+	long k;
+	int istest, is32b;
+
+	istest = (node->code == TEST);
+	is32b = ISTLONG(q1typ(node));
+
+	/* Can this be optimized out ? */
+	if (istest && isreg(&node->q1) && (node->q1.reg == gc->cmp_cur_z))
+		return;
+
+	/* Load operands */
+	_gc_op_pre(gc, node, istest?1:2, NULL, &reg1, &reg2, &k);
+
+	if (!isreg(&node->q1) && !isconst(&node->q1))
+		_gc_load_op(gc, &node->q1, reg1, q1typ(node));
+
+	if (!istest && !isreg(&node->q2) && !isconst(&node->q2))
+		_gc_load_op(gc, &node->q2, reg2, q2typ(node));
+
+	reg_pair(reg1, &rp1);
+	reg_pair(reg2, &rp2);
+
+	if (reg2 == R_I)
+		rp2.r1 = rp2.r2 = R_I;
+
+	/* Do the compare */
+	if (is32b) {
+		/* 32b compare */
+		if (istest) {
+			_gc_emit_mov(gc, R_A, rp1.r2);
+			_gc_emit_alu(gc, "or", R_A, R_A, rp1.r1, 0);
+		} else {
+			_gc_emit_mov(gc, R_A, rp1.r1);
+			_gc_emit_alu(gc, "sub", R_A, R_A, rp2.r1, k & 0xffff);
+			_gc_emit_mov(gc, R_A, rp1.r2);
+			_gc_emit_alu(gc, "subcy", R_A, R_A, rp2.r2, (k >> 16) & 0xffff);
+		}
+	} else {
+		/* 16b compare */
+		if (node->code == TEST) {
+			_gc_emit_alu(gc, "test", 0, reg1, R_I, 0xffff);
+		} else {
+			_gc_emit_alu(gc, "cmp", 0, reg1, reg2, k);
+		}
+	}
+
+	/* Clean up */
+	_gc_op_post(gc, node);
+}
+
+static void
+gc_func_branch(struct gc_state *gc, struct IC *node)
+{
+	const char *cc, *ecc;
+	char label[16];
+
+	/* If q1 exists, it's the result of an lib_call compare */
+	if (node->q1.flags) {
+		int r;
+		if (isreg(&node->q1)) {
+			r = node->q1.reg;
+		} else {
+			_gc_load_op(gc, &node->q1, R_A, q1typ(node));
+			r = R_A;
+		}
+		_gc_emit_alu(gc, "cmp", 0, r, -1, 0);
+		gc->cmp_signed = 1;
+	}
+
+	/* Select condition code */
+	switch (node->code) {
+		case BRA: ecc = NULL; cc = ""; break;
+		case BEQ: ecc = NULL; cc = ".z"; break;
+		case BNE: ecc = NULL; cc = ".nz"; break;
+		case BLT: ecc = gc->cmp_signed ? "gt" : "hi"; cc = ".z"; break;
+		case BGE: ecc = gc->cmp_signed ? "gt" : "hi"; cc = ".nz"; break;
+		case BLE: ecc = gc->cmp_signed ? "ge" : "hs"; cc = ".z"; break;
+		case BGT: ecc = gc->cmp_signed ? "ge" : "hs"; cc = ".nz"; break;
+		default: ierror(0);
+	}
+
+	if (ecc)
+		_gc_emit(gc, "\tcc\t%s\n", ecc);
+
+	snprintf(label, sizeof(label)-1, "%s%d", labprefix, node->typf);
+	_gc_emit(gc, "\timm\t$hi(%s)\n", label);
+	_gc_emit(gc, "\tba%s\t$lo(%s)\n", cc, label);
+	_gc_emit_nop(gc);
+}
+
+static void
+gc_func_label(struct gc_state *gc, struct IC *node)
+{
+	_gc_emit(gc, "%s%d:\n", labprefix, node->typf);
+}
+
+static void
+gc_func_call(struct gc_state *gc, struct IC *node)
+{
+	if ((node->q1.flags & (VAR | DREFOBJ)) == VAR &&
+	     node->q1.v->fi && node->q1.v->fi->inline_asm)
+	{
+		emit_inline_asm(gc->f, node->q1.v->fi->inline_asm);
+	}
+	else if (node->q1.flags & DREFOBJ)
+	{
+		/* Function pointer */
+		if (node->q1.dtyp != PPOINTER)
+			ierror(1);
+
+		if (node->q1.flags & KONST) {
+			/* Constant, do immediate jump */
+			long k = const2long(&node->q1, node->q1.dtyp);
+			k = _gc_emit_imm(gc, k);
+			_gc_emit(gc, "\tbal\t$%d\n", k);
+		} else {
+			/* Load variable into A */
+			if (node->q1.flags & REG)
+				_gc_emit_mov(gc, R_A, node->q1.reg);
+			else
+				_gc_load_from_mem(gc, R_A, pointer_type(node->q1.v->vtyp), zm2l(zl2zm(node->q1.val.vlong)), 0, node->q1.v);
+
+			/* Do the jump */
+			_gc_emit_mov(gc, R_X, R_A);
+			_gc_emit(gc, "\tbalx\tX\n");
+		}
+
+		_gc_emit_nop(gc);
+	}
+	else
+	{
+		char *sym = sym_name(node->q1.v);
+
+		if (!TINY_PMEM) _gc_emit(gc, "\timm\t$(hi(%s))\n", sym);
+		_gc_emit(gc, "\tbal\t$(lo(%s))\n", sym);
+
+		_gc_emit_nop(gc);
+	}
+
+	/* FIXME: fixup stack pointer after the call ?!? */
+}
+
+static void
+gc_func_push(struct gc_state *gc, struct IC *node)
+{
+	/* FIXME */
+}
+
+static void
+gc_func_getreturn(struct gc_state *gc, struct IC *node)
+{
+	int dst_reg;
+
+	/* Is it relevant at all ? */
+	if (!node->q1.reg) {
+		ierror(0);
+		return;
+	}
+
+	/* Is the target a register ? */
+	if (isreg(&node->z))
+	{
+		/* Yes, need move */
+		_gc_move_gpr(gc, node->z.reg, node->q1.reg);
+	} else {
+		/* Nope, not supported */
+		ierror(0);
+	}
+}
+
+static void
+gc_func_setreturn(struct gc_state *gc, struct IC *node)
+{
+	int src_reg;
+
+	/* Is it relevant at all ? */
+	if (!node->z.reg) {
+		ierror(0);
+		return;
+	}
+
+	/* Special case for small constants */
+	if ((node->z.reg == R_A) && isconst(&node->q1)) {
+		gc->val_rv = const2long(&node->q1, q1typ(node));
+		return;
+	}
+
+	/* Load value into register */
+	src_reg = node->z.reg;
+	_gc_load_op(gc, &node->q1, src_reg, q1typ(node));
+
+	/* If the target is R_A, we need to defer */
+	if (node->z.reg == R_A) {
+		if ((regscratch[src_reg] || regsa[src_reg]) && (src_reg != R_A)) {
+			gc->reg_rv = src_reg;
+		} else {
+			_gc_emit_mov(gc, R_A, src_reg);
+			_gc_emit_mov(gc, R_R0, R_A);
+			gc->reg_rv = R_R0;
+			gc->reg_lw = R_R0;
+			BSET(regs_modified, R_R0);
+		}
+	} else {
+		_gc_move_gpr(gc, node->z.reg, src_reg);
+	}
+}
+
+static void
+gc_func_movefromreg(struct gc_state *gc, struct IC *node)
+{
+	_gc_store_op(gc, &node->z, node->q1.reg, ztyp(node));
+}
+
+static void
+gc_func_movetoreg(struct gc_state *gc, struct IC *node)
+{
+	_gc_load_op(gc, &node->q1, node->z.reg, q1typ(node));
+}
+
+static void
+gc_func_address(struct gc_state *gc, struct IC *node)
+{
+	long sp_offset;
+
+	/* q1 is always an 'auto' (stack object) */
+	if (ztyp(node) != DPOINTER)
+		ierror(1);
+
+	if (!isauto(node->q1.v->storage_class))
+		ierror(0);
+
+	/* Compute real offset */
+	sp_offset = _gc_real_offset(gc, node->q1.v, zm2l(zl2zm(node->q1.val.vlong)));
+
+	_gc_emit_mov(gc, R_A, R_Y);
+	_gc_emit_alu(gc, "add", R_A, R_A, R_I, sp_offset);
+
+	/* Store it where we were asked */
+	_gc_store_op(gc, &node->z, R_A, ztyp(node));
+}
+
+static void
+gc_func_ic(struct gc_state *gc, struct IC *node)
+{
+	/* If nop, abort early */
+	if (node->code == NOP)
+		return;
+
+	/* Un-needed converts */
+	if (node->code == CONVERT && !must_convert(node->typf,node->typf2,0)) {
+		node->code = ASSIGN;
+		node->q2.val.vmax = sizetab[node->typf&NQ];
+	}
+
+	/* Debug */
+#ifdef DBG
+	emit(gc->f, "\n\t; %s\n", ename[node->code]);
+#endif
+
+	/* Main dispatch */
+#define GC_OP(c,n) case c: gc_func_ ## n (gc, node); break;
+
+	switch (node->code)
+	{
+	GC_OP(ASSIGN,		assign)
+	GC_OP(CONVERT,		convert)
+	GC_OP(OR,		alu_2op)
+	GC_OP(XOR,		alu_2op)
+	GC_OP(AND,		alu_2op)
+	GC_OP(ADD,		alu_2op)
+	GC_OP(SUB,		alu_2op)
+	GC_OP(KOMPLEMENT,	not)
+	GC_OP(MINUS,		neg)
+	GC_OP(LSHIFT,		shift)
+	GC_OP(RSHIFT,		shift)
+	GC_OP(ALLOCREG, 	allocreg)
+	GC_OP(FREEREG,		freereg)
+	GC_OP(COMPARE,		cmp_test)
+	GC_OP(TEST,		cmp_test)
+	GC_OP(BEQ ... BRA,	branch)
+	GC_OP(LABEL,		label)
+	GC_OP(CALL,		call)
+	GC_OP(PUSH,		push)
+	GC_OP(GETRETURN,	getreturn)
+	GC_OP(SETRETURN,	setreturn)
+	GC_OP(MOVEFROMREG,	movefromreg)
+	GC_OP(MOVETOREG,	movetoreg)
+	GC_OP(ADDRESS,		address)
+	GC_OP(ADDI2P,		alu_2op)
+	GC_OP(SUBIFP,		alu_2op)
+	GC_OP(SUBPFP,		alu_2op)
+
+		/* Those are always handled with libcall */
+	case MULT:
+	case DIV:
+	case MOD:
+	default:
+		break;//ierror(0);
+	}
+
+#undef GC_OP
+}
+
+
+/****************************************/
+/*  End of private fata and functions.  */
+/****************************************/
+
+/*  Does necessary initializations for the code-generator. Gets called  */
+/*  once at the beginning and should return 0 in case of problems.      */
+int init_cg(void)
+{
+	int i, j;
+
+	/* Macros */
+	target_macros = marray;
+
+	/* Alignement / size for types */
+	stackalign = l2zm(1L);
+	maxalign   = l2zm(1L);
+	char_bit   = l2zm(16L);
+
+	for (i=0; i<=MAX_TYPE; i++) {
+		sizetab[i]=l2zm(msizetab[i]);
+		align[i]=l2zm(malign[i]);
+	}
+
+	/* Registers */
+	regnames[0] = "noreg";
+
+		/* Defaults */
+	memset(regscratch, 0x00, sizeof(regscratch));
+	memset(regsa,      0x00, sizeof(regsa));
+	memset(reg_prio,   0x00, sizeof(reg_prio));
+
+		/* GPRs rX:  1-16 */
+	for (i=0; i<16; i++)
+	{
+		j = R_R0 + i;
+		regnames[j] = mymalloc(3);
+		sprintf(regnames[j], "r%x", i);
+		regsize[j] = l2zm(1L);
+		regtype[j] = &ityp;
+	}
+
+		/* GPRs sX: 17-32 */
+	for (i=0; i<16; i++)
+	{
+		j = R_S0 + i;
+		regnames[j] = mymalloc(3);
+		sprintf(regnames[j], "s%x", i);
+		regsize[j] = l2zm(1L);
+		regtype[j] = &ityp;
+	}
+
+		/* GPRs pair rXp: 33-40 */
+	for (i=0; i<8; i++)
+	{
+		j = R_R0P + i;
+		regnames[j] = mymalloc(3);
+		sprintf(regnames[j], "r%xp", 2*i);
+		regsize[j] = l2zm(2L);
+		regtype[j] = &ltyp;
+	}
+
+		/* GPRs pair sXp: 41-48 */
+	for (i=0; i<8; i++)
+	{
+		j = R_S0P + i;
+		regnames[j] = mymalloc(3);
+		sprintf(regnames[j], "s%xp", 2*i);
+		regsize[j] = l2zm(2L);
+		regtype[j] = &ltyp;
+	}
+
+		/* Use the first 8 registers as scratch
+		 * registers */
+	for (i=0; i<8; i++) {
+		regscratch[R_R0 + i] = 1;
+		regscratch[R_S0 + i] = 1;
+	}
+
+	for (i=0; i<4; i++) {
+		regscratch[R_R0P + i] = 1;
+		regscratch[R_S0P + i] = 1;
+	}
+
+		/* Code gen internally uses re/rf pair */
+	regsa[R_RE] = regsa[R_RF] = regsa[R_REP] = 1;
+
+		/* Priority */
+	/* FIXME: TODO */
+
+		/* SPRs: 49-51 */
+	regnames[R_A] = "A";
+	regsize[R_A]  = l2zm(1L);
+	regtype[R_A]  = &ityp;
+	regsa[R_A]    = 1;		/* Special, used by codegen */
+
+	regnames[R_X] = "X";
+	regsize[R_X]  = l2zm(1L);
+	regtype[R_X]  = &ityp;
+	regsa[R_X]    = 1;		/* Link Register */
+
+	regnames[R_Y] = "Y";
+	regsize[R_Y]  = l2zm(1L);
+	regtype[R_Y]  = &ityp;
+	regsa[R_Y]    = 1;		/* Used as Stack pointer */
+
+	regnames[R_I] = "I";
+	regsize[R_I]  = l2zm(1L);
+	regtype[R_I]  = &ityp;
+	regsa[R_I]    = 1;		/* Virtual Immediate register */
+
+	/*  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.          */
+	t_min[CHAR]=l2zm(-32768L);
+	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(32767UL);
+	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(65535UL);
+	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);
+
+	/* Built-ins */
+#define UINT	(UNSIGNED|INT)
+#define ULONG	(UNSIGNED|LONG)
+#define ULLONG	(UNSIGNED|LLONG)
+
+		/* 16 bit ops: lsl/lsr + mul/div/mod done in libcall */
+	declare_builtin("__lslint16",  INT,  INT,  R_R0, INT,  R_R1, 1, 0);
+	declare_builtin("__lsrint16",  INT,  INT,  R_R0, INT,  R_R1, 1, 0);
+	declare_builtin("__lsruint16", UINT, UINT, R_R0, INT,  R_R1, 1, 0);
+
+	declare_builtin("__mulint16",  INT,  INT,  R_R0, INT,  R_R1, 1, 0);
+	declare_builtin("__divint16",  INT,  INT,  R_R0, INT,  R_R1, 1, 0);
+	declare_builtin("__divuint16", UINT, UINT, R_R0, UINT, R_R1, 1, 0);
+	declare_builtin("__modint16",  INT,  INT,  R_R0, INT,  R_R1, 1, 0);
+	declare_builtin("__moduint16", UINT, UINT, R_R0, UINT, R_R1, 1, 0);
+
+		/* 32 bit ops: lsl/lsr + mul/div/mod done in libcall */
+	declare_builtin("__lslint32",  LONG,  LONG,  R_R0P, INT,   R_R2,  1, 0);
+	declare_builtin("__lsrint32",  LONG,  LONG,  R_R0P, INT,   R_R2,  1, 0);
+	declare_builtin("__lsruint32", ULONG, ULONG, R_R0P, INT,   R_R2,  1, 0);
+
+	declare_builtin("__mulint32",  LONG,  LONG,  R_R0P, LONG,  R_R2P, 1, 0);
+	declare_builtin("__divint32",  LONG,  LONG,  R_R0P, LONG,  R_R2P, 1, 0);
+	declare_builtin("__divuint32", ULONG, ULONG, R_R0P, ULONG, R_R2P, 1, 0);
+	declare_builtin("__modint32",  LONG,  LONG,  R_R0P, LONG,  R_R2P, 1, 0);
+	declare_builtin("__moduint32", ULONG, ULONG, R_R0P, ULONG, R_R2P, 1, 0);
+
+		/* 64 bits ops: everything done in libcall */
+	declare_builtin("__orint64",   LLONG,  LLONG, 0,  LLONG,  0, 1, 0);
+	declare_builtin("__eorint64",  LLONG,  LLONG, 0,  LLONG,  0, 1, 0);
+	declare_builtin("__andint64",  LLONG,  LLONG, 0,  LLONG,  0, 1, 0);
+
+	declare_builtin("__lslint64",  LLONG,  LLONG,  0, INT,    0, 1, 0);
+	declare_builtin("__lsrint64",  LLONG,  LLONG,  0, INT,    0, 1, 0);
+	declare_builtin("__lsruint64", ULLONG, ULLONG, 0, INT,    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("__mulint64",  LLONG,  LLONG,  0, LLONG,  0, 1, 0);
+	declare_builtin("__divint64",  LLONG,  LLONG,  0, LLONG,  0, 1, 0);
+	declare_builtin("__divuint64", ULLONG, ULLONG, 0, ULLONG, 0, 1, 0);
+	declare_builtin("__modint64",  LLONG,  LLONG,  0, LLONG,  0, 1, 0);
+	declare_builtin("__moduint64", ULLONG, ULLONG, 0, ULLONG, 0, 1, 0);
+
+	declare_builtin("__negint64",  LLONG,  LLONG,  0, 0,      0, 1, 0);
+	declare_builtin("__notint64",  LLONG,  LLONG,  0, 0,      0, 1, 0);
+
+	declare_builtin("__cmpint64",  INT,    LLONG,  0, LLONG,  0, 1, 0);
+	declare_builtin("__cmpuint64", INT,    ULLONG, 0, ULLONG, 0, 1, 0);
+
+		/* 64 bits conversions */
+	declare_builtin("__uint64touint16", ULLONG,  UINT, R_R0,  0, 0, 1, 0);
+	declare_builtin("__uint64tosint16", ULLONG,   INT, R_R0,  0, 0, 1, 0);
+	declare_builtin("__uint64touint32", ULLONG, ULONG, R_R0P, 0, 0, 1, 0);
+	declare_builtin("__uint64tosint32", ULLONG,  LONG, R_R0P, 0, 0, 1, 0);
+
+	declare_builtin("__sint64touint16",  LLONG,  UINT, R_R0,  0, 0, 1, 0);
+	declare_builtin("__sint64tosint16",  LLONG,   INT, R_R0,  0, 0, 1, 0);
+	declare_builtin("__sint64touint32",  LLONG, ULONG, R_R0P, 0, 0, 1, 0);
+	declare_builtin("__sint64tosint32",  LLONG,  LONG, R_R0P, 0, 0, 1, 0);
+
+	declare_builtin("__uint16touint64",  UINT, ULLONG, 0, 0, 0, 1, 0);
+	declare_builtin("__sint16touint64",   INT, ULLONG, 0, 0, 0, 1, 0);
+	declare_builtin("__uint32touint64", ULONG, ULLONG, 0, 0, 0, 1, 0);
+	declare_builtin("__sint32touint64",  LONG, ULLONG, 0, 0, 0, 1, 0);
+
+	declare_builtin("__uint16tosint64",  UINT,  LLONG, 0, 0, 0, 1, 0);
+	declare_builtin("__sint16tosint64",   INT,  LLONG, 0, 0, 0, 1, 0);
+	declare_builtin("__uint32tosint64", ULONG,  LLONG, 0, 0, 0, 1, 0);
+	declare_builtin("__sint32tosint64",  LONG,  LLONG, 0, 0, 0, 1, 0);
+
+		/* Float / Int conversions */
+			/* int16 */
+	declare_builtin("__sint16toflt32", FLOAT,  INT,  R_R0,  0, 0, 1, 0);
+	declare_builtin("__uint16toflt32", FLOAT,  UINT, R_R0,  0, 0, 1, 0);
+	declare_builtin("__sint16toflt64", DOUBLE, INT,  R_R0,  0, 0, 1, 0);
+	declare_builtin("__uint16toflt64", DOUBLE, UINT, R_R0,  0, 0, 1, 0);
+
+	declare_builtin("__flt32tosint16", INT,  FLOAT,  R_R0P, 0, 0, 1, 0);
+	declare_builtin("__flt32touint16", UINT, FLOAT,  R_R0P, 0, 0, 1, 0);
+	declare_builtin("__flt64tosint16", INT,  DOUBLE, 0,     0, 0, 1, 0);
+	declare_builtin("__flt64touint16", UINT, DOUBLE, 0,     0, 0, 1, 0);
+
+			/* int32 */
+	declare_builtin("__sint32toflt32", FLOAT,  LONG,  R_R0P, 0, 0, 1, 0);
+	declare_builtin("__uint32toflt32", FLOAT,  ULONG, R_R0P, 0, 0, 1, 0);
+	declare_builtin("__sint32toflt64", DOUBLE, LONG,  R_R0P, 0, 0, 1, 0);
+	declare_builtin("__uint32toflt64", DOUBLE, ULONG, R_R0P, 0, 0, 1, 0);
+
+	declare_builtin("__flt32tosint32", LONG,  FLOAT,  R_R0P, 0, 0, 1, 0);
+	declare_builtin("__flt32touint32", ULONG, FLOAT,  R_R0P, 0, 0, 1, 0);
+	declare_builtin("__flt64tosint32", LONG,  DOUBLE, 0,     0, 0, 1, 0);
+	declare_builtin("__flt64touint32", ULONG, DOUBLE, 0,     0, 0, 1, 0);
+
+			/* int64 */
+	declare_builtin("__sint64toflt32", FLOAT,  LLONG,  0, 0, 0, 1, 0);
+	declare_builtin("__uint64toflt32", FLOAT,  ULLONG, 0, 0, 0, 1, 0);
+	declare_builtin("__sint64toflt64", DOUBLE, LLONG,  0, 0, 0, 1, 0);
+	declare_builtin("__uint64toflt64", DOUBLE, ULLONG, 0, 0, 0, 1, 0);
+
+	declare_builtin("__flt32tosint64", LLONG,  FLOAT,  0, 0, 0, 1, 0);
+	declare_builtin("__flt32touint64", ULLONG, FLOAT,  0, 0, 0, 1, 0);
+	declare_builtin("__flt64tosint64", LLONG,  DOUBLE, 0, 0, 0, 1, 0);
+	declare_builtin("__flt64touint64", ULLONG, DOUBLE, 0, 0, 0, 1, 0);
+
+		/* Inter-Float conversions */
+	declare_builtin("__flt32toflt64", DOUBLE, FLOAT,  0, 0, 0, 1, 0);
+	declare_builtin("__flt64toflt32", FLOAT,  DOUBLE, 0, 0, 0, 1, 0);
+
+		/* Floating point math */
+			/* float */
+	declare_builtin("__addflt32", FLOAT, FLOAT, R_R0P, FLOAT, R_R2P, 1, 0);
+	declare_builtin("__subflt32", FLOAT, FLOAT, R_R0P, FLOAT, R_R2P, 1, 0);
+	declare_builtin("__mulflt32", FLOAT, FLOAT, R_R0P, FLOAT, R_R2P, 1, 0);
+	declare_builtin("__divflt32", FLOAT, FLOAT, R_R0P, FLOAT, R_R2P, 1, 0);
+	declare_builtin("__negflt32", FLOAT, FLOAT, R_R0P, FLOAT, R_R2P, 1, 0);
+
+	declare_builtin("__cmpflt32", INT,   FLOAT, R_R0P, FLOAT, R_R2P, 1, 0);
+
+			/* double */
+	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);
+
+#undef UINT
+#undef ULONG
+#undef ULLONG
+
+	return 1;
+}
+
+void cleanup_cg(FILE *f)
+{
+	/* Nothing to do */
+}
+
+/*  Returns the register in which variables of type t are returned. */
+/*  If the value cannot be returned in a register returns 0.        */
+int freturn(struct Typ *t)
+{
+	int f = t->flags & NQ;
+
+	/* Any scalar that fits in 16 bits uses A as return register */
+	if (ISSCALAR(f) && (msizetab[f] == 1))
+		return R_A;
+
+	/* Any scalar that fits in 32 bits used R0/R1 as return register */
+	if (ISSCALAR(f) && (msizetab[f] == 2))
+		return R_R0P;
+}
+
+/*  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.                  */
+int regok(int r, int t, int mode)
+{
+	if (r == 0)
+		return 0;
+
+	if (ISTSHORT(t)) {
+		if (r >= R_R0 && r <= R_RF)
+			return 1;
+		if (r >= R_S0 && r <= R_SF)
+			return 1;
+		if (r == R_A || r == R_X || r == R_Y)
+			return 1;
+	}
+
+	if (ISTLONG(t)) {
+		if (r >= R_R0P && r <= R_REP)
+			return 1;
+		if (r >= R_S0P && r <= R_SEP)
+			return 1;
+	}
+
+	return 0;
+}
+
+int dangerous_IC(struct IC *p)
+{
+	/* Only memory accesses are 'dangerous' */
+	int c=p->code;
+	if((p->q1.flags&DREFOBJ)||(p->q2.flags&DREFOBJ)||(p->z.flags&DREFOBJ))
+		return 1;
+	return 0;
+}
+
+/*  Returns zero if code for converting np to type t    */
+/*  can be omitted.                                     */
+int must_convert(int o,int t, int const_expr)
+{
+	int op=o&NQ,tp=t&NQ;
+
+	if (op==tp) return 0;
+
+	if (ISPOINTER(op) && ISPOINTER(tp))
+		return 1; /* No conversion actually possible between pointer types ! */
+
+	if (ISTSHORT(op) && ISTSHORT(tp))
+		return 0; /* All 'short' types are compatible */
+
+	return 1;
+}
+
+int shortcut(int code, int t)
+{
+	t &= NQ;
+	if (t == CHAR || t == SHORT || t == INT)
+		return 1;
+	return 0;
+}
+
+void gen_code(FILE *f, struct IC *p, struct Var *v, zmax offset)
+{
+	struct gc_state gc;
+	struct IC *node;
+
+	gc_func_begin(&gc, f, p, v, offset);
+	for (node=p; node; node=node->next)
+		gc_func_ic(&gc, node);
+	gc_func_end(&gc, f, p, v, offset);
+}
+
+void gen_ds(FILE *f, zmax size, struct Typ *t)
+{
+	long s = zm2l(size);
+	emit(f, "\t.space %ld\n", s);
+}
+
+void gen_align(FILE *f, zmax align)
+{
+	long a = zm2l(align);
+
+	if (a > 1)
+		emit(f, "\t.align %ld\n", a);
+}
+
+void gen_var_head(FILE *f, struct Var *v)
+{
+	const char*section_names[] = { /* bit 2: pmem, bit 1: init, bit 0: const */
+		"bss", NULL, "data", "rodata",
+		"pmem_bss", NULL, "pmem_data", "pmem_rodata",
+	};
+	int section_type;
+	struct Typ *tv;
+	char *attr;
+
+	tv = v->vtyp;
+	while (tv->flags==ARRAY)
+		tv = tv->next;
+	attr = tv->attr;
+
+	if (isstatic(v->storage_class) || isextern(v->storage_class))
+	{
+		/* Select section */
+		section_type  = (attr && strstr(attr, STR_PMEM)) ? 4 : 0;
+		section_type |= v->clist ? 2 : 0;
+		section_type |= (v->clist && is_const(v->vtyp)) ? 1 : 0;
+
+		emit(f, "\t.section %s\n", section_names[section_type]);
+
+		/* Symbol name */
+		if (isstatic(v->storage_class))
+			emit(f, "%s%ld:\n", labprefix, zm2l(v->offset));
+		else
+			emit(f, "%s%s:\n", idprefix, v->identifier);
+
+		/* FIXME: export global symbols */
+	}
+	else
+	{
+		ierror(0);
+	}
+}
+
+void gen_dc(FILE *f, int t, struct const_list *p)
+{
+	const char *dct[] = { "", "byte", "short",  "short", "long", "long", "long", "long" };
+	int tb;
+
+	if (ISPOINTER(t))
+		t = UNSIGNED|SHORT;
+	tb = t & NQ;
+
+	if (tb > LDOUBLE)
+		ierror(0);
+
+	emit(f, "\t.%s\t", dct[t&NQ]);
+
+	if (!p->tree)
+	{
+		if (ISFLOAT(tb)) {
+			unsigned char *ip;
+			emit(f,"0x%02x%02x%02x%02x",ip[0],ip[1],ip[2],ip[3]);
+			if(tb != FLOAT){
+				emit(f,",0x%02x%02x%02x%02x",ip[4],ip[5],ip[6],ip[7]);
+			}
+		} else if (tb == LLONG) {
+			/* Init */
+			zumax tmp;
+			eval_const(&p->val,t);
+			tmp = vumax;
+
+			/* Lower 32b */
+			vumax = zumand(tmp,ul2zum(0xffffffff));
+			gval.vulong = zum2zul(vumax);
+			emitval(f, &gval, UNSIGNED|LONG);
+
+			emit(f, ",");
+
+			/* Upper 32b */
+			vumax = zumand(zumrshift(vumax,ul2zum(32UL)),ul2zum(0xffffffff));
+			gval.vulong = zum2zul(vumax);
+			emitval(f, &gval, UNSIGNED|LONG);
+		} else {
+			emitval(f, &p->val, (t&NU)|UNSIGNED);
+		}
+	}
+	else
+	{
+		if ((p->tree->o.flags & (VAR | VARADR)) == (VAR | VARADR)) {
+			emit(f, "%s", sym_name(p->tree->o.v));
+		} else {
+			/* Not supported ... no idea what to do here */
+			ierror(0);
+		}
+	}
+
+	emit(f,"\n");
+}
+
+void init_db(FILE *f)
+{
+	/* not supported */
+}
+
+void cleanup_db(FILE *f)
+{
+	/* not supported */
+}
+
+/* Return name of library function, if this node should be
+   implemented via libcall. */
+char *use_libcall(int c,int t,int t2)
+{
+	static const char *names[] = { "na", "int16", "int16", "int16", "int32", "int64", "flt32", "flt64" };
+	static const struct {
+		int code;
+		int use_sign;
+		int types;
+	} lib_ops[] = {
+#define TB(x) (1 << (x))
+		{ OR,      0, TB(LLONG) },
+		{ XOR,     0, TB(LLONG) },
+		{ AND,     0, TB(LLONG) },
+		{ LSHIFT,  0, TB(DOUBLE) | TB(FLOAT) | TB(LLONG) | TB(LONG) | TB(INT) | TB(SHORT) | TB(CHAR) },
+		{ RSHIFT,  1, TB(DOUBLE) | TB(FLOAT) | TB(LLONG) | TB(LONG) | TB(INT) | TB(SHORT) | TB(CHAR) },
+		{ ADD,     0, TB(DOUBLE) | TB(FLOAT) | TB(LLONG) },
+		{ SUB,     0, TB(DOUBLE) | TB(FLOAT) | TB(LLONG) },
+		{ MULT,    0, TB(DOUBLE) | TB(FLOAT) | TB(LLONG) | TB(LONG) | TB(INT) | TB(SHORT) | TB(CHAR) },
+		{ DIV,     1, TB(DOUBLE) | TB(FLOAT) | TB(LLONG) | TB(LONG) | TB(INT) | TB(SHORT) | TB(CHAR) },
+		{ MOD,     1, TB(DOUBLE) | TB(FLOAT) | TB(LLONG) | TB(LONG) | TB(INT) | TB(SHORT) | TB(CHAR) },
+		{ COMPARE, 1, TB(DOUBLE) | TB(FLOAT) | TB(LLONG) },
+		{ -1 }
+	};
+#undef TB
+	static char fname[20];
+	const char *n, *n2, *s, *s2;
+	int i;
+
+	/* We don't really support long doubles */
+	if (t==LDOUBLE)  t=DOUBLE;
+	if (t2==LDOUBLE) t2=DOUBLE;
+
+	/* Safety */
+	if (((t&NQ) < CHAR) || ((t&NQ) > DOUBLE))
+		return NULL;
+	if ((t2&NQ) > DOUBLE)
+		return NULL;
+
+	/* Get name string for t/t2 and sign char */
+	n  = names[t  & NQ]; s  = ISFLOAT(t)  ? "" : ((t  & UNSIGNED) ? "u" : "s");
+	n2 = names[t2 & NQ]; s2 = ISFLOAT(t2) ? "" : ((t2 & UNSIGNED) ? "u" : "s");
+
+	/* Conversions */
+	if (c == CONVERT)
+	{
+		/* Build name */
+		snprintf(fname, sizeof(fname)-1, "__%s%sto%s%s", s, n, s2, n2);
+
+		/* All conversion with float are library */
+		if (ISFLOAT(t) || ISFLOAT(t2))
+			return fname;
+
+		/* No match */
+		return NULL;
+	}
+
+	/* Scan for supported operations */
+	for (i=0; lib_ops[i].code > 0; i++)
+	{
+		/* Match op */
+		if (lib_ops[i].code != c)
+			continue;
+
+		/* Supported type ? */
+		if ((lib_ops[i].types & (1 << (t&NQ))) == 0)
+			return NULL;
+
+		/* Build name */
+		if (lib_ops[i].use_sign)
+			snprintf(fname, sizeof(fname)-1, "__%s%s%s", ename[c], s, n);
+		else
+			snprintf(fname, sizeof(fname)-1, "__%s%s", ename[c], n);
+
+		return fname;
+	}
+
+	return NULL;
+}
+
+/* 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.                                            */
+int reg_pair(int r,struct rpair *p)
+{
+	if ((r >= R_R0P) && (r <= R_REP))
+	{
+		p->r1 = R_R0 + 2 * (r -  R_R0P);
+		p->r2 = R_R1 + 2 * (r -  R_R0P);
+		return 1;
+	}
+
+	if ((r >= R_S0P) && (r <= R_SEP))
+	{
+		p->r1 = R_S0 + 2 * (r -  R_S0P);
+		p->r2 = R_S1 + 2 * (r -  R_S0P);
+		return 1;
+	}
+
+	return 0;
+}
+
+int reg_parm(struct reg_handle *p, struct Typ *t,int vararg,struct Typ *d)
+{
+	int f = t->flags & NQ;
+
+	/* Exclusions */
+	if (!ISSCALAR(f)) return 0;
+	if (p->gpr >= 4 || vararg) return 0;
+	if (f==LLONG || f==DOUBLE || f==LDOUBLE) return 0;
+
+	/* Pairs (possibly 'loosing' one reg if misaligned) */
+	if (f==LONG || f==FLOAT) {
+		p->gpr += (p->gpr & 1);	/* align */
+		if (p->gpr >= 4)
+			return 0;
+		p->gpr += 2;
+		return R_R0P + (p->gpr / 2) - 1;
+	}
+
+	/* Normal */
+	return R_R0 + p->gpr++;
+}
+
+int pointer_type(struct Typ *p)
+{
+	while (ISARRAY(p->flags))
+		p=p->next;
+	if (ISFUNC(p->flags))
+		return PPOINTER;
+	if (p->attr && strstr(p->attr, STR_PMEM))
+		return PPOINTER;
+	return DPOINTER;
+}
+
+void conv_typ(struct Typ *p)
+{
+	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_PMEM))
+					p->flags=((p->flags&~NU)|PPOINTER);
+			}
+		}
+		p=p->next;
+	}
+}
+
+/* Below is mostly copied from supp.c */
+void printval(FILE *f,union atyps *p,int t)
+{
+	t&=NU;
+	if(t==CHAR){fprintf(f,"C");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)){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)){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){fprintf(f,"M");printzm(f,p->vmax);}
+	if(t==(UNSIGNED|MAXINT)){fprintf(f,"UM");printzum(f,p->vumax);}
+	if(t==DPOINTER){fprintf(f,"Pd");vumax=zul2zum(p->vushort);printzum(f,vumax);}
+	if(t==PPOINTER){fprintf(f,"Pp");vumax=zul2zum(p->vushort);printzum(f,vumax);}
+}
+
+void emitval(FILE *f,union atyps *p,int t)
+{
+	t&=NU;
+	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)){vumax=zui2zum(p->vuint);emitzum(f,vumax);}
+	if(t==LONG){vmax=zl2zm(p->vlong);emitzm(f,vmax);}
+	if(t==(UNSIGNED|LONG)){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);}
+	if(t==DPOINTER){vumax=zus2zum(p->vushort);emitzum(f,vumax);}
+	if(t==PPOINTER){vumax=zus2zum(p->vushort);emitzum(f,vumax);}
+}
+
+void insert_const(union atyps *p,int t)
+{
+	if(!p) ierror(0);
+	t&=NU;
+	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|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==DPOINTER) {p->vushort=vushort;return;}
+	if(t==PPOINTER) {p->vushort=vushort;return;}
+}
+
+void eval_const(union atyps *p,int t)
+{
+	int f=t&NQ;
+	if(!p) ierror(0);
+	if(f==MAXINT||(f>=CHAR&&f<=LLONG)){
+		if(!(t&UNSIGNED)){
+			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==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)){
+			vumax=zus2zum(p->vushort);
+			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);
+}
diff --git a/machines/fire16/machine.dt b/machines/fire16/machine.dt
new file mode 100644
index 0000000..fa60647
--- /dev/null
+++ b/machines/fire16/machine.dt
@@ -0,0 +1,16 @@
+S16BSLE S16BSBE
+S16BULE S16BUBE
+S16BSLE S16BSBE
+S16BULE S16BUBE
+S16BSLE S16BSBE
+S16BULE S16BUBE
+S32BSLE S32BSBE
+S32BULE S32BUBE
+S64BSLE S64BSBE
+S64BULE S64BUBE
+S32BIEEELE
+S64BIEEELE
+S64BIEEELE
+S16BULE S16BUBE
+
+
diff --git a/machines/fire16/machine.h b/machines/fire16/machine.h
new file mode 100644
index 0000000..f723321
--- /dev/null
+++ b/machines/fire16/machine.h
@@ -0,0 +1,189 @@
+/* 
+ * Backend for the Fire16 iCE40 SoftCore
+ * (c) 2019 by Sylvain Munaut
+ */
+
+#include "dt.h"
+
+
+/*  This struct can be used to implement machine-specific           */
+/*  addressing-modes.                                               */
+struct AddressingMode {
+	int not_used_yet;	// FIXME
+};
+
+/*  The number of registers of the target machine.                  */
+	/* - 16 rN GPR + 8 pairs
+	 * - 16 sN GPR + 8 pairs
+	 * - A, X, Y, I
+	 */
+#define MAXR 52
+
+/*  Number of commandline-options the code-generator accepts.       */
+#define MAXGF 20
+
+/*  If this is set to zero vbcc will not generate ICs where the     */
+/*  target operand is the same as the 2nd source operand.           */
+/*  This can sometimes simplify the code-generator, but usually     */
+/*  the code is better if the code-generator allows it.             */
+#define USEQ2ASZ 1
+
+/*  This specifies the smallest integer type that can be added to a */
+/*  pointer.                                                        */
+#define MINADDI2P CHAR
+
+/*  This specifies the smallest integer type that can be added to a */
+/*  pointer.                                                        */
+#define MAXADDI2P INT
+
+/*  If the bytes of an integer are ordered most significant byte    */
+/*  byte first and then decreasing set BIGENDIAN to 1.              */
+#define BIGENDIAN 0
+
+/*  If the bytes of an integer are ordered lest significant byte    */
+/*  byte first and then increasing set LITTLEENDIAN to 1.           */
+#define LITTLEENDIAN 1
+
+/*  Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive.    */
+
+/*  If switch-statements should be generated as a sequence of       */
+/*  SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1.      */
+/*  This can yield better code on some machines.                    */
+#define SWITCHSUBS 0
+
+/*  In optimizing compilation certain library memcpy/strcpy-calls   */
+/*  with length known at compile-time will be inlined using an      */
+/*  ASSIGN-IC if the size is less or equal to INLINEMEMCPY.         */
+/*  The type used for the ASSIGN-IC will be UNSIGNED|CHAR.          */
+#define INLINEMEMCPY 16
+
+/*  Parameters are sometimes passed in registers without __reg.     */
+#define HAVE_REGPARMS 1
+
+/*  Structure for reg_parm().                                       */
+struct reg_handle{
+    unsigned long gpr;
+};
+
+/*  We have register pairs.                                         */
+#define HAVE_REGPAIRS 1
+
+/*  We use unsigned int as size_t rather than unsigned long which   */
+/*  is the default setting.                                         */
+#define HAVE_INT_SIZET 1
+
+/*  We have asm_peephole to optimize assembly-output */
+#define HAVE_TARGET_PEEPHOLE 0	/* FIXME: not yet */
+
+/*  We have some target-specific variable attributes.               */
+#define HAVE_TARGET_ATTRIBUTES 1
+
+/* We do not have target-specific pragmas */
+#undef HAVE_TARGET_PRAGMAS
+
+/*  We keep track of all registers modified by a function.          */
+#define HAVE_REGS_MODIFIED 1
+
+/* We have a implement our own cost-functions to adapt
+   register-allocation */
+#if 0 /* FIXME */
+#define HAVE_TARGET_RALLOC 1
+#define cost_move_reg(x,y)  XXX
+#define cost_load_reg(x,y)  XXX
+#define cost_save_reg(x,y)  XXX
+#define cost_pushpop_reg(x) XXX
+#endif
+
+/* we do not have a mark_eff_ics function, this is used to prevent
+   optimizations on code which can already be implemented by efficient
+   assembly */
+#undef HAVE_TARGET_EFF_IC
+
+/* we do not need extra elements in the IC */
+#undef HAVE_EXT_IC
+
+/* we need extended types (for pmem/dmem pointers) */
+#define HAVE_EXT_TYPES 1
+
+#undef CHAR
+#undef SHORT
+#undef INT
+#undef LONG
+#undef LLONG
+#undef FLOAT
+#undef DOUBLE
+#undef LDOUBLE
+#undef VOID
+#undef POINTER
+#undef ARRAY
+#undef STRUCT
+#undef UNION
+#undef ENUM
+#undef FUNKT
+#undef BOOL
+#undef MAXINT
+#undef MAX_TYPE
+
+#define CHAR 1
+#define SHORT 2
+#define INT 3
+#define LONG 4
+#define LLONG 5
+#define FLOAT 6
+#define DOUBLE 7
+#define LDOUBLE 8
+#define VOID 9
+#define DPOINTER 10
+#define PPOINTER 11
+#define ARRAY 12
+#define STRUCT 13
+#define UNION 14
+#define ENUM 15
+#define FUNKT 16
+#define BOOL 17
+#define MAXINT 18
+#define MAX_TYPE MAXINT
+
+#define POINTER_TYPE(x) pointer_type(x)
+extern int pointer_type();
+#define ISPOINTER(x) ((x&NQ)>=DPOINTER&&(x&NQ)<=PPOINTER)
+#define ISSCALAR(x) ((x&NQ)>=CHAR&&(x&NQ)<=PPOINTER)
+#define ISINT(x) ((x&NQ)>=CHAR&&(x&NQ)<=LLONG)
+#define PTRDIFF_T(x) (INT)
+
+typedef zllong zmax;
+typedef zullong zumax;
+
+union atyps{
+  zchar vchar;
+  zuchar vuchar;
+  zshort vshort;
+  zushort vushort;
+  zint vint;
+  zuint vuint;
+  zlong vlong;
+  zulong vulong;
+  zllong vllong;
+  zullong vullong;
+  zmax vmax;
+  zumax vumax;
+  zfloat vfloat;
+  zdouble vdouble;
+  zldouble vldouble;
+};
+
+
+/* we need our own printval */
+#define HAVE_TGT_PRINTVAL 1
+
+/* we want to replace some ICs with libcalls */
+#define HAVE_LIBCALLS 1
+
+/* we much prefer BNE */
+#define HAVE_WANTBNE 1
+
+/* size of buffer for asm-output */
+#define EMIT_BUF_LEN 1024 /* should be enough */
+
+/* number of asm-output lines buffered */
+#define EMIT_BUF_DEPTH 4
diff --git a/machines/generic/machine.c b/machines/generic/machine.c
new file mode 100755
index 0000000..f7b86ac
--- /dev/null
+++ b/machines/generic/machine.c
@@ -0,0 +1,1166 @@
+/*  Example backend for vbcc, it models a generic 32bit RISC or CISC
+    CPU.
+ 
+    Configurable at build-time are:
+    - number of (32bit) general-purpose-registers
+    - number of (64bit) floating-point-registers
+    - number of (8bit) condition-code-registers
+    - mechanism for stack-arguments (moving ot fixed sp)
+ 
+    It allows to select as run-time-options:
+    - two- or three-address code
+    - memory operands or load-store-architecture
+    - number of register-arguments
+    - number of caller-save-registers
+*/                                                                             
+
+#include "supp.h"
+
+static char FILE_[]=__FILE__;
+
+/*  Public data that MUST be there.                             */
+
+/* Name and copyright. */
+char cg_copyright[]="vbcc generic code-generator V0.1b (c) in 2001 by Volker Barthelmann";
+
+/*  Commandline-flags the code-generator accepts:
+    0: just a flag
+    VALFLAG: a value must be specified
+    STRINGFLAG: a string can be specified
+    FUNCFLAG: a function will be called
+    apart from FUNCFLAG, all other versions can only be specified once */
+int g_flags[MAXGF]={0,0,
+		    VALFLAG,VALFLAG,VALFLAG,
+		    0,0,
+		    VALFLAG,VALFLAG,0};
+
+/* the flag-name, do not use names beginning with l, L, I, D or U, because
+   they collide with the frontend */
+char *g_flags_name[MAXGF]={"three-addr","load-store",
+			   "volatile-gprs","volatile-fprs","volatile-ccrs",
+			   "imm-ind","gpr-ind",
+			   "gpr-args","fpr-args","use-commons"};
+
+/* the results of parsing the command-line-flags will be stored here */
+union ppi g_flags_val[MAXGF];
+
+/*  Alignment-requirements for all types in bytes.              */
+zmax align[MAX_TYPE+1];
+
+/*  Alignment that is sufficient for every object.              */
+zmax maxalign;
+
+/*  CHAR_BIT for the target machine.                            */
+zmax char_bit;
+
+/*  sizes of the basic 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. will be initialized in init_cg(),
+    register number 0 is invalid, valid registers start at 1 */
+char *regnames[MAXR+1];
+
+/*  The Size of each register in bytes.                         */
+zmax regsize[MAXR+1];
+
+/*  a 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];
+
+/* specifies the priority for the register-allocator, if the same
+   estimated cost-saving can be obtained by several registers, the
+   one with the highest priority will be used */
+int reg_prio[MAXR+1];
+
+/* an empty reg-handle representing initial state */
+struct reg_handle empty_reg_handle={0,0};
+
+/* Names of target-specific variable attributes.                */
+char *g_attr_name[]={"__interrupt",0};
+
+
+/****************************************/
+/*  Private data and functions.         */
+/****************************************/
+
+#define THREE_ADDR (g_flags[0]&USEDFLAG)
+#define LOAD_STORE (g_flags[1]&USEDFLAG)
+#define VOL_GPRS   ((g_flags[2]&USEDFLAG)?g_flags_val[2].l:NUM_GPRS/2)
+#define VOL_FPRS   ((g_flags[3]&USEDFLAG)?g_flags_val[3].l:NUM_FPRS/2)
+#define VOL_CCRS   ((g_flags[4]&USEDFLAG)?g_flags_val[4].l:NUM_CCRS/2)
+#define IMM_IND    ((g_flags[5]&USEDFLAG)?1:0)
+#define GPR_IND    ((g_flags[6]&USEDFLAG)?2:0)
+#define GPR_ARGS   ((g_flags[7]&USEDFLAG)?g_flags_val[7].l:0)
+#define FPR_ARGS   ((g_flags[8]&USEDFLAG)?g_flags_val[8].l:0)
+#define USE_COMMONS (g_flags[9]&USEDFLAG)
+
+
+/* alignment of basic data-types, used to initialize align[] */
+static long malign[MAX_TYPE+1]=  {1,1,2,4,4,4,4,8,8,1,4,1,1,1,4,1};
+/* sizes of basic data-types, used to initialize sizetab[] */
+static long msizetab[MAX_TYPE+1]={1,1,2,4,4,8,4,8,8,0,4,0,0,0,4,0};
+
+/* used to initialize regtyp[] */
+static struct Typ ltyp={LONG},ldbl={DOUBLE},lchar={CHAR};
+
+/* macros defined by the backend */
+static char *marray[]={"__section(x)=__vattr(\"section(\"#x\")\")",
+		       "__GENERIC__",
+		       0};
+
+/* special registers */
+static int sp;                     /*  Stackpointer                        */
+static int t1,t2,t3;               /*  temporary gprs */
+static int f1,f2,f3;               /*  temporary fprs */
+
+#define dt(t) (((t)&UNSIGNED)?udt[(t)&NQ]:sdt[(t)&NQ])
+static char *sdt[MAX_TYPE+1]={"??","c","s","i","l","ll","f","d","ld","v","p"};
+static char *udt[MAX_TYPE+1]={"??","uc","us","ui","ul","ull","f","d","ld","v","p"};
+
+/* sections */
+#define DATA 0
+#define BSS 1
+#define CODE 2
+#define RODATA 3
+#define SPECIAL 4
+
+static long stack;
+static int stack_valid;
+static int section=-1,newobj;
+static char *codename="\t.text\n",
+  *dataname="\t.data\n",
+  *bssname="",
+  *rodataname="\t.section\t.rodata\n";
+
+/* return-instruction */
+static char *ret;
+
+/* label at the end of the function (if any) */
+static int exit_label;
+
+/* assembly-prefixes for labels and external identifiers */
+static char *labprefix="l",*idprefix="_";
+
+#if FIXED_SP
+/* variables to calculate the size and partitioning of the stack-frame
+   in the case of FIXED_SP */
+static long frameoffset,pushed,maxpushed,framesize;
+#else
+/* variables to keep track of the current stack-offset in the case of
+   a moving stack-pointer */
+static long notpopped,dontpop,stackoffset,maxpushed;
+#endif
+
+static long localsize,rsavesize,argsize;
+
+static void emit_obj(FILE *f,struct obj *p,int t);
+
+/* calculate the actual current offset of an object relativ to the
+   stack-pointer; we use a layout like this:
+   ------------------------------------------------
+   | arguments to this function                   |
+   ------------------------------------------------
+   | return-address [size=4]                      |
+   ------------------------------------------------
+   | caller-save registers [size=rsavesize]       |
+   ------------------------------------------------
+   | local variables [size=localsize]             |
+   ------------------------------------------------
+   | arguments to called functions [size=argsize] |
+   ------------------------------------------------
+   All sizes will be aligned as necessary.
+   In the case of FIXED_SP, the stack-pointer will be adjusted at
+   function-entry to leave enough space for the arguments and have it
+   aligned to 16 bytes. Therefore, when calling a function, the
+   stack-pointer is always aligned to 16 bytes.
+   For a moving stack-pointer, the stack-pointer will usually point
+   to the bottom of the area for local variables, but will move while
+   arguments are put on the stack.
+
+   This is just an example layout. Other layouts are also possible.
+*/
+
+static long real_offset(struct obj *o)
+{
+  long off=zm2l(o->v->offset);
+  if(off<0){
+    /* function parameter */
+    off=localsize+rsavesize+4-off-zm2l(maxalign);
+  }
+
+#if FIXED_SP
+  off+=argsize;
+#else
+  off+=stackoffset;
+#endif
+  off+=zm2l(o->val.vmax);
+  return off;
+}
+
+/*  Initializes an addressing-mode structure and returns a pointer to
+    that object. Will not survive a second call! */
+static struct obj *cam(int flags,int base,long offset)
+{
+  static struct obj obj;
+  static struct AddressingMode am;
+  obj.am=&am;
+  am.flags=flags;
+  am.base=base;
+  am.offset=offset;
+  return &obj;
+}
+
+/* changes to a special section, used for __section() */
+static int special_section(FILE *f,struct Var *v)
+{
+  char *sec;
+  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;
+}
+
+/* generate code to load the address of a variable into register r */
+static void load_address(FILE *f,int r,struct obj *o,int type)
+/*  Generates code to load the address of a variable into register r.   */
+{
+  if(!(o->flags&VAR)) ierror(0);
+  if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER){
+    long off=real_offset(o);
+    if(THREE_ADDR){
+      emit(f,"\tadd.%s\t%s,%s,%ld\n",dt(POINTER),regnames[r],regnames[sp],off);
+    }else{
+      emit(f,"\tmov.%s\t%s,%s\n",dt(POINTER),regnames[r],regnames[sp]);
+      if(off)
+	emit(f,"\tadd.%s\t%s,%ld\n",dt(POINTER),regnames[r],off);
+    }
+  }else{
+    emit(f,"\tmov.%s\t%s,",dt(POINTER),regnames[r]);
+    emit_obj(f,o,type);
+    emit(f,"\n");
+  }
+}
+/* Generates code to load a memory object into register r. tmp is a
+   general purpose register which may be used. tmp can be r. */
+static void load_reg(FILE *f,int r,struct obj *o,int type)
+{
+  type&=NU;
+  if(o->flags&VARADR){
+    load_address(f,r,o,POINTER);
+  }else{
+    if((o->flags&(REG|DREFOBJ))==REG&&o->reg==r)
+      return;
+    emit(f,"\tmov.%s\t%s,",dt(type),regnames[r]);
+    emit_obj(f,o,type);
+    emit(f,"\n");
+  }
+}
+
+/*  Generates code to store register r into memory object o. */
+static void store_reg(FILE *f,int r,struct obj *o,int type)
+{
+  type&=NQ;
+  emit(f,"\tmov.%s\t",dt(type));
+  emit_obj(f,o,type);
+  emit(f,",%s\n",regnames[r]);
+}
+
+/*  Yields log2(x)+1 or 0. */
+static long pof2(zumax x)
+{
+  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 struct IC *preload(FILE *,struct IC *);
+
+static void function_top(FILE *,struct Var *,long);
+static void function_bottom(FILE *f,struct Var *,long);
+
+#define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
+#define isconst(x) ((p->x.flags&(KONST|DREFOBJ))==KONST)
+
+static int q1reg,q2reg,zreg;
+
+static char *ccs[]={"eq","ne","lt","ge","le","gt",""};
+static char *logicals[]={"or","xor","and"};
+static char *arithmetics[]={"slw","srw","add","sub","mullw","divw","mod"};
+
+/* compare if two objects are the same */
+static int compare_objects(struct obj *o1,struct obj *o2)
+{
+  if((o1->flags&(REG|DREFOBJ))==REG&&(o2->flags&(REG|DREFOBJ))==REG&&o1->reg==o2->reg)
+    return 1;
+  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&REG)||o1->reg==o2->reg){
+        return 1;
+      }
+    }
+  }
+  return 0;
+}
+
+/* Does some pre-processing like fetching operands from memory to
+   registers etc. */
+static struct IC *preload(FILE *f,struct IC *p)
+{
+  int r;
+
+  if(isreg(q1))
+    q1reg=p->q1.reg;
+  else
+    q1reg=0;
+
+  if(isreg(q2))
+    q2reg=p->q2.reg;
+  else
+    q2reg=0;
+
+  if(isreg(z)&&(THREE_ADDR||!compare_objects(&p->q2,&p->z))){
+    zreg=p->z.reg;
+  }else{
+    if(ISFLOAT(ztyp(p)))
+      zreg=f1;
+    else
+      zreg=t1;
+  }
+  
+  if((p->q1.flags&(DREFOBJ|REG))==DREFOBJ&&!p->q1.am){
+    p->q1.flags&=~DREFOBJ;
+    load_reg(f,t1,&p->q1,q1typ(p));
+    p->q1.reg=t1;
+    p->q1.flags|=(REG|DREFOBJ);
+  }
+  if(p->q1.flags&&LOAD_STORE&&!isreg(q1)){
+    if(p->code==ASSIGN&&isreg(z))
+      q1reg=p->z.reg;
+    else if(ISFLOAT(q1typ(p)))
+      q1reg=f1;
+    else
+      q1reg=t1;
+    load_reg(f,q1reg,&p->q1,q1typ(p));
+    p->q1.reg=q1reg;
+    p->q1.flags=REG;
+  }
+
+  if((p->q2.flags&(DREFOBJ|REG))==DREFOBJ&&!p->q2.am){
+    p->q2.flags&=~DREFOBJ;
+    load_reg(f,t1,&p->q2,q2typ(p));
+    p->q2.reg=t1;
+    p->q2.flags|=(REG|DREFOBJ);
+  }
+  if(p->q2.flags&&LOAD_STORE&&!isreg(q2)){
+    if(ISFLOAT(q2typ(p)))
+      q2reg=f2;
+    else
+      q2reg=t2;
+    load_reg(f,q2reg,&p->q2,q2typ(p));
+    p->q2.reg=q2reg;
+    p->q2.flags=REG;
+  }
+  return p;
+}
+
+/* save the result (in zreg) into p->z */
+void save_result(FILE *f,struct IC *p)
+{
+  if((p->z.flags&(REG|DREFOBJ))==DREFOBJ&&!p->z.am){
+    p->z.flags&=~DREFOBJ;
+    load_reg(f,t2,&p->z,POINTER);
+    p->z.reg=t2;
+    p->z.flags|=(REG|DREFOBJ);
+  }
+  if(isreg(z)){
+    if(p->z.reg!=zreg)
+      emit(f,"\tmov.%s\t%s,%s\n",dt(ztyp(p)),regnames[p->z.reg],regnames[zreg]);
+  }else{
+    store_reg(f,zreg,&p->z,ztyp(p));
+  }
+}
+
+/* prints an object */
+static void emit_obj(FILE *f,struct obj *p,int t)
+{
+  if(p->am){
+    if(p->am->flags&GPR_IND) emit(f,"(%s,%s)",regnames[p->am->offset],regnames[p->am->base]);
+    if(p->am->flags&IMM_IND) emit(f,"(%ld,%s)",p->am->offset,regnames[p->am->base]);
+    return;
+  }
+  if((p->flags&(KONST|DREFOBJ))==(KONST|DREFOBJ)){
+    emitval(f,&p->val,p->dtyp&NU);
+    return;
+  }
+  if(p->flags&DREFOBJ) emit(f,"(");
+  if(p->flags&REG){
+    emit(f,"%s",regnames[p->reg]);
+  }else if(p->flags&VAR) {
+    if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER)
+      emit(f,"%ld(%s)",real_offset(p),regnames[sp]);
+    else{
+      if(!zmeqto(l2zm(0L),p->val.vmax)){emitval(f,&p->val,LONG);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(p->flags&KONST){
+    emitval(f,&p->val,t&NU);
+  }
+  if(p->flags&DREFOBJ) emit(f,")");
+}
+
+/*  Test if there is a sequence of FREEREGs containing FREEREG reg.
+    Used by peephole. */
+static int exists_freereg(struct IC *p,int reg)
+{
+  while(p&&(p->code==FREEREG||p->code==ALLOCREG)){
+    if(p->code==FREEREG&&p->q1.reg==reg) return 1;
+    p=p->next;
+  }
+  return 0;
+}
+
+/* search for possible addressing-modes */
+static void peephole(struct IC *p)
+{
+  int c,c2,r;struct IC *p2;struct AddressingMode *am;
+
+  for(;p;p=p->next){
+    c=p->code;
+    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;
+
+    /* Try const(reg) */
+    if(IMM_IND&&(c==ADDI2P||c==SUBIFP)&&isreg(z)&&(p->q2.flags&(KONST|DREFOBJ))==KONST){
+      int base;zmax of;struct obj *o;
+      eval_const(&p->q2.val,p->typf);
+      if(c==SUBIFP) of=zmsub(l2zm(0L),vmax); else of=vmax;
+      if(1/*zmleq(l2zm(-32768L),vmax)&&zmleq(vmax,l2zm(32767L))*/){
+	r=p->z.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(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) break;
+	      o=&p2->q1;
+	    }
+	    if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
+	      if(o) break;
+	      o=&p2->q2;
+	    }
+	    if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
+	      if(o) 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);
+		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;
+	  }
+        }
+      }
+    }
+    /* Try reg,reg */
+    if(GPR_IND&&c==ADDI2P&&isreg(q2)&&isreg(z)&&(isreg(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||(q1typ(p2)&NQ)==LLONG) break;
+            o=&p2->q1;
+          }
+          if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
+            if(o||(q2typ(p2)&NQ)==LLONG) break;
+            o=&p2->q2;
+          }
+          if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
+            if(o||(ztyp(p2)&NQ)==LLONG) 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=GPR_IND;
+              am->base=base;
+              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;
+        }
+      }
+    }
+  }
+}
+
+/* generates the function entry code */
+static void function_top(FILE *f,struct Var *v,long offset)
+{
+  rsavesize=0;
+  if(!special_section(f,v)&&section!=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));
+}
+/* generates the function exit code */
+static void function_bottom(FILE *f,struct Var *v,long offset)
+{
+  emit(f,ret);
+}
+
+/****************************************/
+/*  End of private data and functions.  */
+/****************************************/
+
+/*  Does necessary initializations for the code-generator. Gets called  */
+/*  once at the beginning and should return 0 in case of problems.      */
+int init_cg(void)
+{
+  int i;
+  /*  Initialize some values which cannot be statically initialized   */
+  /*  because they are stored in the target's arithmetic.             */
+  maxalign=l2zm(8L);
+  char_bit=l2zm(8L);
+  stackalign=l2zm(4);
+
+  for(i=0;i<=MAX_TYPE;i++){
+    sizetab[i]=l2zm(msizetab[i]);
+    align[i]=l2zm(malign[i]);
+  }
+
+  regnames[0]="noreg";
+  for(i=FIRST_GPR;i<=LAST_GPR;i++){
+    regnames[i]=mymalloc(10);
+    sprintf(regnames[i],"gpr%d",i-FIRST_GPR);
+    regsize[i]=l2zm(4L);
+    regtype[i]=&ltyp;
+  }
+  for(i=FIRST_FPR;i<=LAST_FPR;i++){
+    regnames[i]=mymalloc(10);
+    sprintf(regnames[i],"fpr%d",i-FIRST_FPR);
+    regsize[i]=l2zm(8L);
+    regtype[i]=&ldbl;
+  }
+  for(i=FIRST_CCR;i<=LAST_CCR;i++){
+    regnames[i]=mymalloc(10);
+    sprintf(regnames[i],"ccr%d",i-FIRST_CCR);
+    regsize[i]=l2zm(1L);
+    regtype[i]=&lchar;
+  }
+
+  /*  Use multiple ccs.   */
+  multiple_ccs=0;
+
+  /*  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.          */
+  t_min[CHAR]=l2zm(-128L);
+  t_min[SHORT]=l2zm(-32768L);
+  t_min[INT]=zmsub(l2zm(-2147483647L),l2zm(1L));
+  t_min[LONG]=t_min(INT);
+  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]=ul2zum(2147483647UL);
+  t_max[LONG]=t_max(INT);
+  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]=ul2zum(4294967295UL);
+  tu_max[LONG]=t_max(UNSIGNED|INT);
+  tu_max[LLONG]=zumkompl(ul2zum(0UL));
+  tu_max[MAXINT]=t_max(UNSIGNED|LLONG);
+  
+  /*  Reserve a few registers for use by the code-generator.      */
+  /*  This is not optimal but simple.                             */
+  sp=FIRST_GPR;
+  t1=FIRST_GPR+1;
+  t2=FIRST_GPR+2;
+  f1=FIRST_FPR;
+  f2=FIRST_FPR+1;
+  regsa[t1]=regsa[t2]=1;
+  regsa[f1]=regsa[f2]=1;
+  regsa[sp]=1;
+  regscratch[t1]=regscratch[t2]=0;
+  regscratch[f1]=regscratch[f2]=0;
+  regscratch[sp]=0;
+
+  for(i=FIRST_GPR;i<=LAST_GPR-VOL_GPRS;i++)
+    regscratch[i]=1;
+  for(i=FIRST_FPR;i<=LAST_FPR-VOL_FPRS;i++)
+    regscratch[i]=1;
+  for(i=FIRST_CCR;i<=LAST_CCR-VOL_CCRS;i++)
+    regscratch[i]=1;
+
+  target_macros=marray;
+
+
+  return 1;
+}
+
+void init_db(FILE *f)
+{
+}
+
+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.        */
+/*  A pointer MUST be returned in a register. The code-generator    */
+/*  has to simulate a pseudo register if necessary.                 */
+{
+  if(ISFLOAT(t->flags)) 
+    return FIRST_FPR+2;
+  if(ISSTRUCT(t->flags)||ISUNION(t->flags)) 
+    return 0;
+  if(zmleq(szof(t),l2zm(4L))) 
+    return FIRST_GPR+3;
+  else
+    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.                                            */
+{
+  return 0;
+}
+
+/* estimate the cost-saving if object o from IC p is placed in
+   register r */
+int cost_savings(struct IC *p,int r,struct obj *o)
+{
+  int c=p->code;
+  if(o->flags&VKONST){
+    if(!LOAD_STORE)
+      return 0;
+    if(o==&p->q1&&p->code==ASSIGN&&(p->z.flags&DREFOBJ))
+      return 4;
+    else
+      return 2;
+  }
+  if(o->flags&DREFOBJ)
+    return 4;
+  if(c==SETRETURN&&r==p->z.reg&&!(o->flags&DREFOBJ)) return 3;
+  if(c==GETRETURN&&r==p->q1.reg&&!(o->flags&DREFOBJ)) return 3;
+  return 2;
+}
+
+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(r==0)
+    return 0;
+  t&=NQ;
+  if(t==0&&r>=FIRST_CCR&&r<=LAST_CCR)
+    return 1;
+  if(ISFLOAT(t)&&r>=FIRST_FPR&&r<=LAST_FPR)
+    return 1;
+  if(t==POINTER&&r>=FIRST_GPR&&r<=LAST_GPR)
+    return 1;
+  if(t>=CHAR&&t<=LONG&&r>=FIRST_GPR&&r<=LAST_GPR)
+    return 1;
+  return 0;
+}
+
+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;
+}
+
+int must_convert(int o,int t,int const_expr)
+/*  Returns zero if code for converting np to type t    */
+/*  can be omitted.                                     */
+/*  On the PowerPC cpu pointers and 32bit               */
+/*  integers have the same representation and can use   */
+/*  the same registers.                                 */
+{
+  int op=o&NQ,tp=t&NQ;
+  if((op==INT||op==LONG||op==POINTER)&&(tp==INT||tp==LONG||tp==POINTER))
+    return 0;
+  if(op==DOUBLE&&tp==LDOUBLE) return 0;
+  if(op==LDOUBLE&&tp==DOUBLE) 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&&section!=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.              */
+{
+  if(zm2l(align)>1) emit(f,"\t.align\t2\n");
+}
+
+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;char *sec;
+  if(v->clist) constflag=is_const(v->vtyp);
+  if(v->storage_class==STATIC){
+    if(ISFUNC(v->vtyp->flags)) return;
+    if(!special_section(f,v)){
+      if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&&section!=DATA){emit(f,dataname);if(f) section=DATA;}
+      if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&&section!=RODATA){emit(f,rodataname);if(f) section=RODATA;}
+      if(!v->clist&&section!=BSS){emit(f,bssname);if(f) section=BSS;}
+    }
+    if(v->clist||section==SPECIAL){
+      gen_align(f,falign(v->vtyp));
+      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){
+    emit(f,"\t.globl\t%s%s\n",idprefix,v->identifier);
+    if(v->flags&(DEFINED|TENTATIVE)){
+      if(!special_section(f,v)){
+	if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&&section!=DATA){emit(f,dataname);if(f) section=DATA;}
+	if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&&section!=RODATA){emit(f,rodataname);if(f) section=RODATA;}
+	if(!v->clist&&section!=BSS){emit(f,bssname);if(f) section=BSS;}
+      }
+      if(v->clist||section==SPECIAL){
+	gen_align(f,falign(v->vtyp));
+        emit(f,"%s%s:\n",idprefix,v->identifier);
+      }else
+        emit(f,"\t.global\t%s%s\n\t.%scomm\t%s%s,",idprefix,v->identifier,(USE_COMMONS?"":"l"),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,"\tdc.%s\t",dt(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[0],ip[1],ip[2],ip[3]);
+      if((t&NQ)!=FLOAT){
+	emit(f,",0x%02x%02x%02x%02x",ip[4],ip[5],ip[6],ip[7]);
+      }
+    }else{
+      emitval(f,&p->val,t&NU);
+    }
+  }else{
+    emit_obj(f,&p->tree->o,t&NU);
+  }
+  emit(f,"\n");newobj=0;
+}
+
+
+/*  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 *p,struct Var *v,zmax offset)
+/*  The main code-generation.                                           */
+{
+  int c,t,i;
+  struct IC *m;
+  argsize=0;
+  if(DEBUG&1) printf("gen_code()\n");
+  for(c=1;c<=MAXR;c++) regs[c]=regsa[c];
+  maxpushed=0;
+
+  /*FIXME*/
+  ret="\trts\n";
+
+  for(m=p;m;m=m->next){
+    c=m->code;t=m->typf&NU;
+    if(c==ALLOCREG) {regs[m->q1.reg]=1;continue;}
+    if(c==FREEREG) {regs[m->q1.reg]=0;continue;}
+
+    /* convert MULT/DIV/MOD with powers of two */
+    if((t&NQ)<=LONG&&(m->q2.flags&(KONST|DREFOBJ))==KONST&&(t&NQ)<=LONG&&(c==MULT||((c==DIV||c==MOD)&&(t&UNSIGNED)))){
+      eval_const(&m->q2.val,t);
+      i=pof2(vmax);
+      if(i){
+        if(c==MOD){
+          vmax=zmsub(vmax,l2zm(1L));
+          m->code=AND;
+        }else{
+          vmax=l2zm(i-1);
+          if(c==DIV) m->code=RSHIFT; else m->code=LSHIFT;
+        }
+        c=m->code;
+	gval.vmax=vmax;
+	eval_const(&gval,MAXINT);
+	if(c==AND){
+	  insert_const(&m->q2.val,t);
+	}else{
+	  insert_const(&m->q2.val,INT);
+	  p->typf2=INT;
+	}
+      }
+    }
+#if FIXED_SP
+    if(c==CALL&&argsize<zm2l(m->q2.val.vmax)) argsize=zm2l(m->q2.val.vmax);
+#endif
+  }
+  peephole(p);
+
+  for(c=1;c<=MAXR;c++){
+    if(regsa[c]||regused[c]){
+      BSET(regs_modified,c);
+    }
+  }
+
+  localsize=(zm2l(offset)+3)/4*4;
+#if FIXED_SP
+  /*FIXME: adjust localsize to get an aligned stack-frame */
+#endif
+
+  function_top(f,v,localsize);
+
+#if FIXED_SP
+  pushed=0;
+#endif
+
+  for(;p;p=p->next){
+    c=p->code;t=p->typf;
+    if(c==NOP) {p->z.flags=0;continue;}
+    if(c==ALLOCREG) {regs[p->q1.reg]=1;continue;}
+    if(c==FREEREG) {regs[p->q1.reg]=0;continue;}
+    if(c==LABEL) {emit(f,"%s%d:\n",labprefix,t);continue;}
+    if(c==BRA){
+      if(0/*t==exit_label&&framesize==0*/)
+	emit(f,ret);
+      else
+	emit(f,"\tb\t%s%d\n",labprefix,t);
+      continue;
+    }
+    if(c>=BEQ&&c<BRA){
+      emit(f,"\tb%s\t",ccs[c-BEQ]);
+      if(isreg(q1)){
+	emit_obj(f,&p->q1,0);
+	emit(f,",");
+      }
+      emit(f,"%s%d\n",labprefix,t);
+      continue;
+    }
+    if(c==MOVETOREG){
+      load_reg(f,p->z.reg,&p->q1,regtype[p->z.reg]->flags);
+      continue;
+    }
+    if(c==MOVEFROMREG){
+      store_reg(f,p->z.reg,&p->q1,regtype[p->z.reg]->flags);
+      continue;
+    }
+    if((c==ASSIGN||c==PUSH)&&((t&NQ)>POINTER||((t&NQ)==CHAR&&zm2l(p->q2.val.vmax)!=1))){
+      ierror(0);
+    }
+    /* switch commutative operands if suitable */
+    if(c==ADD||c==MULT||c==AND||c==XOR||c==OR){
+      if(compare_objects(&p->q2,&p->z)){
+	struct obj tmp;
+	tmp=p->q1;
+	p->q1=p->q2;
+	p->q2=tmp;
+      }
+    }
+
+    p=preload(f,p);
+    c=p->code;
+    if(c==SUBPFP) c=SUB;
+    if(c==ADDI2P) c=ADD;
+    if(c==SUBIFP) c=SUB;
+    if(c==CONVERT){
+      if(ISFLOAT(q1typ(p))||ISFLOAT(ztyp(p))) ierror(0);
+      if(sizetab[q1typ(p)&NQ]<sizetab[ztyp(p)&NQ]){
+	if(q1typ(p)&UNSIGNED)
+	  emit(f,"\tzext.%s\t%s\n",dt(q1typ(p)),regnames[zreg]);
+	else
+	  emit(f,"\tsext.%s\t%s\n",dt(q1typ(p)),regnames[zreg]);
+      }
+      save_result(f,p);
+      continue;
+    }
+    if(c==KOMPLEMENT){
+      load_reg(f,zreg,&p->q1,t);
+      emit(f,"\tcpl.%s\t%s\n",dt(t),regnames[zreg]);
+      save_result(f,p);
+      continue;
+    }
+    if(c==SETRETURN){
+      load_reg(f,p->z.reg,&p->q1,t);
+      BSET(regs_modified,p->z.reg);
+      continue;
+    }
+    if(c==GETRETURN){
+      if(p->q1.reg){
+        zreg=p->q1.reg;
+	save_result(f,p);
+      }else
+        p->z.flags=0;
+      continue;
+    }
+    if(c==CALL){
+      int reg;
+      /*FIXME*/
+#if 0      
+      if(stack_valid&&(p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&(p->q1.v->fi->flags&ALL_STACK)){
+	if(framesize+zum2ul(p->q1.v->fi->stack1)>stack)
+	  stack=framesize+zum2ul(p->q1.v->fi->stack1);
+      }else
+	stack_valid=0;
+#endif
+      if((p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&p->q1.v->fi->inline_asm){
+        emit_inline_asm(f,p->q1.v->fi->inline_asm);
+      }else{
+	emit(f,"\tcall\t");
+	emit_obj(f,&p->q1,t);
+	emit(f,"\n");
+      }
+      /*FIXME*/
+#if FIXED_SP
+      pushed-=zm2l(p->q2.val.vmax);
+#endif
+      if((p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&(p->q1.v->fi->flags&ALL_REGS)){
+	bvunite(regs_modified,p->q1.v->fi->regs_modified,RSIZE);
+      }else{
+	int i;
+	for(i=1;i<=MAXR;i++){
+	  if(regscratch[i]) BSET(regs_modified,i);
+	}
+      }
+      continue;
+    }
+    if(c==ASSIGN||c==PUSH){
+      if(t==0) ierror(0);
+      if(c==PUSH){
+#if FIXED_SP
+	emit(f,"\tmov.%s\t%ld(%s),",dt(t),pushed,regnames[sp]);
+	emit_obj(f,&p->q1,t);
+	emit(f,"\n");
+	pushed+=zm2l(p->q2.val.vmax);
+#else
+	emit(f,"\tpush.%s\t",dt(t));
+	emit_obj(f,&p->q1,t);
+	emit(f,"\n");
+	push(zm2l(p->q2.val.vmax));
+#endif
+	continue;
+      }
+      if(c==ASSIGN){
+	load_reg(f,zreg,&p->q1,t);
+	save_result(f,p);
+      }
+      continue;
+    }
+    if(c==ADDRESS){
+      load_address(f,zreg,&p->q1,POINTER);
+      save_result(f,p);
+      continue;
+    }
+    if(c==MINUS){
+      load_reg(f,zreg,&p->q1,t);
+      emit(f,"\tneg.%s\t%s\n",dt(t),regnames[zreg]);
+      save_result(f,p);
+      continue;
+    }
+    if(c==TEST){
+      emit(f,"\ttst.%s\t",dt(t));
+      if(multiple_ccs)
+	emit(f,"%s,",regnames[zreg]);
+      emit_obj(f,&p->q1,t);
+      emit(f,"\n");
+      if(multiple_ccs)
+	save_result(f,p);
+      continue;
+    }
+    if(c==COMPARE){
+      emit(f,"\tcmp.%s\t",dt(t));
+      if(multiple_ccs)
+	emit(f,"%s,",regnames[zreg]);
+      emit_obj(f,&p->q1,t);
+      emit(f,",");
+      emit_obj(f,&p->q2,t);
+      emit(f,"\n");
+      if(multiple_ccs)
+	save_result(f,p);
+      continue;
+    }
+    if((c>=OR&&c<=AND)||(c>=LSHIFT&&c<=MOD)){
+      if(!THREE_ADDR)
+	load_reg(f,zreg,&p->q1,t);
+      if(c>=OR&&c<=AND)
+	emit(f,"\t%s.%s\t%s,",logicals[c-OR],dt(t),regnames[zreg]);
+      else
+	emit(f,"\t%s.%s\t%s,",arithmetics[c-LSHIFT],dt(t),regnames[zreg]);
+      if(THREE_ADDR){
+	emit_obj(f,&p->q1,t);
+	emit(f,",");
+      }
+      emit_obj(f,&p->q2,t);
+      emit(f,"\n");
+      save_result(f,p);
+      continue;
+    }
+    pric2(stdout,p);
+    ierror(0);
+  }
+  function_bottom(f,v,localsize);
+  if(stack_valid){
+    if(!v->fi) v->fi=new_fi();
+    v->fi->flags|=ALL_STACK;
+    v->fi->stack1=stack;
+  }
+  emit(f,"# stacksize=%lu%s\n",zum2ul(stack),stack_valid?"":"+??");
+}
+
+int shortcut(int code,int typ)
+{
+  return 0;
+}
+
+int reg_parm(struct reg_handle *m, struct Typ *t,int vararg,struct Typ *d)
+{
+  int f;
+  f=t->flags&NQ;
+  if(f<=LONG||f==POINTER){
+    if(m->gregs>=GPR_ARGS)
+      return 0;
+    else
+      return FIRST_GPR+3+m->gregs++;
+  }
+  if(ISFLOAT(f)){
+    if(m->fregs>=FPR_ARGS)
+      return 0;
+    else
+      return FIRST_FPR+2+m->fregs++;
+  }
+  return 0;
+}
+
+int handle_pragma(const char *s)
+{
+}
+void cleanup_cg(FILE *f)
+{
+}
+void cleanup_db(FILE *f)
+{
+  if(f) section=-1;
+}
+
diff --git a/machines/generic/machine.dt b/machines/generic/machine.dt
new file mode 100755
index 0000000..526c8d4
--- /dev/null
+++ b/machines/generic/machine.dt
@@ -0,0 +1,16 @@
+S8BS
+S8BU
+S16BSBE S16BSLE
+S16BUBE S16BULE
+S32BSBE S32BSLE
+S32BUBE S32BULE
+S32BSBE S32BSLE
+S32BUBE S32BULE
+S64BSBE S64BSLE
+S64BUBE S64BULE
+S32BIEEEBE
+S64BIEEEBE
+S64BIEEEBE
+S32BUBE S32BULE
+
+
diff --git a/machines/generic/machine.h b/machines/generic/machine.h
new file mode 100755
index 0000000..118a4d7
--- /dev/null
+++ b/machines/generic/machine.h
@@ -0,0 +1,151 @@
+/*  Example backend for vbcc, it models a generic 32bit RISC or CISC
+    CPU.
+
+    Configurable at build-time are:
+    - number of (32bit) general-purpose-registers
+    - number of (64bit) floating-point-registers
+    - number of (8bit) condition-code-registers
+    - mechanism for stack-arguments (moving ot fixed sp)
+
+    It allows to select as run-time-options:
+    - two- or three-address code
+    - memory operands or load-store-architecture
+    - number of register-arguments
+    - number of caller-save-registers
+*/
+
+/* buil-time configurable options: */
+#define NUM_GPRS 32
+#define NUM_FPRS 32
+#define NUM_CCRS 8
+#define FIXED_SP 1
+
+#include "dt.h"
+
+/* internally used by the backend */
+#define FIRST_GPR 1
+#define LAST_GPR (FIRST_GPR+NUM_GPRS-1)
+#define FIRST_FPR (LAST_GPR+1)
+#define LAST_FPR (FIRST_FPR+NUM_FPRS-1)
+#define FIRST_CCR (LAST_FPR+1)
+#define LAST_CCR (FIRST_CCR+NUM_CCRS-1)
+
+/*  This struct can be used to implement machine-specific           */
+/*  addressing-modes.                                               */
+/*  Currently possible are (const,gpr) and (gpr,gpr)                */
+struct AddressingMode{
+    int flags;
+    int base;
+    long offset;
+};
+
+/*  The number of registers of the target machine.                  */
+#define MAXR NUM_GPRS+NUM_FPRS+NUM_CCRS
+
+/*  Number of commandline-options the code-generator accepts.       */
+#define MAXGF 20
+
+/*  If this is set to zero vbcc will not generate ICs where the     */
+/*  target operand is the same as the 2nd source operand.           */
+/*  This can sometimes simplify the code-generator, but usually     */
+/*  the code is better if the code-generator allows it.             */
+#define USEQ2ASZ 1
+
+/*  This specifies the smallest integer type that can be added to a */
+/*  pointer.                                                        */
+#define MINADDI2P INT
+
+/*  If the bytes of an integer are ordered most significant byte    */
+/*  byte first and then decreasing set BIGENDIAN to 1.              */
+#define BIGENDIAN 1
+
+/*  If the bytes of an integer are ordered lest significant byte    */
+/*  byte first and then increasing set LITTLEENDIAN to 1.           */
+#define LITTLEENDIAN 0
+
+/*  Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive.    */
+
+/*  If switch-statements should be generated as a sequence of       */
+/*  SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1.      */
+/*  This can yield better code on some machines.                    */
+#define SWITCHSUBS 0
+
+/*  In optimizing compilation certain library memcpy/strcpy-calls   */
+/*  with length known at compile-time will be inlined using an      */
+/*  ASSIGN-IC if the size is less or equal to INLINEMEMCPY.         */
+/*  The type used for the ASSIGN-IC will be UNSIGNED|CHAR.          */
+#define INLINEMEMCPY 1024
+
+/*  Parameters are sometimes passed in registers without __reg.     */
+#define HAVE_REGPARMS 1
+
+/*  Parameters on the stack should be pushed in order rather than   */
+/*  in reverse order.                                               */
+#define ORDERED_PUSH FIXED_SP
+
+/*  Structure for reg_parm().                                       */
+struct reg_handle{
+    unsigned long gregs;
+    unsigned long fregs;
+};
+
+/*  We have some target-specific variable attributes.               */
+#define HAVE_TARGET_ATTRIBUTES
+
+/* We have target-specific pragmas */
+#define HAVE_TARGET_PRAGMAS
+
+/*  We keep track of all registers modified by a function.          */
+#define HAVE_REGS_MODIFIED 1
+
+/* We have a implement our own cost-functions to adapt 
+   register-allocation */
+#define HAVE_TARGET_RALLOC 1
+#define cost_move_reg(x,y) 1
+#define cost_load_reg(x,y) 2
+#define cost_save_reg(x,y) 2
+#define cost_pushpop_reg(x) 3
+
+/* size of buffer for asm-output, this can be used to do
+   peephole-optimizations of the generated assembly-output */
+#define EMIT_BUF_LEN 1024 /* should be enough */
+/* number of asm-output lines buffered */
+#define EMIT_BUF_DEPTH 4
+
+/*  We have no asm_peephole to optimize assembly-output */
+#define HAVE_TARGET_PEEPHOLE 0
+
+/* we do not have a mark_eff_ics function, this is used to prevent
+   optimizations on code which can already be implemented by efficient
+   assembly */
+#undef HAVE_TARGET_EFF_IC
+
+/* we only need the standard data types (no bit-types, different pointers
+   etc.) */
+#undef HAVE_EXT_TYPES
+#undef HAVE_TGT_PRINTVAL
+
+/* we do not need extra elements in the IC */
+#undef HAVE_EXT_IC
+
+/* we do not use unsigned int as size_t (but unsigned long, the default) */
+#define HAVE_INT_SIZET 1
+
+/* we do not need register-pairs */
+#undef HAVE_REGPAIRS
+
+
+/* do not create CONVERT ICs from integers smaller than int to floats */
+#define MIN_INT_TO_FLOAT_TYPE INT
+
+/* do not create CONVERT ICs from floats to ints smaller than int */
+#define MIN_FLOAT_TO_INT_TYPE INT
+
+/* do not create CONVERT_ICs from floats to unsigned integers */
+#define AVOID_FLOAT_TO_UNSIGNED 1
+
+/* do not create CONVERT_ICs from unsigned integers to floats */
+#define AVOID_UNSIGNED_TO_FLOAT 1
+
+/* convert multiplications/division by powers of two to shifts */
+#define HAVE_POF2OPT 1
diff --git a/machines/hc12/machine.c b/machines/hc12/machine.c
new file mode 100755
index 0000000..c6bc237
--- /dev/null
+++ b/machines/hc12/machine.c
@@ -0,0 +1,3872 @@
+/*  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?)
+  struct-copy Problemfälle
+  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 V1.0 (c) in 2000-2021 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","double64"};
+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"};
+
+/*  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,1};
+
+int reg_prio[MAXR+1]={0,0,1,1,0,0,1};
+
+struct reg_handle empty_reg_handle={0};
+
+/* Names of target-specific variable attributes.                */
+char *g_attr_name[]={"__interrupt","__dpage",0};
+#define INTERRUPT 1
+#define DPAGE     2
+
+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",".4byte",".4byte",
+		    "(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||ISFLOAT(t&NQ))
+#define ISHWORD(t) ((t&NQ)==INT||(t&NQ)==SHORT||(t&NQ)==NPOINTER)
+#define ISCHWORD(t) ((t&NQ)==CHAR||ISHWORD(t))
+#define ISCHAR(t) ((t&NQ)==CHAR)
+#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 EXTEND(t) (((t)&UNSIGNED)?"\tclra\n":SEX)
+
+#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) 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(ISFLOAT(p->am->base)){
+	unsigned char *m=(unsigned char *)&p->val.vfloat;
+	if(zm2l(p->am->offset)==2)
+	  emit(f,"#0x%02x%02x",m[2],m[3]);
+	else
+	  emit(f,"#0x%02x%02x",m[0],m[1]);
+	return;
+      }else if((t&NQ)==CHAR){
+	vumax=zumrshift(vumax,24-8*p->am->offset);
+	vumax=zumand(vumax,ul2zum(255UL));
+      }else{
+	vumax=zumrshift(vumax,16-8*p->am->offset);
+	vumax=zumand(vumax,ul2zum(0xFFFFUL));
+      }
+      emit(f,"#%lu",zum2ul(vumax));
+      return;
+    }
+    if(flags<POST_INC||flags>PRE_DEC||CPU==6812)
+      emit(f,"%ld",p->am->offset&0xffff);
+    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&REG){
+    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>=-16&&off<=15)
+	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>=-16&&off<=15)
+      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|KONST))==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&(DREFOBJ|KONST))==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)&&section!=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&&regused[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&&regused[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&&regused[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&REG)||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&REG)&&p2->q1.reg==p->z.reg)||((p2->q2.flags&REG)&&p2->q2.reg==p->z.reg)||((p2->z.flags&REG)&&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&REG)||p->q2.reg!=r)&&(!(p->z.flags&REG)||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&REG)&&p2->q1.reg==r)||((p2->q2.flags&REG)&&p2->q2.reg==r)||((p2->z.flags&REG)&&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&REG)||p->q1.reg!=r)&&(!(p->z.flags&REG)||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&REG)&&p2->q1.reg==r)||((p2->q2.flags&REG)&&p2->q2.reg==r)||((p2->z.flags&REG)&&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&REG)||p->q1.reg!=r)&&(!(p->q2.flags&REG)||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&REG)&&p2->q1.reg==r)||((p2->q2.flags&REG)&&p2->q2.reg==r)||((p2->z.flags&REG)&&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&REG)&&ISACC(p->q2.reg)) ierror(0);
+    if(p->z.am)
+      if(p->z.am->flags==ACC_IND) ierror(0);
+    else
+      if((p->z.flags&REG)&&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&REG)||p->q1.reg!=r)&&
+	 (!(p->q2.flags&REG)||p->q2.reg!=r)&&
+	 (!(p->z.flags&REG)||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&REG)&&p->q1.reg==r) return 0;
+    if((p->q2.flags&REG)&&p->q2.reg==r) return 0;
+    if((p->z.flags&REG)&&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(g_flags[13]&USEDFLAG){
+    msizetab[DOUBLE]=msizetab[LDOUBLE]=8;
+    dct[DOUBLE]=dct[LDOUBLE]=".8byte";
+  }
+  
+
+  /*  Initialize some values which cannot be statically initialized   */
+  /*  because they are stored in the target's arithmetic.             */
+  maxalign=l2zm(1L);
+  char_bit=l2zm(8L);
+  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]=&ltyp;
+
+  /*  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.          */
+  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==9)
+    marray[1]="__TURBO9__";
+  target_macros=marray;
+
+
+  if(CPU==9||CPU==6812){
+    declare_builtin("__mulint16",INT,INT,acc,INT,iy,1,mystrdup("\temul"));
+    declare_builtin("__divint16",INT,INT,acc,INT,ix,1,mystrdup("\tidivs\n\ttfr\tx,d"));
+    declare_builtin("__divuint16",UNSIGNED|INT,UNSIGNED|INT,acc,UNSIGNED|INT,ix,1,mystrdup("\tidiv\n\ttfr\tx,d"));
+    declare_builtin("__modint16",INT,INT,acc,INT,ix,1,mystrdup("\tidivs"));
+    declare_builtin("__moduint16",UNSIGNED|INT,UNSIGNED|INT,acc,UNSIGNED|INT,ix,1,mystrdup("\tidiv"));
+  }else{
+    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("__sint16toflt32",FLOAT,INT,0,0,0,1,0);
+  declare_builtin("__uint16toflt32",FLOAT,UNSIGNED|INT,0,0,0,1,0);
+  declare_builtin("__sint16toflt64",DOUBLE,INT,0,0,0,1,0);
+  declare_builtin("__uint16toflt64",DOUBLE,UNSIGNED|INT,0,0,0,1,0);
+  declare_builtin("__flt32tosint16",INT,FLOAT,0,0,0,1,0);
+  declare_builtin("__flt32touint16",UNSIGNED|INT,FLOAT,0,0,0,1,0);
+  declare_builtin("__flt64tosint16",INT,DOUBLE,0,0,0,1,0);
+  declare_builtin("__flt64touint16",UNSIGNED|INT,DOUBLE,0,0,0,1,0);
+
+  declare_builtin("__sint8toflt32",FLOAT,CHAR,0,0,0,1,0);
+  declare_builtin("__uint8toflt32",FLOAT,UNSIGNED|CHAR,0,0,0,1,0);
+  declare_builtin("__sint8toflt64",DOUBLE,CHAR,0,0,0,1,0);
+  declare_builtin("__uint8toflt64",DOUBLE,UNSIGNED|CHAR,0,0,0,1,0);
+  declare_builtin("__flt32tosint8",CHAR,FLOAT,0,0,0,1,0);
+  declare_builtin("__flt32touint8",UNSIGNED|CHAR,FLOAT,0,0,0,1,0);
+  declare_builtin("__flt64tosint8",CHAR,DOUBLE,0,0,0,1,0);
+  declare_builtin("__flt64touint8",UNSIGNED|CHAR,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,0,0,1,0);
+  declare_builtin("__cmpflt32",CHAR,FLOAT,0,FLOAT,0,1,0);
+
+  declare_builtin("__addflt32 ",DOUBLE,DOUBLE,0,DOUBLE,0,1,0);
+  declare_builtin("__subflt32 ",DOUBLE,DOUBLE,0,DOUBLE,0,1,0);
+  declare_builtin("__mulflt32 ",DOUBLE,DOUBLE,0,DOUBLE,0,1,0);
+  declare_builtin("__divflt32 ",DOUBLE,DOUBLE,0,DOUBLE,0,1,0);
+  declare_builtin("__negflt32 ",DOUBLE,DOUBLE,0,0,0,1,0);
+  declare_builtin("__cmpflt32 ",CHAR,DOUBLE,0,DOUBLE,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,0,0,1,0);
+  declare_builtin("__cmpflt64 ",CHAR,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)&&regok(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){
+      sprintf(fname,"__cmp%sint32",(t&UNSIGNED)?"u":"s");
+      ret=fname;
+    }
+    if(ISFLOAT(t)){
+      return (t==FLOAT)?"__cmpflt32":"__cmpflt32 ";
+      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(ISFLOAT(t)&&ISFLOAT(t2)) return 0;
+#if 0
+      /* currently support only 32bit flt */
+      if(t==FLOAT&&t2==DOUBLE) return "__flt64toflt32";
+      if(t==DOUBLE&&t2==FLOAT) return "__flt32toflt64";
+#endif
+      if(ISFLOAT(t)){
+        sprintf(fname,"__%cint%ldtoflt%ld",(t2&UNSIGNED)?'u':'s',zm2l(sizetab[t2&NQ])*8,zm2l(sizetab[t&NQ])*8);
+        ret=fname;
+      }
+      if(ISFLOAT(t2)){
+        sprintf(fname,"__flt%ldto%cint%ld",zm2l(sizetab[t2&NQ])*8,(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%s",ename[c],(c!=MULT&&(t&UNSIGNED))?"u":"",ISFLOAT(t)?"flt":"int",zm2l(sizetab[t&NQ])*8,(t&NQ)>=DOUBLE?" ":"");
+          ret=fname;
+	}
+      }
+    }
+    if((c==MULT/*&&(CPU!=6812||(t&NQ)==LONG)*/)||c==DIV||c==MOD){
+      sprintf(fname,"__%s%s%s%ld%s",ename[c],(c!=MULT&&(t&UNSIGNED))?"u":"",ISFLOAT(t)?"flt":"int",zm2l(sizetab[t&NQ])*8,(t&NQ)>=DOUBLE?" ":"");
+      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(ISFLOAT(op)){
+    if(ISFLOAT(tp)) return 0;
+    return 1;
+  }
+  if(ISFLOAT(tp)) return 1;
+  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&&section!=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))&&section!=DATA){
+	emit(f,dataname);if(f) section=DATA;
+      }
+      if(v->clist&&constflag&&!(g_flags[3]&USEDFLAG)&&section!=RODATA){
+	emit(f,rodataname);if(f) section=RODATA;
+      }
+      if(!v->clist&&section!=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))&&section!=DATA){
+	  emit(f,dataname);if(f) section=DATA;
+	}
+	if(v->clist&&constflag&&!(g_flags[3]&USEDFLAG)&&section!=RODATA){
+	  emit(f,rodataname);if(f) section=RODATA;
+	}
+	if(!v->clist&&section!=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;
+      if(zm2l(sizetab[t&NQ])==8){
+	emit(f,",0x%02x%02x%02x%02x",ip[4],ip[5],ip[6],ip[7]);
+      }
+      emit(f,"0x%02x%02x%02x%02x",ip[0],ip[1],ip[2],ip[3]);
+    }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
+    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((regsa[c]==REGSA_NEVER||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]&&regs[ix]&&regs[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;
+  if(!v->fi) v->fi=new_fi();
+  v->fi->flags|=ALL_REGS;
+  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>=BEQ&&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)&&ISINT(t)&&ISLWORD(p->typf2)&&ISINT(p->typf2)){
+      p->code=c=ASSIGN;
+      p->q2.val.vmax=l2zm(4L);
+    }
+
+    if((p->q2.flags&REG)&&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))&&ISINT(t))
+      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&REG)&&p->q2.reg==ix){
+	  if((p->z.flags&REG)&&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&REG)&&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");
+	}
+	dontpop += 4;
+	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)&&regs[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)&&regs[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");
+	  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(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?(CPU==6812?size:(size/2)):size/8);
+	  if(regs[acc]&&!scratchreg(acc,p)){
+	    if(c==PUSH)
+	      emit(f,"\tst%c\t%ld,%s\n",(CPU!=6812&&cnt<=255)?'b':'d',loff-roff-6-stackoffset,regnames[sp]);
+	    else{
+	      if(CPU!=6812&&cnt<=255){
+		emit(f,SPUSH("b"));
+		push(1);
+	      }else{
+		emit(f,SPUSHD);
+		push(2);
+	      }
+	    }
+	    pd=(CPU!=6812&&cnt<=255)?1:2;
+	  }
+	  if(CPU!=6812&&cnt<=255)
+	    emit(f,"\tldb\t#%lu\n",cnt);
+	  else
+	    emit(f,"\tldd\t#%lu\n",cnt);
+	  cc=0;
+#if 0
+	  if(CPU!=6812&&((!regsa[iu]&&regs[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\t1,%s+,1,%s+\n",regnames[qr],regnames[zr]);
+	      size=0;
+	    }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<=255)
+	      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]&&regs[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]&&regs[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&REG)||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)&&regs[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)&&regs[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&&reg==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&&reg==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&&reg==ix&&CPU==6812){
+		emit(f,"\tinx\n");
+	      }else if(l==1&&reg==iy&&CPU==6812){
+		emit(f,"\tiny\n");
+	      }else if(l==-1&&reg==ix&&CPU==6812){
+		emit(f,"\tdex\n");
+	      }else if(l==-1&&reg==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)&&regs[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>=16){
+	    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!=6812?"\tlsra\n\trorb\n":"\tlsrd\n");
+	      }else{
+		if(oldl>8||(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!=6812?"\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;
+
+	  /* tell if X or D are ready for shifting */
+	  int xdone = 0; 
+	  int ddone = 0;
+
+	  /* free X if q1 is in X */
+	  if (ISRX(q1)) {
+	    ddone = 1;
+	    if (ISRACC(q2)) {
+	      xdone = 1;
+	      if (ISCHAR(p->typf2)) emit(f, EXTEND(p->typf2));
+	      emit(f, "\texg\tx,d\n");
+	    }
+	    else {
+	      emit(f, "\ttfr\tx,d\n");
+	    }
+	  }
+	  /* load q2 in X if not done yet */
+	  if (!xdone) {
+	    if (ISLWORD(p->typf2)) {
+	      /* q2 is 32bit, it is in memory, we take the lower 16bit */
+	      inc_addr(&p->q2, 2, p->typf2);
+	      load_reg(f, ix, &p->q2, INT);
+	    }
+	    else if (ISHWORD(p->typf2)) {
+	      /* q2 is 16bit, load it directly in X */
+	      load_reg(f, ix, &p->q2, INT);
+	    }
+	    else {
+	      /* q2 is 8bit, we must extend it in D */
+	      /* if D is busy with q1, save q1 in X */
+	      if (ddone || ISRACC(q1)) {
+		if (ISCHAR(t)) emit(f, EXTEND(t));
+		emit(f, "\ttfr\td,x\n");
+		load_reg(f, acc, &p->q2, CHAR);
+		emit(f, EXTEND(p->typf2));
+		emit(f, "\texg\tx,d\n");
+		ddone = 1;
+	      }
+	      else {
+		load_reg(f, acc, &p->q2, CHAR);
+		emit(f, EXTEND(p->typf2));
+		emit(f, "\ttfr\td,x\n");
+	      }
+	    }
+	  }
+	  /* load q1 in D if not done yet */
+	  if (!ddone) {
+	    load_reg(f, acc, &p->q1, t);
+	    if (ISCHAR(t)) emit(f, EXTEND(t));
+	  }
+
+
+	  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>>8)&255;
+	    if(c==AND&&h==0)
+	      emit(f,"\tclra\n");
+	    else if(c==XOR&&h==255)
+	      emit(f,"\tcoma\n");
+	    else if((c==AND&&h!=255)||(c==OR&&h!=0)||(c==XOR&&h!=0))
+	      emit(f,"\t%sa\t#%lu\n",s,h);
+	  }
+	  h=l&255;
+	  if(c==AND&&h==0)
+	    emit(f,"\tclrb\n");
+	  else if(c==XOR&&h==255)
+	    emit(f,"\tcomb\n");
+	  else if((c==AND&&h!=255)||(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;
+} 
diff --git a/machines/hc12/machine.dt b/machines/hc12/machine.dt
new file mode 100755
index 0000000..7c090f1
--- /dev/null
+++ b/machines/hc12/machine.dt
@@ -0,0 +1,16 @@
+S8BS
+S8BU
+S16BSBE S16BSLE
+S16BUBE S16BULE
+S16BSBE S16BSLE
+S16BUBE S16BULE
+S32BSBE S32BSLE
+S32BUBE S32BULE
+S64BSBE S64BSLE
+S64BUBE S64BULE
+S32BIEEEBE
+S32BIEEEBE
+S32BIEEEBE
+S16BUbE S16BULE
+
+
diff --git a/machines/hc12/machine.h b/machines/hc12/machine.h
new file mode 100755
index 0000000..096e608
--- /dev/null
+++ b/machines/hc12/machine.h
@@ -0,0 +1,191 @@
+/*  Example of a code-generator for Motorola 68hc12 16bit microcontrollers.*/
+
+#include "dt.h"
+
+/* We have extended types! What we have to do to support them:      */
+/* - #define HAVE_EXT_TYPES
+   - #undef all standard types
+   - #define all standard types plus new types
+   - write eval_const and insert_const
+   - write typedefs for zmax and zumax
+   - write typname[]
+   - write conv_typ()
+   - optionally #define ISPOINTER, ISARITH, ISINT etc.
+   - optionally #define HAVE_TGT_PRINTVAL and write printval
+   - optionally #define POINTER_TYPE
+   - optionally #define HAVE_TGT_FALIGN and write falign
+   - optionally #define HAVE_TGT_SZOF and write szof
+   - optionally add functions for attribute-handling
+*/
+#define HAVE_EXT_TYPES 1
+
+#define HAVE_TGT_PRINTVAL
+
+#undef CHAR
+#undef SHORT
+#undef INT
+#undef LONG
+#undef LLONG
+#undef FLOAT
+#undef DOUBLE
+#undef LDOUBLE
+#undef VOID
+#undef POINTER
+#undef ARRAY
+#undef STRUCT
+#undef UNION
+#undef ENUM
+#undef FUNKT
+#undef MAXINT
+#undef MAX_TYPE
+
+#define BIT 1
+#define CHAR 2
+#define SHORT 3
+#define INT 4
+#define LONG 5
+#define LLONG 6
+#define FLOAT 7
+#define DOUBLE 8
+#define LDOUBLE 9
+#define VOID 10
+#define NPOINTER 11
+#define FPOINTER 12
+#define HPOINTER 13
+#define ARRAY 14
+#define STRUCT 15
+#define UNION 16
+#define ENUM 17
+#define FUNKT 18
+
+#define MAXINT 19
+
+#define MAX_TYPE MAXINT
+
+#define POINTER_TYPE(x) pointer_type(x)
+extern int pointer_type();
+#define ISPOINTER(x) ((x&NQ)>=NPOINTER&&(x&NQ)<=HPOINTER)
+#define ISSCALAR(x) ((x&NQ)>=BIT&&(x&NQ)<=HPOINTER)
+#define ISINT(x) ((x&NQ)>=BIT&&(x&NQ)<=LLONG)
+#define PTRDIFF_T(x) ((x)==HPOINTER?LONG:INT)
+
+typedef zllong zmax;
+typedef zullong zumax;
+
+union atyps{
+  zchar vchar;
+  zuchar vuchar;
+  zshort vshort;
+  zushort vushort;
+  zint vint;
+  zuint vuint;
+  zlong vlong;
+  zulong vulong;
+  zllong vllong;
+  zullong vullong;
+  zmax vmax;
+  zumax vumax;
+  zfloat vfloat;
+  zdouble vdouble;
+  zldouble vldouble;
+};
+
+/*  This struct can be used to implement machine-specific           */
+/*  addressing-modes.                                               */
+/*  Not used in this code-generrator.                               */
+struct AddressingMode{
+    int flags;
+    int base;
+    long offset;
+    struct Var *v;
+};
+
+/* This type will be added to every IC. Can be used by the cg.      */
+#define HAVE_EXT_IC 1
+struct ext_ic {
+  int flags;
+  int r;
+  long offset;
+};
+
+/*  The number of registers of the target machine.                  */
+#define MAXR 6
+
+/*  Number of commandline-options the code-generator accepts.       */
+#define MAXGF 20
+
+/*  If this is set to zero vbcc will not generate ICs where the     */
+/*  target operand is the same as the 2nd source operand.           */
+/*  This can sometimes simplify the code-generator, but usually     */
+/*  the code is better if the code-generator allows it.             */
+#define USEQ2ASZ 1
+
+/*  This specifies the smallest integer type that can be added to a */
+/*  pointer.                                                        */
+extern int MINADDI2P;
+
+/*  If the bytes of an integer are ordered most significant byte    */
+/*  byte first and then decreasing set BIGENDIAN to 1.              */
+#define BIGENDIAN 1
+
+/*  If the bytes of an integer are ordered lest significant byte    */
+/*  byte first and then increasing set LITTLEENDIAN to 1.           */
+#define LITTLEENDIAN 0
+
+/*  Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive.    */
+
+/*  If switch-statements should be generated as a sequence of       */
+/*  SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1.      */
+/*  This can yield better code on some machines.                    */
+extern int switchsubs;
+#define SWITCHSUBS switchsubs
+
+/*  In optimizing compilation certain library memcpy/strcpy-calls   */
+/*  with length known at compile-time will be inlined using an      */
+/*  ASSIGN-IC if the size is less or equal to INLINEMEMCPY.         */
+/*  The type used for the ASSIGN-IC will be UNSIGNED|CHAR.          */
+#define INLINEMEMCPY 1024
+
+#define HAVE_REGPARMS 1
+
+struct reg_handle {
+  int gpr;
+};
+
+/*  We use unsigned int as size_t rather than unsigned long which   */
+/*  is the default setting.                                         */
+#define HAVE_INT_SIZET 1
+
+/*  We have register pairs.                                         */
+#define HAVE_REGPAIRS 1
+
+/*  We keep track of all registers modified by a function.          */
+#define HAVE_REGS_MODIFIED 1
+
+#define HAVE_TARGET_RALLOC 1
+#define cost_load_reg(r,v) 4
+#define cost_save_reg(r,v) 4
+#define cost_move_reg(i,j) 2
+#define cost_pushpop_reg(r) 2
+
+/* size of buffer for asm-output */
+#define EMIT_BUF_LEN 1024 /* should be enough */
+/* number of asm-output lines buffered */
+#define EMIT_BUF_DEPTH 4
+
+/*  We have asm_peephole to optimize assembly-output */
+#define HAVE_TARGET_PEEPHOLE 1
+
+/*  We have some target-specific variable attributes.               */
+#define HAVE_TARGET_ATTRIBUTES 1
+
+/* We use builtin libcalls for some operations */
+#define HAVE_LIBCALLS 1
+
+/* We prefer BNE rather than BGT. */
+#define HAVE_WANTBNE 1
+
+#define HAVE_POF2OPT 1
+
+/* Use char for return of comparison libcalls */
+#define LIBCALL_CMPTYPE CHAR
diff --git a/machines/i386/machine.c b/machines/i386/machine.c
new file mode 100755
index 0000000..68c553c
--- /dev/null
+++ b/machines/i386/machine.c
@@ -0,0 +1,2048 @@
+
+/*  Code generator for Intel 80386 or higher.                   */
+
+#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 i386 V0.7a (c) in 1996-2006 by Volker Barthelmann";
+
+/*  Commandline-flags the code-generator accepts                */
+int g_flags[MAXGF]={VALFLAG,VALFLAG,0,0,
+                    0,0,0,0,
+		    0};
+char *g_flags_name[MAXGF]={"cpu","fpu","no-delayed-popping","const-in-data",
+                           "merge-constants","elf","longalign","safe-fp",
+			   "use-framepointer"};
+union ppi g_flags_val[MAXGF];
+
+/* Typenames (needed because of HAVE_EXT_TYPES). */
+char *typname[]={"strange","char","short","bshort","int","bint",
+		 "long","blong","long long","blong long",
+		 "float","bfloat","double","bdouble",
+		 "long double","blong double","void",
+                 "pointer","bpointer",
+		 "array","struct","union","enum","function"};
+
+/*  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[MAXR+1]={"noreg","%eax","%ecx","%edx","%ebx",
+                                "%esi","%edi","%ebp","%esp",
+                                "%st(0)","%st(1)","%st(2)","%st(3)",
+                                "%st(4)","%st(5)","%st(6)","%st(7)",
+                                "%eax/%edx","%esi/%edi"};
+
+/*  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,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0};
+
+
+/****************************************/
+/*  Some private data and functions.    */
+/****************************************/
+
+#define USEFP (g_flags[8]&USEDFLAG)
+
+static long malign[MAX_TYPE+1]=  {1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,1,1,1,2,2};
+static long msizetab[MAX_TYPE+1]={0,1,2,2,4,4,4,4,8,8,4,4,8,8,8,8,0,4,4,0,0,0,4,0};
+
+#define ISBE(x) (((x)&NQ)==BPOINTER||(((x)&NQ)>=BSHORT&&((x)&NQ)<=BLDOUBLE&&((x)&1)))
+#define LETYPE(x) ((x)-1)
+
+struct Typ ltyp={LONG},ldbl={DOUBLE};
+
+#define DATA 0
+#define BSS 1
+#define CODE 2
+
+static char *marray[]={"__I386__","__X86__",
+		       "__bigendian=__attr(\"bigendian\")",
+		       "__littleendian=__attr(\"littleendian\")",
+		       0};
+
+static int section=-1,newobj;
+static char *codename="\t.text\n",*dataname="\t.data\n",*bssname="";
+static const int ax=1,cx=2,dx=3,bx=4,si=5,di=6,bp=7,sp=8,axdx=17,sidi=18;
+static char x_t[]={'?','b','w','w','l','l','l','l','?','?','s','s','l','l','l','l','v','l','l','a','s','u','e','f'};
+static void pr(FILE *,struct IC *);
+static void function_top(FILE *,struct Var *,long);
+static void function_bottom(FILE *f,struct Var *,long);
+
+#define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
+#define isconst(x) ((p->x.flags&(KONST|DREFOBJ))==KONST)
+#define isvaddr(x) ((p->x.flags&(VARADR|DREFOBJ))==VARADR)
+#define isvconst(x) (isconst(x)||isvaddr(x))
+
+static long loff,stackoffset,notpopped,dontpop,maxpushed,stack;
+
+static char *ccs[]={"z","nz","l","ge","le","g","mp"};
+static char *ccu[]={"z","nz","b","ae","be","a","mp"};
+static char *logicals[]={"or","xor","and"};
+static char *arithmetics[]={"sal","sar","add","sub","imul","div","mod"};
+static char *farithmetics[]={"f?","f?","fadd","fsub","fmul","fdiv","fsubr","fdivr"};
+static char *dct[]={"","byte","short","short","long","long",
+		    "long","long","long","long","long","long","long","long",
+		    "long","long","long","long","long","long"};
+
+static int pushedsize,pushorder=2;
+static int fst[8];
+static int cxl,dil,sil;
+static char *idprefix="",*labprefix="l";
+
+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;
+}
+/* pushed on the stack by a callee, no pop needed */
+static void callee_push(long l)
+{
+}
+static void push(long l)
+{
+  stackoffset-=l;
+  if(stackoffset<maxpushed) maxpushed=stackoffset;
+}
+static void pop(long l)
+{
+  stackoffset+=l;
+}
+
+void title(FILE *f)
+{
+  static int done;
+  extern char *inname; /*grmpf*/
+  if(!done&&f){
+    done=1;
+    emit(f,"\t.file\t\"%s\"\n",inname);
+  }
+} 
+
+static void emit_obj(FILE *f,struct obj *p,int t)
+/*  Gibt Objekt auf Bildschirm aus                      */
+{
+  if((p->flags&(DREFOBJ|KONST))==(DREFOBJ|KONST)){
+    emitval(f,&p->val,p->dtyp&NU);
+    return;
+  }
+  if((p->flags&(DREFOBJ|REG))==(DREFOBJ|REG)) emit(f,"(");
+  if(p->flags&VARADR) emit(f,"$");
+  if((p->flags&VAR)&&!(p->flags&REG)) {
+    if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER){
+      if(USEFP||vlas){
+	if(!zmleq(l2zm(0L),p->v->offset))
+	  emit(f,"%ld(%s)",(long)(-zm2l(p->v->offset)+zm2l(p->val.vmax))+4,regnames[bp]);
+	else
+	  emit(f,"%ld(%s)",(long)(zm2l(p->v->offset)+zm2l(p->val.vmax))-loff-pushedsize,regnames[bp]);
+      }else{
+	if(!zmleq(l2zm(0L),p->v->offset))
+	  emit(f,"%ld(%s)",(long)(loff-zm2l(p->v->offset)+zm2l(p->val.vmax))-stackoffset+pushedsize,regnames[sp]);
+	else
+	  emit(f,"%ld(%s)",(long)(zm2l(p->v->offset)+zm2l(p->val.vmax)-stackoffset),regnames[sp]);
+      }
+    }else{
+      if(!zmeqto(l2zm(0L),p->val.vmax)){emitval(f,&p->val,LONG);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(p->flags&REG){
+    if(p->reg>8){
+      int i;
+      for(i=0;i<8;i++){
+        if(fst[i]==p->reg)
+          emit(f,"%s",regnames[i+9]);
+      }
+    }else{
+      t&=NQ;
+      if(t==CHAR&&!(p->flags&DREFOBJ)) emit(f,"%%%cl",regnames[p->reg][2]);
+      else if(t==SHORT&&!(p->flags&DREFOBJ)) emit(f,"%%%s",regnames[p->reg]+2);
+      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|REG)) emit(f,")");
+}
+
+static char *mregname(int r,int t)
+{
+  static char s[8];
+  t&=NQ;
+  if(t==CHAR) sprintf(s,"%%%cl",regnames[r][2]);
+  else if(t==SHORT) sprintf(s,"%%%s",regnames[r]+2);
+  else sprintf(s,"%s",regnames[r]);
+  return s;
+}
+
+
+static void emit_lword(FILE *f,struct obj *o)
+{
+  if(o->flags&KONST){
+    static struct obj cobj;
+    cobj.flags=KONST;
+    eval_const(&o->val,UNSIGNED|LLONG);
+    vumax=zumand(vumax,ul2zum(0xffffffff));
+    cobj.val.vulong=zum2zul(vumax);
+    emit_obj(f,&cobj,UNSIGNED|LONG);
+  }else if((o->flags&(REG|DREFOBJ))==REG){
+    if(!reg_pair(o->reg,&rp)) ierror(0);
+    emit(f,"%s",regnames[rp.r1]);
+  }else
+    emit_obj(f,o,UNSIGNED|LONG);
+}
+
+static void emit_hword(FILE *f,struct obj *o)
+{
+  if(o->flags&KONST){
+    static struct obj cobj;
+    cobj.flags=KONST;
+    eval_const(&o->val,UNSIGNED|LLONG);
+    vumax=zumand(zumrshift(vumax,ul2zum(32UL)),ul2zum(0xffffffff));
+    cobj.val.vulong=zum2zul(vumax);
+    emit_obj(f,&cobj,UNSIGNED|LONG);
+  }else if(o->flags&DREFOBJ){
+    if(!(o->flags&REG)) ierror(0);
+    emit(f,"4(%s)",regnames[o->reg]);
+  }else if(o->flags&REG){
+    if(!reg_pair(o->reg,&rp)) ierror(0);
+    emit(f,"%s",regnames[rp.r2]);
+  }else{
+    o->val.vmax=zmadd(o->val.vmax,l2zm(4L));
+    emit_obj(f,o,UNSIGNED|LONG);
+    o->val.vmax=zmsub(o->val.vmax,l2zm(4L));
+  }
+}
+
+static void dwarf2_print_frame_location(FILE *f,struct Var *v)
+{
+  /*FIXME: needs a location list and correct register trabslation */
+  struct obj o;
+  o.flags=REG;
+  if(USEFP||vlas)
+    o.reg=bp;
+  else
+    o.reg=sp;
+  o.val.vmax=l2zm(0L);
+  o.v=0;
+  dwarf2_print_location(f,&o);
+}
+static int dwarf2_regnumber(int r)
+{
+  static int dwarf_regs[17]={-1,0,1,2,3,6,7,5,4,16,17,18,19,20,21,22,23};
+  return dwarf_regs[r];
+}
+static zmax dwarf2_fboffset(struct Var *v)
+{
+  if(!v||(v->storage_class!=AUTO&&v->storage_class!=REGISTER)) ierror(0);
+  if(USEFP||vlas){
+    if(!zmleq(l2zm(0L),v->offset))
+      return l2zm((long)(-zm2l(v->offset))+4);
+    else
+      return l2zm((long)(zm2l(v->offset))-loff-pushedsize);
+  }else{
+    if(!zmleq(l2zm(0L),v->offset))
+      return l2zm((long)(loff-zm2l(v->offset))+pushedsize);
+    else
+      return v->offset;
+  }
+}
+static void fxch(FILE *f,int i)
+{
+    int m;
+    emit(f,"\tfxch\t%s\n",regnames[i+9]);
+    m=fst[0];fst[0]=fst[i];fst[i]=m;
+}
+static int freest(void)
+{
+    int i;
+    for(i=0;i<8;i++){
+        if(fst[i]<0) return i;
+    }
+    for(i=0;i<8;i++){
+        if(fst[i]==0) return i;
+    }
+    ierror(0);
+}
+static void fpush(FILE *f)
+{
+    int i;
+    if(fst[7]>0){
+        i=freest();
+        if(fst[i]==0) emit(f,"\tffree\t%s\n",regnames[i+9]);
+        fxch(f,i);fxch(f,7);
+    }
+    for(i=7;i>0;i--)
+        fst[i]=fst[i-1];
+    fst[0]=-1;
+}
+static void fpop(void)
+{
+    int i;
+/*    if(fst[0]>0&&regs[fst[0]]) ierror(0);*/
+    for(i=0;i<7;i++)
+        fst[i]=fst[i+1];
+    fst[7]=-1;
+}
+static void fload(FILE *f,struct obj *o,int t)
+{
+    emit(f,"\tfld");
+    if((o->flags&(REG|DREFOBJ))==REG) emit(f,"\t");
+        else emit(f,"%c\t",x_t[t&NQ]);
+    emit_obj(f,o,t);emit(f,"\n");
+    fpush(f);
+}
+static void fstore(FILE *f,struct obj *o,int t)
+{
+    int i;
+    if((o->flags&(REG|DREFOBJ))==REG){
+        for(i=0;i<8;i++)
+            if(fst[i]==o->reg) fst[i]=0;
+        fst[0]=o->reg;
+    }else{
+        emit(f,"\tfstp%c\t",x_t[t&NQ]);emit_obj(f,o,t);
+        fpop();emit(f,"\n");
+    }
+}
+static void prfst(FILE *f,char *s)
+{
+    int i;
+    if(DEBUG==0) return;
+    emit(f,"#\t%s\t",s);
+    for(i=0;i<8;i++){
+        if(fst[i]>=0){
+            if(fst[i]==0) emit(f,"+++ ");
+              else        emit(f,"%s ",regnames[fst[i]]+3);
+        }else{
+            emit(f,"--- ");
+        }
+    }
+    emit(f,"\n");
+}
+static void finit(void)
+{
+    int i;
+    for(i=0;i<8;i++){
+        if(regs[i+9])
+            fst[i]=i+9;
+        else
+            fst[i]=-1;
+    }
+}
+static void forder(FILE *f)
+{
+    int i,m,unordered;
+    prfst(f,"forder");
+    for(i=0;i<8;i++){
+        if(fst[i]==0){emit(f,"\tffree\t%s\n",regnames[i+9]);fst[i]=-1;}
+    }
+oloop:
+    unordered=0;
+    for(i=0;i<8;i++){
+        if(fst[i]>0&&fst[i]!=i+9&&regs[fst[i]]){unordered=1;break;}
+    }
+    if(!unordered) return;
+    if(fst[0]>=0&&regs[fst[0]]){
+        if(fst[0]!=9){
+            fxch(f,fst[0]-9);
+            goto oloop;
+        }else{
+            fxch(f,freest());
+        }
+    }
+    for(i=1;i<8;i++){
+        if(fst[i]>=0&&fst[i]!=i+9&&regs[fst[i]]&&fst[i]!=9){
+            fxch(f,i);
+            goto oloop;
+        }
+    }
+    if(regs[9]){
+        for(i=1;i<8;i++){
+            if(fst[i]==9){ fxch(f,i);return;}
+        }
+    }
+}
+static void pr(FILE *f,struct IC *p)
+{
+    int i;
+    for(;pushorder>2;pushorder>>=1){
+        for(i=1;i<=8;i++){
+            if(regs[i]&pushorder){
+	      if(p->code==PUSH||p->code==CALL){
+		emit(f,"\tmovl\t%ld(%s),%s\n",loff-4-stackoffset,regnames[sp],regnames[i]);
+	      }else{
+                emit(f,"\tpopl\t%s\n",regnames[i]);
+                pop(4);
+	      }
+	      regs[i]&=~pushorder;
+            }
+        }
+    }
+    for(i=1;i<=8;i++)
+        if(regs[i]&2) regs[i]&=~2;
+}
+static void function_top(FILE *f,struct Var *v,long offset)
+/*  erzeugt Funktionskopf                       */
+{
+    int i;
+    if(section!=CODE){emit(f,codename);if(f) section=CODE;}
+    if(v->storage_class==EXTERN){
+      if((v->flags&(INLINEFUNC|INLINEEXT))!=INLINEFUNC)
+	emit(f,"\t.globl\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));
+    if(USEFP||vlas)
+      emit(f,"\tpushl\t%s\n\tmovl\t%s,%s\n",regnames[bp],regnames[sp],regnames[bp]);
+    for(pushedsize=0,i=1;i<sp;i++){
+        if(regused[i]&&!regscratch[i]){
+            emit(f,"\tpushl\t%s\n",regnames[i]);
+            pushedsize+=4;
+        }
+    }
+    if(offset) emit(f,"\tsubl\t$%ld,%%esp\n",offset);
+}
+static void function_bottom(FILE *f,struct Var *v,long offset)
+/*  erzeugt Funktionsende                       */
+{
+    int i;
+    forder(f);
+    if(offset) emit(f,"\taddl\t$%ld,%%esp\n",offset);
+    for(i=sp-1;i>0;i--){
+        if(regused[i]&&!regscratch[i]){
+            emit(f,"\tpopl\t%s\n",regnames[i]);
+        }
+    }
+    if(USEFP||vlas) emit(f,"\tpopl\t%s\n",regnames[bp]);
+    emit(f,"\tret\n");
+    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));
+    }    
+}
+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&REG)||o1->reg==o2->reg){
+	return 1;
+      }
+    }
+  }
+  return 0;
+}
+static int get_reg(FILE *f,struct IC *p,int type)
+{
+  int i;
+  /*  If we can use a register which was already used by the compiler */
+  /*  or it is a sratch register then we can use it without problems. */
+  for(i=1;i<=8;i++){
+    if(!regs[i]&&(regused[i]||regscratch[i])&&regok(i,type,0)){
+      regs[i]=2;
+      BSET(regs_modified,i);
+      return(i);
+    }
+  }
+  /*  Otherwise we have to save this register.                        */
+  /*  We may not use a register which is used in this IC.             */
+  for(i=1;i<=8;i++){
+    if(regs[i]<2&&regok(i,type,0)
+       &&(!(p->q1.flags&REG)||p->q1.reg!=i)
+       &&(!(p->q2.flags&REG)||p->q2.reg!=i)
+       &&(!(p->z.flags&REG)||p->z.reg!=i)
+       &&(p->code!=SETRETURN||p->z.reg!=i)
+       &&(p->code!=GETRETURN||p->q1.reg!=i) ){
+      
+      if(p->code==PUSH||p->code==CALL){
+	emit(f,"\tmovl\t%s,%ld(%s)\n",regnames[i],loff-4-stackoffset,regnames[sp]);
+      }else{
+	emit(f,"\tpushl\t%s\n",regnames[i]);
+	push(4);
+      }
+      /*  Mark register as pushed (taking care of the order). */
+      pushorder<<=1; regs[i]|=pushorder;
+      BSET(regs_modified,i);
+      return i;
+    }
+  }
+  ierror(0);
+}
+static void move(FILE *f,struct obj *q,int qr,struct obj *z,int zr,int t)
+/*  Generates code to move object q (or register qr) into object z (or  */
+/*  register zr).                                                       */
+{
+  t&=NQ;
+  if(q&&(q->flags&(REG|DREFOBJ))==REG) qr=q->reg;
+  if(z&&(z->flags&(REG|DREFOBJ))==REG) zr=z->reg;
+  if((t&NQ)==LLONG){
+    if(qr&&zr&&qr==zr) return;
+    emit(f,"\tmovl\t");
+    if(qr){
+      if(!reg_pair(qr,&rp)) ierror(0);
+      emit(f,"%s",regnames[rp.r1]);
+    }else
+      emit_lword(f,q);
+    emit(f,",");
+    if(zr){
+      if(!reg_pair(zr,&rp)) ierror(0);
+      emit(f,"%s",regnames[rp.r1]);
+    }else
+      emit_lword(f,z);
+    emit(f,"\n");
+    emit(f,"\tmovl\t");
+    if(qr){
+      if(!reg_pair(qr,&rp)) ierror(0);
+      emit(f,"%s",regnames[rp.r2]);
+    }else
+      emit_hword(f,q);
+    emit(f,",");
+    if(zr){
+      if(!reg_pair(zr,&rp)) ierror(0);
+      emit(f,"%s",regnames[rp.r2]);
+    }else
+      emit_hword(f,z);
+    emit(f,"\n");
+    return;
+  }
+  if(qr&&zr){
+    if(qr!=zr)
+      emit(f,"\tmovl\t%s,%s\n",regnames[qr],regnames[zr]);
+    return;
+  }
+  if(zr&&(q->flags&(KONST|DREFOBJ))==KONST){
+    eval_const(&q->val,t);
+    if(zmeqto(vmax,l2zm(0L))&&zumeqto(vumax,ul2zum(0UL))&&zldeqto(vldouble,d2zld(0.0))){
+      emit(f,"\txorl\t%s,%s\n",regnames[zr],regnames[zr]);
+      return;
+    }
+  }
+  emit(f,"\tmov%c\t",x_t[t&NQ]);
+  if(qr){
+    emit(f,"%s",mregname(qr,t));
+  }else
+    emit_obj(f,q,t);
+  emit(f,",");
+  if(zr){
+    emit(f,"%s",mregname(zr,t));
+  }else
+    emit_obj(f,z,t);
+  emit(f,"\n");
+}
+static long pof2(zumax x)
+/*  Yields log2(x)+1 oder 0. */
+{
+    zumax p;int ln=1;
+    p=ul2zum(1UL);
+    while(ln<=32&&zumleq(p,x)){
+        if(zumeqto(x,p)) return ln;
+        ln++;p=zumadd(p,p);
+    }
+    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;
+  /*  Initialize some values which cannot be statically initialized   */
+  /*  because they are stored in the target's arithmetic.             */
+  maxalign=l2zm(4L);
+  char_bit=l2zm(8L);
+  if(g_flags[6]&USEDFLAG){
+    for(i=SHORT;i<=MAX_TYPE;i++) malign[i]=4;
+  }
+  for(i=0;i<=MAX_TYPE;i++){
+    sizetab[i]=l2zm(msizetab[i]);
+    align[i]=l2zm(malign[i]);
+  }
+  for(i=1;i<= 8;i++) {regsize[i]=l2zm(4L);regtype[i]=&ltyp;}
+  for(i=9;i<=16;i++) {regsize[i]=l2zm(8L);regtype[i]=&ldbl;}
+
+  /*  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.          */
+  t_min[CHAR]=l2zm(-128L);
+  t_min[SHORT]=l2zm(-32768L);
+  t_min[INT]=zmsub(l2zm(-2147483647L),l2zm(1L));
+  t_min[LONG]=t_min(INT);
+  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]=ul2zum(2147483647UL);
+  t_max[LONG]=t_max(INT);
+  t_max[LLONG]=zumrshift(zumkompl(ul2zum(0UL)),ul2zum(1UL));
+  t_max[MAXINT]=t_max(LLONG);
+  t_min[BSHORT]=l2zm(-32768L);
+  t_min[BINT]=zmsub(l2zm(-2147483647L),l2zm(1L));
+  t_min[BLONG]=t_min(INT);
+  t_min[BLLONG]=zmlshift(l2zm(1L),l2zm(63L));
+  t_max[BSHORT]=ul2zum(32767UL);
+  t_max[BINT]=ul2zum(2147483647UL);
+  t_max[BLONG]=t_max(INT);
+  t_max[BLLONG]=zumrshift(zumkompl(ul2zum(0UL)),ul2zum(1UL));
+  tu_max[CHAR]=ul2zum(255UL);
+  tu_max[SHORT]=ul2zum(65535UL);
+  tu_max[INT]=ul2zum(4294967295UL);
+  tu_max[LONG]=t_max(UNSIGNED|INT);
+  tu_max[LLONG]=zumkompl(ul2zum(0UL));
+  tu_max[BSHORT]=ul2zum(65535UL);
+  tu_max[BINT]=ul2zum(4294967295UL);
+  tu_max[BLONG]=t_max(UNSIGNED|INT);
+  tu_max[BLLONG]=zumkompl(ul2zum(0UL));
+  tu_max[MAXINT]=t_max(UNSIGNED|LLONG);
+
+  /*  Reserve a few registers for use by the code-generator.      */
+  /*  We only reserve the stack-pointer here.                     */
+  regsa[sp]=1;
+  if(USEFP) regsa[bp]=regscratch[bp]=1;
+  /*  We need at least one free slot in the flaoting point stack  */
+  regsa[16]=1;regscratch[16]=0;
+  /*  Use l%d as labels and _%s as identifiers by default. If     */
+  /*  -elf is specified we use .l%d and %s instead.               */
+  if(g_flags[5]&USEDFLAG) labprefix=".l"; else idprefix="_";
+  target_macros=marray;
+
+  declare_builtin("__mulll",LLONG,LLONG,0,LLONG,0,1,0);
+  declare_builtin("__addll",LLONG,LLONG,0,LLONG,0,1,0);
+  declare_builtin("__subll",LLONG,LLONG,0,LLONG,0,1,0);
+  declare_builtin("__andll",LLONG,LLONG,0,LLONG,0,1,0);
+  declare_builtin("__orll",LLONG,LLONG,0,LLONG,0,1,0);
+  declare_builtin("__eorll",LLONG,LLONG,0,LLONG,0,1,0);
+  declare_builtin("__negll",LLONG,LLONG,0,0,0,1,0);
+  declare_builtin("__notll",LLONG,LLONG,0,0,0,1,0);
+  declare_builtin("__lslll",LLONG,LLONG,0,INT,0,1,0);
+
+  declare_builtin("__divll",LLONG,LLONG,0,LLONG,0,1,0);
+  declare_builtin("__divull",UNSIGNED|LLONG,UNSIGNED|LLONG,0,UNSIGNED|LLONG,0,1,0);
+  declare_builtin("__modll",LLONG,LLONG,0,LLONG,0,1,0);
+  declare_builtin("__modull",UNSIGNED|LLONG,UNSIGNED|LLONG,0,UNSIGNED|LLONG,0,1,0);
+  declare_builtin("__lsrll",LLONG,LLONG,0,INT,0,1,0);
+  declare_builtin("__lsrull",UNSIGNED|LLONG,UNSIGNED|LLONG,0,INT,0,1,0);
+  declare_builtin("__cmpll",INT,LLONG,0,LLONG,0,1,0);
+  declare_builtin("__cmpull",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);
+
+  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.        */
+{
+    if(ISFLOAT(t->flags)) return 9;
+    if((t->flags&NQ)==LLONG) return axdx;
+    if(ISSCALAR(t->flags)) return ax;
+    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==axdx){
+    p->r1=ax;
+    p->r2=dx;
+    return 1;
+  }else if(r==sidi){
+    p->r1=si;
+    p->r2=di;
+    return 1;
+  }
+  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(r==0) return(0);
+    t&=NQ;
+    if(r>8&&r<axdx){
+      if(g_flags[7]&USEDFLAG) return 0;
+      if(ISFLOAT(t)) return 1;
+        else                  return 0;
+    }
+    if(r==axdx||r==sidi) 
+      return t==LLONG;
+    if(t==CHAR&&(r==si||r==di||r==bp)) return 0;
+    if(t<=BLONG) return 1;
+    if(ISPOINTER(t)) return 1;
+    return 0;
+}
+
+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;
+}
+
+int must_convert(int o,int t,int const_expr)
+/*  Returns zero if code for converting np to type t    */
+/*  can be omitted.                                     */
+/*  In this generic 32bit RISC cpu pointers and 32bit   */
+/*  integers have the same representation and can use   */
+/*  the same registers.                                 */
+{
+  int op=o&NQ,tp=t&NQ,of,tf;
+  of=ISBE(op);
+  tf=ISBE(tp);
+  if(of!=tf) return 1;
+  if(of) op=LETYPE(op);
+  if(tf) tp=LETYPE(tp);
+    
+  if(tp==POINTER&&op==POINTER) return 0;
+  if((t&UNSIGNED)&&(o&UNSIGNED)&&zmeqto(sizetab[tp],sizetab[op])) return 0;
+  if((tp==INT&&op==LONG)||(tp==LONG&&op==INT)) return 0;
+  if(op==tp) return 0;
+  return 1;
+}
+
+/* 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){
+      sprintf(fname,"__cmp%sll",(t&UNSIGNED)?"u":"");
+      ret=fname;
+    }
+  }else{
+    t&=NU;
+    if(c==CONVERT){
+      if(ISFLOAT(t)&&(t2&NU)==LLONG){
+	sprintf(fname,"__%cint64toflt%d",(t2&UNSIGNED)?'u':'s',(t==FLOAT)?32:64);
+	ret=fname;
+      }
+      if(ISFLOAT(t2)&&(t&NU)==LLONG){
+	sprintf(fname,"__flt%dto%cint64",((t2&NU)==FLOAT)?32:64,(t&UNSIGNED)?'u':'s');
+	ret=fname;
+      }
+    }
+    if((t&NQ)==LLONG){
+      if((c>=LSHIFT&&c<=MOD)||(c>=OR&&c<=AND)||c==PMULT||(c>=EQUAL&&c<=GREATEREQ)||c==KOMPLEMENT||c==MINUS){
+	if(t==(UNSIGNED|LLONG)&&(c==DIV||c==MOD||c==RSHIFT)){
+	  sprintf(fname,"__%sull",ename[c]);
+	  ret=fname;
+	}else if((t&NQ)==LLONG){
+	  sprintf(fname,"__%sll",ename[c]);
+	  ret=fname;
+	}else printf("un %d\n",c);
+      }
+    }
+  }
+  return ret;
+}
+
+void gen_ds(FILE *f,zmax size,struct Typ *t)
+/*  This function has to create <size> bytes of storage */
+/*  initialized with zero.                              */
+{
+  title(f);
+  if(newobj) 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.              */
+{
+  title(f);
+  if(zm2l(align)>1) emit(f,"\t.align\t4\n");
+}
+
+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;
+  title(f);
+  if(v->clist) constflag=is_const(v->vtyp);
+  if(v->storage_class==STATIC){
+    if((v->vtyp->flags&NQ)==FUNKT) return;
+    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&&(!constflag||(g_flags[3]&USEDFLAG))&&section!=DATA){emit(f,dataname);if(f) section=DATA;}
+    if(v->clist&&constflag&&!(g_flags[3]&USEDFLAG)&&section!=CODE){emit(f,codename);if(f) section=CODE;}
+    if(!v->clist&&section!=BSS){emit(f,bssname);if(f) section=BSS;}
+    if(section!=BSS)
+      emit(f,"\t.align\t4\n%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){
+    emit(f,"\t.globl\t%s%s\n",idprefix,v->identifier);
+    if(v->flags&(DEFINED|TENTATIVE)){
+      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&&(!constflag||(g_flags[3]&USEDFLAG))&&section!=DATA){emit(f,dataname);if(f) section=DATA;}
+      if(v->clist&&constflag&&!(g_flags[3]&USEDFLAG)&&section!=CODE){emit(f,codename);if(f) section=CODE;}
+      if(!v->clist&&section!=BSS){emit(f,bssname);if(f) section=BSS;}
+      if(section!=BSS)
+        emit(f,"\t.align\t4\n%s%s:\n",idprefix,v->identifier);
+      else{
+        emit(f,"\t.comm\t%s%s,",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.                      */
+{
+    title(f);
+    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 if((t&NQ)==LLONG){
+	  zumax tmp;
+	  eval_const(&p->val,t);
+	  tmp=vumax;
+	  vumax=zumand(vumax,ul2zum(0xffffffff));
+	  gval.vulong=zum2zul(vumax);
+	  emitval(f,&gval,UNSIGNED|LONG);
+	  emit(f,",");
+	  vumax=zumand(zumrshift(tmp,ul2zum(32UL)),ul2zum(0xffffffff));
+	  gval.vulong=zum2zul(vumax);
+	  emitval(f,&gval,UNSIGNED|LONG);
+        }else{
+            emitval(f,&p->val,t&NU);
+        }
+    }else{
+        int m=p->tree->o.flags;
+        p->tree->o.flags&=~VARADR;
+        emit_obj(f,&p->tree->o,t&NU);
+        p->tree->o.flags=m;
+    }
+    emit(f,"\n");newobj=0;
+}
+
+/*  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 *p,struct Var *v,zmax offset)
+{
+    int c,t,lastcomp=0,reg;
+    struct IC *m;
+    if(DEBUG&1) printf("gen_code()\n");
+    for(c=1;c<=15;c++) regs[c]=regsa[c];
+    regs[16]=0;
+    for(c=1;c<=MAXR;c++){
+      if(regsa[c]||regused[c]){
+	BSET(regs_modified,c);
+      }
+    }
+    title(f);
+    loff=((zm2l(offset)+3)/4)*4;
+    for(m=p;m;m=m->next){
+      /* do we need another stack-slot? */
+      /* could do a more precise check */
+      if((m->code==PUSH&&(m->q1.flags&(REG|DREFOBJ))==DREFOBJ)||
+	 (m->code==CALL&&(m->q1.flags&DREFOBJ))||
+	 (m->code==CONVERT&&!ISFLOAT(m->typf)&&ISFLOAT(m->typf2)) ){
+	loff+=4;
+	break;
+      }
+    }
+    function_top(f,v,loff);
+    stackoffset=notpopped=dontpop=0;
+    finit();
+    for(;p;pr(f,p),p=p->next){
+        c=p->code;t=p->typf;
+	if(debug_info)
+	  dwarf2_line_info(f,p);
+        if(c==NOP) continue;
+        if(c==SUBPFP) c=SUB;
+        if(c==SUBIFP) c=SUB;
+        if(c==ADDI2P) c=ADD;
+        if(c==ALLOCREG){
+            regs[p->q1.reg]=1;
+            continue;
+        }
+        if(c==FREEREG){
+            if(p->q1.reg>=9){
+                for(c=0;c<8;c++)
+                    if(fst[c]==p->q1.reg) fst[c]=0;
+            }
+            regs[p->q1.reg]=0;
+            continue;
+        }
+        if(notpopped&&!dontpop){
+	  if(c==LABEL||c==COMPARE||c==TEST||c==BRA){
+	    emit(f,"\taddl\t$%ld,%%esp\n",notpopped);
+	    pop(notpopped);
+	    notpopped=0;
+	  }
+        }
+
+	if(c==COMPARE&&isconst(q2)&&(t&NQ)!=LLONG){
+	  struct case_table *ct=calc_case_table(p,JUMP_TABLE_DENSITY);
+	  if(ct&&ct->num>=JUMP_TABLE_LENGTH){
+	    int r,defl,tabl=++label;
+	    long l;unsigned long ul;
+	    /*FIXME: we do not generate a jump-table if we do not have a
+	      free register */
+	    for(r=1;r<=8;r++){
+	      if(!regs[r]&&regscratch[r])
+		break;
+	    }
+	    if(r<=8){
+	      BSET(regs_modified,r);
+	      if(ct->next_ic->code==BRA)
+		defl=ct->next_ic->typf;
+	      else
+		defl=++label;
+	      if((p->q1.flags&(REG|DREFOBJ))==DREFOBJ){
+		p->q1.flags&=~DREFOBJ;
+		emit(f,"\tmovl\t");
+		emit_obj(f,&p->q1,POINTER);
+		emit(f,",%s\n",regnames[r]);
+		p->q1.flags|=(REG|DREFOBJ);
+		p->q1.reg=r;
+	      }
+	      emit(f,"\tmovl\t");
+	      emit_obj(f,&p->q1,t);
+	      emit(f,",%s\n",regnames[r]);
+	      emit(f,"\tsubl\t$");
+	      if(t&UNSIGNED)
+		emitzum(f,ct->min.vumax);
+	      else
+		emitzm(f,ct->min.vmax);
+	      emit(f,",%s\n",regnames[r]);
+	      emit(f,"\tcmpl\t$");
+	      emitzum(f,ct->diff);
+	      emit(f,",%s\n",regnames[r]);
+	      emit(f,"\tja\t%s%d\n",labprefix,defl);
+	      emit(f,"\tjmp\t*%s%d(,%s,4)\n",labprefix,tabl,regnames[r]);
+	      emit(f,"\t.align\t2\n");
+	      emit(f,"%s%d:\n",labprefix,tabl);
+	      emit_jump_table(f,ct,"\t.long\t",labprefix,defl);
+	      if(ct->next_ic->code!=BRA){
+		emit(f,"%s%d:\n",labprefix,defl);
+		p=ct->next_ic->prev;
+	      }else
+		p=ct->next_ic;
+	      continue;
+	    }
+	  }
+	}
+        if(c==LABEL){
+	  if(t>label) ierror(0);
+	  forder(f);
+	  emit(f,"%s%d:\n",labprefix,t);
+	  continue;
+	}
+        if(c>=BEQ&&c<=BRA){
+            forder(f);
+            if(lastcomp&UNSIGNED) emit(f,"\tj%s\t%s%d\n",ccu[c-BEQ],labprefix,t);
+                else              emit(f,"\tj%s\t%s%d\n",ccs[c-BEQ],labprefix,t);
+            continue;
+        }
+        if(c==MOVETOREG){
+            if(p->z.reg>8){
+                for(c=0;c<8;c++){
+                    if(fst[c]==p->z.reg) fst[c]=0;
+                }
+                fload(f,&p->q1,DOUBLE);
+                fst[0]=p->z.reg;
+                continue;
+            }
+            move(f,&p->q1,0,0,p->z.reg,LONG);
+            continue;
+        }
+        if(c==MOVEFROMREG){
+            if(p->q1.reg>8){
+                if(fst[0]!=p->q1.reg){
+                    for(c=0,reg=-1;c<8;c++){
+                        if(fst[c]==p->q1.reg) reg=c;
+                    }
+                    if(reg<0) ierror(0);
+                    fxch(f,reg);
+                }
+                emit(f,"\tfstpl\t");emit_obj(f,&p->z,DOUBLE);
+                emit(f,"\n");fpop();
+                continue;
+            }
+            move(f,0,p->q1.reg,&p->z,0,LONG);
+            continue;
+        }
+        if((p->q1.flags&(DREFOBJ|REG|KONST))==DREFOBJ||((p->q1.flags&DREFOBJ)&&ISBE(p->q1.dtyp))){
+	  reg=get_reg(f,p,LONG);
+	  move(f,&p->q1,0,0,reg,LONG);
+	  p->q1.flags|=REG;p->q1.reg=reg;
+	  p->q1.flags&=~KONST;
+	  if(ISBE(p->q1.dtyp))
+	    emit(f,"\tbswap\t%s\n",regnames[reg]);
+        }
+        if((p->q2.flags&(DREFOBJ|REG|KONST))==DREFOBJ||((p->q2.flags&DREFOBJ)&&ISBE(p->q2.dtyp))){
+	  reg=get_reg(f,p,LONG);
+	  move(f,&p->q2,0,0,reg,LONG);
+	  p->q2.flags|=REG;p->q2.reg=reg;
+	  p->q2.flags&=~KONST;
+	  if(ISBE(p->q2.dtyp))
+	    emit(f,"\tbswap\t%s\n",regnames[reg]);
+        }
+        if((p->z.flags&(DREFOBJ|REG|KONST))==DREFOBJ||((p->z.flags&DREFOBJ)&&ISBE(p->z.dtyp))){
+	  reg=get_reg(f,p,LONG);
+	  /* sehr unschoen */
+	  if(c==GETRETURN&&reg==p->q1.reg) reg=get_reg(f,p,LONG);
+	  move(f,&p->z,0,0,reg,LONG);
+	  p->z.flags|=REG;p->z.reg=reg;
+	  p->z.flags&=~KONST;
+	  if(ISBE(p->z.dtyp))
+	    emit(f,"\tbswap\t%s\n",regnames[reg]);
+        }
+	if((t&NQ)==LDOUBLE) p->typf=t=DOUBLE;
+	if(c==CONVERT&&(t&NQ)==LLONG&&(p->typf2&NQ)==LLONG) c=ASSIGN;
+        if(c==CONVERT){
+            int to=p->typf2&NU;
+	    if(to==LDOUBLE) to=DOUBLE;
+            if((t&NU)==LONG) t=INT;
+            if((t&NU)==(UNSIGNED|LONG)||(t&NU)==POINTER) t=(UNSIGNED|INT);
+            if((to&NU)==LONG) to=INT;
+            if((to&NU)==(UNSIGNED|LONG)||(to&NU)==POINTER) to=(UNSIGNED|INT);
+	    if((to&NQ)==LLONG){
+	      int useqreg=0;
+	      if(isreg(z)) 
+		reg=p->z.reg;
+	      else if(isreg(q1)&&reg_pair(p->q1.reg,&rp)&&regok(rp.r1,t,0))
+		reg=useqreg=rp.r1;
+	      else
+		reg=get_reg(f,p,INT);
+	      if(!useqreg){
+		emit(f,"\tmovl\t");
+		if(isreg(q1)){
+		  if(!reg_pair(p->q1.reg,&rp)) ierror(0);
+		  emit(f,"%s",regnames[rp.r1]);
+		}else{
+		  emit_obj(f,&p->q1,INT);
+		}
+		emit(f,",%s\n",regnames[reg]);
+	      }
+	      if(!isreg(z)||p->z.reg!=reg)
+		move(f,0,reg,&p->z,0,t);
+	      continue;
+	    }
+            if((to&NQ)<=INT&&(t&NQ)<=LLONG){
+	      if(isreg(z)){
+		reg=p->z.reg;
+		if(reg_pair(reg,&rp)) reg=rp.r1;
+	      }else if(isreg(q1)&&regok(p->q1.reg,t,0))
+		reg=p->q1.reg;
+	      else
+		reg=get_reg(f,p,((to&NQ)==CHAR||(t&NQ)==CHAR)?CHAR:LONG);
+	      if((to&NQ)<=SHORT){
+		emit(f,"\tmov%c%cl\t",(to&UNSIGNED)?'z':'s',x_t[to&NQ]);
+		emit_obj(f,&p->q1,to);
+		emit(f,",%s\n",regnames[reg]);
+	      }else{
+		move(f,&p->q1,0,0,reg,to);
+	      }
+	      if((t&NQ)==LLONG){
+		if(isreg(z)){
+		  if(to&UNSIGNED)
+		    emit(f,"\txorl\t%s,%s\n",regnames[rp.r2],regnames[rp.r2]);
+		  else{
+		    move(f,0,reg,0,rp.r2,INT);
+		    emit(f,"\tsarl\t$31,%s\n",regnames[rp.r2]);
+		  }
+		}else{
+		  move(f,0,reg,&p->z,0,INT);
+		  if(to&UNSIGNED){
+		    emit(f,"\tmovl\t$0,");
+		    emit_hword(f,&p->z);
+		    emit(f,"\n");
+		  }else{
+		    emit(f,"\tsarl\t$31,%s\n",regnames[reg]);
+		    emit(f,"\tmovl\t%s,",regnames[reg]);
+		    emit_hword(f,&p->z);
+		    emit(f,"\n");
+		  }
+		}
+	      }else
+		move(f,0,reg,&p->z,0,t);
+	      continue;
+            }
+            if(ISFLOAT(t)){
+                if(ISFLOAT(to)){
+                    if(isreg(q1)&&fst[0]==p->q1.reg){
+                        if(isreg(z)){
+                            if(p->z.reg==fst[0]) continue;
+                            for(reg=0,c=7;c>=0;c--){
+                                if(fst[c]==p->z.reg){reg=c;break;}
+                                if(fst[c]<0) reg=c;
+                            }
+                            fst[reg]=p->z.reg;
+                        }
+                        emit(f,"\tfst%c\t",x_t[t&NQ]);
+                        emit_obj(f,&p->z,t);emit(f,"\n");
+                        continue;
+                    }
+                    fload(f,&p->q1,to);
+                    fstore(f,&p->z,t);
+                    continue;
+                }
+                if((to&NQ)<=SHORT){
+                    if(isreg(q1)){
+                        reg=p->q1.reg;
+                        if(to&UNSIGNED){
+                            emit(f,"\tandl\t$%ld,%s\n",(to&NQ)==CHAR?255L:65535L,regnames[reg]);
+                        }else{
+/*                            emit(f,"\tc%ctl\t%s\n",x_t[to&NQ],regnames[reg]);*/
+                            if((to&NQ)==SHORT){
+                                emit(f,"\tmovswl\t%%%s,%s\n",regnames[reg]+2,regnames[reg]);
+                            }else{
+                                emit(f,"\tmovsbl\t%%%cl,%s\n",regnames[reg][2],regnames[reg]);
+                            }
+                        }
+                    }else{
+                        reg=get_reg(f,p,LONG);
+                        if(to&UNSIGNED){
+                            emit(f,"\tmovz%cl\t",x_t[to&NQ]);
+                        }else{
+                            emit(f,"\tmovs%cl\t",x_t[to&NQ]);
+                        }
+                        emit_obj(f,&p->q1,to);emit(f,",%s\n",regnames[reg]);
+                    }
+                    emit(f,"\tpushl\t%s\n",regnames[reg]);
+                    emit(f,"\tfildl\t(%s)\n\taddl\t$4,%s\n",regnames[sp],regnames[sp]);
+                }else{
+                    if(to&UNSIGNED){
+                        emit(f,"\tpushl\t$0\n\tpushl\t");
+			push(4);
+                        emit_obj(f,&p->q1,to);
+                        emit(f,"\n\tfildq\t(%s)\n\taddl\t$8,%s\n",regnames[sp],regnames[sp]);
+			pop(4);
+                    }else{
+                        if(isreg(q1)){
+                            emit(f,"\tpushl\t%s\n\tfildl\t(%s)\n\taddl\t$4,%s\n",regnames[p->q1.reg],regnames[sp],regnames[sp]);
+                        }else{
+                            emit(f,"\tfildl\t");emit_obj(f,&p->q1,t);
+                            emit(f,"\n");
+                        }
+                    }
+                }
+                fpush(f);
+                fstore(f,&p->z,t);
+                continue;
+            }
+            if(ISFLOAT(to)){
+	      int cwr;
+	      if(isreg(z)&&regok(p->z.reg,CHAR,0))
+		cwr=p->z.reg;
+	      else
+		cwr=get_reg(f,p,CHAR);
+	      emit(f,"\tfnstcw\t%d(%s)\n",loff-4-stackoffset,regnames[sp]);
+	      emit(f,"\tmovw\t%d(%s),%%%s\n",loff-4-stackoffset,regnames[sp],regnames[cwr]+2);
+	      emit(f,"\tmovb\t$12,%%%ch\n",regnames[cwr][2]);
+	      emit(f,"\tmovw\t%%%s,%d(%s)\n",regnames[cwr]+2,loff-2-stackoffset,regnames[sp]);
+	      emit(f,"\tfldcw\t%d(%s)\n",loff-2-stackoffset,regnames[sp]);
+	      if(isreg(q1)&&fst[0]==p->q1.reg){
+		if((t&NQ)==CHAR){
+		  if(isreg(z)) reg=p->z.reg; else reg=get_reg(f,p,CHAR);
+		  emit(f,"\tsubl\t$4,%s\n\tfistl\t(%s)\n\tmovsbl\t(%s),%s\n\taddl\t$4,%s\n",regnames[sp],regnames[sp],regnames[sp],regnames[reg],regnames[sp]);
+		  move(f,0,reg,&p->z,0,t);
+		}else{
+		  if(isreg(z)){
+		    emit(f,"\tsubl\t$4,%s\n\tfistl\t(%s)\n\tmov%c\t(%s),",regnames[sp],regnames[sp],x_t[t&NQ],regnames[sp]);
+		    push(4);
+		    emit_obj(f,&p->z,t);emit(f,"\n\taddl\t$4,%s\n",regnames[sp]);
+		    pop(4);
+		  }else{
+		    emit(f,"\tfist%c\t",x_t[t&NQ]);
+		    emit_obj(f,&p->z,t);emit(f,"\n");
+		  }
+		}
+	      }else{
+		fload(f,&p->q1,to);
+		if((t&NQ)==CHAR){
+		  if(isreg(z)) reg=p->z.reg; else reg=get_reg(f,p,CHAR);
+		  emit(f,"\tsubl\t$4,%s\n\tfistpl\t(%s)\n\tmovsbl\t(%s),%s\n\taddl\t$4,%s\n",regnames[sp],regnames[sp],regnames[sp],regnames[reg],regnames[sp]);
+		  fpop(); move(f,0,reg,&p->z,0,t);
+		}else{
+		  if(isreg(z)){
+		    emit(f,"\tsubl\t$4,%s\n\tfistpl\t(%s)\n\tmov%c\t(%s),",regnames[sp],regnames[sp],x_t[t&NQ],regnames[sp]);
+		    push(4);
+		    emit_obj(f,&p->z,t);
+		    emit(f,"\n\taddl\t$4,%s\n",regnames[sp]);
+		    pop(4);
+		    fpop();
+		  }else{
+		    emit(f,"\tfistp%s\t",(t&NQ)==SHORT?"":"l");
+		    emit_obj(f,&p->z,t);emit(f,"\n");fpop();
+		  }
+		}
+	      }
+	      emit(f,"\tfldcw\t%d(%s)\n",loff-4-stackoffset,regnames[sp]);
+	      continue;
+            }
+pric2(stdout,p);
+            ierror(0);
+        }
+        if(c==MINUS||c==KOMPLEMENT){
+            char *s;
+            if(ISFLOAT(t)){
+                if(isreg(z)&&p->z.reg==9&&isreg(q1)&&p->q1.reg==9){
+                    emit(f,"\tfchs\n");
+                    continue;
+                }
+                fload(f,&p->q1,t);
+                emit(f,"\tfchs\n");
+                emit(f,"\tfstp%c\t",x_t[t&NQ]);
+                emit_obj(f,&p->z,t);emit(f,"\n");
+                fpop();
+                continue;
+            }
+            if(c==MINUS) s="neg"; else s="not";
+            if(compare_objects(&p->q1,&p->q2)){
+                emit(f,"\t%s%c\t",s,x_t[t&NQ]);
+                emit_obj(f,&p->z,t);emit(f,"\n");
+                continue;
+            }
+            if(isreg(z)) reg=p->z.reg; else reg=get_reg(f,p,t);
+            move(f,&p->q1,0,0,reg,t);
+            emit(f,"\t%s%c\t%s\n",s,x_t[t&NQ],regnames[reg]);
+            move(f,0,reg,&p->z,0,t);
+            continue;
+        }
+        if(c==SETRETURN){
+            if(p->z.reg){
+                if(p->z.reg==9){
+                    if(!isreg(q1)||fst[0]!=p->q1.reg)
+                        fload(f,&p->q1,t);
+                }else{
+                    move(f,&p->q1,0,0,p->z.reg,t);
+                }
+		BSET(regs_modified,p->z.reg);
+            }
+            continue;
+        }
+        if(c==GETRETURN){
+            if(p->q1.reg){
+                if(p->q1.reg==9){
+                    if(!isreg(z)||fst[0]!=p->z.reg)
+                        fstore(f,&p->z,t);
+                }else{
+                    move(f,0,p->q1.reg,&p->z,0,t);
+                }
+            }
+            continue;
+        }
+        if(c==CALL){
+            int reg;
+            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);
+            }else{
+              if(p->q1.flags&DREFOBJ){
+                if(!(p->q1.flags&REG)) ierror(0);
+                emit(f,"\tcall\t*%s\n",regnames[p->q1.reg]);
+              }else{
+                emit(f,"\tcall\t");emit_obj(f,&p->q1,t);
+                emit(f,"\n");
+              }
+            }
+            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)&&!vlas&&stackoffset==-notpopped){
+                /*  Entfernen der Parameter verzoegern  */
+              }else{
+                emit(f,"\taddl\t$%ld,%%esp\n",zm2l(p->q2.val.vmax));
+                pop(zm2l(p->q2.val.vmax));
+                notpopped-=zm2l(p->q2.val.vmax);
+              }
+            }
+	    if((p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&(p->q1.v->fi->flags&ALL_REGS)){
+	      bvunite(regs_modified,p->q1.v->fi->regs_modified,RSIZE);
+	    }else{
+	      int i;
+	      for(i=1;i<=MAXR;i++){
+		if(regscratch[i]) BSET(regs_modified,i);
+	      }
+	    }
+            continue;
+        }
+        if(c==ASSIGN||c==PUSH){
+            if(c==PUSH) dontpop+=zm2l(p->q2.val.vmax);
+            if(ISFLOAT(t)){
+                if(c==ASSIGN){
+                    prfst(f,"fassign");
+                    fload(f,&p->q1,t);
+                    fstore(f,&p->z,t);
+                    continue;
+                }else if(isreg(q1)){
+                    prfst(f,"fpush");
+                    emit(f,"\tsubl\t$%ld,%s\n",zm2l(sizetab[t&NQ]),regnames[sp]);
+                    push(zm2l(sizetab[t&NQ]));
+                    if(fst[0]==p->q1.reg){
+                        emit(f,"\tfst%c\t(%s)\n",x_t[t&NQ],regnames[sp]);
+                    }else{
+                        fload(f,&p->q1,t);
+                        emit(f,"\tfstp%c\t(%s)\n",x_t[t&NQ],regnames[sp]);
+                        fpop();
+                    }
+                    continue;
+                }
+            }
+	    if((t&NQ)==LLONG){
+	      if(c==ASSIGN){
+		if(isconst(q1)||isreg(q1)||isreg(z)){
+		  move(f,&p->q1,0,&p->z,0,t);
+		}else{
+		  int r=get_reg(f,p,INT);
+		  emit(f,"\tmovl\t");
+		  emit_lword(f,&p->q1);
+		  emit(f,",%s\n",regnames[r]);
+		  emit(f,"\tmovl\t%s,",regnames[r]);
+		  emit_lword(f,&p->z);
+		  emit(f,"\n");
+		  emit(f,"\tmovl\t");
+		  emit_hword(f,&p->q1);
+		  emit(f,",%s\n",regnames[r]);
+		  emit(f,"\tmovl\t%s,",regnames[r]);
+		  emit_hword(f,&p->z);
+		  emit(f,"\n");
+		}
+	      }else{
+		emit(f,"\tpushl\t");
+		emit_hword(f,&p->q1);
+		emit(f,"\n");
+		push(4);
+		emit(f,"\tpushl\t");
+		emit_lword(f,&p->q1);
+		emit(f,"\n");
+		push(4);
+	      }
+	      continue;
+	    }
+            if(!ISSCALAR(t)||!zmeqto(p->q2.val.vmax,sizetab[t&NQ])||!zmleq(p->q2.val.vmax,l2zm(4L))){
+                int mdi=di,msi=si,m=0;long l;
+                l=zm2l(p->q2.val.vmax);
+                if(regs[cx]){m|=1;if(!cxl)cxl=++label;emit(f,"\tmovl\t%s,%s%d\n",regnames[cx],labprefix,cxl);}
+                if(regs[msi]||!regused[msi]){m|=2;if(!sil)sil=++label;emit(f,"\tmovl\t%s,%s%d\n",regnames[msi],labprefix,sil);}
+                if(regs[mdi]||!regused[mdi]){m|=4;if(!dil)dil=++label;emit(f,"\tmovl\t%s,%s%d\n",regnames[mdi],labprefix,dil);}
+                if((p->z.flags&REG)&&p->z.reg==msi&&(p->q1.flags&REG)&&p->q1.reg==mdi){
+                    msi=di;mdi=si;
+                    m|=8;
+                }
+                if(!(p->z.flags&REG)||p->z.reg!=msi){
+                    emit(f,"\tleal\t");emit_obj(f,&p->q1,t);
+                    emit(f,",%s\n",regnames[msi]);
+                }
+                if(c==PUSH){
+                    emit(f,"\tsubl\t$%ld,%s\n\tmovl\t%s,%s\n",l,regnames[sp],regnames[sp],regnames[mdi]);
+                    push(l);
+		    l=zm2l(p->z.val.vmax);
+                }else{
+                    emit(f,"\tleal\t");emit_obj(f,&p->z,t);
+                    emit(f,",%s\n",regnames[mdi]);
+                }
+                if((p->z.flags&REG)&&p->z.reg==msi){
+                    emit(f,"\tleal\t");emit_obj(f,&p->q1,t);
+                    emit(f,",%s\n",regnames[msi]);
+                }
+                if(m&8){
+                    msi=si;mdi=di;
+                    emit(f,"\txchg\t%s,%s\n",regnames[msi],regnames[mdi]);
+                }
+                if((t&NQ)==ARRAY||(t&NQ)==CHAR||l<4){
+                    emit(f,"\tmovl\t$%ld,%s\n\trep\n\tmovsb\n",l,regnames[cx]);
+                }else{
+                    if(l>=8)
+                        emit(f,"\tmovl\t$%ld,%s\n\trep\n",l/4,regnames[cx]);
+                    emit(f,"\tmovsl\n");
+                    if(l&2) emit(f,"\tmovsw\n");
+                    if(l&1) emit(f,"\tmovsb\n");
+                }
+                if(m&4) emit(f,"\tmovl\t%s%d,%s\n",labprefix,dil,regnames[mdi]);
+                if(m&2) emit(f,"\tmovl\t%s%d,%s\n",labprefix,sil,regnames[msi]);
+                if(m&1) emit(f,"\tmovl\t%s%d,%s\n",labprefix,cxl,regnames[cx]);
+                continue;
+            }
+            if(c==PUSH){
+                emit(f,"\tpush%c\t",(t&NQ)==FLOAT?x_t[LONG]:x_t[t&NQ]);
+                emit_obj(f,&p->q1,t);emit(f,"\n");
+                push(zm2l(p->q2.val.vmax));
+                continue;
+            }
+            if(c==ASSIGN){
+                if(isconst(q1)){
+                    move(f,&p->q1,0,&p->z,0,t);
+                    continue;
+                }
+                if(isreg(z)) reg=p->z.reg;
+                else if(isreg(q1)) reg=p->q1.reg;
+                else reg=get_reg(f,p,t);
+                move(f,&p->q1,0,0,reg,t);
+                move(f,0,reg,&p->z,0,t);
+                continue;
+            }
+            ierror(0);
+        }
+        if(c==ADDRESS){
+            if(isreg(z)) reg=p->z.reg; else reg=get_reg(f,p,LONG);
+            emit(f,"\tleal\t");emit_obj(f,&p->q1,t);
+            emit(f,",%s\n",regnames[reg]);
+            move(f,0,reg,&p->z,0,POINTER);
+            continue;
+        }
+        if(c==TEST){
+            lastcomp=t;
+            if(ISFLOAT(t)){
+                if(isreg(q1)&&fst[0]==p->q1.reg){
+                    emit(f,"\tftst\n");lastcomp|=UNSIGNED;
+                    continue;
+                }else{
+                    p->code=c=COMPARE;
+                    p->q2.flags=KONST;
+                    p->q2.val.vldouble=d2zld(0.0);
+                    if((t&NQ)==FLOAT) p->q2.val.vfloat=zld2zf(p->q2.val.vldouble);
+                    if((t&NQ)==DOUBLE) p->q2.val.vdouble=zld2zd(p->q2.val.vldouble);
+
+                    /*  fall through to COMPARE */
+                }
+            }else{
+              if(isvconst(q1)){
+                reg=get_reg(f,p,t);
+                move(f,&p->q1,0,0,reg,t);
+                p->q1.flags=REG;
+                p->q1.reg=reg;
+              }
+	      if((t&NQ)==LLONG){
+		reg=get_reg(f,p,INT);
+		if(isreg(q1)){
+		  if(!reg_pair(p->q1.reg,&rp)) ierror(0);
+		  move(f,0,rp.r1,0,reg,INT);
+		  emit(f,"\torl\t%s,%s\n",regnames[rp.r2],regnames[reg]);
+		}else{
+		  move(f,&p->q1,0,0,reg,INT);
+		  emit(f,"\torl\t");
+		  emit_hword(f,&p->q1);
+		  emit(f,",%s\n",regnames[reg]);
+		}
+		continue;
+	      }
+	      if(isreg(q1)){
+		emit(f,"\ttest%c\t",x_t[t&NQ]);
+                emit_obj(f,&p->q1,t);emit(f,",");
+                emit_obj(f,&p->q1,t);emit(f,"\n");
+	      }else{
+		emit(f,"\tcmp%c\t$0,",x_t[t&NQ]);
+		emit_obj(f,&p->q1,t);emit(f,"\n");
+	      }
+	      continue;
+            }
+        }
+        if(c==COMPARE){
+            lastcomp=t;
+            if(isreg(q2)||isvconst(q1)){
+                struct IC *b=p->next;
+                struct obj o;
+                o=p->q1;p->q1=p->q2;p->q2=o;
+                while(b&&b->code==FREEREG) b=b->next;
+                if(!b) ierror(0);
+                if(b->code==BLT) b->code=BGT;
+                else if(b->code==BLE) b->code=BGE;
+                else if(b->code==BGT) b->code=BLT;
+                else if(b->code==BGE) b->code=BLE;
+            }
+            if(ISFLOAT(t)){
+                prfst(f,"fcomp");
+                if(isreg(q1)&&p->q1.reg==fst[0]){
+                    emit(f,"\tfcom%c\t",x_t[t&NQ]);
+                    emit_obj(f,&p->q2,t);emit(f,"\n");
+                }else{
+                    fload(f,&p->q1,t);
+                    emit(f,"\tfcomp%c\t",x_t[t&NQ]);
+                    emit_obj(f,&p->q2,t);emit(f,"\n");
+                    fpop();
+                }
+		if(regs[ax]) emit(f,"\tpushl\t%s\n",regnames[ax]);
+                emit(f,"\tfstsw\n\tsahf\n");
+		if(regs[ax]) emit(f,"\tpopl\t%s\n",regnames[ax]);
+                lastcomp|=UNSIGNED;
+                continue;
+            }
+            if(!isreg(q1)){
+                if(!isreg(q2)&&(!isvconst(q2)||isvconst(q1))){
+                    reg=get_reg(f,p,t);
+                    move(f,&p->q1,0,0,reg,t);
+                    p->q1.flags=REG;
+                    p->q1.reg=reg;
+                }
+            }
+	    if(isreg(q1)&&isconst(q2)){
+	      eval_const(&p->q2.val,t);
+	      if(zmeqto(vmax,l2zm(0L))){
+		emit(f,"\ttest%c\t",x_t[t&NQ]);
+                emit_obj(f,&p->q1,t);emit(f,",");
+                emit_obj(f,&p->q1,t);emit(f,"\n");
+		continue;
+	      }
+	    }
+	    if(isreg(q2)&&isconst(q1)){
+	      eval_const(&p->q1.val,t);
+	      if(zmeqto(vmax,l2zm(0L))){
+		emit(f,"\ttest%c\t",x_t[t&NQ]);
+                emit_obj(f,&p->q2,t);emit(f,",");
+                emit_obj(f,&p->q2,t);emit(f,"\n");
+		continue;
+	      }
+	    }
+            emit(f,"\tcmp%c\t",x_t[t&NQ]);
+            emit_obj(f,&p->q2,t);emit(f,",");
+            emit_obj(f,&p->q1,t);emit(f,"\n");
+            continue;
+        }
+        if(ISFLOAT(t)){
+            char s[2];
+            prfst(f,"fmath");
+            if(isreg(q2)) s[0]=0; else {s[0]=x_t[t&NQ];s[1]=0;}
+            if(isreg(z)&&isreg(q1)&&p->q1.reg==fst[0]&&p->z.reg==fst[0]){
+                emit(f,"\t%s%s\t",farithmetics[c-LSHIFT],s);
+                emit_obj(f,&p->q2,t); emit(f,"\n");continue;
+            }
+            fload(f,&p->q1,t);
+            emit(f,"\t%s%s\t",farithmetics[c-LSHIFT],s);
+            emit_obj(f,&p->q2,t); emit(f,"\n");
+            fstore(f,&p->z,t); 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)){
+                    if(c==MOD){
+                        vmax=zmsub(vmax,l2zm(1L));
+                        p->code=AND;
+                    }else{
+                        vmax=l2zm(ln-1);
+                        if(c==DIV) p->code=RSHIFT; else p->code=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,INT);
+		      p->typf2=INT;
+		    }
+                }
+            }
+        }
+        if(c==MOD||c==DIV){
+            int m=0;
+	    BSET(regs_modified,dx);
+	    BSET(regs_modified,ax);
+            if(regs[ax]&&(!isreg(z)||p->z.reg!=ax)){
+                emit(f,"\tpushl\t%s\n",regnames[ax]);
+		push(4);
+		m|=1;
+            }
+            if(isreg(q2)&&p->q2.reg==ax){
+                emit(f,"\tpushl\t%s\n",regnames[ax]);
+		push(4);
+		m|=16;
+            }
+            if(regs[dx]&&(!isreg(z)||p->z.reg!=dx)){
+                emit(f,"\tpushl\t%s\n",regnames[dx]);
+		push(4);
+		m|=2;
+            }
+            if((p->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&(p->q2.reg==ax||p->q2.reg==dx)){
+                move(f,&p->q2,0,0,dx,t);
+                emit(f,"\tpushl\t%s\n",regnames[dx]);
+		push(4);
+                m|=8;
+            }
+	    if(isreg(q1)&&p->q1.reg==dx&&(m&10)==10)
+	      emit(f,"\tmovl\t4(%s),%s\n",regnames[sp],regnames[ax]);
+	    else
+	      move(f,&p->q1,0,0,ax,t);
+            if(isconst(q2)){
+                emit(f,"\tpush%c\t",x_t[t&NQ]);emit_obj(f,&p->q2,t);
+                emit(f,"\n");
+		push(4);
+		m|=4;
+            }
+	    if(isreg(q2)&&p->q2.reg==dx){
+	      emit(f,"\tpushl\t%s\n",regnames[dx]);
+	      push(4);
+	      m|=4;
+	    }
+            if(t&UNSIGNED) emit(f,"\txorl\t%s,%s\n\tdivl\t",regnames[dx],regnames[dx]);
+                else       emit(f,"\tcltd\n\tidivl\t");
+            if((m&12)||(isreg(q2)&&p->q2.reg==dx)){
+                emit(f,"(%s)",regnames[sp]);
+            }else if(isreg(q2)&&p->q2.reg==ax){
+                emit(f,"%s(%s)",(m&10)?"4":"",regnames[sp]);
+            }else{
+                emit_obj(f,&p->q2,t);
+            }
+            emit(f,"\n");
+            if(c==DIV) move(f,0,ax,&p->z,0,t);
+                else   move(f,0,dx,&p->z,0,t);
+            if(m&4){ emit(f,"\taddl\t$%ld,%s\n",zm2l(sizetab[t&NQ]),regnames[sp]);pop(4);}
+            if(m&8){ emit(f,"\tpopl\t%s\n",regnames[dx]);pop(4);}
+            if(m&2){ emit(f,"\tpopl\t%s\n",regnames[dx]);pop(4);}
+            if(m&1){ emit(f,"\tpopl\t%s\n",regnames[ax]);pop(4);}
+            if(m&16){ emit(f,"\taddl\t$%ld,%s\n",zm2l(sizetab[t&NQ]),regnames[sp]);pop(4);}
+            continue;
+        }
+        if(!isconst(q2)&&(c==LSHIFT||c==RSHIFT)){
+            char *s=arithmetics[c-LSHIFT];
+            int fl=0;
+            if(c==RSHIFT&&(t&UNSIGNED)) s="shr";
+            if(((p->q1.flags&REG)&&p->q1.reg==cx)||((p->z.flags&REG)&&p->z.reg==cx)
+               ||(!compare_objects(&p->q1,&p->z)&&!isreg(q1))){
+                fl=regs[cx];regs[cx]=2; /* don't want cx */
+                reg=get_reg(f,p,t);
+                regs[cx]=fl;
+                if(isreg(z)&&p->z.reg==cx) fl=0;
+                if(fl){emit(f,"\tpushl\t%s\n",regnames[cx]);push(4);}
+                move(f,&p->q1,0,0,reg,t);
+                move(f,&p->q2,0,0,cx,t);
+                emit(f,"\t%s%c\t%%cl,%s\n",s,x_t[t&NQ],mregname(reg,t));
+                move(f,0,reg,&p->z,0,t);
+                if(fl){emit(f,"\tpopl\t%s\n",regnames[cx]);pop(4);}
+                continue;
+            }else{
+                if(!isreg(q2)||p->q2.reg!=cx){
+                    if(regs[cx]){emit(f,"\tpushl\t%s\n",regnames[cx]);push(4);fl=1;}
+                    move(f,&p->q2,0,0,cx,t);
+                }
+                if(compare_objects(&p->q1,&p->z)){
+                    emit(f,"\t%s%c\t%%cl,",s,x_t[t&NQ]);
+                    emit_obj(f,&p->z,t);emit(f,"\n");
+                }else{
+                    move(f,0,p->q1.reg,&p->z,0,t);
+                    emit(f,"\t%s%c\t%%cl,",s,x_t[t&NQ]);
+                    emit_obj(f,&p->z,t);emit(f,"\n");
+                }
+                if(fl) {emit(f,"\tpopl\t%s\n",regnames[cx]);pop(4);}
+                continue;
+            }
+        }
+        if((c>=LSHIFT&&c<=MOD)||(c>=OR&&c<=AND)){
+            char *s;
+            if(c>=OR&&c<=AND) s=logicals[c-OR];
+                else s=arithmetics[c-LSHIFT];
+            if(c==RSHIFT&&(t&UNSIGNED)) s="shr";
+            if(c!=MULT&&compare_objects(&p->q1,&p->z)){
+                if(isreg(z)||isreg(q1)||isconst(q2)){
+                    if(isconst(q2)&&(c==ADD||c==SUB)){
+                        eval_const(&p->q2.val,t);
+                        if(zmeqto(vmax,l2zm(1L))&&zumeqto(vumax,ul2zum(1UL))&&zldeqto(vldouble,d2zld(1.0))){
+                            if(c==ADD) s="inc"; else s="dec";
+                            emit(f,"\t%s%c\t",s,x_t[t&NQ]);
+                            emit_obj(f,&p->z,t);emit(f,"\n");
+                            continue;
+                        }
+                    }
+                    emit(f,"\t%s%c\t",s,x_t[t&NQ]);
+                    emit_obj(f,&p->q2,t);emit(f,",");
+                    emit_obj(f,&p->z,t);emit(f,"\n");
+                    continue;
+                }else{
+                    if(isreg(q2)) reg=p->q2.reg; else reg=get_reg(f,p,t);
+                    move(f,&p->q2,0,0,reg,t);
+                    emit(f,"\t%s%c\t%s",s,x_t[t&NQ],mregname(reg,t));
+                    emit(f,","); emit_obj(f,&p->z,t);emit(f,"\n");
+                    continue;
+                }
+            }
+	    if(c==AND&&isreg(z)){
+	      /* can we use test instruction? */
+	      struct IC *p2=p->next;
+	      while(p2->code==ALLOCREG||p2->code==FREEREG)
+		p2=p2->next;
+	      if(p2->code==TEST&&(p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==p->z.reg){
+		struct IC *p3=p2->next;
+		while(p3->code==ALLOCREG||p3->code==FREEREG){
+		  if(p3->code==FREEREG&&p3->q1.reg==p->z.reg)
+		    break;
+		  p3=p3->next;
+		}
+		if(p3->code==FREEREG&&p3->q1.reg==p->z.reg){
+		  /* we can use test */
+		  p2->code=NOP;
+		  if(notpopped&&!dontpop){
+		    emit(f,"\taddl\t$%ld,%%esp\n",notpopped);
+		    pop(notpopped);
+		    notpopped=0;
+		  }
+		  if(isconst(q1)){
+		    struct obj tmp=p->q1;
+		    p->q1=p->q2;
+		    p->q2=tmp;
+		  }
+		  if(!isreg(q1)&&!isreg(q2)&&!isconst(q2)){
+		    int r=get_reg(f,p,t);
+		    move(f,&p->q1,0,0,r,t);
+		    p->q1.flags=REG;
+		    p->q1.reg=r;
+		  }
+		  emit(f,"\ttest%c\t",x_t[t&NQ]);
+		  emit_obj(f,&p->q2,t);
+		  emit(f,",");
+		  emit_obj(f,&p->q1,t);
+		  emit(f,"\n");
+		  continue;
+		}
+	      }
+	    }
+	      
+	    if(isreg(z)&&(p->q2.flags&REG)&&p->q2.reg==p->z.reg){
+	      if(c==ADD||c==AND||c==OR||c==XOR){
+		struct obj tmp;
+		tmp=p->q1;
+		p->q1=p->q2;
+		p->q2=tmp;
+	      }
+	    }
+            if(isreg(z)&&(!(p->q2.flags&REG)||p->q2.reg!=p->z.reg)) reg=p->z.reg; else reg=get_reg(f,p,t);
+            move(f,&p->q1,0,0,reg,t);
+            if(isconst(q2)&&(c==ADD||c==SUB)){
+                eval_const(&p->q2.val,t);
+                if(zmeqto(vmax,l2zm(1L))&&zumeqto(vumax,ul2zum(1UL))&&zldeqto(vldouble,d2zld(1.0))){
+                    if(c==ADD) s="inc"; else s="dec";
+                    emit(f,"\t%s%c\t%s\n",s,x_t[t&NQ],mregname(reg,t));
+                }else{
+                    emit(f,"\t%s%c\t",s,x_t[t&NQ]);
+                    emit_obj(f,&p->q2,t);emit(f,",%s\n",mregname(reg,t));
+                }
+            }else{
+                emit(f,"\t%s%c\t",s,x_t[t&NQ]);
+                emit_obj(f,&p->q2,t);emit(f,",%s\n",mregname(reg,t));
+            }
+            move(f,0,reg,&p->z,0,t);
+            continue;
+        }
+        ierror(0);
+    }
+    if(notpopped){
+        emit(f,"\taddl\t$%ld,%%esp\n",notpopped);
+        pop(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 code,int typ)
+{
+  return(0);
+}
+
+void cleanup_cg(FILE *f)
+{
+  struct fpconstlist *p;
+  unsigned char *ip;
+
+  title(f);
+  while(p=firstfpc){
+    if(f){
+      if(section!=CODE){emit(f,codename);if(f) section=CODE;}
+      emit(f,"\t.align\t4\n");
+      emit(f,"%s%d:\n\t.long\t",labprefix,p->label);
+      ip=(unsigned char *)&p->val.vdouble;
+      emit(f,"0x%02x%02x%02x%02x",ip[3],ip[2],ip[1],ip[0]);
+      if((p->typ&NQ)==DOUBLE||(p->typ&NQ)==LDOUBLE){
+	emit(f,",0x%02x%02x%02x%02x",ip[7],ip[6],ip[5],ip[4]);
+      }
+      emit(f,"\n");
+    }
+    firstfpc=p->next;
+    free(p);
+  }
+  if(f){
+    if(section!=BSS){emit(f,bssname);if(f) section=BSS;}
+    if(cxl) emit(f,"\t.lcomm\t%s%d,4\n",labprefix,cxl);
+    if(sil) emit(f,"\t.lcomm\t%s%d,4\n",labprefix,sil);
+    if(dil) emit(f,"\t.lcomm\t%s%d,4\n",labprefix,dil);
+  }
+}
+void init_db(FILE *f)
+{
+  dwarf2_setup(sizetab[POINTER],".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;
+}
+
+
+void insert_const(union atyps *p,int t)
+/*  Traegt Konstante in entprechendes Feld ein.       */
+{
+  if(!p) ierror(0);
+  t&=NU;
+  if(ISBE(t))
+    t=LETYPE(t);
+  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|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==POINTER) {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(ISBE(f))
+    f=LETYPE(f);
+  if(!p) ierror(0);
+  if(f==MAXINT||(f>=CHAR&&f<=LLONG)){
+    if(!(t&UNSIGNED)){
+      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==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)){
+      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(ISBE(t)){
+    fprintf(f,"B");
+    t=LETYPE(t);
+  }
+  if(t==CHAR){fprintf(f,"C");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)){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)){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){fprintf(f,"M");printzm(f,p->vmax);}
+  if(t==(UNSIGNED|MAXINT)){fprintf(f,"UM");printzum(f,p->vumax);}
+  /*FIXME*/
+  if(t==POINTER){fprintf(f,"P");vumax=zul2zum(p->vulong);printzum(f,vumax);}
+}
+void emitval(FILE *f,union atyps *p,int t)
+/*  Gibt atyps aus.                                     */
+{
+  t&=NU;
+  /*FIXME?*/
+  if(ISBE(t))
+    t=LETYPE(t);
+  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)){vumax=zui2zum(p->vuint);emitzum(f,vumax);}
+  if(t==LONG){vmax=zl2zm(p->vlong);emitzm(f,vmax);}
+  if(t==(UNSIGNED|LONG)){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);}
+  /*FIXME*/
+  if(t==POINTER){vumax=zul2zum(p->vulong);emitzum(f,vumax);}
+} 
+
+void conv_typ(struct Typ *p)
+/* Erzeugt extended types in einem Typ. */
+{
+  char *attr;
+  while(p){
+    if(ISSCALAR(p->flags)&&(p->flags&NQ)!=CHAR&&(attr=p->attr)&&strstr(attr,"bigendian")){
+      if(!ISBE(p->flags))
+	p->flags++;
+    }
+    if(ISSCALAR(p->flags)&&(p->flags&NQ)!=CHAR&&(attr=p->attr)&&strstr(attr,"littleendian")){
+      if(ISBE(p->flags))
+	p->flags--;
+    }
+    p=p->next;
+  }
+}
diff --git a/machines/i386/machine.dt b/machines/i386/machine.dt
new file mode 100755
index 0000000..47b1bfa
--- /dev/null
+++ b/machines/i386/machine.dt
@@ -0,0 +1,16 @@
+S8BS
+S8BU
+S16BSLE S16BSBE
+S16BULE S16BUBE
+S32BSLE S32BSBE
+S32BULE S32BUBE
+S32BSLE S32BSBE
+S32BULE S32BUBE
+S64BSLE S64BSBE
+S64BULE S64BUBE
+S32BIEEELE
+S64BIEEELE
+S64BIEEELE
+S32BULE S32BUBE
+
+
diff --git a/machines/i386/machine.h b/machines/i386/machine.h
new file mode 100755
index 0000000..6c1aed5
--- /dev/null
+++ b/machines/i386/machine.h
@@ -0,0 +1,176 @@
+/*  Example of a code-generator for an Intel 386 or higher.         */
+
+#include "dt.h"
+
+/* We have extended types! What we have to do to support them:      */
+/* - #define HAVE_EXT_TYPES
+   - #undef all standard types
+   - #define all standard types plus new types
+   - write eval_const and insert_const
+   - write typedefs for zmax and zumax
+   - write typname[]
+   - write conv_typ()
+   - optionally #define ISPOINTER, ISARITH, ISINT etc.
+   - optionally #define HAVE_TGT_PRINTVAL and write printval
+   - optionally #define POINTER_TYPE
+   - optionally #define HAVE_TGT_FALIGN and write falign
+   - optionally #define HAVE_TGT_SZOF and write szof
+   - optionally add functions for attribute-handling
+*/
+#define HAVE_EXT_TYPES 1
+
+#define HAVE_TGT_PRINTVAL
+
+#undef CHAR
+#undef SHORT
+#undef INT
+#undef LONG
+#undef LLONG
+#undef FLOAT
+#undef DOUBLE
+#undef LDOUBLE
+#undef VOID
+#undef POINTER
+#undef ARRAY
+#undef STRUCT
+#undef UNION
+#undef ENUM
+#undef FUNKT
+#undef MAXINT
+#undef MAX_TYPE
+
+#define CHAR 1
+#define SHORT 2
+#define BSHORT 3
+#define INT 4
+#define BINT 5
+#define LONG 6
+#define BLONG 7
+#define LLONG 8
+#define BLLONG 9
+#define FLOAT 10
+#define BFLOAT 11
+#define DOUBLE 12
+#define BDOUBLE 13
+#define LDOUBLE 14
+#define BLDOUBLE 15
+#define VOID 16
+#define POINTER 17
+#define BPOINTER 18
+#define ARRAY 19
+#define STRUCT 20
+#define UNION 21
+#define ENUM 22
+#define FUNKT 23
+ 
+#define MAXINT 24 /* should not be accesible to application */
+ 
+#define MAX_TYPE MAXINT
+
+#define ISPOINTER(x) ((x&NQ)==POINTER||(x&NQ)==BPOINTER)
+#define ISSCALAR(x) ((x&NQ)>=CHAR&&(x&NQ)<=BPOINTER)
+#define ISINT(x) ((x&NQ)>=CHAR&&(x&NQ)<=BLLONG)
+
+typedef zllong zmax;
+typedef zullong zumax;
+
+union atyps{
+  zchar vchar;
+  zuchar vuchar;
+  zshort vshort;
+  zushort vushort;
+  zint vint;
+  zuint vuint;
+  zlong vlong;
+  zulong vulong;
+  zllong vllong;
+  zullong vullong;
+  zmax vmax;
+  zumax vumax;
+  zfloat vfloat;
+  zdouble vdouble;
+  zldouble vldouble;
+};
+
+/*  This struct can be used to implement machine-specific           */
+/*  addressing-modes.                                               */
+/*  Not used in this code-generrator.                               */
+struct AddressingMode{
+  int mode;
+  int base;
+  int idx;
+  int scal;
+  zmax offset;
+  struct Var *v;
+};
+
+/*  The number of registers of the target machine.                  */
+#define MAXR 18
+
+/*  Number of commandline-options the code-generator accepts.       */
+#define MAXGF 10
+
+/*  If this is set to zero vbcc will not generate ICs where the     */
+/*  target operand is the same as the 2nd source operand.           */
+/*  This can sometimes simplify the code-generator, but usually     */
+/*  the code is better if the code-generator allows it.             */
+#define USEQ2ASZ 1
+
+/*  This specifies the smallest integer type that can be added to a */
+/*  pointer.                                                        */
+#define MINADDI2P INT
+#define MAXADDI2P LONG
+
+/*  If the bytes of an integer are ordered most significant byte    */
+/*  byte first and then decreasing set BIGENDIAN to 1.              */
+#define BIGENDIAN 0
+
+/*  If the bytes of an integer are ordered lest significant byte    */
+/*  byte first and then increasing set LITTLEENDIAN to 1.           */
+#define LITTLEENDIAN 1
+
+/*  Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive.    */
+
+/*  If switch-statements should be generated as a sequence of       */
+/*  SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1.      */
+/*  This can yield better code on some machines.                    */
+#define SWITCHSUBS 0
+
+/*  In optimizing compilation certain library memcpy/strcpy-calls   */
+/*  with length known at compile-time will be inlined using an      */
+/*  ASSIGN-IC if the size is less or equal to INLINEMEMCPY.         */
+/*  The type used for the ASSIGN-IC will be UNSIGNED|CHAR.          */
+#define INLINEMEMCPY 1024
+
+/*  We keep track of all registers modified by a function.          */
+#define HAVE_REGS_MODIFIED 1
+
+/* size of buffer for asm-output */
+#define EMIT_BUF_LEN 1024 /* should be enough */
+/* number of asm-output lines buffered */
+#define EMIT_BUF_DEPTH 4
+
+/*  We have no asm_peephole to optimize assembly-output */
+#define HAVE_TARGET_PEEPHOLE 0
+
+#define JUMP_TABLE_DENSITY 0.8
+#define JUMP_TABLE_LENGTH 4
+
+/* We use builtin libcalls for some operations */
+#define HAVE_LIBCALLS 1
+
+/* support for variable-length arrays */
+#define ALLOCVLA_REG 1
+#define ALLOCVLA_INLINEASM "\tsubl\t%eax,%esp\n\tandl\t$-5,%esp\n\tmovl\t%esp,%eax"
+/* TODO: find a better solution some time */
+#define FREEVLA_REG 0
+#define FREEVLA_INLINEASM "\tmovl\t(%esp),%esp\n\tsubl\t$4,%esp"
+#define OLDSPVLA_INLINEASM "\tmovl\t%esp,%eax"
+#define FPVLA_REG 7
+
+/* do not create CONVERT_ICs from floats to unsigned integers */
+#define AVOID_FLOAT_TO_UNSIGNED 1
+
+/* do not create CONVERT_ICs from unsigned integers to floats */
+#define AVOID_UNSIGNED_TO_FLOAT 1
+
diff --git a/machines/m65/compress.c b/machines/m65/compress.c
new file mode 100644
index 0000000..19f033d
--- /dev/null
+++ b/machines/m65/compress.c
@@ -0,0 +1,123 @@
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "vcpr.h"
+
+
+const char tg_copyright[]="6502 code compressor V0.1 (c) 2020 by Volker Barthelmann";
+
+char *inst[]={
+  "lda","ldx","sta","stx","ldy","sty",
+  "adc","sbc","and","ora","eor",
+  "bne","beq","bcc","bcs","bvs","bvc","bpl","bmi",
+  "clc","sec",
+  /*"pla","pha",*/
+  "txa","tax","tya","tay",
+  "inc","dec","dex","inx","iny","dey",
+  /*"rts","rti",*/"jsr","jmp",
+  "cmp","cpx","cpy",
+  "asl","lsr","ror","rol"
+};
+
+int minsave=5;
+
+void parse_line(char *s,line *p)
+{
+  int l,i;
+  static int secok=0;
+  char buf[16],buf2[16],*e;
+
+  if(sscanf(s," %8s %8s",buf,buf2)==2&&!strcmp(buf,"section")){
+    if(!strcmp(buf2,"text"))
+      secok=1;
+    else
+      secok=0;
+    p->flags=BARRIER;
+    return;
+  }
+
+  if(sscanf(s,"l%d:",&l)==1){
+    p->flags|=LABDEF;
+    p->l1=l;
+    p->size=0;
+    if(!secok) p->flags|=BARRIER;
+    return;
+  }
+
+  if(!secok){
+    p->flags|=BARRIER;
+    return;
+  }
+
+  if(!isspace(*s)){
+    p->flags=BARRIER;
+    return;
+  }
+  while(isspace(*s))
+    s++;
+  for(e=s;isalpha(*e);e++);
+
+  for(i=0;i<sizeof(inst)/sizeof(inst[0]);i++){
+    if(!strncmp(s,inst[i],e-s)){
+      while(isspace(*e)) e++;
+      if(*e==0){
+	p->size=1;
+	return;
+      }
+      p->size=2;
+      if(sscanf(e,"l%d",&l)==1){
+	p->flags|=LABUSE;
+	p->l1=l;
+      }
+      if(*s=='b'||!strncmp(s,"jmp",3)){
+	p->flags|=BRANCH;
+      }
+      return;
+    }
+  }
+  p->flags=BARRIER;
+}
+
+static int nlab;
+
+#define SECTION "\tsection\ttext\n"
+
+void add_header(line *after)
+{
+  nlab=new_label();
+  line *new;
+  new=new_line();
+  new->flags=LABDEF;
+  new->l1=nlab;
+  new->code=mymalloc(16); /* TODO */
+  sprintf(new->code,"x%d:\n",nlab);
+  insert_line(after,new);
+  new=new_line();
+  new->flags=BARRIER;
+  new->code=mymalloc(strlen(SECTION)+1);
+  strcpy(new->code,SECTION);
+  insert_line(after,new);
+}
+
+void add_ret(line *after)
+{
+  line *new=new_line();
+  new->size=1;
+  new->flags=BARRIER;
+  new->code=mymalloc(8); /*TODO*/
+  strcpy(new->code,"\trts\n");
+  insert_line(after,new);
+}
+
+void add_jsr(line *after)
+{
+  line *new=new_line();
+  new->flags=LABUSE;
+  new->size=3;
+  new->l1=nlab;
+  new->code=mymalloc(24); /* TODO */
+  sprintf(new->code,"\tjsr\tx%d\n",nlab);
+  insert_line(after,new);
+}
diff --git a/machines/m65/machine.c b/machines/m65/machine.c
new file mode 100644
index 0000000..45819f1
--- /dev/null
+++ b/machines/m65/machine.c
@@ -0,0 +1,5163 @@
+/*  MEGA65 45GS02 backend for vbcc
+    (c) Volker Barthelmann 2020
+    (c) Paul Gardner-Stephen 2020
+
+*/                                                                             
+
+#include "supp.h"
+#include "vbc.h"
+
+#include <math.h>
+
+static char FILE_[]=__FILE__;
+
+/*  Public data that MUST be there.                             */
+
+/* Name and copyright. */
+char cg_copyright[]="vbcc 45GS02 (MEGA65) code-generator V0.1 (c) in 2020 by Volker Barthelmann, Paul Gardner-Stephen";
+
+/*  Commandline-flags the code-generator accepts:
+    0: just a flag
+    VALFLAG: a value must be specified
+    STRINGFLAG: a string can be specified
+    FUNCFLAG: a function will be called
+    apart from FUNCFLAG, all other versions can only be specified once */
+int g_flags[MAXGF]={0,0,
+		    VALFLAG,0,0,
+		    0,0,
+		    VALFLAG,VALFLAG,0,0,
+		    VALFLAG,0,0,0,
+		    0,0,0,
+		    0};
+
+/* the flag-name, do not use names beginning with l, L, I, D or U, because
+   they collide with the frontend */
+char *g_flags_name[MAXGF]={"std-syntax","no-rax",
+			   "volatile-regs","ieee","no-peephole",
+			   "cbmascii","softstack",
+			   "reg-args","int-args","mainargs","no-bank-vars",
+			   "common-banknr","btmp-zpage","oldfp","large",
+			   "glob-acc","avoid-bank-switch","manual-banking",
+			   "atascii","65c02"};
+
+/* the results of parsing the command-line-flags will be stored here */
+union ppi g_flags_val[MAXGF];
+
+/*  Alignment-requirements for all types in bytes.              */
+zmax align[MAX_TYPE+1];
+
+/*  Alignment that is sufficient for every object.              */
+zmax maxalign;
+
+/*  CHAR_BIT for the target machine.                            */
+zmax char_bit;
+
+/*  sizes of the basic 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. will be initialized in init_cg(),
+    register number 0 is invalid, valid registers start at 1 */
+char *regnames[MAXR+1];
+
+/*  The Size of each register in bytes.                         */
+zmax regsize[MAXR+1];
+
+/*  a 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];
+
+/* specifies the priority for the register-allocator, if the same
+   estimated cost-saving can be obtained by several registers, the
+   one with the highest priority will be used */
+int reg_prio[MAXR+1];
+
+/* an empty reg-handle representing initial state */
+struct reg_handle empty_reg_handle={0,0};
+
+/* Names of target-specific variable attributes.                */
+char *g_attr_name[]={"__interrupt","__zpage","__nocpr",0};
+
+#define INTERRUPT 1
+#define ZPAGE 2
+#define NOCOMPRESS 4
+
+/****************************************/
+/*  Private data and functions.         */
+/****************************************/
+
+#define STDSYNTAX  (g_flags[0]&USEDFLAG)
+#define NORAX      (g_flags[1]&USEDFLAG)
+#define VOL_GPRS   ((g_flags[2]&USEDFLAG)?g_flags_val[2].l:NUM_GPRS/2)
+#define IEEE       (g_flags[3]&USEDFLAG)
+#define NOPEEP     (g_flags[4]&USEDFLAG)
+#define CBMASCII   (g_flags[5]&USEDFLAG)
+#define SOFTSTACK  (g_flags[6]&USEDFLAG)
+#define GPR_ARGS   ((g_flags[7]&USEDFLAG)?g_flags_val[7].l:8)
+#define MAINARGS   (g_flags[9]&USEDFLAG)
+#define NOBANKVARS (g_flags[10]&USEDFLAG)
+#define COMMONBANK ((g_flags[11]&USEDFLAG)?g_flags_val[11].l:0)
+#define BIGZPAGE   (g_flags[12]&USEDFLAG)
+#define OLDFP      (g_flags[13]&USEDFLAG)
+#define LARGE      (g_flags[14]&USEDFLAG)
+#define GLOBACC    (g_flags[15]&USEDFLAG)
+#define NOSWITCH   (g_flags[16]&USEDFLAG)
+#define NOBANKING  (g_flags[17]&USEDFLAG)
+#define ATASCII    (g_flags[18]&USEDFLAG)
+#define C02        (g_flags[19]&USEDFLAG)
+
+
+
+#define STR_NEAR "near"
+#define STR_FAR "far"
+#define STR_HUGE "huge"
+
+#define PLA (-1)
+#define JMPIND (-2)
+
+static void function_top(FILE *,struct Var *,long);
+static void function_bottom(FILE *f,struct Var *,long);
+
+#define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
+#define isacc(x) (isreg(x)&&(p->x.reg==ra||p->x.reg==rax))
+#define isconst(x) ((p->x.flags&(KONST|DREFOBJ))==KONST)
+
+#define isptr(r) ((r)>=FIRST_PAIR&&(r)<=LAST_PAIR)
+
+static int q1reg,q2reg,zreg;
+
+static char *ccs[]={"eq","ne","lt","ge","le","gt",""};
+static char *logicals[]={"ora","eor","and"};
+static char *arithmetics[]={"slw","srw","adc","sbc","mullw","divw","mod"};
+
+/* alignment of basic data-types, used to initialize align[] */
+static long malign[MAX_TYPE+1]=  {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+/* sizes of basic data-types, used to initialize sizetab[] */
+static long msizetab[MAX_TYPE+1]={1,1,2,2,4,8,4,4,4,0,2,3,3,0,0,0,1,0};
+static char *mregnames[MAXR+1];
+
+/* Typenames (needed because of HAVE_EXT_TYPES). */
+char *typname[]={"strange","char","short","int","long","long long",
+                 "float","double","long double","void",
+                 "near-pointer","far-pointer","huge-pointer",
+                 "array","struct","union","enum","function"};
+
+
+/* used to initialize regtyp[] */
+static struct Typ ityp={INT},ctyp={CHAR},ftyp={FLOAT},lltyp={LLONG};
+
+/* macros defined by the backend */
+static char *marray[]={"__section(x)=__vattr(\"section(\"#x\")\")",
+		       "__m65__", 
+		       "__SIZE_T_INT",
+		       "__bank(x)=__vattr(\"bank(\"#x\")\")",
+                       "__far=__attr(\"far\")",
+                       "__near=__attr(\"near\")",
+                       "__huge=__attr(\"huge\")",
+		       0};
+
+/* special registers */
+static int ra=1, rx=2, ry=3, rz=4, sp1=5,sp2=6,sp=7,fp,fp1,fp2;
+static int t4=LAST_GPR,t3=LAST_GPR-1,t2=LAST_GPR-2,t1=LAST_GPR-3;
+static int rax=8;
+static int raxyz=9;
+static int yval;
+#define NOVAL 1000
+
+static int t1,t2,f1,f2; /*tODO: remove*/
+
+static int pushedacc,pushedx,nopeep,cbmascii,atascii,ieee;
+static int c02,noy;
+static int has_inc_a=1;                // MEGA65 has INC A / INA instruction
+static int has_zero_reg=0;
+static char *jmpinst;
+static int pass;
+static int libsave;
+static struct rpair rp2;
+static int cbank;
+static Var bankv;
+static int bankvoffset;
+static int bankcnum;
+static obj zstore;
+static int zstoreflag;
+
+#define SECLEN 128
+char *use_sec;
+int use_bank=-1;
+
+#define dt(t) (((t)&UNSIGNED)?udt[(t)&NQ]:sdt[(t)&NQ])
+static char *sdt[MAX_TYPE+1]={"??","c","s","i","l","ll","f","d","ld","v","p"};
+static char *udt[MAX_TYPE+1]={"??","uc","us","ui","ul","ull","f","d","ld","v","p"};
+
+/* perhaps provide version with 8bit int? */
+#define ISCHAR(t) ((t&NQ)==CHAR)
+#define ISSHORT(t) ((t&NQ)==SHORT||(t&NQ)==INT||(t&NQ)==POINTER)
+#define ISFPOINTER(t) ((t&NQ)==FPOINTER)
+#define ISLONG(t) ((t&NQ)==LONG)
+#define ISLLONG(t) ((t&NQ)==LLONG)
+
+#define ISIDX(r) (r==rx||r==rz)
+
+/* am */
+#define IMM_IND 1
+#define GPR_IND 2
+#define ABS_IND 3
+
+/* sections */
+#define DATA 0
+#define BSS 1
+#define CODE 2
+#define RODATA 3
+#define SPECIAL 4
+
+static long stack;
+static int stack_valid;
+static int section=-1,newobj;
+static char *codename="\tsection\ttext",
+  *dataname="\tsection\tdata",
+  *bssname="\tsection\tbss",
+  *rodataname="\tsection\trodata";
+
+/* return-instruction */
+static char *ret;
+
+/* label at the end of the function (if any) */
+static int exit_label;
+
+/* assembly-prefixes for labels and external identifiers */
+static char *labprefix="l",*idprefix="_";
+
+/* variables to calculate the size and partitioning of the stack-frame
+   in the case of FIXED_SP */
+static long frameoffset,pushed,maxpushed,framesize;
+
+static long localsize,rsavesize,rscnt,argsize;
+
+static void emit_obj(FILE *f,struct obj *p,int t);
+
+/* calculate the actual current offset of an object relativ to the
+   stack-pointer; we use a layout like this:
+   ------------------------------------------------
+   | arguments to this function                   |
+   ------------------------------------------------
+   | caller-save registers [size=rsavesize]       |
+   ------------------------------------------------
+   | local variables [size=localsize]             |
+   ------------------------------------------------
+   | arguments to called functions [size=argsize] |
+   ------------------------------------------------
+   All sizes will be aligned as necessary.
+   In the case of FIXED_SP, the stack-pointer will be adjusted at
+   function-entry to leave enough space for the arguments and have it
+   aligned to 16 bytes. Therefore, when calling a function, the
+   stack-pointer is always aligned to 16 bytes.
+   For a moving stack-pointer, the stack-pointer will usually point
+   to the bottom of the area for local variables, but will move while
+   arguments are put on the stack.
+
+   This is just an example layout. Other layouts are also possible.
+*/
+
+static int bank(Var *v)
+{
+  char *s=v->vattr;
+  int n,r;
+  if(!NOBANKING&&s&&(s=strstr(s,"bank("))){
+    if(sscanf(s+5,"%i",&n)==1)
+      return n;
+  }
+  return -1;
+}
+
+static void ebank(FILE *f,int b)
+{
+  if(b>=0) emit(f,"%d",b);
+  emit(f,"\n");
+}
+
+static long real_offset(struct obj *o)
+{
+  long off=zm2l(o->v->offset);
+  if(off<0){
+    /* function parameter */
+    off=localsize+rsavesize-off-zm2l(maxalign);
+  }
+
+  off+=argsize;
+  off+=zm2l(o->val.vmax);
+  return off;
+}
+
+/*  Initializes an addressing-mode structure and returns a pointer to
+    that object. Will not survive a second call! */
+static struct obj *cam(int flags,int base,long offset)
+{
+  static struct obj obj;
+  static struct AddressingMode am;
+  obj.am=&am;
+  am.flags=flags;
+  am.base=base;
+  am.offset=offset;
+  return &obj;
+}
+
+/* changes to a special section, used for __section() */
+static int special_section(FILE *f,struct Var *v)
+{
+  char *sec;
+  if(v->tattr&ZPAGE){
+    emit(f,"\tsection\tzpage\n");
+  }else{
+    if(!v->vattr) return 0;
+    sec=strstr(v->vattr,"section(");
+    if(!sec) return 0;
+    sec+=strlen("section(");
+    emit(f,"\tsection\t");
+    while(*sec&&*sec!=')') emit_char(f,*sec++);
+    emit(f,"\n");
+  }
+  if(f) section=SPECIAL;
+  return 1;
+}
+
+
+
+#define chk_coll(x) do{if((x)==r||(x)==r1||(x)==r2) return 0;	\
+    if(reg_pair((x),&rp)&&(rp.r1==r||rp.r2==r)) return 0;}while(0)
+
+static int scratch(IC *p,int r)
+{
+  int r1,r2;
+  if(!p) return 1;
+  if(reg_pair(r,&rp)){
+    r1=rp.r1;
+    r2=rp.r2;
+  }else{
+    r1=0;
+    r2=0;
+  }
+  if(isreg(z)&&p->z.reg==r){
+    if(!(p->q2.flags&REG))
+      return 1;
+    if(p->q2.reg==r||p->q2.reg==r1||p->q2.reg==r2)
+      return 0;
+    if(reg_pair(p->q2.reg,&rp))
+      if(rp.r1==r||rp.r2==r)
+	return 0;
+    return 1;
+  }
+  while(p){
+    if(p->code==LABEL||p->code==CALL)
+      return 0;
+    if(p->code>=BEQ&&p->code<=BRA)
+      return 0;
+    if(p->code==FREEREG||p->code==ALLOCREG){
+      if(p->q1.reg==r)
+	return 1;
+      if(reg_pair(p->q1.reg,&rp)&&(rp.r1==r||rp.r2==r))
+	return 1;
+    }
+    if(p->q1.am) chk_coll(p->q1.am->base);
+    if(p->q2.am) chk_coll(p->q2.am->base);
+    if(p->z.am) chk_coll(p->z.am->base);
+    if(p->q1.flags&REG) chk_coll(p->q1.reg);
+    if(p->q2.flags&REG) chk_coll(p->q2.reg);
+    if(p->z.flags&REG){
+      if(p->z.flags&DREFOBJ)
+	chk_coll(p->z.reg);
+      else{
+	if(p->z.reg==r)
+	  return 1;
+	if(reg_pair(p->z.reg,&rp)&&(rp.r1==r||rp.r2==r))
+	  return 1;
+      }
+    }
+
+    p=p->next;
+  }
+  return 1;
+}
+
+static int rsavecur;
+static int in_isr;
+
+static int get_reg(FILE *f,IC *p,int t)
+{
+  int r,r1,r2,pass,flag;
+
+  for(pass=0;pass<5;pass++){
+    for(r=MAXR;r>sp;r--){
+      if(reg_pair(r,&rp)){
+	r1=rp.r1;
+	r2=rp.r2;
+      }else{
+	r1=0;
+	r2=0;
+      }
+      if((pass==0||pass==3)&&(!regscratch[r]||in_isr))
+	continue;
+      if(pass<3){
+	if(regs[r]) continue;
+	if(r1&&(regs[r1]||regs[r2])) continue;
+      }
+      if(pass==2&&!(regs[r]&4))
+	continue;
+      if((p->q1.flags&REG)&&(p->q1.reg==r||p->q1.reg==r1||p->q1.reg==r2)) continue;
+      if((p->q2.flags&REG)&&(p->q2.reg==r||p->q2.reg==r1||p->q2.reg==r2)) continue;
+      if((p->z.flags&REG)&&(p->z.reg==r||p->z.reg==r1||p->z.reg==r2)) continue;
+      if(regok(r,t,1)){
+	flag=8;
+	if(regs[r]){
+	  flag|=2;
+	  if(p->code==COMPARE||p->code==TEST)
+	    ierror(0);
+	  if(regs[ra]){
+	    emit(f,"\ttay\n");
+	    yval=NOVAL;
+	  }
+	  if(r1){
+	    emit(f,"\tlda\t%s\n",mregnames[r1]);
+	    emit(f,"\tpha\n");
+	    emit(f,"\tlda\t%s\n",mregnames[r2]);
+	    emit(f,"\tpha\n");
+	  }else{
+	    emit(f,"\tlda\t%s\n",mregnames[r]);
+	    emit(f,"\tpha\n");
+	  }
+	  if(regs[ra])
+	    emit(f,"\ttya\n");
+	}
+	if(r1){
+	  regs[r1]|=flag;
+	  regs[r2]|=flag;
+	}
+	regs[r]|=flag;
+	regused[r]=1;
+	regused[r1]=1;
+	regused[r2]=1;
+	return r;
+      }
+    }
+  }
+  pric2(stdout,p);
+  ierror(0);
+}
+
+static void get_acc(FILE *f, IC *p,int t)
+{
+  int r;
+  if(isacc(z)) return;
+  t&=NQ;
+  if(ISCHAR(t)){
+    if(1/*!isreg(q1)||(p->q1.reg!=ra&&p->q1.reg!=rax)*/){
+      if((regs[ra]||regs[rax])&&!scratch(p,ra)&&!pushedacc){
+	if(optsize||(regs[t1]&&regs[t2]&&regs[t3]&&regs[t4])){
+	  emit(f,"\tpha\n");
+	  pushedacc=-1;
+	}else{
+	  r=get_reg(f,p,CHAR);
+	  emit(f,"\tsta\t%s\n",mregnames[r]);
+	  pushedacc=r;
+	}
+      }
+    }
+  }else{
+    if(1/*!isreg(q1)||p->q1.reg!=rax*/){
+      if((regs[ra]||regs[rax])&&(!scratch(p,ra)||!scratch(p,rax))&&!pushedacc){
+	r=get_reg(f,p,CHAR);
+	emit(f,"\tsta\t%s\n",mregnames[r]);
+	pushedacc=r;
+      }
+      if((regs[rx]||regs[rax])&&!scratch(p,rax)&&!pushedx){
+	r=get_reg(f,p,CHAR);
+	emit(f,"\tstx\t%s\n",mregnames[r]);
+	pushedx=r;
+      }
+    }
+  }
+}
+
+static int cmp_get_acc(FILE *f,IC *p,IC *branch)
+{
+  if(!regs[ra]&&!regs[rax])
+    return 0;
+  if(branch==0&&pushedacc)
+    return 0;
+  if(branch&&isreg(q1)&&(p->q1.reg==ra||p->q1.reg==rax))
+    if(branch->code==BEQ||branch->code==BNE||(p->typf&UNSIGNED))
+      return 0;
+  if(scratch(p,ra))
+    return 0;
+  if(!regs[rx]&&!regs[rax]){
+    emit(f,"\ttax\n");
+    pushedacc=rx;
+  }
+  emit(f,"\tpha\n");
+  pushedacc=-1;
+  return pushedacc;
+}
+
+static void reload_acc_opt(FILE *f,IC *p)
+{
+  if(pushedacc==0) return;
+  if(pushedacc>0){
+    while(p){
+      if(p->code!=FREEREG) break;
+      if(p->q1.reg==ra||p->q1.reg==rax){
+	pushedacc=0;
+	return;
+      }
+      p=p->next;
+    }
+  }
+  if(pushedacc==-1)
+    emit(f,"\tpla\n");
+  else if(pushedacc==rx)
+    emit(f,"\ttxa\n");
+  else if(pushedacc==ry)
+    emit(f,"\ttya\n");
+  else if(pushedacc){
+    emit(f,"\tlda\t%s\n",mregnames[pushedacc]);
+    regs[pushedacc]&=~8;
+  }
+  pushedacc=0;
+}
+
+static void reload_acc(FILE *f)
+{
+  reload_acc_opt(f,0);
+}
+
+static void push(int i)
+{
+  pushed-=i;
+  if(pushed<maxpushed)
+    maxpushed=pushed;
+}
+
+static void pop(int i)
+{
+  pushed+=i;
+  if(pushed>0) ierror(0);
+}
+
+static int indirect(obj *o)
+{
+  if((o->flags&(DREFOBJ|KONST))==DREFOBJ)
+    return 1;
+  if((o->flags&(REG|VAR))!=VAR){
+    if(o->reg==ra||ISIDX(o->reg)||o->reg==rax)
+      return 1;
+    return 0;
+  }
+  if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)
+    return 1;
+  return 0;
+}
+
+void convfloat(void)
+{
+}  
+
+void sety(FILE *f,int val)
+{
+  if(yval==val)
+    return;
+  if(val-yval==1)
+    emit(f,"\tiny\n");
+  else if(yval-val==1)
+    emit(f,"\tdey\n");
+  else{
+    emit(f,"\tldy\t#%d\n",val);
+    if(val<0||val>255)
+      ierror(0);
+  }
+  yval=val;
+}
+
+static void cnv_fp(void)
+{
+  double d,mant;
+  int exp;
+  unsigned long t;
+
+  if(ieee){
+    vfloat=zld2zf(vldouble);
+    memcpy((void*)&vmax,(void*)&vfloat,4);
+  }else{
+    d=zld2d(vldouble);
+    mant=frexp(d,&exp);
+    exp=(exp+127)&255;
+    t=((unsigned long)(mant*8388608))&0xffffff;
+    t|=((long)exp)<<24;
+    
+    t=((t&0xff)<<24)|((t&0xff00)<<8)|((t&0xff0000)>>8)|((t&0xff000000)>>24);
+    vmax=l2zm((long)t);
+    if(mant==0&&d==0) vmax=Z0;
+  }
+}
+
+static void emit_ieee(FILE *f,union atyps *p,int t)
+{
+  unsigned char *ip=(unsigned char *)&p->vdouble;
+  emit(f,"0x%02x%02x,0x%02x%02x",ip[1],ip[0],ip[3],ip[2]);
+  if(t==DOUBLE||t==LDOUBLE)
+    emit(f,",0x%02x%02x,0x%02x%02x",ip[5],ip[4],ip[7],ip[6]);
+  emit(f,"\n");
+}
+
+static void emit_lobyte(FILE *f,obj *o,int t)
+{
+  if(o->flags&KONST){
+    if(o->flags&DREFOBJ){
+      eval_const(&o->val,o->dtyp);
+       emit(f,"%d",zm2l(vmax));
+    }else{
+      eval_const(&o->val,t);
+      if(ISFLOAT(t)) cnv_fp();
+      emit(f,"#%d",zm2l(vmax)&255);
+    }
+  }else if(o->flags&VARADR){
+    emit(f,"#<(");
+    emit_obj(f,o,t);
+    emit(f,")");
+  }else if((o->flags&(REG|DREFOBJ))==REG){
+    if(!reg_pair(o->reg,&rp))
+      emit(f,"%s",mregnames[o->reg]);
+    else
+      emit(f,"%s",mregnames[rp.r1]);
+  }else{
+    if(c02&&(o->flags&(DREFOBJ|KONST))==DREFOBJ) noy=1;
+    emit_obj(f,o,t);
+    noy=0;
+  }
+}
+
+static void emit_hibyte(FILE *f,obj *o,int t)
+{
+  if(o->flags&KONST){
+    if(o->flags&DREFOBJ){
+      eval_const(&o->val,o->dtyp);
+      emit(f,"%d",zm2l(vmax)+1);
+    }else{
+      eval_const(&o->val,t);
+      if(ISFLOAT(t)) cnv_fp();
+      emit(f,"#%d",(zm2l(vmax)>>8)&255);
+    }
+  }else if(o->flags&VARADR){
+    emit(f,"#>(");
+    emit_obj(f,o,t);
+    emit(f,")");
+  }else if((o->flags&(REG|DREFOBJ))==REG){
+    if(o->reg>=FIRST_BIG&&o->reg<=LAST_BIGP){
+      emit(f,"%s+1",mregnames[o->reg]);
+    }else{
+      if(!reg_pair(o->reg,&rp))
+	ierror(0);
+      emit(f,"%s",mregnames[rp.r2]);
+    }
+  }else{
+    if(o->flags&VARADR)
+      emit(f,"#");
+    if(!(o->flags&DREFOBJ))
+      o->val.vmax=zmadd(o->val.vmax,Z1);
+    emit_obj(f,o,t);
+    if(!(o->flags&DREFOBJ))
+      o->val.vmax=zmsub(o->val.vmax,Z1);
+  }
+}
+
+static void emit_byte3(FILE *f,obj *o,int t)
+{
+  if(o->flags&KONST){
+    if(o->flags&DREFOBJ){
+      eval_const(&o->val,o->dtyp);
+      emit(f,"%d",zm2l(vmax)+2);
+    }else{
+      eval_const(&o->val,t);
+      if(ISFLOAT(t)) cnv_fp();
+      emit(f,"#%d",(zm2l(vmax)>>16)&255);
+    }
+  }else if((o->flags&(REG|DREFOBJ))==REG){
+    emit(f,"%s+2",mregnames[o->reg]);
+  }else if(o->flags&VARADR){
+    emit(f,"#%d",bank(o->v));
+  }else{
+    if(!(o->flags&DREFOBJ))
+      o->val.vmax=zmadd(o->val.vmax,l2zm(2L));
+    emit_obj(f,o,t);
+    if(!(o->flags&DREFOBJ))
+      o->val.vmax=zmsub(o->val.vmax,l2zm(2L));
+  }
+}
+
+static void emit_byte4(FILE *f,obj *o,int t)
+{
+  if(o->flags&KONST){
+    if(o->flags&DREFOBJ){
+      eval_const(&o->val,o->dtyp);
+      emit(f,"%d",zm2l(vmax)+3);
+    }else{
+      eval_const(&o->val,t);
+      if(ISFLOAT(t)) cnv_fp();
+      emit(f,"#%d",(zm2l(vmax)>>24)&255);
+    }
+  }else if((o->flags&(REG|DREFOBJ))==REG){
+    emit(f,"%s+3",mregnames[o->reg]);
+  }else{
+    if(!(o->flags&DREFOBJ))
+      o->val.vmax=zmadd(o->val.vmax,l2zm(3L));
+    emit_obj(f,o,t);
+    if(!(o->flags&DREFOBJ))
+      o->val.vmax=zmsub(o->val.vmax,l2zm(3L));
+  }
+}
+
+static void do_lobyte(FILE *f,char *s,obj *o,int type)
+{
+  if(o->am){
+    if(o->am->flags==IMM_IND)
+      sety(f,o->am->offset);
+    else if(o->am->flags==GPR_IND||o->am->flags==ABS_IND){
+      if(o->am->idx==ra)
+	emit(f,"\ttay\n");
+      else{
+	if(ISIDX(o->am->idx)){
+	  if(o->am->flags==GPR_IND){
+	    emit(f,"\tpha\n");
+	    emit(f,"\tt%sa\n",mregnames[o->am->idx]);
+	    emit(f,"\ttay\n");
+	    emit(f,"\tpla\n");
+	  }
+	}else
+	  emit(f,"\tldy\t%s\n",mregnames[o->am->idx]);
+      }
+      yval=NOVAL;
+    }else
+      ierror(0);
+  }else if((o->flags&(DREFOBJ|KONST))==DREFOBJ){
+    if(!c02) sety(f,0);
+  }else if((o->flags&(VAR|REG|VARADR))==VAR&&(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)){
+    sety(f,(int)real_offset(o));
+  }
+  emit(f,"\t%s\t",s);
+  emit_lobyte(f,o,type);
+  emit(f,"\n");
+}
+
+static void do_hibyte(FILE *f,char *s,obj *o,int type)
+{
+  int ami=0;
+  if(o->am){
+    if(o->am->flags==IMM_IND)
+      sety(f,o->am->offset+1);
+    else if(o->am->flags==ABS_IND){
+      if(o->am->offset==ra)
+	emit(f,"\ttay\n");
+      else
+	emit(f,"\tldy\t%s\n",mregnames[o->am->idx]);
+      o->am->offset++;ami=1;
+      yval=NOVAL;
+    }else
+      ierror(0);
+  }else  if((o->flags&(DREFOBJ|KONST))==DREFOBJ){
+    sety(f,1);
+  }else if((o->flags&(VAR|REG|VARADR))==VAR&&(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)){
+    sety(f,(int)real_offset(o)+1);
+  }
+  emit(f,"\t%s\t",s);
+  emit_hibyte(f,o,type);
+  emit(f,"\n");
+  if(ami) o->am->offset--;
+}
+
+static void do_byte3(FILE *f,char *s,obj *o,int type)
+{
+  int ami=0;
+  if(o->am){
+    if(o->am->flags==IMM_IND)
+      sety(f,o->am->offset+2);
+    else if(o->am->flags==ABS_IND){
+      if(o->am->offset==ra)
+	emit(f,"\ttay\n");
+      else
+	emit(f,"\tldy\t%s\n",mregnames[o->am->idx]);
+      yval=NOVAL;
+      o->am->offset+=2;ami=1;
+    }else
+      ierror(0);
+  }else  if((o->flags&(DREFOBJ|KONST))==DREFOBJ){
+    sety(f,2);
+  }else if((o->flags&(VAR|REG|VARADR))==VAR&&(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)){
+    sety(f,(int)real_offset(o)+2);
+  }
+  emit(f,"\t%s\t",s);
+  emit_byte3(f,o,type);
+  emit(f,"\n");
+  if(ami) o->am->offset-=2;
+}
+
+static void do_byte4(FILE *f,char *s,obj *o,int type)
+{
+  int ami=0;
+  if(o->am){
+    if(o->am->flags==IMM_IND)
+      sety(f,o->am->offset+3);
+    else if(o->am->flags==ABS_IND){
+      if(o->am->offset==ra)
+	emit(f,"\ttay\n");
+      else
+	emit(f,"\tldy\t%s\n",mregnames[o->am->idx]);
+      yval=NOVAL;
+      o->am->offset+=3;ami=1;
+    }else
+      ierror(0);
+  }else  if((o->flags&(DREFOBJ|KONST))==DREFOBJ){
+    sety(f,3);
+  }else if((o->flags&(VAR|REG|VARADR))==VAR&&(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)){
+    sety(f,(int)real_offset(o)+3);
+  }
+  emit(f,"\t%s\t",s);
+  emit_byte4(f,o,type);
+  emit(f,"\n");
+  if(ami) o->am->offset-=3;
+}
+
+static void load_lobyte(FILE *f,obj *o,int t)
+{
+  if((o->flags&(REG|DREFOBJ))==REG){
+    if(o->reg==ra||o->reg==rax)
+      return;
+    if(o->reg==rx){
+      emit(f,"\ttxa\n");
+      return;
+    }
+  }
+  do_lobyte(f,"lda",o,t);
+}
+
+static void load_hibyte(FILE *f,obj *o,int t)
+{
+  if((o->flags&REG)&&(o->reg==rx||o->reg==rax))
+    emit(f,"\ttxa\n");
+  else
+    do_hibyte(f,"lda",o,t);
+}
+
+static void store_lobyte(FILE *f,obj *o,int t)
+{
+  if((o->flags&(REG|DREFOBJ))==REG){
+    if(o->reg==ra||o->reg==rax)
+      return;
+    if(o->reg==rx){
+      emit(f,"\ttax\n");
+      return;
+    }
+  }
+  do_lobyte(f,"sta",o,t);
+}
+
+static void store_hibyte(FILE *f,obj *o,int t)
+{
+  if((o->flags&REG)&&(o->reg==rx||o->reg==rax))
+    emit(f,"\ttax\n");
+  else
+    do_hibyte(f,"sta",o,t);
+}
+
+static void load_acc(FILE *f,obj *o,int type)
+{
+  if((o->flags&REG)&&(o->reg==ra||o->reg==rax))
+    return;
+  if(!ISCHAR(type)){
+    if(indirect(o)){
+      do_hibyte(f,"lda",o,type);
+      emit(f,"\ttax\n");
+    }else
+      do_hibyte(f,"ldx",o,type);
+  }
+  if((o->flags&(REG|DREFOBJ))==REG&&o->reg==rx)
+    emit(f,"\ttxa\n");
+  else
+    do_lobyte(f,"lda",o,type);
+}
+
+static void store_acc(FILE *f,obj *o,int type)
+{
+  if((o->flags&(DREFOBJ|KONST))==DREFOBJ&&((!(o->flags&REG))||!isptr(o->reg))){
+    ierror(0);
+  }
+  if((o->flags&REG)&&(o->reg==ra||o->reg==rax))
+    return;
+  if((o->flags&REG)&&o->reg==rx){
+    emit(f,"\ttax\n");
+    return;
+  }
+  store_lobyte(f,o,type);
+  if(!ISCHAR(type)){
+    if(indirect(o)){
+      /*TODO: save accu */
+      emit(f,"\ttxa\n");
+      store_hibyte(f,o,type);
+    }else
+      do_hibyte(f,"stx",o,type);
+  }
+}
+
+static void load_reg(FILE *f,int r,struct obj *o,int type)
+{
+  static obj ro;
+  if(ISIDX(r)&&!indirect(o)){
+    static char ldr[4]="ldr";
+    ldr[2]=mregnames[r][0];
+    do_lobyte(f,ldr,o,type);
+    return;
+  }
+  ro.flags=REG;
+  ro.reg=r;
+  load_lobyte(f,o,type);
+  store_lobyte(f,&ro,type);
+  if(!ISCHAR(type)){
+    load_hibyte(f,o,type);
+    store_hibyte(f,&ro,type);
+  }
+}
+
+static void store_reg(FILE *f,int r,struct obj *o,int type)
+{
+  static obj ro;
+  if(ISIDX(r)){
+    if((o->flags&(REG|DREFOBJ))==REG){
+      if(o->reg==r)
+	return;
+      if(o->reg==ra){
+	emit(f,"\tt%sa\n",mregnames[r]);
+	return;
+      }
+    }
+    if(!indirect(o)){
+      static char str[4]="str";
+      str[2]=mregnames[r][0];
+      do_lobyte(f,str,o,type);
+      return;
+    }
+  }
+  ro.flags=REG;
+  ro.reg=r;
+  if(r!=ra&&r!=rax)
+    load_acc(f,&ro,type);
+  store_acc(f,o,type);
+}
+
+static struct fpconstlist {
+  struct fpconstlist *next;
+  int label;
+  int t;
+  union atyps val;
+} *firstfpc;
+
+static int addfpconst(struct obj *o,int t)
+{
+  struct fpconstlist *p=firstfpc;
+  t&=NQ;
+  if(t==LDOUBLE) t=DOUBLE;
+  for(p=firstfpc;p;p=p->next){
+    if(t==p->t){
+      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==LONG&&zmeqto(vmax,zl2zm(o->val.vlong))) return p->label;
+      if(t==LLONG&&zmeqto(vmax,zll2zm(o->val.vllong))) return p->label;
+    }
+  }
+  p=mymalloc(sizeof(struct fpconstlist));
+  p->next=firstfpc;
+  p->t=t;
+  p->label=++label;
+  p->val=o->val;
+  firstfpc=p;
+  return p->label;
+}
+
+/* generate code to load the address of a local variable into register r */
+static void load_laddr(FILE *f,int r,struct obj *o)
+{
+  long l=real_offset(o);
+  /* assumes acc is available */
+  if(!reg_pair(r,&rp)) ierror(0);
+  emit(f,"\tlda\t%s\n",mregnames[fp]);
+  if(l!=0)
+    emit(f,"\tclc\n");
+  if(l&255)
+    emit(f,"\tadc\t#%ld\n",l&255);
+  emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
+  emit(f,"\tlda\t%s\n",mregnames[fp2]);
+  if(l!=0)
+    emit(f,"\tadc\t#%ld\n",(l>>8)&255);
+  emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
+}
+
+/* generate code to load the address of a variable into register r */
+static void load_address(FILE *f,int r,struct obj *o,int t)
+{
+  if(o->flags&DREFOBJ){
+    o->flags&=~DREFOBJ;
+    load_reg(f,r,o,POINTER);
+    o->flags|=DREFOBJ;
+  }else if((o->flags&(REG|DREFOBJ))==REG){
+    if(!reg_pair(r,&rp)) ierror(0);
+    emit(f,"\tlda\t#>%s\n",mregnames[o->reg]);
+    emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
+    emit(f,"\tlda\t#<%s\n",mregnames[o->reg]);
+    emit(f,"\tsta\t%s\n",mregnames[rp.r1]);    
+  }else if(o->flags&VAR){
+    if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER){
+      load_laddr(f,r,o);
+    }else{
+      o->flags|=VARADR;
+      load_reg(f,r,o,POINTER);
+      o->flags&=~VARADR;
+    }
+  }else if((o->flags&(KONST|DREFOBJ))==KONST){
+    int l=addfpconst(o,t);
+    if(!ieee) ierror(0);
+    if(!reg_pair(r,&rp)) ierror(0);
+    emit(f,"\tlda\t#>%s%d\n",labprefix,l);
+    emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
+    emit(f,"\tlda\t#<%s%d\n",labprefix,l);
+    emit(f,"\tsta\t%s\n",mregnames[rp.r1]);    
+  }else
+    ierror(0);
+}
+
+
+/*  Yields log2(x)+1 or 0. */
+static long pof2(zumax x)
+{
+  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 incmem(FILE *f,obj *o,int t,int op,int x)
+{
+  int i,idx=0;
+  char *s;
+  if((o->flags&(REG|DREFOBJ))==REG&&ISIDX(o->reg)){
+    static char buf[4]="   ";
+    idx=1;s=buf;
+    if(op==ADD){s[0]='i';s[1]='n';}else{s[0]='d';s[1]='e';}
+    s[2]=mregnames[o->reg][0];
+  }else if(op==ADD)
+    s="inc";
+  else if(op==SUB)
+    s="dec";
+  else if(op==LSHIFT)
+    s="asl";
+  else if(op==RSHIFT&&(t&UNSIGNED))
+    s="clc\n\tror";
+  else if(op==RSHIFT){
+    s="cmp\t#128\n\tror";
+  }else
+    ierror(0);
+  if(ISCHAR(t)){
+    for(i=0;i<x;i++){
+      if(idx){
+	emit(f,"\t%s\n",s);
+      }else{
+	emit(f,"\t%s\t",s);
+	emit_obj(f,o,t);
+	emit(f,"\n");
+      }
+    }
+  }else{
+    for(i=0;i<x;i++){
+      if(op==SUB){
+	/* caller mus make sure accu is available */
+	load_lobyte(f,o,t);
+	emit(f,"\tbne\t%s%d\n",labprefix,++label);
+	emit(f,"\tdec\t");
+	emit_hibyte(f,o,t);
+	emit(f,"\n");
+	emit(f,"%s%d:\n",labprefix,label);
+	emit(f,"\tdec\t");
+	emit_lobyte(f,o,t);
+	emit(f,"\n");	
+      }else if(op==ADD){
+	emit(f,"\t%s\t",s);
+	emit_lobyte(f,o,t);
+	emit(f,"\n");
+	emit(f,"\tbne\t%s%d\n",labprefix,++label);
+	emit(f,"\t%s\t",s);
+	emit_hibyte(f,o,t);
+	emit(f,"\n");
+	emit(f,"%s%d:\n",labprefix,label);
+      }else if(op==LSHIFT){
+	// 4510 / 45GS02 have ASW/ROW operations
+	// for left-shifting 16-bit values
+	
+	emit(f,"\tasw\t");
+	emit_obj(f,o,t);
+	emit(f,"\n");
+
+      }else if(op==RSHIFT&&(t&UNSIGNED)){
+	emit(f,"\tclc\n");
+	emit(f,"\tror\t");
+	emit_hibyte(f,o,t);
+	emit(f,"\n");
+	emit(f,"\tror\t");
+	emit_lobyte(f,o,t);
+	emit(f,"\n");
+      }else if(op==RSHIFT){
+	load_hibyte(f,o,t);
+	emit(f,"\tcmp\t#128\n");
+	emit(f,"\tror\t");
+	emit_hibyte(f,o,t);
+	emit(f,"\n");
+	emit(f,"\tror\t");
+	emit_lobyte(f,o,t);
+	emit(f,"\n");	
+      }else{
+	printf("op=%d\n",op);
+	ierror(0);
+      }
+    }
+  }
+}
+
+static void preload_obj(FILE *f,IC *p,obj *o)
+{
+  int r;long of;
+
+  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");
+
+
+  if((o->flags&(VAR|REG))==VAR&&(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)&&(of=real_offset(o))+zm2l(szof(o->v->vtyp))>255){
+    r=get_reg(f,p,POINTER);
+    if(o->flags&DREFOBJ)
+      get_acc(f,p,INT);
+    else
+      cmp_get_acc(f,p,0);
+    if(!reg_pair(r,&rp)) ierror(0);
+    emit(f,"\tlda\t%s\n",mregnames[fp1]);
+    emit(f,"\tclc\n");
+    if(of&0xff)
+      emit(f,"\tadc\t#%ld\n",of&0xff);
+    emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
+    emit(f,"\tlda\t%s\n",mregnames[fp2]);
+    if(1/*of&0xff00*/)
+      emit(f,"\tadc\t#%ld\n",(of>>8)&0xff);
+    emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
+    o->flags|=REG;
+    o->reg=r;
+    if(o->flags&DREFOBJ){
+      if(!c02) sety(f,0);
+      emit(f,"\tlda\t(%s)%s\n",mregnames[r],c02?"":",y");
+      emit(f,"\ttxa\n");
+      sety(f,1);
+      emit(f,"\tlda\t(%s),y\n",mregnames[r]);
+      emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
+      emit(f,"\tstx\t%s\n",mregnames[rp.r1]);
+    }else{
+      o->flags|=DREFOBJ;
+      o->dtyp=POINTER;
+    }
+  }
+
+  if((o->flags&(DREFOBJ|KONST))==DREFOBJ&&(!(o->flags&REG)||!isptr(o->reg))&&(!(o->flags&VAR)||!(o->v->tattr&ZPAGE))&&!ISFPOINTER(o->dtyp)){
+    cmp_get_acc(f,p,0);
+    r=get_reg(f,p,POINTER);
+    o->flags&=~DREFOBJ;
+    load_reg(f,r,o,POINTER);
+    o->flags|=REG|DREFOBJ;
+    o->reg=r;
+  }
+}
+
+static void far_copy(FILE *f,IC *p)
+{
+  int b;long l;
+  get_acc(f,p,INT);
+  if(p->code==PUSH){
+    if(!reg_pair(LAST_PAIR,&rp)) ierror(0);
+    emit(f,"\tlda\t%s\n",mregnames[sp]);
+    if(pushed) emit(f,"\tclc\n");
+    if(pushed&0xff) emit(f,"\tadc\t#%d\n",(pushed&0xff));
+    emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
+    emit(f,"\tlda\t%s+1\n",mregnames[sp]);
+    if(pushed) emit(f,"\tadc\t#%d\n",((pushed>>8)&0xff));
+    emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
+    pushed+=zm2l(p->q2.val.vmax);
+    emit(f,"\tldx\t#%d\n",bankcnum);
+  }else if(p->z.flags&DREFOBJ){
+    if(!reg_pair(LAST_PAIR,&rp)) ierror(0);
+    p->z.flags&=~DREFOBJ;
+    load_lobyte(f,&p->z,FPOINTER);
+    emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
+    load_hibyte(f,&p->z,FPOINTER);
+    emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
+    if(indirect(&p->z)){
+      do_byte3(f,"lda",&p->z,FPOINTER);
+      emit(f,"\ttax\n");
+    }else
+      do_byte3(f,"ldx",&p->z,FPOINTER);
+  }else{
+    load_address(f,LAST_PAIR,&p->z,POINTER);
+    b=bank(p->z.v);
+    emit(f,"\tldx\t#%d\n",b>=0?b:bankcnum);
+  }
+  if(p->q1.flags&DREFOBJ){
+    if(!reg_pair(LAST_PAIR-1,&rp)) ierror(0);
+    p->q1.flags&=~DREFOBJ;
+    load_lobyte(f,&p->q1,FPOINTER);
+    emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
+    load_hibyte(f,&p->q1,FPOINTER);
+    emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
+    if(indirect(&p->q1)){
+      do_byte3(f,"lda",&p->q1,FPOINTER);
+      emit(f,"\ttay\n");
+    }else
+      do_byte3(f,"ldy",&p->q1,FPOINTER);
+  }else{
+    load_address(f,LAST_PAIR-1,&p->q1,POINTER);
+    b=bank(p->q1.v);
+    sety(f,b>=0?b:bankcnum);
+  }
+  l=zm2l(p->q2.val.vmax);
+  emit(f,"\tlda\t#%d\n",(l>>8)&0xff);
+  emit(f,"\tsta\t%s__bankcopy_len+1\n",idprefix);
+  emit(f,"\tlda\t#%d\n",(l)&0xff);
+  emit(f,"\tsta\t%s__bankcopy_len\n",idprefix);
+  emit(f,"\tlda\t#%d\n",cbank>=0?cbank:bankcnum);
+  emit(f,"\tjsr\t%s__bankcopy\n",idprefix);
+  yval=NOVAL;
+}
+
+static void load_far(FILE *f,IC *p,obj *o,int t)
+{
+  int pushed=0;
+  if(!(o->flags&DREFOBJ)) ierror(0);
+  o->flags&=~DREFOBJ;
+  t&=NQ;
+  if(zmeqto(sizetab[t],Z0)) return;
+  /*get_acc(f,p,INT);*/
+  if(pushedacc==t3||pushedacc==t4) ierror(0);
+  if(pushedx==t3||pushedx==t4) ierror(0);
+  if(regs[ra]||regs[rax]){
+    if(isacc(q1)||isacc(q2)||!isacc(z)){
+      pushed=1;
+      emit(f,"\tpha\n");
+      if(regs[rax]) emit(f,"\ttxa\n\tpha\n");
+    }
+  }
+  load_reg(f,LAST_PAIR,o,POINTER);
+  if(!indirect(o))
+    do_byte3(f,"ldy",o,CHAR);
+  else{
+    do_byte3(f,"lda",o,CHAR);
+    emit(f,"\ttay\n");
+  }
+  emit(f,"\tldx\t#%d\n",bankvoffset);
+  emit(f,"\tlda\t#%d\n",cbank>=0?cbank:bankcnum);
+  emit(f,"\tjsr\t%s__bankload%d\n",idprefix,(int)zm2l(sizetab[t]));
+  yval=NOVAL;
+  o->flags=VAR;
+  o->v=&bankv;
+  o->val.vmax=l2zm((long)bankvoffset);
+  bankvoffset+=zm2l(sizetab[t]);
+  if(pushed){
+    if(regs[rax]) emit(f,"\tpla\n\ttax\n");
+    emit(f,"\tpla\n");
+  }
+}
+
+static void load_banked(FILE *f,IC *p,obj *o,int t)
+{
+  int pushed=0,m;
+  if(o->flags&DREFOBJ) t=o->dtyp;
+  t&=NQ;
+  if(zmeqto(sizetab[t],Z0)) return;
+  /*get_acc(f,p,INT);*/
+  if(pushedacc==t3||pushedacc==t4) ierror(0);
+  if(pushedx==t3||pushedx==t4) ierror(0);
+  if(regs[ra]||regs[rax]){
+    if(isacc(q1)||isacc(q2)||!isacc(z)){
+      pushed=1;
+      emit(f,"\tpha\n");
+      if(regs[rax]||regs[rx]) emit(f,"\ttxa\n\tpha\n");
+    }
+  }
+  m=o->flags;
+  o->flags&=~DREFOBJ;
+  load_address(f,LAST_PAIR,o,POINTER);
+  o->flags=m;
+  emit(f,"\tldx\t#%d\n",bankvoffset);
+  emit(f,"\tlda\t#%d\n",cbank>=0?cbank:bankcnum);
+  sety(f,bank(o->v));
+  emit(f,"\tjsr\t%s__bankload%d\n",idprefix,(int)zm2l(sizetab[t]));
+  yval=NOVAL;
+  o->v=&bankv;
+  o->val.vmax=l2zm((long)bankvoffset);
+  bankvoffset+=zm2l(sizetab[t]);
+  if(pushed){
+    if(regs[rax]||regs[rx]) emit(f,"\tpla\n\ttax\n");
+    emit(f,"\tpla\n");
+  }
+}
+
+static void preload(FILE *f,IC *p)
+{
+  int r,mra=regs[ra],mrax=regs[rax];
+  int bq1=-1,bq2=-1,bz=-1,sb=-1,zbuf=0;
+
+  if(p->code==GETRETURN&&p->q1.reg==ra&&!regs[ra])
+    regs[ra]=1;
+
+  if(p->code==GETRETURN&&p->q1.reg==rax&&!regs[rax])
+    regs[rax]=1;
+
+  bankvoffset=0;
+
+  if(!NOBANKVARS){
+    if((p->q1.flags&(VAR|VARADR))==VAR) bq1=bank(p->q1.v);
+    if((p->q2.flags&(VAR|VARADR))==VAR) bq2=bank(p->q2.v);
+    if((p->z.flags&(VAR|VARADR))==VAR) bz=bank(p->z.v);
+
+    if((p->q1.flags&(VAR|VARADR))==(VAR|VARADR)){
+      r=bank(p->q1.v);
+      /*if(r>=0&&r!=cbank) ierror(0);*/
+    }
+    
+    if((p->code==ASSIGN||p->code==PUSH)&&!zmleq(p->q2.val.vmax,l2zm(4L))){
+      if(p->q1.flags&DREFOBJ) preload_obj(f,p,&p->q1);
+      if(p->z.flags&DREFOBJ) preload_obj(f,p,&p->z);
+      return;
+    }
+
+    if(p->code!=CALL){
+      /* TODO: some optimizations possible */
+      if(bq1>=0&&bq1!=cbank){
+	if(cbank<0&&!NOSWITCH)
+	  sb=bq1;
+	else
+	  load_banked(f,p,&p->q1,q1typ(p));
+      }
+      if(bq2>=0&&bq2!=cbank){
+	if((bq2==sb||(cbank<0&&sb<0))&&!NOSWITCH)
+	  sb=bq2;
+	else
+	  load_banked(f,p,&p->q2,q2typ(p));
+      }
+      if(bz>=0&&bz!=cbank&&(p->z.flags&DREFOBJ)){
+	if((bz==sb||(cbank<0&&sb<0))||!NOSWITCH)
+	  sb=bz;
+	else
+	  load_banked(f,p,&p->z,ztyp(p));
+      }
+      
+      if(sb>=0){
+	if(NOSWITCH) ierror(0);
+	sety(f,sb);
+	emit(f,"\tjsr\t%s__bankswitch\n",idprefix);
+	yval=NOVAL;
+      }
+    }
+  }
+
+  if((p->q1.flags&DREFOBJ)&&ISFPOINTER(p->q1.dtyp)&&p->code!=CALL) load_far(f,p,&p->q1,q1typ(p));
+  if((p->q2.flags&DREFOBJ)&&ISFPOINTER(p->q2.dtyp)) load_far(f,p,&p->q2,q2typ(p));
+
+  if(isacc(q2)){
+    static obj o;
+    int t=q2typ(p);
+    r=get_reg(f,p,t);
+    o.flags=REG;
+    o.reg=r;
+    store_acc(f,&o,t);
+    p->q2.reg=r;
+  }
+
+  if(p->code!=ADDRESS){
+    preload_obj(f,p,&p->q1);
+    if((p->q1.flags&(DREFOBJ|VAR|REG))==(DREFOBJ|VAR|REG)&&
+       (p->q2.flags&(DREFOBJ|VAR|REG))==(DREFOBJ|VAR)&&
+       p->q1.v==p->q2.v){
+      p->q2.flags|=REG;
+      p->q2.reg=p->q1.reg;
+    }
+    if((p->q1.flags&(DREFOBJ|VAR|REG))==(DREFOBJ|VAR|REG)&&
+       (p->z.flags&(DREFOBJ|VAR|REG))==(DREFOBJ|VAR)&&
+       p->q1.v==p->z.v){
+      p->z.flags|=REG;
+      p->z.reg=p->q1.reg;
+    }
+  }
+
+  preload_obj(f,p,&p->q2);
+  if((p->q2.flags&(DREFOBJ|VAR|REG))==(DREFOBJ|VAR|REG)&&
+     (p->z.flags&(DREFOBJ|VAR|REG))==(DREFOBJ|VAR)&&
+     p->q2.v==p->z.v){
+    p->z.flags|=REG;
+    p->z.reg=p->q1.reg;
+  }
+
+
+  if((p->z.flags&DREFOBJ)&&ISFPOINTER(p->z.dtyp)) zbuf=1;
+  if((p->z.flags&(VAR|DREFOBJ))==VAR){
+    bz=bank(p->z.v);
+    if(bz>=0&&bz!=cbank) zbuf=1;
+  }
+  
+  if(zbuf&&!NOBANKVARS){
+    zstore=p->z;
+    p->z.flags=VAR;
+    p->z.v=&bankv;
+    p->z.val.vmax=l2zm((long)bankvoffset);
+    zstoreflag=1;
+    /*bankvoffset+=zm2l(sizetab[p->typf&NQ]);*/
+  }else{
+    preload_obj(f,p,&p->z);
+
+    if(isreg(z)){
+      r=0;
+      if(p->q1.am&&p->q1.am->base==p->z.reg){
+	r=get_reg(f,p,POINTER);
+	cmp_get_acc(f,p,0);
+	if(!reg_pair(p->q1.am->base,&rp)) ierror(0);
+	if(!reg_pair(r,&rp2)) ierror(0);
+	emit(f,"\tlda\t%s\n",mregnames[rp.r1]);
+	emit(f,"\tsta\t%s\n",mregnames[rp2.r1]);
+	emit(f,"\tlda\t%s\n",mregnames[rp.r2]);
+	emit(f,"\tsta\t%s\n",mregnames[rp2.r2]);
+	p->q1.am->base=p->q1.reg=r;
+      }else if((p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p->q1.reg==p->z.reg){
+	r=get_reg(f,p,POINTER);
+	cmp_get_acc(f,p,0);
+	if(!reg_pair(p->z.reg,&rp)) ierror(0);
+	if(!reg_pair(r,&rp2)) ierror(0);
+	emit(f,"\tlda\t%s\n",mregnames[rp.r1]);
+	emit(f,"\tsta\t%s\n",mregnames[rp2.r1]);
+	emit(f,"\tlda\t%s\n",mregnames[rp.r2]);
+	emit(f,"\tsta\t%s\n",mregnames[rp2.r2]);
+	p->q1.reg=r;
+      }
+      if(p->q2.am&&p->q2.am->base==p->z.reg){
+	if(r==0){
+	  r=get_reg(f,p,POINTER);
+	  cmp_get_acc(f,p,0);
+	  if(!reg_pair(p->q2.am->base,&rp)) ierror(0);
+	  if(!reg_pair(r,&rp2)) ierror(0);
+	  emit(f,"\tlda\t%s\n",mregnames[rp.r1]);
+	  emit(f,"\tsta\t%s\n",mregnames[rp2.r1]);
+	  emit(f,"\tlda\t%s\n",mregnames[rp.r2]);
+	  emit(f,"\tsta\t%s\n",mregnames[rp2.r2]);
+	}
+	p->q2.am->base=p->q2.reg=r;
+      }else if((p->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p->q2.reg==p->z.reg){
+	if(r==0){
+	  r=get_reg(f,p,POINTER);
+	  cmp_get_acc(f,p,0);
+	  if(!reg_pair(p->z.reg,&rp)) ierror(0);
+	  if(!reg_pair(r,&rp2)) ierror(0);
+	  emit(f,"\tlda\t%s\n",mregnames[rp.r1]);
+	  emit(f,"\tsta\t%s\n",mregnames[rp2.r1]);
+	  emit(f,"\tlda\t%s\n",mregnames[rp.r2]);
+	  emit(f,"\tsta\t%s\n",mregnames[rp2.r2]);
+	}
+	p->q2.reg=r;
+      }
+    }
+    if(isacc(z)){
+      if(isacc(q2)){
+	if(p->q2.reg==rax){
+	  r=get_reg(f,p,INT);
+	  if(!reg_pair(r,&rp)) ierror(0);
+	  emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
+	  emit(f,"\tstx\t%s\n",mregnames[rp.r2]);
+	}else{
+	  r=get_reg(f,p,CHAR);
+	  emit(f,"\tsta\t%s\n",mregnames[r]);
+	}
+	p->q2.reg=r;
+	if(isacc(q1))
+	  p->q1.reg=r;
+      }
+    }
+  }     
+ 
+  reload_acc(f);
+
+  regs[ra]=mra;
+  regs[rax]=mrax;
+}
+
+
+/* compare if two objects are the same */
+static int compare_objects(struct obj *o1,struct obj *o2)
+{
+  if((o1->flags&(REG|DREFOBJ))==REG&&(o2->flags&(REG|DREFOBJ))==REG&&o1->reg==o2->reg)
+    return 1;
+  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&REG)||o1->reg==o2->reg){
+        return 1;
+      }
+    }
+  }
+  return 0;
+}
+
+/* save the result (in zreg) into p->z */
+void save_result(FILE *f,struct IC *p)
+{
+  ierror(0);
+}
+
+/* prints an object */
+static void emit_obj(FILE *f,struct obj *p,int t)
+{
+  if(p->am){
+    if(p->am->flags==IMM_IND)
+      emit(f,"(%s),y ;am(%ld)",mregnames[p->am->base],p->am->offset);
+    else if(p->am->flags==GPR_IND)
+      emit(f,"(%s),y ;am(%s)",mregnames[p->am->base],mregnames[p->am->idx]);
+    else if(p->am->flags==ABS_IND){
+      emit(f,"%ld",p->am->offset);
+      if(p->am->v){
+	Var *v=p->am->v;
+	if(v->storage_class==EXTERN)
+	  emit(f,"+%s%s",idprefix,v->identifier);
+	else
+	  emit(f,"+%s%ld",labprefix,zm2l(v->offset));
+      }
+      if(ISIDX(p->am->idx))
+	emit(f,",%s ;am(%s)",mregnames[p->am->idx],mregnames[p->am->idx]);
+      else
+	emit(f,",y ;am(%s)",mregnames[p->am->idx]);
+    }else
+      ierror(0);
+    return;
+  }
+  if((p->flags&(KONST|DREFOBJ))==(KONST|DREFOBJ)){
+    emitval(f,&p->val,p->dtyp&NU);
+    return;
+  }
+  if(p->flags&DREFOBJ) emit(f,"(");
+  if(p->flags&REG){
+    emit(f,"%s",mregnames[p->reg]);
+  }else if(p->flags&VAR) {
+    if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER)
+      emit(f,"(%s),y",mregnames[fp]);
+    else{
+      if(!zmeqto(l2zm(0L),p->val.vmax)){emitval(f,&p->val,MAXINT);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(p->flags&KONST){
+    if(/*ieee&&((t&NQ)==DOUBLE||(t&NQ)==LDOUBLE)*/ISFLOAT(t))
+      emit(f,"%s%d",labprefix,addfpconst(p,t));
+    else
+      emitval(f,&p->val,t&NU);
+  }
+  if(p->flags&DREFOBJ) emit(f,")%s",noy?"":",y");
+}
+
+/*  Test if there is a sequence of FREEREGs containing FREEREG reg.
+    Used by peephole. */
+static int exists_freereg(struct IC *p,int reg)
+{
+  while(p&&(p->code==FREEREG||p->code==ALLOCREG)){
+    if(p->code==FREEREG&&p->q1.reg==reg) return 1;
+    p=p->next;
+  }
+  return 0;
+}
+
+char amode_buff[8192];
+char *render_amode(struct AddressingMode *am)
+{
+  return "(amode: not implemented)";
+}
+
+char val_buff[8192];
+char *render_val(union atyps val)
+{
+  snprintf(val_buff,8192,"(val: %02x...)",
+	   val.vuchar);
+  return val_buff;
+}
+
+char var_buff[8192];
+char *render_var(struct Var *v)
+{
+  if (!v) return "<null>";
+  snprintf(var_buff,8192,"(var id=%s)",v->identifier);
+  return var_buff;
+}
+
+char obj_buff[8192];
+char *render_obj(struct obj o)
+{
+  // XXX Calling render_var() can result in segfaults
+  snprintf(obj_buff,8192,"(flags=%d, reg=%d, dtype=%d, var=%s, amode=%s, val=%s)",
+	   o.flags,o.reg,o.dtyp,"render_var(o.v)",render_amode(o.am),render_val(o.val));
+  return obj_buff;
+}
+
+/* search for possible addressing-modes */
+static void peephole(struct IC *p)
+{
+  int c,c2,r;struct IC *p2;struct AddressingMode *am;
+
+  fprintf(stderr,"peephole() called.\n");
+
+  /*
+    XXX PGS Things to consider adding here:
+    1. Removal of dead loads when we know a register already has loaded the target we want.
+    2. Removal of dead stores to local stack variables that never get read before returning from a function?
+    3. Removal of SP decrement and increment, when no use of local stack is made.
+    4. Promoting stack variables to global variables where it saves time and/or space?
+    5. Using Z as a temporary scratch register for local variables, where it doesn't upset
+       other things?
+  */
+    
+  
+  for(;p;p=p->next){
+    fprintf(stderr,"  Instruction @ %p : ",p);
+    fprintf(stderr,"code=%d, ",p->code);
+    fprintf(stderr,"\n    q1=%s, ",render_obj(p->q1));
+    fprintf(stderr,"\n    q2=%s, ",render_obj(p->q2));
+    fprintf(stderr,"\n    z=%s, ",render_obj(p->z));
+    fprintf(stderr,"\n");
+    
+    c=p->code;
+    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;
+
+    /* Try const(reg) */
+    if((c==ADDI2P||c==SUBIFP)&&isreg(z)&&(p->q2.flags&(KONST|DREFOBJ))==KONST&&!ISFPOINTER(p->typf2)){
+      int base;zmax of;struct obj *o;
+      eval_const(&p->q2.val,p->typf);
+      if(c==SUBIFP) of=zmsub(l2zm(0L),vmax); else of=vmax;
+      if(zmleq(Z0,of)&&zmleq(of,l2zm(255L))){
+	r=p->z.reg;
+	if(isreg(q1)&&isptr(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*/){
+	    int t,mc;
+	    if((c2==ASSIGN|c2==PUSH)&&(p2->typf&NQ)==CHAR&&!zmeqto(p2->q2.val.vmax,Z1))
+	      mc=1;
+	    else
+	      mc=0;
+	    if(!p2->q1.am&&(p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r){
+	      if(o||mc) break;
+	      t=q1typ(p2)&NQ;
+	      if(t>POINTER||ISFLOAT(t)) break;
+	      o=&p2->q1;
+	    }
+	    if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
+	      if(o||mc) break;
+	      t=q2typ(p2)&NQ;
+	      if(t>POINTER||ISFLOAT(t)) break;
+	      o=&p2->q2;
+	    }
+	    if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
+	      if(o||mc) break;
+	      t=ztyp(p2)&NQ;
+	      if(t>POINTER||ISFLOAT(t)) 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(o==&p->q1||o==&p->q2) break;
+	    }
+	    if(m==r){
+	      if(o){
+		o->am=am=mymalloc(sizeof(*am));
+		am->flags=IMM_IND;
+		am->base=base;
+		am->offset=(int)zm2l(of);
+		if(isreg(q1)&&isptr(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];
+		}
+	      }
+	      break;
+	    }
+	    if(c2!=FREEREG&&m==base) break;
+	    continue;
+	  }
+        }
+      }
+    }
+    /* Try reg,reg */
+    if(c==ADDI2P&&(p->typf&NU)==(UNSIGNED|CHAR)&&!ISFPOINTER(p->typf2)&&isreg(q2)&&p->q2.reg!=ra&&isreg(z)&&(isreg(q1)||p->q2.reg!=p->z.reg)){
+      int base,idx,ind;struct obj *o;
+      r=p->z.reg;idx=p->q2.reg;
+      if(isreg(q1)) base=p->q1.reg; else base=r;
+      if((p->q1.flags&VARADR)||(p->q1.flags&(KONST|DREFOBJ))==KONST)
+	ind=0;
+      else
+	ind=1;
+      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||(ind&&(q1typ(p2)&NQ)!=CHAR)) break;
+            o=&p2->q1;
+          }
+          if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
+            if(o||(ind&&(q2typ(p2)&NQ)!=CHAR)) break;
+            o=&p2->q2;
+          }
+          if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
+            if(o||(ind&&(ztyp(p2)&NQ)!=CHAR)) 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->idx=idx;
+	      if(ind){
+		am->flags=GPR_IND;
+		am->base=base;
+		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];
+		}
+	      }else{
+		am->flags=ABS_IND;
+		am->base=0;
+		eval_const(&p->q1.val,MAXINT);
+		am->offset=zm2l(vmax);
+		if(p->q1.flags&VARADR)
+		  am->v=p->q1.v;
+		else
+		  am->v=0;
+		p->code=c=NOP;p->q1.flags=p->q2.flags=p->z.flags=0;
+	      }
+            }
+            break;
+          }
+          if(c2!=FREEREG&&m==base) break;
+          continue;
+        }
+      }
+    }
+  }
+}
+
+static void pr(FILE *f,struct IC *p)
+{
+  int r;
+
+  if(zstoreflag){
+    int off;
+    if(p->z.flags!=VAR||p->z.v!=&bankv) ierror(0);
+    off=(int)zm2l(p->z.val.vmax);
+    p->z=zstore;
+    get_acc(f,p,INT);
+    if(zstore.flags&DREFOBJ){
+      if(!ISFPOINTER(zstore.dtyp)) ierror(0);
+      zstore.flags&=~DREFOBJ;
+      load_reg(f,LAST_PAIR,&zstore,POINTER);
+      if(indirect(&zstore)){
+	do_byte3(f,"lda",&zstore,FPOINTER);
+	emit(f,"\ttay\n");
+      }else
+	do_byte3(f,"ldy",&zstore,FPOINTER);
+      yval=NOVAL;
+    }else{
+      load_address(f,LAST_PAIR,&zstore,p->typf);
+      r=bank(zstore.v);
+      sety(f,r>=0?r:bankcnum);
+    }
+    emit(f,"\tldx\t#%d\n",off);
+    emit(f,"\tlda\t#%d\n",cbank>=0?cbank:bankcnum);
+    emit(f,"\tjsr\t%s__bankstore%d\n",idprefix,(int)zm2l(sizetab[p->typf&NQ]));
+    yval=NOVAL;
+    zstoreflag=0;
+  }
+
+  for(r=1;r<=MAXR;r++){
+    if(regs[r]&8)
+      regs[r]&=~8;
+  }
+  for(r=FIRST_GPR;r<=LAST_GPR;r++){
+    int ta=0;
+    if(regs[r]&2){
+      if(regs[ra]&&!pushedacc){
+	emit(f,"\ttay\n");
+	yval=NOVAL;
+	ta=1;
+      }
+      emit(f,"\tpla\n");
+      emit(f,"\tsta\t%s\n",mregnames[r]);
+      regs[r]&=~2;
+    }
+    if(ta)
+      emit(f,"\ttya\n");
+  }
+  if(pushedx){
+    emit(f,"\tldx\t%s\n",mregnames[pushedx]);
+    pushedx=0;
+  }
+
+  reload_acc_opt(f,p->next);
+}
+
+struct cmplist {struct cmplist *next;int from,to,mode;} *first_cmplist;
+
+static void add_cmplist(int from, int to, int mode)
+{
+  struct cmplist *new;
+  new=mymalloc(sizeof(*new));
+  new->next=first_cmplist;
+  new->from=from;
+  new->to=to;
+  new->mode=mode;
+  first_cmplist=new;
+}
+
+static void incsp(FILE *f,long of)
+{
+  if(of==0) return;
+  if(of==1||of==-1){
+    static obj o;
+    o.flags=REG;
+    o.reg=sp;
+    if(of==1)
+      incmem(f,&o,INT,ADD,1);
+    else
+      incmem(f,&o,INT,SUB,1);
+  }else if(of==256){
+    emit(f,"\tinc\t%s+1\n",mregnames[sp]);
+  }else if(of==-256){
+    emit(f,"\tdec\t%s+1\n",mregnames[sp]);
+  }else{
+    long abs;
+    if(of>0){
+      abs=of;
+      emit(f,"\tclc\n");
+    }else{
+      abs=-of;
+      emit(f,"\tsec\n");
+    }
+    if(abs&255){
+      emit(f,"\tlda\t%s\n",mregnames[sp]);
+      if(of>0){
+	emit(f,"\tadc\t#%ld\n",abs&255);
+      }else{
+	emit(f,"\tsbc\t#%ld\n",abs&255);
+      }
+      emit(f,"\tsta\t%s\n",mregnames[sp]);
+    }
+    if((abs&0xff00)==0){
+      if(of>0){
+	emit(f,"\tbcc\t%s%d\n",labprefix,++label);
+	emit(f,"\tinc\t%s+1\n",mregnames[sp]);
+	emit(f,"%s%d:\n",labprefix,label);
+      }else{
+	emit(f,"\tbcs\t%s%d\n",labprefix,++label);
+	emit(f,"\tdec\t%s+1\n",mregnames[sp]);
+	emit(f,"%s%d:\n",labprefix,label);
+      }	
+    }else{
+      emit(f,"\tlda\t%s+1\n",mregnames[sp]);
+      if(of>0)
+	emit(f,"\tadc\t#%ld\n",(abs>>8)&255);
+      else
+	emit(f,"\tsbc\t#%ld\n",(abs>>8)&255);
+      emit(f,"\tsta\t%s+1\n",mregnames[sp]);
+    }
+  }
+}
+
+/* generates the function entry code */
+static void function_top(FILE *f,struct Var *v,long offset)
+{
+  int i,r,of;
+  rsavesize=0;
+  libsave=1;
+  
+  if(!optsize||(v->tattr&NOCOMPRESS)) emit(f,";vcprmin=10000\n");
+  if(vlas) emit(f,"___fo\tset\t%ld\n",(long)argsize);
+  r=0;
+  for(i=FIRST_GPR;i<=LAST_GPR;i++){
+    if((regused[i]&&(in_isr||!regscratch[i]))||(in_isr&&function_calls&&regscratch[i]&&!regsa[i])){
+      if(i!=LAST_GPR-VOL_GPRS+1&&r==0) libsave=0;
+      rsavesize++;
+      r=1;
+    }else{
+      if(i==LAST_GPR-VOL_GPRS+1) libsave=0;
+      r=0;
+    }
+  }
+  rscnt=rsavesize;
+  if(rscnt&&!SOFTSTACK){
+    if(optspeed||rscnt<2)
+      rsavesize=0;
+    else if(!optsize&&rscnt<=5)
+      rsavesize=0;
+  }
+  
+  if(!special_section(f,v)){emit(f,codename);ebank(f,bank(v));if(f) section=CODE;} 
+  if(v->storage_class==EXTERN){
+    if((v->flags&(INLINEFUNC|INLINEEXT))!=INLINEFUNC)
+      emit(f,"\tglobal\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));
+  
+  offset=localsize+argsize+rsavesize;
+  
+  if(in_isr){
+    emit(f,"\tpha\n");
+    emit(f,"\tphx\n");
+    emit(f,"\tphy\n");
+    emit(f,"\tphz\n");
+    if(offset||function_calls){
+      emit(f,"\tlda\t%s\n",mregnames[sp]);
+      emit(f,"\tpha\n");
+      emit(f,"\tlda\t%s+1\n",mregnames[sp]);
+      emit(f,"\tpha\n");
+      emit(f,"\tlda\t#<(___isrstack-%ld)\n",offset);
+      emit(f,"\tsta\t%s\n",mregnames[sp]);
+      emit(f,"\tlda\t#>(___isrstack-%ld)\n",offset);
+      emit(f,"\tsta\t%s+1\n",mregnames[sp]);
+    }
+  }
+
+  if(MAINARGS&&v->storage_class==EXTERN&&!strcmp(v->identifier,"main")&&v->vtyp->exact->count>1)
+    emit(f,"\tjsr\tinitmainargs\n");
+
+  yval=NOVAL;
+  of=argsize+localsize;
+
+  if(rsavesize>0&&of+rsavesize>255){
+    offset-=rsavesize;
+    incsp(f,-rsavesize);
+    of=0;
+  }else{
+    incsp(f,-offset);
+    offset=0;
+  }
+
+
+  if(!libsave||rscnt!=rsavesize||optspeed||rscnt<=1||(rscnt<=3&&(!optsize)))
+    libsave=0;
+  
+  if(libsave){
+    sety(f,of+rsavesize-1);
+    emit(f,"\tjsr\t%s__rsave%ld\n",idprefix,rscnt);
+    yval=of;
+  }else{
+    for(i=FIRST_GPR;i<=LAST_GPR;i++){
+      if((regused[i]&&(in_isr||!regscratch[i]))||(in_isr&&function_calls&&regscratch[i]&&!regsa[i])){
+	if(rscnt!=rsavesize){
+	  emit(f,"\tlda\t%s\n",mregnames[i]);
+	  emit(f,"\tpha\n");
+	}else{
+	  sety(f,of++);
+	  emit(f,"\tlda\t%s\n",mregnames[i]);
+	  emit(f,"\tsta\t(%s),y\n",mregnames[sp]);
+	}
+      }
+    }
+  }
+
+
+
+  incsp(f,-offset);
+
+  if(vlas){
+    emit(f,"\tlda\t%s\n",mregnames[sp]);
+    emit(f,"\tsta\t%s\n",mregnames[fp]);
+    emit(f,"\tlda\t%s\n",mregnames[sp2]);
+    emit(f,"\tsta\t%s\n",mregnames[fp2]);
+  }
+}
+
+/* generates the function exit code */
+static void function_bottom(FILE *f,struct Var *v,long offset)
+{
+  int i,of,ar;
+  struct cmplist *p;
+  offset=localsize+argsize+rsavesize;
+  of=argsize+localsize;
+
+  i=freturn(v->vtyp->next);
+  if(i==ra||i==rax) ar=1; else ar=0;
+
+  if(rscnt!=rsavesize){
+    if(ar&&!pushedacc){
+      pushedacc=t4;
+      emit(f,"\tsta\t%s\n",mregnames[pushedacc]);
+    }
+    for(i=LAST_GPR;i>=FIRST_GPR;i--){
+      if((regused[i]&&(in_isr||!regscratch[i]))||(in_isr&&function_calls&&regscratch[i]&&!regsa[i])){
+	emit(f,"\tpla\n");
+	emit(f,"\tsta\t%s\n",mregnames[i]);
+      }
+    }
+  }
+  if(rsavesize>0&&of+rsavesize>255){
+    if(of!=1&&ar&&!pushedacc){
+      pushedacc=t4;
+      emit(f,"\tsta\t%s\n",mregnames[pushedacc]);
+    }
+    incsp(f,of);
+    offset-=of;
+    of=0;
+  }
+  if(rsavesize>0){
+    if(ar&&!pushedacc){
+      pushedacc=t4;
+      emit(f,"\tsta\t%s\n",mregnames[pushedacc]);
+    }
+  }
+  if(rsavesize){
+    if(libsave){
+      sety(f,of+rsavesize-1);
+      emit(f,"\tjsr\t%s__rload%ld\n",idprefix,rscnt);
+      yval=of;
+    }else{
+      for(i=FIRST_GPR;i<=LAST_GPR;i++){
+	if((regused[i]&&(in_isr||!regscratch[i]))||(in_isr&&function_calls&&regscratch[i]&&!regsa[i])){
+	  sety(f,of++);
+	  emit(f,"\tlda\t(%s),y\n",mregnames[sp]);
+	  emit(f,"\tsta\t%s\n",mregnames[i]);
+	}
+      }
+    }
+  }
+  if(in_isr){
+    if(offset||function_calls){
+      emit(f,"\tpla\n");
+      emit(f,"\tsta\t%s+1\n",mregnames[sp]);
+      emit(f,"\tpla\n");
+      emit(f,"\tsta\t%s\n",mregnames[sp]);
+    }
+  }else if(offset==2&&!pushedacc){
+    emit(f,"\tinc\t%s\n",mregnames[sp]);
+    emit(f,"\tbeq\t%s%d\n",labprefix,++label);
+    emit(f,"\tinc\t%s\n",mregnames[sp]);
+    emit(f,"\tbeq\t%s%d\n",labprefix,++label);
+    reload_acc(f);
+    emit(f,ret);
+    emit(f,"%s%d:\n",labprefix,label-1);
+    emit(f,"\tinc\t%s\n",mregnames[sp]);
+    emit(f,"%s%d:\n",labprefix,label);
+    emit(f,"\tinc\t%s+1\n",mregnames[sp]);
+  }else{
+    if(offset!=0&&ar&&!pushedacc){
+      pushedacc=t4;
+      emit(f,"\tsta\t%s\n",mregnames[pushedacc]);
+    }
+    incsp(f,offset);
+  }
+
+  reload_acc(f);
+
+  if(in_isr){
+    emit(f,"\tplz\n");
+    emit(f,"\tply\n");
+    emit(f,"\tplx\n");
+    emit(f,"\tpla\n");
+  }
+  emit(f,ret);
+
+  for(p=first_cmplist;p;){
+    struct cmplist *m;
+    emit(f,"%s%d:\n",labprefix,p->from);
+    if(p->mode==JMPIND){
+      /* indirect call */
+      emit(f,"\tjmp\t(%s)\n",mregnames[p->to]);
+    }else{
+      pushedacc=p->mode;
+      reload_acc(f);
+      emit(f,"\t%s\t%s%d\n",jmpinst,labprefix,p->to);
+    }
+    m=p;
+    p=p->next;
+    free(m);
+  }
+  first_cmplist=0;
+  pushedacc=0;
+}
+
+/****************************************/
+/*  End of private data and functions.  */
+/****************************************/
+
+/*  Does necessary initializations for the code-generator. Gets called  */
+/*  once at the beginning and should return 0 in case of problems.      */
+int init_cg(void)
+{
+  int i;
+  /*  Initialize some values which cannot be statically initialized   */
+  /*  because they are stored in the target's arithmetic.             */
+  maxalign=l2zm(1L);
+  char_bit=l2zm(8L);
+  stackalign=l2zm(1);
+
+  if(IEEE){
+    ieee=1;
+    msizetab[DOUBLE]=msizetab[LDOUBLE]=l2zm(8L);
+  }
+
+
+  mregnames[0]=regnames[0]="noreg";
+  for(i=FIRST_GPR;i<=LAST_GPR;i++){
+    regnames[i]=mymalloc(10);
+    sprintf(regnames[i],"r%d",i-FIRST_GPR);
+    mregnames[i]=regnames[i];
+    regsize[i]=l2zm(1L);
+    regtype[i]=&ctyp;
+  }
+  for(i=FIRST_PAIR;i<=LAST_PAIR;i++){
+    int sr=(i-FIRST_PAIR)*2+FIRST_GPR;
+    regnames[i]=mymalloc(10);
+    sprintf(regnames[i],"%s/%s",mregnames[sr],mregnames[sr+1]);
+    mregnames[i]=regnames[sr];
+    regsize[i]=l2zm(2L);
+    regtype[i]=&ityp;
+  }
+  for(i=FIRST_BIG;i<=LAST_BIG;i++){
+    regnames[i]=mymalloc(10);
+    sprintf(regnames[i],"btmp%d",i-FIRST_BIG);
+    mregnames[i]=regnames[i];
+    regsize[i]=msizetab[FLOAT];
+    regtype[i]=&ftyp;
+    regsa[i]=0;
+    regscratch[i]=1;
+  }
+  for(i=FIRST_BIGP;i<=LAST_BIGP;i++){
+    int sr=(i-FIRST_BIGP)*2+FIRST_BIG;
+    regnames[i]=mymalloc(20);
+    sprintf(regnames[i],"%s/%s",mregnames[sr],mregnames[sr+1]);
+    mregnames[i]=regnames[sr];
+    regsize[i]=msizetab[LLONG];
+    regtype[i]=&lltyp;
+    regsa[i]=0;
+    regscratch[i]=1;
+  }
+
+  mregnames[ra] = regnames[ra] = "a";
+  mregnames[rx] = regnames[rx] = "x";
+  mregnames[ry] = regnames[ry] = "y";
+  mregnames[rz] = regnames[rz] = "z";
+  regsize[ra]=regsize[rx]=regsize[ry]=regsize[rz]=l2zm(1L);
+  regtype[ra]=regtype[rx]=regtype[ry]=regtype[rz]=&ctyp;
+  mregnames[sp]=regnames[sp] = "sp";
+  mregnames[sp1]=regnames[sp1] = "sp";
+  mregnames[sp2]=regnames[sp2] = "sp+1";
+
+  mregnames[rax]=regnames[rax] = "ax";
+  regsize[rax]=regsize[sp]=l2zm(2L);
+  regtype[rax]=regtype[sp]=&ityp;
+
+  reg_prio[ra]=reg_prio[rax]=100;
+  reg_prio[rx]=50;
+  reg_prio[rz]=50;
+
+  mregnames[raxyz]=regnames[raxyz] = "axyz";
+  regsize[raxyz]=l2zm(4L);
+  regtype[raxyz]=&ftyp;
+
+  /*  Use multiple ccs.   */
+  multiple_ccs=0;
+
+  short_push=1;
+
+  static_cse=0;
+
+  dref_cse=1;
+
+  /*prefer_statics=1; TODO */
+
+
+  if(optsize){
+    clist_copy_stack=2;
+    clist_copy_pointer=2;
+    clist_copy_static=2;
+  }else if(optspeed){
+    clist_copy_stack=64;
+    clist_copy_pointer=64;
+    clist_copy_static=64;
+  }else{
+    clist_copy_stack=8;
+    clist_copy_pointer=8;
+    clist_copy_static=8;
+  }
+
+  /*  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.          */
+  t_min[CHAR]=l2zm(-128L);
+  t_min[SHORT]=l2zm(-32768L);
+  t_min[LONG]=zmsub(l2zm(-2147483647L),l2zm(1L));
+  t_min[INT]=t_min(SHORT);
+  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[LONG]=ul2zum(2147483647UL);
+  t_max[INT]=t_max(SHORT);
+  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[LONG]=ul2zum(4294967295UL);
+  tu_max[INT]=t_max(UNSIGNED|SHORT);
+  tu_max[LLONG]=zumkompl(ul2zum(0UL));
+  tu_max[MAXINT]=t_max(UNSIGNED|LLONG);
+  
+  /*  Reserve a few registers for use by the code-generator.      */
+  /*  This is not optimal but simple.                             */
+  regsa[raxyz]=regsa[ry]=regsa[sp]=regsa[sp1]=regsa[sp2]=REGSA_NEVER;
+  regsa[t1]=regsa[t2]=regsa[t3]=regsa[t4]=REGSA_NEVER;
+  regscratch[ra]=regscratch[rx]=regscratch[rax]=1;
+  if(!GLOBACC)
+    regsa[ra]=/*regsa[rx]=*/regsa[rax]=REGSA_TEMPS;
+  regscratch[sp]=regscratch[sp1]=regscratch[sp2]=regscratch[ry]=regscratch[rz]=0;
+  regscratch[t1]=regscratch[t2]=regscratch[t3]=regscratch[t4]=1;
+
+  for(i=FIRST_GPR;i<=LAST_GPR-VOL_GPRS;i++){
+    regscratch[i]=1;
+    if(i&1)
+      regscratch[FIRST_PAIR+(i-FIRST_GPR)/2]=1;
+  }
+
+  target_macros=marray;
+
+  declare_builtin("__mulint16",INT,INT,FIRST_PAIR,INT,FIRST_PAIR+1,1,0);
+  declare_builtin("__muluint16",UNSIGNED|INT,UNSIGNED|INT,FIRST_PAIR,UNSIGNED|INT,FIRST_PAIR+1,1,0);
+  declare_builtin("__divuint16",UNSIGNED|INT,UNSIGNED|INT,FIRST_PAIR,UNSIGNED|INT,FIRST_PAIR+1,1,0);
+  declare_builtin("__divint16",INT,INT,FIRST_PAIR,INT,FIRST_PAIR+1,1,0);
+  declare_builtin("__moduint16",UNSIGNED|INT,UNSIGNED|INT,FIRST_PAIR,UNSIGNED|INT,FIRST_PAIR+1,1,0);
+  declare_builtin("__modint16",INT,INT,FIRST_PAIR,INT,FIRST_PAIR+1,1,0);
+
+  declare_builtin("__mulint32",LONG,LONG,FIRST_BIG+1,LONG,FIRST_BIG+2,1,0);
+  declare_builtin("__muluint32",UNSIGNED|LONG,UNSIGNED|LONG,FIRST_BIG+1,UNSIGNED|LONG,FIRST_BIG+2,1,0);
+  declare_builtin("__divint32",LONG,LONG,FIRST_BIG,LONG,FIRST_BIG+1,1,0);
+  declare_builtin("__divuint32",UNSIGNED|LONG,UNSIGNED|LONG,FIRST_BIG,UNSIGNED|LONG,FIRST_BIG+1,1,0);
+  declare_builtin("__modint32",LONG,LONG,FIRST_BIG,LONG,FIRST_BIG+1,1,0);
+  declare_builtin("__moduint32",UNSIGNED|LONG,UNSIGNED|LONG,FIRST_BIG,UNSIGNED|LONG,FIRST_BIG+1,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("__divint64",LLONG,LLONG,0,LLONG,0,1,0);
+  declare_builtin("__divuint64",UNSIGNED|LLONG,UNSIGNED|LLONG,0,UNSIGNED|LLONG,0,1,0);
+  declare_builtin("__modint64",LLONG,LLONG,0,LLONG,0,1,0);
+  declare_builtin("__moduint64",UNSIGNED|LLONG,UNSIGNED|LLONG,0,UNSIGNED|LLONG,0,1,0);
+  declare_builtin("__lsrint64",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("__sint32toflt32",FLOAT,LONG,OLDFP?0:FIRST_BIG,0,0,1,0);
+  declare_builtin("__uint32toflt32",FLOAT,UNSIGNED|LONG,OLDFP?0:FIRST_BIG,0,0,1,0);
+  declare_builtin("__flt32tosint32",LONG,FLOAT,OLDFP?0:FIRST_BIG,0,0,1,0);
+  declare_builtin("__flt32touint32",UNSIGNED|LONG,FLOAT,OLDFP?0:FIRST_BIG,0,0,1,0);
+  declare_builtin("__sint16toflt32",FLOAT,INT,FIRST_PAIR,0,0,1,0);
+  declare_builtin("__uint16toflt32",FLOAT,UNSIGNED|INT,FIRST_PAIR,0,0,1,0);
+  declare_builtin("__flt32tosint16",INT,FLOAT,OLDFP?0:FIRST_BIG,0,0,1,0);
+  declare_builtin("__flt32touint16",UNSIGNED|INT,FLOAT,OLDFP?0:FIRST_BIG,0,0,1,0);
+
+  declare_builtin("__sint32toflt64",DOUBLE,LONG,OLDFP?0:FIRST_BIG,0,0,1,0);
+  declare_builtin("__uint32toflt64",DOUBLE,UNSIGNED|LONG,OLDFP?0:FIRST_BIG,0,0,1,0);
+  declare_builtin("__flt64tosint32",LONG,DOUBLE,OLDFP?0:FIRST_BIGP,0,0,1,0);
+  declare_builtin("__flt64touint32",UNSIGNED|LONG,DOUBLE,OLDFP?0:FIRST_BIGP,0,0,1,0);
+  declare_builtin("__sint16toflt64",DOUBLE,INT,FIRST_PAIR,0,0,1,0);
+  declare_builtin("__uint16toflt64",DOUBLE,UNSIGNED|INT,FIRST_PAIR,0,0,1,0);
+  declare_builtin("__flt64tosint16",INT,DOUBLE,OLDFP?0:FIRST_BIGP,0,0,1,0);
+  declare_builtin("__flt64touint16",UNSIGNED|INT,DOUBLE,OLDFP?0:FIRST_BIGP,0,0,1,0);
+
+  declare_builtin("__flt64toflt32",FLOAT,DOUBLE,OLDFP?0:FIRST_BIGP,0,0,1,0);
+  declare_builtin("__flt32toflt64",DOUBLE,FLOAT,OLDFP?0:FIRST_BIG,0,0,1,0);
+
+  declare_builtin("__addflt32",FLOAT,FLOAT,OLDFP?0:FIRST_BIG+1,FLOAT,OLDFP?0:FIRST_BIG,1,0);
+  declare_builtin("__subflt32",FLOAT,FLOAT,OLDFP?0:FIRST_BIG+1,FLOAT,OLDFP?0:FIRST_BIG,1,0);
+  declare_builtin("__mulflt32",FLOAT,FLOAT,OLDFP?0:FIRST_BIG+1,FLOAT,OLDFP?0:FIRST_BIG,1,0);
+  declare_builtin("__divflt32",FLOAT,FLOAT,OLDFP?0:FIRST_BIG+1,FLOAT,OLDFP?0:FIRST_BIG,1,0);
+  declare_builtin("__negflt32",FLOAT,FLOAT,OLDFP?0:FIRST_BIG,0,0,1,0);
+  declare_builtin("__cmpsflt32",CHAR,FLOAT,OLDFP?0:FIRST_BIG+1,FLOAT,OLDFP?0:FIRST_BIG,1,0);
+
+#if 0
+  for(i=1;i<MAXR;i++){
+    printf("%02d %s scratch=%d ",i,regnames[i],regscratch[i]);
+    if(reg_pair(i,&rp))
+      printf("pair(%s,%s)",regnames[rp.r1],regnames[rp.r2]);
+    printf("\n");
+  }
+#endif
+
+  if(NOPEEP) nopeep=1;
+  if(CBMASCII) cbmascii=1;
+  if(ATASCII) atascii=1;
+  if(C02){
+    c02=1;
+    has_zero_reg=1;
+    has_inc_a=1;
+    jmpinst="bra";
+  }else
+    jmpinst="jmp";
+
+  for(i=0;i<=MAX_TYPE;i++){
+    sizetab[i]=l2zm(msizetab[i]);
+    align[i]=l2zm(malign[i]);
+  }
+
+  bankv.storage_class=EXTERN;
+  bankv.identifier="__bankv";
+  bankv.vtyp=new_typ();
+  bankv.vtyp->flags=CHAR;
+
+  bankcnum=COMMONBANK;
+
+  return 1;
+}
+
+void init_db(FILE *f)
+{
+}
+
+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.        */
+/*  A pointer MUST be returned in a register. The code-generator    */
+/*  has to simulate a pseudo register if necessary.                 */
+{
+  int typ=t->flags&NQ;
+  if(ISSTRUCT(typ)||ISUNION(typ)||typ==VOID) 
+    return 0;
+  if(OLDFP&&ISFLOAT(typ)) return FIRST_GPR;
+  if(typ==LONG||typ==FLOAT||ISFPOINTER(typ)||(!ieee&&(typ==DOUBLE||typ==LDOUBLE)))
+    return FIRST_BIG;
+  if(typ==LLONG||(ieee&&(typ==DOUBLE||typ==LDOUBLE)))
+    return FIRST_BIGP;
+  if(zmleq(szof(t),l2zm(1L)))
+    return ra;
+  if(zmleq(szof(t),l2zm(2L))) 
+    return rax;
+  else
+    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>=FIRST_PAIR&&r<=LAST_PAIR){
+    p->r1=(r-FIRST_PAIR)*2+FIRST_GPR;
+    p->r2=p->r1+1;
+    return 1;
+  }else if(r>=FIRST_BIGP&&r<=LAST_BIGP){
+    p->r1=(r-FIRST_BIGP)*2+FIRST_BIG;
+    p->r2=p->r1+1;
+    return 1;
+  }else if(r==rax){
+    p->r1=ra;
+    p->r2=rx;
+    return 1;
+  }else if(r==raxyz) {
+    // TODO: PGS: How do we declare a reg pair that is made of 4 regs, not 2?
+    return 0;
+  }else if(r==sp){
+    p->r1=sp1;
+    p->r2=sp2;
+    return 1;
+  }
+  return 0;
+}
+
+/* estimate the cost-saving if object o from IC p is placed in
+   register r */
+int cost_savings(struct IC *p,int r,struct obj *o)
+{
+  int c=p->code;
+  if(ISIDX(r)){
+    if(c==ADD||c==SUB||c==ADDI2P||c==SUBIFP){
+      if(o==&p->q2&&c!=ADDI2P) return -2;
+    }else if(c==ASSIGN){
+      if(o==&p->q1&&indirect(&p->z)) return 1;
+      if(o==&p->z&&indirect(&p->q1)) return 1;
+    }else if(c==COMPARE){
+      //if(o==&p->q1&&indirect(&p->q2)) return INT_MIN;
+      //if(o==&p->q2&&indirect(&p->q1)) return INT_MIN;
+    }else if(c==TEST){
+    }else if(c==SETRETURN||c==GETRETURN){
+    }else
+      return INT_MIN;
+  }
+  /*TODO: adapt this */
+  if(o->flags&VKONST){
+    return 0;
+    if(o==&p->q1&&p->code==ASSIGN&&(p->z.flags&DREFOBJ))
+      return 4;
+    else
+      return 2;
+  }
+  if(o->flags&DREFOBJ){
+    if(isptr(r))
+      return 4;
+    if(r==rax)
+      return INT_MIN;
+  }
+  if(c==SETRETURN&&r==p->z.reg&&!(o->flags&DREFOBJ)) return 6;
+  if(c==GETRETURN&&r==p->q1.reg&&!(o->flags&DREFOBJ)) return 6;
+  if(r==ra)
+    return 5;
+  if(ISIDX(r))
+    return 4;
+  if(r==rax)
+    return 2;
+  return 2;
+}
+
+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(r==0)
+    return 0;
+  if(r==rax&&NORAX)
+    return 0;
+  t&=NQ;
+  if(ISCHAR(t))
+    if(r==ra||(ISIDX(r)&&(optflags&2))||(r>=FIRST_GPR&&r<=LAST_GPR))
+      return 1;
+  if(ISSHORT(t)){
+    if(r==rax){
+      if(t==POINTER&&mode<0)
+	return 1;
+      if(t!=POINTER)
+	return 1;
+    }
+    if(r>=FIRST_PAIR&&r<=LAST_PAIR)
+      return 1;
+  }
+  if(r>=FIRST_BIG&&r<=LAST_BIG){
+    if(t==LONG||t==FLOAT||((t==DOUBLE||t==LDOUBLE)&&!ieee))
+      return 1;
+    if(t==FPOINTER)
+      return 1;
+  }
+  if(r>=FIRST_BIGP&&r<=LAST_BIGP){
+    if(t==LLONG||((t==DOUBLE||t==LDOUBLE)&&ieee))
+      return 1;
+  }
+  return 0;
+}
+
+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;
+}
+
+int must_convert(int o,int t,int const_expr)
+/*  Returns zero if code for converting np to type t    */
+/*  can be omitted.                                     */
+/*  On the PowerPC cpu pointers and 32bit               */
+/*  integers have the same representation and can use   */
+/*  the same registers.                                 */
+{
+  int op=o&NQ,tp=t&NQ;
+
+  if(op==tp) return 0;
+  if(ISCHAR(op)&&ISCHAR(tp)) return 0;
+  if(ISSHORT(op)&&ISSHORT(tp)) return 0;
+  if(!ieee&&ISFLOAT(op)&&ISFLOAT(tp)) return 0;
+  if(op==DOUBLE&&tp==LDOUBLE) return 0;
+  if(op==LDOUBLE&&tp==DOUBLE) 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(STDSYNTAX)
+    emit(f,"\tspace\t%ld\n",zm2l(size));
+  else
+    emit(f,"\treserve\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.              */
+{
+  if(zm2l(align)>1) emit(f,"\talign 1\n");
+}
+
+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,b=bank(v);char *sec;
+  if(v->clist) constflag=is_const(v->vtyp);
+  if(v->storage_class==STATIC){
+    if(ISFUNC(v->vtyp->flags)) return;
+    if(v->tattr&ZPAGE)
+      emit(f,"\tzpage\t%s%ld\n",labprefix,zm2l(v->offset));
+    if(!special_section(f,v)){
+      if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))){emit(f,dataname);ebank(f,b);if(f) section=DATA;}
+      if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)){emit(f,rodataname);ebank(f,b);if(f) section=RODATA;}
+      if(!v->clist){emit(f,bssname);ebank(f,b);if(f) section=BSS;}
+    }
+    gen_align(f,falign(v->vtyp));
+    emit(f,"%s%ld:\n",labprefix,zm2l(v->offset));
+    newobj=1;
+  }
+  if(v->storage_class==EXTERN){
+    emit(f,"\tglobal\t%s%s\n",idprefix,v->identifier);
+    if(v->tattr&ZPAGE)
+      emit(f,"\tzpage\t%s%s\n",idprefix,v->identifier);
+    if(v->flags&(DEFINED|TENTATIVE)){
+      if(!special_section(f,v)){
+	if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))){emit(f,dataname);ebank(f,b);if(f) section=DATA;}
+	if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)){emit(f,rodataname);ebank(f,b);if(f) section=RODATA;}
+	if(!v->clist){emit(f,bssname);ebank(f,b);if(f) section=BSS;}
+      }
+
+      gen_align(f,falign(v->vtyp));
+      emit(f,"%s%s:\n",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.                      */
+{
+  if(ISCHAR(t))
+    emit(f,"\tbyte\t");
+  else
+    emit(f,"\tword\t");
+  if(!p->tree){
+    if(ISLONG(t)||ISFLOAT(t)){
+      if(ieee&&ISFLOAT(t)){
+	emit_ieee(f,&p->val,t&NQ);
+      }else{
+	eval_const(&p->val,t&NU);
+	if(ISFLOAT(t)) cnv_fp();
+	gval.vmax=zmand(vmax,l2zm(0xffffL));
+	emitval(f,&gval,MAXINT);
+	emit(f,",");
+	gval.vmax=zmand(zmrshift(vmax,l2zm(16L)),l2zm(0xffffL));
+	emitval(f,&gval,MAXINT);
+      }
+    }else{
+      if(ISFPOINTER(t)){
+	eval_const(&p->val,t&NU);
+	emit(f,"%ld\n",(long)zm2l(vmax)&0xffff);
+	emit(f,"\tbyte\t%d\n",(int)((zm2l(vmax)>>16)&0xff));
+      }else
+	emitval(f,&p->val,t&NU);
+    }
+  }else{
+    emit_obj(f,&p->tree->o,t&NU);
+    if(ISFPOINTER(t)){
+      int b;
+      if((p->tree->o.flags&(VAR|VARADR))!=(VAR|VARADR)) ierror(0);
+      b=bank(p->tree->o.v);
+      emit(f,"\n\tbyte\t%d",b>=0?b:bankcnum);
+    }
+  }
+  emit(f,"\n");newobj=0;
+}
+
+
+/*  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 *p,struct Var *v,zmax offset)
+/*  The main code-generation.                                           */
+{
+  int c,t,i;
+  struct IC *mi;
+  FILE *rf=f;
+  static char *dbgfile;
+  static int dbgline;
+
+  if(vlas){
+    fp=FPVLA_REG;
+    if(!reg_pair(fp,&rp)) ierror(0);
+    fp1=rp.r1;
+    fp2=rp.r2;
+    regused[fp]=regused[fp1]=regused[fp2]=1;
+   }else{
+    fp=sp;
+    fp1=sp1;
+    fp2=sp2;
+  }
+  argsize=0;
+  localsize=offset;
+  if(DEBUG&1) printf("gen_code()\n");
+
+  cbank=bank(v);
+
+  if(!v->fi) v->fi=new_fi();
+  v->fi->flags|=ALL_REGS;
+
+  for(pass=0;pass<2;pass++){
+
+    if(DEBUG&1) printf("pass %d\n",pass);
+
+    if(pass==0){
+      f=0;
+      mi=clone_ic(p);
+    }else
+      f=rf;
+
+    for(c=1;c<=MAXR;c++) regs[c]=0; /*regsa[c];*/
+    maxpushed=0;
+
+    /*FIXME*/
+    if(v->tattr&INTERRUPT){
+      ret="\trti\n";
+      in_isr=1;
+    }else{
+      ret="\trts\n";
+      in_isr=0;
+    }
+
+    if(!nopeep) peephole(pass==0?p:mi);
+
+    function_top(f,v,localsize);
+
+    pushed=0;
+
+    yval=NOVAL;
+
+    dbgfile=0;
+    dbgline=0;
+
+    for(p=pass==0?p:mi;p;pr(f,p),p=p->next){
+
+
+
+      if(DEBUG&1) pric2(stdout,p);
+
+      if(debug_info){
+	if(p->file&&p->line){
+	  if(p->file!=dbgfile||p->line!=dbgline){
+	    dbgfile=p->file;
+	    dbgline=p->line;
+	    emit(f,"; %d \"%s\"\n",dbgline,dbgfile);
+	  }
+	}
+      }
+
+      c=p->code;t=p->typf;
+
+      if(c==NOP) {p->z.flags=0;continue;}
+      if(c==ALLOCREG){
+	regs[p->q1.reg]=1;
+	if(reg_pair(p->q1.reg,&rp)){
+	  regs[rp.r1]=1;
+	  regs[rp.r2]=1;
+	}
+	continue;
+      }
+      if(c==FREEREG){
+	regs[p->q1.reg]=0;
+	if(reg_pair(p->q1.reg,&rp)){
+	  regs[rp.r1]=0;
+	  regs[rp.r2]=0;
+	}
+	continue;
+      }
+      if(c==LABEL) {emit(f,"%s%d:\n",labprefix,t);yval=NOVAL;continue;}
+      if(c==BRA){
+	yval=NOVAL;
+	if(t==exit_label&&localsize+argsize+rsavesize+rscnt==0)
+	  emit(f,ret);
+	else
+	  emit(f,"\t%s\t%s%d\n",jmpinst,labprefix,t);
+	continue;
+      }
+      if(c>=BEQ&&c<BRA){
+	yval=NOVAL;
+	continue;
+      }
+
+      if(c==MOVETOREG){
+	p->code=c=ASSIGN;
+	p->typf=t=regtype[p->z.reg]->flags;
+	p->q2.val.vmax=sizetab[regtype[p->z.reg]->flags];
+      }
+      if(c==MOVEFROMREG){
+	p->code=c=ASSIGN;
+	p->typf=t=regtype[p->q1.reg]->flags;
+	p->q2.val.vmax=sizetab[regtype[p->q1.reg]->flags];
+      }
+      if(c==CONVERT&&ISCHAR(t)&&ISCHAR(p->typf2)){
+	p->code=c=ASSIGN;
+	p->q2.val.vmax=sizetab[CHAR];
+      }
+      if(c==CONVERT&&msizetab[t&NQ]==3&&msizetab[p->typf2&NQ]==3){
+	p->code=c=ASSIGN;
+	p->q2.val.vmax=sizetab[SHORT];
+      }
+      if(c==CONVERT&&ISSHORT(t)&&ISSHORT(p->typf2)){
+	p->code=c=ASSIGN;
+	p->q2.val.vmax=sizetab[SHORT];
+      }
+      if(c==CONVERT&&ISLONG(t)&&ISLONG(p->typf2)){
+	p->code=c=ASSIGN;
+	p->q2.val.vmax=sizetab[LONG];
+      }
+      if(c==CONVERT&&ISLLONG(t)&&ISLLONG(p->typf2)){
+	p->code=c=ASSIGN;
+	p->q2.val.vmax=sizetab[LLONG];
+      }
+      if(c==CONVERT&&ISFLOAT(t)&&ISFLOAT(p->typf2)){
+	p->code=c=ASSIGN;
+	p->q2.val.vmax=sizetab[t&NQ];
+      }
+
+
+      /* switch commutative operands if suitable */
+      if(c==ADD||c==MULT||c==AND||c==XOR||c==OR||(c==ADDI2P&&ISSHORT(t)&&!ISFPOINTER(p->typf2))){
+	if(compare_objects(&p->q2,&p->z)||isacc(q2)){
+	  struct obj tmp;
+	  tmp=p->q1;
+	  p->q1=p->q2;
+	  p->q2=tmp;
+	}
+      }
+
+      if(c==COMPARE&&(p->q1.flags&(KONST|DREFOBJ))==KONST){
+	obj tmp;
+	tmp=p->q1;
+	p->q1=p->q2;
+	p->q2=tmp;
+      }
+
+      c=p->code;
+      if(c==SUBPFP) c=SUB;
+      /*if(c==ADDI2P) c=ADD;*/
+      /*if(c==SUBIFP) c=SUB;*/
+
+
+      if(c==MINUS){
+	if(isacc(q1)&&isacc(z)){
+          if(ISCHAR(t)){
+            emit(f,"\tneg\n");
+          }else{
+	    emit(f,"\teor\t#255\n");
+            emit(f,"\tclc\n");
+            emit(f,"\tadc\t#1\n");
+          }
+          if(!ISCHAR(t)){
+            emit(f,"\tpha\n");
+            emit(f,"\ttxa\n");
+            emit(f,"\teor\t#255\n");
+            emit(f,"\tadc\t#0\n");
+            emit(f,"\ttax\n");
+            emit(f,"\tpla\n");
+          }
+          continue;
+        }
+	p->code=c=SUB;
+	p->q2=p->q1;
+	p->q1.flags=KONST;
+	p->q1.am=0;
+	gval.vmax=Z0;
+	eval_const(&gval,MAXINT);
+	insert_const(&p->q1.val,t);
+      }
+
+      preload(f,p);
+
+      if(c==CONVERT){
+	int to=q1typ(p)&NU;
+	t&=NU;
+	if(ISCHAR(t)){
+	  get_acc(f,p,CHAR);
+	  load_lobyte(f,&p->q1,to);
+	  store_lobyte(f,&p->z,t);
+	  continue;
+	}
+	if(ISLONG(to)){
+	  if(!isacc(z))
+	    get_acc(f,p,CHAR);
+	  if(zm2l(sizetab[t&NQ])==3){
+	    do_byte3(f,"lda",&p->q1,to);
+	    do_byte3(f,"sta",&p->z,t);
+	  }
+	  if(zm2l(sizetab[t&NQ])>=2){
+	    load_hibyte(f,&p->q1,to);
+	    store_hibyte(f,&p->z,t);
+	  }
+	  load_lobyte(f,&p->q1,to);
+	  store_lobyte(f,&p->z,t);
+	  continue;
+	}
+	if(ISSHORT(to)){
+	  if((t&UNSIGNED)||ISFPOINTER(t))
+	    get_acc(f,p,CHAR);
+	  else
+	    get_acc(f,p,SHORT);
+	  load_lobyte(f,&p->q1,to);
+	  store_lobyte(f,&p->z,t);
+	  load_hibyte(f,&p->q1,to);
+	  store_hibyte(f,&p->z,t);
+	  if(ISFPOINTER(t)){
+	    int b=-1;
+	    if((p->q1.flags&(VARADR|DREFOBJ))==VARADR) b=bank(p->q1.v);
+	    emit(f,"\tlda\t#%d\n",b>=0?b:bankcnum);
+	    do_byte3(f,"sta",&p->z,t);
+	    continue;
+	  }
+	  if(to&UNSIGNED){
+	    if(has_zero_reg&&!indirect(&p->z)){
+	      // 65C02 Z is Zero, not a changeable register, so we can
+	      // use it to clear upper bytes.
+	      // This is NOT the case on 4510/M65, where Z is an index register
+	      do_byte3(f,"stz",&p->z,t);
+	      do_byte4(f,"stz",&p->z,t);
+	    }else{
+	      emit(f,"\tlda\t#0\n");
+	      do_byte3(f,"sta",&p->z,t);
+	      do_byte4(f,"sta",&p->z,t);
+	    }
+	  }else{
+	    emit(f,"\tldx\t#0\n");
+	    emit(f,"\tcmp\t#0\n");
+	    emit(f,"\tbpl\t%s%d\n",labprefix,++label);
+	    emit(f,"\tdex\n");
+	    emit(f,"%s%d:\n",labprefix,label);
+	    if(indirect(&p->z)){
+	      emit(f,"\ttxa\n");
+	      do_byte3(f,"sta",&p->z,t);
+	      do_byte4(f,"sta",&p->z,t);
+	    }else{
+	      do_byte3(f,"stx",&p->z,t);
+	      do_byte4(f,"stx",&p->z,t);
+	    }
+	  }
+	  continue;
+	}
+	if(ISCHAR(to)){
+	  if(to&UNSIGNED){
+	    get_acc(f,p,CHAR);
+	    if(ISLONG(t)){
+	      load_lobyte(f,&p->q1,to);
+	      store_lobyte(f,&p->z,t);
+	      if(has_zero_reg&&!indirect(&p->z)){
+		// 65C02 Z is Zero, not a changeable register, so we can
+		// use it to clear upper bytes.
+		// This is NOT the case on 4510/M65, where Z is an index register
+		do_hibyte(f,"stz",&p->z,t);
+		do_byte3(f,"stz",&p->z,t);
+		if(ISLONG(t))
+		  do_byte4(f,"stz",&p->z,t);
+	      }else{
+		emit(f,"\tlda\t#0\n");
+		store_hibyte(f,&p->z,t);
+		do_byte3(f,"sta",&p->z,t);
+		if(ISLONG(t))
+		  do_byte4(f,"sta",&p->z,t);
+	      }
+	      continue;
+	    }
+	    if(isacc(z))
+	      emit(f,"\tldx\t#0\n");
+	    else if(isacc(q1)){
+	      emit(f,"\tldx\t#0\n");
+	      store_acc(f,&p->z,t);
+	      continue;
+	    }else{
+	      if(has_zero_reg&&!indirect(&p->z)){
+		// 65C02 Z is Zero, not a changeable register, so we can
+		// use it to clear upper bytes.
+		// This is NOT the case on 4510/M65, where Z is an index register
+		do_hibyte(f,"stz",&p->z,t);
+	      }else{
+		emit(f,"\tlda\t#0\n");
+		store_hibyte(f,&p->z,t);
+	      }
+	    }
+	    load_lobyte(f,&p->q1,to);
+	    store_lobyte(f,&p->z,t);
+	  }else{
+	    int l=++label;
+	    get_acc(f,p,SHORT);
+	    emit(f,"\tldx\t#0\n");
+	    if(isreg(q1)&&p->q1.reg==ra)
+	      emit(f,"\tcmp\t#0\n");
+	    else
+	      load_lobyte(f,&p->q1,to);
+	    emit(f,"\tbpl\t%s%d\n",labprefix,label);
+	    emit(f,"\tdex\n");
+	    emit(f,"%s%d:\n",labprefix,label);
+	    store_lobyte(f,&p->z,t);
+	    if(indirect(&p->z)&&(!isreg(z)||p->z.reg!=rax)){
+	      emit(f,"\ttxa\n");
+	      store_hibyte(f,&p->z,t);
+	      if(ISLONG(t)){
+		do_byte3(f,"sta",&p->z,t);
+		do_byte4(f,"sta",&p->z,t);
+	      }
+	    }else{
+	      if(!isreg(z)||p->z.reg!=rax){
+		emit(f,"\tstx\t");
+		emit_hibyte(f,&p->z,t);
+		emit(f,"\n");
+	      }
+	      if(ISLONG(t)){
+		do_byte3(f,"stx",&p->z,t);
+		do_byte4(f,"stx",&p->z,t);
+	      }
+	    }
+	  }
+	  if(ISFPOINTER(t)){
+	    emit(f,"\tlda\t#%d\n",cbank>=0?cbank:bankcnum);
+	    do_byte3(f,"sta",&p->z,t);
+	  }
+	  continue;
+	}
+	if(ISFPOINTER(to)){
+	  get_acc(f,p,CHAR);
+	  if(zm2l(sizetab[t&NQ])>=3){
+	    do_byte3(f,"lda",&p->q1,to);
+	    do_byte3(f,"sta",&p->z,t);
+	  }
+	  if(zm2l(sizetab[t&NQ])>=2){
+	    load_hibyte(f,&p->q1,to);
+	    store_hibyte(f,&p->z,t);
+	  }
+	  load_lobyte(f,&p->q1,to);
+	  store_lobyte(f,&p->z,t);
+
+	  continue;
+	}
+	ierror(0);
+      }
+
+      if(c==KOMPLEMENT){
+	get_acc(f,p,CHAR);
+	if(ISCHAR(t)){
+	  load_acc(f,&p->q1,t);
+	  emit(f,"\teor\t#-1\n");
+	  store_acc(f,&p->z,t);
+	}else{
+	  if(isacc(q1))
+	    emit(f,"\tpha\n");
+	  if(ISLONG(t)){
+	    do_byte4(f,"lda",&p->q1,t);
+	    emit(f,"\teor\t#-1\n");
+	    do_byte4(f,"sta",&p->z,t);
+	    do_byte3(f,"lda",&p->q1,t);
+	    emit(f,"\teor\t#-1\n");
+	    do_byte3(f,"sta",&p->z,t);
+	  }
+	  load_hibyte(f,&p->q1,t);
+	  emit(f,"\teor\t#-1\n");
+	  store_hibyte(f,&p->z,t);
+	  if(isacc(q1))
+	    emit(f,"\tpla\n");
+	  load_lobyte(f,&p->q1,t);
+	  emit(f,"\teor\t#-1\n");
+	  store_lobyte(f,&p->z,t);
+	}
+	continue;
+      }
+      if(c==SETRETURN){
+	t&=NQ;
+	if(isreg(q1)&&p->q1.reg==p->z.reg) continue;
+	if(t==LONG||t==LLONG||ISFLOAT(t)||ISFPOINTER(t)){
+	  long l=zm2l(p->q2.val.vmax);
+	  int zr=p->z.reg;
+	  //get_acc(f,p,t);
+	  if((optsize||l>4)&&!ISFPOINTER(t)){
+	    int ind=indirect(&p->q1);
+	    if(ind) load_address(f,LAST_PAIR,&p->q1,t);
+	    BSET(regused,t3);
+	    BSET(regused,t4);
+	    sety(f,l-1);
+	    emit(f,"%s%d:\n",labprefix,++label);
+	    if(ind)
+	      emit(f,"\tlda\t(%s),y\n",mregnames[LAST_PAIR]);
+	    else{
+	      emit(f,"\tlda\t");
+	      if(!ISFLOAT(t)&&(p->q1.flags&(KONST|DREFOBJ))==KONST){
+		emit(f,"%s%d",labprefix,addfpconst(&p->q1,t));
+	      }else
+		emit_obj(f,&p->q1,t);
+	      emit(f,",y\n");
+	    }
+	    emit(f,"\tsta\t%s,y\n",mregnames[zr]);
+	    emit(f,"\tdey\n");
+	    emit(f,"\tbpl\t%s%d\n",labprefix,label);
+	    yval=255;
+	  }else{
+	    if((p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)){
+	      if(p->q1.reg==zr){
+		int r=get_reg(f,p,POINTER);
+		if(r==FIRST_PAIR||r==FIRST_PAIR+1)
+		  ierror(0);
+		if(!reg_pair(r,&rp2)) ierror(0);
+		emit(f,"\tlda\t%s\n",mregnames[zr]);
+		emit(f,"\tsta\t%s\n",mregnames[rp2.r1]);
+		emit(f,"\tlda\t%s+1\n",mregnames[zr]);
+		emit(f,"\tsta\t%s\n",mregnames[rp2.r2]);
+		p->q1.reg=r;
+	      }
+	    }
+	    load_lobyte(f,&p->q1,t);
+	    emit(f,"\tsta\t%s\n",mregnames[zr]);
+	    load_hibyte(f,&p->q1,t);
+	    emit(f,"\tsta\t%s+1\n",mregnames[zr]);
+	    do_byte3(f,"lda",&p->q1,t);
+	    emit(f,"\tsta\t%s+2\n",mregnames[zr]);
+	    if(!ISFPOINTER(t)){
+	      do_byte4(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s+3\n",mregnames[zr]);
+	    }
+	    /*TODO:regused OLDFP */
+	    regused[zr]=1;
+	  }
+	  continue;
+	}
+	//get_acc(f,p,t);
+	load_acc(f,&p->q1,t);
+	regused[ra]=1;
+	regused[rx]=1;
+	continue;
+      }
+      if(c==GETRETURN){
+	t&=NQ;
+	if(isreg(z)&&p->q1.reg==p->z.reg) continue;
+	if(t==LONG||t==LLONG||ISFLOAT(t)||ISFPOINTER(t)){
+	  long l=zm2l(p->q2.val.vmax);
+	  int qr=p->q1.reg;
+	  if((optsize||l>4)&&!ISFPOINTER(t)){
+	    int ind=indirect(&p->z);
+	    if(ind) load_address(f,LAST_PAIR,&p->z,t);
+	    BSET(regused,t3);
+	    BSET(regused,t4);
+	    sety(f,l-1);
+	    emit(f,"%s%d:\n",labprefix,++label);
+	    emit(f,"\tlda\t%s,y\n",mregnames[qr]);
+	    if(ind)
+	      emit(f,"\tsta\t(%s),y\n",mregnames[LAST_PAIR]);
+	    else{
+	      emit(f,"\tsta\t");
+	      emit_obj(f,&p->z,t);
+	      emit(f,",y\n");
+	    }
+	    emit(f,"\tdey\n");
+	    emit(f,"\tbpl\t%s%d\n",labprefix,label);
+	    yval=255;
+	  }else{
+	    if((p->z.reg&(REG|DREFOBJ))==(REG|DREFOBJ)){
+	      if(p->z.reg==qr) ierror(0);
+	    }
+	    emit(f,"\tlda\t%s\n",mregnames[qr]);
+	    store_lobyte(f,&p->z,t);
+	    emit(f,"\tlda\t%s+1\n",mregnames[qr]);
+	    store_hibyte(f,&p->z,t);
+	    emit(f,"\tlda\t%s+2\n",mregnames[qr]);
+	    do_byte3(f,"sta",&p->z,t);
+	    if(!ISFPOINTER(t)){
+	      emit(f,"\tlda\t%s+3\n",mregnames[qr]);
+	      do_byte4(f,"sta",&p->z,t);
+	    }
+	  }
+	  continue;
+	}
+	if(p->q1.reg)
+	  store_acc(f,&p->z,t);
+	continue;
+      }
+      if(c==CALL){
+	int reg;
+
+	if(argsize<zm2l(p->q2.val.vmax)) argsize=zm2l(p->q2.val.vmax);
+
+	/*FIXME*/
+#if 0      
+	if(stack_valid&&(p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&(p->q1.v->fi->flags&ALL_STACK)){
+	  if(framesize+zum2ul(p->q1.v->fi->stack1)>stack)
+	    stack=framesize+zum2ul(p->q1.v->fi->stack1);
+	}else
+	  stack_valid=0;
+#endif
+	if((p->q1.flags&(VAR|DREFOBJ))==VAR&&!strcmp("__va_start",p->q1.v->identifier)){
+	  long of=va_offset(v)+localsize+rsavesize+argsize;
+	  emit(f,"\tlda\t%s\n",mregnames[fp]);
+	  if(of){
+	    emit(f,"\tclc\n");
+	    if(of&255)
+	      emit(f,"\tadc\t#%d\n",(of&255));
+	  }
+	  emit(f,"\tldx\t%s+1\n",mregnames[fp]);
+	  if(of&0xff00){
+	    emit(f,"\tpha\n");
+	    emit(f,"\ttxa\n");
+	    emit(f,"\tadc\t#%d\n",(of>>8)&255);
+	    emit(f,"\ttax\n");
+	    emit(f,"\tpla\n");
+	  }else if(of){
+	    emit(f,"\tbcc\t%s%d\n",labprefix,++label);
+	    emit(f,"\tinx\n");
+	    emit(f,"%s%d:\n",labprefix,label);
+	  }
+	  continue;
+	}
+	if((p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&p->q1.v->fi->inline_asm){
+	  emit(f,";startinline\n");
+	  emit_inline_asm(f,p->q1.v->fi->inline_asm);
+	  emit(f,";endinline\n");
+	}else if(p->q1.flags&DREFOBJ){
+	  if(ISFPOINTER(p->q1.dtyp)){
+	    p->q1.flags&=~DREFOBJ;
+	    load_reg(f,LAST_PAIR,&p->q1,POINTER);
+	    if(indirect(&p->q1)){
+	      do_byte3(f,"lda",&p->q1,FPOINTER);
+	      emit(f,"\ttay\n");
+	    }else
+	      do_byte3(f,"ldy",&p->q1,FPOINTER);
+	    emit(f,"\tlda\t#%d\n",cbank>=0?cbank:bankcnum);
+	    emit(f,"\tjsr\t%s__bankjsr\n",idprefix);
+	    yval=NOVAL;
+	  }else{
+	    if(!(p->q1.flags&REG)) ierror(0);
+	    emit(f,"\tjsr\t%s%d\n",labprefix,++label);
+	    yval=NOVAL;
+	    add_cmplist(label,p->q1.reg,JMPIND);
+	  }
+	}else{
+	  int tbank=-1;
+	  if(p->q1.flags&VAR) tbank=bank(p->q1.v);
+	  if(tbank!=cbank&&tbank>=0){
+	    if(cbank>=0){
+	      load_address(f,LAST_PAIR,&p->q1,t);
+	      sety(f,tbank);
+	      emit(f,"\tlda\t#%d\n",cbank);
+	      emit(f,"\tjsr\t%s__bankjsr\n",idprefix);
+	      yval=NOVAL;
+	      continue;
+	    }
+	    sety(f,tbank);
+	    emit(f,"\tjsr\t%s__bankswitch\n",idprefix);
+	    yval=NOVAL;
+	  }
+	  if((p->q1.flags&VAR)&&!strcmp(p->q1.v->identifier,"_fmemcpy"))
+	    emit(f,"\tlda\t#%d\n",cbank>=0?cbank:bankcnum);
+	  emit(f,"\tjsr\t");
+	  emit_obj(f,&p->q1,t);
+	  emit(f,"\n");
+	}
+	pushed-=zm2l(p->q2.val.vmax);
+	if(!calc_regs(p,f!=0)&&v->fi) v->fi->flags&=~ALL_REGS;
+	yval=NOVAL;
+	continue;
+      }
+      if(c==ASSIGN||c==PUSH){
+	if(t==0) ierror(0);
+	if((p->q1.flags&(KONST|DREFOBJ))==KONST&&(t&NQ)==LLONG){
+	  int i;
+	  eval_const(&p->q1.val,t);
+	  for(i=0;i<8;i++){
+	    emit(f,"\tlda\t#%d\n",zm2l(vmax)&255);
+	    vmax=zmrshift(vmax,l2zm(8L));
+	    if(c==PUSH||(p->z.flags&DREFOBJ)){
+	      sety(f,i+((c==PUSH)?pushed:0));
+	      emit(f,"\tsta\t(%s),y\n",(c==PUSH)?mregnames[sp]:mregnames[p->z.reg]);
+	    }else{
+	      p->z.val.vmax=zmadd(p->z.val.vmax,l2zm((long)i));
+	      emit(f,"\tsta\t");
+	      emit_lobyte(f,&p->z,t);
+	      emit(f,"\n");
+	      p->z.val.vmax=zmsub(p->z.val.vmax,l2zm((long)i));
+	    }
+	  }
+	  if(c==PUSH) pushed+=8;
+	  continue;
+	}  
+
+	if(!zmleq(p->q2.val.vmax,l2zm(4L))){
+	  long len=zm2l(p->q2.val.vmax);
+	  int r1,r2,loops,looplab;
+	  if(len>32767) ierror(0);
+	  if(!NOBANKVARS){
+	    int bq=-1,bz=-1,s=-1;
+	    if((p->q1.flags&(VAR|DREFOBJ))==VAR) bq=bank(p->q1.v);
+	    if((p->z.flags&(VAR|DREFOBJ))==VAR) bz=bank(p->z.v);
+	    if(((p->q1.flags&DREFOBJ)&&ISFPOINTER(p->q1.dtyp))||
+	       ((p->z.flags&DREFOBJ)&&ISFPOINTER(p->z.dtyp))){
+	      far_copy(f,p);
+	      continue;
+	    }
+	    if(cbank<0){
+	      if(bq>=0&&bz>=0){
+		if(bq!=bz){
+		  far_copy(f,p);
+		  continue;
+		}
+		s=bq;
+	      }else{
+		if(bq>=0) s=bq;
+		if(bz>=0) s=bz;
+	      }
+	      if(s>=0){
+		sety(f,s);
+		emit(f,"\tjsr\t%s__bankswitch\n",idprefix);
+		yval=NOVAL;
+	      }
+	    }else{
+	      if((bq>=0&&bq!=cbank)||(bz>=0&&bz!=cbank)){
+		far_copy(f,p);
+		continue;
+	      }
+	    }
+	  }
+	  get_acc(f,p,CHAR);
+	  if((p->q1.flags&(DREFOBJ|KONST))==DREFOBJ){
+	    if(p->q1.flags&REG){
+	      r1=p->q1.reg;
+	      if(!reg_pair(r1,&rp)) ierror(0);
+	      if(len>128){
+		emit(f,"\tlda\t%s\n",mregnames[rp.r1]);
+		emit(f,"\tclc\n");
+		if(len&128)
+		  emit(f,"\tadc\t#128\n");
+		emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
+		if(len>255){
+		  emit(f,"\tlda\t%s\n",mregnames[rp.r2]);
+		  emit(f,"\tadc\t#%ld\n",(len>>8)&255);
+		  emit(f,"\tsta\t%s\n",mregnames[rp.r2]);	
+		}else{
+		  emit(f,"\tbcc\t%s%d\n",labprefix,++label);
+		  emit(f,"\tinc\t%s\n",mregnames[rp.r2]);
+		  emit(f,"%s%d:\n",labprefix,label);
+		}
+	      }
+	    }else
+	      ierror(0);
+	  }else if(!indirect(&p->q1)&&len<=128&&(p->q1.flags&(DREFOBJ|KONST))!=KONST){
+	    r1=0;
+	  }else{
+	    Var *v=p->q1.v;
+	    /*if((p->q1.flags&(VARADR|VAR))!=VAR) ierror(0);*/
+	    r1=get_reg(f,p,POINTER);
+	    if(len>128) p->q1.val.vmax=zmadd(p->q1.val.vmax,l2zm(len&0xff80));
+	    load_address(f,r1,&p->q1,t);
+	    if(len>128) p->q1.val.vmax=zmsub(p->q1.val.vmax,l2zm(len&0xff80));
+	  }
+	  if((p->z.flags&(DREFOBJ|KONST))==DREFOBJ){
+	    if(p->z.flags&REG){
+	      r2=p->z.reg;
+	      if(!reg_pair(r2,&rp)) ierror(0);
+	      if(len>128){
+		emit(f,"\tlda\t%s\n",mregnames[rp.r1]);
+		emit(f,"\tclc\n");
+		if(len&128)
+		  emit(f,"\tadc\t#128\n");
+		emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
+		if(len>255){
+		  emit(f,"\tlda\t%s\n",mregnames[rp.r2]);
+		  emit(f,"\tadc\t#%ld\n",(len>>8)&255);
+		  emit(f,"\tsta\t%s\n",mregnames[rp.r2]);	
+		}else{
+		  emit(f,"\tbcc\t%s%d\n",labprefix,++label);
+		  emit(f,"\tinc\t%s\n",mregnames[rp.r2]);
+		  emit(f,"%s%d:\n",labprefix,label);
+		}
+	      }
+	    }else
+	      ierror(0);
+	  }else if(c==PUSH){
+	    if(len<=128&&pushed==0){
+	      r2=sp;
+	    }else{
+	      r2=get_reg(f,p,POINTER);
+	      if(!reg_pair(r2,&rp)) ierror(0);
+	      emit(f,"\tlda\t%s\n",mregnames[sp]);
+	      emit(f,"\tclc\n");
+	      if(((pushed+(len&128))&255)!=0)
+		emit(f,"\tadc\t#%ld\n",(pushed+(len&128))&255);
+	      emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
+	      emit(f,"\tlda\t%s\n",mregnames[sp2]);
+	      emit(f,"\tadc\t#%ld\n",((pushed+len)>>8)&255);
+	      emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
+	    }
+	  }else if(!indirect(&p->z)&&len<=128){
+	    r2=0;
+	  }else{
+	    Var *v=p->z.v;
+	    r2=get_reg(f,p,POINTER);
+	    if(len>128) p->z.val.vmax=zmadd(p->z.val.vmax,l2zm(len&0xff80));
+	    load_address(f,r2,&p->z,t);
+	    if(len>128) p->z.val.vmax=zmsub(p->z.val.vmax,l2zm(len&0xff80));
+	  }
+	  if(len>128){
+	    get_acc(f,p,POINTER); /* get x */
+	    emit(f,"\tldx\t#%ld\n",((len>>7)+1)&255);
+	  }
+	  sety(f,(len-1)&127);
+	  if((optsize&&len>4)||len>8){
+	    emit(f,"%s%d:\n",labprefix,looplab=++label);
+	    if(optsize)
+	      loops=1;
+	    else{
+	      if((len&3)==0)
+		loops=4;
+	      else if((len&1)==0)
+		loops=2;
+	      else
+		loops=1;
+	    }
+	  }else
+	    loops=len;
+	  if(r1&&!reg_pair(r1,&rp)) ierror(0);
+	  if(r2&&!reg_pair(r2,&rp2)) ierror(0);
+	  for(i=0;i<loops;i++){
+	    if(r1)
+	      emit(f,"\tlda\t(%s),y\n",mregnames[rp.r1]);
+	    else{
+	      emit(f,"\tlda\t");
+	      emit_obj(f,&p->q1,t);
+	      emit(f,",y\n");
+	    }
+	    if(r2)
+	      emit(f,"\tsta\t(%s),y\n",mregnames[rp2.r1]);
+	    else{
+	      emit(f,"\tsta\t");
+	      emit_obj(f,&p->z,t);
+	      emit(f,",y\n");
+	    }
+	    emit(f,"\tdey\n");
+	  }
+	  if(loops!=len){
+	    emit(f,"\tbpl\t%s%d\n",labprefix,label);
+	  }	  
+	  if(len>128){
+	    emit(f,"\tlda\t%s\n",mregnames[rp.r1]);
+	    emit(f,"\tsec\n");
+	    emit(f,"\tsbc\t#128\n");
+	    emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
+	    emit(f,"\tbcs\t%s%d\n",labprefix,++label);
+	    emit(f,"\tdec\t%s\n",mregnames[rp.r2]);
+	    emit(f,"%s%d:\n",labprefix,label);
+	    emit(f,"\tlda\t%s\n",mregnames[rp2.r1]);
+	    emit(f,"\tsec\n");
+	    emit(f,"\tsbc\t#128\n");
+	    emit(f,"\tsta\t%s\n",mregnames[rp2.r1]);
+	    emit(f,"\tbcs\t%s%d\n",labprefix,++label);
+	    emit(f,"\tdec\t%s\n",mregnames[rp2.r2]);
+	    emit(f,"%s%d:\n",labprefix,label);
+	    emit(f,"\tldy\t#127\n");
+	    emit(f,"\tdex\n");
+	    emit(f,"\tbne\t%s%d\n",labprefix,looplab);
+	  }
+	  yval=NOVAL;
+	  if(c==PUSH)
+	    pushed+=zm2l(p->q2.val.vmax);
+	  continue;
+	}
+	if(c==PUSH){
+	  get_acc(f,p,CHAR);
+	  load_lobyte(f,&p->q1,t);
+	  if(c02&&pushed==0){
+	    emit(f,"\tsta\t(%s)\n",mregnames[sp]);
+	  }else{
+	    sety(f,pushed);
+	    emit(f,"\tsta\t(%s),y\n",mregnames[sp]);
+	  }
+	  if(!zmleq(p->q2.val.vmax,Z1)){
+	    load_hibyte(f,&p->q1,t);
+	    sety(f,pushed+1);
+	    emit(f,"\tsta\t(%s),y\n",mregnames[sp]);
+	  }
+	  if(!zmleq(p->q2.val.vmax,l2zm(2L))){
+	    do_byte3(f,"lda",&p->q1,t);
+	    sety(f,pushed+2);
+	    emit(f,"\tsta\t(%s),y\n",mregnames[sp]);
+	  }
+	  if(!zmleq(p->q2.val.vmax,l2zm(3L))){
+	    do_byte4(f,"lda",&p->q1,t);
+	    sety(f,pushed+3);
+	    emit(f,"\tsta\t(%s),y\n",mregnames[sp]);
+	  }
+
+	  pushed+=zm2l(p->q2.val.vmax);
+	  continue;
+	}
+	if(c==ASSIGN){
+	  int c2m;unsigned long v;
+	  if(isreg(q1)&&isreg(z)&&p->q1.reg==p->z.reg) continue;
+	  if(isacc(q1)){
+	    if(p->q1.reg==rax) get_acc(f,p,CHAR);
+	    store_acc(f,&p->z,t);
+	    continue;
+	  }
+	  if(c02&&!indirect(&p->z)&&(p->q1.flags&(DREFOBJ|KONST))==KONST){
+	    eval_const(&p->q1.val,t);
+	    if(ISFLOAT(t)){
+	      cnv_fp();
+	      v=zum2ul(zm2zum(vmax));
+	    }else
+	      v=zum2ul(vumax);
+	    c2m=1;
+	  }else
+	    c2m=0;
+	  if(!c2m||v!=0)
+	    get_acc(f,p,CHAR);
+	  if(0/*ISCHAR(t)*/){
+	    load_acc(f,&p->q1,t);
+	    store_acc(f,&p->z,t);
+	  }else{
+            // TODO: PGS: Use AXYZ for 32-bit copy if appropriate
+	    // TOGO: PGS: Consider using AXYZ for load, even for 16 or 24-bit values
+	    if(!zmleq(p->q2.val.vmax,l2zm(3L))){
+	      if(c2m&&(v&0xFF000000)==0){
+		// 65C02 Z is Zero, not a changeable register, so we can
+		// use it to clear upper bytes.
+		// This is NOT the case on 4510/M65, where Z is an index register
+		do_byte4(f,"stz",&p->z,t);
+	      }else{
+		do_byte4(f,"lda",&p->q1,t);
+		do_byte4(f,"sta",&p->z,t);
+	      }
+	    }
+	    if(!zmleq(p->q2.val.vmax,l2zm(2L))){
+	      if(c2m&&(v&0xFF0000)==0){
+		// 65C02 Z is Zero, not a changeable register, so we can
+		// use it to clear upper bytes.
+		// This is NOT the case on 4510/M65, where Z is an index register
+		do_byte3(f,"stz",&p->z,t);
+	      }else{
+		do_byte3(f,"lda",&p->q1,t);
+		do_byte3(f,"sta",&p->z,t);
+	      }
+	    }
+	    if(!zmleq(p->q2.val.vmax,l2zm(1L))){
+	      if(c2m&&(v&0xFF00)==0){
+		// 65C02 Z is Zero, not a changeable register, so we can
+		// use it to clear upper bytes.
+		// This is NOT the case on 4510/M65, where Z is an index register
+		do_hibyte(f,"stz",&p->z,t);
+	      }else{
+		load_hibyte(f,&p->q1,t);
+		store_hibyte(f,&p->z,t);
+	      }
+	    }
+	    if(c2m&&(v&0xFF)==0){
+	      // 65C02 Z is Zero, not a changeable register, so we can
+	      // use it to clear upper bytes.
+	      // This is NOT the case on 4510/M65, where Z is an index register
+	      do_lobyte(f,"stz",&p->z,t);
+	    }else{
+	      if(isreg(q1)&&ISIDX(p->q1.reg)){
+		store_reg(f,p->q1.reg,&p->z,CHAR);
+	      }else if(isreg(z)&&ISIDX(p->z.reg)){
+		load_reg(f,p->z.reg,&p->q1,t);
+	      }else{
+		load_lobyte(f,&p->q1,t);
+		store_lobyte(f,&p->z,t);
+	      }
+	    }
+	  }
+	}
+	continue;
+      }
+      if(c==ADDRESS){
+	long o=real_offset(&p->q1);
+	get_acc(f,p,CHAR);
+	emit(f,"\tlda\t%s\n",mregnames[fp1]);
+	if(o){
+	  emit(f,"\tclc\n");
+	  if((o&255)!=0)
+	    emit(f,"\tadc\t#%ld\n",real_offset(&p->q1)&255);
+	}
+	store_lobyte(f,&p->z,t);
+	if(isacc(z)) emit(f,"\tpha\n");
+	emit(f,"\tlda\t%s\n",mregnames[fp2]);
+	if(o!=0)
+	  emit(f,"\tadc\t#%ld\n",real_offset(&p->q1)>>8&255);
+	store_hibyte(f,&p->z,t);
+	if(isacc(z)) emit(f,"\tpla\n");
+	continue;
+      }
+
+      if(c==COMPARE||c==TEST){
+	IC *branch=p->next;
+	int pacc=0,bc,bout;
+	while(branch){
+	  if(branch->code>=BEQ&&branch->code<BRA)
+	    break;
+	  if(branch->code!=FREEREG&&branch->code!=ALLOCREG&&branch->code!=NOP)
+	    ierror(0);
+	  branch=branch->next;
+	}
+	bc=branch->code;
+	bout=branch->typf;
+	if(c==TEST){
+	  p->q2.flags=KONST;
+	  gval.vmax=Z0;
+	  eval_const(&gval,MAXINT);
+	  insert_const(&p->q2.val,t);
+	}
+	if((bc==BLE||bc==BGT)&&(p->q2.flags&(DREFOBJ|KONST))==KONST){
+	  eval_const(&p->q2.val,t);
+	  if(!zmeqto(vmax,l2zm(255L))){
+	    vmax=zmadd(vmax,Z1);
+	    gval.vmax=vmax;
+	    eval_const(&gval,t);
+	    insert_const(&p->q2.val,t);
+	    if(bc==BLE) bc=BLT; else bc=BGE;
+	    branch->code=bc;
+	  }
+	}
+	if(ieee&&ISFLOAT(t)){
+	  if(!ieee) ierror(0);
+	  t&=NQ;
+	  if(regs[LAST_PAIR]) ierror(0);
+	  regs[LAST_PAIR]=1;
+	  if(regs[ra]||regs[rax])
+	    ierror(0);
+	  load_address(f,LAST_PAIR,&p->q2,t);
+	  BSET(regused,t3);
+	  BSET(regused,t4);
+	  emit(f,"\tjsr\t%s__fload%c\n",idprefix,(t==FLOAT?'s':'d'));
+	  yval=NOVAL;
+	  load_address(f,LAST_PAIR,&p->q1,t);
+	  emit(f,"\tjsr\t%s__fcmp%c\n",idprefix,(t==FLOAT?'s':'d'));
+	  yval=NOVAL;
+	  regs[LAST_PAIR]=0;
+	  if(bc==BLT||bc==BLE)
+	    emit(f,"\tbmi\t%s%d\n",labprefix,bout);
+	  else if(bc==BGT|bc==BGE)
+	    emit(f,"\tbvs\t%s%d\n",labprefix,bout);
+	  if(bc==BEQ||bc==BLE||bc==BGE)
+	    emit(f,"\tbeq\t%s%d\n",labprefix,bout);
+	  if(bc==BNE)
+	    emit(f,"\tbne\t%s%d\n",labprefix,bout);
+	  continue;
+	}
+	if(ISCHAR(t)){
+	  char *s=0;
+	  if(isreg(q1)&&ISIDX(p->q1.reg)&&!indirect(&p->q2)&&(bc==BEQ||bc==BNE||(t&UNSIGNED))){
+	    static char buf[4]="cpr";
+	    s=buf;s[2]=mregnames[p->q1.reg][0];
+	  }else{
+	    if(pacc=cmp_get_acc(f,p,branch))
+	      bout=++label;
+	    load_acc(f,&p->q1,t);
+	    if(bc==BEQ||bc==BNE||(t&UNSIGNED)){
+	      s="cmp";
+	    }else{
+	      if(bc==BLT||bc==BGE)
+		emit(f,"\tsec\n");
+	      else
+		emit(f,"\tclc\n");
+	      s="sbc";
+	    }
+	  }
+	  if(c==TEST)
+	    emit(f,"\t%s\t#0\n",s);
+	  else
+	    do_lobyte(f,s,&p->q2,t);
+	  if(bc==BEQ)
+	    emit(f,"\tbeq\t%s%d\n",labprefix,bout);
+	  else if(bc==BNE)
+	    emit(f,"\tbne\t%s%d\n",labprefix,bout);
+	  else if(t&UNSIGNED){
+	    if(bc==BLT)
+	      emit(f,"\tbcc\t%s%d\n",labprefix,bout);
+	    else if(bc==BGE)
+	      emit(f,"\tbcs\t%s%d\n",labprefix,bout);
+	    else if(bc==BLE){
+	      emit(f,"\tbcc\t%s%d\n",labprefix,bout);
+	      emit(f,"\tbeq\t%s%d\n",labprefix,bout);
+	    }else if(bc==BGT){
+	      emit(f,";\n\tbeq\t%s%d\n",labprefix,++label);
+	      emit(f,"\tbcs\t%s%d\n",labprefix,bout);
+	      emit(f,"%s%d:\n",labprefix,label);
+	    }else
+	      ierror(0);
+	  }else{
+	    emit(f,"\tbvc\t%s%d\n",labprefix,++label);
+	    emit(f,"\teor\t#128\n");
+	    emit(f,"%s%d:\n",labprefix,label);
+	    if(bc==BLT||bc==BLE)
+	      emit(f,"\tbmi\t%s%d\n",labprefix,bout);
+	    else
+	      emit(f,"\tbpl\t%s%d\n",labprefix,bout);
+	  }
+	  if(pacc){
+	    reload_acc(f);
+	    add_cmplist(bout,branch->typf,pacc);
+	  }
+	  continue;
+	}else if(bc==BEQ||bc==BNE||(t&UNSIGNED)||ISFPOINTER(t)){
+	  int in=0;
+	  if(pacc=cmp_get_acc(f,p,branch))
+	    bout=++label;
+
+	  // PGS Check for special cases of comparing to constants
+	  if(!(ISLONG(t)||ISFPOINTER(t)||isacc(q1))) {
+	    // Is a 16-bit value
+	    if (p->q2.flags&KONST) {
+	      if (!(p->q2.flags&DREFOBJ)) {
+		eval_const(&p->q2.val,t);
+		if(ISFLOAT(t)) cnv_fp();
+		if (zm2l(vmax)==0x100) {
+		  if (bc==BGE) {
+		    // >= $100 we can check by just reading the 2nd byte
+		    // If non-zero, then we take the branch
+		    do_hibyte(f,"lda",&p->q1,t);
+		    emit(f,"\tbne\t%s%d\n",labprefix,bout);
+		    continue;
+		  } else if (bc==BLT) {
+		    // <$100 we can check by just reading the 2nd byte
+		    // And if zero, then we take the branch
+		    do_hibyte(f,"lda",&p->q1,t);
+		    emit(f,"\tbeq\t%s%d\n",labprefix,bout);		  
+		    continue;
+		  }
+		} else if (zm2l(vmax)<0x100) {
+		  // Values <$100 we can do almost as simply, but we have to
+		  // also check the low byte for exceptions.
+		  // XXX PGS TODO
+		  
+		}
+	      }
+	    }
+	  }
+	  
+	  // Far-Pointers are 32-bit on M65
+	  if(ISLONG(t)||ISFPOINTER(t)){
+	    do_byte4(f,"lda",&p->q1,t);
+	    if(c==TEST)
+	      emit(f,"\tcmp\t#0\n");
+	    else
+	      do_byte4(f,"cmp",&p->q2,t);
+	    if(bc==BEQ)
+	      emit(f,"\tbne\t%s%d\n",labprefix,in=++label);
+	    else if(bc==BNE)
+	      emit(f,"\tbne\t%s%d\n",labprefix,bout);
+	    else if(bc==BLT||bc==BLE){
+	      emit(f,"\tbcc\t%s%d\n",labprefix,bout);
+	      emit(f,"\tbne\t%s%d\n",labprefix,in=++label);
+	    }else if(bc==BGE||bc==BGT){
+	      emit(f,"\tbcc\t%s%d\n",labprefix,in=++label);	
+	      emit(f,"\tbne\t%s%d\n",labprefix,bout);
+	    }else
+	      ierror(0);
+	  }
+	  if(ISLONG(t)||ISFPOINTER(t)){
+	    do_byte3(f,"lda",&p->q1,t);
+	    if(c==TEST)
+	      emit(f,"\tcmp\t#0\n");
+	    else
+	      do_byte3(f,"cmp",&p->q2,t);
+	    if(bc==BEQ)
+	      emit(f,"\tbne\t%s%d\n",labprefix,in?in:(in=++label));
+	    else if(bc==BNE)
+	      emit(f,"\tbne\t%s%d\n",labprefix,bout);
+	    else if(bc==BLT||bc==BLE){
+	      emit(f,"\tbcc\t%s%d\n",labprefix,bout);
+	      emit(f,"\tbne\t%s%d\n",labprefix,in?in:(in=++label));
+	    }else if(bc==BGE||bc==BGT){
+	      emit(f,"\tbcc\t%s%d\n",labprefix,in?in:(in=++label));	
+	      emit(f,"\tbne\t%s%d\n",labprefix,bout);
+	    }else
+	      ierror(0);	  
+	  }
+	  if(isacc(q1)){
+	    if(!indirect(&p->q2)){
+	      do_hibyte(f,"cpx",&p->q2,t);
+	    }else{
+	      int r=get_reg(f,p,CHAR);
+	      emit(f,"\tpha\n");
+	      load_hibyte(f,&p->q2,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r]);
+	      emit(f,"\tpla\n");
+	      emit(f,"\tcpx\t%s\n",mregnames[r]);
+	    }
+	  }else{
+	    load_hibyte(f,&p->q1,t);
+	    if(c==TEST)
+	      emit(f,"\tcmp\t#0\n");
+	    else
+	      do_hibyte(f,"cmp",&p->q2,t);
+	  }
+	  if(bc==BEQ)
+	    emit(f,"\tbne\t%s%d\n",labprefix,in?in:(in=++label));
+	  else if(bc==BNE)
+	    emit(f,"\tbne\t%s%d\n",labprefix,bout);
+	  else if(bc==BLT||bc==BLE){
+	    emit(f,"\tbcc\t%s%d\n",labprefix,bout);
+	    emit(f,"\tbne\t%s%d\n",labprefix,in?in:(in=++label));
+	  }else if(bc==BGE||bc==BGT){
+	    emit(f,"\tbcc\t%s%d\n",labprefix,in?in:(in=++label));
+	    emit(f,"\tbne\t%s%d\n",labprefix,bout);
+	  }else
+	    ierror(0);
+	  load_lobyte(f,&p->q1,t);
+	  if(c==TEST)
+	    emit(f,"\tcmp\t#0\n");
+	  else
+	    do_lobyte(f,"cmp",&p->q2,t);
+	  if(bc==BEQ)
+	    emit(f,"\tbeq\t%s%d\n",labprefix,bout);
+	  else if(bc==BNE)
+	    emit(f,"\tbne\t%s%d\n",labprefix,bout);
+	  else if(bc==BLT)
+	    emit(f,"\tbcc\t%s%d\n",labprefix,bout);
+	  else if(bc==BGE)
+	    emit(f,"\tbcs\t%s%d\n",labprefix,bout);	
+	  else if(bc==BLE){
+	    emit(f,"\tbcc\t%s%d\n",labprefix,bout);
+	    emit(f,"\tbeq\t%s%d\n",labprefix,bout);
+	  }else if(bc==BGT){
+	    emit(f,"\tbcc\t%s%d\n",labprefix,in);
+	    emit(f,"\tbne\t%s%d\n",labprefix,bout);
+	  }else
+	    ierror(0);
+	  if(in)
+	    emit(f,"%s%d:\n",labprefix,in);
+	  if(pacc){
+	    reload_acc(f);
+	    add_cmplist(bout,branch->typf,pacc);
+	  }
+	  continue;
+	}else{
+	  if(bc==BGT||bc==BLE){
+	    obj o;
+	    if(isacc(q1)){
+	      int r;
+	      if(pacc=cmp_get_acc(f,p,branch))
+		bout=++label;
+	      r=get_reg(f,p,CHAR);
+	      emit(f,"\tsta\t%s\n",mregnames[r]);
+	      load_lobyte(f,&p->q2,t);
+	      emit(f,"\tcmp\t%s\n",mregnames[r]);
+	      emit(f,"\tstx\t%s\n",mregnames[r]);
+	      load_hibyte(f,&p->q2,t);
+	      emit(f,"\tsbc\t%s\n",mregnames[r]);
+	      emit(f,"\tbvc\t%s%d\n",labprefix,++label);
+	      emit(f,"\teor\t#128\n");
+	      emit(f,"%s%d:\n",labprefix,label);
+	      if(bc==BGT)
+		emit(f,"\tbmi\t%s%d\n",labprefix,bout);
+	      else
+		emit(f,"\tbpl\t%s%d\n",labprefix,bout);
+	      if(pacc){
+		reload_acc(f);
+		add_cmplist(bout,branch->typf,pacc);
+	      }
+	      continue;
+	    }else{
+	      o=p->q1;p->q1=p->q2;p->q2=o;
+	      if(bc==BGT) bc=BLT; else bc=BGE;
+	    }
+	  }
+	  if(pacc=cmp_get_acc(f,p,branch))
+	    bout=++label;
+	  if(ISLONG(t)){
+	    load_lobyte(f,&p->q1,t);
+	    do_lobyte(f,"cmp",&p->q2,t);
+	    load_hibyte(f,&p->q1,t);
+	    do_hibyte(f,"sbc",&p->q2,t);
+	    do_byte3(f,"lda",&p->q1,t);
+	    do_byte3(f,"sbc",&p->q2,t);
+	    do_byte4(f,"lda",&p->q1,t);
+	    do_byte4(f,"sbc",&p->q2,t);
+	  }else{
+	    load_lobyte(f,&p->q1,t);
+	    do_lobyte(f,"cmp",&p->q2,t);
+	    load_hibyte(f,&p->q1,t);
+	    do_hibyte(f,"sbc",&p->q2,t);
+	  }
+	  emit(f,"\tbvc\t%s%d\n",labprefix,++label);
+	  emit(f,"\teor\t#128\n");
+	  emit(f,"%s%d:\n",labprefix,label);
+	  if(bc==BLT)
+	    emit(f,"\tbmi\t%s%d\n",labprefix,bout);
+	  else if(bc==BGE)
+	    emit(f,"\tbpl\t%s%d\n",labprefix,bout);
+	  else
+	    ierror(0);
+	  if(pacc){
+	    reload_acc(f);
+	    add_cmplist(bout,branch->typf,pacc);
+	  }
+	  continue; 
+	}
+	ierror(0);
+      }
+      if((c==ADD||c==SUB||c==ADDI2P||c==SUBIFP)&&compare_objects(&p->q1,&p->z)&&(!indirect(&p->q1)||(isreg(q1)&&ISIDX(p->q1.reg)))&&isconst(q2)&&!isacc(z)){
+	long l;
+	eval_const(&p->q2.val,q2typ(p));
+	l=zm2l(vmax);
+	if(c==ADDI2P/*&&(t2&NQ)==POINTER*/) {c=ADD;t=UNSIGNED|INT;}
+	if(c==SUBIFP/*&&(t2&NQ)==POINTER*/) {c=SUB;t=UNSIGNED|INT;}
+	if(c==SUB||c==SUBIFP) l=-l;
+	/*TODO: allow larger types */
+	if(l<3&&l>-3&&(t&NQ)<=INT){
+	  if(l<0){
+	    get_acc(f,p,CHAR);
+	    incmem(f,&p->z,t,SUB,-l);
+	  }else
+	    incmem(f,&p->z,t,ADD,l);
+	  continue;
+	}
+      }
+
+      if((c==LSHIFT||c==RSHIFT)&&isreg(q1)&&isreg(z)&&isconst(q2)&&p->q1.reg==p->z.reg&&p->z.reg!=ra&&p->z.reg!=rax){
+	long l;
+	eval_const(&p->q2.val,q2typ(p));
+	l=zm2l(vmax);
+	/*TODO: allow larger types */
+	if(l<5&&(t&NQ)<=INT){
+	  if(c==RSHIFT&&!(t&UNSIGNED))
+	    get_acc(f,p,CHAR);
+	  incmem(f,&p->z,t,c,l);
+	  continue;
+	}
+      }
+
+      if(c==LSHIFT||c==RSHIFT){
+	long l=-1;int loop=0,r,r2,r3,outl=0;
+	if(isconst(q2)){
+	  eval_const(&p->q2.val,q2typ(p));
+	  l=zm2l(vmax);
+	  loop=0;
+	}else
+	  loop=1;
+	if(l>=0&&optsize){
+	  if(c==LSHIFT&&(l&7)>6) 
+	    loop=1;
+	  else if(c==RSHIFT&&(t&UNSIGNED)&&(l&7)>3)
+	    loop=1;
+	  else if(c==RSHIFT&&!(t&UNSIGNED)&&(l&7)>2)
+	    loop=1;
+	}
+
+	if(!ISCHAR(t))
+	  r=get_reg(f,p,CHAR);
+	if(ISLONG(t)){
+	  r2=get_reg(f,p,CHAR);
+	  r3=get_reg(f,p,CHAR);
+	}
+	if(ISLONG(t)){
+	  get_acc(f,p,CHAR);
+	  if(l>=24){
+	    if(c==LSHIFT){
+	      load_lobyte(f,&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r3]);
+	      emit(f,"\tlda\t#0\n");
+	      emit(f,"\tsta\t%s\n",mregnames[r]);
+	      emit(f,"\tsta\t%s\n",mregnames[r2]);
+	    }else if(c==RSHIFT&&!(t&UNSIGNED)){
+	      do_byte4(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r3]);
+	      sety(f,0);
+	      emit(f,"\tcmp\t#0\n");
+	      emit(f,"\tbpl\t%s%d\n",labprefix,++label);
+	      emit(f,"\tdey\n");
+	      emit(f,"%s%d:\n",labprefix,label);
+	      emit(f,"\tsty\t%s\n",mregnames[r]);
+	      emit(f,"\tsty\t%s\n",mregnames[r2]);
+	      emit(f,"\ttya\n");
+	      yval=NOVAL;
+	    }else{
+	      emit(f,"\tlda\t#0\n");
+	      emit(f,"\tsta\t%s\n",mregnames[r3]);
+	      emit(f,"\tsta\t%s\n",mregnames[r2]);
+	      emit(f,"\tsta\t%s\n",mregnames[r]);
+	      do_byte4(f,"lda",&p->q1,t);
+
+	    }
+	  }else if(l>=16){
+	    if(c==LSHIFT){
+	      load_lobyte(f,&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r2]);
+	      load_hibyte(f,&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r3]);
+	      emit(f,"\tlda\t#0\n");
+	      emit(f,"\tsta\t%s\n",mregnames[r]);
+	    }else if(c==RSHIFT&&!(t&UNSIGNED)){
+	      do_byte3(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r3]);
+	      do_byte4(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r2]);
+	      sety(f,0);
+	      emit(f,"\tcmp\t#0\n");
+	      emit(f,"\tbpl\t%s%d\n",labprefix,++label);
+	      emit(f,"\tdey\n");
+	      emit(f,"%s%d:\n",labprefix,label);
+	      emit(f,"\tsty\t%s\n",mregnames[r]);
+	      emit(f,"\ttya\n");
+	      yval=NOVAL;
+	    }else{
+	      emit(f,"\tlda\t#0\n");
+	      emit(f,"\tsta\t%s\n",mregnames[r2]);
+	      emit(f,"\tsta\t%s\n",mregnames[r3]);
+	      do_byte4(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r]);
+	      do_byte3(f,"lda",&p->q1,t);
+
+	    }
+	  }else if(l>=8){
+	    if(c==LSHIFT){
+	      load_lobyte(f,&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r]);
+	      load_hibyte(f,&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r2]);
+	      do_byte3(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r3]);
+	      emit(f,"\tlda\t#0\n");
+	    }else if(c==RSHIFT&&!(t&UNSIGNED)){
+	      load_hibyte(f,&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r3]);
+	      do_byte3(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r2]);
+	      do_byte4(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r]);
+	      sety(f,0);
+	      emit(f,"\tcmp\t#0\n");
+	      emit(f,"\tbpl\t%s%d\n",labprefix,++label);
+	      emit(f,"\tdey\n");
+	      emit(f,"%s%d:\n",labprefix,label);
+	      emit(f,"\ttya\n");
+	      yval=NOVAL;
+	    }else{
+	      emit(f,"\tlda\t#0\n");
+	      emit(f,"\tsta\t%s\n",mregnames[r3]);
+	      do_byte4(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r2]);
+	      do_byte3(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r]);
+	      load_hibyte(f,&p->q1,t);
+
+	    }
+	  }else if(c==RSHIFT&&!(t&UNSIGNED)){
+	    load_lobyte(f,&p->q1,t);
+	    emit(f,"\tsta\t%s\n",mregnames[r3]);
+	    load_hibyte(f,&p->q1,t);
+	    emit(f,"\tsta\t%s\n",mregnames[r2]);
+	    do_byte3(f,"lda",&p->q1,t);
+	    emit(f,"\tsta\t%s\n",mregnames[r]);
+	    do_byte4(f,"lda",&p->q1,t);
+	  }else{
+	    do_byte4(f,"lda",&p->q1,t);
+	    emit(f,"\tsta\t%s\n",mregnames[r3]);
+	    do_byte3(f,"lda",&p->q1,t);
+	    emit(f,"\tsta\t%s\n",mregnames[r2]);
+	    load_hibyte(f,&p->q1,t);
+	    emit(f,"\tsta\t%s\n",mregnames[r]);
+	    load_lobyte(f,&p->q1,t);
+	  }
+	}else
+	  get_acc(f,p,t);
+	if(!ISLONG(t)){
+	  if(l>=8){
+	    if(!ISSHORT(t)) ierror(0);
+	    if(c==LSHIFT){
+	      if(indirect(&p->q1)){
+		load_lobyte(f,&p->q1,t);
+		emit(f,"\ttax\n");
+		emit(f,"\tlda\t#0\n");
+	      }else{
+		if(isacc(q1))
+		  emit(f,"\ttax\n");
+		else
+		  do_lobyte(f,"ldx",&p->q1,t);
+		emit(f,"\tlda\t#0\n");
+	      }
+	    }else{
+	      load_hibyte(f,&p->q1,t);
+	      emit(f,"\tldx\t#0\n");
+	      if(!(t&UNSIGNED)){
+		emit(f,"\tcmp\t#0\n");
+		emit(f,"\tbpl\t%s%d\n",labprefix,++label);
+		emit(f,"\tdex\n");
+		emit(f,"%s%d:\n",labprefix,label);
+	      }
+	    }
+	  }else
+	    load_acc(f,&p->q1,t);
+	}
+	if(ISSHORT(t))
+	  emit(f,"\tstx\t%s\n",mregnames[r]);
+	if(l>=0) l&=7;
+	if(loop){
+	  if(l>=0)
+	    sety(f,l);
+	  else{
+	    if(indirect(&p->q2)){
+	      emit(f,"\tpha\n");
+	      load_lobyte(f,&p->q2,q2typ(p));
+	      emit(f,"\ttay\n");
+	      emit(f,"\tpla\n");
+	      emit(f,"\tcpy\t#0\n");
+	    }else{
+	      emit(f,"\tldy\t");
+	      emit_lobyte(f,&p->q2,q2typ(p));
+	      emit(f,"\n");
+	    }
+	    outl=++label;
+	    emit(f,"\tbeq\t%s%d\n",labprefix,outl);
+	  }
+	  emit(f,"%s%d:\n",labprefix,++label);
+	}else{
+	  if(ISCHAR(t))
+	    l&=7;
+	  else if(ISSHORT(t))
+	    l&=15;
+	  else
+	    l&=31;
+	}
+	while(l>0||loop){
+	  if(c==LSHIFT){
+	    emit(f,"\tasl\n");
+	    if(!ISCHAR(t))
+	      emit(f,"\trol\t%s\n",mregnames[r]);
+	    if(ISLONG(t)){
+	      emit(f,"\trol\t%s\n",mregnames[r2]);
+	      emit(f,"\trol\t%s\n",mregnames[r3]);
+	    }
+	  }else if(t&UNSIGNED){
+	    emit(f,"\tclc\n");
+	    if(ISLONG(t)){
+	      emit(f,"\tror\t%s\n",mregnames[r3]);
+	      emit(f,"\tror\t%s\n",mregnames[r2]);
+	    }
+	    if(!ISCHAR(t))
+	      emit(f,"\tror\t%s\n",mregnames[r]);
+	    emit(f,"\tror\n");
+	  }else{
+	    if(ISLONG(t)){
+	      emit(f,"\tcmp\t#128\n");
+	      emit(f,"\tror\n");
+	      emit(f,"\tror\t%s\n",mregnames[r]);
+	      emit(f,"\tror\t%s\n",mregnames[r2]);
+	      emit(f,"\tror\t%s\n",mregnames[r3]);
+	    }else{
+	      if(!ISCHAR(t)){
+		emit(f,"\tcpx\t#128\n");
+		emit(f,"\tror\t%s\n",mregnames[r]);
+	      }else
+		emit(f,"\tcmp\t#128\n");
+	      emit(f,"\tror\n");
+	    }
+	  }
+	  if(loop){
+	    emit(f,"\tdey\n");
+	    emit(f,"\tbne\t%s%d\n",labprefix,label);
+	    if(outl) emit(f,"%s%d:\n",labprefix,outl);
+	    yval=0;
+	    break;
+	  }
+	  l--;
+	}
+	if(ISLONG(t)){
+	  if(c==RSHIFT&&!(t&UNSIGNED)){
+	    do_byte4(f,"sta",&p->z,t);
+	    emit(f,"\tlda\t%s\n",mregnames[r]);
+	    do_byte3(f,"sta",&p->z,t);
+	    emit(f,"\tlda\t%s\n",mregnames[r2]);
+	    store_hibyte(f,&p->z,t);
+	    emit(f,"\tlda\t%s\n",mregnames[r3]);
+	    store_lobyte(f,&p->z,t);
+	  }else{
+	    store_lobyte(f,&p->z,t);
+	    emit(f,"\tlda\t%s\n",mregnames[r]);
+	    store_hibyte(f,&p->z,t);
+	    emit(f,"\tlda\t%s\n",mregnames[r2]);
+	    do_byte3(f,"sta",&p->z,t);
+	    emit(f,"\tlda\t%s\n",mregnames[r3]);
+	    do_byte4(f,"sta",&p->z,t);
+	  }
+	}else{
+	  if(!ISCHAR(t))
+	    emit(f,"\tldx\t%s\n",mregnames[r]);
+	  if(ISCHAR(t)||indirect(&p->z))
+	    store_acc(f,&p->z,t);
+	  else{
+	    store_lobyte(f,&p->z,t);
+	    if(!isreg(z)||p->z.reg!=rax){
+	      emit(f,"\tstx\t");
+	      emit_hibyte(f,&p->z,t);
+	      emit(f,"\n");
+	    }
+	  }
+	}
+	continue;
+      }
+
+      if((c>=OR&&c<=AND)||(c>=LSHIFT&&c<=MOD)||c==ADDI2P||c==SUBIFP){
+	char *s;int t2=t,pt=p->typf2;
+	if(!isacc(z))
+	  get_acc(f,p,CHAR);
+	if(c==ADDI2P||c==SUBIFP){
+	  if(c==ADDI2P) c=ADD; else c=SUB;
+	  t=UNSIGNED|INT;
+	  if((pt&NQ)==POINTER&&(p->q1.flags&(KONST|DREFOBJ))==KONST){
+	    eval_const(&p->q1.val,POINTER);
+	    insert_const(&p->q1.val,UNSIGNED|INT);
+	  }
+	}
+	if(c>=OR&&c<=AND)
+	  s=logicals[c-OR];
+	else
+	  s=arithmetics[c-LSHIFT];
+      
+	if(ISFLOAT(t)){
+	  if(!ieee) ierror(0);
+	  t&=NQ;
+	  if(regs[LAST_PAIR]) ierror(0);
+	  get_acc(f,p,INT);
+	  regs[LAST_PAIR]=1;
+	  load_address(f,LAST_PAIR,&p->q1,t);
+	  BSET(regused,t3);
+	  BSET(regused,t4);
+	  emit(f,"\tjsr\t%s__fload%c\n",idprefix,(t==FLOAT?'s':'d'));
+	  yval=NOVAL;
+	  load_address(f,LAST_PAIR,&p->q2,t);
+	  emit(f,"\tjsr\t%s__f%s%c\n",idprefix,ename[c],(t==FLOAT?'s':'d'));
+	  yval=NOVAL;
+	  load_address(f,LAST_PAIR,&p->z,t);
+	  emit(f,"\tjsr\t%s__fstore%c\n",idprefix,(t==FLOAT?'s':'d'));
+	  yval=NOVAL;
+	  regs[LAST_PAIR]=0;
+	  continue;
+	}else if(ISLONG(t)){
+	  if(c==ADD) emit(f,"\tclc\n");
+	  if(c==SUB) emit(f,"\tsec\n");
+	  load_lobyte(f,&p->q1,t);
+	  do_lobyte(f,s,&p->q2,t);
+	  store_lobyte(f,&p->z,t);
+	  load_hibyte(f,&p->q1,t);
+	  do_hibyte(f,s,&p->q2,t);
+	  store_hibyte(f,&p->z,t);
+	  do_byte3(f,"lda",&p->q1,t);
+	  do_byte3(f,s,&p->q2,t);
+	  do_byte3(f,"sta",&p->z,t);
+	  do_byte4(f,"lda",&p->q1,t);
+	  do_byte4(f,s,&p->q2,t);
+	  do_byte4(f,"sta",&p->z,t);
+	  continue;
+	}else if(ISCHAR(t)){
+	  load_acc(f,&p->q1,t);
+	  if(has_inc_a&&(c==ADD||c==SUB)&&(p->q2.flags&(KONST|DREFOBJ))==KONST){
+	    eval_const(&p->q2.val,t);
+	    if(zmeqto(vmax,Z1)||zmeqto(vmax,l2zm(2L))){
+	      if(zmeqto(vmax,l2zm(2L)))
+		emit(f,"\t%s\n",c==ADD?"ina":"dea");
+	      emit(f,"\t%s\n",c==ADD?"ina":"dea");
+	      store_acc(f,&p->z,t);
+	      continue;
+	    }
+	  }
+	  if(c==ADD) emit(f,"\tclc\n");
+	  if(c==SUB) emit(f,"\tsec\n");
+	  if(isreg(q2)&&ISIDX(p->q2.reg)){
+	    int r=get_reg(f,p,CHAR);
+	    emit(f,"\tst%s\t%s\n",mregnames[p->q2.reg],mregnames[r]);
+	    p->q2.flags=REG;
+	    p->q2.reg=r;
+	  }
+	  do_lobyte(f,s,&p->q2,t);
+	  store_acc(f,&p->z,t);
+	}else if(c==ADD||c==SUB){
+	  int a,r;long l=1;
+	  if(isconst(q2)){
+	    eval_const(&p->q2.val,t2);
+	    l=zm2l(vmax);
+	    l&=0xff00;
+	  }
+	  if(isreg(z)&&p->z.reg==rax) a=1; else a=0;
+	  if((t2&NU)==CHAR&&(p->q2.flags&(KONST|DREFOBJ))!=KONST){
+	    emit(f,"\tldx\t#0\n");
+	  }
+	  if((t2&NU)==CHAR&&(p->q2.flags&(KONST|DREFOBJ))!=KONST){
+	    load_lobyte(f,&p->q2,t);
+	    emit(f,"\tbpl\t%s%d\n",labprefix,++label);
+	    emit(f,"\tdex\n");
+	    emit(f,"%s%d:\n",labprefix,label);
+	    if(c==ADD){
+	      if(c==ADD) emit(f,"\tclc\n"); else emit(f,"\tsec\n");
+	      do_lobyte(f,s,&p->q1,t);
+	      if(isacc(z))
+		emit(f,"\tpha\n");
+	      else
+		store_lobyte(f,&p->z,t);
+	      emit(f,"\ttxa\n");
+	      do_hibyte(f,s,&p->q1,t);
+	      store_hibyte(f,&p->z,t);
+	      if(ISFPOINTER(pt)&&!compare_objects(&p->q1,&p->z)){
+		do_byte3(f,"lda",&p->q1,pt);
+		do_byte3(f,"sta",&p->z,pt);
+	      }
+	      if(isacc(z))
+		emit(f,"\tpla\n");
+	      continue;
+	    }
+	    r=get_reg(f,p,CHAR);
+	    emit(f,"\tstx\t%s\n",mregnames[r]);
+	  }
+	  load_lobyte(f,&p->q1,t);
+	  if(c==ADD) emit(f,"\tclc\n"); else emit(f,"\tsec\n");
+	  do_lobyte(f,s,&p->q2,t2);
+	  store_lobyte(f,&p->z,t);
+	  if(l==0&&isreg(q1)&&isreg(z)&&p->q1.reg==p->z.reg){
+	    if(c==ADD){
+	      emit(f,"\tbcc\t%s%d\n",labprefix,++label);
+	      if(a)
+		emit(f,"\tinx\n");
+	      else{
+		/*if(!reg_pair(p->z.reg,&rp)) ierror(0);*/
+		emit(f,"\tinc\t%s+1\n",mregnames[p->z.reg]);
+	      }
+	    }else{
+	      emit(f,"\tbcs\t%s%d\n",labprefix,++label);
+	      if(a)
+		emit(f,"\tdex\n");
+	      else{
+		if(!reg_pair(p->z.reg,&rp)) ierror(0);
+		emit(f,"\tdec\t%s\n",mregnames[rp.r2]);
+	      }
+	    }
+	    emit(f,"%s%d:\n",labprefix,label);
+	  }else{
+	    if(a==1) emit(f,"\tpha\n");
+	    if((t2&NQ)==CHAR){
+	      if(t2&UNSIGNED){
+		load_hibyte(f,&p->q1,t);
+		emit(f,"\t%s\t#0\n",s);
+	      }else{
+		load_hibyte(f,&p->q1,t);
+		if((p->q2.flags&(KONST|DREFOBJ))==KONST){
+		  eval_const(&p->q2.val,t2);
+		  if(zmleq(Z0,vmax))
+		    emit(f,"\t%s\t#0\n",s);
+		  else
+		    emit(f,"\t%s\t#255\n",s);
+		}else{
+		  emit(f,"\t%s\t%s\n",s,mregnames[r]);
+		}
+	      }
+	    }else{
+	      load_hibyte(f,&p->q1,t);
+	      do_hibyte(f,s,&p->q2,t2);
+	    }
+	    store_hibyte(f,&p->z,t);
+	    if(a==1) emit(f,"\tpla\n");
+	    if(ISFPOINTER(pt)&&p->code!=SUBPFP){
+	      if(!compare_objects(&p->q1,&p->z)){
+		do_byte3(f,"lda",&p->q1,FPOINTER);
+		do_byte3(f,"sta",&p->z,FPOINTER);
+	      }
+	    }
+	  }
+	}else{
+	  if(isacc(q1))
+	    emit(f,"\tpha\n");
+	  load_hibyte(f,&p->q1,t);
+	  do_hibyte(f,s,&p->q2,t);
+	  store_hibyte(f,&p->z,t);
+	  if(isacc(q1))
+	    emit(f,"\tpla\n");
+	  load_lobyte(f,&p->q1,t);
+	  do_lobyte(f,s,&p->q2,t);
+	  store_lobyte(f,&p->z,t);
+	}
+	continue;
+      }
+      pric2(stdout,p);
+      ierror(0);
+    }
+
+    function_bottom(f,v,localsize);
+    
+    for(c=1;c<=MAXR;c++){
+      if(regsa[c]||regused[c]){
+	BSET(regs_modified,c);
+      }
+    }
+
+    if(stack_valid){
+      if(!v->fi) v->fi=new_fi();
+      v->fi->flags|=ALL_STACK;
+      v->fi->stack1=stack;
+    }
+  }
+
+  free_IC(mi);
+
+  emit(f,"; stacksize=%lu%s\n",zum2ul(stack),stack_valid?"":"+??");
+}
+
+int shortcut(int code,int typ)
+{
+  if(code==COMPARE/*||code==MULT*/||code==ADD||code==SUB||code==AND||code==OR||code==XOR||code==LSHIFT||code==RSHIFT||code==MINUS||code==KOMPLEMENT||code==NEGATION)
+    return 1;
+
+  return 0;
+}
+
+static int fattr(type *p,char *s)
+{
+  if(p->attr&&strstr(p->attr,s))
+    return 1;
+  if(p->next)
+    return fattr(p->next,s);
+  else
+    return 0;
+}
+
+int reg_parm(struct reg_handle *m, struct Typ *t,int vararg,struct Typ *d)
+{
+  int f;
+
+  if(vararg)
+    return 0;
+  f=t->flags&NQ;
+  if(OLDFP&&ISFLOAT(f)) return 0;
+  if(d&&fattr(d,"__stackparms__"))
+    return 0;
+  if(d&&fattr(d,"__cc65__")){
+    m->regs++;
+    printf("arg=%d cnt=%d\n",m->regs,d->exact->count);
+    if(m->regs==d->exact->count-1){
+      if(ISCHAR(t->flags))
+	return ra;
+      if(ISSHORT(t->flags))
+	return rax;
+    }
+    return 0;
+  }
+  if(ISCHAR(f)){
+    if(!t->exact){
+      if(m->regs>=GPR_ARGS-1)
+	return 0;
+      f=FIRST_GPR+m->regs;
+      m->regs+=2;
+      return f;
+    }else{
+      if(m->regs>=GPR_ARGS)
+	return 0;
+      else
+	return FIRST_GPR+m->regs++;
+    }
+  }
+  if(ISSHORT(f)||f==POINTER){
+    if(m->regs>=GPR_ARGS-1)
+      return 0;
+    else{
+      if(m->regs&1) m->regs+=1;
+      m->regs+=2;
+      return FIRST_PAIR+m->regs/2-1;
+    }
+  }
+  if(f==FPOINTER||f==LONG||f==FLOAT||(!ieee&&(f==DOUBLE||f==LDOUBLE))){
+    if(m->bregs>=4)
+      return 0;
+    else
+      return FIRST_BIG+m->bregs++;
+  }
+  if(f==LLONG||(ieee&&(f==DOUBLE||f==LDOUBLE))){
+    if(m->bregs>=3)
+      return 0;
+    else{
+      if(m->bregs&1)  m->bregs++;
+      m->bregs+=2;
+      return FIRST_BIGP+m->bregs/2-1;
+    }
+  }
+  return 0;
+}
+
+int handle_pragma(const char *s)
+{
+  static char sec[SECLEN];
+  int i;
+  if(sscanf(s,"section %127s",sec)==1){
+    if(!strcmp(sec,"default"))
+      use_sec=0;
+    else
+      use_sec=sec;
+    return 1;
+  }
+  if(sscanf(s,"bank %d",&i)==1){
+    use_bank=i;
+    return 1;
+  }
+}
+void cleanup_cg(FILE *f)
+{
+  int i;
+  struct fpconstlist *p=firstfpc;
+
+  if(f&&p){
+    emit(f,rodataname);emit(f,"\n");
+    section=RODATA;
+  }
+  while(p=firstfpc){
+    emit(f,"%s%d:\n\tword\t",labprefix,p->label);
+    if(ieee)
+      emit_ieee(f,&p->val,p->t);
+    else{
+      int words=zm2l(sizetab[p->t&NQ])/2;
+      eval_const(&p->val,p->t);
+      if(ISFLOAT(p->t)) cnv_fp();
+      for(i=0;i<words;i++){
+	emit(f,"%ld",zm2l(vmax)&0xffff);
+	if(i<words-1){emit(f,",");vmax=zmrshift(vmax,l2zm(16L));}
+      }
+      emit(f,"\n");
+      /*emit(f,"%ld,%ld\n",zm2l(vmax)&0xffff,zm2l(zmrshift(vmax,l2zm(16L)))&0xffff);*/
+    }
+    firstfpc=p->next;
+    free(p);
+  }
+
+  emit(f,"\tzpage\t%s\n",mregnames[sp]);
+  for(i=FIRST_GPR;i<=LAST_GPR;i++)
+    emit(f,"\tzpage\t%s\n",mregnames[i]);
+  for(i=FIRST_BIG;i<=LAST_BIG;i++)
+    emit(f,"\tzpage\t%s\n",mregnames[i]);
+
+}
+void cleanup_db(FILE *f)
+{
+  if(f) section=-1;
+}
+
+static char *zops[]={
+  "adc","and","asl","bit","eor","lda","ora",
+  "tax","txa","tay","tya","sbc"};
+
+static int setszflag(char *op)
+{
+  int i;
+  for(i=0;i<sizeof(zops)/sizeof(zops[0]);i++)
+    if(!strcmp(op,zops[i]))
+      return 1;
+  return 0;
+}
+
+static char *zxops[]={
+  "tax","txa","ldx","inx","dex"};
+
+static int setszxflag(char *op)
+{
+  int i;
+  for(i=0;i<sizeof(zxops)/sizeof(zxops[0]);i++)
+    if(!strcmp(op,zxops[i]))
+      return 1;
+  return 0;
+}
+
+enum peepf { NEEDSAME = 1, REMOVE1ST = 2};
+struct peeps {char *s1,*s2,*r;enum peepf flags;};
+
+
+
+int emit_peephole(void)
+{
+  int entries,i,j;
+  char *asmline[EMIT_BUF_DEPTH];
+  char buf1[1024],buf2[1024];
+  char op1[8],op2[8];
+  static char ca[1024],cx[1024],cy[1024],cz[1024];
+  static int rm,disabled;
+
+  fprintf(stderr,"Called emit_peephole()\n");
+  
+  static struct peeps elim[]={
+    "lda","sta",0,NEEDSAME,
+    "ldx","stx",0,NEEDSAME,
+    "sta","sta",0,NEEDSAME,
+    "stx","stx",0,NEEDSAME,
+    "sta","lda",0,NEEDSAME,
+    "stx","ldx",0,NEEDSAME,
+    "txa","tax",0,0,
+    "tax","txa",0,0,
+    "lda","lda",0,REMOVE1ST,
+    "ldx","ldx",0,REMOVE1ST,
+    "ldy","ldy",0,REMOVE1ST,
+    "ldz","ldz",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,
+    "taz","ldz",0,REMOVE1ST,
+    "tax","ldx",0,REMOVE1ST,
+    "txa","lda",0,REMOVE1ST,
+    "tya","lda",0,REMOVE1ST,
+    "tza","lda",0,REMOVE1ST,
+    "lda","ldx","\ttax\n",NEEDSAME,
+    "lda","ldy","\ttay\n",NEEDSAME,
+    "ldx","lda","\ttxa\n",NEEDSAME,
+    "ldy","lda","\ttya\n",NEEDSAME,
+    "sta","ldx","\ttax\n",NEEDSAME,
+    "sta","ldy","\ttay\n",NEEDSAME,
+    "stx","lda","\ttxa\n",NEEDSAME,
+    "sty","lda","\ttya\n",NEEDSAME,
+
+  };
+
+  if(nopeep) return 0;
+
+  i=emit_l;
+  if(emit_f==0)
+    entries=i-emit_f+1;
+  else
+    entries=EMIT_BUF_DEPTH;
+  asmline[0]=emit_buffer[i];
+
+  if(!strcmp(asmline[0],";startinline\n")) disabled=1;
+  if(!strcmp(asmline[0],";endinline\n")) disabled=0;
+  if(disabled) return 0;
+
+  buf1[0]=0;op1[0]=0;
+  if((j=sscanf(asmline[0]," %6s %999s",op1,buf1))>=1){
+    printf("a=%s x=%s y=%s, z=%s\n",ca,cx,cy,cz);
+    printf("\t\t%s %s\n",op1,buf1);
+    if(!strcmp(op1,"sta")) {
+      // Work out when we are accessing variables on the stack
+      if (!strcmp(buf1,"(sp),y")) {
+	// We invalidate this when Y changes
+	snprintf(ca,1024,"(sp),y",cy);
+      } 
+    } else if(!strcmp(op1,"sta")){
+      // Remove writes to wherever A was loaded from
+      if (!strcmp(buf1,ca)) {
+	remove_asm();
+	return rm=1;
+      }
+    } else if(!strcmp(op1,"lda")){
+      if(buf1[0]=='#'){
+	if(!rm&&!strcmp(buf1,ca)){remove_asm();return rm=1;}
+	strcpy(ca,buf1);
+      }else {
+	// Work out when we are accessing variables on the stack
+	if (!strcmp(buf1,"(sp),y")) {	 
+	  if(!strcmp(buf1,ca)){
+	    remove_asm();
+	    return rm=1;
+	  }
+	  snprintf(ca,1024,"(sp),y",cy);
+	}
+	// Similarly look for register loads
+	// We can sometimes remove some of those, too.
+	if ((strlen(buf1)>1)&&(buf1[0]=='r')) {
+	  if (strcmp(ca,buf1)) 
+	    snprintf(ca,1024,"%s",buf1);
+	  else {
+	    // Don't re-load A with the same contents it already has
+	    remove_asm();
+	    return rm=1;
+	  }
+	}
+      }
+    }else if(!strcmp(op1,"ldx")){
+      if(buf1[0]=='#'){
+	if(!rm&&!strcmp(buf1,cx)){remove_asm();return rm=1;}
+	strcpy(cx,buf1);
+      }else cx[0]=0;
+    }else if(!strcmp(op1,"ldy")){
+      if(buf1[0]=='#'){
+	if(!rm&&!strcmp(buf1,cy)){remove_asm();return rm=1;}
+	strcpy(cy,buf1);
+      }else cy[0]=0;
+    }else if(!strcmp(op1,"ldz")){
+      if(buf1[0]=='#'){
+	if(!rm&&!strcmp(buf1,cz)){remove_asm();return rm=1;}
+	strcpy(cz,buf1);
+      }else cz[0]=0;
+    }else{
+      // TODO: PGS: Add the AXYZ operations to the clobber lists.
+      //            Will we need to handle them specially?
+      static char clobbernone[]="clc cld cli clv cmp cpx cpy dec inc nop pha php plp sec sed sei sta stx sty stz";
+      static char clobbera[]="adc and asl eor lsr ora pla rol ror sbc txa tya tza neg";
+      static char clobberx[]="dex inx tax tsx";
+      static char clobbery[]="dey iny tay";
+      static char clobberz[]="dez inz taz";
+      if(strstr(clobbernone,op1)){
+	// Invalidate A holding a stack variable byte if SP changes
+	if (strstr(buf1,"sp")) {
+	  printf("buf1='%s'\n",buf1);
+	  if (strstr(ca,"(sp),y")) ca[0]=0;
+	}	
+      }else if(strstr(clobbera,op1))
+	ca[0]=0;
+      else if(strstr(clobberx,op1))
+	cx[0]=0;
+      else if(strstr(clobbery,op1)) {
+	cy[0]=0;
+	// Invalidate A holding a stack variable byte if Y changes
+	if (strstr(ca,"(sp),y")) ca[0]=0;
+      }
+      else if(strstr(clobberz,op1))
+	cz[0]=0;
+      else
+	ca[0]=cx[0]=cy[0]=cz[0]=0;
+    }
+  }else{
+    ca[0]=cx[0]=cy[0]=cz[0]=0;
+  }
+
+  rm=0;
+
+  if(sscanf(asmline[0]," %6s %999s",op1,buf1)==2&&!strcmp(op1,"and")&&!strcmp(buf1,"#0")){
+    strcpy(asmline[0],"\tlda\t#0\n");
+    return rm=1;
+  }
+
+  if(entries>=2){
+    i--;
+    if(i<0) i=EMIT_BUF_DEPTH-1;
+    asmline[1]=emit_buffer[i];
+
+
+    if(!strcmp(asmline[0],"; volatile barrier\n")&&!strcmp(asmline[0],asmline[1])){
+      remove_asm();
+      return rm=1;
+    }
+
+    if(sscanf(asmline[0]," %6s",op1)==1&&!strcmp(op1,"rts")&&
+       sscanf(asmline[1]," %6s %999s",op2,buf2)==2&&!strcmp(op2,"jsr")){
+      sprintf(asmline[1],"\tjmp\t%s\n",buf2);
+      remove_asm();
+      return rm=1;
+    }
+
+    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(elim[j].r){
+	    strcpy(asmline[0],elim[j].r);
+	  }else{
+	    if(elim[j].flags&REMOVE1ST)
+	      strcpy(asmline[1],asmline[0]);
+	    remove_asm();
+	  }
+	  return rm=1;
+	}
+      }else{
+	if(sscanf(asmline[1]," %6s",op1)==1&&
+	   sscanf(asmline[0]," %6s",op2)==1&&
+	   !strcmp(op1,elim[j].s1)&&!strcmp(op2,elim[j].s2)){
+	  if(elim[j].flags&REMOVE1ST)
+	    strcpy(asmline[1],asmline[0]);
+	  remove_asm();
+	  return rm=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 0
+      if(!strcmp(op1,"lda")&&buf1[0]=='#'){
+	if(sscanf(asmline[1]," %6s %999s",op2,buf2)==2&&
+	   !strcmp(op2,"sta")){
+	  if(sscanf(asmline[2]," %6s %999s",op2,buf2)==2&&
+	     !strcmp(op2,"lda")&&!strcmp(buf1,buf2)){
+	    remove_asm();
+	    return rm=1;
+	  }
+	}
+      }
+#endif
+      if(!strcmp(op1,"beq")||!strcmp(op1,"bne")){
+	if(sscanf(asmline[1]," %6s %999s",op2,buf2)==2&&
+	   !strcmp(op2,"cmp")&&!strcmp(buf2,"#0")){
+	  if(sscanf(asmline[2]," %6s",op2)==1&&
+	     setszflag(op2)){
+	    strcpy(asmline[1],asmline[0]);
+	    remove_asm();
+	    return rm=1;
+	  }
+	}
+      }
+      if(!strcmp(op1,"beq")||!strcmp(op1,"bne")){
+	if(sscanf(asmline[1]," %6s %999s",op2,buf2)==2&&
+	   !strcmp(op2,"cpx")&&!strcmp(buf2,"#0")){
+	  if(sscanf(asmline[2]," %6s",op2)==1&&
+	     setszxflag(op2)){
+	    strcpy(asmline[1],asmline[0]);
+	    remove_asm();
+	    return rm=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)&&!ieee)){
+      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(ISSHORT(t)&&c!=MULT&&c!=DIV&&c!=MOD&&!ISFLOAT(t2))
+      return 0;
+    if(ISLONG(t)&&c!=MULT&&c!=DIV&&c!=MOD&&!ISFLOAT(t2))
+      return 0;
+
+    if(!ieee&&ISFLOAT(t)) t=FLOAT;
+    if(t==LDOUBLE) t=DOUBLE;
+    if(t2==LDOUBLE) t2=DOUBLE;
+    if(!ieee&&ISFLOAT(t2)) t2=FLOAT;
+    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)==INT||(t&NQ)==LONG||(t&NQ)==LLONG||(!ieee&&ISFLOAT(t))){
+      if((c>=LSHIFT&&c<=MOD)||(c>=OR&&c<=AND)||c==KOMPLEMENT||c==MINUS){
+        if(t==(UNSIGNED|LLONG)&&(c==MULT||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 if(t==(UNSIGNED|INT)&&(c==DIV||c==MOD||c==RSHIFT)){
+          sprintf(fname,"__%suint16",ename[c]);
+          ret=fname;
+        }else if((t&NQ)==INT){
+          sprintf(fname,"__%sint16",ename[c]);
+          ret=fname;
+        }else{
+          sprintf(fname,"__%s%s%s%ld",ename[c],(t&UNSIGNED)?"u":"",ISFLOAT(t)?"flt":"int",zm2l(sizetab[t&NQ])*8);
+          ret=fname;
+        }
+      }
+    }
+  }
+
+  return ret;
+}
+
+
+int pointer_varadr(Var *v)
+{
+  int b=bank(v);
+  if(b>=0&&b!=bankcnum&&!NOBANKVARS){
+    if(cur_funcv&&bank(cur_funcv)!=b)
+      return FPOINTER;
+  }
+  return pointer_type(v->vtyp);
+}
+
+int pointer_type(struct Typ *p)
+{
+  struct Typ *merk=p;
+  if(!p) ierror(0);
+  if(LARGE) return FPOINTER;
+  while(ISARRAY(p->flags)||ISFUNC(p->flags)) p=p->next;
+  if(p->attr){
+    char *s;
+    if(strstr(p->attr,STR_HUGE)) return HPOINTER;
+    if(strstr(p->attr,STR_FAR)) return FPOINTER;
+    if(strstr(p->attr,STR_NEAR)) return POINTER;
+  }
+  return POINTER;
+}
+
+unsigned char cbmconv(unsigned char x)
+{
+  static unsigned char ctab[256]={
+    0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x14,0x09,0x0D,0x11,0x93,0x0A,0x0E,0x0F,
+    0x10,0x0B,0x12,0x13,0x08,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
+    0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
+    0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
+    0x40,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
+    0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0x5B,0xBF,0x5D,0x5E,0xA4,
+    0xAD,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
+    0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0xB3,0xDD,0xAB,0xB1,0xDF,
+    0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
+    0x90,0x91,0x92,0x0C,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
+    0xA0,0xA1,0xA2,0xA3,0x5F,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0x7D,0xAC,0x60,0xAE,0xAF,
+    0xB0,0x7E,0xB2,0x7B,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0x5C,
+    0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
+    0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0xDC,0x7C,0xDE,0x7F,
+    0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
+    0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
+  };
+
+  static unsigned char atab[]={0xfd,8,0x7f,0x9b,11,0x7d};
+
+  if(cbmascii)
+    return ctab[x&255];
+  else if(atascii&&x>=7&&x<=12)
+    return atab[x-7];
+  else
+    return x;
+}
+
+void insert_const(union atyps *p,int t)
+/*  Traegt Konstante in entprechendes Feld ein.       */
+{
+  if(!p) ierror(0);
+/*  *p = (union atyps) 0 ; /* rfi: clear unused bits */
+  t&=NU;
+  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|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==POINTER) {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>=CHAR&&f<=LLONG)){
+    if(!(t&UNSIGNED)){
+      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==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==POINTER)
+	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==CHAR){fprintf(f,"C");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==POINTER){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)
+/*  Gibt atyps aus.                                     */
+{
+  t&=NU;
+  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==POINTER){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)|POINTER);
+        if(strstr(attr,STR_FAR))
+          p->flags=((p->flags&~NU)|FPOINTER);
+        if(strstr(attr,STR_HUGE))
+          p->flags=((p->flags&~NU)|HPOINTER);
+      }
+    }
+    p=p->next;
+  }
+}
+
+void add_var_hook_post(Var *v)
+{
+  if(use_sec&&(v->storage_class==STATIC||v->storage_class==EXTERN)){
+    char buf[SECLEN+32];
+    sprintf(buf,"section(\"%s\");",use_sec);
+    add_attr(&v->vattr,buf);
+  }
+  if(use_bank>=0&&(v->storage_class==STATIC||v->storage_class==EXTERN)){
+    char buf[64];
+    /*sprintf(buf,"section(\"bank%d\");bank(%d)",use_bank,use_bank);*/
+    sprintf(buf,"bank(%d)",use_bank);
+    add_attr(&v->vattr,buf);
+  }
+}
+
+int decide_reverse(zmax v)
+{
+  if(zmeqto(v,Z1)||zmeqto(v,l2zm(2L)))
+    return 1;
+  if(optspeed)
+    if(zmeqto(v,l2zm(4L))||zmeqto(v,l2zm(8L))||zmeqto(v,l2zm(256L))||zmeqto(v,l2zm(512L)))
+      return 1;
+  
+  return 0;
+}
+
+static int is_single_eff_ic(struct IC *p)
+{
+  struct Var *v,*idx;
+  if(p->code!=ADDI2P||(p->typf2&NQ)!=POINTER)
+    return 0;
+  if(!(p->q2.flags&KONST)){
+    if((p->typf&NU)!=(UNSIGNED|CHAR))
+      return 0;
+    if((p->q2.flags&(VAR|DREFOBJ))!=VAR)
+      return 0;
+    if(p->q2.v->storage_class!=AUTO&&p->q2.v->storage_class!=REGISTER)
+      return 0;
+    idx=p->q2.v;
+  }else{
+    idx=0;
+    eval_const(&p->q2.val,p->typf);
+    /* TODO: more precise check considering data type useful? */
+    if(!zmleq(vumax,l2zm(255L)))
+      return 0;
+    return 1;
+  }
+  if(p->q1.flags&DREFOBJ)
+    return 0;
+  if((p->z.flags&(VAR|DREFOBJ))!=VAR)
+    return 0;
+  if(p->z.v->storage_class==STATIC||p->z.v->storage_class==EXTERN)
+    return 0;
+  v=p->z.v;
+  for(p=p->next;p;p=p->next){
+    int c=p->code;
+    if(c==LABEL||(c>=BEQ&&c<=BRA))
+      return 1; /* TODO: how elaborate should we test? */
+    if((p->q1.flags&VAR)&&p->q1.v==v){
+      if(p->q1.flags&DREFOBJ)
+        return 1;
+      else
+        return 0;
+    }
+    if((p->q2.flags&VAR)&&p->q2.v==v){
+      if(p->q2.flags&DREFOBJ)
+        return 1;
+      else
+        return 0;
+    }
+    if((p->z.flags&VAR)&&p->z.v==v){
+      if(p->z.flags&DREFOBJ)
+        return 1;
+      else
+        return 0;
+    }
+    if((p->z.flags&VAR)&&p->z.v==idx)
+      return 0;
+  }
+  return 0;
+}
+
+void mark_eff_ics(void)
+{
+  struct IC *p;
+  for(p=first_ic;p;p=p->next){
+    if(is_single_eff_ic(p))
+      p->flags|=EFF_IC;
+    else
+      p->flags&=~EFF_IC;
+  }
+}
diff --git a/machines/m65/machine.dt b/machines/m65/machine.dt
new file mode 100755
index 0000000..eab38c9
--- /dev/null
+++ b/machines/m65/machine.dt
@@ -0,0 +1,16 @@
+S8BS
+S8BU
+S16BSLE S16BSBE
+S16BULE S16BUBE
+S16BSLE S16BSBE
+S16BULE S16BUBE
+S32BSLE S32BSBE
+S32BULE S32BUBE
+S64BSLE S64BSBE
+S64BULE S64BUBE
+S32BIEEELE
+S64BIEEELE
+S64BIEEELE
+S16BULE S16BUBE
+
+
diff --git a/machines/m65/machine.h b/machines/m65/machine.h
new file mode 100755
index 0000000..ca54ff9
--- /dev/null
+++ b/machines/m65/machine.h
@@ -0,0 +1,269 @@
+/*  MEGA65 / 45GS02 backend for vbcc
+    (c) Volker Barthelmann 2020
+    (c) Paul Gardner-Stephen 2020
+
+*/
+
+/* built-time configurable options: */
+#define NUM_GPRS 32
+#define NUM_PAIRS (NUM_GPRS/2)
+#define NUM_BIG 4
+#define NUM_BIGP (NUM_BIG/2)
+#define FIXED_SP 1
+
+#include "dt.h"
+
+#undef CHAR
+#undef SHORT
+#undef INT
+#undef LONG
+#undef LLONG
+#undef FLOAT
+#undef DOUBLE
+#undef LDOUBLE
+#undef VOID
+#undef POINTER
+#undef ARRAY
+#undef STRUCT
+#undef UNION
+#undef ENUM
+#undef FUNKT
+#undef BOOL
+#undef MAXINT
+#undef MAX_TYPE
+
+#define CHAR 1
+#define SHORT 2
+#define INT 3
+#define LONG 4
+#define LLONG 5
+#define FLOAT 6
+#define DOUBLE 7
+#define LDOUBLE 8
+#define VOID 9
+#define POINTER 10
+#define FPOINTER 11
+#define HPOINTER 12
+#define ARRAY 13
+#define STRUCT 14
+#define UNION 15
+#define ENUM 16
+#define FUNKT 17
+#define BOOL 18
+
+#define MAXINT 19
+
+#define MAX_TYPE MAXINT
+
+
+#define POINTER_TYPE(x) pointer_type(x)
+#define POINTER_VARADR(x) pointer_varadr(x)
+extern int pointer_type();
+extern int pointer_varadr();
+#define ISPOINTER(x) ((x&NQ)>=POINTER&&(x&NQ)<=HPOINTER)
+#define ISSCALAR(x) ((x&NQ)>=CHAR&&(x&NQ)<=HPOINTER)
+#define ISINT(x) ((x&NQ)>=CHAR&&(x&NQ)<=LLONG)
+#define PTRDIFF_T(x) ((x)==HPOINTER?LONG:INT)
+
+typedef zllong zmax;
+typedef zullong zumax;
+
+union atyps{
+  zchar vchar;
+  zuchar vuchar;
+  zshort vshort;
+  zushort vushort;
+  zint vint;
+  zuint vuint;
+  zlong vlong;
+  zulong vulong;
+  zllong vllong;
+  zullong vullong;
+  zmax vmax;
+  zumax vumax;
+  zfloat vfloat;
+  zdouble vdouble;
+  zldouble vldouble;
+};
+
+
+/* internally used by the backend */
+#define FIRST_GPR 10
+#define LAST_GPR (FIRST_GPR+NUM_GPRS-1)
+#define FIRST_PAIR (LAST_GPR+1)
+#define LAST_PAIR (FIRST_PAIR+NUM_PAIRS-1)
+#define FIRST_BIG (LAST_PAIR+1)
+#define LAST_BIG (FIRST_BIG+NUM_BIG-1)
+#define FIRST_BIGP (LAST_BIG+1)
+#define LAST_BIGP (FIRST_BIGP+NUM_BIGP-1)
+
+/*  This struct can be used to implement machine-specific           */
+/*  addressing-modes.                                               */
+/*  Currently possible are (const,gpr) and (gpr,gpr)                */
+struct AddressingMode{
+  int flags;
+  int base;
+  int idx;
+  long offset;
+  void *v;
+};
+
+/*  The number of registers of the target machine.                  */
+#define MAXR LAST_BIGP
+
+/*  Number of commandline-options the code-generator accepts.       */
+#define MAXGF 20
+
+/*  If this is set to zero vbcc will not generate ICs where the     */
+/*  target operand is the same as the 2nd source operand.           */
+/*  This can sometimes simplify the code-generator, but usually     */
+/*  the code is better if the code-generator allows it.             */
+#define USEQ2ASZ 1
+
+/*  This specifies the smallest integer type that can be added to a */
+/*  pointer.                                                        */
+#define MINADDI2P CHAR
+
+/*  If the bytes of an integer are ordered most significant byte    */
+/*  byte first and then decreasing set BIGENDIAN to 1.              */
+#define BIGENDIAN 0
+
+/*  If the bytes of an integer are ordered lest significant byte    */
+/*  byte first and then increasing set LITTLEENDIAN to 1.           */
+#define LITTLEENDIAN 1
+
+/*  Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive.    */
+
+/*  If switch-statements should be generated as a sequence of       */
+/*  SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1.      */
+/*  This can yield better code on some machines.                    */
+#define SWITCHSUBS 0
+
+/*  In optimizing compilation certain library memcpy/strcpy-calls   */
+/*  with length known at compile-time will be inlined using an      */
+/*  ASSIGN-IC if the size is less or equal to INLINEMEMCPY.         */
+/*  The type used for the ASSIGN-IC will be UNSIGNED|CHAR.          */
+#define INLINEMEMCPY 1024
+
+/*  Parameters are sometimes passed in registers without __reg.     */
+#define HAVE_REGPARMS 1
+
+/*  Parameters on the stack should be pushed in order rather than   */
+/*  in reverse order.                                               */
+#define ORDERED_PUSH FIXED_SP
+
+/*  Structure for reg_parm().                                       */
+struct reg_handle{
+  int regs;
+  int bregs;
+};
+
+/*  We have some target-specific variable attributes.               */
+#define HAVE_TARGET_ATTRIBUTES
+
+/* We have target-specific pragmas */
+#define HAVE_TARGET_PRAGMAS
+
+/*  We keep track of all registers modified by a function.          */
+#define HAVE_REGS_MODIFIED 1
+
+/* We have a implement our own cost-functions to adapt 
+   register-allocation */
+#define HAVE_TARGET_RALLOC 1
+#define cost_move_reg(x,y) 3
+// MEGA65 CPU has one wait-state on reads when CPU is at full speed
+#define cost_load_reg(x,y) 5
+#define cost_save_reg(x,y) 4
+#define cost_pushpop_reg(x) 6
+
+/* size of buffer for asm-output, this can be used to do
+   peephole-optimizations of the generated assembly-output */
+#define EMIT_BUF_LEN 1024 /* should be enough */
+/* number of asm-output lines buffered */
+#define EMIT_BUF_DEPTH 8
+
+/*  We have no asm_peephole to optimize assembly-output */
+#define HAVE_TARGET_PEEPHOLE 1
+
+/* we do not have a mark_eff_ics function, this is used to prevent
+   optimizations on code which can already be implemented by efficient
+   assembly */
+#undef HAVE_TARGET_EFF_IC
+
+/* we have additional types */
+#define HAVE_EXT_TYPES
+#define HAVE_TGT_PRINTVAL
+
+/* we do not need extra elements in the IC */
+#undef HAVE_EXT_IC
+
+/* we do not use unsigned int as size_t (but unsigned long, the default) */
+#define HAVE_INT_SIZET 1
+
+/* we do not need register-pairs */
+#define HAVE_REGPAIRS 1
+
+
+/* do not create CONVERT ICs from integers smaller than int to floats */
+#define MIN_INT_TO_FLOAT_TYPE INT
+
+/* do not create CONVERT ICs from floats to ints smaller than int */
+#define MIN_FLOAT_TO_INT_TYPE INT
+
+/* do not create CONVERT_ICs from floats to unsigned integers */
+#define AVOID_FLOAT_TO_UNSIGNED 0
+
+/* do not create CONVERT_ICs from unsigned integers to floats */
+#define AVOID_UNSIGNED_TO_FLOAT 0
+
+/* convert multiplications/division by powers of two to shifts */
+#define HAVE_POF2OPT 1
+
+/* We use builtin libcalls for some operations */
+#define HAVE_LIBCALLS 1
+
+/* Use char for return of comparison libcalls */
+#define LIBCALL_CMPTYPE CHAR
+
+/* We prefer BNE rather than BGT. */
+#define HAVE_WANTBNE 1
+
+#define BESTCOPYT CHAR
+
+#define HAVE_AOS4 1
+
+#define CHARCONV(x) cbmconv(x)
+unsigned char cbmconv(unsigned char);
+
+#define ALLOCVLA_REG FIRST_PAIR
+#define ALLOCVLA_INLINEASM "\tlda\tsp\n"\
+                           "\tsec\n"\
+                           "\tsbc\tr0\n"\
+                           "\tsta\tsp\n"\
+                           "\tlda\tsp+1\n"\
+                           "\tsbc\tr1\n"\
+                           "\tsta\tsp+1\n"\
+                           "\tlda\tsp\n"\
+                           "\tclc\n"\
+                           "\tldx\tsp+1\n"\
+                           "\tadc\t#___fo\n"\
+                           "\tbcc\t*+3\n"\
+                           "\tinx\n"
+
+#define FREEVLA_REG FIRST_PAIR
+#define FREEVLA_INLINEASM "\tlda\tr0\n"\
+                          "\tsta\tsp\n"\
+                          "\tlda\tr1\n"\
+                          "\tsta\tsp+1\n"
+
+#define OLDSPVLA_INLINEASM "\tlda\tsp+1\n"\
+                           "\ttax\n"\
+                           "\tlda\tsp"
+
+#define FPVLA_REG (LAST_PAIR-2)
+
+#define HAVE_TARGET_VARHOOK_POST 1
+
+#define HAVE_DECIDE_REVERSE 1
+
+#define HAVE_TARGET_EFF_IC 1
diff --git a/machines/m65/merge.c b/machines/m65/merge.c
new file mode 100755
index 0000000..2e43d73
--- /dev/null
+++ b/machines/m65/merge.c
@@ -0,0 +1,4995 @@
+/*  MEGA65 45GS02 backend for vbcc
+    (c) Volker Barthelmann 2020
+    (c) Paul Gardner-Stephen 2020
+
+*/                                                                             
+
+#include "supp.h"
+#include "vbc.h"
+
+#include <math.h>
+
+static char FILE_[]=__FILE__;
+
+/*  Public data that MUST be there.                             */
+
+/* Name and copyright. */
+char cg_copyright[]="vbcc 45GS02 (MEGA65) code-generator V0.1 (c) in 2020 by Volker Barthelmann, Paul Gardner-Stephen";
+
+/*  Commandline-flags the code-generator accepts:
+    0: just a flag
+    VALFLAG: a value must be specified
+    STRINGFLAG: a string can be specified
+    FUNCFLAG: a function will be called
+    apart from FUNCFLAG, all other versions can only be specified once */
+int g_flags[MAXGF]={0,0,
+		    VALFLAG,0,0,
+		    0,0,
+		    VALFLAG,VALFLAG,0,0,
+		    VALFLAG,0,0,0,
+		    0,0,0,
+		    0};
+
+/* the flag-name, do not use names beginning with l, L, I, D or U, because
+   they collide with the frontend */
+char *g_flags_name[MAXGF]={"std-syntax","no-rax",
+			   "volatile-regs","ieee","no-peephole",
+			   "cbmascii","softstack",
+			   "reg-args","int-args","mainargs","no-bank-vars",
+			   "common-banknr","btmp-zpage","oldfp","large",
+			   "glob-acc","avoid-bank-switch","manual-banking",
+			   "atascii"};
+
+/* the results of parsing the command-line-flags will be stored here */
+union ppi g_flags_val[MAXGF];
+
+/*  Alignment-requirements for all types in bytes.              */
+zmax align[MAX_TYPE+1];
+
+/*  Alignment that is sufficient for every object.              */
+zmax maxalign;
+
+/*  CHAR_BIT for the target machine.                            */
+zmax char_bit;
+
+/*  sizes of the basic 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. will be initialized in init_cg(),
+    register number 0 is invalid, valid registers start at 1 */
+char *regnames[MAXR+1];
+
+/*  The Size of each register in bytes.                         */
+zmax regsize[MAXR+1];
+
+/*  a 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];
+
+/* specifies the priority for the register-allocator, if the same
+   estimated cost-saving can be obtained by several registers, the
+   one with the highest priority will be used */
+int reg_prio[MAXR+1];
+
+/* an empty reg-handle representing initial state */
+struct reg_handle empty_reg_handle={0,0};
+
+/* Names of target-specific variable attributes.                */
+char *g_attr_name[]={"__interrupt","__zpage","__nocpr",0};
+
+#define INTERRUPT 1
+#define ZPAGE 2
+#define NOCOMPRESS 4
+
+/****************************************/
+/*  Private data and functions.         */
+/****************************************/
+
+#define STDSYNTAX  (g_flags[0]&USEDFLAG)
+#define NORAX      (g_flags[1]&USEDFLAG)
+#define VOL_GPRS   ((g_flags[2]&USEDFLAG)?g_flags_val[2].l:NUM_GPRS/2)
+#define IEEE       (g_flags[3]&USEDFLAG)
+#define NOPEEP     (g_flags[4]&USEDFLAG)
+#define CBMASCII   (g_flags[5]&USEDFLAG)
+#define SOFTSTACK  (g_flags[6]&USEDFLAG)
+#define GPR_ARGS   ((g_flags[7]&USEDFLAG)?g_flags_val[7].l:8)
+#define MAINARGS   (g_flags[9]&USEDFLAG)
+#define NOBANKVARS (g_flags[10]&USEDFLAG)
+#define COMMONBANK ((g_flags[11]&USEDFLAG)?g_flags_val[11].l:0)
+#define BIGZPAGE   (g_flags[12]&USEDFLAG)
+#define OLDFP      (g_flags[13]&USEDFLAG)
+#define LARGE      (g_flags[14]&USEDFLAG)
+#define GLOBACC    (g_flags[15]&USEDFLAG)
+#define NOSWITCH   (g_flags[16]&USEDFLAG)
+#define NOBANKING  (g_flags[17]&USEDFLAG)
+#define ATASCII    (g_flags[18]&USEDFLAG)
+
+
+
+#define STR_NEAR "near"
+#define STR_FAR "far"
+#define STR_HUGE "huge"
+
+#define PLA (-1)
+#define JMPIND (-2)
+
+static void function_top(FILE *,struct Var *,long);
+static void function_bottom(FILE *f,struct Var *,long);
+
+#define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
+#define isacc(x) (isreg(x)&&(p->x.reg==ra||p->x.reg==rax))
+#define isconst(x) ((p->x.flags&(KONST|DREFOBJ))==KONST)
+
+#define isptr(r) ((r)>=FIRST_PAIR&&(r)<=LAST_PAIR)
+
+static int q1reg,q2reg,zreg;
+
+static char *ccs[]={"eq","ne","lt","ge","le","gt",""};
+static char *logicals[]={"ora","eor","and"};
+static char *arithmetics[]={"slw","srw","adc","sbc","mullw","divw","mod"};
+
+/* alignment of basic data-types, used to initialize align[] */
+static long malign[MAX_TYPE+1]=  {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+/* sizes of basic data-types, used to initialize sizetab[] */
+static long msizetab[MAX_TYPE+1]={1,1,2,2,4,8,4,4,4,0,2,3,3,0,0,0,1,0};
+static char *mregnames[MAXR+1];
+
+/* Typenames (needed because of HAVE_EXT_TYPES). */
+char *typname[]={"strange","char","short","int","long","long long",
+                 "float","double","long double","void",
+                 "near-pointer","far-pointer","huge-pointer",
+                 "array","struct","union","enum","function"};
+
+
+/* used to initialize regtyp[] */
+static struct Typ ityp={INT},ctyp={CHAR},ftyp={FLOAT},lltyp={LLONG};
+
+/* macros defined by the backend */
+static char *marray[]={"__section(x)=__vattr(\"section(\"#x\")\")",
+		       "__m65__", 
+		       "__SIZE_T_INT",
+		       "__bank(x)=__vattr(\"bank(\"#x\")\")",
+                       "__far=__attr(\"far\")",
+                       "__near=__attr(\"near\")",
+                       "__huge=__attr(\"huge\")",
+		       0};
+
+/* special registers */
+static int ra=1, rx=2, ry=3, rz=4, sp1=5,sp2=6,sp=7,fp,fp1,fp2;
+static int t4=LAST_GPR,t3=LAST_GPR-1,t2=LAST_GPR-2,t1=LAST_GPR-3;
+static int rax=8;
+static int raxyz=9;
+static int yval;
+#define NOVAL 1000
+
+static int t1,t2,f1,f2; /*tODO: remove*/
+
+static int pushedacc,pushedx,nopeep,cbmascii,atascii,ieee;
+static int pass;
+static int libsave;
+static struct rpair rp2;
+static int cbank;
+static Var bankv;
+static int bankvoffset;
+static int bankcnum;
+static obj zstore;
+static int zstoreflag;
+
+#define SECLEN 128
+char *use_sec;
+int use_bank=-1;
+
+#define dt(t) (((t)&UNSIGNED)?udt[(t)&NQ]:sdt[(t)&NQ])
+static char *sdt[MAX_TYPE+1]={"??","c","s","i","l","ll","f","d","ld","v","p"};
+static char *udt[MAX_TYPE+1]={"??","uc","us","ui","ul","ull","f","d","ld","v","p"};
+
+/* perhaps provide version with 8bit int? */
+#define ISCHAR(t) ((t&NQ)==CHAR)
+#define ISSHORT(t) ((t&NQ)==SHORT||(t&NQ)==INT||(t&NQ)==POINTER)
+#define ISFPOINTER(t) ((t&NQ)==FPOINTER)
+#define ISLONG(t) ((t&NQ)==LONG)
+#define ISLLONG(t) ((t&NQ)==LLONG)
+
+/* am */
+#define IMM_IND 1
+#define GPR_IND 2
+#define ABS_IND 3
+
+/* sections */
+#define DATA 0
+#define BSS 1
+#define CODE 2
+#define RODATA 3
+#define SPECIAL 4
+
+static long stack;
+static int stack_valid;
+static int section=-1,newobj;
+static char *codename="\tsection\ttext",
+  *dataname="\tsection\tdata",
+  *bssname="\tsection\tbss",
+  *rodataname="\tsection\trodata";
+
+/* return-instruction */
+static char *ret;
+
+/* label at the end of the function (if any) */
+static int exit_label;
+
+/* assembly-prefixes for labels and external identifiers */
+static char *labprefix="l",*idprefix="_";
+
+/* variables to calculate the size and partitioning of the stack-frame
+   in the case of FIXED_SP */
+static long frameoffset,pushed,maxpushed,framesize;
+
+static long localsize,rsavesize,rscnt,argsize;
+
+static void emit_obj(FILE *f,struct obj *p,int t);
+
+/* calculate the actual current offset of an object relativ to the
+   stack-pointer; we use a layout like this:
+   ------------------------------------------------
+   | arguments to this function                   |
+   ------------------------------------------------
+   | caller-save registers [size=rsavesize]       |
+   ------------------------------------------------
+   | local variables [size=localsize]             |
+   ------------------------------------------------
+   | arguments to called functions [size=argsize] |
+   ------------------------------------------------
+   All sizes will be aligned as necessary.
+   In the case of FIXED_SP, the stack-pointer will be adjusted at
+   function-entry to leave enough space for the arguments and have it
+   aligned to 16 bytes. Therefore, when calling a function, the
+   stack-pointer is always aligned to 16 bytes.
+   For a moving stack-pointer, the stack-pointer will usually point
+   to the bottom of the area for local variables, but will move while
+   arguments are put on the stack.
+
+   This is just an example layout. Other layouts are also possible.
+*/
+
+static int bank(Var *v)
+{
+  char *s=v->vattr;
+  int n,r;
+  if(!NOBANKING&&s&&(s=strstr(s,"bank("))){
+    if(sscanf(s+5,"%i",&n)==1)
+      return n;
+  }
+  return -1;
+}
+
+static void ebank(FILE *f,int b)
+{
+  if(b>=0) emit(f,"%d",b);
+  emit(f,"\n");
+}
+
+static long real_offset(struct obj *o)
+{
+  long off=zm2l(o->v->offset);
+  if(off<0){
+    /* function parameter */
+    off=localsize+rsavesize-off-zm2l(maxalign);
+  }
+
+  off+=argsize;
+  off+=zm2l(o->val.vmax);
+  return off;
+}
+
+/*  Initializes an addressing-mode structure and returns a pointer to
+    that object. Will not survive a second call! */
+static struct obj *cam(int flags,int base,long offset)
+{
+  static struct obj obj;
+  static struct AddressingMode am;
+  obj.am=&am;
+  am.flags=flags;
+  am.base=base;
+  am.offset=offset;
+  return &obj;
+}
+
+/* changes to a special section, used for __section() */
+static int special_section(FILE *f,struct Var *v)
+{
+  char *sec;
+  if(v->tattr&ZPAGE){
+    emit(f,"\tsection\tzpage\n");
+  }else{
+    if(!v->vattr) return 0;
+    sec=strstr(v->vattr,"section(");
+    if(!sec) return 0;
+    sec+=strlen("section(");
+    emit(f,"\tsection\t");
+    while(*sec&&*sec!=')') emit_char(f,*sec++);
+    emit(f,"\n");
+  }
+  if(f) section=SPECIAL;
+  return 1;
+}
+
+
+
+#define chk_coll(x) do{if((x)==r||(x)==r1||(x)==r2) return 0;	\
+    if(reg_pair((x),&rp)&&(rp.r1==r||rp.r2==r)) return 0;}while(0)
+
+static int scratch(IC *p,int r)
+{
+  int r1,r2;
+  if(!p) return 1;
+  if(reg_pair(r,&rp)){
+    r1=rp.r1;
+    r2=rp.r2;
+  }else{
+    r1=0;
+    r2=0;
+  }
+  if(isreg(z)&&p->z.reg==r){
+    if(!(p->q2.flags&REG))
+      return 1;
+    if(p->q2.reg==r||p->q2.reg==r1||p->q2.reg==r2)
+      return 0;
+    if(reg_pair(p->q2.reg,&rp))
+      if(rp.r1==r||rp.r2==r)
+	return 0;
+    return 1;
+  }
+  while(p){
+    if(p->code==LABEL||p->code==CALL)
+      return 0;
+    if(p->code>=BEQ&&p->code<=BRA)
+      return 0;
+    if(p->code==FREEREG||p->code==ALLOCREG){
+      if(p->q1.reg==r)
+	return 1;
+      if(reg_pair(p->q1.reg,&rp)&&(rp.r1==r||rp.r2==r))
+	return 1;
+    }
+    if(p->q1.am) chk_coll(p->q1.am->base);
+    if(p->q2.am) chk_coll(p->q2.am->base);
+    if(p->z.am) chk_coll(p->z.am->base);
+    if(p->q1.flags&REG) chk_coll(p->q1.reg);
+    if(p->q2.flags&REG) chk_coll(p->q2.reg);
+    if(p->z.flags&REG){
+      if(p->z.flags&DREFOBJ)
+	chk_coll(p->z.reg);
+      else{
+	if(p->z.reg==r)
+	  return 1;
+	if(reg_pair(p->z.reg,&rp)&&(rp.r1==r||rp.r2==r))
+	  return 1;
+      }
+    }
+
+    p=p->next;
+  }
+  return 1;
+}
+
+static int rsavecur;
+static int in_isr;
+
+static int get_reg(FILE *f,IC *p,int t)
+{
+  int r,r1,r2,pass,flag;
+
+  for(pass=0;pass<5;pass++){
+    for(r=MAXR;r>sp;r--){
+      if(reg_pair(r,&rp)){
+	r1=rp.r1;
+	r2=rp.r2;
+      }else{
+	r1=0;
+	r2=0;
+      }
+      if((pass==0||pass==3)&&(!regscratch[r]||in_isr))
+	continue;
+      if(pass<3){
+	if(regs[r]) continue;
+	if(r1&&(regs[r1]||regs[r2])) continue;
+      }
+      if(pass==2&&!(regs[r]&4))
+	continue;
+      if((p->q1.flags&REG)&&(p->q1.reg==r||p->q1.reg==r1||p->q1.reg==r2)) continue;
+      if((p->q2.flags&REG)&&(p->q2.reg==r||p->q2.reg==r1||p->q2.reg==r2)) continue;
+      if((p->z.flags&REG)&&(p->z.reg==r||p->z.reg==r1||p->z.reg==r2)) continue;
+      if(regok(r,t,1)){
+	flag=8;
+	if(regs[r]){
+	  flag|=2;
+	  if(p->code==COMPARE||p->code==TEST)
+	    ierror(0);
+	  if(regs[ra]){
+	    emit(f,"\ttay\n");
+	    yval=NOVAL;
+	  }
+	  if(r1){
+	    emit(f,"\tlda\t%s\n",mregnames[r1]);
+	    emit(f,"\tpha\n");
+	    emit(f,"\tlda\t%s\n",mregnames[r2]);
+	    emit(f,"\tpha\n");
+	  }else{
+	    emit(f,"\tlda\t%s\n",mregnames[r]);
+	    emit(f,"\tpha\n");
+	  }
+	  if(regs[ra])
+	    emit(f,"\ttya\n");
+	}
+	if(r1){
+	  regs[r1]|=flag;
+	  regs[r2]|=flag;
+	}
+	regs[r]|=flag;
+	regused[r]=1;
+	regused[r1]=1;
+	regused[r2]=1;
+	return r;
+      }
+    }
+  }
+  pric2(stdout,p);
+  ierror(0);
+}
+
+static void get_acc(FILE *f, IC *p,int t)
+{
+  int r;
+  if(isacc(z)) return;
+  t&=NQ;
+  if(ISCHAR(t)){
+    if(1/*!isreg(q1)||(p->q1.reg!=ra&&p->q1.reg!=rax)*/){
+      if((regs[ra]||regs[rax])&&!scratch(p,ra)&&!pushedacc){
+	if(optsize||(regs[t1]&&regs[t2]&&regs[t3]&&regs[t4])){
+	  emit(f,"\tpha\n");
+	  pushedacc=-1;
+	}else{
+	  r=get_reg(f,p,CHAR);
+	  emit(f,"\tsta\t%s\n",mregnames[r]);
+	  pushedacc=r;
+	}
+      }
+    }
+  }else{
+    if(1/*!isreg(q1)||p->q1.reg!=rax*/){
+      if((regs[ra]||regs[rax])&&(!scratch(p,ra)||!scratch(p,rax))&&!pushedacc){
+	r=get_reg(f,p,CHAR);
+	emit(f,"\tsta\t%s\n",mregnames[r]);
+	pushedacc=r;
+      }
+      if((regs[rx]||regs[rax])&&!scratch(p,rax)&&!pushedx){
+	r=get_reg(f,p,CHAR);
+	emit(f,"\tstx\t%s\n",mregnames[r]);
+	pushedx=r;
+      }
+    }
+  }
+}
+
+static int cmp_get_acc(FILE *f,IC *p,IC *branch)
+{
+  if(!regs[ra]&&!regs[rax])
+    return 0;
+  if(branch==0&&pushedacc)
+    return 0;
+  if(branch&&isreg(q1)&&(p->q1.reg==ra||p->q1.reg==rax))
+    if(branch->code==BEQ||branch->code==BNE||(p->typf&UNSIGNED))
+      return 0;
+  if(scratch(p,ra))
+    return 0;
+  if(!regs[rx]&&!regs[rax]){
+    emit(f,"\ttax\n");
+    pushedacc=rx;
+  }
+  emit(f,"\tpha\n");
+  pushedacc=-1;
+  return pushedacc;
+}
+
+static void reload_acc_opt(FILE *f,IC *p)
+{
+  if(pushedacc==0) return;
+  if(pushedacc>0){
+    while(p){
+      if(p->code!=FREEREG) break;
+      if(p->q1.reg==ra||p->q1.reg==rax){
+	pushedacc=0;
+	return;
+      }
+      p=p->next;
+    }
+  }
+  if(pushedacc==-1)
+    emit(f,"\tpla\n");
+  else if(pushedacc==rx)
+    emit(f,"\ttxa\n");
+  else if(pushedacc==ry)
+    emit(f,"\ttya\n");
+  else if(pushedacc){
+    emit(f,"\tlda\t%s\n",mregnames[pushedacc]);
+    regs[pushedacc]&=~8;
+  }
+  pushedacc=0;
+}
+
+static void reload_acc(FILE *f)
+{
+  reload_acc_opt(f,0);
+}
+
+static void push(int i)
+{
+  pushed-=i;
+  if(pushed<maxpushed)
+    maxpushed=pushed;
+}
+
+static void pop(int i)
+{
+  pushed+=i;
+  if(pushed>0) ierror(0);
+}
+
+static int indirect(obj *o)
+{
+  if((o->flags&(DREFOBJ|KONST))==DREFOBJ)
+    return 1;
+  if((o->flags&(REG|VAR))!=VAR)
+    return 0;
+  if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)
+    return 1;
+  return 0;
+}
+
+void convfloat(void)
+{
+}  
+
+void sety(FILE *f,int val)
+{
+  if(yval==val)
+    return;
+  if(val-yval==1)
+    emit(f,"\tiny\n");
+  else if(yval-val==1)
+    emit(f,"\tdey\n");
+  else{
+    emit(f,"\tldy\t#%d\n",val);
+    if(val<0||val>255)
+      ierror(0);
+  }
+  yval=val;
+}
+
+static void cnv_fp(void)
+{
+  double d,mant;
+  int exp;
+  unsigned long t;
+
+  if(ieee){
+    vfloat=zld2zf(vldouble);
+    memcpy((void*)&vmax,(void*)&vfloat,4);
+  }else{
+    d=zld2d(vldouble);
+    mant=frexp(d,&exp);
+    exp=(exp+127)&255;
+    t=((unsigned long)(mant*8388608))&0xffffff;
+    t|=((long)exp)<<24;
+    
+    t=((t&0xff)<<24)|((t&0xff00)<<8)|((t&0xff0000)>>8)|((t&0xff000000)>>24);
+    vmax=l2zm((long)t);
+  }
+}
+
+static void emit_ieee(FILE *f,union atyps *p,int t)
+{
+  unsigned char *ip=(unsigned char *)&p->vdouble;
+  emit(f,"0x%02x%02x,0x%02x%02x",ip[1],ip[0],ip[3],ip[2]);
+  if(t==DOUBLE||t==LDOUBLE)
+    emit(f,",0x%02x%02x,0x%02x%02x",ip[5],ip[4],ip[7],ip[6]);
+  emit(f,"\n");
+}
+
+static void emit_lobyte(FILE *f,obj *o,int t)
+{
+  if(o->flags&KONST){
+    if(o->flags&DREFOBJ){
+      eval_const(&o->val,o->dtyp);
+       emit(f,"%d",zm2l(vmax));
+    }else{
+      eval_const(&o->val,t);
+      if(ISFLOAT(t)) cnv_fp();
+      emit(f,"#%d",zm2l(vmax)&255);
+    }
+  }else if(o->flags&VARADR){
+    emit(f,"#<(");
+    emit_obj(f,o,t);
+    emit(f,")");
+  }else if((o->flags&(REG|DREFOBJ))==REG){
+    if(!reg_pair(o->reg,&rp))
+      emit(f,"%s",mregnames[o->reg]);
+    else
+      emit(f,"%s",mregnames[rp.r1]);
+  }else{
+    emit_obj(f,o,t);
+  }
+}
+
+static void emit_hibyte(FILE *f,obj *o,int t)
+{
+  if(o->flags&KONST){
+    if(o->flags&DREFOBJ){
+      eval_const(&o->val,o->dtyp);
+      emit(f,"%d",zm2l(vmax)+1);
+    }else{
+      eval_const(&o->val,t);
+      if(ISFLOAT(t)) cnv_fp();
+      emit(f,"#%d",(zm2l(vmax)>>8)&255);
+    }
+  }else if(o->flags&VARADR){
+    emit(f,"#>(");
+    emit_obj(f,o,t);
+    emit(f,")");
+  }else if((o->flags&(REG|DREFOBJ))==REG){
+    if(o->reg>=FIRST_BIG&&o->reg<=LAST_BIGP){
+      emit(f,"%s+1",mregnames[o->reg]);
+    }else{
+      if(!reg_pair(o->reg,&rp))
+	ierror(0);
+      emit(f,"%s",mregnames[rp.r2]);
+    }
+  }else{
+    if(o->flags&VARADR)
+      emit(f,"#");
+    if(!(o->flags&DREFOBJ))
+      o->val.vmax=zmadd(o->val.vmax,Z1);
+    emit_obj(f,o,t);
+    if(!(o->flags&DREFOBJ))
+      o->val.vmax=zmsub(o->val.vmax,Z1);
+  }
+}
+
+static void emit_byte3(FILE *f,obj *o,int t)
+{
+  if(o->flags&KONST){
+    if(o->flags&DREFOBJ){
+      eval_const(&o->val,o->dtyp);
+      emit(f,"%d",zm2l(vmax)+2);
+    }else{
+      eval_const(&o->val,t);
+      if(ISFLOAT(t)) cnv_fp();
+      emit(f,"#%d",(zm2l(vmax)>>16)&255);
+    }
+  }else if((o->flags&(REG|DREFOBJ))==REG){
+    emit(f,"%s+2",mregnames[o->reg]);
+  }else if(o->flags&VARADR){
+    emit(f,"#%d",bank(o->v));
+  }else{
+    if(!(o->flags&DREFOBJ))
+      o->val.vmax=zmadd(o->val.vmax,l2zm(2L));
+    emit_obj(f,o,t);
+    if(!(o->flags&DREFOBJ))
+      o->val.vmax=zmsub(o->val.vmax,l2zm(2L));
+  }
+}
+
+static void emit_byte4(FILE *f,obj *o,int t)
+{
+  if(o->flags&KONST){
+    if(o->flags&DREFOBJ){
+      eval_const(&o->val,o->dtyp);
+      emit(f,"%d",zm2l(vmax)+3);
+    }else{
+      eval_const(&o->val,t);
+      if(ISFLOAT(t)) cnv_fp();
+      emit(f,"#%d",(zm2l(vmax)>>24)&255);
+    }
+  }else if((o->flags&(REG|DREFOBJ))==REG){
+    emit(f,"%s+3",mregnames[o->reg]);
+  }else{
+    if(!(o->flags&DREFOBJ))
+      o->val.vmax=zmadd(o->val.vmax,l2zm(3L));
+    emit_obj(f,o,t);
+    if(!(o->flags&DREFOBJ))
+      o->val.vmax=zmsub(o->val.vmax,l2zm(3L));
+  }
+}
+
+static void do_lobyte(FILE *f,char *s,obj *o,int type)
+{
+  if(o->am){
+    if(o->am->flags==IMM_IND)
+      sety(f,o->am->offset);
+    else if(o->am->flags==GPR_IND||o->am->flags==ABS_IND){
+      if(o->am->offset==ra)
+	emit(f,"\ttay\n");
+      else
+	emit(f,"\tldy\t%s\n",mregnames[o->am->idx]);
+      yval=NOVAL;
+    }else
+      ierror(0);
+  }else if((o->flags&(DREFOBJ|KONST))==DREFOBJ){
+    sety(f,0);
+  }else if((o->flags&(VAR|REG|VARADR))==VAR&&(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)){
+    sety(f,(int)real_offset(o));
+  }
+  emit(f,"\t%s\t",s);
+  emit_lobyte(f,o,type);
+  emit(f,"\n");
+}
+
+static void do_hibyte(FILE *f,char *s,obj *o,int type)
+{
+  int ami=0;
+  if(o->am){
+    if(o->am->flags==IMM_IND)
+      sety(f,o->am->offset+1);
+    else if(o->am->flags==ABS_IND){
+      if(o->am->offset==ra)
+	emit(f,"\ttay\n");
+      else
+	emit(f,"\tldy\t%s\n",mregnames[o->am->idx]);
+      o->am->offset++;ami=1;
+      yval=NOVAL;
+    }else
+      ierror(0);
+  }else  if((o->flags&(DREFOBJ|KONST))==DREFOBJ){
+    sety(f,1);
+  }else if((o->flags&(VAR|REG|VARADR))==VAR&&(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)){
+    sety(f,(int)real_offset(o)+1);
+  }
+  emit(f,"\t%s\t",s);
+  emit_hibyte(f,o,type);
+  emit(f,"\n");
+  if(ami) o->am->offset--;
+}
+
+static void do_byte3(FILE *f,char *s,obj *o,int type)
+{
+  int ami=0;
+  if(o->am){
+    if(o->am->flags==IMM_IND)
+      sety(f,o->am->offset+2);
+    else if(o->am->flags==ABS_IND){
+      if(o->am->offset==ra)
+	emit(f,"\ttay\n");
+      else
+	emit(f,"\tldy\t%s\n",mregnames[o->am->idx]);
+      yval=NOVAL;
+      o->am->offset+=2;ami=1;
+    }else
+      ierror(0);
+  }else  if((o->flags&(DREFOBJ|KONST))==DREFOBJ){
+    sety(f,2);
+  }else if((o->flags&(VAR|REG|VARADR))==VAR&&(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)){
+    sety(f,(int)real_offset(o)+2);
+  }
+  emit(f,"\t%s\t",s);
+  emit_byte3(f,o,type);
+  emit(f,"\n");
+  if(ami) o->am->offset-=2;
+}
+
+static void do_byte4(FILE *f,char *s,obj *o,int type)
+{
+  int ami=0;
+  if(o->am){
+    if(o->am->flags==IMM_IND)
+      sety(f,o->am->offset+3);
+    else if(o->am->flags==ABS_IND){
+      if(o->am->offset==ra)
+	emit(f,"\ttay\n");
+      else
+	emit(f,"\tldy\t%s\n",mregnames[o->am->idx]);
+      yval=NOVAL;
+      o->am->offset+=3;ami=1;
+    }else
+      ierror(0);
+  }else  if((o->flags&(DREFOBJ|KONST))==DREFOBJ){
+    sety(f,3);
+  }else if((o->flags&(VAR|REG|VARADR))==VAR&&(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)){
+    sety(f,(int)real_offset(o)+3);
+  }
+  emit(f,"\t%s\t",s);
+  emit_byte4(f,o,type);
+  emit(f,"\n");
+  if(ami) o->am->offset-=3;
+}
+
+static void load_lobyte(FILE *f,obj *o,int t)
+{
+  if((o->flags&(REG|DREFOBJ))==REG){
+    if(o->reg==ra||o->reg==rax)
+      return;
+    if(o->reg==rx){
+      emit(f,"\ttxa\n");
+      return;
+    }
+  }
+  do_lobyte(f,"lda",o,t);
+}
+
+static void load_hibyte(FILE *f,obj *o,int t)
+{
+  if((o->flags&REG)&&(o->reg==rx||o->reg==rax))
+    emit(f,"\ttxa\n");
+  else
+    do_hibyte(f,"lda",o,t);
+}
+
+static void store_lobyte(FILE *f,obj *o,int t)
+{
+  if((o->flags&(REG|DREFOBJ))==REG){
+    if(o->reg==ra||o->reg==rax)
+      return;
+    if(o->reg==rx){
+      emit(f,"\ttax\n");
+      return;
+    }
+  }
+  do_lobyte(f,"sta",o,t);
+}
+
+static void store_hibyte(FILE *f,obj *o,int t)
+{
+  if((o->flags&REG)&&(o->reg==rx||o->reg==rax))
+    emit(f,"\ttax\n");
+  else
+    do_hibyte(f,"sta",o,t);
+}
+
+static void load_acc(FILE *f,obj *o,int type)
+{
+  if((o->flags&REG)&&(o->reg==ra||o->reg==rax))
+    return;
+  if(!ISCHAR(type)){
+    if(indirect(o)){
+      do_hibyte(f,"lda",o,type);
+      emit(f,"\ttax\n");
+    }else
+      do_hibyte(f,"ldx",o,type);
+  }
+  if((o->flags&(REG|DREFOBJ))==REG&&o->reg==rx)
+    emit(f,"\ttxa\n");
+  else
+    do_lobyte(f,"lda",o,type);
+}
+
+static void store_acc(FILE *f,obj *o,int type)
+{
+  if((o->flags&(DREFOBJ|KONST))==DREFOBJ&&((!(o->flags&REG))||!isptr(o->reg))){
+    ierror(0);
+  }
+  if((o->flags&REG)&&(o->reg==ra||o->reg==rax))
+    return;
+  if((o->flags&REG)&&o->reg==rx){
+    emit(f,"\ttax\n");
+    return;
+  }
+  store_lobyte(f,o,type);
+  if(!ISCHAR(type)){
+    if(indirect(o)){
+      /*TODO: save accu */
+      emit(f,"\ttxa\n");
+      store_hibyte(f,o,type);
+    }else
+      do_hibyte(f,"stx",o,type);
+  }
+}
+
+static void load_reg(FILE *f,int r,struct obj *o,int type)
+{
+  static obj ro;
+  ro.flags=REG;
+  ro.reg=r;
+  load_lobyte(f,o,type);
+  store_lobyte(f,&ro,type);
+  if(!ISCHAR(type)){
+    load_hibyte(f,o,type);
+    store_hibyte(f,&ro,type);
+  }
+}
+
+static void store_reg(FILE *f,int r,struct obj *o,int type)
+{
+  static obj ro;
+  if(r==rx){
+    if((o->flags&(REG|DREFOBJ))==REG){
+      if(o->reg==rx)
+	return;
+      if(o->reg==ra){
+	emit(f,"\ttxa\n");
+	return;
+      }
+    }
+  }
+  ro.flags=REG;
+  ro.reg=r;
+  if(r!=ra&&r!=rax)
+    load_acc(f,&ro,type);
+  store_acc(f,o,type);
+}
+
+static struct fpconstlist {
+  struct fpconstlist *next;
+  int label;
+  int t;
+  union atyps val;
+} *firstfpc;
+
+static int addfpconst(struct obj *o,int t)
+{
+  struct fpconstlist *p=firstfpc;
+  t&=NQ;
+  if(t==LDOUBLE) t=DOUBLE;
+  for(p=firstfpc;p;p=p->next){
+    if(t==p->t){
+      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==LONG&&zmeqto(vmax,zl2zm(o->val.vlong))) return p->label;
+      if(t==LLONG&&zmeqto(vmax,zll2zm(o->val.vllong))) return p->label;
+    }
+  }
+  p=mymalloc(sizeof(struct fpconstlist));
+  p->next=firstfpc;
+  p->t=t;
+  p->label=++label;
+  p->val=o->val;
+  firstfpc=p;
+  return p->label;
+}
+
+/* generate code to load the address of a local variable into register r */
+static void load_laddr(FILE *f,int r,struct obj *o)
+{
+  long l=real_offset(o);
+  /* assumes acc is available */
+  if(!reg_pair(r,&rp)) ierror(0);
+  emit(f,"\tlda\t%s\n",mregnames[fp]);
+  if(l!=0)
+    emit(f,"\tclc\n");
+  if(l&255)
+    emit(f,"\tadc\t#%ld\n",l&255);
+  emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
+  emit(f,"\tlda\t%s\n",mregnames[fp2]);
+  if(l!=0)
+    emit(f,"\tadc\t#%ld\n",(l>>8)&255);
+  emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
+}
+
+/* generate code to load the address of a variable into register r */
+static void load_address(FILE *f,int r,struct obj *o,int t)
+{
+  if(o->flags&DREFOBJ){
+    o->flags&=~DREFOBJ;
+    load_reg(f,r,o,POINTER);
+    o->flags|=DREFOBJ;
+  }else if((o->flags&(REG|DREFOBJ))==REG){
+    if(!reg_pair(r,&rp)) ierror(0);
+    emit(f,"\tlda\t#>%s\n",mregnames[o->reg]);
+    emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
+    emit(f,"\tlda\t#<%s\n",mregnames[o->reg]);
+    emit(f,"\tsta\t%s\n",mregnames[rp.r1]);    
+  }else if(o->flags&VAR){
+    if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER){
+      load_laddr(f,r,o);
+    }else{
+      o->flags|=VARADR;
+      load_reg(f,r,o,POINTER);
+      o->flags&=~VARADR;
+    }
+  }else if((o->flags&(KONST|DREFOBJ))==KONST){
+    int l=addfpconst(o,t);
+    if(!ieee) ierror(0);
+    if(!reg_pair(r,&rp)) ierror(0);
+    emit(f,"\tlda\t#>%s%d\n",labprefix,l);
+    emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
+    emit(f,"\tlda\t#<%s%d\n",labprefix,l);
+    emit(f,"\tsta\t%s\n",mregnames[rp.r1]);    
+  }else
+    ierror(0);
+}
+
+
+/*  Yields log2(x)+1 or 0. */
+static long pof2(zumax x)
+{
+  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 incmem(FILE *f,obj *o,int t,int op,int x)
+{
+  int i;
+  char *s;
+
+  // PGS: All registers and pseudo registers on the M65 target
+  // live in zero-page, so we can use INW and DEW for fast
+  // increment/decrement.
+  if (o->flags&REG) {
+    switch(op) {
+    case ADD:
+      if(ISCHAR(t)){
+	emit(f,"\tinc\t");
+	emit_obj(f,o,t);
+	emit(f,"\n");	
+      } else {
+	emit(f,"\tinw\t");
+	emit_obj(f,o,t);
+	emit(f,"\n");	
+      }
+      return;
+      break;
+    case SUB:
+      if(ISCHAR(t)){
+	emit(f,"\tdec\t");
+	emit_obj(f,o,t);
+	emit(f,"\n");	
+      } else {
+	emit(f,"\tdew\t");
+	emit_obj(f,o,t);
+	emit(f,"\n");	
+      }
+      return;
+      break;
+    }
+  }
+  
+  if(op==ADD)
+    s="inc";
+  else if(op==SUB)
+    s="dec";
+  else if(op==LSHIFT)
+    s="asl";
+  else if(op==RSHIFT&&(t&UNSIGNED))
+    s="clc\n\tror";
+  else if(op==RSHIFT){
+    s="cmp\t#128\n\tror";
+  }else
+    ierror(0);
+  if(ISCHAR(t)){
+    for(i=0;i<x;i++){
+      emit(f,"\t%s\t",s);
+      emit_obj(f,o,t);
+      emit(f,"\n");
+    }
+  }else{
+    for(i=0;i<x;i++){
+      if(op==SUB){
+	/* caller mus make sure accu is available */
+	load_lobyte(f,o,t);
+	emit(f,"\tbne\t%s%d\n",labprefix,++label);
+	emit(f,"\tdec\t");
+	emit_hibyte(f,o,t);
+	emit(f,"\n");
+	emit(f,"%s%d:\n",labprefix,label);
+	emit(f,"\tdec\t");
+	emit_lobyte(f,o,t);
+	emit(f,"\n");	
+      }else if(op==ADD){
+	emit(f,"\t%s\t",s);
+	emit_lobyte(f,o,t);
+	emit(f,"\n");
+	emit(f,"\tbne\t%s%d\n",labprefix,++label);
+	emit(f,"\t%s\t",s);
+	emit_hibyte(f,o,t);
+	emit(f,"\n");
+	emit(f,"%s%d:\n",labprefix,label);
+      }else if(op==LSHIFT){
+	// 4510 / 45GS02 have ASW/ROW operations
+	// for left-shifting 16-bit values
+	
+	emit(f,"\tasw\t");
+	emit_lobyte(f,o,t);
+	emit(f,"\n");
+
+      }else if(op==RSHIFT&&(t&UNSIGNED)){
+	emit(f,"\tclc\n");
+	emit(f,"\tror\t");
+	emit_hibyte(f,o,t);
+	emit(f,"\n");
+	emit(f,"\tror\t");
+	emit_lobyte(f,o,t);
+	emit(f,"\n");
+      }else if(op==RSHIFT){
+	load_hibyte(f,o,t);
+	emit(f,"\tcmp\t#128\n");
+	emit(f,"\tror\t");
+	emit_hibyte(f,o,t);
+	emit(f,"\n");
+	emit(f,"\tror\t");
+	emit_lobyte(f,o,t);
+	emit(f,"\n");	
+      }else{
+	printf("op=%d\n",op);
+	ierror(0);
+      }
+    }
+  }
+}
+
+static void preload_obj(FILE *f,IC *p,obj *o)
+{
+  int r;long of;
+
+  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");
+
+
+  if((o->flags&(VAR|REG))==VAR&&(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)&&(of=real_offset(o))+zm2l(szof(o->v->vtyp))>255){
+    r=get_reg(f,p,POINTER);
+    if(o->flags&DREFOBJ)
+      get_acc(f,p,INT);
+    else
+      cmp_get_acc(f,p,0);
+    if(!reg_pair(r,&rp)) ierror(0);
+    emit(f,"\tlda\t%s\n",mregnames[fp1]);
+    emit(f,"\tclc\n");
+    if(of&0xff)
+      emit(f,"\tadc\t#%ld\n",of&0xff);
+    emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
+    emit(f,"\tlda\t%s\n",mregnames[fp2]);
+    if(1/*of&0xff00*/)
+      emit(f,"\tadc\t#%ld\n",(of>>8)&0xff);
+    emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
+    o->flags|=REG;
+    o->reg=r;
+    if(o->flags&DREFOBJ){
+      sety(f,0);
+      emit(f,"\tlda\t(%s),y\n",mregnames[r]);
+      emit(f,"\ttxa\n");
+      sety(f,1);
+      emit(f,"\tlda\t(%s),y\n",mregnames[r]);
+      emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
+      emit(f,"\tstx\t%s\n",mregnames[rp.r1]);
+    }else{
+      o->flags|=DREFOBJ;
+      o->dtyp=POINTER;
+    }
+  }
+
+  if((o->flags&(DREFOBJ|KONST))==DREFOBJ&&(!(o->flags&REG)||!isptr(o->reg))&&(!(o->flags&VAR)||!(o->v->tattr&ZPAGE))&&!ISFPOINTER(o->dtyp)){
+    cmp_get_acc(f,p,0);
+    r=get_reg(f,p,POINTER);
+    o->flags&=~DREFOBJ;
+    load_reg(f,r,o,POINTER);
+    o->flags|=REG|DREFOBJ;
+    o->reg=r;
+  }
+}
+
+static void far_copy(FILE *f,IC *p)
+{
+  int b;long l;
+  get_acc(f,p,INT);
+  if(p->code==PUSH){
+    if(!reg_pair(LAST_PAIR,&rp)) ierror(0);
+    emit(f,"\tlda\t%s\n",mregnames[sp]);
+    if(pushed) emit(f,"\tclc\n");
+    if(pushed&0xff) emit(f,"\tadc\t#%d\n",(pushed&0xff));
+    emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
+    emit(f,"\tlda\t%s+1\n",mregnames[sp]);
+    if(pushed) emit(f,"\tadc\t#%d\n",((pushed>>8)&0xff));
+    emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
+    pushed+=zm2l(p->q2.val.vmax);
+    emit(f,"\tldx\t#%d\n",bankcnum);
+  }else if(p->z.flags&DREFOBJ){
+    if(!reg_pair(LAST_PAIR,&rp)) ierror(0);
+    p->z.flags&=~DREFOBJ;
+    load_lobyte(f,&p->z,FPOINTER);
+    emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
+    load_hibyte(f,&p->z,FPOINTER);
+    emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
+    if(indirect(&p->z)){
+      do_byte3(f,"lda",&p->z,FPOINTER);
+      emit(f,"\ttax\n");
+    }else
+      do_byte3(f,"ldx",&p->z,FPOINTER);
+  }else{
+    load_address(f,LAST_PAIR,&p->z,POINTER);
+    b=bank(p->z.v);
+    emit(f,"\tldx\t#%d\n",b>=0?b:bankcnum);
+  }
+  if(p->q1.flags&DREFOBJ){
+    if(!reg_pair(LAST_PAIR-1,&rp)) ierror(0);
+    p->q1.flags&=~DREFOBJ;
+    load_lobyte(f,&p->q1,FPOINTER);
+    emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
+    load_hibyte(f,&p->q1,FPOINTER);
+    emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
+    if(indirect(&p->q1)){
+      do_byte3(f,"lda",&p->q1,FPOINTER);
+      emit(f,"\ttay\n");
+    }else
+      do_byte3(f,"ldy",&p->q1,FPOINTER);
+  }else{
+    load_address(f,LAST_PAIR-1,&p->q1,POINTER);
+    b=bank(p->q1.v);
+    sety(f,b>=0?b:bankcnum);
+  }
+  l=zm2l(p->q2.val.vmax);
+  emit(f,"\tlda\t#%d\n",(l>>8)&0xff);
+  emit(f,"\tsta\t%s__bankcopy_len+1\n",idprefix);
+  emit(f,"\tlda\t#%d\n",(l)&0xff);
+  emit(f,"\tsta\t%s__bankcopy_len\n",idprefix);
+  emit(f,"\tlda\t#%d\n",cbank>=0?cbank:bankcnum);
+  emit(f,"\tjsr\t%s__bankcopy\n",idprefix);
+  yval=NOVAL;
+}
+
+static void load_far(FILE *f,IC *p,obj *o,int t)
+{
+  int pushed=0;
+  if(!(o->flags&DREFOBJ)) ierror(0);
+  o->flags&=~DREFOBJ;
+  t&=NQ;
+  if(zmeqto(sizetab[t],Z0)) return;
+  /*get_acc(f,p,INT);*/
+  if(pushedacc==t3||pushedacc==t4) ierror(0);
+  if(pushedx==t3||pushedx==t4) ierror(0);
+  if(regs[ra]||regs[rax]){
+    if(isacc(q1)||isacc(q2)||!isacc(z)){
+      pushed=1;
+      emit(f,"\tpha\n");
+      if(regs[rax]) emit(f,"\ttxa\n\tpha\n");
+    }
+  }
+  load_reg(f,LAST_PAIR,o,POINTER);
+  if(!indirect(o))
+    do_byte3(f,"ldy",o,CHAR);
+  else{
+    do_byte3(f,"lda",o,CHAR);
+    emit(f,"\ttay\n");
+  }
+  emit(f,"\tldx\t#%d\n",bankvoffset);
+  emit(f,"\tlda\t#%d\n",cbank>=0?cbank:bankcnum);
+  emit(f,"\tjsr\t%s__bankload%d\n",idprefix,(int)zm2l(sizetab[t]));
+  yval=NOVAL;
+  o->flags=VAR;
+  o->v=&bankv;
+  o->val.vmax=l2zm((long)bankvoffset);
+  bankvoffset+=zm2l(sizetab[t]);
+  if(pushed){
+    if(regs[rax]) emit(f,"\tpla\n\ttax\n");
+    emit(f,"\tpla\n");
+  }
+}
+
+static void load_banked(FILE *f,IC *p,obj *o,int t)
+{
+  int pushed=0,m;
+  if(o->flags&DREFOBJ) t=o->dtyp;
+  t&=NQ;
+  if(zmeqto(sizetab[t],Z0)) return;
+  /*get_acc(f,p,INT);*/
+  if(pushedacc==t3||pushedacc==t4) ierror(0);
+  if(pushedx==t3||pushedx==t4) ierror(0);
+  if(regs[ra]||regs[rax]){
+    if(isacc(q1)||isacc(q2)||!isacc(z)){
+      pushed=1;
+      emit(f,"\tpha\n");
+      if(regs[rax]) emit(f,"\ttxa\n\tpha\n");
+    }
+  }
+  m=o->flags;
+  o->flags&=~DREFOBJ;
+  load_address(f,LAST_PAIR,o,POINTER);
+  o->flags=m;
+  emit(f,"\tldx\t#%d\n",bankvoffset);
+  emit(f,"\tlda\t#%d\n",cbank>=0?cbank:bankcnum);
+  sety(f,bank(o->v));
+  emit(f,"\tjsr\t%s__bankload%d\n",idprefix,(int)zm2l(sizetab[t]));
+  yval=NOVAL;
+  o->v=&bankv;
+  o->val.vmax=l2zm((long)bankvoffset);
+  bankvoffset+=zm2l(sizetab[t]);
+  if(pushed){
+    if(regs[rax]) emit(f,"\tpla\n\ttax\n");
+    emit(f,"\tpla\n");
+  }
+}
+
+static void preload(FILE *f,IC *p)
+{
+  int r,mra=regs[ra],mrax=regs[rax];
+  int bq1=-1,bq2=-1,bz=-1,sb=-1,zbuf=0;
+
+  if(p->code==GETRETURN&&p->q1.reg==ra&&!regs[ra])
+    regs[ra]=1;
+
+  if(p->code==GETRETURN&&p->q1.reg==rax&&!regs[rax])
+    regs[rax]=1;
+
+  bankvoffset=0;
+
+  if(!NOBANKVARS){
+    if((p->q1.flags&(VAR|VARADR))==VAR) bq1=bank(p->q1.v);
+    if((p->q2.flags&(VAR|VARADR))==VAR) bq2=bank(p->q2.v);
+    if((p->z.flags&(VAR|VARADR))==VAR) bz=bank(p->z.v);
+
+    if((p->q1.flags&(VAR|VARADR))==(VAR|VARADR)){
+      r=bank(p->q1.v);
+      /*if(r>=0&&r!=cbank) ierror(0);*/
+    }
+    
+    if((p->code==ASSIGN||p->code==PUSH)&&!zmleq(p->q2.val.vmax,l2zm(4L))){
+      if(p->q1.flags&DREFOBJ) preload_obj(f,p,&p->q1);
+      if(p->z.flags&DREFOBJ) preload_obj(f,p,&p->z);
+      return;
+    }
+
+    if(p->code!=CALL){
+      /* TODO: some optimizations possible */
+      if(bq1>=0&&bq1!=cbank){
+	if(cbank<0&&!NOSWITCH)
+	  sb=bq1;
+	else
+	  load_banked(f,p,&p->q1,q1typ(p));
+      }
+      if(bq2>=0&&bq2!=cbank){
+	if((bq2==sb||(cbank<0&&sb<0))&&!NOSWITCH)
+	  sb=bq2;
+	else
+	  load_banked(f,p,&p->q2,q2typ(p));
+      }
+      if(bz>=0&&bz!=cbank&&(p->z.flags&DREFOBJ)){
+	if((bz==sb||(cbank<0&&sb<0))||!NOSWITCH)
+	  sb=bz;
+	else
+	  load_banked(f,p,&p->z,ztyp(p));
+      }
+      
+      if(sb>=0){
+	if(NOSWITCH) ierror(0);
+	sety(f,sb);
+	emit(f,"\tjsr\t%s__bankswitch\n",idprefix);
+	yval=NOVAL;
+      }
+    }
+  }
+
+  if((p->q1.flags&DREFOBJ)&&ISFPOINTER(p->q1.dtyp)&&p->code!=CALL) load_far(f,p,&p->q1,q1typ(p));
+  if((p->q2.flags&DREFOBJ)&&ISFPOINTER(p->q2.dtyp)) load_far(f,p,&p->q2,q2typ(p));
+
+  if(isacc(q2)){
+    static obj o;
+    int t=q2typ(p);
+    r=get_reg(f,p,t);
+    o.flags=REG;
+    o.reg=r;
+    store_acc(f,&o,t);
+    p->q2.reg=r;
+  }
+
+  if(p->code!=ADDRESS){
+    preload_obj(f,p,&p->q1);
+    if((p->q1.flags&(DREFOBJ|VAR|REG))==(DREFOBJ|VAR|REG)&&
+       (p->q2.flags&(DREFOBJ|VAR|REG))==(DREFOBJ|VAR)&&
+       p->q1.v==p->q2.v){
+      p->q2.flags|=REG;
+      p->q2.reg=p->q1.reg;
+    }
+    if((p->q1.flags&(DREFOBJ|VAR|REG))==(DREFOBJ|VAR|REG)&&
+       (p->z.flags&(DREFOBJ|VAR|REG))==(DREFOBJ|VAR)&&
+       p->q1.v==p->z.v){
+      p->z.flags|=REG;
+      p->z.reg=p->q1.reg;
+    }
+  }
+
+  preload_obj(f,p,&p->q2);
+  if((p->q2.flags&(DREFOBJ|VAR|REG))==(DREFOBJ|VAR|REG)&&
+     (p->z.flags&(DREFOBJ|VAR|REG))==(DREFOBJ|VAR)&&
+     p->q2.v==p->z.v){
+    p->z.flags|=REG;
+    p->z.reg=p->q1.reg;
+  }
+
+
+  if((p->z.flags&DREFOBJ)&&ISFPOINTER(p->z.dtyp)) zbuf=1;
+  if((p->z.flags&(VAR|DREFOBJ))==VAR){
+    bz=bank(p->z.v);
+    if(bz>=0&&bz!=cbank) zbuf=1;
+  }
+  
+  if(zbuf&&!NOBANKVARS){
+    zstore=p->z;
+    p->z.flags=VAR;
+    p->z.v=&bankv;
+    p->z.val.vmax=l2zm((long)bankvoffset);
+    zstoreflag=1;
+    /*bankvoffset+=zm2l(sizetab[p->typf&NQ]);*/
+  }else{
+    preload_obj(f,p,&p->z);
+
+    if(isreg(z)){
+      r=0;
+      if(p->q1.am&&p->q1.am->base==p->z.reg){
+	r=get_reg(f,p,POINTER);
+	cmp_get_acc(f,p,0);
+	if(!reg_pair(p->q1.am->base,&rp)) ierror(0);
+	if(!reg_pair(r,&rp2)) ierror(0);
+	emit(f,"\tlda\t%s\n",mregnames[rp.r1]);
+	emit(f,"\tsta\t%s\n",mregnames[rp2.r1]);
+	emit(f,"\tlda\t%s\n",mregnames[rp.r2]);
+	emit(f,"\tsta\t%s\n",mregnames[rp2.r2]);
+	p->q1.am->base=p->q1.reg=r;
+      }else if((p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p->q1.reg==p->z.reg){
+	r=get_reg(f,p,POINTER);
+	cmp_get_acc(f,p,0);
+	if(!reg_pair(p->z.reg,&rp)) ierror(0);
+	if(!reg_pair(r,&rp2)) ierror(0);
+	emit(f,"\tlda\t%s\n",mregnames[rp.r1]);
+	emit(f,"\tsta\t%s\n",mregnames[rp2.r1]);
+	emit(f,"\tlda\t%s\n",mregnames[rp.r2]);
+	emit(f,"\tsta\t%s\n",mregnames[rp2.r2]);
+	p->q1.reg=r;
+      }
+      if(p->q2.am&&p->q2.am->base==p->z.reg){
+	if(r==0){
+	  r=get_reg(f,p,POINTER);
+	  cmp_get_acc(f,p,0);
+	  if(!reg_pair(p->q2.am->base,&rp)) ierror(0);
+	  if(!reg_pair(r,&rp2)) ierror(0);
+	  emit(f,"\tlda\t%s\n",mregnames[rp.r1]);
+	  emit(f,"\tsta\t%s\n",mregnames[rp2.r1]);
+	  emit(f,"\tlda\t%s\n",mregnames[rp.r2]);
+	  emit(f,"\tsta\t%s\n",mregnames[rp2.r2]);
+	}
+	p->q2.am->base=p->q2.reg=r;
+      }else if((p->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p->q2.reg==p->z.reg){
+	if(r==0){
+	  r=get_reg(f,p,POINTER);
+	  cmp_get_acc(f,p,0);
+	  if(!reg_pair(p->z.reg,&rp)) ierror(0);
+	  if(!reg_pair(r,&rp2)) ierror(0);
+	  emit(f,"\tlda\t%s\n",mregnames[rp.r1]);
+	  emit(f,"\tsta\t%s\n",mregnames[rp2.r1]);
+	  emit(f,"\tlda\t%s\n",mregnames[rp.r2]);
+	  emit(f,"\tsta\t%s\n",mregnames[rp2.r2]);
+	}
+	p->q2.reg=r;
+      }
+    }
+    if(isacc(z)){
+      if(isacc(q2)){
+	if(p->q2.reg==rax){
+	  r=get_reg(f,p,INT);
+	  if(!reg_pair(r,&rp)) ierror(0);
+	  emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
+	  emit(f,"\tstx\t%s\n",mregnames[rp.r2]);
+	}else{
+	  r=get_reg(f,p,CHAR);
+	  emit(f,"\tsta\t%s\n",mregnames[r]);
+	}
+	p->q2.reg=r;
+	if(isacc(q1))
+	  p->q1.reg=r;
+      }
+    }
+  }     
+ 
+  reload_acc(f);
+
+  regs[ra]=mra;
+  regs[rax]=mrax;
+}
+
+
+/* compare if two objects are the same */
+static int compare_objects(struct obj *o1,struct obj *o2)
+{
+  if((o1->flags&(REG|DREFOBJ))==REG&&(o2->flags&(REG|DREFOBJ))==REG&&o1->reg==o2->reg)
+    return 1;
+  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&REG)||o1->reg==o2->reg){
+        return 1;
+      }
+    }
+  }
+  return 0;
+}
+
+/* save the result (in zreg) into p->z */
+void save_result(FILE *f,struct IC *p)
+{
+  ierror(0);
+}
+
+/* prints an object */
+static void emit_obj(FILE *f,struct obj *p,int t)
+{
+  if(p->am){
+    if(p->am->flags==IMM_IND)
+      emit(f,"(%s),y ;am(%ld)",mregnames[p->am->base],p->am->offset);
+    else if(p->am->flags==GPR_IND)
+      emit(f,"(%s),y ;am(%s)",mregnames[p->am->base],mregnames[p->am->idx]);
+    else if(p->am->flags==ABS_IND){
+      emit(f,"%ld",p->am->offset);
+      if(p->am->v){
+	Var *v=p->am->v;
+	if(v->storage_class==EXTERN)
+	  emit(f,"+%s%s",idprefix,v->identifier);
+	else
+	  emit(f,"+%s%ld",labprefix,zm2l(v->offset));
+      }
+      emit(f,",y ;am(%s)",mregnames[p->am->idx]);
+    }else
+      ierror(0);
+    return;
+  }
+  if((p->flags&(KONST|DREFOBJ))==(KONST|DREFOBJ)){
+    emitval(f,&p->val,p->dtyp&NU);
+    return;
+  }
+  if(p->flags&DREFOBJ) emit(f,"(");
+  if(p->flags&REG){
+    emit(f,"%s",mregnames[p->reg]);
+  }else if(p->flags&VAR) {
+    if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER)
+      emit(f,"(%s),y",mregnames[fp]);
+    else{
+      if(!zmeqto(l2zm(0L),p->val.vmax)){emitval(f,&p->val,MAXINT);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(p->flags&KONST){
+    if(/*ieee&&((t&NQ)==DOUBLE||(t&NQ)==LDOUBLE)*/ISFLOAT(t))
+      emit(f,"%s%d",labprefix,addfpconst(p,t));
+    else
+      emitval(f,&p->val,t&NU);
+  }
+  if(p->flags&DREFOBJ) emit(f,"),y");
+}
+
+/*  Test if there is a sequence of FREEREGs containing FREEREG reg.
+    Used by peephole. */
+static int exists_freereg(struct IC *p,int reg)
+{
+  while(p&&(p->code==FREEREG||p->code==ALLOCREG)){
+    if(p->code==FREEREG&&p->q1.reg==reg) return 1;
+    p=p->next;
+  }
+  return 0;
+}
+
+char amode_buff[8192];
+char *render_amode(struct AddressingMode *am)
+{
+  return "(amode: not implemented)";
+}
+
+char val_buff[8192];
+char *render_val(union atyps val)
+{
+  snprintf(val_buff,8192,"(val: %02x...)",
+	   val.vuchar);
+  return val_buff;
+}
+
+char var_buff[8192];
+char *render_var(struct Var *v)
+{
+  if (!v) return "<null>";
+  snprintf(var_buff,8192,"(var id=%s)",v->identifier);
+  return var_buff;
+}
+
+char obj_buff[8192];
+char *render_obj(struct obj o)
+{
+  // XXX Calling render_var() can result in segfaults
+  snprintf(obj_buff,8192,"(flags=%d, reg=%d, dtype=%d, var=%s, amode=%s, val=%s)",
+	   o.flags,o.reg,o.dtyp,"render_var(o.v)",render_amode(o.am),render_val(o.val));
+  return obj_buff;
+}
+
+/* search for possible addressing-modes */
+static void peephole(struct IC *p)
+{
+  int c,c2,r;struct IC *p2;struct AddressingMode *am;
+
+  fprintf(stderr,"peephole() called.\n");
+
+  /*
+    XXX PGS Things to consider adding here:
+    1. Removal of dead loads when we know a register already has loaded the target we want.
+    2. Removal of dead stores to local stack variables that never get read before returning from a function?
+    3. Removal of SP decrement and increment, when no use of local stack is made.
+    4. Promoting stack variables to global variables where it saves time and/or space?
+    5. Using Z as a temporary scratch register for local variables, where it doesn't upset
+       other things?
+  */
+    
+  
+  for(;p;p=p->next){
+    fprintf(stderr,"  Instruction @ %p : ",p);
+    fprintf(stderr,"code=%d, ",p->code);
+    fprintf(stderr,"\n    q1=%s, ",render_obj(p->q1));
+    fprintf(stderr,"\n    q2=%s, ",render_obj(p->q2));
+    fprintf(stderr,"\n    z=%s, ",render_obj(p->z));
+    fprintf(stderr,"\n");
+    
+    c=p->code;
+    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;
+
+    /* Try const(reg) */
+    if((c==ADDI2P||c==SUBIFP)&&isreg(z)&&(p->q2.flags&(KONST|DREFOBJ))==KONST&&!ISFPOINTER(p->typf2)){
+      int base;zmax of;struct obj *o;
+      eval_const(&p->q2.val,p->typf);
+      if(c==SUBIFP) of=zmsub(l2zm(0L),vmax); else of=vmax;
+      if(zmleq(Z0,of)&&zmleq(of,l2zm(255L))){
+	r=p->z.reg;
+	if(isreg(q1)&&isptr(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*/){
+	    int t,mc;
+	    if((c2==ASSIGN|c2==PUSH)&&(p2->typf&NQ)==CHAR&&!zmeqto(p2->q2.val.vmax,Z1))
+	      mc=1;
+	    else
+	      mc=0;
+	    if(!p2->q1.am&&(p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r){
+	      if(o||mc) break;
+	      t=q1typ(p2)&NQ;
+	      if(t>POINTER||ISFLOAT(t)) break;
+	      o=&p2->q1;
+	    }
+	    if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
+	      if(o||mc) break;
+	      t=q2typ(p2)&NQ;
+	      if(t>POINTER||ISFLOAT(t)) break;
+	      o=&p2->q2;
+	    }
+	    if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
+	      if(o||mc) break;
+	      t=ztyp(p2)&NQ;
+	      if(t>POINTER||ISFLOAT(t)) 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(o==&p->q1||o==&p->q2) break;
+	    }
+	    if(m==r){
+	      if(o){
+		o->am=am=mymalloc(sizeof(*am));
+		am->flags=IMM_IND;
+		am->base=base;
+		am->offset=(int)zm2l(of);
+		if(isreg(q1)&&isptr(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];
+		}
+	      }
+	      break;
+	    }
+	    if(c2!=FREEREG&&m==base) break;
+	    continue;
+	  }
+        }
+      }
+    }
+    /* Try reg,reg */
+    if(c==ADDI2P&&(p->typf&NU)==(UNSIGNED|CHAR)&&!ISFPOINTER(p->typf2)&&isreg(q2)&&p->q2.reg!=ra&&isreg(z)&&(isreg(q1)||p->q2.reg!=p->z.reg)){
+      int base,idx,ind;struct obj *o;
+      r=p->z.reg;idx=p->q2.reg;
+      if(isreg(q1)) base=p->q1.reg; else base=r;
+      if((p->q1.flags&VARADR)||(p->q1.flags&(KONST|DREFOBJ))==KONST)
+	ind=0;
+      else
+	ind=1;
+      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||(ind&&(q1typ(p2)&NQ)!=CHAR)) break;
+            o=&p2->q1;
+          }
+          if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
+            if(o||(ind&&(q2typ(p2)&NQ)!=CHAR)) break;
+            o=&p2->q2;
+          }
+          if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
+            if(o||(ind&&(ztyp(p2)&NQ)!=CHAR)) 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->idx=idx;
+	      if(ind){
+		am->flags=GPR_IND;
+		am->base=base;
+		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];
+		}
+	      }else{
+		am->flags=ABS_IND;
+		am->base=0;
+		eval_const(&p->q1.val,MAXINT);
+		am->offset=zm2l(vmax);
+		if(p->q1.flags&VARADR)
+		  am->v=p->q1.v;
+		else
+		  am->v=0;
+		p->code=c=NOP;p->q1.flags=p->q2.flags=p->z.flags=0;
+	      }
+            }
+            break;
+          }
+          if(c2!=FREEREG&&m==base) break;
+          continue;
+        }
+      }
+    }
+  }
+}
+
+static void pr(FILE *f,struct IC *p)
+{
+  int r;
+
+  if(zstoreflag){
+    int off;
+    if(p->z.flags!=VAR||p->z.v!=&bankv) ierror(0);
+    off=(int)zm2l(p->z.val.vmax);
+    p->z=zstore;
+    get_acc(f,p,INT);
+    if(zstore.flags&DREFOBJ){
+      if(!ISFPOINTER(zstore.dtyp)) ierror(0);
+      zstore.flags&=~DREFOBJ;
+      load_reg(f,LAST_PAIR,&zstore,POINTER);
+      if(indirect(&zstore)){
+	do_byte3(f,"lda",&zstore,FPOINTER);
+	emit(f,"\ttay\n");
+      }else
+	do_byte3(f,"ldy",&zstore,FPOINTER);
+      yval=NOVAL;
+    }else{
+      load_address(f,LAST_PAIR,&zstore,p->typf);
+      r=bank(zstore.v);
+      sety(f,r>=0?r:bankcnum);
+    }
+    emit(f,"\tldx\t#%d\n",off);
+    emit(f,"\tlda\t#%d\n",cbank>=0?cbank:bankcnum);
+    emit(f,"\tjsr\t%s__bankstore%d\n",idprefix,(int)zm2l(sizetab[p->typf&NQ]));
+    yval=NOVAL;
+    zstoreflag=0;
+  }
+
+  for(r=1;r<=MAXR;r++){
+    if(regs[r]&8)
+      regs[r]&=~8;
+  }
+  for(r=FIRST_GPR;r<=LAST_GPR;r++){
+    int ta=0;
+    if(regs[r]&2){
+      if(regs[ra]&&!pushedacc){
+	emit(f,"\ttay\n");
+	yval=NOVAL;
+	ta=1;
+      }
+      emit(f,"\tpla\n");
+      emit(f,"\tsta\t%s\n",mregnames[r]);
+      regs[r]&=~2;
+    }
+    if(ta)
+      emit(f,"\ttya\n");
+  }
+  if(pushedx){
+    emit(f,"\tldx\t%s\n",mregnames[pushedx]);
+    pushedx=0;
+  }
+
+  reload_acc_opt(f,p->next);
+}
+
+struct cmplist {struct cmplist *next;int from,to,mode;} *first_cmplist;
+
+static void add_cmplist(int from, int to, int mode)
+{
+  struct cmplist *new;
+  new=mymalloc(sizeof(*new));
+  new->next=first_cmplist;
+  new->from=from;
+  new->to=to;
+  new->mode=mode;
+  first_cmplist=new;
+}
+
+static void incsp(FILE *f,long of)
+{
+  if(of==0) return;
+  if(of==1||of==-1){
+    static obj o;
+    o.flags=REG;
+    o.reg=sp;
+    if(of==1)
+      incmem(f,&o,INT,ADD,1);
+    else
+      incmem(f,&o,INT,SUB,1);
+  }else if(of==256){
+    emit(f,"\tinc\t%s+1\n",mregnames[sp]);
+  }else if(of==-256){
+    emit(f,"\tdec\t%s+1\n",mregnames[sp]);
+  }else{
+    long abs;
+    if(of>0){
+      abs=of;
+      emit(f,"\tclc\n");
+    }else{
+      abs=-of;
+      emit(f,"\tsec\n");
+    }
+    if(abs&255){
+      emit(f,"\tlda\t%s\n",mregnames[sp]);
+      if(of>0){
+	emit(f,"\tadc\t#%ld\n",abs&255);
+      }else{
+	emit(f,"\tsbc\t#%ld\n",abs&255);
+      }
+      emit(f,"\tsta\t%s\n",mregnames[sp]);
+    }
+    if((abs&0xff00)==0){
+      if(of>0){
+	emit(f,"\tbcc\t%s%d\n",labprefix,++label);
+	emit(f,"\tinc\t%s+1\n",mregnames[sp]);
+	emit(f,"%s%d:\n",labprefix,label);
+      }else{
+	emit(f,"\tbcs\t%s%d\n",labprefix,++label);
+	emit(f,"\tdec\t%s+1\n",mregnames[sp]);
+	emit(f,"%s%d:\n",labprefix,label);
+      }	
+    }else{
+      emit(f,"\tlda\t%s+1\n",mregnames[sp]);
+      if(of>0)
+	emit(f,"\tadc\t#%ld\n",(abs>>8)&255);
+      else
+	emit(f,"\tsbc\t#%ld\n",(abs>>8)&255);
+      emit(f,"\tsta\t%s+1\n",mregnames[sp]);
+    }
+  }
+}
+
+/* generates the function entry code */
+static void function_top(FILE *f,struct Var *v,long offset)
+{
+  int i,r,of;
+  rsavesize=0;
+  libsave=1;
+
+  if(!optsize||(v->tattr&NOCOMPRESS)) emit(f,";vcprmin=10000\n");
+  if(vlas) emit(f,"___fo\tset\t%ld\n",(long)argsize);
+  r=0;
+  for(i=FIRST_GPR;i<=LAST_GPR;i++){
+    if((regused[i]&&(in_isr||!regscratch[i]))||(in_isr&&function_calls&&regscratch[i]&&!regsa[i])){
+      if(i!=LAST_GPR-VOL_GPRS+1&&r==0) libsave=0;
+      rsavesize++;
+      r=1;
+    }else{
+      if(i==LAST_GPR-VOL_GPRS+1) libsave=0;
+      r=0;
+    }
+  }
+  rscnt=rsavesize;
+  if(rscnt&&!SOFTSTACK){
+    if(optspeed||rscnt<2)
+      rsavesize=0;
+    else if(!optsize&&rscnt<=5)
+      rsavesize=0;
+  }
+
+  if(!special_section(f,v)){emit(f,codename);ebank(f,bank(v));if(f) section=CODE;} 
+  if(v->storage_class==EXTERN){
+    if((v->flags&(INLINEFUNC|INLINEEXT))!=INLINEFUNC)
+      emit(f,"\tglobal\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));
+
+  offset=localsize+argsize+rsavesize;
+
+  if(in_isr){
+    emit(f,"\tpha\n");
+    emit(f,"\tphx\n");
+    emit(f,"\tphy\n");
+    emit(f,"\tphz\n");
+    if(offset||function_calls){
+      emit(f,"\tlda\t%s\n",mregnames[sp]);
+      emit(f,"\tpha\n");
+      emit(f,"\tlda\t%s+1\n",mregnames[sp]);
+      emit(f,"\tpha\n");
+      emit(f,"\tlda\t#<(___isrstack-%ld)\n",offset);
+      emit(f,"\tsta\t%s\n",mregnames[sp]);
+      emit(f,"\tlda\t#>(___isrstack-%ld)\n",offset);
+      emit(f,"\tsta\t%s+1\n",mregnames[sp]);
+    }
+  }
+
+  if(MAINARGS&&v->storage_class==EXTERN&&!strcmp(v->identifier,"main")&&v->vtyp->exact->count>1)
+    emit(f,"\tjsr\tinitmainargs\n");
+
+  yval=NOVAL;
+  of=argsize+localsize;
+
+  if(rsavesize>0&&of+rsavesize>255){
+    offset-=rsavesize;
+    incsp(f,-rsavesize);
+    of=0;
+  }else{
+    incsp(f,-offset);
+    offset=0;
+  }
+
+
+  if(!libsave||rscnt!=rsavesize||optspeed||rscnt<=1||(rscnt<=3&&(!optsize)))
+    libsave=0;
+  
+  if(libsave){
+    sety(f,of+rsavesize-1);
+    emit(f,"\tjsr\t%s__rsave%ld\n",idprefix,rscnt);
+    yval=of;
+  }else{
+    for(i=FIRST_GPR;i<=LAST_GPR;i++){
+      if((regused[i]&&(in_isr||!regscratch[i]))||(in_isr&&function_calls&&regscratch[i]&&!regsa[i])){
+	if(rscnt!=rsavesize){
+	  emit(f,"\tlda\t%s\n",mregnames[i]);
+	  emit(f,"\tpha\n");
+	}else{
+	  sety(f,of++);
+	  emit(f,"\tlda\t%s\n",mregnames[i]);
+	  emit(f,"\tsta\t(%s),y\n",mregnames[sp]);
+	}
+      }
+    }
+  }
+
+
+
+  incsp(f,-offset);
+
+  if(vlas){
+    emit(f,"\tlda\t%s\n",mregnames[sp]);
+    emit(f,"\tsta\t%s\n",mregnames[fp]);
+    emit(f,"\tlda\t%s\n",mregnames[sp2]);
+    emit(f,"\tsta\t%s\n",mregnames[fp2]);
+  }
+}
+
+/* generates the function exit code */
+static void function_bottom(FILE *f,struct Var *v,long offset)
+{
+  int i,of,ar;
+  struct cmplist *p;
+  offset=localsize+argsize+rsavesize;
+  of=argsize+localsize;
+
+  i=freturn(v->vtyp->next);
+  if(i==ra||i==rax) ar=1; else ar=0;
+
+  if(rscnt!=rsavesize){
+    if(ar&&!pushedacc){
+      pushedacc=t4;
+      emit(f,"\tsta\t%s\n",mregnames[pushedacc]);
+    }
+    for(i=LAST_GPR;i>=FIRST_GPR;i--){
+      if((regused[i]&&(in_isr||!regscratch[i]))||(in_isr&&function_calls&&regscratch[i]&&!regsa[i])){
+	emit(f,"\tpla\n");
+	emit(f,"\tsta\t%s\n",mregnames[i]);
+      }
+    }
+  }
+  if(rsavesize>0&&of+rsavesize>255){
+    if(of!=1&&ar&&!pushedacc){
+      pushedacc=t4;
+      emit(f,"\tsta\t%s\n",mregnames[pushedacc]);
+    }
+    incsp(f,of);
+    offset-=of;
+    of=0;
+  }
+  if(rsavesize>0){
+    if(ar&&!pushedacc){
+      pushedacc=t4;
+      emit(f,"\tsta\t%s\n",mregnames[pushedacc]);
+    }
+  }
+  if(rsavesize){
+    if(libsave){
+      sety(f,of+rsavesize-1);
+      emit(f,"\tjsr\t%s__rload%ld\n",idprefix,rscnt);
+      yval=of;
+    }else{
+      for(i=FIRST_GPR;i<=LAST_GPR;i++){
+	if((regused[i]&&(in_isr||!regscratch[i]))||(in_isr&&function_calls&&regscratch[i]&&!regsa[i])){
+	  sety(f,of++);
+	  emit(f,"\tlda\t(%s),y\n",mregnames[sp]);
+	  emit(f,"\tsta\t%s\n",mregnames[i]);
+	}
+      }
+    }
+  }
+  if(in_isr){
+    if(offset||function_calls){
+      emit(f,"\tpla\n");
+      emit(f,"\tsta\t%s+1\n",mregnames[sp]);
+      emit(f,"\tpla\n");
+      emit(f,"\tsta\t%s\n",mregnames[sp]);
+    }
+  }else if(offset==2&&!pushedacc){
+    emit(f,"\tinc\t%s\n",mregnames[sp]);
+    emit(f,"\tbeq\t%s%d\n",labprefix,++label);
+    emit(f,"\tinc\t%s\n",mregnames[sp]);
+    emit(f,"\tbeq\t%s%d\n",labprefix,++label);
+    reload_acc(f);
+    emit(f,ret);
+    emit(f,"%s%d:\n",labprefix,label-1);
+    emit(f,"\tinc\t%s\n",mregnames[sp]);
+    emit(f,"%s%d:\n",labprefix,label);
+    emit(f,"\tinc\t%s+1\n",mregnames[sp]);
+  }else{
+    if(offset!=0&&ar&&!pushedacc){
+      pushedacc=t4;
+      emit(f,"\tsta\t%s\n",mregnames[pushedacc]);
+    }
+    incsp(f,offset);
+  }
+
+  reload_acc(f);
+
+  if(in_isr){
+    emit(f,"\tplz\n");
+    emit(f,"\tply\n");
+    emit(f,"\tplx\n");
+    emit(f,"\tpla\n");
+  }
+  emit(f,ret);
+
+  for(p=first_cmplist;p;){
+    struct cmplist *m;
+    emit(f,"%s%d:\n",labprefix,p->from);
+    if(p->mode==JMPIND){
+      /* indirect call */
+      emit(f,"\tjmp\t(%s)\n",mregnames[p->to]);
+    }else{
+      pushedacc=p->mode;
+      reload_acc(f);
+      emit(f,"\tjmp\t%s%d\n",labprefix,p->to);
+    }
+    m=p;
+    p=p->next;
+    free(m);
+  }
+  first_cmplist=0;
+  pushedacc=0;
+}
+
+/****************************************/
+/*  End of private data and functions.  */
+/****************************************/
+
+/*  Does necessary initializations for the code-generator. Gets called  */
+/*  once at the beginning and should return 0 in case of problems.      */
+int init_cg(void)
+{
+  int i;
+  /*  Initialize some values which cannot be statically initialized   */
+  /*  because they are stored in the target's arithmetic.             */
+  maxalign=l2zm(1L);
+  char_bit=l2zm(8L);
+  stackalign=l2zm(1);
+
+  if(IEEE){
+    ieee=1;
+    msizetab[DOUBLE]=msizetab[LDOUBLE]=l2zm(8L);
+  }
+
+
+  mregnames[0]=regnames[0]="noreg";
+  for(i=FIRST_GPR;i<=LAST_GPR;i++){
+    regnames[i]=mymalloc(10);
+    sprintf(regnames[i],"r%d",i-FIRST_GPR);
+    mregnames[i]=regnames[i];
+    regsize[i]=l2zm(1L);
+    regtype[i]=&ctyp;
+  }
+  for(i=FIRST_PAIR;i<=LAST_PAIR;i++){
+    int sr=(i-FIRST_PAIR)*2+FIRST_GPR;
+    regnames[i]=mymalloc(10);
+    sprintf(regnames[i],"%s/%s",mregnames[sr],mregnames[sr+1]);
+    mregnames[i]=regnames[sr];
+    regsize[i]=l2zm(2L);
+    regtype[i]=&ityp;
+  }
+  for(i=FIRST_BIG;i<=LAST_BIG;i++){
+    regnames[i]=mymalloc(10);
+    sprintf(regnames[i],"btmp%d",i-FIRST_BIG);
+    mregnames[i]=regnames[i];
+    regsize[i]=msizetab[FLOAT];
+    regtype[i]=&ftyp;
+    regsa[i]=0;
+    regscratch[i]=1;
+  }
+  for(i=FIRST_BIGP;i<=LAST_BIGP;i++){
+    int sr=(i-FIRST_BIGP)*2+FIRST_BIG;
+    regnames[i]=mymalloc(20);
+    sprintf(regnames[i],"%s/%s",mregnames[sr],mregnames[sr+1]);
+    mregnames[i]=regnames[sr];
+    regsize[i]=msizetab[LLONG];
+    regtype[i]=&lltyp;
+    regsa[i]=0;
+    regscratch[i]=1;
+  }
+
+  mregnames[ra] = regnames[ra] = "a";
+  mregnames[rx] = regnames[rx] = "x";
+  mregnames[ry] = regnames[ry] = "y";
+  mregnames[rz] = regnames[rz] = "z";
+  regsize[ra]=regsize[rx]=regsize[ry]=l2zm(1L);
+  regtype[ra]=regtype[rx]=regtype[ry]=&ctyp;
+  mregnames[sp]=regnames[sp] = "sp";
+  mregnames[sp1]=regnames[sp1] = "sp";
+  mregnames[sp2]=regnames[sp2] = "sp+1";
+
+  mregnames[rax]=regnames[rax] = "ax";
+  regsize[rax]=regsize[sp]=l2zm(2L);
+  regtype[rax]=regtype[sp]=&ityp;
+
+  reg_prio[ra]=reg_prio[rax]=100;
+  reg_prio[rx]=50;
+
+  mregnames[raxyz]=regnames[raxyz] = "axyz";
+  regsize[raxyz]=l2zm(3L);
+  regtype[raxyz]=&lltyp;
+
+  /*  Use multiple ccs.   */
+  multiple_ccs=0;
+
+  short_push=1;
+
+  static_cse=0;
+
+  dref_cse=1;
+
+  /*prefer_statics=1; TODO */
+
+
+  if(optsize){
+    clist_copy_stack=2;
+    clist_copy_pointer=2;
+    clist_copy_static=2;
+  }else if(optspeed){
+    clist_copy_stack=64;
+    clist_copy_pointer=64;
+    clist_copy_static=64;
+  }else{
+    clist_copy_stack=8;
+    clist_copy_pointer=8;
+    clist_copy_static=8;
+  }
+
+  /*  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.          */
+  t_min[CHAR]=l2zm(-128L);
+  t_min[SHORT]=l2zm(-32768L);
+  t_min[LONG]=zmsub(l2zm(-2147483647L),l2zm(1L));
+  t_min[INT]=t_min(SHORT);
+  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[LONG]=ul2zum(2147483647UL);
+  t_max[INT]=t_max(SHORT);
+  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[LONG]=ul2zum(4294967295UL);
+  tu_max[INT]=t_max(UNSIGNED|SHORT);
+  tu_max[LLONG]=zumkompl(ul2zum(0UL));
+  tu_max[MAXINT]=t_max(UNSIGNED|LLONG);
+  
+  /*  Reserve a few registers for use by the code-generator.      */
+  /*  This is not optimal but simple.                             */
+  regsa[raxyz]=regsa[rz]=regsa[ry]=regsa[sp]=regsa[sp1]=regsa[sp2]=REGSA_NEVER;
+  regsa[t1]=regsa[t2]=regsa[t3]=regsa[t4]=REGSA_NEVER;
+  regscratch[ra]=regscratch[rx]=regscratch[rax]=1;
+  if(!GLOBACC)
+    regsa[ra]=regsa[rx]=regsa[rax]=REGSA_TEMPS;
+  regscratch[sp]=regscratch[sp1]=regscratch[sp2]=regscratch[ry]=regscratch[rz]=0;
+  regscratch[t1]=regscratch[t2]=regscratch[t3]=regscratch[t4]=1;
+
+  for(i=FIRST_GPR;i<=LAST_GPR-VOL_GPRS;i++){
+    regscratch[i]=1;
+    if(i&1)
+      regscratch[FIRST_PAIR+(i-FIRST_GPR)/2]=1;
+  }
+
+  target_macros=marray;
+
+  declare_builtin("__mulint16",INT,INT,FIRST_PAIR,INT,FIRST_PAIR+1,1,0);
+  declare_builtin("__muluint16",UNSIGNED|INT,UNSIGNED|INT,FIRST_PAIR,UNSIGNED|INT,FIRST_PAIR+1,1,0);
+  declare_builtin("__divuint16",UNSIGNED|INT,UNSIGNED|INT,FIRST_PAIR,UNSIGNED|INT,FIRST_PAIR+1,1,0);
+  declare_builtin("__divint16",INT,INT,FIRST_PAIR,INT,FIRST_PAIR+1,1,0);
+  declare_builtin("__moduint16",UNSIGNED|INT,UNSIGNED|INT,FIRST_PAIR,UNSIGNED|INT,FIRST_PAIR+1,1,0);
+  declare_builtin("__modint16",INT,INT,FIRST_PAIR,INT,FIRST_PAIR+1,1,0);
+
+  declare_builtin("__mulint32",LONG,LONG,FIRST_BIG+1,LONG,FIRST_BIG+2,1,0);
+  declare_builtin("__muluint32",UNSIGNED|LONG,UNSIGNED|LONG,FIRST_BIG+1,UNSIGNED|LONG,FIRST_BIG+2,1,0);
+  declare_builtin("__divint32",LONG,LONG,FIRST_BIG,LONG,FIRST_BIG+1,1,0);
+  declare_builtin("__divuint32",UNSIGNED|LONG,UNSIGNED|LONG,FIRST_BIG,UNSIGNED|LONG,FIRST_BIG+1,1,0);
+  declare_builtin("__modint32",LONG,LONG,FIRST_BIG,LONG,FIRST_BIG+1,1,0);
+  declare_builtin("__moduint32",UNSIGNED|LONG,UNSIGNED|LONG,FIRST_BIG,UNSIGNED|LONG,FIRST_BIG+1,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("__divint64",LLONG,LLONG,0,LLONG,0,1,0);
+  declare_builtin("__divuint64",UNSIGNED|LLONG,UNSIGNED|LLONG,0,UNSIGNED|LLONG,0,1,0);
+  declare_builtin("__modint64",LLONG,LLONG,0,LLONG,0,1,0);
+  declare_builtin("__moduint64",UNSIGNED|LLONG,UNSIGNED|LLONG,0,UNSIGNED|LLONG,0,1,0);
+  declare_builtin("__lsrint64",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("__sint32toflt32",FLOAT,LONG,OLDFP?0:FIRST_BIG,0,0,1,0);
+  declare_builtin("__uint32toflt32",FLOAT,UNSIGNED|LONG,OLDFP?0:FIRST_BIG,0,0,1,0);
+  declare_builtin("__flt32tosint32",LONG,FLOAT,OLDFP?0:FIRST_BIG,0,0,1,0);
+  declare_builtin("__flt32touint32",UNSIGNED|LONG,FLOAT,OLDFP?0:FIRST_BIG,0,0,1,0);
+  declare_builtin("__sint16toflt32",FLOAT,INT,FIRST_PAIR,0,0,1,0);
+  declare_builtin("__uint16toflt32",FLOAT,UNSIGNED|INT,FIRST_PAIR,0,0,1,0);
+  declare_builtin("__flt32tosint16",INT,FLOAT,OLDFP?0:FIRST_BIG,0,0,1,0);
+  declare_builtin("__flt32touint16",UNSIGNED|INT,FLOAT,OLDFP?0:FIRST_BIG,0,0,1,0);
+
+  declare_builtin("__sint32toflt64",DOUBLE,LONG,OLDFP?0:FIRST_BIG,0,0,1,0);
+  declare_builtin("__uint32toflt64",DOUBLE,UNSIGNED|LONG,OLDFP?0:FIRST_BIG,0,0,1,0);
+  declare_builtin("__flt64tosint32",LONG,DOUBLE,OLDFP?0:FIRST_BIGP,0,0,1,0);
+  declare_builtin("__flt64touint32",UNSIGNED|LONG,DOUBLE,OLDFP?0:FIRST_BIGP,0,0,1,0);
+  declare_builtin("__sint16toflt64",DOUBLE,INT,FIRST_PAIR,0,0,1,0);
+  declare_builtin("__uint16toflt64",DOUBLE,UNSIGNED|INT,FIRST_PAIR,0,0,1,0);
+  declare_builtin("__flt64tosint16",INT,DOUBLE,OLDFP?0:FIRST_BIGP,0,0,1,0);
+  declare_builtin("__flt64touint16",UNSIGNED|INT,DOUBLE,OLDFP?0:FIRST_BIGP,0,0,1,0);
+
+  declare_builtin("__flt64toflt32",FLOAT,DOUBLE,OLDFP?0:FIRST_BIGP,0,0,1,0);
+  declare_builtin("__flt32toflt64",DOUBLE,FLOAT,OLDFP?0:FIRST_BIG,0,0,1,0);
+
+  declare_builtin("__addflt32",FLOAT,FLOAT,OLDFP?0:FIRST_BIG+1,FLOAT,OLDFP?0:FIRST_BIG,1,0);
+  declare_builtin("__subflt32",FLOAT,FLOAT,OLDFP?0:FIRST_BIG+1,FLOAT,OLDFP?0:FIRST_BIG,1,0);
+  declare_builtin("__mulflt32",FLOAT,FLOAT,OLDFP?0:FIRST_BIG+1,FLOAT,OLDFP?0:FIRST_BIG,1,0);
+  declare_builtin("__divflt32",FLOAT,FLOAT,OLDFP?0:FIRST_BIG+1,FLOAT,OLDFP?0:FIRST_BIG,1,0);
+  declare_builtin("__negflt32",FLOAT,FLOAT,OLDFP?0:FIRST_BIG,0,0,1,0);
+  declare_builtin("__cmpsflt32",CHAR,FLOAT,OLDFP?0:FIRST_BIG+1,FLOAT,OLDFP?0:FIRST_BIG,1,0);
+
+#if 0
+  for(i=1;i<MAXR;i++){
+    printf("%02d %s scratch=%d ",i,regnames[i],regscratch[i]);
+    if(reg_pair(i,&rp))
+      printf("pair(%s,%s)",regnames[rp.r1],regnames[rp.r2]);
+    printf("\n");
+  }
+#endif
+
+  if(NOPEEP) nopeep=1;
+  if(CBMASCII) cbmascii=1;
+  if(ATASCII) atascii=1;
+
+
+  for(i=0;i<=MAX_TYPE;i++){
+    sizetab[i]=l2zm(msizetab[i]);
+    align[i]=l2zm(malign[i]);
+  }
+
+  bankv.storage_class=EXTERN;
+  bankv.identifier="__bankv";
+  bankv.vtyp=new_typ();
+  bankv.vtyp->flags=CHAR;
+
+  bankcnum=COMMONBANK;
+
+  return 1;
+}
+
+void init_db(FILE *f)
+{
+}
+
+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.        */
+/*  A pointer MUST be returned in a register. The code-generator    */
+/*  has to simulate a pseudo register if necessary.                 */
+{
+  int typ=t->flags&NQ;
+  if(ISSTRUCT(typ)||ISUNION(typ)||typ==VOID) 
+    return 0;
+  if(OLDFP&&ISFLOAT(typ)) return FIRST_GPR;
+  if(typ==LONG||typ==FLOAT||ISFPOINTER(typ)||(!ieee&&(typ==DOUBLE||typ==LDOUBLE)))
+    return FIRST_BIG;
+  if(typ==LLONG||(ieee&&(typ==DOUBLE||typ==LDOUBLE)))
+    return FIRST_BIGP;
+  if(zmleq(szof(t),l2zm(1L)))
+    return ra;
+  if(zmleq(szof(t),l2zm(2L))) 
+    return rax;
+  else
+    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>=FIRST_PAIR&&r<=LAST_PAIR){
+    p->r1=(r-FIRST_PAIR)*2+FIRST_GPR;
+    p->r2=p->r1+1;
+    return 1;
+  }else if(r>=FIRST_BIGP&&r<=LAST_BIGP){
+    p->r1=(r-FIRST_BIGP)*2+FIRST_BIG;
+    p->r2=p->r1+1;
+    return 1;
+  }else if(r==rax){
+    p->r1=ra;
+    p->r2=rx;
+    return 1;
+  }else if(r==raxyz) {
+    // TODO: PGS: How do we declare a reg pair that is made of 4 regs, not 2?
+    p->r1=ra;
+    p->r2=rx;
+    return 1;
+  }else if(r==sp){
+    p->r1=sp1;
+    p->r2=sp2;
+    return 1;
+  }
+  return 0;
+}
+
+/* estimate the cost-saving if object o from IC p is placed in
+   register r */
+int cost_savings(struct IC *p,int r,struct obj *o)
+{
+  int c=p->code;
+  /*TODO: adapt this */
+  if(o->flags&VKONST){
+    return 0;
+    if(o==&p->q1&&p->code==ASSIGN&&(p->z.flags&DREFOBJ))
+      return 4;
+    else
+      return 2;
+  }
+  if(o->flags&DREFOBJ){
+    if(isptr(r))
+      return 4;
+    if(r==rax)
+      return INT_MIN;
+  }
+  if(c==SETRETURN&&r==p->z.reg&&!(o->flags&DREFOBJ)) return 6;
+  if(c==GETRETURN&&r==p->q1.reg&&!(o->flags&DREFOBJ)) return 6;
+  if(r==ra)
+    return 5;
+  if(r==rx)
+    return 4;
+  if(r==rax)
+    return 2;
+  return 2;
+}
+
+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(r==0)
+    return 0;
+  if(r==rax&&NORAX)
+    return 0;
+  t&=NQ;
+  if(ISCHAR(t))
+    if(r==ra/*||r==rx*/||(r>=FIRST_GPR&&r<=LAST_GPR))
+      return 1;
+  if(ISSHORT(t)){
+    if(r==rax){
+      if(t==POINTER&&mode<0)
+	return 1;
+      if(t!=POINTER)
+	return 1;
+    }
+    if(r>=FIRST_PAIR&&r<=LAST_PAIR)
+      return 1;
+  }
+  if(r>=FIRST_BIG&&r<=LAST_BIG){
+    if(t==LONG||t==FLOAT||((t==DOUBLE||t==LDOUBLE)&&!ieee))
+      return 1;
+    if(t==FPOINTER)
+      return 1;
+  }
+  if(r>=FIRST_BIGP&&r<=LAST_BIGP){
+    if(t==LLONG||((t==DOUBLE||t==LDOUBLE)&&ieee))
+      return 1;
+  }
+  return 0;
+}
+
+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;
+}
+
+int must_convert(int o,int t,int const_expr)
+/*  Returns zero if code for converting np to type t    */
+/*  can be omitted.                                     */
+/*  On the PowerPC cpu pointers and 32bit               */
+/*  integers have the same representation and can use   */
+/*  the same registers.                                 */
+{
+  int op=o&NQ,tp=t&NQ;
+
+  if(op==tp) return 0;
+  if(ISCHAR(op)&&ISCHAR(tp)) return 0;
+  if(ISSHORT(op)&&ISSHORT(tp)) return 0;
+  if(!ieee&&ISFLOAT(op)&&ISFLOAT(tp)) return 0;
+  if(op==DOUBLE&&tp==LDOUBLE) return 0;
+  if(op==LDOUBLE&&tp==DOUBLE) 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(STDSYNTAX)
+    emit(f,"\tspace\t%ld\n",zm2l(size));
+  else
+    emit(f,"\treserve\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.              */
+{
+  if(zm2l(align)>1) emit(f,"\talign 1\n");
+}
+
+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,b=bank(v);char *sec;
+  if(v->clist) constflag=is_const(v->vtyp);
+  if(v->storage_class==STATIC){
+    if(ISFUNC(v->vtyp->flags)) return;
+    if(v->tattr&ZPAGE)
+      emit(f,"\tzpage\t%s%ld\n",labprefix,zm2l(v->offset));
+    if(!special_section(f,v)){
+      if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))){emit(f,dataname);ebank(f,b);if(f) section=DATA;}
+      if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)){emit(f,rodataname);ebank(f,b);if(f) section=RODATA;}
+      if(!v->clist){emit(f,bssname);ebank(f,b);if(f) section=BSS;}
+    }
+    gen_align(f,falign(v->vtyp));
+    emit(f,"%s%ld:\n",labprefix,zm2l(v->offset));
+    newobj=1;
+  }
+  if(v->storage_class==EXTERN){
+    emit(f,"\tglobal\t%s%s\n",idprefix,v->identifier);
+    if(v->tattr&ZPAGE)
+      emit(f,"\tzpage\t%s%s\n",idprefix,v->identifier);
+    if(v->flags&(DEFINED|TENTATIVE)){
+      if(!special_section(f,v)){
+	if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))){emit(f,dataname);ebank(f,b);if(f) section=DATA;}
+	if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)){emit(f,rodataname);ebank(f,b);if(f) section=RODATA;}
+	if(!v->clist){emit(f,bssname);ebank(f,b);if(f) section=BSS;}
+      }
+
+      gen_align(f,falign(v->vtyp));
+      emit(f,"%s%s:\n",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.                      */
+{
+  if(ISCHAR(t))
+    emit(f,"\tbyte\t");
+  else
+    emit(f,"\tword\t");
+  if(!p->tree){
+    if(ISLONG(t)||ISFLOAT(t)){
+      if(ieee&&ISFLOAT(t)){
+	emit_ieee(f,&p->val,t&NQ);
+      }else{
+	eval_const(&p->val,t&NU);
+	if(ISFLOAT(t)) cnv_fp();
+	gval.vmax=zmand(vmax,l2zm(0xffffL));
+	emitval(f,&gval,MAXINT);
+	emit(f,",");
+	gval.vmax=zmand(zmrshift(vmax,l2zm(16L)),l2zm(0xffffL));
+	emitval(f,&gval,MAXINT);
+      }
+    }else{
+      if(ISFPOINTER(t)){
+	eval_const(&p->val,t&NU);
+	emit(f,"%ld\n",(long)zm2l(vmax)&0xffff);
+	emit(f,"\tbyte\t%d\n",(int)((zm2l(vmax)>>16)&0xff));
+      }else
+	emitval(f,&p->val,t&NU);
+    }
+  }else{
+    emit_obj(f,&p->tree->o,t&NU);
+    if(ISFPOINTER(t)){
+      int b;
+      if((p->tree->o.flags&(VAR|VARADR))!=(VAR|VARADR)) ierror(0);
+      b=bank(p->tree->o.v);
+      emit(f,"\n\tbyte\t%d",b>=0?b:bankcnum);
+    }
+  }
+  emit(f,"\n");newobj=0;
+}
+
+
+/*  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 *p,struct Var *v,zmax offset)
+/*  The main code-generation.                                           */
+{
+  int c,t,i;
+  struct IC *mi;
+  FILE *rf=f;
+  static char *dbgfile;
+  static int dbgline;
+
+  if(vlas){
+    fp=FPVLA_REG;
+    if(!reg_pair(fp,&rp)) ierror(0);
+    fp1=rp.r1;
+    fp2=rp.r2;
+    regused[fp]=regused[fp1]=regused[fp2]=1;
+   }else{
+    fp=sp;
+    fp1=sp1;
+    fp2=sp2;
+  }
+  argsize=0;
+  localsize=offset;
+  if(DEBUG&1) printf("gen_code()\n");
+
+  cbank=bank(v);
+
+  if(!v->fi) v->fi=new_fi();
+  v->fi->flags|=ALL_REGS;
+
+  for(pass=0;pass<2;pass++){
+
+    if(DEBUG&1) printf("pass %d\n",pass);
+
+    if(pass==0){
+      f=0;
+      mi=clone_ic(p);
+    }else
+      f=rf;
+
+    for(c=1;c<=MAXR;c++) regs[c]=0; /*regsa[c];*/
+    maxpushed=0;
+
+    /*FIXME*/
+    if(v->tattr&INTERRUPT){
+      ret="\trti\n";
+      in_isr=1;
+    }else{
+      ret="\trts\n";
+      in_isr=0;
+    }
+
+    if(!nopeep) peephole(pass==0?p:mi);
+
+    function_top(f,v,localsize);
+
+    pushed=0;
+
+    yval=NOVAL;
+
+    dbgfile=0;
+    dbgline=0;
+
+    for(p=pass==0?p:mi;p;pr(f,p),p=p->next){
+
+
+
+      if(DEBUG&1) pric2(stdout,p);
+
+      if(debug_info){
+	if(p->file&&p->line){
+	  if(p->file!=dbgfile||p->line!=dbgline){
+	    dbgfile=p->file;
+	    dbgline=p->line;
+	    emit(f,"; %d \"%s\"\n",dbgline,dbgfile);
+	  }
+	}
+      }
+
+      c=p->code;t=p->typf;
+
+      if(c==NOP) {p->z.flags=0;continue;}
+      if(c==ALLOCREG){
+	regs[p->q1.reg]=1;
+	if(reg_pair(p->q1.reg,&rp)){
+	  regs[rp.r1]=1;
+	  regs[rp.r2]=1;
+	}
+	continue;
+      }
+      if(c==FREEREG){
+	regs[p->q1.reg]=0;
+	if(reg_pair(p->q1.reg,&rp)){
+	  regs[rp.r1]=0;
+	  regs[rp.r2]=0;
+	}
+	continue;
+      }
+      if(c==LABEL) {emit(f,"%s%d:\n",labprefix,t);yval=NOVAL;continue;}
+      if(c==BRA){
+	yval=NOVAL;
+	if(t==exit_label&&localsize+argsize+rsavesize+rscnt==0)
+	  emit(f,ret);
+	else
+	  emit(f,"\tjmp\t%s%d\n",labprefix,t);
+	continue;
+      }
+      if(c>=BEQ&&c<BRA){
+	yval=NOVAL;
+	continue;
+      }
+
+      if(c==MOVETOREG){
+	p->code=c=ASSIGN;
+	p->typf=t=regtype[p->z.reg]->flags;
+	p->q2.val.vmax=sizetab[regtype[p->z.reg]->flags];
+      }
+      if(c==MOVEFROMREG){
+	p->code=c=ASSIGN;
+	p->typf=t=regtype[p->q1.reg]->flags;
+	p->q2.val.vmax=sizetab[regtype[p->q1.reg]->flags];
+      }
+      if(c==CONVERT&&ISCHAR(t)&&ISCHAR(p->typf2)){
+	p->code=c=ASSIGN;
+	p->q2.val.vmax=sizetab[CHAR];
+      }
+      if(c==CONVERT&&msizetab[t&NQ]==3&&msizetab[p->typf2&NQ]==3){
+	p->code=c=ASSIGN;
+	p->q2.val.vmax=sizetab[SHORT];
+      }
+      if(c==CONVERT&&ISSHORT(t)&&ISSHORT(p->typf2)){
+	p->code=c=ASSIGN;
+	p->q2.val.vmax=sizetab[SHORT];
+      }
+      if(c==CONVERT&&ISLONG(t)&&ISLONG(p->typf2)){
+	p->code=c=ASSIGN;
+	p->q2.val.vmax=sizetab[LONG];
+      }
+      if(c==CONVERT&&ISLLONG(t)&&ISLLONG(p->typf2)){
+	p->code=c=ASSIGN;
+	p->q2.val.vmax=sizetab[LLONG];
+      }
+      if(c==CONVERT&&ISFLOAT(t)&&ISFLOAT(p->typf2)){
+	p->code=c=ASSIGN;
+	p->q2.val.vmax=sizetab[t&NQ];
+      }
+
+
+      /* switch commutative operands if suitable */
+      if(c==ADD||c==MULT||c==AND||c==XOR||c==OR||(c==ADDI2P&&ISSHORT(t)&&!ISFPOINTER(p->typf2))){
+	if(compare_objects(&p->q2,&p->z)||isacc(q2)){
+	  struct obj tmp;
+	  tmp=p->q1;
+	  p->q1=p->q2;
+	  p->q2=tmp;
+	}
+      }
+
+      if(c==COMPARE&&(p->q1.flags&(KONST|DREFOBJ))==KONST){
+	obj tmp;
+	tmp=p->q1;
+	p->q1=p->q2;
+	p->q2=tmp;
+      }
+
+      c=p->code;
+      if(c==SUBPFP) c=SUB;
+      /*if(c==ADDI2P) c=ADD;*/
+      /*if(c==SUBIFP) c=SUB;*/
+
+
+      if(c==MINUS){
+	if(isacc(q1)&&isacc(z)){
+	  emit(f,"\tneg\n");
+	  if(!ISCHAR(t)){
+	    emit(f,"\tpha\n");
+	    emit(f,"\ttxa\n");
+	    emit(f,"\teor\t#255\n");
+	    emit(f,"\tadc\t#0\n");
+	    emit(f,"\ttax\n");
+	    emit(f,"\tpla\n");
+	  }
+	  continue;
+	}
+	p->code=c=SUB;
+	p->q2=p->q1;
+	p->q1.flags=KONST;
+	gval.vmax=Z0;
+	eval_const(&gval,MAXINT);
+	insert_const(&p->q1.val,t);
+      }
+
+      preload(f,p);
+
+      if(c==CONVERT){
+	int to=q1typ(p)&NU;
+	t&=NU;
+	if(ISCHAR(t)){
+	  get_acc(f,p,CHAR);
+	  load_lobyte(f,&p->q1,to);
+	  store_lobyte(f,&p->z,t);
+	  continue;
+	}
+	if(ISLONG(to)){
+	  if(!isacc(z))
+	    get_acc(f,p,CHAR);
+	  if(zm2l(sizetab[t&NQ])==3){
+	    do_byte3(f,"lda",&p->q1,to);
+	    do_byte3(f,"sta",&p->z,t);
+	  }
+	  if(zm2l(sizetab[t&NQ])>=2){
+	    load_hibyte(f,&p->q1,to);
+	    store_hibyte(f,&p->z,t);
+	  }
+	  load_lobyte(f,&p->q1,to);
+	  store_lobyte(f,&p->z,t);
+	  continue;
+	}
+	if(ISSHORT(to)){
+	  if((t&UNSIGNED)||ISFPOINTER(t))
+	    get_acc(f,p,CHAR);
+	  else
+	    get_acc(f,p,SHORT);
+	  load_lobyte(f,&p->q1,to);
+	  store_lobyte(f,&p->z,t);
+	  load_hibyte(f,&p->q1,to);
+	  store_hibyte(f,&p->z,t);
+	  if(ISFPOINTER(t)){
+	    int b=-1;
+	    if((p->q1.flags&(VARADR|DREFOBJ))==VARADR) b=bank(p->q1.v);
+	    emit(f,"\tlda\t#%d\n",b>=0?b:bankcnum);
+	    do_byte3(f,"sta",&p->z,t);
+	    continue;
+	  }
+	  if(to&UNSIGNED){
+	    emit(f,"\tlda\t#0\n");
+	    do_byte3(f,"sta",&p->z,t);
+	    do_byte4(f,"sta",&p->z,t);
+	  }else{
+	    emit(f,"\tldx\t#0\n");
+	    emit(f,"\tcmp\t#0\n");
+	    emit(f,"\tbpl\t%s%d\n",labprefix,++label);
+	    emit(f,"\tdex\n");
+	    emit(f,"%s%d:\n",labprefix,label);
+	    if(indirect(&p->z)){
+	      emit(f,"\ttxa\n");
+	      do_byte3(f,"sta",&p->z,t);
+	      do_byte4(f,"sta",&p->z,t);
+	    }else{
+	      do_byte3(f,"stx",&p->z,t);
+	      do_byte4(f,"stx",&p->z,t);
+	    }
+	  }
+	  continue;
+	}
+	if(ISCHAR(to)){
+	  if(to&UNSIGNED){
+	    get_acc(f,p,CHAR);
+	    if(ISLONG(t)){
+	      load_lobyte(f,&p->q1,to);
+	      store_lobyte(f,&p->z,t);
+	      emit(f,"\tlda\t#0\n");
+	      store_hibyte(f,&p->z,t);
+	      do_byte3(f,"sta",&p->z,t);
+	      if(ISLONG(t))
+		do_byte4(f,"sta",&p->z,t);
+	      continue;
+	    }
+	    if(isacc(z))
+	      emit(f,"\tldx\t#0\n");
+	    else if(isacc(q1)){
+	      emit(f,"\tldx\t#0\n");
+	      store_acc(f,&p->z,t);
+	      continue;
+	    }else{
+	      emit(f,"\tlda\t#0\n");
+	      store_hibyte(f,&p->z,t);
+	    }
+	    load_lobyte(f,&p->q1,to);
+	    store_lobyte(f,&p->z,t);
+	  }else{
+	    int l=++label;
+	    get_acc(f,p,SHORT);
+	    emit(f,"\tldx\t#0\n");
+	    if(isreg(q1)&&p->q1.reg==ra)
+	      emit(f,"\tcmp\t#0\n");
+	    else
+	      load_lobyte(f,&p->q1,to);
+	    emit(f,"\tbpl\t%s%d\n",labprefix,label);
+	    emit(f,"\tdex\n");
+	    emit(f,"%s%d:\n",labprefix,label);
+	    store_lobyte(f,&p->z,t);
+	    if(indirect(&p->z)){
+	      emit(f,"\ttxa\n");
+	      store_hibyte(f,&p->z,t);
+	      if(ISLONG(t)){
+		do_byte3(f,"sta",&p->z,t);
+		do_byte4(f,"sta",&p->z,t);
+	      }
+	    }else{
+	      if(!isreg(z)||p->z.reg!=rax){
+		emit(f,"\tstx\t");
+		emit_hibyte(f,&p->z,t);
+		emit(f,"\n");
+	      }
+	      if(ISLONG(t)){
+		do_byte3(f,"stx",&p->z,t);
+		do_byte4(f,"stx",&p->z,t);
+	      }
+	    }
+	  }
+	  if(ISFPOINTER(t)){
+	    emit(f,"\tlda\t#%d\n",cbank>=0?cbank:bankcnum);
+	    do_byte3(f,"sta",&p->z,t);
+	  }
+	  continue;
+	}
+	if(ISFPOINTER(to)){
+	  get_acc(f,p,CHAR);
+	  if(zm2l(sizetab[t&NQ])>=3){
+	    do_byte3(f,"lda",&p->q1,to);
+	    do_byte3(f,"sta",&p->z,t);
+	  }
+	  if(zm2l(sizetab[t&NQ])>=2){
+	    load_hibyte(f,&p->q1,to);
+	    store_hibyte(f,&p->z,t);
+	  }
+	  load_lobyte(f,&p->q1,to);
+	  store_lobyte(f,&p->z,t);
+
+	  continue;
+	}
+	ierror(0);
+      }
+
+      if(c==KOMPLEMENT){
+	get_acc(f,p,CHAR);
+	if(ISCHAR(t)){
+	  load_acc(f,&p->q1,t);
+	  emit(f,"\teor\t#-1\n");
+	  store_acc(f,&p->z,t);
+	}else{
+	  if(isacc(q1))
+	    emit(f,"\tpha\n");
+	  if(ISLONG(t)){
+	    do_byte4(f,"lda",&p->q1,t);
+	    emit(f,"\teor\t#-1\n");
+	    do_byte4(f,"sta",&p->z,t);
+	    do_byte3(f,"lda",&p->q1,t);
+	    emit(f,"\teor\t#-1\n");
+	    do_byte3(f,"sta",&p->z,t);
+	  }
+	  load_hibyte(f,&p->q1,t);
+	  emit(f,"\teor\t#-1\n");
+	  store_hibyte(f,&p->z,t);
+	  if(isacc(q1))
+	    emit(f,"\tpla\n");
+	  load_lobyte(f,&p->q1,t);
+	  emit(f,"\teor\t#-1\n");
+	  store_lobyte(f,&p->z,t);
+	}
+	continue;
+      }
+      if(c==SETRETURN){
+	t&=NQ;
+	if(isreg(q1)&&p->q1.reg==p->z.reg) continue;
+	if(t==LONG||t==LLONG||ISFLOAT(t)||ISFPOINTER(t)){
+	  long l=zm2l(p->q2.val.vmax);
+	  int zr=p->z.reg;
+	  //get_acc(f,p,t);
+	  if((optsize||l>4)&&!ISFPOINTER(t)){
+	    int ind=indirect(&p->q1);
+	    if(ind) load_address(f,LAST_PAIR,&p->q1,t);
+	    BSET(regused,t3);
+	    BSET(regused,t4);
+	    sety(f,l-1);
+	    emit(f,"%s%d:\n",labprefix,++label);
+	    if(ind)
+	      emit(f,"\tlda\t(%s),y\n",mregnames[LAST_PAIR]);
+	    else{
+	      emit(f,"\tlda\t");
+	      if(!ISFLOAT(t)&&(p->q1.flags&(KONST|DREFOBJ))==KONST){
+		emit(f,"%s%d",labprefix,addfpconst(&p->q1,t));
+	      }else
+		emit_obj(f,&p->q1,t);
+	      emit(f,",y\n");
+	    }
+	    emit(f,"\tsta\t%s,y\n",mregnames[zr]);
+	    emit(f,"\tdey\n");
+	    emit(f,"\tbpl\t%s%d\n",labprefix,label);
+	    yval=255;
+	  }else{
+	    if((p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)){
+	      if(p->q1.reg==zr){
+		int r=get_reg(f,p,POINTER);
+		if(r==FIRST_PAIR||r==FIRST_PAIR+1)
+		  ierror(0);
+		if(!reg_pair(r,&rp2)) ierror(0);
+		emit(f,"\tlda\t%s\n",mregnames[zr]);
+		emit(f,"\tsta\t%s\n",mregnames[rp2.r1]);
+		emit(f,"\tlda\t%s+1\n",mregnames[zr]);
+		emit(f,"\tsta\t%s\n",mregnames[rp2.r2]);
+		p->q1.reg=r;
+	      }
+	    }
+	    load_lobyte(f,&p->q1,t);
+	    emit(f,"\tsta\t%s\n",mregnames[zr]);
+	    load_hibyte(f,&p->q1,t);
+	    emit(f,"\tsta\t%s+1\n",mregnames[zr]);
+	    do_byte3(f,"lda",&p->q1,t);
+	    emit(f,"\tsta\t%s+2\n",mregnames[zr]);
+	    if(!ISFPOINTER(t)){
+	      do_byte4(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s+3\n",mregnames[zr]);
+	    }
+	    /*TODO:regused OLDFP */
+	    regused[zr]=1;
+	  }
+	  continue;
+	}
+	//get_acc(f,p,t);
+	load_acc(f,&p->q1,t);
+	regused[ra]=1;
+	regused[rx]=1;
+	continue;
+      }
+      if(c==GETRETURN){
+	t&=NQ;
+	if(isreg(z)&&p->q1.reg==p->z.reg) continue;
+	if(t==LONG||t==LLONG||ISFLOAT(t)||ISFPOINTER(t)){
+	  long l=zm2l(p->q2.val.vmax);
+	  int qr=p->q1.reg;
+	  if((optsize||l>4)&&!ISFPOINTER(t)){
+	    int ind=indirect(&p->z);
+	    if(ind) load_address(f,LAST_PAIR,&p->z,t);
+	    BSET(regused,t3);
+	    BSET(regused,t4);
+	    sety(f,l-1);
+	    emit(f,"%s%d:\n",labprefix,++label);
+	    emit(f,"\tlda\t%s,y\n",mregnames[qr]);
+	    if(ind)
+	      emit(f,"\tsta\t(%s),y\n",mregnames[LAST_PAIR]);
+	    else{
+	      emit(f,"\tsta\t");
+	      emit_obj(f,&p->z,t);
+	      emit(f,",y\n");
+	    }
+	    emit(f,"\tdey\n");
+	    emit(f,"\tbpl\t%s%d\n",labprefix,label);
+	    yval=255;
+	  }else{
+	    if((p->z.reg&(REG|DREFOBJ))==(REG|DREFOBJ)){
+	      if(p->z.reg==qr) ierror(0);
+	    }
+	    emit(f,"\tlda\t%s\n",mregnames[qr]);
+	    store_lobyte(f,&p->z,t);
+	    emit(f,"\tlda\t%s+1\n",mregnames[qr]);
+	    store_hibyte(f,&p->z,t);
+	    emit(f,"\tlda\t%s+2\n",mregnames[qr]);
+	    do_byte3(f,"sta",&p->z,t);
+	    if(!ISFPOINTER(t)){
+	      emit(f,"\tlda\t%s+3\n",mregnames[qr]);
+	      do_byte4(f,"sta",&p->z,t);
+	    }
+	  }
+	  continue;
+	}
+	if(p->q1.reg)
+	  store_acc(f,&p->z,t);
+	continue;
+      }
+      if(c==CALL){
+	int reg;
+
+	if(argsize<zm2l(p->q2.val.vmax)) argsize=zm2l(p->q2.val.vmax);
+
+	/*FIXME*/
+#if 0      
+	if(stack_valid&&(p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&(p->q1.v->fi->flags&ALL_STACK)){
+	  if(framesize+zum2ul(p->q1.v->fi->stack1)>stack)
+	    stack=framesize+zum2ul(p->q1.v->fi->stack1);
+	}else
+	  stack_valid=0;
+#endif
+	if((p->q1.flags&(VAR|DREFOBJ))==VAR&&!strcmp("__va_start",p->q1.v->identifier)){
+	  long of=va_offset(v)+localsize+rsavesize+argsize;
+	  emit(f,"\tlda\t%s\n",mregnames[fp]);
+	  if(of){
+	    emit(f,"\tclc\n");
+	    if(of&255)
+	      emit(f,"\tadc\t#%d\n",(of&255));
+	  }
+	  emit(f,"\tldx\t%s+1\n",mregnames[fp]);
+	  if(of&0xff00){
+	    emit(f,"\tpha\n");
+	    emit(f,"\ttxa\n");
+	    emit(f,"\tadc\t#%d\n",(of>>8)&255);
+	    emit(f,"\ttax\n");
+	    emit(f,"\tpla\n");
+	  }else if(of){
+	    emit(f,"\tbcc\t%s%d\n",labprefix,++label);
+	    emit(f,"\tinx\n");
+	    emit(f,"%s%d:\n",labprefix,label);
+	  }
+	  continue;
+	}
+	if((p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&p->q1.v->fi->inline_asm){
+	  emit(f,";startinline\n");
+	  emit_inline_asm(f,p->q1.v->fi->inline_asm);
+	  emit(f,";endinline\n");
+	}else if(p->q1.flags&DREFOBJ){
+	  if(ISFPOINTER(p->q1.dtyp)){
+	    p->q1.flags&=~DREFOBJ;
+	    load_reg(f,LAST_PAIR,&p->q1,POINTER);
+	    if(indirect(&p->q1)){
+	      do_byte3(f,"lda",&p->q1,FPOINTER);
+	      emit(f,"\ttay\n");
+	    }else
+	      do_byte3(f,"ldy",&p->q1,FPOINTER);
+	    emit(f,"\tlda\t#%d\n",cbank>=0?cbank:bankcnum);
+	    emit(f,"\tjsr\t%s__bankjsr\n",idprefix);
+	    yval=NOVAL;
+	  }else{
+	    if(!(p->q1.flags&REG)) ierror(0);
+	    emit(f,"\tjsr\t%s%d\n",labprefix,++label);
+	    yval=NOVAL;
+	    add_cmplist(label,p->q1.reg,JMPIND);
+	  }
+	}else{
+	  int tbank=-1;
+	  if(p->q1.flags&VAR) tbank=bank(p->q1.v);
+	  if(tbank!=cbank&&tbank>=0){
+	    if(cbank>=0){
+	      load_address(f,LAST_PAIR,&p->q1,t);
+	      sety(f,tbank);
+	      emit(f,"\tlda\t#%d\n",cbank);
+	      emit(f,"\tjsr\t%s__bankjsr\n",idprefix);
+	      yval=NOVAL;
+	      continue;
+	    }
+	    sety(f,tbank);
+	    emit(f,"\tjsr\t%s__bankswitch\n",idprefix);
+	    yval=NOVAL;
+	  }
+	  if((p->q1.flags&VAR)&&!strcmp(p->q1.v->identifier,"_fmemcpy"))
+	    emit(f,"\tlda\t#%d\n",cbank>=0?cbank:bankcnum);
+	  emit(f,"\tjsr\t");
+	  emit_obj(f,&p->q1,t);
+	  emit(f,"\n");
+	}
+	pushed-=zm2l(p->q2.val.vmax);
+	if(!calc_regs(p,f!=0)&&v->fi) v->fi->flags&=~ALL_REGS;
+	yval=NOVAL;
+	continue;
+      }
+      if(c==ASSIGN||c==PUSH){
+	if(t==0) ierror(0);
+	if((p->q1.flags&(KONST|DREFOBJ))==KONST&&(t&NQ)==LLONG){
+	  int i;
+	  eval_const(&p->q1.val,t);
+	  for(i=0;i<8;i++){
+	    emit(f,"\tlda\t#%d\n",zm2l(vmax)&255);
+	    vmax=zmrshift(vmax,l2zm(8L));
+	    if(c==PUSH||(p->z.flags&DREFOBJ)){
+	      sety(f,i+((c==PUSH)?pushed:0));
+	      emit(f,"\tsta\t(%s),y\n",(c==PUSH)?mregnames[sp]:mregnames[p->z.reg]);
+	    }else{
+	      p->z.val.vmax=zmadd(p->z.val.vmax,l2zm((long)i));
+	      emit(f,"\tsta\t");
+	      emit_lobyte(f,&p->z,t);
+	      emit(f,"\n");
+	      p->z.val.vmax=zmsub(p->z.val.vmax,l2zm((long)i));
+	    }
+	  }
+	  if(c==PUSH) pushed+=8;
+	  continue;
+	}  
+
+	if(!zmleq(p->q2.val.vmax,l2zm(4L))){
+	  long len=zm2l(p->q2.val.vmax);
+	  int r1,r2,loops,looplab;
+	  if(len>32767) ierror(0);
+	  if(!NOBANKVARS){
+	    int bq=-1,bz=-1,s=-1;
+	    if((p->q1.flags&(VAR|DREFOBJ))==VAR) bq=bank(p->q1.v);
+	    if((p->z.flags&(VAR|DREFOBJ))==VAR) bz=bank(p->z.v);
+	    if(((p->q1.flags&DREFOBJ)&&ISFPOINTER(p->q1.dtyp))||
+	       ((p->z.flags&DREFOBJ)&&ISFPOINTER(p->z.dtyp))){
+	      far_copy(f,p);
+	      continue;
+	    }
+	    if(cbank<0){
+	      if(bq>=0&&bz>=0){
+		if(bq!=bz){
+		  far_copy(f,p);
+		  continue;
+		}
+		s=bq;
+	      }else{
+		if(bq>=0) s=bq;
+		if(bz>=0) s=bz;
+	      }
+	      if(s>=0){
+		sety(f,s);
+		emit(f,"\tjsr\t%s__bankswitch\n",idprefix);
+		yval=NOVAL;
+	      }
+	    }else{
+	      if((bq>=0&&bq!=cbank)||(bz>=0&&bz!=cbank)){
+		far_copy(f,p);
+		continue;
+	      }
+	    }
+	  }
+	  get_acc(f,p,CHAR);
+	  if((p->q1.flags&(DREFOBJ|KONST))==DREFOBJ){
+	    if(p->q1.flags&REG){
+	      r1=p->q1.reg;
+	      if(!reg_pair(r1,&rp)) ierror(0);
+	      if(len>128){
+		emit(f,"\tlda\t%s\n",mregnames[rp.r1]);
+		emit(f,"\tclc\n");
+		if(len&128)
+		  emit(f,"\tadc\t#128\n");
+		emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
+		if(len>255){
+		  emit(f,"\tlda\t%s\n",mregnames[rp.r2]);
+		  emit(f,"\tadc\t#%ld\n",(len>>8)&255);
+		  emit(f,"\tsta\t%s\n",mregnames[rp.r2]);	
+		}else{
+		  emit(f,"\tbcc\t%s%d\n",labprefix,++label);
+		  emit(f,"\tinc\t%s\n",mregnames[rp.r2]);
+		  emit(f,"%s%d:\n",labprefix,label);
+		}
+	      }
+	    }else
+	      ierror(0);
+	  }else if(!indirect(&p->q1)&&len<=128&&(p->q1.flags&(DREFOBJ|KONST))!=KONST){
+	    r1=0;
+	  }else{
+	    Var *v=p->q1.v;
+	    /*if((p->q1.flags&(VARADR|VAR))!=VAR) ierror(0);*/
+	    r1=get_reg(f,p,POINTER);
+	    if(len>128) p->q1.val.vmax=zmadd(p->q1.val.vmax,l2zm(len&0xff80));
+	    load_address(f,r1,&p->q1,t);
+	    if(len>128) p->q1.val.vmax=zmsub(p->q1.val.vmax,l2zm(len&0xff80));
+	  }
+	  if((p->z.flags&(DREFOBJ|KONST))==DREFOBJ){
+	    if(p->z.flags&REG){
+	      r2=p->z.reg;
+	      if(!reg_pair(r2,&rp)) ierror(0);
+	      if(len>128){
+		emit(f,"\tlda\t%s\n",mregnames[rp.r1]);
+		emit(f,"\tclc\n");
+		if(len&128)
+		  emit(f,"\tadc\t#128\n");
+		emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
+		if(len>255){
+		  emit(f,"\tlda\t%s\n",mregnames[rp.r2]);
+		  emit(f,"\tadc\t#%ld\n",(len>>8)&255);
+		  emit(f,"\tsta\t%s\n",mregnames[rp.r2]);	
+		}else{
+		  emit(f,"\tbcc\t%s%d\n",labprefix,++label);
+		  emit(f,"\tinc\t%s\n",mregnames[rp.r2]);
+		  emit(f,"%s%d:\n",labprefix,label);
+		}
+	      }
+	    }else
+	      ierror(0);
+	  }else if(c==PUSH){
+	    if(len<=128&&pushed==0){
+	      r2=sp;
+	    }else{
+	      r2=get_reg(f,p,POINTER);
+	      if(!reg_pair(r2,&rp)) ierror(0);
+	      emit(f,"\tlda\t%s\n",mregnames[sp]);
+	      emit(f,"\tclc\n");
+	      if(((pushed+(len&128))&255)!=0)
+		emit(f,"\tadc\t#%ld\n",(pushed+(len&128))&255);
+	      emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
+	      emit(f,"\tlda\t%s\n",mregnames[sp2]);
+	      emit(f,"\tadc\t#%ld\n",((pushed+len)>>8)&255);
+	      emit(f,"\tsta\t%s\n",mregnames[rp.r2]);
+	    }
+	  }else if(!indirect(&p->z)&&len<=128){
+	    r2=0;
+	  }else{
+	    Var *v=p->z.v;
+	    r2=get_reg(f,p,POINTER);
+	    if(len>128) p->z.val.vmax=zmadd(p->z.val.vmax,l2zm(len&0xff80));
+	    load_address(f,r2,&p->z,t);
+	    if(len>128) p->z.val.vmax=zmsub(p->z.val.vmax,l2zm(len&0xff80));
+	  }
+	  if(len>128){
+	    get_acc(f,p,POINTER); /* get x */
+	    emit(f,"\tldx\t#%ld\n",((len>>7)+1)&255);
+	  }
+	  sety(f,(len-1)&127);
+	  if((optsize&&len>4)||len>8){
+	    emit(f,"%s%d:\n",labprefix,looplab=++label);
+	    if(optsize)
+	      loops=1;
+	    else{
+	      if((len&3)==0)
+		loops=4;
+	      else if((len&1)==0)
+		loops=2;
+	      else
+		loops=1;
+	    }
+	  }else
+	    loops=len;
+	  if(r1&&!reg_pair(r1,&rp)) ierror(0);
+	  if(r2&&!reg_pair(r2,&rp2)) ierror(0);
+	  for(i=0;i<loops;i++){
+	    if(r1)
+	      emit(f,"\tlda\t(%s),y\n",mregnames[rp.r1]);
+	    else{
+	      emit(f,"\tlda\t");
+	      emit_obj(f,&p->q1,t);
+	      emit(f,",y\n");
+	    }
+	    if(r2)
+	      emit(f,"\tsta\t(%s),y\n",mregnames[rp2.r1]);
+	    else{
+	      emit(f,"\tsta\t");
+	      emit_obj(f,&p->z,t);
+	      emit(f,",y\n");
+	    }
+	    emit(f,"\tdey\n");
+	  }
+	  if(loops!=len){
+	    emit(f,"\tbpl\t%s%d\n",labprefix,label);
+	  }	  
+	  if(len>128){
+	    emit(f,"\tlda\t%s\n",mregnames[rp.r1]);
+	    emit(f,"\tsec\n");
+	    emit(f,"\tsbc\t#128\n");
+	    emit(f,"\tsta\t%s\n",mregnames[rp.r1]);
+	    emit(f,"\tbcs\t%s%d\n",labprefix,++label);
+	    emit(f,"\tdec\t%s\n",mregnames[rp.r2]);
+	    emit(f,"%s%d:\n",labprefix,label);
+	    emit(f,"\tlda\t%s\n",mregnames[rp2.r1]);
+	    emit(f,"\tsec\n");
+	    emit(f,"\tsbc\t#128\n");
+	    emit(f,"\tsta\t%s\n",mregnames[rp2.r1]);
+	    emit(f,"\tbcs\t%s%d\n",labprefix,++label);
+	    emit(f,"\tdec\t%s\n",mregnames[rp2.r2]);
+	    emit(f,"%s%d:\n",labprefix,label);
+	    emit(f,"\tldy\t#127\n");
+	    emit(f,"\tdex\n");
+	    emit(f,"\tbne\t%s%d\n",labprefix,looplab);
+	  }
+	  yval=NOVAL;
+	  if(c==PUSH)
+	    pushed+=zm2l(p->q2.val.vmax);
+	  continue;
+	}
+	if(c==PUSH){
+	  get_acc(f,p,CHAR);
+	  load_lobyte(f,&p->q1,t);
+	  sety(f,pushed);
+	  emit(f,"\tsta\t(%s),y\n",mregnames[sp]);
+	  if(!zmleq(p->q2.val.vmax,Z1)){
+	    load_hibyte(f,&p->q1,t);
+	    sety(f,pushed+1);
+	    emit(f,"\tsta\t(%s),y\n",mregnames[sp]);
+	  }
+	  if(!zmleq(p->q2.val.vmax,l2zm(2L))){
+	    do_byte3(f,"lda",&p->q1,t);
+	    sety(f,pushed+2);
+	    emit(f,"\tsta\t(%s),y\n",mregnames[sp]);
+	  }
+	  if(!zmleq(p->q2.val.vmax,l2zm(3L))){
+	    do_byte4(f,"lda",&p->q1,t);
+	    sety(f,pushed+3);
+	    emit(f,"\tsta\t(%s),y\n",mregnames[sp]);
+	  }
+
+	  pushed+=zm2l(p->q2.val.vmax);
+	  continue;
+	}
+	if(c==ASSIGN){
+	  if(isreg(q1)&&isreg(z)&&p->q1.reg==p->z.reg) continue;
+	  if(isacc(q1)){
+	    if(p->q1.reg==rax) get_acc(f,p,CHAR);
+	    store_acc(f,&p->z,t);
+	    continue;
+	  }
+	  get_acc(f,p,CHAR);
+	  if(0/*ISCHAR(t)*/){
+	    load_acc(f,&p->q1,t);
+	    store_acc(f,&p->z,t);
+	  }else{
+            // TODO: PGS: Use AXYZ for 32-bit copy if appropriate
+	    // TOGO: PGS: Consider using AXYZ for load, even for 16 or 24-bit values
+	    if(!zmleq(p->q2.val.vmax,l2zm(3L))){
+	      do_byte4(f,"lda",&p->q1,t);
+	      do_byte4(f,"sta",&p->z,t);
+	    }
+	    if(!zmleq(p->q2.val.vmax,l2zm(2L))){
+	      do_byte3(f,"lda",&p->q1,t);
+	      do_byte3(f,"sta",&p->z,t);
+	    }
+	    if(!zmleq(p->q2.val.vmax,l2zm(1L))){
+	      load_hibyte(f,&p->q1,t);
+	      store_hibyte(f,&p->z,t);
+	    }
+	    load_lobyte(f,&p->q1,t);
+	    store_lobyte(f,&p->z,t);
+	  }
+	}
+	continue;
+      }
+      if(c==ADDRESS){
+	long o=real_offset(&p->q1);
+	get_acc(f,p,CHAR);
+	emit(f,"\tlda\t%s\n",mregnames[fp1]);
+	if(o){
+	  emit(f,"\tclc\n");
+	  if((o&255)!=0)
+	    emit(f,"\tadc\t#%ld\n",real_offset(&p->q1)&255);
+	}
+	store_lobyte(f,&p->z,t);
+	if(isacc(z)) emit(f,"\tpha\n");
+	emit(f,"\tlda\t%s\n",mregnames[fp2]);
+	if(o!=0)
+	  emit(f,"\tadc\t#%ld\n",real_offset(&p->q1)>>8&255);
+	store_hibyte(f,&p->z,t);
+	if(isacc(z)) emit(f,"\tpla\n");
+	continue;
+      }
+
+      if(c==COMPARE||c==TEST){
+	IC *branch=p->next;
+	int pacc=0,bc,bout;
+	while(branch){
+	  if(branch->code>=BEQ&&branch->code<BRA)
+	    break;
+	  if(branch->code!=FREEREG&&branch->code!=ALLOCREG&&branch->code!=NOP)
+	    ierror(0);
+	  branch=branch->next;
+	}
+	bc=branch->code;
+	bout=branch->typf;
+	if(c==TEST){
+	  p->q2.flags=KONST;
+	  gval.vmax=Z0;
+	  eval_const(&gval,MAXINT);
+	  insert_const(&p->q2.val,t);
+	}
+	if(ieee&&ISFLOAT(t)){
+	  if(!ieee) ierror(0);
+	  t&=NQ;
+	  if(regs[LAST_PAIR]) ierror(0);
+	  regs[LAST_PAIR]=1;
+	  if(regs[ra]||regs[rax])
+	    ierror(0);
+	  load_address(f,LAST_PAIR,&p->q2,t);
+	  BSET(regused,t3);
+	  BSET(regused,t4);
+	  emit(f,"\tjsr\t%s__fload%c\n",idprefix,(t==FLOAT?'s':'d'));
+	  yval=NOVAL;
+	  load_address(f,LAST_PAIR,&p->q1,t);
+	  emit(f,"\tjsr\t%s__fcmp%c\n",idprefix,(t==FLOAT?'s':'d'));
+	  yval=NOVAL;
+	  regs[LAST_PAIR]=0;
+	  if(bc==BLT||bc==BLE)
+	    emit(f,"\tbmi\t%s%d\n",labprefix,bout);
+	  else if(bc==BGT|bc==BGE)
+	    emit(f,"\tbvs\t%s%d\n",labprefix,bout);
+	  if(bc==BEQ||bc==BLE||bc==BGE)
+	    emit(f,"\tbeq\t%s%d\n",labprefix,bout);
+	  if(bc==BNE)
+	    emit(f,"\tbne\t%s%d\n",labprefix,bout);
+	  continue;
+	}
+	if(ISCHAR(t)){
+	  char *s;
+	  if(pacc=cmp_get_acc(f,p,branch))
+	    bout=++label;
+	  load_acc(f,&p->q1,t);
+	  if(bc==BEQ||bc==BNE||(t&UNSIGNED)){
+	    s="cmp";
+	  }else{
+	    if(bc==BLT||bc==BGE)
+	      emit(f,"\tsec\n");
+	    else
+	      emit(f,"\tclc\n");
+	    s="sbc";
+	  }
+	  if(c==TEST)
+	    emit(f,"\t%s\t#0\n",s);
+	  else
+	    do_lobyte(f,s,&p->q2,t);
+	  if(bc==BEQ)
+	    emit(f,"\tbeq\t%s%d\n",labprefix,bout);
+	  else if(bc==BNE)
+	    emit(f,"\tbne\t%s%d\n",labprefix,bout);
+	  else if(t&UNSIGNED){
+	    if(bc==BLT)
+	      emit(f,"\tbcc\t%s%d\n",labprefix,bout);
+	    else if(bc==BGE)
+	      emit(f,"\tbcs\t%s%d\n",labprefix,bout);
+	    else if(bc==BLE){
+	      emit(f,"\tbcc\t%s%d\n",labprefix,bout);
+	      emit(f,"\tbeq\t%s%d\n",labprefix,bout);
+	    }else if(bc==BGT){
+	      emit(f,";\n\tbeq\t%s%d\n",labprefix,++label);
+	      emit(f,"\tbcs\t%s%d\n",labprefix,bout);
+	      emit(f,"%s%d:\n",labprefix,label);
+	    }else
+	      ierror(0);
+	  }else{
+	    emit(f,"\tbvc\t%s%d\n",labprefix,++label);
+	    emit(f,"\teor\t#128\n");
+	    emit(f,"%s%d:\n",labprefix,label);
+	    if(bc==BLT||bc==BLE)
+	      emit(f,"\tbmi\t%s%d\n",labprefix,bout);
+	    else
+	      emit(f,"\tbpl\t%s%d\n",labprefix,bout);
+	  }
+	  if(pacc){
+	    reload_acc(f);
+	    add_cmplist(bout,branch->typf,pacc);
+	  }
+	  continue;
+	}else if(bc==BEQ||bc==BNE||(t&UNSIGNED)||ISFPOINTER(t)){
+	  int in=0;
+	  if(pacc=cmp_get_acc(f,p,branch))
+	    bout=++label;
+
+	  // PGS Check for special cases of comparing to constants
+	  if(!(ISLONG(t)||ISFPOINTER(t)||isacc(q1))) {
+	    // Is a 16-bit value
+	    if (p->q2.flags&KONST) {
+	      if (!(p->q2.flags&DREFOBJ)) {
+		eval_const(&p->q2.val,t);
+		if(ISFLOAT(t)) cnv_fp();
+		if (zm2l(vmax)==0x100) {
+		  if (bc==BGE) {
+		    // >= $100 we can check by just reading the 2nd byte
+		    // If non-zero, then we take the branch
+		    do_hibyte(f,"lda",&p->q1,t);
+		    emit(f,"\tbne\t%s%d\n",labprefix,bout);
+		    continue;
+		  } else if (bc==BLT) {
+		    // <$100 we can check by just reading the 2nd byte
+		    // And if zero, then we take the branch
+		    do_hibyte(f,"lda",&p->q1,t);
+		    emit(f,"\tbeq\t%s%d\n",labprefix,bout);		  
+		    continue;
+		  }
+		} else if (zm2l(vmax)<0x100) {
+		  // Values <$100 we can do almost as simply, but we have to
+		  // also check the low byte for exceptions.
+		  // XXX PGS TODO
+		  
+		}
+	      }
+	    }
+	  }
+	  
+	  // Far-Pointers are 32-bit on M65
+	  if(ISLONG(t)||ISFPOINTER(t)){
+	    do_byte4(f,"lda",&p->q1,t);
+	    if(c==TEST)
+	      emit(f,"\tcmp\t#0\n");
+	    else
+	      do_byte4(f,"cmp",&p->q2,t);
+	    if(bc==BEQ)
+	      emit(f,"\tbne\t%s%d\n",labprefix,in=++label);
+	    else if(bc==BNE)
+	      emit(f,"\tbne\t%s%d\n",labprefix,bout);
+	    else if(bc==BLT||bc==BLE){
+	      emit(f,"\tbcc\t%s%d\n",labprefix,bout);
+	      emit(f,"\tbne\t%s%d\n",labprefix,in=++label);
+	    }else if(bc==BGE||bc==BGT){
+	      emit(f,"\tbcc\t%s%d\n",labprefix,in=++label);	
+	      emit(f,"\tbne\t%s%d\n",labprefix,bout);
+	    }else
+	      ierror(0);
+	  }
+	  if(ISLONG(t)||ISFPOINTER(t)){
+	    do_byte3(f,"lda",&p->q1,t);
+	    if(c==TEST)
+	      emit(f,"\tcmp\t#0\n");
+	    else
+	      do_byte3(f,"cmp",&p->q2,t);
+	    if(bc==BEQ)
+	      emit(f,"\tbne\t%s%d\n",labprefix,in?in:(in=++label));
+	    else if(bc==BNE)
+	      emit(f,"\tbne\t%s%d\n",labprefix,bout);
+	    else if(bc==BLT||bc==BLE){
+	      emit(f,"\tbcc\t%s%d\n",labprefix,bout);
+	      emit(f,"\tbne\t%s%d\n",labprefix,in?in:(in=++label));
+	    }else if(bc==BGE||bc==BGT){
+	      emit(f,"\tbcc\t%s%d\n",labprefix,in?in:(in=++label));	
+	      emit(f,"\tbne\t%s%d\n",labprefix,bout);
+	    }else
+	      ierror(0);	  
+	  }
+	  if(isacc(q1)){
+	    if(!indirect(&p->q2)){
+	      do_hibyte(f,"cpx",&p->q2,t);
+	    }else{
+	      int r=get_reg(f,p,CHAR);
+	      emit(f,"\tpha\n");
+	      load_hibyte(f,&p->q2,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r]);
+	      emit(f,"\tpla\n");
+	      emit(f,"\tcpx\t%s\n",mregnames[r]);
+	    }
+	  }else{
+	    load_hibyte(f,&p->q1,t);
+	    if(c==TEST)
+	      emit(f,"\tcmp\t#0\n");
+	    else
+	      do_hibyte(f,"cmp",&p->q2,t);
+	  }
+	  if(bc==BEQ)
+	    emit(f,"\tbne\t%s%d\n",labprefix,in?in:(in=++label));
+	  else if(bc==BNE)
+	    emit(f,"\tbne\t%s%d\n",labprefix,bout);
+	  else if(bc==BLT||bc==BLE){
+	    emit(f,"\tbcc\t%s%d\n",labprefix,bout);
+	    emit(f,"\tbne\t%s%d\n",labprefix,in?in:(in=++label));
+	  }else if(bc==BGE||bc==BGT){
+	    emit(f,"\tbcc\t%s%d\n",labprefix,in?in:(in=++label));
+	    emit(f,"\tbne\t%s%d\n",labprefix,bout);
+	  }else
+	    ierror(0);
+	  load_lobyte(f,&p->q1,t);
+	  if(c==TEST)
+	    emit(f,"\tcmp\t#0\n");
+	  else
+	    do_lobyte(f,"cmp",&p->q2,t);
+	  if(bc==BEQ)
+	    emit(f,"\tbeq\t%s%d\n",labprefix,bout);
+	  else if(bc==BNE)
+	    emit(f,"\tbne\t%s%d\n",labprefix,bout);
+	  else if(bc==BLT)
+	    emit(f,"\tbcc\t%s%d\n",labprefix,bout);
+	  else if(bc==BGE)
+	    emit(f,"\tbcs\t%s%d\n",labprefix,bout);	
+	  else if(bc==BLE){
+	    emit(f,"\tbcc\t%s%d\n",labprefix,bout);
+	    emit(f,"\tbeq\t%s%d\n",labprefix,bout);
+	  }else if(bc==BGT){
+	    emit(f,"\tbcc\t%s%d\n",labprefix,in);
+	    emit(f,"\tbne\t%s%d\n",labprefix,bout);
+	  }else
+	    ierror(0);
+	  if(in)
+	    emit(f,"%s%d:\n",labprefix,in);
+	  if(pacc){
+	    reload_acc(f);
+	    add_cmplist(bout,branch->typf,pacc);
+	  }
+	  continue;
+	}else{
+	  if(bc==BGT||bc==BLE){
+	    obj o;
+	    if(isacc(q1)){
+	      int r;
+	      if(pacc=cmp_get_acc(f,p,branch))
+		bout=++label;
+	      r=get_reg(f,p,CHAR);
+	      emit(f,"\tsta\t%s\n",mregnames[r]);
+	      load_lobyte(f,&p->q2,t);
+	      emit(f,"\tcmp\t%s\n",mregnames[r]);
+	      emit(f,"\tstx\t%s\n",mregnames[r]);
+	      load_hibyte(f,&p->q2,t);
+	      emit(f,"\tsbc\t%s\n",mregnames[r]);
+	      emit(f,"\tbvc\t%s%d\n",labprefix,++label);
+	      emit(f,"\teor\t#128\n");
+	      emit(f,"%s%d:\n",labprefix,label);
+	      if(bc==BGT)
+		emit(f,"\tbmi\t%s%d\n",labprefix,bout);
+	      else
+		emit(f,"\tbpl\t%s%d\n",labprefix,bout);
+	      if(pacc){
+		reload_acc(f);
+		add_cmplist(bout,branch->typf,pacc);
+	      }
+	      continue;
+	    }else{
+	      o=p->q1;p->q1=p->q2;p->q2=o;
+	      if(bc==BGT) bc=BLT; else bc=BGE;
+	    }
+	  }
+	  if(pacc=cmp_get_acc(f,p,branch))
+	    bout=++label;
+	  if(ISLONG(t)){
+	    load_lobyte(f,&p->q1,t);
+	    do_lobyte(f,"cmp",&p->q2,t);
+	    load_hibyte(f,&p->q1,t);
+	    do_hibyte(f,"sbc",&p->q2,t);
+	    do_byte3(f,"lda",&p->q1,t);
+	    do_byte3(f,"sbc",&p->q2,t);
+	    do_byte4(f,"lda",&p->q1,t);
+	    do_byte4(f,"sbc",&p->q2,t);
+	  }else{
+	    load_lobyte(f,&p->q1,t);
+	    do_lobyte(f,"cmp",&p->q2,t);
+	    load_hibyte(f,&p->q1,t);
+	    do_hibyte(f,"sbc",&p->q2,t);
+	  }
+	  emit(f,"\tbvc\t%s%d\n",labprefix,++label);
+	  emit(f,"\teor\t#128\n");
+	  emit(f,"%s%d:\n",labprefix,label);
+	  if(bc==BLT)
+	    emit(f,"\tbmi\t%s%d\n",labprefix,bout);
+	  else if(bc==BGE)
+	    emit(f,"\tbpl\t%s%d\n",labprefix,bout);
+	  else
+	    ierror(0);
+	  if(pacc){
+	    reload_acc(f);
+	    add_cmplist(bout,branch->typf,pacc);
+	  }
+	  continue; 
+	}
+	ierror(0);
+      }
+      if((c==ADD||c==SUB||c==ADDI2P||c==SUBIFP)&&compare_objects(&p->q1,&p->z)&&!indirect(&p->q1)&&isconst(q2)&&!isacc(z)){
+	long l;
+	eval_const(&p->q2.val,q2typ(p));
+	l=zm2l(vmax);
+	if(c==ADDI2P/*&&(t2&NQ)==POINTER*/) {c=ADD;t=UNSIGNED|INT;}
+	if(c==SUBIFP/*&&(t2&NQ)==POINTER*/) {c=SUB;t=UNSIGNED|INT;}
+	if(c==SUB||c==SUBIFP) l=-l;
+	/*TODO: allow larger types */
+	if(l<3&&l>-3&&(t&NQ)<=INT){
+	  if(l<0){
+	    get_acc(f,p,CHAR);
+	    incmem(f,&p->z,t,SUB,-l);
+	  }else
+	    incmem(f,&p->z,t,ADD,l);
+	  continue;
+	}
+      }
+
+      if((c==LSHIFT||c==RSHIFT)&&isreg(q1)&&isreg(z)&&isconst(q2)&&p->q1.reg==p->z.reg&&p->z.reg!=ra&&p->z.reg!=rax){
+	long l;
+	eval_const(&p->q2.val,q2typ(p));
+	l=zm2l(vmax);
+	/*TODO: allow larger types */
+	if(l<5&&(t&NQ)<=INT){
+	  if(c==RSHIFT&&!(t&UNSIGNED))
+	    get_acc(f,p,CHAR);
+	  incmem(f,&p->z,t,c,l);
+	  continue;
+	}
+      }
+
+      if(c==LSHIFT||c==RSHIFT){
+	long l=-1;int loop=0,r,r2,r3,outl=0;
+	if(isconst(q2)){
+	  eval_const(&p->q2.val,q2typ(p));
+	  l=zm2l(vmax);
+	  loop=0;
+	}else
+	  loop=1;
+	if(l>=0&&optsize){
+	  if(c==LSHIFT&&(l&7)>6) 
+	    loop=1;
+	  else if(c==RSHIFT&&(t&UNSIGNED)&&(l&7)>3)
+	    loop=1;
+	  else if(c==RSHIFT&&!(t&UNSIGNED)&&(l&7)>2)
+	    loop=1;
+	}
+
+	if(!ISCHAR(t))
+	  r=get_reg(f,p,CHAR);
+	if(ISLONG(t)){
+	  r2=get_reg(f,p,CHAR);
+	  r3=get_reg(f,p,CHAR);
+	}
+	if(ISLONG(t)){
+	  get_acc(f,p,CHAR);
+	  if(l>=24){
+	    if(c==LSHIFT){
+	      load_lobyte(f,&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r3]);
+	      emit(f,"\tlda\t#0\n");
+	      emit(f,"\tsta\t%s\n",mregnames[r]);
+	      emit(f,"\tsta\t%s\n",mregnames[r2]);
+	    }else if(c==RSHIFT&&!(t&UNSIGNED)){
+	      do_byte4(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r3]);
+	      sety(f,0);
+	      emit(f,"\tcmp\t#0\n");
+	      emit(f,"\tbpl\t%s%d\n",labprefix,++label);
+	      emit(f,"\tdey\n");
+	      emit(f,"%s%d:\n",labprefix,label);
+	      emit(f,"\tsty\t%s\n",mregnames[r]);
+	      emit(f,"\tsty\t%s\n",mregnames[r2]);
+	      emit(f,"\ttya\n");
+	      yval=NOVAL;
+	    }else{
+	      emit(f,"\tlda\t#0\n");
+	      emit(f,"\tsta\t%s\n",mregnames[r3]);
+	      emit(f,"\tsta\t%s\n",mregnames[r2]);
+	      emit(f,"\tsta\t%s\n",mregnames[r]);
+	      do_byte4(f,"lda",&p->q1,t);
+
+	    }
+	  }else if(l>=16){
+	    if(c==LSHIFT){
+	      load_lobyte(f,&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r2]);
+	      load_hibyte(f,&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r3]);
+	      emit(f,"\tlda\t#0\n");
+	      emit(f,"\tsta\t%s\n",mregnames[r]);
+	    }else if(c==RSHIFT&&!(t&UNSIGNED)){
+	      do_byte3(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r3]);
+	      do_byte4(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r2]);
+	      sety(f,0);
+	      emit(f,"\tcmp\t#0\n");
+	      emit(f,"\tbpl\t%s%d\n",labprefix,++label);
+	      emit(f,"\tdey\n");
+	      emit(f,"%s%d:\n",labprefix,label);
+	      emit(f,"\tsty\t%s\n",mregnames[r]);
+	      emit(f,"\ttya\n");
+	      yval=NOVAL;
+	    }else{
+	      emit(f,"\tlda\t#0\n");
+	      emit(f,"\tsta\t%s\n",mregnames[r2]);
+	      emit(f,"\tsta\t%s\n",mregnames[r3]);
+	      do_byte4(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r]);
+	      do_byte3(f,"lda",&p->q1,t);
+
+	    }
+	  }else if(l>=8){
+	    if(c==LSHIFT){
+	      load_lobyte(f,&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r]);
+	      load_hibyte(f,&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r2]);
+	      do_byte3(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r3]);
+	      emit(f,"\tlda\t#0\n");
+	    }else if(c==RSHIFT&&!(t&UNSIGNED)){
+	      load_hibyte(f,&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r3]);
+	      do_byte3(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r2]);
+	      do_byte4(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r]);
+	      sety(f,0);
+	      emit(f,"\tcmp\t#0\n");
+	      emit(f,"\tbpl\t%s%d\n",labprefix,++label);
+	      emit(f,"\tdey\n");
+	      emit(f,"%s%d:\n",labprefix,label);
+	      emit(f,"\ttya\n");
+	      yval=NOVAL;
+	    }else{
+	      emit(f,"\tlda\t#0\n");
+	      emit(f,"\tsta\t%s\n",mregnames[r3]);
+	      do_byte4(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r2]);
+	      do_byte3(f,"lda",&p->q1,t);
+	      emit(f,"\tsta\t%s\n",mregnames[r]);
+	      load_hibyte(f,&p->q1,t);
+
+	    }
+	  }else if(c==RSHIFT&&!(t&UNSIGNED)){
+	    load_lobyte(f,&p->q1,t);
+	    emit(f,"\tsta\t%s\n",mregnames[r3]);
+	    load_hibyte(f,&p->q1,t);
+	    emit(f,"\tsta\t%s\n",mregnames[r2]);
+	    do_byte3(f,"lda",&p->q1,t);
+	    emit(f,"\tsta\t%s\n",mregnames[r]);
+	    do_byte4(f,"lda",&p->q1,t);
+	  }else{
+	    do_byte4(f,"lda",&p->q1,t);
+	    emit(f,"\tsta\t%s\n",mregnames[r3]);
+	    do_byte3(f,"lda",&p->q1,t);
+	    emit(f,"\tsta\t%s\n",mregnames[r2]);
+	    load_hibyte(f,&p->q1,t);
+	    emit(f,"\tsta\t%s\n",mregnames[r]);
+	    load_lobyte(f,&p->q1,t);
+	  }
+	}else
+	  get_acc(f,p,t);
+	if(!ISLONG(t)){
+	  if(l>=8){
+	    if(!ISSHORT(t)) ierror(0);
+	    if(c==LSHIFT){
+	      if(indirect(&p->q1)){
+		load_lobyte(f,&p->q1,t);
+		emit(f,"\ttax\n");
+		emit(f,"\tlda\t#0\n");
+	      }else{
+		if(isacc(q1))
+		  emit(f,"\ttax\n");
+		else
+		  do_lobyte(f,"ldx",&p->q1,t);
+		emit(f,"\tlda\t#0\n");
+	      }
+	    }else{
+	      load_hibyte(f,&p->q1,t);
+	      emit(f,"\tldx\t#0\n");
+	      if(!(t&UNSIGNED)){
+		emit(f,"\tcmp\t#0\n");
+		emit(f,"\tbpl\t%s%d\n",labprefix,++label);
+		emit(f,"\tdex\n");
+		emit(f,"%s%d:\n",labprefix,label);
+	      }
+	    }
+	  }else
+	    load_acc(f,&p->q1,t);
+	}
+	if(ISSHORT(t))
+	  emit(f,"\tstx\t%s\n",mregnames[r]);
+	if(l>=0) l&=7;
+	if(loop){
+	  if(l>=0)
+	    sety(f,l);
+	  else{
+	    if(indirect(&p->q2)){
+	      emit(f,"\tpha\n");
+	      load_lobyte(f,&p->q2,q2typ(p));
+	      emit(f,"\ttay\n");
+	      emit(f,"\tpla\n");
+	      emit(f,"\tcpy\t#0\n");
+	    }else{
+	      emit(f,"\tldy\t");
+	      emit_lobyte(f,&p->q2,q2typ(p));
+	      emit(f,"\n");
+	    }
+	    outl=++label;
+	    emit(f,"\tbeq\t%s%d\n",labprefix,outl);
+	  }
+	  emit(f,"%s%d:\n",labprefix,++label);
+	}else{
+	  if(ISCHAR(t))
+	    l&=7;
+	  else if(ISSHORT(t))
+	    l&=15;
+	  else
+	    l&=31;
+	}
+	while(l>0||loop){
+	  if(c==LSHIFT){
+	    emit(f,"\tasl\n");
+	    if(!ISCHAR(t))
+	      emit(f,"\trol\t%s\n",mregnames[r]);
+	    if(ISLONG(t)){
+	      emit(f,"\trol\t%s\n",mregnames[r2]);
+	      emit(f,"\trol\t%s\n",mregnames[r3]);
+	    }
+	  }else if(t&UNSIGNED){
+	    emit(f,"\tclc\n");
+	    if(ISLONG(t)){
+	      emit(f,"\tror\t%s\n",mregnames[r3]);
+	      emit(f,"\tror\t%s\n",mregnames[r2]);
+	    }
+	    if(!ISCHAR(t))
+	      emit(f,"\tror\t%s\n",mregnames[r]);
+	    emit(f,"\tror\n");
+	  }else{
+	    if(ISLONG(t)){
+	      emit(f,"\tcmp\t#128\n");
+	      emit(f,"\tror\n");
+	      emit(f,"\tror\t%s\n",mregnames[r]);
+	      emit(f,"\tror\t%s\n",mregnames[r2]);
+	      emit(f,"\tror\t%s\n",mregnames[r3]);
+	    }else{
+	      if(!ISCHAR(t)){
+		emit(f,"\tcpx\t#128\n");
+		emit(f,"\tror\t%s\n",mregnames[r]);
+	      }else
+		emit(f,"\tcmp\t#128\n");
+	      emit(f,"\tror\n");
+	    }
+	  }
+	  if(loop){
+	    emit(f,"\tdey\n");
+	    emit(f,"\tbne\t%s%d\n",labprefix,label);
+	    if(outl) emit(f,"%s%d:\n",labprefix,outl);
+	    yval=0;
+	    break;
+	  }
+	  l--;
+	}
+	if(ISLONG(t)){
+	  if(c==RSHIFT&&!(t&UNSIGNED)){
+	    do_byte4(f,"sta",&p->z,t);
+	    emit(f,"\tlda\t%s\n",mregnames[r]);
+	    do_byte3(f,"sta",&p->z,t);
+	    emit(f,"\tlda\t%s\n",mregnames[r2]);
+	    store_hibyte(f,&p->z,t);
+	    emit(f,"\tlda\t%s\n",mregnames[r3]);
+	    store_lobyte(f,&p->z,t);
+	  }else{
+	    store_lobyte(f,&p->z,t);
+	    emit(f,"\tlda\t%s\n",mregnames[r]);
+	    store_hibyte(f,&p->z,t);
+	    emit(f,"\tlda\t%s\n",mregnames[r2]);
+	    do_byte3(f,"sta",&p->z,t);
+	    emit(f,"\tlda\t%s\n",mregnames[r3]);
+	    do_byte4(f,"sta",&p->z,t);
+	  }
+	}else{
+	  if(!ISCHAR(t))
+	    emit(f,"\tldx\t%s\n",mregnames[r]);
+	  if(ISCHAR(t)||indirect(&p->z))
+	    store_acc(f,&p->z,t);
+	  else{
+	    store_lobyte(f,&p->z,t);
+	    if(!isreg(z)||p->z.reg!=rax){
+	      emit(f,"\tstx\t");
+	      emit_hibyte(f,&p->z,t);
+	      emit(f,"\n");
+	    }
+	  }
+	}
+	continue;
+      }
+
+      if((c>=OR&&c<=AND)||(c>=LSHIFT&&c<=MOD)||c==ADDI2P||c==SUBIFP){
+	char *s;int t2=t,pt=p->typf2;
+	if(!isacc(z))
+	  get_acc(f,p,CHAR);
+	if(c==ADDI2P||c==SUBIFP){
+	  if(c==ADDI2P) c=ADD; else c=SUB;
+	  t=UNSIGNED|INT;
+	  if((pt&NQ)==POINTER&&(p->q1.flags&(KONST|DREFOBJ))==KONST){
+	    eval_const(&p->q1.val,POINTER);
+	    insert_const(&p->q1.val,UNSIGNED|INT);
+	  }
+	}
+	if(c>=OR&&c<=AND)
+	  s=logicals[c-OR];
+	else
+	  s=arithmetics[c-LSHIFT];
+      
+	if(ISFLOAT(t)){
+	  if(!ieee) ierror(0);
+	  t&=NQ;
+	  if(regs[LAST_PAIR]) ierror(0);
+	  get_acc(f,p,INT);
+	  regs[LAST_PAIR]=1;
+	  load_address(f,LAST_PAIR,&p->q1,t);
+	  BSET(regused,t3);
+	  BSET(regused,t4);
+	  emit(f,"\tjsr\t%s__fload%c\n",idprefix,(t==FLOAT?'s':'d'));
+	  yval=NOVAL;
+	  load_address(f,LAST_PAIR,&p->q2,t);
+	  emit(f,"\tjsr\t%s__f%s%c\n",idprefix,ename[c],(t==FLOAT?'s':'d'));
+	  yval=NOVAL;
+	  load_address(f,LAST_PAIR,&p->z,t);
+	  emit(f,"\tjsr\t%s__fstore%c\n",idprefix,(t==FLOAT?'s':'d'));
+	  yval=NOVAL;
+	  regs[LAST_PAIR]=0;
+	  continue;
+	}else if(ISLONG(t)){
+	  if(c==ADD) emit(f,"\tclc\n");
+	  if(c==SUB) emit(f,"\tsec\n");
+	  load_lobyte(f,&p->q1,t);
+	  do_lobyte(f,s,&p->q2,t);
+	  store_lobyte(f,&p->z,t);
+	  load_hibyte(f,&p->q1,t);
+	  do_hibyte(f,s,&p->q2,t);
+	  store_hibyte(f,&p->z,t);
+	  do_byte3(f,"lda",&p->q1,t);
+	  do_byte3(f,s,&p->q2,t);
+	  do_byte3(f,"sta",&p->z,t);
+	  do_byte4(f,"lda",&p->q1,t);
+	  do_byte4(f,s,&p->q2,t);
+	  do_byte4(f,"sta",&p->z,t);
+	  continue;
+	}else if(ISCHAR(t)){
+	  load_acc(f,&p->q1,t);
+	  if(c==ADD) emit(f,"\tclc\n");
+	  if(c==SUB) emit(f,"\tsec\n");
+	  do_lobyte(f,s,&p->q2,t);
+	  store_acc(f,&p->z,t);
+	}else if(c==ADD||c==SUB){
+	  int a,r;long l=1;
+	  if(isconst(q2)){
+	    eval_const(&p->q2.val,t2);
+	    l=zm2l(vmax);
+	    l&=0xff00;
+	  }
+	  if(isreg(z)&&p->z.reg==rax) a=1; else a=0;
+	  if((t2&NU)==CHAR&&(p->q2.flags&(KONST|DREFOBJ))!=KONST){
+	    emit(f,"\tldx\t#0\n");
+	  }
+	  if((t2&NU)==CHAR&&(p->q2.flags&(KONST|DREFOBJ))!=KONST){
+	    load_lobyte(f,&p->q2,t);
+	    emit(f,"\tbpl\t%s%d\n",labprefix,++label);
+	    emit(f,"\tdex\n");
+	    emit(f,"%s%d:\n",labprefix,label);
+	    if(c==ADD){
+	      if(c==ADD) emit(f,"\tclc\n"); else emit(f,"\tsec\n");
+	      do_lobyte(f,s,&p->q1,t);
+	      if(isacc(z))
+		emit(f,"\tpha\n");
+	      else
+		store_lobyte(f,&p->z,t);
+	      emit(f,"\ttxa\n");
+	      do_hibyte(f,s,&p->q1,t);
+	      store_hibyte(f,&p->z,t);
+	      if(ISFPOINTER(pt)&&!compare_objects(&p->q1,&p->z)){
+		do_byte3(f,"lda",&p->q1,pt);
+		do_byte3(f,"sta",&p->z,pt);
+	      }
+	      if(isacc(z))
+		emit(f,"\tpla\n");
+	      continue;
+	    }
+	    r=get_reg(f,p,CHAR);
+	    emit(f,"\tstx\t%s\n",mregnames[r]);
+	  }
+	  load_lobyte(f,&p->q1,t);
+	  if(c==ADD) emit(f,"\tclc\n"); else emit(f,"\tsec\n");
+	  do_lobyte(f,s,&p->q2,t2);
+	  store_lobyte(f,&p->z,t);
+	  if(l==0&&isreg(q1)&&isreg(z)&&p->q1.reg==p->z.reg){
+	    if(c==ADD){
+	      emit(f,"\tbcc\t%s%d\n",labprefix,++label);
+	      if(a)
+		emit(f,"\tinx\n");
+	      else{
+		/*if(!reg_pair(p->z.reg,&rp)) ierror(0);*/
+		emit(f,"\tinc\t%s+1\n",mregnames[p->z.reg]);
+	      }
+	    }else{
+	      emit(f,"\tbcs\t%s%d\n",labprefix,++label);
+	      if(a)
+		emit(f,"\tdex\n");
+	      else{
+		if(!reg_pair(p->z.reg,&rp)) ierror(0);
+		emit(f,"\tdec\t%s\n",mregnames[rp.r2]);
+	      }
+	    }
+	    emit(f,"%s%d:\n",labprefix,label);
+	  }else{
+	    if(a==1) emit(f,"\tpha\n");
+	    if((t2&NQ)==CHAR){
+	      if(t2&UNSIGNED){
+		load_hibyte(f,&p->q1,t);
+		emit(f,"\t%s\t#0\n",s);
+	      }else{
+		load_hibyte(f,&p->q1,t);
+		if((p->q2.flags&(KONST|DREFOBJ))==KONST){
+		  eval_const(&p->q2.val,t2);
+		  if(zmleq(Z0,vmax))
+		    emit(f,"\t%s\t#0\n",s);
+		  else
+		    emit(f,"\t%s\t#255\n",s);
+		}else{
+		  emit(f,"\t%s\t%s\n",s,mregnames[r]);
+		}
+	      }
+	    }else{
+	      load_hibyte(f,&p->q1,t);
+	      do_hibyte(f,s,&p->q2,t2);
+	    }
+	    store_hibyte(f,&p->z,t);
+	    if(a==1) emit(f,"\tpla\n");
+	    if(ISFPOINTER(pt)&&p->code!=SUBPFP){
+	      if(!compare_objects(&p->q1,&p->z)){
+		do_byte3(f,"lda",&p->q1,FPOINTER);
+		do_byte3(f,"sta",&p->z,FPOINTER);
+	      }
+	    }
+	  }
+	}else{
+	  if(isacc(q1))
+	    emit(f,"\tpha\n");
+	  load_hibyte(f,&p->q1,t);
+	  do_hibyte(f,s,&p->q2,t);
+	  store_hibyte(f,&p->z,t);
+	  if(isacc(q1))
+	    emit(f,"\tpla\n");
+	  load_lobyte(f,&p->q1,t);
+	  do_lobyte(f,s,&p->q2,t);
+	  store_lobyte(f,&p->z,t);
+	}
+	continue;
+      }
+      pric2(stdout,p);
+      ierror(0);
+    }
+
+    function_bottom(f,v,localsize);
+    
+    for(c=1;c<=MAXR;c++){
+      if(regsa[c]||regused[c]){
+	BSET(regs_modified,c);
+      }
+    }
+
+    if(stack_valid){
+      if(!v->fi) v->fi=new_fi();
+      v->fi->flags|=ALL_STACK;
+      v->fi->stack1=stack;
+    }
+  }
+
+  free_IC(mi);
+
+  emit(f,"; stacksize=%lu%s\n",zum2ul(stack),stack_valid?"":"+??");
+}
+
+int shortcut(int code,int typ)
+{
+  if(code==COMPARE/*||code==MULT*/||code==ADD||code==SUB||code==AND||code==OR||code==XOR||code==LSHIFT||code==RSHIFT/*||code==MINUS*/||code==KOMPLEMENT)
+    return 1;
+
+  return 0;
+}
+
+static int fattr(type *p,char *s)
+{
+  if(p->attr&&strstr(p->attr,s))
+    return 1;
+  if(p->next)
+    return fattr(p->next,s);
+  else
+    return 0;
+}
+
+int reg_parm(struct reg_handle *m, struct Typ *t,int vararg,struct Typ *d)
+{
+  int f;
+
+  if(vararg)
+    return 0;
+  f=t->flags&NQ;
+  if(OLDFP&&ISFLOAT(f)) return 0;
+  if(d&&fattr(d,"__stackparms__"))
+    return 0;
+  if(d&&fattr(d,"__cc65__")){
+    m->regs++;
+    printf("arg=%d cnt=%d\n",m->regs,d->exact->count);
+    if(m->regs==d->exact->count-1){
+      if(ISCHAR(t->flags))
+	return ra;
+      if(ISSHORT(t->flags))
+	return rax;
+    }
+    return 0;
+  }
+  if(ISCHAR(f)){
+    if(!t->exact){
+      if(m->regs>=GPR_ARGS-1)
+	return 0;
+      f=FIRST_GPR+m->regs;
+      m->regs+=2;
+      return f;
+    }else{
+      if(m->regs>=GPR_ARGS)
+	return 0;
+      else
+	return FIRST_GPR+m->regs++;
+    }
+  }
+  if(ISSHORT(f)||f==POINTER){
+    if(m->regs>=GPR_ARGS-1)
+      return 0;
+    else{
+      if(m->regs&1) m->regs+=1;
+      m->regs+=2;
+      return FIRST_PAIR+m->regs/2-1;
+    }
+  }
+  if(f==FPOINTER||f==LONG||f==FLOAT||(!ieee&&(f==DOUBLE||f==LDOUBLE))){
+    if(m->bregs>=4)
+      return 0;
+    else
+      return FIRST_BIG+m->bregs++;
+  }
+  if(f==LLONG||(ieee&&(f==DOUBLE||f==LDOUBLE))){
+    if(m->bregs>=3)
+      return 0;
+    else{
+      if(m->bregs&1)  m->bregs++;
+      m->bregs+=2;
+      return FIRST_BIGP+m->bregs/2-1;
+    }
+  }
+  return 0;
+}
+
+int handle_pragma(const char *s)
+{
+  static char sec[SECLEN];
+  int i;
+  if(sscanf(s,"section %127s",sec)==1){
+    if(!strcmp(sec,"default"))
+      use_sec=0;
+    else
+      use_sec=sec;
+    return 1;
+  }
+  if(sscanf(s,"bank %d",&i)==1){
+    use_bank=i;
+    return 1;
+  }
+}
+void cleanup_cg(FILE *f)
+{
+  int i;
+  struct fpconstlist *p=firstfpc;
+
+  if(f&&p){
+    emit(f,rodataname);emit(f,"\n");
+    section=RODATA;
+  }
+  while(p=firstfpc){
+    emit(f,"%s%d:\n\tword\t",labprefix,p->label);
+    if(ieee)
+      emit_ieee(f,&p->val,p->t);
+    else{
+      int words=zm2l(sizetab[p->t&NQ])/2;
+      eval_const(&p->val,p->t);
+      if(ISFLOAT(p->t)) cnv_fp();
+      for(i=0;i<words;i++){
+	emit(f,"%ld",zm2l(vmax)&0xffff);
+	if(i<words-1){emit(f,",");vmax=zmrshift(vmax,l2zm(16L));}
+      }
+      emit(f,"\n");
+      /*emit(f,"%ld,%ld\n",zm2l(vmax)&0xffff,zm2l(zmrshift(vmax,l2zm(16L)))&0xffff);*/
+    }
+    firstfpc=p->next;
+    free(p);
+  }
+
+  emit(f,"\tzpage\t%s\n",mregnames[sp]);
+  for(i=FIRST_GPR;i<=LAST_GPR;i++)
+    emit(f,"\tzpage\t%s\n",mregnames[i]);
+  for(i=FIRST_BIG;i<=LAST_BIG;i++)
+    emit(f,"\tzpage\t%s\n",mregnames[i]);
+
+}
+void cleanup_db(FILE *f)
+{
+  if(f) section=-1;
+}
+
+static char *zops[]={
+  "adc","and","asl","bit","eor","lda","ora",
+  "tax","txa","tay","tya","sbc"};
+
+static int setszflag(char *op)
+{
+  int i;
+  for(i=0;i<sizeof(zops)/sizeof(zops[0]);i++)
+    if(!strcmp(op,zops[i]))
+      return 1;
+  return 0;
+}
+
+
+enum peepf { NEEDSAME = 1, REMOVE1ST = 2};
+struct peeps {char *s1,*s2,*r;enum peepf flags;};
+
+
+
+int emit_peephole(void)
+{
+  int entries,i,j;
+  char *asmline[EMIT_BUF_DEPTH];
+  char buf1[1024],buf2[1024];
+  char op1[8],op2[8];
+  static char ca[1024],cx[1024],cy[1024],cz[1024];
+  static int rm,disabled;
+
+  fprintf(stderr,"Called emit_peephole()\n");
+  
+  static struct peeps elim[]={
+    "lda","sta",0,NEEDSAME,
+    "ldx","stx",0,NEEDSAME,
+    "sta","sta",0,NEEDSAME,
+    "stx","stx",0,NEEDSAME,
+    "sta","lda",0,NEEDSAME,
+    "stx","ldx",0,NEEDSAME,
+    "txa","tax",0,0,
+    "tax","txa",0,0,
+    "lda","lda",0,REMOVE1ST,
+    "ldx","ldx",0,REMOVE1ST,
+    "ldy","ldy",0,REMOVE1ST,
+    "ldz","ldz",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,
+    "taz","ldz",0,REMOVE1ST,
+    "tax","ldx",0,REMOVE1ST,
+    "txa","lda",0,REMOVE1ST,
+    "tya","lda",0,REMOVE1ST,
+    "tza","lda",0,REMOVE1ST,
+    "lda","ldx","\ttax\n",NEEDSAME,
+    "lda","ldy","\ttay\n",NEEDSAME,
+    "ldx","lda","\ttxa\n",NEEDSAME,
+    "ldy","lda","\ttya\n",NEEDSAME,
+    "sta","ldx","\ttax\n",NEEDSAME,
+    "sta","ldy","\ttay\n",NEEDSAME,
+    "stx","lda","\ttxa\n",NEEDSAME,
+    "sty","lda","\ttya\n",NEEDSAME,
+
+  };
+
+  if(nopeep) return 0;
+
+  i=emit_l;
+  if(emit_f==0)
+    entries=i-emit_f+1;
+  else
+    entries=EMIT_BUF_DEPTH;
+  asmline[0]=emit_buffer[i];
+
+  if(!strcmp(asmline[0],";startinline\n")) disabled=1;
+  if(!strcmp(asmline[0],";endinline\n")) disabled=0;
+  if(disabled) return 0;
+
+  buf1[0]=0;op1[0]=0;
+  if((j=sscanf(asmline[0]," %6s %999s",op1,buf1))>=1){
+    printf("a=%s x=%s y=%s, z=%s\n",ca,cx,cy,cz);
+    printf("\t\t%s %s\n",op1,buf1);
+    if(!strcmp(op1,"sta")) {
+      // Work out when we are accessing variables on the stack
+      if (!strcmp(buf1,"(sp),y")) {
+	// We invalidate this when Y changes
+	snprintf(ca,1024,"(sp),y",cy);
+      } 
+    } else if(!strcmp(op1,"sta")){
+      // Remove writes to wherever A was loaded from
+      if (!strcmp(buf1,ca)) {
+	remove_asm();
+	return rm=1;
+      }
+    } else if(!strcmp(op1,"lda")){
+      if(buf1[0]=='#'){
+	if(!strcmp(buf1,ca)){remove_asm();return rm=1;}
+	strcpy(ca,buf1);
+      }else {
+	// Work out when we are accessing variables on the stack
+	if (!strcmp(buf1,"(sp),y")) {	 
+	  if(!strcmp(buf1,ca)){
+	    remove_asm();
+	    return rm=1;
+	  }
+	  snprintf(ca,1024,"(sp),y",cy);
+	}
+	// Similarly look for register loads
+	// We can sometimes remove some of those, too.
+	if ((strlen(buf1)>1)&&(buf1[0]=='r')) {
+	  if (strcmp(ca,buf1)) 
+	    snprintf(ca,1024,"%s",buf1);
+	  else {
+	    // Don't re-load A with the same contents it already has
+	    remove_asm();
+	    return rm=1;
+	  }
+	}
+      }
+    }else if(!strcmp(op1,"ldx")){
+      if(buf1[0]=='#'){
+	if(!rm&&!strcmp(buf1,cx)){remove_asm();return rm=1;}
+	strcpy(cx,buf1);
+      }else cx[0]=0;
+    }else if(!strcmp(op1,"ldy")){
+      if(buf1[0]=='#'){
+	if(!rm&&!strcmp(buf1,cy)){remove_asm();return rm=1;}
+	strcpy(cy,buf1);
+      }else cy[0]=0;
+    }else if(!strcmp(op1,"ldz")){
+      if(buf1[0]=='#'){
+	if(!rm&&!strcmp(buf1,cz)){remove_asm();return rm=1;}
+	strcpy(cz,buf1);
+      }else cz[0]=0;
+    }else{
+      // TODO: PGS: Add the AXYZ operations to the clobber lists.
+      //            Will we need to handle them specially?
+      static char clobbernone[]="clc cld cli clv cmp cpx cpy dec inc nop pha php plp sec sed sei sta stx sty stz";
+      static char clobbera[]="adc and asl eor lsr ora pla rol ror sbc txa tya tza neg";
+      static char clobberx[]="dex inx tax tsx";
+      static char clobbery[]="dey iny tay";
+      static char clobberz[]="dez inz taz";
+      if(strstr(clobbernone,op1)){
+	// Invalidate A holding a stack variable byte if SP changes
+	if (strstr(buf1,"sp")) {
+	  printf("buf1='%s'\n",buf1);
+	  if (strstr(ca,"(sp),y")) ca[0]=0;
+	}	
+      }else if(strstr(clobbera,op1))
+	ca[0]=0;
+      else if(strstr(clobberx,op1))
+	cx[0]=0;
+      else if(strstr(clobbery,op1)) {
+	cy[0]=0;
+	// Invalidate A holding a stack variable byte if Y changes
+	if (strstr(ca,"(sp),y")) ca[0]=0;
+      }
+      else if(strstr(clobberz,op1))
+	cz[0]=0;
+      else
+	ca[0]=cx[0]=cy[0]=cz[0]=0;
+    }
+  }else{
+    ca[0]=cx[0]=cy[0]=cz[0]=0;
+  }
+
+  rm=0;
+
+  if(sscanf(asmline[0]," %6s %999s",op1,buf1)==2&&!strcmp(op1,"and")&&!strcmp(buf1,"#0")){
+    strcpy(asmline[0],"\tlda\t#0\n");
+    return rm=1;
+  }
+
+  if(entries>=2){
+    i--;
+    if(i<0) i=EMIT_BUF_DEPTH-1;
+    asmline[1]=emit_buffer[i];
+
+
+    if(!strcmp(asmline[0],"; volatile barrier\n")&&!strcmp(asmline[0],asmline[1])){
+      remove_asm();
+      return rm=1;
+    }
+
+    if(sscanf(asmline[0]," %6s",op1)==1&&!strcmp(op1,"rts")&&
+       sscanf(asmline[1]," %6s %999s",op2,buf2)==2&&!strcmp(op2,"jsr")){
+      sprintf(asmline[1],"\tjmp\t%s\n",buf2);
+      remove_asm();
+      return rm=1;
+    }
+
+    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(elim[j].r){
+	    strcpy(asmline[0],elim[j].r);
+	  }else{
+	    if(elim[j].flags&REMOVE1ST)
+	      strcpy(asmline[1],asmline[0]);
+	    remove_asm();
+	  }
+	  return rm=1;
+	}
+      }else{
+	if(sscanf(asmline[1]," %6s",op1)==1&&
+	   sscanf(asmline[0]," %6s",op2)==1&&
+	   !strcmp(op1,elim[j].s1)&&!strcmp(op2,elim[j].s2)){
+	  if(elim[j].flags&REMOVE1ST)
+	    strcpy(asmline[1],asmline[0]);
+	  remove_asm();
+	  return rm=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 0
+      if(!strcmp(op1,"lda")&&buf1[0]=='#'){
+	if(sscanf(asmline[1]," %6s %999s",op2,buf2)==2&&
+	   !strcmp(op2,"sta")){
+	  if(sscanf(asmline[2]," %6s %999s",op2,buf2)==2&&
+	     !strcmp(op2,"lda")&&!strcmp(buf1,buf2)){
+	    remove_asm();
+	    return rm=1;
+	  }
+	}
+      }
+#endif
+      if(!strcmp(op1,"beq")||!strcmp(op1,"bne")){
+	if(sscanf(asmline[1]," %6s %999s",op1,buf1)==2&&
+	   !strcmp(op1,"cmp")&&!strcmp(buf1,"#0")){
+	  if(sscanf(asmline[2]," %6s",op1)==1&&
+	     setszflag(op1)){
+	    strcpy(asmline[1],asmline[0]);
+	    remove_asm();
+	    return rm=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)&&!ieee)){
+      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(ISSHORT(t)&&c!=MULT&&c!=DIV&&c!=MOD&&!ISFLOAT(t2))
+      return 0;
+    if(ISLONG(t)&&c!=MULT&&c!=DIV&&c!=MOD&&!ISFLOAT(t2))
+      return 0;
+
+    if(!ieee&&ISFLOAT(t)) t=FLOAT;
+    if(t==LDOUBLE) t=DOUBLE;
+    if(t2==LDOUBLE) t2=DOUBLE;
+    if(!ieee&&ISFLOAT(t2)) t2=FLOAT;
+    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)==INT||(t&NQ)==LONG||(t&NQ)==LLONG||(!ieee&&ISFLOAT(t))){
+      if((c>=LSHIFT&&c<=MOD)||(c>=OR&&c<=AND)||c==KOMPLEMENT||c==MINUS){
+        if(t==(UNSIGNED|LLONG)&&(c==MULT||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 if(t==(UNSIGNED|INT)&&(c==DIV||c==MOD||c==RSHIFT)){
+          sprintf(fname,"__%suint16",ename[c]);
+          ret=fname;
+        }else if((t&NQ)==INT){
+          sprintf(fname,"__%sint16",ename[c]);
+          ret=fname;
+        }else{
+          sprintf(fname,"__%s%s%s%ld",ename[c],(t&UNSIGNED)?"u":"",ISFLOAT(t)?"flt":"int",zm2l(sizetab[t&NQ])*8);
+          ret=fname;
+        }
+      }
+    }
+  }
+
+  return ret;
+}
+
+
+int pointer_varadr(Var *v)
+{
+  int b=bank(v);
+  if(b>=0&&b!=bankcnum&&!NOBANKVARS){
+    if(cur_funcv&&bank(cur_funcv)!=b)
+      return FPOINTER;
+  }
+  return pointer_type(v->vtyp);
+}
+
+int pointer_type(struct Typ *p)
+{
+  struct Typ *merk=p;
+  if(!p) ierror(0);
+  if(LARGE) return FPOINTER;
+  while(ISARRAY(p->flags)||ISFUNC(p->flags)) p=p->next;
+  if(p->attr){
+    char *s;
+    if(strstr(p->attr,STR_HUGE)) return HPOINTER;
+    if(strstr(p->attr,STR_FAR)) return FPOINTER;
+    if(strstr(p->attr,STR_NEAR)) return POINTER;
+  }
+  return POINTER;
+}
+
+unsigned char cbmconv(unsigned char x)
+{
+  static unsigned char ctab[256]={
+    0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x14,0x09,0x0D,0x11,0x93,0x0A,0x0E,0x0F,
+    0x10,0x0B,0x12,0x13,0x08,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
+    0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
+    0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
+    0x40,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
+    0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0x5B,0xBF,0x5D,0x5E,0xA4,
+    0xAD,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
+    0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0xB3,0xDD,0xAB,0xB1,0xDF,
+    0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
+    0x90,0x91,0x92,0x0C,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
+    0xA0,0xA1,0xA2,0xA3,0x5F,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0x7D,0xAC,0x60,0xAE,0xAF,
+    0xB0,0x7E,0xB2,0x7B,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0x5C,
+    0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
+    0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0xDC,0x7C,0xDE,0x7F,
+    0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
+    0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
+  };
+
+  static unsigned char atab[]={0xfd,8,0x7f,0x9b,11,0x7d};
+
+  if(cbmascii)
+    return ctab[x&255];
+  else if(atascii&&x>=7&&x<=12)
+    return atab[x-7];
+  else
+    return x;
+}
+
+void insert_const(union atyps *p,int t)
+/*  Traegt Konstante in entprechendes Feld ein.       */
+{
+  if(!p) ierror(0);
+/*  *p = (union atyps) 0 ; /* rfi: clear unused bits */
+  t&=NU;
+  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|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==POINTER) {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>=CHAR&&f<=LLONG)){
+    if(!(t&UNSIGNED)){
+      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==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==POINTER)
+	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==CHAR){fprintf(f,"C");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==POINTER){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)
+/*  Gibt atyps aus.                                     */
+{
+  t&=NU;
+  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==POINTER){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)|POINTER);
+        if(strstr(attr,STR_FAR))
+          p->flags=((p->flags&~NU)|FPOINTER);
+        if(strstr(attr,STR_HUGE))
+          p->flags=((p->flags&~NU)|HPOINTER);
+      }
+    }
+    p=p->next;
+  }
+}
+
+void add_var_hook_post(Var *v)
+{
+  if(use_sec&&(v->storage_class==STATIC||v->storage_class==EXTERN)){
+    char buf[SECLEN+32];
+    sprintf(buf,"section(\"%s\");",use_sec);
+    add_attr(&v->vattr,buf);
+  }
+  if(use_bank>=0&&(v->storage_class==STATIC||v->storage_class==EXTERN)){
+    char buf[64];
+    /*sprintf(buf,"section(\"bank%d\");bank(%d)",use_bank,use_bank);*/
+    sprintf(buf,"bank(%d)",use_bank);
+    add_attr(&v->vattr,buf);
+  }
+}
+
+int decide_reverse(zmax v)
+{
+  if(zmeqto(v,Z1)||zmeqto(v,l2zm(2L)))
+    return 1;
+  if(optspeed)
+    if(zmeqto(v,l2zm(4L))||zmeqto(v,l2zm(8L))||zmeqto(v,l2zm(256L))||zmeqto(v,l2zm(512L)))
+      return 1;
+  
+  return 0;
+}
+
+static int is_single_eff_ic(struct IC *p)
+{
+  struct Var *v,*idx;
+  if(p->code!=ADDI2P||(p->typf2&NQ)!=POINTER)
+    return 0;
+  if(!(p->q2.flags&KONST)){
+    if((p->typf&NU)!=(UNSIGNED|CHAR))
+      return 0;
+    if((p->q2.flags&(VAR|DREFOBJ))!=VAR)
+      return 0;
+    if(p->q2.v->storage_class!=AUTO&&p->q2.v->storage_class!=REGISTER)
+      return 0;
+    idx=p->q2.v;
+  }else{
+    idx=0;
+    eval_const(&p->q2.val,p->typf);
+    /* TODO: more precise check considering data type useful? */
+    if(!zmleq(vumax,l2zm(255L)))
+      return 0;
+    return 1;
+  }
+  if(p->q1.flags&DREFOBJ)
+    return 0;
+  if((p->z.flags&(VAR|DREFOBJ))!=VAR)
+    return 0;
+  if(p->z.v->storage_class==STATIC||p->z.v->storage_class==EXTERN)
+    return 0;
+  v=p->z.v;
+  for(p=p->next;p;p=p->next){
+    int c=p->code;
+    if(c==LABEL||(c>=BEQ&&c<=BRA))
+      return 1; /* TODO: how elaborate should we test? */
+    if((p->q1.flags&VAR)&&p->q1.v==v){
+      if(p->q1.flags&DREFOBJ)
+        return 1;
+      else
+        return 0;
+    }
+    if((p->q2.flags&VAR)&&p->q2.v==v){
+      if(p->q2.flags&DREFOBJ)
+        return 1;
+      else
+        return 0;
+    }
+    if((p->z.flags&VAR)&&p->z.v==v){
+      if(p->z.flags&DREFOBJ)
+        return 1;
+      else
+        return 0;
+    }
+    if((p->z.flags&VAR)&&p->z.v==idx)
+      return 0;
+  }
+  return 0;
+}
+
+void mark_eff_ics(void)
+{
+  struct IC *p;
+  for(p=first_ic;p;p=p->next){
+    if(is_single_eff_ic(p))
+      p->flags|=EFF_IC;
+    else
+      p->flags&=~EFF_IC;
+  }
+}
diff --git a/machines/m68k/machine.c b/machines/m68k/machine.c
new file mode 100644
index 0000000..3e96a31
--- /dev/null
+++ b/machines/m68k/machine.c
@@ -0,0 +1,5595 @@
+/*  $VER: vbcc (m68k/machine.c) $Revision: 1.139 $     */
+/*  Code generator for Motorola 680x0 CPUs. Supports 68000-68060+68881/2    */
+/*  and ColdFire.                                                           */
+/*  vasm, PhxAss and the GNU assembler is supported.                        */
+
+
+#include "supp.h"
+
+#define NEW_RET 0
+
+static char FILE_[]=__FILE__;
+
+#include "dwarf2.c"
+
+/*  Public data that MUST be there.                             */
+
+/* Name and copyright. */
+char cg_copyright[]="vbcc code-generator for m68k/ColdFire V1.15 (c) in 1995-2022 by Volker Barthelmann";
+
+/*  Commandline-flags the code-generator accepts                */
+int g_flags[MAXGF]={VALFLAG,VALFLAG,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+char *g_flags_name[MAXGF]={
+    "cpu","fpu","d2scratch","noa4","sc","sd","prof","const-in-data",
+    "use-framepointer","no-peephole","no-delayed-popping",
+    "gas","branch-opt","no-fp-return","no-mreg-return","hunkdebug",
+    "no-intz","old-peephole","conservative-sr","elf","use-commons",
+    "a2scratch","old-softfloat","amiga-softfloat","fastcall","fp2scratch",
+    "no-reserve-regs","phxass","clean-fattr","old-libcalls","vbcccall",
+    "float64"
+};
+
+union ppi g_flags_val[MAXGF];
+
+/*  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[MAXR+1]={"noreg","a0","a1","a2","a3","a4","a5","a6","a7",
+                               "d0","d1","d2","d3","d4","d5","d6","d7",
+                        "fp0","fp1","fp2","fp3","fp4","fp5","fp6","fp7",
+                        "d0/d1","d2/d3","d4/d5","d6/d7"};
+
+static char *elfregnames[MAXR+1]={"noreg","%a0","%a1","%a2","%a3","%a4","%a5","%a6","%a7",
+			   "%d0","%d1","%d2","%d3","%d4","%d5","%d6","%d7",
+			   "%fp0","%fp1","%fp2","%fp3","%fp4","%fp5","%fp6","%fp7",
+			   "%d0/%d1","%d2/%d3","%d4/%d5","%d6/%d7"};
+
+static char *mregnames[MAXR+1];
+
+/*  The Size of each register in bytes.                         */
+zmax regsize[MAXR+1];
+
+/*  Type which can store each register. */
+type *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]={0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+/*  Specifies which registers may be scratched by functions.    */
+int regscratch[MAXR+1]={0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,
+			1,0,0,0};
+
+int reg_prio[MAXR+1]={0,4,4,3,3,3,3,3,0,2,2,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,0,0,0};
+
+treg_handle empty_reg_handle={0,0,0};
+
+/* Names of target-specific variable attributes.                */
+char *g_attr_name[]={"__far","__near","__chip","__saveds",
+                     "__interrupt","__amigainterrupt",0};
+#define FAR 1
+#define NEAR 2
+#define CHIP 4
+#define SAVEDS 8
+#define INTERRUPT 16
+#define AMIINTERRUPT 32
+#define STDARGS 64 /* not used, just for compatibility */
+
+int MINADDI2P=SHORT;
+
+/****************************************/
+/*  Some private data and functions.    */
+/****************************************/
+#define CPU             (g_flags_val[0].l)
+#define FPU             (g_flags_val[1].l)
+#define D2SCRATCH       (g_flags[2]&USEDFLAG)
+#define NOA4            (g_flags[3]&USEDFLAG)
+#define SMALLCODE       (g_flags[4]&USEDFLAG)
+#define SMALLDATA       (g_flags[5]&USEDFLAG)
+#define PROFILER        (g_flags[6]&USEDFLAG)
+#define CONSTINDATA     (g_flags[7]&USEDFLAG)
+#define USEFRAMEPOINTER (g_flags[8]&USEDFLAG)
+#define NOPEEPHOLE      (g_flags[9]&USEDFLAG)
+#define NODELAYEDPOP    (g_flags[10]&USEDFLAG)
+#define GAS             (g_flags[11]&USEDFLAG)
+#define BRANCHOPT       (g_flags[12]&USEDFLAG)
+#define NOFPRETURN      (g_flags[13]&USEDFLAG)
+#define NOMREGRETURN    (g_flags[14]&USEDFLAG)
+#define HUNKDEBUG       (g_flags[15]&USEDFLAG)
+#define NOINTZ          (g_flags[16]&USEDFLAG)
+#define OLDPEEPHOLE     (g_flags[17]&USEDFLAG)
+#define CONSERVATIVE_SR (g_flags[18]&USEDFLAG)
+#define ELF             (g_flags[19]&USEDFLAG)
+#define USE_COMMONS     (g_flags[20]&USEDFLAG)
+#define A2SCRATCH       (g_flags[21]&USEDFLAG)
+#define OLD_SOFTFLOAT   (g_flags[22]&USEDFLAG)
+#define AMI_SOFTFLOAT   (g_flags[23]&USEDFLAG)
+#define FASTCALL        (g_flags[24]&USEDFLAG)
+#define FP2SCRATCH      (g_flags[25]&USEDFLAG)
+#define RESERVEREGS     (g_flags[26]&USEDFLAG)
+#define PHXASS          (g_flags[27]&USEDFLAG)
+#define CLEANFATTR      (g_flags[28]&USEDFLAG)
+#define OLDLIBCALLS     (g_flags[29]&USEDFLAG)
+#define VBCCCALL        (g_flags[30]&USEDFLAG)
+#define FLOAT64         (g_flags[31]&USEDFLAG)
+
+
+static int use_sd;
+
+#ifdef M68K_16BIT_INT
+static long malign[MAX_TYPE+1]=  {1,1,2,2,2,2,2,2,2,1,2,1,1,1,2,1};
+static long msizetab[MAX_TYPE+1]={0,1,2,2,4,8,4,8,8,0,4,0,0,0,4,0};
+#else
+static long malign[MAX_TYPE+1]=  {1,1,2,2,2,2,2,2,2,1,2,1,1,1,2,1};
+static long msizetab[MAX_TYPE+1]={0,1,2,4,4,8,4,8,8,0,4,0,0,0,4,0};
+#endif
+
+static type ltyp={LONG},larray={ARRAY,&ltyp},lltyp={LLONG};
+
+static char cpu_macro[16],fpu_macro[16],*marray[16];
+
+static char pushreglist[200],popreglist[200];
+
+#define DATA 0
+#define BSS 1
+#define CODE 2
+#define SPECIAL 3
+
+static char *labprefix,*idprefix;
+
+static int reglabel,freglabel,section=-1;
+enum {
+  a0=1,a1,a2,a3,a4,a5,a6,a7,
+  d0,d1,d2,d3,d4,d5,d6,d7,
+  fp0,fp1,fp2,fp3,fp4,fp5,fp6,fp7,
+  d0d1,d2d3,d4d5,d6d7
+};
+static int sp=8,fbp=6,framesize;
+static int stack_valid;
+static char *codename,*bssname,*dataname;
+static char *m_bssname,*m_dataname;
+static char *rprefix;
+
+static void emit_obj(FILE *,obj *,int);
+static IC *do_refs(FILE *,IC *);
+static void pr(FILE *,IC *);
+static int get_reg(FILE *,int,IC *,int);
+static long pof2(zumax);
+static void function_top(FILE *,Var *,long);
+static void function_bottom(FILE *f,Var *,long);
+
+#define saveregs(x,y) saveregswfp(x,y,0)
+static void saveregswfp(FILE *,IC *,int);
+static void restoreregsa(FILE *,IC *);
+static void restoreregsd(FILE *,IC *);
+
+static void assign(FILE *,IC *,obj *,obj *,int,long,int);
+static int compare_objects(obj *o1,obj *o2);
+
+static char x_s[]={'0','b','w','3','l'};
+#ifdef M68K_16BIT_INT
+static char x_t[]={'?','b','w','w','l','L','s','d','d','v','l','a','s','u','e','f'};
+#else
+static char x_t[]={'?','b','w','l','l','L','s','d','d','v','l','a','s','u','e','f'};
+#endif
+
+static char *quick[2]={"","q"};
+static char *strshort[2]={"l","w"};
+
+static char *ubranch[]={"eq","ne","cs","cc","ls","hi"};
+
+static int pushedreg,stored_cc; /* pushedreg&2: aregsaved; 4: dreg; 8: freg */
+                                /* 16: durch RESTOREREGS gepushed           */
+static int comptyp;
+static int pushflag;
+static int geta4;
+static int dscratch=1,ascratch=1,fscratch=1;
+
+#define D16OFF 1024
+
+static int newobj=0;   /*  um zu erkennen, ob neue section erlaubt ist */
+
+static int cf;
+static int add_stdargs;
+
+static int isquickkonst(union atyps *,int),isquickkonst2(union atyps *,int),regavailable(int);
+static void move(FILE *,obj *,int,obj *,int,int);
+static void loadext(FILE *,int,obj *,int);
+static void add(FILE *,obj *,int,obj *,int,int);
+static void sub(FILE *,obj *,int,obj *,int,int);
+static void mult(FILE *,obj *,int,obj *,int,int,int,IC *);
+
+extern int static_cse;
+
+static void scratch_modified(void)
+{
+  BSET(regs_modified,a0);
+  BSET(regs_modified,a1);
+  BSET(regs_modified,d0);
+  BSET(regs_modified,d1);
+  if(FPU>68000){
+    BSET(regs_modified,fp0);
+    BSET(regs_modified,fp1);
+  }
+  if(D2SCRATCH) BSET(regs_modified,d2);
+  if(A2SCRATCH) BSET(regs_modified,a2);
+  if(FP2SCRATCH) BSET(regs_modified,fp2);
+
+}
+
+static long pof2(zumax x)
+/*  Yields log2(x)+1 oder 0. */
+{
+    zumax p;int ln=1;
+    p=ul2zum(1UL);
+    while(ln<=32&&zumleq(p,x)){
+        if(zumeqto(x,p)) return ln;
+        ln++;p=zumadd(p,p);
+    }
+    return 0;
+}
+
+#define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
+#define isconst(x) ((p->x.flags&(KONST|DREFOBJ))==KONST)
+
+#ifdef M68K_16BIT_INT
+#define ISHWORD(x) ((x&NQ)<=INT)
+#else
+#define ISHWORD(x) ((x&NQ)<INT)
+#endif
+
+#define PEA -1
+#define LEA -2
+
+#define FUNCPREFIX(t) ((stdargs(t)&&rparmtype!=PARMVBCC)?idprefix:(rparmtype==PARMVBCC?"@$":"@"))
+
+static void emit_lword(FILE *,obj *);
+static void emit_hword(FILE *,obj *);
+static int addressing(IC *);
+static long notpopped,dontpop,stackoffset,loff,maxpushed,stack;
+static int offlabel,regoffset;
+/*  For keeping track of condition codes.   */
+static obj *cc_set,*cc_set_tst;
+static int cc_typ,cc_typ_tst;
+static int missing,savedemit,savedalloc;
+static int lastpush,unorderedpush,pushoff[MAXR+1];
+
+static int vsec(FILE *f,Var *v)
+{
+  char *type="bss";
+  if(!sec_per_obj||(v->tattr&CHIP)) return 0;
+  if(ISFUNC(v->vtyp->flags)||(v->clist&&is_const(v->vtyp))) type="code"; else if(v->clist) type="data";
+  emit(f,"\t%ssection\t\"DONTMERGE_%s.%s.%ld\"%s%s\n",GAS?".":"",type,v->identifier,v->storage_class==STATIC/*&&!ISFUNC(v->vtyp->flags)*/?(long)zm2l(v->offset):0L,GAS?"":",",GAS?"":type);
+  if(f) section=SPECIAL;
+  return 1;
+}
+
+static int special_section(FILE *f,Var *v)
+{
+  char *sec;
+  if(!v->vattr) return vsec(f,v);;
+  sec=strstr(v->vattr,"section(");
+  if(!sec) return vsec(f,v);;
+  sec+=strlen("section(");
+  if(GAS)
+    emit(f,"\t.section\t");
+  else
+    emit(f,"\tsection\t");
+  while(*sec&&*sec!=')') emit_char(f,*sec++);
+  emit(f,"\n");
+  if(f) section=SPECIAL;
+  return 1;
+}
+
+static enum{
+  PARMSTD,
+  PARMVBCC,
+  PARMSAS
+} rparmtype;
+
+static int stdargs(type *t)
+{
+  type *p;
+
+  if(VBCCCALL) rparmtype=PARMVBCC;
+  else if(FASTCALL) rparmtype=PARMSAS;
+  else rparmtype=PARMSTD;
+
+  for(p=t->next;p;p=p->next){
+    if(p->attr&&strstr(p->attr,"__stdargs")) {rparmtype=PARMSTD;return 1;}
+    if(p->attr&&strstr(p->attr,"__vbccargs")) {rparmtype=PARMVBCC;return 0;}
+    if(p->attr&&strstr(p->attr,"__regargs")) {rparmtype=PARMSAS;return 0;}
+    if(CLEANFATTR) break;
+  }
+  if((!FASTCALL&&!VBCCCALL)||add_stdargs) return 1;
+  if(t->flags==FUNKT&&is_varargs(t)) return 1;
+  return 0;
+}
+
+/* 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;
+}
+
+void title(FILE *f)
+{
+  static int done;
+  extern char *inname; /*grmpf*/
+  if(!done&&f){
+    done=1;
+    if(GAS)
+      emit(f,"\t.file\t\"%s\"\n",inname);
+    else
+      emit(f,"\tidnt\t\"%s\"\n",inname);
+  }
+}      
+
+static int is_arg_reg(IC *p,int r)
+{
+  int i,u;IC *a;
+  for(i=0;i<p->arg_cnt;i++){
+    a=p->arg_list[i];
+    u=0;
+    if((a->z.flags&(REG|DREFOBJ))==REG)
+      u=a->z.reg;
+    else if((a->z.flags&VAR)&&a->z.v->reg)
+      u=a->z.v->reg;
+    if(u){
+      if(r==u||(reg_pair(u,&rp)&&r==rp.r1||r==rp.r2)){
+	return 1;
+      }
+    }
+  }
+  return 0;
+}
+
+static int am_uses_reg(IC *p,int i)
+{
+  if((p->q1.am&&((p->q1.am->dreg&127)==i||p->q1.am->basereg==i))
+     ||(p->q2.am&&((p->q2.am->dreg&127)==i||p->q2.am->basereg==i))
+     ||(p->z.am&&((p->z.am->dreg&127)==i||p->z.am->basereg==i)))
+    return 1;
+  return 0;
+}
+
+/* check if register can be scratched */
+static int scratchreg(int r,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&REG)&&p->q1.reg==r) return 0;
+    if((p->q2.flags&REG)&&p->q2.reg==r) return 0;
+    if((p->z.flags&REG)&&p->z.reg==r) return 0;
+    if(am_uses_reg(p,r)) return 0;
+  }
+}
+
+
+
+static int pget_reg(FILE *f,int flag,IC *p,int useq1)
+{
+  int i;
+
+  flag=1+flag*8;
+
+  if(useq1){
+    if(isreg(q1)&&p->q1.reg>=flag&&p->q1.reg<=flag+7&&scratchreg(p->q1.reg,p))
+      return p->q1.reg;
+  }
+
+  for(i=flag;i<flag+8;i++){
+    if(regs[i]==1&&(!p||(i!=p->q1.reg&&i!=p->q2.reg&&i!=p->z.reg))){
+      if(p){
+	if(am_uses_reg(p,i))
+	  continue;
+	if(p->code==CALL&&is_arg_reg(p,i))
+	  continue;
+      }
+      regs[i]|=8;
+      pushflag=1;
+      emit(f,"\tmove.l\t%s,%ld(%s)\n",mregnames[i],-stackoffset,mregnames[sp]);
+      if(i<d0) 
+	pushedreg|=2;
+      else if (i<fp0)
+	pushedreg|=4;
+      else
+	pushedreg|=8;
+      BSET(regs_modified,i);
+      return i;
+    }
+  }
+  ierror(0);
+}
+
+static int get_reg(FILE *f,int flag,IC *p,int useq1)
+/*  Gets a register: flag=0=areg, 1=dreg, 2=fpreg           */
+{
+  int i;
+
+  flag=1+flag*8;
+
+  if(useq1){
+    if(isreg(q1)&&p->q1.reg>=flag&&p->q1.reg<=flag+7&&scratchreg(p->q1.reg,p))
+      return p->q1.reg;
+  }
+
+  for(i=flag;i<flag+8;i++){
+    if(regs[i]==0){
+      if(p){
+	if(am_uses_reg(p,i))
+	  continue;
+	if(p->code==CALL&&is_arg_reg(p,i))
+	  continue;
+      }
+      regs[i]=2;pushedreg|=1;
+      if(!regused[i]&&!regscratch[i]){regused[i]=1; }
+      BSET(regs_modified,i);
+      return i;
+    }
+  }
+  for(i=flag;i<flag+8;i++){
+    static rpair rp;
+    if(regs[i]==1){
+      if(p){
+	if((p->q1.am&&((p->q1.am->dreg&127)==i||p->q1.am->basereg==i))
+	   ||(p->q2.am&&((p->q2.am->dreg&127)==i||p->q2.am->basereg==i))
+	   ||(p->z.am&&((p->z.am->dreg&127)==i||p->z.am->basereg==i))){
+	  continue;
+	}
+	if(p->code==CALL&&is_arg_reg(p,i))
+	  continue;
+	if(p->q1.flags&REG){
+	  if(p->q1.reg==i) continue;
+	  if(reg_pair(p->q1.reg,&rp)&&(rp.r1==i||rp.r2==i)) continue;
+	}
+	if(p->q2.flags&REG){
+	  if(p->q2.reg==i) continue;
+	  if(reg_pair(p->q2.reg,&rp)&&(rp.r1==i||rp.r2==i)) continue;
+	}
+	if(p->z.flags&REG){
+	  if(p->z.reg==i) continue;
+	  if(reg_pair(p->z.reg,&rp)&&(rp.r1==i||rp.r2==i)) continue;
+	}
+      }
+      regs[i]+=4;
+      if(i<lastpush){
+	unorderedpush=1;
+	/*printf("%s %s\n",mregnames[lastpush],mregnames[i]);*/
+      }
+      if(i<fp0){
+	emit(f,"\tmove.l\t%s,-(%s)\n",mregnames[i],mregnames[sp]);
+	push(4);
+	pushoff[i]=pushoff[lastpush]+4;
+      }else{
+	emit(f,"\tfmove.x\t%s,-(%s)\n",mregnames[i],mregnames[sp]);
+	push(12);
+	pushoff[i]=pushoff[lastpush]+12;
+      }
+      lastpush=i;
+      if(i<d0)
+	pushedreg|=2;
+      else if(i<fp0)
+	pushedreg|=4;
+      else
+	pushedreg|=8;
+      BSET(regs_modified,i);
+      return i;
+    }
+  }
+  ierror(0);
+}
+static int isquickkonst(union atyps *p,int t)
+/*  Returns 1 if constant is between -128 and 127.   */
+{
+    zmax zm;zumax zum;
+    if(ISFLOAT(t)) return 0;
+    eval_const(p,t);
+    if(t&UNSIGNED){
+        zum=ul2zum(127UL);
+        return zumleq(vumax,zum);
+    }else{
+        zm=l2zm(-129L);
+        if(zmleq(vmax,zm)) return 0;
+        zm=l2zm(127L);
+        return zmleq(vmax,zm);
+    }
+}
+static int isquickkonst2(union atyps *p,int t)
+/*  Returns 1 if constant is between 1 and 8.   */
+{
+    zmax zm;zumax zum;
+    if(ISFLOAT(t)) return 0;
+    eval_const(p,t);
+    if(t&UNSIGNED){
+        if(zumeqto(ul2zum(0UL),vumax)) return 0;
+        zum=ul2zum(8UL);
+        return zumleq(vumax,zum);
+    }else{
+        if(zmeqto(l2zm(0L),vmax)) return 0;
+        zm=l2zm(-1L);
+        if(zmleq(vmax,zm)) return 0;
+        zm=l2zm(8L);
+        return zmleq(vmax,zm);
+    }
+}
+
+static int pregavailable(IC *p,int art)
+/*  Returns true if matching register is available. Handles arglist*/
+{
+    int i;
+    art=1+art*8;
+    for(i=art+1;i<art+8;i++)
+      if(regs[i]==0&&!is_arg_reg(p,i)) return(1);
+    return 0;
+}
+
+static int regavailable(int art)
+/*  Returns true if matching register is available.     */
+{
+    int i;
+    art=1+art*8;
+    for(i=art+1;i<art+8;i++)
+        if(regs[i]==0) return(1);
+    return 0;
+}
+static int compare_objects(obj *o1,obj *o2)
+/*  Tests if two objects are equal.     */
+{
+  if((o1->flags&(REG|DREFOBJ))==REG&&(o2->flags&(REG|DREFOBJ))==REG&&o1->reg==o2->reg)
+    return 1;
+  if((o1->flags&(KONST|VAR|DREFOBJ|REG|VARADR))==(o2->flags&(KONST|VAR|DREFOBJ|REG|VARADR))&&o1->am==o2->am){
+    if(!(o1->flags&VAR)||(o1->v==o2->v&&zmeqto(o1->val.vmax,o2->val.vmax))){
+      if(!(o1->flags&REG)||o1->reg==o2->reg){
+	return 1;
+      }
+    }
+  }
+  return 0;
+}
+static IC *do_refs(FILE *f,IC *p)
+/*  Loads DREFOBJs into address registers, if necessary.    */
+/*  Small constants are loaded into data registers if this  */
+/*  improves code.                                          */
+{
+    int reg,c=p->code,t=p->typf,equal;
+    if((p->q1.flags&DREFOBJ)&&!(p->q1.flags&KONST)&&(!(p->q1.flags&REG)||p->q1.reg<1||p->q1.reg>8)){
+        equal=0;
+        if(compare_objects(&p->q1,&p->q2)) equal|=1;
+        if(compare_objects(&p->q1,&p->z)) equal|=2;
+	if(p->code==PUSH&&!pregavailable(p,0))
+	  reg=pget_reg(f,0,p,0);
+	else if(p->code==CALL&&!pregavailable(p,0))
+	  return p;
+	else
+	  reg=get_reg(f,0,p,0);
+        p->q1.flags&=~DREFOBJ;
+        emit(f,"\tmove.l\t");emit_obj(f,&p->q1,POINTER);
+        p->q1.flags=REG|DREFOBJ;
+        p->q1.reg=reg;
+        emit(f,",%s\n",mregnames[p->q1.reg]);
+        if(equal&1) p->q2=p->q1;
+        if(equal&2) p->z=p->q1;
+	if(c==TEST) cc_set_tst=cc_set=0;
+    }
+    if((p->q2.flags&DREFOBJ)&&!(p->q2.flags&KONST)&&(!(p->q2.flags&REG)||p->q2.reg<1||p->q2.reg>8)){
+        if(compare_objects(&p->q2,&p->z)) equal=1; else equal=0;
+        reg=get_reg(f,0,p,0);
+        p->q2.flags&=~DREFOBJ;
+        emit(f,"\tmove.l\t");emit_obj(f,&p->q2,POINTER);
+        p->q2.flags=REG|DREFOBJ;
+        p->q2.reg=reg;
+        emit(f,",%s\n",mregnames[p->q2.reg]);
+        if(equal) p->z=p->q2;
+    }
+    if((p->z.flags&DREFOBJ)&&!(p->z.flags&KONST)&&(!(p->z.flags&REG)||p->z.reg<1||p->z.reg>8)){
+      reg=get_reg(f,0,p,0);
+        p->z.flags&=~DREFOBJ;
+        emit(f,"\tmove.l\t");emit_obj(f,&p->z,POINTER);
+        p->z.flags=REG|DREFOBJ;
+        p->z.reg=reg;
+        emit(f,",%s\n",mregnames[p->z.reg]);
+    }
+    if(CPU!=68040){
+    /*  Don't do it on 040 because it's slower. */
+        if(x_t[t&NQ]=='l'&&(t&NQ)!=FLOAT&&(c!=ASSIGN||!isreg(z))&&
+           c!=MULT&&c!=DIV&&c!=MOD&&c!=LSHIFT&&c!=RSHIFT&&c!=SETRETURN&&c!=PUSH&&c!=ADDI2P&&c!=SUBIFP&&
+           (!(p->z.flags&REG)||p->z.reg<d0||p->z.reg>d7)){
+            /*  Constants into registers.    */
+            if(isconst(q1)&&isquickkonst(&p->q1.val,t)&&((c!=ADD&&c!=SUB&&c!=ADDI2P&&c!=SUBIFP)||!isquickkonst2(&p->q1.val,t))){
+                eval_const(&p->q1.val,t);
+                if((!zldeqto(d2zld(0.0),vldouble)||!zmeqto(l2zm(0L),vmax)||!zumeqto(ul2zum(0UL),vumax))&&regavailable(1)){
+		  reg=get_reg(f,1,p,0);
+		  move(f,&p->q1,0,0,reg,t);
+		  p->q1.flags=REG;p->q1.reg=reg;
+		  p->q1.val.vmax=l2zm(0L);
+                }
+            }
+            if(isconst(q2)&&isquickkonst(&p->q2.val,t)&&((c!=ADD&&c!=SUB&&c!=ADDI2P&&c!=SUBIFP)||!isquickkonst2(&p->q2.val,t))){
+                eval_const(&p->q2.val,t);
+                if((!zldeqto(d2zld(0.0),vldouble)||!zmeqto(l2zm(0L),vmax)||!zumeqto(ul2zum(0UL),vumax))&&regavailable(1)){
+		  reg=get_reg(f,1,p,0);
+		  move(f,&p->q2,0,0,reg,t);
+		  p->q2.flags=REG;p->q2.reg=reg;
+		  p->q2.val.vmax=l2zm(0L);
+                }
+            }
+        }
+    }
+    return p;
+}
+static void pr(FILE *f,IC *p)
+/*  Release registers and pop them from stack if necessary. */
+{
+  int i,size=0;char *s="";
+    /*  To keep track of condition codes.   */
+#if 0
+  if((pushedreg&12)&&(p->code==TEST||p->code==COMPARE)){
+    char *fp;IC *branch;
+    if(FPU>68000&&ISFLOAT(p->typf)) fp="f"; else fp="";
+    branch=p;
+    while(branch->code<BEQ||branch->code>=BRA) branch=branch->next;
+    /*FIXME*/
+    if((p->typf&UNSIGNED)||ISPOINTER(p->typf)){
+      emit(f,"\ts%s\t-2(%s)\n",ubranch[branch->code-BEQ],mregnames[sp]);
+    }else{
+      emit(f,"\t%ss%s\t-2(%s)\n",fp,ename[branch->code]+1,mregnames[sp]);
+    }
+    stored_cc=1;
+  }
+#endif
+  if((pushedreg&12)&&(p->code==TEST||p->code==COMPARE||p->code==SETRETURN)){
+    s="m";
+    if(!GAS&&!PHXASS) emit(f,"\topt\tom-\n");
+  }
+  for(i=MAXR;i>0;i--){
+    if(regs[i]==2) regs[i]=0;
+    if(regs[i]&8){
+      regs[i]&=~8;
+      
+      emit(f,"\tmove%s.l\t%ld(%s),%s\n",s,-stackoffset,mregnames[sp],mregnames[i]);
+      if(i>=d0) cc_set=0;
+      if(cc_set&&(cc_set->flags&REG)&&cc_set->reg==i)
+	cc_set=0;
+      missing++;
+    }
+    if(regs[i]&4){
+      regs[i]&=~4;
+      if(i>=1&&i<=d7){
+	if(unorderedpush)
+	  emit(f,"\tmove%s.l\t%d(%s),%s\n",s,pushoff[lastpush]-pushoff[i],mregnames[sp],mregnames[i]);
+	else{
+	  if(cf&&*s=='m'){
+	    emit(f,"\tmove%s.l\t(%s),%s\n\taddq.l\t#4,%s\n",s,mregnames[sp],mregnames[i],mregnames[sp]);
+	  }else{
+	    emit(f,"\tmove%s.l\t(%s)+,%s\n",s,mregnames[sp],mregnames[i]);
+	  }
+	}
+	pop(4);size+=4;
+      }else if(i>=fp0&&i<=fp7){
+	if(unorderedpush)
+	  emit(f,"\tfmove%s.x\t%d(%s),%s\n",s,pushoff[lastpush]-pushoff[i],mregnames[sp],mregnames[i]);
+	else
+	  emit(f,"\tfmove%s.x\t(%s)+,%s\n",s,mregnames[sp],mregnames[i]);
+	pop(12);size+=12;
+      }else if(i>=25&&i<=28){
+	if(unorderedpush)
+	  emit(f,"\tmovem.l\t%d(%s),%s\n",pushoff[lastpush]-pushoff[i],mregnames[sp],mregnames[i]);
+	else{
+	  if(cf)
+	    emit(f,"\tmovem.l\t(%s),%s\n\taddq.l\t#8,%s\n",mregnames[sp],mregnames[i],mregnames[sp]);
+	  else
+	    emit(f,"\tmovem.l\t(%s)+,%s\n",mregnames[sp],mregnames[i]);
+	}
+	pop(8);size+=8;
+      }else
+	ierror(0);
+      if(i>=d0) cc_set=0;
+      if(cc_set&&(cc_set->flags&REG)&&cc_set->reg==i)
+	cc_set=0;
+      missing++;
+    }
+  }
+  if(*s=='m'&&!GAS&&!PHXASS) emit(f,"\topt\tom+\n");
+#if 0
+  if((pushedreg&12)&&(p->code==TEST||p->code==COMPARE))
+    emit(f,"\ttst.b\t-%d(%s)\n",size+2,mregnames[sp]);
+#endif
+  if(unorderedpush)
+    emit(f,"\tadd%s.%c\t#%d,%s\n",pushoff[lastpush]<=8?"q":"",cf?'l':'w',pushoff[lastpush],mregnames[sp]);
+  lastpush=0;
+  unorderedpush=0;
+}
+static void emit_obj(FILE *f,obj *p,int t)
+/*  Write object.   */
+{
+  if(p->am){
+    /*  Addressing modes.   */
+    if(NOPEEPHOLE) {ierror(0);p->am=0;return;}
+    if(p->am->skal>=0){
+      long l=0;
+      if(p->flags&D16OFF) l=zm2l(p->val.vmax);
+      emit(f,"(%ld",p->am->dist+l);
+      if(!GAS&&CPU>=68020&&((p->am->dist+l)>32767||(p->am->dist+l)<-32768))
+	emit(f,".l");
+      else if(!GAS&&CPU>=68020&&((p->am->dist+l)>127||(p->am->dist+l)<-128))
+	emit(f,".w");
+      emit(f,",%s",mregnames[p->am->basereg]);
+      if(p->am->dreg){
+	emit(f,",%s",mregnames[p->am->dreg&127]);
+	if(p->am->dreg&128) emit(f,".w"); else emit(f,".l");
+	if(p->am->skal) emit(f,"*%d",p->am->skal);
+      }
+      emit(f,")");
+      return;
+    }
+    if((p->flags&D16OFF)&&p->am->skal<0&&!zmeqto(l2zm(0L),p->val.vmax)) ierror(0);
+    if(p->am->skal==-1){
+      emit(f,"(%s)+",mregnames[p->am->basereg]);
+      return;
+    }
+    if(p->am->skal==-2){    /*  Noch nicht implementiert    */
+      emit(f,"-(%s)",mregnames[p->am->basereg]);
+      return;
+    }
+  }
+  if(p->flags&DREFOBJ){
+    if(p->flags&KONST){
+      emitval(f,&p->val,p->dtyp&NU);
+      return;
+    }
+    emit(f,"(");
+    if((p->flags&D16OFF)&&!zmeqto(l2zm(0L),p->val.vmax)){
+      emitval(f,&p->val,MAXINT);
+      if(!zmleq(p->val.vmax,l2zm(32767L))||!zmleq(l2zm(-32768L),p->val.vmax))
+	emit(f,".l");
+      else if(!zmleq(p->val.vmax,l2zm(127L))||!zmleq(l2zm(-128L),p->val.vmax))
+	emit(f,".w");
+      emit(f,",");
+    }
+  }
+  if(p->flags&VARADR) emit(f,"#");
+  if(p->flags&VAR) {
+    if(p->flags&REG){
+      emit(f,"%s",mregnames[p->reg]);
+    }else if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER){
+      long os;
+      os=zm2l(p->val.vmax);
+      if(!USEFRAMEPOINTER&&!vlas){
+	if(!zmleq(l2zm(0L),p->v->offset)) 
+	  os=os+loff-zm2l(p->v->offset)+(PROFILER?16:0);
+	else
+	  os=os+zm2l(p->v->offset);
+	if(!GAS&&CPU>=68020&&(os-stackoffset)>0x7c00) /* +l%d max.1024? */
+	  emit(f,"((%ld+%s%d).l,%s)",os-stackoffset,labprefix,offlabel,mregnames[sp]);
+	else
+	  emit(f,"(%ld+%s%d,%s)",os-stackoffset,labprefix,offlabel,mregnames[sp]); 
+      }else{
+	if(!zmleq(l2zm(0L),p->v->offset))
+	  os=os-zm2l(p->v->offset)+4+(PROFILER?16:0);
+	else
+	  os=os-(zm2l(p->v->offset)+zm2l(szof(p->v->vtyp)));
+	emit(f,"(%ld",os);
+	if(!GAS&&CPU>=68020&&os>0x7fff)
+	  emit(f,".l");
+	emit(f,",%s)",mregnames[fbp]);
+      }
+    }else{
+      if(!zmeqto(l2zm(0L),p->val.vmax)){emitval(f,&p->val,MAXINT);emit(f,"+");}
+      if(p->v->storage_class==STATIC){
+	emit(f,"%s%ld",labprefix,zm2l(p->v->offset));
+      }else{
+	if(ISFUNC(p->v->vtyp->flags))
+	  emit(f,"%s%s",FUNCPREFIX(p->v->vtyp),p->v->identifier);
+	else
+	  emit(f,"%s%s",idprefix,p->v->identifier);
+      }
+      if(use_sd&&!(p->flags&VARADR)&&!ISFUNC(p->v->vtyp->flags)
+	 &&!(p->v->tattr&(CHIP|FAR))&&(CONSTINDATA||!is_const(p->v->vtyp))
+	 &&zmleq(l2zm(0L),p->val.vmax)&&!zmleq(szof(p->v->vtyp),p->val.vmax))
+	emit(f,"(a4)");
+    }
+  }
+  if((p->flags&REG)&&!(p->flags&VAR)) emit(f,"%s",mregnames[p->reg]);
+  if(p->flags&KONST){
+    /*  This requires IEEE floats/doubles on the host compiler. */
+    if(ISFLOAT(t)){
+      unsigned char *ip=(unsigned char *)&p->val.vfloat;
+      char *s;
+      if(GAS) s="0x"; else s="$";
+      emit(f,"#%s%02x%02x%02x%02x",s,ip[0],ip[1],ip[2],ip[3]);
+      if((t&NQ)!=FLOAT){
+	if(DEBUG&1) printf("doubleconst=%f\n",zld2d(zd2zld(p->val.vdouble)));
+	emit(f,"%02x%02x%02x%02x",ip[4],ip[5],ip[6],ip[7]);
+      }
+    }else{
+      emit(f,"#");emitval(f,&p->val,t&NU);
+    }
+  }
+  if(p->flags&DREFOBJ) emit(f,")");
+}
+static void dwarf2_print_frame_location(FILE *f,Var *v)
+{
+  /*FIXME: needs a location list and correct register trabslation */
+  obj o;
+  o.flags=REG;
+  if(USEFRAMEPOINTER||vlas)
+    o.reg=fbp;
+  else
+    o.reg=sp;
+  o.val.vmax=l2zm(0L);
+  o.v=0;
+  dwarf2_print_location(f,&o);
+}
+static int dwarf2_regnumber(int r)
+{
+  if(r<=8)
+    return r+7;
+  else if(r<=d7)
+    return r-8;
+  else if(r<=fp7)
+    return r+1;
+  else
+    ierror(0);
+}
+static zmax dwarf2_fboffset(Var *v)
+{
+  long os;
+  if(!v||(v->storage_class!=AUTO&&v->storage_class!=REGISTER)) ierror(0);
+  if(!USEFRAMEPOINTER&&!vlas){
+    if(!zmleq(l2zm(0L),v->offset)) 
+      os=loff-zm2l(v->offset);
+    else
+      os=zm2l(v->offset);
+    return l2zm(os+framesize);
+  }else{
+    if(!zmleq(l2zm(0L),v->offset)) 
+      return l2zm(-zm2l(v->offset)+4);
+    else
+      return l2zm(-(zm2l(v->offset)+zm2l(szof(v->vtyp))));
+  }
+}
+
+static char tsh[]={'w','l'};
+static int proflabel,stacksizelabel;
+static void function_top(FILE *f,Var *v,long offset)
+/*  Writes function header. */
+{
+    geta4=0;
+    if(GAS){
+    }else{
+        if(debug_info&&HUNKDEBUG) emit(f,"\tsymdebug\n");
+        if(CPU!=68000) emit(f,"\tmachine\t%ld\n",CPU);
+        if(cf) strshort[1]="l";
+        if(FPU>68000) emit(f,"\tfpu\t1\n");
+        if(SMALLCODE) emit(f,"\tnear\tcode\n");
+        if(use_sd) emit(f,"\tnear\ta4,-2\n");
+	if(PHXASS){
+	  emit(f,"\topt\t0\n\topt\tNQLPSM");
+	  if(CPU!=68040) emit(f,"R");
+	  if(1/*BRANCHOPT||(optflags&2)*/) emit(f,"BT");
+	  emit(f,"\n");
+	}else{
+	  emit(f,"\topt o+,ol+,op+,oc+,ot+,oj+,ob+,om+");
+	  if(CPU==68040) emit(f,",a-");
+	  emit(f,"\n");
+	}
+    }
+    if(!special_section(f,v)&&section!=CODE){emit(f,codename);if(f) section=CODE;}
+    if(PROFILER){
+        proflabel=++label;
+        if(GAS){
+            emit(f,"%s%d:\n\t.byte\t\"%s\",0\n",labprefix,proflabel,v->identifier);
+        }else{
+            emit(f,"%s%d\n\tdc.b\t\"%s\",0\n",labprefix,proflabel,v->identifier);
+        }
+    }
+    if(v->storage_class==EXTERN){
+      if((v->flags&(INLINEFUNC|INLINEEXT))!=INLINEFUNC){
+        if(GAS){
+	  emit(f,"\t.global\t%s%s\n",FUNCPREFIX(v->vtyp),v->identifier);
+        }else{
+	  emit(f,"\tpublic\t%s%s\n",FUNCPREFIX(v->vtyp),v->identifier);
+        }
+      }
+    }
+    if(v->storage_class==EXTERN){
+      if(GAS){
+        emit(f,"\t.align\t4\n%s%s:\n",FUNCPREFIX(v->vtyp),v->identifier);
+      }else{
+        emit(f,"\tcnop\t0,4\n%s%s\n",FUNCPREFIX(v->vtyp),v->identifier);
+      }
+    }else{
+      if(GAS){
+        emit(f,"\t.align\t4\n%s%ld:\n",labprefix,zm2l(v->offset));
+      }else{
+        emit(f,"\tcnop\t0,4\n%s%ld\n",labprefix,zm2l(v->offset));
+      }
+    }      
+    if(stack_check&&!(v->tattr&AMIINTERRUPT)){
+      stacksizelabel=++label;
+      if(GAS){
+	emit(f,"\tmove.l\t#%s%d,-(%s)\n\tjbsr\t___stack_check\n\taddq.l\t#4,%s\n",labprefix,stacksizelabel,mregnames[sp],mregnames[sp]);
+      }else{
+	emit(f,"\tmove.l\t#%s%d,-(%s)\n\tjsr\t___stack_check\n\taddq.l\t#4,%s\n",labprefix,stacksizelabel,mregnames[sp],mregnames[sp]);
+      }
+    }      
+    if(PROFILER){
+        if(GAS){
+            emit(f,"\tsub.l\t#16,%s\n\tmove.l\t%s,-(%s)\n\tpea\t%s%d\n\t.global\t__startprof\n\tjbsr\t__startprof\n\taddq.%s\t#8,%s\n",mregnames[sp],mregnames[sp],mregnames[sp],labprefix,proflabel,strshort[1],mregnames[sp]);
+        }else{
+            emit(f,"\tsub.l\t#16,%s\n\tmove.l\t%s,-(%s)\n\tpea\t%s%d\n\tpublic\t__startprof\n\tjsr\t__startprof\n\taddq.%s\t#8,%s\n",mregnames[sp],mregnames[sp],mregnames[sp],labprefix,proflabel,strshort[1],mregnames[sp]);
+        }
+    }
+    offset=-((offset+4-1)/4)*4;
+    loff=-offset;offlabel=++label;
+    if(!USEFRAMEPOINTER&&!vlas){
+      if(offset<0) emit(f,"\tsub%s.%s\t#%ld,%s\n",quick[offset>=-8],strshort[offset>=-32768],-offset,mregnames[sp]);
+    }else{
+      if(offset>=-32768||CPU>=68020){
+	emit(f,"\tlink.%c\t%s,#%ld\n",tsh[offset<-32768],mregnames[fbp],offset);
+      }else{
+	emit(f,"\tlink.w\t%s,#-32768\n",mregnames[fbp]);offset+=32768;
+	  emit(f,"\tsub.%c\t#%ld,%s\n",tsh[offset<-32768],offset,mregnames[fbp]);
+      }
+    }
+    if(FPU>68000&&float_used){
+        if(GAS){
+            emit(f,"\t.word\t0xf227,%s%d\n",labprefix,freglabel);
+        }else{
+            emit(f,"\tfmovem.x\t%s%d,-(%s)\n",labprefix,freglabel,mregnames[sp]);
+        }
+    }
+    if(cf){
+      emit(f,"\tsub.l\t#%s%d,%s\n",labprefix,offlabel,mregnames[sp]);
+      if(GAS){
+        emit(f,"\tmovem.l\t#%s%d,(%s)\n",labprefix,reglabel,mregnames[sp]);
+      }else{
+        emit(f,"\tmovem.l\t%s%d,(%s)\n",labprefix,reglabel,mregnames[sp]);
+      }
+    }else{
+      if(GAS){
+        emit(f,"\tmovem.l\t#%s%d,-(%s)\n",labprefix,reglabel,mregnames[sp]);
+      }else{
+        emit(f,"\tmovem.l\t%s%d,-(%s)\n",labprefix,reglabel,mregnames[sp]);
+      }
+    }
+    if((v->tattr&SAVEDS)&&use_sd) emit(f,"\txref\t_LinkerDB\n\tlea\t_LinkerDB,a4\n");
+    stack_valid=1;
+    stack=0;
+}
+static void function_bottom(FILE *f,Var *v,long offset)
+/*  Writes function footer. */
+{
+    int i,size=0;unsigned int pushval,popval;
+    *pushreglist=0;*popreglist=0;
+    pushval=popval=0;
+    if((v->tattr&SAVEDS)&&use_sd) geta4=1;
+    for(i=1;i<=16;i++){
+        if((((regused[i]&&!regscratch[i])||((v->tattr&INTERRUPT)&&BTST(regs_modified,i)))&&!regsa[i])||(i==5&&geta4)||(i==d0&&pushflag)){
+            if(*pushreglist) strcat(pushreglist,"/");
+            strcat(pushreglist,mregnames[i]);
+	    if(i!=d0||(v->tattr&INTERRUPT)){
+	      if(*popreglist) strcat(popreglist,"/");
+	      strcat(popreglist,mregnames[i]);
+	    }
+            if(i<d0){
+	      pushval|=(256>>i);popval|=(128<<i);
+	    }else{
+	      pushval|=(0x8000>>(i-9));
+	      if(i!=d0) popval|=(1<<(i-9));
+	    }
+            size+=4;
+        }
+    }
+    if(pushflag){
+      emit(f,"\taddq.%c\t#4,%s\n",cf?'l':'w',mregnames[sp]);
+      if(v->tattr&INTERRUPT) ierror(0);
+    }
+    if(cf){
+      if(GAS){
+        if(popval)
+	  emit(f,"\t.equ\t%s%d,%u\n\tmovem.l\t(%s),#%u\n\tadd.l\t#%s%d%s,%s\n",labprefix,reglabel,pushval,mregnames[sp],popval,labprefix,offlabel,pushflag?"-4":"",mregnames[sp]);
+        else
+	  emit(f,"\t.equ\t%s%d,0\n",labprefix,reglabel);
+      }else{
+        if(*pushreglist)
+	  emit(f,"%s%d\treg\t%s\n",labprefix,reglabel,pushreglist);
+	else
+	  emit(f,"%s%d\treg\n",labprefix,reglabel);
+	if(*popreglist)
+	  emit(f,"\tmovem.l\t(%s),%s\n\tadd.l\t#%s%d%s,%s\n",mregnames[sp],popreglist,labprefix,offlabel,pushflag?"-4":"",mregnames[sp]);
+      }
+    }else{
+      if(GAS){
+        if(popval)
+	  emit(f,"\t.equ\t%s%d,%u\n\tmovem.l\t(%s)+,#%u\n",labprefix,reglabel,pushval,mregnames[sp],popval);
+        else
+	  emit(f,"\t.equ\t%s%d,0\n",labprefix,reglabel);
+      }else{
+        if(*pushreglist)
+	  emit(f,"%s%d\treg\t%s\n",labprefix,reglabel,pushreglist);
+        else
+	  emit(f,"%s%d\treg\n",labprefix,reglabel);
+	if(*popreglist)
+	  emit(f,"\tmovem.l\t(%s)+,%s\n",mregnames[sp],popreglist);
+      }
+    }
+    *pushreglist=0;*popreglist=0;pushval=0xe000;popval=0xd000;
+    for(i=fp0;i<=fp7;i++){
+      if((((regused[i]&&!regscratch[i])||((v->tattr&INTERRUPT)&&BTST(regs_modified,i)))&&!regsa[i])){
+	if(*popreglist) strcat(popreglist,"/");
+	strcat(popreglist,mregnames[i]);
+	pushval|=(1<<(i-17));popval|=(0x80>>(i-17));
+	size+=12;
+      }
+    }
+    if(FPU>68000&&(float_used||(v->tattr&INTERRUPT))){
+      if(GAS){
+	if(popval!=0xd000)
+	  emit(f,"\t.equ\t%s%d,0x%x\n\t.word\t0xf21f,0x%x\n",labprefix,freglabel,(int)pushval,(int)popval);
+	else
+	  emit(f,"\t.equ\t%s%d,0xe000\n",labprefix,freglabel);
+      }else{
+	if(*popreglist)
+	  emit(f,"%s%d\tfreg\t%s\n\tfmovem.x\t(%s)+,%s%d\n",labprefix,freglabel,popreglist,mregnames[sp],labprefix,freglabel);
+	else
+	  emit(f,"%s%d\tfreg\n",labprefix,freglabel);
+        }
+    }
+    if(cf||(!USEFRAMEPOINTER&&!vlas)){
+      if(GAS){
+	emit(f,"\t.equ\t%s%d,%d\n",labprefix,offlabel,size);
+      }else{
+	emit(f,"%s%d\tequ\t%d\n",labprefix,offlabel,size);
+      }
+    }
+    if(!USEFRAMEPOINTER&&!vlas){
+      if(loff) emit(f,"\tadd%s.%s\t#%ld,%s\n",quick[loff<=8],strshort[loff<32768],loff,mregnames[sp]);
+      framesize=size;
+    }else
+      emit(f,"\tunlk\t%s\n",mregnames[fbp]);
+    if(PROFILER){
+        if(GAS){
+            emit(f,"\tmove.l\t%s,-(%s)\n\t.global\t__endprof\n\tjbsr\t__endprof\n\tadd.%s\t#20,%s\n",mregnames[sp],mregnames[sp],strshort[1],mregnames[sp]);
+        }else{
+            emit(f,"\tmove.l\t%s,-(%s)\n\tpublic\t__endprof\n\tjsr\t__endprof\n\tadd.%s\t#20,%s\n",mregnames[sp],mregnames[sp],strshort[1],mregnames[sp]);
+        }
+    }
+    if(v->tattr&INTERRUPT)
+      emit(f,"\trte\n");
+    else
+      emit(f,"\trts\n");
+    if(stack_check&&!(v->tattr&AMIINTERRUPT)){
+      if(GAS)
+	emit(f,"\t.equ\t%s%d,%ld\n",labprefix,stacksizelabel,size+loff-maxpushed);
+      else
+	emit(f,"%s%d\tequ\t%ld\n",labprefix,stacksizelabel,size+loff-maxpushed);
+    }
+    if(stack_valid){
+      if(!v->fi) v->fi=new_fi();
+      v->fi->flags|=ALL_STACK;
+      v->fi->stack1=l2zm(size+loff+stack);
+      emit(f,"%c stacksize=%ld\n",GAS?'#':';',size+loff+stack);
+    }
+}
+static void move(FILE *f,obj *q,int qreg,obj *z,int zreg,int t)
+/*  erzeugt eine move Anweisung...Da sollen mal Optimierungen rein  */
+{
+    if(!zreg&&(z->flags&(REG|DREFOBJ))==REG) zreg=z->reg;
+    if(!qreg&&(q->flags&(REG|DREFOBJ))==REG) qreg=q->reg;
+    if(zreg==qreg&&zreg) return;
+    if(q&&(q->flags&VARADR)&&zreg>=1&&zreg<=8){
+        emit(f,"\tlea\t");
+        q->flags&=~VARADR;emit_obj(f,q,t);q->flags|=VARADR;
+        emit(f,",%s\n",mregnames[zreg]);
+	BSET(regs_modified,zreg);
+        return;
+    }
+    if(zreg>=d0&&zreg<fp0&&q&&(q->flags&(KONST|DREFOBJ))==KONST&&isquickkonst(&q->val,t)){
+        emit(f,"\tmoveq\t");
+    }else{
+        if((zreg>=fp0&&zreg<=fp7)||(qreg>=fp0&&qreg<=fp7)){
+            if(qreg>=fp0&&qreg<=fp7&&zreg>=fp0&&zreg<=fp7) emit(f,"\tfmove.x\t");
+             else emit(f,"\tfmove.%c\t",x_t[t&NQ]);
+        }else{
+	  if(!cf||qreg||zreg)
+            emit(f,"\tmove.%c\t",x_s[msizetab[t&NQ]]);
+        }
+    }
+    if(cf&&!qreg&&!zreg){
+        static IC dummy;
+        dummy.code=ASSIGN;
+        dummy.typf=t;
+        dummy.q1=*q;
+        dummy.q2.flags=0;
+        dummy.z=*z;
+        qreg=get_reg(f,1,&dummy,0);
+	emit(f,"\tmove.%c\t",x_s[msizetab[t&NQ]]);
+        emit_obj(f,q,t);
+        emit(f,",%s\n\tmove.%c\t%s,",mregnames[qreg],x_s[msizetab[t&NQ]],mregnames[qreg]);
+        emit_obj(f,z,t);
+        emit(f,"\n");
+    }else{
+      if(qreg) emit(f,"%s",mregnames[qreg]); else emit_obj(f,q,t);
+      emit(f,",");
+      if(zreg) emit(f,"%s",mregnames[zreg]); else emit_obj(f,z,t);
+      emit(f,"\n");
+      if(zreg) BSET(regs_modified,zreg);
+    }
+}
+static void loadext(FILE *f,int r,obj *q,int t)
+/*  laedt Objekt q vom Typ t in Register r und erweitert auf long   */
+{
+    if(t&UNSIGNED){
+      if((q->flags&(REG|DREFOBJ))==REG&&q->reg==r)
+        emit(f,"\tand.l\t#%u,%s\n",((t&NQ)==CHAR?0xffu:0xffffu),mregnames[r]);
+      else
+        emit(f,"\tmoveq\t#0,%s\n",mregnames[r]);
+    }
+    move(f,q,0,0,r,t);
+#ifdef M68K_16BIT_INT
+    if((t&NU)==SHORT||(t&NU)==INT) emit(f,"\text.l\t%s\n",mregnames[r]);
+#else
+    if((t&NU)==SHORT) emit(f,"\text.l\t%s\n",mregnames[r]);
+#endif
+    if((t&NU)==CHAR){
+      if(cf||CPU>=68020)
+        emit(f,"\textb.l\t%s\n",mregnames[r]);
+      else
+        emit(f,"\text.w\t%s\n\text.l\t%s\n",mregnames[r],mregnames[r]);
+    }
+}
+
+static void add(FILE *f,obj *q,int qreg,obj *z,int zreg,int t)
+/*  erzeugt eine add Anweisung...Da sollen mal Optimierungen rein   */
+{
+    if(!qreg&&!q) ierror(0);
+    if(!zreg&&!z) ierror(0);
+    if(!zreg&&(z->flags&(REG|DREFOBJ))==REG) zreg=z->reg;
+    if(cf&&x_t[t&NQ]!='l'&&(qreg||(q->flags&(KONST|DREFOBJ))!=KONST)) ierror(0);
+    if(!qreg&&(q->flags&(KONST|DREFOBJ))==KONST&&isquickkonst2(&q->val,t)){
+      emit(f,"\taddq.%c\t",cf?'l':x_t[t&NQ]);
+    }else{
+        /*  hier noch Abfrage, ob #c.w,ax   */
+      emit(f,"\tadd.%c\t",cf?'l':x_t[t&NQ]);
+    }
+    if(qreg) emit(f,"%s",mregnames[qreg]); else emit_obj(f,q,t);
+    emit(f,",");
+    if(zreg) emit(f,"%s",mregnames[zreg]); else emit_obj(f,z,t);
+    emit(f,"\n");
+}
+static void sub(FILE *f,obj *q,int qreg,obj *z,int zreg,int t)
+/*  erzeugt eine sub Anweisung...Da sollen mal Optimierungen rein   */
+{
+    if(cf&&x_t[t&NQ]!='l'&&(qreg||(q->flags&(KONST|DREFOBJ))!=KONST)) ierror(0);
+    if(!zreg&&(z->flags&(REG|DREFOBJ))==REG) zreg=z->reg;
+    if(q&&(q->flags&(KONST|DREFOBJ))==KONST&&isquickkonst2(&q->val,t)){
+      emit(f,"\tsubq.%c\t",cf?'l':x_t[t&NQ]);
+    }else{
+        /*  hier noch Abfrage, ob #c.w,ax   */
+      emit(f,"\tsub.%c\t",cf?'l':x_t[t&NQ]);
+    }
+    if(qreg) emit(f,"%s",mregnames[qreg]); else emit_obj(f,q,t);
+    emit(f,",");
+    if(zreg) emit(f,"%s",mregnames[zreg]); else emit_obj(f,z,t);
+    emit(f,"\n");
+}
+static void mult(FILE *f,obj *q,int qreg,obj *z,int zreg, int t,int c,IC *p)
+/*  erzeugt eine mult Anweisung...Da sollen mal Optimierungen rein  */
+/*  erzeugt auch div/mod etc.                                       */
+{
+  int modreg;
+  if(!qreg&&(q->flags&(REG|DREFOBJ))==REG) qreg=q->reg;
+  if(!zreg&&(z->flags&(REG|DREFOBJ))==REG) zreg=z->reg;
+  if(cf&&!qreg) {qreg=get_reg(f,1,p,0);move(f,q,0,0,qreg,t);}
+  if((c==MULT||c==DIV||c==MOD)&&CPU<68020&&!cf&&msizetab[t&NQ]==4){
+    if(c==MULT){
+      /*  ist das mit get_reg(.,.,0) ok? nochmal ueberdenken...   */
+      /*  ...die ganze Routine am besten...                       */
+      /*  ...es war nicht, deshalb ist es jetzt geaendert         */
+      int dx,dy,t1,t2;
+      if(zreg>=d0&&zreg<=d7){
+	dx=zreg;
+      }else{
+	dx=get_reg(f,1,p,0);
+	move(f,z,0,0,dx,t);
+      }
+      if(qreg>=d0&&qreg<=d7&&qreg!=dx){
+	dy=qreg;
+      }else{
+	dy=get_reg(f,1,p,0);
+	move(f,q,0,0,dy,t);
+      }
+      t1=get_reg(f,1,p,0);t2=get_reg(f,1,p,0);
+      if(t1==dx||t2==dx||t1==dy||t2==dy) ierror(0);
+      emit(f,"\tmove.l\t%s,%s\n",mregnames[dx],mregnames[t1]);
+      emit(f,"\tmove.l\t%s,%s\n",mregnames[dy],mregnames[t2]);
+      emit(f,"\tswap\t%s\n",mregnames[t1]);
+      emit(f,"\tswap\t%s\n",mregnames[t2]);
+      emit(f,"\tmulu.w\t%s,%s\n",mregnames[dy],mregnames[t1]);
+      emit(f,"\tmulu.w\t%s,%s\n",mregnames[dx],mregnames[t2]);
+      emit(f,"\tmulu.w\t%s,%s\n",mregnames[dy],mregnames[dx]);
+      emit(f,"\tadd.w\t%s,%s\n",mregnames[t2],mregnames[t1]);
+      emit(f,"\tswap\t%s\n",mregnames[t1]);
+      emit(f,"\tclr.w\t%s\n",mregnames[t1]);
+      emit(f,"\tadd.l\t%s,%s\n",mregnames[t1],mregnames[dx]);
+      if(zreg!=dx) move(f,0,t1,z,0,t);
+    }else ierror(0);
+    return;
+  }
+  if(c==MULT){
+    /*  das duerfte nur der Aesthetik dienen... */
+    if(t&UNSIGNED) 
+      emit(f,"\tmulu.%c\t",x_t[t&NQ]);
+    else 
+      emit(f,"\tmuls.%c\t",x_t[t&NQ]);
+    if((t&NQ)<=SHORT) cc_set=0;
+  }
+  if(c==DIV||(c==MOD&&ISHWORD(t))){
+    if(t&UNSIGNED){
+      if(ISHWORD(t)) emit(f,"\tand.l\t#65535,%s\n",mregnames[zreg]);
+      emit(f,"\tdivu.%c\t",x_t[t&NQ]);
+    }else{
+      if(ISHWORD(t)) emit(f,"\text.l\t%s\n",mregnames[zreg]);
+      emit(f,"\tdivs.%c\t",x_t[t&NQ]);
+    }
+  }  
+  if(qreg) 
+    emit(f,"%s",mregnames[qreg]); 
+  else 
+    emit_obj(f,q,t);
+  emit(f,",");
+  /*  eigentlich muss zreg!=0 sein...     */
+  if(zreg) 
+    emit(f,"%s",mregnames[zreg]); 
+  else 
+    emit_obj(f,z,t);
+  emit(f,"\n");
+  if(c==MOD){
+    emit(f,"\tswap\t%s\n",mregnames[zreg]);
+    cc_set=0;
+  }
+}
+static IC *am_freedreg[9],*am_shiftdreg[9];
+static IC *am_dist_ic[9],*am_dreg_ic[9],*am_use[9];
+/*  am_dist_ic und am_dreg_ic werden auch fuer (ax)+ benutzt    */
+static long am_dist[9],am_dreg[9],am_base[9],am_inc[9],am_skal[9],am_dbase[9];
+#define AMS sizeof(AddressingMode)
+
+static int mopsize(IC *p,int reg)
+/*  Liefert die Groesse in Bytes, mit der im IC auf (reg) zugegriffen wird. */
+{
+    int c=p->code;
+    if(c==ADDI2P||c==SUBIFP){
+        if((p->q2.flags&REG)&&p->q2.reg==reg)
+            return zm2l(sizetab[p->typf&NQ]);
+        return 4;
+    }
+    if(c==CONVERT){
+        if((p->z.flags&REG)&&p->z.reg==reg)
+          return zm2l(sizetab[p->typf&NQ]);
+        else
+          return zm2l(sizetab[p->typf2&NQ]);
+    }
+    return zm2l(sizetab[p->typf&NQ]);
+}
+static void clear_am(int reg)
+/*  loescht Werte fuer erweiterte Adressierungsarten fuer Register reg  */
+{
+    if(reg<0||reg>d7) ierror(0);
+    if(DEBUG&32) printf("clear_am(%s)\n",mregnames[reg]);
+    if(reg<=8){
+        am_dist_ic[reg]=am_dreg_ic[reg]=am_use[reg]=0;
+        am_dist[reg]=am_dreg[reg]=am_base[reg]=am_inc[reg]=0;
+    }else{
+        reg-=8;
+        am_freedreg[reg]=am_shiftdreg[reg]=0;
+        am_skal[reg]=am_dbase[reg]=0;
+    }
+}
+static void mod_reg(int r)
+{
+  int i;
+  for(i=1;i<=8;i++){
+    if((!am_use[i]&&am_base[i]==r)||(am_dreg[i]&127)==r)
+      clear_am(i);
+  }
+#if 0
+  if(r>=9&&r<=16){
+    for(i=9;i<=16;i++){
+      if(am_dbase[i-8]==r)
+	clear_am(i);
+    }
+  }
+#endif
+}
+/* return non-zero if IC is implemented by a function call */
+static int islibcall(IC *p)
+{
+  int c=p->code,t=p->typf/NQ;
+  if((c==DIV||c==MOD)&&CPU<68020)
+    return 1;
+  if(t==LLONG&&c!=ADD&&c!=SUB&&c!=OR&&c!=AND&&c!=XOR&&c!=COMPARE)
+    return 1;
+  if(ISFLOAT(t)&&FPU<=68000)
+    return 1;
+  if(c==CONVERT){
+    if(t==LLONG||ISFLOAT(t)) 
+      return 1;
+    t=p->typf2&NQ;
+    if(t==LLONG||ISFLOAT(t))
+      return 1;
+  }
+  return 0;
+}
+
+static int new_peephole(IC *first)
+{
+  int localused=0,c,r,t,c2;long sz;
+  IC *p,*p2;
+  AddressingMode *am;
+  for(p=first;p;p=p->next){
+    int c=p->code;
+    if(!localused){
+      if((p->q1.flags&(VAR|REG))==VAR&&(p->q1.v->storage_class==AUTO||p->q1.v->storage_class==REGISTER)&&zmleq(l2zm(0L),p->q1.v->offset))
+	localused=1;
+      if((p->q2.flags&(VAR|REG))==VAR&&(p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER)&&zmleq(l2zm(0L),p->q2.v->offset))
+	localused=1;
+      if((p->z.flags&(VAR|REG))==VAR&&(p->z.v->storage_class==AUTO||p->z.v->storage_class==REGISTER)&&zmleq(l2zm(0L),p->z.v->offset))
+	localused=1;
+      if(DEBUG&32&&localused==1) printf("localused=1\n");
+    }
+    /* -(ax) */
+    if(c==SUBIFP&&isreg(q1)&&isreg(z)&&p->q1.reg==p->z.reg&&p->q1.reg<=8&&isconst(q2)){
+      r=p->q1.reg;
+      eval_const(&p->q2.val,q2typ(p));
+      sz=zm2l(vmax);
+      if(sz==1||sz==2||sz==4||sz==8){
+	for(p2=p->next;p2;p2=p2->next){
+	  c2=p2->code;
+	  if(!p2->q1.am&&(p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r&&(!(p2->q2.flags&REG)||p2->q2.reg!=r)&&(!(p2->z.flags&REG)||p2->z.reg!=r)&&(c2!=CONVERT||(q1typ(p2)&NQ)<=(ztyp(p2)&NQ))){
+	    t=(q1typ(p2)&NQ);
+	    if((ISINT(t)||ISPOINTER(t))&&t!=LLONG&&zmeqto(sizetab[q1typ(p2)&NQ],l2zm(sz))&&!islibcall(p2)){
+	      p2->q1.am=am=mymalloc(sizeof(*am));
+	      p2->q1.val.vmax=l2zm(0L);
+	      am->basereg=r;
+	      am->dist=0;
+	      am->skal=-2;
+	      am->dreg=0;
+	      p->code=NOP;
+	      p->q1.flags=p->q2.flags=p->z.flags=0;
+	      break;
+	    }
+	  }
+	  if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r&&(!(p2->q1.flags&REG)||p2->q1.reg!=r)&&(!(p2->z.flags&REG)||p2->z.reg!=r)){
+	    t=(q2typ(p2)&NQ);
+	    if((ISINT(t)||ISPOINTER(t))&&t!=LLONG&&zmeqto(sizetab[q2typ(p2)&NQ],l2zm(sz))&&!islibcall(p2)){
+	      p2->q2.am=am=mymalloc(sizeof(*am));
+	      p2->q2.val.vmax=l2zm(0L);
+	      am->basereg=r;
+	      am->dist=0;
+	      am->skal=-2;
+	      am->dreg=0;
+	      p->code=NOP;
+	      p->q1.flags=p->q2.flags=p->z.flags=0;
+	      break;
+	    }
+	  }
+	  if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r&&(!(p2->q2.flags&REG)||p2->q2.reg!=r)&&(!(p2->q1.flags&REG)||p2->q1.reg!=r)){
+	    t=(ztyp(p2)&NQ);
+	    if((ISINT(t)||ISPOINTER(t))&&t!=LLONG&&zmeqto(sizetab[ztyp(p2)&NQ],l2zm(sz))&&!islibcall(p2)){
+	      p2->z.am=am=mymalloc(sizeof(*am));
+	      p2->z.val.vmax=l2zm(0L);
+	      am->basereg=r;
+	      am->dist=0;
+	      am->skal=-2;
+	      am->dreg=0;
+	      p->code=NOP;
+	      p->q1.flags=p->q2.flags=p->z.flags=0;
+	      break;
+	    }
+	  }
+	  if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
+	  if((p2->q1.flags&REG)&&p2->q1.reg==r) break;
+	  if((p2->q2.flags&REG)&&p2->q2.reg==r) break;
+	  if((p2->z.flags&REG)&&p2->z.reg==r) break;
+	}
+      }
+    }
+    /* (ax)+ in q1 */
+    if(!p->q1.am&&(p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p->q1.reg<=8&&(c!=CONVERT||(q1typ(p)&NQ)<=(ztyp(p)&NQ))){
+      t=(q1typ(p)&NQ);
+      sz=zm2l(sizetab[t]);
+      r=p->q1.reg;
+      if((sz==1||sz==2||sz==4||sz==8)&&(ISINT(t)||ISPOINTER(t))&&t!=LLONG&&(!(p->q2.flags&REG)||p->q2.reg!=r)&&(!(p->z.flags&REG)||p->z.reg!=r)&&(!p->q2.am||p->q2.am->basereg!=r)&&(!p->z.am||p->z.am->basereg!=r)){
+	for(p2=p->next;p2;p2=p2->next){
+	  c2=p2->code;
+	  if(c2==ADDI2P&&(p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r&&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg==r&&(p2->q2.flags&(KONST|DREFOBJ))==KONST&&!islibcall(p)){
+	    eval_const(&p2->q2.val,q2typ(p2));
+	    if(zmeqto(vmax,l2zm(sz))){
+	      p->q1.am=am=mymalloc(sizeof(*am));
+	      p->q1.val.vmax=l2zm(0L);
+	      am->basereg=r;
+	      am->dist=0;
+	      am->skal=-1;
+	      am->dreg=0;
+	      p2->code=NOP;
+	      p2->q1.flags=p2->q2.flags=p2->z.flags=0;
+	      break;
+	    }
+	  }
+	  if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
+	  if((p2->q1.flags&REG)&&p2->q1.reg==r) break;
+	  if((p2->q2.flags&REG)&&p2->q2.reg==r) break;
+	  if((p2->z.flags&REG)&&p2->z.reg==r) break;
+	  if(p2->q1.am&&p2->q1.am->basereg==r) break;
+	  if(p2->q2.am&&p2->q2.am->basereg==r) break;
+	  if(p2->z.am&&p2->z.am->basereg==r) break;
+	}
+      }
+    }
+    /* (ax)+ in q2 */
+    if(!p->q2.am&&(p->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p->q2.reg<=8){
+      t=(q2typ(p)&NQ);
+      sz=zm2l(sizetab[t]);
+      r=p->q2.reg;
+      if((sz==1||sz==2||sz==4||sz==8)&&(ISINT(t)||ISPOINTER(t))&&t!=LLONG&&(!(p->q1.flags&REG)||p->q1.reg!=r)&&(!(p->z.flags&REG)||p->z.reg!=r)&&(!p->q1.am||p->q1.am->basereg!=r)&&(!p->z.am||p->z.am->basereg!=r)){
+	for(p2=p->next;p2;p2=p2->next){
+	  c2=p2->code;
+	  if(c2==ADDI2P&&(p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r&&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg==r&&(p2->q2.flags&(KONST|DREFOBJ))==KONST&&!islibcall(p)){
+	    eval_const(&p2->q2.val,q2typ(p2));
+	    if(zmeqto(vmax,l2zm(sz))){
+	      p->q2.am=am=mymalloc(sizeof(*am));
+	      p->q2.val.vmax=l2zm(0L);
+	      am->basereg=r;
+	      am->dist=0;
+	      am->skal=-1;
+	      am->dreg=0;
+	      p2->code=NOP;
+	      p2->q1.flags=p2->q2.flags=p2->z.flags=0;
+	      break;
+	    }
+	  }
+	  if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
+	  if((p2->q1.flags&REG)&&p2->q1.reg==r) break;
+	  if((p2->q2.flags&REG)&&p2->q2.reg==r) break;
+	  if((p2->z.flags&REG)&&p2->z.reg==r) break;
+	  if(p2->q1.am&&p2->q1.am->basereg==r) break;
+	  if(p2->q2.am&&p2->q2.am->basereg==r) break;
+	  if(p2->z.am&&p2->z.am->basereg==r) break;
+	}
+      }
+    }
+    /* (ax)+ in z */
+    if(!p->z.am&&(p->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p->z.reg<=8){
+      t=(ztyp(p)&NQ);
+      sz=zm2l(sizetab[t]);
+      r=p->z.reg;
+      if((sz==1||sz==2||sz==4||sz==8)&&(ISINT(t)||ISPOINTER(t))&&t!=LLONG&&(!(p->q1.flags&REG)||p->q1.reg!=r)&&(!(p->q2.flags&REG)||p->q2.reg!=r)&&(!p->q2.am||p->q2.am->basereg!=r)&&(!p->q1.am||p->q1.am->basereg!=r)){
+	for(p2=p->next;p2;p2=p2->next){
+	  c2=p2->code;
+	  if(c2==ADDI2P&&(p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r&&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg==r&&(p2->q2.flags&(KONST|DREFOBJ))==KONST&&!islibcall(p)){
+	    eval_const(&p2->q2.val,q2typ(p2));
+	    if(zmeqto(vmax,l2zm(sz))){
+	      p->z.am=am=mymalloc(sizeof(*am));
+	      p->z.val.vmax=l2zm(0L);
+	      am->basereg=r;
+	      am->dist=0;
+	      am->skal=-1;
+	      am->dreg=0;
+	      p2->code=NOP;
+	      p2->q1.flags=p2->q2.flags=p2->z.flags=0;
+	      break;
+	    }
+	  }
+	  if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
+	  if((p2->q1.flags&REG)&&p2->q1.reg==r) break;
+	  if((p2->q2.flags&REG)&&p2->q2.reg==r) break;
+	  if((p2->z.flags&REG)&&p2->z.reg==r) break;
+	  if(p2->q1.am&&p2->q1.am->basereg==r) break;
+	  if(p2->q2.am&&p2->q2.am->basereg==r) break;
+	  if(p2->z.am&&p2->z.am->basereg==r) break;
+	}
+      }
+    }
+    /* d(ax) (+d(ax,dy)) */
+    if((c==ADDI2P||c==SUBIFP)&&isreg(z)&&p->z.reg<=8&&(p->q2.flags&(KONST|DREFOBJ))==KONST){
+      int base,idx=-1;zmax of;obj *o;
+      IC *idx_ic=0,*free_idx=0,*free_base=0,*use=0;
+      eval_const(&p->q2.val,p->typf);
+      if(c==SUBIFP) of=zmsub(l2zm(0L),vmax); else of=vmax;
+      if(CPU>=68020||(zmleq(l2zm(-32768L),vmax)&&zmleq(vmax,l2zm(32767L)))){
+	r=p->z.reg;
+	if(isreg(q1)&&p->q1.reg<=8) base=p->q1.reg; else base=r;
+	o=0;
+	for(p2=p->next;p2;p2=p2->next){
+	  c2=p2->code;
+	  if(!idx_ic&&c2==ADDI2P&&(p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r&&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg==r&&(p2->q2.flags&(REG|DREFOBJ))==REG&&p2->q2.reg>=d0&&p2->q2.reg<fp0){
+	    if(CPU>=68020||(zmleq(of,l2zm(127L))&&zmleq(l2zm(-128L),of))){
+	      idx=p2->q2.reg;
+	      idx_ic=p2;
+	      continue;
+	    }
+	  }
+	  if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
+	  if(!use&&idx_ic&&c2==FREEREG&&p2->q1.reg==idx){
+	    free_idx=p2;
+	    continue;
+	  }
+	  if(!use&&c2==FREEREG&&p2->q1.reg==base){
+	    free_base=p2;
+	    continue;
+	  }
+	  if(idx_ic){
+	    if((p2->q1.flags&REG)&&p2->q1.reg==idx) break;
+	    if((p2->q2.flags&REG)&&p2->q2.reg==idx) break;
+	    if((p2->z.flags&REG)&&p2->z.reg==idx) break;
+	    if(p2->q1.am&&(p2->q1.am->dreg&127)==idx) break;
+	    if(p2->q2.am&&(p2->q2.am->dreg&127)==idx) break;
+	    if(p2->z.am&&(p2->z.am->dreg&127)==idx) break;
+	    if(c2==ALLOCREG&&p2->q1.reg==idx) break;
+	  }
+
+	  if(!p2->q1.am&&(p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r&&c2==PUSH){
+	    if(o) break;
+	    o=&p2->q1;
+	    use=p2;
+	    continue;
+	  }
+
+	  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) break;
+	      o=&p2->q1;
+	      use=p2;
+	    }
+	    if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
+	      if(o) break;
+	      o=&p2->q2;
+	      use=p2;
+	    }
+	    if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
+
+	      if(o) break;
+	      if(p2->z.flags&&(idx==d0||idx==d1)&&FPU<=68000&&ISFLOAT(ztyp(p2))&&!(p2->q2.flags==0&&c2!=CONVERT)) break;
+	      o=&p2->z;
+	      use=p2;
+	    }
+	  }
+	  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));
+		o->val.vmax=l2zm(0L);
+		am->basereg=base;
+		am->dist=zm2l(of);
+		am->skal=0;
+		if(free_base) move_IC(use,free_base);
+		if(idx_ic){
+		  am->dreg=idx;
+		  if(ISHWORD(idx_ic->typf)) am->dreg|=128;
+		  if(free_idx) move_IC(use,free_idx);
+		  idx_ic->code=NOP;
+		  idx_ic->q1.flags=idx_ic->q2.flags=idx_ic->z.flags=0;
+		}else
+		  am->dreg=0;
+		if(isreg(q1)&&p->q1.reg<=8){
+		  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];
+		}
+		if(!(o->flags&DREFOBJ)){
+		  o->flags|=DREFOBJ;
+		  if(use->code==PUSH)
+		    use->code=PEA;
+		  else if(use->code==ASSIGN)
+		    use->code=LEA;
+		  else
+		    ierror(0);
+		}
+	      }
+	      break;
+	    }
+	    if(c2!=FREEREG&&m==base) break;
+	    continue;
+	  }
+        }
+      }
+    }
+    /* (ax,dy) (+d(ax,dy)) */
+    if(c==ADDI2P&&isreg(q2)&&p->q2.reg>=d0&&isreg(z)&&p->z.reg<=8&&(isreg(q1)||p->q2.reg!=p->z.reg)){
+      int base,idx;obj *o;
+      long dist=0;
+      IC *free_idx=0,*free_base=0,*use=0,*off=0;
+      r=p->z.reg;idx=p->q2.reg;
+      if(isreg(q1)&&p->q1.reg<=8) base=p->q1.reg; else base=r;
+      o=0;
+      for(p2=p->next;p2;p2=p2->next){
+        c2=p2->code;
+	if(!off&&(c2==ADDI2P||c2==SUBIFP)&&(p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r&&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg==r&&(p2->q2.flags&(KONST|DREFOBJ))==KONST){
+	  eval_const(&p2->q2.val,p2->typf);
+	  if(c2==SUBIFP) vmax=zmsub(l2zm(0L),vmax);
+	  if(CPU>=68020||(zmleq(vmax,l2zm(127L))&&zmleq(l2zm(-128L),vmax))){
+	    dist=zm2l(vmax);
+	    off=p2;
+	    continue;
+	  }
+	}
+	
+        if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
+
+
+
+	if(!p2->q1.am&&(p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r&&c2==PUSH){
+	  if(o) break;
+
+	  o=&p2->q1;
+	  use=p2;
+	  continue;
+	}
+
+        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==ALLOCREG&&(p->q1.reg==idx||p->q1.reg==base)) break;
+	if(!use&&c2==FREEREG&&p2->q1.reg==base) free_base=p2;
+	if(!use&&c2==FREEREG&&p2->q1.reg==idx) free_idx=p2;
+
+
+        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||(q1typ(p2)&NQ)==LLONG) break;
+            o=&p2->q1;use=p2;
+          }
+          if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
+            if(o||(q2typ(p2)&NQ)==LLONG) break;
+            o=&p2->q2;use=p2;
+          }
+          if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
+            if(o||(ztyp(p2)&NQ)==LLONG) break;
+	    if(p2->z.flags&&(idx==d0||idx==d1)&&FPU<=68000&&ISFLOAT(ztyp(p2))&&!(p2->q2.flags==0&&c2!=CONVERT)) break;
+
+            o=&p2->z;use=p2;
+          }
+        }
+        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){
+	    /* do not use addressing mode for libcalls */
+	    if(FPU<=68000&&o&&o==&use->z&&(ISFLOAT(use->typf)||ISFLOAT(use->typf2))&&use->code!=ASSIGN)
+	      break;
+            if(o){
+              o->am=am=mymalloc(sizeof(*am));
+	      o->val.vmax=l2zm(0L);
+              am->basereg=base;
+              am->dreg=idx;
+	      am->dist=dist;
+	      am->skal=0;
+	      if(ISHWORD(q2typ(p))) am->dreg|=128;
+	      if(isreg(q1)&&p->q1.reg<=8){
+		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];
+	      }
+	      if(off){
+		off->code=NOP;
+		off->q1.flags=off->q2.flags=off->z.flags=0;
+	      }
+	      if(!use) ierror(0);
+	      if(free_idx) move_IC(use,free_idx);
+	      if(free_base) move_IC(use,free_base);
+	      if(free_idx&&use->next!=free_idx&&use->next->next!=free_idx) ierror(0);
+	      if(free_base&&use->next!=free_base&&use->next->next!=free_base) ierror(0);
+	      if(!(o->flags&DREFOBJ)){
+		o->flags|=DREFOBJ;
+		if(use->code==PUSH)
+		  use->code=PEA;
+		else if(use->code==ASSIGN)
+		  use->code=LEA;
+		else
+		  ierror(0);
+	      }		   
+	    }
+
+            break;
+          }
+          if(c2!=FREEREG&&m==base) break;
+          continue;
+        }
+      }
+    }
+    
+
+  }
+
+  /* do an additional pass to search for scaled addressing-modes */
+  if(CPU>=68020){
+    for(p=first;p;p=p->next){
+      c=p->code;t=p->typf;
+      if((c==MULT||c==LSHIFT)&&isconst(q2)&&isreg(z)&&p->z.reg>=d0&&p->z.reg<=d7&&ISINT(t)&&(t&NQ)<=LONG){
+	unsigned long ul;
+	r=p->z.reg;
+	eval_const(&p->q2.val,q2typ(p));
+	ul=zum2ul(vumax);
+	if(c==LSHIFT){
+	  if(ul<=3)
+	    ul=1<<ul;
+	  else
+	    ul=0;
+	}
+	if(ul==2||ul==4||ul==8){
+	  AddressingMode *amuse=0;
+	  IC *free_src=0,*free_rsrc=0,*use=0;
+	  int src_mod=0;
+	  for(p2=p->next;p2;p2=p2->next){
+	    c2=p2->code;
+	    if(!use&&p2->q1.am&&p2->q1.am->skal==0&&(p2->q1.am->dreg&127)==r&&(!p2->q2.am||(p2->q2.am->dreg&127)!=r)&&(!p2->z.am||(p2->z.am->dreg&127)!=r)&&(!(p2->q2.flags&REG)||p2->q2.flags!=r)&&(!(p2->z.flags&REG)||p2->z.flags!=r)){
+	      amuse=p2->q1.am;
+	      use=p2;
+	      continue;
+	    }
+	    if(!use&&p2->q2.am&&p2->q2.am->skal==0&&(p2->q2.am->dreg&127)==r&&(!p2->q1.am||(p2->q1.am->dreg&127)!=r)&&(!p2->z.am||(p2->z.am->dreg&127)!=r)&&(!(p2->q1.flags&REG)||p2->q1.flags!=r)&&(!(p2->z.flags&REG)||p2->z.flags!=r)){
+	      amuse=p2->q2.am;
+	      use=p2;
+	      continue;
+	    }
+	    if(!use&&p2->z.am&&p2->z.am->skal==0&&(p2->z.am->dreg&127)==r&&(!p2->q2.am||(p2->q2.am->dreg&127)!=r)&&(!p2->q1.am||(p2->q1.am->dreg&127)!=r)&&(!(p2->q2.flags&REG)||p2->q2.flags!=r)&&(!(p2->z.flags&REG)||p2->z.flags!=r)){
+	      amuse=p2->z.am;
+	      use=p2;
+	      continue;
+	    }
+	    if(!use&&c2==FREEREG&&p2->q1.reg==r){
+	      free_src=p2;
+	      continue;
+	    }
+	    if(!use&&c2==FREEREG&&isreg(q1)&&p->q1.reg>=d0&&p->q1.reg<=d7&&p2->q1.reg==p->q1.reg){
+	      free_rsrc=p2;
+	      continue;
+	    }
+	    if(use&&((c2==FREEREG&&p2->q1.reg==r)||((p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg==r))){
+	      amuse->skal=ul;
+	      if(!src_mod&&isreg(q1)&&p->q1.reg>=d0&&p->q1.reg<=d7){
+		amuse->dreg=p->q1.reg;
+		p->code=NOP;
+		p->q1.flags=p->q2.flags=p->z.flags=0;
+	      }else{
+		p->code=ASSIGN;
+		p->q2.flags=0;
+		p->q2.val.vmax=sizetab[p->typf&NQ];
+	      }
+	      if(free_src) move_IC(use,free_src);
+	      if(free_rsrc) move_IC(use,free_rsrc);
+	      break;
+	    }
+	    if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
+	    if((p2->q1.flags&REG)&&p2->q1.reg==r) break;
+	    if((p2->q2.flags&REG)&&p2->q2.reg==r) break;
+	    if((p2->z.flags&REG)&&p2->z.reg==r) break;
+	    if(p2->q1.am&&(p2->q1.am->dreg&127)==r) break;
+	    if(p2->q2.am&&(p2->q2.am->dreg&127)==r) break;
+	    if(p2->z.am&&(p2->z.am->dreg&127)==r) break;
+	    if((p2->z.flags&(REG|DREFOBJ))==REG&&(p->q1.flags&(REG|DREFOBJ))&&p2->z.reg==p->q1.reg)
+	      src_mod=1;
+	  }
+	}
+      }
+    }	    
+  }
+
+  /* another pass to remove unnecessary ALLOCREGs */
+  for(p=first;p;p=p->next){
+    if(p->code==ALLOCREG){
+      r=p->q1.reg;
+      for(p2=p->next;p2;p2=p2->next){
+	c2=p2->code;
+	if(c2==ALLOCREG&&p2->q1.reg==r) ierror(0);
+	if(c2==FREEREG&&p2->q1.reg==r){
+	  p->code=NOP;
+	  p->q1.flags=0;
+	  p2->code=NOP;
+	  p2->q1.flags=0;
+	  savedalloc++;
+	  break;
+	}
+	if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
+	if((p2->q1.flags&REG)&&p2->q1.reg==r) break;
+	if((p2->q2.flags&REG)&&p2->q2.reg==r) break;
+	if((p2->z.flags&REG)&&p2->z.reg==r) break;
+	if((am=p2->q1.am)&&(am->basereg==r||(am->dreg&127)==r)) break;
+	if((am=p2->q2.am)&&(am->basereg==r||(am->dreg&127)==r)) break;
+	if((am=p2->z.am)&&(am->basereg==r||(am->dreg&127)==r)) break;
+      }
+    }
+  }
+
+  return localused;
+}
+static int addressing(IC *p)
+/*  Untersucht ICs auf erweiterte Addresierungsarten    */
+{
+    int count,localused=0;
+    if(!OLDPEEPHOLE) return new_peephole(p);
+    if(DEBUG&32) printf("addressing() started\n");
+    for(count=1;count<=16;count++) clear_am(count);
+    for(count=0;p;p=p->next){
+        int c=p->code,q1reg,q2reg,zreg;
+        if(p->q1.flags&REG) q1reg=p->q1.reg; else q1reg=0;
+        if(p->q2.flags&REG) q2reg=p->q2.reg; else q2reg=0;
+        if(p->z.flags&REG) zreg=p->z.reg; else zreg=0;
+        if(c==ADDI2P) c=ADD;
+        if(c==SUBIFP) c=SUB;
+        if(DEBUG&32) pric2(stdout,p);
+        if(!localused){
+            if((p->q1.flags&(VAR|REG))==VAR&&(p->q1.v->storage_class==AUTO||p->q1.v->storage_class==REGISTER)&&zmleq(l2zm(0L),p->q1.v->offset))
+                localused=1;
+            if((p->q2.flags&(VAR|REG))==VAR&&(p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER)&&zmleq(l2zm(0L),p->q2.v->offset))
+                localused=1;
+            if((p->z.flags&(VAR|REG))==VAR&&(p->z.v->storage_class==AUTO||p->z.v->storage_class==REGISTER)&&zmleq(l2zm(0L),p->z.v->offset))
+                localused=1;
+            if(DEBUG&32&&localused==1) printf("localused=1\n");
+        }
+        if(c==ASSIGN&&isreg(q1)&&isreg(z)&&q1reg>=1&&q1reg<=8&&zreg>=1&&zreg<=8){
+        /*  fuer (ax)+  */
+            int i;
+            clear_am(q1reg);
+            for(i=1;i<=8;i++)
+                if(am_base[i]==zreg||am_base[i]==q1reg) clear_am(i);
+	    mod_reg(zreg);
+            clear_am(zreg);am_base[zreg]=q1reg;am_dreg_ic[zreg]=p;
+            if(DEBUG&32) printf("move %s,%s found\n",mregnames[q1reg],mregnames[zreg]);
+            continue;
+        }
+        if(c==MULT&&CPU>=68020&&isconst(q2)&&isreg(z)&&zreg>=d0&&zreg<=d7){
+        /*  dx=a*const, fuer Skalierung    */
+            int dreg=zreg-8;
+            if(dreg<1||dreg>8) ierror(0);
+            if(q1reg>=1&&q1reg<=d7){
+                if(isreg(q1)&&(q1reg>8||am_use[q1reg]!=p)) clear_am(q1reg);
+                if((p->q1.flags&DREFOBJ)&&q1reg<=8&&am_use[q1reg]) clear_am(q1reg);
+            }
+            if(DEBUG&32) printf("mult x,const->dreg found\n");
+	    mod_reg(zreg);
+            if(am_skal[dreg]) {clear_am(zreg);continue;}
+            eval_const(&p->q2.val,p->typf);
+            am_skal[dreg]=zm2l(vmax);
+            if(am_skal[dreg]!=2&&am_skal[dreg]!=4&&am_skal[dreg]!=8)
+                {clear_am(zreg);continue;}
+            am_shiftdreg[dreg]=p;
+            if(isreg(q1)&&q1reg>=d0&&q1reg<=d7) am_dbase[dreg]=q1reg; else am_dbase[dreg]=zreg;
+	    if((p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)) clear_am(p->q1.reg);
+            if(DEBUG&32) printf("is usable\n");
+            continue;
+        }
+        if((c==ADD||c==SUB)&&isconst(q2)&&zreg>=1&&zreg<=8&&isreg(z)){
+        /*  add ax,#const,ax->az Test auf d8/16 fehlt noch (nicht mehr) */
+            long l;
+            if(zreg<1||zreg>8) ierror(0);
+            eval_const(&p->q2.val,p->typf);
+            l=zm2l(vmax);
+            if(c==SUB) l=-l;
+	    mod_reg(zreg);
+            if(q1reg==zreg&&isreg(q1)&&am_use[zreg]&&(l==1||l==2||l==4)){
+                if(l==mopsize(am_use[zreg],zreg)&&(am_use[zreg]->code!=CONVERT||zmleq(sizetab[am_use[zreg]->typf2&NQ],sizetab[am_use[zreg]->typf&NQ]))){
+                    IC *op=am_use[zreg];
+                    obj *o=0;
+                    if(DEBUG&32){ printf("found postincrement:\n");pric2(stdout,op);pric2(stdout,p);}
+                    if((op->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&op->q1.reg==zreg){
+                        if(DEBUG&32) printf("q1\n");
+                        o=&op->q1;
+                    }
+                    if((op->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&op->q2.reg==zreg){
+                        if(DEBUG&32) printf("q2\n");
+                        if(o) continue; else o=&op->q2;
+                    }
+                    if((op->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&op->z.reg==zreg){
+                        if(DEBUG&32) printf("z\n");
+                        if(o) continue; else o=&op->z;
+                    }
+                    o->am=mymalloc(AMS);
+                    o->am->basereg=zreg;
+                    o->am->skal=-1;
+                    o->am->dist=0;
+                    o->am->dreg=0;
+                    p=p->prev;
+                    remove_IC(p->next);
+                    clear_am(zreg);continue;
+                }
+            }
+            clear_am(q1reg);
+            if(am_dist[zreg]||am_inc[zreg]||am_use[zreg]) {clear_am(zreg);continue;} /* nur ein Offset */
+            if(isreg(q1)&&q1reg==zreg&&(l==1||l==2||l==4)){
+            /*  ax+=const, fuer (ax)+   */
+                int i,f;
+                for(f=0,i=1;i<=8;i++){
+                    if(am_base[i]==zreg&&!am_dreg[i]&&!am_dist[i]){
+                        if(f) ierror(0);
+                        am_inc[i]=l;am_dist_ic[i]=p;f=i;
+                        if(DEBUG&32) printf("inc %s found\n",mregnames[i]);
+                    }
+                }
+                if(f) continue;
+            }
+            am_dist[zreg]=l;
+            if(DEBUG&32) printf("dist=%ld\n",am_dist[zreg]);
+            if(CPU<68020){
+            /*  bei <68020 darf der Offset nur 16bit oder 8bit bei dreg sein */
+                if((am_dreg[zreg]&&(am_dist[zreg]<-128||am_dist[zreg]>127))||am_dist[zreg]<-32768||am_dist[zreg]>32767)
+                    {clear_am(zreg);continue;}
+            }
+            am_dist_ic[zreg]=p;
+            if(am_base[zreg]){
+                if(q1reg!=zreg||!isreg(q1)) {clear_am(zreg);continue;}
+            }else{
+                if(q1reg>=1&&q1reg<=8&&isreg(q1)) am_base[zreg]=q1reg; else am_base[zreg]=zreg;
+                if(DEBUG&32) printf("%s potential base for %s\n",mregnames[am_base[zreg]],mregnames[zreg]);
+            }
+            if(DEBUG&32) printf("add #const,%s found\n",mregnames[zreg]);
+            continue;
+        }
+        if(c==ADD&&q2reg>=d0&&q2reg<=d7&&isreg(q2)&&zreg>=1&&zreg<=8&&isreg(z)&&(p->q1.flags&(REG|DREFOBJ))!=(REG|DREFOBJ)){
+        /*  add ax,dy->az   */
+            int i;
+            if(zreg<1||zreg>8) ierror(0);
+            for(i=1;i<=8;i++)
+                if(am_dreg[i]==q2reg){ clear_am(q2reg);clear_am(i);}
+            clear_am(q1reg);
+	    mod_reg(zreg);
+            if(am_dreg[zreg]||am_inc[zreg]||am_use[zreg]) {clear_am(zreg);continue;} /* nur ein Regoffset */
+            if(CPU<68020&&(am_dist[zreg]<-128||am_dist[zreg]>127))
+                {clear_am(zreg);continue;} /* bei <68020 nur 8bit Offset */
+            am_dreg[zreg]=q2reg;
+            if(ISHWORD(p->typf)) am_dreg[zreg]|=128; /* dx.w statt dx.l */
+            am_dreg_ic[zreg]=p;
+            if(am_base[zreg]){
+                if(q1reg!=zreg||!isreg(q1)) {clear_am(zreg);continue;}
+            }else{
+                if(q1reg>=1&&q1reg<=8&&isreg(q1)) am_base[zreg]=q1reg; else am_base[zreg]=zreg;
+            }
+            if(DEBUG&32) printf("add %s,%s found\n",mregnames[q2reg],mregnames[zreg]);
+            continue;
+        }
+        if(c==FREEREG){
+        /*  wir koennen den Modus tatsaechlich benutzen */
+            AddressingMode *am;IC *p1,*p2;int dreg,i;
+            if(DEBUG&32) printf("freereg %s found\n",mregnames[p->q1.reg]);
+            if(q1reg>=d0&&q1reg<=d7) {am_freedreg[q1reg-8]=p;if(DEBUG&32) printf("freedreg[%d]=%lx\n",q1reg-8,(long)p);}
+            if(q1reg>8) continue;
+            if(DEBUG&32) printf("use=%p,base=%p,dist=%p,dreg=%p\n",(void*)am_use[q1reg],(void*)am_base[q1reg],(void*)am_dist[q1reg],(void*)am_dreg[q1reg]);
+            for(i=1;i<=8;i++) if(am_base[i]==q1reg) clear_am(i);
+            if(!am_use[q1reg]||!am_base[q1reg]) continue;
+            if(am_inc[q1reg]&&am_inc[q1reg]!=mopsize(am_use[q1reg],q1reg))
+                {clear_am(q1reg);continue;}
+            if(!am_dist[q1reg]&&!am_dreg[q1reg]&&!am_inc[q1reg]) continue;
+            p1=am_dist_ic[q1reg];p2=am_dreg_ic[q1reg];
+            if(DEBUG&32){
+                printf("could really use %s\n",mregnames[q1reg]);
+                if(p1) pric2(stdout,p1);
+                if(p2) pric2(stdout,p2);
+            }
+            if(am_base[q1reg]==q1reg){
+                if(p1) {p1->q2.flags=0;p1->code=ASSIGN;p1->q2.val.vmax=l2zm(4L);p1->typf=POINTER;}
+                if(p2) {p2->q2.flags=0;p2->code=ASSIGN;p2->q2.val.vmax=l2zm(4L);p2->typf=POINTER;}
+            }else{
+                if(p1) remove_IC(p1);
+                if(p2) remove_IC(p2);
+            }
+            dreg=(am_dreg[q1reg]&127)-8;
+            am=mymalloc(AMS);
+            am->skal=0;
+            am->basereg=am_base[q1reg];
+            am->dist=am_dist[q1reg];
+            am->dreg=am_dreg[q1reg];
+            if(am_inc[q1reg]) am->skal=-1;
+            if(dreg>0){
+                /*  bei (d,ax,dy) das freereg dy nach hinten verschieben    */
+                if(dreg<1||dreg>8) ierror(0);
+                if(p1=am_freedreg[dreg]){
+                    if(DEBUG&32){
+                        printf("freereg %s moved from %p to %p\n",mregnames[dreg+8],(void*)p1,(void*)p);
+                        pric2(stdout,p1);
+                    }
+                    if(p1->code!=FREEREG){ierror(0);printf("freereg[%d]=%p\n",dreg,(void*)p1);continue;}
+                    if(!p1->next) {ierror(0);continue;}
+                    if(!p1->prev) {ierror(0);continue;}
+                    p1->prev->next=p1->next;
+                    p1->next->prev=p1->prev;
+                    p1->next=p->next;
+                    p1->prev=p;
+                    if(p->next) p->next->prev=p1;
+                    p->next=p1;
+                }
+                if(am_skal[dreg]){
+                /*  Skalierung bearbeiten   */
+                    if(p1){
+                        am->skal=am_skal[dreg];
+                        am->dreg=am_dbase[dreg];
+                        p1=am_shiftdreg[dreg];
+                        if(DEBUG&32) pric2(stdout,p1);
+                        if(am_dbase[dreg]==dreg+8){
+                            p1->code=ASSIGN;p1->q2.flags=0;p1->q2.val.vmax=sizetab[p1->typf&NQ];
+                        }else remove_IC(p1);
+                    }
+                    clear_am(dreg+8);
+                }
+            }
+            /*  das hier duerfte unnoetig sein, da die Adressierungsart in  */
+            /*  einem IC eigentlich hoechstens einmal vorkommen darf        */
+            if(q1reg<0||q1reg>8) ierror(0);
+            p1=am_use[q1reg];
+            if(DEBUG&32) pric2(stdout,p1);
+            if(p1->code==PUSH&&p1->q1.reg==q1reg&&((p1->q1.flags&(DREFOBJ|REG))==(REG))){
+                p1->q1.am=mymalloc(AMS);
+                memcpy(p1->q1.am,am,AMS);
+                p->q1.val.vmax=l2zm(0L);
+                p1->code=PEA;
+                if(DEBUG&32) printf("q1 patched\n");
+            }
+            if(p1->q1.reg==q1reg&&((p1->q1.flags&(DREFOBJ|REG))==(DREFOBJ|REG))){
+                p1->q1.am=mymalloc(AMS);
+                memcpy(p1->q1.am,am,AMS);
+                p1->q1.val.vmax=l2zm(0L);
+                if(DEBUG&32) printf("q1 patched\n");
+            }
+            if(p1->q2.reg==q1reg&&((p1->q2.flags&(DREFOBJ|REG))==(DREFOBJ|REG))){
+                p1->q2.am=mymalloc(AMS);
+                memcpy(p1->q2.am,am,AMS);
+                p1->q2.val.vmax=l2zm(0L);
+                if(DEBUG&32) printf("q2 patched\n");
+            }
+            if(p1->z.reg==q1reg&&((p1->z.flags&(DREFOBJ|REG))==(DREFOBJ|REG))){
+                p1->z.am=mymalloc(AMS);
+                memcpy(p1->z.am,am,AMS);
+                p1->z.val.vmax=l2zm(0L);
+                if(DEBUG&32) printf("z patched\n");
+            }
+            free(am);count++;
+            clear_am(q1reg);
+            continue;
+        }
+        if(c>=LABEL&&c<=BRA){
+            int i;      /*  ueber basic blocks hinweg unsicher  */
+            for(i=1;i<=16;i++) clear_am(i);
+            continue;
+        }
+        /*  Wenn Libraryaufrufe noetig sind (floating point ohne FPU oder   */
+        /*  32bit mul/div/mod ohne 020+) keine Addressierungsarten nutzen   */
+        if(FPU<=68000&&(ISFLOAT(p->typf)||(p->code==CONVERT&&ISFLOAT(p->typf2)))){
+            int i;
+            for(i=1;i<=16;i++) clear_am(i);
+            continue;
+        }
+        if(CPU<68020&&(c==DIV||c==MOD)){
+            int i;
+            for(i=1;i<=16;i++) clear_am(i);
+            continue;
+        }
+        if(c==PUSH&&((p->q1.flags&(DREFOBJ|REG))==REG&&q1reg<=8&&!am_use[q1reg]&&(am_inc[q1reg]||am_dist[q1reg]||am_dreg[q1reg]))){
+            if(q1reg<1||q1reg>8) ierror(0);
+            if(am_inc[q1reg]&&am_inc[q1reg]!=msizetab[p->typf&NQ]) clear_am(q1reg); else am_use[q1reg]=p;
+            if(DEBUG&32) printf("use of %s found\n",mregnames[q1reg]);
+            continue;
+        }
+        if(((p->q1.flags&(DREFOBJ|REG))==(DREFOBJ|REG)&&q1reg<=8)){
+            if(q1reg<1||q1reg>8) ierror(0);
+            if(am_use[q1reg]&&(am_use[q1reg]!=p||am_inc[q1reg])) clear_am(q1reg); else am_use[q1reg]=p;
+            if(am_inc[q1reg]&&am_inc[q1reg]!=sizetab[p->typf&NQ]) clear_am(q1reg);
+            if(DEBUG&32) printf("use of %s found\n",mregnames[q1reg]);
+        }
+        if(((p->q2.flags&(DREFOBJ|REG))==(DREFOBJ|REG)&&q2reg<=8)){
+            if(q2reg<1||q2reg>8) ierror(0);
+            if(am_use[q2reg]&&(am_use[q2reg]!=p||am_inc[q2reg])) clear_am(q2reg); else am_use[q2reg]=p;
+            if(am_inc[q2reg]&&am_inc[q2reg]!=sizetab[p->typf&NQ]) clear_am(q2reg);
+            if(DEBUG&32) printf("use of %s found\n",mregnames[q2reg]);
+        }
+        if(((p->z.flags&(DREFOBJ|REG))==(DREFOBJ|REG)&&zreg<=8)){
+            if(zreg<1||zreg>8) ierror(0);
+            if(am_use[zreg]&&(am_use[zreg]!=p||am_inc[zreg])) clear_am(zreg); else am_use[zreg]=p;
+            if(am_inc[zreg]&&am_inc[zreg]!=sizetab[p->typf&NQ]) clear_am(zreg);
+            if(DEBUG&32) printf("use of %s found\n",mregnames[zreg]);
+        }
+        if(c==ALLOCREG){
+        /*  allocreg zaehlt als zerstoerung von reg */
+            p->z.flags=REG;
+            p->z.reg=zreg=q1reg=p->q1.reg;
+        }
+        if(q1reg>=1&&q1reg<=d7&&isreg(q1)&&(q1reg>8||am_use[q1reg]!=p)) clear_am(q1reg);
+        if(q2reg>=1&&q2reg<=d7&&isreg(q2)&&(q2reg>8||am_use[q2reg]!=p)) clear_am(q2reg);
+        if(zreg>=1&&zreg<=d7&&isreg(z)) clear_am(zreg);
+        if(isreg(z)&&zreg<=d7){
+        /*  schauen, ob eines der Register ueberschrieben wird  */
+        /*  wohl noch sehr langsam                              */
+	  mod_reg(zreg);
+        }
+        if(c==ALLOCREG) p->z.flags=0;
+    }
+    if(DEBUG&1) printf("%d addressingmodes used, localused=%d\n",count,localused);
+    return localused;
+}
+static int alignment(obj *o)
+/*  versucht rauszufinden, wie ein Objekt alignet ist   */
+{
+    /*  wenn es keine Variable ist, kann man nichts aussagen    */
+    long os;
+    if(o->am||!(o->flags&VAR)) return -1;
+    if((o->flags&DREFOBJ)){
+      if(!(o->v->flags&NOTTYPESAFE)||!ISPOINTER(o->v->vtyp->flags)||zmeqto(falign(o->v->vtyp->next),l2zm(1L)))
+	return -1;
+      else
+	return 0;
+    }
+    if(!o->v) ierror(0);
+    os=zm2l(o->val.vmax);
+    if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER){
+        if(!USEFRAMEPOINTER&&!vlas){
+            if(!zmleq(l2zm(0L),o->v->offset)) os=os+loff-zm2l(o->v->offset);
+             else              os=os+zm2l(o->v->offset);
+        }else{
+            if(!zmleq(l2zm(0L),o->v->offset)) os=os-zm2l(o->v->offset);
+             else              os=os-(zm2l(o->v->offset)+zm2l(szof(o->v->vtyp)));
+        }
+    }else{
+      if(!(o->v->flags&(TENTATIVE|DEFINED))&&zmeqto(falign(o->v->vtyp),l2zm(1L)))
+	return -1;
+    }
+    
+    return os&3;
+}
+static void stored0d1(FILE *f,obj *o,int t)
+{
+  if((o->flags&(REG|DREFOBJ))==REG){
+    if(!reg_pair(o->reg,&rp)) ierror(0);
+    if(o->reg==25) return;
+    emit(f,"\tmove.l\t%s,%s\n",mregnames[d0],mregnames[rp.r1]);
+    emit(f,"\tmove.l\t%s,%s\n",mregnames[10],mregnames[rp.r2]);
+  }else{
+    if(cf&&(o->flags&(REG|DREFOBJ))!=(REG|DREFOBJ)){
+      emit(f,"\tmove.l\t%s,",mregnames[d0]);
+      emit_obj(f,o,t);
+      emit(f,"\n");
+      emit(f,"\tmove.l\t%s,",mregnames[d1]);
+      o->val.vmax=zmadd(o->val.vmax,l2zm(4L));
+      emit_obj(f,o,t);
+      o->val.vmax=zmsub(o->val.vmax,l2zm(4L));
+      emit(f,"\n");
+    }else{
+      emit(f,"\tmovem.l\t%s,",mregnames[d0d1]);
+      emit_obj(f,o,t);
+      emit(f,"\n");
+    }
+  }
+}
+static void loadd0d1(FILE *f,obj *o,int t)
+{
+  if((o->flags&(REG|DREFOBJ))==REG){
+    if(!reg_pair(o->reg,&rp)) 
+      ierror(0);
+    if(o->reg==25) return;
+    emit(f,"\tmove.l\t%s,%s\n",mregnames[rp.r1],mregnames[d0]);
+    emit(f,"\tmove.l\t%s,%s\n",mregnames[rp.r2],mregnames[10]);
+  }else{
+    if(cf){
+      emit(f,"\tmove.l\t");
+      emit_obj(f,o,t);
+      emit(f,",%s\n",mregnames[d0]);
+      emit(f,"\tmove.l\t");
+      o->val.vmax=zmadd(o->val.vmax,l2zm(4L));
+      emit_obj(f,o,t);
+      o->val.vmax=zmsub(o->val.vmax,l2zm(4L));
+      emit(f,",%s\n",mregnames[d1]);
+    }else{
+      emit(f,"\tmovem.l\t");
+      emit_obj(f,o,t);
+      emit(f,",%s\n",mregnames[d0d1]);
+    }
+  }
+}
+static void assign(FILE *f,IC *p,obj *q,obj *z,int c,long size,int t)
+/*  Generiert Code fuer Zuweisungen und PUSH.   */
+{
+    /*  auch noch sehr fpu-spezifisch   */
+  if(FPU<=68000&&((t&NQ)==DOUBLE||(t&NQ)==LDOUBLE)&&!((q->flags&(KONST|DREFOBJ))==KONST))
+    t=LLONG;
+  if(ISFLOAT(t)){
+    if(q&&(q->flags&(KONST|DREFOBJ))==KONST){
+      if(z&&(z->flags&(DREFOBJ|REG))==REG&&z->reg>=fp0&&z->reg<=fp7){
+	/*  FP-Konstante->Register (muss immer reinpassen)  */
+	if(z->reg>=fp0) emit(f,"\tfmove"); else emit(f,"\tmove");
+	emit(f,".%c\t",x_t[t&NQ]);emit_obj(f,q,t);
+	emit(f,",%s\n",mregnames[z->reg]);
+      }else{
+	/*  FP-Konstante->Speicher (evtl. auf zweimal)  */
+	int m,r;unsigned char *ip=(unsigned char *)&q->val.vfloat; /* nicht sehr schoen  */
+	char *s;
+	if(cf&&c==ASSIGN) r=get_reg(f,1,p,0);
+	if(GAS) s="0x"; else s="$";
+	if(c==PUSH&&(t&NQ)!=FLOAT){
+	  emit(f,"\tmove.l\t#%s%02x%02x%02x%02x,-(%s)\n",s,ip[4],ip[5],ip[6],ip[7],mregnames[sp]);
+	  push(4);
+	}
+	emit(f,"\tmove.l\t#%s%02x%02x%02x%02x,",s,ip[0],ip[1],ip[2],ip[3]);
+	if(c==ASSIGN){
+	  if(cf)
+	    emit(f,"%s\n\tmove.l\t%s,",mregnames[r],mregnames[r]);
+	  if(isreg(z)&&reg_pair(p->z.reg,&rp))
+	    emit(f,"%s",mregnames[rp.r1]);
+	  else
+	    emit_obj(f,z,t);
+	}else{
+	  emit(f,"-(%s)",mregnames[sp]);
+	  push(4);
+	}
+	emit(f,"\n");
+	if((t&NQ)==FLOAT||c==PUSH) return;
+	m=0;
+	if(z&&(z->flags&REG)){
+	  m=1;z->flags|=D16OFF;
+	  z->val.vmax=l2zm(0L);
+	}
+	vmax=l2zm(4L);
+	z->val.vmax=zmadd(z->val.vmax,vmax);
+	emit(f,"\tmove.l\t#%s%02x%02x%02x%02x,",s,ip[4],ip[5],ip[6],ip[7]);
+	if(cf)
+	  emit(f,"%s\n\tmove.l\t%s,",mregnames[r],mregnames[r]);
+	if(isreg(z)&&reg_pair(p->z.reg,&rp))
+	  emit(f,"%s",mregnames[rp.r2]);
+	else
+	  emit_obj(f,z,t);
+	emit(f,"\n");
+	if(m){
+	  z->flags&=~D16OFF;vmax=l2zm(4L);
+	  z->val.vmax=zmsub(z->val.vmax,vmax);
+	}
+      }
+      return;
+    }
+    if((q&&(q->flags&REG)&&q->reg>=fp0)||(z&&(z->flags&REG)&&z->reg>=fp0)){
+      if(c==ASSIGN&&(q->flags&REG)&&(z->flags&REG)&&q->reg==z->reg) return;
+      if(c==ASSIGN){ move(f,q,0,z,0,t);return;}
+      emit(f,"\tfmove.%c\t",x_t[t&NQ]);
+      emit_obj(f,q,t);
+      emit(f,",");
+      if(c==PUSH){
+	emit(f,"-(%s)",mregnames[sp]);
+	push(size);
+      } else 
+	emit_obj(f,z,t);
+      emit(f,"\n");return;
+    }
+    if(size==8) t=LLONG;
+  }
+  if((t&NQ)==LLONG){
+    if(z&&compare_objects(q,z)) return;
+    if(((cf&&c==ASSIGN)||(q->flags&(REG|DREFOBJ))==REG)&&(!z||(z->flags&(REG|DREFOBJ))!=REG)){
+      if(cf){
+	if(c==ASSIGN){
+	  int r;
+	  if((q->flags&(REG|DREFOBJ))==REG){
+	    if(!reg_pair(q->reg,&rp)) ierror(0);
+	    r=rp.r2;
+	  }else{
+	    r=get_reg(f,1,p,0);
+	    emit(f,"\tmove.l\t");
+	    emit_lword(f,q);
+	    emit(f,",%s\n",mregnames[r]);
+	  }
+	  emit(f,"\tmove.l\t%s,",mregnames[r]);
+	  emit_lword(f,z);
+	  emit(f,"\n");
+	  if((q->flags&(REG|DREFOBJ))==REG){
+	    r=rp.r1;
+	  }else{
+	    emit(f,"\tmove.l\t");
+	    emit_hword(f,q);
+	    emit(f,",%s\n",mregnames[r]);
+	  }
+	  emit(f,"\tmove.l\t%s,",mregnames[r]);
+	  emit_hword(f,z);
+	  emit(f,"\n");
+	}else{
+	  emit(f,"\tsubq.l\t#8,%s\n",mregnames[sp]);
+	  push(8);
+	  emit(f,"\tmovem.l\t%s,(%s)\n",mregnames[q->reg],mregnames[sp]);
+	}
+      }else{
+	emit(f,"\tmovem.l\t%s,",mregnames[q->reg]);
+	if(c==ASSIGN){
+	  emit_obj(f,z,t);
+	}else{
+	  emit(f,"-(%s)",mregnames[sp]);
+	  push(8);
+	}
+	emit(f,"\n");
+      }
+      return;
+    }
+    if(!cf&&(q->flags&(REG|DREFOBJ))!=REG&&!((q->flags&(KONST|DREFOBJ))==KONST)&&z&&(z->flags&(REG|DREFOBJ))==REG){
+      emit(f,"\tmovem.l\t");
+      emit_obj(f,q,t);
+      emit(f,",%s\n",mregnames[z->reg]);
+      return;
+    }
+    emit(f,"\tmove.l\t");
+    emit_lword(f,q);
+    emit(f,",");
+    if(c==ASSIGN){
+      emit_lword(f,z);
+    }else{
+      emit(f,"-(%s)",mregnames[sp]);
+      push(4);
+    }
+    emit(f,"\n");
+    emit(f,"\tmove.l\t");
+    emit_hword(f,q);
+    emit(f,",");
+    if(c==ASSIGN){
+      emit_hword(f,z);
+    }else{
+      emit(f,"-(%s)",mregnames[sp]);
+      push(4);
+    }
+    emit(f,"\n");    
+    return;
+  }
+  if((size==1||size==2||size==4)&&!ISARRAY(t)&&(p->code!=PUSH||zm2l(p->z.val.vmax)!=3)&&((t&NQ)!=CHAR||size==1)){
+    if(ISSTRUCT(t)||ISUNION(t)){
+      if(p->code==PUSH&&!zmeqto(p->q2.val.vmax,p->z.val.vmax)){
+	if(size!=4&&size!=2) ierror(size);
+	emit(f,"\tsubq.%s\t#%d,%s\n",cf?"l":"w",size,mregnames[sp]);
+	push(size);
+	size=zm2l(p->z.val.vmax);
+	if(size!=1&&size!=2) ierror(0);
+	emit(f,"\tmove.%c\t",size==1?'b':'w');
+	emit_obj(f,q,(size==1?CHAR:SHORT));
+	emit(f,",(%s)\n",mregnames[sp]);
+	return;
+      }else{
+	if(size==1)
+	  t=CHAR;
+	else if(size==2)
+	  t=SHORT;
+	else
+	  t=LONG;
+      }
+    }
+    if(c==ASSIGN){move(f,q,0,z,0,t);return;}
+    /*  Sonderfall pea  */
+    if((q->flags&VARADR)&&c==PUSH){
+      emit(f,"\tpea\t");
+      q->flags&=~VARADR; emit_obj(f,q,t); q->flags|=VARADR;
+      emit(f,"\n"); 
+      push(size);
+      return;
+    }
+    emit(f,"\tmove.%c\t",x_s[size]);
+    emit_obj(f,q,t);
+    emit(f,",");
+    if(c==PUSH){
+      emit(f,"-(%s)",mregnames[sp]);
+      push(size);
+    } else 
+      emit_obj(f,z,t);
+    emit(f,"\n");return;
+  }else{
+    int a1,a2,qreg,zreg,dreg,loops,scratch=0,down=0;char *cpstr;
+    long s=size,osize=size;
+    IC *m;
+    for(m=p->next;m&&m->code==FREEREG;m=m->next){
+      if(q&&m->q1.reg==q->reg) scratch|=1;
+      if(z&&m->q1.reg==z->reg) scratch|=2;
+    }
+    a1=alignment(q);
+    if(c!=PUSH)  a2=alignment(z); else a2=0;
+    if(a1<0||a2<0) {a1=1;a2=2;}
+    if(p->typf2==2||p->typf2==4) {a1=a2=0;}
+    if((c==PUSH||(scratch&1))&&(q->flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&q->reg>=1&&q->reg<=8&&!q->am){
+      qreg=q->reg;
+      if(c==PUSH&&(a1&1)==0&&(a2&1)==0)
+	emit(f,"\tadd%s.%s\t#%ld,%s\n",quick[s<=8],strshort[s<=32767],(long)s,mregnames[q->reg]);
+    }else{
+      if(c!=ASSIGN&&!regavailable(0))
+	qreg=pget_reg(f,0,p,0);
+      else
+	qreg=get_reg(f,0,p,0);
+      if(c==PUSH&&(a1&1)==0&&(a2&1)==0){
+	q->flags|=D16OFF; 
+	q->val.vmax=zmadd(q->val.vmax,l2zm((long)s));
+	emit(f,"\tlea\t");emit_obj(f,q,POINTER);
+	q->val.vmax=zmsub(q->val.vmax,l2zm((long)s));
+	emit(f,",%s\n",mregnames[qreg]);
+      }else{
+	emit(f,"\tlea\t");emit_obj(f,q,POINTER);
+	emit(f,",%s\n",mregnames[qreg]);
+      }	      
+    }
+    if(c==PUSH){
+      if((a1&1)==0&&(a2&1)==0){
+	zreg=8;
+      }else{
+	emit(f,"\tsub%s.%s\t#%ld,%s\n",quick[s<=8],strshort[s<=32767],(long)s,mregnames[sp]);
+	push(size);
+	size=0;
+	if(!regavailable(0))
+	  zreg=pget_reg(f,0,p,0);
+	else
+	  zreg=get_reg(f,0,p,0);
+	emit(f,"\tmove.l\t%s,%s\n",mregnames[sp],mregnames[zreg]);
+      }
+    }else{
+      if((scratch&2)&&(z->flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&z->reg>=1&&z->reg<=8&&!z->am){
+	zreg=z->reg;
+      }else{
+	zreg=get_reg(f,0,p,0);
+	emit(f,"\tlea\t");emit_obj(f,z,POINTER);
+	emit(f,",%s\n",mregnames[zreg]);
+      }
+    }
+    /*  wenn Typ==CHAR, dann ist das ein inline_memcpy und wir nehmen   */
+    /*  das unguenstigste Alignment an                                  */
+    /*if((t&NQ)==CHAR){ a1=1;a2=2;}*/
+    
+    if(c==PUSH&&(a1&1)==0&&(a2&1)==0){
+      cpstr="\tmove.%c\t-(%s),-(%s)\n";
+      down=1;
+    }else
+      cpstr="\tmove.%c\t(%s)+,(%s)+\n";
+    
+    if((a1&1)&&(a2&1)){emit(f,cpstr,'b',mregnames[qreg],mregnames[zreg]);s--;a1&=~1;a2&=~1;}
+    if((a1&2)&&(a2&2)){emit(f,cpstr,'w',mregnames[qreg],mregnames[zreg]);s-=2;a1&=~2;a2&=~2;}
+    if(!(a1&1)&&!(a2&1)) loops=s/16-1; else loops=s/4-1;
+    if(loops>0){
+      if(c!=ASSIGN&&!regavailable(1)) dreg=pget_reg(f,1,p,0);
+      else dreg=get_reg(f,1,p,0);
+      emit(f,"\tmove%s.l\t#%d,%s\n%s%d:\n",quick[loops>=-128&&loops<=127],loops,mregnames[dreg],labprefix,++label);
+    }
+    if(loops>=0){
+      int t;
+      if(!(a1&1)&&!(a2&1)) t='l'; else t='b';
+      emit(f,cpstr,t,mregnames[qreg],mregnames[zreg]);
+      emit(f,cpstr,t,mregnames[qreg],mregnames[zreg]);
+      emit(f,cpstr,t,mregnames[qreg],mregnames[zreg]);
+      emit(f,cpstr,t,mregnames[qreg],mregnames[zreg]);
+    }
+    if(loops>0){
+      if(!cf&&loops<=32767&&loops>=-32768){
+	emit(f,"\tdbra\t%s,%s%d\n",mregnames[dreg],labprefix,label);
+      }else{
+	emit(f,"\tsubq.l\t#1,%s\n\tbge\t%s%d\n",mregnames[dreg],labprefix,label);
+      }
+    }
+    if(!(a1&1)&&!(a2&1)){
+      if(s&8){
+	emit(f,cpstr,'l',mregnames[qreg],mregnames[zreg]);
+	emit(f,cpstr,'l',mregnames[qreg],mregnames[zreg]);
+      }
+      if(s&4) emit(f,cpstr,'l',mregnames[qreg],mregnames[zreg]);
+      if(s&2) emit(f,cpstr,'w',mregnames[qreg],mregnames[zreg]);
+      if(s&1) emit(f,cpstr,'b',mregnames[qreg],mregnames[zreg]);
+    }else{
+      s&=3;
+      while(s){emit(f,cpstr,'b',mregnames[qreg],mregnames[zreg]);s--;}
+    }
+    if(c==PUSH&&qreg==q->reg&&(!(scratch&1))&&!down)
+      emit(f,"\tsub%s.%s\t#%ld,%s\n",quick[osize<=8],strshort[osize<=32767],osize,regnames[qreg]);
+    if(c==PUSH) push(size);
+  }
+  return;
+}
+static int muststore(IC *p,int r)
+{
+  if(!regs[r])
+    return 0;
+#if 0
+  /* mal bei Gelegenheit testen */
+  while(p){
+    if(p->code==FREEREG&&p->q1.reg==r)
+      return 0;
+    if((p->q1.flags&REG)&&p->q1.reg==r)
+      return 1;
+    if(p->q1.am&&(p->q1.am->basereg==r||(p->q1.am->dreg&127)==r))
+      return 1;
+    if((p->q2.flags&REG)&&p->q2.reg==r)
+      return 1;
+    if(p->q2.am&&(p->q2.am->basereg==r||(p->q2.am->dreg&127)==r))
+      return 1;
+    if(p->z.am&&(p->z.am->basereg==r||(p->z.am->dreg&127)==r))
+      return 1;
+    if((p->z.flags&REG)&&p->z.reg==r)
+      return (p->z.flags&DREFOBJ)!=0;
+    if(p->code>=LABEL&&p->code<=BRA)
+      return 1;
+    p=p->next;
+  }
+  return 0;
+#else
+  return 1;
+#endif
+}
+
+static int store_saveregs;
+static void saveregswfp(FILE *f,IC *p,int storefp)
+{
+    int dontsave;
+    store_saveregs=0;
+    if((p->z.flags&(REG|DREFOBJ))==REG) dontsave=p->z.reg; else dontsave=0;
+    if(dontsave!= d0&&dontsave!=25&&(muststore(p,d0)||muststore(p,d0d1))) {emit(f,"\tmove.l\t%s,-(%s)\n",mregnames[d0],mregnames[sp]);push(4);store_saveregs|=1;}
+    if(dontsave!=10&&dontsave!=25&&(muststore(p,d1)||muststore(p,d0d1))) {emit(f,"\tmove.l\t%s,-(%s)\n",mregnames[d1],mregnames[sp]);push(4);store_saveregs|=2;}
+    if(dontsave!= fp0&&muststore(p,fp0)) {emit(f,"\tfmove.x\t%s,-(%s)\n",mregnames[fp0],mregnames[sp]);push(12);store_saveregs|=16;}
+    if(dontsave!= fp1&&muststore(p,fp1)) {emit(f,"\tfmove.x\t%s,-(%s)\n",mregnames[fp1],mregnames[sp]);push(12);store_saveregs|=32;}
+    if(dontsave!= a0&&muststore(p,a0)) {emit(f,"\tmove.l\t%s,-(%s)\n",mregnames[a0],mregnames[sp]);push(4);store_saveregs|=4;}
+    if(dontsave!= a1&&muststore(p,a1)) {emit(f,"\tmove.l\t%s,-(%s)\n",mregnames[a1],mregnames[sp]);push(4);store_saveregs|=8;}
+
+}
+static void restoreregsa(FILE *f,IC *p)
+{
+    if(store_saveregs&8) {emit(f,"\tmove.l\t(%s)+,%s\n",mregnames[sp],mregnames[a1]);pop(4);}
+    if(store_saveregs&4) {emit(f,"\tmove.l\t(%s)+,%s\n",mregnames[sp],mregnames[a0]);pop(4);}
+}
+static void restoreregsd(FILE *f,IC *p)
+{
+    int dontsave;
+    if((p->z.flags&(REG|DREFOBJ))==REG) dontsave=p->z.reg; else dontsave=0;
+    if(dontsave!=fp1&&(store_saveregs&32)){
+      emit(f,"\tfmove.x\t(%s)+,%s\n",mregnames[sp],mregnames[fp1]);
+      pop(12);
+    }
+    if(dontsave!=fp0&&(store_saveregs&16)){
+      emit(f,"\tfmove.x\t(%s)+,%s\n",mregnames[sp],mregnames[fp0]);
+      pop(12);
+    }
+    if(dontsave!=10&&(store_saveregs&2)){
+      if(!GAS&&!PHXASS)
+	emit(f,"\topt\tom-\n");
+      if(cf)
+        emit(f,"\tmovem.l\t(%s),%s\n\taddq.l\t#4,%s\n",mregnames[sp],mregnames[d1],mregnames[sp]);
+      else
+	emit(f,"\tmovem.l\t(%s)+,%s\n",mregnames[sp],mregnames[d1]);
+      pop(4);
+      if(!GAS&&!PHXASS)
+	emit(f,"\topt\tom+\n");
+    }
+    if(dontsave!=d0 &&(store_saveregs&1)){
+      if(!GAS&&!PHXASS)
+	emit(f,"\topt\tom-\n");
+      if(cf)
+        emit(f,"\tmovem.l\t(%s),%s\n\taddq.l\t#4,%s\n",mregnames[sp],mregnames[d0],mregnames[sp]);
+      else
+	emit(f,"\tmovem.l\t(%s)+,%s\n",mregnames[sp],mregnames[d0]);
+      pop(4);
+      if(!GAS&&!PHXASS)
+	emit(f,"\topt\tom+\n");
+    }
+}
+
+/* emits the low word of a long long object */
+static void emit_lword(FILE *f,obj *o)
+{
+  if((o->flags&(REG|DREFOBJ))==REG){
+    if(!reg_pair(o->reg,&rp))
+      ierror(0);
+    emit(f,"%s",mregnames[rp.r2]);
+  }else if((o->flags&(KONST|DREFOBJ))==KONST){
+    eval_const(&o->val,UNSIGNED|LLONG);
+    vumax=zumand(vumax,ul2zum(0xffffffff));
+    insert_const(&gval,UNSIGNED|MAXINT);
+    emit(f,"#");
+    emitval(f,&gval,UNSIGNED|MAXINT);
+  }else{
+    if(o->am||(o->flags&REG)){
+      o->flags|=D16OFF;
+      o->val.vmax=l2zm(0L);
+    }
+    o->val.vmax=zmadd(o->val.vmax,l2zm(4L));
+    emit_obj(f,o,LLONG);
+    o->flags&=~D16OFF;
+    o->val.vmax=zmsub(o->val.vmax,l2zm(4L));
+  }
+}
+/* emits the high word of a long long object */
+static void emit_hword(FILE *f,obj *o)
+{
+  if((o->flags&(REG|DREFOBJ))==REG){
+    if(!reg_pair(o->reg,&rp)) 
+      ierror(0);
+    emit(f,"%s",mregnames[rp.r1]);
+  }else if((o->flags&(KONST|DREFOBJ))==KONST){
+    eval_const(&o->val,UNSIGNED|MAXINT);
+    vumax=zumand(zumrshift(vumax,ul2zum(32UL)),ul2zum(0xffffffff));
+    insert_const(&gval,UNSIGNED|MAXINT);
+    emit(f,"#");
+    emitval(f,&gval,UNSIGNED|MAXINT);
+  }else{
+    emit_obj(f,o,LONG);
+  }
+}
+/* process ICs with long long; return 1 if IC has been handled */
+static int handle_llong(FILE *f,IC *p)
+{
+  int c=p->code,r=0,t=p->typf&NU;
+  char *libfuncname;
+
+  if(c==ADDRESS) return 0;
+  
+  cc_set=0;
+  if(c==GETRETURN){
+    if(isreg(z)&&p->z.reg==25)
+      return 1;
+    emit(f,"\tmove.l\t%s,",mregnames[d1]);
+    emit_lword(f,&p->z);
+    emit(f,"\n");
+    emit(f,"\tmove.l\t%s,",mregnames[d0]);
+    emit_hword(f,&p->z);
+    emit(f,"\n");
+    return 1;
+  }
+  if(c==SETRETURN){
+    if(isreg(q1)&&p->q1.reg==25)
+      return 1;
+    emit(f,"\tmove.l\t");
+    emit_lword(f,&p->q1);
+    emit(f,",%s\n",mregnames[d1]);
+    emit(f,"\tmove.l\t");
+    emit_hword(f,&p->q1);
+    emit(f,",%s\n",mregnames[d0]);    
+    return 1;
+  }
+  if(c==CONVERT){
+    int told=q1typ(p),tnew=ztyp(p);
+    if(ISPOINTER(told)) told=UNSIGNED|LONG;
+    if(ISPOINTER(tnew)) tnew=UNSIGNED|LONG;
+    if(ISFLOAT(told)){
+      if(!OLD_SOFTFLOAT) ierror(0);
+      saveregs(f,p);
+      assign(f,p,&p->q1,0,PUSH,msizetab[told&NQ],told);
+      scratch_modified();
+      if(GAS)
+	emit(f,"\t.global\t__flt%ldto%cint64\n\tjbsr\t__flt%ldto%cint64\n\taddq.%s\t#%ld,%s\n",msizetab[told&NQ]*8,(tnew&UNSIGNED)?'u':'s',msizetab[told&NQ]*8,(tnew&UNSIGNED)?'u':'s',strshort[1],msizetab[told&NQ],mregnames[sp]);
+      else
+	emit(f,"\tpublic\t__flt%ldto%cint64\n\tjsr\t__flt%ldto%cint64\n\taddq.%s\t#%ld,%s\n",msizetab[told&NQ]*8,(tnew&UNSIGNED)?'u':'s',msizetab[told&NQ]*8,(tnew&UNSIGNED)?'u':'s',strshort[1],msizetab[told&NQ],mregnames[sp]);
+      pop(msizetab[told]);
+      restoreregsa(f,p);
+      if(!isreg(z)||p->z.reg!=25){ /* d0/d1 */
+	emit(f,"\tmove.l\t%s,",mregnames[d1]);
+	emit_lword(f,&p->z);
+	emit(f,"\n");
+	emit(f,"\tmove.l\t%s,",mregnames[d0]);
+	emit_hword(f,&p->z);
+	emit(f,"\n");
+      }
+      restoreregsd(f,p);
+      return 1;
+    }
+    if(ISFLOAT(tnew)){
+      saveregswfp(f,p,1);
+      assign(f,p,&p->q1,0,PUSH,msizetab[told&NQ],told);
+      scratch_modified();
+      if(GAS)
+	emit(f,"\t.global\t__%cint64toflt%ld\n\tjbsr\t__%cint64toflt%ld\n\taddq.%s\t#%ld,%s\n",(told&UNSIGNED)?'u':'s',msizetab[tnew&NQ]*8,(told&UNSIGNED)?'u':'s',msizetab[tnew&NQ]*8,strshort[1],msizetab[told&NQ],mregnames[sp]);
+      else
+	emit(f,"\tpublic\t__%cint64toflt%ld\n\tjsr\t__%cint64toflt%ld\n\taddq.%s\t#%ld,%s\n",(told&UNSIGNED)?'u':'s',msizetab[tnew&NQ]*8,(told&UNSIGNED)?'u':'s',msizetab[tnew&NQ]*8,strshort[1],msizetab[told&NQ],mregnames[sp]);
+      pop(msizetab[told&NQ]);
+      restoreregsa(f,p);
+      if(FPU>68000){
+	emit(f,"\tfmove.x\tfp0,");
+	emit_obj(f,&p->z,tnew);
+	emit(f,"\n");
+      }else if((tnew&NQ)==FLOAT){
+	emit(f,"\tmove.l\t%s,",mregnames[d0]);
+	emit_obj(f,&p->z,tnew);
+	emit(f,"\n");
+      }else{
+	emit(f,"\tmove.l\td1,");
+	emit_lword(f,&p->z);
+	emit(f,"\n");
+	emit(f,"\tmove.l\t%s,",mregnames[d0]);
+	emit_hword(f,&p->z);
+	emit(f,"\n");
+      }
+      restoreregsd(f,p);
+      return 1;
+    }
+    if((told&NQ)<LLONG){
+      int destreg=0;
+      if(ISHWORD(told)||!(told&UNSIGNED)){
+	if(isreg(z)){
+	  if(!reg_pair(p->z.reg,&rp)) ierror(0);
+	  r=rp.r2;
+	  destreg=1;
+	}else{
+	  r=get_reg(f,1,p,0);
+	}
+	loadext(f,r,&p->q1,told);
+	p->q1.flags=REG;
+	p->q1.reg=r;
+	p->q1.am=0;
+      }
+      if(!destreg){
+	emit(f,"\tmove.l\t");
+	emit_obj(f,&p->q1,told);
+	emit(f,",");
+	emit_lword(f,&p->z);
+	emit(f,"\n");
+      }
+      if(told&UNSIGNED){
+	emit(f,"\tmove.l\t#0,");
+	emit_hword(f,&p->z);
+	emit(f,"\n");
+      }else{
+	int tmp;
+	if(r==0)
+	  ierror(0);
+	if(destreg){
+	  emit(f,"\tmove.l\t%s,%s\n",mregnames[r],mregnames[rp.r1]);
+	  r=rp.r1;
+	}
+	tmp=get_reg(f,1,p,0);
+	emit(f,"\tmoveq\t#31,%s\n",mregnames[tmp]);
+	emit(f,"\tasr.l\t%s,%s\n",mregnames[tmp],mregnames[r]);
+	if(!destreg){
+	  emit(f,"\tmove.l\t%s,",mregnames[r]);
+	  emit_hword(f,&p->z);
+	  emit(f,"\n");
+	}
+      }
+      return 1;
+    }
+    if((tnew&NQ)<LLONG){
+      if((tnew&NQ)<INT&&!isreg(z)){
+	r=get_reg(f,1,p,0);
+	emit(f,"\tmove.l\t");
+	emit_lword(f,&p->q1);
+	emit(f,",%s\n",mregnames[r]);
+	emit(f,"\tmove.%c\t%s,",x_t[tnew&NQ],mregnames[r]);
+	emit_obj(f,&p->z,tnew);
+	emit(f,"\n");
+      }else{
+	emit(f,"\tmove.%c\t",x_t[tnew&NQ]);
+	p->q1.val.vmax=zmadd(p->q1.val.vmax,zmsub(sizetab[LONG],sizetab[tnew&NQ]));
+	emit_lword(f,&p->q1);
+	emit(f,",");
+	emit_obj(f,&p->z,tnew);
+	emit(f,"\n");
+      }
+      return 1;
+    }
+    assign(f,p,&p->q1,&p->z,ASSIGN,msizetab[t],t);
+    return 1;
+  }
+  if(c==ASSIGN){
+    assign(f,p,&p->q1,&p->z,ASSIGN,msizetab[t],t);
+    return 1;
+  }
+  if(c==PUSH){
+    dontpop+=zm2l(p->q2.val.vmax);
+    assign(f,p,&p->q1,0,PUSH,msizetab[t],t);
+    return 1;
+  }  
+  if(c==MINUS||c==KOMPLEMENT){
+    char *sl,*sh;
+    if(c==MINUS){
+      sl="neg.l";
+      sh="negx.l";
+    }else
+      sl=sh="not.l";
+    if(!cf&&compare_objects(&p->q1,&p->z)){
+      emit(f,"\t%s\t",sl);
+      emit_lword(f,&p->z);
+      emit(f,"\n");
+      emit(f,"\t%s\t",sh);
+      emit_hword(f,&p->z);
+      emit(f,"\n");      
+      return 1;
+    }
+    if(isreg(z)){
+      if(!reg_pair(p->z.reg,&rp)) ierror(0);
+      assign(f,p,&p->q1,&p->z,ASSIGN,msizetab[t],t);
+      emit(f,"\t%s\t%s\n",sl,mregnames[rp.r2]);
+      emit(f,"\t%s\t%s\n",sh,mregnames[rp.r1]);
+      return 1;
+    }
+    r=get_reg(f,1,p,0);
+    emit(f,"\tmove.l\t");
+    emit_lword(f,&p->q1);
+    emit(f,",%s\n",mregnames[r]);
+    emit(f,"\t%s\t%s\n",sl,mregnames[r]);
+    emit(f,"\tmove.l\t%s,",mregnames[r]);
+    emit_lword(f,&p->z);
+    emit(f,"\n");
+    emit(f,"\tmove.l\t");
+    emit_hword(f,&p->q1);
+    emit(f,",%s\n",mregnames[r]);
+    emit(f,"\t%s\t%s\n",sh,mregnames[r]);
+    emit(f,"\tmove.l\t%s,",mregnames[r]);
+    emit_hword(f,&p->z);    
+    emit(f,"\n");
+    return 1;
+  }
+  if((c>=OR&&c<=AND)||c==ADD||c==SUB){
+    char *sl,*sh;int t2=0;
+    switch_IC(p);
+    if(c==ADD){sl="add.l";sh="addx.l";}
+    else if(c==SUB){sl="sub.l";sh="subx.l";}
+    else if(c==AND){sl=sh="and.l";}
+    else if(c==OR){sl=sh="or.l";}
+    else if(c==XOR){sl=sh="eor.l";}
+    else
+      ierror(0);
+    if(isreg(q1)&&isreg(q2)&&isreg(z)&&p->q1.reg==p->q2.reg&&p->q1.reg==p->z.reg){
+      if(!reg_pair(p->q1.reg,&rp)) ierror(0);
+      emit(f,"\t%s\t%s,%s\n",sl,mregnames[rp.r2],mregnames[rp.r2]);
+      emit(f,"\t%s\t%s,%s\n",sh,mregnames[rp.r1],mregnames[rp.r1]);
+      return 1;
+    }
+    if(!isreg(z)&&compare_objects(&p->q1,&p->z)){
+      if(isreg(q2)||(isconst(q2)&&(c==ADD||c==SUB)&&!cf)){
+	if(!r) r=get_reg(f,1,p,0);
+	emit(f,"\t%s\t",sl);
+	emit_lword(f,&p->q2);
+      }else{
+	if(!r) r=get_reg(f,1,p,0);
+	emit(f,"\tmove.l\t");
+	emit_lword(f,&p->q2);
+	emit(f,",%s\n",mregnames[r]);
+	emit(f,"\t%s\t%s",sl,mregnames[r]);
+      }
+      emit(f,",");
+      emit_lword(f,&p->z);
+      emit(f,"\n");
+      if(!isreg(q2)||c==ADD||c==SUB||c==XOR){
+	emit(f,"\tmove.l\t");
+	emit_hword(f,&p->q1);
+	emit(f,",%s\n",mregnames[r]);
+	if(isreg(q2)){
+	  if(!reg_pair(p->q2.reg,&rp)) ierror(0);
+	  t2=rp.r1;
+	}else{
+	  t2=get_reg(f,1,p,0);
+	  emit(f,"\tmove.l\t");
+	  emit_hword(f,&p->q2);
+	  emit(f,",%s\n",mregnames[t2]);
+	}
+	emit(f,"\t%s\t%s,%s\n",sh,mregnames[t2],mregnames[r]);
+	emit(f,"\tmove.l\t%s,",mregnames[r]);
+	emit_hword(f,&p->z);
+	emit(f,"\n");
+      }else{
+	if(isreg(q2)){
+	  emit(f,"\t%s\t",sh);
+	  emit_hword(f,&p->q2);
+	}else{
+	  if(!r) r=get_reg(f,1,p,0);
+	  emit(f,"\tmove.l\t");
+	  emit_hword(f,&p->q2);
+	  emit(f,",%s\n",mregnames[r]);
+	  emit(f,"\t%s\t%s",sh,mregnames[r]);
+	}
+	emit(f,",");
+	emit_hword(f,&p->z);
+	emit(f,"\n");      
+      }
+      return 1;
+    }
+    if(isreg(z)&&(!isreg(q2)||p->z.reg!=p->q2.reg)){
+      if(!reg_pair(p->z.reg,&rp)) ierror(0);
+      r=rp.r2;
+    }else{
+      r=get_reg(f,1,p,0);
+    }
+    if(!compare_objects(&p->q1,&p->z)){
+      emit(f,"\tmove.l\t");
+      emit_lword(f,&p->q1);
+      emit(f,",%s\n",mregnames[r]);
+    }
+    if(c==XOR){
+      t2=get_reg(f,1,p,0);
+      emit(f,"\tmove.l\t");
+      emit_lword(f,&p->q2);
+      emit(f,",%s\n",mregnames[t2]);
+      emit(f,"\t%s\t%s,%s\n",sl,mregnames[t2],mregnames[r]);
+    }else{
+      emit(f,"\t%s\t",sl);
+      emit_lword(f,&p->q2);
+      emit(f,",%s\n",mregnames[r]);
+    }
+    if(isreg(z)&&(!isreg(q2)||p->z.reg!=p->q2.reg)){
+      if(!reg_pair(p->z.reg,&rp)) ierror(0);
+      r=rp.r1;
+    }else{
+      emit(f,"\tmove.l\t%s,",mregnames[r]);
+      emit_lword(f,&p->z);
+      emit(f,"\n");
+    }
+    if(!compare_objects(&p->q1,&p->z)){
+      emit(f,"\tmove.l\t");
+      emit_hword(f,&p->q1);
+      emit(f,",%s\n",mregnames[r]);
+    }
+    if(c==XOR||c==ADD||c==SUB){
+      if(isreg(q2)){
+	if(!reg_pair(p->q2.reg,&rp)) ierror(0);
+	t2=rp.r1;
+      }else{
+	if(!t2) t2=get_reg(f,1,p,0);
+	emit(f,"\tmove.l\t");
+	emit_hword(f,&p->q2);
+	emit(f,",%s\n",mregnames[t2]);
+      }
+      emit(f,"\t%s\t%s,%s\n",sh,mregnames[t2],mregnames[r]);
+    }else{
+      emit(f,"\t%s\t",sh);
+      emit_hword(f,&p->q2);
+      emit(f,",%s\n",mregnames[r]);
+    }
+    if(!isreg(z)||(isreg(q2)&&p->z.reg==p->q2.reg)){
+      emit(f,"\tmove.l\t%s,",mregnames[r]);
+      emit_hword(f,&p->z);
+      emit(f,"\n");
+    }      
+    return 1;
+  }
+  if(c==TEST){
+    p->code=c=COMPARE;
+    p->q2.flags=KONST;
+    if((t&NU)==LLONG)
+      p->q2.val.vllong=zm2zll(l2zm(0L));
+    else if((t&NU)==(UNSIGNED|LLONG))
+      p->q2.val.vullong=zum2zull(ul2zum(0UL));
+    else
+      ierror(0);
+  }
+  if(c==COMPARE){
+    int rl,rh,t2;
+    comptyp=p->typf;
+    rl=get_reg(f,1,p,0);
+    rh=get_reg(f,1,p,0);
+    emit(f,"\tmove.l\t");
+    emit_lword(f,&p->q1);
+    emit(f,",%s\n",mregnames[rl]);
+    emit(f,"\tmove.l\t");
+    emit_hword(f,&p->q1);
+    emit(f,",%s\n",mregnames[rh]);
+    if(isreg(q2)){
+      if(!reg_pair(p->q2.reg,&rp)) ierror(0);
+      t2=rp.r1;
+    }else{
+      t2=get_reg(f,1,p,0);
+      emit(f,"\tmove.l\t");
+      emit_hword(f,&p->q2);
+      emit(f,",%s\n",mregnames[t2]);
+    }
+    emit(f,"\tsub.l\t");
+    emit_lword(f,&p->q2);
+    emit(f,",%s\n",mregnames[rl]);
+    emit(f,"\tsubx.l\t%s,%s\n",mregnames[t2],mregnames[rh]);
+    return 1;
+  }
+  saveregs(f,p);
+  if((c==LSHIFT||c==RSHIFT)&&(q2typ(p)&NQ)==LLONG){
+    emit(f,"\tmove.l\t");
+    emit_lword(f,&p->q2);
+    emit(f,",-(%s)\n",mregnames[sp]);
+    push(4);
+  }else
+    assign(f,p,&p->q2,0,PUSH,msizetab[q2typ(p)&NQ],q2typ(p));
+  assign(f,p,&p->q1,0,PUSH,msizetab[q1typ(p)&NQ],q1typ(p));
+  scratch_modified();
+  if(c==MULT){
+    if(CPU==68060)
+      libfuncname="__mulint64_060";
+    else if(CPU>=68020)
+      libfuncname="__mulint64_020";
+    else
+      libfuncname="__mulint64";
+  }else if(c==DIV){
+    if(t&UNSIGNED){
+      if(CPU==68060)
+	libfuncname="__divuint64_060";
+      else if(CPU>=68020)
+	libfuncname="__divuint64_020";
+      else
+	libfuncname="__divuint64";
+    }else{
+      if(CPU==68060)
+	libfuncname="__divsint64_060";
+      else if(CPU>=68020)
+	libfuncname="__divsint64_020";
+      else
+	libfuncname="__divsint64";
+    }
+  }else if(c==MOD){
+    if(t&UNSIGNED){
+      if(CPU==68060)
+	libfuncname="__moduint64_060";
+      else if(CPU>=68020)
+	libfuncname="__moduint64_020";
+      else
+	libfuncname="__moduint64";
+    }else{
+      if(CPU==68060)
+	libfuncname="__modsint64_060";
+      else if(CPU>=68020)
+	libfuncname="__modsint64_020";
+      else
+	libfuncname="__modsint64";
+    }
+  }else if(c==RSHIFT){
+    if(t&UNSIGNED)
+      libfuncname="__rshuint64";
+    else
+      libfuncname="__rshsint64";
+  }else if(c==LSHIFT)
+    libfuncname="__lshint64";
+  else{
+    printf("c=%d\n",c);
+    ierror(0);
+  }
+  if(GAS)
+    emit(f,"\t.global\t%s\n\tjbsr\t%s\n",libfuncname,libfuncname);
+  else
+    emit(f,"\tpublic\t%s\n\tjsr\t%s\n",libfuncname,libfuncname);
+  if(c==LSHIFT||c==RSHIFT){
+#ifdef M68K_16BIT_INT
+    emit(f,"\tadd.%s\t#10,%s\n",strshort[1],mregnames[sp]);
+    pop(10);
+#else
+    emit(f,"\tadd.%s\t#12,%s\n",strshort[1],mregnames[sp]);
+    pop(12);
+#endif
+  }else{
+    emit(f,"\tadd.%s\t#16,%s\n",strshort[1],mregnames[sp]);
+    pop(16);
+  }
+  restoreregsa(f,p);
+  if(!isreg(z)||p->z.reg!=25){
+    emit(f,"\tmove.l\t%s,",mregnames[d0]);
+    emit_hword(f,&p->z);
+    emit(f,"\n");
+    emit(f,"\tmove.l\t%s,",mregnames[10]);
+    emit_lword(f,&p->z);
+    emit(f,"\n");
+  }    
+  restoreregsd(f,p);
+  return 1;
+}
+
+/* generate inlines for Amiga IEEE softcalls */
+static char *ami_ieee(char *base,int off)
+{
+  char *s;
+  if(cf) ierror(0);
+  s=mymalloc(128);
+  sprintf(s,"\tmove.l\t%s,-(%s)\n\tmove.l\t%sMathIeee%sBase%s,%s\n\tjsr\t%d(%s)\n\tmove.l\t(%s)+,%s",mregnames[a6],mregnames[sp],idprefix,base,use_sd?"(a4)":"",mregnames[a6],off,mregnames[a6],mregnames[sp],mregnames[a6]);
+  return s;
+}
+
+/****************************************/
+/*  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;
+    larray.size=l2zm(3L);
+    /*  Initialize some values which cannot be statically initialized   */
+    /*  because they are stored in the target's arithmetic.             */
+    maxalign=l2zm(4L);
+    char_bit=l2zm(8L);
+    for(i=0;i<=MAX_TYPE;i++){
+        sizetab[i]=l2zm(msizetab[i]);
+        align[i]=l2zm(malign[i]);
+    }
+    for(i= 1;i<=16;i++) {regsize[i]=l2zm( 4L);regtype[i]=&ltyp;}
+    for(i=fp0;i<=fp7;i++) {regsize[i]=l2zm(12L);regtype[i]=&larray;}
+    for(i=25;i<=28;i++) {regsize[i]=l2zm( 8L);regtype[i]=&lltyp;}
+
+    if(ELF){
+      for(i=1;i<=MAXR;i++)
+	mregnames[i]=elfregnames[i];
+      idprefix="";
+      labprefix=".l";
+      rprefix="%";
+    }else{
+      for(i=1;i<=MAXR;i++)
+	mregnames[i]=regnames[i];
+      idprefix="_";
+      labprefix="l";
+      rprefix="";
+    }
+
+    if(SMALLDATA) use_sd=1;
+
+
+    /*  default CPU is 68000    */
+    if(!(g_flags[0]&USEDFLAG)) CPU=68000;
+    if(CPU==68040) static_cse=0; else static_cse=1;
+    if(CPU<68000) cf=1;
+    if(cf) MINADDI2P=INT; /* requires 32bit int! */
+    /*  no FPU by default       */
+    if(!(g_flags[1]&USEDFLAG)) FPU=0;
+    if(FPU<=68000) {x_t[FLOAT]='l';}
+    if(D2SCRATCH){regscratch[d2]=1;dscratch++;}
+    if(A2SCRATCH) {regscratch[a2]=1;ascratch++;}
+    if(FP2SCRATCH) {regscratch[fp2]=1;fscratch++;}
+
+    if(NOA4) regsa[5]=1;
+    if(GAS){
+        codename="\t.text\n";
+        bssname="";
+        dataname="\t.data\n";
+        if(use_sd) regsa[5]=1;
+    }else{
+        codename="\tsection\t\"CODE\",code\n";
+        if(use_sd){
+            /*  preparing small data    */
+            regsa[5]=1;
+            bssname= "\tsection\t\"__MERGED\",bss\n";
+            dataname="\tsection\t\"__MERGED\",data\n";
+        }else{
+            bssname= "\tsection\t\"BSS\",bss\n";
+            dataname="\tsection\t\"DATA\",data\n";
+        }
+    }
+    m_dataname=dataname;
+    m_bssname=bssname;
+    /*  a5 can be used if no framepointer is used.  */
+    if(!USEFRAMEPOINTER){ regsa[fbp]=0;/*fbp=sp;*/}
+    if(DEBUG&1) printf("CPU=%ld FPU=%ld\n",CPU,FPU);
+    /*  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.          */
+    t_min[CHAR]=l2zm(-128L);
+    t_min[SHORT]=l2zm(-32768L);
+    t_min[LONG]=zmsub(l2zm(-2147483647L),l2zm(1L));
+#ifdef M68K_16BIT_INT
+    t_min[INT]=t_min(SHORT);
+#else
+    t_min[INT]=t_min(LONG);
+#endif
+    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[LONG]=ul2zum(2147483647UL);
+#ifdef M68K_16BIT_INT
+    t_max[INT]=t_max(SHORT);
+#else
+    t_max[INT]=t_max(LONG);
+#endif
+    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[LONG]=ul2zum(4294967295UL);
+#ifdef M68K_16BIT_INT
+    tu_max[INT]=t_max(UNSIGNED|SHORT);
+#else
+    tu_max[INT]=t_max(UNSIGNED|LONG);
+#endif
+    tu_max[LLONG]=zumkompl(ul2zum(0UL));
+    tu_max[MAXINT]=t_max(UNSIGNED|LLONG);
+
+#ifdef M68K_16BIT_INT
+    stackalign=2;
+#endif
+
+    if(FLOAT64){
+      sizetab[FLOAT]=sizetab[DOUBLE];
+      align[FLOAT]=malign[DOUBLE];
+    }
+
+    marray[0]="__section(x)=__vattr(\"section(\"#x\")\")";
+    marray[1]="__M68K__";
+
+    if(CPU>=68000&&CPU<69000)
+      sprintf(cpu_macro,"__M%ld=1",CPU);
+    else
+      sprintf(cpu_macro,"__COLDFIRE=1");
+    marray[2]=cpu_macro;
+
+#ifdef M68K_16BIT_INT
+    marray[3]="__INTSIZE=16";
+#else
+    marray[3]="__INTSIZE=32";
+#endif
+
+    marray[4]="__stdargs=__attr(\"__stdargs;\")";
+    marray[5]="__regargs=__attr(\"__regargs;\")";
+    marray[6]="__vbccargs=__attr(\"__vbccargs;\")";
+    marray[7]="__fp0ret=__attr(\"__fp0ret;\")";
+    if(SMALLDATA) 
+      marray[8]="__SMALL_DATA__";
+    else
+      marray[8]="__LARGE_DATA__";
+
+    if(FPU==68881){
+      sprintf(fpu_macro,"__M68881=1");
+      marray[9]=fpu_macro;
+    }else if(FPU>68000&&FPU<69000){
+      sprintf(fpu_macro,"__M68882=1");
+      marray[9]=fpu_macro;
+    }else
+      marray[9]=0;
+    marray[10]=0;
+    target_macros=marray;
+
+    if(AMI_SOFTFLOAT&&!optsize){
+      declare_builtin("_ieeeaddl",FLOAT,FLOAT,d0,FLOAT,d1,1,ami_ieee("SingBas",-66));
+      declare_builtin("_ieeesubl",FLOAT,FLOAT,d0,FLOAT,d1,1,ami_ieee("SingBas",-72));
+      declare_builtin("_ieeemull",FLOAT,FLOAT,d0,FLOAT,d1,1,ami_ieee("SingBas",-78));
+      declare_builtin("_ieeedivl",FLOAT,FLOAT,d0,FLOAT,d1,1,ami_ieee("SingBas",-84));
+      declare_builtin("_ieeenegl",FLOAT,FLOAT,d0,0,0,1,ami_ieee("SingBas",-60));
+      declare_builtin("_ieeeaddd",DOUBLE,DOUBLE,d0d1,DOUBLE,d2d3,1,ami_ieee("DoubBas",-66));
+      declare_builtin("_ieeesubd",DOUBLE,DOUBLE,d0d1,DOUBLE,d2d3,1,ami_ieee("DoubBas",-72));
+      declare_builtin("_ieeemuld",DOUBLE,DOUBLE,d0d1,DOUBLE,d2d3,1,ami_ieee("DoubBas",-78));
+      declare_builtin("_ieeedivd",DOUBLE,DOUBLE,d0d1,DOUBLE,d2d3,1,ami_ieee("DoubBas",-84));
+      declare_builtin("_ieeenegd",DOUBLE,DOUBLE,d0d1,0,0,1,ami_ieee("DoubBas",-60));
+      declare_builtin("_ieees2d",DOUBLE,FLOAT,d0,0,0,1,ami_ieee("DoubTrans",-108));
+      declare_builtin("_ieeed2s",FLOAT,DOUBLE,d0d1,0,0,1,ami_ieee("DoubTrans",-102));
+      declare_builtin("_ieeefltsl",FLOAT,LONG,d0,0,0,1,ami_ieee("SingBas",-36));
+      declare_builtin("_ieeefltsd",DOUBLE,LONG,d0,0,0,1,ami_ieee("DoubBas",-36));
+      declare_builtin("_ieeefltul",FLOAT,UNSIGNED|LONG,0,0,0,1,0);
+      declare_builtin("_ieeefltud",DOUBLE,UNSIGNED|LONG,0,0,0,1,0);
+      declare_builtin("_ieeefixlsl",LONG,FLOAT,d0,0,0,1,ami_ieee("SingBas",-30));
+      declare_builtin("_ieeefixlsw",SHORT,FLOAT,d0,0,0,1,ami_ieee("SingBas",-30));
+      declare_builtin("_ieeefixlsb",CHAR,FLOAT,d0,0,0,1,ami_ieee("SingBas",-30));
+      declare_builtin("_ieeefixdsl",LONG,DOUBLE,d0d1,0,0,1,ami_ieee("DoubBas",-30));
+      declare_builtin("_ieeefixdsw",SHORT,DOUBLE,d0d1,0,0,1,ami_ieee("DoubBas",-30));
+      declare_builtin("_ieeefixdsb",CHAR,DOUBLE,d0d1,0,0,1,ami_ieee("DoubBas",-30));
+      declare_builtin("_ieeefixlul",UNSIGNED|LONG,FLOAT,0,0,0,1,0);
+      declare_builtin("_ieeefixluw",UNSIGNED|SHORT,FLOAT,0,0,0,1,0);
+      declare_builtin("_ieeefixlub",UNSIGNED|CHAR,FLOAT,0,0,0,1,0);
+      declare_builtin("_ieeefixdul",UNSIGNED|LONG,DOUBLE,0,0,0,1,0);
+      declare_builtin("_ieeefixduw",UNSIGNED|SHORT,DOUBLE,0,0,0,1,0);
+      declare_builtin("_ieeefixdub",UNSIGNED|CHAR,DOUBLE,0,0,0,1,0);
+      declare_builtin("_ieeecmpl",INT,FLOAT,d0,FLOAT,d1,1,ami_ieee("SingBas",-42));
+      declare_builtin("_ieeecmpd",INT,DOUBLE,d0d1,DOUBLE,d2d3,1,ami_ieee("DoubBas",-42));
+#if 0
+      declare_builtin("_ieeecmpllt",INT,FLOAT,0,FLOAT,0,1,0);
+      declare_builtin("_ieeecmplle",INT,FLOAT,0,FLOAT,0,1,0);
+      declare_builtin("_ieeecmplgt",INT,FLOAT,0,FLOAT,0,1,0);
+      declare_builtin("_ieeecmplge",INT,FLOAT,0,FLOAT,0,1,0);
+      declare_builtin("_ieeecmpleq",INT,FLOAT,0,FLOAT,0,1,0);
+      declare_builtin("_ieeecmplneq",INT,FLOAT,0,FLOAT,0,1,0);
+      declare_builtin("_ieeecmpdlt",INT,DOUBLE,0,DOUBLE,0,1,0);
+      declare_builtin("_ieeecmpdle",INT,DOUBLE,0,DOUBLE,0,1,0);
+      declare_builtin("_ieeecmpdgt",INT,DOUBLE,0,DOUBLE,0,1,0);
+      declare_builtin("_ieeecmpdge",INT,DOUBLE,0,DOUBLE,0,1,0);
+      declare_builtin("_ieeecmpdeq",INT,DOUBLE,0,DOUBLE,0,1,0);
+      declare_builtin("_ieeecmpdneq",INT,DOUBLE,0,DOUBLE,0,1,0);
+#endif
+      declare_builtin("_ieeetstl",INT,FLOAT,d0,0,0,1,ami_ieee("SingBas",-48));
+      declare_builtin("_ieeetstd",INT,DOUBLE,d0d1,0,0,1,ami_ieee("DoubBas",-48));
+      declare_builtin("_flt32tosint64",LLONG,FLOAT,0,0,0,1,0);
+      declare_builtin("_flt64tosint64",LLONG,DOUBLE,0,0,0,1,0);
+      declare_builtin("_flt32touint64",UNSIGNED|LLONG,FLOAT,0,0,0,1,0);
+      declare_builtin("_flt64touint64",UNSIGNED|LLONG,DOUBLE,0,0,0,1,0);
+      declare_builtin("_sint64toflt32",FLOAT,LLONG,0,0,0,1,0);
+      declare_builtin("_sint64toflt64",DOUBLE,LLONG,0,0,0,1,0);
+      declare_builtin("_uint64toflt32",FLOAT,UNSIGNED|LLONG,0,0,0,1,0);
+      declare_builtin("_uint64toflt64",DOUBLE,UNSIGNED|LLONG,0,0,0,1,0);
+    }else{
+      int pd0,pd1,pd0d1;
+      if(VBCCCALL){
+	pd0=d0;pd1=d1;pd0d1=d0d1;
+      }else{
+	pd0=pd1=pd0d1=0;
+      }
+	
+      declare_builtin("_ieeeaddl",FLOAT,FLOAT,pd0,FLOAT,pd1,1,0);
+      declare_builtin("_ieeesubl",FLOAT,FLOAT,pd0,FLOAT,pd1,1,0);
+      declare_builtin("_ieeemull",FLOAT,FLOAT,pd0,FLOAT,pd1,1,0);
+      declare_builtin("_ieeedivl",FLOAT,FLOAT,pd0,FLOAT,pd1,1,0);
+      declare_builtin("_ieeenegl",FLOAT,FLOAT,pd0,0,0,1,0);
+      declare_builtin("_ieeeaddd",DOUBLE,DOUBLE,pd0d1,DOUBLE,0,1,0);
+      declare_builtin("_ieeesubd",DOUBLE,DOUBLE,pd0d1,DOUBLE,0,1,0);
+      declare_builtin("_ieeemuld",DOUBLE,DOUBLE,pd0d1,DOUBLE,0,1,0);
+      declare_builtin("_ieeedivd",DOUBLE,DOUBLE,pd0d1,DOUBLE,0,1,0);
+      declare_builtin("_ieeenegd",DOUBLE,DOUBLE,pd0d1,0,0,1,0);
+      declare_builtin("_ieees2d",DOUBLE,FLOAT,pd0,0,0,1,0);
+      declare_builtin("_ieeed2s",FLOAT,DOUBLE,pd0d1,0,0,1,0);
+      declare_builtin("_ieeefltsl",FLOAT,LONG,pd0,0,0,1,0);
+      declare_builtin("_ieeefltsd",DOUBLE,LONG,pd0,0,0,1,0);
+      declare_builtin("_ieeefltul",FLOAT,UNSIGNED|LONG,pd0,0,0,1,0);
+      declare_builtin("_ieeefltud",DOUBLE,UNSIGNED|LONG,pd0,0,0,1,0);
+      declare_builtin("_ieeefixlsl",LONG,FLOAT,pd0,0,0,1,0);
+      declare_builtin("_ieeefixlsw",SHORT,FLOAT,pd0,0,0,1,0);
+      declare_builtin("_ieeefixlsb",CHAR,FLOAT,pd0,0,0,1,0);
+      declare_builtin("_ieeefixdsl",LONG,DOUBLE,pd0d1,0,0,1,0);
+      declare_builtin("_ieeefixdsw",SHORT,DOUBLE,pd0d1,0,0,1,0);
+      declare_builtin("_ieeefixdsb",CHAR,DOUBLE,pd0d1,0,0,1,0);
+      declare_builtin("_ieeefixlul",UNSIGNED|LONG,FLOAT,pd0,0,0,1,0);
+      declare_builtin("_ieeefixluw",UNSIGNED|SHORT,FLOAT,pd0,0,0,1,0);
+      declare_builtin("_ieeefixlub",UNSIGNED|CHAR,FLOAT,pd0,0,0,1,0);
+      declare_builtin("_ieeefixdul",UNSIGNED|LONG,DOUBLE,pd0d1,0,0,1,0);
+      declare_builtin("_ieeefixduw",UNSIGNED|SHORT,DOUBLE,pd0d1,0,0,1,0);
+      declare_builtin("_ieeefixdub",UNSIGNED|CHAR,DOUBLE,pd0d1,0,0,1,0);
+      declare_builtin("_ieeefixdub",UNSIGNED|CHAR,DOUBLE,pd0d1,0,0,1,0);
+      declare_builtin("_ieeecmpl",INT,FLOAT,pd0,FLOAT,pd1,1,0);
+      declare_builtin("_ieeecmpd",INT,DOUBLE,pd0d1,DOUBLE,0,1,0);
+#if 0
+      declare_builtin("_ieeecmpllt",INT,FLOAT,0,FLOAT,0,1,0);
+      declare_builtin("_ieeecmplle",INT,FLOAT,0,FLOAT,0,1,0);
+      declare_builtin("_ieeecmplgt",INT,FLOAT,0,FLOAT,0,1,0);
+      declare_builtin("_ieeecmplge",INT,FLOAT,0,FLOAT,0,1,0);
+      declare_builtin("_ieeecmpleq",INT,FLOAT,0,FLOAT,0,1,0);
+      declare_builtin("_ieeecmplneq",INT,FLOAT,0,FLOAT,0,1,0);
+      declare_builtin("_ieeecmpdlt",INT,DOUBLE,0,DOUBLE,0,1,0);
+      declare_builtin("_ieeecmpdle",INT,DOUBLE,0,DOUBLE,0,1,0);
+      declare_builtin("_ieeecmpdgt",INT,DOUBLE,0,DOUBLE,0,1,0);
+      declare_builtin("_ieeecmpdge",INT,DOUBLE,0,DOUBLE,0,1,0);
+      declare_builtin("_ieeecmpdeq",INT,DOUBLE,0,DOUBLE,0,1,0);
+      declare_builtin("_ieeecmpdneq",INT,DOUBLE,0,DOUBLE,0,1,0);
+#endif
+      declare_builtin("_ieeetstl",INT,FLOAT,pd0,0,0,1,0);
+      declare_builtin("_ieeetstd",INT,DOUBLE,pd0d1,0,0,1,0);
+      declare_builtin("_flt32tosint64",LLONG,FLOAT,pd0,0,0,1,0);
+      declare_builtin("_flt64tosint64",LLONG,DOUBLE,pd0d1,0,0,1,0);
+      declare_builtin("_flt32touint64",UNSIGNED|LLONG,FLOAT,pd0,0,0,1,0);
+      declare_builtin("_flt64touint64",UNSIGNED|LLONG,DOUBLE,pd0d1,0,0,1,0);
+      declare_builtin("_sint64toflt32",FLOAT,LLONG,pd0d1,0,0,1,0);
+      declare_builtin("_sint64toflt64",DOUBLE,LLONG,pd0d1,0,0,1,0);
+      declare_builtin("_uint64toflt32",FLOAT,UNSIGNED|LLONG,pd0d1,0,0,1,0);
+      declare_builtin("_uint64toflt64",DOUBLE,UNSIGNED|LLONG,pd0d1,0,0,1,0);
+    }
+    {
+      char *asm;
+      declare_builtin("_divs",LONG,LONG,d0,LONG,d1,1,0);
+      declare_builtin("_divu",LONG,LONG,d0,LONG,d1,1,0);
+#define SMODS "\tjsr\t__divs\n\tmove.l\td1,d0"
+#define SMODU "\tjsr\t__divu\n\tmove.l\td1,d0"
+      asm=mymalloc(strlen(SMODS)+1);
+      strcpy(asm,SMODS);
+      declare_builtin("_mods",LONG,LONG,d0,LONG,d1,1,asm);
+      asm=mymalloc(strlen(SMODU)+1);
+      strcpy(asm,SMODU);
+      declare_builtin("_modu",LONG,LONG,d0,LONG,d1,1,asm);
+    }
+    declare_builtin("_lshint64",LLONG,LLONG,0,INT,0,1,0);
+    declare_builtin("_rshsint64",LLONG,LLONG,0,INT,0,1,0);
+    declare_builtin("_rshuint64",(UNSIGNED|LLONG),(UNSIGNED|LLONG),0,INT,0,1,0);
+
+    return 1;
+}
+
+int freturn(type *t)
+/*  Returns the register in which variables of type t are returned. */
+/*  If the value cannot be returned in a register returns 0.        */
+{
+    long l;int tu=t->flags&NQ;
+    if(t->attr&&ISFLOAT(tu)&&FPU>68000&&strstr(t->attr,"__fp0ret;")) return fp0;
+    if(tu==FLOAT&&FLOAT64) tu+=DOUBLE-FLOAT;
+    if(tu==FLOAT){
+        if(FPU>68000&&!NOFPRETURN)
+            return fp0;
+        else
+            return d0;
+    }
+    if(tu==DOUBLE||tu==LDOUBLE){
+        if(FPU>68000&&!NOFPRETURN){
+            return fp0;
+        }else{
+            if(NOMREGRETURN) return 0;
+#if NEW_RET
+            return d0d1;
+#else
+	    return d0;
+#endif
+        }
+    }
+    if(tu==STRUCT||tu==UNION){
+        if(!NOMREGRETURN){
+            l=zm2l(szof(t));
+#if NEW_RET
+	    if(l==4) return d0;
+	    if(l==8) return d0d1;
+	    /* alte Variante; unschoen */
+	    if(l==12) return d0;
+	    if(l==16) return d0;
+#else
+            if(l==4||l==8||l==12||l==16) return d0;
+#endif
+        }
+        return 0;
+    }
+    if(tu==LLONG)
+      return d0d1;
+    if(zmleq(szof(t),l2zm(4L))) return d0; else return 0;
+}
+int cost_savings(IC *p,int r,obj *o)
+{
+  int c=p->code;
+  if((r==a6||r==d7||r==d6d7||r==fp7)&&!RESERVEREGS) return -1;
+  if(c==SETRETURN&&r==p->z.reg&&!(o->flags&DREFOBJ)) return 3;
+  if(c==GETRETURN&&r==p->q1.reg&&!(o->flags&DREFOBJ)) return 3;
+  if(o->flags&VKONST){
+    int t;
+    if(CPU==68040) return 0;
+    t=o->v->ctyp&NQ;
+    if(ISFLOAT(t)) return 2;
+    if(t==CHAR&&r>=a0&&r<=a7) return 0/*INT_MIN*/;
+    if(t==LLONG) return 0;
+    if(cf&&(t<INT)&&p->q2.flags) return 0/*INT_MIN*/;
+    eval_const(&o->v->cobj.val,t);
+    if(zmeqto(vmax,Z0)) return 0;
+    if(o->flags&DREFOBJ) return 2;
+    if((p->code==ASSIGN&&o==&p->q1)||p->code==PUSH||p->code==SETRETURN){
+      if(p->code==PUSH||(p->z.flags&DREFOBJ)||
+	 ((p->z.flags&VAR)&&(p->z.v->storage_class==STATIC||p->z.v->storage_class==EXTERN))){
+	if(r>=d0&&r<=d7)
+	  return 2;
+	else
+	  return 1;
+      }
+      return 0;
+    }
+    if(c==ADDI2P||c==SUBIFP){
+      if(zmleq(vmax,l2zm(32767L))&&zmleq(l2zm(-32768L),vmax)) return 0;
+      if(r>=d0&&r<=d7)
+	return 3;
+      return CPU<68020?1:0;
+    }
+    if(c==ADD||c==SUB||c==ADDI2P||c==SUBIFP||c==SUBPFP){
+      if(zmleq(vmax,l2zm(8L))&&zmleq(l2zm(-8L),vmax)) return 0;
+      if(p->flags&EFF_IC) return 0;
+      if(r>=d0&&r<=d7)
+	return 2;
+      else
+	return 1;
+    }
+    if(c==COMPARE){
+      if(r>=d0&&r<=d7)
+	return 2;
+      else
+	return 1;
+    }
+    if(r>=a0&&r<=a7) return INT_MIN;
+    /* TODO: which allocations are useful? */
+    return 0;
+  }
+  if(o->flags&DREFOBJ){
+    if(r>=a0&&r<=a7){
+      return 4;
+    }
+  }
+  if((c==ADDI2P||c==SUBIFP||c==ADDRESS)&&(o==&p->q1||o==&p->z)&&r>=a0&&r<=a7){
+    return 4;
+  }
+  if(r>=a0&&r<=a7){
+    if(o->flags&DREFOBJ) ierror(0);
+    if(c!=GETRETURN&&c!=SETRETURN&&c!=ASSIGN&&c!=PUSH&&c!=TEST&&c!=COMPARE&&c!=CONVERT){
+      if(c==ADDI2P||c==SUBIFP){
+	if(o==&p->q2)
+	  return INT_MIN;
+      }else if(c==SUBPFP){
+	if(o==&p->z)
+	  return INT_MIN;
+      }else{
+	return INT_MIN;
+      }
+    }
+    if(c==CONVERT&&((p->typf&NQ)==CHAR||(p->typf2&NQ)==CHAR||ISFLOAT(p->typf)||ISFLOAT(p->typf2)))
+      return INT_MIN;
+  }
+
+  if(c==TEST&&r>=d0&&r<=d7){
+    return 3;
+  }
+  if(o==&p->z&&(p->q1.flags&VKONST)){
+    eval_const(&p->q1.v->cobj.val,p->q1.v->ctyp&NQ);
+    if(zmleq(vmax,l2zm(127L))&&zmleq(l2zm(-128L),vmax)&&r>=d0&&r<=d7)
+      return 3;
+  }
+  return 2;
+}
+
+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(r==0) return 0;
+  t&=NQ;
+  if(ISFLOAT(t)){
+    if(FPU>68000){
+      if(r>=fp0&&r<=fp7) return(1); else return 0;
+    }else{
+      if(t==FLOAT&&!FLOAT64)
+	return (r>=d0&&r<=d7);
+      else
+	return (r>=25&&r<=28);
+    }
+  }
+  if(t==POINTER&&mode<=0&&r>=d0&&r<=d7) return 1;
+  if(t==POINTER&&r>=1&&r<=8) return 1;
+  if(t>=CHAR&&t<=LONG){
+    if((r>=d0&&r<=d7)||(mode==-1&&t>=SHORT&&r>=1&&r<=8)) return 1;
+  }
+  if(t==LLONG&&r>=25&&r<=28) return 1;
+  return 0;
+}
+
+int dangerous_IC(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;
+}
+
+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;
+    /*  All pointers have the same representation.  */
+    if(tp==POINTER&&op==POINTER) return 0;
+    /*  Pointer and int/long as well   */
+    if(const_expr){
+#ifdef M68K_16BIT_INT
+      if(tp==POINTER&&(op==LONG)) return 0;
+      if(op==POINTER&&(tp==LONG)) return 0;
+#else
+      if(tp==POINTER&&(op==INT||op==LONG)) return 0;
+      if(op==POINTER&&(tp==INT||tp==LONG)) return 0;
+#endif
+    }
+    /*  Signed und Unsigned integers with the same size, too.  */
+    if(op==tp) return 0;
+#ifdef M68K_16BIT_INT
+    /*  int==short   */
+    if((tp==INT&&op==SHORT)||(tp==SHORT&&op==INT)) return 0;
+#else
+    /*  int==long   */
+    if((tp==INT&&op==LONG)||(tp==LONG&&op==INT)) return 0;
+#endif
+    if(FLOAT64&&ISFLOAT(op)&&ISFLOAT(tp)) return 0;
+    /* long double==double */
+    if((op==DOUBLE||op==LDOUBLE)&&(tp==DOUBLE||tp==LDOUBLE)) return 0;
+    return 1;
+}
+
+void gen_ds(FILE *f,zmax size,type *t)
+/*  This function has to create <size> bytes of storage */
+/*  initialized with zero.                              */
+{
+  title(f);
+  if(GAS){
+    if(newobj&&section!=SPECIAL)
+      emit(f,"%ld\n",zm2l(size));
+    else
+      emit(f,"\t.space\t%ld\n",zm2l(size));
+    newobj=0;
+  }else{
+    /*if(section!=BSS&&section!=SPECIAL&&newobj){emit(f,bssname);if(f) section=BSS;}*/
+    emit(f,"\tds.b\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.              */
+{
+  title(f);
+  if(zm2l(align)>1){
+    if(GAS){
+      emit(f,"\t.align\t4\n");
+    }else{
+      emit(f,"\tcnop\t0,4\n");
+    }
+  }
+}
+void gen_var_head(FILE *f,Var *v)
+/*  This function has to create the head of a variable  */
+/*  definition, i.e. the label and information for      */
+/*  linkage etc.                                        */
+{
+  int constflag;
+  title(f);
+  if(v->clist) constflag=is_const(v->vtyp);
+  if(v->tattr&(FAR|CHIP)){
+    if(v->tattr&CHIP){
+      dataname="\tsection\t\"CHIP_DATA\",data,chip\n";
+      bssname="\tsection\t\"CHIP_BSS\",bss,chip\n";
+    }else{
+      dataname="\tsection\t\"DATA\",data\n";
+      bssname="\tsection\t\"BSS\",bss\n";
+    }
+    if(f) section=-1;
+  }else{
+    dataname=m_dataname;
+    bssname=m_bssname;
+  }
+  if(v->storage_class==STATIC){
+    if(ISFUNC(v->vtyp->flags)) return;
+    if(!special_section(f,v)){
+      if(v->clist&&(!constflag||CONSTINDATA/*||use_sd*/)&&section!=DATA){emit(f,dataname);if(f) section=DATA;}
+      if(v->clist&&constflag&&!CONSTINDATA/*&&!use_sd*/&&section!=CODE){emit(f,codename);if(f) section=CODE;}
+      if(!v->clist&&section!=BSS){emit(f,bssname);if(f) section=BSS;}
+    }
+    if(GAS){
+      if(section!=BSS) emit(f,"\t.align\t4\n%s%ld:\n",labprefix,zm2l(v->offset));
+      else emit(f,"\t.comm\t%s%ld,",labprefix,zm2l(v->offset));
+    }else{
+      emit(f,"\tcnop\t0,4\n%s%ld\n",labprefix,zm2l(v->offset));
+    }
+    newobj=1;
+  }
+  if(v->storage_class==EXTERN){
+    if(GAS){
+      emit(f,"\t.global\t%s%s\n",ISFUNC(v->vtyp->flags)?FUNCPREFIX(v->vtyp):idprefix,v->identifier);
+    }else{
+      emit(f,"\tpublic\t%s%s\n",ISFUNC(v->vtyp->flags)?FUNCPREFIX(v->vtyp):idprefix,v->identifier);
+    }
+    if(v->flags&(DEFINED|TENTATIVE)){
+      if(!special_section(f,v)){
+	if(v->clist&&(!constflag||CONSTINDATA/*||use_sd*/)&&section!=DATA){emit(f,dataname);if(f) section=DATA;}
+	if(v->clist&&constflag&&!CONSTINDATA/*&&!use_sd*/&&section!=CODE){emit(f,codename);if(f) section=CODE;}
+	if(!v->clist&&section!=BSS){emit(f,bssname);if(f) section=BSS;}
+      }
+      if(GAS){
+	if(section!=BSS)
+	  emit(f,"\t.align\t4\n%s%s:\n",idprefix,v->identifier);
+	else
+	  emit(f,"\t.global\t%s%s\n\t.%scomm\t%s%s,",idprefix,v->identifier,(USE_COMMONS?"":"l"),idprefix,v->identifier);
+      }else{
+	emit(f,"\tcnop\t0,4\n%s%s\n",idprefix,v->identifier);
+      }
+      newobj=1;
+    }
+  }
+  if(v->tattr&(FAR|CHIP)) {if(f) section=-1;newobj=0;}
+}
+void gen_dc(FILE *f,int t,const_list *p)
+/*  This function has to create static storage          */
+/*  initialized with const-list p.                      */
+{
+  char s;
+  title(f);
+  if(!p) ierror(0);
+/*    if(section!=DATA){emit(f,dataname);if(f) section=DATA;}*/
+  if(ISFLOAT(t)||(t&NQ)==LLONG) s='l'; else s=x_t[t&NQ];
+  if(GAS){
+    char *str;
+    if(s=='b') str="\t.byte\t";
+    else if(s=='w') str="\t.short\t";
+    else if(s=='l') str="\t.long\t";
+    else ierror(0);
+    emit(f,"%s",str);
+  }else{
+    emit(f,"\tdc.%c\t",s);
+  }
+  if(!p->tree){
+    if(ISFLOAT(t)){
+      /*  auch wieder nicht sehr schoen und IEEE noetig   */
+      unsigned char *ip;char *s;
+      ip=(unsigned char *)&p->val.vdouble;
+      if(GAS) s="0x"; else s="$";
+      emit(f,"%s%02x%02x%02x%02x",s,ip[0],ip[1],ip[2],ip[3]);
+      if((t&NQ)!=FLOAT){
+	emit(f,",%s%02x%02x%02x%02x",s,ip[4],ip[5],ip[6],ip[7]);
+      }
+    }else if((t&NQ)==LLONG){
+      zumax tmp;
+      eval_const(&p->val,t);
+      tmp=vumax;
+      vumax=zumand(zumrshift(vumax,ul2zum(32UL)),ul2zum(0xffffffff)); 
+      gval.vulong=zum2zul(vumax);
+      emitval(f,&gval,UNSIGNED|LONG);
+      emit(f,",");
+      vumax=zumand(tmp,ul2zum(0xffffffff)); 
+      gval.vulong=zum2zul(vumax);
+      emitval(f,&gval,UNSIGNED|LONG);
+    }else{
+      emitval(f,&p->val,t&NU);
+    }
+  }else{
+    int m,m2,m3;
+    p->tree->o.am=0;
+    m=p->tree->o.flags;
+    p->tree->o.flags&=~VARADR;
+    m2=g_flags[5];
+    g_flags[5]&=~USEDFLAG;
+    m3=use_sd;
+    use_sd=0;
+    emit_obj(f,&p->tree->o,t&NU);
+    p->tree->o.flags=m;
+    g_flags[5]=m2;
+    use_sd=m3;
+  }
+  emit(f,"\n");newobj=0;
+}
+
+static void allocreg(int r)
+{
+  if(reg_pair(r,&rp)){
+    regs[rp.r1]=1;
+    regs[rp.r2]=1;
+  }
+  regs[r]=1;
+}
+
+static void freereg(int r)
+{
+  if(reg_pair(r,&rp)){
+    regs[rp.r1]=0;
+    regs[rp.r2]=0;
+  }
+  regs[r]=0;
+}
+
+/*  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,IC *p,Var *v,zmax offset)
+{
+  int c,t;char fp[2]="\0\0";
+  int act_line=0;char *act_file=0;
+  int shiftisdiv;
+  if(DEBUG&1) printf("gen_code()\n");
+  for(c=1;c<=MAXR;c++) regs[c]=regsa[c];
+  if(!NOPEEPHOLE){
+    /*  Adressierungsarten benutzen */
+    if(!addressing(p)) offset=l2zm(0L);
+  }
+  title(f);
+  if(debug_info){
+    if(HUNKDEBUG){
+      if(!GAS){
+	act_line=1;
+	emit(f,"\tdsource\t\"%s\"\n",filename);
+	emit(f,"\tdebug\t%d\n",act_line);
+      }
+    }
+  }
+  reglabel=++label;freglabel=++label;
+  function_top(f,v,zm2l(offset));
+  cc_set=cc_set_tst=0;
+  stackoffset=notpopped=dontpop=maxpushed=0;
+  for(c=1;c<=MAXR;c++){
+    if(regsa[c]||regused[c]){
+      BSET(regs_modified,c);
+    }
+  }
+  for(;p;pr(f,p),p=p->next){
+    if(debug_info){
+      if(HUNKDEBUG){
+	if(p->file&&p->file!=act_file){
+	  act_file=p->file;
+	  if(!GAS) emit(f,"\tdsource\t\"%s\"\n",act_file);
+	}
+	if(p->line&&p->line!=act_line){
+	  act_line=p->line;
+	  if(!GAS) emit(f,"\tdebug\t%d\n",act_line);
+	}
+      }else{
+	dwarf2_line_info(f,p);
+      }
+    }
+
+    if(FLOAT64){
+      if(p->code==CONVERT)
+	if((q1typ(p)&NQ)==FLOAT) p->typf2+=DOUBLE-FLOAT;
+      if((ztyp(p)&NQ)==FLOAT) p->typf+=DOUBLE-FLOAT;
+    }
+
+    c=p->code;t=p->typf;
+    if(c==NOP) continue;
+    cc_set_tst=cc_set;
+    cc_typ_tst=cc_typ;
+    shiftisdiv=0;
+    if(cc_set_tst&&(DEBUG&512)){emit(f,"; cc_set_tst=");emit_obj(f,cc_set_tst,t);emit(f,"\n");}
+    if(cc_set&&(DEBUG&512)){emit(f,"; cc_set=");emit_obj(f,cc_set,t);emit(f,"\n");}
+    pushedreg&=16;if(c==RESTOREREGS) pushedreg=0;
+    if(DEBUG&256){emit(f,"; "); pric2(f,p);}
+    if(DEBUG&512) emit(f,"; stackoffset=%ld, notpopped=%ld, pushedreg=%d, dontpop=%ld\n",stackoffset,notpopped,pushedreg,dontpop);
+    /*  muessen wir Argumente poppen?   */
+    if(notpopped&&!dontpop){
+      int flag=0;
+      if(c==LABEL||c==COMPARE||c==TEST||c==BRA){
+	emit(f,"\tadd%s.%s\t#%ld,%s\n",quick[notpopped<=8],strshort[notpopped<32768],notpopped,mregnames[sp]);
+	pop(notpopped);notpopped=0;/*cc_set_tst=cc_set=0;*/
+      }
+    }
+    /*  na, ob das hier ok ist..?   */
+    if(c==SUBPFP) c=SUB;
+    if(c==PMULT) c=MULT;
+    if(c==ALLOCREG){
+      allocreg(p->q1.reg);
+      continue;
+    }
+    if(c==FREEREG){
+      freereg(p->q1.reg);
+      continue;
+    }
+    if(c==LABEL){
+      if(debug_info&&HUNKDEBUG) act_line=0;
+      if(GAS){
+	emit(f,"%s%d:\n",labprefix,t);
+      }else{
+	emit(f,"%s%d\n",labprefix,t);
+      }
+      cc_set=0;continue;
+    }
+    if(c==BRA){emit(f,"\t%sbra\t%s%d\n",(GAS?"j":""),labprefix,t);continue;}
+    if(c>=BEQ&&c<BRA){
+      if(GAS){
+	if(stored_cc){emit(f,"\tjne\t%s%d\n",labprefix,t);stored_cc=0;continue;}
+	if((comptyp&UNSIGNED)||(comptyp&NQ)==POINTER){
+	  emit(f,"\tj%s\t%s%d\n",ubranch[c-BEQ],labprefix,t);
+	}else{
+	  emit(f,"\t%sj%s\t%s%d\n",fp,ename[c]+1,labprefix,t);
+	}
+      }else{
+	if(stored_cc){emit(f,"\tbne\t%s%d\n",labprefix,t);stored_cc=0;continue;}
+	if((comptyp&UNSIGNED)||(comptyp&NQ)==POINTER){
+	  emit(f,"\tb%s\t%s%d\n",ubranch[c-BEQ],labprefix,t);
+	}else{
+	  emit(f,"\t%s%s\t%s%d\n",fp,ename[c],labprefix,t);
+	}
+      }
+      continue;
+    }
+#if 0
+    if(CPU>=68020&&(c==LSHIFT||c==MULT)&&(p->q2.flags&(KONST|DREFOBJ))==KONST&&isreg(z)&&p->z.reg>=d0&&p->z.reg<=d7&&ISINT(p->typf)){
+      int l=0;
+      eval_const(&p->q2.val,q2typ(p));
+      if(c==LSHIFT&&zmeqto(vmax,l2zm(1L))) l=2;
+      if(c==LSHIFT&&zmeqto(vmax,l2zm(2L))) l=4;
+      if(c==LSHIFT&&zmeqto(vmax,l2zm(3L))) l=8;
+      if(c==MULT&&zmeqto(vmax,l2zm(2L))) l=2;
+      if(c==MULT&&zmeqto(vmax,l2zm(4L))) l=4;
+      if(c==MULT&&zmeqto(vmax,l2zm(8L))) l=8;
+      if(l!=0){
+	IC *p2=p->next;
+	while(p2&&(p2->code==ALLOCREG||p2->code==FREEREG)) p2=p2->next;
+	if((p2->code==ADD||p2->code==ADDI2P)&&(p2->q2.flags&(REG|DREFOBJ))==REG&&p2->q2.reg==p->z.reg&&(p2->typf&NU)==(p->typf&NU)&&(p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg>=a0&&p2->q1.reg<=a7&&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg>=a0&&p2->z.reg<=a7){
+	  IC *p3=p2->next;
+	  while(p3&&p3->code==FREEREG) if(p3&&p3->q1.reg==p->z.reg) break;
+	  if(p3&&p3->code==FREEREG&&p3->q1.reg==p->z.reg){
+	    int r;
+	    if(isreg(q1)&&p->q1.reg>=d0&&p->q1.reg<=d7)
+	      r=p->q1.reg;
+	    else{
+	      move(f,&p->q1,0,0,p->z.reg,p->typf);
+	      r=p->z.reg;
+	    }
+	    emit(f,"\tlea\t(%s,%s.%c*%d),%s\n",mregnames[p2->q1.reg],mregnames[r],sizetab[p->typf&NQ]==2?'w':'l',l,mregnames[p2->z.reg]);
+	    p->code=NOP;
+	    p->q1.flags=p->q2.flags=p->z.flags=0;
+	    p2->code=NOP;
+	    p2->q1.flags=p2->q2.flags=p2->z.flags=0;
+	    continue;
+	  }
+	}
+      }
+    }
+#endif
+    if(c==COMPARE&&isconst(q2)&&!cf&&(t&NQ)!=LLONG){
+      case_table *ct=calc_case_table(p,JUMP_TABLE_DENSITY);
+      IC *p2;
+      if(ct&&(ct->num>=JUMP_TABLE_LENGTH||(!isreg(q1)&&ct->num>=JUMP_TABLE_LENGTH/2))){
+	int r,defl,tabl=++label,rts=0,i,ar=0;
+	if(ct->next_ic->code==BRA)
+	  defl=ct->next_ic->typf;
+	else
+	  defl=++label;
+	for(r=d0;r<=d7;r++)
+	  if(!regs[r]) break;
+	if(r>d7){
+	  if((!(p->q1.flags&REG))||p->q1.reg!=d0)
+	    r=d0;
+	  else
+	    r=d1;
+	  emit(f,"\tsubq.%s\t#4,%s\n",cf?"l":"w",mregnames[sp]);
+	  emit(f,"\tmove.l\t%s,-(%s)\n",mregnames[r],mregnames[sp]);
+	  push(8);
+	}else{
+	  regused[r]=1;
+	  BSET(regs_modified,r);
+	}
+	if(!regs[r]||(p->q1.flags&(REG|DREFOBJ))==DREFOBJ){
+	  for(ar=1;ar<sp;ar++)
+	    if(!regs[ar]) break;
+	  if(ar>=sp){
+	    ar=a0;
+	    if(!regs[r]){
+	      emit(f,"\tsubq.%s\t#4,%s\n",cf?"l":"w",mregnames[sp]);
+	      push(4);
+	    }
+	    emit(f,"\tmove.l\t%s,-(%s)\n",mregnames[ar],mregnames[sp]);
+	    push(4);
+	  }else{
+	    regused[ar]=1;
+	    BSET(regs_modified,ar);
+	  }
+	}
+	if(regs[r]||(ar&&regs[ar])) defl=++label;
+	if(!p->q1.am&&(p->q1.flags&(REG|DREFOBJ))==DREFOBJ){
+	  p->q1.flags&=~DREFOBJ;
+	  move(f,&p->q1,0,0,ar,POINTER);
+	  p->q1.flags|=(REG|DREFOBJ);
+	  p->q1.flags&=~VAR;
+	  p->q1.reg=ar;
+	}
+	if((t&NU)==(UNSIGNED|CHAR))
+	  emit(f,"\tmoveq\t#0,%s\n",mregnames[r]);
+	move(f,&p->q1,0,0,r,t);
+	if((t&NU)==CHAR){
+	  emit(f,"\text.w\t%s\n",mregnames[r]);
+	  t=SHORT;
+	}
+	if((t&NU)==(UNSIGNED|CHAR))
+	  t=(UNSIGNED|SHORT);
+	if(((t&UNSIGNED)&&!zumeqto(ct->min.vumax,ul2zum(0UL)))||
+	   (!(t&UNSIGNED)&&!zmeqto(ct->min.vmax,l2zm(0L)))){
+	  emit(f,"\tsub.%c\t#",x_t[t&NQ]);
+	  if(t&UNSIGNED)
+	    emitzum(f,ct->min.vumax);
+	  else
+	    emitzm(f,ct->min.vmax);
+	  emit(f,",%s\n",mregnames[r]);
+	}
+	emit(f,"\tcmp.%c\t#",x_t[t&NQ]);
+	emitzum(f,ct->diff);
+	emit(f,",%s\n",mregnames[r]);
+	if(regs[r]||regs[ar])
+	  emit(f,"\tbhi\t%s%d\n",labprefix,++label);
+	else
+	  emit(f,"\tbhi\t%s%d\n",labprefix,defl);
+	if(CPU<68020)
+	  emit(f,"\tlsl.%c\t#2,%s\n",x_t[t&NQ],mregnames[r]);
+	for(i=MAXR;i>=1;i--)
+	  if(regs[i]&4) rts=1;
+	if(regs[r]||regs[ar]){
+	  int off;
+	  if(regs[r]) off=4; else off=0;
+	  if(ar&&regs[ar]) off+=4;
+	  if(CPU>=68020)
+	    emit(f,"\tmove.l\t%s%d(%spc,%s.%c*4),%d(%s)\n",labprefix,tabl,rprefix,mregnames[r],x_t[t&NQ],off,mregnames[sp]);
+	  else
+	    emit(f,"\tmove.l\t%s%d(%spc,%s.%c),%d(%s)\n",labprefix,tabl,rprefix,mregnames[r],x_t[t&NQ],off,mregnames[sp]);
+	  if(ar&&regs[ar]){
+	    emit(f,"\tmove.l\t(%s)+,%s\n",mregnames[sp],mregnames[ar]);
+	    pop(4);
+	  }	      
+	  if(regs[r]){
+	    emit(f,"\tmove.l\t(%s)+,%s\n",mregnames[sp],mregnames[r]);
+	    pop(4);
+	  }
+	  emit(f,"\trts\n");
+	  pop(4);
+	}else{
+	  if(CPU>=68020)
+	    emit(f,"\tmove.l\t%s%d(%spc,%s.%c*4),%s\n",labprefix,tabl,rprefix,mregnames[r],x_t[t&NQ],mregnames[ar]);
+	  else
+	    emit(f,"\tmove.l\t%s%d(%spc,%s.%c),%s\n",labprefix,tabl,rprefix,mregnames[r],x_t[t&NQ],mregnames[ar]);
+	  emit(f,"\tjmp\t(%s)\n",mregnames[ar]);
+	}
+	if(GAS){
+	  emit(f,"\t.align\t2\n");
+	  emit(f,"%s%d:\n",labprefix,tabl);
+	  emit_jump_table(f,ct,"\t.long\t","l",defl);
+	}else{
+	  emit(f,"\tcnop\t0,4\n");
+	  emit(f,"%s%d\n",labprefix,tabl);
+	  emit_jump_table(f,ct,"\tdc.l\t","l",defl);
+	}
+	if(ct->next_ic->code!=BRA||regs[r]||(ar&&regs[ar])){
+	  if(regs[r]||(ar&&regs[ar])){
+	    emit(f,"%s%d%s\n",labprefix,label,GAS?":":"");
+	    if(ar&&regs[ar])
+	      emit(f,"\tmove.l\t(%s)+,%s\n",mregnames[sp],mregnames[ar]);
+	    if(regs[r])
+	      emit(f,"\tmove.l\t(%s)+,%s\n",mregnames[sp],mregnames[r]);
+	    emit(f,"\taddq.%c\t#4,%s\n",cf?'l':'w',mregnames[sp]);
+	  }
+	  emit(f,"%s%d%s\n",labprefix,defl,GAS?":":"");
+	  p2=ct->next_ic->prev;
+	}else
+	  p2=ct->next_ic;
+	if(p->prev) p=p->prev;
+	do{
+	  p=p->next;
+	  if(p->code==ALLOCREG)
+	    allocreg(p->q1.reg);
+	  if(p->code==FREEREG)
+	    freereg(p->q1.reg);
+	}while(p!=p2);
+	continue;
+      }
+    }
+    if(p->q1.am){
+      if(!regs[p->q1.am->basereg]){
+	pric2(stdout,p);printf("%s\n",mregnames[p->q1.am->basereg]); ierror(0);
+      }
+      if(p->q1.am->dreg&&!regs[p->q1.am->dreg&127]){
+	printf("Register %s:\n",mregnames[p->q1.am->dreg&127]);
+	ierror(0);
+      }
+    }
+    if(p->q2.am){
+      if(!regs[p->q2.am->basereg]) {pric2(stdout,p);ierror(0);}
+      if(p->q2.am->dreg&&!regs[p->q2.am->dreg&127]) {printf("Register %s:\n",mregnames[p->q2.am->dreg&127]);ierror(0);}
+    }
+    if(p->z.am){
+      if(!regs[p->z.am->basereg]) {pric2(stdout,p);printf("am=%p b=%s,i=%s,o=%ld,s=%d\n",(void*)p->z.am,mregnames[p->z.am->basereg],mregnames[p->z.am->dreg&127],p->z.am->dist,p->z.am->skal);ierror(0);}
+      if(p->z.am->dreg&&!regs[p->z.am->dreg&127]) {printf("Register %s:\n",mregnames[p->z.am->dreg&127]);ierror(0);}
+    }
+    if((p->q1.flags&REG)&&!regs[p->q1.reg]&&p->code!=MOVEFROMREG&&(!reg_pair(p->q1.reg,&rp)||!regs[rp.r1]||!regs[rp.r2])){
+      printf("Register %s:\n",mregnames[p->q1.reg]);pric2(stdout,p);terror("illegal use of register");}
+    if((p->q2.flags&REG)&&!regs[p->q2.reg]&&(!reg_pair(p->q2.reg,&rp)||!regs[rp.r1]||!regs[rp.r2])){printf("Register %s:\n",mregnames[p->q2.reg]);pric2(stdout,p);terror("illegal use of register");}
+    if((p->z.flags&REG)&&!regs[p->z.reg]&&p->code!=MOVETOREG&&(!reg_pair(p->z.reg,&rp)||!regs[rp.r1]||!regs[rp.r2])){printf("Register %s:\n",mregnames[p->z.reg]);if(reg_pair(p->z.reg,&rp)) printf("%s=%d %s=%d\n",regnames[rp.r1],regs[rp.r1],regnames[rp.r2],regs[rp.r2]);pric2(stdout,p);terror("illegal use of register");}
+    /*        if((p->q2.flags&REG)&&(p->z.flags&REG)&&p->q2.reg==p->z.reg){pric2(stdout,p);ierror(0);}*/
+    /*if((p->q2.flags&VAR)&&(p->z.flags&VAR)&&p->q2.v==p->z.v&&compare_objects(&p->q2,&p->z)){pric2(stdout,p);ierror(0);}*/
+    /*  COMPARE #0 durch TEST ersetzen (erlaubt, da tst alle Flags setzt)   */
+    if(c==COMPARE&&isconst(q2)){
+      eval_const(&p->q2.val,t);
+      if(zmeqto(l2zm(0L),vmax)&&zumeqto(ul2zum(0UL),vumax)&&zldeqto(d2zld(0.0),vldouble)){
+	c=p->code=TEST;p->q2.flags=0;
+      }
+    }
+    if(c==COMPARE&&isconst(q1)){
+      eval_const(&p->q1.val,t);
+      if(zmeqto(l2zm(0L),vmax)&&zumeqto(ul2zum(0UL),vumax)&&zldeqto(d2zld(0.0),vldouble)){
+	IC *bp=p->next;int bc;
+	c=p->code=TEST;p->q1=p->q2;p->q2.flags=0;p->q2.am=0;
+	/*  Nachfolgenden Branch umdrehen   */
+	while(bp&&bp->code==FREEREG) bp=bp->next;
+	bc=bp->code;
+	if(!bp||bc<BEQ||bc>BGT) ierror(0);
+	if(bc==BLT) bp->code=BGT;
+	if(bc==BGT) bp->code=BLT;
+	if(bc==BLE) bp->code=BGE;
+	if(bc==BGE) bp->code=BLE;
+      }
+    }
+    /*  gesetzte ConditionCodes merken  */
+    if(p->z.flags&&(!isreg(z)||p->z.reg>=d0)&&(c!=CONVERT||!ISFLOAT(p->typf2))&&((!ISFLOAT(t))||FPU>68000)){
+      cc_set=&p->z;cc_typ=p->typf;
+    }else{
+      cc_set=0;
+    }
+    if(c==LEA){
+      if(!isreg(z)||p->z.reg>8) ierror(0);
+      emit(f,"\tlea\t");emit_obj(f,&p->q1,t);
+      emit(f,",%s\n",mregnames[p->z.reg]);
+      continue;
+    }
+    if(c==PEA){
+      emit(f,"\tpea\t");emit_obj(f,&p->q1,t);emit(f,"\n");
+      push(zm2l(p->q2.val.vmax));
+      dontpop+=zm2l(p->q2.val.vmax);
+      continue;
+    }
+    if(c==MOVEFROMREG){
+      if(p->q1.reg<fp0)
+	emit(f,"\tmove.l\t%s,",mregnames[p->q1.reg]);
+      else if(p->q1.reg<25)
+	emit(f,"\tfmove.x\t%s,",mregnames[p->q1.reg]);
+      else
+	emit(f,"\tmovem.l\t%s,",mregnames[p->q1.reg]);
+      emit_obj(f,&p->z,t);emit(f,"\n");
+      continue;
+    }
+    if(c==MOVETOREG){
+      if(p->z.reg<fp0)
+	emit(f,"\tmove.l\t");
+      else if(p->z.reg<25)
+	emit(f,"\tfmove.x\t");
+      else
+	emit(f,"\tmovem.l\t");
+      emit_obj(f,&p->q1,t);emit(f,",%s\n",mregnames[p->z.reg]);
+      continue;
+    }
+    if(NOPEEPHOLE){
+      if(p->q1.am||p->q2.am||p->z.am){
+	ierror(0);
+	p->q1.am=p->q2.am=p->z.am=0;
+      }
+    }
+    p=do_refs(f,p);
+    if((p->q1.flags&&(q1typ(p)&NQ)==LLONG)||(p->q2.flags&&(q2typ(p)&NQ)==LLONG&&p->code!=LSHIFT&&p->code!=RSHIFT)||(p->z.flags&&(ztyp(p)&NQ)==LLONG)){
+      if(handle_llong(f,p)){
+	*fp=0;
+	continue;
+      }
+    }
+    if(NOPEEPHOLE){
+      if(p->q1.am||p->q2.am||p->z.am){
+	ierror(0);
+	p->q1.am=p->q2.am=p->z.am=0;
+      }
+    }
+#ifdef M68K_16BIT_INT
+    if(c==CONVERT&&((t&NQ)==LONG||(t&NQ)==POINTER)&&((p->typf2&NQ)==LONG||(p->typf2&NQ)==POINTER)){
+      p->code=c=ASSIGN;
+      p->q2.val.vmax=sizetab[LONG];
+    }                 
+#else
+    if(c==CONVERT&&((t&NQ)==LONG||(t&NQ)==INT||(t&NQ)==POINTER)&&((p->typf2&NQ)==LONG||(p->typf2&NQ)==INT||(p->typf2&NQ)==POINTER)){
+      p->code=c=ASSIGN;
+      p->q2.val.vmax=sizetab[LONG];
+    }                 
+#endif
+    if(c==CONVERT){
+      int to;
+      if((t&NQ)==POINTER) t=(UNSIGNED|LONG);
+      if((t&NQ)==LDOUBLE) t=DOUBLE;
+      to=p->typf2&NU;
+      if(to==POINTER) to=UNSIGNED|LONG;
+      if(to==LDOUBLE) to=DOUBLE;
+#ifdef M68K_16BIT_INT
+      if((to==(UNSIGNED|CHAR)||to==(UNSIGNED|SHORT)||to==(UNSIGNED|INT))&&!(t&UNSIGNED)&&(t&NQ)>(to&NQ))
+	cc_set=0;
+#else
+      if((to==(UNSIGNED|CHAR)||to==(UNSIGNED|SHORT))&&!(t&UNSIGNED)&&(t&NQ)>(to&NQ))
+	cc_set=0;
+#endif
+      if(ISFLOAT(t)||ISFLOAT(to)){
+	if(FPU>68000){
+	  int zreg=0,freg=0;
+	  if(ISFLOAT(t)&&ISFLOAT(to)){
+	    if(isreg(q1)&&isreg(z)){
+	      if(p->q1.reg!=p->z.reg)
+		emit(f,"\tfmove.x\t%s,%s\n",mregnames[p->q1.reg],mregnames[p->z.reg]);
+	      continue;
+	    }
+	  }
+	  if(isreg(z)&&p->z.reg>=fp0)
+	    zreg=p->z.reg;
+	  if(isreg(q1)&&p->q1.reg>=fp0){
+	    if(!zreg&&(t&UNSIGNED)&&!ISHWORD(t))
+	      zreg=p->q1.reg; 
+	    else 
+	      zreg=freg=get_reg(f,2,p,1);}
+	  if(!zreg) zreg=freg=get_reg(f,2,p,0);
+	  if((to&UNSIGNED)&&x_t[to&NQ]!='l'){
+	    int dreg=get_reg(f,1,p,0);
+	    emit(f,"\tmoveq\t#0,%s\n",mregnames[dreg]);
+	    move(f,&p->q1,0,0,dreg,to);
+	    move(f,0,dreg,0,zreg,LONG);
+	  }else{
+	    if(!isreg(q1)||p->q1.reg!=zreg)
+	      move(f,&p->q1,0,0,zreg,to);
+	  }
+	  if(!ISFLOAT(t)){
+	    if((t&UNSIGNED)&&!ISHWORD(t)){
+	      char *s;
+	      int dreg1,dreg2;
+	      int l1=++label,l2=++label;
+	      if(GAS) s="0x"; else s="$";
+	      if(isreg(z)) 
+		dreg1=p->z.reg;
+	      else
+		dreg1=get_reg(f,1,p,0);
+	      if(FPU==68040)
+		dreg2=get_reg(f,1,p,0);
+	      if(!freg){
+		if(!(isreg(q1)&&p->next&&p->next->code==FREEREG&&p->next->q1.reg==zreg)){
+		  freg=get_reg(f,2,p,1);
+		  emit(f,"\tfmove.x\t%s,%s\n",mregnames[zreg],mregnames[freg]);
+		  zreg=freg;
+		}		
+	      }
+	      emit(f,"\tfcmp.d\t#%s41e0000000000000,%s\n",s,mregnames[zreg]);
+	      emit(f,"\tfbge\t%s%d\n",labprefix,l1);
+	      if(FPU==68040){
+		emit(f,"\tfmove.l\t%sfpcr,%s\n",rprefix,mregnames[dreg2]);
+		emit(f,"\tmoveq\t#16,%s\n",mregnames[dreg1]);
+		emit(f,"\tor.l\t%s,%s\n",mregnames[dreg2],mregnames[dreg1]);
+		emit(f,"\tand.w\t#-33,%s\n",mregnames[dreg1]);
+		emit(f,"\tfmove.l\t%s,%sfpcr\n",mregnames[dreg1],rprefix);
+	      }else{
+		emit(f,"\tfintrz\t%s\n",mregnames[zreg]);
+	      }
+	      emit(f,"\tfmove.l\t%s,%s\n",mregnames[zreg],mregnames[dreg1]);
+	      emit(f,"\tbra\t%s%d\n",labprefix,l2);
+	      emit(f,"%s%d:\n",labprefix,l1);
+	      emit(f,"\tfsub.d\t#%s41e0000000000000,%s\n",s,mregnames[zreg]);
+	      if(FPU==68040){
+		emit(f,"\tfmove.l\t%sfpcr,%s\n",rprefix,mregnames[dreg2]);
+		emit(f,"\tmoveq\t#16,%s\n",mregnames[dreg1]);
+		emit(f,"\tor.l\t%s,%s\n",mregnames[dreg2],mregnames[dreg1]);
+		emit(f,"\tand.w\t#-33,%s\n",mregnames[dreg1]);
+		emit(f,"\tfmove.l\t%s,%sfpcr\n",mregnames[dreg1],rprefix);
+	      }else{
+		emit(f,"\tfintrz\t%s\n",mregnames[zreg]);
+	      }
+	      emit(f,"\tfmove.l\t%s,%s\n",mregnames[zreg],mregnames[dreg1]);
+	      emit(f,"\tbchg\t#31,%s\n",mregnames[dreg1]);
+	      emit(f,"%s%d:\n",labprefix,l2);
+	      if(FPU==68040)
+		emit(f,"\tfmove.l\t%s,%sfpcr\n",mregnames[dreg2],rprefix);
+	      move(f,0,dreg1,&p->z,0,t);
+	      continue;
+	    }	      
+	    /*  nach integer, d.h. Kommastellen abschneiden */
+	    if(FPU==68040/*||FPU==68060*/){
+	      /*  bei 040 emuliert    */
+	      int dreg1,dreg2;
+	      if(!NOINTZ){
+		if(isreg(z))
+		  dreg1=p->z.reg;
+		else
+		  dreg1=get_reg(f,1,p,0);
+		dreg2=get_reg(f,1,p,0);
+		emit(f,"\tfmove.l\t%sfpcr,%s\n",rprefix,mregnames[dreg2]);
+		emit(f,"\tmoveq\t#16,%s\n",mregnames[dreg1]);
+		emit(f,"\tor.l\t%s,%s\n",mregnames[dreg2],mregnames[dreg1]);
+		emit(f,"\tand.w\t#-33,%s\n",mregnames[dreg1]);
+		emit(f,"\tfmove.l\t%s,%sfpcr\n",mregnames[dreg1],rprefix);
+	      }else{
+		dreg1=get_reg(f,1,p,0);
+	      }
+	      if((t&UNSIGNED)&&ISHWORD(t)){
+		emit(f,"\tfmove.l\t%s,%s\n",mregnames[zreg],mregnames[dreg1]);
+		emit(f,"\tmove.%c\t%s,",x_t[t&NQ],mregnames[dreg1]);
+	      }else{
+		emit(f,"\tfmove.%c\t%s,",x_t[t&NQ],mregnames[zreg]);
+	      }
+	      emit_obj(f,&p->z,t);emit(f,"\n");
+	      if(!NOINTZ)
+		emit(f,"\tfmove.l\t%s,%sfpcr\n",mregnames[dreg2],rprefix);
+	      continue;
+	    }else{
+	      if(!NOINTZ){
+		if(!isreg(q1)||p->q1.reg!=zreg){
+		  emit(f,"\tfintrz.x\t%s\n",mregnames[zreg]);
+		}else{
+		  int nreg=get_reg(f,2,p,1);
+		  emit(f,"\tfintrz.x\t%s,%s\n",mregnames[zreg],mregnames[nreg]);
+		  zreg=nreg;
+		}
+	      }
+	      if((t&UNSIGNED)&&ISHWORD(t)){
+		int r;
+		if(isreg(z)) r=p->z.reg; else r=get_reg(f,1,p,0);
+		move(f,0,zreg,0,r,LONG);
+		move(f,0,r,&p->z,0,t);
+	      }else{
+		move(f,0,zreg,&p->z,0,t);
+	      }
+	      continue;
+	    }
+	  }
+	  if((to&UNSIGNED)&&x_t[to&NQ]=='l'){
+	    int nlabel;
+	    emit(f,"\ttst.%c\t",x_t[to&NQ]);
+	    emit_obj(f,&p->q1,to);emit(f,"\n");
+	    nlabel=++label;
+	    emit(f,"\tbge.s\t%s%d\n",labprefix,nlabel);
+	    emit(f,"\tfadd.d\t#4294967296,%s\n",mregnames[zreg]);
+	    emit(f,"%s%d:\n",labprefix,nlabel);
+	  }
+	  if(!(p->z.reg)||p->z.reg!=zreg){
+	    move(f,0,zreg,&p->z,0,t);
+	  }
+	}else{
+	  cc_set=0;
+	  if((to&NQ)==(t&NQ)){
+	    assign(f,p,&p->q1,&p->z,ASSIGN,sizetab[to&NQ],t);
+	    continue;
+	  }
+	  if((to&NQ)==FLOAT&&((t&NQ)==DOUBLE||(t&NQ)==LDOUBLE)){
+	    if(!OLD_SOFTFLOAT)
+	      ierror(0);
+	    saveregs(f,p);
+	    assign(f,p,&p->q1,0,PUSH,msizetab[FLOAT],FLOAT);
+	    scratch_modified();
+	    if(GAS){
+	      emit(f,"\t.global\t__ieees2d\n\tjbsr\t__ieees2d\n\taddq.%s\t#4,%s\n",strshort[1],mregnames[sp]);
+	    }else{
+	      emit(f,"\tpublic\t__ieees2d\n\tjsr\t__ieees2d\n\taddq.%s\t#4,%s\n",strshort[1],mregnames[sp]);
+	    }
+	    pop(4);
+	    restoreregsa(f,p);
+	    stored0d1(f,&p->z,t);
+	    restoreregsd(f,p);
+	    continue;
+	  }
+	  if(((to&NQ)==DOUBLE||(to&NQ)==LDOUBLE)&&(t&NQ)==FLOAT){
+	    if(!OLD_SOFTFLOAT) ierror(0);
+	    saveregs(f,p);
+	    assign(f,p,&p->q1,0,PUSH,msizetab[DOUBLE],DOUBLE);
+	    scratch_modified();
+	    if(GAS){
+	      emit(f,"\t.global\t__ieeed2s\n\tjbsr\t__ieeed2s\n\taddq.%s\t#8,%s\n",strshort[1],mregnames[sp]);
+	    }else{
+	      emit(f,"\tpublic\t__ieeed2s\n\tjsr\t__ieeed2s\n\taddq.%s\t#8,%s\n",strshort[1],mregnames[sp]);
+	    }
+	    pop(8);
+	    restoreregsa(f,p);
+	    move(f,0,d0,&p->z,0,t);
+	    restoreregsd(f,p);
+	    continue;
+	  }
+	  if(ISFLOAT(to)){
+	    int uns;
+	    if(!OLD_SOFTFLOAT) ierror(0);
+	    saveregs(f,p);
+	    if(t&UNSIGNED) uns='u'; else uns='s';
+	    assign(f,p,&p->q1,0,PUSH,sizetab[to&NQ],to);
+	    scratch_modified();
+	    if(GAS){
+	      emit(f,"\t.global\t__ieeefix%c%c\n\tjbsr\t__ieeefix%c%c\n\taddq.%s\t#%ld,%s\n",x_t[to&NQ],uns,x_t[to&NQ],uns,strshort[1],zm2l(sizetab[to&NQ]),mregnames[sp]);
+	    }else{
+	      emit(f,"\tpublic\t__ieeefix%c%c\n\tjsr\t__ieeefix%c%c\n\taddq.%s\t#%ld,%s\n",x_t[to&NQ],uns,x_t[to&NQ],uns,strshort[1],zm2l(sizetab[to&NQ]),mregnames[sp]);
+	    }
+	    pop(sizetab[to&NQ]);
+	    restoreregsa(f,p);
+	    move(f,0,d0,&p->z,0,t);
+	    restoreregsd(f,p);
+	    continue;
+	  }else{
+	    int uns,xt=x_t[to&NQ];
+	    if(!OLD_SOFTFLOAT) ierror(0);
+	    saveregs(f,p);
+	    if(to&UNSIGNED) uns='u'; else uns='s';
+	    if(xt!='l'){
+	      emit(f,"\tsubq.%s\t#4,%s\n",strshort[1],mregnames[sp]);
+	      push(4);
+	    }
+	    emit(f,"\tmove.%c\t",xt);
+	    emit_obj(f,&p->q1,to);
+	    if(xt!='l')
+	      emit(f,",(%s)\n",mregnames[sp]); 
+	    else{
+	      emit(f,",-(%s)\n",mregnames[sp]);
+	      push(4);
+	    }
+	    scratch_modified();
+	    if(GAS){
+	      emit(f,"\t.global\t__ieeeflt%c%c%c\n\tjbsr\t__ieeeflt%c%c%c\n\taddq.%s\t#4,%s\n",uns,xt,x_t[t&NQ],uns,xt,x_t[t&NQ],strshort[1],mregnames[sp]);
+	    }else{
+	      emit(f,"\tpublic\t__ieeeflt%c%c%c\n\tjsr\t__ieeeflt%c%c%c\n\taddq.%s\t#4,%s\n",uns,xt,x_t[t&NQ],uns,xt,x_t[t&NQ],strshort[1],mregnames[sp]);
+	    }
+	    pop(4);
+	    restoreregsa(f,p);
+	    if((t&NQ)==DOUBLE||(t&NQ)==LDOUBLE)
+	      stored0d1(f,&p->z,t);
+	    else
+	      move(f,0,d0,&p->z,0,t);
+	    restoreregsd(f,p);
+	    continue;
+	  }
+	}
+	continue;
+      }
+      if((to&NQ)<(t&NQ)){
+	int zreg;
+	if(isreg(z)&&p->z.reg>=d0&&p->z.reg<=d7){
+	  zreg=p->z.reg;
+	}else{
+	  zreg=get_reg(f,1,p,0);
+	}
+	if(sizetab[t&NQ]!=sizetab[LONG]||sizetab[to&NQ]!=sizetab[LONG]){
+	  /*  aufpassen, falls unsigned und Quelle==Ziel  */
+	  if((to&UNSIGNED)&&isreg(q1)&&zreg==p->q1.reg){
+	    unsigned long l;
+	    if((to&NQ)==CHAR) l=0xff; else l=0xffff;
+	    emit(f,"\tand.%c\t#%lu,%s\n",cf?'l':x_t[t&NQ],l,mregnames[zreg]);
+	    continue;
+	  }
+	  if((to&UNSIGNED)&&p->q1.am&&(zreg==p->q1.am->basereg||zreg==(p->q1.am->dreg&127))){
+	    /*  aufpassen, falls unsigned und Ziel im am  */
+	    unsigned long l;
+	    if((to&NQ)==CHAR) l=0xff; else l=0xffff;
+	    move(f,&p->q1,0,0,zreg,to);
+	    emit(f,"\tand.%c\t#%lu,%s\n",cf?'l':x_t[t&NQ],l,mregnames[zreg]);
+	  }else{
+	    if(to&UNSIGNED)
+	      emit(f,"\tmoveq\t#0,%s\n",mregnames[zreg]);
+	    move(f,&p->q1,0,0,zreg,to);
+	  }
+	  if(!(to&UNSIGNED)){
+#ifdef M68K_16BIT_INT
+	    if((to&NQ)==CHAR&&((t&NQ)==SHORT||(t&NQ)==INT)) emit(f,"\text.w\t%s\n",mregnames[zreg]);
+	    if(((to&NQ)==SHORT||(to&NQ)==INT)&&msizetab[t&NQ]==4) emit(f,"\text.l\t%s\n",mregnames[zreg]);
+#else
+	    if((to&NQ)==CHAR&&(t&NQ)==SHORT) emit(f,"\text.w\t%s\n",mregnames[zreg]);
+	    if((to&NQ)==SHORT&&msizetab[t&NQ]==4) emit(f,"\text.l\t%s\n",mregnames[zreg]);
+#endif
+	    if((to&NQ)==CHAR&&msizetab[t&NQ]==4){
+	      if(cf||CPU>=68020)
+		emit(f,"\textb.l\t%s\n",mregnames[zreg]);
+	      else
+		emit(f,"\text.w\t%s\n\text.l\t%s\n",mregnames[zreg],mregnames[zreg]);
+	    }
+	  }
+	}
+	if(!isreg(z)||p->z.reg!=zreg){
+	  move(f,0,zreg,&p->z,0,t);
+	}
+      }else{
+	long diff;int m;
+	m=0;
+	if(p->q1.flags&REG){
+	  p->q1.val.vmax=l2zm(0L);
+	  p->q1.flags|=D16OFF;m=1;
+	}
+	diff=msizetab[to&NQ]-msizetab[t&NQ];
+	vmax=l2zm(diff);
+	p->q1.val.vmax=zmadd(p->q1.val.vmax,vmax);
+	move(f,&p->q1,0,&p->z,0,t);
+	vmax=l2zm(diff);
+	p->q1.val.vmax=zmsub(p->q1.val.vmax,vmax);
+	if(m) p->q1.flags&=~D16OFF;
+	if(compare_objects(&p->q1,&p->z))
+	  cc_set=0;
+      }
+      continue;
+    }
+    if(ISFLOAT(t)&&FPU>68000) *fp='f'; else *fp=0;
+    if(c==MINUS||c==KOMPLEMENT){
+      int zreg;
+      if(ISFLOAT(t)){
+	if(FPU>68000){
+	  if(isreg(z)) zreg=p->z.reg; else zreg=get_reg(f,2,p,1);
+	  emit(f,"\tfneg.");
+	  if(isreg(q1)) emit(f,"x\t%s",mregnames[p->q1.reg]);
+	  else    {emit(f,"%c\t",x_t[t&NQ]);emit_obj(f,&p->q1,t);}
+	  emit(f,",%s\n",mregnames[zreg]);
+	  if(!isreg(z)||p->z.reg!=zreg){
+	    move(f,0,zreg,&p->z,0,t);
+	  }
+	  continue;
+	}else{
+	  if(!OLD_SOFTFLOAT) ierror(0);
+	  saveregs(f,p);
+	  assign(f,p,&p->q1,0,PUSH,msizetab[t&NQ],t);
+	  scratch_modified();
+	  if(GAS){
+	    emit(f,"\t.global\t__ieeeneg%c\n\tjbsr\t__ieeeneg%c\n\taddq.%s\t#%ld,%s\n",x_t[t&NQ],x_t[t&NQ],strshort[1],msizetab[t&NQ],mregnames[sp]);
+	  }else{
+	    emit(f,"\tpublic\t__ieeeneg%c\n\tjsr\t__ieeeneg%c\n\taddq.%s\t#%ld,%s\n",x_t[t&NQ],x_t[t&NQ],strshort[1],msizetab[t&NQ],mregnames[sp]);
+	  }
+	  pop(msizetab[t&NQ]);
+	  restoreregsa(f,p);
+	  if((t&NQ)!=FLOAT)
+	    stored0d1(f,&p->z,t);
+	  else
+	    move(f,0,d0,&p->z,0,t);
+	  restoreregsd(f,p);
+	  continue;
+	}
+      }
+      if(!cf&&compare_objects(&p->q1,&p->z)){
+	emit(f,"\t%s.%c\t",ename[c],x_t[t&NQ]);
+	emit_obj(f,&p->q1,t);emit(f,"\n");
+	continue;
+      }
+      if(isreg(z)&&p->z.reg>=d0/*&&p->z.reg<=d7*/)
+	zreg=p->z.reg; else zreg=get_reg(f,1,p,1);
+      if(!isreg(q1)||p->q1.reg!=zreg){
+	move(f,&p->q1,0,0,zreg,t);
+      }
+      emit(f,"\t%s.%c\t%s\n",ename[c],x_t[t&NQ],mregnames[zreg]);
+      if(!isreg(z)||p->z.reg!=zreg){
+	move(f,0,zreg,&p->z,0,t);
+      }
+      continue;
+    }
+    if(c==SETRETURN){
+      /*  Returnwert setzen - q2.val.vmax==size, z.reg==Returnregister */
+      if(((t&NQ)==DOUBLE||(t&NQ)==LDOUBLE)&&p->z.reg==d0){
+	BSET(regs_modified,d0);BSET(regs_modified,10);
+	if(isconst(q1)){
+	  unsigned char *ip=(unsigned char *)&p->q1.val.vdouble;
+	  char *s;
+	  if(GAS) s="0x"; else s="$";
+	  emit(f,"\tmove.l\t#%s%02x%02x%02x%02x,%s\n",s,ip[0],ip[1],ip[2],ip[3],mregnames[d0]);
+	  emit(f,"\tmove.l\t#%s%02x%02x%02x%02x,%s\n",s,ip[4],ip[5],ip[6],ip[7],mregnames[d1]);
+	  continue;
+	}
+	if(isreg(q1)&&p->q1.reg>=fp0&&p->q1.reg<=fp7){
+	  emit(f,"\tfmove.d\t%s,-(%s)\n\tmovem.l\t(%s)+,%s\n",mregnames[p->q1.reg],mregnames[sp],mregnames[sp],mregnames[d0d1]);
+	}else{
+	  loadd0d1(f,&p->q1,t);
+	}
+	continue;
+      }
+      if((ISSTRUCT(t)||ISUNION(t))&&p->z.reg==d0){
+	long l=zm2l(p->q2.val.vmax);
+	emit(f,"\tmovem.l\t");emit_obj(f,&p->q1,t);
+	emit(f,",%s",mregnames[d0]);BSET(regs_modified,d0);
+	if(l>=8) {emit(f,"/%s",mregnames[d1]);BSET(regs_modified,d1);}
+	if(l>=12) {emit(f,"/%s",mregnames[a0]);BSET(regs_modified,a0);}
+	if(l>=16) {emit(f,"/%s",mregnames[a1]);BSET(regs_modified,a1);}
+	emit(f,"\n");
+	continue;
+      }
+      /*  Wenn Returnwert ueber Zeiger gesetzt wird, nichts noetig    */
+      if(p->z.reg){
+	move(f,&p->q1,0,0,p->z.reg,p->typf);
+	BSET(regs_modified,p->z.reg);
+	if(v->tattr&AMIINTERRUPT){
+	  /* if necessary, set condition-codes */
+	  if(p->z.reg!=d0) ierror(0);
+	  if(isreg(q1)&&p->q1.reg==d0)
+	    emit(f,"\ttst.%c\t%s\n",x_t[t&NQ],mregnames[d0]);
+	}
+      }
+      continue;
+    }
+    if(c==GETRETURN){
+      /*  Returnwert holen - q2.val.vmax==size, q1.reg==Returnregister     */
+      if(((t&NQ)==DOUBLE||(t&NQ)==LDOUBLE)&&(p->q1.reg==d0||p->q1.reg==d0d1)){
+	if(isreg(z)&&p->z.reg>=fp0&&p->z.reg<=fp7){
+	  emit(f,"\tmovem.l\t%s,-(%s)\n\tfmove.d\t(%s)+,%s\n",mregnames[d0d1],mregnames[sp],mregnames[sp],mregnames[p->z.reg]);
+	}else{
+	  stored0d1(f,&p->z,t);
+	}
+	continue;
+      }
+      if((ISSTRUCT(t)||ISUNION(t))&&p->q1.reg==d0){
+	long l=zm2l(p->q2.val.vmax);
+	emit(f,"\tmovem.l\t");
+	emit(f,"%s",mregnames[d0]);
+	if(l>=8) emit(f,"/%s",mregnames[d1]);
+	if(l>=12) emit(f,"/%s",mregnames[a0]);
+	if(l>=16) emit(f,"/%s",mregnames[a1]);
+	emit(f,",");emit_obj(f,&p->z,t);emit(f,"\n");
+	continue;
+      }
+
+      /*  Wenn Returnwert ueber Zeiger gesetzt wird, nichts noetig    */
+      cc_set=0;
+      if(p->q1.reg){
+	move(f,0,p->q1.reg,&p->z,0,p->typf);
+	if(!(p->z.flags&REG)||(p->z.reg!=p->q1.reg&&p->z.reg>=d0)){ cc_set=&p->z;cc_typ=p->typf;}
+      }
+      continue;
+    }
+    if(c==CALL){
+      if((p->q1.flags&(VAR|DREFOBJ))==VAR&&!strcmp("__va_start",p->q1.v->identifier)){
+	int sr=(USEFRAMEPOINTER||vlas)?fbp:sp;
+	long va_off=0;
+	if(USEFRAMEPOINTER||vlas){
+	  emit(f,"\tmove.l\t%s,%s\n",mregnames[fbp],mregnames[d0]);
+	  emit(f,"\tadd.l\t#%ld,%s\n",(long)(8+zm2l(va_offset(v)))+(PROFILER?16:0),mregnames[d0]);
+	}else{
+	  emit(f,"\tmove.l\t%s,%s\n",mregnames[sp],mregnames[d0]);
+	  emit(f,"\tadd.l\t#%s%d+%ld,%s\n",labprefix,offlabel,(long)(4+zm2l(va_offset(v)))+loff+(PROFILER?16:0),mregnames[d0]);
+	}
+	BSET(regs_modified,d0);
+	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);
+	if(stack_valid&&(p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&(p->q1.v->fi->flags&ALL_STACK))
+	  callee_push(zum2ul(p->q1.v->fi->stack1));
+	else
+	  stack_valid=0;
+      }else{
+	if((p->q1.flags&(REG|DREFOBJ))==DREFOBJ){
+	  if(1/*CPU<68020*/){
+	    emit(f,"\tpea\t%s%d(pc)\n",labprefix,++label);
+	    emit(f,"\tmove.l\t");
+	  }else
+	    emit(f,"\t%s\t([",GAS?"jbsr":"jsr");
+	  p->q1.flags&=~DREFOBJ;
+	  emit_obj(f,&p->q1,POINTER);
+	  p->q1.flags|=DREFOBJ;
+	  if(1/*CPU<68020*/){
+	    emit(f,",-(%s)\n",mregnames[sp]);
+	    emit(f,"\trts\n");
+	    emit(f,"%s%d%s\n",labprefix,label,GAS?":":"");
+	  }else
+	    emit(f,"])\n");
+	}else{
+	  if(GAS){
+	    emit(f,"\tjbsr\t");
+	  }else{
+	    emit(f,"\tjsr\t");
+	  }
+	  /*  Wenn geta4() aufgerufen wurde, merken.  */
+	  if(use_sd&&(p->q1.flags&(VAR|DREFOBJ))==VAR&&!strcmp(p->q1.v->identifier,"geta4")&&p->q1.v->storage_class==EXTERN)
+	    geta4=1;
+	  if((p->q1.flags&(DREFOBJ|REG|KONST))==DREFOBJ) ierror(0);
+	  emit_obj(f,&p->q1,t);
+	  emit(f,"\n");
+	}
+	push(4);
+	if(stack_valid&&(p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&(p->q1.v->fi->flags&ALL_STACK))
+	  callee_push(zum2ul(p->q1.v->fi->stack1));
+	else
+	  stack_valid=0;
+	pop(4);
+      }
+      if(debug_info&&HUNKDEBUG) act_line=0;
+      if(!zmeqto(p->q2.val.vmax,l2zm(0L))){
+	notpopped+=zm2l(p->q2.val.vmax);
+	dontpop-=zm2l(p->q2.val.vmax);
+	if(!NODELAYEDPOP&&!(pushedreg&30)&&!vlas&&stackoffset==-notpopped){
+	  /*  Entfernen der Parameter verzoegern  */
+	}else{
+	  if(debug_info&&HUNKDEBUG&&!GAS){ act_line=p->line; emit(f,"\tdebug\t%d\n",act_line);}
+	  emit(f,"\tadd%s.%s\t#%ld,%s\n",quick[zm2l(p->q2.val.vmax)<=8],strshort[zm2l(p->q2.val.vmax)<32768],zm2l(p->q2.val.vmax),mregnames[sp]);
+	  pop(zm2l(p->q2.val.vmax));
+	  notpopped-=zm2l(p->q2.val.vmax);
+	}
+      }
+      if((p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&(p->q1.v->fi->flags&ALL_REGS)){
+	bvunite(regs_modified,p->q1.v->fi->regs_modified,RSIZE);
+      }else{
+	int i;
+	for(i=1;i<=MAXR;i++){
+	  if(regscratch[i])
+	    if(i<fp0||i>fp7||FPU>68000) 
+	      BSET(regs_modified,i);
+	}
+      }
+      continue;
+    }
+    if(c==TEST){
+      /*  ConditionCodes schon gesetzt?   */
+      cc_set=&p->q1;cc_typ=t;
+      comptyp=t;
+      if(cc_set_tst&&t==cc_typ_tst){
+	IC *branch;
+	if(t&UNSIGNED){
+	  branch=p->next;
+	  while(branch&&(branch->code<BEQ||branch->code>BGT))
+	    branch=branch->next;
+	  if(!branch) continue;
+	  if(branch->code==BLE) branch->code=BEQ;
+	  if(branch->code==BGT) branch->code=BNE;
+	  if(branch->code==BGE) {branch->code=BRA;continue;}
+	  if(branch->code==BLT) {branch->code=NOP;continue;}
+	}
+	if(compare_objects(&p->q1,cc_set_tst)&&p->q1.am==cc_set_tst->am&&zmeqto(p->q1.val.vmax,cc_set_tst->val.vmax)){
+	  if(DEBUG&512){emit(f,"; tst eliminated: cc=");emit_obj(f,cc_set_tst,t);
+	  emit(f,", q1=");emit_obj(f,&p->q1,t);emit(f,"\n");}
+	  continue;
+	}
+      }
+      if(CPU<68020&&isreg(q1)&&p->q1.reg>=1&&p->q1.reg<=8){
+	/*  tst ax gibt es nicht bei <68000 :-( */
+	if(regavailable(1)){
+	  emit(f,"\tmove.%c\t%s,%s\n",x_t[t&NQ],mregnames[p->q1.reg],mregnames[get_reg(f,1,p,0)]);
+	}else{
+	  emit(f,"\tcmp.%c\t#0,%s\n",cf?'l':'w',mregnames[p->q1.reg]);
+	}
+	continue;
+      }
+      if(ISFLOAT(t)&&FPU<=68000){
+	/*  nicht sehr schoen   */
+	int result=get_reg(f,1,p,0);
+	if(!OLD_SOFTFLOAT) ierror(0);
+	saveregs(f,p);
+	assign(f,p,&p->q1,0,PUSH,msizetab[t&NQ],t);
+	scratch_modified();
+	if(GAS){
+	  emit(f,"\t.global\t__ieeetst%c\n\tjbsr\t__ieeetst%c\n\taddq.%s\t#%ld,%s\n",x_t[t&NQ],x_t[t&NQ],strshort[1],msizetab[t&NQ],mregnames[sp]);
+	}else{
+	  emit(f,"\tpublic\t__ieeetst%c\n\tjsr\t__ieeetst%c\n\taddq.%s\t#%ld,%s\n",x_t[t&NQ],x_t[t&NQ],strshort[1],msizetab[t&NQ],mregnames[sp]);
+	}
+	pop(msizetab[t&NQ]);
+	restoreregsa(f,p);
+	if(result!=d0) emit(f,"\tmove.l\t%s,%s\n",mregnames[d0],mregnames[result]);
+	emit(f,"\ttst.l\t%s\n",mregnames[result]);
+	restoreregsd(f,p);
+	continue;
+      }
+      if(isreg(q1)&&p->q1.reg>=fp0&&p->q1.reg<=fp7){
+	emit(f,"\tftst.x\t%s\n",mregnames[p->q1.reg]);
+      }else if(p->q1.flags&(VARADR|KONST)){
+	int r=get_reg(f,1,p,0);
+	emit(f,"\tmove.%c\t",x_t[t&NQ]);
+	emit_obj(f,&p->q1,t);
+	emit(f,",%s\n",mregnames[r]);
+      }else{
+	emit(f,"\t%stst.%c\t",fp,x_t[t&NQ]);emit_obj(f,&p->q1,t);
+	emit(f,"\n");
+      }
+      continue;
+    }
+    if(c==ASSIGN||c==PUSH){
+      if(c==ASSIGN&&compare_objects(&p->q1,&p->z)) cc_set=0;
+      if(c==PUSH) dontpop+=zm2l(p->q2.val.vmax);
+      assign(f,p,&p->q1,&p->z,c,zm2l(p->q2.val.vmax),t);
+      continue;
+    }
+    if(c==ADDRESS){
+      int zreg;
+      if(isreg(z)&&p->z.reg>=1&&p->z.reg<=8)
+	zreg=p->z.reg; else zreg=get_reg(f,0,p,0);
+      emit(f,"\tlea\t");emit_obj(f,&p->q1,t);
+      emit(f,",%s\n",mregnames[zreg]);
+      if(!isreg(z)||p->z.reg!=zreg){
+	move(f,0,zreg,&p->z,0,POINTER);
+      }
+      continue;
+    }
+    if(c==COMPARE){
+      int zreg;
+      comptyp=t;
+      if(isconst(q1)||isreg(q2)){
+	/*  evtl. Argumente von cmp und nachfolgendes bcc umdrehen  */
+	IC *n;obj m;
+	n=p->next;
+	while(n){
+	  if(n->code>=BEQ&&n->code<BRA){
+	    if(!p->z.flags){
+	      if(DEBUG&1) printf("arguments of cmp exchanged\n");
+	      m=p->q1;p->q1=p->q2;p->q2=m;
+	      p->z.flags=1;
+	    }
+	    /*  nachfolgenden Branch umdrehen   */
+	    switch(n->code){
+	    case BGT: n->code=BLT;break;
+	    case BLT: n->code=BGT;break;
+	    case BGE: n->code=BLE;break;
+	    case BLE: n->code=BGE;break;
+	    }
+	    break;
+	  }
+	  if(n->code==FREEREG) n=n->next; else break; /*  compare ohne branch => leerer Block o.ae.   */
+	}
+      }
+      if(ISFLOAT(t)){
+	if(FPU>68000){
+	  if(isreg(q1)&&p->q1.reg>=fp0){
+	    zreg=p->q1.reg;
+	  }else{
+	    zreg=get_reg(f,2,p,0);
+	    move(f,&p->q1,0,0,zreg,t);
+	  }
+	  if(isreg(q2)){emit(f,"\tfcmp.x\t%s,%s\n",mregnames[p->q2.reg],mregnames[zreg]);continue;}
+	  emit(f,"\tfcmp.%c\t",x_t[t&NQ]);emit_obj(f,&p->q2,t);
+	  emit(f,",%s\n",mregnames[zreg]);
+	  continue;
+	}else{
+	  /*  nicht sehr schoen   */
+	  int result=get_reg(f,1,p,0);
+	  if(!OLD_SOFTFLOAT) ierror(0);
+	  saveregs(f,p);
+	  assign(f,p,&p->q2,0,PUSH,msizetab[t&NQ],t);
+	  assign(f,p,&p->q1,0,PUSH,msizetab[t&NQ],t);
+	  scratch_modified();
+	  if(GAS){
+	    emit(f,"\t.global\t__ieeecmp%c\n\tjbsr\t__ieeecmp%c\n\tadd.%s\t#%ld,%s\n",x_t[t&NQ],x_t[t&NQ],strshort[1],2*msizetab[t&NQ],mregnames[sp]);
+	  }else{
+	    emit(f,"\tpublic\t__ieeecmp%c\n\tjsr\t__ieeecmp%c\n\tadd.%s\t#%ld,%s\n",x_t[t&NQ],x_t[t&NQ],strshort[1],2*msizetab[t&NQ],mregnames[sp]);
+	  }
+	  pop(2*msizetab[t&NQ]);
+	  restoreregsa(f,p);
+	  if(result!=d0) emit(f,"\tmove.l\t%s,%s\n",mregnames[d0],mregnames[result]);
+	  emit(f,"\ttst.l\t%s\n",mregnames[result]);
+	  restoreregsd(f,p);
+	  continue;
+	}
+      }
+      if(cf&&x_t[t&NQ]!='l'){
+	if(isreg(q1)) zreg=p->q1.reg; else zreg=get_reg(f,1,p,0);
+	loadext(f,zreg,&p->q1,t);
+	if(isconst(q2)){
+	  emit(f,"\tcmp.l\t");
+	  emit_obj(f,&p->q2,t);
+	}else{
+	  int r;
+	  if(isreg(q2)) r=p->q2.reg; else r=get_reg(f,1,p,0);
+	  loadext(f,r,&p->q2,t);
+	  emit(f,"\tcmp.l\t%s",mregnames[r]);
+	}
+	emit(f,",%s\n",mregnames[zreg]);
+	continue;
+      }
+      if((p->q2.flags&(KONST|VARADR))&&!(p->q1.flags&(KONST|VARADR))&&(!cf||isreg(q1))){
+	emit(f,"\tcmp.%c\t",x_t[t&NQ]);emit_obj(f,&p->q2,t);
+	emit(f,",");emit_obj(f,&p->q1,t);emit(f,"\n");
+	continue;
+      }
+      if(isreg(q1)){
+	zreg=p->q1.reg;
+      }else{
+	zreg=get_reg(f,1,p,1);    /* hier evtl. auch Adressregister nehmen */
+	move(f,&p->q1,0,0,zreg,t);
+      }
+      emit(f,"\tcmp.%c\t",x_t[t&NQ]);emit_obj(f,&p->q2,t);
+      emit(f,",%s\n",mregnames[zreg]);
+      continue;
+    }
+    if(c==ADDI2P||c==SUBIFP){
+      int zreg=-1,r;
+
+      /*  hier die zweite Alternative mit isreg() schreiben?  */
+      if((((p->q2.flags&REG)&&(p->z.flags&REG)&&p->q2.reg==p->z.reg&&(!(p->q1.flags&REG)||p->q1.reg!=p->z.reg))||
+	 (compare_objects(&p->q2,&p->z)&&!compare_objects(&p->q1,&p->z)))){
+	obj m;
+	if(c==ADDI2P&&x_t[t&NQ]=='l'){
+	  m=p->q1;p->q1=p->q2;p->q2=m;
+	}else{
+	  if(!cf&&x_t[t&NQ]=='l'&&isreg(q2)&&p->q2.reg>=d0&&p->q2.reg<=d7){
+	    m=p->q1;p->q1=p->q2;p->q2=m;
+	    c=ADDI2P;
+	    emit(f,"\tneg.%c\t",x_t[t&NQ]);
+	    emit_obj(f,&p->q1,t);emit(f,"\n");
+	  }else{
+	    zreg=get_reg(f,0,p,0);
+	  }
+	}
+      }
+
+      if(isreg(q1)&&p->q1.reg<=8&&isreg(z)&&p->z.reg<=8&&p->q1.reg!=p->z.reg){
+	/*  q1 und z Adressregister => lea nehmen   */
+	if(isconst(q2)){
+	  eval_const(&p->q2.val,t);
+	  if(c==SUBIFP) vmax=zmsub(l2zm(0L),vmax);
+	  if(CPU>=68020||(zmleq(vmax,l2zm(32767))&&zmleq(l2zm(-32768),vmax))){
+	    emit(f,"\tlea\t(%ld",zm2l(vmax));
+	    if(!GAS&&zm2l(vmax)>0x7fff)
+	      emit(f,".l");
+	    emit(f,",%s),%s\n",mregnames[p->q1.reg],mregnames[p->z.reg]);
+	    continue;
+	  }
+	}else if(c==ADDI2P&&isreg(q2)){
+	  emit(f,"\tlea\t(%s,%s.%c),%s\n",mregnames[p->q1.reg],mregnames[p->q2.reg],x_t[t&NQ],mregnames[p->z.reg]);
+	  continue;
+	}
+      }
+      if(compare_objects(&p->q1,&p->z)){
+	if(isconst(q2)&&(!cf||isquickkonst2(&p->q2.val,t))){
+	  if(c==ADDI2P)
+	    emit(f,"\tadd%s.l\t",quick[isquickkonst2(&p->q2.val,t)]);
+	  else
+	    emit(f,"\tsub%s.l\t",quick[isquickkonst2(&p->q2.val,t)]);
+	  emit_obj(f,&p->q2,t);emit(f,",");
+	  emit_obj(f,&p->z,POINTER);emit(f,"\n");
+	  continue;
+	}
+	if(isreg(q1)&&(x_t[t&NQ]=='l'||p->q1.reg<=8)){
+	  if(c==ADDI2P)
+	    emit(f,"\tadd.%c\t",x_t[t&NQ]);
+	  else
+	    emit(f,"\tsub.%c\t",x_t[t&NQ]);
+	  emit_obj(f,&p->q2,t);emit(f,",%s\n",mregnames[p->z.reg]);
+	  continue;
+	}
+	if(isreg(q2)&&p->q2.reg>=9&&p->q2.reg<=16){
+	  r=p->q2.reg;
+	}else{
+	  r=get_reg(f,1,p,0);
+	  move(f,&p->q2,0,0,r,t);
+	}
+	if(x_t[t&NQ]!='l'&&(!isreg(z)||p->z.reg<1||p->z.reg>8)){
+	  /*  wenn Ziel kein Adressregister, muss short erst auf long */
+	  /*  char darf hier nicht auftreteten und long passt schon   */
+	  if(t&UNSIGNED){
+	    if(CPU>=68040)
+	      emit(f,"\tand.l\t#65535,%s\n",mregnames[r]);
+	    else
+	      emit(f,"\tswap\t%s\n\tclr.w\t%s\n\tswap\t%s\n",mregnames[r],mregnames[r],mregnames[r]);
+	  }else 
+	    emit(f,"\text.l\t%s\n",mregnames[r]);
+	  t=POINTER;
+	}
+	/*                if(c==ADDI2P)
+			  emit(f,"\tadd.%c\t%s,",x_t[t&NQ],mregnames[r]);
+			  else
+			  emit(f,"\tsub.%c\t%s,",x_t[t&NQ],mregnames[r]);
+			  emit_obj(f,&p->z,t);emit(f,"\n");*/
+	if(c==ADDI2P) 
+	  add(f,0,r,&p->z,0,t);
+	else
+	  sub(f,0,r,&p->z,0,t);
+	continue;
+      }
+      if(isreg(z)&&zreg==-1&&p->z.reg>=1&&p->z.reg<=d7)
+	zreg=p->z.reg; 
+      else 
+	zreg=get_reg(f,0,p,0);
+      /*  Spezialfall, falls Ziel Datenregister und short */
+      /*  nicht schoen, aber auf die Schnelle...          */
+      if(x_t[t&NQ]!='l'&&zreg>8){
+	move(f,&p->q2,0,0,zreg,t);
+	if(t&UNSIGNED){
+	  if(CPU>=68040)
+	    emit(f,"\tand.l\t#65535,%s\n",mregnames[zreg]);
+	  else
+	    emit(f,"\tswap\t%s\n\tclr.w\t%s\n\tswap\t%s\n",mregnames[zreg],mregnames[zreg],mregnames[zreg]);
+	}else
+	  emit(f,"\text.l\t%s\n",mregnames[zreg]);
+	if(c==SUBIFP) emit(f,"\tneg.l\t%s\n",mregnames[zreg]);
+	add(f,&p->q1,0,0,zreg,POINTER);
+	if(!isreg(z)||p->z.reg!=zreg)
+	  move(f,0,zreg,&p->z,0,POINTER);
+	continue;
+      }
+      if(!isreg(q1)||p->q1.reg!=zreg){
+	move(f,&p->q1,0,0,zreg,POINTER);
+      }
+      if(c==ADDI2P)
+	add(f,&p->q2,0,0,zreg,t);
+      else 
+	sub(f,&p->q2,0,0,zreg,t);
+      if(!isreg(z)||p->z.reg!=zreg){
+	move(f,0,zreg,&p->z,0,POINTER);
+      }
+      continue;
+    }
+    if((c>=OR&&c<=AND)||c==MULT||c==ADD){
+      if(!isreg(q1)&&!isreg(z)&&isreg(q2)){
+	obj o;
+	o=p->q1;p->q1=p->q2;p->q2=o;
+      }
+    }
+    switch_IC(p);
+    if((c>=OR&&c<=AND)||(c>=LSHIFT&&c<=MOD)){
+      int zreg,q1reg,q2reg;
+      if(isconst(q2)&&
+	 (!(p->q1.flags&REG)||!(p->z.flags&REG)||p->q1.reg!=p->z.reg)&&
+	 (!(p->q1.flags&VAR)||!(p->z.flags&VAR)||p->q1.v!=p->z.v)&&
+	 ((c>=OR&&c<=AND)||c==ADD||c==MULT)){
+	obj o;
+	if(c==MULT){
+	  eval_const(&p->q2.val,t);
+	  if(zmleq(l2zm(0L),vmax)&&zumleq(ul2zum(0UL),vumax)&&!pof2(vumax)){
+	    o=p->q1;p->q1=p->q2;p->q2=o;
+	  }
+	}else{
+	  if(!cf||!ISHWORD(t)){
+	    o=p->q1;p->q1=p->q2;p->q2=o;
+	  }
+	}
+      }
+      if(ISFLOAT(t)){
+	if(FPU>68000){
+	  if(compare_objects(&p->q2,&p->z)&&!compare_objects(&p->q2,&p->q1)){
+	    obj m;
+	    if(c==ADD||c==MULT){
+	      m=p->q1;p->q1=p->q2;p->q2=m;
+	    }else{
+	      if(isreg(q2)){
+		if(c==SUB){
+		  emit(f,"\tfneg.x\t%s\n",mregnames[p->q2.reg]);
+		  m=p->q1;p->q1=p->q2;p->q2=m;
+		  p->code=c=ADD;
+		}else{
+		  int tmp=get_reg(f,2,p,0);
+		  move(f,&p->q2,0,0,tmp,t);
+		  p->q2.reg=tmp;
+		  p->q2.flags=REG;
+		}
+	      }
+	    }
+	  }
+	  if(isreg(z)&&p->z.reg>=fp0)
+	    zreg=p->z.reg;
+	  else 
+	    zreg=get_reg(f,2,p,1);
+	  if(!isreg(q1)||p->q1.reg!=p->z.reg)
+	    move(f,&p->q1,0,0,zreg,t);
+	  emit(f,"\tf%s.",ename[c]);
+	  if(isreg(q2))
+	    emit(f,"x\t");
+	  else
+	    emit(f,"%c\t",x_t[t&NQ]);
+	  emit_obj(f,&p->q2,t);
+	  emit(f,",%s\n",mregnames[zreg]);
+	  if(!isreg(z)||p->z.reg!=zreg){
+	    move(f,0,zreg,&p->z,0,t);
+	  }
+	  continue;
+	}else{
+	  if(!OLD_SOFTFLOAT) ierror(0);
+	  saveregs(f,p);
+	  assign(f,p,&p->q2,0,PUSH,msizetab[t&NQ],t);
+	  assign(f,p,&p->q1,0,PUSH,msizetab[t&NQ],t);
+	  scratch_modified();
+	  if(GAS){
+	    emit(f,"\t.global\t__ieee%s%c\n\tjbsr\t__ieee%s%c\n\tadd.%s\t#%ld,%s\n",ename[c],x_t[t&NQ],ename[c],x_t[t&NQ],strshort[1],2*msizetab[t&NQ],mregnames[sp]);
+	  }else{
+	    emit(f,"\tpublic\t__ieee%s%c\n\tjsr\t__ieee%s%c\n\tadd.%s\t#%ld,%s\n",ename[c],x_t[t&NQ],ename[c],x_t[t&NQ],strshort[1],2*msizetab[t&NQ],mregnames[sp]);
+	  }
+	  pop(2*msizetab[t&NQ]);
+	  restoreregsa(f,p);
+	  if((t&NQ)==DOUBLE||(t&NQ)==LDOUBLE)
+	    stored0d1(f,&p->z,t);
+	  else
+	    move(f,0,d0,&p->z,0,t);
+	  restoreregsd(f,p);
+	  continue;
+	}
+      }
+      if(((c==MULT||c==DIV)||(c==MOD&&(p->typf&UNSIGNED)))&&isconst(q2)){
+	/*  ersetzt mul etc. mit Zweierpotenzen     */
+	/*  hier evtl. noch Fehler                  */
+	long ln;
+	eval_const(&p->q2.val,t);
+	if(zmleq(l2zm(0L),vmax)&&zumleq(ul2zum(0UL),vumax)){
+	  if(ln=pof2(vumax)){
+	    if(c==MOD){
+	      vmax=zmsub(vmax,l2zm(1L));
+	      p->code=AND;
+	    }else{
+	      vmax=l2zm(ln-1);
+	      if(c==DIV){
+		p->code=RSHIFT;
+		shiftisdiv=1;
+	      }else
+		p->code=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,INT);
+	      p->typf2=INT;
+	    }
+	  }
+	}
+      }
+      if(c==DIV||c==MOD){
+	if(x_t[t&NQ]=='l'&&CPU<68020){
+	  /*  das hier ist auch nicht allzu schoen  */
+	  char *fname;
+	  cc_set=0;   /*  Library-Funktionen setzen cc nicht immer */
+	  saveregs(f,p);
+	  emit(f,"\tmove.l\t"); emit_obj(f,&p->q2,t);
+	  emit(f,",-(%s)\n",mregnames[sp]);
+	  push(4);
+	  emit(f,"\tmove.l\t"); emit_obj(f,&p->q1,t);
+	  emit(f,",-(%s)\n",mregnames[sp]);
+	  push(4);
+	  if(t&UNSIGNED) fname="divu"; else fname="divs";
+	  scratch_modified();
+	  if(GAS){
+	    emit(f,"\t.global\t__l%s\n\tjbsr\t__l%s\n",fname,fname);
+	  }else{
+	    emit(f,"\tpublic\t__l%s\n\tjsr\t__l%s\n",fname,fname);
+	  }
+	  emit(f,"\taddq.%s\t#8,%s\n",strshort[1],mregnames[sp]);
+	  if(c==MOD) emit(f,"\tmove.l\td1,d0\n");
+	  pop(8);
+	  restoreregsa(f,p);
+	  move(f,0,d0,&p->z,0,t);
+	  restoreregsd(f,p);
+	  continue;
+	}
+
+      }
+      /*  hier die zweite Alternative mit isreg() schreiben?  */
+      if(compare_objects(&p->q2,&p->z)&&!compare_objects(&p->q2,&p->q1)){
+	obj m;
+	if((c>=OR&&c<=AND)||c==ADD||c==SUB){
+	  if(c!=SUB){
+	    m=p->q1;p->q1=p->q2;p->q2=m;
+	  }else{
+	    if(isreg(q2)&&p->q2.reg>=d0&&p->q2.reg<=d7){
+	      m=p->q1;p->q1=p->q2;p->q2=m;
+	      c=ADD;
+	      emit(f,"\tneg.%c\t",x_t[t&NQ]);
+	      emit_obj(f,&p->q1,t);emit(f,"\n");
+	    }
+	  }
+	}
+      }
+      if(compare_objects(&p->q1,&p->z)){
+	if((c>=OR&&c<=AND)||c==ADD||c==SUB){
+	  int r;
+	  if(isconst(q2)&&(!cf||isreg(z)||((c==ADD||c==SUB)&&isquickkonst2(&p->q2.val,t&NQ)))){
+	    if(cf&&((t&NQ)==CHAR||ISHWORD(t))){
+	      if(isreg(q1)) r=p->q1.reg; else r=get_reg(f,1,p,1);
+	      loadext(f,r,&p->q1,t);
+	      emit(f,"\t%s.l\t",ename[c]);
+	      emit_obj(f,&p->q2,t);
+	      emit(f,",%s\n",mregnames[r]);
+	      move(f,0,r,&p->z,0,t);
+	      continue;
+	    }else{
+	      if(c==ADD) {add(f,&p->q2,0,&p->z,0,t);continue;}
+	      if(c==SUB) {sub(f,&p->q2,0,&p->z,0,t);continue;}
+	      emit(f,"\t%s.%c\t",ename[c],x_t[t&NQ]);
+	      emit_obj(f,&p->q2,t);emit(f,",");
+	      emit_obj(f,&p->z,t);emit(f,"\n");
+	    }
+	    continue;
+	  }
+	  if(!isreg(z)&&(!cf||x_t[t&NQ]=='l')){
+	    if(isreg(q2)&&p->q2.reg>=d0&&p->q2.reg<=d7)
+	      r=p->q2.reg; else r=get_reg(f,1,p,0);
+	    if(!isreg(q2)||p->q2.reg!=r){
+	      move(f,&p->q2,0,0,r,t);
+	    }
+	    emit(f,"\t%s.%c\t%s,",ename[c],x_t[t&NQ],mregnames[r]);
+	    emit_obj(f,&p->z,t);emit(f,"\n");
+	    continue;
+	  }
+	}
+      }
+      /*  bei xor oder asl (ausser 0<=const<=8) muss q2 in Register   */
+      if(isreg(q2)&&p->q2.reg>=d0&&p->q2.reg<=d7){
+	q2reg=p->q2.reg;
+      }else{
+	if(c==LSHIFT||c==RSHIFT||c==XOR){
+	  int t2=q2typ(p)&NU;
+	  eval_const(&p->q2.val,t2);
+	  if(c==XOR||!isconst(q2)||!isquickkonst2(&p->q2.val,t2)){
+	    if((c==LSHIFT||c==RSHIFT)&&(p->typf2&NQ)==LLONG){
+	      if(!isreg(q2)){
+		q2reg=get_reg(f,1,p,0);
+		emit(f,"\tmove.l\t");
+		emit_lword(f,&p->q2);
+		emit(f,",%s\n",mregnames[q2reg]);
+	      }else{
+		if(!reg_pair(p->q2.reg,&rp)) ierror(0);
+		q2reg=rp.r2;
+	      }
+	    }else{
+	      q2reg=get_reg(f,1,p,0);
+	      move(f,&p->q2,0,0,q2reg,t2);
+	    }
+	  }else q2reg=0;
+	}else{
+	  q2reg=0;
+	}
+      }
+      if(c==MOD&&!ISHWORD(t)){
+	int modreg;
+	if(isreg(z)&&p->z.reg>=d0&&p->z.reg<=d7&&p->z.reg!=q2reg)
+	  zreg=p->z.reg; else zreg=get_reg(f,1,p,0);
+	modreg=get_reg(f,1,p,1);
+	if(modreg==zreg) modreg=get_reg(f,1,p,0);
+	move(f,&p->q1,0,0,modreg,t);
+	if(0 /*CPU==68060*/){
+	  /*  div?l.l wird da emuliert?   */
+	  emit(f,"\tsmi\t%s\n\textb.l\t%s\n",mregnames[zreg],mregnames[zreg]);
+	  if(t&UNSIGNED) emit(f,"\tdivu.%c\t",x_t[t&NQ]); else emit(f,"\tdivs.%c\t",x_t[t&NQ]);
+	}else{
+	  if(t&UNSIGNED) emit(f,"\tdivul.%c\t",x_t[t&NQ]); else emit(f,"\tdivsl.%c\t",x_t[t&NQ]);
+	}
+	emit_obj(f,&p->q2,t);
+	emit(f,",%s:%s\n",mregnames[zreg],mregnames[modreg]);
+	move(f,0,zreg,&p->z,0,t);
+	cc_set=0;
+	continue;
+      }
+      if(isreg(z)&&p->z.reg>=d0&&p->z.reg<=d7&&(p->z.reg!=q2reg||(isreg(q1)&&p->q1.reg==q2reg)))
+	zreg=p->z.reg; else zreg=get_reg(f,1,p,1);
+      if(isreg(q1)&&p->q1.reg>=d0&&p->q1.reg<=d7)
+	q1reg=p->q1.reg; else q1reg=0;
+      if(q1reg!=zreg){
+	move(f,&p->q1,0,0,zreg,t);
+      }
+      if(c!=MULT&&c!=DIV&&c!=MOD&&c!=ADD&&c!=SUB){
+	if(cf&&c==RSHIFT){
+	  if(cf&&(t&NU)==CHAR)
+	    emit(f,"\textb.l\t%s\n",mregnames[zreg]);
+	  else if(cf&&(t&NU)==SHORT)
+	    emit(f,"\text.w\t%s\n",mregnames[zreg]);
+	  if(cf&&(t&NU)==(UNSIGNED|CHAR))
+	    emit(f,"\tand.l\t#255,%s\n",mregnames[zreg]);
+	  else if(cf&&(t&NU)==(UNSIGNED|SHORT))
+	    emit(f,"\tand.l\t#65535,%s\n",mregnames[zreg]);
+	}
+	if(shiftisdiv&&!(t&UNSIGNED)){
+	  unsigned long l;
+	  eval_const(&p->q2.val,p->typf2);
+	  l=(1<<zum2ul(vumax))-1;
+	  if(isreg(q1)&&p->q1.reg==zreg)
+	    emit(f,"\ttst.%c\t%s\n",x_t[t&NQ],mregnames[zreg]);
+	  emit(f,"\tbge\t%s%d\n",labprefix,++label);
+	  emit(f,"\tadd%s.%c\t#%ld,%s\n",(l<=7?"q":""),x_t[t&NQ],l,mregnames[zreg]);
+	  emit(f,"%s%d:\n",labprefix,label);
+	}
+	if(c==RSHIFT&&!(t&UNSIGNED))
+	  emit(f,"\tasr.%c\t",cf?'l':x_t[t&NQ]);
+	else
+	  emit(f,"\t%s.%c\t",ename[c],cf?'l':x_t[t&NQ]);
+	if(q2reg)
+	  emit(f,"%s",mregnames[q2reg]);
+	else 
+	  emit_obj(f,&p->q2,q2typ(p));
+	emit(f,",%s\n",mregnames[zreg]);
+      }else{
+	if(c==ADD) add(f,&p->q2,q2reg,0,zreg,t);
+	if(c==SUB) sub(f,&p->q2,q2reg,0,zreg,t);
+	if(c==MULT||c==DIV||c==MOD) mult(f,&p->q2,q2reg,0,zreg,t,c,p);
+      }
+      if((!isreg(z)||p->z.reg!=zreg)){
+	move(f,0,zreg,&p->z,0,t);
+      }
+      continue;
+    }
+    ierror(0);
+  }
+  if(notpopped){
+    emit(f,"\tadd%s.%s\t#%ld,%s\n",quick[notpopped<=8],strshort[notpopped<32768],notpopped,mregnames[sp]);
+    pop(notpopped);notpopped=0;
+  }
+  function_bottom(f,v,zm2l(offset));
+  if(debug_info&&!HUNKDEBUG){
+    emit(f,"%s%d:\n",labprefix,++label);
+    dwarf2_function(f,v,label);
+    if(f) section=-1;
+  }
+  pushflag=0;
+}
+
+/*FIXME*/
+int shortcut(int code,int typ)
+{
+  if(!cf&&(code==COMPARE||code==ADD||code==SUB||code==AND||code==OR||code==XOR||code==LSHIFT||code==RSHIFT)) return(1);
+  if(!cf&&code==MULT&&(typ&NQ)!=CHAR) return 1;
+
+  return 0;
+}
+void init_db(FILE *f)
+{
+  if(!HUNKDEBUG){
+    if(GAS)
+      dwarf2_setup(sizetab[POINTER],".byte",".2byte",".4byte",".4byte","l","_",".section");
+    else
+      dwarf2_setup(sizetab[POINTER],"dc.b","dc.w","dc.l","dc.l","l","_","section");
+    dwarf2_print_comp_unit_header(f);
+  }
+}
+void cleanup_db(FILE *f)
+{
+  if(!HUNKDEBUG&&f){
+    dwarf2_cleanup(f);
+    if(f) section=-1;
+  }
+}
+void cleanup_cg(FILE *f)
+{
+  title(f);
+  if(f&&stack_check){
+    if(GAS)
+      emit(f,"\t.global\t___stack_check\n");
+    else
+      emit(f,"\tpublic\t___stack_check\n");
+  }
+  /*printf("pushed %d, saved %d, removed allocreg %d\n",missing,savedemit,savedalloc);*/
+  return;
+}
+
+/* mark instructions which can (probably) be implemented with faster
+   machine-code than the IC migh suggest, e.g. an addition which can
+   be merged with a load bz use of target addressing-modes;
+   the optimizer should hesitate to modifz such instructions if it's not
+   a definite win */
+
+static int is_single_eff_ic(IC *p)
+{
+  Var *v;
+  if(p->code!=ADDI2P&&p->code!=SUBIFP)
+    return 0;
+  if(!isconst(q2)){
+    if(CONSERVATIVE_SR){
+      if((p->q2.flags&(VAR|DREFOBJ))!=VAR)
+	return 0;
+      if(p->q2.v->storage_class==STATIC||p->q2.v->storage_class==EXTERN)
+	return 0;
+    }else
+      return 0;
+  }
+  if((p->q1.flags&(VAR|DREFOBJ))!=VAR)
+    return 0;
+  if(p->q1.v->storage_class==STATIC||p->q1.v->storage_class==EXTERN)
+    return 0;
+  if((p->z.flags&(VAR|DREFOBJ))!=VAR)
+    return 0;
+  if(p->z.v->storage_class==STATIC||p->z.v->storage_class==EXTERN)
+    return 0;
+  v=p->z.v;
+  for(p=p->next;p;p=p->next){
+    int c=p->code;
+    if(c==LABEL||(c>=BEQ&&c<=BRA))
+      return 0;
+    if((p->q1.flags&VAR)&&p->q1.v==v){
+      if(p->q1.flags&DREFOBJ)
+	return 1;
+      else
+	return 0;
+    }
+    if((p->q2.flags&VAR)&&p->q2.v==v){
+      if(p->q2.flags&DREFOBJ)
+	return 1;
+      else
+	return 0;
+    }
+    if((p->z.flags&VAR)&&p->z.v==v){
+      if(p->z.flags&DREFOBJ)
+	return 1;
+      else
+	return 0;
+    }
+  }
+}
+void mark_eff_ics(void)
+{
+  IC *p;
+  for(p=first_ic;p;p=p->next){
+    if(is_single_eff_ic(p))
+      p->flags|=EFF_IC;
+    else
+      p->flags&=~EFF_IC;
+  }
+}
+
+int reg_pair(int r,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<=fp7) return 0;
+  if(p){
+    switch(r){
+    case d0d1: p->r1=d0;p->r2=d1;break;
+    case d2d3: p->r1=d2;p->r2=d3;break;
+    case d4d5: p->r1=d4;p->r2=d5;break;
+    case d6d7: p->r1=d6;p->r2=d7;break;
+    default: ierror(0);
+    }
+  }
+  return 1;
+}
+
+int emit_peephole(void)
+{
+  int entries,i,r1,r2,r3,r4;
+  char *asmline[EMIT_BUF_DEPTH],c1,c2,c3,c4,e;
+
+  if(OLDPEEPHOLE) return 0;
+  i=emit_l;
+  if(emit_f==0)
+    entries=i-emit_f+1;
+  else
+    entries=EMIT_BUF_DEPTH;
+  asmline[0]=emit_buffer[i];
+  if(entries>=2){
+    i--;
+    if(i<0) i=EMIT_BUF_DEPTH-1;
+    asmline[1]=emit_buffer[i];
+    if(sscanf(asmline[1],"\tmove.l\t(a7)+,%c%d\n%c",&c1,&r1,&e)==2&&
+       sscanf(asmline[0],"\tmove.l\t%c%d,-(a7%c",&c2,&r2,&e)==3&&
+       c1==c2&&r1==r2&&(c1=='a'||c1=='d')&&r1>=0&&r1<=7&&e==')'){
+      sprintf(asmline[1],"\tmove.l\t(a7),%c%d\n",c1,r1);
+      remove_asm();
+      savedemit++;
+      return 1;
+    }
+    if(sscanf(asmline[1],"\tmovem.l\t(a7)+,%c%d\n%c",&c1,&r1,&e)==2&&
+       sscanf(asmline[0],"\tmove.l\t%c%d,-(a7%c",&c2,&r2,&e)==3&&
+       c1==c2&&r1==r2&&(c1=='a'||c1=='d')&&r1>=0&&r1<=7&&e==')'){
+      sprintf(asmline[1],"\tmove.l\t(a7),%c%d\n",c1,r1);
+      remove_asm();
+      savedemit++;
+      return 1;
+    }
+
+    if(sscanf(asmline[1],"\tmove.l\t%c%d,%c%d\n%c",&c1,&r1,&c2,&r2,&e)==4&&
+       sscanf(asmline[0],"\tmove.l\t%c%d,%c%d\n%c",&c3,&r3,&c4,&r4,&e)==4&&
+       c1==c4&&r1==r4&&c2==c3&&r2==r3&&r1>=0&&r1<=7&&r2>=0&&r2<=7&&
+       (c1=='a'||c1=='d')&&(c2=='a'||c2=='d')){
+      /* create tst instruction if condition codes of address register are needed */
+      if(c1=='d'&&c2=='a'&&cc_set!=0&&(cc_set->flags&(REG|DREFOBJ))==REG&&cc_set->reg==a0+r2)
+	sprintf(asmline[0],"\ttst.l\t%s\n",mregnames[d0+r1]);
+      else
+	remove_asm();
+      savedemit++;
+      return 1;
+    }
+  }
+  return 0;
+}
+
+char *use_libcall(int c,int t,int t2)
+{
+  static char fname[32];
+  char *ret=0;
+  int f;
+
+  t&=NU;
+  t2&=NU;
+
+  if(c==LSHIFT&&((t&NQ)==LLONG)) return "_lshint64";
+  if(c==RSHIFT&&t==LLONG) return "_rshsint64";
+  if(c==RSHIFT&&t==(UNSIGNED|LLONG)) return "_rshuint64";
+
+
+  if(FPU>68000){
+    if(c!=CONVERT) return 0;
+    if((!ISFLOAT(t)||(t2&NQ)!=LLONG)&&
+       (!ISFLOAT(t2)||(t&NQ)!=LLONG))
+      return 0;
+  }
+  if(OLD_SOFTFLOAT) return 0;
+
+  if(t==LDOUBLE) t=DOUBLE;
+  if(t2==LDOUBLE) t2=DOUBLE;
+  if(FLOAT64){
+    if(t==FLOAT) t=DOUBLE;
+    if(t2==FLOAT) t2=DOUBLE;
+  }
+
+  if(c==COMPARE){
+    if(ISFLOAT(t)){
+      sprintf(fname,"_ieeecmp%c",x_t[t]);
+      ret=fname;
+    }
+  }else if(c==CONVERT){
+    if(t2==INT) t2=(zm2l(sizetab[INT])==4?LONG:SHORT);
+    if(t2==(UNSIGNED|INT)) t2=(sizetab[INT]==4?(UNSIGNED|LONG):(UNSIGNED|SHORT));
+    if(t==FLOAT&&t2==DOUBLE) return "_ieeed2s";
+    if(t==DOUBLE&&t2==FLOAT) return "_ieees2d";
+    if(t==DOUBLE&&t2==DOUBLE) return 0;
+    if(t==FLOAT||t==DOUBLE){
+      if((t2&NQ)==LLONG)
+	sprintf(fname,"_%cint64toflt%s",(t2&UNSIGNED)?'u':'s',t==FLOAT?"32":"64");
+      else
+	sprintf(fname,"_ieeeflt%c%c",(t2&UNSIGNED)?'u':'s',x_t[t]);
+      ret=fname;
+    }
+    if(t2==FLOAT||t2==DOUBLE){
+      if((t&NQ)==LLONG)
+	sprintf(fname,"_flt%sto%cint64",t2==FLOAT?"32":"64",(t&UNSIGNED)?'u':'s');
+      else
+	sprintf(fname,"_ieeefix%c%c%c",x_t[t2],(t2&UNSIGNED)?'u':'s',x_t[t&NQ]);
+      ret=fname;
+    }
+  }else if(ISFLOAT(t)){
+    if(c==MINUS){
+      sprintf(fname,"_ieeeneg%c",x_t[t&NQ]);
+      ret=fname;
+    }else if(c>=ADD&&c<=DIV){
+      sprintf(fname,"_ieee%s%c",ename[c],x_t[t&NQ]);
+      ret=fname;
+    }
+    if(c==TEST){
+      sprintf(fname,"_ieeetst%c",x_t[t&NQ]);
+      ret=fname;
+    }
+  }else if(CPU<68020&&!OLDLIBCALLS){
+    if((c==DIV||c==MOD)&&ISINT(t)&&zm2l(sizetab[t&NQ])==4){
+      sprintf(fname,"_%s%c",ename[c],(t&UNSIGNED)?'u':'s');
+      ret=fname;
+    }
+  }
+  return ret;
+}
+
+
+int reg_parm(treg_handle *p,type *t,int mode,type *fkt)
+{
+  int f;
+
+  if(!fkt||fkt->flags!=FUNKT)
+    ierror(0);
+
+  if(!fkt->next)
+    ierror(0);
+
+  if(stdargs(fkt))
+     return 0;
+
+  f=t->flags&NQ;
+  if(mode/*||f==LLONG||!ISSCALAR(f)*/)
+    return 0;
+  if(ISPOINTER(f)){
+    if(p->ar>ascratch)
+      return 0;
+    else
+      return a0+p->ar++;
+  }
+  if(ISFLOAT(f)||f==LLONG){
+    if(FPU<=68000||f==LLONG){
+      if(rparmtype==PARMSAS) return 0;
+      if(f!=FLOAT){
+	if(p->dr!=0) return 0;
+	p->dr+=2;
+	return d0d1;
+      }
+      if(p->dr>dscratch)
+	return 0;
+      else
+	return d0+p->dr++;
+    }else{
+      if(p->fr>fscratch)
+	return 0;
+      else
+	return fp0+p->fr++;
+    }
+  }
+  if(!ISINT(f)) return 0;
+  if(p->dr>dscratch)
+    return 0;
+  else
+    return d0+p->dr++;
+}
+
+int handle_pragma(const char *s)
+{
+  if(!strncmp("stdargs-on",s,10)){
+    add_stdargs=1;
+    return 1;
+  }
+  if(!strncmp("stdargs-off",s,11)){
+    add_stdargs=0;
+    return 1;
+  }
+  return 0;
+}
+
+void add_var_hook_pre(const char *identifier, type *t, int storage_class,const_list *clist)
+{
+  if(!add_stdargs) return;
+  if(ISFUNC(t->flags))
+    add_attr(&t->next->attr,"__stdargs");
+}
diff --git a/machines/m68k/machine.dt b/machines/m68k/machine.dt
new file mode 100755
index 0000000..526c8d4
--- /dev/null
+++ b/machines/m68k/machine.dt
@@ -0,0 +1,16 @@
+S8BS
+S8BU
+S16BSBE S16BSLE
+S16BUBE S16BULE
+S32BSBE S32BSLE
+S32BUBE S32BULE
+S32BSBE S32BSLE
+S32BUBE S32BULE
+S64BSBE S64BSLE
+S64BUBE S64BULE
+S32BIEEEBE
+S64BIEEEBE
+S64BIEEEBE
+S32BUBE S32BULE
+
+
diff --git a/machines/m68k/machine.h b/machines/m68k/machine.h
new file mode 100644
index 0000000..c9d2afe
--- /dev/null
+++ b/machines/m68k/machine.h
@@ -0,0 +1,118 @@
+/*  $VER: vbcc (m68k/machine.h) $Revision: 1.13 $     */
+
+#include "dt.h"
+
+/*  This struct can be used to implement machine-specific           */
+/*  addressing-modes.                                               */
+typedef struct AddressingMode{
+    int basereg;
+    long dist;
+    int skal;
+    int dreg;
+} AddressingMode;
+
+/*  The number of registers of the target machine.                  */
+#define MAXR 28
+
+/*  Number of commandline-options the code-generator accepts.       */
+#define MAXGF 35
+
+/*  If this is set to zero vbcc will not generate ICs where the     */
+/*  target operand is the same as the 2nd source operand.           */
+/*  This can sometimes simplify the code-generator, but usually     */
+/*  the code is better if the code-generator allows it.             */
+#define USEQ2ASZ 1
+
+/*  This specifies the smallest integer type that can be added to a */
+/*  pointer.                                                        */
+extern int MINADDI2P;
+
+/*  This specifies the smallest unsigned type that can be added to a */
+/*  pointer.                                                        */
+#define MINADDUI2P (UNSIGNED|INT)
+
+
+/*  This specifies the biggest integer type that can be added to a  */
+/*  pointer.                                                        */
+#define MAXADDI2P LONG
+
+/*  If the bytes of an integer are ordered most significant byte    */
+/*  byte first and then decreasing set BIGENDIAN to 1.              */
+#define BIGENDIAN 1
+
+/*  If the bytes of an integer are ordered lest significant byte    */
+/*  byte first and then increasing set LITTLEENDIAN to 1.           */
+#define LITTLEENDIAN 0
+
+/*  Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive.    */
+
+/*  If switch-statements should be generated as a sequence of       */
+/*  SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1.      */
+/*  This can yield better code on some machines.                    */
+#define SWITCHSUBS 1
+
+/*  In optimizing compilation certain library memcpy/strcpy-calls   */
+/*  with length known at compile-time will be inlined using an      */
+/*  ASSIGN-IC if the size is less or equal to INLINEMEMCPY.         */
+/*  The type used for the ASSIGN-IC will be UNSIGNED|CHAR.          */
+#define INLINEMEMCPY 256
+
+/*  We have some target-specific variable attributes.               */
+#define HAVE_TARGET_ATTRIBUTES 1
+
+/*  We keep track of all registers modified by a function.          */
+#define HAVE_REGS_MODIFIED 1
+
+#define HAVE_TARGET_RALLOC 1
+#define cost_move_reg(x,y) 1
+#define cost_load_reg(x,y) 2
+#define cost_save_reg(x,y) 2
+#define cost_pushpop_reg(x) 2
+
+/* size of buffer for asm-output */
+#define EMIT_BUF_LEN 1024 /* should be enough */
+/* number of asm-output lines buffered */
+#define EMIT_BUF_DEPTH 4
+
+/*  We have no asm_peephole to optimize assembly-output */
+#define HAVE_TARGET_PEEPHOLE 1
+
+/* we have a mark_eff_ics function */
+#define HAVE_TARGET_EFF_IC 1
+
+/* we have register-pairs */
+#define HAVE_REGPAIRS 1
+
+#define HAVE_REGPARMS 1
+
+struct reg_handle {
+  int dr,ar,fr;
+};
+
+
+#define JUMP_TABLE_DENSITY 0.8
+#define JUMP_TABLE_LENGTH 8
+
+/* support for variable-length arrays */
+#define ALLOCVLA_REG 9
+#define ALLOCVLA_INLINEASM "\taddq.l\t#3,d0\n\tand.b\t#252,d0\n\tsub.l\td0,a7\n\tmove.l\ta7,d0"
+#define FREEVLA_REG 0
+/* TODO: find a better solution some time */
+#define FREEVLA_INLINEASM "\tmove.l\t(a7),a7\n\tsubq.l\t#4,a7"
+#define OLDSPVLA_INLINEASM "\tmove.l\ta7,d0"
+#define FPVLA_REG 6
+
+/* We use builtin libcalls for some operations */
+#define HAVE_LIBCALLS 1
+
+/* We have target-specific pragmas */
+#define HAVE_TARGET_PRAGMAS
+
+/* We have a target-specific add_var hook */
+#define HAVE_TARGET_VARHOOK_PRE
+
+#define HAVE_POF2OPT 1
+
+#ifndef M68K_16BIT_INT
+#define HAVE_INT_SIZET 1
+#endif
diff --git a/machines/m68ks/machine.c b/machines/m68ks/machine.c
new file mode 100755
index 0000000..ca342b5
--- /dev/null
+++ b/machines/m68ks/machine.c
@@ -0,0 +1,7 @@
+/*  Code generator for Motorola 680x0 CPUs. Supports 68000-68060+68881/2    */
+/*  and ColdFire.                                                           */
+/*  PhxAss and the GNU assembler is supported.                              */
+
+/*  stub for ST version with 16bit int  */
+
+#include "machines/m68k/machine.c"
diff --git a/machines/m68ks/machine.dt b/machines/m68ks/machine.dt
new file mode 100755
index 0000000..44544a2
--- /dev/null
+++ b/machines/m68ks/machine.dt
@@ -0,0 +1,16 @@
+S8BS
+S8BU
+S16BSBE S16BSLE
+S16BUBE S16BULE
+S16BSBE S16BSLE
+S16BUBE S16BULE
+S32BSBE S32BSLE
+S32BUBE S32BULE
+S64BSBE S64BSLE
+S64BUBE S64BULE
+S32BIEEEBE
+S64BIEEEBE
+S64BIEEEBE
+S32BUBE S32BULE
+
+
diff --git a/machines/m68ks/machine.h b/machines/m68ks/machine.h
new file mode 100755
index 0000000..ac3ee6a
--- /dev/null
+++ b/machines/m68ks/machine.h
@@ -0,0 +1,14 @@
+/*  Code generator for Motorola 680x0 CPUs. Supports 68000-68060+68881/2    */
+/*  and ColdFire.                                                           */
+/*  PhxAss and the GNU assembler is supported.                              */
+
+/*  stub for ST version with 16bit int  */
+
+#define M68K_16BIT_INT
+
+#define PTRDIFF_T(x) LONG
+
+#define BESTCOPYT LONG
+
+#include "dt.h"
+#include "../m68k/machine.h"
diff --git a/machines/mark/machine.c b/machines/mark/machine.c
new file mode 100644
index 0000000..f4859dc
--- /dev/null
+++ b/machines/mark/machine.c
@@ -0,0 +1,1526 @@
+#include "supp.h"
+//#define DEBUG_MARK
+
+static char FILE_[]=__FILE__;
+
+//#include "version.h"
+char cg_copyright[]="not for public release";
+
+int g_flags[MAXGF]={};
+char *g_flags_name[MAXGF]={};
+union ppi g_flags_val[MAXGF];
+
+struct reg_handle empty_reg_handle={0};
+
+extern int handle_pragma(const char * c){return 0;}
+
+//support for ISR
+char *g_attr_name[] = {"__interrupt", 0};
+#define INTERRUPT 1
+
+/*
+ * Define registers codes
+ */
+
+#define R0 1  //zero register
+#define R1 2  //reserved for compiler
+#define R2 3  //reserved for compiler
+#define R3 4  //reserved for compiler
+#define R4 5  //condition codes
+#define R5 6  //return value
+#define R6 7
+#define R7 8
+#define R8 9
+#define R9 10
+#define R10 11
+#define R11 12
+#define R12 13
+#define FP 14 //frame pointer
+#define PC 15 //program counter
+#define SP 16 //stack pointer
+
+/*
+ * Custom function
+ */
+
+//evalue compare IC and prepare condition codes in R3 (COMPARE IC is followed by BRANCH allways)
+void compare(FILE *f, struct IC *p);
+//helper function for loading obj o into register dest_reg
+void load_into_reg(FILE *f, int dest_reg, struct obj *o, int type, int tmp_reg);
+//store reg into obj o
+void store_from_reg(FILE *f, int source_reg, struct obj *o, int type, int tmp_reg, int tmp_reg_b);
+//take care about all arithmetic IC
+void arithmetic(FILE *f, struct IC *p);
+//load constant into register
+void load_cons(FILE *f, int reg, long int value);
+
+/*
+ * Data Types
+ */
+zmax char_bit; // CHAR_BIT for the target machine.
+zmax align[MAX_TYPE+1]; //  Alignment-requirements for all types in bytes.
+zmax maxalign; //  Alignment that is sufficient for every object.
+zmax sizetab[MAX_TYPE+1]; //  sizes of the basic types (in bytes)
+
+//  Minimum and Maximum values each type can have.
+zmax t_min[MAX_TYPE+1];
+zumax t_max[MAX_TYPE+1];
+zumax tu_max[MAX_TYPE+1];
+
+
+/*
+ * Register  Set
+ */
+
+/*
+ * Names of all registers. will be initialized in init_cg(),
+ * register number 0 is invalid, valid registers start at 1
+ */
+char *regnames[MAXR+1];
+
+/*
+ *  The Size of each register in bytes.
+ */
+zmax regsize[MAXR+1];
+
+/*
+ *   Specifies which registers may be scratched by functions.
+ */
+int regscratch[MAXR+1];
+
+/*
+ *   a 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 the priority for the register-allocator, if the same
+ * estimated cost-saving can be obtained by several registers, the
+ * one with the highest priority will be used
+ */
+int reg_prio[MAXR+1];
+
+
+/*
+ * Does necessary initializations for the code-generator. Gets called
+ * once at the beginning and should return 0 in case of problems.
+ */
+int init_cg(void){
+
+    #ifdef DEBUG_MARK
+    printf("Called init_cg()\n");
+    #endif
+
+    int i;
+
+    maxalign=l2zm(1L);
+    char_bit=l2zm(32L);
+
+    for(i=0;i<=MAX_TYPE;i++){
+        align[i] = l2zm(1L);
+        sizetab[i] = l2zm(1L);
+    }
+
+    t_min[CHAR] = zmsub(l2zm(-2147483647L),l2zm(1L));
+    t_min[SHORT] = t_min[CHAR];
+    t_min[INT] = t_min[CHAR];
+    t_min[LONG] = t_min[CHAR];
+    t_min[LLONG] = t_min[CHAR];
+    t_min[MAXINT] = t_min[CHAR];
+
+    t_max[CHAR] = ul2zum(2147483647UL);
+    t_max[SHORT] = t_max[CHAR];
+    t_max[INT] = t_max[CHAR];
+    t_max[LONG] = t_max[CHAR];
+    t_max[LLONG] = t_max[CHAR];
+    t_max[MAXINT] = t_max[CHAR];
+
+    tu_max[CHAR]=ul2zum(4294967295UL);
+    tu_max[SHORT] = tu_max[CHAR];
+    tu_max[INT] = tu_max[CHAR];
+    tu_max[LONG] = tu_max[CHAR];
+    tu_max[LLONG] = tu_max[CHAR];
+    tu_max[MAXINT] = tu_max[CHAR];
+
+
+    regnames[0] = "noreg";
+    reg_prio[0] = 0;
+    regscratch[0] = 0;
+    regsa[0] = 0;
+
+    //zero register
+    regnames[1] = "R0";
+    reg_prio[1] = 0;
+    regscratch[1] = 0;
+    regsa[1] = 1;
+
+    //R1 reserved for backed
+    regnames[2] = "R1";
+    reg_prio[2] = 0;
+    regscratch[2] = 0;
+    regsa[2] = 1;
+
+    //R2 reserved for backed
+    regnames[3] = "R2";
+    reg_prio[3] = 0;
+    regscratch[3] = 0;
+    regsa[3] = 1;
+
+    //R3 reserved for backed
+    regnames[4] = "R3";
+    reg_prio[4] = 0;
+    regscratch[4] = 0;
+    regsa[4] = 1;
+
+    //R4 condition codes
+    regnames[5] = "R4";
+    reg_prio[5] = 0;
+    regscratch[5] = 0;
+    regsa[5] = 1;
+
+    //R5 return value for function
+    regnames[6] = "R5";
+    reg_prio[6] = 0;
+    regscratch[6] = 0;
+    regsa[6] = 1;
+
+    regnames[7] = "R6";
+    reg_prio[7] = 0;
+    regscratch[7] = 0;
+    regsa[7] = 0;
+
+    regnames[8] = "R7";
+    reg_prio[8] = 0;
+    regscratch[8] = 0;
+    regsa[8] = 0;
+
+    regnames[9] = "R8";
+    reg_prio[9] = 0;
+    regscratch[9] = 0;
+    regsa[9] = 0;
+
+    regnames[10] = "R9";
+    reg_prio[10] = 0;
+    regscratch[10] = 0;
+    regsa[10] = 0;
+
+    regnames[11] = "R10";
+    reg_prio[11] = 0;
+    regscratch[11] = 0;
+    regsa[11] = 0;
+
+    regnames[12] = "R11";
+    reg_prio[12] = 0;
+    regscratch[12] = 0;
+    regsa[12] = 0;
+
+    regnames[13] = "R12";
+    reg_prio[13] = 0;
+    regscratch[13] = 0;
+    regsa[13] = 0;
+
+    // Frame pointer
+    regnames[FP] = "R13";
+    reg_prio[14] = 0;
+    regscratch[14] = 0;
+    regsa[14] = 1;
+
+    // Program counter
+    regnames[15] = "PC";
+    reg_prio[15] = 0;
+    regscratch[15] = 0;
+    regsa[15] = 1;
+
+    // Stack pointer
+    regnames[16] = "SP";
+    reg_prio[16] = 0;
+    regscratch[16] = 0;
+    regsa[16] = 1;
+
+
+    for(i=0;i<=MAXR;i++){
+        regsize[i] = l2zm(1L);
+    }
+
+    // Use multiple ccs
+    multiple_ccs = 0;
+
+    return 1;
+}
+
+void cleanup_cg(FILE *f){
+    #ifdef DEBUG_MARK
+    printf("Called cleanup_cg()\n");
+    #endif
+}
+
+/*
+ * Returns the register in which variables of type t are returned.
+ * If the value cannot be returned in a register returns 0.
+ */
+int freturn(struct Typ *t){
+    return R5;
+}
+
+/*
+ * 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.
+ */
+int regok(int r,int t,int mode){
+    return 1;
+}
+
+/*
+ *  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 dangerous_IC(struct IC *p){
+    return 0;
+}
+
+/*
+ *  Returns zero if code for converting np to type t
+ *  can be omitted.
+ *  On the PowerPC cpu pointers and 32bit
+ *  integers have the same representation and can use
+ *  the same registers.
+ */
+int must_convert(int o,int t,int const_expr){
+    return 0;
+}
+
+int shortcut(int code,int typ){
+    return 0;
+}
+
+/*
+ *  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 *p,struct Var *v,zmax offset){
+    #ifdef DEBUG_MARK
+    printf("Called gen_code(FILE *f,struct IC *p,struct Var *v,zmax offset)\n");
+    printf("\tIdentifier: %s", v->identifier);
+    #endif
+
+    //emit function head
+    if(v->storage_class==EXTERN){
+        if( (v->flags & (INLINEFUNC|INLINEEXT)) != INLINEFUNC ){
+            emit(f,".EXPORT \t %s \n",v->identifier);
+        }
+        emit(f,"%s: \n",v->identifier);
+    }
+    else{
+        emit(f,"L_%ld:\n",zm2l(v->offset));
+    }
+
+    //emit function prologue
+    emit(f, "\tPUSH \t %s\n", regnames[FP]);  //push FP
+    emit(f, "\tOR   \t %s %s %s\n",regnames[R0], regnames[SP], regnames[FP]); //MOVE SP -> FP
+
+    //make space for auto variables at stack
+    for(int i = 0; i < zm2l(offset); i++){
+        emit(f, "\tDEC \t %s %s\n", regnames[SP], regnames[SP]);
+    }
+
+    //store backend registers
+    emit(f, "\tPUSH \t R1\n\tPUSH \t R2\n\tPUSH \t R3\n\tPUSH \t R4\n");
+
+    //find used registers
+    int saved_regs[7] = {0, 0, 0, 0, 0, 0, 0};
+
+    struct IC *ps = p;
+    for(;ps;ps=ps->next){
+        if( ((ps->code) != FREEREG) && ((ps->code) != ALLOCREG) ){
+            if(((ps->q1.flags) & (KONST|VAR|REG|DREFOBJ|VARADR)) == REG){
+                if(((ps->q1.reg) > R5) && ((ps->q1.reg) < FP)){
+                    saved_regs[(ps->q1.reg) - 7] = 1;
+                }
+            }
+            if(((ps->q2.flags) & (KONST|VAR|REG|DREFOBJ|VARADR)) == REG){
+                if(((ps->q2.reg) > R5) && ((ps->q2.reg) < FP)){
+                    saved_regs[(ps->q2.reg) - 7] = 1;
+                }
+            }
+            if(((ps->z.flags) & (KONST|VAR|REG|DREFOBJ|VARADR)) == REG){
+                if(((ps->z.reg) > R5) && ((ps->z.reg) < FP)){
+                    saved_regs[(ps->z.reg) - 7] = 1;
+                }
+            }
+        }
+    }
+
+    //save used registers
+    for(int i = 0; i < 7; i++){
+        if(saved_regs[i] == 1){
+            emit(f, "\tPUSH \t %s\n", regnames[i + 7]);
+        }
+    }
+
+    //emit function body
+    for(;p;p=p->next){
+        int c = p->code;
+
+        #ifdef DEBUG_MARK
+        emit(f, "\n\t;p->code: %d\n", p->code);
+        #endif
+
+        switch(p->code){
+            case ASSIGN:
+                #ifdef DEBUG_MARK
+                printf("\n\tASSIGN\n\tz.flags:%d\tq1.flags:%d\ttypf:%d\n", p->z.flags, p->q1.flags, p->typf);
+                #endif
+
+                //we can simplify assign when both operands are in registers
+                if((((p->q1.flags) & (KONST|VAR|REG|DREFOBJ|VARADR)) == REG) &&
+                   (((p->z.flags) & (KONST|VAR|REG|DREFOBJ|VARADR)) == REG) ){
+                    emit(f, "\tOR   \t %s %s %s",regnames[R0], regnames[p->q1.reg], regnames[p->z.reg]);
+                }
+
+                //this is another optimalization, if have to assign zero; then
+                //zero is read from R0 insted pushing constant into register
+                else if(
+                (((p->q1.flags) & (KONST|VAR|REG|DREFOBJ|VARADR)) == KONST) &&
+                ((p->q1.val.vmax) == 0)
+                ){
+                    store_from_reg(f, R0, &(p->z), p->typf, R2, R3);
+                }
+
+                else{
+                    load_into_reg(f, R1, &(p->q1), p->typf, R2);
+                    store_from_reg(f, R1, &(p->z), p->typf, R2, R3);
+                }
+
+                break;
+            case OR:
+                #ifdef DEBUG_MARK
+                printf("\n\tOR\n");
+                #endif
+                arithmetic(f, p);
+                break;
+            case XOR:
+                #ifdef DEBUG_MARK
+                printf("\n\tXOR\n");
+                #endif
+                arithmetic(f, p);
+                break;
+            case AND:
+                #ifdef DEBUG_MARK
+                printf("\n\tAND\n");
+                #endif
+                arithmetic(f, p);
+                break;
+            case LSHIFT:
+                #ifdef DEBUG_MARK
+                printf("\n\tLSHIFT\n");
+                #endif
+                arithmetic(f, p);
+                break;
+            case RSHIFT:
+                #ifdef DEBUG_MARK
+                printf("\n\tRSHIFT\n");
+                #endif
+                arithmetic(f, p);
+                break;
+            case ADD:
+                #ifdef DEBUG_MARK
+                printf("\n\tADD\n");
+                #endif
+                arithmetic(f, p);
+                break;
+            case SUB:
+                #ifdef DEBUG_MARK
+                printf("\n\tSUB\n");
+                #endif
+                arithmetic(f, p);
+                break;
+            case MULT:
+                #ifdef DEBUG_MARK
+                printf("\n\tMULT\n");
+                #endif
+                arithmetic(f, p);
+                break;
+            case DIV:
+                #ifdef DEBUG_MARK
+                printf("\n\tDIV\n");
+                #endif
+                arithmetic(f, p);
+                break;
+            case MOD:
+                #ifdef DEBUG_MARK
+                printf("\n\tMOD\n");
+                #endif
+                arithmetic(f, p);
+                break;
+            case KOMPLEMENT:
+                #ifdef DEBUG_MARK
+                printf("\n\tKOMPLEMENT\n");
+                #endif
+                arithmetic(f, p);
+                break;
+            case MINUS:
+                #ifdef DEBUG_MARK
+                printf("\n\tMINUS\n");
+                #endif
+                arithmetic(f, p);
+                break;
+            case ADDRESS:
+                #ifdef DEBUG_MARK
+                printf("\n\tADDRESS\n");
+                #endif
+
+                if(
+                (((p->q1.flags) & (KONST|VAR|REG|DREFOBJ|VARADR)) == VAR) &&
+                (((p->q1.v->storage_class) & (AUTO|REGISTER|STATIC|EXTERN)) == AUTO)
+                ){
+                    if(ISARRAY(p->q1.v->flags)){
+                        load_cons(f, R1, zm2l(p->q1.v->offset)+zm2l(p->q1.val.vmax));
+                    }
+                    else{
+                        load_cons(f, R1, zm2l(p->q1.v->offset));
+                    }
+                    emit(f, "\tADD \t R1 R13 R1\n");
+                    store_from_reg(f, R1, &(p->z), p->typf, R2, R3);
+                }
+                else{
+                    ierror(0);
+                }
+
+                break;
+            case CALL:
+                #ifdef DEBUG_MARK
+                printf("\n\tCALL\n\tq1.flags: %d\n", p->q1.flags);
+                #endif
+
+                if((p->q1.flags & (VAR|DREFOBJ)) == VAR && p->q1.v->fi && p->q1.v->fi->inline_asm){
+                    emit_inline_asm(f,p->q1.v->fi->inline_asm);
+                }
+                else{
+
+                    if(((p->q1.flags) & (KONST|VAR|REG|DREFOBJ|VARADR)) == VAR){
+
+                        #ifdef DEBUG_MARK
+                        printf("\tq1.v->storage_class: %d\n", p->q1.v->storage_class);
+                        #endif
+
+                        switch((p->q1.v->storage_class) & (AUTO|REGISTER|STATIC|EXTERN)){
+                            case EXTERN:
+                                emit(f, "\tCALL \t %s\n", p->q1.v->identifier);
+                                for(int i = 0; i < (p->q2.val.vmax); i++){
+                                    emit(f, "\tINC \t %s %s\n", regnames[SP], regnames[SP]);
+                                }
+                                break;
+                            case STATIC:
+                                emit(f, "\tCALL \t L_%ld\n", zm2l(p->q1.v->offset));
+                                for(int i = 0; i < (p->q2.val.vmax); i++){
+                                    emit(f, "\tINC \t %s %s\n", regnames[SP], regnames[SP]);
+                                }
+                                break;
+                            default:
+                                #ifdef DEBUG_MARK
+                                printf("\tThis is not implemented!\n");
+                                #else
+                                ierror(0);
+                                #endif
+                                break;
+                        }
+
+                    }
+                    else if(((p->q1.flags) & (KONST|VAR|REG|DREFOBJ|VARADR)) == (VAR|DREFOBJ)){
+                        #ifdef DEBUG_MARK
+                        printf("\tq1.v->storage_class: %d\n", p->q1.v->storage_class);
+                        #endif                        
+                        load_into_reg(f, R1, &(p->q1), p->typf, R3);
+                        emit(f, "\tCALLI\t %s\n", regnames[R1]);                        
+                        emit(f, "\tINC \t %s %s\n", regnames[SP], regnames[SP]);                        
+                    }
+                    else{
+                        #ifdef DEBUG_MARK
+                        printf("\tThis is not implemented!\n");
+                        #else
+                        ierror(0);
+                        #endif
+                    }
+                }
+                break;
+            case CONVERT:
+                #ifdef DEBUG_MARK
+                printf("\n\tCONVERT\n");
+                #endif
+
+                break;
+            case ALLOCREG:
+                #ifdef DEBUG_MARK
+                printf("\n\tALLOCREG\n");
+                #endif
+
+                regs[p->q1.reg] = 1;
+                break;
+            case FREEREG:
+                #ifdef DEBUG_MARK
+                printf("\n\tFREEREG\n");
+                #endif
+
+                regs[p->q1.reg] = 0;
+                break;
+            case COMPARE:
+                #ifdef DEBUG_MARK
+                printf("\n\tCOMPARE\n");
+                #endif
+
+                compare(f, p);
+                break;
+            case TEST:
+                #ifdef DEBUG_MARK
+                printf("\n\tTEST\n");
+                #endif
+
+                compare(f, p);
+                break;
+            case LABEL:
+                #ifdef DEBUG_MARK
+                printf("\n\tLABEL\n");
+                #endif
+
+                emit(f,"L_%d:\n",p->typf);
+                break;
+            case BEQ:
+                #ifdef DEBUG_MARK
+                printf("\n\tBEQ\n");
+                #endif
+
+                emit(f, "\tBNZ \t R4 L_%d\n", p->typf);
+                break;
+            case BNE:
+                #ifdef DEBUG_MARK
+                printf("\n\tBNE\n");
+                #endif
+
+                emit(f, "\tBNZ \t R4 L_%d\n", p->typf);
+                break;
+            case BLT:
+                #ifdef DEBUG_MARK
+                printf("\n\tBLT\n");
+                #endif
+
+                emit(f, "\tBNZ \t R4 L_%d\n", p->typf);
+                break;
+            case BGE:
+                #ifdef DEBUG_MARK
+                printf("\n\tBGE\n");
+                #endif
+
+                emit(f, "\tBNZ \t R4 L_%d\n", p->typf);
+                break;
+            case BLE:
+                #ifdef DEBUG_MARK
+                printf("\n\tBLE\n");
+                #endif
+
+                emit(f, "\tBNZ \t R4 L_%d\n", p->typf);
+                break;
+            case BGT:
+                #ifdef DEBUG_MARK
+                printf("\n\tBGT\n");
+                #endif
+
+                emit(f, "\tBNZ \t R4 L_%d\n", p->typf);
+                break;
+            case BRA:
+                #ifdef DEBUG_MARK
+                printf("\n\tBRA\n");
+                #endif
+
+                emit(f, "\tBZ   \t R0 L_%d\n", p->typf);
+                break;
+            case PUSH:
+                #ifdef DEBUG_MARK
+                printf("\n\tPUSH\n");
+                #endif
+
+                load_into_reg(f, R1, &(p->q1), p->typf, R2);
+                emit(f, "\tPUSH \t R1\n");
+                break;
+            case ADDI2P:
+                #ifdef DEBUG_MARK
+                printf("\n\tADDI2P\n");
+                #endif
+                arithmetic(f, p);
+                break;
+            case SUBIFP:
+                #ifdef DEBUG_MARK
+                printf("\n\tSUBIFP\n");
+                #endif
+                arithmetic(f, p);
+                break;
+            case SUBPFP:
+                #ifdef DEBUG_MARK
+                printf("\n\tSUBPFP\n");
+                #endif
+                arithmetic(f, p);
+                break;
+            case GETRETURN:
+                #ifdef DEBUG_MARK
+                printf("\n\tGETRETURN\n");
+                #endif
+                if((p->q1.reg) != 0){
+                    store_from_reg(f, p->q1.reg, &(p->z), p->typf, R2, R3);
+                }
+                else{
+                    #ifdef DEBUG_MARK
+                    printf("\tq1.reg == 0, didn't know how to dealt with it!");
+                    #else
+                    ierror(0);
+                    #endif
+                }
+                break;
+            case SETRETURN:
+                #ifdef DEBUG_MARK
+                printf("\n\tSETRETURN\n\tz.flags:%d\n", p->z.flags);
+                #endif
+                if((p->z.reg) != 0){
+                    load_into_reg(f, p->z.reg, &(p->q1), p->typf, R1);
+                }
+                else{
+                    #ifdef DEBUG_MARK
+                    printf("\tz.reg == 0, didn't know how to dealt with it!");
+                    #else
+                    ierror(0);
+                    #endif
+                }
+                break;
+            case MOVEFROMREG:
+                #ifdef DEBUG_MARK
+                printf("\n\tMOVEFROMREG\n");
+                #endif
+
+                store_from_reg(f, p->q1.reg, &(p->z), p->typf, R1, R3);
+                break;
+            case MOVETOREG:
+                #ifdef DEBUG_MARK
+                printf("\n\tMOVETOREG\n");
+                #endif
+
+                load_into_reg(f, p->z.reg, &(p->q1), p->typf, R1);
+                break;
+            case NOP:
+                #ifdef DEBUG_MARK
+                printf("\n\tNOP\n");
+                #endif
+                break;
+            default:
+                #ifdef DEBUG_MARK
+                printf("\tSomething is wrong in gencode()!\n");
+                #else
+                ierror(0);
+                #endif
+                break;
+        }
+    }
+
+    //restore used registers
+    for(int i = 6; i >= 0; i--){
+        if(saved_regs[i] == 1){
+            emit(f, "\tPOP \t %s\n", regnames[i + 7]);
+        }
+    }
+
+    //restore backend registers
+    emit(f, "\tPOP \t R4\n\tPOP \t R3\n\tPOP \t R2\n\tPOP \t R1\n");
+
+    //emit function epilogue
+    emit(f, "\tOR  \t %s %s %s\n",regnames[R0], regnames[FP], regnames[SP]); //restore SP from FP
+    emit(f, "\tPOP \t %s\n", regnames[FP]); //restore old FP from stack
+
+    //return
+    if((v->tattr)&INTERRUPT){
+        emit(f, "\tRETI\n");
+    }
+    else{
+        emit(f, "\tRET\n");
+    }
+}
+
+/*
+ *  This function has to create <size> bytes of storage
+ *  initialized with zero.
+ */
+void gen_ds(FILE *f,zmax size,struct Typ *t){
+    #ifdef DEBUG_MARK
+    printf("Called gen_ds(FILE *f,zmax size,struct Typ *t)\n");
+    #endif
+    emit(f, "\t.DS \t%ld\n", zm2l(size));
+}
+
+/*
+ *  This function has to make sure the next data is
+ *  aligned to multiples of <align> bytes.
+ */
+void gen_align(FILE *f,zmax align){}
+
+/*
+ *  This function has to create the head of a variable
+ *  definition, i.e. the label and information for
+ *  linkage etc.
+ */
+void gen_var_head(FILE *f,struct Var *v){
+    #ifdef DEBUG_MARK
+    printf("Called gen_var_head(FILE *f,struct Var *v)\n");
+    #endif
+
+    switch((v->storage_class) & (STATIC|EXTERN|AUTO|REGISTER)){
+        case STATIC:
+            #ifdef DEBUG_MARK
+            printf("\tHave to emit static variable head.\n");
+            #endif
+            emit(f,"L_%ld:\n", zm2l(v->offset));
+            break;
+        case EXTERN:
+            #ifdef DEBUG_MARK
+            printf("\tHave to emit extern variable head.\n");
+            #endif
+
+            if(v->flags&(DEFINED|TENTATIVE)){
+                emit(f,".EXPORT \t %s\n", v->identifier);
+                emit(f,"%s:\n", v->identifier);
+            }
+            else{
+                emit(f,".IMPORT \t %s\n", v->identifier);
+            }
+            break;
+        default:
+            #ifdef DEBUG_MARK
+            printf("\tCant generate head, unknown storage class: %d\n", v->storage_class);
+            #else
+            ierror(0);
+            #endif
+            break;
+    }
+}
+
+/*
+ *  This function has to create static storage
+ *  initialized with const-list p.
+ */
+void gen_dc(FILE *f,int t,struct const_list *p){
+    #ifdef DEBUG_MARK
+    printf("Called gen_dc(FILE *f,int t,struct const_list *p)\n");
+    #endif
+
+    if(!p->tree){
+        if(ISFLOAT(t)){
+            emit(f,"\t.DAT \t ");
+            emit(f,"0x%x", *(unsigned int*)&p->val);
+            emit(f,"\n");
+        }
+        else{
+            emit(f,"\t.DAT \t ");
+            emitval(f,&p->val,t&NU);
+            emit(f,"\n");
+        }
+    }
+    else{
+        emit(f,"\t.DAT \t ");
+        struct const_list *p_next = p;
+        for(;p_next;p_next=p_next->next){
+            emitval(f,&p_next->val,t&NU);
+            emit(f, " ");
+        }
+        emit(f, "\n");
+    }
+}
+
+//this is for debug, not needed now
+void init_db(FILE *f){}
+void cleanup_db(FILE *f){}
+
+int reg_parm(struct reg_handle *m, struct Typ *t,int vararg,struct Typ *d){
+    //this will put all arguments into stack
+    return 0;
+}
+
+/*
+ * 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.
+ */
+int reg_pair(int r,struct rpair *p){
+    return 0;
+}
+
+void compare(FILE *f, struct IC *p){
+
+    int q1reg = 0;
+    int q2reg = 0;
+
+    //load operands into R1 and R2
+    if(((p->q1.flags) & (KONST|VAR|REG|DREFOBJ|VARADR)) != REG){
+        load_into_reg(f, R1, &(p->q1), p->typf, R3);
+        q1reg = R1;
+    }
+    else{
+        q1reg = p->q1.reg;
+    }
+
+    if((p->code) != TEST){
+        if(((p->q2.flags) & (KONST|VAR|REG|DREFOBJ|VARADR)) != REG){
+            load_into_reg(f, R2, &(p->q2), p->typf, R3);
+            q2reg = R2;
+        }
+        else{
+            q2reg = p->q2.reg;
+        }
+    }
+    else{
+        q2reg = R2;
+        emit(f, "\tOR  \t %s %s %s\n",regnames[R0], regnames[R0], regnames[R2]);
+    }
+
+    //find branch IC
+    struct IC *branch_ic;
+    branch_ic = p->next;
+    while(branch_ic && ((branch_ic->code) == FREEREG) ) {
+        branch_ic = branch_ic->next;
+    }
+
+    //emit compare code
+    if (((p->typf) & FLOAT) == FLOAT || ((p->typf) & DOUBLE) == DOUBLE || ((p->typf) & LDOUBLE) == LDOUBLE){
+        switch(branch_ic->code){
+            case BEQ:
+                emit(f, "\tCMPF \t EQ %s %s R4\n", regnames[q1reg], regnames[q2reg]);
+                break;
+            case BNE:
+                emit(f, "\tCMPF \t NEQ %s %s R4\n", regnames[q1reg], regnames[q2reg]);
+                break;
+            case BLT:
+                emit(f, "\tCMPF \t L %s %s R4\n", regnames[q1reg], regnames[q2reg]);
+                break;
+            case BGE:
+                emit(f, "\tCMPF \t GE %s %s R4\n", regnames[q1reg], regnames[q2reg]);
+                break;
+            case BLE:
+                emit(f, "\tCMPF \t LE %s %s R4\n", regnames[q1reg], regnames[q2reg]);
+                break;
+            case BGT:
+                emit(f, "\tCMPF \t G %s %s R4\n", regnames[q1reg], regnames[q2reg]);
+                break;
+            default:
+                ierror(0);
+                break;
+        }
+    }
+    else{
+        switch(branch_ic->code){
+            case BEQ:
+                emit(f, "\tCMPI \t EQ %s %s R4\n", regnames[q1reg], regnames[q2reg]);
+                break;
+            case BNE:
+                emit(f, "\tCMPI \t NEQ %s %s R4\n", regnames[q1reg], regnames[q2reg]);
+                break;
+            case BLT:
+                if((p->typf & UNSIGNED) == UNSIGNED){
+                    emit(f, "\tCMPI \t LU %s %s R4\n", regnames[q1reg], regnames[q2reg]);
+                }
+                else{
+                    emit(f, "\tCMPI \t L %s %s R4\n", regnames[q1reg], regnames[q2reg]);
+                }
+                break;
+            case BGE:
+                if((p->typf & UNSIGNED) == UNSIGNED){
+                    emit(f, "\tCMPI \t GEU %s %s R4\n", regnames[q1reg], regnames[q2reg]);
+                }
+                else{
+                    emit(f, "\tCMPI \t GE %s %s R4\n", regnames[q1reg], regnames[q2reg]);
+                }
+                break;
+            case BLE:
+                if((p->typf & UNSIGNED) == UNSIGNED){
+                    emit(f, "\tCMPI \t LEU %s %s R4\n", regnames[q1reg], regnames[q2reg]);
+                }
+                else{
+                    emit(f, "\tCMPI \t LE %s %s R4\n", regnames[q1reg], regnames[q2reg]);
+                }
+                break;
+            case BGT:
+                if((p->typf & UNSIGNED) == UNSIGNED){
+                    emit(f, "\tCMPI \t GU %s %s R4\n", regnames[q1reg], regnames[q2reg]);
+                }
+                else{
+                    emit(f, "\tCMPI \t G %s %s R4\n", regnames[q1reg], regnames[q2reg]);
+                }
+                break;
+            default:
+                ierror(0);
+                break;
+        }
+    }
+}
+
+void load_into_reg(FILE *f, int dest_reg, struct obj *o, int type, int tmp_reg){
+    switch((o->flags) & (KONST|VAR|REG|DREFOBJ|VARADR)){
+        case KONST:
+            load_cons(f, dest_reg, o->val.vmax);
+            break;
+        case (KONST|DREFOBJ):
+            //place memory location constant point to into register
+            emit(f, "\tLD  \t ");
+            emitval(f, &(o->val), type);
+            emit(f, " %s\n", regnames[dest_reg]);
+            break;
+        case REG:
+            //move between registers
+            if((o->reg) != dest_reg){
+                emit(f, "\tOR  \t %s %s %s\n",regnames[R0], regnames[o->reg], regnames[dest_reg]);
+            }
+            break;
+        case VAR:
+            //put value of variable into register
+
+            switch((o->v->storage_class) & (STATIC|EXTERN|AUTO|REGISTER)){
+                case STATIC:
+                    if(zm2l(o->val.vmax) != 0){
+                        emit(f, "\tMVIA \t %s L_%ld\n", regnames[dest_reg], zm2l(o->v->offset));
+                        load_cons(f, tmp_reg, zm2l(o->val.vmax));
+                        emit(f, "\tADD \t %s %s %s\n", regnames[dest_reg], regnames[tmp_reg], regnames[tmp_reg]);
+                        emit(f, "\tLDI \t %s %s\n", regnames[tmp_reg], regnames[dest_reg]);
+                    }
+                    else{
+                        emit(f, "\tLD \t L_%ld %s\n", zm2l(o->v->offset), regnames[dest_reg]);
+                    }
+                    break;
+                case EXTERN:
+                    if(zm2l(o->val.vmax) != 0){
+                        emit(f, "\tMVIA \t %s %s\n", regnames[dest_reg], o->v->identifier);
+                        load_cons(f, tmp_reg, zm2l(o->val.vmax));
+                        emit(f, "\tADD \t %s %s %s\n", regnames[dest_reg], regnames[tmp_reg], regnames[tmp_reg]);
+                        emit(f, "\tLDI \t %s %s\n", regnames[tmp_reg], regnames[dest_reg]);
+                    }
+                    else{
+                        emit(f, "\tLD \t %s %s\n", o->v->identifier , regnames[dest_reg]);
+                    }
+                    break;
+                case AUTO:
+                    if((o->v->offset) < 0){
+                        //this is argument
+                        load_cons(f, dest_reg, (zm2l(o->v->offset)/(-1L))+2+zm2l(o->val.vmax));
+                        emit(f, "\tADD \t %s %s %s\n", regnames[dest_reg],regnames[FP], regnames[tmp_reg]);
+                        emit(f, "\tLDI \t %s %s\n", regnames[tmp_reg], regnames[dest_reg]);
+                    }
+                    else{
+                        //this is auto variable
+                        int offset = zm2l(o->v->offset)+zm2l(o->val.vmax);
+
+                        if(offset == 0){
+                            emit(f, "\tLDI \t %s %s\n", regnames[FP], regnames[dest_reg]);
+                        }
+                        else if(offset == 1){
+                            emit(f, "\tDEC \t %s %s\n", regnames[FP], regnames[tmp_reg]);
+                            emit(f, "\tLDI \t %s %s\n", regnames[tmp_reg], regnames[dest_reg]);
+                        }
+                        else{
+                            load_cons(f, dest_reg, offset);
+                            emit(f, "\tSUB \t %s %s %s\n", regnames[FP],regnames[dest_reg], regnames[tmp_reg]);
+                            emit(f, "\tLDI \t %s %s\n", regnames[tmp_reg], regnames[dest_reg]);
+                        }
+
+                    }
+                    break;
+                default:
+                    #ifdef DEBUG_MARK
+                    printf("\tHave to load variable that is not static, extern or auto, this is not implemented!\n");
+                    #else
+                    ierror(0);
+                    #endif
+                    break;
+            }
+
+            break;
+        case (VAR|REG):
+            if((o->reg) != dest_reg){
+                emit(f, "\tOR  \t %s %s %s\n", regnames[R0], regnames[o->reg], regnames[dest_reg]);
+            }
+            break;
+        case (REG|DREFOBJ):
+            //point into memory with register value
+
+            emit(f, "\tLDI \t %s %s\n", regnames[o->reg], regnames[dest_reg]);
+            break;
+        case (VAR|DREFOBJ):
+            //use variable value as pointer to memory
+
+            switch((o->v->storage_class) & (STATIC|EXTERN|AUTO|REGISTER)){
+                case STATIC:
+                    if(zm2l(o->val.vmax) != 0){
+                        emit(f, "\tMVIA \t %s L_%ld\n", regnames[dest_reg], zm2l(o->v->offset));
+                        load_cons(f, tmp_reg, zm2l(o->val.vmax));
+                        emit(f, "\tADD \t %s %s %s\n", regnames[dest_reg], regnames[tmp_reg], regnames[dest_reg]);
+                        emit(f, "\tLDI \t %s %s\n", regnames[dest_reg], regnames[tmp_reg]);
+                    }
+                    else{
+                        emit(f, "\tLD  \t L_%ld %s\n", zm2l(o->v->offset), regnames[tmp_reg]);
+                    }
+                    emit(f, "\tLDI \t %s %s\n", regnames[tmp_reg], regnames[dest_reg]);
+                    break;
+                case EXTERN:
+                    if(zm2l(o->val.vmax) != 0){
+                        emit(f, "\tMVIA \t %s %s\n", regnames[dest_reg], o->v->identifier);
+                        load_cons(f, tmp_reg, zm2l(o->val.vmax));
+                        emit(f, "\tADD \t %s %s %s\n", regnames[dest_reg], regnames[tmp_reg], regnames[dest_reg]);
+                        emit(f, "\tLDI \t %s %s\n", regnames[dest_reg], regnames[tmp_reg]);
+                    }
+                    else{
+                        emit(f, "\tLD \t %s %s\n", o->v->identifier , regnames[tmp_reg]);
+                    }
+                    emit(f, "\tLDI \t %s %s\n", regnames[tmp_reg], regnames[dest_reg]);
+                    break;
+                case AUTO:
+                    if((o->v->offset) < 0){
+                        //this is argument
+                        load_cons(f, dest_reg, (zm2l(o->v->offset)/(-1L))+2+zm2l(o->val.vmax));
+                        emit(f, "\tADD \t %s %s %s\n", regnames[dest_reg],regnames[FP], regnames[tmp_reg]);
+                        emit(f, "\tLDI \t %s %s\n", regnames[tmp_reg], regnames[dest_reg]);
+                    }
+                    else{
+                        //this is auto variable
+                        int offset = zm2l(o->v->offset)+zm2l(o->val.vmax);
+
+                        if(offset == 0){
+                            emit(f, "\tLDI \t %s %s\n", regnames[FP], regnames[dest_reg]);
+                        }
+                        else if(offset == 1){
+                            emit(f, "\tDEC \t %s %s\n", regnames[FP], regnames[tmp_reg]);
+                            emit(f, "\tLDI \t %s %s\n", regnames[tmp_reg], regnames[dest_reg]);
+                        }
+                        else{
+                            load_cons(f, dest_reg, offset);
+                            emit(f, "\tSUB \t %s %s %s\n", regnames[FP],regnames[dest_reg], regnames[tmp_reg]);
+                            emit(f, "\tLDI \t %s %s\n", regnames[tmp_reg], regnames[dest_reg]);
+                        }
+
+                    }
+                    break;
+                default:
+                    #ifdef DEBUG_MARK
+                    printf("\tHave to load variable that is not static, extern or auto, this is not implemented!\n");
+                    #else
+                    ierror(0);
+                    #endif
+                    break;
+            }
+
+            emit(f, "\tLDI \t %s %s\n", regnames[dest_reg], regnames[tmp_reg]);
+            emit(f, "\tOR  \t R0 %s %s\n", regnames[tmp_reg], regnames[dest_reg]);
+
+            break;
+        case (VAR|REG|DREFOBJ):
+            if((o->reg) != dest_reg){
+                emit(f, "\tOR  \t %s %s %s\n",regnames[R0], regnames[o->reg], regnames[tmp_reg]);
+            }
+            emit(f, "\tLDI \t %s %s\n", regnames[tmp_reg], regnames[dest_reg]);
+            break;
+        case (VAR|VARADR):
+            //into dest_reg store address of variable
+            switch((o->v->storage_class) & (STATIC|EXTERN)){
+                case EXTERN:
+                    emit(f, "\tMVIA \t %s %s\n", regnames[dest_reg], o->v->identifier);
+                    break;
+                case STATIC:
+                    emit(f, "\tMVIA \t %s L_%ld\n", regnames[dest_reg], zm2l(o->v->offset));
+                    break;
+                default: //this is pointless storage_class can be only static or extern with VARADR
+                    ierror(0);
+            }            
+            //this is useful when object is array and we want adres of nonfirst element
+            if(o->val.vmax > 0){
+                load_cons(f, tmp_reg, o->val.vmax);
+                emit(f, "\tADD \t %s %s %s\n", regnames[dest_reg], regnames[tmp_reg], regnames[dest_reg]);              
+            }
+            
+            break;
+        default:
+            #ifdef DEBUG_MARK
+            printf("\tSomething is wrong while acuring operand!\n");
+            #else
+            ierror(0);
+            #endif
+            break;
+    }
+}
+
+void store_from_reg(FILE *f, int source_reg, struct obj *o, int type, int tmp_reg, int tmp_reg_b){
+    switch((o->flags) & (KONST|VAR|REG|DREFOBJ|VARADR)){
+        case KONST:
+            //How can I store register into KONST?!
+            ierror(0);
+            break;
+        case (KONST|DREFOBJ):
+            //use konstant as pointer into memory
+            emit(f, "\tST  \t %s ", regnames[source_reg]);
+            emitval(f, &(o->val), type);
+            emit(f, "\n");
+            break;
+        case REG:
+            //move from register into register
+            if(source_reg != (o->reg)){
+                emit(f, "\tOR  \t %s %s %s\n",regnames[R0], regnames[source_reg], regnames[o->reg]);
+            }
+            break;
+        case VAR:
+            //load register into variable
+            switch((o->v->storage_class) & (STATIC|EXTERN|AUTO|REGISTER)){
+                case STATIC:
+                    if(zm2l(o->val.vmax) != 0){
+                        emit(f, "\tMVIA \t %s L_%ld\n", regnames[tmp_reg], zm2l(o->v->offset));
+                        load_cons(f, tmp_reg_b, zm2l(o->val.vmax));
+                        emit(f, "\tADD \t %s %s %s\n", regnames[tmp_reg], regnames[tmp_reg_b], regnames[tmp_reg]);
+                        emit(f, "\tSTI \t %s %s\n", regnames[source_reg], regnames[tmp_reg]);
+                    }
+                    else{
+                        emit(f, "\tST  \t %s L_%ld\n", regnames[source_reg], zm2l(o->v->offset));
+                    }
+                    break;
+                case EXTERN:
+                    if(zm2l(o->val.vmax) != 0){
+                        emit(f, "\tMVIA \t %s %s\n", regnames[tmp_reg], o->v->identifier);
+                        load_cons(f, tmp_reg_b, zm2l(o->val.vmax));
+                        emit(f, "\tADD \t %s %s %s\n", regnames[tmp_reg], regnames[tmp_reg_b], regnames[tmp_reg]);
+                        emit(f, "\tSTI \t %s %s\n", regnames[source_reg], regnames[tmp_reg]);
+                    }
+                    else{
+                        emit(f, "\tST  \t %s %s\n", regnames[source_reg], o->v->identifier);
+                    }
+                    break;
+                case AUTO:
+                    if((o->v->offset) < 0){
+                        //function argument
+                        load_cons(f, tmp_reg, (zm2l(o->v->offset)/(-1L))+2+zm2l(o->val.vmax));
+                        emit(f, "\tADD \t %s %s %s\n", regnames[tmp_reg],regnames[FP], regnames[tmp_reg]);
+                        emit(f, "\tSTI \t %s %s\n", regnames[source_reg], regnames[tmp_reg]);
+                    }
+                    else{
+                        //auto variable
+                        int offset = zm2l(o->v->offset)+zm2l(o->val.vmax);
+                        if (offset == 0){
+                            emit(f, "\tSTI \t %s %s\n", regnames[source_reg], regnames[FP]);
+                        }
+                        else if(offset == 1){
+                            emit(f, "\tDEC \t %s %s\n", regnames[FP], regnames[tmp_reg]);
+                            emit(f, "\tSTI \t %s %s\n", regnames[source_reg], regnames[tmp_reg]);
+                        }
+                        else{
+                            load_cons(f, tmp_reg, offset);
+                            emit(f, "\tSUB \t %s %s %s\n", regnames[FP],regnames[tmp_reg], regnames[tmp_reg]);
+                            emit(f, "\tSTI \t %s %s\n", regnames[source_reg], regnames[tmp_reg]);
+                        }
+                    }
+                    break;
+                default:
+                    #ifdef DEBUG_MARK
+                    printf("\tHave to store into variable that is not static, extern or auto, this is not implemented!\n");
+                    #else
+                    ierror(0);
+                    #endif
+                    break;
+            }
+            break;
+        case (VAR|REG):
+            emit(f, "\tOR   \t %s %s %s\n", regnames[R0], regnames[source_reg], regnames[o->reg]);
+            break;
+        case (REG|DREFOBJ):
+            //use value in register as pointer into memory
+            emit(f, "\tSTI \t %s %s\n", regnames[source_reg], regnames[o->reg]);
+            break;
+        case (VAR|DREFOBJ):
+            //use value in variable as pointer into memory
+            switch((o->v->storage_class) & (STATIC|EXTERN|AUTO|REGISTER)){
+                case STATIC:
+                    if(zm2l(o->val.vmax) != 0){
+                        emit(f, "\tMVIA \t %s L_%ld\n", regnames[tmp_reg], zm2l(o->v->offset));
+                        load_cons(f, tmp_reg_b, zm2l(o->val.vmax));
+                        emit(f, "\tADD \t %s %s %s\n", regnames[tmp_reg], regnames[tmp_reg_b], regnames[tmp_reg_b]);
+                        emit(f, "\tLDI \t %s %s\n", regnames[tmp_reg_b], regnames[tmp_reg]);
+                    }
+                    else{
+                        emit(f, "\tLD  \t L_%ld %s\n", zm2l(o->v->offset), regnames[tmp_reg]);
+                    }
+                    emit(f, "\tSTI \t %s %s\n", regnames[source_reg], regnames[tmp_reg]);
+                    break;
+                case EXTERN:
+                    if(zm2l(o->val.vmax) != 0){
+                        emit(f, "\tMVIA \t %s %s\n", regnames[tmp_reg], o->v->identifier);
+                        load_cons(f, tmp_reg_b, zm2l(o->val.vmax));
+                        emit(f, "\tADD \t %s %s %s\n", regnames[tmp_reg], regnames[tmp_reg_b], regnames[tmp_reg_b]);
+                        emit(f, "\tLDI \t %s %s\n", regnames[tmp_reg_b], regnames[tmp_reg]);
+                    }
+                    else{
+                        emit(f, "\tLD  \t %s %s\n", o->v->identifier, regnames[tmp_reg] );
+                    }
+                    emit(f, "\tSTI \t %s %s\n", regnames[source_reg], regnames[tmp_reg]);
+                    break;
+                case AUTO:
+                    if((o->v->offset) < 0){
+                        //function argument
+                        load_cons(f, tmp_reg, (zm2l(o->v->offset)/(-1L))+2+zm2l(o->val.vmax));
+                        emit(f, "\tADD \t %s %s %s\n", regnames[tmp_reg],regnames[FP], regnames[tmp_reg_b]);
+                        emit(f, "\tLDI \t %s %s\n", regnames[tmp_reg_b], regnames[tmp_reg]);
+                        emit(f, "\tSTI \t %s %s\n", regnames[source_reg], regnames[tmp_reg]);
+                    }
+                    else{
+                        //auto variable
+                        int offset = zm2l(o->v->offset)+zm2l(o->val.vmax);
+                        if(offset == 0){
+                            emit(f, "\tLDI \t %s %s\n", regnames[FP], regnames[tmp_reg_b]);
+                        }
+                        else if(offset == 1){
+                            emit(f, "\tDEC \t %s %s\n", regnames[FP], regnames[tmp_reg_b]);
+                            emit(f, "\tLDI \t %s %s\n", regnames[tmp_reg_b], regnames[tmp_reg]);
+                        }
+                        else{
+                            load_cons(f, tmp_reg, offset);
+                            emit(f, "\tSUB \t %s %s %s\n", regnames[FP],regnames[tmp_reg], regnames[tmp_reg]);
+                            emit(f, "\tLDI \t %s %s\n", regnames[tmp_reg], regnames[tmp_reg_b]);
+                        }
+                        emit(f, "\tSTI \t %s %s\n", regnames[source_reg], regnames[tmp_reg_b]);
+                    }
+                    break;
+                default:
+                    #ifdef DEBUG_MARK
+                    printf("\tHave to store into variable that is not static, extern or auto, this is not implemented!\n");
+                    #else
+                    ierror(0);
+                    #endif
+                    break;
+            }
+            break;
+        case (VAR|REG|DREFOBJ):
+            emit(f, "\tSTI \t %s %s\n", regnames[source_reg], regnames[o->reg]);
+            break;
+        case (VAR|VARADR): //use variable address as pointer
+            switch(o->v->storage_class){
+                case STATIC:
+                    emit(f, "\tMVIA \t %s L_%ld\n", regnames[tmp_reg], zm2l(o->v->offset));
+                    emit(f, "\tSTI \t %s %s\n", regnames[source_reg], regnames[tmp_reg]);
+                    break;
+                case EXTERN:
+                    emit(f, "\tMVIA \t %s %s\n", regnames[tmp_reg], o->v->identifier);
+                    emit(f, "\tSTI \t %s %s\n", regnames[source_reg], regnames[tmp_reg]);
+                    break;
+                default: //can be only static or extern
+                    ierror(0);
+                    break;
+            }
+            break;
+        default:
+            #ifdef DEBUG_MARK
+            printf("\tCant store reg into object, unknown object!\n");
+            #else
+            ierror(0);
+            #endif
+            break;
+    }
+}
+
+void arithmetic(FILE *f, struct IC *p){
+    int q1reg = 0;
+    int q2reg = 0;
+
+    int zreg = 0;
+    int movez = 0;
+
+    int unary = 0;
+
+    int isunsigned = 0;
+    if (((p->typf) & UNSIGNED) == UNSIGNED){
+        isunsigned = 1;
+    }
+
+    if(((p->code) == MINUS) || ((p->code) == KOMPLEMENT)){
+        unary = 1;
+    }
+
+    //load first operand
+    if(((p->q1.flags) & (KONST|VAR|REG|DREFOBJ|VARADR)) == REG){
+        q1reg = p->q1.reg;
+    }
+    else{
+        load_into_reg(f, R1, &(p->q1), p->typf, R3);
+        q1reg = R1;
+    }
+
+    //load second operand
+    if(unary != 1){
+        if(((p->q2.flags) & (KONST|VAR|REG|DREFOBJ|VARADR)) == REG){
+            q2reg = p->q2.reg;
+        }
+        else{
+            load_into_reg(f, R2, &(p->q2), p->typf, R3);
+            q2reg = R2;
+        }
+    }
+
+    //prepare target register
+    if(((p->z.flags) & (KONST|VAR|REG|DREFOBJ|VARADR)) == REG){
+        zreg = p->z.reg;
+    }
+    else{
+        zreg = R1;
+        movez = 1;
+    }
+
+    if (((p->typf) & FLOAT) == FLOAT || ((p->typf) & DOUBLE) == DOUBLE || ((p->typf) & LDOUBLE) == LDOUBLE){
+        switch(p->code){
+            case ADD:
+                emit(f, "\tFADD \t ");
+                break;
+            case SUB:
+                emit(f, "\tFSUB \t ");
+                break;
+            case MULT:
+                emit(f, "\tFMUL \t ");
+                break;
+            case DIV:
+                emit(f, "\tFDIV \t ");
+                break;
+            case MINUS:
+                load_cons(f, R2, 0x3f800000);
+                emit(f, "\tSUB \t ");
+                unary = 0;
+                q2reg = R2;
+                break;
+            default:
+                #ifdef DEBUG_MARK
+                printf("This is not implemented!\n");
+                #else
+                ierror(0);
+                #endif
+                break;
+        }
+    }
+    else{
+
+        //emit instruction opcode
+        switch(p->code){
+            case OR:
+                emit(f, "\tOR  \t ");
+                break;
+            case XOR:
+                emit(f, "\tXOR \t ");
+                break;
+            case AND:
+                emit(f, "\tAND \t ");
+                break;
+            case LSHIFT:
+                emit(f, "\tLSL \t ");
+                break;
+            case RSHIFT:
+                if(isunsigned == 1) {
+                    emit(f, "\tLSR \t ");
+                }
+                else{
+                    emit(f, "\tASR \t ");
+                }
+                break;
+            case ADD:
+                emit(f, "\tADD \t ");
+                break;
+            case SUB:
+                emit(f, "\tSUB \t ");
+                break;
+            case MULT:
+                if(isunsigned == 1) {
+                    emit(f, "\tMULU \t ");
+                }
+                else{
+                    emit(f, "\tMUL \t ");
+                }
+                break;
+            case DIV:
+                if(isunsigned == 1) {
+                    emit(f, "\tDIVU \t ");
+                }
+                else{
+                    emit(f, "\tDIV \t ");
+                }
+                break;
+            case MOD:
+                if(isunsigned == 1) {
+                    emit(f, "\tREMU \t ");
+                }
+                else{
+                    emit(f, "\tREM \t ");
+                }
+                break;
+            case ADDI2P:
+                emit(f, "\tADD \t ");
+                break;
+            case SUBIFP:
+                emit(f, "\tSUB \t ");
+                break;
+            case SUBPFP:
+                emit(f, "\tSUB \t ");
+                break;
+            case MINUS:
+                emit(f, "\tDEC \t ");
+                break;
+            case KOMPLEMENT:
+                emit(f, "\tNOT \t ");
+                break;
+            default:
+                #ifdef DEBUG_MARK
+                printf("\tPassed invalid IC into arithmetic()\n\tp->code: %d\n", p->code);
+                #else
+                ierror(0);
+                #endif
+                break;
+        }
+    }
+
+    //emit instruction arguments
+    if(unary != 1){
+        emit(f, "%s %s %s\n", regnames[q1reg], regnames[q2reg], regnames[zreg]);
+    }
+    else{
+        emit(f, "%s %s\n", regnames[q1reg], regnames[zreg]);
+    }
+
+    if(movez == 1){
+        store_from_reg(f, R1, &(p->z), p->typf, R2, R3);
+    }
+}
+
+void load_cons(FILE *f, int reg, long int value){
+    if(value == 0){
+        emit(f, "\tOR  \t R0 R0 %s\n", regnames[reg]);
+    }
+    else if((16777216 > value) && (value > 0)){
+        emit(f, "\tMVIA \t %s %ld\n", regnames[reg], value);
+    }
+    else if (value > 0){
+        emit(f, "\t.MVI \t %s %ld\n", regnames[reg], value);
+    }
+    else{
+        emit(f, "\t.MVI \t %s 0x%x\n", regnames[reg], value);
+    }
+}
diff --git a/machines/mark/machine.dt b/machines/mark/machine.dt
new file mode 100644
index 0000000..230a53c
--- /dev/null
+++ b/machines/mark/machine.dt
@@ -0,0 +1,15 @@
+S32BSLE S32BSBE
+S32BULE S32BUBE
+S32BSLE S32BSBE
+S32BULE S32BUBE
+S32BSLE S32BSBE
+S32BULE S32BUBE
+S32BSLE S32BSBE
+S32BULE S32BUBE
+S32BSLE S32BSBE
+S32BULE S32BUBE
+S32BIEEELE S32BIEEEBE
+S32BIEEELE S32BIEEEBE
+S32BIEEELE S32BIEEEBE
+S32BULE S32BUBE
+
diff --git a/machines/mark/machine.h b/machines/mark/machine.h
new file mode 100644
index 0000000..013e6ea
--- /dev/null
+++ b/machines/mark/machine.h
@@ -0,0 +1,93 @@
+#include "dt.h"
+
+//bez speciálních adresních modu
+struct AddressingMode {
+    int never_used;
+};
+
+struct reg_handle {
+  int gpr;
+};
+
+// sem nacpat počet registrů, ale co SP, PC a Zero reg? To jsou spec. registry
+// které kompilátor nemůže jen tak používat
+#define MAXR 16
+
+// počet argumentů, nemám žádné ale doku tvrdí že t i tak musí být MAXGF 1
+#define MAXGF 1
+
+//může být druhý operand IC stejný jako cíl? 0-ano 1-ne
+#define USEQ2ASZ 0
+
+//A co mám jako kurva dát sem?! Zkusím CHAR když to nebude fungovat dej tam INT!
+#define MINADDI2P CHAR
+
+// další wtf! Moje arch tohle neřeší, tak tam prostě prskneme malého indiána
+#define BIGENDIAN 0
+#define LITTLEENDIAN 1
+
+//switche chci compilovat na COMPARE/BEQ nikoliv na SUB/TEST/BEQ
+#define SWITCHSUBS 0
+
+// obšlehnuto z generic, tady toho je vůbec hodně obšlehnutého
+#define INLINEMEMCPY 1024
+
+// reverse argument push order
+//#define ORDERED_PUSH 0
+
+// argumenty klidně do registrů
+#define HAVE_REGPARMS 1
+
+//nemám registrové páry
+#undef HAVE_REGPAIRS
+
+//nó, ale zvhledem k tomu že long a int je na mej arch stejný tak je to asi k prdu ale budiž
+#undef HAVE_INT_SIZET
+
+// a teď ty sračky pro peephole optimalizace, ty dělat nebudu tak jsem tohle obšlehl z generic
+
+/* size of buffer for asm-output, this can be used to do
+   peephole-optimizations of the generated assembly-output */
+#define EMIT_BUF_LEN 1024 /* should be enough */
+/* number of asm-output lines buffered */
+#define EMIT_BUF_DEPTH 4
+/*  We have no asm_peephole to optimize assembly-output */
+#define HAVE_TARGET_PEEPHOLE 0
+
+
+// tohle je zatím k hovnu později se to ale může hodit
+#define HAVE_TARGET_ATTRIBUTES
+#define HAVE_TARGET_PRAGMAS
+
+#undef HAVE_REGS_MODIFIED //nepodporuji interprocedural register allocation
+
+//tohle je dobrý pro CPU s registrama co mají pevně danou funkci, moje arch je ortogonální až běda tak to nemusím řešit
+#undef HAVE_TARGET_RALLOC
+
+// pro mě zbytečné, je to pro aptimalizaci
+#undef HAVE_EXT_IC
+
+//tohle je sranda, doku se tu odkazuje na kapitolu která není napsaná, nicméně, externí typy nepotřebujeme
+#undef HAVE_EXT_TYPES
+
+#undef HAVE_TGT_PRINTVAL //tohle je stejná  sračka jako ta vejš, kdo ví k čemu to je ale nechci to
+
+// no, nemám páru jak to nastavit tak je to obšlehnuté
+#define JUMP_TABLE_DENSITY 0.8
+#define JUMP_TABLE_LENGTH 12
+
+/* toto je pro variable lenght arrays (nutno použít -c99) zatím to jebu, spousta architektur to taky nemá
+#define ALLOCVLA_REG <reg>
+#define ALLOCVLA_INLINEASM <inline asm>
+#define FREEVLA_REG <reg>
+#define FREEVLA_INLINEASM <inline asm>
+#define OLDSPVLA_INLINEASM <inline asm>
+#define FPVLA_REG <reg>
+*/
+
+//tohle je pro nahrazení složitějších operací voláím do knihoven - super věc ale zatím to jebu a budu generovat makra
+#undef HAVE_LIBCALLS
+
+// who cares?
+#define AVOID_FLOAT_TO_UNSIGNED 1
+#define AVOID_UNSIGNED_TO_FLOAT 1
diff --git a/machines/messiahtron/machine.c b/machines/messiahtron/machine.c
new file mode 100755
index 0000000..675df3f
--- /dev/null
+++ b/machines/messiahtron/machine.c
@@ -0,0 +1,2717 @@
+/*  Example backend for vbcc, it models a generic 32bit RISC or CISC

+CPU.

+

+Configurable at build-time are:

+- number of (32bit) general-purpose-registers

+- number of (64bit) floating-point-registers

+- number of (8bit) condition-code-registers

+- mechanism for stack-arguments (moving ot fixed sp)

+

+It allows to select as run-time-options:

+- two- or three-address code

+- memory operands or load-store-architecture

+- number of register-arguments

+- number of caller-save-registers

+*/                                                                             

+

+#include "../../supp.h"

+

+static char FILE_[]=__FILE__;

+

+/*  Public data that MUST be there.                             */

+

+/* Name and copyright. */

+char cg_copyright[]="vbcc Messiahtron code-generator "__DATE__" (c) in 2008 by Andrew Price";

+

+/*  Commandline-flags the code-generator accepts:

+0: just a flag

+VALFLAG: a value must be specified

+STRINGFLAG: a string can be specified

+FUNCFLAG: a function will be called

+apart from FUNCFLAG, all other versions can only be specified once */

+int g_flags[MAXGF]={0,0,

+VALFLAG,VALFLAG,VALFLAG,

+0,0,

+VALFLAG,VALFLAG,0};

+

+/* the flag-name, do not use names beginning with l, L, I, D or U, because

+they collide with the frontend */

+char *g_flags_name[MAXGF]={"three-addr","load-store",

+"volatile-gprs","volatile-fprs","volatile-ccrs",

+"imm-ind","gpr-ind",

+"gpr-args","fpr-args","use-commons"};

+

+/* the results of parsing the command-line-flags will be stored here */

+union ppi g_flags_val[MAXGF];

+

+/*  Alignment-requirements for all types in bytes.              */

+zmax align[MAX_TYPE+1];

+

+/*  Alignment that is sufficient for every object.              */

+zmax maxalign;

+

+/*  CHAR_BIT for the target machine.                            */

+zmax char_bit;

+

+/*  sizes of the basic 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. will be initialized in init_cg(),

+register number 0 is invalid, valid registers start at 1 */

+char *regnames[MAXR+1];

+

+/*  The Size of each register in bytes.                         */

+zmax regsize[MAXR+1];

+

+/*  a 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];

+

+/* specifies the priority for the register-allocator, if the same

+estimated cost-saving can be obtained by several registers, the

+one with the highest priority will be used */

+int reg_prio[MAXR+1];

+

+/* an empty reg-handle representing initial state */

+struct reg_handle empty_reg_handle={0,0};

+

+/* Names of target-specific variable attributes.                */

+char *g_attr_name[]={"__interrupt",0};

+

+

+/****************************************/

+/*  Private data and functions.         */

+/****************************************/

+

+#define THREE_ADDR (g_flags[0]&USEDFLAG)

+#define LOAD_STORE (g_flags[1]&USEDFLAG)

+//#define VOL_FIXED   NUM_FIXED

+#define VOL_16BIT   ((g_flags[3]&USEDFLAG)?g_flags_val[3].l:NUM_16BIT/2)

+#define VOL_32BIT   ((g_flags[4]&USEDFLAG)?g_flags_val[4].l:NUM_32BIT/2)

+#define VOL_64BIT   ((g_flags[4]&USEDFLAG)?g_flags_val[5].l:NUM_64BIT/2)

+#define VOL_8BIT   ((g_flags[4]&USEDFLAG)?g_flags_val[6].l:NUM_8BIT/2)

+#define IMM_IND    ((g_flags[5]&USEDFLAG)?1:0)

+#define GPR_IND    ((g_flags[6]&USEDFLAG)?2:0)

+//#define ARGS8   ((g_flags[7]&USEDFLAG)?g_flags_val[7].l:1)

+//#define ARGS16   ((g_flags[7]&USEDFLAG)?g_flags_val[7].l:0)

+//#define ARGS32   ((g_flags[7]&USEDFLAG)?g_flags_val[7].l:0)

+//#define ARGS64   ((g_flags[7]&USEDFLAG)?g_flags_val[7].l:0)

+// #define FPR_ARGS   ((g_flags[8]&USEDFLAG)?g_flags_val[8].l:0)

+//#define USE_COMMONS (g_flags[9]&USEDFLAG)

+

+

+/* alignment of basic data-types, used to initialize align[] */

+static long malign[MAX_TYPE+1]={1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};

+/* sizes of basic data-types, used to initialize sizetab[] */

+static long msizetab[MAX_TYPE+1]={0,1,2,4,4,8,4,8,8,0,4,0,0,0,4,0};

+

+/* used to initialize regtyp[] */

+static struct Typ llong={LLONG},ltyp={LONG},lshort={SHORT},lchar={CHAR};

+

+/* macros defined by the backend */

+static char *marray[]={"__section(x)=__vattr(\"section(\"#x\")\")",

+"__GENERIC__",

+0};

+

+/* special registers */

+static int sp;                     /*  Stackpointer                        */

+static int t8bit1,t8bit2;               /*  temporary gprs */

+static int t16bit1,t16bit2;

+static int t32bit1,t32bit2;

+static int t64bit1,t64bit2;

+

+#define dt(t) (((t)&UNSIGNED)?udt[(t)&NQ]:sdt[(t)&NQ])

+static char *sdt[MAX_TYPE+1]={"??","c","s","i","l","ll","f","d","ld","v","p"};

+static char *udt[MAX_TYPE+1]={"??","uc","us","ui","ul","ull","f","d","ld","v","p"};

+

+/* sections */

+#define DATA 0

+#define BSS 1

+#define CODE 2

+#define RODATA 3

+#define SPECIAL 4

+

+static long stack;

+static int stack_valid;

+static int section=-1,newobj;

+static char *codename=".resetlocals\n;code\n",

+*dataname=";data\n",

+*bssname=";bss\n",

+*rodataname=";read only data\n";

+

+/* return-instruction */

+static char *ret;

+

+/* label at the end of the function (if any) */

+static int exit_label;

+

+/* assembly-prefixes for labels and external identifiers */

+static char *labprefix="l",*idprefix="_";

+

+/* variables to keep track of the current stack-offset in the case of

+a moving stack-pointer */

+static long loff,stackoffset,notpopped,dontpop,maxpushed,stack;

+static pushorder=2;

+

+static long localsize,rsavesize,argsize;

+

+/* pushed on the stack by a callee, no pop needed */

+static void callee_push(long l)

+{

+}

+

+static void push(long l)

+{

+	stackoffset-=l;

+	if(stackoffset<maxpushed)

+		maxpushed=stackoffset;

+}

+static void pop(long l)

+{

+	stackoffset+=l;

+}

+

+static void emit_obj(FILE *f,struct obj *p,int t);

+

+/* calculate the actual current offset of an object relativ to the

+stack-pointer; we use a layout like this:

+------------------------------------------------

+| arguments to this function                   |

+------------------------------------------------

+| return-address [size=4]                      |

+------------------------------------------------

+| caller-save registers [size=rsavesize]       |

+------------------------------------------------

+| local variables [size=localsize]             |

+------------------------------------------------

+| arguments to called functions [size=argsize] |

+------------------------------------------------

+All sizes will be aligned as necessary.

+In the case of FIXED_SP, the stack-pointer will be adjusted at

+function-entry to leave enough space for the arguments and have it

+aligned to 16 bytes. Therefore, when calling a function, the

+stack-pointer is always aligned to 16 bytes.

+For a moving stack-pointer, the stack-pointer will usually point

+to the bottom of the area for local variables, but will move while

+arguments are put on the stack.

+

+This is just an example layout. Other layouts are also possible.

+*/

+

+static long real_offset(struct obj *o)

+{

+	long off=zm2l(o->v->offset);

+	if(off<0){

+		/* function parameter */

+		off=localsize+rsavesize+4-off-zm2l(maxalign);

+	}

+

+	off+=4;

+

+	off+=stackoffset;

+	off+=zm2l(o->val.vmax);

+	return off;

+}

+

+/*  Initializes an addressing-mode structure and returns a pointer to

+that object. Will not survive a second call! */

+static struct obj *cam(int flags,int base,long offset)

+{

+	static struct obj obj;

+	static struct AddressingMode am;

+	obj.am=&am;

+	am.flags=flags;

+	am.base=base;

+	am.offset=offset;

+	return &obj;

+}

+

+/* changes to a special section, used for __section() */

+static int special_section(FILE *f,struct Var *v)

+{

+	char *sec;

+	if(!v->vattr) return 0;

+	sec=strstr(v->vattr,"section(");

+	if(!sec) return 0;

+	sec+=strlen("section(");

+	emit(f,"; section");

+	while(*sec&&*sec!=')') emit_char(f,*sec++);

+	emit(f,"\n");

+	if(f) section=SPECIAL;

+	return 1;

+}

+

+/* generate code to load the address of a variable into register r */

+static void load_address(FILE *f,int r,struct obj *o,int type)

+/*  Generates code to load the address of a variable into register r.   */

+{

+	if(!(o->flags&VAR))

+		ierror(0);

+	if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)

+	{

+		long off=real_offset(o);

+		emit(f,"\tmov\t%s %s ; load_address %s\n",regnames[r],regnames[sp],dt(POINTER));

+		if(off)

+		{

+			emit(f,"\tmov\tb30 %ld ; %s\n",off,dt(POINTER));

+			emit(f,"\tsub\t%s b30 ; %s\n",regnames[r],dt(POINTER));

+		}

+	}

+	else

+	{

+		emit(f,"\tmov\t%s ",regnames[r]);

+		emit_obj(f,o,type);

+		emit(f," ;%s\n", dt(POINTER));

+	}

+}

+/* Generates code to load a memory object into register r. tmp is a

+general purpose register which may be used. tmp can be r. */

+static void load_reg(FILE *f,int r,struct obj *o,int type)

+{

+	type&=NU;

+	if(o->flags&VARADR)

+	{

+		load_address(f,r,o,POINTER);

+	}

+	else

+	{

+		if((o->flags&(REG|DREFOBJ))==REG&&o->reg==r)

+			return;

+		if((o->flags&VAR)&&!(o->flags&REG))

+		{

+			if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)

+			{

+				unsigned long offset = real_offset(o);

+				if(offset == 0)

+				{

+					emit(f,"\tmov\t%s\t[z2] ;%s\n",regnames[r],dt(type));

+				}

+				else

+				{

+					emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);

+					emit(f,"\tmov\tb29\tz2\n");

+					emit(f,"\tsub\tb29\tb28\n");

+					if(ISFLOAT(type))

+						emit(f,"\tmovf\t%s\t[b29] ;%s\n",regnames[r],dt(type));

+					else if((type & UNSIGNED) || type == POINTER || type == STRUCT)

+						emit(f,"\tmov\t%s\t[b29] ;%s\n",regnames[r],dt(type));

+					else

+						emit(f,"\tmovs\t%s\t[b29] ;%s\n",regnames[r],dt(type));

+				}

+

+				return;

+			}

+		}

+

+		if(ISFLOAT(type))

+			emit(f,"\tmovf \t%s ",regnames[r]);

+		else if((type & UNSIGNED) || type == POINTER || type == STRUCT)

+			emit(f,"\tmov \t%s ",regnames[r]);

+		else

+			emit(f,"\tmovs \t%s ",regnames[r]);

+		emit_obj(f,o,type);

+		emit(f," ;%s\n",dt(type));

+	}

+}

+

+/*  Generates code to store register r into memory object o. */

+static void store_reg(FILE *f,int r,struct obj *o,int type)

+{

+	type&=NQ;

+

+	if((o->flags&VAR)&&!(o->flags&REG))

+	{

+

+		if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)

+		{

+			unsigned long offset = real_offset(o);

+

+			if(offset == 0)

+			{

+				if(ISFLOAT(type))

+					emit(f,"\tmovf\t[z2]\t%s ;%s\n",regnames[r],dt(type));

+				else if((type & UNSIGNED) || type == POINTER || type == STRUCT)

+					emit(f,"\tmov\t[z2]\t%s ;%s\n",regnames[r],dt(type));

+				else

+					emit(f,"\tmovs\t[z2]\t%s ;%s\n",regnames[r],dt(type));

+			}

+			else

+			{

+				emit(f,"\tmov\tb28\t%ld ; mov to stack\n", offset);

+				emit(f,"\tmov\tb29\tz2\n");

+				emit(f,"\tsub\tb29\tb28\n");

+				if(ISFLOAT(type))

+					emit(f,"\tmovf\t[b29]\t%s ;%s\n",regnames[r],dt(type));

+				else if((type & UNSIGNED) || type == POINTER || type == STRUCT)

+					emit(f,"\tmov\t[b29]\t%s ;%s\n",regnames[r],dt(type));

+				else

+					emit(f,"\tmovs\t[b29]\t%s ;%s\n",regnames[r],dt(type));

+			}

+			return;

+		}

+	}

+	if(r == 0)

+		emit(f, ";");

+

+	if(ISFLOAT(type))

+		emit(f,"\tmovf\t");

+	else if(type & UNSIGNED)

+		emit(f,"\tmov\t");

+	else

+		emit(f,"\tmovs\t");

+

+	emit_obj(f,o,type);

+	emit(f,"\t%s ;%s\n",regnames[r],dt(type));

+}

+

+/*  Yields log2(x)+1 or 0. */

+static long pof2(zumax x)

+{

+	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 struct IC *preload(FILE *,struct IC *);

+

+static void function_top(FILE *,struct Var *,long);

+static void function_bottom(FILE *f,struct Var *,long);

+

+#define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)

+#define isconst(x) ((p->x.flags&(KONST|DREFOBJ))==KONST)

+

+static int q1reg,q2reg,zreg;

+

+/* Does some pre-processing like fetching operands from memory to

+registers etc. */

+static struct IC *preload(FILE *f,struct IC *p)

+{

+	int r;

+

+	if(isreg(q1))

+		q1reg=p->q1.reg;

+	else

+		q1reg=0;

+

+	if(isreg(q2))

+		q2reg=p->q2.reg;

+	else

+		q2reg=0;

+

+//	emit(f," ; Preload register type %d\t%d z:%d\t%d\t ", q1typ(p), q1typ(p) & NQ, ztyp(p), ztyp(p) & NQ);

+

+	if(isreg(z))

+	{

+		zreg=p->z.reg;

+//		emit(f," is a reg ");

+	}

+	else

+	{

+		if((ztyp(p) & NQ) == CHAR)

+		{

+//			emit(f," is a 8 bit reg (1) ");

+			zreg=t8bit1;

+		}

+		else if((ztyp(p) & NQ) == SHORT)

+		{

+//			emit(f," is a 16 bit reg (1) ");

+			zreg=t16bit1;

+		}

+		else if((ztyp(p) & NQ) == LDOUBLE || (ztyp(p) & NQ) == LLONG || (ztyp(p) & NQ) == DOUBLE)

+		{

+//			emit(f," is a 64 bit reg (1) ");

+			zreg=t64bit1;

+		}

+		else

+		{

+//			emit(f," is a 32 bit reg (1) ");

+			zreg=t32bit1;

+		}

+	}

+

+	if((p->q1.flags&(DREFOBJ|REG))==DREFOBJ&&!p->q1.am){

+		p->q1.flags&=~DREFOBJ;

+		if((q1typ(p) & NQ) == CHAR)

+		{

+			load_reg(f,t8bit1,&p->q1,q1typ(p));

+			p->q1.reg=t8bit1;

+//			emit(f," is a 8 bit reg (2) ");

+		}

+		else if((q1typ(p) & NQ) == SHORT)

+		{

+			load_reg(f,t16bit1,&p->q1,q1typ(p));

+			p->q1.reg=t16bit1;

+//			emit(f," is a 16 bit reg (2) ");

+		}

+		else if((q1typ(p) & NQ) == LDOUBLE || (q1typ(p) & NQ) == LLONG || (q1typ(p) & NQ) == DOUBLE)

+		{

+			load_reg(f,t64bit1,&p->q1,q1typ(p));

+			p->q1.reg=t64bit1;

+//			emit(f," is a 64 bit reg (2) ");

+		}

+		else

+		{

+			load_reg(f,t32bit1,&p->q1,q1typ(p));

+			p->q1.reg=t32bit1;

+//			emit(f," is a 32 bit reg (2) ");

+		}

+		p->q1.flags|=(REG|DREFOBJ);

+	}

+	if(p->q1.flags&&LOAD_STORE&&!isreg(q1)){

+		if((q1typ(p) & NQ) == CHAR)

+		{

+			q1reg=t8bit1;

+//			emit(f," is a 8 bit reg (3) ");

+		}

+		else if((q1typ(p) & NQ) == SHORT)

+		{

+			q1reg=t16bit1;

+//			emit(f," is a 16 bit reg (3) ");

+		}

+		else if((q1typ(p) & NQ) == LDOUBLE || (q1typ(p) & NQ) == LLONG || (q1typ(p) & NQ) == DOUBLE)

+		{

+			q1reg=t64bit1;

+//			emit(f," is a 64 bit reg (3) ");

+		}

+		else

+		{

+			q1reg=t32bit1;

+//			emit(f," is a 32 bit reg (3) ");

+		}

+		load_reg(f,q1reg,&p->q1,q1typ(p));

+		p->q1.reg=q1reg;

+		p->q1.flags=REG;

+	}

+

+	if((p->q2.flags&(DREFOBJ|REG))==DREFOBJ&&!p->q2.am){

+		p->q2.flags&=~DREFOBJ;

+		if((q1typ(p) & NQ) == CHAR)

+		{

+			load_reg(f,t8bit1,&p->q2,q2typ(p));

+			p->q2.reg=t8bit1;

+//			emit(f," is a 8 bit reg (4) ");

+		}

+		else if((q1typ(p) & NQ) == SHORT)

+		{

+			load_reg(f,t16bit1,&p->q2,q2typ(p));

+			p->q2.reg=t16bit1;

+//			emit(f," is a 16 bit reg (4) ");

+		}

+		else if((q1typ(p) & NQ) == LDOUBLE || (q1typ(p) & NQ) == LLONG || (q1typ(p) & NQ) == DOUBLE)

+		{

+			load_reg(f,t64bit1,&p->q2,q2typ(p));

+			p->q2.reg=t64bit1;

+//			emit(f," is a 64 bit reg (4) ");

+		}

+		else

+		{

+			load_reg(f,t32bit1,&p->q2,q2typ(p));

+			p->q2.reg=t32bit1;

+//			emit(f," is a 32 bit reg (4) ");

+		}

+

+		p->q2.flags|=(REG|DREFOBJ);

+	}

+	if(p->q2.flags&&LOAD_STORE&&!isreg(q2)){

+		if((q1typ(p) & NQ) == CHAR)

+		{

+			q2reg=t8bit1;

+//			emit(f," is a 8 bit reg (5) ");

+		}

+		else if((q1typ(p) & NQ) == SHORT)

+		{

+			q2reg=t16bit1;

+//			emit(f," is a 16 bit reg (5) ");

+		}

+		else if((q1typ(p) & NQ) == LDOUBLE || (q1typ(p) & NQ) == LLONG || (q1typ(p) & NQ) == DOUBLE)

+		{

+			q2reg=t64bit1;

+//			emit(f," is a 64 bit reg (5) ");

+		}

+		else

+		{

+			q2reg=t32bit1;

+//			emit(f," is a 32 bit reg (5) ");

+		}

+

+		load_reg(f,q2reg,&p->q2,q2typ(p));

+		p->q2.reg=q2reg;

+		p->q2.flags=REG;

+	}

+

+//	emit(f,"\n");

+	return p;

+}

+

+/* save the result (in zreg) into p->z */

+void save_result(FILE *f,struct IC *p)

+{

+	if((p->z.flags&(REG|DREFOBJ))==DREFOBJ&&!p->z.am){

+		p->z.flags&=~DREFOBJ;

+		if((p->typf & NQ) == CHAR)

+		{

+			load_reg(f,t8bit2,&p->z,POINTER);

+			p->z.reg=t8bit2;

+		}

+		else if((p->typf & NQ) == SHORT)

+		{

+			load_reg(f,t16bit2,&p->z,POINTER);

+			p->z.reg=t16bit2;

+		}

+		else if((p->typf & NQ) == LDOUBLE || (p->typf & NQ) == LLONG || (p->typf & NQ) == DOUBLE)

+		{

+			load_reg(f,t64bit2,&p->z,POINTER);

+			p->z.reg=t64bit2;

+		}

+		else

+		{

+			load_reg(f,t32bit2,&p->z,POINTER);

+			p->z.reg=t32bit2;

+		}

+		p->z.flags|=(REG|DREFOBJ);

+		//printf("setting reg to %s\n", regnames[p->z.reg]);

+	}

+

+	if(isreg(z)){

+		if(p->z.reg!=zreg)

+			emit(f,"\tmov\t%s %s ;%s\n",regnames[p->z.reg],regnames[zreg],dt(ztyp(p)));

+	}else{

+		store_reg(f,zreg,&p->z,ztyp(p));

+	}

+}

+

+/* prints an object */

+static void emit_obj(FILE *f,struct obj *p,int t)

+{

+	//printf("type = %i\n", t);

+	if((p->flags&(DREFOBJ|KONST))==(DREFOBJ|KONST))

+	{

+		emitval(f,&p->val,p->dtyp&NU);

+		return;

+	}

+	if((p->flags&(DREFOBJ|REG))==(DREFOBJ|REG))

+		emit(f,"[");

+

+	if((p->flags&VAR)&&!(p->flags&REG))

+	{

+		if(!zmeqto(l2zm(0L),p->val.vmax))

+		{

+			emitval(f,&p->val,LONG);

+			emit(f,"+");

+		}

+		if(p->v->storage_class==STATIC)

+		{

+			emit(f,"%s%ld", labprefix, zm2l(p->v->offset));

+		}

+		else

+		{

+			if(t == FUNKT)

+				emit(f,"%s%s", idprefix, p->v->identifier);

+			else if(p->flags&VARADR)

+				emit(f,"%s%s", idprefix, p->v->identifier);

+			else

+				emit(f,"[%s%s]", idprefix, p->v->identifier);

+		}

+	}

+	if(p->flags&REG)

+	{

+		emit(f, "%s", regnames[p->reg]);

+	}

+	if(p->flags&KONST)

+	{

+		if(ISFLOAT(t))

+		{

+			//			case FLOAT:

+			char *values = (char *)&p->val.vfloat;

+			// swap the order

+			char tmp = values[0];

+			values[0] = values[3];

+			values[3] = tmp;

+			tmp = values[1];

+			values[1] = values[2];

+			values[2] = tmp;

+

+			emit(f, "0x%1X", *(unsigned int *)values);

+			//				break;

+

+			//			case DOUBLE:

+			//				fprintf(fp, "[double #%08X]", obj->val.vdouble);

+			//			emit(f,"0f%e",/*labprefix,*/p->val.vfloat);

+			//			emit(f,"0f");

+			//			emitval(f,&p->val,t&NU);

+		}

+		else if(t & UNSIGNED)

+		{

+			//			emit(f, "0u");

+			emitval(f,&p->val,t&NU);

+		}

+		else

+		{

+			emit(f,"0s");

+			emitval(f,&p->val,t&NU);

+		}

+	}

+	if((p->flags&(DREFOBJ|REG))==(DREFOBJ|REG))

+		emit(f,"]");

+}

+

+/*  Test if there is a sequence of FREEREGs containing FREEREG reg.

+Used by peephole. */

+static int exists_freereg(struct IC *p,int reg)

+{

+	while(p&&(p->code==FREEREG||p->code==ALLOCREG))

+	{

+		if(p->code==FREEREG&&p->q1.reg==reg)

+			return 1;

+		p=p->next;

+	}

+	return 0;

+}

+

+/* search for possible addressing-modes */

+static void peephole(struct IC *p)

+{

+	int c,c2,r;

+	struct IC *p2;

+	struct AddressingMode *am;

+

+	for(;p;p=p->next)

+	{

+		c=p->code;

+		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;

+

+		/* Try const(reg) */

+		if(IMM_IND&&(c==ADDI2P||c==SUBIFP)&&isreg(z)&&(p->q2.flags&(KONST|DREFOBJ))==KONST)

+		{

+			int base;zmax of;struct obj *o;

+			eval_const(&p->q2.val,p->typf);

+			if(c==SUBIFP) of=zmsub(l2zm(0L),vmax); else of=vmax;

+			if(1/*zmleq(l2zm(-32768L),vmax)&&zmleq(vmax,l2zm(32767L))*/)

+			{

+				r=p->z.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(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) break;

+							o=&p2->q1;

+						}

+						if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r)

+						{

+							if(o) break;

+							o=&p2->q2;

+						}

+						if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r)

+						{

+							if(o) 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);

+								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;

+					}

+				}

+			}

+		}

+		/* Try reg,reg */

+		if(GPR_IND&&c==ADDI2P&&isreg(q2)&&isreg(z)&&(isreg(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||(q1typ(p2)&NQ)==LLONG) break;

+						o=&p2->q1;

+					}

+					if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r)

+					{

+						if(o||(q2typ(p2)&NQ)==LLONG) break;

+						o=&p2->q2;

+					}

+					if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r)

+					{

+						if(o||(ztyp(p2)&NQ)==LLONG) 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=GPR_IND;

+							am->base=base;

+							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;

+				}

+			}

+		}

+	}

+}

+

+static void pr(FILE *f,struct IC *p)

+{

+	int i;

+	for(;pushorder>2;pushorder>>=1)

+	{

+		for(i=1;i<=8;i++)

+		{

+			if(regs[i]&pushorder)

+			{

+				if(p->code==PUSH||p->code==CALL)

+				{

+					//emit(f,"\tmovl\t%ld(%s),%s\n",loff-4-stackoffset,regnames[sp],regnames[i]);

+				}

+				else

+				{

+					emit(f,"\tpop\t%s\n",regnames[i]);

+					pop(4);

+				}

+				regs[i]&=~pushorder;

+			}

+		}

+	}

+	for(i=1;i<=8;i++)

+		if(regs[i]&2) regs[i]&=~2;

+}

+

+/* generates the function entry code */

+static void function_top(FILE *f,struct Var *v,long offset)

+{

+	rsavesize=0;

+	if(!special_section(f,v)&&section!=CODE){emit(f,codename);if(f) section=CODE;} 

+	if(v->storage_class==EXTERN)

+	{

+		if((v->flags&(INLINEFUNC|INLINEEXT))!=INLINEFUNC)

+			emit(f,".global ");

+		//      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));

+

+	// reserve enough in stack for local functions

+	if(offset > 0)

+	{

+		emit(f,"\tmov\tb28\t%d\n", offset);

+		emit(f,"\tadd\tz2\tb28 ;reserve %d on stack\n", offset);

+	}

+}

+/* generates the function exit code */

+static void function_bottom(FILE *f,struct Var *v,long offset)

+{

+	// reserve enough in stack for local functions

+	if(offset > 0)

+	{

+		emit(f,"\tmov\tb28\t%d\n", offset);

+		emit(f,"\tsub\tz2\tb28 ;reserve %d on stack\n", offset);

+	}

+

+	emit(f,ret);

+}

+

+/****************************************/

+/*  End of private data and functions.  */

+/****************************************/

+

+/*  Does necessary initializations for the code-generator. Gets called  */

+/*  once at the beginning and should return 0 in case of problems.      */

+int init_cg(void)

+{

+	int i;

+	/*  Initialize some values which cannot be statically initialized   */

+	/*  because they are stored in the target's arithmetic.             */

+	maxalign=l2zm(1L);

+	char_bit=l2zm(8L);

+

+	for(i=0;i<=MAX_TYPE;i++)

+	{

+		sizetab[i]=l2zm(msizetab[i]);

+		align[i]=l2zm(malign[i]);

+	}

+

+	regnames[0]="noreg";

+	regtype[0]=mymalloc(sizeof(struct Typ));

+	//	for(i=FIRST_FIXED;i<=LAST_FIXED;i++)

+	//	{

+	//		regnames[i]=mymalloc(10);

+	//		sprintf(regnames[i],"b%d",(i-FIRST_FIXED) + 27);

+	//		regsize[i]=4;

+	//		regtype[i]=&ltyp;

+	//	}

+

+	// static struct Typ lltype={LLONG},ltyp={LONG},lshort={SHORT},lchar={CHAR};

+

+	for(i=FIRST_16BIT;i<=LAST_16BIT;i++)

+	{

+		regnames[i]=mymalloc(10);

+		sprintf(regnames[i],"a%d",i-FIRST_16BIT);

+		regsize[i]=2;

+		regtype[i]=mymalloc(sizeof(struct Typ));

+	}

+

+	for(i=FIRST_32BIT;i<=LAST_32BIT;i++)

+	{

+		regnames[i]=mymalloc(10);

+		sprintf(regnames[i],"b%d",(i-FIRST_32BIT) + 5);

+		regsize[i]=4;

+		regtype[i]=mymalloc(sizeof(struct Typ));

+	}

+

+	for(i=FIRST_64BIT;i<=LAST_64BIT;i++)

+	{

+		regnames[i]=mymalloc(10);

+		sprintf(regnames[i],"c%d",(i-FIRST_64BIT) + 9);

+		regsize[i]=8;

+		regtype[i]=mymalloc(sizeof(struct Typ));

+	}

+

+	for(i=FIRST_8BIT;i<=LAST_8BIT;i++)

+	{

+		regnames[i]=mymalloc(10);

+		sprintf(regnames[i],"h%d",(i-FIRST_8BIT));

+		regsize[i]=1;

+		//regtype[i]=&lchar;

+		regtype[i]=mymalloc(sizeof(struct Typ));

+	}

+

+	regnames[STACK_POINTER]=mymalloc(10);

+	sprintf(regnames[STACK_POINTER],"z2");

+	regsize[STACK_POINTER]=4;

+	regtype[STACK_POINTER]=&ltyp;

+	regtype[STACK_POINTER]=mymalloc(sizeof(struct Typ));

+

+	/*  Use multiple ccs.   */

+	multiple_ccs=0;

+

+	/*  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.          */

+	t_min[CHAR]=l2zm(-128L);

+	t_min[SHORT]=l2zm(-32768L);

+	t_min[INT]=zmsub(l2zm(-2147483647L),l2zm(1L));

+	t_min[LONG]=t_min(INT);

+	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]=ul2zum(2147483647UL);

+	t_max[LONG]=t_max(INT);

+	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]=ul2zum(4294967295UL);

+	tu_max[LONG]=t_max(UNSIGNED|INT);

+	tu_max[LLONG]=zumkompl(ul2zum(0UL));

+	tu_max[MAXINT]=t_max(UNSIGNED|LLONG);

+

+	for(i=FIRST_16BIT;i<=LAST_16BIT-VOL_16BIT;i++)

+		regscratch[i]=1;

+	for(i=FIRST_32BIT;i<=LAST_32BIT-VOL_32BIT;i++)

+		regscratch[i]=1;

+	for(i=FIRST_64BIT;i<=LAST_64BIT-VOL_64BIT;i++)

+		regscratch[i]=1;

+	for(i=FIRST_8BIT;i<=LAST_8BIT-VOL_8BIT;i++)

+		regscratch[i]=1;

+

+	/*  Reserve a few registers for use by the code-generator.      */

+	/*  This is not optimal but simple.                             */

+	sp=STACK_POINTER;

+	t8bit1=FIRST_8BIT;

+	t8bit2=FIRST_8BIT+1;

+	t16bit1=FIRST_16BIT;

+	t16bit2=FIRST_16BIT+1;

+	t32bit1=FIRST_32BIT;

+	t32bit2=FIRST_32BIT+1;

+	t64bit1=FIRST_64BIT;

+	t64bit2=FIRST_64BIT+1;

+	regsa[t8bit1]=regsa[t8bit2]=1;

+	regsa[t16bit1]=regsa[t16bit2]=1;

+	regsa[t32bit1]=regsa[t32bit2]=1;

+	regsa[t64bit1]=regsa[t64bit2]=1;

+	regsa[sp]=1;

+	regscratch[t8bit1]=regscratch[t8bit2]=0;

+	regscratch[t16bit1]=regscratch[t16bit2]=0;

+	regscratch[t32bit1]=regscratch[t32bit2]=0;

+	regscratch[t64bit1]=regscratch[t64bit2]=0;

+	regscratch[sp]=0;

+

+	//	for(i=FIRST_FIXED;i<=LAST_FIXED-VOL_FIXED;i++)

+	//		regscratch[i]=1;

+	target_macros=marray;

+

+	return 1;

+}

+

+void init_db(FILE *f)

+{

+}

+

+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.        */

+/*  A pointer MUST be returned in a register. The code-generator    */

+/*  has to simulate a pseudo register if necessary.                 */

+{

+	if(ISSTRUCT(t->flags)||ISUNION(t->flags)) 

+		return 0;

+	if(t->size == 1)

+		return FIRST_8BIT+3;

+	if(t->size == 2)

+		return FIRST_16BIT+3;

+	if(t->size == 4)

+		return FIRST_32BIT+3;

+	if(t->size == 8)

+		return FIRST_64BIT+3;

+

+	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.                                            */

+{

+	return 0;

+}

+

+/* estimate the cost-saving if object o from IC p is placed in

+register r */

+int cost_savings(struct IC *p,int r,struct obj *o)

+{

+	int c=p->code;

+	if(o->flags&VKONST)

+	{

+		if(!LOAD_STORE)

+			return 0;

+		if(o==&p->q1&&p->code==ASSIGN&&(p->z.flags&DREFOBJ))

+			return 4;

+		else

+			return 2;

+	}

+	if(o->flags&DREFOBJ)

+		return 4;

+	if(c==SETRETURN&&r==p->z.reg&&!(o->flags&DREFOBJ))

+		return 3;

+	if(c==GETRETURN&&r==p->q1.reg&&!(o->flags&DREFOBJ))

+		return 3;

+	return 2;

+}

+

+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(r==0)

+		return 0;

+	t&=NQ;

+

+	if(r>=FIRST_8BIT&&r<=LAST_8BIT)

+	{

+//		printf("8 bit register: ");

+		if(t == CHAR)

+		{

+//			printf(" can fit\n");

+			return 1;

+		}

+//		else

+//			printf(" can't fit\n");

+	}

+	else if(r>=FIRST_16BIT&&r<=LAST_16BIT)

+	{

+//		printf("16 bit register: ");

+		if(t == SHORT)

+		{

+//			printf(" can fit\n");

+			return 1;

+		}

+//		else

+//			printf(" can't fit\n");

+	}

+	else if(r>=FIRST_32BIT&&r<=LAST_32BIT)

+	{

+//		printf("32 bit register: ");

+		if(t == INT || t == LONG || t == FLOAT

+			||t == POINTER)

+		{

+//			printf(" can fit\n");

+			return 1;

+		}

+//		etse

+//			printf(" can't fit\n");

+	}

+	else if(r>=FIRST_64BIT&&r<=LAST_64BIT)

+	{

+//		printf("64 bit register: ");

+		if(t == LDOUBLE || t == DOUBLE || t == LLONG)

+		{

+//			printf(" can fit\n");

+			return 1;

+		}

+//		else

+//			printf(" can't fit\n");;

+	}

+

+	return 0;

+

+

+	/*#define CHAR 1

+	#define SHORT 2

+	#define INT 3

+	#define LONG 4

+	#define LLONG 5

+	#define FLOAT 6

+	#define DOUBLE 7

+	#define LDOUBLE 8

+	#define VOID 9

+	#define POINTER 10

+	#define ARRAY 11

+	#define STRUCT 12

+	#define UNION 13

+	#define ENUM 14*/

+}

+

+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;

+}

+

+int must_convert(int o,int t,int const_expr)

+/*  Returns zero if code for converting np to type t    */

+/*  can be omitted.                                     */

+/*  On the PowerPC cpu pointers and 32bit               */

+/*  integers have the same representation and can use   */

+/*  the same registers.                                 */

+{

+	int op=o&NQ,tp=t&NQ;

+

+	if(op == LONG || op == POINTER)

+		op = INT;

+

+	if(tp==LONG || tp ==POINTER)

+		tp = INT;

+

+	if(op == tp) // same type

+		if((o & NQ)== (t & NQ)) // same signess

+			return 0; // no code needed

+

+	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&&section!=SPECIAL)

+		emit(f," data %ld\n",zm2l(size));

+	else

+		emit(f," data %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.              */

+{

+	if(zm2l(align)>1)

+		emit(f,"; NOT IMPLEMENTED - \t.align\t%d\n", align);

+}

+

+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;

+	char *sec;

+	if(v->clist) constflag=is_const(v->vtyp);

+	if(v->storage_class==STATIC)

+	{

+		if(ISFUNC(v->vtyp->flags))

+			return;

+		if(!special_section(f,v))

+		{

+			if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&&section!=DATA){emit(f,dataname);if(f) section=DATA;}

+			if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&&section!=RODATA){emit(f,rodataname);if(f) section=RODATA;}

+			if(!v->clist&&section!=BSS){emit(f,bssname);if(f) section=BSS;}

+		}

+		if(v->clist||section==SPECIAL)

+		{

+			gen_align(f,falign(v->vtyp));

+			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)

+	{

+		//  emit(f,"\t.globl\t%s%s\n",idprefix,v->identifier);

+		if(v->flags&(DEFINED|TENTATIVE))

+		{

+			if(!special_section(f,v))

+			{

+				if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&&section!=DATA)

+				{

+					emit(f,dataname);

+					if(f)

+						section=DATA;

+				}

+				if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&&section!=RODATA)

+				{

+					emit(f,rodataname);

+					if(f)

+						section=RODATA;

+				}

+				if(!v->clist&&section!=BSS)

+				{

+					emit(f,bssname);

+					if(f)

+						section=BSS;

+				}

+			}

+			if(v->clist||section==SPECIAL)

+			{

+				gen_align(f,falign(v->vtyp));

+				//        emit(f,"%s%s:\n",idprefix,v->identifier);

+			}

+			else

+				emit(f,".global %s%s:",/*(USE_COMMONS?"":"l"),*/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,"\tdc.%s\t",dt(t&NQ));

+	int o = t&NQ;

+	int size = 4;

+	if(o == CHAR)

+		size = 1;

+	if(o == SHORT)

+		size = 2;

+	if(o == LLONG || t == DOUBLE)

+		size = 8;

+

+	emit(f,"\tdata\t%i\t",size);

+	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[0],ip[1],ip[2],ip[3]);

+			if((t&NQ)!=FLOAT){

+				emit(f,",0x%02x%02x%02x%02x",ip[4],ip[5],ip[6],ip[7]);

+			}

+		}

+		else if(o & UNSIGNED)

+		{

+			emitval(f,&p->val,t);

+		}

+		else

+		{

+			emit(f, "0s");

+			emitval(f,&p->val,t);

+		}

+	}

+	else

+	{

+		emit_obj(f,&p->tree->o,t);

+	}

+	emit(f,"\n");

+	newobj=0;

+}

+

+

+/*  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 *p,struct Var *v,zmax offset)

+/*  The main code-generation.                                           */

+{

+	int c,t,i,lastcomp=0;

+	struct IC *m;

+	argsize=0;

+	if(DEBUG&1)

+		printf("gen_code()\n");

+	for(c=1;c<=MAXR;c++)

+		regs[c]=regsa[c];

+	maxpushed=0;

+

+	/*FIXME*/

+	ret="\tret\n";

+

+	struct IC *p_test = 0;

+	char test_handled = 0;

+	int test_reg = 0;

+	int test_reg2 = 0;

+

+	for(m=p;m;m=m->next)

+	{

+		c=m->code;t=m->typf;

+		if(c==ALLOCREG)

+		{

+			regs[m->q1.reg]=1;

+			continue;

+		}

+		if(c==FREEREG)

+		{

+			regs[m->q1.reg]=0;

+			continue;

+		}

+

+		/* convert MULT/DIV/MOD with powers of two */

+		if((t&NQ)<=LONG&&(m->q2.flags&(KONST|DREFOBJ))==KONST&&(t&NQ)<=LONG&&(c==MULT||((c==DIV||c==MOD)&&(t&UNSIGNED))))

+		{

+			eval_const(&m->q2.val,t);

+			i=pof2(vmax);

+			if(i)

+			{

+				if(c==MOD)

+				{

+					vmax=zmsub(vmax,l2zm(1L));

+					m->code=AND;

+				}

+				else

+				{

+					vmax=l2zm(i-1);

+					if(c==DIV)

+						m->code=RSHIFT;

+					else

+						m->code=LSHIFT;

+				}

+				c=m->code;

+				gval.vmax=vmax;

+				eval_const(&gval,MAXINT);

+				if(c==AND)

+				{

+					insert_const(&m->q2.val,t);

+				}

+				else

+				{

+					insert_const(&m->q2.val,INT);

+					p->typf2=INT;

+				}

+			}

+		}

+#if FIXED_SP

+		if(c==CALL&&argsize<zm2l(m->q2.val.vmax))

+			argsize=zm2l(m->q2.val.vmax);

+#endif

+	}

+	peephole(p);

+

+	for(c=1;c<=MAXR;c++)

+	{

+		if(regsa[c]||regused[c])

+		{

+			BSET(regs_modified,c);

+		}

+	}

+

+	localsize=(zm2l(offset)+3)/4*4;

+#if FIXED_SP

+	/*FIXME: adjust localsize to get an aligned stack-frame */

+#endif

+

+	function_top(f,v,localsize);

+

+	stackoffset=notpopped=dontpop=0;

+

+	for(;p;p=p->next)

+	{

+		c=p->code;t=p->typf;

+		if(c==NOP)

+		{

+			p->z.flags=0;

+			continue;

+		}

+

+		if(c==ALLOCREG)

+		{

+			regs[p->q1.reg]=1;

+			continue;

+		}

+

+		if(c==FREEREG)

+		{

+			regs[p->q1.reg]=0;

+			continue;

+		}

+		if(c==LABEL)

+		{

+			emit(f,"%s%d:\n",labprefix,t);

+			continue;

+		}

+

+		if(notpopped&&!dontpop)

+		{

+			if(c==LABEL||c==COMPARE||c==TEST||c==BRA)

+			{

+				emit(f,"\taddl\t$%ld,%%esp\n",notpopped);

+				pop(notpopped);

+				notpopped=0;

+			}

+		}

+		if(c==BRA)

+		{

+			emit(f,"\tmov b29 %s%d\n", labprefix, t);

+			emit(f,"\tjmp\tb29\n");

+

+			//emit(f,"\tmov b29\t");

+			//if(isreg(q1)){

+			//emit_obj(f,&p->q1,0);

+			//emit(f,",");

+			//}

+			//emit(f,"%s%d;\n",labprefix,t);

+			continue;

+		}

+

+		if(c==MOVETOREG)

+		{

+			//printf("reg: %s\n", regnames[p->z.reg]);

+			if(p->z.reg <= MAXR)

+				load_reg(f,p->z.reg,&p->q1,regtype[p->z.reg]->flags);

+			else

+				emit(f," ; move non existant reg in to %s\n",regnames[p->q1.reg]);

+			continue;

+		}

+		if(c==MOVEFROMREG)

+		{

+			//			printf("reg: %s\n", regnames[p->z.reg]);

+			if(p->z.reg <= MAXR)

+				store_reg(f, p->z.reg, &p->q1, regtype[p->z.reg]->flags);

+			continue;

+		}

+		if((c==ASSIGN||c==PUSH)&&((t&NQ)>POINTER||((t&NQ)==CHAR&&zm2l(p->q2.val.vmax)!=1)))

+		{

+			ierror(0);

+		}

+		p=preload(f,p);

+		c=p->code;

+		if(c==SUBPFP)

+			c=SUB;

+		if(c==ADDI2P)

+			c=ADD;

+		if(c==SUBIFP)

+			c=SUB;

+		if(c==CONVERT)

+		{

+			load_reg(f,zreg,&p->q1,p->typf2);

+			if(ISFLOAT(p->typf)) // convert to float

+			{

+				if(ISFLOAT(p->typf2)) // from float

+				{					

+					//					emit(f,"\tmovf\t%s\t%s\n", regnames[zreg], regnames[p->q1.reg]);

+				}

+				else if(!(p->typf2 & UNSIGNED)) // from signed

+				{

+					//					emit(f,"\tmovs\t%s\t%s\n", regnames[zreg], regnames[p->q1.reg]);

+					emit(f,"\tstf\t%s ;%s\n",regnames[zreg],dt(q1typ(p)));

+				}

+				else if(p->typf2 & UNSIGNED) // from unsigned

+				{

+					//					emit(f,"\tmov\t%s\t%s\n", regnames[zreg], regnames[p->q1.reg]);

+					emit(f,"\tutf\t%s ;%s\n",regnames[zreg],dt(q1typ(p)));

+				}

+			}

+			else if(!(p->typf & UNSIGNED)) // convert to signed

+			{

+				if(ISFLOAT(p->typf2)) // from float

+				{

+					//					emit(f,"\tmovf\t%s\t%s\n", regnames[zreg], regnames[p->q1.reg]);

+					emit(f,"\tfts\t%s ;%s\n",regnames[zreg],dt(q1typ(p)));

+				}

+				else if(!(p->typf2 & UNSIGNED)) // from signed

+				{

+					//					emit(f,"\tmovs\t%s\t%s\n", regnames[zreg], regnames[p->q1.reg]);

+				}

+				else if(p->typf2 & UNSIGNED) // from unsigned

+				{

+					//					emit(f,"\tmov\t%s\t", regnames[zreg]);

+					//					emit_obj(f,&p->q1,p->typf2);

+//					emit(f,"\n\tuts\t%s ;%s\n",regnames[zreg],dt(q1typ(p)));

+				}

+			}

+			else if(p->typf & UNSIGNED) // convert to unsigned

+			{

+				if(ISFLOAT(p->typf2)) // from float

+				{

+					//					emit(f,"\tmovf\t%s\t%s\n", regnames[zreg], regnames[p->q1.reg]);

+					emit(f,"\tftu\t%s ;%s\n",regnames[zreg],dt(q1typ(p)));

+				}

+				else if(!(p->typf2 & UNSIGNED)) // from signed

+				{

+					//					emit(f,"\tmovs\t%s\t%s\n", regnames[zreg], regnames[p->q1.reg]);

+//					emit(f,"\tstu\t%s ;%s\n",regnames[zreg],dt(q1typ(p)));

+				}

+				else if(p->typf2 & UNSIGNED) // from unsigned

+				{

+					//					emit(f,"\tmov\t%s\t%s\n", regnames[zreg], regnames[p->q1.reg]);

+				}

+			}

+			save_result(f,p);

+			continue;

+		}

+		if(c==KOMPLEMENT)

+		{

+			load_reg(f,zreg,&p->q1,t);

+			emit(f,"\tcpl.%s\t%s\n",dt(t),regnames[zreg]);

+			save_result(f,p);

+			continue;

+		}

+		if(c==SETRETURN)

+		{

+			load_reg(f,p->z.reg,&p->q1,t);

+			BSET(regs_modified,p->z.reg);

+			continue;

+		}

+		if(c==GETRETURN)

+		{

+			if(p->q1.reg)

+			{

+				zreg=p->q1.reg;

+				save_result(f,p);

+			}

+			else

+				p->z.flags=0;

+			continue;

+		}

+		if(c==CALL)

+		{

+			int reg;

+			/*FIXME*/

+#if 0      

+			if(stack_valid&&(p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&(p->q1.v->fi->flags&ALL_STACK))

+			{

+				if(framesize+zum2ul(p->q1.v->fi->stack1)>stack)

+					stack=framesize+zum2ul(p->q1.v->fi->stack1);

+			}else

+				stack_valid=0;

+#endif

+			if((p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&p->q1.v->fi->inline_asm)

+			{

+				emit_inline_asm(f,p->q1.v->fi->inline_asm);

+			}

+			else

+			{

+				emit(f, "\tmov\tb29\t");

+				emit_obj(f,&p->q1,t);

+				emit(f,"\n");

+				emit(f,"\tcall\tb29\n");

+			}

+			/*FIXME*/

+#if FIXED_SP

+			pushed-=zm2l(p->q2.val.vmax);

+#endif

+			if((p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&(p->q1.v->fi->flags&ALL_REGS))

+			{

+				bvunite(regs_modified,p->q1.v->fi->regs_modified,RSIZE);

+			}

+			else

+			{

+				int i;

+				for(i=1;i<=MAXR;i++)

+				{

+					if(regscratch[i]) BSET(regs_modified,i);

+				}

+			}

+			continue;

+		}

+		if(c==ASSIGN||c==PUSH)

+		{

+			if(t==0)

+				ierror(0);

+			if(c==PUSH)

+			{

+				emit(f,"\tpush\t"/*,dt(t)*/);

+				emit_obj(f,&p->q1,t);

+				emit(f,"\n");

+				push(zm2l(p->q2.val.vmax));

+				continue;

+			}

+			if(c==ASSIGN)

+			{

+				load_reg(f,zreg,&p->q1,t);

+				if(q2reg != 0)

+					load_reg(f,q2reg,&p->q2,t);

+				save_result(f,p);

+			}

+			continue;

+		}

+		if(c==ADDRESS)

+		{

+			load_address(f,zreg,&p->q1,POINTER);

+			save_result(f,p);

+			continue;

+		}

+		if(c==MINUS)

+		{

+			load_reg(f,zreg,&p->q1,t);

+			emit(f,"\tneg\t%s ; %s\n",dt(t),regnames[zreg]);

+			save_result(f,p);

+			continue;

+		}

+		if(c >= BEQ && c < BRA)

+		{

+

+			char *ccu[]={"cmp","nequ","gt","!gte","gte","!gt"};

+			char *ccs[]={"cmps","nequs","gts","!gtes","gtes","!gts"};

+			char *ccf[]={"cmpf","nequf","gtf","!gtef","gtef","!gtf"};

+			if(p_test == 0)

+			{

+				printf("Calling %s without a test!\n",ccs[c-BEQ]);

+				emit(f,"Calling %s without a test!\n",ccs[c-BEQ]);

+				continue;

+			}

+

+			struct IC *p_old = p;

+			p = p_test;

+			t=p->typf;

+

+			if(test_handled == 0)

+			{

+				if(ISFLOAT(t))

+				{

+					if(isreg(q2))

+					{

+						char instruction[10];

+						sprintf(instruction, "%s", ccf[c-BEQ]);

+						if(instruction[0] == '!')

+						{

+							instruction[0] = ' ';

+							emit(f,"\n\t%s\t%s\t%s\n",instruction,regnames[test_reg],regnames[test_reg2]);

+						}

+						else

+							emit(f,"\n\t%s\t%s\t%s\n",instruction,regnames[test_reg2],regnames[test_reg]);

+

+						save_result(f,p);

+					}

+					else

+					{

+						if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))

+						{

+							unsigned long offset = real_offset(&p->q2);

+							if(offset == 0)

+							{

+								emit(f,"\tmovf\tb28\t[z2]\n");

+							}

+							else

+							{

+								emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);

+								emit(f,"\tmov\tb29\tz2\n");

+								emit(f,"\tsub\tb29\tb28\n");

+								emit(f,"\tmovf\tb28\t[b29]\n");

+							}

+						}

+						else

+						{

+							emit(f,"\tmovf\tb28\t");

+							emit_obj(f,&p->q2,t);

+							emit(f,"\n");

+						}

+

+						char instruction[10];

+						sprintf(instruction, "%s", ccf[c-BEQ]);

+						if(instruction[0] == '!')

+						{

+							instruction[0] = ' ';

+							emit(f,"\n\t%s\t%s\tb28\n",instruction,regnames[test_reg]);

+						}

+						else

+							emit(f,"\n\t%s\tb28\t%s\n",instruction,regnames[test_reg]);

+					}

+				}

+				else if(t & UNSIGNED)

+				{

+					if(isreg(q2))

+					{

+						char instruction[10];

+						sprintf(instruction, "%s", ccu[c-BEQ]);

+						if(instruction[0] == '!')

+						{

+							instruction[0] = ' ';

+							emit(f,"\n\t%s\t%s\t%s\n",instruction,regnames[test_reg2],regnames[test_reg]);

+						}

+						else

+							emit(f,"\n\t%s\t%s\t%s\n",instruction,regnames[test_reg],regnames[test_reg2]);

+						save_result(f,p);

+						continue;

+					}

+					else

+					{

+						if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))

+						{

+							unsigned long offset = real_offset(&p->q2);

+							if(offset == 0)

+							{

+								emit(f,"\tmov\tb28\t[z2]\n");

+							}

+							else

+							{

+								emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);

+								emit(f,"\tmov\tb29\tz2\n");

+								emit(f,"\tsub\tb29\tb28\n");

+								emit(f,"\tmov\tb28\t[b29]\n");

+							}

+						}

+						else

+						{

+							emit(f,"\tmov\tb28\t");

+							emit_obj(f,&p->q2,t);

+							emit(f,"\n");

+						}

+

+						char instruction[10];

+						sprintf(instruction, "%s", ccu[c-BEQ]);

+						if(instruction[0] == '!')

+						{

+							instruction[0] = ' ';

+							emit(f,"\n\t%s\t%s\tb28\n",instruction,regnames[test_reg]);

+						}

+						else

+							emit(f,"\n\t%s\tb28\t%s\n",instruction,regnames[test_reg]);

+					}

+				}

+				else

+				{

+					if(isreg(q2))

+					{

+						char instruction[10];

+						sprintf(instruction, "%s", ccs[c-BEQ]);

+						if(instruction[0] == '!')

+						{

+							instruction[0] = ' ';

+							emit(f,"\n\t%s\t%s\t%s\n",instruction,regnames[test_reg],regnames[test_reg2]);

+						}

+						else

+							emit(f,"\n\t%s\t%s\t%s\n",instruction,regnames[p->q2.reg],regnames[test_reg]);

+

+						save_result(f,p);

+						continue;

+					}

+					else

+					{

+						if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))

+						{

+							unsigned long offset = real_offset(&p->q2);

+							if(offset == 0)

+							{

+								emit(f,"\tmovs\tb28\t[z2]\n");

+							}

+							else

+							{

+								emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);

+								emit(f,"\tmov\tb29\tz2\n");

+								emit(f,"\tsub\tb29\tb28\n");

+								emit(f,"\tmovs\tb28\t[b29]\n");

+							}

+						}

+						else

+						{

+							emit(f,"\tmovs\tb28\t");

+							emit_obj(f,&p->q2,t);

+							emit(f,"\n");

+						}

+

+						char instruction[10];

+						sprintf(instruction, "%s", ccs[c-BEQ]);

+						if(instruction[0] == '!')

+						{

+							instruction[0] = ' ';

+							emit(f,"\n\t%s\t%s\tb28\n",instruction,regnames[test_reg]);

+						}

+						else

+							emit(f,"\n\t%s\tb28\t%s\n",instruction,regnames[test_reg]);

+					}

+				}

+

+				//emit(f,"\tj%s\t",ccs[c-BEQ]);

+				//if(isreg(q1))

+				//{

+				//emit_obj(f,&p->q1,0);

+				//emit(f,",");

+				//}

+				//emit(f,"%s%d ;\n",labprefix,t);

+

+				// next

+

+			}

+			else

+			{

+				if(p_old->code == BEQ)

+				{

+					emit(f,"\n\trz\t%s\n",regnames[test_reg]);

+				}

+				else if(p_old->code == BNE)

+				{

+					emit(f,"\n\trnz\t%s\n",regnames[test_reg]);

+				}

+				else

+					emit(f,"not sure what to do with %d\n", p_old->code);

+			}

+

+			p = p_old;

+			t=p->typf;

+

+			test_handled = 0;

+

+			emit(f,"\tmov\tb28\t%s%d\n",labprefix,t);

+			emit(f,"\tjnz\tz0\tb28\n");

+			continue;

+		}	

+		if(c==TEST)

+		{

+			// printf("found test");

+/*			emit(f,"\ttst\t");

+			if(multiple_ccs)

+				emit(f,"%s,",regnames[zreg]);

+			emit_obj(f,&p->q1,t);

+			emit(f," ; %s\n",dt(t));

+			if(multiple_ccs)

+				save_result(f,p); */

+

+			test_reg = zreg;

+			test_reg2 = q2reg;

+

+			if(!isreg(q1))

+					load_reg(f,test_reg,&p->q1,t);

+

+			p_test = p;

+			test_handled = 1;

+

+			continue;

+		}

+		if(c==COMPARE)

+		{

+			test_reg = zreg;

+			test_reg2 = q2reg;

+			

+			if(!isreg(q1))

+					load_reg(f,zreg,&p->q1,t);

+

+			p_test = p;

+			test_handled = 0;

+//			emit(f, "; compare %s\n", regnames[zreg]);

+			continue;

+		}

+		if(c==OR)

+		{

+			emit(f,"\tmov\tb28\t");

+			emit_obj(f,&p->q2,t);

+

+			emit(f,"\n\tor\t%s b28\n",/*dt(t),*/regnames[zreg]);

+			save_result(f,p);

+			continue;

+		}

+		if(c==XOR)

+		{

+			emit(f,"\tmov\tb28\t");

+			emit_obj(f,&p->q2,t);

+

+			emit(f,"\n\txor\t%s b28\n",/*dt(t),*/regnames[zreg]);

+			save_result(f,p);

+			continue;

+		}

+		if(c==AND)

+		{

+			emit(f,"\tmov\tb28\t");

+			emit_obj(f,&p->q2,t);

+

+			emit(f,"\n\tand\t%s b28\n",/*dt(t),*/regnames[zreg]);

+			save_result(f,p);

+			continue;

+		}

+

+		if(c==LSHIFT)

+		{

+			emit(f,"\tmov\tb28\t");

+			emit_obj(f,&p->q2,t);

+

+			emit(f,"\n\tsal\t%s b28\n",/*dt(t),*/regnames[zreg]);

+			save_result(f,p);

+			continue;

+		}

+

+		if(c==RSHIFT)

+		{

+			emit(f,"\tmov\tb28\t");

+			emit_obj(f,&p->q2,t);

+

+			emit(f,"\n\tsar\t%s b28\n",/*dt(t),*/regnames[zreg]);

+			save_result(f,p);

+			continue;

+		}

+

+		if(c==ADD) ///////////////////////////////////////// ADDITION

+		{

+			if(!isreg(q1))

+				load_reg(f,zreg,&p->q1,t);

+

+			if(p->q2.flags&KONST)

+			{

+				if(ISFLOAT(t))

+				{

+					char *ds = (char *)&p->q2.val.vfloat;

+					char tmp = ds[0];

+					ds[0] = ds[3];

+					ds[3] = tmp;

+					tmp = ds[1];

+					ds[1] = ds[2];

+					ds[2] = tmp;

+

+					if((*(float *)ds) == 1.0f)

+					{

+						emit(f,"\tincf\t%s\n", regnames[zreg]);

+						save_result(f,p);

+						continue;

+					}

+				}

+				else if(t & UNSIGNED)

+				{

+					if(*(unsigned int *)&p->q2.val == 1)

+					{

+						emit(f,"\tinc\t%s\n", regnames[zreg]);

+						save_result(f,p);

+						continue;

+					}

+				}

+				else

+				{

+					if(*(unsigned int *)&p->q2.val == 1)

+					{

+						emit(f,"\tincs\t%s\n", regnames[zreg]);

+						save_result(f,p);

+						continue;

+					}

+				}

+			}

+

+			if(ISFLOAT(t))

+			{

+				if(isreg(q2))

+				{

+					emit(f,"\n\taddf\t%s\t%s\n",/*dt(t),*/regnames[zreg],regnames[p->q2.reg]);

+					save_result(f,p);

+					continue;

+				}

+

+				if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))

+				{

+					unsigned long offset = real_offset(&p->q2);

+					if(offset == 0)

+					{

+						emit(f,"\tmovf\tb28\t[z2]\n");

+					}

+					else

+					{

+						emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);

+						emit(f,"\tmov\tb29\tz2\n");

+						emit(f,"\tsub\tb29\tb28\n");

+						emit(f,"\tmovf\tb28\t[b29]\n");

+					}

+				}

+				else

+				{

+					emit(f,"\tmovf\tb28\t");

+					emit_obj(f,&p->q2,t);

+					emit(f,"\n");

+				}

+

+				emit(f,"\n\taddf\t%s b28\n",/*dt(t),*/regnames[zreg]);

+				save_result(f,p);

+				continue;

+			}

+			else if(t & UNSIGNED)

+			{

+				if(isreg(q2))

+				{

+					emit(f,"\n\tadd\t%s\t%s\n",/*dt(t),*/regnames[zreg],regnames[p->q2.reg]);

+					save_result(f,p);

+					continue;

+				}

+

+				if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))

+				{

+					unsigned long offset = real_offset(&p->q2);

+					if(offset == 0)

+					{

+						emit(f,"\tmov\tb28\t[z2]\n");

+					}

+					else

+					{

+						emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);

+						emit(f,"\tmov\tb29\tz2\n");

+						emit(f,"\tsub\tb29\tb28\n");

+						emit(f,"\tmov\tb28\t[b29]\n");

+					}

+				}

+				else

+				{

+					emit(f,"\tmov\tb28\t");

+					emit_obj(f,&p->q2,t);

+					emit(f,"\n");

+				}

+

+				emit(f,"\n\tadd\t%s b28\n",/*dt(t),*/regnames[zreg]);

+				save_result(f,p);

+				continue;

+			}

+			else

+			{

+				if(isreg(q2))

+				{

+					emit(f,"\n\tadds\t%s\t%s\n",/*dt(t),*/regnames[zreg],regnames[p->q2.reg]);

+					save_result(f,p);

+					continue;

+				}

+

+				if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))

+				{

+					unsigned long offset = real_offset(&p->q2);

+					if(offset == 0)

+					{

+						emit(f,"\tmovs\tb28\t[z2]\n");

+					}

+					else

+					{

+						emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);

+						emit(f,"\tmov\tb29\tz2\n");

+						emit(f,"\tsub\tb29\tb28\n");

+						emit(f,"\tmovs\tb28\t[b29]\n");

+					}

+				}

+				else

+				{

+					emit(f,"\tmovs\tb28\t");

+					emit_obj(f,&p->q2,t);

+					emit(f,"\n");

+				}

+

+				emit(f,"\n\tadds\t%s b28\n",/*dt(t),*/regnames[zreg]);

+				save_result(f,p);

+				continue;

+			}

+		}

+

+		if(c==SUB)

+		{

+			if(!isreg(q1))

+				load_reg(f,zreg,&p->q1,t);

+

+			if(p->q2.flags&KONST)

+			{

+				if(ISFLOAT(t))

+				{

+					char *ds = (char *)&p->q2.val.vfloat;

+					char tmp = ds[0];

+					ds[0] = ds[3];

+					ds[3] = tmp;

+					tmp = ds[1];

+					ds[1] = ds[2];

+					ds[2] = tmp;

+

+					if((*(float *)ds) == 1.0f)

+					{

+						emit(f,"\tdecf\t%s\n", regnames[zreg]);

+						save_result(f,p);

+						continue;

+					}

+				}

+				else if(t & UNSIGNED)

+				{

+					if(*(unsigned int *)&p->q2.val == 1)

+					{

+						emit(f,"\tdec\t%s\n", regnames[zreg]);

+						save_result(f,p);

+						continue;

+					}

+				}

+				else

+				{

+					if(*(unsigned int *)&p->q2.val == 1)

+					{

+						emit(f,"\tdecs\t%s\n", regnames[zreg]);

+						save_result(f,p);

+						continue;

+					}

+				}

+			}

+			if(ISFLOAT(t))

+			{

+				if(isreg(q2))

+				{

+					emit(f,"\n\tsubf\t%s\t%s\n",/*dt(t),*/regnames[zreg],regnames[p->q2.reg]);

+					save_result(f,p);

+					continue;

+				}

+

+				if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))

+				{

+					unsigned long offset = real_offset(&p->q2);

+					if(offset == 0)

+					{

+						emit(f,"\tmovf\tb28\t[z2]\n");

+					}

+					else

+					{

+						emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);

+						emit(f,"\tmov\tb29\tz2\n");

+						emit(f,"\tsub\tb29\tb28\n");

+						emit(f,"\tmovf\tb28\t[b29]\n");

+					}

+				}

+				else

+				{

+					emit(f,"\tmovf\tb28\t");

+					emit_obj(f,&p->q2,t);

+					emit(f,"\n");

+				}

+

+				emit(f,"\n\tsubf\t%s\tb28\n",/*dt(t),*/regnames[zreg]);

+				save_result(f,p);

+				continue;

+			}

+			else if(t & UNSIGNED)

+			{

+				if(isreg(q2))

+				{

+					emit(f,"\n\tsub\t%s\t%s\n",/*dt(t),*/regnames[zreg],regnames[p->q2.reg]);

+					save_result(f,p);

+					continue;

+				}

+

+				if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))

+				{

+					unsigned long offset = real_offset(&p->q2);

+					if(offset == 0)

+					{

+						emit(f,"\tmov\tb28\t[z2]\n");

+					}

+					else

+					{

+						emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);

+						emit(f,"\tmov\tb29\tz2\n");

+						emit(f,"\tsub\tb29\tb28\n");

+						emit(f,"\tmov\tb28\t[b29]\n");

+					}

+				}

+				else

+				{

+					emit(f,"\tmov\tb28\t");

+					emit_obj(f,&p->q2,t);

+					emit(f,"\n");

+				}

+

+				emit(f,"\n\tsub\t%s\tb28\n",/*dt(t),*/regnames[zreg]);

+				save_result(f,p);

+				continue;

+			}

+			else

+			{

+				if(isreg(q2))

+				{

+					emit(f,"\n\tsubs\t%s\t%s\n",/*dt(t),*/regnames[zreg],regnames[p->q2.reg]);

+					save_result(f,p);

+					continue;

+				}

+

+				if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))

+				{

+					unsigned long offset = real_offset(&p->q2);

+					if(offset == 0)

+					{

+						emit(f,"\tmovs\tb28\t[z2]\n");

+					}

+					else

+					{

+						emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);

+						emit(f,"\tmov\tb29\tz2\n");

+						emit(f,"\tsub\tb29\tb28\n");

+						emit(f,"\tmovs\tb28\t[b29]\n");

+					}

+				}

+				else

+				{

+					emit(f,"\tmovs\tb28\t");

+					emit_obj(f,&p->q2,t);

+					emit(f,"\n");

+				}

+

+				emit(f,"\n\tsubs\t%s\tb28\n",/*dt(t),*/regnames[zreg]);

+				save_result(f,p);

+				continue;

+			}

+		}

+

+		if(c==MULT)

+		{

+			if(ISFLOAT(t))

+			{

+				if(isreg(q2))

+				{

+					emit(f,"\n\tmulf\t%s\t%s\n",/*dt(t),*/regnames[zreg],regnames[p->q2.reg]);

+					save_result(f,p);

+					continue;

+				}

+

+				if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))

+				{

+					unsigned long offset = real_offset(&p->q2);

+					if(offset == 0)

+					{

+						emit(f,"\tmovf\tb28\t[z2]\n");

+					}

+					else

+					{

+						emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);

+						emit(f,"\tmov\tb29\tz2\n");

+						emit(f,"\tsub\tb29\tb28\n");

+						emit(f,"\tmovf\tb28\t[b29]\n");

+					}

+				}

+				else

+				{

+					emit(f,"\tmovf\tb28\t");

+					emit_obj(f,&p->q2,t);

+					emit(f,"\n");

+				}

+

+				emit(f,"\n\tmulf\t%s\tb28\n",/*dt(t),*/regnames[zreg]);

+				save_result(f,p);

+				continue;

+			}

+			else if(t & UNSIGNED)

+			{

+				if(isreg(q2))

+				{

+					emit(f,"\n\tmul\t%s\t%s\n",/*dt(t),*/regnames[zreg],regnames[p->q2.reg]);

+					save_result(f,p);

+					continue;

+				}

+

+				if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))

+				{

+					unsigned long offset = real_offset(&p->q2);

+					if(offset == 0)

+					{

+						emit(f,"\tmov\tb28\t[z2]\n");

+					}

+					else

+					{

+						emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);

+						emit(f,"\tmov\tb29\tz2\n");

+						emit(f,"\tsub\tb29\tb28\n");

+						emit(f,"\tmov\tb28\t[b29]\n");

+					}

+				}

+				else

+				{

+					emit(f,"\tmov\tb28\t");

+					emit_obj(f,&p->q2,t);

+					emit(f,"\n");

+				}

+

+				emit(f,"\n\tmul\t%s\tb28\n",/*dt(t),*/regnames[zreg]);

+				save_result(f,p);

+				continue;

+			}

+			else

+			{

+				if(isreg(q2))

+				{

+					emit(f,"\n\tmuls\t%s\t%s\n",/*dt(t),*/regnames[zreg],regnames[p->q2.reg]);

+					save_result(f,p);

+					continue;

+				}

+

+				if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))

+				{

+					unsigned long offset = real_offset(&p->q2);

+					if(offset == 0)

+					{

+						emit(f,"\tmovs\tb28\t[z2]\n");

+					}

+					else

+					{

+						emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);

+						emit(f,"\tmov\tb29\tz2\n");

+						emit(f,"\tsub\tb29\tb28\n");

+						emit(f,"\tmovs\tb28\t[b29]\n");

+					}

+				}

+				else

+				{

+					emit(f,"\tmovs\tb28\t");

+					emit_obj(f,&p->q2,t);

+					emit(f,"\n");

+				}

+

+				emit(f,"\n\tmuls\t%s\tb28\n",/*dt(t),*/regnames[zreg]);

+				save_result(f,p);

+				continue;

+			}

+

+			continue;

+		}

+

+		if(c==DIV)

+		{

+			if(ISFLOAT(t))

+			{

+				if(isreg(q2))

+				{

+					emit(f,"\n\tdivf\t%s\t%s\n",/*dt(t),*/regnames[zreg],regnames[p->q2.reg]);

+					save_result(f,p);

+					continue;

+				}

+

+				if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))

+				{

+					unsigned long offset = real_offset(&p->q2);

+					if(offset == 0)

+					{

+						emit(f,"\tmovf\tb28\t[z2]\n");

+					}

+					else

+					{

+						emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);

+						emit(f,"\tmov\tb29\tz2\n");

+						emit(f,"\tsub\tb29\tb28\n");

+						emit(f,"\tmovf\tb28\t[b29]\n");

+					}

+				}

+				else

+				{

+					emit(f,"\tmovf\tb28\t");

+					emit_obj(f,&p->q2,t);

+					emit(f,"\n");

+				}

+

+				emit(f,"\n\tdivf\t%s\tb28\n",/*dt(t),*/regnames[zreg]);

+				save_result(f,p);

+				continue;

+			}

+			else if(t & UNSIGNED)

+			{

+				if(isreg(q2))

+				{

+					emit(f,"\n\tdiv\t%s\t%s\n",/*dt(t),*/regnames[zreg],regnames[p->q2.reg]);

+					save_result(f,p);

+					continue;

+				}

+

+				if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))

+				{

+					unsigned long offset = real_offset(&p->q2);

+					if(offset == 0)

+					{

+						emit(f,"\tmov\tb28\t[z2]\n");

+					}

+					else

+					{

+						emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);

+						emit(f,"\tmov\tb29\tz2\n");

+						emit(f,"\tsub\tb29\tb28\n");

+						emit(f,"\tmov\tb28\t[b29]\n");

+					}

+				}

+				else

+				{

+					emit(f,"\tmov\tb28\t");

+					emit_obj(f,&p->q2,t);

+					emit(f,"\n");

+				}

+

+				emit(f,"\n\tdiv\t%s\tb28\n",/*dt(t),*/regnames[zreg]);

+				save_result(f,p);

+				continue;

+			}

+			else

+			{

+				if(isreg(q2))

+				{

+					emit(f,"\n\tdivs\t%s\t%s\n",/*dt(t),*/regnames[zreg],regnames[p->q2.reg]);

+					save_result(f,p);

+					continue;

+				}

+

+				if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))

+				{

+					unsigned long offset = real_offset(&p->q2);

+					if(offset == 0)

+					{

+						emit(f,"\tmovs\tb28\t[z2]\n");

+					}

+					else

+					{

+						emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);

+						emit(f,"\tmov\tb29\tz2\n");

+						emit(f,"\tsub\tb29\tb28\n");

+						emit(f,"\tmovs\tb28\t[b29]\n");

+					}

+				}

+				else

+				{

+					emit(f,"\tmovs\tb28\t");

+					emit_obj(f,&p->q2,t);

+					emit(f,"\n");

+				}

+

+				emit(f,"\n\tdivs\t%s\tb28\n",/*dt(t),*/regnames[zreg]);

+				save_result(f,p);

+				continue;

+			}

+		}

+

+		if(c==MOD)

+		{

+			if(ISFLOAT(t))

+			{

+				if(isreg(q2))

+				{

+					emit(f,"\n\tmodf\t%s\t%s\n",/*dt(t),*/regnames[zreg],regnames[p->q2.reg]);

+					save_result(f,p);

+					continue;

+				}

+

+				if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))

+				{

+					unsigned long offset = real_offset(&p->q2);

+					if(offset == 0)

+					{

+						emit(f,"\tmovf\tb28\t[z2]\n");

+					}

+					else

+					{

+						emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);

+						emit(f,"\tmov\tb29\tz2\n");

+						emit(f,"\tsub\tb29\tb28\n");

+						emit(f,"\tmovf\tb28\t[b29]\n");

+					}

+				}

+				else

+				{

+					emit(f,"\tmovf\tb28\t");

+					emit_obj(f,&p->q2,t);

+					emit(f,"\n");

+				}

+

+				emit(f,"\n\tmodf\t%s\tb28\n",/*dt(t),*/regnames[zreg]);

+				save_result(f,p);

+				continue;

+			}

+			else if(t & UNSIGNED)

+			{

+				if(isreg(q2))

+				{

+					emit(f,"\n\tmod\t%s\t%s\n",/*dt(t),*/regnames[zreg],regnames[p->q2.reg]);

+					save_result(f,p);

+					continue;

+				}

+

+				if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))

+				{

+					unsigned long offset = real_offset(&p->q2);

+					if(offset == 0)

+					{

+						emit(f,"\tmov\tb28\t[z2]\n");

+					}

+					else

+					{

+						emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);

+						emit(f,"\tmov\tb29\tz2\n");

+						emit(f,"\tsub\tb29\tb28\n");

+						emit(f,"\tmov\tb28\t[b29]\n");

+					}

+				}

+				else

+				{

+					emit(f,"\tmov\tb28\t");

+					emit_obj(f,&p->q2,t);

+					emit(f,"\n");

+				}

+

+				emit(f,"\n\tmod\t%s\tb28\n",/*dt(t),*/regnames[zreg]);

+				save_result(f,p);

+				continue;

+			}

+			else

+			{

+				if(isreg(q2))

+				{

+					emit(f,"\n\tmods\t%s\t%s\n",/*dt(t),*/regnames[zreg],regnames[p->q2.reg]);

+					save_result(f,p);

+					continue;

+				}

+

+				if(((p->q2.flags&VAR)&&!(p->q2.flags&REG)) && (p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER))

+				{

+					unsigned long offset = real_offset(&p->q2);

+					if(offset == 0)

+					{

+						emit(f,"\tmovs\tb28\t[z2]\n");

+					}

+					else

+					{

+						emit(f,"\tmov\tb28\t%ld ; get from stack\n", offset);

+						emit(f,"\tmov\tb29\tz2\n");

+						emit(f,"\tsub\tb29\tb28\n");

+						emit(f,"\tmovs\tb28\t[b29]\n");

+					}

+				}

+				else

+				{

+					emit(f,"\tmovs\tb28\t");

+					emit_obj(f,&p->q2,t);

+					emit(f,"\n");

+				}

+

+				emit(f,"\n\tmods\t%s\tb28\n",/*dt(t),*/regnames[zreg]);

+				save_result(f,p);

+				continue;

+			}

+		}

+

+		pric2(stdout,p);

+		ierror(0);

+	}

+	function_bottom(f,v,localsize);

+	if(stack_valid)

+	{

+		if(!v->fi)

+			v->fi=new_fi();

+		v->fi->flags|=ALL_STACK;

+		v->fi->stack1=stack;

+	}

+	emit(f," ; stacksize=%lu%s\n",zum2ul(stack),stack_valid?"":"+??");

+}

+

+int shortcut(int code,int typ)

+{

+	return 1;

+}

+

+int reg_parm(struct reg_handle *m, struct Typ *t,int vararg,struct Typ *d)

+{

+	int f;

+	f=t->flags&NQ;

+	if(f==CHAR)

+	{

+		if(m->regs8>=NUM_8BIT)

+			return 0;

+		else

+			return FIRST_8BIT+m->regs8++;

+	}

+	if(f==SHORT)

+	{

+		if(m->regs16>=NUM_16BIT)

+			return 0;

+		else

+			return FIRST_16BIT+m->regs16++;

+	}

+	if(f==INT || f==LONG || f==POINTER || f==FLOAT)

+	{

+		if(m->regs32>=NUM_32BIT)

+			return 0;

+		else

+			return FIRST_32BIT+m->regs32++;

+	}

+	if(f==DOUBLE || f==LDOUBLE || f==LLONG){

+		if(m->regs64>=NUM_64BIT)

+			return 0;

+		else

+			return FIRST_64BIT+m->regs64++;

+	}

+	return 0;

+}

+

+int handle_pragma(const char *s)

+{

+	return 0;

+}

+

+void cleanup_cg(FILE *f)

+{

+	if(!f)

+		return;

+

+}

+

+void cleanup_db(FILE *f)

+{

+	if(f)

+		section=-1;

+}

+

+/*

+C registers:

+b28 - temp - store var during calculation/comparison

+b29 - temp - store address during jump

+b30 - temp store address of parameters

+b31 - temp store addresses to jump to

+

+a0 - 16 bit					4

+a1 - 16 bit					5

+a2 - 16 bit					6

+a3 - 16 bit					7

+a4 - 16 bit					8

+a5 - 16 bit					9

+a6 - 16 bit					10

+a7 - 16 bit					11

+a8 - 16 bit					12

+a9 - 16 bit					13

+b5 - 32 bit					14

+b6 - 32 bit					15

+b7 - 32 bit					16

+b8 - 32 bit					17

+b9 - 32 bit					18

+b10 - 32 bit					19

+b11 - 32 bit					20

+b12 - 32 bit					21

+b13 - 32 bit					22

+b14 - 32 bit					23

+b15 - 32 bit					24

+b16 - 32 bit					25

+b17 - 32 bit					26

+c9  - 64 bit					27

+c10 - 64 bit					28

+c11 - 64 bit					29

+c12 - 64 bit					30

+c13 - 64 bit					31

+

+h0 - 8bit					32

+h1 - 8bit					33

+h2 - 8bit					34

+h3 - 8bit					35

+*/

diff --git a/machines/messiahtron/machine.dt b/machines/messiahtron/machine.dt
new file mode 100755
index 0000000..526c8d4
--- /dev/null
+++ b/machines/messiahtron/machine.dt
@@ -0,0 +1,16 @@
+S8BS
+S8BU
+S16BSBE S16BSLE
+S16BUBE S16BULE
+S32BSBE S32BSLE
+S32BUBE S32BULE
+S32BSBE S32BSLE
+S32BUBE S32BULE
+S64BSBE S64BSLE
+S64BUBE S64BULE
+S32BIEEEBE
+S64BIEEEBE
+S64BIEEEBE
+S32BUBE S32BULE
+
+
diff --git a/machines/messiahtron/machine.h b/machines/messiahtron/machine.h
new file mode 100755
index 0000000..acab9ae
--- /dev/null
+++ b/machines/messiahtron/machine.h
@@ -0,0 +1,184 @@
+/*  Example backend for vbcc, it models a generic 32bit RISC or CISC
+    CPU.
+
+    Configurable at build-time are:
+    - number of (32bit) general-purpose-registers
+    - number of (64bit) floating-point-registers
+    - number of (8bit) condition-code-registers
+    - mechanism for stack-arguments (moving ot fixed sp)
+
+    It allows to select as run-time-options:
+    - two- or three-address code
+    - memory operands or load-store-architecture
+    - number of register-arguments
+    - number of caller-save-registers
+*/
+
+/* buil-time configurable options: */
+
+#undef CHAR
+#undef SHORT
+#undef INT
+#undef LONG
+#undef LLONG
+#undef FLOAT
+#undef DOUBLE
+#undef LDOUBLE
+#undef VOID
+#undef POINTER
+#undef ARRAY
+#undef STRUCT
+#undef UNION
+#undef ENUM
+#undef FUNKT
+#undef MAXINT
+#undef MAX_TYPE
+
+#define CHAR 1
+#define SHORT 2
+#define INT 3
+#define LONG 4
+#define LLONG 5
+#define FLOAT 6
+#define DOUBLE 7
+#define LDOUBLE 8
+#define VOID 9
+#define POINTER 10
+#define ARRAY 11
+#define STRUCT 12
+#define UNION 13
+#define ENUM 14
+#define FUNKT 15
+#define MAXINT 16 /* should not be accesible to application */
+#define MAX_TYPE MAXINT
+
+
+//#define NUM_FIXED 4
+#define NUM_16BIT 10
+#define NUM_32BIT 13
+#define NUM_64BIT 5
+#define NUM_8BIT  4
+
+#include "dt.h"
+
+/* internally used by the backend */
+//#define FIRST_FIXED 1
+//#define LAST_FIXED (FIRST_FIXED+NUM_FIXED-1)
+#define FIRST_16BIT 1//(LAST_FIXED+1)
+#define LAST_16BIT (FIRST_16BIT+NUM_16BIT-1)
+#define FIRST_32BIT (LAST_16BIT+1)
+#define LAST_32BIT (FIRST_32BIT+NUM_32BIT-1)
+#define FIRST_64BIT (LAST_32BIT+1)
+#define LAST_64BIT (FIRST_64BIT+NUM_64BIT-1)
+#define FIRST_8BIT (LAST_64BIT+1)
+#define LAST_8BIT (FIRST_8BIT+NUM_8BIT-1)
+#define STACK_POINTER (LAST_8BIT+1)
+
+// #define FIXED_SP 1
+
+/*  This struct can be used to implement machine-specific           */
+/*  addressing-modes.                                               */
+/*  Currently possible are (const,gpr) and (gpr,gpr)                */
+struct AddressingMode{
+    int flags;
+    int base;
+    long offset;
+};
+
+/*  The number of registers of the target machine.                  */
+#define MAXR NUM_16BIT+NUM_32BIT+NUM_64BIT+NUM_8BIT+1
+
+/*  Number of commandline-options the code-generator accepts.       */
+#define MAXGF 20
+
+/*  If this is set to zero vbcc will not generate ICs where the     */
+/*  target operand is the same as the 2nd source operand.           */
+/*  This can sometimes simplify the code-generator, but usually     */
+/*  the code is better if the code-generator allows it.             */
+#define USEQ2ASZ 1
+
+/*  This specifies the smallest integer type that can be added to a */
+/*  pointer.                                                        */
+#define MINADDI2P CHAR
+
+/*  If the bytes of an integer are ordered most significant byte    */
+/*  byte first and then decreasing set BIGENDIAN to 1.              */
+#define BIGENDIAN 1
+
+/*  If the bytes of an integer are ordered lest significant byte    */
+/*  byte first and then increasing set LITTLEENDIAN to 1.           */
+#define LITTLEENDIAN 0
+
+/*  Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive.    */
+
+/*  If switch-statements should be generated as a sequence of       */
+/*  SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1.      */
+/*  This can yield better code on some machines.                    */
+#define SWITCHSUBS 0
+
+/*  In optimizing compilation certain library memcpy/strcpy-calls   */
+/*  with length known at compile-time will be inlined using an      */
+/*  ASSIGN-IC if the size is less or equal to INLINEMEMCPY.         */
+/*  The type used for the ASSIGN-IC will be UNSIGNED|CHAR.          */
+#define INLINEMEMCPY 1024
+
+/*  Parameters are sometimes passed in registers without __reg.     */
+#define HAVE_REGPARMS 1
+
+/*  Parameters on the stack should be pushed in order rather than   */
+/*  in reverse order.                                               */
+#define ORDERED_PUSH 1
+
+/*  Structure for reg_parm().                                       */
+struct reg_handle{
+    unsigned long regs8;
+    unsigned long regs16;
+	unsigned long regs32;
+	unsigned long regs64;
+};
+
+/*  We have some target-specific variable attributes.               */
+#define HAVE_TARGET_ATTRIBUTES
+
+/* We have target-specific pragmas */
+#define HAVE_TARGET_PRAGMAS
+
+/*  We keep track of all registers modified by a function.          */
+#define HAVE_REGS_MODIFIED 1
+
+/* We have a implement our own cost-functions to adapt 
+   register-allocation */
+#define HAVE_TARGET_RALLOC 1
+#define cost_move_reg(x,y) 1
+#define cost_load_reg(x,y) 2
+#define cost_save_reg(x,y) 2
+#define cost_pushpop_reg(x) 3
+
+/* size of buffer for asm-output, this can be used to do
+   peephole-optimizations of the generated assembly-output */
+#define EMIT_BUF_LEN 1024 /* should be enough */
+/* number of asm-output lines buffered */
+#define EMIT_BUF_DEPTH 4
+
+/*  We have no asm_peephole to optimize assembly-output */
+#define HAVE_TARGET_PEEPHOLE 0
+
+/* we do not have a mark_eff_ics function, this is used to prevent
+   optimizations on code which can already be implemented by efficient
+   assembly */
+#undef HAVE_TARGET_EFF_IC
+
+/* we only need the standard data types (no bit-types, different pointers
+   etc.) */
+#undef HAVE_EXT_TYPES
+#undef HAVE_TGT_PRINTVAL
+
+/* we do not need extra elements in the IC */
+#undef HAVE_EXT_IC
+
+/* we do not use unsigned int as size_t (but unsigned long, the default) */
+#undef HAVE_INT_SIZET
+
+/* we do not need register-pairs */
+#undef HAVE_REGPAIRS
+
diff --git a/machines/minx/machine.c b/machines/minx/machine.c
new file mode 100755
index 0000000..2417521
--- /dev/null
+++ b/machines/minx/machine.c
@@ -0,0 +1,1021 @@
+/*  Example backend for vbcc, it models a generic 32bit RISC or CISC
+ CPU.
+ 
+ Configurable at build-time are:
+ - number of (32bit) general-purpose-registers
+ - number of (64bit) floating-point-registers
+ - number of (8bit) condition-code-registers
+ - mechanism for stack-arguments (moving ot fixed sp)
+ 
+ It allows to select as run-time-options:
+ - two- or three-address code
+ - memory operands or load-store-architecture
+ - number of register-arguments
+ - number of caller-save-registers
+ */                                                                             
+
+#include "supp.h"
+
+static char FILE_[]=__FILE__;
+
+/*  Public data that MUST be there.                             */
+
+/* Name and copyright. */
+char cg_copyright[]="vbcc generic code-generator V0.01 for Minx (c) in 2001 by zoranc";
+
+/*  Commandline-flags the code-generator accepts:
+ 0: just a flag
+ VALFLAG: a value must be specified
+ STRINGFLAG: a string can be specified
+ FUNCFLAG: a function will be called
+ apart from FUNCFLAG, all other versions can only be specified once */
+int g_flags[MAXGF]={0,0,
+  VALFLAG,VALFLAG,VALFLAG,
+  0,0,
+  VALFLAG,VALFLAG,0};
+
+/* the flag-name, do not use names beginning with l, L, I, D or U, because
+ they collide with the frontend */
+char *g_flags_name[MAXGF]={"three-addr","load-store",
+  "volatile-gprs","volatile-fprs","volatile-ccrs",
+  "imm-ind","gpr-ind",
+  "gpr-args","fpr-args","use-commons"};
+
+/* the results of parsing the command-line-flags will be stored here */
+union ppi g_flags_val[MAXGF];
+
+/*  Alignment-requirements for all types in bytes.              */
+zmax align[MAX_TYPE+1];
+
+/*  Alignment that is sufficient for every object.              */
+zmax maxalign;
+
+/*  CHAR_BIT for the target machine.                            */
+zmax char_bit;
+
+/*  sizes of the basic 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. will be initialized in init_cg(),
+ register number 0 is invalid, valid registers start at 1 */
+char *regnames[MAXR+1];
+
+/*  The Size of each register in bytes.                         */
+zmax regsize[MAXR+1];
+
+/*  a 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];
+
+/* specifies the priority for the register-allocator, if the same
+ estimated cost-saving can be obtained by several registers, the
+ one with the highest priority will be used */
+int reg_prio[MAXR+1];
+
+/* an empty reg-handle representing initial state */
+struct reg_handle empty_reg_handle={0,0};
+
+/* Names of target-specific variable attributes.                */
+char *g_attr_name[]={"__interrupt",0};
+
+
+/****************************************/
+/*  Private data and functions.         */
+/****************************************/
+
+#define THREE_ADDR (g_flags[0]&USEDFLAG)
+#define LOAD_STORE (g_flags[1]&USEDFLAG)
+#define VOL_GPRS   ((g_flags[2]&USEDFLAG)?g_flags_val[2].l:NUM_GPRS/2)
+#define VOL_FPRS   ((g_flags[3]&USEDFLAG)?g_flags_val[3].l:NUM_FPRS/2)
+#define VOL_CCRS   ((g_flags[4]&USEDFLAG)?g_flags_val[4].l:NUM_CCRS/2)
+#define IMM_IND    ((g_flags[5]&USEDFLAG)?1:0)
+#define GPR_IND    ((g_flags[6]&USEDFLAG)?2:0)
+#define GPR_ARGS   ((g_flags[7]&USEDFLAG)?g_flags_val[7].l:0)
+#define FPR_ARGS   ((g_flags[8]&USEDFLAG)?g_flags_val[8].l:0)
+#define USE_COMMONS (g_flags[9]&USEDFLAG)
+
+
+/* alignment of basic data-types, used to initialize align[] */
+static long malign[MAX_TYPE+1]=  {1,1,2,4,4,4,4,8,8,1,4,1,1,1,4,1};
+/* sizes of basic data-types, used to initialize sizetab[] */
+static long msizetab[MAX_TYPE+1]={1,1,2,4,4,8,4,8,8,0,4,0,0,0,4,0};
+
+/* used to initialize regtyp[] */
+static struct Typ ltyp={LONG},ldbl={DOUBLE},lchar={CHAR};
+
+/* macros defined by the backend */
+static char *marray[]={"__section(x)=__vattr(\"section(\"#x\")\")",
+  "__GENERIC__",
+  0};
+
+/* special registers */
+static int sp;                     /*  Stackpointer                        */
+static int t1,t2,t3;               /*  temporary gprs */
+static int f1,f2,f3;               /*  temporary fprs */
+
+#define dt(t) (((t)&UNSIGNED)?udt[(t)&NQ]:sdt[(t)&NQ])
+static char *sdt[MAX_TYPE+1]={"??","c","s","i","l","ll","f","d","ld","v","p"};
+static char *udt[MAX_TYPE+1]={"??","uc","us","ui","ul","ull","f","d","ld","v","p"};
+
+/* sections */
+#define DATA 0
+#define BSS 1
+#define CODE 2
+#define RODATA 3
+#define SPECIAL 4
+
+static long stack;
+static int stack_valid;
+static int section=-1,newobj;
+static char *codename="\t.text\n",
+*dataname="\t.data\n",
+*bssname="",
+*rodataname="\t.section\t.rodata\n";
+
+/* return-instruction */
+static char *ret;
+
+/* label at the end of the function (if any) */
+static int exit_label;
+
+/* assembly-prefixes for labels and external identifiers */
+static char *labprefix="l",*idprefix="_";
+
+#if FIXED_SP
+/* variables to calculate the size and partitioning of the stack-frame
+ in the case of FIXED_SP */
+static long frameoffset,pushed,maxpushed,framesize;
+#else
+/* variables to keep track of the current stack-offset in the case of
+ a moving stack-pointer */
+static long notpopped,dontpop,stackoffset,maxpushed;
+#endif
+
+static long localsize,rsavesize,argsize;
+
+static void emit_obj(FILE *f,struct obj *p,int t);
+
+/* calculate the actual current offset of an object relativ to the
+ stack-pointer; we use a layout like this:
+ ------------------------------------------------
+ | arguments to this function                   |
+ ------------------------------------------------
+ | return-address [size=4]                      |
+ ------------------------------------------------
+ | caller-save registers [size=rsavesize]       |
+ ------------------------------------------------
+ | local variables [size=localsize]             |
+ ------------------------------------------------
+ | arguments to called functions [size=argsize] |
+ ------------------------------------------------
+ All sizes will be aligned as necessary.
+ In the case of FIXED_SP, the stack-pointer will be adjusted at
+ function-entry to leave enough space for the arguments and have it
+ aligned to 16 bytes. Therefore, when calling a function, the
+ stack-pointer is always aligned to 16 bytes.
+ For a moving stack-pointer, the stack-pointer will usually point
+ to the bottom of the area for local variables, but will move while
+ arguments are put on the stack.
+ 
+ This is just an example layout. Other layouts are also possible.
+ */
+
+static long real_offset(struct obj *o)
+{
+  long off=zm2l(o->v->offset);
+  if(off<0){
+    /* function parameter */
+    off=localsize+rsavesize+4-off-zm2l(maxalign);
+  }
+  
+#if FIXED_SP
+  off+=argsize;
+#else
+  off+=stackoffset;
+#endif
+  off+=zm2l(o->val.vmax);
+  return off;
+}
+
+/*  Initializes an addressing-mode structure and returns a pointer to
+ that object. Will not survive a second call! */
+static struct obj *cam(int flags,int base,long offset)
+{
+  static struct obj obj;
+  static struct AddressingMode am;
+  obj.am=&am;
+  am.flags=flags;
+  am.base=base;
+  am.offset=offset;
+  return &obj;
+}
+
+/* changes to a special section, used for __section() */
+static int special_section(FILE *f,struct Var *v)
+{
+  char *sec;
+  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;
+}
+
+/* generate code to load the address of a variable into register r */
+static void load_address(FILE *f,int r,struct obj *o,int type)
+/*  Generates code to load the address of a variable into register r.   */
+{
+  if(!(o->flags&VAR)) ierror(0);
+  if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER){
+    long off=real_offset(o);
+    if(THREE_ADDR){
+      emit(f,"\tadd.%s\t%s,%s,%ld\n",dt(POINTER),regnames[r],regnames[sp],off);
+    }else{
+      emit(f,"\tmov.%s\t%s,%s\n",dt(POINTER),regnames[r],regnames[sp]);
+      if(off)
+        emit(f,"\tadd.%s\t%s,%ld\n",dt(POINTER),regnames[r],off);
+    }
+  }else{
+    emit(f,"\tmov.%s\t%s,",dt(POINTER),regnames[r]);
+    emit_obj(f,o,type);
+    emit(f,"\n");
+  }
+}
+/* Generates code to load a memory object into register r. tmp is a
+ general purpose register which may be used. tmp can be r. */
+static void load_reg(FILE *f,int r,struct obj *o,int type)
+{
+  type&=NU;
+  if(o->flags&VARADR){
+    load_address(f,r,o,POINTER);
+  }else{
+    if((o->flags&(REG|DREFOBJ))==REG&&o->reg==r)
+      return;
+    emit(f,"\tmov.%s\t%s,",dt(type),regnames[r]);
+    emit_obj(f,o,type);
+    emit(f,"\n");
+  }
+}
+
+/*  Generates code to store register r into memory object o. */
+static void store_reg(FILE *f,int r,struct obj *o,int type)
+{
+  type&=NQ;
+  emit(f,"\tmov.%s\t",dt(type));
+  emit_obj(f,o,type);
+  emit(f,",%s\n",regnames[r]);
+}
+
+/*  Yields log2(x)+1 or 0. */
+static long pof2(zumax x)
+{
+  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 struct IC *preload(FILE *,struct IC *);
+
+static void function_top(FILE *,struct Var *,long);
+static void function_bottom(FILE *f,struct Var *,long);
+
+#define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
+#define isconst(x) ((p->x.flags&(KONST|DREFOBJ))==KONST)
+
+static int q1reg,q2reg,zreg;
+
+static char *ccs[]={"eq","ne","lt","ge","le","gt",""};
+static char *logicals[]={"or","xor","and"};
+static char *arithmetics[]={"slw","srw","add","sub","mullw","divw","mod"};
+
+/* Does some pre-processing like fetching operands from memory to
+ registers etc. */
+static struct IC *preload(FILE *f,struct IC *p)
+{
+  int r;
+  
+  if(isreg(q1))
+    q1reg=p->q1.reg;
+  else
+    q1reg=0;
+  
+  if(isreg(q2))
+    q2reg=p->q2.reg;
+  else
+    q2reg=0;
+  
+  if(isreg(z)){
+    zreg=p->z.reg;
+  }else{
+    if(ISFLOAT(ztyp(p)))
+      zreg=f1;
+    else
+      zreg=t1;
+  }
+  
+  if((p->q1.flags&(DREFOBJ|REG))==DREFOBJ&&!p->q1.am){
+    p->q1.flags&=~DREFOBJ;
+    load_reg(f,t1,&p->q1,q1typ(p));
+    p->q1.reg=t1;
+    p->q1.flags|=(REG|DREFOBJ);
+  }
+  if(p->q1.flags&&LOAD_STORE&&!isreg(q1)){
+    if(ISFLOAT(q1typ(p)))
+      q1reg=f1;
+    else
+      q1reg=t1;
+    load_reg(f,q1reg,&p->q1,q1typ(p));
+    p->q1.reg=q1reg;
+    p->q1.flags=REG;
+  }
+  
+  if((p->q2.flags&(DREFOBJ|REG))==DREFOBJ&&!p->q2.am){
+    p->q2.flags&=~DREFOBJ;
+    load_reg(f,t1,&p->q2,q2typ(p));
+    p->q2.reg=t1;
+    p->q2.flags|=(REG|DREFOBJ);
+  }
+  if(p->q2.flags&&LOAD_STORE&&!isreg(q2)){
+    if(ISFLOAT(q2typ(p)))
+      q2reg=f2;
+    else
+      q2reg=t2;
+    load_reg(f,q2reg,&p->q2,q2typ(p));
+    p->q2.reg=q2reg;
+    p->q2.flags=REG;
+  }
+  return p;
+}
+
+/* save the result (in zreg) into p->z */
+void save_result(FILE *f,struct IC *p)
+{
+  if((p->z.flags&(REG|DREFOBJ))==DREFOBJ&&!p->z.am){
+    p->z.flags&=~DREFOBJ;
+    load_reg(f,t2,&p->z,POINTER);
+    p->z.reg=t2;
+    p->z.flags|=(REG|DREFOBJ);
+  }
+  if(isreg(z)){
+    if(p->z.reg!=zreg)
+      emit(f,"\tmov.%s\t%s,%s\n",dt(ztyp(p)),regnames[p->z.reg],regnames[zreg]);
+  }else{
+    store_reg(f,zreg,&p->z,ztyp(p));
+  }
+}
+
+/* prints an object */
+static void emit_obj(FILE *f,struct obj *p,int t)
+{
+  if(p->am){
+    if(p->am->flags&GPR_IND) emit(f,"(%s,%s)",regnames[p->am->offset],regnames[p->am->base]);
+    if(p->am->flags&IMM_IND) emit(f,"(%ld,%s)",p->am->offset,regnames[p->am->base]);
+    return;
+  }
+  if((p->flags&(KONST|DREFOBJ))==(KONST|DREFOBJ)){
+    emitval(f,&p->val,p->dtyp&NU);
+    return;
+  }
+  if(p->flags&DREFOBJ) emit(f,"(");
+  if(p->flags&REG){
+    emit(f,"%s",regnames[p->reg]);
+  }else if(p->flags&VAR) {
+    if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER)
+      emit(f,"%ld(%s)",real_offset(p),regnames[sp]);
+    else{
+      if(!zmeqto(l2zm(0L),p->val.vmax)){emitval(f,&p->val,LONG);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(p->flags&KONST){
+    emitval(f,&p->val,t&NU);
+  }
+  if(p->flags&DREFOBJ) emit(f,")");
+}
+
+/*  Test if there is a sequence of FREEREGs containing FREEREG reg.
+ Used by peephole. */
+static int exists_freereg(struct IC *p,int reg)
+{
+  while(p&&(p->code==FREEREG||p->code==ALLOCREG)){
+    if(p->code==FREEREG&&p->q1.reg==reg) return 1;
+    p=p->next;
+  }
+  return 0;
+}
+
+/* generates the function entry code */
+static void function_top(FILE *f,struct Var *v,long offset)
+{
+  rsavesize=0;
+  if(!special_section(f,v)&&section!=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));
+  if(offset)
+    emit(f,"\tsub.i\tgpr0,%ld\n", offset);
+}
+/* generates the function exit code */
+static void function_bottom(FILE *f,struct Var *v,long offset)
+{
+  if(offset)
+    emit(f,"\tadd.i\tgpr0,%ld\n", offset);
+  emit(f,ret);
+}
+
+/****************************************/
+/*  End of private data and functions.  */
+/****************************************/
+
+/*  Does necessary initializations for the code-generator. Gets called  */
+/*  once at the beginning and should return 0 in case of problems.      */
+int init_cg(void)
+{
+  int i;
+  /*  Initialize some values which cannot be statically initialized   */
+  /*  because they are stored in the target's arithmetic.             */
+  maxalign=l2zm(8L);
+  char_bit=l2zm(8L);
+  
+  for(i=0;i<=MAX_TYPE;i++){
+    sizetab[i]=l2zm(msizetab[i]);
+    align[i]=l2zm(malign[i]);
+  }
+  
+  regnames[0]="noreg";
+  for(i=FIRST_GPR;i<=LAST_GPR;i++){
+    regnames[i]=mymalloc(10);
+    sprintf(regnames[i],"gpr%d",i-FIRST_GPR);
+    regsize[i]=l2zm(4L);
+    regtype[i]=&ltyp;
+  }
+  for(i=FIRST_FPR;i<=LAST_FPR;i++){
+    regnames[i]=mymalloc(10);
+    sprintf(regnames[i],"fpr%d",i-FIRST_FPR);
+    regsize[i]=l2zm(8L);
+    regtype[i]=&ldbl;
+  }
+  for(i=FIRST_CCR;i<=LAST_CCR;i++){
+    regnames[i]=mymalloc(10);
+    sprintf(regnames[i],"ccr%d",i-FIRST_CCR);
+    regsize[i]=l2zm(1L);
+    regtype[i]=&lchar;
+  }
+  
+  /*  Use multiple ccs.   */
+  multiple_ccs=0;
+  
+  /*  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.          */
+  t_min[CHAR]=l2zm(-128L);
+  t_min[SHORT]=l2zm(-32768L);
+  t_min[INT]=zmsub(l2zm(-2147483647L),l2zm(1L));
+  t_min[LONG]=t_min(INT);
+  t_min[LLONG]=zmlshift(l2zm(1L),l2zm(31L));
+  t_min[MAXINT]=t_min(LLONG);
+  t_max[CHAR]=ul2zum(127L);
+  t_max[SHORT]=ul2zum(32767UL);
+  t_max[INT]=ul2zum(2147483647UL);
+  t_max[LONG]=t_max(INT);
+  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]=ul2zum(4294967295UL);
+  tu_max[LONG]=t_max(UNSIGNED|INT);
+  tu_max[LLONG]=zumkompl(ul2zum(0UL));
+  tu_max[MAXINT]=t_max(UNSIGNED|LLONG);
+  
+  /*  Reserve a few registers for use by the code-generator.      */
+  /*  This is not optimal but simple.                             */
+  sp=FIRST_GPR;
+  t1=FIRST_GPR+1;
+  t2=FIRST_GPR+2;
+  f1=FIRST_FPR;
+  f2=FIRST_FPR+1;
+  regsa[t1]=regsa[t2]=1;
+  regsa[f1]=regsa[f2]=1;
+  regsa[sp]=1;
+  regscratch[t1]=regscratch[t2]=0;
+  regscratch[f1]=regscratch[f2]=0;
+  regscratch[sp]=0;
+  
+  for(i=FIRST_GPR;i<=LAST_GPR-VOL_GPRS;i++)
+    regscratch[i]=1;
+  for(i=FIRST_FPR;i<=LAST_FPR-VOL_FPRS;i++)
+    regscratch[i]=1;
+  for(i=FIRST_CCR;i<=LAST_CCR-VOL_CCRS;i++)
+    regscratch[i]=1;
+  
+  target_macros=marray;
+  
+  
+  return 1;
+}
+
+void init_db(FILE *f)
+{
+}
+
+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.        */
+/*  A pointer MUST be returned in a register. The code-generator    */
+/*  has to simulate a pseudo register if necessary.                 */
+{
+  if(ISFLOAT(t->flags)) 
+    return FIRST_FPR+2;
+  if(ISSTRUCT(t->flags)||ISUNION(t->flags)) 
+    return 0;
+  if(zmleq(szof(t),l2zm(4L))) 
+    return FIRST_GPR+3;
+  else
+    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.                                            */
+{
+  return 0;
+}
+
+/* estimate the cost-saving if object o from IC p is placed in
+ register r */
+int cost_savings(struct IC *p,int r,struct obj *o)
+{
+  int c=p->code;
+  if(o->flags&VKONST){
+    if(!LOAD_STORE)
+      return 0;
+    if(o==&p->q1&&p->code==ASSIGN&&(p->z.flags&DREFOBJ))
+      return 4;
+    else
+      return 2;
+  }
+  if(o->flags&DREFOBJ)
+    return 4;
+  if(c==SETRETURN&&r==p->z.reg&&!(o->flags&DREFOBJ)) return 3;
+  if(c==GETRETURN&&r==p->q1.reg&&!(o->flags&DREFOBJ)) return 3;
+  return 2;
+}
+
+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(r==0)
+    return 0;
+  t&=NQ;
+  if(t==0&&r>=FIRST_CCR&&r<=LAST_CCR)
+    return 1;
+  if(ISFLOAT(t)&&r>=FIRST_FPR&&r<=LAST_FPR)
+    return 1;
+  if(t==POINTER&&r>=FIRST_GPR&&r<=LAST_GPR)
+    return 1;
+  if(t>=CHAR&&t<=LONG&&r>=FIRST_GPR&&r<=LAST_GPR)
+    return 1;
+  return 0;
+}
+
+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;
+}
+
+int must_convert(int o,int t,int const_expr)
+/*  Returns zero if code for converting np to type t    */
+/*  can be omitted.                                     */
+/*  On the PowerPC cpu pointers and 32bit               */
+/*  integers have the same representation and can use   */
+/*  the same registers.                                 */
+{
+  int op=o&NQ,tp=t&NQ;
+  if((op==INT||op==LONG||op==POINTER)&&(tp==INT||tp==LONG||tp==POINTER))
+    return 0;
+  if(op==DOUBLE&&tp==LDOUBLE) return 0;
+  if(op==LDOUBLE&&tp==DOUBLE) 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&&section!=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.              */
+{
+  if(zm2l(align)>1) emit(f,"\t.align\t2\n");
+}
+
+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;char *sec;
+  if(v->clist) constflag=is_const(v->vtyp);
+  if(v->storage_class==STATIC){
+    if(ISFUNC(v->vtyp->flags)) return;
+    if(!special_section(f,v)){
+      if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&&section!=DATA){emit(f,dataname);if(f) section=DATA;}
+      if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&&section!=RODATA){emit(f,rodataname);if(f) section=RODATA;}
+      if(!v->clist&&section!=BSS){emit(f,bssname);if(f) section=BSS;}
+    }
+    if(v->clist||section==SPECIAL){
+      gen_align(f,falign(v->vtyp));
+      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){
+    emit(f,"\t.globl\t%s%s\n",idprefix,v->identifier);
+    if(v->flags&(DEFINED|TENTATIVE)){
+      if(!special_section(f,v)){
+        if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&&section!=DATA){emit(f,dataname);if(f) section=DATA;}
+        if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&&section!=RODATA){emit(f,rodataname);if(f) section=RODATA;}
+        if(!v->clist&&section!=BSS){emit(f,bssname);if(f) section=BSS;}
+      }
+      if(v->clist||section==SPECIAL){
+        gen_align(f,falign(v->vtyp));
+        emit(f,"%s%s:\n",idprefix,v->identifier);
+      }else
+        emit(f,"\t.global\t%s%s\n\t.%scomm\t%s%s,",idprefix,v->identifier,(USE_COMMONS?"":"l"),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,"\tdc.%s\t",dt(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[0],ip[1],ip[2],ip[3]);
+      if((t&NQ)!=FLOAT){
+        emit(f,",0x%02x%02x%02x%02x",ip[4],ip[5],ip[6],ip[7]);
+      }
+    }else{
+      emitval(f,&p->val,t&NU);
+    }
+  }else{
+    emit_obj(f,&p->tree->o,t&NU);
+  }
+  emit(f,"\n");newobj=0;
+}
+
+
+/*  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 *p,struct Var *v,zmax offset)
+/*  The main code-generation.                                           */
+{
+  int c,t,i;
+  struct IC *m;
+  argsize=0;
+  if(DEBUG&1) printf("gen_code()\n");
+  for(c=1;c<=MAXR;c++) regs[c]=regsa[c];
+  maxpushed=0;
+  
+  /*FIXME*/
+  ret="\trts\n";
+  
+  for(m=p;m;m=m->next){
+    c=m->code;t=m->typf&NU;
+    if(c==ALLOCREG) {regs[m->q1.reg]=1;continue;}
+    if(c==FREEREG) {regs[m->q1.reg]=0;continue;}
+    
+    /* convert MULT/DIV/MOD with powers of two */
+    if((t&NQ)<=LONG&&(m->q2.flags&(KONST|DREFOBJ))==KONST&&(t&NQ)<=LONG&&(c==MULT||((c==DIV||c==MOD)&&(t&UNSIGNED)))){
+      eval_const(&m->q2.val,t);
+      i=pof2(vmax);
+      if(i){
+        if(c==MOD){
+          vmax=zmsub(vmax,l2zm(1L));
+          m->code=AND;
+        }else{
+          vmax=l2zm(i-1);
+          if(c==DIV) m->code=RSHIFT; else m->code=LSHIFT;
+        }
+        c=m->code;
+        gval.vmax=vmax;
+        eval_const(&gval,MAXINT);
+        if(c==AND){
+          insert_const(&m->q2.val,t);
+        }else{
+          insert_const(&m->q2.val,INT);
+          p->typf2=INT;
+        }
+      }
+    }
+#if FIXED_SP
+    if(c==CALL&&argsize<zm2l(m->q2.val.vmax)) argsize=zm2l(m->q2.val.vmax);
+#endif
+  }
+  
+  for(c=1;c<=MAXR;c++){
+    if(regsa[c]||regused[c]){
+      BSET(regs_modified,c);
+    }
+  }
+  
+  localsize=(zm2l(offset)+3)/4*4;
+#if FIXED_SP
+  /*FIXME: adjust localsize to get an aligned stack-frame */
+#endif
+  
+  function_top(f,v,localsize);
+
+#if FIXED_SP
+  pushed=0;
+#endif
+  
+  for(;p;p=p->next){
+    c=p->code;t=p->typf;
+    if(c==NOP) {p->z.flags=0;continue;}
+    if(c==ALLOCREG) {regs[p->q1.reg]=1;continue;}
+    if(c==FREEREG) {regs[p->q1.reg]=0;continue;}
+    if(c==LABEL) {emit(f,"%s%d:\n",labprefix,t);continue;}
+    if(c==BRA){
+      if(t==exit_label)
+        emit(f,ret);
+      else
+        emit(f,"\tb\t%s%d\n",labprefix,t);
+      continue;
+    }
+    if(c>=BEQ&&c<BRA){
+      emit(f,"\tb%s\t",ccs[c-BEQ]);
+      if(isreg(q1)){
+        emit_obj(f,&p->q1,0);
+        emit(f,",");
+      }
+      emit(f,"%s%d\n",labprefix,t);
+      continue;
+    }
+    if(c==MOVETOREG){
+      load_reg(f,p->z.reg,&p->q1,regtype[p->z.reg]->flags);
+      continue;
+    }
+    if(c==MOVEFROMREG){
+      store_reg(f,p->z.reg,&p->q1,regtype[p->z.reg]->flags);
+      continue;
+    }
+    if((c==ASSIGN||c==PUSH)&&((t&NQ)>POINTER||((t&NQ)==CHAR&&zm2l(p->q2.val.vmax)!=1))){
+      ierror(0);
+    }
+    p=preload(f,p);
+    c=p->code;
+    if(c==SUBPFP) c=SUB;
+    if(c==ADDI2P) c=ADD;
+    if(c==SUBIFP) c=SUB;
+    if(c==CONVERT){
+      if(ISFLOAT(q1typ(p))||ISFLOAT(ztyp(p))) ierror(0);
+      if(sizetab[q1typ(p)&NQ]<sizetab[ztyp(p)&NQ]){
+        if(q1typ(p)&UNSIGNED)
+          emit(f,"\tzext.%s\t%s\n",dt(q1typ(p)),regnames[zreg]);
+        else
+          emit(f,"\tsext.%s\t%s\n",dt(q1typ(p)),regnames[zreg]);
+      }
+      save_result(f,p);
+      continue;
+    }
+    if(c==KOMPLEMENT){
+      load_reg(f,zreg,&p->q1,t);
+      emit(f,"\tcpl.%s\t%s\n",dt(t),regnames[zreg]);
+      save_result(f,p);
+      continue;
+    }
+    if(c==SETRETURN){
+      load_reg(f,p->z.reg,&p->q1,t);
+      BSET(regs_modified,p->z.reg);
+      continue;
+    }
+    if(c==GETRETURN){
+      if(p->q1.reg){
+        zreg=p->q1.reg;
+        save_result(f,p);
+      }else
+        p->z.flags=0;
+      continue;
+    }
+    if(c==CALL){
+      int reg;
+      /*FIXME*/
+#if 0      
+      if(stack_valid&&(p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&(p->q1.v->fi->flags&ALL_STACK)){
+        if(framesize+zum2ul(p->q1.v->fi->stack1)>stack)
+          stack=framesize+zum2ul(p->q1.v->fi->stack1);
+      }else
+        stack_valid=0;
+#endif
+      if((p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&p->q1.v->fi->inline_asm){
+        emit_inline_asm(f,p->q1.v->fi->inline_asm);
+      }else{
+        emit(f,"\tcall\t");
+        emit_obj(f,&p->q1,t);
+        emit(f,"\n");
+      }
+      /*FIXME*/
+#if FIXED_SP
+      pushed-=zm2l(p->q2.val.vmax);
+#endif
+      if((p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&(p->q1.v->fi->flags&ALL_REGS)){
+        bvunite(regs_modified,p->q1.v->fi->regs_modified,RSIZE);
+      }else{
+        int i;
+        for(i=1;i<=MAXR;i++){
+          if(regscratch[i]) BSET(regs_modified,i);
+        }
+      }
+      continue;
+    }
+    if(c==ASSIGN||c==PUSH){
+      if(t==0) ierror(0);
+      if(c==PUSH){
+#if FIXED_SP
+        emit(f,"\tmov.%s\t%ld(%s),",dt(t),pushed,regnames[sp]);
+        emit_obj(f,&p->q1,t);
+        emit(f,"\n");
+        pushed+=zm2l(p->q2.val.vmax);
+#else
+        emit(f,"\tpush.%s\t",dt(t));
+        emit_obj(f,&p->q1,t);
+        emit(f,"\n");
+        /*pushed += zm2l(p->q2.val.vmax);*/
+#endif
+        continue;
+      }
+      if(c==ASSIGN){
+        load_reg(f,zreg,&p->q1,t);
+        save_result(f,p);
+      }
+      continue;
+    }
+    if(c==ADDRESS){
+      load_address(f,zreg,&p->q1,POINTER);
+      save_result(f,p);
+      continue;
+    }
+    if(c==MINUS){
+      load_reg(f,zreg,&p->q1,t);
+      emit(f,"\tneg.%s\t%s\n",dt(t),regnames[zreg]);
+      save_result(f,p);
+      continue;
+    }
+    if(c==TEST){
+      emit(f,"\ttst.%s\t",dt(t));
+      if(multiple_ccs)
+        emit(f,"%s,",regnames[zreg]);
+      emit_obj(f,&p->q1,t);
+      emit(f,"\n");
+      if(multiple_ccs)
+        save_result(f,p);
+      continue;
+    }
+    if(c==COMPARE){
+      emit(f,"\tcmp.%s\t",dt(t));
+      if(multiple_ccs)
+        emit(f,"%s,",regnames[zreg]);
+      emit_obj(f,&p->q1,t);
+      emit(f,",");
+      emit_obj(f,&p->q2,t);
+      emit(f,"\n");
+      if(multiple_ccs)
+        save_result(f,p);
+      continue;
+    }
+    if((c>=OR&&c<=AND)||(c>=LSHIFT&&c<=MOD)){
+      if(!THREE_ADDR)
+        load_reg(f,zreg,&p->q1,t);
+      if(c>=OR&&c<=AND)
+        emit(f,"\t%s.%s\t%s,",logicals[c-OR],dt(t),regnames[zreg]);
+      else
+        emit(f,"\t%s.%s\t%s,",arithmetics[c-LSHIFT],dt(t),regnames[zreg]);
+      if(THREE_ADDR){
+        emit_obj(f,&p->q1,t);
+        emit(f,",");
+      }
+      emit_obj(f,&p->q2,t);
+      emit(f,"\n");
+      save_result(f,p);
+      continue;
+    }
+    pric2(stdout,p);
+    ierror(0);
+  }
+  function_bottom(f,v,localsize);
+  if(stack_valid){
+    if(!v->fi) v->fi=new_fi();
+    v->fi->flags|=ALL_STACK;
+    v->fi->stack1=stack;
+  }
+  emit(f,"# stacksize=%lu%s\n",zum2ul(stack),stack_valid?"":"+??");
+}
+
+int shortcut(int c, int typ)
+{
+  if(c==COMPARE||c==ADD||c==SUB||c==AND||c==OR||c==XOR) return 1;
+  return 0;
+}
+
+int reg_parm(struct reg_handle *m, struct Typ *t,int vararg,struct Typ *d)
+{
+  int f;
+  f=t->flags&NQ;
+  if(f<=LONG||f==POINTER){
+    if(m->gregs>=GPR_ARGS)
+      return 0;
+    else
+      return FIRST_GPR+3+m->gregs++;
+  }
+  if(ISFLOAT(f)){
+    if(m->fregs>=FPR_ARGS)
+      return 0;
+    else
+      return FIRST_FPR+2+m->fregs++;
+  }
+  return 0;
+}
+
+int handle_pragma(const char *s)
+{
+}
+void cleanup_cg(FILE *f)
+{
+}
+void cleanup_db(FILE *f)
+{
+  if(f) section=-1;
+}
+
diff --git a/machines/minx/machine.dt b/machines/minx/machine.dt
new file mode 100755
index 0000000..736fdec
--- /dev/null
+++ b/machines/minx/machine.dt
@@ -0,0 +1,14 @@
+S8BS
+S8BU
+S8BS
+S8BU
+S16BSLE
+S16BULE
+S32BSLE
+S32BULE
+S32BSLE
+S32BULE
+S32BIEEELE
+S64BIEEELE
+S64BIEEELE
+S32BULE
diff --git a/machines/minx/machine.h b/machines/minx/machine.h
new file mode 100755
index 0000000..25626fa
--- /dev/null
+++ b/machines/minx/machine.h
@@ -0,0 +1,136 @@
+/*  Example backend for vbcc, it models a generic 32bit RISC or CISC
+    CPU.
+
+    Configurable at build-time are:
+    - number of (32bit) general-purpose-registers
+    - number of (64bit) floating-point-registers
+    - number of (8bit) condition-code-registers
+    - mechanism for stack-arguments (moving ot fixed sp)
+
+    It allows to select as run-time-options:
+    - two- or three-address code
+    - memory operands or load-store-architecture
+    - number of register-arguments
+    - number of caller-save-registers
+*/
+
+/* buil-time configurable options: */
+#define NUM_GPRS 4
+#define NUM_FPRS 1
+#define NUM_CCRS 1
+#define FIXED_SP 1
+
+#include "dt.h"
+
+/* internally used by the backend */
+#define FIRST_GPR 1
+#define LAST_GPR (FIRST_GPR+NUM_GPRS-1)
+#define FIRST_FPR (LAST_GPR+1)
+#define LAST_FPR (FIRST_FPR+NUM_FPRS-1)
+#define FIRST_CCR (LAST_FPR+1)
+#define LAST_CCR (FIRST_CCR+NUM_CCRS-1)
+
+/*  This struct can be used to implement machine-specific           */
+/*  addressing-modes.                                               */
+/*  Currently possible are (const,gpr) and (gpr,gpr)                */
+struct AddressingMode{
+    int flags;
+    int base;
+    long offset;
+};
+
+/*  The number of registers of the target machine.                  */
+#define MAXR NUM_GPRS+NUM_FPRS+NUM_CCRS
+
+/*  Number of commandline-options the code-generator accepts.       */
+#define MAXGF 20
+
+/*  If this is set to zero vbcc will not generate ICs where the     */
+/*  target operand is the same as the 2nd source operand.           */
+/*  This can sometimes simplify the code-generator, but usually     */
+/*  the code is better if the code-generator allows it.             */
+#define USEQ2ASZ 1
+
+/*  This specifies the smallest integer type that can be added to a */
+/*  pointer.                                                        */
+#define MINADDI2P INT
+
+/*  If the bytes of an integer are ordered most significant byte    */
+/*  byte first and then decreasing set BIGENDIAN to 1.              */
+#define BIGENDIAN 0
+
+/*  If the bytes of an integer are ordered lest significant byte    */
+/*  byte first and then increasing set LITTLEENDIAN to 1.           */
+#define LITTLEENDIAN 1
+
+/*  Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive.    */
+
+/*  If switch-statements should be generated as a sequence of       */
+/*  SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1.      */
+/*  This can yield better code on some machines.                    */
+#define SWITCHSUBS 0
+
+/*  In optimizing compilation certain library memcpy/strcpy-calls   */
+/*  with length known at compile-time will be inlined using an      */
+/*  ASSIGN-IC if the size is less or equal to INLINEMEMCPY.         */
+/*  The type used for the ASSIGN-IC will be UNSIGNED|CHAR.          */
+#define INLINEMEMCPY 1024
+
+/*  Parameters are sometimes passed in registers without __reg.     */
+#define HAVE_REGPARMS 1
+
+/*  Parameters on the stack should be pushed in order rather than   */
+/*  in reverse order.                                               */
+#define ORDERED_PUSH FIXED_SP
+
+/*  Structure for reg_parm().                                       */
+struct reg_handle{
+    unsigned long gregs;
+    unsigned long fregs;
+};
+
+/*  We have some target-specific variable attributes.               */
+#define HAVE_TARGET_ATTRIBUTES
+
+/* We have target-specific pragmas */
+#define HAVE_TARGET_PRAGMAS
+
+/*  We keep track of all registers modified by a function.          */
+#define HAVE_REGS_MODIFIED 1
+
+/* We have a implement our own cost-functions to adapt 
+   register-allocation */
+#define HAVE_TARGET_RALLOC 1
+#define cost_move_reg(x,y) 1
+#define cost_load_reg(x,y) 2
+#define cost_save_reg(x,y) 2
+#define cost_pushpop_reg(x) 3
+
+/* size of buffer for asm-output, this can be used to do
+   peephole-optimizations of the generated assembly-output */
+#define EMIT_BUF_LEN 1024 /* should be enough */
+/* number of asm-output lines buffered */
+#define EMIT_BUF_DEPTH 4
+
+/*  We have no asm_peephole to optimize assembly-output */
+#define HAVE_TARGET_PEEPHOLE 0
+
+/* we do not have a mark_eff_ics function, this is used to prevent
+   optimizations on code which can already be implemented by efficient
+   assembly */
+#undef HAVE_TARGET_EFF_IC
+
+/* we only need the standard data types (no bit-types, different pointers
+   etc.) */
+#undef HAVE_EXT_TYPES
+#undef HAVE_TGT_PRINTVAL
+
+/* we do not need extra elements in the IC */
+#undef HAVE_EXT_IC
+
+/* we do not use unsigned int as size_t (but unsigned long, the default) */
+#undef HAVE_INT_SIZET
+
+/* we do not need register-pairs */
+#undef HAVE_REGPAIRS
+
diff --git a/machines/pm/emit.h b/machines/pm/emit.h
new file mode 100755
index 0000000..aa11b2e
--- /dev/null
+++ b/machines/pm/emit.h
@@ -0,0 +1,7 @@
+
+/* automaticaly generated by process_all.h; do not edit it */
+
+#include "emit_mult.h"
+#include "emit_div_mod.h"
+#include "emit_start.h"
+#include "emit_end.h"
diff --git a/machines/pm/emit_div_mod.h b/machines/pm/emit_div_mod.h
new file mode 100755
index 0000000..c9c6129
--- /dev/null
+++ b/machines/pm/emit_div_mod.h
@@ -0,0 +1,69 @@
+
+/* automaticaly generated from the file div_mod.asm do not modify */
+
+static void emit_div_mod(FILE *f)
+{
+	emit(f,"vbcc___div_mod16x16_16:\n");
+	emit(f,"\tpush\tx\n");
+	emit(f,"\tpush\ty\n");
+	emit(f,"\tmov\tx, 0\n");
+	emit(f,"\tcmp\tba, 0\n");
+	emit(f,"\tjns\tvbcc___dm_banotneg\n");
+	emit(f,"\tnot\ta\n");
+	emit(f,"\tnot\tb\n");
+	emit(f,"\tinc\tba\n");
+	emit(f,"\tadd\tx, 0x0011\n");
+	emit(f,"vbcc___dm_banotneg:\n");
+	emit(f,"\txchg\tba, hl\n");
+	emit(f,"\tcmp\tba, 0\n");
+	emit(f,"\tjns\tvbcc___dm_hlnotneg\n");
+	emit(f,"\tnot\ta\n");
+	emit(f,"\tnot\tb\n");
+	emit(f,"\tinc\tba\n");
+	emit(f,"\tinc\tx\n");
+	emit(f,"vbcc___dm_hlnotneg:\n");
+	emit(f,"\txchg\tba, hl\n");
+	emit(f,"\tpush\tx\n");
+	emit(f,"\tmov\tx, 0\n");
+	emit(f,"\tmov\ty, 1\n");
+	emit(f,"vbcc___dm_shiftloop:\n");
+	emit(f,"\tshl\ta\n");
+	emit(f,"\trolc\tb\n");
+	emit(f,"\txchg\tba, x\n");
+	emit(f,"\trolc\ta\n");
+	emit(f,"\trolc\tb\n");
+	emit(f,"\txchg\tba, x\n");
+	emit(f,"\tsub\tx, hl\n");
+	emit(f,"\tjns\tvbcc___dm_resnotneg\n");
+	emit(f,"\tadd\tx, hl\n");
+	emit(f,"vbcc___dm_resnotneg:\n");
+	emit(f,"\txchg\tba, y\n");
+	emit(f,"\trolc\ta\n");
+	emit(f,"\trolc\tb\n");
+	emit(f,"\txchg\tba, y\n");
+	emit(f,"\tjc\tvbcc___dm_done\n");
+	emit(f,"\tjmp\tvbcc___dm_shiftloop\n");
+	emit(f,"vbcc___dm_done:\n");
+	emit(f,"\tpop\tba\n");
+	emit(f,"\ttst\ta, 0x10\n");
+	emit(f,"\txchg\tba, x\n");
+	emit(f,"\tjz\tvbcc___dm_modnotneg\n");
+	emit(f,"\tnot\ta\n");
+	emit(f,"\tnot\tb\n");
+	emit(f,"\tinc\tba\n");
+	emit(f,"vbcc___dm_modnotneg:\n");
+	emit(f,"\tmov\thl, ba\n");
+	emit(f,"\tmov\tba, x\n");
+	emit(f,"\ttst\ta, 0x01\n");
+	emit(f,"\tmov\tba, y\n");
+	emit(f,"\tjz\tvbcc___dm_resnonegate\n");
+	emit(f,"\tinc\tba\n");
+	emit(f,"\tjmp\tvbcc___dm_resnegate\n");
+	emit(f,"vbcc___dm_resnonegate:\n");
+	emit(f,"\tnot\tb\n");
+	emit(f,"\tnot\ta\n");
+	emit(f,"vbcc___dm_resnegate:\n");
+	emit(f,"\tpop\ty\n");
+	emit(f,"\tpop\tx\n");
+	emit(f,"\tret\n");
+}
diff --git a/machines/pm/emit_end.h b/machines/pm/emit_end.h
new file mode 100755
index 0000000..2a77b2e
--- /dev/null
+++ b/machines/pm/emit_end.h
@@ -0,0 +1,20 @@
+
+/* automaticaly generated from the file end.asm do not modify */
+
+static void emit_end(FILE *f)
+{
+	if(!used_interrupt[15]) {
+	emit(f, "%s15:\n", int_handler_prefix);
+	used_interrupt[15] = (1);
+	}
+	emit(f,"\tmovb\t[nn+0x29], (1<<7)\n");
+	emit(f,"\ttest\t[nn+0x52], (1<<7)\n");
+	emit(f,"\tjnz\tvbcc___noturnoff\n");
+	emit(f,"\tcint\t0x24\n");
+	emit(f,"vbcc___noturnoff:\n");
+	emit(f,"\treti\n");
+	emit_unised_irq_labels(f);
+	emit(f,"\treti\n");
+	emit_mult(f);
+	emit_div_mod(f);
+}
diff --git a/machines/pm/emit_mult.h b/machines/pm/emit_mult.h
new file mode 100755
index 0000000..35012be
--- /dev/null
+++ b/machines/pm/emit_mult.h
@@ -0,0 +1,23 @@
+
+/* automaticaly generated from the file mult.asm do not modify */
+
+static void emit_mult(FILE *f)
+{
+	emit(f,"vbcc___mul16x16_16:\n");
+	emit(f,"\tpush\thl\n");
+	emit(f,"\tmul\tl, a\n");
+	emit(f,"\tpush\thl\n");
+	emit(f,"\tmov\thl,[sp+3]\n");
+	emit(f,"\tmul\tl, a\n");
+	emit(f,"\tmov\ta, b\n");
+	emit(f,"\tmov\tb, l\n");
+	emit(f,"\tmov\thl, [sp+2]\n");
+	emit(f,"\tmul\tl, a\n");
+	emit(f,"\tmov\ta, l\n");
+	emit(f,"\tadd\ta, b\n");
+	emit(f,"\tmov\tb, a\n");
+	emit(f,"\txor\ta, a\n");
+	emit(f,"\tpop\thl\n");
+	emit(f,"\tadd\tba, hl\n");
+	emit(f,"\tpop\thl\n");
+	emit(f,"\tret\n");}
diff --git a/machines/pm/emit_start.h b/machines/pm/emit_start.h
new file mode 100755
index 0000000..6d7d79e
--- /dev/null
+++ b/machines/pm/emit_start.h
@@ -0,0 +1,44 @@
+
+/* automaticaly generated from the file start.asm do not modify */
+
+static void emit_start(FILE *f)
+{
+	emit(f,".org 0x2100\n");
+	emit(f,".db \"MN\"\n");
+	emit_irq_vectors(f);
+	emit(f,".orgfill 0x21A4\n");
+	emit(f,".db \"NINTENDO\"\n");
+	emit(f,".db \"%s\"\n", game_id);
+	emit(f,".db \"%s\"\n", game_name);
+	emit(f,".orgfill 0x21BC\n");
+	emit(f,".db \"2P\"\n");
+	emit(f,".orgfill 0x21D0\n");
+	emit(f,"vbcc___start_rom_vars:\n");
+	emit(f,".org 0x1000\n");
+	emit(f,"vbcc___start_ram_vars:\n");
+	emit(f,".org 0x2000\n");
+	emit(f,"vbcc___end_ram_vars:\n");
+	emit(f,".org 0x31D0\n");
+	emit(f,".equ  vbcc___ram_vars_offset %d - 0x1000\n", start_ram_vars);
+	emit(f, "%s0:\n", int_handler_prefix);
+	emit(f,"\tmov\t\tx, vbcc___start_rom_vars + vbcc___ram_vars_offset\n");
+	emit(f,"\tmov\t\ty, vbcc___start_ram_vars + vbcc___ram_vars_offset\n");
+	emit(f,"\tmov\t\thl, vbcc___end_ram_vars\n");
+	emit(f,"vbcc__copy_vars_loop:\n");
+	emit(f,"\tmov\t\ta,[x]\n");
+	emit(f,"\tmov\t\t[y],a\n");
+	emit(f,"\tinc\t\tx\n");
+	emit(f,"\tinc\t\ty\n");
+	emit(f,"\tcmp\t\thl, y\n");
+	emit(f,"\tjnz\t\tvbcc__copy_vars_loop\n");
+	emit(f,"\tmovw\tsp, 0x2000\n");
+	emit(f,"\tmovw\tnn, 0x2000\n");
+	emit(f,"\tmovb\t[nn+0x21], 0x0C\n");
+	emit(f,"\tmovb\t[nn+0x25], (1<<7)\n");
+	emit(f,"\tmovb\tflags, 0\n");
+	emit(f,"\tmovb\t[nn+0x80], 0b00001000\n");
+	emit(f,"\tmovb\t[nn+0x81], 0b00001001\n");
+	emit(f,"\tcall\tmain\n");
+	emit(f,"vbcc___infinite_loop:\n");
+	emit(f,"\tjmp\tvbcc___infinite_loop\n");
+}
diff --git a/machines/pm/machine.c b/machines/pm/machine.c
new file mode 100755
index 0000000..81ca077
--- /dev/null
+++ b/machines/pm/machine.c
@@ -0,0 +1,1412 @@
+
+#include "supp.h"
+
+
+static debug_prints = 0;
+
+static char FILE_[]=__FILE__;
+
+/* Name and copyright. */
+char cg_copyright[]="vbcc code-generator for Pokemon Mini V0.019 (c) in 2011 by zoranc";
+
+
+/*  Commandline-flags the code-generator accepts:
+    0: just a flag
+    VALFLAG: a value must be specified
+    STRINGFLAG: a string can be specified
+    FUNCFLAG: a function will be called
+    apart from FUNCFLAG, all other versions can only be specified once */
+int g_flags[MAXGF]= { FUNCFLAG, STRINGFLAG, STRINGFLAG, STRINGFLAG };
+
+/* the flag-name, do not use names beginning with l, L, I, D or U, because
+   they collide with the frontend */
+char *g_flags_name[MAXGF] = { "h", "ram-vars", "id", "name" };
+
+/* the results of parsing the command-line-flags will be stored here */
+union ppi g_flags_val[MAXGF];
+
+#define HELP_DUMP      (g_flags[0]&USEDFLAG)
+#define RAM_VARS_ADDR  ((g_flags[1]&USEDFLAG)?address_number(g_flags_val[1].p):0x14E0)
+#define GAME_ID        ((g_flags[2]&USEDFLAG)?g_flags_val[2].p:"PKCC")
+#define GAME_NAME      ((g_flags[3]&USEDFLAG)?g_flags_val[3].p:"PokeCCbyZC")
+
+
+
+/*  Alignment-requirements for all types in bytes.              */
+zmax align[MAX_TYPE+1];
+
+/*  Alignment that is sufficient for every object.              */
+zmax maxalign;
+
+/*  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];
+
+/*  CHAR_BIT of the target machine.                             */
+zmax char_bit;
+
+/*  Names of all registers.                                     */
+char *regnames[]={"noreg","x","y", "ba", "hl"};
+char *regnames_low[]={"noreg","noreg","noreg", "a", "l"};
+char *regnames_high[]={"noreg","noreg","noreg", "b", "h"};
+
+/*  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};
+
+
+/****************************************/
+/*  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};
+static long msizetab[MAX_TYPE+1]={0,1,1,2,4,4,4,8,8,0,2,0,0,0,2,0};
+
+struct Typ ityp={SHORT},ltyp={LONG};
+
+static int ix = 1,iy = 2;
+static int q1reg,q2reg,zreg;
+static int ba = 3,hl = 4;               /*  temporary gprs */
+
+
+/* return-instruction */
+static char *ret;
+
+static char *marray[]={"__POKEMINI__",0};
+
+#define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
+#define isconst(x) ((p->x.flags&(KONST|DREFOBJ))==KONST)
+
+#define ISLWORD(t) ((t&NQ)==LONG||(t&NQ)==FLOAT)
+#define ISHWORD(t) ((t&NQ)==INT)
+
+
+/* assembly-prefixes for labels and external identifiers */
+static char *labprefix="vbcc___l",*idprefix="";
+
+/* has to be 4 bytes long */
+static char game_id[10] = "PKCC";
+/* can be up to 12 bytes long */
+static char game_name[20] = "PokeCCbyZC";
+
+static void emit_irq_vectors(FILE *f);
+static void emit_unised_irq_labels(FILE *f);
+static int used_interrupt[26];
+static char *int_handler_prefix="vbcc___interrupt_handler_";
+
+static int start_ram_vars = 0x14E0;
+static int ram_rom_distance = 0x11D0;
+static int end_ram_vars;
+static int last_was_rom = 1;
+static int ram_vars_initialized = 0;
+
+/* Names of target-specific variable attributes.                */
+char *g_attr_name[]={"__interrupt", "__rom", "__align8", "__align64", 0};
+#define INTERRUPT 1
+#define ROM 2
+#define ALIGN8 4
+#define ALIGN64 8
+
+#include "emit.h"
+
+
+#define dt(t) (((t)&UNSIGNED)?udt[(t)&NQ]:sdt[(t)&NQ])
+static char *sdt[MAX_TYPE+1]={"??","c","s","i","l","ll","f","d","ld","v","p"};
+static char *udt[MAX_TYPE+1]={"??","uc","us","ui","ul","ull","f","d","ld","v","p"};
+
+
+//static char *ccs[]={"eq","ne","lt","ge","le","gt",""};
+static char *ccs2[]={"nz","z","ge","l","g","le",""};
+//static char *uccs2[]={"nzb","zb","ge","l","g","le",""};
+static char *uccs2[]={"nz","z","nc","c","c","nc",""};
+//static char *uccs2[]={"nzb","zb","no","o","ns","s",""};
+static char *logicals[]={"or","xor","and"};
+static char *arithmetics[]={"slw","srw","add","sub","mullw","divw","mod"};
+
+static void emit_obj(FILE *f,struct obj *p,int t);
+
+static long localsize, rsavesize, /*argsize,*/ pushed;
+
+#define NOT_IMP() not_implemented((f),(__LINE__))
+void not_implemented(FILE *f, int line)
+{
+	emit(f, ";\tNOT IMPLEMENTED: %s LINE: %d !!!\n", __FILE__, line);
+}
+
+/* calculate the actual current offset of an object relativ to the
+ stack-pointer; we use a layout like this:
+ ------------------------------------------------
+ | arguments to this function                   |
+ ------------------------------------------------
+ | return-address [size=3]                      |
+ ------------------------------------------------
+ | caller-save registers [size=rsavesize]       |
+ ------------------------------------------------
+ | local variables [size=localsize]             |
+ ------------------------------------------------
+ | arguments to called functions [size=argsize] |
+ ------------------------------------------------
+ All sizes will be aligned as necessary.
+ In the case of FIXED_SP, the stack-pointer will be adjusted at
+ function-entry to leave enough space for the arguments and have it
+ aligned to 16 bytes. Therefore, when calling a function, the
+ stack-pointer is always aligned to 16 bytes.
+ For a moving stack-pointer, the stack-pointer will usually point
+ to the bottom of the area for local variables, but will move while
+ arguments are put on the stack.
+ 
+ This is just an example layout. Other layouts are also possible.
+ */
+
+static long real_offset(struct obj *o)
+{
+	long off=zm2l(o->v->offset);
+
+	if(off<0){
+		/* function parameter */
+		off=localsize+rsavesize+3-off-zm2l(maxalign);
+	}
+
+	off+=pushed;
+
+	off+=zm2l(o->val.vmax);
+
+	return off;
+}
+
+static void emit_irq_vectors(FILE *f)
+{
+	int i;
+	for(i=0; i<26; i++)
+	{
+		emit(f, ".orgfill 0x%x\n", 0x2102 + 6 * i);
+		emit(f, "\tjmp\t%s%d\n", int_handler_prefix, i);
+	}
+	
+	used_interrupt[0] = 1;
+}
+
+static void emit_unised_irq_labels(FILE *f)
+{
+	int i;
+	for(i=0; i<26; i++)
+	{
+		if(!used_interrupt[i])
+			emit(f, "%s%d:\n", int_handler_prefix, i);
+	}
+}
+
+char *flags_verbose(int flags, char *str)
+{
+	static char *flag_str[] = {"KONST", "VAR", "", "", "", "DREFOBJ", "REG", "VARADR"};
+	int i;
+	
+	strcpy(str, "");
+	
+	for(i=0; i<8; i++)
+	{
+		if(flags & (1 << i))
+		{
+			if(strlen(str)!=0 && strlen(flag_str[i])!=0)
+				strcat(str, "|");
+			strcat(str, flag_str[i]);
+		}
+	}
+	
+	return str;
+}
+
+/* generate code to load the address of a variable into register r */
+static void load_address(FILE *f,int r,struct obj *o,int type)
+/*  Generates code to load the address of a variable into register r.   */
+{
+  char str[100];
+  if(debug_prints)
+   	emit(f, ";\tload_address(reg:%s, flags:%s, type:%s)\n", regnames[r], flags_verbose(o->flags, str), typname[type&NQ]);
+  if(!(o->flags&VAR)) ierror(0);
+  if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER)
+  {
+    long off=real_offset(o);
+    emit(f,"\tmov\t%s,sp\n",regnames[r]);
+    if(off)
+      emit(f,"\tadd\t%s,%ld\n",regnames[r],off);
+  }
+  else
+  {
+    emit(f,"\tmov\t%s,",regnames[r]);
+    emit_obj(f,o,type);
+    emit(f,"\n");
+  }
+}
+/* Generates code to load a memory object into register r. tmp is a
+ general purpose register which may be used. tmp can be r. */
+static void load_reg(FILE *f, int r, struct obj *o, int type, int type2)
+{
+  char str[100];
+  if(debug_prints)
+    emit(f, ";\tload_reg(reg:%s, flags:%s, type:%s, type2:%s)\n", regnames[r], flags_verbose(o->flags, str), typname[type&NQ], (type2&NQ)?typname[type2&NQ]:"");
+  type&=NU;
+  if(o->flags&VARADR)
+  {
+    load_address(f,r,o,POINTER);
+  }
+  else
+  {
+    if((o->flags&(REG|DREFOBJ))==REG&&o->reg==r)
+      return;
+    if( msizetab[(type&NQ)] == 1 && 
+         !((o->flags==VAR) /*&& (o->v->storage_class==AUTO||o->v->storage_class==REGISTER)*/))
+    {
+    	/* TODO */
+    	/* optimise this like in the store_reg() */
+		int is_16_reg = ((o->flags&(REG|DREFOBJ)) == REG) && msizetab[type2&NQ] == 2;
+		if(r == ba || r == hl)
+    	{
+			/* handle case of transfer 16-bit reg -> 8-bit reg*/
+			emit(f,"\tmov\t%s,",is_16_reg?regnames[r]:regnames_low[r]);
+			emit_obj(f,o,type);
+			emit(f,"\n");
+		}
+		else if(r==ix && ((o->flags&(REG|DREFOBJ)) == REG))
+		{
+			if(!is_16_reg)
+				emit(f, "\tmov\t%s, 0\n", regnames_high[o->reg]); // or maybe expand sign?
+			emit(f, "\tmov\tx,");
+			emit_obj(f,o,type);
+			emit(f,"\n");
+		}
+		else
+			NOT_IMP();
+    }
+    else
+    {
+		if((o->flags==VAR) && type==ARRAY)
+		{
+			emit(f,"\tmov\t%s,",regnames[r]);
+			o->flags |= VARADR;
+			emit_obj(f,o,type);
+			o->flags &= ~VARADR;
+			emit(f,"\n");
+		}
+		else
+		{
+			emit(f,"\tmov\t%s,",regnames[r]);
+			emit_obj(f,o,type);
+			emit(f,"\n");
+		}
+    }
+  }
+}
+
+static int free_index_reg()
+{
+	if(!regs[ix]) return ix;
+	if(!regs[iy]) return iy;
+	return 0;
+}
+
+/*  Generates code to store register r into memory object o. */
+static void store_reg(FILE *f,int r,struct obj *o,int type)
+{
+	char str[100];
+    if(debug_prints)
+    	emit(f, ";\tstore_reg(reg:%s, flags:%s, type:%s)\n", regnames[r], flags_verbose(o->flags, str), typname[type&NQ]);
+	type&=NQ;
+   if( msizetab[(type&NQ)] == 1 )
+   {
+    	if(r == ba)
+    	{
+			if((o->flags==VAR) && (o->v->storage_class==AUTO||o->v->storage_class==REGISTER))
+			{
+				int ind_reg = free_index_reg();
+				long off = real_offset(o);
+				
+				if(off == 0)
+				{
+					emit(f, "\tinc\tsp\n");
+					emit(f, "\tpush\ta\n");
+				}
+				else if(ind_reg)
+				{
+					emit(f, "\tmov\t%s,sp\n", regnames[ind_reg]);
+					emit(f, "\tmov\t[%s+%ld],%s\n", regnames[ind_reg], off, regnames_low[r]);
+				}
+				else
+				{
+					emit(f,"\tmov\thl,sp\n");
+					emit(f,"\tadd\thl,%ld\n",off);
+					emit(f,"\tmov\t[hl],%s\n", regnames_low[r]);
+				}
+			}
+			else
+			{
+				emit(f,"\tmov\t");
+				emit_obj(f,o,type);
+				emit(f,",%s\n",regnames_low[r]);
+			}
+		}
+		else if(r==ix && (o->flags==VAR))
+		{
+			emit(f, "\tmov\thl,");
+			emit_obj(f,o,type);
+			emit(f, "\n");
+			emit(f, "\tmov\th, 0\n"); // maybe extend sign?
+			emit(f, "\tmov\tx,hl\n");
+		}
+		else
+			NOT_IMP();
+   }
+	else
+	{
+		emit(f,"\tmov\t");
+		emit_obj(f,o,type);
+		emit(f,",%s\n",regnames[r]);
+	}
+}
+
+
+/* Does some pre-processing like fetching operands from memory to
+ registers etc. */
+static struct IC *preload(FILE *f,struct IC *p)
+{
+  int r;
+
+  if(debug_prints)
+    emit(f, ";\tpreload() - start\n");
+  
+  if(isreg(q1))
+    q1reg=p->q1.reg;
+  else
+    q1reg=0;
+  
+  if(isreg(q2))
+    q2reg=p->q2.reg;
+  else
+    q2reg=0;
+  
+  if(isreg(z) && ADD <= p->code && p->code <= SUB)
+  {
+    zreg=p->z.reg;
+  }
+  else
+  {
+    /*
+    if(ISFLOAT(ztyp(p)))
+      zreg=f1;
+    else
+    */
+      zreg=ba;
+  }
+  if((p->q1.flags&(DREFOBJ|REG))==DREFOBJ&&!p->q1.am)
+  {
+    if(debug_prints)
+      emit(f, ";\tpreload() - q1\n");
+    p->q1.flags&=~DREFOBJ;
+    load_reg(f,hl,&p->q1,POINTER,0);
+    p->q1.reg=hl;
+    p->q1.flags|=(REG|DREFOBJ);
+	 p->q1.flags&=~KONST;
+  }
+  if(p->q1.flags/* &&LOAD_STORE */&&!isreg(q1))
+  {
+    if(debug_prints)
+      emit(f, ";\tpreload() - q1a\n");
+    /*
+    if(ISFLOAT(q1typ(p)))
+      q1reg=f1;
+    else
+    */
+      q1reg=ba;
+    load_reg(f,q1reg,&p->q1,q1typ(p),0);
+    p->q1.reg=q1reg;
+    p->q1.flags=REG;
+  }
+  
+  if((p->q2.flags&(DREFOBJ|REG))==DREFOBJ&&!p->q2.am)
+  {
+    if(debug_prints)
+      emit(f, ";\tpreload() - q2\n");
+    p->q2.flags&=~DREFOBJ;
+    load_reg(f,hl,&p->q2,POINTER, 0);
+    p->q2.reg=hl;
+    p->q2.flags|=(REG|DREFOBJ);
+	 p->q1.flags&=~KONST;
+  }
+  if(p->q2.flags/* &&LOAD_STORE */&&!isreg(q2))
+  {
+    if(debug_prints)
+      emit(f, ";\tpreload() - q2a\n");
+    /*
+    if(ISFLOAT(q2typ(p)))
+      q2reg=f2;
+    else
+    */
+      q2reg=hl;
+    load_reg(f,q2reg,&p->q2,q2typ(p), 0);
+    p->q2.reg=q2reg;
+    p->q2.flags=REG;
+  }
+  
+  if(debug_prints)
+    emit(f, ";\tpreload() - end\n");
+  
+  return p;
+}
+
+/* save the result (in zreg) into p->z */
+void save_result(FILE *f,struct IC *p)
+{
+  char str[100];
+  if(debug_prints)
+   	emit(f, ";\tsave_result(flags:%s)\n", flags_verbose(p->z.flags, str));
+  if((p->z.flags&(REG|DREFOBJ))==DREFOBJ&&!p->z.am){
+    p->z.flags&=~DREFOBJ;
+    load_reg(f,hl,&p->z,POINTER, 0);
+    p->z.reg=hl;
+    p->z.flags|=(REG|DREFOBJ);
+	p->z.flags&=~KONST;
+  }
+  if(isreg(z)){
+    if(p->z.reg!=zreg)
+      emit(f,"\tmov\t%s,%s\n",regnames[p->z.reg],regnames[zreg]);
+  }else{
+    store_reg(f,zreg,&p->z,ztyp(p));
+  }
+}
+
+/* prints an object */
+static void emit_obj(FILE *f,struct obj *p,int t)
+{
+	/*
+	if(p->am){
+	if(p->am->flags&GPR_IND) emit(f,"(%s,%s)",regnames[p->am->offset],regnames[p->am->base]);
+	if(p->am->flags&IMM_IND) emit(f,"(%ld,%s)",p->am->offset,regnames[p->am->base]);
+	return;
+	}
+	*/
+	if((p->flags&(KONST|DREFOBJ))==(KONST|DREFOBJ))
+	{
+		emitval(f,&p->val,p->dtyp&NU);
+		return;
+	}
+	if((p->flags&DREFOBJ)||(p->flags&(VAR|VARADR))==VAR) emit(f,"[");
+	if(p->flags&REG)
+	{
+		emit(f,"%s",regnames[p->reg]);
+	}
+	else if(p->flags&VAR) 
+	{
+		//emit(f,"{%d,%d}", p->v->storage_class, p->flags);
+		if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER)
+			emit(f,"sp+%ld",real_offset(p));
+		else
+		{
+			//emit(f,"[");
+			if(!zmeqto(l2zm(0L),p->val.vmax))
+			{
+				emitval(f,&p->val,LONG);
+				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);
+			}
+			//emit(f,"]");
+		}
+	}
+	if(p->flags&KONST)
+	{
+		emitval(f,&p->val,t&NU);
+	}
+	if((p->flags&DREFOBJ)||(p->flags&(VAR|VARADR))==VAR) emit(f,"]");
+}
+
+/*  Yields log2(x)+1 or 0. */
+static long pof2(zumax x)
+{
+  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;
+}
+
+/* emit a logical instruction */
+static void emit_logical(FILE *f, int c, struct obj *q, int t)
+{
+	if(zreg==ba)
+	{
+		emit(f, "\tpush\t%s\n", regnames[q->reg]);
+		emit(f, "\tmov\thl,sp\n");
+		emit(f, "\t%s\ta,[hl]\n", logicals[c-OR]);
+		emit(f, "\txchg\ta,b\n");
+		emit(f, "\tinc\thl\n");
+		emit(f, "\t%s\ta,[hl]\n", logicals[c-OR]);
+		emit(f, "\txchg\ta,b\n");
+		emit(f, "\tpop\t%s\n", regnames[q->reg]);
+	}
+	else
+	{
+		NOT_IMP();
+		emit(f,";\t%s\t%s,",logicals[c-OR],regnames[zreg]);
+		emit_obj(f,q,t);
+		emit(f,"\n");
+	}
+}
+
+/* emit a shift instruction */
+static void emit_shift(FILE *f, int c, struct obj *q, int t)
+{
+	int l1, l2, l3;
+	l1 = ++label;
+	l2 = ++label;
+	l3 = ++label;
+	if(zreg==ba)
+	{
+		emit(f, "\tcmp\t%s,16\n",regnames[q->reg]); 
+		emit(f, "\tjc\t%s%d\n",labprefix,l1);
+		if(c == RSHIFT && !(t&UNSIGNED))
+			emit(f, "\tmov\tba,0xffff\n");
+		else
+			emit(f, "\tmov\tba, 0\n");
+		emit(f, "\tjmp\t%s%d\n",labprefix,l3);
+		emit(f, "%s%d:\n",labprefix,l1);
+		emit(f, "\tcmp\t%s,0\n",regnames[q->reg]); 
+		emit(f, "\tjz\t%s%d\n",labprefix,l3);
+		emit(f, "%s%d:\n",labprefix,l2);
+		if(c == LSHIFT)
+		{
+			emit(f, "\tshl\ta\n");
+			emit(f, "\trolc\tb\n");
+		}
+		else
+		{
+			if (t&UNSIGNED)
+				emit(f, "\tshr\tb\n");
+			else
+				emit(f, "\tsar\tb\n");
+			emit(f, "\trorc\ta\n");
+		}
+		emit(f, "\tdec\t%s\n", regnames[q->reg]);
+		emit(f, "\tjnz\t%s%d\n",labprefix,l2);
+		emit(f, "%s%d:\n",labprefix,l3);
+	}
+	else
+	{
+		NOT_IMP();
+		emit(f,";\t%s\t%s,", arithmetics[c-LSHIFT], regnames[zreg]);
+		emit_obj(f,q,t);
+		emit(f,"\n");
+	}
+}
+static void emit_move_array(FILE *f, struct obj *z, struct obj *q, int size)
+{
+	int l1;
+	l1 = ++label;
+	emit(f,"\tmov\thl,%d\n", size);
+	if(regs[ix])
+	{
+		pushed+=2;
+		emit(f, "\tpush\tx\n");
+	}
+	if(regs[iy])
+	{
+		pushed+=2;
+		emit(f, "\tpush\ty\n");
+	}
+	load_reg(f, iy, q, POINTER, 0);
+	z->flags |= VARADR;
+	load_reg(f, ix, z, POINTER, 0);
+	z->flags &= ~VARADR;
+	
+	emit(f, "%s%d:\n",labprefix,l1);
+	emit(f, "\tmov\t[x],[y]\n");
+	emit(f, "\tinc\tx\n");
+	emit(f, "\tinc\ty\n");
+	emit(f, "\tdec\thl\n");
+	emit(f, "\tjnzb\t%s%d\n",labprefix,l1);
+	
+	if(regs[iy])
+	{
+		pushed-=2;
+		emit(f, "\tpop\ty\n");
+	}
+	if(regs[ix])
+	{
+		pushed-=2;
+		emit(f, "\tpop\tx\n");
+	}
+}
+
+/* generates the function entry code */
+static void function_top(FILE *f,struct Var *v,long offset)
+{
+  emit(f,"\n");
+  rsavesize=0;
+  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));
+  if(offset)
+    emit(f,"\tsub\tsp,%ld\n", offset);
+}
+
+/* generates the function exit code */
+static void function_bottom(FILE *f,struct Var *v,long offset)
+{
+  if(offset)
+    emit(f,"\tadd\tsp,%ld\n", offset);
+  emit(f,ret);
+}
+
+int address_number(char *str)
+{
+	if(strncmp(str, "0x", 2)==0)
+		return strtol(str, 0, 16);
+	else
+		return atoi(str);
+}
+
+/****************************************/
+/*  End of private data and functions.  */
+/****************************************/
+
+void help(char *str)
+{
+	printf("Parameters:\n");
+	printf("  -help             This help screen \n");
+	printf("  -ram-vars=<ADDR>  Address from which will start ram variables. \n");
+	printf("                        Default value is 0x14E0 \n");
+	printf("  -id=<ID_STR>      Identificatior of the game. Maximum 4 characters long.\n");
+	printf("  -name=<NAME_STR>  Name of the game. Maximum 12 characters. \n");	
+	fflush(stdout);
+	exit(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.                                            */
+{
+   return 0;
+}
+
+
+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;
+	/*  Initialize some values which cannot be statically initialized   */
+	/*  because they are stored in the target's arithmetic.             */
+	maxalign=l2zm(1L);
+	char_bit=l2zm(8L);
+	for(i=0;i<=MAX_TYPE;i++)
+	{
+		sizetab[i]=l2zm(msizetab[i]);
+		align[i]=l2zm(malign[i]);
+	}
+	for(i=1;i<=MAXR;i++)
+	{
+		regsize[i]=l2zm(2L);regtype[i]=&ityp;
+	}   
+
+	/*  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.          */
+	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);
+
+	start_ram_vars = RAM_VARS_ADDR;
+
+	memset(game_id, 0, sizeof(game_id));
+	strncpy(game_id, GAME_ID, 4);
+
+	memset(game_name, 0, sizeof(game_id));
+	strncpy(game_name, GAME_NAME, 12);
+
+	target_macros=marray;
+
+	for(i=0; i<26; i++)
+		used_interrupt[i] = 0;
+
+	return 1;
+}
+
+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;
+}
+
+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)&&((f&NQ)==INT||(f&NQ)==SHORT||f==CHAR))
+      return ix;
+   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;
+   return 1;
+}
+
+int shortcut(int c,int t)
+{
+	/* TODO */
+	/* enable those for more optimised code */
+	/*if(c==COMPARE||c==AND||c==OR||c==XOR) return 1;*/
+	return 0;
+}
+
+
+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&&section!=SPECIAL)
+    emit(f,"%ld\n",zm2l(size));
+  else
+    emit(f,"\t.space\t%ld\n",zm2l(size));
+  newobj=0;
+  */
+  int i;
+  int num_per_line = 16;
+  for(i=0; i<size; ++i)
+  {
+     if(i % num_per_line == 0)
+     emit(f, "\t.db\t");
+   if(i % num_per_line == num_per_line - 1 || i == size - 1)
+       emit(f, "0\n");
+     else
+       emit(f, "0, ");
+  }
+}
+
+void gen_dc(FILE *f,int t,struct const_list *p)
+/*  This function has to create static storage          */
+/*  initialized with const-list p.                      */
+{
+  if((t&NQ)==CHAR || (t&NQ)==SHORT)
+    emit(f,"\t.db\t");
+  else if((t&NQ)==INT || (t&NQ)==POINTER)
+    emit(f,"\t.dw\t");
+  else
+    emit(f,";\tdc.%s %d\t",dt(t&NQ), 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[0],ip[1],ip[2],ip[3]);
+      if((t&NQ)!=FLOAT)
+      {
+        emit(f,",0x%02x%02x%02x%02x",ip[4],ip[5],ip[6],ip[7]);
+      }
+    }
+    else
+    */
+	 emitval(f,&p->val,t&NU);
+	 if((t&NQ)==CHAR && 0x20 <= p->val.vchar && p->val.vchar <=0x7f)
+		emit(f, "\t; '%c'", (char)p->val.vchar);
+  }
+  else
+  {
+    emit_obj(f,&p->tree->o,t&NU);
+  }
+  emit(f,"\n");
+  //newobj=0;
+}
+
+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 = 0;
+  char *sec;
+  if(v->clist) constflag=is_const(v->vtyp);
+  
+  if(v->tattr&ALIGN8)
+  {
+		emit(f, "\t.align\t8\n");
+		/*
+		emit(f, "\t.equ\tvbcc___unaligned_address .\n");
+		emit(f, "\t.equ\tvbcc___unaligned_address2 (vbcc___unaligned_address + 7)\n");
+		emit(f, "\t.equ\tvbcc___unaligned_address3 (vbcc___unaligned_address2 & 7)\n");
+		emit(f, "\t.equ\tvbcc___unaligned_address4 (vbcc___unaligned_address2 - vbcc___unaligned_address3)\n");
+		emit(f, "\t.org\tvbcc___unaligned_address4\n");
+		*/
+  }
+  
+  if(v->tattr&ALIGN64)
+  {
+		emit(f, "\t.align\t64\n");
+		/*
+		emit(f, "\t.equ\tvbcc___unaligned_address .\n");
+		emit(f, "\t.equ\tvbcc___unaligned_address2 (vbcc___unaligned_address + 63)\n");
+		emit(f, "\t.equ\tvbcc___unaligned_address3 (vbcc___unaligned_address2 & 63)\n");
+		emit(f, "\t.equ\tvbcc___unaligned_address4 (vbcc___unaligned_address2 - vbcc___unaligned_address3)\n");
+		emit(f, "\t.org\tvbcc___unaligned_address4\n");
+		*/
+  }
+  
+  if(/*(v->tattr&ROM) ||*/ /*constflag*/ is_const(v->vtyp))
+  {
+	//emit(f, "\n\t; CONST\n");
+	if(!last_was_rom)
+	{
+		emit(f, "\t.equ\tvbcc___saved_rom_shadow .\n");
+		emit(f, "\t.org\tvbcc___saved_rom_shadow - %d\n", ram_rom_distance);
+		emit(f, "\t.equ\tvbcc___saved_ram_addr .\n");
+		emit(f, "\t.org\tvbcc___saved_rom_addr\n");
+		last_was_rom = 1;
+	}
+  }
+  else
+  {
+	//emit(f, "; in ram!!!  %s%ld:  %s%s: \n",labprefix,zm2l(v->offset), idprefix,v->identifier);
+	if(last_was_rom)
+	{
+		emit(f, "\t.equ\tvbcc___saved_rom_addr .\n");
+		if(!ram_vars_initialized)
+		{
+			emit(f, "\t.org\t%d\n", start_ram_vars);
+			emit(f, "\t.equ\tvbcc___saved_ram_addr .\n");
+			ram_vars_initialized = 1;
+		}
+		else
+		{
+			emit(f, "\t.org\tvbcc___saved_ram_addr\n");
+		}
+		last_was_rom = 0;
+	}
+	else
+	{
+		emit(f, "\t.equ\tvbcc___saved_rom_shadow .\n");
+		emit(f, "\t.org\tvbcc___saved_rom_shadow - %d\n", ram_rom_distance);
+		emit(f, "\t.equ\tvbcc___saved_ram_addr .\n");
+	}
+  }
+  
+  if(v->storage_class==STATIC)
+  {
+    if(!ISFUNC(v->vtyp->flags))
+	{
+		/*
+		if(!special_section(f,v)){
+		  if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&&section!=DATA){emit(f,dataname);if(f) section=DATA;}
+		  if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&&section!=RODATA){emit(f,rodataname);if(f) section=RODATA;}
+		  if(!v->clist&&section!=BSS){emit(f,bssname);if(f) section=BSS;}
+		}
+		if(v->clist||section==SPECIAL){
+		  gen_align(f,falign(v->vtyp));
+		  emit(f,"%s%ld:\n",labprefix,zm2l(v->offset));
+		}else
+		  emit(f,"\t.lcomm\t%s%ld,",labprefix,zm2l(v->offset));
+		newobj=1;
+		*/
+		emit(f,"%s%ld:\n",labprefix,zm2l(v->offset));
+	}
+  }
+  if(v->storage_class==EXTERN)
+  {
+    //emit(f,"\t.globl\t%s%s\n",idprefix,v->identifier);
+    if(v->flags&(DEFINED|TENTATIVE)){
+      /*
+      if(!special_section(f,v)){
+        if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&&section!=DATA){emit(f,dataname);if(f) section=DATA;}
+        if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&&section!=RODATA){emit(f,rodataname);if(f) section=RODATA;}
+        if(!v->clist&&section!=BSS){emit(f,bssname);if(f) section=BSS;}
+      }
+      if(v->clist||section==SPECIAL){
+        gen_align(f,falign(v->vtyp));
+        emit(f,"%s%s:\n",idprefix,v->identifier);
+      }else
+        emit(f,"\t.global\t%s%s\n\t.%scomm\t%s%s,",idprefix,v->identifier,(USE_COMMONS?"":"l"),idprefix,v->identifier);
+      newobj=1;
+      */
+      emit(f,"%s%s:\n",idprefix,v->identifier);
+    }
+  }
+  if(!last_was_rom)
+  {
+	emit(f, "\t.org\tvbcc___saved_ram_addr + %d\n", ram_rom_distance);	
+  }
+}
+
+static int init_dump = 0;
+
+
+/*  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 *p,struct Var *v,zmax offset)
+{
+    int c, t, t2, i, cmp_type = 0;
+    struct IC *m;
+
+	if(!init_dump)
+	{
+		init_dump = 1;
+		emit_start(f);
+	}
+	
+	if(strcmp(v->identifier,"main")==0)
+	{
+		emit_end(f);
+	}
+		
+    localsize=(zm2l(offset));
+    for(m=p;m;m=m->next)
+    {
+		c=m->code;t=m->typf&NU;
+		/* convert MULT/DIV/MOD with powers of two */
+		if((t&NQ)<=LONG&&(m->q2.flags&(KONST|DREFOBJ))==KONST&&(t&NQ)<=LONG&&(c==MULT||((c==DIV||c==MOD)&&(t&UNSIGNED)))){
+		  eval_const(&m->q2.val,t);
+		  i=pof2(vmax);
+		  if(i){
+			if(c==MOD){
+			  vmax=zmsub(vmax,l2zm(1L));
+			  m->code=AND;
+			}else{
+			  vmax=l2zm(i-1);
+			  if(c==DIV) m->code=RSHIFT; else m->code=LSHIFT;
+			}
+			c=m->code;
+			gval.vmax=vmax;
+			eval_const(&gval,MAXINT);
+			if(c==AND){
+			  insert_const(&m->q2.val,t);
+			}else{
+			  insert_const(&m->q2.val,INT);
+			  m->typf2=INT;
+			}
+		  }
+		}
+        //if(c==CALL&&argsize<zm2l(m->q2.val.vmax)) argsize=zm2l(m->q2.val.vmax);
+    }
+ 	//emit(f, ";%s\n", v->identifier);
+	
+	if(v->tattr&INTERRUPT)
+	{
+		char *p;
+		
+		for(p = v->identifier; *p; ++p)
+			if(isdigit(*p))
+				break;
+		if(!*p)
+		{
+			fprintf(stderr, "ERROR: Interrupt routine with no interrupt number!\n");
+		}
+		else
+		{
+			int num = atoi(p);
+			if(used_interrupt[num])
+			{
+				fprintf(stderr, "ERROR: Interrupt %d defined twice!\n", num);
+			}
+			else
+			{
+				used_interrupt[num] = 1;
+				emit(f, "%s%d:\n", int_handler_prefix, num);
+				
+				emit(f, "\tpushax\n");
+				ret="\tpopax\n\treti\n";
+			}
+		}
+	}
+	else
+		ret="\tret\n";
+ 
+    function_top(f,v,localsize);
+    pushed=0;
+ 	
+
+    for(;p;p=p->next)
+    {
+		if(debug_prints)
+		{
+			fprintf(f,";;;;");
+			pric2(f,p);
+		}
+		
+		c=p->code;
+		t=p->typf&NU;
+		t2=p->typf2&NU;
+		
+		if(c==ALLOCREG) 
+		{
+			regs[p->q1.reg]=1;
+			continue;
+		}
+		if(c==FREEREG) 
+		{
+			regs[p->q1.reg]=0;
+			continue;
+		}
+		if(c==BRA){
+		  /*
+		  if(t==exit_label)
+			emit(f,ret);
+		  else
+		  */
+			emit(f,"\tjmp\t%s%d\n",labprefix,t);
+		  continue;
+		}
+		if(c>=BEQ&&c<BRA){
+			int tmp_label = ++label;
+			/* FIXME */
+			/* some of the comparissions can be also 16-bit jumps */
+			if(debug_prints)
+				emit(f, "; t: 0x%x (0x%x)  so: ", cmp_type, UNSIGNED);
+			if(cmp_type&UNSIGNED)
+			{
+				if(debug_prints)
+					emit(f, "UNSIGNED\n");
+				if(c < BLE)
+				{
+					emit(f,"\tj%s\t%s%d\n",uccs2[c-BEQ],labprefix,tmp_label);
+					emit(f,"\tjmp\t%s%d\n",labprefix,t);
+				}
+				else
+				{
+					if(c==BLE)
+					{
+						emit(f,"\tjz\t%s%d\n",labprefix,t);
+						emit(f,"\tj%s\t%s%d\n",uccs2[c-BEQ],labprefix,t);
+					}
+					else /* BGT */
+					{
+						emit(f,"\tjz\t%s%d\n",labprefix,tmp_label);
+						emit(f,"\tj%s\t%s%d\n",uccs2[c-BEQ],labprefix,t);
+					}
+				}
+			}
+			else
+			{
+				if(debug_prints)
+					emit(f, "SIGNED\n");
+				emit(f,"\tj%s\t%s%d\n",ccs2[c-BEQ],labprefix,tmp_label);
+				emit(f,"\tjmp\t%s%d\n",labprefix,t);
+			}
+			emit(f,"%s%d:\n",labprefix,tmp_label);
+			continue;
+		}
+		if(c==MOVETOREG){
+		  load_reg(f,p->z.reg,&p->q1,regtype[p->z.reg]->flags, 0);
+		  continue;
+		}
+		if(c==MOVEFROMREG){
+		  store_reg(f,p->z.reg,&p->q1,regtype[p->z.reg]->flags);
+		  continue;
+		}
+		if(c==CALL){					
+			if((p->q1.flags & (VAR|DREFOBJ)) == VAR &&
+				p->q1.v->fi &&
+				p->q1.v->fi->inline_asm)
+			{
+				emit_inline_asm(f,p->q1.v->fi->inline_asm);
+			}
+			else
+			{
+				emit(f,"\tcall\t");
+				if(p->q1.v->storage_class==STATIC)
+				{
+					emit(f,"%s%ld",labprefix,zm2l(p->q1.v->offset));
+				}
+				else
+				{
+					emit(f,"%s%s",idprefix,p->q1.v->identifier);
+				}
+				emit(f,"\n");
+			}		  
+			if(pushed != 0)
+				emit(f,"\tadd\tsp,%ld\n", pushed);			
+			pushed = 0;
+			continue;
+		}
+		
+		if(c==ADDRESS)
+		{
+			if(isreg(z))
+				zreg=p->z.reg;
+			else
+				zreg=ba;
+			load_address(f,zreg,&p->q1,POINTER);
+			save_result(f,p);
+			continue;
+		}
+			 
+		p=preload(f,p);
+		c=p->code;
+		
+		if(c==SUBPFP) c=SUB;
+		if(c==ADDI2P) c=ADD;
+		if(c==SUBIFP) c=SUB;
+		
+		if(c==CONVERT)
+		{
+			/* FIXME */
+			if(ISFLOAT(q1typ(p))||ISFLOAT(ztyp(p))) ierror(0);
+			load_reg(f,zreg,&p->q1,t, t2);
+			if(sizetab[q1typ(p)&NQ]<sizetab[ztyp(p)&NQ] && (ztyp(p)&NQ&POINTER)!=POINTER)
+			{
+				if(zreg == ba && msizetab[q1typ(p)&NQ] == 1)
+				{
+					if(q1typ(p)&UNSIGNED)
+						emit(f,"\tmov\tb,0\n");
+					else
+						emit(f,"\tex\tba,a\n",dt(q1typ(p)),regnames[zreg]);
+				}
+				else
+					NOT_IMP();
+			}
+			save_result(f,p);
+			continue;
+		}
+		
+		if(c==SETRETURN){
+		  load_reg(f,p->z.reg,&p->q1,t, 0);
+		  continue;
+		}
+		
+		if(c==GETRETURN){
+		  if(p->q1.reg){
+			zreg=p->q1.reg;
+			save_result(f,p);
+		  }else
+			p->z.flags=0;
+		  continue;
+		}
+	 
+		if(c==ASSIGN)
+		{
+			if(debug_prints)
+				emit(f,"; ASSIGN start\n");
+			if(t==0) 
+				ierror(0);
+			if(t==ARRAY)
+			{
+				emit_move_array(f, &p->z, &p->q1, p->q2.val.vmax);
+			}
+			else
+			{
+				load_reg(f,zreg,&p->q1,t, 0);
+				save_result(f,p);
+			}
+			if(debug_prints)
+				emit(f,"; ASSIGN end\n");
+			continue;
+		}
+		
+		if(c==PUSH)
+		{
+			if(t==0) ierror(0);
+			pushed+=zm2l(p->q2.val.vmax);
+			//emit(f,"\tmov\t[sp+%ld],",pushed);
+			emit(f, "\tpush\t");
+			emit_obj(f,&p->q1,t);
+			emit(f,"\n");
+			continue;
+		}
+		
+		if(c==LABEL) 
+		{
+			emit(f,"%s%d:\n",labprefix,t);
+			continue;
+		}
+
+		if(c==KOMPLEMENT)
+		{
+			load_reg(f,ba,&p->q1,t, 0);
+			emit(f,"\tnot\ta\n");
+			emit(f,"\tnot\tb\n");
+			save_result(f,p);
+			continue;
+		}
+		
+		if(c==MINUS)
+		{
+			load_reg(f,ba,&p->q1,t, 0);
+			emit(f,"\tmov\thl,0\n");
+			emit(f,"\tsub\thl,ba\n");
+			emit(f,"\tmov\tba,hl\n");
+			save_result(f,p);
+			continue;
+		}
+		
+		if(c==TEST)
+		{
+			if(q1reg != ba)
+			{
+				emit(f, "\tmov\tba,");
+				emit_obj(f,&p->q1,t);
+				emit(f, "\n");
+			}
+			emit(f,"\tcmp\t%s,0\n", (msizetab[(t&NQ)]==1)?"a":"ba");
+			continue;
+		}
+		
+		if(c==COMPARE)
+		{
+			cmp_type = t;
+			if(q1reg != ba)
+			{
+				emit(f, "\tmov\tba,");
+				emit_obj(f,&p->q1,t);
+				emit(f, "\n");
+			}
+			emit(f,"\tcmp\t%s,", (msizetab[(t&NQ)]==1)?"a":"ba");
+			emit_obj(f,&p->q2,t);
+			emit(f,"\n");
+			continue;
+		}
+    
+		if((c>=OR&&c<=AND)||(c>=LSHIFT&&c<=MOD))
+		{
+			load_reg(f, zreg, &p->q1, t, 0);
+			if(c>=OR&&c<=AND)
+			{
+				emit_logical(f, c, &p->q2, t);
+			}
+			else if(c>=LSHIFT&&c<=RSHIFT)
+			{
+				emit_shift(f, c, &p->q2, t);
+			}
+			else if(c==MULT)
+			{
+				load_reg(f, ba, &p->q1, t, 0);
+				load_reg(f, hl, &p->q2, t, 0);
+				emit(f, "\tcall\tvbcc___mul16x16_16\n");
+			}
+			else if(DIV <=c && c <=MOD)
+			{
+				load_reg(f, ba, &p->q1, t, 0);
+				load_reg(f, hl, &p->q2, t, 0);
+				emit(f, "\tcall\tvbcc___div_mod16x16_16\n");
+				if(c==MOD)
+					emit(f, "\tmov\tba, hl\n");
+			}
+			else
+			{
+				if(zreg != ba)
+					emit(f, "\tmov\tba,%s\n", regnames[zreg]);
+				emit(f,"\t%s\t%s,",arithmetics[c-LSHIFT],regnames[ba]);
+				emit_obj(f,&p->q2,t);
+				emit(f,"\n");
+				if(zreg != ba)
+					emit(f, "\tmov\t%s,ba\n", regnames[zreg]);
+			}
+			save_result(f,p);
+			continue;
+		}
+		 
+		fprintf(f,";\tNOT IMPLEMENTED INSTRUCTION >>> %s <<< (code:%d)\n", ename[p->code], p->code);
+		fprintf(f,";;;;");
+		pric2(f,p);
+    }
+
+    function_bottom(f,v,localsize);
+}
+
+void cleanup_cg(FILE *f)
+{
+}
+
+void init_db(FILE *f)
+{
+}
+void cleanup_db(FILE *f)
+{
+} 
diff --git a/machines/pm/machine.dt b/machines/pm/machine.dt
new file mode 100755
index 0000000..0926f51
--- /dev/null
+++ b/machines/pm/machine.dt
@@ -0,0 +1,16 @@
+S8BS
+S8BU
+S16BSBE S16BSLE
+S16BUBE S16BULE
+S16BSBE S16BSLE
+S16BUBE S16BULE
+S32BSBE S32BSLE
+S32BUBE S32BULE
+S64BSBE S64BSLE
+S64BUBE S64BULE
+S32BIEEEBE
+S64BIEEEBE
+S64BIEEEBE
+S16BUbE S16BULE
+
+
diff --git a/machines/pm/machine.h b/machines/pm/machine.h
new file mode 100755
index 0000000..2b4bec6
--- /dev/null
+++ b/machines/pm/machine.h
@@ -0,0 +1,55 @@
+
+
+#include "dt.h"
+
+
+
+/*  The number of registers of the target machine.                  */
+#define MAXR 2
+
+/*  Number of commandline-options the code-generator accepts.       */
+#define MAXGF 4
+
+
+/*  If this is set to zero vbcc will not generate ICs where the     */
+/*  target operand is the same as the 2nd source operand.           */
+/*  This can sometimes simplify the code-generator, but usually     */
+/*  the code is better if the code-generator allows it.             */
+#define USEQ2ASZ 1
+
+/*  This specifies the smallest integer type that can be added to a */
+/*  pointer.                                                        */
+#define MINADDI2P INT
+
+/*  If the bytes of an integer are ordered most significant byte    */
+/*  byte first and then decreasing set BIGENDIAN to 1.              */
+#define BIGENDIAN 0
+
+/*  If the bytes of an integer are ordered lest significant byte    */
+/*  byte first and then increasing set LITTLEENDIAN to 1.           */
+#define LITTLEENDIAN 1
+
+/*  Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive.    */
+
+/*  If switch-statements should be generated as a sequence of       */
+/*  SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1.      */
+/*  This can yield better code on some machines.                    */
+#define SWITCHSUBS 1
+
+/*  In optimizing compilation certain library memcpy/strcpy-calls   */
+/*  with length known at compile-time will be inlined using an      */
+/*  ASSIGN-IC if the size is less or equal to INLINEMEMCPY.         */
+/*  The type used for the ASSIGN-IC will be UNSIGNED|CHAR.          */
+#define INLINEMEMCPY 1024
+
+/* size of buffer for asm-output */
+#define EMIT_BUF_LEN 20000 /* should be enough */
+
+/* number of asm-output lines buffered */
+#define EMIT_BUF_DEPTH 1
+
+/*  We have asm_peephole to optimize assembly-output */
+#define HAVE_TARGET_PEEPHOLE 0
+
+/*  We have some target-specific variable attributes.               */
+#define HAVE_TARGET_ATTRIBUTES
diff --git a/machines/ppc/machine.c b/machines/ppc/machine.c
new file mode 100644
index 0000000..e547fc1
--- /dev/null
+++ b/machines/ppc/machine.c
@@ -0,0 +1,4012 @@
+/*  Code generator for a PPC RISC cpu with 32 general purpose,  */
+/*  32 floating point and 8 condition code registers.           */
+
+#include "supp.h"
+
+static char FILE_[]=__FILE__;
+
+#include "dwarf2.c"
+
+/*  Public data that MUST be there.                             */
+
+/* Name and copyright. */
+char cg_copyright[]="vbcc code-generator for PPC V0.7 (c) in 1997-2022 by Volker Barthelmann";
+
+/*  Commandline-flags the code-generator accepts                */
+int g_flags[MAXGF]={STRINGFLAG,STRINGFLAG,0,0,0,0,
+                    0,0,0,0,0,
+                    0,0,0,0,0,0,
+		    0,0,0};
+char *g_flags_name[MAXGF]={"cpu","fpu","const-in-data","sd","merge-constants","fsub-zero",
+                           "elf","amiga-align","no-regnames","no-peephole","setccs",
+                           "use-lmw","poweropen","sc","madd","eabi","gas",
+			   "no-align-args","conservative-sr","use-commons",
+                           "baserel32os4","baserel32mos","oldlibcalls"};
+union ppi g_flags_val[MAXGF];
+
+/*  Alignment-requirements for all types in bytes.              */
+zmax align[MAX_TYPE+1];
+
+/*  Alignment that is sufficient for every object.              */
+zmax maxalign;
+
+/*  CHAR_BIT for the target machine.                            */
+zmax char_bit;
+
+/*  Tabelle fuer die Groesse der einzelnen Typen                */
+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[MAXR+1]={"noreg",
+                        "r0","r1","r2","r3","r4","r5","r6","r7",
+                        "r8","r9","r10","r11","r12","r13","r14","r15",
+                        "r16","r17","r18","r19","r20","r21","r22","r23",
+                        "r24","r25","r26","r27","r28","r29","r30","r31",
+                        "f0","f1","f2","f3","f4","f5","f6","f7",
+                        "f8","f9","f10","f11","f12","f13","f14","f15",
+                        "f16","f17","f18","f19","f20","f21","f22","f23",
+                        "f24","f25","f26","f27","f28","f29","f30","f31",
+                        "cr0","cr1","cr2","cr3","cr4","cr5","cr6","cr7",
+                        "cnt",
+			"r3/r4","r5/r6","r7/r8","r9/r10",
+			"r14/r15","r16/r17","r18/r19","r20/r21",
+			"r22/r23","r24/r25","r26/r27","r28/r29","r30/r31",
+			"lr"};
+
+/*  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,1,1,1,1,1,1,1,1,1,1,1,0,0,0,
+		          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+		          1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
+			  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+			  1,1,0,0,0,1,1,1,1,
+			  1,1,1,1,
+			  0,0,0,0,0,0,0,0,0};
+
+int reg_prio[MAXR+1]={0,0,0,0,19,20,21,22,23,24,25,26,27,28,0,1,2,
+		        3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,
+		        0,1,2,3,4,5,6,7,8,9,10,11,12,13,0,0,
+		        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+		        1,1,0,0,0,1,1,1,1,
+		        19,21,23,25,
+		        1,3,5,7,9,11,13,15,17};
+
+struct reg_handle empty_reg_handle={0,0};
+
+/* Names of target-specific variable attributes.                */
+char *g_attr_name[]={"__far","__near","__chip","__saveds","__rfi","__saveall",
+		     "__syscall","__nosave","__brel",0};
+#define FAR 1
+#define NEAR 2
+#define CHIP 4
+#define SAVEDS 8
+#define RFI 16
+#define SAVEALL 32
+#define SYSCALL 64
+#define NOSAVE 128
+#define BREL 256
+
+/****************************************/
+/*  Private data and functions.         */
+/****************************************/
+
+#define SMALLDATA (g_flags[3]&USEDFLAG)
+#define POWEROPEN (g_flags[12]&USEDFLAG)
+#define STORMC (g_flags[13]&USEDFLAG)
+#define EABI (g_flags[15]&USEDFLAG)
+#define GAS (g_flags[16]&USEDFLAG)
+#define NOALIGNARGS (g_flags[17]&USEDFLAG)
+#define CONSERVATIVE_SR (g_flags[18]&USEDFLAG)
+#define USE_COMMONS (g_flags[19]&USEDFLAG)
+#define BASERELOS4 (g_flags[20]&USEDFLAG)
+#define BASERELMOS (g_flags[21]&USEDFLAG)
+#define OLDLIBCALLS (g_flags[22]&USEDFLAG)
+
+
+static char *mregnames[MAXR+1];
+
+static char *ret="\tblr\n";
+
+static long malign[MAX_TYPE+1]=  {1,1,2,4,4,8,4,8,8,1,4,1,1,1,4,1};
+static long msizetab[MAX_TYPE+1]={1,1,2,4,4,8,4,8,8,0,4,0,0,0,4,0};
+
+static struct Typ ltyp={LONG},lltyp={LLONG},ldbl={DOUBLE},lchar={CHAR};
+
+static char *marray[]={"__section(x,y)=__vattr(\"section(\"#x\",\"#y\")\")",
+		       "__PPC__",
+		       "__aos4libcall=__attr(\"aos4libcall;\")",
+		       "__linearvarargs=__attr(\"linearvarargs;\")",
+		       "__interrupt=__rfi __saveall",
+		       0};
+
+const int r4=5,r5=6,r6=7,r3r4=74,r5r6=75;
+
+
+static int r0=1;                   /*  special register                    */
+static int r2=3;                   /*  reserved or toc                     */
+static int r3=4;                   /*  return value                        */
+static int sp=2;                   /*  Stackpointer                        */
+static int fp=2;                   /*  Framepointer                        */
+static int vlafp=32;               /*  Framepointer to use with vlas       */
+static int sd=14;                  /*  SmallDataPointer                    */
+static int sd2=3;                  /*  SmallData2 (eabi)                   */
+static int t1=12,t2=13,t3=1;       /*  Temporaries used by code generator  */
+static int f1=45,f2=46,f3=33;      /*  Temporaries used by code generator  */
+static int cr0=65;                 /*  Default condition-code-register     */
+static int ctr=73;                 /*  ctr                                 */
+static int lr=87;                  /*  link register                       */
+static int bp32os4=3;              /*  baserel32 pointer for Amiga OS4     */
+static int bp32mos=14;             /*  baserel32 pointer for MorphOS       */
+
+#define DATA 0
+#define BSS 1
+#define CODE 2
+#define RODATA 3
+#define TOC 4
+#define SDATA 5
+#define SDATA2 6
+#define SBSS 7
+#define SPECIAL 8
+
+#if HAVE_OSEK
+/* removed */
+/* removed */
+#endif
+
+static long stack;
+static int stack_valid;
+static long tmpoff; /* offset for additional temporaries, upper end! */
+static int lastlabel,exit_label;
+static int sdp;
+static int q1loaded,q2loaded;
+static int section=-1,newobj,crsave;
+static char *codename="\t.text\n\t.align\t2\n",
+  *dataname="\t.data\n\t.align\t2\n",
+  *bssname="",
+  *rodataname="\t.section\t.rodata\n\t.align\t2\n",
+  *tocname="\t.tocd\n\t.align\t2\n",
+  *sdataname="\t.section\t\".sdata\",\"aw\"\n\t.align\t2\n",
+  *sdata2name="\t.section\t\".sdata2\",\"a\"\n\t.align\t2\n",
+  *sbssname="\t.section\t\".sbss\",\"auw\"\n\t.align\t2\n";
+
+static char *labprefix="l",*idprefix="_",*tocprefix="@_";
+static long frameoffset,pushed,maxpushed,framesize,localoffset,minframe=8;
+static void emit_obj(FILE *f,struct obj *p,int t);
+
+static int all_regs;
+
+struct StatFPtrList {
+  struct StatFPtrList *next;
+  struct Var *vptr;
+};
+static struct StatFPtrList *firstfptr = NULL;
+
+void title(FILE *f)
+{
+  static int done;
+  extern char *inname; /*grmpf*/
+  if(!done&&f){
+    done=1;
+    emit(f,"\t.file\t\"%s\"\n",inname);
+  }
+} 
+
+static long real_offset(struct obj *o)
+{
+  long off;
+  if(zm2l(o->v->offset)>=0){
+     return zm2l(o->v->offset)+frameoffset+zm2l(o->val.vmax);
+  }else{
+    return framesize+minframe-zm2l(o->v->offset)-zm2l(maxalign)+zm2l(o->val.vmax);
+  }
+}
+static long hi(long off)
+{
+  zmax zm=l2zm(off),r=zmrshift(zm,l2zm(16L));
+  if(!zmeqto(zmand(zm,l2zm(32768L)),l2zm(0L))) r=zmadd(r,l2zm(1L));
+  return zm2l(zs2zm(zm2zs(zmand(r,l2zm(65535L)))));
+}
+static long lo(long off)
+{
+  return zm2l(zs2zm(zm2zs(zmand(l2zm(off),l2zm(65535L)))));
+}
+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(t==LDOUBLE) t=DOUBLE;
+  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;
+      }
+    }
+  }
+  p=mymalloc(sizeof(struct fpconstlist));
+  p->next=firstfpc;
+  p->label=++label;
+  p->typ=t;
+  p->val=o->val;
+  firstfpc=p;
+  return p->label;
+}
+
+#define REG_IND 1
+#define IMM_IND 2
+#define UPDATE  64
+
+static struct obj *cam(int flags,int base,long offset)
+/*  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;
+  return &obj;
+}
+
+static char *ldts[]={"","bz","ha","wz","wz","wz","fs","fd","fd","","wz"};
+static char *ldtu[]={"","bz","hz","wz","wz","wz","??","??","??","??","??"};
+static char *sdts[]={"","b","h","w","w","w","fs","fd","fd","","w"};
+static char *sdtu[]={"","b","h","w","w","w","??","??","??","??","??"};
+
+#define ldt(t) ((t&UNSIGNED)?ldtu[t&NQ]:ldts[t&NQ])
+#define sdt(t) ((t&UNSIGNED)?sdtu[t&NQ]:sdts[t&NQ])
+
+static int special_section(FILE *f,struct Var *v)
+{
+  char *sec;
+  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 int use_sd(int t)
+/*  Shall the object of type t be addressed in small-data-mode?  */
+{
+  int r=0;
+  if(ISFUNC(t)) return 0;
+  if(g_flags[3]&USEDFLAG) 
+    r=sd;
+  else if(STORMC&&(t&NQ)<=POINTER) 
+    r=sd;
+  else if(EABI&&ISSCALAR(t)){
+    if(t&CONST)
+      r=sd2;
+    else
+      r=sd;
+  }
+  return r;
+}
+
+static void load_address(FILE *f,int r,struct obj *o,int typ)
+/*  Generates code to load the address of a variable into register r.   */
+{
+  BSET(regs_modified,r);
+  if(!(o->flags&VAR)) 
+    ierror(0);
+  if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER){
+    long off=real_offset(o);
+    if(off<=32767){
+      emit(f,"\taddi\t%s,%s,%ld\n",mregnames[r],mregnames[fp],off);
+    }else{
+      if(r==r0){
+	BSET(regs_modified,t2);
+	emit(f,"\taddis\t%s,%s,%ld\n",mregnames[t2],mregnames[fp],hi(off));
+	emit(f,"\taddi\t%s,%s,%ld\n",mregnames[r],mregnames[t2],lo(off));
+      }else{
+	emit(f,"\taddis\t%s,%s,%ld\n",mregnames[r],mregnames[fp],hi(off));
+	emit(f,"\taddi\t%s,%s,%ld\n",mregnames[r],mregnames[r],lo(off));
+      }
+    }
+  }else{
+    if((sdp=use_sd(o->v->vtyp->flags))&&!(o->v->tattr&FAR)
+       &&zmleq(l2zm(0L),o->val.vmax)&&!zmleq(szof(o->v->vtyp),o->val.vmax)){
+      emit(f,"\tla\t%s,",mregnames[r]);
+      emit_obj(f,o,typ);
+      if(GAS)
+	emit(f,"@sda21(0)\n");
+      else
+	emit(f,"(%s)\n",mregnames[sdp]);
+    }else{
+      if(POWEROPEN){
+        zmax offset=o->val.vmax;
+	if(f){
+	  if((o->v->vtyp->flags&NQ)==FUNKT&&o->v->storage_class==STATIC){
+	    /* check if static function pointer was already created in TOC */
+	    struct StatFPtrList **oldsfp=&firstfptr;
+	    struct StatFPtrList *sfp=firstfptr;
+	    while(sfp){
+	      if(sfp->vptr==o->v) break;
+	      oldsfp=&sfp->next;
+	      sfp=sfp->next;
+	    }
+	    if(!sfp){
+	      *oldsfp=sfp=mymalloc(sizeof(struct StatFPtrList));
+	      sfp->next=NULL;
+	      sfp->vptr=o->v;
+	    }
+	  }
+	  emit(f,"\tl%s\t%s,%s",ldt(LONG),mregnames[r],tocprefix);
+	  o->val.vmax=l2zm(0L);emit_obj(f,o,POINTER);o->val.vmax=offset;
+	  emit(f,"(%s)\n",mregnames[r2]);
+	  if(hi(zm2l(offset))) emit(f,"\taddis\t%s,%s,%ld\n",mregnames[r],mregnames[r],hi(zm2l(offset)));
+	  if(lo(zm2l(offset))) emit(f,"\taddi\t%s,%s,%ld\n",mregnames[r],mregnames[r],lo(zm2l(offset)));
+	}
+      }else{
+        if(BASERELOS4){
+          emit(f,"\taddis\t%s,%s,",mregnames[r],mregnames[bp32os4]);
+          emit_obj(f,o,typ);emit(f,"@brel@ha\n");
+          emit(f,"\taddi\t%s,%s,",mregnames[r],mregnames[r]);
+          emit_obj(f,o,typ);emit(f,"@brel@l\n");
+        }else if(BASERELMOS){
+          emit(f,"\taddis\t%s,%s,",mregnames[r],mregnames[bp32mos]);
+          emit_obj(f,o,typ);emit(f,"@drel@ha\n");
+          emit(f,"\taddi\t%s,%s,",mregnames[r],mregnames[r]);
+          emit_obj(f,o,typ);emit(f,"@drel@l\n");
+        }else{
+          emit(f,"\tlis\t%s,",mregnames[r]);
+          emit_obj(f,o,typ);emit(f,"@ha\n");
+          emit(f,"\taddi\t%s,%s,",mregnames[r],mregnames[r]);
+          emit_obj(f,o,typ);emit(f,"@l\n");
+        }
+      }
+    }
+  }
+}
+static void load_reg(FILE *f,int r,struct obj *o,int typ,int tmp)
+/*  Generates code to load a memory object into register r. tmp is a    */
+/*  general purpose register which may be used. tmp can be r.           */
+{
+  typ&=NU;
+  BSET(regs_modified,r);
+  if(o->flags&KONST){
+    long l;
+    eval_const(&o->val,typ);
+    if(ISFLOAT(typ)){
+      int lab;
+      if((g_flags[5]&USEDFLAG)&&zldeqto(vldouble,d2zld(0.0))){
+        emit(f,"\tfsub\t%s,%s,%s\n",mregnames[r],mregnames[r],mregnames[r]);
+        return;
+      }
+      lab=addfpconst(o,typ);
+      if(sdp=use_sd(typ)){
+	if(GAS)
+	  emit(f,"\tl%s\t%s,%s%d@sda21(0)\n",ldt(typ),mregnames[r],labprefix,lab);
+	else
+	  emit(f,"\tl%s\t%s,%s%d(%s)\n",ldt(typ),mregnames[r],labprefix,lab,mregnames[sdp]);
+      }else{
+	BSET(regs_modified,tmp);
+        if(POWEROPEN){
+          emit(f,"\tl%s\t%s,%s%s%ld(%s)\n",ldt(LONG),mregnames[tmp],tocprefix,labprefix,(long)lab,mregnames[r2]);
+          emit(f,"\tl%s\t%s,0(%s)\n",ldt(typ),mregnames[r],mregnames[tmp]);
+        }else{
+          emit(f,"\tlis\t%s,%s%d@ha\n",mregnames[tmp],labprefix,lab);
+          emit(f,"\tl%s\t%s,%s%d@l(%s)\n",ldt(typ),mregnames[r],labprefix,lab,mregnames[tmp]);
+        }
+      }
+      return;
+    }
+    if(r==1) ierror(0);
+    l=hi(zm2l(vmax));
+    if(l){
+      emit(f,"\tlis\t%s,%ld\n",mregnames[r],l);
+      l=lo(zm2l(vmax));
+      if(l)
+	emit(f,"\taddi\t%s,%s,%ld\n",mregnames[r],mregnames[r],l);
+    }else{
+      emit(f,"\tli\t%s,%ld\n",mregnames[r],lo(vmax));
+    }
+    return;
+  }
+  if((o->flags&VAR)&&(o->v->storage_class==EXTERN||o->v->storage_class==STATIC)){
+    if(o->flags&VARADR){
+      load_address(f,r,o,POINTER);
+    }else{
+      if((sdp=use_sd(o->v->vtyp->flags))&&!(o->v->tattr&FAR)){
+        emit(f,"\tl%s\t%s,",ldt(typ),mregnames[r]);
+        emit_obj(f,o,typ);
+	if(GAS)
+	  emit(f,"@sda21(0)\n");
+	else
+	  emit(f,"(%s)\n",mregnames[sdp]);
+      }else{
+	BSET(regs_modified,tmp);
+        if(POWEROPEN){
+          zmax offset=o->val.vmax;
+          emit(f,"\tl%s\t%s,%s",ldt(LONG),mregnames[tmp],tocprefix);
+          o->val.vmax=l2zm(0L);emit_obj(f,o,POINTER);o->val.vmax=offset;
+          emit(f,"(%s)\n",mregnames[r2]);
+          if(hi(zm2l(offset))) emit(f,"\taddis\t%s,%s,%ld\n",mregnames[tmp],mregnames[tmp],hi(zm2l(offset)));
+          emit(f,"\tl%s\t%s,%ld(%s)\n",ldt(typ),mregnames[r],lo(zm2l(offset)),mregnames[tmp]);
+        }else{
+          if(BASERELOS4){
+            emit(f,"\taddis\t%s,%s,",mregnames[tmp],mregnames[bp32os4]);
+            emit_obj(f,o,typ);emit(f,"@brel@ha\n");
+            emit(f,"\tl%s\t%s,",ldt(typ),mregnames[r]);
+            emit_obj(f,o,typ);emit(f,"@brel@l(%s)\n",mregnames[tmp]);
+          }else if(BASERELMOS){
+            emit(f,"\taddis\t%s,%s,",mregnames[tmp],mregnames[bp32mos]);
+            emit_obj(f,o,typ);emit(f,"@drel@ha\n");
+            emit(f,"\tl%s\t%s,",ldt(typ),mregnames[r]);
+            emit_obj(f,o,typ);emit(f,"@drel@l(%s)\n",mregnames[tmp]);
+          }else{
+            emit(f,"\tlis\t%s,",mregnames[tmp]);
+            emit_obj(f,o,typ);emit(f,"@ha\n");
+            emit(f,"\tl%s\t%s,",ldt(typ),mregnames[r]);
+            emit_obj(f,o,typ);emit(f,"@l(%s)\n",mregnames[tmp]);
+          }
+        }
+      }
+    }
+  }else{
+    if((o->flags&(DREFOBJ|REG))==REG){
+      if(r!=o->reg)
+        emit(f,"\t%smr\t%s,%s\n",r>=33?"f":"",mregnames[r],mregnames[o->reg]);
+    }else if(!o->am&&(o->flags&(DREFOBJ|REG))==(REG|DREFOBJ)){
+      emit(f,"\tl%s\t%s,0(%s)\n",ldt(typ),mregnames[r],mregnames[o->reg]);
+    }else if(!o->am){
+      long off=real_offset(o);
+      if(off<=32767){
+        emit(f,"\tl%s\t%s,%ld(%s)\n",ldt(typ),mregnames[r],off,mregnames[fp]);
+      }else{
+	BSET(regs_modified,tmp);
+        emit(f,"\taddis\t%s,%s,%ld\n",mregnames[tmp],mregnames[fp],hi(off));
+        emit(f,"\tl%s\t%s,%ld(%s)\n",ldt(typ),mregnames[r],lo(zm2l(off)),mregnames[tmp]);
+      }
+    }else{
+      emit(f,"\tl%s%s%s\t%s,",ldt(typ),(o->am->flags&UPDATE)?"u":"",(o->am->flags&REG_IND)?"x":"",mregnames[r]);
+      emit_obj(f,o,typ);emit(f,"\n");
+    }
+  }
+}
+
+static void store_reg(FILE *f,int r,struct obj *o,int typ)
+/*  Generates code to store register r into memory object o.            */
+{
+  int tmp;
+  typ&=NQ;
+  if((o->flags&VAR)&&(o->v->storage_class==EXTERN||o->v->storage_class==STATIC)){
+    int tmp=t1;
+    if(tmp==r) tmp=t2;
+    if((sdp=use_sd(o->v->vtyp->flags))&&!(o->v->tattr&FAR)){
+      emit(f,"\tst%s\t%s,",sdt(typ),mregnames[r]);
+      emit_obj(f,o,typ);
+      if(GAS)
+	emit(f,"@sda21(0)\n");
+      else
+	emit(f,"(%s)\n",mregnames[sdp]);
+      return;
+    }else{
+      BSET(regs_modified,tmp);
+      if(POWEROPEN){
+        zmax offset=o->val.vmax;
+        emit(f,"\tl%s\t%s,%s",ldt(LONG),mregnames[tmp],tocprefix);
+        o->val.vmax=l2zm(0L);emit_obj(f,o,POINTER);o->val.vmax=offset;
+        emit(f,"(%s)\n",mregnames[r2]);
+        if(hi(zm2l(offset))) emit(f,"\taddis\t%s,%s,%ld\n",mregnames[tmp],mregnames[tmp],hi(zm2l(offset)));
+        emit(f,"\tst%s\t%s,%ld(%s)\n",sdt(typ),mregnames[r],lo(zm2l(offset)),mregnames[tmp]);
+        return;
+      }else{
+        if(BASERELOS4){
+          emit(f,"\taddis\t%s,%s,",mregnames[tmp],mregnames[bp32os4]);
+          emit_obj(f,o,typ);emit(f,"@brel@ha\n");
+          emit(f,"\tst%s\t%s,",sdt(typ),mregnames[r]);
+          emit_obj(f,o,typ);emit(f,"@brel@l(%s)\n",mregnames[tmp]);
+        }else if(BASERELMOS){
+          emit(f,"\taddis\t%s,%s,",mregnames[tmp],mregnames[bp32mos]);
+          emit_obj(f,o,typ);emit(f,"@drel@ha\n");
+          emit(f,"\tst%s\t%s,",sdt(typ),mregnames[r]);
+          emit_obj(f,o,typ);emit(f,"@drel@l(%s)\n",mregnames[tmp]);
+        }else{
+          emit(f,"\tlis\t%s,",mregnames[tmp]);
+          emit_obj(f,o,typ);emit(f,"@ha\n");
+          emit(f,"\tst%s\t%s,",sdt(typ),mregnames[r]);
+          emit_obj(f,o,typ);emit(f,"@l(%s)\n",mregnames[tmp]);
+        }
+        return;
+      }
+    }
+  }
+  if(!(o->flags&DREFOBJ)&&!o->am){
+    long off=real_offset(o);
+    if(r==t1) tmp=t2; else tmp=t1;
+    if(off<=32767){
+      emit(f,"\tst%s\t%s,%ld(%s)\n",sdt(typ),mregnames[r],off,mregnames[fp]);
+    }else{
+
+      BSET(regs_modified,tmp);
+      emit(f,"\taddis\t%s,%s,%ld\n",mregnames[tmp],mregnames[fp],hi(off));
+      emit(f,"\tst%s\t%s,%ld(%s)\n",sdt(typ),mregnames[r],lo(off),mregnames[tmp]);
+    }
+  }else{
+    if(!o->am){
+      emit(f,"\tst%s\t%s,",sdt(typ),mregnames[r]);
+      emit_obj(f,o,typ);emit(f,"\n");
+    }else{
+      emit(f,"\tst%s%s%s\t%s,",sdt(typ),(o->am->flags&UPDATE)?"u":"",(o->am->flags&REG_IND)?"x":"",mregnames[r]);
+      emit_obj(f,o,typ);emit(f,"\n");
+    }
+  }
+}
+
+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;
+}
+
+#if 1
+static char *dct[]={"","byte","2byte","4byte","4byte","4byte","4byte","4byte","4byte"};
+#else
+static char *dct[]={"","byte","short","long","long","long","long","long","long"};
+#endif
+static struct IC *do_refs(FILE *,struct IC *);
+static void pr(FILE *,struct IC *);
+static void function_top(FILE *,struct Var *,long);
+static void function_bottom(FILE *f,struct Var *,long);
+
+#define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
+
+static int q1reg,q2reg,zreg;
+
+static char *ccs[]={"eq","ne","lt","ge","le","gt",""};
+static char *logicals[]={"or","xor","and"};
+static char *record[]={"","."};
+static char *arithmetics[]={"slw","srw","add","sub","mullw","divw","mod"};
+static char *isimm[]={"","i"};
+
+static struct IC *do_refs(FILE *f,struct IC *p)
+/*  Does some pre-processing like fetching operands from memory to      */
+/*  registers etc.                                                      */
+{
+  int typ,typ1,reg,c=abs(p->code);
+
+  q1loaded=q2loaded=0;
+
+  /* cannot use q1typ, because p->code may have been negated */
+  if(c==CONVERT) 
+    typ=p->typf2;
+  else
+    typ=p->typf;
+
+  if((typ&NQ)==POINTER) typ=UNSIGNED|LONG;
+
+  if((c==SUB||c==SUBIFP)&&(p->q2.flags&(KONST|DREFOBJ))==KONST&&(typ&NQ)<=LLONG){
+    eval_const(&p->q2.val,typ);
+    if(zmleq(vmax,l2zm(32768L))&&zmleq(l2zm(-32767L),vmax)){
+      union atyps val;
+      if(c==SUB){
+        if(p->code==SUB) p->code=c=ADD; else p->code=c=-ADD;
+      }else{
+        if(p->code==SUBIFP) p->code=c=ADDI2P; else p->code=c=-ADDI2P;
+      }
+      c=abs(c);
+      val.vmax=zmsub(l2zm(0L),vmax);
+      eval_const(&val,MAXINT);
+      insert_const(&p->q2.val,typ);
+      p->typf=typ=(typ&~UNSIGNED);
+    }
+  }
+
+  q1reg=q2reg=zreg=0;
+  if(p->q1.flags&REG) q1reg=p->q1.reg;
+  if(p->q2.flags&REG) q2reg=p->q2.reg;
+  if((p->z.flags&(REG|DREFOBJ))==REG) zreg=p->z.reg;
+
+  if((p->q1.flags&(KONST|DREFOBJ))==KONST){
+    eval_const(&p->q1.val,typ);
+    if(ISFLOAT(typ)) reg=f1; else reg=t1;
+    if(c==ASSIGN&&zreg) reg=zreg;
+    if(c==SETRETURN&&p->z.reg) reg=p->z.reg;
+    if(c!=SUB||(typ&NQ)>LONG||!zmleq(vmax,l2zm(32767L))||!zmleq(l2zm(-32768L),vmax)){
+      load_reg(f,reg,&p->q1,typ,t1);
+      q1reg=reg;
+      q1loaded=1;
+    }
+  }else if(c!=ADDRESS){
+    if(ISFLOAT(typ)) reg=f1; else reg=t1;
+    if((c==ASSIGN||(c==CONVERT&&ISINT(p->typf2)))&&zreg>=1&&zreg<=32) reg=zreg;
+    if((c==ASSIGN||(c==CONVERT&&ISFLOAT(p->typf2)))&&zreg>=33&&zreg<=64) reg=zreg;
+    if(c==SETRETURN&&p->z.reg) reg=p->z.reg;
+    if(p->q1.am){
+      load_reg(f,reg,&p->q1,typ,t1);
+      q1reg=reg;
+      q1loaded=1;
+    }else{
+      if(p->q1.flags&&!q1reg){
+        if(p->q1.flags&DREFOBJ) {typ1=POINTER;reg=t1;} else typ1=typ;
+        if((typ1&NQ)<=POINTER){
+          int m=p->q1.flags;
+          p->q1.flags&=~DREFOBJ;
+          load_reg(f,reg,&p->q1,typ1,t1);
+          p->q1.flags=m;
+          q1reg=reg;
+	  q1loaded=1;
+        }
+      }
+      if((p->q1.flags&DREFOBJ)&&(typ&NQ)<=POINTER){
+        if(ISFLOAT(typ)) reg=f1; else reg=t1;
+        if((c==ASSIGN||(c==CONVERT&&ISINT(p->typf2)))&&zreg>=1&&zreg<=32) reg=zreg;
+	if((c==ASSIGN||(c==CONVERT&&ISFLOAT(p->typf2)))&&zreg>=33&&zreg<=64) reg=zreg;
+        if(c==SETRETURN&&p->z.reg) reg=p->z.reg;
+        if(p->q1.am)
+          load_reg(f,reg,&p->q1,typ,t1);
+        else
+          load_reg(f,reg,cam(IMM_IND,q1reg,0),typ,t1);
+        q1reg=reg;
+	q1loaded=1;
+      }
+    }
+  }
+  /* cannot use q2typ (see above) */
+  typ=p->typf;
+  if((p->q2.flags&(KONST|DREFOBJ))==KONST){
+    eval_const(&p->q2.val,typ);
+    if(ISFLOAT(typ)) reg=f2; else reg=t2;
+    if(ISFLOAT(typ)||c==DIV||c==SUB||c==MOD){
+      load_reg(f,reg,&p->q2,typ,t2);
+      q2reg=reg;
+      q2loaded=1;
+    }else{
+      if((c>=OR&&c<=AND)||(c==COMPARE&&(typ&UNSIGNED))){
+        if(!zumleq(vumax,ul2zum(65535UL))){
+          load_reg(f,reg,&p->q2,typ,t2);
+          q2reg=reg;
+	  q2loaded=1;
+        }
+      }else{
+        if(!zmleq(vmax,l2zm(32767L))||!zmleq(l2zm(-32768L),vmax)){
+          load_reg(f,reg,&p->q2,typ,t2);
+          q2reg=reg;
+	  q2loaded=1;
+        }
+      }
+    }
+  }else{
+    if(p->q2.am){
+      if(ISFLOAT(typ)) reg=f2; else reg=t2;
+      load_reg(f,reg,&p->q2,typ,t2);
+      q2reg=reg;
+      q2loaded=1;
+    }else{
+      if(p->q2.flags&&!q2reg){
+        if((p->q2.flags&DREFOBJ)) typ1=POINTER; else typ1=typ;
+        if(ISFLOAT(typ1)) reg=f2; else reg=t2;
+        if((typ1&NQ)<=POINTER){
+          int m=p->q2.flags;
+          p->q2.flags&=~DREFOBJ;
+          load_reg(f,reg,&p->q2,typ1,t2);
+          p->q2.flags=m;
+          q2reg=reg;
+	  q2loaded=1;
+        }
+      }
+      if((p->q2.flags&DREFOBJ)&&(typ&NQ)<=POINTER){
+        if(ISFLOAT(typ)) reg=f2; else reg=t2;
+        if(p->q2.am)
+          load_reg(f,reg,&p->q2,typ,t2);
+        else
+          load_reg(f,reg,cam(IMM_IND,q2reg,0),typ,t2);
+        q2reg=reg;
+	q2loaded=1;
+      }
+    }
+  }
+  if(p->z.am||(p->z.flags&&!isreg(z))){
+    typ=p->typf;
+    if(c!=ADDRESS&&ISFLOAT(typ)) zreg=f3; else zreg=t3;
+  }
+  if(q1reg){p->q1.flags=REG;p->q1.reg=q1reg;p->q1.am=0;}
+  if(q2reg){p->q2.flags=REG;p->q2.reg=q2reg;p->q2.am=0;}
+  return p;
+}
+static void pr(FILE *f,struct IC *p)
+     /*  Writes the destination register to the real destination if necessary.   */
+{
+  int typ=p->typf;
+  if(p->code==ADDRESS) typ=POINTER;
+  if(p->z.flags){
+    if(zreg>=74&&zreg<=86){printf("c=%d\n",p->code); ierror(0);}
+    if(p->z.am){
+      store_reg(f,zreg,&p->z,typ);
+    }else if(!isreg(z)){
+      if(p->z.flags&DREFOBJ){
+        if(p->z.flags&REG){
+          if(p->z.am)
+            store_reg(f,zreg,&p->z,typ);
+          else
+            store_reg(f,zreg,cam(IMM_IND,p->z.reg,0),typ);
+        }else{
+          int r;
+          if(t1==zreg) r=t2; else r=t1;
+          load_reg(f,r,&p->z,POINTER,r);
+          store_reg(f,zreg,cam(IMM_IND,r,0),typ);
+        }
+      }else{
+        store_reg(f,zreg,&p->z,typ);
+      }
+    }else{
+      if(p->z.reg!=zreg)
+        emit(f,"\t%smr\t%s,%s\n",(zreg>=33&&zreg<=64)?"f":"",mregnames[p->z.reg],mregnames[zreg]);
+    }
+  }
+}
+static int dwarf2_regnumber(int r)
+{
+  if(r==0) ierror(0);
+  if(r<=32)
+    return r-1;
+  else if(r<=64)
+    return r+6;
+  else
+    ierror(0);
+}
+static zmax dwarf2_fboffset(struct Var *v)
+{
+  struct obj o;
+  if(!v||(v->storage_class!=AUTO&&v->storage_class!=REGISTER)) ierror(0);
+  o.flags=VAR;
+  o.v=v;
+  o.val.vmax=l2zm(0L);
+  return l2zm(real_offset(&o));
+}
+static void dwarf2_print_frame_location(FILE *f,struct Var *v)
+{
+  struct obj o;
+  o.flags=REG;
+  o.reg=sp;
+  o.val.vmax=l2zm(0L);
+  o.v=0;
+  dwarf2_print_location(f,&o);
+}
+static void emit_obj(FILE *f,struct obj *p,int t)
+/*  Prints an object.                               */
+{
+  if(p->am){
+    if(p->am->flags&REG_IND) emit(f,"%s,%s",mregnames[p->am->offset],mregnames[p->am->base]);
+    if(p->am->flags&IMM_IND) emit(f,"%ld(%s)",p->am->offset,mregnames[p->am->base]);
+    return;
+  }
+  /*  if(p->flags&DREFOBJ) emit(f,"(");*/
+  if(p->flags&VAR) {
+    if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER){
+      if(p->flags&REG){
+        emit(f,"%s",mregnames[p->reg]);
+      }else{
+        emit(f,"%ld(%s)",real_offset(p),mregnames[fp]);
+      }
+    }else{
+      if(!zmeqto(l2zm(0L),p->val.vmax)){emitval(f,&p->val,MAXINT);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((p->flags&REG)&&!(p->flags&VAR)) emit(f,"%s",mregnames[p->reg]);
+  if(p->flags&KONST){
+    emitval(f,&p->val,t&NU);
+  }
+  /*  if(p->flags&DREFOBJ) emit(f,")");*/
+}
+static int exists_freereg(struct IC *p,int reg)
+/*  Test if there is a sequence of FREEREGs containing FREEREG reg. */
+{
+  while(p&&(p->code==FREEREG||p->code==ALLOCREG)){
+    if(p->code==FREEREG&&p->q1.reg==reg) return 1;
+    p=p->next;
+  }
+  return 0;
+}
+
+static size_t lsize;
+static bvtype *once,*twice;
+
+static void peephole(struct IC *p)
+/* Try to use addressing modes */
+{
+  int c,c2,r,cnt,maxlabel,uselr=0;struct IC *p2;struct AddressingMode *am;
+  if(cross_module){
+    lastlabel=0;
+    for(p2=p;p2;p2=p2->next){
+      if(p2->code>=LABEL&&p2->code<=BRA){
+	if(!lastlabel||p2->typf<lastlabel) lastlabel=p2->typf;
+	if(p->typf>maxlabel) maxlabel=p->typf;
+      }
+    }
+  }else{
+    maxlabel=label; /*FIXME*/
+  }
+  /*lsize=((label-lastlabel+1+7)/CHAR_BIT)*CHAR_BIT;*/
+  lsize=BVSIZE(label-lastlabel+1);
+  once=mymalloc(lsize);
+  twice=mymalloc(lsize);
+  memset(once,0,lsize);
+  memset(twice,0,lsize);
+  for(;p;p=p->next){
+    c=p->code;
+    if(c==CALL){
+      if(p->call_list==0){
+	uselr=1;
+      }else{
+	int i;
+	for(i=0;i<p->call_cnt;i++)
+	  if(!p->call_list[i].v->fi||
+	     !p->call_list[i].v->fi->inline_asm||
+	     !(p->call_list[i].v->fi->flags&ALL_REGS)||
+	     BTST(p->call_list[i].v->fi->regs_modified,lr))
+	    uselr=1;
+      }
+    }
+    if((q1typ(p)&NQ)==LLONG&&(c==MULT||c==DIV||c==MOD||c==LSHIFT||c==RSHIFT)) uselr=1;
+    if(c==CONVERT&&(q1typ(p)&NQ)==LLONG&&ISFLOAT(ztyp(p)&NQ)) uselr=1;
+    if(c==CONVERT&&(ztyp(p)&NQ)==LLONG&&ISFLOAT(q1typ(p)&NQ)) uselr=1;
+    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;
+    /* Test which labels are jumped to more than once. */
+    if((c>=BEQ&&c<=BRA)&&p->typf-lastlabel>=lsize*CHAR_BIT){
+      printf("lsize=%lu p->typf=%d lastlabel=%d\n",lsize,p->typf,lastlabel);
+      ierror(0);
+    }
+    if(c>=BEQ&&c<=BRA){
+      if(BTST(once,p->typf-lastlabel))
+        BSET(twice,p->typf-lastlabel);
+      else
+        BSET(once,p->typf-lastlabel);
+    }
+    /* Try test-opt */
+    if(c==TEST&&!(p->q1.flags&DREFOBJ)){
+      for(p2=p->prev;p2;p2=p2->prev){
+        c2=p2->code;
+        if(c2==NOP||c2==ALLOCREG||c2==FREEREG) continue;
+        if(c2==CALL||(c2>=LABEL&&c2<=BRA)) break;
+        if((p2->z.flags&DREFOBJ)&&(p->q1.flags&(REG|DREFOBJ))!=REG) break;
+        if(p->q1.flags==p2->z.flags&&p->q1.am==p2->z.am){
+          if(!(p->q1.flags&VAR)||(p->q1.v==p2->z.v&&zmeqto(p->q1.val.vmax,p2->z.val.vmax))){
+            if(!(p->q1.flags&REG)||p->q1.reg==p2->z.reg){
+              if(p->z.flags==0||(isreg(z)&&p->z.reg==cr0)){
+                if(p->typf==p2->typf&&(!(p->typf&UNSIGNED)||!multiple_ccs)){
+		  p2->ext.setcc=1;
+                }
+                break;
+              }
+            }
+          }
+        }
+      }
+    }
+    /* Try update */
+    if((c==ADDI2P||c==SUBIFP)&&isreg(q1)&&isreg(z)&&p->q1.reg==p->z.reg){
+      if((p->q2.flags&(KONST|DREFOBJ))==KONST){
+        eval_const(&p->q2.val,p->typf);
+        if(c==SUBIFP) vmax=zmsub(l2zm(0L),vmax);
+        if(zmleq(l2zm(-32768L),vmax)&&zmleq(vmax,l2zm(32767L))){
+          struct obj *o;
+          r=p->q1.reg;cnt=0;o=0;
+          for(p2=p->next;p2;p2=p2->next){
+            c2=p2->code;
+            if(c2==NOP||c2==ALLOCREG||c2==FREEREG) continue;
+            if((c2==CALL/*&&regscratch[r]*/)||(c2>=LABEL&&c2<=BRA)) break;
+            if((p2->q1.flags&(DREFOBJ|REG))==REG&&p2->q1.reg==r) break;
+            if((p2->q2.flags&(DREFOBJ|REG))==REG&&p2->q2.reg==r) break;
+            if((p2->z.flags&(DREFOBJ|REG))==REG&&p2->z.reg==r) break;
+            if((p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r) cnt|=1;
+            if((p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r) cnt|=2;
+            if((p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r) cnt|=4;
+            if((cnt&3)==3) break;
+            if(cnt){
+	      if(cnt&1){
+		if((q1typ(p2)&NQ)==LLONG) break;
+		o=&p2->q1;
+	      }else if(cnt&2){
+		if((q2typ(p2)&NQ)==LLONG) break;
+		o=&p2->q2;
+	      }else{
+		if((ztyp(p2)&NQ)==LLONG) break;
+		o=&p2->z;
+	      }
+              if(p2->code==ASSIGN&&((p2->typf&NQ)>POINTER||!zmeqto(p2->q2.val.vmax,sizetab[p2->typf&NQ])))
+                break;
+              o->am=am=mymalloc(sizeof(*am));
+              o->am->flags=(IMM_IND|UPDATE);
+              o->am->base=r;
+              o->am->offset=zm2l(vmax);
+              p->code=c=NOP;
+              break;
+            }
+          }
+        }
+      }
+    }
+    /* Try const(reg) */
+#ifndef oldpeep
+    if((c==ADDI2P||c==SUBIFP)&&isreg(z)&&(p->q2.flags&(KONST|DREFOBJ))==KONST){
+      int base;zmax of;struct obj *o;
+      eval_const(&p->q2.val,p->typf);
+      if(c==SUBIFP) of=zmsub(l2zm(0L),vmax); else of=vmax;
+      if(zmleq(l2zm(-32768L),vmax)&&zmleq(vmax,l2zm(32767L))){
+	r=p->z.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(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) break;
+	      o=&p2->q1;
+	    }
+	    if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
+	      if(o) break;
+	      o=&p2->q2;
+	    }
+	    if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
+	      if(o) 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);
+		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;
+	  }
+        }
+      }
+    }
+#else
+    if((c==ADDI2P||c==SUBIFP)&&(p->q2.flags&(KONST|DREFOBJ))==KONST&&isreg(z)){
+      int base;zmax of;
+      p2=p->next;
+      while(p2&&(p2->code==FREEREG||p2->code==ALLOCREG)) p2=p2->next;
+      if(p2) c2=p2->code; else c2=0;
+      eval_const(&p->q2.val,p->typf);
+      if(c==SUBIFP) of=zmsub(l2zm(0L),vmax); else of=vmax;
+      r=p->z.reg;
+      if(isreg(q1)) base=p->q1.reg; else base=r;
+      if(c2&&zmleq(l2zm(-32768L),of)&&zmleq(of,l2zm(32767L))&&c2!=CALL&&(c2<LABEL||c2>BRA)
+         &&(c2!=ASSIGN||((p2->typf&NQ)<=POINTER&&zmeqto(p2->q2.val.vmax,sizetab[p2->typf&NQ])))
+         &&c2!=ADDRESS&&(((p2->z.flags&(DREFOBJ|REG))==REG&&p2->z.reg==r&&p2->q2.flags==0)||exists_freereg(p2->next,r))){
+        if(((p2->q1.flags&(REG|DREFOBJ))!=REG||p2->q1.reg!=r)
+           &&((p2->q2.flags&(REG|DREFOBJ))!=REG||p2->q2.reg!=r)){
+          cnt=0;
+          if((p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r){
+            p2->q1.am=am=mymalloc(sizeof(*am));
+            p2->q1.am->flags=IMM_IND;
+            p2->q1.am->base=base;
+            p2->q1.am->offset=zm2l(of);
+            cnt++;
+          }
+          if((p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
+            p2->q2.am=am=mymalloc(sizeof(*am));
+            p2->q2.am->flags=IMM_IND;
+            p2->q2.am->base=base;
+            p2->q2.am->offset=zm2l(of);
+            cnt++;
+          }
+          if((p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
+            p2->z.am=am=mymalloc(sizeof(*am));
+            p2->z.am->flags=IMM_IND;
+            p2->z.am->base=base;
+            p2->z.am->offset=zm2l(of);
+            cnt++;
+          }
+          if(isreg(q1)){
+            p->code=NOP;p->q1.flags=p->q2.flags=p->z.flags=0;
+          }else{
+            p->code=ASSIGN;p->q2.flags=0;
+          }
+          if(cnt==1&&((p2->q1.flags&(DREFOBJ|REG))!=REG||p2->q1.reg!=base)
+             &&((p2->q2.flags&(DREFOBJ|REG))!=REG||p2->q2.reg!=base)
+             &&((p2->z.flags&(DREFOBJ|REG))!=REG||p2->z.reg!=base) ){
+            /* Can we use update? */
+            p2=p2->next;
+            while(p2&&(p2->code==FREEREG||p2->code==ALLOCREG)) p2=p2->next;
+            if(p2){
+              c2=p2->code;
+              if(c2==ADDI2P||c2==SUBIFP){
+                if((p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==base
+                   &&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg==base
+                   &&(p2->q2.flags&(KONST|DREFOBJ))==KONST ){
+                  eval_const(&p2->q2.val,p2->typf);
+                  if(c2==SUBIFP) vmax=zmsub(l2zm(0L),vmax);
+                  if(zmeqto(vmax,of)){
+                    am->flags|=UPDATE;
+                    p2->code=NOP;
+                  }
+                }
+              }
+            }
+          }
+          continue;
+        }
+      }
+    }
+#endif
+    /* Try reg,reg */
+#ifndef oldpeep
+    if(c==ADDI2P&&isreg(q2)&&isreg(z)&&(isreg(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||(q1typ(p2)&NQ)==LLONG) break;
+            o=&p2->q1;
+          }
+          if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
+            if(o||(q2typ(p2)&NQ)==LLONG) break;
+            o=&p2->q2;
+          }
+          if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
+            if(o||(ztyp(p2)&NQ)==LLONG) 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=REG_IND;
+              am->base=base;
+              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;
+        }
+      }
+    }
+#else
+    if(c==ADDI2P&&isreg(q2)&&isreg(z)&&p->q2.reg!=p->z.reg){
+      int base,idx;
+      p2=p->next;
+      while(p2&&(p2->code==FREEREG||p2->code==ALLOCREG)) p2=p2->next;
+      if(p2) c2=p2->code; else c2=0;
+      r=p->z.reg;idx=p->q2.reg;
+      if(isreg(q1)) base=p->q1.reg; else base=r;
+      if(c2&&c2!=CALL&&(c2<LABEL||c2>BRA)
+         &&(c2!=ASSIGN||((p2->typf&NQ)<=POINTER&&zmeqto(p2->q2.val.vmax,sizetab[p2->typf&NQ])))
+         &&c2!=ADDRESS&&exists_freereg(p2->next,r)){
+        if(((p2->q1.flags&(REG|DREFOBJ))!=REG||p2->q1.reg!=r)
+           &&((p2->q2.flags&(REG|DREFOBJ))!=REG||p2->q2.reg!=r) ){
+          cnt=0;
+          if((p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r){
+            p2->q1.am=am=mymalloc(sizeof(*am));
+            p2->q1.am->flags=REG_IND;
+            p2->q1.am->base=base;
+            p2->q1.am->offset=idx;
+            cnt++;
+          }
+          if((p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
+            p2->q2.am=am=mymalloc(sizeof(*am));
+            p2->q2.am->flags=REG_IND;
+            p2->q2.am->base=base;
+            p2->q2.am->offset=idx;
+            cnt++;
+          }
+          if((p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
+            p2->z.am=am=mymalloc(sizeof(*am));
+            p2->z.am->flags=REG_IND;
+            p2->z.am->base=base;
+            p2->z.am->offset=idx;
+            cnt++;
+          }
+          if(isreg(q1)){
+            p->code=NOP;p->q1.flags=p->q2.flags=p->z.flags=0;
+          }else{
+            p->code=ASSIGN;p->q2.flags=0;
+          }
+          if(cnt==1&&((p2->q1.flags&(DREFOBJ|REG))!=REG||p2->q1.reg!=base)
+             &&((p2->q2.flags&(DREFOBJ|REG))!=REG||p2->q2.reg!=base)
+             &&((p2->z.flags&(DREFOBJ|REG))!=REG||p2->z.reg!=base) ){
+            /* Can we use update? */
+            p2=p2->next;
+            while(p2&&(p2->code==FREEREG||p2->code==ALLOCREG)) p2=p2->next;
+            if(p2){
+              c2=p2->code;
+              if(c2==ADDI2P){
+                if((p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==base
+                   &&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg==base
+                   &&(p2->q2.flags&(REG|DREFOBJ))==REG&&p2->q2.reg==idx){
+                  am->flags|=UPDATE;
+                  p2->code=NOP;
+                }
+              }
+            }
+          }
+          continue;
+        }
+      }
+    }
+#endif
+  }
+  if(!uselr) function_calls=0;
+}
+
+static void toc_entry(FILE *f,struct Var *v)
+/*  Create a toc-entry.  */
+{
+  if(!use_sd(v->vtyp->flags)||(v->tattr&FAR)){
+    if(v->storage_class==STATIC&&!ISFUNC(v->vtyp->flags)){
+      emit(f,tocname);
+      emit(f,"%s%s%ld:\n",tocprefix,labprefix,zm2l(v->offset));
+      emit(f,"\t.long\t%s%ld\n",labprefix,zm2l(v->offset));
+    }else{
+      if(!ISFUNC(v->vtyp->flags)){
+        emit(f,tocname);
+        emit(f,"%s%s%s:\n",tocprefix,idprefix,v->identifier);
+        emit(f,"\t.long\t%s%s\n",idprefix,v->identifier);
+      }
+      if(v->storage_class==EXTERN)
+        emit(f,"\t.global\t%s%s%s\n",tocprefix,idprefix,v->identifier);
+    }
+    if(f) section=TOC;
+  }
+}
+
+static int savereg(struct Var *v,int i)
+{
+  if(v->tattr&(SYSCALL|NOSAVE)) return 0;
+  if(vlas&&i==fp) return 1;
+  if((i==sd&&(v->tattr&SAVEDS))||(regused[i]&&!regscratch[i]&&!regsa[i])
+     ||((v->tattr&SAVEALL)&&i<=32&&(regscratch[i]||i==t1||i==t2||i==t3)&&((!v->fi)||(!(v->fi->flags&ALL_REGS))||BTST(v->fi->regs_modified,i)) ))
+    return 1;
+  return 0;
+}
+
+static int stmw,stme;
+
+static void function_top(FILE *f,struct Var *v,long offset)
+/*  Generates function top.                             */
+{
+  int i,preg;long of;
+  if(POWEROPEN) toc_entry(f,v);
+  if(mregnames[1]!=regnames[1]) emit(f,"#vsc elf\n");
+  if(g_flags[0]&USEDFLAG) emit(f,"#vsc cpu %s\n",g_flags_val[0].p);
+  if(g_flags[1]&USEDFLAG) emit(f,"#vsc fpu %s\n",g_flags_val[1].p);
+  if(!special_section(f,v)&&section!=CODE){emit(f,codename);if(f) section=CODE;}
+  if(!GAS) emit(f,"\t.sdreg\t%s\n",mregnames[sd]);
+  if(!optsize) emit(f,"\t.align\t4\n");
+  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));
+  frameoffset=minframe+maxpushed;
+  framesize=frameoffset+offset;
+  stme=0;
+  for(i=1;i<=64;i++){
+    if(savereg(v,i)){
+      if(i<=32) framesize+=4; else framesize+=8;
+      if(i<=32&&stme==0) stme=i;
+    }else{
+      if(i<=32) stme=0;
+    }
+  }
+  if(stme==32||!(g_flags[11]&USEDFLAG)) stme=0;
+  for(crsave=0,i=65;i<=72;i++)
+    if((regused[i]&&!regscratch[i]&&!regsa[i])) crsave=1;
+  if(crsave&&!POWEROPEN) framesize+=4;
+  if(framesize==minframe&&((v->tattr&(SYSCALL))||(function_calls==0&&!crsave))) framesize=frameoffset=0;
+  if(EABI)
+    framesize=(framesize+7)/8*8;
+  else
+    framesize=(framesize+15)/16*16;
+  stack=framesize;
+  stack_valid=1;
+  if(v->tattr&SYSCALL){
+    emit(f,"#barrier\n");
+    emit(f,"\tmtspr\t81,0\n");
+    emit(f,"#barrier\n");
+    emit(f,"\tstwu\t%s,-4(%s)\n",mregnames[t1],mregnames[sp]);
+    emit(f,"\tmflr\t%s\n",mregnames[t1]);
+    emit(f,"\tstwu\t%s,-4(%s)\n",mregnames[t1],mregnames[sp]);
+    emit(f,"\tbl\t%s__syscall_init\n",idprefix);
+    /*FIXME: das koennte man evtl. noch sparen */
+    emit(f,"\taddi\t%s,%s,-8\n",mregnames[sp],mregnames[sp]);
+  }else if(v->tattr&NOSAVE){
+    /* nothing */
+  }else if(function_calls||(stack_check&&framesize)){
+    emit(f,"\tmflr\t%s\n",mregnames[t1]);
+    BSET(regs_modified,t1);
+  }
+  if(stack_check&&framesize){
+    BSET(regs_modified,t2);
+    if(framesize<=32767){
+      emit(f,"\tli\t%s,%ld\n",mregnames[t2],framesize);
+    }else{
+      emit(f,"\tlis\t%s,%ld\n",mregnames[t2],hi(framesize));
+      emit(f,"\taddi\t%s,%s,%ld\n",mregnames[t2],mregnames[t2],lo(framesize));
+    }     
+    emit(f,"\tbl\t%s__stack_check\n",idprefix);
+    if(!function_calls){
+      emit(f,"\tmtlr\t%s\n",mregnames[t1]);
+      BSET(regs_modified,lr);
+    }
+  }
+  if(function_calls&&!(v->tattr&(SYSCALL|NOSAVE))&&framesize>=32760){
+    if(POWEROPEN)
+      emit(f,"\tst%s\t%s,8(%s)\n",sdt(LONG),mregnames[t1],mregnames[sp]);
+    else
+      emit(f,"\tst%s\t%s,4(%s)\n",sdt(LONG),mregnames[t1],mregnames[sp]);
+  }
+  of=minframe+maxpushed+offset;
+  if(framesize!=0){
+    if(framesize<=32767){
+      emit(f,"\tstwu\t%s,-%ld(%s)\n",mregnames[sp],framesize,mregnames[sp]);
+      preg=sp;
+    }else{
+      BSET(regs_modified,t1);
+      BSET(regs_modified,t2);
+      emit(f,"\tmr\t%s,%s\n",mregnames[t2],mregnames[sp]);
+      emit(f,"\tlis\t%s,%ld\n",mregnames[t1],hi(-framesize));
+      emit(f,"\taddi\t%s,%s,%ld\n",mregnames[t1],mregnames[t1],lo(-framesize));
+      emit(f,"\tstwux\t%s,%s,%s\n",mregnames[sp],mregnames[sp],mregnames[t1]);
+      preg=t2;of-=framesize;
+    }
+  }
+  if(crsave&&!(v->tattr&NOSAVE)){
+    BSET(regs_modified,t3);
+    if(POWEROPEN){
+      emit(f,"\tmfcr\t%s\n\tst%s\t%s,4(%s)\n",mregnames[t3],sdt(LONG),mregnames[t3],mregnames[preg]);
+    }else{
+      emit(f,"\tmfcr\t%s\n\tst%s\t%s,%ld(%s)\n",mregnames[t3],sdt(LONG),mregnames[t3],of,mregnames[preg]);
+      of+=4;
+    }
+  }
+  for(i=1;i<=64;i++){
+    if(savereg(v,i)){
+      if(i<=32){
+	if(i==stme){
+          emit(f,"\tstmw\t%s,%ld(%s)\n",mregnames[stme],of,mregnames[preg]);
+          of+=(32-stme+1)*4;
+          i=32;
+        }else{
+          emit(f,"\tst%s\t%s,%ld(%s)\n",sdt(LONG),mregnames[i],of,mregnames[preg]);
+          of+=4;
+        }
+      }else{
+        emit(f,"\tst%s\t%s,%ld(%s)\n",sdt(DOUBLE),mregnames[i],of,mregnames[preg]);
+        of+=8;
+      }
+    }
+  }
+  if(function_calls&&!(v->tattr&(SYSCALL|NOSAVE))&&framesize<32760){
+    if(POWEROPEN)
+      emit(f,"\tst%s\t%s,%ld(%s)\n",sdt(LONG),mregnames[t1],framesize+8,mregnames[sp]);
+    else
+      emit(f,"\tst%s\t%s,%ld(%s)\n",sdt(LONG),mregnames[t1],framesize+4,mregnames[sp]);
+  }
+  if((v->tattr&SAVEDS)&&(SMALLDATA||BASERELMOS||POWEROPEN)){
+    if(POWEROPEN){
+      emit(f,"\t.global\t%s__getr2\n",idprefix);
+      if(!function_calls)
+        emit(f,"\tmflr\t%s\n",mregnames[t2]);
+      emit(f,"\tbl\t%s__getr2\n",idprefix);
+      if(!function_calls){
+        emit(f,"\tmtlr\t%s\n",mregnames[t2]);
+	BSET(regs_modified,lr);
+      }
+    }else{
+      if(BASERELMOS){
+        emit(f,"\t.global\t%s__restore_r13\n",idprefix);
+        emit(f,"\tbl\t%s__restore_r13\n",idprefix);
+      }else{
+        emit(f,"\tlis\t%s,%s_SDA_BASE_@ha\n",mregnames[sd],idprefix);
+        emit(f,"\taddi\t%s,%s,%s_SDA_BASE_@l\n",mregnames[sd],mregnames[sd],idprefix);
+      }
+    }
+  }
+  if(v->tattr&BREL){
+    if(BASERELOS4){
+      emit(f,"\t.global\t%s__baserel_get_addr\n",idprefix);
+      emit(f,"\tbl\t%s__baserel_get_addr\n",idprefix);
+    }
+  }
+  if(vlas){
+    emit(f,"\tmr\t%s,%s\n",mregnames[fp],mregnames[sp]);
+    emit(f,"\t.set\t____fo,%ld\n",frameoffset);
+  }
+}
+static void function_bottom(FILE *f,struct Var *v,long offset)
+/*  Generates function bottom.                          */
+{
+  int i,preg;long of;
+  if(v->tattr&SYSCALL){
+    emit(f,"\tb\t%s__dispatch\n",idprefix);
+  }else{
+    of=minframe+maxpushed+offset;
+    if(framesize<=32767){
+      preg=sp;
+    }else{
+      emit(f,"\tlwz\t%s,0(%s)\n",mregnames[t2],mregnames[sp]);
+      preg=t2;of-=framesize;
+    }
+    if(crsave&&!(v->tattr&NOSAVE)){
+      if(POWEROPEN){
+	emit(f,"\tl%s\t%s,8(%s)\n\tmtcr\t%s\n",ldt(LONG),mregnames[t1],mregnames[preg],mregnames[t1]);
+      }else{
+	emit(f,"\tl%s\t%s,%ld(%s)\n\tmtcr\t%s\n",ldt(LONG),mregnames[t1],of,mregnames[preg],mregnames[t1]);
+	of+=4;
+      }
+    }
+    if(function_calls&&!(v->tattr&NOSAVE)&&framesize<32760){
+      BSET(regs_modified,lr);
+      if(POWEROPEN)
+	emit(f,"\tl%s\t%s,%ld(%s)\n",ldt(LONG),mregnames[t1],framesize+8,mregnames[sp]);
+      else
+	emit(f,"\tl%s\t%s,%ld(%s)\n",ldt(LONG),mregnames[t1],framesize+4,mregnames[sp]);
+    }
+    for(i=1;i<=64;i++){
+      if(savereg(v,i)){
+	if(i<=32){
+	  if(i==stme){
+	    emit(f,"\tlmw\t%s,%ld(%s)\n",mregnames[stme],of,mregnames[preg]);
+	    of+=(32-stme+1)*4;
+	    i=32;
+	  }else{
+	    emit(f,"\tl%s\t%s,%ld(%s)\n",ldt(LONG),mregnames[i],of,mregnames[preg]);
+	    of+=4;
+	  }
+	}else{
+	  emit(f,"\tl%s\t%s,%ld(%s)\n",ldt(DOUBLE),mregnames[i],of,mregnames[preg]);
+	  of+=8;
+	}
+      }
+    }
+    if(framesize){
+      if(framesize<=32767)
+	emit(f,"\taddi\t%s,%s,%ld\n",mregnames[sp],mregnames[sp],framesize);
+      else
+	emit(f,"\tmr\t%s,%s\n",mregnames[sp],mregnames[preg]);
+    }
+    if(function_calls&&!(v->tattr&NOSAVE)){
+      if(framesize<32760){
+	emit(f,"\tmtlr\t%s\n",mregnames[t1]);
+      }else{
+	BSET(regs_modified,lr);
+	if(POWEROPEN)
+	  emit(f,"\tl%s\t%s,8(%s)\n\tmtlr\t%s\n",ldt(LONG),mregnames[t1],mregnames[sp],mregnames[t1]);
+	else
+	  emit(f,"\tl%s\t%s,4(%s)\n\tmtlr\t%s\n",ldt(LONG),mregnames[t1],mregnames[sp],mregnames[t1]);
+      }
+    }
+    emit(f,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(all_regs&&v->fi) v->fi->flags|=ALL_REGS;
+}
+
+static int balign(struct obj *o)
+/*  Liefert die unteren 2 Bits des Objekts. 1 wenn unklar. */
+{
+  int sc;
+  if(o->flags&DREFOBJ) return 1;
+  if(o->am) ierror(0);
+  if(!(o->flags&VAR)) ierror(0);
+  sc=o->v->storage_class;
+  if(sc==EXTERN||sc==STATIC){
+    /* Alle statischen Daten werden vom cg auf 32bit alignt. */
+    return zm2l(zmand(o->val.vmax,l2zm(3L)));
+  }
+  if(sc==AUTO||sc==REGISTER){
+    zmax of=o->v->offset;
+    if(!zmleq(l2zm(0L),of))
+      of=zmsub(l2zm(0L),zmadd(of,maxalign));
+    return zm2l(zmand(zmadd(of,o->val.vmax),l2zm(3L)));
+  }
+  ierror(0);
+}
+
+/* load hiword of a long long object */
+static void load_hword(FILE *f,int r,struct obj *o,int t,int tmp)
+{
+  struct rpair rp;
+  BSET(regs_modified,r);
+  if(o->flags&KONST){
+    static struct obj cobj;
+    cobj.flags=KONST;
+    eval_const(&o->val,t);
+    vumax=zumand(zumrshift(vumax,ul2zum(32UL)),ul2zum(0xffffffff)); 
+    cobj.val.vulong=zum2zul(vumax);
+    load_reg(f,r,&cobj,UNSIGNED|LONG,tmp);
+  }else if(!o->am&&(o->flags&DREFOBJ)){
+    if(!(o->flags&REG)) ierror(0);
+    emit(f,"\tlwz\t%s,0(%s)\n",mregnames[r],mregnames[o->reg]);
+  }else if(!o->am&&(o->flags&REG)){
+    struct rpair rp;
+    if(!reg_pair(o->reg,&rp)) 
+      ierror(0);
+    if(rp.r1!=r)
+      emit(f,"\tmr\t%s,%s\n",mregnames[r],mregnames[rp.r1]);
+  }else{
+    load_reg(f,r,o,UNSIGNED|LONG,tmp);
+  }
+}
+
+/* load loword of a long long object */
+static void load_lword(FILE *f,int r,struct obj *o,int t,int tmp)
+{
+  struct rpair rp;
+  BSET(regs_modified,r);
+  if(o->flags&KONST){
+    static struct obj cobj;
+    cobj.flags=KONST;
+    eval_const(&o->val,t);
+    vumax=zumand(vumax,ul2zum(0xffffffff)); 
+    cobj.val.vulong=zum2zul(vumax);
+    load_reg(f,r,&cobj,UNSIGNED|LONG,tmp);
+  }else if(o->am){
+    if(o->am->flags!=IMM_IND) ierror(0);
+    o->am->offset+=4;
+    load_reg(f,r,o,UNSIGNED|LONG,tmp);
+    o->am->offset-=4;   
+  }else if(o->flags&DREFOBJ){
+    if(!(o->flags&REG)) ierror(0);
+    emit(f,"\tlwz\t%s,4(%s)\n",mregnames[r],mregnames[o->reg]);
+  }else if(o->flags&REG){
+    if(!reg_pair(o->reg,&rp)) ierror(0);
+    if(rp.r2!=r)
+      emit(f,"\tmr\t%s,%s\n",mregnames[r],mregnames[rp.r2]);
+  }else{
+    o->val.vmax=zmadd(o->val.vmax,l2zm(4L));
+    load_reg(f,r,o,UNSIGNED|LONG,tmp);
+    o->val.vmax=zmsub(o->val.vmax,l2zm(4L));
+  }
+}    
+/* store hiword of a long long object */
+static void store_hword(FILE *f,int r,struct obj *o)
+{
+  struct rpair rp;
+  if(!o->am&&(o->flags&DREFOBJ)){
+    if(!(o->flags&REG)) ierror(0);
+    emit(f,"\tstw\t%s,0(%s)\n",mregnames[r],mregnames[o->reg]);
+  }else if(!o->am&&(o->flags&REG)){
+    if(!reg_pair(o->reg,&rp)) ierror(0);
+    if(rp.r1!=r)
+      emit(f,"\tmr\t%s,%s\n",mregnames[rp.r1],mregnames[r]);
+  }else{
+    store_reg(f,r,o,UNSIGNED|LONG);
+  }
+}
+
+/* store loword of a long long object */
+static void store_lword(FILE *f,int r,struct obj *o)
+{
+  struct rpair rp;
+  if(o->am){
+    if(o->am->flags!=IMM_IND) ierror(0);
+    o->am->offset+=4;
+    store_reg(f,r,o,UNSIGNED|LONG);
+    o->am->offset-=4;
+  }else if(o->flags&DREFOBJ){
+    if(!(o->flags&REG)) ierror(0);
+    emit(f,"\tstw\t%s,4(%s)\n",mregnames[r],mregnames[o->reg]);
+  }else if(o->flags&REG){
+    if(!reg_pair(o->reg,&rp)) ierror(0);
+    if(rp.r2!=r)
+      emit(f,"\tmr\t%s,%s\n",mregnames[rp.r2],mregnames[r]);
+  }else{
+    o->val.vmax=zmadd(o->val.vmax,l2zm(4L));
+    store_reg(f,r,o,UNSIGNED|LONG);
+    o->val.vmax=zmsub(o->val.vmax,l2zm(4L));
+  }
+}
+/* if object cannot be dereferenced with a single load, load its address
+   in register r (!=r0) and modify the object */
+static void create_loadable(FILE *f,struct obj *o,int r)
+{
+  struct rpair rp;
+  if(o->am) return;
+  if((o->flags&(REG|DREFOBJ))==DREFOBJ){
+    o->flags&=~DREFOBJ;
+    load_reg(f,r,o,POINTER,r);
+    o->flags|=(REG|DREFOBJ);
+    o->reg=r;
+  }
+  if((o->flags&(VAR|REG))==VAR){
+    if((o->v->storage_class==STATIC||o->v->storage_class==EXTERN)&&(!use_sd(o->v->vtyp->flags)||(o->v->tattr&FAR))){
+      load_address(f,r,o,POINTER);
+      o->reg=r;
+      o->flags=(REG|DREFOBJ);
+    }
+    if((o->v->storage_class==AUTO||o->v->storage_class==REGISTER)&&real_offset(o)>32760){
+      load_address(f,r,o,POINTER);
+      o->reg=r;
+      o->flags=(REG|DREFOBJ);
+    }
+  }
+}
+
+static int get_reg()
+{
+  int i;
+  for(i=2;i<=32;i++){
+    if(!regs[i]&&(regscratch[i]||regused[i]))
+      break;
+  }
+  if(i<=32){
+    BSET(regs_modified,i);
+    return i;
+  }
+  return 0;
+}
+
+static int handle_llong(FILE *f,struct IC *p)
+{
+  int c=p->code,t,savemask=0;char *libfuncname;
+  int msp;long mtmpoff;
+
+  t=(ztyp(p)&NU);
+
+  if(c==ADDRESS) return 0;
+
+
+  if(c==GETRETURN){
+    create_loadable(f,&p->z,t1);
+    if(!reg_pair(p->q1.reg,&rp)) ierror(0);
+    store_hword(f,rp.r1,&p->z);
+    store_lword(f,rp.r2,&p->z);
+    p->z.flags=0;
+    return 1;
+  }
+
+  if(c==SETRETURN){
+    create_loadable(f,&p->q1,t1);
+    if(!reg_pair(p->z.reg,&rp)) ierror(0);
+    load_hword(f,rp.r1,&p->q1,q1typ(p),t2);
+    load_lword(f,rp.r2,&p->q1,q1typ(p),t2);
+    p->z.flags=0;
+    return 1;
+  }
+
+  if(c==CONVERT&&(q1typ(p)&NQ)==LLONG&&(ztyp(p)&NQ)==LLONG){
+    p->code=c=ASSIGN;
+    p->q2.val.vmax=sizetab[LLONG];
+  }
+
+  if(c==ASSIGN||c==PUSH){
+    int r;
+    create_loadable(f,&p->q1,t1);
+    if(c==ASSIGN){
+      create_loadable(f,&p->z,t2);
+    }else{
+      pushed=(pushed+3)/4*4;
+      if(align_arguments)
+	pushed=(pushed+7)/8*8;
+    }
+    if(isreg(z)){
+      if(!reg_pair(p->z.reg,&rp)) ierror(0);
+      load_hword(f,rp.r1,&p->q1,q1typ(p),t1);
+    }else{
+      if(isreg(q1)){
+	if(!reg_pair(p->q1.reg,&rp)) ierror(0);
+	r=rp.r1;
+      }else{
+	if(p->q1.flags&KONST)
+	  r=t1;
+	else
+	  r=t3;
+	load_hword(f,r,&p->q1,q1typ(p),t1);
+      }
+      if(c==ASSIGN){
+	store_hword(f,r,&p->z);
+      }else{
+	emit(f,"\tstw\t%s,%ld(%s)\n",mregnames[r],pushed+minframe,mregnames[sp]);
+	pushed+=4;
+      }
+    }
+    if(isreg(z)){
+      if(!reg_pair(p->z.reg,&rp)) ierror(0);
+      load_lword(f,rp.r2,&p->q1,q1typ(p),t1);
+    }else{
+      if(isreg(q1)){
+	if(!reg_pair(p->q1.reg,&rp)) ierror(0);
+	r=rp.r2;
+      }else{
+	if(p->q1.flags&KONST)
+	  r=t1;
+	else
+	  r=t3;
+	load_lword(f,r,&p->q1,q1typ(p),t1);
+      }
+      if(c==ASSIGN){
+	store_lword(f,r,&p->z);
+      }else{
+	emit(f,"\tstw\t%s,%ld(%s)\n",mregnames[r],pushed+minframe,mregnames[sp]);
+	pushed+=4;
+      }    
+    }
+    p->z.flags=0;
+    return 1;
+  }
+
+  if(c==CONVERT&&(t&NQ)<LLONG){
+    if(isreg(q1)){
+      if(!reg_pair(p->q1.reg,&rp)) ierror(0);
+      zreg=rp.r2;
+    }else{
+      int r;
+      if(!p->q1.am&&(p->q1.flags&(REG|DREFOBJ))==DREFOBJ)
+        create_loadable(f,&p->q1,t1);
+      if(isreg(z))
+        r=p->z.reg;
+      else
+        r=t1;
+      load_lword(f,r,&p->q1,q1typ(p),t2);
+      zreg=r;
+    }
+    return 1;               
+  }
+  if(c==CONVERT&&(q1typ(p)&NQ)<LLONG){
+    int zl,zh,told=q1typ(p);
+    if(isreg(z)){
+      if(!reg_pair(p->z.reg,&rp)) ierror(0);
+      zh=rp.r1;
+      zl=rp.r2;
+    }else{
+      zl=t2;
+      zh=t3;
+    }
+    if(!p->q1.am&&(p->q1.flags&(REG|DREFOBJ))==DREFOBJ)
+      create_loadable(f,&p->q1,t1);
+    load_reg(f,zl,&p->q1,q1typ(p),t1);
+    if(told&UNSIGNED){
+      if((told&NQ)==CHAR)
+	emit(f,"\tclrlwi\t%s,%s,24\n",mregnames[zl],mregnames[zl]);
+      if((told&NQ)==SHORT)
+	emit(f,"\tclrlwi\t%s,%s,16\n",mregnames[zl],mregnames[zl]);
+      emit(f,"\tli\t%s,0\n",mregnames[zh]);
+    }else{
+      if((told&NQ)==CHAR)
+	emit(f,"\textsb\t%s,%s\n",mregnames[zl],mregnames[zl]);
+      if((told&NQ)==SHORT)
+	emit(f,"\textsh\t%s,%s\n",mregnames[zl],mregnames[zl]);
+      emit(f,"\tsrawi\t%s,%s,31\n",mregnames[zh],mregnames[zl]);
+    }
+    create_loadable(f,&p->z,t1);
+    store_lword(f,zl,&p->z);
+    store_hword(f,zh,&p->z);
+    p->z.flags=0;
+    return 1;
+  }
+
+  if(c==TEST){
+    p->code=c=COMPARE;
+    if(p->typf&UNSIGNED)
+      p->q2.val.vullong=zum2zull(ul2zum(0UL));
+    else
+      p->q2.val.vllong=zm2zll(l2zm(0L));
+    p->q2.flags=KONST;
+  }
+
+  if(c==KOMPLEMENT){
+    p->code=c=XOR;
+    p->q2.flags=KONST;
+    if(p->typf&UNSIGNED)
+      p->q2.val.vullong=tu_max[LLONG];
+    else
+      p->q2.val.vllong=l2zm(-1L);
+  }
+  if(c==MINUS){
+    p->code=c=SUB;
+    p->q2=p->q1;
+    p->q1.flags=KONST;
+    p->q1.am=0;
+    if(p->typf&UNSIGNED)
+      p->q1.val.vullong=ul2zum(0UL);
+    else
+      p->q1.val.vllong=l2zm(0L);
+  }    
+
+  switch_IC(p);
+
+  if(c==COMPARE){
+    int l1,l2,h1,h2,tmp,falselab=++label,c;
+    zumax lo,uhi;zmax shi;
+    char *sh;
+    struct IC *b;
+    if(multiple_ccs)
+      ierror(0); /* still needed? */
+    else
+      p->z.reg=cr0;
+    b=p->next;
+    while(b->code==ALLOCREG||b->code==FREEREG) b=b->next;
+    c=b->code;
+    if(c<BEQ||c>BGT) ierror(0);
+    if(p->typf&UNSIGNED)
+      sh="cmplw";
+    else
+      sh="cmpw";
+    if((c==BNE||c==BEQ)&&(p->q2.flags&KONST)&&p->z.reg==cr0){
+      eval_const(&p->q2.val,q2typ(p));
+      if(zmeqto(vmax,l2zm(0L))&&zumeqto(vumax,ul2zum(0UL))){
+	if(isreg(q1)){
+	  if(!reg_pair(p->q1.reg,&rp)) ierror(0);
+	  emit(f,"\tor.\t%s,%s,%s\n",mregnames[t1],mregnames[rp.r1],mregnames[rp.r2]);
+	}else{
+	  create_loadable(f,&p->q1,t1);
+	  load_lword(f,t3,&p->q1,q1typ(p),t2);
+	  load_hword(f,t1,&p->q1,q1typ(p),t2);
+	  emit(f,"\tor.\t%s,%s,%s\n",mregnames[t3],mregnames[t3],mregnames[t1]);
+	}
+	return 1;
+      }
+    }
+    h1=h2=l1=l2=0;
+    if(isreg(q1)){
+      if(!reg_pair(p->q1.reg,&rp)) ierror(0);
+      h1=rp.r1;
+      l1=rp.r2;
+    }else{
+      create_loadable(f,&p->q1,t1);
+      h1=l1=t3;
+    }
+    if(isreg(q2)){
+      if(!reg_pair(p->q2.reg,&rp)) ierror(0);
+      h2=rp.r1;
+      l2=rp.r2;      
+    }else if(p->q2.flags&KONST){
+      eval_const(&p->q2.val,q2typ(p));
+      lo=zumrshift(zumlshift(vumax,ul2zum(32UL)),ul2zum(32UL));
+      if(zumleq(lo,ul2zum(65535L)))
+	l2=-1; 
+      if(p->typf&UNSIGNED){
+	uhi=zumrshift(vumax,ul2zum(32UL));
+	if(zumleq(uhi,ul2zum(65535L)))
+	  h2=-1; 
+      }else{
+	shi=zmrshift(vmax,l2zm(32L));
+	if(zmleq(shi,l2zm(32767L))&&zmleq(l2zm(-32768L),shi))
+	  h2=-1;
+      }
+    }
+    if(h2==0||l2==0){
+      if(!(p->q1.flags&REG)||p->q1.reg!=t1){
+	create_loadable(f,&p->q2,t1);
+      }else if(tmp=get_reg()){
+	create_loadable(f,&p->q2,tmp);
+      }
+      if(h2==0) h2=t2;
+      if(l2==0) l2=t2;
+    }
+    load_hword(f,h1,&p->q1,q1typ(p),0);
+    if(h2==-1){
+      emit(f,"\t%si\t%s,%s,",sh,mregnames[p->z.reg],mregnames[h1]);
+      if(p->typf&UNSIGNED)
+	emitzum(f,uhi);
+      else
+	emitzm(f,shi);
+      emit(f,"\n");
+    }else{
+      load_hword(f,h2,&p->q2,q2typ(p),t2);
+      emit(f,"\t%s\t%s,%s,%s\n",sh,mregnames[p->z.reg],mregnames[h1],mregnames[h2]);
+    }
+    if(c==BGT||c==BGE){
+      emit(f,"\tbgt\t%s,%s%d\n",mregnames[p->z.reg],labprefix,b->typf);
+      emit(f,"\tblt\t%s,%s%d\n",mregnames[p->z.reg],labprefix,falselab);
+    }else if(c==BLT||c==BLE){
+      emit(f,"\tblt\t%s,%s%d\n",mregnames[p->z.reg],labprefix,b->typf);
+      emit(f,"\tbgt\t%s,%s%d\n",mregnames[p->z.reg],labprefix,falselab);
+    }else if(c!=BNE){
+      emit(f,"\tbne\t%s,%s%d\n",mregnames[p->z.reg],labprefix,falselab);
+    }else{
+      emit(f,"\tbne\t%s,%s%d\n",mregnames[p->z.reg],labprefix,b->typf);
+    }
+
+    load_lword(f,l1,&p->q1,q1typ(p),t1);
+    if(l2==-1){
+      emit(f,"\tcmplwi\t%s,%s,",mregnames[p->z.reg],mregnames[l1]);
+      emitzm(f,lo);
+      emit(f,"\n");
+    }else{
+      load_lword(f,l2,&p->q2,q2typ(p),t2);
+      emit(f,"\tcmplw\t%s,%s,%s\n",mregnames[p->z.reg],mregnames[l1],mregnames[l2]);
+    }   
+    emit(f,"\tb%s\t%s,%s%d\n",ccs[c-BEQ],mregnames[p->z.reg],labprefix,b->typf);
+    emit(f,"%s%d:\n",labprefix,falselab);
+    b->code=NOP;
+	   
+    return 1;
+  }
+
+  if(c==ADD||c==SUB||c==AND||c==OR||c==XOR){
+    /*FIXME: q2==z, q1reg+q2reg=zreg */
+    int zl,zh,l1,l2,h1,h2,tmp;
+    char *sl,*sh;
+    if(c==ADD){
+      sl="addc";
+      sh="adde";
+    }else if(c==SUB){
+      /* there is no subc, therefore we always use reverse order */
+      sl="subfc";
+      sh="subfe";
+    }else if(c==AND){
+      sl=sh="and";
+    }else if(c==OR){
+      sl=sh="or";
+    }else if(c==XOR){
+      sl=sh="xor";
+    }else
+      ierror(0);
+    l1=l2=h1=h2=zl=zh=0;
+    create_loadable(f,&p->q1,t1);
+    if(isreg(q1)){
+      if(!reg_pair(p->q1.reg,&rp)) ierror(0);
+      h1=rp.r1;
+      l1=rp.r2;
+    }else{
+      create_loadable(f,&p->q1,t1);
+      l1=t3;
+      h1=t1;
+    }
+    if(isreg(q2)){
+      if(!reg_pair(p->q2.reg,&rp)) ierror(0);
+      h2=rp.r1;
+      l2=rp.r2;
+    }else if(p->q2.flags&KONST){
+      /* check for immediates */
+      if(c==OR||c==XOR){
+	/* or and xor can always be done using (x)ori and (x)oris */
+	h2=l2=-1;
+      }
+      if(c==ADD){
+	zmax tmp;
+	eval_const(&p->q2.val,q2typ(p));
+	tmp=zmrshift(vmax,l2zm(32L));
+	/* there are addze and addme instructions */
+	if(zmeqto(tmp,l2zm(0L))||zmeqto(tmp,l2zm(-1L)))
+	  h2=-1;	
+	/* addic supports 16bit signed values */
+	tmp=zmrshift(zmlshift(vmax,l2zm(32L)),l2zm(32L));	
+	if(zmleq(tmp,l2zm(32767L))&&zmleq(l2zm(-32768L),tmp))
+	  l2=-1;
+      }
+      if(c==SUB){
+	zmax tmp;
+	eval_const(&p->q2.val,q2typ(p));
+	tmp=zmrshift(vmax,l2zm(32L));
+	/* there are addze and addme instructions */
+	if(zmeqto(tmp,l2zm(0L))||zmeqto(tmp,l2zm(1L)))
+	  h2=-1;	
+	/* addic supports 16bit signed values */
+	tmp=zmrshift(zmlshift(vmax,l2zm(32L)),l2zm(32L));	
+	if(zmleq(tmp,l2zm(32768L))&&zmleq(l2zm(-32767L),tmp))
+	  l2=-1;
+      }	
+    }
+    if(!l2||!h2){
+      if(!(p->q1.flags&REG)||p->q1.reg!=t1){
+	create_loadable(f,&p->q2,t1);
+      }else if(tmp=get_reg()){
+	create_loadable(f,&p->q2,tmp);
+      }
+      if(h2==0) h2=t2;
+      if(l2==0) l2=t2;
+    }
+    if(isreg(z)&&(!isreg(q2)||p->z.reg!=p->q2.reg)){
+      if(!reg_pair(p->z.reg,&rp)) ierror(0);
+      zh=rp.r1;
+      zl=rp.r2;
+    }else{
+      zl=t3;
+      zh=t1;
+    }
+    if((p->q1.flags&KONST)&&l1==t3){
+      load_lword(f,t2,&p->q1,q1typ(p),0);
+      emit(f,"\tmr\t%s,%s\n",mregnames[t3],mregnames[t2]);
+      BSET(regs_modified,t3);
+    }else
+      load_lword(f,l1,&p->q1,q1typ(p),0);
+    if(l2!=-1){
+      load_lword(f,l2,&p->q2,q2typ(p),t2);
+      emit(f,"\t%s\t%s,%s,%s\n",sl,mregnames[zl],mregnames[l2],mregnames[l1]);
+    }else{
+      eval_const(&p->q2.val,q2typ(p));
+      if(c==ADD||c==SUB){
+	if(c==SUB) vmax=zmsub(l2zm(0L),vmax);
+	vmax=zmrshift(zmlshift(vmax,l2zm(32L)),l2zm(32L));
+	emit(f,"\taddic\t%s,%s,",mregnames[zl],mregnames[l1]);
+	emitzm(f,vmax);
+	emit(f,"\n");
+      }else if(c==OR||c==XOR){
+	zumax tmp;
+	if(zumeqto(zumand(vumax,ul2zum(0xffffffffUL)),ul2zum(0xffffffffUL))){
+	  if(c==XOR)
+	    emit(f,"\tnor\t%s,%s,%s\n",mregnames[zl],mregnames[l1],mregnames[l1]);
+	  else
+	    emit(f,"\tli\t%s,-1\n",mregnames[zl]);
+	}else{
+	  tmp=zumand(vumax,ul2zum(0xffffUL));
+	  if(!zumeqto(tmp,ul2zum(0UL))){
+	    emit(f,"\t%si\t%s,%s,",sl,mregnames[zl],mregnames[l1]);
+	    emitzum(f,tmp);
+	    emit(f,"\n");
+	    l1=zl;
+	  }
+	  tmp=zumand(zumrshift(vumax,ul2zum(16UL)),ul2zum(0xffff));
+	  if(!zumeqto(tmp,ul2zum(0UL))){
+	    emit(f,"\t%sis\t%s,%s,",sl,mregnames[zl],mregnames[l1]);
+	    emitzum(f,tmp);
+	    emit(f,"\n");
+	    l1=zl;
+	  }
+	  if(l1!=zl)
+	    emit(f,"\tmr\t%s,%s\n",mregnames[zl],mregnames[l1]);
+	}
+      }else
+	ierror(0);
+    }
+    if(h2!=-1){
+      load_hword(f,h2,&p->q2,q2typ(p),t2);    
+      load_hword(f,h1,&p->q1,q1typ(p),0);
+      emit(f,"\t%s\t%s,%s,%s\n",sh,mregnames[zh],mregnames[h2],mregnames[h1]);
+    }else{
+      load_hword(f,h1,&p->q1,q1typ(p),0);
+      eval_const(&p->q2.val,q2typ(p));
+      if(c==ADD||c==SUB){
+	if(c==SUB) vmax=zmsub(l2zm(0L),vmax);
+	vmax=zmrshift(vmax,l2zm(32L));
+	if(zmeqto(vmax,l2zm(0L))){
+	  emit(f,"\taddze\t%s,%s\n",mregnames[zh],mregnames[h1]);
+	}else if(zmeqto(vmax,l2zm(-1L))){
+	  emit(f,"\taddme\t%s,%s\n",mregnames[zh],mregnames[h1]);
+	}else
+	  ierror(0);
+      }else if(c==OR||c==XOR){
+	zumax tmp;
+	if(zumeqto(zumand(zumrshift(vumax,ul2zum(32L)),ul2zum(0xffffffffUL)),ul2zum(0xffffffffUL))){
+	  if(c==XOR)
+	    emit(f,"\tnor\t%s,%s,%s\n",mregnames[zh],mregnames[h1],mregnames[h1]);
+	  else
+	    emit(f,"\tli\t%s,-1\n",mregnames[zh]);
+	}else{
+	  tmp=zumand(zumrshift(vumax,ul2zum(32UL)),ul2zum(0xffffUL));
+	  if(!zumeqto(tmp,ul2zum(0UL))){
+	    emit(f,"\t%si\t%s,%s,",sl,mregnames[zh],mregnames[h1]);
+	    emitzum(f,tmp);
+	    emit(f,"\n");
+	    h1=zh;
+	  }
+	  tmp=zumand(zumrshift(vumax,ul2zum(48UL)),ul2zum(0xffff));
+	  if(!zumeqto(tmp,ul2zum(0UL))){
+	    emit(f,"\t%sis\t%s,%s,",sl,mregnames[zh],mregnames[h1]);
+	    emitzum(f,tmp);
+	    emit(f,"\n");
+	    h1=zh;
+	  }	
+	  if(h1!=zh)
+	    emit(f,"\tmr\t%s,%s\n",mregnames[zh],mregnames[h1]);
+	}
+      }
+    }
+    if(p->z.flags){
+      create_loadable(f,&p->z,t2);
+      store_lword(f,zl,&p->z);
+      store_hword(f,zh,&p->z);
+      p->z.flags=0;
+    }
+    return 1;
+  }
+
+  create_loadable(f,&p->q1,t1);
+
+  if(tmpoff>=32768&&(regs[r3]||regs[r4]||regs[r5]||regs[r6])){
+    emit(f,"\taddis\t%s,%s,%ld\n",mregnames[t2],mregnames[sp],hi(tmpoff));
+    if(lo(tmpoff)) emit(f,"\taddi\t%s,%s,%ld\n",mregnames[t2],mregnames[t2],lo(tmpoff));
+    msp=t2;
+    mtmpoff=0;
+  }else{
+    msp=sp;
+    mtmpoff=tmpoff;
+  }
+
+  if(regs[r3]){ emit(f,"\tstw\t%s,%ld(%s)\n",mregnames[r3],mtmpoff-4,mregnames[msp]);savemask|=1;}
+  if(regs[r4]){ emit(f,"\tstw\t%s,%ld(%s)\n",mregnames[r4],mtmpoff-8,mregnames[msp]);savemask|=2;}
+  if(regs[r5]) {emit(f,"\tstw\t%s,%ld(%s)\n",mregnames[r5],mtmpoff-12,mregnames[msp]);savemask|=4;}
+  if(regs[r6]) {emit(f,"\tstw\t%s,%ld(%s)\n",mregnames[r6],mtmpoff-16,mregnames[msp]);savemask|=8;}
+
+  if((p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p->q1.reg>=r3&&p->q1.reg<=r6){
+    emit(f,"\tmr\t%s,%s\n",mregnames[t1],mregnames[p->q1.reg]);
+    p->q1.reg=t1;
+  }
+  if((p->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p->q2.reg>=r3&&p->q2.reg<=r6){
+    emit(f,"\tmr\t%s,%s\n",mregnames[t2],mregnames[p->q2.reg]);
+    p->q2.reg=t2;
+  }
+  
+  if((q1typ(p)&NQ)==LLONG){
+    if(p->q1.am&&p->q1.am->base==r3){
+      if(p->q1.am->flags==REG_IND&&p->q1.am->offset==r4) ierror(0);
+      load_lword(f,r4,&p->q1,q1typ(p),0);
+      load_hword(f,r3,&p->q1,q1typ(p),0);
+    }else{
+      if(p->q1.am&&p->q1.am->flags==REG_IND&&p->q1.am->offset==r3) ierror(0);
+      load_hword(f,r3,&p->q1,q1typ(p),0);
+      load_lword(f,r4,&p->q1,q1typ(p),0);
+    }
+  }else{
+    if(!ISFLOAT(q1typ(p))) ierror(0);
+    load_reg(f,f1,&p->q1,q1typ(p),0); 
+  }
+  
+  if(p->q2.flags){
+    create_loadable(f,&p->q2,t2);
+    if((q2typ(p)&NQ)==LLONG){
+      if(isreg(q2)&&p->q2.reg==r3r4){
+	emit(f,"\tlwz\t%s,%ld(%s)\n",mregnames[r5],mtmpoff-4,mregnames[msp]);
+	emit(f,"\tlwz\t%s,%ld(%s)\n",mregnames[r6],mtmpoff-8,mregnames[msp]);
+      }else{
+	if(p->q2.am&&p->q2.am->base==r5){
+	  if(p->q2.am->flags==REG_IND&&p->q2.am->offset==r6) ierror(0);
+	  load_lword(f,r6,&p->q2,q2typ(p),0);
+	  load_hword(f,r5,&p->q2,q2typ(p),0);
+	}else{
+	  if(p->q2.am&&p->q2.am->flags==REG_IND&&p->q2.am->offset==r5) ierror(0);
+	  load_hword(f,r5,&p->q2,q2typ(p),0);
+	  load_lword(f,r6,&p->q2,q2typ(p),0);
+	}
+      }
+    }else{
+      if((q2typ(p)&NQ)>=LLONG) ierror(0);
+      if(isreg(q2)&&p->q2.reg==r3){
+	emit(f,"\tlwz\t%s,%ld(%s)\n",mregnames[r5],mtmpoff-4,mregnames[msp]);
+      }else{
+	load_reg(f,r5,&p->q2,q2typ(p),0);
+      }      
+    }
+  }
+
+  if(c==MULT) libfuncname="__mulint64";
+  else if(c==DIV){
+    if(t&UNSIGNED)
+      libfuncname="__divuint64";
+    else
+      libfuncname="__divsint64";
+  }else if(c==MOD){
+    if(t&UNSIGNED)
+      libfuncname="__moduint64";
+    else
+      libfuncname="__modsint64";
+  }else if(c==CONVERT){
+    static char s[32];
+    if(ISFLOAT(q1typ(p)))
+      sprintf(s,"__flt%dto%cint64",(q1typ(p)&NQ)==FLOAT?32:64,(ztyp(p)&UNSIGNED)?'u':'s');
+    else
+      sprintf(s,"__%cint64toflt%d",(q1typ(p)&UNSIGNED)?'u':'s',(ztyp(p)&NQ)==FLOAT?32:64);
+    libfuncname=s;
+  }else if(c==RSHIFT){
+    if(t&UNSIGNED)
+      libfuncname="__rshuint64";
+    else
+      libfuncname="__rshsint64";
+  }else if(c==LSHIFT)
+    libfuncname="__lshint64";
+  else{
+    printf("c=%d\n",c);
+    ierror(0);
+  }
+  emit(f,"\t.global\t%s%s\n",idprefix,libfuncname);
+  emit(f,"\tbl\t%s%s\n",idprefix,libfuncname);
+  stack_valid=0; /*FIXME*/
+
+  if((p->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)){
+    if((p->z.reg==r3&&(savemask&1))||
+       (p->z.reg==r4&&(savemask&2))||
+       (p->z.reg==r5&&(savemask&4))||
+       (p->z.reg==r6&&(savemask&8))){
+      if(p->z.reg==r3)
+	emit(f,"\tlwz\t%s,%ld(%s)\n",mregnames[t1],mtmpoff-4,mregnames[msp]);
+      else if(p->z.reg==r4)
+	emit(f,"\tlwz\t%s,%ld(%s)\n",mregnames[t1],mtmpoff-8,mregnames[msp]);
+      else if(p->z.reg==r5)
+	emit(f,"\tlwz\t%s,%ld(%s)\n",mregnames[t1],mtmpoff-12,mregnames[msp]);
+      else if(p->z.reg==r6)
+	emit(f,"\tlwz\t%s,%ld(%s)\n",mregnames[t1],mtmpoff-16,mregnames[msp]);
+      else
+	ierror(0);
+      p->z.reg=t1;
+    }
+  }
+
+  if((p->z.flags&REG)&&p->z.reg==r3)
+    savemask&=~1;
+  if((p->z.flags&REG)&&p->z.reg==r4)
+    savemask&=~2;
+  if((p->z.flags&REG)&&p->z.reg==r5)
+    savemask&=~4;
+  if((p->z.flags&REG)&&p->z.reg==r6)
+    savemask&=~8;
+  if((p->z.flags&REG)&&p->z.reg==r3r4)
+    savemask&=~3;
+  if((p->z.flags&REG)&&p->z.reg==r5r6)
+    savemask&=~12;
+
+
+  if(ISFLOAT(ztyp(p))){
+    zreg=f1;
+  }else{
+    create_loadable(f,&p->z,t1);
+    store_hword(f,r3,&p->z);
+    store_lword(f,r4,&p->z);
+    p->z.flags=0;
+  }
+
+  if(savemask&1)
+    emit(f,"\tlwz\t%s,%ld(%s)\n",mregnames[r3],mtmpoff-4,mregnames[msp]);
+  if(savemask&2)
+    emit(f,"\tlwz\t%s,%ld(%s)\n",mregnames[r4],mtmpoff-8,mregnames[msp]);
+  if(savemask&4)
+    emit(f,"\tlwz\t%s,%ld(%s)\n",mregnames[r5],mtmpoff-12,mregnames[msp]);
+  if(savemask&8)
+    emit(f,"\tlwz\t%s,%ld(%s)\n",mregnames[r6],mtmpoff-16,mregnames[msp]);
+  
+  return 1;
+}
+/****************************************/
+/*  End of private data 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;
+  /*  Initialize some values which cannot be statically initialized   */
+  /*  because they are stored in the target's arithmetic.             */
+  maxalign=l2zm(8L);
+  if(POWEROPEN){
+    stackalign=l2zm(4L);
+    align_arguments=0;
+  }else{
+    tocname=sdataname;
+    stackalign=l2zm(4L);
+    if(NOALIGNARGS)
+      align_arguments=0;
+    else
+      align_arguments=1;
+  }
+  char_bit=l2zm(8L);
+  if(g_flags[7]&USEDFLAG){
+    malign[INT]=malign[LONG]=malign[LLONG]=malign[POINTER]=malign[FLOAT]=malign[DOUBLE]=malign[LDOUBLE]=2;
+  }
+  for(i=0;i<=MAX_TYPE;i++){
+    sizetab[i]=l2zm(msizetab[i]);
+    align[i]=l2zm(malign[i]);
+  }
+  for(i=0;i<=MAXR;i++) mregnames[i]=regnames[i];
+  for(i= 1;i<=32;i++){
+    regsize[i]=l2zm(4L);
+    regtype[i]=&ltyp;
+    if(g_flags[8]&USEDFLAG) mregnames[i]++;
+  }
+  for(i=33;i<=64;i++){
+    regsize[i]=l2zm(8L);
+    regtype[i]=&ldbl;
+    if(g_flags[8]&USEDFLAG) mregnames[i]++;
+  }
+  for(i=65;i<=72;i++){
+    regsize[i]=l2zm(1L);
+    regtype[i]=&lchar;
+    if(g_flags[8]&USEDFLAG) mregnames[i]+=2;
+  }
+  for(i=74;i<=86;i++){
+    regsize[i]=l2zm(8L);
+    regtype[i]=&lltyp;
+  }
+
+  /*  Use multiple ccs.   */
+  multiple_ccs=1;
+
+  /*  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.          */
+  t_min[CHAR]=l2zm(-128L);
+  t_min[SHORT]=l2zm(-32768L);
+  t_min[INT]=zmsub(l2zm(-2147483647L),l2zm(1L));
+  t_min[LONG]=t_min(INT);
+  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]=ul2zum(2147483647UL);
+  t_max[LONG]=t_max(INT);
+  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]=ul2zum(4294967295UL);
+  tu_max[LONG]=t_max(UNSIGNED|INT);
+  tu_max[LLONG]=zumkompl(ul2zum(0UL));
+  tu_max[MAXINT]=t_max(UNSIGNED|LLONG);
+
+  /*  Reserve a few registers for use by the code-generator.      */
+  /*  This is not optimal but simple.                             */
+  if(POWEROPEN){
+    sd=r2;
+  }
+  regsa[t1]=regsa[t2]=regsa[t3]=1;
+  regsa[f1]=regsa[f2]=regsa[f3]=1;
+  regsa[sp]=regsa[fp]=regsa[sd]=regsa[r2]=1;
+  regscratch[t1]=regscratch[t2]=regscratch[t3]=0;
+  regscratch[f1]=regscratch[f2]=regscratch[f3]=0;
+  regscratch[sp]=regscratch[fp]=regscratch[sd]=regscratch[r2]=0;
+
+  if(g_flags[6]&USEDFLAG) {minframe=8;labprefix=".l";idprefix="";}
+  if(POWEROPEN) {minframe=24;labprefix="l";idprefix="_";}
+
+  if(optsize){
+    dataname="\t.data\n";
+    rodataname="\t.section\t.rodata\n";
+    sdataname="\t.section\t\".sdata\",\"aw\"\n";
+    sdata2name="\t.section\t\".sdata2\",\"a\"\n";
+    sbssname="\t.section\t\".sbss\",\"auw\"\n";
+  }
+
+  if(BASERELOS4) bssname="\t.bss\n";
+
+  target_macros=marray;
+
+  declare_builtin("__mulint64",LLONG,LLONG,r3r4,LLONG,r5r6,1,0);
+  declare_builtin("__divsint64",LLONG,LLONG,r3r4,LLONG,r5r6,1,0);
+  declare_builtin("__divuint64",UNSIGNED|LLONG,UNSIGNED|LLONG,r3r4,UNSIGNED|LLONG,r5r6,1,0);
+  declare_builtin("__modsint64",LLONG,LLONG,r3r4,LLONG,r5r6,1,0);
+  declare_builtin("__moduint64",UNSIGNED|LLONG,UNSIGNED|LLONG,r3r4,UNSIGNED|LLONG,r5r6,1,0);
+  declare_builtin("__lshint64",LLONG,LLONG,r3r4,INT,r5,1,0);
+  declare_builtin("__rshsint64",LLONG,LLONG,r3r4,INT,r5,1,0);
+  declare_builtin("__rshuint64",LLONG,UNSIGNED|LLONG,r3r4,INT,r5,1,0);
+
+  return 1;
+}
+
+void init_db(FILE *f)
+{
+  dwarf2_setup(sizetab[POINTER],".byte",".2byte",".4byte",".4byte",labprefix,idprefix,".section");
+  dwarf2_print_comp_unit_header(f);
+}
+
+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.        */
+/*  A pointer MUST be returned in a register. The code-generator    */
+/*  has to simulate a pseudo register if necessary.                 */
+{
+  if(ISFLOAT(t->flags)) return 34; /* f1 */
+    if(ISSTRUCT(t->flags)||ISUNION(t->flags)) return 0;
+    if(zmleq(szof(t),l2zm(4L))) return r3; 
+    if((t->flags&NQ)==LLONG) return 74; /* r3/r4 */
+    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<74||r>86)
+    return 0;
+  switch(r){
+  case 74: p->r1=4;p->r2=5;return 1;
+  case 75: p->r1=6;p->r2=7;return 1;
+  case 76: p->r1=8;p->r2=9;return 1;
+  case 77: p->r1=10;p->r2=11;return 1;
+  case 78: p->r1=15;p->r2=16;return 1;
+  case 79: p->r1=17;p->r2=18;return 1;
+  case 80: p->r1=19;p->r2=20;return 1;
+  case 81: p->r1=21;p->r2=22;return 1;
+  case 82: p->r1=23;p->r2=24;return 1;
+  case 83: p->r1=25;p->r2=26;return 1;
+  case 84: p->r1=27;p->r2=28;return 1;
+  case 85: p->r1=29;p->r2=30;return 1;
+  case 86: p->r1=31;p->r2=32;return 1;
+  }
+  ierror(0);
+}
+
+
+int cost_savings(struct IC *p,int r,struct obj *o)
+{
+  int c=p->code;
+  if(o->flags&VKONST){
+    struct obj *co=&o->v->cobj;
+    int longload;
+    if(o->flags&DREFOBJ)
+      return 4;
+    if(ISFLOAT(p->typf)) return 2;
+    longload=0;
+    if((co->flags&VARADR)&&!use_sd(o->v->vtyp->flags))
+      longload=2;
+    if(co->flags&KONST){
+      eval_const(&co->val,p->typf);
+      if(p->typf&UNSIGNED){
+	if(!zumleq(vumax,ul2zum(65535UL)))
+	  longload=2;
+      }else{
+	if(!zmleq(vmax,l2zm(32767L))||zmleq(vmax,l2zm(-32769L)))
+	  longload=2;
+      }
+    }
+    if(o==&p->q1&&p->code==ASSIGN&&((p->z.flags&DREFOBJ)||p->z.v->storage_class==STATIC||p->z.v->storage_class==EXTERN))
+      return longload+2;
+    else
+      return longload;
+  }
+  if(o->flags&DREFOBJ)
+    return 4;
+  if(c==SETRETURN&&r==p->z.reg&&!(o->flags&DREFOBJ)) return 3;
+  if(c==GETRETURN&&r==p->q1.reg&&!(o->flags&DREFOBJ)) return 3;
+  return 2;
+}
+
+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(r==0) return 0;
+    t&=NQ;
+    if(t==0){
+        if(r>=65&&r<=72) return 1; else return 0;
+    }
+    if(ISFLOAT(t)&&r>=33&&r<=64) return 1;
+    if(t==POINTER&&r>=1&&r<=32) return 1;
+    if(t>=CHAR&&t<=LONG&&r>=1&&r<=32) return 1;
+    if(t==LLONG&&r>=74&&r<=86) return 1;
+    return 0;
+}
+
+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)&&!(p->q2.flags&KONST))
+    return 1;
+  return 0;
+}
+
+int must_convert(int o,int t,int const_expr)
+/*  Returns zero if code for converting np to type t    */
+/*  can be omitted.                                     */
+/*  On the PowerPC cpu pointers and 32bit               */
+/*  integers have the same representation and can use   */
+/*  the same registers.                                 */
+{
+    int op=o&NQ,tp=t&NQ;
+    if((op==INT||op==LONG||op==POINTER)&&(tp==INT||tp==LONG||tp==POINTER))
+      return 0;
+    if(op==DOUBLE&&tp==LDOUBLE) return 0;
+    if(op==LDOUBLE&&tp==DOUBLE) return 0;
+    if(op==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.                              */
+{
+  title(f);
+  if(newobj&&section!=TOC&&section!=SBSS&&section!=SPECIAL&&!BASERELOS4)
+    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.              */
+{
+  title(f);
+  if(!optsize&&(zm2l(align)<4))
+    emit(f,"\t.align\t2\n");
+  else
+    if(zm2l(align)>1)
+      emit(f,"\t.align\t%ld\n",pof2(align)-1);
+}
+
+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;char *sec;
+  title(f);
+  if(v->clist) constflag=is_const(v->vtyp);
+  if(v->storage_class==STATIC){
+    if(ISFUNC(v->vtyp->flags)) return;
+    if(!special_section(f,v)){
+      if(use_sd(v->vtyp->flags)&&!(v->tattr&FAR)){
+	if(EABI){
+	  if(v->clist&&!constflag&&section!=SDATA){emit(f,sdataname);if(f) section=SDATA;}
+	  if(v->clist&&constflag&&section!=SDATA2){emit(f,sdata2name);if(f) section=SDATA2;}
+	  if(!v->clist&&section!=SBSS){emit(f,sbssname);if(f) section=SBSS;}
+	}else if (POWEROPEN){
+	  if(section!=TOC){emit(f,tocname);if(f) section=TOC;}
+	}
+        else {
+	  if(v->clist&&section!=SDATA){emit(f,sdataname);if(f) section=SDATA;}
+	  if(!v->clist&&section!=SBSS){emit(f,sbssname);if(f) section=SBSS;}
+        }
+      }else{
+        if(BASERELOS4){
+          if(v->clist&&section!=DATA){emit(f,dataname); if(f) section=DATA;}
+        }else if(BASERELMOS){
+          if(v->clist&&section!=SDATA){emit(f,sdataname); if(f) section=SDATA;}
+          if(!v->clist&&section!=SBSS){emit(f,sbssname); if(f) section=SBSS;}
+        }else{
+          if(POWEROPEN) toc_entry(f,v);
+          if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&&section!=DATA){emit(f,dataname);if(f) section=DATA;}
+          if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&&section!=RODATA){emit(f,rodataname);if(f) section=RODATA;}
+	  if(!USE_COMMONS&&!v->clist&&section!=BSS){emit(f,bssname);if(f) section=BSS;}
+        }
+      }
+    }
+    if(v->clist||section==TOC||section==SBSS||section==SPECIAL){
+      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)));
+      gen_align(f,falign(v->vtyp));
+      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){
+    emit(f,"\t.global\t%s%s\n",idprefix,v->identifier);
+    if(POWEROPEN&&(!use_sd(v->vtyp->flags)||(v->tattr&FAR)))
+      emit(f,"\t.global\t%s%s%s\n",tocprefix,idprefix,v->identifier);
+    if(v->flags&(DEFINED|TENTATIVE)){
+      if(!special_section(f,v)){
+	if(use_sd(v->vtyp->flags)&&!(v->tattr&FAR)){
+	  if(EABI){
+	    if(v->clist&&!constflag&&section!=SDATA){emit(f,sdataname);if(f) section=SDATA;}
+	    if(v->clist&&constflag&&section!=SDATA2){emit(f,sdata2name);if(f) section=SDATA2;}
+	    if(!v->clist&&section!=SBSS){emit(f,sbssname);if(f) section=SBSS;}
+	  }else if (POWEROPEN){
+	    if(section!=TOC){emit(f,tocname);if(f) section=TOC;}
+	  }
+          else {
+	    if(v->clist&&section!=SDATA){emit(f,sdataname);if(f) section=SDATA;}
+	    if(!USE_COMMONS&&!v->clist&&section!=SBSS){emit(f,sbssname);if(f) section=SBSS;}
+          }
+	}else{
+          if(BASERELOS4){
+            if(v->clist&&section!=DATA){emit(f,dataname); if(f) section=DATA;}
+          }else if(BASERELMOS){
+            if(v->clist&&section!=SDATA){emit(f,sdataname); if(f) section=SDATA;}
+            if(!USE_COMMONS&&!v->clist&&section!=SBSS){emit(f,sbssname); if(f) section=SBSS;}
+          }else{
+            if(POWEROPEN) toc_entry(f,v);
+            if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&&section!=DATA){emit(f,dataname);if(f) section=DATA;}
+            if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&&section!=RODATA){emit(f,rodataname);if(f) section=RODATA;}
+	    if(!USE_COMMONS&&!v->clist&&section!=BSS){emit(f,bssname);if(f) section=BSS;}
+          }
+	}
+      }
+      if(v->clist||section==TOC||section==SBSS||section==SPECIAL){
+        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)));
+	gen_align(f,falign(v->vtyp));
+        emit(f,"%s%s:\n",idprefix,v->identifier);
+      }else{
+        emit(f,"\t.%scomm\t%s%s,",USE_COMMONS?"":"l",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.                      */
+{
+  title(f);
+  if((t&NQ)==POINTER) t=UNSIGNED|LONG;
+  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[0],ip[1],ip[2],ip[3]);
+      if((t&NQ)!=FLOAT){
+	emit(f,",0x%02x%02x%02x%02x",ip[4],ip[5],ip[6],ip[7]);
+      }
+    }else if((t&NQ)==LLONG){
+      zumax tmp;
+      eval_const(&p->val,t);
+      tmp=vumax;
+      vumax=zumand(zumrshift(vumax,ul2zum(32UL)),ul2zum(0xffffffff)); 
+      gval.vulong=zum2zul(vumax);
+      emitval(f,&gval,UNSIGNED|LONG);
+      emit(f,",");
+      vumax=zumand(tmp,ul2zum(0xffffffff)); 
+      gval.vulong=zum2zul(vumax);
+      emitval(f,&gval,UNSIGNED|LONG);
+    }else{
+      emitval(f,&p->val,t&NU);
+    }
+  }else{
+    emit_obj(f,&p->tree->o,t&NU);
+  }
+  emit(f,"\n");newobj=0;
+}
+
+static void allocreg(int r)
+{
+  if(reg_pair(r,&rp)){
+    regs[rp.r1]=1;
+    regs[rp.r2]=1;
+  }
+  regs[r]=1;
+}
+
+static void freereg(int r)
+{
+  if(reg_pair(r,&rp)){
+    regs[rp.r1]=0;
+    regs[rp.r2]=0;
+  }
+  regs[r]=0;
+}
+
+/*  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 *p,struct Var *v,zmax offset)
+/*  The main code-generation.                                           */
+{
+  int c,t,i,addbuf,varargs=0,fixedgpr,fixedfpr,setcc,ccset;
+  char *fpp;int fpf;struct IC *m;
+  long of=(zm2l(offset)+3)/4*4,regbase,vparmos=0;
+  if(DEBUG&1) printf("gen_code()\n");
+  for(c=1;c<=MAXR;c++) regs[c]=regsa[c];
+  if(vlas) fp=vlafp; else fp=sp;
+  maxpushed=0;addbuf=0;
+  if(v->tattr&RFI)
+    ret="\trfi\n";
+  else
+    ret="\tblr\n";
+  if(!v->fi) v->fi=new_fi();
+  title(f);
+  for(m=p;m;m=m->next){
+    c=m->code;t=m->typf&NU;
+    m->ext.setcc=0;
+    if(c==ALLOCREG){
+      allocreg(m->q1.reg);
+      continue;
+    }
+    if(c==FREEREG){
+      freereg(m->q1.reg);
+      continue;
+    }
+    if(c==COMPARE&&(m->q2.flags&KONST)&&(t&NQ)!=CHAR&&(t&NQ)!=SHORT){
+      eval_const(&m->q2.val,t);
+      if(zmeqto(vmax,l2zm(0L))&&zldeqto(vldouble,d2zld(0.0))){
+        m->q2.flags=0;m->code=c=TEST;
+      }
+    }
+    if((t&NQ)<=LLONG&&(m->q2.flags&KONST)&&(t&NQ)<=LLONG&&(c==MULT||((c==DIV||c==MOD)&&(t&UNSIGNED)))){
+      eval_const(&m->q2.val,t);
+      i=pof2(vmax);
+      if(i){
+        if(c==MOD){
+          vmax=zmsub(vmax,l2zm(1L));
+          m->code=AND;
+        }else{
+          vmax=l2zm(i-1);
+          if(c==DIV) m->code=RSHIFT; else m->code=LSHIFT;
+        }
+        c=m->code;
+	gval.vmax=vmax;
+	eval_const(&gval,MAXINT);
+	if(c==AND){
+	  insert_const(&m->q2.val,t);
+	}else{
+	  insert_const(&m->q2.val,INT);
+	  m->typf2=INT;
+	}
+      }
+    }
+    if(addbuf<16){
+      if((q1typ(m)&NQ)==LLONG&&(c==MULT||c==DIV||c==MOD||c==LSHIFT||c==RSHIFT)) {addbuf=16;function_calls++;}
+      if(c==CONVERT&&(q1typ(m)&NQ)==LLONG&&ISFLOAT(ztyp(m)&NQ)){addbuf=16;function_calls++;}
+      if(c==CONVERT&&(ztyp(m)&NQ)==LLONG&&ISFLOAT(q1typ(m)&NQ)){addbuf=16;function_calls++;}
+      if(addbuf<8){
+	if(c==CONVERT&&ISFLOAT(m->typf2)&&!ISFLOAT(t)) addbuf=8;
+	if(c==CONVERT&&!ISFLOAT(m->typf2)&&ISFLOAT(t)) addbuf=8;
+      }
+    }
+    if(c==CALL&&maxpushed<zm2l(m->q2.val.vmax)) maxpushed=zm2l(m->q2.val.vmax);
+    if(c==CALL&&(m->q1.flags&VAR)&&!strcmp(m->q1.v->identifier,"__va_start")) varargs=1;
+  }
+  once=twice=0;
+  if(!(g_flags[9]&USEDFLAG)) peephole(p);
+  if(varargs){
+    fixedgpr=fixedfpr=0;
+    if(!freturn(v->vtyp->next)) fixedgpr++;
+    for(i=0;i<v->vtyp->exact->count;i++){
+      c=(*v->vtyp->exact->sl)[i].styp->flags&NQ;
+      if(fixedgpr<8&&(c==POINTER||c<=LONG))
+	fixedgpr++;
+      else if(fixedgpr<7&&c==LLONG)
+	fixedgpr=(fixedgpr+3)/2*2;
+      else if(fixedfpr<8&&ISFLOAT(c)) 
+	fixedfpr++;
+      else{
+	
+	vparmos+=zm2l(szof((*v->vtyp->exact->sl)[i].styp));
+	vparmos=(vparmos+zm2l(stackalign)-1)/zm2l(stackalign)*zm2l(stackalign);
+      }
+    }
+    regbase=of;
+    addbuf+=96;
+  }
+  for(c=1;c<=MAXR;c++){
+    if((!regsa[c])&&regused[c]){
+      BSET(regs_modified,c);
+    }
+  }
+  of+=addbuf;tmpoff=minframe+maxpushed+of;
+  function_top(f,v,of);
+  all_regs=1;
+  if(varargs){
+    regbase=frameoffset+regbase;
+    fpp="";
+    if(!(g_flags[8]&USEDFLAG)) fpp="r";
+    for(i=fixedgpr;i<8;i++)
+      emit(f,"\tstw\t%s%d,%ld(%s)\n",fpp,i+3,regbase+i*4,mregnames[sp]);
+    if(!(g_flags[8]&USEDFLAG)) fpp="f";
+    for(i=fixedfpr;i<8;i++)
+      emit(f,"\tstfd\t%s%d,%ld(%s)\n",fpp,i+1,regbase+32+i*8,mregnames[sp]);
+  }
+  pushed=0;ccset=0;
+  for(;p;pr(f,p),p=p->next){
+    c=p->code;t=p->typf;
+    setcc=p->ext.setcc;
+    if(debug_info)
+      dwarf2_line_info(f,p);
+    if(c==NOP) {p->z.flags=0;continue;}
+    if(c==ALLOCREG){
+      allocreg(p->q1.reg);
+      continue;
+    }
+    if(c==FREEREG){
+      freereg(p->q1.reg);
+      continue;
+    }
+    if(c==COMPARE&&(p->q2.flags&KONST)&&(t&NQ)!=LLONG){
+      struct case_table *ct=calc_case_table(p,JUMP_TABLE_DENSITY);
+      if(ct&&(ct->num>=JUMP_TABLE_LENGTH||(!isreg(q1)&&ct->num>=JUMP_TABLE_LENGTH/2))){
+	int r,defl,tabl=++label;
+	long l;unsigned long ul;
+	struct IC *np;
+	for(np=p;np!=ct->next_ic;np=np->next){
+	  if(np->code==ALLOCREG) allocreg(np->q1.reg);
+	  if(np->code==FREEREG) freereg(np->q1.reg);
+	}
+	if(ct->next_ic->code==BRA)
+	  defl=ct->next_ic->typf;
+	else
+	  defl=++label;
+	if(!isreg(q1)){
+	  if(!p->q1.am&&(p->q1.flags&(REG|DREFOBJ))==DREFOBJ){
+	    p->q1.flags&=~DREFOBJ;
+	    load_reg(f,t1,&p->q1,POINTER,t1);
+	    p->q1.flags|=(REG|DREFOBJ);
+	    p->q1.flags&=~VAR;
+	    p->q1.reg=t1;
+	  }
+	  load_reg(f,t2,&p->q1,p->typf,t1);
+	  r=t2;
+	}else
+	  r=p->q1.reg;
+	if(t&UNSIGNED)
+	  l=-(long)zum2ul(ct->min.vumax);
+	else
+	  l=-zm2l(ct->min.vmax);
+	if(l>=-32767&&l<=32767){
+	  emit(f,"\taddi\t%s,%s,%ld\n",mregnames[t2],mregnames[r],l);
+	}else{
+	  emit(f,"\taddis\t%s,%s,%ld\n",mregnames[t2],mregnames[r],hi(l));
+	  if(lo(l))
+	    emit(f,"\taddi\t%s,%s,%ld\n",mregnames[t2],mregnames[t2],lo(l));
+	}
+	ul=zum2ul(ct->diff);
+	if(regs[cr0]) ierror(0);
+	if(ul<=65535){
+	  emit(f,"\tcmplwi\t%s,%lu\n",mregnames[t2],ul);
+	}else{
+	  emit(f,"\tlis\t%s,%ld\n",mregnames[t1],hi(ul));
+	  if(lo(ul))
+	    emit(f,"\taddi\t%s,%s,%ld\n",mregnames[t1],regnames[t1],lo(ul));
+	}
+	emit(f,"\tbgt\t%s,%s%d\n",mregnames[cr0],labprefix,defl);
+	emit(f,"\tslwi\t%s,%s,2\n",mregnames[t2],mregnames[t2]);
+	/*FIXME: small-data */
+	if(POWEROPEN){
+	  emit(f,"\tlwz\t%s,%s%s%d(%s)\n",mregnames[t1],tocprefix,labprefix,tabl,mregnames[r2]);
+	}else{
+	  emit(f,"\tlis\t%s,%s%d@ha\n",mregnames[t1],labprefix,tabl);
+	  emit(f,"\taddi\t%s,%s,%s%d@l\n",mregnames[t1],mregnames[t1],labprefix,tabl);
+	}
+	emit(f,"\tlwzx\t%s,%s,%s\n",mregnames[t2],mregnames[t1],mregnames[t2]);
+	emit(f,"\tmtctr\t%s\n",mregnames[t2]);
+	emit(f,"\tbctr\n");
+	BSET(regs_modified,ctr);
+	if(POWEROPEN){
+	  emit(f,tocname);
+	  emit(f,"%s%s%d:\n",tocprefix,labprefix,tabl);
+	  emit(f,"\t.long\t%s%d\n",labprefix,tabl);
+	}
+	emit(f,rodataname);
+	emit(f,"\t.align\t2\n");
+	emit(f,"%s%d:\n",labprefix,tabl);
+	emit_jump_table(f,ct,"\t.long\t",labprefix,defl);
+	if(!special_section(f,v)) emit(f,codename);
+	if(ct->next_ic->code!=BRA){
+	  emit(f,"%s%d:\n",labprefix,defl);
+	  p=ct->next_ic->prev;
+	}else
+	  p=ct->next_ic;
+	continue;
+      }
+    }
+    if(c==LABEL) {ccset=0;emit(f,"%s%d:\n",labprefix,t);continue;}
+    if(c==BRA){
+      ccset=0;
+      if(t==exit_label&&framesize==0)
+	emit(f,ret);
+      else
+	emit(f,"\tb\t%s%d\n",labprefix,t);
+      continue;
+    }
+    if(c>=BEQ&&c<BRA){
+      ccset=0;
+      if(!(p->q1.flags&REG)) p->q1.reg=cr0;
+      if(!(g_flags[9]&USEDFLAG)&&!BTST(twice,p->typf-lastlabel)){
+        struct IC *p2,*p3,*p4;int exit_label;
+        p2=p->next;
+        while(p2&&(p2->code==FREEREG||p2->code==ALLOCREG)) p2=p2->next;
+        if(p2&&p2->code==SETRETURN&&p2->z.reg){p2->code=ASSIGN;p2->z.flags=REG;}
+        if(p2&&p2->code==ASSIGN&&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg<=32){
+          p3=p2->next;
+          while(p3&&(p3->code==FREEREG||p3->code==ALLOCREG)) p3=p3->next;
+          if(p3&&p3->code==BRA){
+            exit_label=p3->typf;
+            p3=p3->next;
+            while(p3&&(p3->code==FREEREG||p3->code==ALLOCREG)) p3=p3->next;
+            if(p3&&p3->code==LABEL&&p3->typf==p->typf){
+              p3=p3->next;
+              while(p3&&(p3->code==FREEREG||p3->code==ALLOCREG)) p3=p3->next;
+              if(p3&&p3->code==SETRETURN&&p3->z.reg){p3->code=ASSIGN;p3->z.flags=REG;}
+              if(p3&&p3->code==ASSIGN&&(p3->z.flags&(REG|DREFOBJ))==REG&&p3->z.reg==p2->z.reg){
+                p4=p3->next;
+                while(p4&&(p4->code==FREEREG||p4->code==ALLOCREG)) p4=p4->next;
+                if(p4&&p4->code==LABEL&&p4->typf==exit_label){
+                  int bit=(p->q1.reg-cr0)*4;
+                  if((p2->q1.flags&KONST)&&(p3->q1.flags&KONST)){
+                    eval_const(&p2->q1.val,p2->typf);
+                    if(zmeqto(vmax,l2zm(0L))){
+                      eval_const(&p3->q1.val,p3->typf);
+                      if(zmeqto(vmax,l2zm(1L))||zmeqto(vmax,l2zm(-1L))){
+                        if(c==BLE){emit(f,"\tcror\t%d,%d,%d\n",bit,bit,bit+2);}
+                        if(c==BGE){bit++;emit(f,"\tcror\t%d,%d,%d\n",bit,bit,bit+1);}
+                        if(c==BNE){bit+=2;emit(f,"\tcrnor\t%d,%d,%d\n",bit,bit,bit);}
+                        if(c==BGT) bit++;
+                        if(c==BEQ) bit+=2;
+                        emit(f,"\tmfcr\t%s\n",mregnames[t1]);
+                        emit(f,"\trlwinm\t%s,%s,%d,%d,%d\n",mregnames[p2->z.reg],mregnames[t1],bit+1,31,31);
+                        if(zmeqto(vmax,l2zm(-1L))) emit(f,"\tneg\t%s,%s\n",mregnames[p2->z.reg],mregnames[p2->z.reg]);
+                        if(BTST(twice,p4->typf-lastlabel)) emit(f,"%s%d:\n",labprefix,p4->typf);
+                        p=p4;continue;
+                      }
+                    }else{
+                      eval_const(&p3->q1.val,p3->typf);
+                      if(zmeqto(vmax,l2zm(0L))){
+                        eval_const(&p2->q1.val,p2->typf);
+                        if(zmeqto(vmax,l2zm(1L))||zmeqto(vmax,l2zm(-1L))){
+                          if(c==BLE){emit(f,"\tcrnor\t%d,%d,%d\n",bit,bit,bit+2);}
+                          if(c==BGE){bit++;emit(f,"\tcrnor\t%d,%d,%d\n",bit,bit,bit+1);}
+                          if(c==BNE){bit+=2;}
+                          if(c==BGT){bit++;emit(f,"\tcrnor\t%d,%d,%d\n",bit,bit,bit);}
+                          if(c==BEQ){bit+=2;emit(f,"\tcrnor\t%d,%d,%d\n",bit,bit,bit);}
+                          if(c==BLT){emit(f,"\tcrnor\t%d,%d,%d\n",bit,bit,bit);}
+                          emit(f,"\tmfcr\t%s\n",mregnames[t1]);
+                          emit(f,"\trlwinm\t%s,%s,%d,%d,%d\n",mregnames[p2->z.reg],mregnames[t1],bit+1,31,31);
+                          if(zmeqto(vmax,l2zm(-1L))) emit(f,"\tneg\t%s,%s\n",mregnames[p2->z.reg],mregnames[p2->z.reg]);
+                          if(BTST(twice,p4->typf-lastlabel)) emit(f,"%s%d:\n",labprefix,p4->typf);
+                          p=p4;continue;
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      if(t==exit_label&&framesize==0&&!strcmp(ret,"\tblr\n"))
+	emit(f,"\tb%slr\t%s\n",ccs[c-BEQ],mregnames[p->q1.reg]);
+      else
+	emit(f,"\tb%s\t%s,%s%d\n",ccs[c-BEQ],mregnames[p->q1.reg],labprefix,t);
+      continue;
+    }
+    if(c==MOVETOREG){
+      if(p->z.reg<=32){
+        load_reg(f,p->z.reg,&p->q1,INT,t1);
+      }else if(p->z.reg>=33&&p->z.reg<=64){
+        load_reg(f,p->z.reg,&p->q1,DOUBLE,t1);
+      }else if(reg_pair(p->z.reg,&rp)){
+	create_loadable(f,&p->q1,t1);
+	load_hword(f,rp.r1,&p->q1,LLONG,t2);
+	load_lword(f,rp.r2,&p->q1,LLONG,t2);
+      }else
+	ierror(0);
+      p->z.flags=0;
+      continue;
+    }
+    if(c==MOVEFROMREG){
+      if(p->q1.reg<=32){
+        store_reg(f,p->q1.reg,&p->z,INT);
+      }else if(p->q1.reg>=33&&p->q1.reg<=64){
+        store_reg(f,p->q1.reg,&p->z,DOUBLE);
+      }else if(reg_pair(p->q1.reg,&rp)){
+	create_loadable(f,&p->z,t1);
+	store_hword(f,rp.r1,&p->z);
+	store_lword(f,rp.r2,&p->z);
+      }else
+	ierror(0);
+      p->z.flags=0;
+      continue;
+    }
+    if((p->q1.flags&&(q1typ(p)&NQ)==LLONG)||(p->q2.flags&&(q2typ(p)&NQ)==LLONG)||(p->z.flags&&(ztyp(p)&NQ)==LLONG))
+      if(handle_llong(f,p))
+	continue;
+    if((c==ASSIGN||c==PUSH)&&((t&NQ)>POINTER||((t&NQ)==CHAR&&zm2l(p->q2.val.vmax)!=1))){
+      unsigned long size,l;
+      int a1,a2,b;char *ld,*st;
+      size=zm2l(p->q2.val.vmax);
+      a1=balign(&p->q1);
+      if(c==ASSIGN) a2=balign(&p->z); else a2=0;
+      b=1;ld=ldt(CHAR);st=sdt(CHAR);
+      if(p->q1.flags&VAR){
+	if(p->q1.flags&DREFOBJ){
+	  if(p->q1.v->vtyp->next&&zmeqto(p->q2.val.vmax,szof(p->q1.v->vtyp->next))&&(a1&1)){
+	    a1=zm2l(falign(p->q1.v->vtyp->next))&3;
+	    a2&=a1;
+	  }
+	}else{
+	  if(zmeqto(p->q2.val.vmax,szof(p->q1.v->vtyp))&&(a1&1)){
+	    a1=zm2l(falign(p->q1.v->vtyp))&3;
+	    a2&=a1;
+	  }
+	}
+      }
+      if(p->z.flags&VAR){
+	if(p->z.flags&DREFOBJ){
+	  if(p->z.v->vtyp->next&&zmeqto(p->q2.val.vmax,szof(p->z.v->vtyp->next))&&(a2&1)){
+	    a2=zm2l(falign(p->z.v->vtyp->next))&3;
+	    a1&=a2;
+	  }
+	}else{
+	  if(zmeqto(p->q2.val.vmax,szof(p->z.v->vtyp))&&(a2&1)){
+	    a2=zm2l(falign(p->z.v->vtyp))&3;
+	    a1&=a2;
+	  }
+	}
+      } 
+      if(a1>=0&&a2>=0){
+        if(a1==0&&a2==0){
+          b=4;ld=ldt(INT);st=sdt(INT);
+        }else if((a1&1)==0&&(a2&1)==0){
+          b=2;ld=ldt(SHORT);st=sdt(SHORT);
+        }
+      }
+      if(p->q1.flags&DREFOBJ){
+        if(p->q1.am){
+          if(p->q1.am->flags&REG_IND){
+	    emit(f,"\tadd\t%s,%s,%s\n",mregnames[t1],mregnames[p->q1.am->offset],mregnames[p->q1.am->base]);
+	    emit(f,"\taddi\t%s,%s,%d\n",mregnames[t1],mregnames[t1],-b);
+	  }
+          if(p->q1.am->flags&IMM_IND)
+	    emit(f,"\taddi\t%s,%s,%ld\n",mregnames[t1],mregnames[p->q1.am->base],p->q1.am->offset-b);
+        }else{
+          p->q1.flags&=~DREFOBJ;
+	  if(isreg(q1)){
+	    emit(f,"\taddi\t%s,%s,%d\n",mregnames[t1],mregnames[p->q1.reg],-b);
+	  }else{
+	    load_reg(f,t1,&p->q1,POINTER,t1);
+	    emit(f,"\taddi\t%s,%s,%d\n",mregnames[t1],mregnames[t1],-b);
+	  }    
+          p->q1.flags|=DREFOBJ;
+        }
+      }else{
+	p->q1.val.vmax=zmsub(p->q1.val.vmax,l2zm((long)b));
+        load_address(f,t1,&p->q1,POINTER);
+	p->q1.val.vmax=zmadd(p->q1.val.vmax,l2zm((long)b));
+      }
+      if(p->z.flags&DREFOBJ){
+        if(p->z.am){
+          if(p->z.am->flags&REG_IND){
+	    emit(f,"\tadd\t%s,%s,%s\n",mregnames[t2],mregnames[p->z.am->offset],mregnames[p->z.am->base]);
+	    emit(f,"\taddi\t%s,%s,%d\n",mregnames[t2],mregnames[t2],-b);
+	  }
+          if(p->z.am->flags&IMM_IND) 
+	    emit(f,"\taddi\t%s,%s,%ld\n",mregnames[t2],mregnames[p->z.am->base],p->z.am->offset-b);
+        }else{
+          p->z.flags&=~DREFOBJ;
+	  if(isreg(z)){
+	    emit(f,"\taddi\t%s,%s,%d\n",mregnames[t2],mregnames[p->z.reg],-b);
+	  }else{
+	    load_reg(f,t2,&p->z,POINTER,t2);
+	    emit(f,"\taddi\t%s,%s,%d\n",mregnames[t2],mregnames[t2],-b);
+	  }
+          p->z.flags|=DREFOBJ;
+        }
+      }else{
+        if(c==PUSH){
+          pushed=(pushed+3)/4*4;
+	  if(align_arguments&&p->ityp){
+	    long al=falign(p->ityp);
+	    pushed=(pushed+al-1)/al*al;
+	  }
+          emit(f,"\taddi\t%s,%s,%ld\n",mregnames[t2],mregnames[sp],pushed+minframe-b);
+          pushed+=size;
+	  size=zm2l(p->z.val.vmax);
+        }else{
+	  p->z.val.vmax=zmsub(p->z.val.vmax,l2zm((long)b));
+          load_address(f,t2,&p->z,POINTER);
+	  p->z.val.vmax=zmsub(p->z.val.vmax,l2zm((long)b));
+        }
+      }
+      BSET(regs_modified,t1);
+      BSET(regs_modified,t2);
+      BSET(regs_modified,t3);
+      if(optspeed)
+	l=size/(8*b);
+      else
+	l=size/b;
+      if(l>1){
+        if(hi(l)){
+	  emit(f,"\tlis\t%s,%lu\n",mregnames[t3],(l>>16)&65535);
+	  emit(f,"\tori\t%s,%s,%lu\n",mregnames[t3],mregnames[t3],l&65535);
+	}else{
+	  emit(f,"\tli\t%s,%ld\n",mregnames[t3],lo(l));
+	}
+        emit(f,"\tmtctr\t%s\n",mregnames[t3]);
+	BSET(regs_modified,ctr);
+        emit(f,"%s%d:\n",labprefix,++label);
+      }
+      if(l>0){
+        for(i=b;optspeed&&i<=7*b;i+=b){
+          emit(f,"\tl%s\t%s,%d(%s)\n",ld,mregnames[t3],i,mregnames[t1]);
+          emit(f,"\tst%s\t%s,%d(%s)\n",st,mregnames[t3],i,mregnames[t2]);
+        }
+        emit(f,"\tl%su\t%s,%d(%s)\n",ld,mregnames[t3],i,mregnames[t1]);
+        emit(f,"\tst%su\t%s,%d(%s)\n",st,mregnames[t3],i,mregnames[t2]);
+	
+      }
+      if(l>1){
+        emit(f,"\tbdnz\t%s%d\n",labprefix,label);
+      }
+      if(optspeed)
+	size=size%(8*b);
+      else
+	size=size%b;
+      for(i=0;i<size/b;i++){
+        emit(f,"\tl%su\t%s,%d(%s)\n",ld,mregnames[t3],b,mregnames[t1]);
+        emit(f,"\tst%su\t%s,%d(%s)\n",st,mregnames[t3],b,mregnames[t2]);
+      }
+      size=size%b;i=b;
+      if(size&2){
+        emit(f,"\tl%su\t%s,%d(%s)\n",ldt(SHORT),mregnames[t3],b,mregnames[t1]);
+        emit(f,"\tst%su\t%s,%d(%s)\n",sdt(SHORT),mregnames[t3],b,mregnames[t2]);
+        i=2;
+      }
+      if(size&1){
+        emit(f,"\tl%su\t%s,%d(%s)\n",ldt(CHAR),mregnames[t3],i,mregnames[t1]);
+        emit(f,"\tst%su\t%s,%d(%s)\n",sdt(CHAR),mregnames[t3],i,mregnames[t2]);
+      }
+      p->z.flags=0;
+      continue;
+    }
+    if(c==TEST&&ISFLOAT(t)){
+      p->code=c=COMPARE;
+      p->q2.flags=KONST;
+      p->q2.val.vldouble=d2zld(0.0);
+      if((t&NQ)==DOUBLE) p->q2.val.vdouble=zld2zd(p->q2.val.vldouble);
+      if((t&NQ)==FLOAT) p->q2.val.vfloat=zld2zf(p->q2.val.vldouble);
+    }
+    p=do_refs(f,p);
+    c=p->code;
+    setcc=p->ext.setcc;
+    if(c==SUBPFP) c=SUB;
+    if(c==ADDI2P) c=ADD;
+    if(c==SUBIFP) c=SUB;
+    if(c==CONVERT){
+      int to;
+      static struct obj o;char *ip;
+      long moff;int offreg;
+      to=p->typf2;
+      if(ISFLOAT(to)){
+        if(ISFLOAT(t)){
+          zreg=q1reg;
+          continue;
+        }
+        if(tmpoff>32767){
+          moff=0;offreg=t1;
+          emit(f,"\taddis\t%s,%s,%ld\n",mregnames[offreg],mregnames[sp],hi(tmpoff));
+          emit(f,"\taddi\t%s,%s,%ld\n",mregnames[offreg],mregnames[offreg],lo(tmpoff));
+        }else{
+          moff=tmpoff;
+          offreg=sp;
+        }
+        if((t&NU)==(UNSIGNED|INT)||(t&NU)==(UNSIGNED|LONG)){
+          o.flags=KONST;
+          ip=(char *)&o.val.vdouble;
+          ip[0]=0x41;
+          ip[1]=0xe0;
+          ip[2]=0x00;
+          ip[3]=0x00;
+          ip[4]=0x00;
+          ip[5]=0x00;
+          ip[6]=0x00;
+          ip[7]=0x00;
+          load_reg(f,f2,&o,DOUBLE,t2);
+          emit(f,"\tfcmpu\t%s,%s,%s\n",mregnames[cr0],mregnames[q1reg],mregnames[f2]);
+          emit(f,"\tcror\t3,2,1\n");
+          emit(f,"\tbso\t%s,%s%d\n",mregnames[cr0],labprefix,++label);
+          emit(f,"\tfctiwz\t%s,%s\n",mregnames[f2],mregnames[q1reg]);
+          emit(f,"\tst%s\t%s,%ld(%s)\n",sdt(DOUBLE),mregnames[f2],moff-8,mregnames[offreg]);
+          emit(f,"\tl%s\t%s,%ld(%s)\n",ldt(t&NQ),mregnames[zreg],moff-zm2l(sizetab[t&NQ]),mregnames[offreg]);
+          emit(f,"\tb\t%s%d\n",labprefix,++label);
+          emit(f,"%s%d:\n",labprefix,label-1);
+          emit(f,"\tfsub\t%s,%s,%s\n",mregnames[f2],mregnames[q1reg],mregnames[f2]);
+          emit(f,"\tfctiwz\t%s,%s\n",mregnames[f2],mregnames[f2]);
+          emit(f,"\tst%s\t%s,%ld(%s)\n",sdt(DOUBLE),mregnames[f2],moff-8,mregnames[offreg]);
+          emit(f,"\tl%s\t%s,%ld(%s)\n",ldt(INT),mregnames[zreg],moff-zm2l(sizetab[t&NQ]),mregnames[offreg]);
+          emit(f,"\txoris\t%s,%s,32768\n",mregnames[zreg],mregnames[zreg]);
+          emit(f,"%s%d:\n",labprefix,label);
+	  BSET(regs_modified,f2);
+	  BSET(regs_modified,zreg);
+	  BSET(regs_modified,q1reg);
+        }else{
+          emit(f,"\tfctiwz\t%s,%s\n",mregnames[f3],mregnames[q1reg]);
+          emit(f,"\tst%s\t%s,%ld(%s)\n",sdt(DOUBLE),mregnames[f3],moff-8,mregnames[offreg]);
+          emit(f,"\tl%s\t%s,%ld(%s)\n",ldt(t&NQ),mregnames[zreg],moff-zm2l(sizetab[t&NQ]),mregnames[offreg]);
+	  BSET(regs_modified,f3);
+	  BSET(regs_modified,zreg);
+	  BSET(regs_modified,q1reg);
+        }
+        if(t==CHAR) emit(f,"\textsb\t%s,%s\n",mregnames[zreg],mregnames[zreg]);
+        continue;
+      }
+      if(ISFLOAT(t)){
+        if(tmpoff>32767){
+          moff=0;offreg=t1;
+	  if(q1reg==t1){
+	    emit(f,"\tmr\t%s,%s\n",mregnames[t3],mregnames[q1reg]);
+	    q1reg=t3;
+	    BSET(regs_modified,t3);
+	  }
+          emit(f,"\taddis\t%s,%s,%ld\n",mregnames[offreg],mregnames[sp],hi(tmpoff));
+          emit(f,"\taddi\t%s,%s,%ld\n",mregnames[offreg],mregnames[offreg],lo(tmpoff));
+        }else{
+          moff=tmpoff;
+          offreg=sp;
+        }
+        o.flags=KONST;
+        ip=(char *)&o.val.vdouble;
+        ip[0]=0x43;
+        ip[1]=0x30;
+        ip[2]=0x00;
+        ip[3]=0x00;
+        ip[4]=0x80;
+        ip[5]=0x00;
+        ip[6]=0x00;
+        ip[7]=0x00;
+        if((to&NU)==(UNSIGNED|INT)||(to&NU)==(UNSIGNED|LONG)){
+          ip[4]=0x00;
+          load_reg(f,f2,&o,DOUBLE,t2);
+          emit(f,"\tlis\t%s,17200\n",mregnames[t2]);
+          emit(f,"\tst%s\t%s,%ld(%s)\n",sdt(INT),mregnames[q1reg],moff-4,mregnames[offreg]);
+          emit(f,"\tst%s\t%s,%ld(%s)\n",sdt(INT),mregnames[t2],moff-8,mregnames[offreg]);
+          emit(f,"\tl%s\t%s,%ld(%s)\n",ldt(DOUBLE),mregnames[zreg],moff-8,mregnames[offreg]);
+          emit(f,"\tfsub\t%s,%s,%s\n",mregnames[zreg],mregnames[zreg],mregnames[f2]);
+        }else{
+          emit(f,"\tlis\t%s,17200\n",mregnames[t2]);
+          emit(f,"\tst%s\t%s,%ld(%s)\n",sdt(INT),mregnames[t2],moff-8,mregnames[offreg]);
+          emit(f,"\txoris\t%s,%s,32768\n",mregnames[t2],mregnames[q1reg]);
+          emit(f,"\tst%s\t%s,%ld(%s)\n",sdt(INT),mregnames[t2],moff-4,mregnames[offreg]);
+          emit(f,"\tl%s\t%s,%ld(%s)\n",ldt(DOUBLE),mregnames[zreg],moff-8,mregnames[offreg]);
+          load_reg(f,f2,&o,DOUBLE,t2);
+          emit(f,"\tfsub\t%s,%s,%s\n",mregnames[zreg],mregnames[zreg],mregnames[f2]);
+        }
+        continue;
+      }
+      if((t&NQ)>=(to&NQ)){
+	if((to&NU)==CHAR){
+	  emit(f,"\textsb%s\t%s,%s\n",record[setcc],mregnames[zreg],mregnames[q1reg]);
+	  ccset|=setcc;
+	}else if((to&NU)==SHORT&&!q1loaded){
+	  emit(f,"\textsh%s\t%s,%s\n",record[setcc],mregnames[zreg],mregnames[q1reg]);
+	  ccset|=setcc;
+	}else if((to&NU)==(UNSIGNED|CHAR)&&!q1loaded){
+	  emit(f,"\tclrlwi%s\t%s,%s,24\n",record[setcc],mregnames[zreg],mregnames[q1reg]);
+	  ccset|=setcc;
+	}else if((to&NU)==(UNSIGNED|SHORT)&&!q1loaded){
+	  emit(f,"\tclrlwi%s\t%s,%s,16\n",record[setcc],mregnames[zreg],mregnames[q1reg]);
+	  ccset|=setcc;
+	}else{
+	  if(setcc){
+	    emit(f,"\tmr.\t%s,%s\n",mregnames[zreg],mregnames[q1reg]);
+	    ccset=1;
+	  }else{
+	    zreg=q1reg;
+	  }
+	}
+	continue;
+      }else{
+	zreg=q1reg;
+        continue;
+      }
+    }
+    if(c==KOMPLEMENT){
+      emit(f,"\tnor%s\t%s,%s,%s\n",record[setcc],mregnames[zreg],mregnames[q1reg],mregnames[q1reg]);
+      ccset|=setcc;
+      continue;
+    }
+    if(ISFLOAT(t)) {fpp="f";fpf=1;} else {fpp="";fpf=0;}
+    if(c==SETRETURN){
+      if(p->z.reg){
+	if((t&NU)==CHAR)
+	  emit(f,"\textsb\t%s,%s\n",mregnames[p->z.reg],mregnames[q1reg]);
+	else if(!q1loaded&&(t&NU)==SHORT)
+	  emit(f,"\textsh\t%s,%s\n",mregnames[p->z.reg],mregnames[q1reg]);
+	else if(!q1loaded&&(t&NU)==(UNSIGNED|CHAR))
+	  emit(f,"\tclrlwi\t%s,%s,24\n",mregnames[p->z.reg],mregnames[q1reg]);
+	else if(!q1loaded&&(t&NU)==(UNSIGNED|SHORT))
+	  emit(f,"\tclrlwi\t%s,%s,16\n",mregnames[p->z.reg],mregnames[q1reg]);
+	else if(p->z.reg!=q1reg)
+	  emit(f,"\t%smr\t%s,%s\n",fpp,mregnames[p->z.reg],mregnames[q1reg]);
+	BSET(regs_modified,p->z.reg);
+      }else
+        ierror(0);
+      continue;
+    }
+    if(c==GETRETURN){
+      if(p->q1.reg)
+        zreg=p->q1.reg;
+      else
+        p->z.flags=0;
+      continue;
+    }
+    if(c==CALL){
+      ccset=0;
+      if(stack_valid){
+	int i;
+	if(p->call_cnt<=0){
+	  err_ic=p;error(320);
+	  stack_valid=0;
+	  v->fi->flags|=(WARNED_STACK|WARNED_REGS);
+	}
+	for(i=0;i<p->call_cnt;i++){
+	  if(p->call_list[i].v->fi&&(p->call_list[i].v->fi->flags&ALL_STACK)){
+	    if(framesize+zum2ul(p->call_list[i].v->fi->stack1)>stack)
+	      stack=framesize+zum2ul(p->call_list[i].v->fi->stack1);
+	  }else{
+	    err_ic=p;
+	    if(!p->call_list[i].v->fi) p->call_list[i].v->fi=new_fi();
+	    if(!(p->call_list[i].v->fi->flags&WARNED_STACK)){
+	      error(317,p->call_list[i].v->identifier);
+	      p->call_list[i].v->fi->flags|=WARNED_STACK;
+	    }
+	    v->fi->flags|=WARNED_STACK;
+	    stack_valid=0;
+	  }
+#if HAVE_OSEK
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+#endif
+	}
+      }
+      if(!calc_regs(p,f!=0)&&v->fi) all_regs=0;
+#if HAVE_OSEK
+/* removed */
+/* removed */
+#endif
+      if((p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&p->q1.v->fi->inline_asm){
+        emit_inline_asm(f,p->q1.v->fi->inline_asm);
+      }else{
+        if((p->q1.flags&(VAR|DREFOBJ))==VAR){
+          if(!strcmp("__va_start",p->q1.v->identifier)){
+            emit(f,"\taddi\t%s,%s,%lu\n",mregnames[r3],mregnames[sp],framesize+minframe+zm2l(va_offset(v))/*+vparmos*/);
+            BSET(regs_modified,r3);continue;
+          }
+          if(!strcmp("__va_regbase",p->q1.v->identifier)){
+            emit(f,"\taddi\t%s,%s,%ld\n",mregnames[r3],mregnames[sp],regbase);
+            BSET(regs_modified,r3);continue;continue;
+          }
+          if(!strcmp("__va_fixedgpr",p->q1.v->identifier)){
+            emit(f,"\tli\t%s,%d\n",mregnames[r3],fixedgpr);
+            BSET(regs_modified,r3);continue;continue;
+          }
+          if(!strcmp("__va_fixedfpr",p->q1.v->identifier)){
+            emit(f,"\tli\t%s,%d\n",mregnames[r3],fixedfpr);
+            BSET(regs_modified,r3);continue;continue;
+          }
+        }
+        if(g_flags[10]&USEDFLAG) emit(f,"\tcreqv\t6,6,6\n");
+	/* poweropen-hack! look if some fp-args have been passed on the stack */
+	if(POWEROPEN&&!zmeqto(p->q2.val.vmax,l2zm(0L))){
+	  int r=45/*f12*/,off=24;
+	  for(i=0;r<47&&i<p->arg_cnt;i++){
+	    if(p->arg_list[i]->code==PUSH){
+	      int typ=p->arg_list[i]->typf;
+	      if(ISFLOAT(typ)){
+		emit(f,"\tl%s\t%s,%d(%s)\n",ldt(typ&NQ),mregnames[r],off,mregnames[sp]);
+		r++;
+	      }
+	    }
+	    off+=(zm2l(p->arg_list[i]->q2.val.vmax)+3)/4*4;
+	  }
+	}
+	if(q1reg){
+          emit(f,"\tmtlr\t%s\n",mregnames[q1reg]);
+          emit(f,"\tblrl\n");
+        }else{
+          emit(f,"\tbl\t");emit_obj(f,&p->q1,t);
+          emit(f,"\n");
+        }
+	BSET(regs_modified,lr);
+      }
+      pushed-=zm2l(p->q2.val.vmax);
+      continue;
+    }
+    if(c==ASSIGN||c==PUSH){
+      if(t==0) ierror(0);
+      if(q1reg||c==PUSH){
+        if(c==PUSH){
+	  pushed=(pushed+3)/4*4;
+	  if(align_arguments&&malign[p->typf&NQ]==8)
+	    pushed=(pushed+7)/8*8;
+          if(q1reg)
+            emit(f,"\tst%s\t%s,%ld(%s)\n",sdt(t&NQ),mregnames[q1reg],pushed+minframe,mregnames[sp]);
+          pushed+=zm2l(p->q2.val.vmax);
+          continue;
+        }
+        if(c==ASSIGN){
+          if(setcc&&!fpf&&sizetab[t&NQ]==sizetab[INT]){
+            emit(f,"\tmr.\t%s,%s\n",mregnames[zreg],mregnames[q1reg]);
+            ccset=1;
+          }else{
+            zreg=q1reg;
+          }
+        }
+        continue;
+      }
+    }
+    if(c==ADDRESS){
+      load_address(f,zreg,&p->q1,POINTER);
+      continue;
+    }
+    if(c==MINUS){
+      emit(f,"\t%sneg%s\t%s,%s\n",fpp,record[setcc&&!fpf],mregnames[zreg],mregnames[q1reg]);
+      if(setcc&&!fpf) ccset=1;
+      continue;
+    }
+    if(c==TEST){
+      if(!(p->z.flags&REG))
+        p->z.reg=cr0;
+      if(!multiple_ccs&&(t&UNSIGNED)){
+        struct IC *p2=p->next;
+        while(p2&&(p2->code==FREEREG||p2->code==ALLOCREG)) p2=p2->next;
+        if(!p2) continue;
+        if(p2->code==BGT) p2->code=BNE;
+        else if(p2->code==BGE) p2->code=BRA;
+        else if(p2->code==BLT) p2->code=NOP;
+        else if(p2->code==BLE) p2->code=BEQ;
+      }
+      if(ccset&&p->z.reg==cr0) continue;
+      if(ISFLOAT(t)){
+        ierror(0);
+      }else{
+	if((t&NU)==CHAR)
+	  emit(f,"\textsb.\t%s,%s\n",mregnames[p->z.reg],mregnames[q1reg]);
+	else if((t&NU)==SHORT)
+	  emit(f,"\textsh.\t%s,%s\n",mregnames[p->z.reg],mregnames[q1reg]);
+	else if((t&NU)==(UNSIGNED|CHAR))
+	  emit(f,"\tandi.\t%s,%s,255\n",mregnames[p->z.reg],mregnames[q1reg]);
+	else if((t&NU)==(UNSIGNED|SHORT))
+	  emit(f,"\tandi.\t%s,%s,65535\n",mregnames[p->z.reg],mregnames[q1reg]);
+	else
+	  emit(f,"\tcmp%swi\t%s,%s,0\n",(t&UNSIGNED)?"l":"",mregnames[p->z.reg],mregnames[q1reg]);
+      }
+      if(p->z.reg==cr0) ccset=0;
+      continue;
+    }
+    if(c==COMPARE){
+      if(!(p->z.flags&REG))
+        p->z.reg=cr0;
+      if(ISFLOAT(t))
+        emit(f,"\tfcmpu\t%s,%s,",mregnames[p->z.reg],mregnames[q1reg]);
+      else
+        emit(f,"\tcmp%sw%s\t%s,%s,",((t&UNSIGNED)||((t&NQ)==POINTER))?"l":"",isimm[q2reg==0],mregnames[p->z.reg],mregnames[q1reg]);
+      emit_obj(f,&p->q2,t);emit(f,"\n");
+      if(p->z.reg==cr0) ccset=0;
+      continue;
+    }
+    BSET(regs_modified,zreg);
+    if(c==AND&&q2reg==0){
+      ccset=setcc;
+      emit(f,"\tandi.\t%s,%s,",mregnames[zreg],mregnames[q1reg]);
+      emit_obj(f,&p->q2,t|UNSIGNED);emit(f,"\n");
+      continue;
+    }
+    if(c>=OR&&c<=AND){
+      emit(f,"\t%s%s%s\t%s,%s,",logicals[c-OR],isimm[q2reg==0],record[setcc&&q2reg],mregnames[zreg],mregnames[q1reg]);
+      emit_obj(f,&p->q2,t|UNSIGNED);emit(f,"\n");
+      if(setcc&&q2reg) ccset=1;
+      continue;
+    }
+    if(c==SUB&&(p->q1.flags&KONST)){
+      emit(f,"\tsubfic\t%s,%s,",mregnames[zreg],mregnames[q2reg]);
+      emit_obj(f,&p->q1,t&NQ);emit(f,"\n");
+      continue;
+    }
+    if(c>=LSHIFT&&c<=MOD){
+      if(c==RSHIFT&&((t&NQ)<=SHORT)){
+	/* special treatment for short shifts used in bitfields with
+	   sub-int type; will not handle the general case (which, however,
+	   should never occur) */
+	int width,shift;
+	width=sizetab[t&NQ]*8;
+	if(!(p->q2.flags&KONST)) ierror(0);
+	eval_const(&p->q2.val,p->typf2&NU);
+	shift=zm2l(vmax);
+	if(shift<0||shift>=width) ierror(0);
+	if(shift==0) continue;
+	if(!(t&UNSIGNED)){
+	  emit(f,"\texts%c\t%s,%s\n",width==8?'b':'h',mregnames[zreg],mregnames[q1reg]);
+	  q1reg=zreg;
+	}
+	emit(f,"\trlwinm\t%s,%s,%d,%d,%d\n",mregnames[zreg],mregnames[q1reg],32-shift,32-width+((t&UNSIGNED)?shift:0),31);
+	continue;
+      }
+      if(c==RSHIFT&&!(t&UNSIGNED)){
+        emit(f,"\tsraw%s%s\t%s,%s,",isimm[q2reg==0],record[setcc],mregnames[zreg],mregnames[q1reg]);
+        emit_obj(f,&p->q2,q2typ(p));
+	/* fix for illegal shift values (undefined behaviour) */
+	if(!isreg(q2))
+	  emit(f,"&31");
+	emit(f,"\n");
+        ccset|=setcc;
+        continue;
+      }
+      if(c==MOD){
+        i=0;
+        if(zreg==q1reg||zreg==q2reg){
+          if(t1!=q1reg&&t1!=q2reg) i=t1;
+          if(t2!=q1reg&&t2!=q2reg) i=t2;
+        }else i=zreg;
+        if(i==0||i==q1reg||i==q2reg) ierror(0);
+        emit(f,"\tdivw%s\t%s,%s,%s\n",(t&UNSIGNED)?"u":"",mregnames[i],mregnames[q1reg],mregnames[q2reg]);
+        emit(f,"\tmullw\t%s,%s,%s\n",mregnames[i],mregnames[i],mregnames[q2reg]);
+        emit(f,"\tsubf%s\t%s,%s,%s\n",record[setcc],mregnames[zreg],mregnames[i],mregnames[q1reg]);
+        ccset|=setcc;
+        continue;
+      }
+      if(c==DIV&&(t&UNSIGNED)){
+        emit(f,"\tdivwu%s%s\t%s,%s,",isimm[q2reg==0],record[setcc&&q2reg],mregnames[zreg],mregnames[q1reg]);
+        if(setcc&&q2reg) ccset=1;
+      }else if(c==MULT&&ISFLOAT(t)){
+	if(isreg(z)&&(g_flags[14]&USEDFLAG)){
+	  struct IC *np=p->next,*add;int madd;
+	  while(np&&(np->code==FREEREG||np->code==ALLOCREG)) np=np->next;
+	  if(np&&(np->code==ADD||np->code==SUB)&&(np->q1.flags&(REG|DREFOBJ))==REG&&(np->q1.reg==p->z.reg||(np->code==ADD&&np->q2.reg==p->z.reg))&&(np->q2.flags&(REG|DREFOBJ))==REG&&np->q1.reg!=np->q2.reg){
+	    add=np;
+	    madd=0;
+	    if((np->z.flags&(REG|DREFOBJ))==REG&&np->z.reg==p->z.reg) madd=1;
+	    np=np->next;
+	    while(np&&(np->code==FREEREG||np->code==ALLOCREG)){
+	      if(np->code==FREEREG&&np->q1.reg==p->z.reg) madd=1;
+	      np=np->next;
+	    }
+	    if(madd){
+	      if((add->z.flags&(REG|DREFOBJ))==REG) zreg=add->z.reg;
+	      if(add->code==ADD){
+		if(add->q1.reg==p->z.reg) madd=add->q2.reg; else madd=add->q1.reg;
+		emit(f,"\tfmadd%s\t%s,%s,%s,%s\n",(t&NQ)==FLOAT?"s":"",mregnames[zreg],mregnames[q1reg],mregnames[q2reg],mregnames[madd]);
+	      }else
+		emit(f,"\tfmsub%s\t%s,%s,%s,%s\n",(t&NQ)==FLOAT?"s":"",mregnames[zreg],mregnames[q1reg],mregnames[q2reg],mregnames[add->q2.reg]);
+	      add->code=NOP;
+	      p->z=add->z;
+	      add->z.am=0;
+	      continue;
+	    }
+	  }
+	}
+	emit(f,"\tfmul%s\t%s,%s,",(t&NQ)==FLOAT?"s":"",mregnames[zreg],mregnames[q1reg]);
+      }else if(c==DIV&&ISFLOAT(t)){
+        emit(f,"\tfdiv%s\t%s,%s,",(t&NQ)==FLOAT?"s":"",mregnames[zreg],mregnames[q1reg]);
+      }else if(c==MULT&&q2reg==0){
+        emit(f,"\tmulli\t%s,%s,",mregnames[zreg],mregnames[q1reg]);
+      }else if(c==ADD&&setcc&&!q2reg){
+        emit(f,"\taddic.\t%s,%s,",mregnames[zreg],mregnames[q1reg]);
+        ccset=1;
+      }else{
+        emit(f,"\t%s%s%s%s%s\t%s,%s,",fpp,arithmetics[c-LSHIFT],(t&NQ)==FLOAT?"s":"",isimm[q2reg==0],record[setcc&&q2reg&&!fpf],mregnames[zreg],mregnames[q1reg]);
+        if(setcc&&q2reg&&!fpf) ccset=1;
+      }
+      emit_obj(f,&p->q2,q2typ(p)&NQ);
+      /* fix for illegal shift values (undefined behaviour) */
+      if((c==LSHIFT||c==RSHIFT)&&q2reg==0) emit(f,"&31");
+      emit(f,"\n");
+      continue;
+    }
+    pric2(stdout,p);
+    ierror(0);
+  }
+  if(!cross_module)  lastlabel=label;  /*FIXME*/
+  free(once);free(twice);
+  function_bottom(f,v,of);
+#if HAVE_OSEK
+/* removed */
+#endif
+  if(stack_valid){
+    if(!v->fi) v->fi=new_fi();
+    if(v->fi->flags&ALL_STACK){
+      if(v->fi->stack1!=stack&&!(v->tattr&SAVEALL))
+	if(f) error(319,"",stack,v->fi->stack1);
+#if HAVE_OSEK
+/* removed */
+/* removed */
+/* removed */
+#endif
+    }else{
+      v->fi->flags|=ALL_STACK;
+      v->fi->stack1=stack;
+    }
+  }
+  emit(f,"# stacksize=%lu%s\n",(unsigned long)stack,stack_valid?"":"+??");
+  if(stack_valid) emit(f,"\t.set\t%s__stack_%s,%lu\n",idprefix,v->identifier,(unsigned long)stack);
+  if(debug_info){
+    emit(f,"%s%d:\n",labprefix,++label);
+    dwarf2_function(f,v,label);
+    if(f) section=-1;
+  }
+}
+
+int shortcut(int code,int typ)
+{
+  return 0;
+}
+
+int reg_parm(struct reg_handle *m, struct Typ *t,int vararg,struct Typ *ft)
+{
+#if HAVE_AOS4
+  extern int aos4_attr(struct Typ *,char *);
+#endif
+  int f;
+  if(!m) ierror(0);
+  if(!t) ierror(0);
+  if(vararg&&POWEROPEN) return 0;
+#ifdef HAVE_AOS4
+  if(vararg&&ft&&aos4_attr(ft,"linearvarargs")) return 0;
+#endif
+  f=t->flags&NQ;
+  if(f<=LONG||f==POINTER){
+    if(m->gregs>=8) return 0;
+    if(POWEROPEN){
+      if(!STORMC) m->fregs++;
+      return -(r3+m->gregs++);
+    }else{
+      return r3+m->gregs++;
+    }
+  }
+  if(f==LLONG){
+    int r;
+    if(m->gregs>=7) return 0;
+    m->gregs=(m->gregs+3)/2*2;
+    if(m->gregs==2) r=74;
+    else if(m->gregs==4) r=75;
+    else if(m->gregs==6) r=76;
+    else if(m->gregs==8) r=77;
+    else ierror(0);
+    if(POWEROPEN) 
+      return -r;
+    else
+      return r;
+  }
+  if(ISFLOAT(f)){
+    if(POWEROPEN){
+      if(m->fregs>=11) return 0; /* hack! we pretend fp-arg 12/13 is passed on the stack */
+      if(!STORMC){
+        if(f!=FLOAT) m->gregs+=2; else m->gregs++;
+      }
+      return -(34+m->fregs++);
+    }else{
+      if(m->fregs>=8) return 0;
+      return 34+m->fregs++;
+    }
+  }
+  return 0;
+}
+
+int handle_pragma(const char *s)
+{
+  if(!strncmp("amiga-align",s,11)){
+    align[INT]=align[LONG]=align[LLONG]=align[POINTER]=align[FLOAT]=align[DOUBLE]=align[LDOUBLE]=l2zm(2L);
+    return 1;
+  }else if(!strncmp("natural-align",s,13)){
+    align[INT]=align[LONG]=align[POINTER]=align[FLOAT]=l2zm(4L);
+    align[LLONG]=align[DOUBLE]=align[LDOUBLE]=l2zm(8L);
+    return 1;
+  }else if(!strncmp("default-align",s,13)){
+    if(g_flags[7]&USEDFLAG){
+      align[INT]=align[LONG]=align[LLONG]=align[POINTER]=align[FLOAT]=align[DOUBLE]=align[LDOUBLE]=l2zm(2L);
+    }else{
+      align[INT]=align[LONG]=align[POINTER]=align[FLOAT]=l2zm(4L);
+      align[LLONG]=align[DOUBLE]=align[LDOUBLE]=l2zm(8L);
+    }
+    return 1;
+  }
+  return 0;
+}
+
+void cleanup_cg(FILE *f)
+{
+  struct fpconstlist *p;
+  unsigned char *ip;
+  struct StatFPtrList *tfp,*fp=firstfptr;
+
+  title(f);
+
+  if(fp){
+    emit(f,tocname);
+    if(f) section=TOC;
+  }
+  while(tfp=fp){
+    emit(f,"%s%s%ld:\n\t.long\t%s%ld\n",
+	 tocprefix,labprefix,zm2l(tfp->vptr->offset),
+	 labprefix,zm2l(tfp->vptr->offset));
+    fp=fp->next;
+    free(tfp);
+  }
+  if(f&&stack_check)
+    emit(f,"\t.global\t%s__stack_check\n",idprefix);
+  while(p=firstfpc){
+    if(f){
+      if(POWEROPEN&&!use_sd(p->typ)){
+        emit(f,tocname);
+        emit(f,"%s%s%ld:\n",tocprefix,labprefix,zm2l(p->label));
+        emit(f,"\t.long\t%s%ld\n",labprefix,zm2l(p->label));
+        if(f) section=TOC;
+      }
+      if(use_sd(p->typ)){
+	if(EABI){
+	  if(section!=SDATA2){emit(f,sdata2name);if(f) section=SDATA2;}
+	}else{
+	  if(section!=TOC){emit(f,tocname);if(f) section=TOC;}
+	}
+      }else{
+        if(section!=RODATA){emit(f,rodataname);if(f) section=RODATA;}
+      }
+      if((p->typ&NQ)==DOUBLE)
+        emit(f,"\t.align\t3\n");
+      else
+        emit(f,"\t.align\t2\n");
+      emit(f,"%s%d:\n\t.long\t",labprefix,p->label);
+      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){
+        emit(f,",0x%02x%02x%02x%02x",ip[4],ip[5],ip[6],ip[7]);
+      }
+      emit(f,"\n");
+    }
+    firstfpc=p->next;
+    free(p);
+  }
+}
+void cleanup_db(FILE *f)
+{
+  dwarf2_cleanup(f);
+  if(f) section=-1;
+}
+/* mark instructions which can (probably) be implemented with faster
+   machine-code than the IC migh suggest, e.g. an addition which can
+   be merged with a load bz use of target addressing-modes;
+   the optimizer should hesitate to modifz such instructions if it's not
+   a definite win */
+
+static int is_single_eff_ic(struct IC *p)
+{
+  struct Var *v;
+  if(p->code!=ADDI2P&&p->code!=SUBIFP)
+    return 0;
+  if(!(p->q2.flags&KONST)){
+    if(CONSERVATIVE_SR){
+      if((p->q2.flags&(VAR|DREFOBJ))!=VAR)
+	return 0;
+      if(p->q2.v->storage_class==STATIC||p->q2.v->storage_class==EXTERN)
+	return 0;
+    }else
+      return 0;
+  }
+  if((p->q1.flags&(VAR|DREFOBJ))!=VAR)
+    return 0;
+  if(p->q1.v->storage_class==STATIC||p->q1.v->storage_class==EXTERN)
+    return 0;
+  if((p->z.flags&(VAR|DREFOBJ))!=VAR)
+    return 0;
+  if(p->z.v->storage_class==STATIC||p->z.v->storage_class==EXTERN)
+    return 0;
+  v=p->z.v;
+  for(p=p->next;p;p=p->next){
+    int c=p->code;
+    if(c==LABEL||(c>=BEQ&&c<=BRA))
+      return 0;
+    if((p->q1.flags&VAR)&&p->q1.v==v){
+      if(p->q1.flags&DREFOBJ)
+	return 1;
+      else
+	return 0;
+    }
+    if((p->q2.flags&VAR)&&p->q2.v==v){
+      if(p->q2.flags&DREFOBJ)
+	return 1;
+      else
+	return 0;
+    }
+    if((p->z.flags&VAR)&&p->z.v==v){
+      if(p->z.flags&DREFOBJ)
+	return 1;
+      else
+	return 0;
+    }
+  }
+}
+void mark_eff_ics(void)
+{
+  struct IC *p;
+  for(p=first_ic;p;p=p->next){
+    if(is_single_eff_ic(p))
+      p->flags|=EFF_IC;
+    else
+      p->flags&=~EFF_IC;
+  }
+}
+
+char *use_libcall(int c,int t,int t2)
+{
+  static char fname[32];
+  char *ret=0;
+
+  if(OLDLIBCALLS) return 0;
+
+  if((t&NQ)==LLONG){
+    ret=fname;
+    if(c==MULT)
+      sprintf(fname,"__mulint64");
+    else if(c==DIV)
+      sprintf(fname,"__div%cint64",(t&UNSIGNED)?'u':'s');
+    else if(c==MOD)
+      sprintf(fname,"__mod%cint64",(t&UNSIGNED)?'u':'s');
+    else if(c==RSHIFT)
+      sprintf(fname,"__rsh%cint64",(t&UNSIGNED)?'u':'s');
+    else if(c==LSHIFT)
+      sprintf(fname,"__lshint64");
+    else
+      ret=0;
+  }
+  return ret;
+}
+
+
+
+#if HAVE_OSEK
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+/* removed */
+#endif
diff --git a/machines/ppc/machine.dt b/machines/ppc/machine.dt
new file mode 100755
index 0000000..526c8d4
--- /dev/null
+++ b/machines/ppc/machine.dt
@@ -0,0 +1,16 @@
+S8BS
+S8BU
+S16BSBE S16BSLE
+S16BUBE S16BULE
+S32BSBE S32BSLE
+S32BUBE S32BULE
+S32BSBE S32BSLE
+S32BUBE S32BULE
+S64BSBE S64BSLE
+S64BUBE S64BULE
+S32BIEEEBE
+S64BIEEEBE
+S64BIEEEBE
+S32BUBE S32BULE
+
+
diff --git a/machines/ppc/machine.h b/machines/ppc/machine.h
new file mode 100755
index 0000000..f02654c
--- /dev/null
+++ b/machines/ppc/machine.h
@@ -0,0 +1,137 @@
+/*  Example of a code-generator for a PowerPC                       */
+
+#include "dt.h"
+
+/*  This struct can be used to implement machine-specific           */
+/*  addressing-modes.                                               */
+/*  Not used in this code-generrator.                               */
+struct AddressingMode{
+    int flags;
+    int base;
+    long offset;
+};
+
+/*  The number of registers of the target machine.                  */
+#define MAXR 87
+
+/*  Number of commandline-options the code-generator accepts.       */
+#define MAXGF 30
+
+/*  If this is set to zero vbcc will not generate ICs where the     */
+/*  target operand is the same as the 2nd source operand.           */
+/*  This can sometimes simplify the code-generator, but usually     */
+/*  the code is better if the code-generator allows it.             */
+#define USEQ2ASZ 1
+
+/*  This specifies the smallest integer type that can be added to a */
+/*  pointer.                                                        */
+#define MINADDI2P INT
+
+/*  This specifies the largest integer type that can be added to a  */
+/*  pointer.                                                        */
+#define MAXADDI2P LONG
+
+#define HAVE_INT_SIZET 1
+
+/*  If the bytes of an integer are ordered most significant byte    */
+/*  byte first and then decreasing set BIGENDIAN to 1.              */
+#define BIGENDIAN 1
+
+/*  If the bytes of an integer are ordered lest significant byte    */
+/*  byte first and then increasing set LITTLEENDIAN to 1.           */
+#define LITTLEENDIAN 0
+
+/*  Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive.    */
+
+/*  If switch-statements should be generated as a sequence of       */
+/*  SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1.      */
+/*  This can yield better code on some machines.                    */
+#define SWITCHSUBS 0
+
+/*  In optimizing compilation certain library memcpy/strcpy-calls   */
+/*  with length known at compile-time will be inlined using an      */
+/*  ASSIGN-IC if the size is less or equal to INLINEMEMCPY.         */
+/*  The type used for the ASSIGN-IC will be UNSIGNED|CHAR.          */
+#define INLINEMEMCPY 256
+
+/*  Parameters are sometimes passed in registers without __reg.     */
+#define HAVE_REGPARMS 1
+
+/*  Parameters on the stack should be pushed in order rather than   */
+/*  in reverse order.                                               */
+#define ORDERED_PUSH 1
+
+/*  Structure for reg_parm().                                       */
+struct reg_handle{
+    unsigned long gregs;
+    unsigned long fregs;
+};
+
+/*  We have some target-specific variable attributes.               */
+#define HAVE_TARGET_ATTRIBUTES
+
+/* We have target-specific pragmas */
+#define HAVE_TARGET_PRAGMAS
+
+/*  We keep track of all registers modified by a function.          */
+#define HAVE_REGS_MODIFIED 1
+
+#define HAVE_TARGET_RALLOC 1
+#define cost_move_reg(x,y) 1
+#define cost_load_reg(x,y) 2
+#define cost_save_reg(x,y) 2
+#define cost_pushpop_reg(x) 3
+
+/* size of buffer for asm-output */
+#define EMIT_BUF_LEN 1024 /* should be enough */
+/* number of asm-output lines buffered */
+#define EMIT_BUF_DEPTH 4
+
+/*  We have no asm_peephole to optimize assembly-output */
+#define HAVE_TARGET_PEEPHOLE 0
+
+/* we have a mark_eff_ics function */
+#define HAVE_TARGET_EFF_IC 1
+
+/* we have register-pairs */
+#define HAVE_REGPAIRS 1
+
+#define JUMP_TABLE_DENSITY 0.8
+#define JUMP_TABLE_LENGTH 12
+
+/* This type will be added to every IC. Can be used by the cg.      */
+#define HAVE_EXT_IC 1
+struct ext_ic {
+  int setcc;
+};
+
+/* OSEK support */
+#define HAVE_OSEK 1
+
+/* We use builtin libcalls for some operations */
+#define HAVE_LIBCALLS 1
+
+/* support for variable-length arrays */
+#define ALLOCVLA_REG 4
+#if 0
+#define ALLOCVLA_INLINEASM "\tlwz\t0,0(1)\n"\
+                           "\taddi\t3,3,7\n"\
+                           "\tsrwi\t3,3,3\n"\
+                           "\tslwi\t3,3,3\n"\
+                           "\tneg\t11,3\n"\
+                           "\tsub\t3,1,3\n"\
+                           "\tsubi\t11,11,8\n"\
+                           "\tstwux\t0,1,11"
+#endif
+#define ALLOCVLA_INLINEASM "\tlwz\t0,0(1)\n"\
+                           "\tneg\t3,3\n"\
+                           "\tsrwi\t3,3,3\n"\
+                           "\tslwi\t3,3,3\n"\
+                           "\tstwux\t0,1,3\n"\
+                           "\taddi\t3,1,____fo"
+#define FREEVLA_REG 6
+#define FREEVLA_INLINEASM "\tlwz\t0,0(1)\n"\
+                          "\tmr\t1,5\n"\
+                          "\tstw\t0,0(1)"
+#define OLDSPVLA_INLINEASM "\tmr\t3,1"
+#define FPVLA_REG 32
diff --git a/machines/ppc/schedule.c b/machines/ppc/schedule.c
new file mode 100755
index 0000000..e7172d3
--- /dev/null
+++ b/machines/ppc/schedule.c
@@ -0,0 +1,1158 @@
+/*
+ * vscppc
+ *
+ * vbcc PowerPC scheduler
+ * (C)1998-2001 by Frank Wille <frank@phoenix.owl.de>
+ *
+ * vscppc is freeware and part of the portable and retargetable ANSI C
+ * compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann.
+ * vscppc may be freely redistributed as long as no modifications are
+ * made and nothing is charged for it. Non-commercial usage is allowed
+ * without any restrictions.
+ * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
+ * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
+ *
+ * History:
+ * V0.5   14-Feb-01
+ *        FSCPR is no longer marked as used/modified, which allows the
+ *        scheduler to rearrange all FPU instructions. As a consequence, the
+ *        only instruction reading FPSCR, mffs, has to be marked as barrier.
+ * V0.4   01-Dec-99
+ *        603e PID7 seems to have a latency of 20 instead 37 for
+ *        the "div" instruction (source: Michal Bartczak).
+ * V0.3b  30-Jul-98
+ *        crxxx instructions used/modified wrong CCRs.
+ * V0.3a  21-Jul-98
+ *        "la" instruction was not recognized.
+ * V0.3   20-Jul-98
+ *        Target-specific options via sched_option() removed. Options
+ *        are passed in the assembler source, e.g. "#vsc elf".
+ *        Differentiation between 603 and 604 (selected by "#vsc cpu").
+ *        Now, scheduling takes place with regard to the real PowerPC
+ *        architecture.
+ * V0.2   12-Jul-98
+
+ *        Option "-elf" lets the scheduler accept ELF/SVR4 sources,
+ *        which only use numbers instead of full register names.
+ *        Target-specific options require a modification in the
+ *        portable scheduler part vsc.c.
+ * V0.1   10-Jul-98
+ *        vscppc seems to be stable, after some tests.
+ *        However, it still needs a lot of fine tuning (my PowerPC
+ *        docs are at home).
+ *        A differentiation between the PPC CPUs (603e, 604e) is missing.
+ * V0.0   09-Jul-98
+ *        File created.
+ *
+ */
+
+#include "vsc.h"
+
+char tg_copyright[]="PowerPC scheduler V0.5 (c) in 1998-2001 by Frank Wille";
+
+static int elf=0,cpu=604;
+
+
+
+int sched_init(void)
+{
+  return (1);
+}
+
+
+void sched_cleanup(void)
+{
+}
+
+
+static void sched_option(char *s)
+{
+  if (!strncmp(s,"elf",3)) {
+    elf = 1;
+  }
+  else if (!strncmp(s,"cpu ",4)) {
+    if (!strncmp(s+4,"603",3))
+      cpu = 603;
+    else if (!strncmp(s+4,"604",3))
+      cpu = 604;
+  }
+}
+
+
+static char *strest(char *s,int n)
+/* returns ptr to the last n characters of string s */
+{
+  return (s + strlen(s) - n);
+}
+
+
+static int setlab(struct sinfo *p,char *lab)
+/* check for a valid local label */
+{
+  int i;
+
+  if (sscanf(lab,elf?".l%d":"l%d",&i) == 1) {
+    p->label = i;
+    return (1);
+  }
+  return (0);
+}
+
+
+static int lsreg(char *s)
+/* checks the operand for load/store addressing mode and returns */
+/* the base register on success, -1 otherwise */
+{
+  char *p = (s+strlen(s))-1;
+  int q;
+
+  while (p>s && *p!='(')
+    --p;
+  if (sscanf(p,elf?"(%d)":"(r%d)",&q) == 1)
+    return (q);
+  return (-1);
+}
+
+
+int sched_info(struct sinfo *p)
+{
+  char buf[16],oper[40],c;
+  int q1,q2,q3,z,i,x,n;
+
+  /* check for vscppc specific options in the source */
+  if (!strncmp(p->txt,"#vsc ",5)) {
+    sched_option(p->txt+5);
+    p->flags = BARRIER;
+    return (1);
+  }
+
+  if (!strncmp(p->txt,"#barrier",8)) {
+    /* an artificial barrier, used e.g. for inline-code */
+    p->flags = BARRIER;
+    return (1);
+  }
+
+  if (sscanf(p->txt," .%15s %39s",buf,oper) >= 1) {
+    /* assembler directive or macro */
+    p->flags = BARRIER;
+    return (1);
+  }
+
+  if (sscanf(p->txt,elf?".l%d:":"l%d:",&i) == 1) {
+    /* a local label */
+    p->label = i;
+    p->flags = LABEL;
+    return (1);
+  }
+
+  if (sscanf(p->txt," mffs%15s %39s",buf,oper) >= 1) {
+    /* mffs reads FPSCR and therefore has to be treated as a barrier, */
+    /* because FPSCR is never marked as used by the scheduler */
+    p->flags = BARRIER;
+    return (1);
+  }
+
+  if ((n = sscanf(p->txt," b%15s %39s",buf,oper)) >= 1) {
+    /* branch instruction */
+    p->latency = 1;
+    BSET(p->pipes,BPU);
+
+    if (n == 1) {
+      /* branch unconditional: b label */
+      if (setlab(p,buf)) {
+        p->flags = UNCOND_BRANCH;
+        return (1);
+      }
+    }
+    else {
+      char *a = strest(buf,3);
+
+      /* reject branch instructions ending with */
+      /* "lr", "ctr", "a" or "l", but accept "bnl" */
+      if ((strncmp(a+1,"lr",2) && strncmp(a,"ctr",3) &&
+           *(a+2)!='l' && *(a+2)!='a') ||
+          !strcmp(buf,"nl")) {
+
+        if (*buf == 'd') {
+          /* bdz... or bdnz... */
+          a = oper;
+          if (strcmp(buf,"dz") && strcmp(buf,"dnz")) {
+            while (*a && *a!=',')
+              a++;
+            if (*a == ',')
+              a++;
+            else
+              a = 0;
+          }
+          if (a) {
+            if (setlab(p,a)) {
+              p->flags = COND_BRANCH;
+              BSET(p->modifies,CTR);
+              /* @@@ unable to determine the used CCRs - set all to used */
+              for (x=CCR; x<(CCR+8); x++)
+                BSET(p->uses,x);
+              return (1);
+            }
+          }
+        }
+
+        else if (*buf == 'c') {
+          if (sscanf(oper,"%d,%d,%s",&q1,&q2,buf) == 3) {
+            /* conditional branch: bc m,n,label */
+            if (setlab(p,buf)) {
+              p->flags = COND_BRANCH;
+              BSET(p->uses,CCR+(q2>>2));
+              return (1);
+            }
+          }
+        }
+
+        else {
+          /* normal conditional branch: b<cond> [crN,]label */
+          a = buf;
+          if (sscanf(oper,elf?"%d,%s":"cr%d,%s",&i,buf) != 2) {
+            i = 0;
+            a = oper;
+          }
+          if (setlab(p,a)) {
+            p->flags = COND_BRANCH;
+            BSET(p->uses,CCR+i);
+            return (1);
+          }
+        }
+      }
+    }
+
+    p->flags = BARRIER;
+    return (1);
+  }
+
+
+  if (cpu == 603) {
+    /* scheduling for the PowerPC 603 */
+
+    if ((!elf && sscanf(p->txt," %15s %c%d,%39s",buf,&c,&z,oper) == 4) ||
+        (elf && sscanf(p->txt," %15s %d,%39s",buf,&z,oper) == 3)) {
+      if (elf) {
+        if ((buf[0]=='l' && buf[1]=='f') || (buf[0]=='s' && buf[2]=='f'))
+          c = 'f';
+        else
+          c = 'r';
+      }
+      if ((q1 = lsreg(oper))>=0 && (c=='r'||c=='f')) {
+        /* load/store instruction ...,d(rQ1) */
+
+        if (!strcmp(buf,"la")) {
+          /* la rZ,d(rQ1) is the same as: addi rZ,rQ1,d */
+          p->latency = 1;
+          BSET(p->pipes,IU);
+          BSET(p->pipes,SRU);  /* addi may also execute in SRU */
+          BSET(p->uses,GPR+q1);
+          BSET(p->modifies,GPR+z);
+          return (1);
+        }
+
+        BSET(p->pipes,LSU);
+        if (*(strest(buf,1)) == 'u')  /* update instruction? */
+          BSET(p->modifies,GPR+q1);
+        else
+          BSET(p->uses,GPR+q1);
+
+        if (c == 'r') {
+          /* integer load/store */
+
+          if (!strncmp(strest(buf,2),"mw",2)) {
+            /* load/store multiple word rz,i(rq1) */
+
+            if (*buf == 'l') {
+              p->latency = 2+(32-z);
+              for (x=z; x<32; x++)
+                BSET(p->modifies,GPR+x);
+              BSET(p->uses,MEM);
+            }
+            else {
+              p->latency = 1+(32-z);
+              for (x=z; x<32; x++)
+                BSET(p->uses,GPR+x);
+              BSET(p->modifies,MEM);
+            }
+          }
+          else {
+            /* load/store integer rz,i(rq1) */
+
+            p->latency = 3;
+            if(*buf == 'l') {
+              BSET(p->modifies,GPR+z);
+              BSET(p->uses,MEM);
+            }
+            else{
+              BSET(p->uses,GPR+z);
+              BSET(p->modifies,MEM);
+            }
+          }
+        }
+
+        else {
+          /* load/store float fz,d(rQ1) */
+
+          p->latency = 3;
+          if(*buf == 'l') {
+            BSET(p->modifies,FPR+z);
+            BSET(p->uses,MEM);
+          }
+          else{
+            BSET(p->uses,FPR+z);
+            BSET(p->modifies,MEM);
+          }
+        }
+
+        return (1);
+      }
+    }
+
+    if ((!elf && sscanf(p->txt," %15s %c%d,r%d,r%d",buf,&c,&z,&q1,&q2) == 5) ||
+        (elf && sscanf(p->txt," %15s %d,%d,%d",buf,&z,&q1,&q2) == 4)) {
+      if (*buf=='l' || (buf[0]=='s' && buf[1]=='t')) {
+        if (elf) {
+          if ((buf[0]=='l' && buf[1]=='f') || (buf[0]=='s' && buf[2]=='f'))
+            c = 'f';
+          else
+            c = 'r';
+        }
+
+        BSET(p->pipes,LSU);
+        BSET(p->uses,GPR+q2);
+        if (!strncmp(strest(buf,2),"ux",2))  /* update instruction? */
+          BSET(p->modifies,GPR+q1);
+        else
+          BSET(p->uses,GPR+q1);
+
+        if (c == 'r') {
+          /* integer load/store */
+
+          if (!strncmp(buf,"lsw",3) || !strncmp(buf,"stsw",4)) {
+            /* load/store string word rz,rq1,rq2/imm */
+            p->flags = BARRIER;  /* too complex... ;) */
+            return (1);
+          }
+          else {
+            /* load/store integer indexed rz,rq1,rq2 */
+
+            p->latency = 3;
+            if(*buf == 'l') {
+              BSET(p->modifies,GPR+z);
+              BSET(p->uses,MEM);
+            }
+            else{
+              if (!strcmp(buf,"stwcx."))
+                p->latency = 8;
+              BSET(p->uses,GPR+z);
+              BSET(p->modifies,MEM);
+            }
+            return (1);
+          }
+        }
+
+        else if (c == 'f') {
+          /* load/store float indexed fz,rq1,rq2 */
+          p->latency = 3;
+          if(*buf == 'l') {
+            BSET(p->modifies,FPR+z);
+            BSET(p->uses,MEM);
+          }
+          else{
+            BSET(p->uses,FPR+z);
+            BSET(p->modifies,MEM);
+          }
+          return (1);
+        }
+      }
+    }
+
+    if (sscanf(p->txt,elf ? " fcm%15s %d,%d,%d" : " fcm%15s cr%d,f%d,f%d",
+               buf,&z,&q1,&q2) == 4) {
+      /* floating point compare CR0 */
+      p->latency = 3;
+      BSET(p->pipes,FPU);
+      BSET(p->modifies,CCR+z);
+      /*BSET(p->modifies,FPSCR);*/
+      BSET(p->uses,FPR+q1);
+      BSET(p->uses,FPR+q2);
+      return (1);
+    }
+    if (sscanf(p->txt,elf ? " fcm%15s %d,%d" : " fcm%15s f%d,f%d",
+               buf,&q1,&q2) == 3) {
+      /* floating point compare */
+      p->latency = 3;
+      BSET(p->pipes,FPU);
+      BSET(p->modifies,CCR);
+      /*BSET(p->modifies,FPSCR);*/
+      BSET(p->uses,FPR+q1);
+      BSET(p->uses,FPR+q2);
+      return (1);
+    }
+
+    if ((n = sscanf(p->txt,elf ? " f%15s %d,%d,%d,%d" :
+                    " f%15s f%d,f%d,f%d,f%d",buf,&z,&q1,&q2,&q3))>=3) {
+      /* floating point operation with 2, 3 or 4 operands */
+
+#if 0
+      if (strncmp(buf,"abs",3) &&
+          strncmp(buf,"mr",2) &&
+          strncmp(buf,"nabs",4) &&
+          strncmp(buf,"neg",3) &&
+          strncmp(buf,"sel",3))
+        BSET(p->modifies,FPSCR);  /* only some instr. don't alter FPSCR */
+#endif
+
+      if (!strncmp(buf,"divs",4) ||
+          !strncmp(buf,"res",3))
+        p->latency = 18;
+      else if (!strncmp(buf,"div",3))
+        p->latency = 33;
+      else if (!strncmp(buf,"mul",3) ||
+               !strncmp(buf,"madd",4) ||
+               !strncmp(buf,"msub",4) ||
+               !strncmp(buf,"nmadd",5) ||
+               !strncmp(buf,"nmsub",5))
+        p->latency = 4;
+      else
+        p->latency = 3;
+
+      if (*(strest(buf,1)) == '.')
+        BSET(p->modifies,CCR+1);
+      BSET(p->pipes,FPU);
+      BSET(p->uses,FPR+q1);
+      if (n >= 4) {
+        BSET(p->uses,FPR+q2);
+        if (n == 5)
+          BSET(p->uses,FPR+q3);
+      }
+      BSET(p->modifies,FPR+z);
+      return (1);
+    }
+
+    if (sscanf(p->txt,elf ? " cm%15s %d,%d,%d" : " cm%15s cr%d,r%d,r%d",
+        buf,&z,&q1,&q2) == 4) {
+      /* integer compare instruction */
+      p->latency = 1;
+      BSET(p->pipes,IU);
+      BSET(p->pipes,SRU);
+      BSET(p->modifies,CCR+z);
+      BSET(p->uses,GPR+q1);
+      if (*(strest(buf,1)) != 'i')
+        BSET(p->uses,GPR+q2);
+      return (1);
+    }
+    if (sscanf(p->txt,elf ? " cm%15s %d,%d" : " cm%15s r%d,r%d",
+        buf,&q1,&q2) == 3) {
+      /* integer compare instruction CR0 */
+      p->latency = 1;
+      BSET(p->pipes,IU);
+      BSET(p->pipes,SRU);
+      BSET(p->modifies,CCR);
+      BSET(p->uses,GPR+q1);
+      if (*(strest(buf,1)) != 'i')
+        BSET(p->uses,GPR+q2);
+      return (1);
+    }
+
+    if (!elf) {
+      if (sscanf(p->txt," cm%15s cr%d,r%d,%d",buf,&z,&q1,&i) == 4) {
+        /* immediate integer compare instruction */
+        p->latency = 1;
+        BSET(p->pipes,IU);
+        BSET(p->pipes,SRU);
+        BSET(p->modifies,CCR+z);
+        BSET(p->uses,GPR+q1);
+        return (1);
+      }
+      if (sscanf(p->txt," cm%15s r%d,%d",buf,&q1,&i) == 3) {
+        /* immediate integer compare instruction CR0 */
+        p->latency = 1;
+        BSET(p->pipes,IU);
+        BSET(p->pipes,SRU);
+        BSET(p->modifies,CCR+z);
+        BSET(p->uses,GPR+q1);
+        return (1);
+      }
+    }
+
+    if ((n = sscanf(p->txt," cr%15s %d,%d,%d",buf,&z,&q1,&q2)) >= 2) {
+      /* condition code register operation (vbcc uses this version) */
+      p->latency = 1;
+      BSET(p->pipes,SRU);
+      BSET(p->modifies,CCR+(z>>4));
+      if (n >= 3) {
+        BSET(p->uses,CCR+(q1>>4));
+        if (n == 4)
+          BSET(p->uses,CCR+(q2>>4));
+      }
+      return (1);
+    }
+
+    if (sscanf(p->txt,elf ? " rlw%15s %d,%d,%d,%d,%d" :
+               " rlw%15s r%d,r%d,%d,%d,%d",buf,&z,&q1,&i,&n,&x) == 6) {
+      /* rotate left: rlwimi, rlwinm, rlwnm r1,r2,x,y,z */
+      p->latency = 1;
+      BSET(p->pipes,IU);
+      if (*(strest(buf,1)) == '.')
+        BSET(p->modifies,CCR);
+      BSET(p->uses,GPR+q1);
+      BSET(p->modifies,GPR+z);
+      return (1);
+    }
+
+    if (sscanf(p->txt,elf ? " %15s %d,%d,%c" : " %15s r%d,r%d,%c",
+        buf,&z,&q1,&c) == 4) {
+      /* op r1,r2,imm */
+      if (!strncmp(buf,"addi",4) ||
+          !strncmp(buf,"andi",4) ||
+          !strncmp(buf,"mulli",5) ||
+          !strncmp(buf,"ori",3) ||
+          !strncmp(buf,"slwi",4) ||
+          !strncmp(buf,"srwi",4) ||
+          !strncmp(buf,"srawi",5) ||
+          !strncmp(buf,"subi",4) ||
+          !strncmp(buf,"xori",4)) {
+        char *a = strest(buf,1);
+
+        if (*buf == 'm')  /* mulli */
+          p->latency = 3;
+        else
+          p->latency = 1;
+        BSET(p->pipes,IU);
+        if (!strncmp(buf,"add",3) && *(buf+4)!='c')
+          BSET(p->pipes,SRU);  /* addi/addis may also execute in SRU */
+        if (*a == '.') {
+          BSET(p->modifies,CCR);
+          --a;
+        }
+        if (*a == 'c')
+          BSET(p->modifies,XER);
+        BSET(p->uses,GPR+q1);
+        BSET(p->modifies,GPR+z);
+        return (1);
+      }
+    }
+
+    if (sscanf(p->txt,elf ? " %15s %d,0,%d" : " %15s r%d,0,r%d",
+        buf,&z,&q2) == 3) {
+      /* op r1,0,r3 */
+      if (!strncmp(buf,"add",3) ||
+          !strncmp(buf,"sub",3)) {
+        p->latency = 1;
+        BSET(p->pipes,IU);
+        if (*(strest(buf,1)) == '.')
+          BSET(p->modifies,CCR);
+        else
+          BSET(p->pipes,SRU);  /* add/addo may also execute in SRU */
+        BSET(p->uses,GPR+q2);
+        BSET(p->modifies,GPR+z);
+        return (1);
+      }
+    }
+
+    if (sscanf(p->txt,elf ? " %15s %d,%d,%d" : " %15s r%d,r%d,r%d",
+        buf,&z,&q1,&q2) == 4) {
+      /* op r1,r2,r3 */
+      if (!strncmp(buf,"add",3) ||
+          !strncmp(buf,"and",3) ||
+          !strncmp(buf,"div",3) ||
+          !strncmp(buf,"eqv",3) ||
+          !strncmp(buf,"mul",3) ||
+          !strncmp(buf,"nand",4) ||
+          !strncmp(buf,"nor",3) ||
+          !strncmp(buf,"or",2) ||
+          !strncmp(buf,"sl",2) ||
+          !strncmp(buf,"sr",2) ||
+          !strncmp(buf,"sub",3) ||
+          !strncmp(buf,"xor",3)) {
+        char *a = strest(buf,1);
+
+        if (!strncmp(buf,"mul",3)) {
+          if (*(buf+5) == 'u')
+            p->latency = 6;  /* mulhwu needs 6 cycles */
+          else
+            p->latency = 5;
+          if (*(buf+3) == 'l')
+            BSET(p->modifies,XER);
+        }
+        else if (!strncmp(buf,"div",3)) {
+/*          p->latency = 37;*/
+          p->latency = 20;  /* 603e has 20 since PID7 */
+          BSET(p->modifies,XER);
+        }
+        else
+          p->latency = 1;
+        BSET(p->pipes,IU);
+        if (!strcmp(buf,"add") || !strcmp(buf,"addo"))
+          BSET(p->pipes,SRU);  /* add/addo may also execute in SRU */
+
+        if (*a == '.') {
+          BSET(p->modifies,CCR);
+          --a;
+        }
+        if (*a == 'o') {
+          BSET(p->modifies,XER);
+          --a;
+        }
+        if (*a == 'c') {
+          BSET(p->modifies,XER);
+          --a;
+        }
+        if (*a == 'e')
+          BSET(p->uses,XER);
+        BSET(p->uses,GPR+q1);
+        BSET(p->uses,GPR+q2);
+        BSET(p->modifies,GPR+z);
+        return (1);
+      }
+    }
+
+    if (sscanf(p->txt,elf ? " l%15s %d,%c" : " l%15s r%d,%c",
+        buf,&z,&c) == 3) {
+      if (*buf == 'i') {
+        /* li, lis -> addi, addis */
+        p->latency = 1;
+        BSET(p->pipes,IU);
+        BSET(p->pipes,SRU);
+        BSET(p->modifies,GPR+z);
+        return (1);
+      }
+    }
+
+    if (sscanf(p->txt,elf ? " %15s %d,%d" : " %15s r%d,r%d",
+        buf,&z,&q1) == 3) {
+      /* op r1,r2 */
+      if (!strncmp(buf,"add",3) ||
+          !strncmp(buf,"exts",4) ||
+          !strncmp(buf,"mr",2) ||
+          !strncmp(buf,"neg",3) ||
+          !strncmp(buf,"sub",3)) {
+        char *a = strest(buf,1);
+
+        p->latency = 1;
+        if (*buf=='a' || *buf=='s')
+          BSET(p->uses,XER);  /* addme/addze/subfme/subfze/... */
+        BSET(p->pipes,IU);
+        if (*a == '.') {
+          BSET(p->modifies,CCR);
+          --a;
+        }
+        if (*a == 'o') {
+          BSET(p->modifies,XER);
+        }
+        BSET(p->uses,GPR+q1);
+        BSET(p->modifies,GPR+z);
+        return (1);
+      }
+    }
+
+    if (sscanf(p->txt,elf?" m%15s %d":" m%15s r%d",buf,&z) == 2) {
+      /* mtxxx, mfxxx: move from/to special registers */
+      int reg=0;
+  
+      if (!strcmp(&buf[1],"xer"))
+        reg = XER;
+      else if (!strcmp(&buf[1],"ctr"))
+        reg = CTR;
+      else if (!strcmp(&buf[1],"lr"))
+        reg = LR;
+      else if (!strncmp(&buf[1],"fs",2))
+        reg = FPSCR;
+      if (reg) {
+        if (reg == FPSCR) {
+          p->latency = 3;
+          BSET(p->pipes,FPU);
+          /*if (*buf == 'f') {
+            BSET(p->uses,reg);
+            BSET(p->modifies,z);
+          }
+          else {*/
+            BSET(p->uses,z);
+            BSET(p->modifies,reg);
+          /*}*/
+        }
+        else {
+          BSET(p->pipes,SRU);
+          if (*buf == 'f') {
+            p->latency = 1;
+            BSET(p->uses,reg);
+            BSET(p->modifies,z);
+          }
+          else {
+            p->latency = 2;
+            BSET(p->uses,z);
+            BSET(p->modifies,reg);
+          }
+        }
+        return (1);
+      }
+    }
+  }
+
+
+  else if (cpu == 604) {
+    /* scheduling for the PowerPC 604 */
+
+    if ((!elf && sscanf(p->txt," %15s %c%d,%39s",buf,&c,&z,oper) == 4) ||
+        (elf && sscanf(p->txt," %15s %d,%39s",buf,&z,oper) == 3)) {
+      if (elf) {
+        if ((buf[0]=='l' && buf[1]=='f') || (buf[0]=='s' && buf[2]=='f'))
+          c = 'f';
+        else
+          c = 'r';
+      }
+      if ((q1 = lsreg(oper))>=0 && (c=='r'||c=='f')) {
+        /* load/store instruction ...,d(rQ1) */
+
+        if (!strcmp(buf,"la")) {
+          /* la rZ,d(rQ1) is the same as: addi rZ,rQ1,d */
+          p->latency = 1;
+          BSET(p->pipes,SCIU1);
+          BSET(p->pipes,SCIU2);
+          BSET(p->uses,GPR+q1);
+          BSET(p->modifies,GPR+z);
+          return (1);
+        }
+
+        BSET(p->pipes,LSU);
+        if (*(strest(buf,1)) == 'u')  /* update instruction? */
+          BSET(p->modifies,GPR+q1);
+        else
+          BSET(p->uses,GPR+q1);
+
+        if (c == 'r') {
+          /* integer load/store */
+
+          if (!strncmp(strest(buf,2),"mw",2)) {
+            /* load/store multiple word rz,i(rq1) */
+
+            p->latency = 2+(32-z);
+            if (*buf == 'l') {
+              for (x=z; x<32; x++)
+                BSET(p->modifies,GPR+x);
+              BSET(p->uses,MEM);
+            }
+            else {
+              for (x=z; x<32; x++)
+                BSET(p->uses,GPR+x);
+              BSET(p->modifies,MEM);
+            }
+          }
+          else {
+            /* load/store integer rz,i(rq1) */
+
+            if(*buf == 'l') {
+              p->latency = 2;
+              BSET(p->modifies,GPR+z);
+              BSET(p->uses,MEM);
+            }
+            else{
+              p->latency = 3;
+              BSET(p->uses,GPR+z);
+              BSET(p->modifies,MEM);
+            }
+          }
+        }
+
+        else {
+          /* load/store float fz,d(rQ1) */
+
+          p->latency = 3;
+          if(*buf == 'l') {
+            BSET(p->modifies,FPR+z);
+            BSET(p->uses,MEM);
+          }
+          else{
+            BSET(p->uses,FPR+z);
+            BSET(p->modifies,MEM);
+          }
+        }
+
+        return (1);
+      }
+    }
+
+    if ((!elf && sscanf(p->txt," %15s %c%d,r%d,r%d",buf,&c,&z,&q1,&q2) == 5) ||
+        (elf && sscanf(p->txt," %15s %d,%d,%d",buf,&z,&q1,&q2) == 4)) {
+      if (*buf=='l' || (buf[0]=='s' && buf[1]=='t')) {
+        if (elf) {
+          if ((buf[0]=='l' && buf[1]=='f') || (buf[0]=='s' && buf[2]=='f'))
+            c = 'f';
+          else
+            c = 'r';
+        }
+
+        BSET(p->pipes,LSU);
+        BSET(p->uses,GPR+q2);
+        if (!strncmp(strest(buf,2),"ux",2))  /* update instruction? */
+          BSET(p->modifies,GPR+q1);
+        else
+          BSET(p->uses,GPR+q1);
+
+        if (c == 'r') {
+          /* integer load/store */
+
+          if (!strncmp(buf,"lsw",3) || !strncmp(buf,"stsw",4)) {
+            /* load/store string word rz,rq1,rq2/imm */
+            p->flags = BARRIER;  /* too complex... ;) */
+            return (1);
+          }
+          else {
+            /* load/store integer indexed rz,rq1,rq2 */
+
+            if(*buf == 'l') {
+              p->latency = 2;
+              BSET(p->modifies,GPR+z);
+              BSET(p->uses,MEM);
+            }
+            else{
+              p->latency = 3;
+              BSET(p->uses,GPR+z);
+              BSET(p->modifies,MEM);
+            }
+            return (1);
+          }
+        }
+
+        else if (c == 'f') {
+          /* load/store float indexed fz,rq1,rq2 */
+          p->latency = 3;
+          if(*buf == 'l') {
+            BSET(p->modifies,FPR+z);
+            BSET(p->uses,MEM);
+          }
+          else{
+            BSET(p->uses,FPR+z);
+            BSET(p->modifies,MEM);
+          }
+          return (1);
+        }
+      }
+    }
+
+    if (sscanf(p->txt,elf ? " fcm%15s %d,%d,%d" : " fcm%15s cr%d,f%d,f%d",
+               buf,&z,&q1,&q2) == 4) {
+      /* floating point compare CR0 */
+      p->latency = 3;
+      BSET(p->pipes,FPU);
+      BSET(p->modifies,CCR+z);
+      /*BSET(p->modifies,FPSCR);*/
+      BSET(p->uses,FPR+q1);
+      BSET(p->uses,FPR+q2);
+      return (1);
+    }
+    if (sscanf(p->txt,elf ? " fcm%15s %d,%d" : " fcm%15s f%d,f%d",
+               buf,&q1,&q2) == 3) {
+      /* floating point compare */
+      p->latency = 3;
+      BSET(p->pipes,FPU);
+      BSET(p->modifies,CCR);
+      /*BSET(p->modifies,FPSCR);*/
+      BSET(p->uses,FPR+q1);
+      BSET(p->uses,FPR+q2);
+      return (1);
+    }
+
+    if ((n = sscanf(p->txt,elf ? " f%15s %d,%d,%d,%d" :
+                    " f%15s f%d,f%d,f%d,f%d",buf,&z,&q1,&q2,&q3))>=3) {
+      /* floating point operation with 2, 3 or 4 operands */
+
+#if 0
+      if (strncmp(buf,"abs",3) &&
+          strncmp(buf,"mr",2) &&
+          strncmp(buf,"nabs",4) &&
+          strncmp(buf,"neg",3) &&
+          strncmp(buf,"sel",3))
+        BSET(p->modifies,FPSCR);  /* only some instr. don't alter FPSCR */
+#endif
+
+      if (!strncmp(buf,"divs",4) ||
+          !strncmp(buf,"res",3))
+        p->latency = 18;
+      else if (!strncmp(buf,"div",3))
+        p->latency = 32;
+      else
+        p->latency = 3;
+
+      if (*(strest(buf,1)) == '.')
+        BSET(p->modifies,CCR+1);
+      BSET(p->pipes,FPU);
+      BSET(p->uses,FPR+q1);
+      if (n >= 4) {
+        BSET(p->uses,FPR+q2);
+        if (n == 5)
+          BSET(p->uses,FPR+q3);
+      }
+      BSET(p->modifies,FPR+z);
+      return (1);
+    }
+
+    if (sscanf(p->txt,elf ? " cm%15s %d,%d,%d" : " cm%15s cr%d,r%d,r%d",
+        buf,&z,&q1,&q2) == 4) {
+      /* integer compare instruction */
+      p->latency = 1;
+      BSET(p->pipes,SCIU1);
+      BSET(p->pipes,SCIU2);
+      BSET(p->modifies,CCR+z);
+      BSET(p->uses,GPR+q1);
+      if (*(strest(buf,1)) != 'i')
+        BSET(p->uses,GPR+q2);
+      return (1);
+    }
+    if (sscanf(p->txt,elf ? " cm%15s %d,%d" : " cm%15s r%d,r%d",
+        buf,&q1,&q2) == 3) {
+      /* integer compare instruction CR0 */
+      p->latency = 1;
+      BSET(p->pipes,SCIU1);
+      BSET(p->pipes,SCIU2);
+      BSET(p->modifies,CCR);
+      BSET(p->uses,GPR+q1);
+      if (*(strest(buf,1)) != 'i')
+        BSET(p->uses,GPR+q2);
+      return (1);
+    }
+
+    if (!elf) {
+      if (sscanf(p->txt," cm%15s cr%d,r%d,%d",buf,&z,&q1,&i) == 4) {
+        /* immediate integer compare instruction */
+        p->latency = 1;
+        BSET(p->pipes,SCIU1);
+        BSET(p->pipes,SCIU2);
+        BSET(p->modifies,CCR+z);
+        BSET(p->uses,GPR+q1);
+        return (1);
+      }
+      if (sscanf(p->txt," cm%15s r%d,%d",buf,&q1,&i) == 3) {
+        /* immediate integer compare instruction CR0 */
+        p->latency = 1;
+        BSET(p->pipes,SCIU1);
+        BSET(p->pipes,SCIU2);
+        BSET(p->modifies,CCR+z);
+        BSET(p->uses,GPR+q1);
+
+        return (1);
+      }
+    }
+
+    if ((n = sscanf(p->txt," cr%15s %d,%d,%d",buf,&z,&q1,&q2)) >= 2) {
+      /* condition code register operation (vbcc uses this version) */
+      p->latency = 1;
+      BSET(p->pipes,CRU);
+      BSET(p->modifies,CCR+(z>>4));
+      if (n >= 3) {
+        BSET(p->uses,CCR+(q1>>4));
+        if (n == 4)
+          BSET(p->uses,CCR+(q2>>4));
+      }
+      return (1);
+    }
+
+    if (sscanf(p->txt,elf ? " rlw%15s %d,%d,%d,%d,%d" :
+               " rlw%15s r%d,r%d,%d,%d,%d",buf,&z,&q1,&i,&n,&x) == 6) {
+      /* rotate left: rlwimi, rlwinm, rlwnm r1,r2,x,y,z */
+      p->latency = 1;
+      BSET(p->pipes,SCIU1);
+      BSET(p->pipes,SCIU2);
+      if (*(strest(buf,1)) == '.')
+        BSET(p->modifies,CCR);
+      BSET(p->uses,GPR+q1);
+      BSET(p->modifies,GPR+z);
+      return (1);
+    }
+
+    if (sscanf(p->txt,elf ? " %15s %d,%d,%c" : " %15s r%d,r%d,%c",
+        buf,&z,&q1,&c) == 4) {
+      /* op r1,r2,imm */
+      if (!strncmp(buf,"addi",4) ||
+          !strncmp(buf,"andi",4) ||
+          !strncmp(buf,"mulli",5) ||
+          !strncmp(buf,"ori",3) ||
+          !strncmp(buf,"slwi",4) ||
+          !strncmp(buf,"srwi",4) ||
+          !strncmp(buf,"srawi",5) ||
+          !strncmp(buf,"subi",4) ||
+          !strncmp(buf,"xori",4)) {
+        char *a = strest(buf,1);
+
+        if (*buf == 'm') { /* mulli */
+          p->latency = 3;
+          BSET(p->pipes,MCIU);
+        }
+        else {
+          p->latency = 1;
+          BSET(p->pipes,SCIU1);
+          BSET(p->pipes,SCIU2);
+        }
+        if (*a == '.') {
+          BSET(p->modifies,CCR);
+          --a;
+        }
+        if (*a == 'c')
+          BSET(p->modifies,XER);
+        BSET(p->uses,GPR+q1);
+        BSET(p->modifies,GPR+z);
+        return (1);
+      }
+    }
+
+    if (sscanf(p->txt,elf ? " %15s %d,0,%d" : " %15s r%d,0,r%d",
+        buf,&z,&q2) == 3) {
+      /* op r1,0,r3 */
+      if (!strncmp(buf,"add",3) ||
+          !strncmp(buf,"sub",3)) {
+        p->latency = 1;
+        BSET(p->pipes,SCIU1);
+        BSET(p->pipes,SCIU2);
+        if (*(strest(buf,1)) == '.')
+          BSET(p->modifies,CCR);
+        else
+          BSET(p->pipes,SRU);  /* add/addo may also execute in SRU */
+        BSET(p->uses,GPR+q2);
+        BSET(p->modifies,GPR+z);
+        return (1);
+      }
+    }
+
+    if (sscanf(p->txt,elf ? " %15s %d,%d,%d" : " %15s r%d,r%d,r%d",
+        buf,&z,&q1,&q2) == 4) {
+      /* op r1,r2,r3 */
+      if (!strncmp(buf,"add",3) ||
+          !strncmp(buf,"and",3) ||
+          !strncmp(buf,"div",3) ||
+          !strncmp(buf,"eqv",3) ||
+          !strncmp(buf,"mul",3) ||
+          !strncmp(buf,"nand",4) ||
+          !strncmp(buf,"nor",3) ||
+          !strncmp(buf,"or",2) ||
+          !strncmp(buf,"sl",2) ||
+          !strncmp(buf,"sr",2) ||
+          !strncmp(buf,"sub",3) ||
+          !strncmp(buf,"xor",3)) {
+        char *a = strest(buf,1);
+
+        if (!strncmp(buf,"mul",3)) {
+          p->latency = 4;
+          BSET(p->pipes,MCIU);
+          if (*(buf+3) == 'l')
+            BSET(p->modifies,XER);
+        }
+        else if (!strncmp(buf,"div",3)) {
+          p->latency = 20;
+          BSET(p->pipes,MCIU);
+          BSET(p->modifies,XER);
+        }
+        else {
+          p->latency = 1;
+          BSET(p->pipes,SCIU1);
+          BSET(p->pipes,SCIU2);
+        }
+        if (*a == '.') {
+          BSET(p->modifies,CCR);
+          --a;
+        }
+        if (*a == 'o') {
+          BSET(p->modifies,XER);
+          --a;
+        }
+        if (*a == 'c') {
+          BSET(p->modifies,XER);
+          --a;
+        }
+        if (*a == 'e')
+          BSET(p->uses,XER);
+        BSET(p->uses,GPR+q1);
+        BSET(p->uses,GPR+q2);
+        BSET(p->modifies,GPR+z);
+        return (1);
+      }
+    }
+
+    if (sscanf(p->txt,elf ? " l%15s %d,%c" : " l%15s r%d,%c",
+        buf,&z,&c) == 3) {
+      if (*buf == 'i') {
+        /* li, lis -> addi, addis */
+        p->latency = 1;
+        BSET(p->pipes,SCIU1);
+        BSET(p->pipes,SCIU2);
+        BSET(p->modifies,GPR+z);
+        return (1);
+      }
+    }
+
+    if (sscanf(p->txt,elf ? " %15s %d,%d" : " %15s r%d,r%d",
+        buf,&z,&q1) == 3) {
+      /* op r1,r2 */
+      if (!strncmp(buf,"add",3) ||
+          !strncmp(buf,"exts",4) ||
+          !strncmp(buf,"mr",2) ||
+          !strncmp(buf,"neg",3) ||
+          !strncmp(buf,"sub",3)) {
+        char *a = strest(buf,1);
+
+        p->latency = 1;
+        BSET(p->pipes,SCIU1);
+        BSET(p->pipes,SCIU2);
+        if (*buf=='a' || *buf=='s')
+          BSET(p->uses,XER);  /* addme/addze/subfme/subfze/... */
+        if (*a == '.') {
+          BSET(p->modifies,CCR);
+          --a;
+        }
+        if (*a == 'o') {
+          BSET(p->modifies,XER);
+        }
+        BSET(p->uses,GPR+q1);
+        BSET(p->modifies,GPR+z);
+        return (1);
+      }
+    }
+
+    if (sscanf(p->txt,elf?" m%15s %d":" m%15s r%d",buf,&z) == 2) {
+      /* mtxxx, mfxxx: move from/to special registers */
+      int reg=0;
+  
+      if (!strcmp(&buf[1],"xer"))
+        reg = XER;
+      else if (!strcmp(&buf[1],"ctr"))
+        reg = CTR;
+      else if (!strcmp(&buf[1],"lr"))
+        reg = LR;
+      else if (!strncmp(&buf[1],"fs",2))
+        reg = FPSCR;
+      if (reg) {
+        if (reg == FPSCR) {
+          p->latency = 3;
+          BSET(p->pipes,FPU);
+          /*if (*buf == 'f') {
+            BSET(p->uses,reg);
+            BSET(p->modifies,z);
+          }
+          else {*/
+            BSET(p->uses,z);
+            BSET(p->modifies,reg);
+          /*}*/
+        }
+        else {
+          BSET(p->pipes,MCIU);
+          if (*buf == 'f') {
+            p->latency = 3;
+            BSET(p->uses,reg);
+            BSET(p->modifies,z);
+          }
+          else {
+            p->latency = 1;
+            BSET(p->uses,z);
+            BSET(p->modifies,reg);
+          }
+        }
+        return (1);
+      }
+    }
+  }
+
+  p->flags = BARRIER;
+  return (1);
+}
diff --git a/machines/ppc/schedule.h b/machines/ppc/schedule.h
new file mode 100755
index 0000000..9d6fba8
--- /dev/null
+++ b/machines/ppc/schedule.h
@@ -0,0 +1,53 @@
+/*
+ * vscppc
+ *
+ * vbcc PowerPC scheduler
+ * (C)1998 by Frank Wille <frank@phoenix.owl.de>
+ *
+ * vscppc is freeware and part of the portable and retargetable ANSI C
+ * compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann.
+ * vscppc may be freely redistributed as long as no modifications are
+ * made and nothing is charged for it. Non-commercial usage is allowed
+ * without any restrictions.
+ * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
+ * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
+ *
+ * History:
+ * V0.3   20-Jul-98
+ *        Differentiation between 603 and 604. Now, scheduling takes
+ *        place with regard to the real PowerPC architecture.
+ * V0.1   10-Jul-98
+ *        vscppc seems to be stable enough, after some tests.
+ *        However, it still needs a lot of fine tuning.
+ *        A differentiation between the PPC CPUs (603e, 604e) is missing.
+ * V0.0   09-Jul-98
+ *        File created.
+ *
+ */
+
+#define PIPES 7   /* the max. number of pipes, as required by the 604 */
+
+/* Pipe Names 603 */
+#define BPU 0     /* Branch Prediction Unit */
+#define SRU 1     /* Special Reg. Unit */
+#define IU 2      /* Integer Unit */
+#define FPU 5     /* Floating Point Unit */
+#define LSU 6     /* Load Store Unit */
+
+/* Pipe Names 604 */
+#define CRU 1     /* Condition Register Unit */
+#define SCIU1 2   /* Single Cycle Integer Unit #1 */
+#define SCIU2 3   /* Single Cycle Integer Unit #2 */
+#define MCIU 4    /* Multiple Cycle Integer Unit */
+
+
+#define REGS 76   /* 32 GPR, 32 FPR, 8 CCR, LR, CTR, XER, FPSCR */
+
+/* REG-offsets */
+#define GPR 0
+#define FPR 32
+#define CCR 64
+#define XER 72
+#define CTR 73
+#define LR 74
+#define FPSCR 75
diff --git a/machines/qnice/machine.c b/machines/qnice/machine.c
new file mode 100755
index 0000000..b919925
--- /dev/null
+++ b/machines/qnice/machine.c
@@ -0,0 +1,2412 @@
+/*  Code generator for qnice cpu.               */
+
+#include "supp.h"
+
+static char FILE_[]=__FILE__;
+/*  Public data that MUST be there.                             */
+
+/* Name and copyright. */
+char cg_copyright[]="vbcc code-generator for qnice V0.1 (c) in 2016 by Volker Barthelmann";
+
+/*  Commandline-flags the code-generator accepts                */
+int g_flags[MAXGF]={VALFLAG,0,0,0,
+                    0,0,0,0,
+                    0,VALFLAG};
+char *g_flags_name[MAXGF]={"cpu","int32","no-delayed-popping","const-in-data",
+                           "merge-constants","no-peephole","mtiny","mlarge",
+                           "mhuge","rw-threshold","soft-mul"};
+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"};
+
+/*  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","R0","R1","R2","R3","R4","R5","R6","R7",
+		  "R8","R9","R10","R11","R12","R13","R14","R15",
+		  "R0/R1","R2/R3","R4/R5","R6/R7",
+		  "R8/R9","R11/R12"};
+
+/*  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,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,1,1};
+
+int reg_prio[MAXR+1]={0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,1,1};
+
+struct reg_handle empty_reg_handle={0};
+
+/* Names of target-specific variable attributes.                */
+char *g_attr_name[]={"__interrupt","__rbank","__norbank",0};
+#define INTERRUPT 1
+#define RBANK 2
+#define NORBANK 4
+
+
+/****************************************/
+/*  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,1,1};
+static long msizetab[MAX_TYPE+1]={0,1,1,1,1,2,4,2,4,4,0,1,2,2,0,0,0,1,0,1,1};
+
+struct Typ ityp={SHORT},ltyp={LONG};
+
+#define INT32 (g_flags[1]&USEDFLAG)
+#define NOPEEP  (g_flags[5]&USEDFLAG)
+#define TINY  1 /*(g_flags[6]&USEDFLAG)*/
+#define LARGE 0 /*(g_flags[7]&USEDFLAG)*/
+#define HUGE  0 /*(g_flags[8]&USEDFLAG)*/
+#define SOFTMUL  (g_flags[10]&USEDFLAG)
+
+
+#define NDATA 0
+#define NBSS 1
+#define NCDATA 2
+#define FDATA 3
+#define FBSS 4
+#define FCDATA 5
+#define HDATA 6
+#define HBSS 7
+#define HCDATA 8
+#define CODE 9
+#define SPECIAL 10
+#define BITS 11
+
+static int section=-1,newobj,scnt;
+static char *codename="\t.text\n",
+  *ndataname="\t.data\n",
+  *fdataname="\t.data\n",
+  *hdataname="\t.data\n",
+  *nbssname="\t.bss\n",
+  *fbssname="\t.bss\n",
+  *hbssname="\t.bss\n",
+  *ncdataname="\t.text\n",
+  *fcdataname="\t.text\n",
+  *hcdataname="\t.text\n";
+
+#define POST_INC 1
+#define PRE_DEC  2
+
+extern int static_cse, dref_cse;
+
+/* (user)stack-pointer, pointer-tmp, int-tmp; reserved for compiler */
+static const int sp=14,sr=15,pc=16,t1=12,t2=13,MTMP1=22;
+static const int r8=9,r9=10,r8r9=21;
+static int tmp1,tmp2,tmp3,tmp4,t2_used;
+static void pr(FILE *,struct IC *);
+static void function_top(FILE *,struct Var *,long);
+static void function_bottom(FILE *f,struct Var *,long);
+static int scratchreg(int,struct IC *);
+static struct Var nvar,fvar;
+static int load_const;
+static struct IC *icp;
+
+static char *marray[]={0,
+                       "__far=__attr(\"far\")",
+		       "__near=__attr(\"near\")",
+		       "__huge=__attr(\"huge\")",
+                       "__section(x,y)=__vattr(\"section(\"#x\",\"#y\")\")",
+		       "__interrupt(x)=__interrupt __vattr(\"ivec(\"__str(x)\")\")",
+		       "__QNICE__",
+		       "__SIZE_T_INT=1",
+		       "__str(x)=#x",
+		       0};
+
+#define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
+#define isconst(x) ((p->x.flags&(KONST|DREFOBJ))==KONST)
+
+static long loff,stack,stackoffset,notpopped,dontpop,maxpushed;
+
+static char *ccs[]={"z","!z","v","!v","??","??"};
+static char *ccu[]={"z","!z","n","!n","??","??"};
+
+static char *logicals[]={"or","xor","and"};
+static char *arithmetics[]={"shl","shr","add","sub"};
+
+static char *dct[]={"",".bit",".short",".short",".short",".short",".short",".short",".short",".short",
+		    "(void)",".short",".long",".long"};
+static int pushedsize,pushorder=2;
+static char *idprefix="_",*labprefix="l";
+static int exit_label,have_frame,stackchecklabel,stack_valid;
+static char *ret,*call,*jump;
+static int frame_used;
+static int rwthreshold;
+
+#define STR_NEAR "near"
+#define STR_FAR "far"
+#define STR_HUGE "huge"
+
+#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)==CHAR||(t&NQ)==NPOINTER)
+#define ISSTATIC(v) ((v)->storage_class==EXTERN||(v)->storage_class==STATIC)
+
+static int ISFAR(struct Var *v)
+{
+  struct Typ *vt;
+  if(v==&nvar) return 0;
+  if(v==&fvar) return 1;
+  vt=v->vtyp;
+  while(ISARRAY(vt->flags)) vt=vt->next;
+  if(vt->attr&&strstr(STR_NEAR,vt->attr))
+    return 0;
+  if(HUGE||LARGE)
+    return 1;
+  if(vt->attr&&(strstr(STR_FAR,vt->attr)||strstr(STR_HUGE,vt->attr)))
+    return 1;
+  return 0;
+}
+
+static int special_section(FILE *f,struct Var *v)
+{
+  char *sec,*e;
+  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;
+}
+static void callee_push(long push)
+{
+  if(push-stackoffset>stack)
+    stack=push-stackoffset;
+}
+static void push(long push)
+{
+  stackoffset-=push;
+  if(stackoffset<maxpushed) 
+    maxpushed=stackoffset;
+  if(-maxpushed>stack) stack=-maxpushed;
+}
+static void pop(long pop)
+{
+  stackoffset+=pop;
+}
+int pointer_type(struct Typ *p)
+{
+  struct Typ *merk=p;
+  if(!p) ierror(0);
+  while(ISARRAY(p->flags)||ISFUNC(p->flags)) p=p->next;
+  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;
+  }
+  if((merk->flags&NQ)==FUNKT){
+    if(TINY)
+      return NPOINTER;
+    else
+      return HPOINTER;
+  }
+  if(LARGE)
+    return FPOINTER;
+  else if(HUGE)
+    return HPOINTER;
+  else
+    return NPOINTER;
+}
+
+/* return non-zero if IC is implemented by a function call */
+static int islibcall(struct IC *p)
+{
+  /* TODO: check if necessary */
+  return 0;
+}
+
+static long voff(struct obj *p)
+{
+  if(p->v->offset<0)
+    return loff-zm2l(p->v->offset)+zm2l(p->val.vmax)-stackoffset+pushedsize;
+  return zm2l(p->v->offset)+zm2l(p->val.vmax)-stackoffset;
+}
+static int alignment(struct obj *o)
+{
+  if(o->flags&DREFOBJ) return 1;
+  if(!(o->flags&VAR)) ierror(0);
+  if(ISSTATIC(o->v)) return zm2l(o->val.vmax)&1;
+  return voff(o)&1;
+}
+
+static void emit_obj(FILE *f,struct obj *p,int t)
+/*  output an operand                      */
+{
+  if(p->am){
+    if(p->am->flags==POST_INC){
+      emit(f,"@%s++",regnames[p->am->base]);
+      return;
+    }else if(p->am->flags==PRE_DEC){
+      emit(f,"@--%s",regnames[p->am->base]);
+      return;
+    }else{
+      ierror(0);
+    }
+  }
+  if((p->flags&(KONST|DREFOBJ))==(KONST|DREFOBJ)){
+    emitval(f,&p->val,p->dtyp&NU);
+    return;
+  }
+  if((p->flags&(DREFOBJ|REG))==(DREFOBJ|REG)) emit(f,"@");
+  /*if(p->flags&VARADR) ierror(0);*/
+  if((p->flags&(VAR|REG))==VAR){
+    if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER){
+      if(voff(p))
+	emit(f,"@%s+#%ld",regnames[sp],voff(p));
+      else emit(f,"@%s",regnames[sp]);
+    }else{
+      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(!zmeqto(l2zm(0L),p->val.vmax))
+	emit(f,"+%ld",(long)zm2l(p->val.vmax)*2);
+    }
+  }
+  if(p->flags&REG){
+    emit(f,"%s",regnames[p->reg]);
+  }
+  /* sometimes we just or a REG into a KONST */
+  if((p->flags&(KONST|REG))==KONST){
+    if(ISFLOAT(t)){
+      ierror(0);
+      emit(f,"#%s%d",labprefix,addfpconst(p,t));
+    }else{
+      emitval(f,&p->val,t&NU);
+    }
+  }
+}
+
+static void emit_lword(FILE *f,struct obj *p,int t,char *def)
+/*  output low-word of an operand */
+{
+  if((p->flags&(KONST|DREFOBJ))==KONST){
+    eval_const(&p->val,t);
+    if(ISFLOAT(t)){
+      unsigned char *ip=(unsigned char *)&vfloat;
+      emit(f,"0x%02x%02x",ip[1],ip[0]);
+    }else{
+      long v;
+      v=zm2l(vmax);
+      emit(f,"%ld",v&0xffff);
+    }
+    return;
+  }
+  if((p->flags&(REG|DREFOBJ))==REG){
+    if(!reg_pair(p->reg,&rp))
+      ierror(0);
+    emit(f,"%s",regnames[rp.r1]);
+    return;
+  }
+  if((p->flags&(REG|DREFOBJ))==(REG|DREFOBJ)){
+    emit(f,def,regnames[p->reg]);
+    return;
+  }
+  ierror(0);
+}
+
+static void emit_hword(FILE *f,struct obj *p,int t,char *def)
+/*  output high-word of an operand */
+{
+  if((p->flags&(KONST|DREFOBJ))==KONST){
+    eval_const(&p->val,t);
+    if(ISFLOAT(t)){
+      unsigned char *ip=(unsigned char *)&vfloat;
+      emit(f,"0x%02x%02x",ip[3],ip[2]);
+    }else{
+      long v;
+      v=zm2l(vmax);
+      emit(f,"%ld",(v>>16)&0xffff);
+    }
+    return;
+  }
+  if((p->flags&(REG|DREFOBJ))==REG){
+    if(!reg_pair(p->reg,&rp))
+      ierror(0);
+    emit(f,"%s",regnames[rp.r2]);
+    return;
+  }
+  if((p->flags&(REG|DREFOBJ))==(REG|DREFOBJ)){
+    emit(f,def,regnames[p->reg]);
+    return;
+  }
+  ierror(0);
+}
+
+static void cleanup_lword(FILE *f,struct obj *p)
+/* cleanup increased address pointers of emit_hlword */
+{
+  if((p->flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&!scratchreg(p->reg,icp))
+    emit(f,"\tsub\t2,%s\n",regnames[p->reg]);
+}
+
+static void pr(FILE *f,struct IC *p)
+{
+}
+
+static void function_top(FILE *f,struct Var *v,long offset)
+/*  erzeugt Funktionskopf                       */
+{
+  int i,rcnt;char *tmp;
+
+  have_frame=0;stack_valid=1;
+  pushedsize=0;
+
+  if(!special_section(f,v)&&section!=CODE){
+    emit(f,codename);
+  }
+  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));  
+  }
+  if(stack_check){
+    stackchecklabel=++label;
+    BSET(regs_modified,t1);
+    emit(f,"\tmov\t%s,#%s%d\n",regnames[t1],labprefix,stackchecklabel);
+    emit(f,"\t%s\t%s__stack_check\n",call,idprefix);/*FIXME:usrstack*/
+  }
+  for(rcnt=0,i=1;i<=16;i++){
+    if(regused[i]&&!regscratch[i]&&!regsa[i])
+      rcnt++;
+  }
+  if(v->tattr&NORBANK) rcnt=0;
+  if(rcnt>((v->tattr&RBANK)?0:rwthreshold)){
+    /*emit(f,"\tadd\t256,%s\n",regnames[sr]);*/
+    emit(f,"\tincrb\n");
+    have_frame=3;
+  }else{
+    for(i=1;i<=16;i++){
+      if(regused[i]&&!regscratch[i]&&!regsa[i]){
+	emit(f,"\tmove\t%s,@--%s\n",regnames[i],regnames[sp]);
+	push(1);
+	have_frame=1;pushedsize+=1;
+      }
+    }
+  }
+  if(offset){
+    emit(f,"\tsub\t%ld,%s\n",offset,regnames[sp]);
+    if(!have_frame) 
+      have_frame|=1;
+  }
+}
+static void function_bottom(FILE *f,struct Var *v,long offset)
+/*  erzeugt Funktionsende                       */
+{
+  int i;
+  if(offset) emit(f,"\tadd\t%ld,%s\n",offset,regnames[sp]);
+  if(have_frame==3){
+    /*emit(f,"\tsub\t256,%s\n",regnames[sr]);*/
+    emit(f,"\tdecrb\n");
+  }else{
+    for(i=16;i>0;i--){
+      if(regused[i]&&!regscratch[i]&&!regsa[i]){
+	emit(f,"\tmove\t@%s++,%s\n",regnames[sp],regnames[i]);
+	pop(1);
+      }
+    }
+  }
+  if(v->tattr&INTERRUPT){
+    emit(f,"\trti\n");
+  }else{
+    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,"%s%d\tequ\t%ld\n",labprefix,stackchecklabel,offset+pushedsize-maxpushed);
+  if(stack_valid){
+    long ustack=stack+offset+pushedsize;
+    if(!v->fi) v->fi=new_fi();
+    if(v->fi->flags&ALL_STACK){
+      if(v->fi->stack1!=stack)
+        if(f) error(319,"stack",ustack,v->fi->stack1);
+    }else{
+      v->fi->flags|=ALL_STACK;
+      v->fi->stack1=stack;
+    }
+    emit(f,"\t.equ\t%s__ustack_%s,%ld\n",idprefix,v->identifier,zm2l(v->fi->stack1));
+  }
+}
+static int compare_objects(struct obj *o1,struct obj *o2)
+{
+  if((o1->flags&(REG|DREFOBJ))==REG&&(o2->flags&(REG|DREFOBJ))==REG&&o1->reg==o2->reg)
+    return 1;
+  if((o1->flags&(KONST|VAR|DREFOBJ|REG|VARADR))==(o2->flags&(KONST|VAR|DREFOBJ|REG|VARADR))&&o1->am==o2->am){
+    if(!(o1->flags&VAR)||(o1->v==o2->v&&zmeqto(o1->val.vmax,o2->val.vmax))){
+      if(!(o1->flags&REG)||o1->reg==o2->reg){
+	return 1;
+      }
+    }
+  }
+  return 0;
+}
+static void clear_ext_ic(struct ext_ic *p)
+{
+  p->flags=0;
+  p->r=0;
+  p->offset=0;
+}
+
+static void peephole(struct IC *p)
+{
+  int c,c2,r,t;struct IC *p2;
+  struct AddressingMode *am;
+  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;
+
+    /* [Rx+] in q1 */
+    if(!p->q1.am&&(p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)){
+      r=p->q1.reg; t=q1typ(p);
+      if((!(p->q2.flags&REG)||p->q2.reg!=r)&&(!(p->z.flags&REG)||p->z.reg!=r)){
+	for(p2=p->next;p2;p2=p2->next){
+	  c2=p2->code;
+	  if((c2==ADD||(c2==ADDI2P&&(p2->typf2&NQ)!=HPOINTER))&&(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(zmeqto(vmax,l2zm(1L))&&ISHWORD(t)){
+	      p2->code=NOP;
+	      p2->q1.flags=p2->q2.flags=p2->z.flags=0;
+	      p->q1.am=mymalloc(sizeof(*am));
+	      p->q1.am->flags=POST_INC;
+	      p->q1.am->base=r;
+	    }else break;
+	  }
+	  if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
+	  if(((p2->q1.flags&REG)&&p2->q1.reg==r)||((p2->q2.flags&REG)&&p2->q2.reg==r)||((p2->z.flags&REG)&&p2->z.reg==r)) break;
+	}
+      }
+    }
+    /* [Rx+] in q2 */
+    if(!p->q2.am&&(p->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)){
+      r=p->q2.reg; t=q2typ(p);
+      if((!(p->q1.flags&REG)||p->q1.reg!=r)&&(!(p->z.flags&REG)||p->z.reg!=r)){
+	for(p2=p->next;p2;p2=p2->next){
+          c2=p2->code;
+	  if((c2==ADD||(c2==ADDI2P&&(p2->typf2&NQ)!=HPOINTER))&&(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(zmeqto(vmax,l2zm(1L))&&ISHWORD(t)){
+	      p2->code=NOP;
+	      p2->q1.flags=p2->q2.flags=p2->z.flags=0;
+	      p->q2.am=mymalloc(sizeof(*am));
+	      p->q2.am->flags=POST_INC;
+	      p->q2.am->base=r;
+	    }else break;
+	  }
+	  if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
+	  if(((p2->q1.flags&REG)&&p2->q1.reg==r)||((p2->q2.flags&REG)&&p2->q2.reg==r)||((p2->z.flags&REG)&&p2->z.reg==r)) break;
+	}
+      }
+    }
+    /* [Rx+] in z */
+    /* currently we do it only if q2 is empty; could be more clever */
+    if(!p->z.am&&!p->q2.flags&&(p->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)){
+      r=p->z.reg; t=ztyp(p);
+      if((!(p->q1.flags&REG)||p->q1.reg!=r)&&(!(p->q2.flags&REG)||p->q2.reg!=r)){
+	for(p2=p->next;p2;p2=p2->next){
+          c2=p2->code;
+	  if((c2==ADD||(c2==ADDI2P&&(p2->typf2&NQ)!=HPOINTER))&&(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(zmeqto(vmax,l2zm(1L))&&ISHWORD(t)){
+	      p2->code=NOP;
+	      p2->q1.flags=p2->q2.flags=p2->z.flags=0;
+	      p->z.am=mymalloc(sizeof(*am));
+	      p->z.am->flags=POST_INC;
+	      p->z.am->base=r;
+	    }else break;
+	  }
+	  if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
+	  if(((p2->q1.flags&REG)&&p2->q1.reg==r)||((p2->q2.flags&REG)&&p2->q2.reg==r)||((p2->z.flags&REG)&&p2->z.reg==r)) break;
+	}
+      }
+    }
+    /* --@Rx */
+    if(c==SUBIFP&&isreg(q1)&&isreg(z)&&p->q1.reg==p->z.reg&&p->q1.reg<=16&&isconst(q2)){
+      long sz;
+      r=p->q1.reg;
+      eval_const(&p->q2.val,q2typ(p));
+      sz=zm2l(vmax);
+      if(sz==1){
+	for(p2=p->next;p2;p2=p2->next){
+	  c2=p2->code;
+	  if(!p2->q1.am&&(p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r&&(!(p2->q2.flags&REG)||p2->q2.reg!=r)&&(!(p2->z.flags&REG)||p2->z.reg!=r)&&(c2!=CONVERT||(q1typ(p2)&NQ)<=(ztyp(p2)&NQ))){
+	    t=(q1typ(p2)&NQ);
+	    if((ISINT(t)||ISPOINTER(t))&&ISHWORD(t)&&zmeqto(sizetab[q1typ(p2)&NQ],l2zm(sz))&&!islibcall(p2)){
+	      p2->q1.am=am=mymalloc(sizeof(*am));
+	      p2->q1.val.vmax=l2zm(0L);
+	      am->base=r;
+	      am->flags=PRE_DEC;
+	      p->code=NOP;
+	      p->q1.flags=p->q2.flags=p->z.flags=0;
+	      break;
+	    }
+	  }
+	  if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r&&(!(p2->q1.flags&REG)||p2->q1.reg!=r)&&(!(p2->z.flags&REG)||p2->z.reg!=r)){
+	    t=(q2typ(p2)&NQ);
+	    if((ISINT(t)||ISPOINTER(t))&&ISHWORD(t)&&zmeqto(sizetab[q2typ(p2)&NQ],l2zm(sz))&&!islibcall(p2)){
+	      p2->q2.am=am=mymalloc(sizeof(*am));
+	      p2->q2.val.vmax=l2zm(0L);
+	      am->base=r;
+	      am->flags=PRE_DEC;
+	      p->code=NOP;
+	      p->q1.flags=p->q2.flags=p->z.flags=0;
+	      break;
+	    }
+	  }
+	  /* currently we do it only if q2 is empty; perhaps be more clever in the future */
+	  if(!p2->z.am&&!p2->q2.flags&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r&&(!(p2->q2.flags&REG)||p2->q2.reg!=r)&&(!(p2->q1.flags&REG)||p2->q1.reg!=r)){
+	    t=(ztyp(p2)&NQ);
+	    if((ISINT(t)||ISPOINTER(t))&&ISHWORD(t)&&zmeqto(sizetab[ztyp(p2)&NQ],l2zm(sz))&&!islibcall(p2)){
+	      p2->z.am=am=mymalloc(sizeof(*am));
+	      p2->z.val.vmax=l2zm(0L);
+	      am->base=r;
+	      am->flags=PRE_DEC;
+	      p->code=NOP;
+	      p->q1.flags=p->q2.flags=p->z.flags=0;
+	      break;
+	    }
+	  }
+	  if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
+	  if((p2->q1.flags&REG)&&p2->q1.reg==r) break;
+	  if((p2->q2.flags&REG)&&p2->q2.reg==r) break;
+	  if((p2->z.flags&REG)&&p2->z.reg==r) break;
+	}
+      }
+    }
+  }
+}
+
+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;
+  return &obj;
+}
+
+
+/* load an operand if necessary, use register r if needed */
+static void load_op(FILE *f,struct obj *o,int t,int r)
+{
+  if(o->am)
+    return;
+
+  if(o->flags&(REG|VARADR))
+    return;
+
+  if(o->flags&KONST){
+    if((t&NQ)==DOUBLE||(t&NQ)==LDOUBLE){
+      int l=addfpconst(o,t);
+      emit(f,"\tmove\t%s%d,%s\n",labprefix,l,regnames[r]);
+      o->reg=r;
+      o->flags=REG|DREFOBJ;
+    }else if(load_const||(o->flags&DREFOBJ)){
+      emit(f,"\tmove\t");
+      emit_obj(f,o,t);
+      emit(f,",%s\n",regnames[r]);
+      o->flags|=REG;
+      o->flags&=~KONST;
+    }else
+      return;
+  }else{
+    if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER){
+      if(ISHWORD(t)&&voff(o)==0){
+	if(o->flags&DREFOBJ){
+	  emit(f,"\tmove\t@%s,%s\n",regnames[sp],regnames[r]);
+	  o->reg=r;
+	  o->flags|=REG|DREFOBJ;
+	  BSET(regs_modified,r);
+	  return;
+	}else
+	  r=sp;
+      }else{
+	emit(f,"\tmove\t%s,%s\n",regnames[sp],regnames[r]);
+	if(voff(o))
+	  emit(f,"\tadd\t%ld,%s\n",voff(o),regnames[r]);
+      }
+      
+    }else{
+      emit(f,"\tmove\t");
+      emit_obj(f,o,t);
+      emit(f,",%s\n",regnames[r]);
+    }
+    
+    
+    if(o->flags&DREFOBJ){
+      emit(f,"\tmove\t@%s,%s\n",regnames[r],regnames[r]);
+    }
+    
+    o->flags|=REG|DREFOBJ;
+  }
+
+  BSET(regs_modified,r);
+  o->reg=r;
+}
+
+static void move(FILE *f,struct obj *q,int qr,struct obj *z,int zr,int t)
+/*  Generates code to move object q (or register qr) into object z (or  */
+/*  register zr). One must be a register and DREFOBJ only allowed with  */
+/*  registers.                                                          */
+{
+  if(q&&z&&compare_objects(q,z))
+    return;
+
+  if(q&&(q->flags&(REG|DREFOBJ))==REG) qr=q->reg;
+  if(z&&(z->flags&(REG|DREFOBJ))==REG) zr=z->reg;
+
+  if(qr&&qr==zr)
+    return;
+
+
+  if(ISLWORD(t)){
+    if(!qr) load_op(f,q,t,t1);
+    if(!zr) load_op(f,z,t,t2);
+    
+    emit(f,"\tmove\t");
+    if(qr&&reg_pair(qr,&rp))
+      emit(f,"%s",regnames[rp.r1]);
+    else
+      emit_lword(f,q,t,"@%s++");
+    emit(f,",");
+    if(zr&&reg_pair(zr,&rp))
+      emit(f,"%s",regnames[rp.r1]);
+    else
+      emit_lword(f,z,t,"@%s++");
+    emit(f,"\n");
+    emit(f,"\tmove\t");
+    if(qr&&reg_pair(qr,&rp))
+      emit(f,"%s",regnames[rp.r2]);
+    else
+      emit_hword(f,q,t,"@%s++");
+    emit(f,",");
+    if(zr&&reg_pair(zr,&rp))
+      emit(f,"%s",regnames[rp.r2]);
+    else
+      emit_hword(f,z,t,"@%s++");
+    emit(f,"\n");
+    if(!qr) cleanup_lword(f,q);
+    if(!zr) cleanup_lword(f,z);
+    return;
+  }
+
+
+  emit(f,"\tmove\t");
+  if(qr) emit(f,"%s",regnames[qr]); else emit_obj(f,q,t);
+  emit(f,",");
+  if(zr) emit(f,"%s",regnames[zr]); else emit_obj(f,z,t);
+  emit(f,"\n");
+}
+
+static int get_reg(FILE *f,struct IC *p)
+{
+  int i;
+  for(i=1;i<=16;i++){
+    if(!regs[i]&&(regscratch[i]||regused[i])&&!regsa[i]){
+      BSET(regs_modified,i);
+      return i;
+    }
+  }
+  return 0;
+}
+
+
+
+static void save_result(FILE *f,int r,struct IC *p,int t)
+/*  Saves result in register r to object o. May use tp or ti. */ 
+{
+  ierror(0);
+}
+
+static int scratchreg(int r,struct IC *p)
+{
+  int c;
+  if(r==t1||r==t2)
+    return 1;
+  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&REG)&&p->q1.reg==r) return 0;
+    if((p->q2.flags&REG)&&p->q2.reg==r) return 0;
+    if((p->z.flags&REG)&&p->z.reg==r) return 0;
+  }
+}
+
+/****************************************/
+/*  End of private fata and functions.  */
+/****************************************/
+
+int emit_peephole(void)
+{
+  int entries,i,r1,r2,r3,r4;long x,y,z;
+  char *asmline[EMIT_BUF_DEPTH];
+  char s1[16],s2[16];
+
+  if(NOPEEP)
+    return 0;
+
+  i=emit_l;
+  if(emit_f==0)
+    entries=i-emit_f+1;
+  else
+    entries=EMIT_BUF_DEPTH;
+  asmline[0]=emit_buffer[i];
+ 
+  if(entries>=1){
+    if(sscanf(asmline[0],"\tmove\t0,R%d",&r1)==1){
+      sprintf(asmline[0],"\txor\tR%d,R%d\n",r1,r1);
+      return 1;
+    }
+  }
+
+  if(entries>=2){
+    i--;
+    if(i<0) i=EMIT_BUF_DEPTH-1;
+    asmline[1]=emit_buffer[i];
+    if(sscanf(asmline[0],"\t%15s\t%ld,R%d",s1,&x,&r1)==3&&sscanf(asmline[1],"\t%15s\t%ld,R%d",s2,&y,&r2)==3&&r1==r2&&!strcmp(s1,s2)&&(!strcmp(s1,"add")||!strcmp(s1,"sub")||!strcmp(s1,"shl")||!strcmp(s1,"shr"))){
+      sprintf(asmline[1],"\t%s\t%ld,R%d\n",s1,x+y,r1);
+      remove_asm();
+      return 1;
+    }
+    if(sscanf(asmline[0],"\t%15s\t%ld,@R%d",s1,&x,&r1)==3&&sscanf(asmline[1],"\t%15s\t%ld,@R%d",s2,&y,&r2)==3&&r1==r2&&!strcmp(s1,s2)&&(!strcmp(s1,"add")||!strcmp(s1,"sub")||!strcmp(s1,"shl")||!strcmp(s1,"shr"))){
+      sprintf(asmline[1],"\t%s\t%ld,@R%d\n",s1,x+y,r1);
+      remove_asm();
+      return 1;
+    }
+    if(sscanf(asmline[0],"\tmove\tR%d,R%d",&r1,&r2)==2&&sscanf(asmline[1],"\tmove\tR%d,R%d",&r3,&r4)==2&&r1==r4&&r2==r3){
+      remove_asm();
+      return 1;
+    }
+    if(sscanf(asmline[0],"\tshl\t1,R%d",&r1)==1&&!strstr(asmline[0],"shr")){
+      sprintf(asmline[0],"\tadd\tR%d,R%d\n",r1,r1);
+      return 1;
+    }
+  } 
+
+  return 0;
+}
+
+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;
+  /*  Initialize some values which cannot be statically initialized   */
+  /*  because they are stored in the target's arithmetic.             */
+  maxalign=l2zm(1L);
+  stackalign=l2zm(1L);
+  char_bit=l2zm(16L);
+  for(i=0;i<=MAX_TYPE;i++){
+    sizetab[i]=l2zm(msizetab[i]);
+    align[i]=l2zm(malign[i]);
+  }
+  for(i=1;i<=MAXR;i++){
+    if(i<=16){
+      regsize[i]=l2zm(1L);regtype[i]=&ityp;
+    }else{
+      regsize[i]=l2zm(2L);regtype[i]=&ltyp;
+    }
+  }	
+  
+  /*  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.          */
+  t_min[CHAR]=l2zm(-32768L);
+  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(32767UL);
+  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(65535UL);
+  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);
+
+  /*  Reserve a few registers for use by the code-generator.      */
+  regsa[sp]=regsa[sr]=regsa[pc]=regsa[t1]=regsa[t2]=regsa[MTMP1]=1;
+  regscratch[sp]=regscratch[sr]=regscratch[pc]=regscratch[t1]=regscratch[t2]=0;
+  target_macros=marray;
+  if(TINY) marray[0]="__TINY__";
+  else if(LARGE) marray[0]="__LARGE__";
+  else if(HUGE) marray[0]="__HUGE__";
+  else marray[0]="__MEDIUM__";
+
+  /*static_cse=0;*/
+  dref_cse=0;
+
+  if(g_flags[9]&USEDFLAG)
+    rwthreshold=g_flags_val[9].l;
+  else{
+    if(optspeed)
+      rwthreshold=1;
+    else
+      rwthreshold=2;
+  }
+
+  /* TODO: set argument registers */
+  declare_builtin("__mulint32",LONG,LONG,r8r9,LONG,0,1,0);
+  declare_builtin("__divint32",LONG,LONG,r8r9,LONG,0,1,0);
+  declare_builtin("__divuint32",LONG,LONG,r8r9,LONG,0,1,0);
+  declare_builtin("__modint32",LONG,LONG,r8r9,LONG,0,1,0);
+  declare_builtin("__moduint32",LONG,LONG,r8r9,LONG,0,1,0);
+  declare_builtin("__lslint32",LONG,LONG,r8r9,INT,11,1,0);
+  declare_builtin("__lsrint32",LONG,LONG,r8r9,INT,11,1,0);
+  declare_builtin("__lsruint32",LONG,LONG,r8r9,INT,11,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("__divint64",LLONG,LLONG,0,LLONG,0,1,0);
+  declare_builtin("__divuint64",UNSIGNED|LLONG,UNSIGNED|LLONG,0,UNSIGNED|LLONG,0,1,0);
+  declare_builtin("__modint64",LLONG,LLONG,0,LLONG,0,1,0);
+  declare_builtin("__moduint64",UNSIGNED|LLONG,UNSIGNED|LLONG,0,UNSIGNED|LLONG,0,1,0);
+  declare_builtin("__lsrint64",LLONG,LLONG,0,INT,0,1,0);
+  declare_builtin("__lsruint64",UNSIGNED|LLONG,UNSIGNED|LLONG,0,INT,0,1,0);
+  declare_builtin("__cmpint64",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("__sint32toflt32",FLOAT,LONG,r8r9,0,0,1,0);
+  declare_builtin("__uint32toflt32",FLOAT,UNSIGNED|LONG,r8r9,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,r8r9,0,0,1,0);
+  declare_builtin("__flt32touint32",UNSIGNED|LONG,FLOAT,r8r9,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("__sint16toflt32",FLOAT,INT,r8,0,0,1,0);
+  declare_builtin("__uint16toflt32",FLOAT,UNSIGNED|INT,r8,0,0,1,0);
+  declare_builtin("__sint16toflt64",DOUBLE,INT,r9,0,0,1,0);
+  declare_builtin("__uint16toflt64",DOUBLE,UNSIGNED|INT,r9,0,0,1,0);
+  declare_builtin("__flt32tosint16",INT,FLOAT,r8r9,0,0,1,0);
+  declare_builtin("__flt32touint16",UNSIGNED|INT,FLOAT,r8r9,0,0,1,0);
+  declare_builtin("__flt64tosint16",INT,DOUBLE,0,0,0,1,0);
+  declare_builtin("__flt64touint16",UNSIGNED|INT,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,r8r9,FLOAT,0,1,0);
+  declare_builtin("__subflt32",FLOAT,FLOAT,r8r9,FLOAT,0,1,0);
+  declare_builtin("__mulflt32",FLOAT,FLOAT,r8r9,FLOAT,0,1,0);
+  declare_builtin("__divflt32",FLOAT,FLOAT,r8r9,FLOAT,0,1,0);
+  declare_builtin("__negflt32",FLOAT,FLOAT,r8r9,0,0,1,0);
+  declare_builtin("__cmpsflt32",INT,FLOAT,r8r9,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,0,0,1,0);
+  declare_builtin("__cmpsflt64",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(f==LLONG||f==DOUBLE||f==LDOUBLE)
+    return 0;
+  if(ISSCALAR(f)){
+    if(f==LONG||f==FPOINTER||f==HPOINTER||f==FLOAT)
+      return r8r9;
+    else
+      return r8;
+  }
+  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.                  */
+{
+  t&=NQ;
+  if(r==0) return(0);
+  if((t<LONG||t==NPOINTER)&&r<=16) return 1;
+  if(t==LONG||t==FLOAT||t==FPOINTER||t==HPOINTER){
+    if(r>16) 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<=16) return 0;
+  if(p){
+    switch(r){
+    case 17: p->r1=1;p->r2=2;break;
+    case 18: p->r1=3;p->r2=4;break;
+    case 19: p->r1=5;p->r2=6;break;
+    case 20: p->r1=7;p->r2=8;break;
+    case 21: p->r1=9;p->r2=10;break;
+    case 22: p->r1=t1;p->r2=t2;break;
+	
+    default: ierror(0);
+    }
+  }
+  return 1;
+}
+
+int cost_savings(struct IC *p,int r,struct obj *o)
+{
+  int c=p->code;
+  if((o->flags&DREFOBJ)){
+    if(o->flags&VKONST) return 1;
+    if(r<=4&&p->q2.flags&&o!=&p->z)
+      return 6;
+    else
+      return 4;
+  }else if(o->flags&VKONST){
+    struct obj *co=&o->v->cobj;
+    if((p->code==ASSIGN&&(p->z.flags&DREFOBJ))||p->code==PUSH)
+      return 4;
+    if(co->flags&VARADR)
+      return 4;
+    if(o==&p->q1)
+      eval_const(&co->val,q1typ(p));
+    else
+      eval_const(&co->val,q2typ(p));
+    /*FIXME*/
+    return 0;
+  }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)&&regok(r,CHAR,0)){
+    return 3;
+  }
+  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;
+  return 0;
+}
+
+int must_convert(int o,int t,int const_expr)
+/*  Returns zero if code for converting np to type t    */
+/*  can be omitted.                                     */
+/*  In this generic 32bit RISC cpu pointers and 32bit   */
+/*  integers have the same representation and can use   */
+/*  the same registers.                                 */
+{
+  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.                              */
+{
+  long l=zm2l(size)*2;
+  if(newobj&&section!=SPECIAL)
+    emit(f,"%ld\n",l);
+  else
+    emit(f,"\t.space\t%ld\n",l);
+  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.              */
+{
+}
+static void new_section(FILE *f,int nsec)
+{
+  if(!f||section==nsec) return;
+  section=nsec;
+  if(nsec==HDATA){
+    emit(f,hdataname);
+  }else if(nsec==FDATA){
+    emit(f,fdataname);
+  }else if(nsec==NDATA){
+    emit(f,ndataname);
+  }else if(nsec==HCDATA){
+    emit(f,hcdataname);
+  }else if(nsec==FCDATA){
+    emit(f,fcdataname);
+  }else if(nsec==NCDATA){
+    emit(f,ncdataname);
+  }else if(nsec==HBSS){
+    emit(f,hbssname);
+  }else if(nsec==FBSS){
+    emit(f,fbssname);
+  }else if(nsec==NBSS){
+    emit(f,nbssname);
+  }
+}
+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;
+  char *attr;struct Typ *tv;
+  tv=v->vtyp;
+  while(tv->flags==ARRAY) tv=tv->next;
+  attr=tv->attr;
+  if(v->clist) constflag=is_const(v->vtyp);
+  if(v->storage_class==STATIC){
+    if(ISFUNC(v->vtyp->flags)) return;
+    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))*2);
+    if(!special_section(f,v)){
+      if((v->vtyp->flags&NQ)==BIT){
+	new_section(f,BITS);
+      }else{
+	if(v->clist&&(!constflag||(g_flags[3]&USEDFLAG))){
+	  if(attr&&strstr(attr,STR_HUGE))
+	    new_section(f,HDATA);
+	  else if(attr&&strstr(attr,STR_FAR))
+	    new_section(f,FDATA);
+	  else if(attr&&strstr(attr,STR_NEAR))
+	    new_section(f,NDATA);
+	  else{
+	    if(HUGE)
+	      new_section(f,HDATA);
+	    else if(LARGE)
+	      new_section(f,FDATA);
+	    else
+	      new_section(f,NDATA);
+	  }
+	}
+	if(v->clist&&constflag&&!(g_flags[3]&USEDFLAG)){
+	  if(attr&&strstr(attr,STR_HUGE))
+	    new_section(f,HCDATA);
+	  else if(attr&&strstr(attr,STR_FAR))
+	    new_section(f,FCDATA);
+	  else if(attr&&strstr(attr,STR_NEAR))
+	    new_section(f,NCDATA);
+	  else{
+	    if(HUGE)
+	      new_section(f,HCDATA);
+	    else if(LARGE)
+	      new_section(f,FCDATA);
+	    else
+	      new_section(f,NCDATA);
+	  }
+	}
+	if(!v->clist){
+	  if(attr&&strstr(attr,STR_HUGE))
+	    new_section(f,HBSS);
+	  else if(attr&&strstr(attr,STR_FAR))
+	    new_section(f,FBSS);
+	  else if(attr&&strstr(attr,STR_NEAR))
+	    new_section(f,NBSS);
+	  else{
+	    if(HUGE)
+	      new_section(f,HBSS);
+	    else if(LARGE)
+	      new_section(f,FBSS);
+	    else
+	      new_section(f,NBSS);
+	  }
+	}
+      }
+    }
+    gen_align(f,falign(v->vtyp));
+    emit(f,"%s%ld:\n",labprefix,zm2l(v->offset));
+  }
+
+  if(v->storage_class==EXTERN){
+    if(v->flags&(DEFINED|TENTATIVE)){
+      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))*2);
+      emit(f,"\t.global\t%s%s\n",idprefix,v->identifier);
+      if(!special_section(f,v)){
+	if(v->clist&&(!constflag||(g_flags[3]&USEDFLAG))){
+	  if(attr&&strstr(attr,STR_HUGE))
+	    new_section(f,HDATA);
+	  else if(attr&&strstr(attr,STR_FAR))
+	    new_section(f,FDATA);
+	  else if(attr&&strstr(attr,STR_NEAR))
+	    new_section(f,NDATA);
+	  else{
+	    if(HUGE)
+	      new_section(f,HDATA);
+	    else if(LARGE)
+	      new_section(f,FDATA);
+	    else
+	      new_section(f,NDATA);
+	  }
+	}
+	if(v->clist&&constflag&&!(g_flags[3]&USEDFLAG)){
+	  if(attr&&strstr(attr,STR_HUGE))
+	    new_section(f,HCDATA);
+	  else if(attr&&strstr(attr,STR_FAR))
+	    new_section(f,FCDATA);
+	  else if(attr&&strstr(attr,STR_NEAR))
+	    new_section(f,NCDATA);
+	  else{
+	    if(HUGE)
+	      new_section(f,HCDATA);
+	    else if(LARGE)
+	      new_section(f,FCDATA);
+	    else
+	      new_section(f,NCDATA);
+	  }
+	}
+	if(!v->clist){
+	  if(attr&&strstr(attr,STR_HUGE))
+	    new_section(f,HBSS);
+	  else if(attr&&strstr(attr,STR_FAR))
+	    new_section(f,FBSS);
+	  else if(attr&&strstr(attr,STR_NEAR))
+	    new_section(f,NBSS);
+	  else{
+	    if(HUGE)
+	      new_section(f,HBSS);
+	    else if(LARGE)
+	      new_section(f,FBSS);
+	    else
+	      new_section(f,NBSS);
+	  }
+	}
+      }
+      gen_align(f,falign(v->vtyp));
+      emit(f,"%s%s:\n",idprefix,v->identifier);
+    }else if(strcmp(v->identifier,"__va_start")){
+      emit(f,"\t.global\t%s%s\n",idprefix,v->identifier);
+    }
+  }
+}
+
+void gen_dc(FILE *f,int t,struct const_list *p)
+/*  This function has to create static storage          */
+/*  initialized with const-list p.                      */
+{
+  if(ISPOINTER(t)){
+    if(p->tree)
+      emit(f,"\t%s\t",dct[t&NQ]); 
+    if(ISLWORD(t))
+      t=UNSIGNED|LONG;
+    else
+      t=UNSIGNED|SHORT;
+    if(!p->tree)
+      emit(f,"\t%s\t",dct[t&NQ]);
+  }else{
+    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,0x%02x%02x",ip[1],ip[0],ip[3],ip[2]);
+      if((t&NQ)==DOUBLE||(t&NQ)==LDOUBLE){
+	emit(f,",0x%02x%02x,0x%02x%02x",ip[5],ip[4],ip[7],ip[6]);
+      }
+    }else{
+      if(ISLWORD(t)){
+	long l;
+	eval_const(&p->val,t);
+	l=zm2l(zmand(p->val.vmax,l2zm(65535L)));
+	emit(f,"%ld",l);
+	l=zm2l(zmand(zmrshift(p->val.vmax,l2zm(16L)),l2zm(65535L)));
+	emit(f,",%ld",l);
+      }else
+	emitval(f,&p->val,(t&NU)|UNSIGNED);
+    }
+  }else{
+    int m=p->tree->o.flags;
+    p->tree->o.flags&=~VARADR;
+    emit_obj(f,&p->tree->o,t&NU);
+    p->tree->o.flags=m;
+  }
+  emit(f,"\n");
+}
+
+/*  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 *p,struct Var *v,zmax offset)
+{
+  int c,t,lastcomp=0,cmpzero=0,elab=0,reg,short_add,bit_reverse,need_return=0;
+  struct obj *bit_obj;char *bit_reg;
+  static int idone;
+  struct obj o,*cc=0;int cc_t;
+  struct IC *p2;
+  if(TINY){
+    call="asub";
+    jump="abra";
+  }else{
+    call="asub";
+    jump="abra";
+  }
+  if(v->tattr&INTERRUPT){
+    ret="rti";
+    need_return=1;
+  }else
+    ret="move\t@R13++,R15";
+
+  if(DEBUG&1) printf("gen_code()\n");
+  if(!v->fi) v->fi=new_fi();
+  v->fi->flags|=ALL_REGS;
+
+  for(p2=p;p2;p2=p2->next) clear_ext_ic(&p2->ext);
+  if(!(g_flags[5]&USEDFLAG)){
+    peephole(p);
+    if(!frame_used) offset=l2zm(0L);
+  }
+  for(c=1;c<=15;c++) regs[c]=regsa[c];
+  regs[16]=0;
+  for(c=1;c<=MAXR;c++){
+    if(regscratch[c]&&(regsa[c]||regused[c])){
+      BSET(regs_modified,c);
+    }
+  }
+  loff=zm2l(offset);
+  function_top(f,v,loff);
+  stackoffset=notpopped=dontpop=maxpushed=0;
+  stack=0;
+  for(;p;pr(f,p),p=p->next){
+    c=p->code;t=p->typf;
+    t2_used=0; short_add=0;
+    icp=p;
+    if(c==NOP) continue;
+    if(c==ALLOCREG){
+      regs[p->q1.reg]=1;
+      if(reg_pair(p->q1.reg,&rp)) regs[rp.r1]=regs[rp.r2]=1;
+      BSET(regs_modified,p->q1.reg);
+      continue;
+    }
+    if(c==FREEREG){
+      regs[p->q1.reg]=0;
+      if(reg_pair(p->q1.reg,&rp)) regs[rp.r1]=regs[rp.r2]=0;
+      continue;
+    }
+    if(notpopped&&!dontpop){
+      int flag=0;
+      if(c==LABEL||c==COMPARE||c==TEST||c==BRA){
+	emit(f,"\tadd\t%ld,%s\n",notpopped,regnames[sp]);
+	pop(notpopped);notpopped=0;cc=0;
+      }
+    }
+    if(c==LABEL) {cc=0;emit(f,"%s%d:\n",labprefix,t);continue;}
+    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,"\trbra\t%s%d,1\n",labprefix,t);
+      }
+      cc=0;continue;
+    }
+    if(c>=BEQ&&c<BRA){
+      char *s=0;
+      cc=0;
+      if(cmpzero){
+	cmpzero=0;
+	if(lastcomp&UNSIGNED){
+	  if(c==BLT) continue;
+	  if(c==BGE) s="1";
+	  if(c==BLE) s="z";
+	  if(c==BGT) s="!z";
+	}else{
+	  if(c==BLT) s="n";
+	  if(c==BGE) s="!n";
+	  if(c==BLE) ierror(0);
+	  if(c==BGT) ierror(0);
+	}
+      }
+      if(!s){
+	if(lastcomp&UNSIGNED) s=ccu[c-BEQ]; else s=ccs[c-BEQ];
+      }
+      if(t==exit_label&&!have_frame){
+	emit(f,"\tabra\t@%s++,%s\n",regnames[sp],s);
+      }else{
+	emit(f,"\trbra\t%s%d,%s\n",labprefix,t,s);
+	if(t==exit_label) need_return=1;
+      }
+      continue;
+    }
+    if(c==MOVETOREG){
+      load_op(f,&p->q1,SHORT,t1);
+      if(p->z.reg<=16){
+	move(f,&p->q1,0,0,p->z.reg,SHORT);
+	cc=&p->q1;cc_t=SHORT;
+      }else{
+	move(f,&p->q1,0,0,p->z.reg,LONG);
+	cc=0;
+      }
+      continue;
+    }
+    if(c==MOVEFROMREG){
+      load_op(f,&p->z,SHORT,t2);
+      if(p->q1.reg<=16){
+	move(f,0,p->q1.reg,&p->z,0,SHORT);
+	cc=&p->z;cc_t=SHORT;
+      }else{
+	move(f,0,p->q1.reg,&p->z,0,LONG);
+	cc=0;
+      }
+      continue;
+    }
+    
+    if(c==TEST){
+      /* TODO: optimize in COMPARE? */
+      lastcomp=t;
+      if(cc&&(cc_t&NU)==(t&NU)&&compare_objects(cc,&p->q1)){
+	continue;
+      }
+
+      p->code=c=COMPARE;
+      gval.vmax=l2zm(0L);
+      p->q2.flags=KONST;
+      eval_const(&gval,MAXINT);
+      insert_const(&p->q2.val,t);
+    } 
+    /* switch operands so that we have matching branch */
+    if(c==COMPARE){
+      p2=p->next;
+      while(p2&&p2->code==FREEREG) p2=p2->next;
+      if(!p2||p2->code<BEQ||p2->code>BGT) ierror(0);
+      if(p2->code==BGT){
+	o=p->q1;p->q1=p->q2;p->q2=o;
+	p2->code=BLT;
+      }else if(p2->code==BLE){
+	o=p->q1;p->q1=p->q2;p->q2=o;
+	p2->code=BGE;
+      }
+    }
+
+    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)){
+	  p2=p->next;
+	  while(p2&&p2->code==FREEREG) p2=p2->next;
+	  if(!p2||p2->code<BEQ||p2->code>BGT) ierror(0);
+	  if((t&UNSIGNED)||p2->code==BNE||p2->code==BEQ||p2->code==BLT||p2->code==BGE){
+	    lastcomp=t;
+	    cmpzero=1;
+	    continue;
+	  }
+	}
+      }
+    }
+
+    if(c==SUBPFP){
+      p->code=c=SUB;
+      if((p->typf2&NQ)==NPOINTER) p->typf=t=INT;
+      else if((p->typf2&NQ)==HPOINTER) p->typf=t=LONG;
+      else ierror(0);
+      if((p->typf2&NQ)==NPOINTER){
+	cc=&p->z;cc_t=NPOINTER;
+      }else{
+	cc=0;
+      }
+    }
+
+    if(c==ADDI2P||c==SUBIFP){
+      /*if(c==ADDI2P) p->code=c=ADD; else p->code=c=SUB;*/
+      if((p->typf2&NQ)!=HPOINTER){
+	p->typf=t=(UNSIGNED|SHORT);
+	short_add=2;
+	if(isreg(q2)&&reg_pair(p->q2.reg,&rp)){
+	  /*FIXME:warning*/
+	  p->q2.reg=rp.r1;
+	}
+      }else if(ISHWORD(t)){
+	p->typf=t=(UNSIGNED|LONG);
+	short_add=1;
+      }
+      if((p->typf2&NQ)==NPOINTER){
+	cc=&p->z;cc_t=NPOINTER;
+      }else{
+	cc=0;
+      }      
+    }
+
+    if(c==CONVERT&&!must_convert(p->typf,p->typf2,0)){
+      p->code=c=ASSIGN;
+      p->q2.val.vmax=sizetab[p->typf&NQ];
+    }
+
+    if(c==CONVERT){
+      int to=p->typf2&NU;
+      if(to==INT||to==CHAR) to=SHORT;
+      if(to==(UNSIGNED|INT)||to==(UNSIGNED|CHAR)||to==NPOINTER) to=(UNSIGNED|SHORT);
+      if(to==FPOINTER||to==HPOINTER) to=(UNSIGNED|LONG);
+      if((t&NU)==INT||(t&NU)==CHAR) t=SHORT;
+      if((t&NU)==(UNSIGNED|INT)||(t&NU)==(UNSIGNED|CHAR)||(t&NU)==NPOINTER) t=(UNSIGNED|SHORT);
+      if((t&NQ)==FPOINTER||(t&NQ)==HPOINTER) t=(UNSIGNED|LONG);
+      if((to&NQ)==LONG){
+	if((t&NQ)!=SHORT) ierror(0);
+	load_op(f,&p->q1,to,t1);
+	load_op(f,&p->z,t,t2);
+	if(isreg(q1)){
+	  if(!reg_pair(p->q1.reg,&rp))
+	    ierror(0);
+	  move(f,0,rp.r1,&p->z,0,t);
+	}else
+	  move(f,&p->q1,0,&p->z,0,t);
+	cc=&p->z;cc_t=t;
+	continue;
+      }else if((t&NQ)==LONG){
+	if((to&NQ)!=SHORT) ierror(0);
+	load_op(f,&p->q1,to,t1);
+	load_op(f,&p->z,t,t2);
+	if(isreg(z)){
+	  if(!reg_pair(p->z.reg,&rp))
+	    ierror(0);
+	  emit(f,"\txor\t%s,%s\n",regnames[rp.r2],regnames[rp.r2]);
+	  move(f,&p->q1,0,0,rp.r1,to);
+	  if(!(to&UNSIGNED)){
+	    emit(f,"\trbra\t%s%d,!n\n",labprefix,++label);
+	    emit(f,"\tsub\t1,%s\n",regnames[rp.r2]);
+	    emit(f,"%s%d:\n",labprefix,label);
+	  }
+	}else{
+	  if(to&UNSIGNED){
+	    emit(f,"\tmove\t");
+	    emit_obj(f,&p->q1,to);
+	    emit(f,",@%s++\n",regnames[p->z.reg]);
+	    emit(f,"\tmove\t0,@%s\n",regnames[p->z.reg]);
+	  }else{
+	    if(isreg(q1)){
+	      reg=p->q1.reg;
+	    }else{
+	      reg=t1;
+	      move(f,&p->q1,0,0,t1,to);
+	    }
+	    emit(f,"\tmove\t%s,@%s++\n",regnames[reg],regnames[p->z.reg]);
+	    emit(f,"\tmove\t0,@%s\n",regnames[p->z.reg]);
+	    emit(f,"\tmove\t%s,%s\n",regnames[reg],regnames[reg]);
+	    emit(f,"\trbra\t%s%d,!n\n",labprefix,++label);
+	    emit(f,"\tsub\t1,@%s\n",regnames[p->z.reg]);
+	    emit(f,"%s%d:\n",labprefix,label);
+	  }
+	  if(!scratchreg(p->z.reg,p))
+	    emit(f,"\tsub\t1,%s\n",regnames[p->z.reg]);
+	}
+	cc=0;
+	continue;
+      }else
+	ierror(0);
+    }
+    if(c==MINUS){
+      p->code=c=SUB;
+      p->q2=p->q1;
+      gval.vmax=l2zm(0L);
+      eval_const(&gval,t);
+      insert_const(&p->q1.val,t);
+      p->q1.flags=KONST;
+    }
+    if(c==KOMPLEMENT){
+      load_op(f,&p->q1,t,t1);
+      load_op(f,&p->z,t,t2);
+      if(ISLWORD(t)){
+	emit(f,"\tnot\t");
+	emit_lword(f,&p->q1,t,"@%s++");
+	emit(f,",");
+	emit_lword(f,&p->z,t,"@%s++");
+	emit(f,"\n");
+	emit(f,"\tnot\t");
+	emit_hword(f,&p->q1,t,"@%s++");
+	emit(f,",");
+	emit_hword(f,&p->z,t,"@%s++");
+	emit(f,"\n");
+	cleanup_lword(f,&p->q1);
+	cleanup_lword(f,&p->z);
+	cc=0;
+      }else{
+	emit(f,"\tnot\t");
+	emit_obj(f,&p->q1,t);
+	emit(f,",");
+	emit_obj(f,&p->z,t);
+	emit(f,"\n");
+	cc=&p->z;cc_t=t;
+      }
+      continue;
+    }
+    if(c==SETRETURN){
+      if(p->z.reg){
+	if(reg_pair(p->z.reg,&rp))
+	  load_op(f,&p->q1,t,t1);
+	else
+	  load_op(f,&p->q1,t,p->z.reg);
+	move(f,&p->q1,0,0,p->z.reg,t);
+	BSET(regs_modified,p->z.reg);
+      }
+      cc=0; /* probably not needed */
+      continue;
+    }
+    if(c==GETRETURN){
+      if(p->q1.reg){
+	if((!isreg(z)||p->z.reg!=p->q1.reg)&&!ISLWORD(t)){ cc=&p->z;cc_t=t;}
+	load_op(f,&p->z,t,t2);
+	move(f,0,p->q1.reg,&p->z,0,t);
+      }
+      continue;
+    }
+    if(c==CALL){
+      int reg,jmp=0;long cstack=0;
+      cc=0;
+      if((p->q1.flags&(VAR|DREFOBJ))==VAR&&!strcmp("__va_start",p->q1.v->identifier)){
+	long va_off=loff-stackoffset+pushedsize+zm2l(va_offset(v))+1;
+	emit(f,"\tmove\t%s,%s\n",regnames[sp],regnames[r8]);
+	if(va_off)
+	  emit(f,"\tadd\t%ld,%s\n",va_off,regnames[r8]);
+	BSET(regs_modified,r8);
+	if(LARGE||HUGE){
+	  emit(f,"\tmove\t0,%s\n",regnames[r9]);
+	  BSET(regs_modified,r9);
+	}
+	continue;
+      }
+      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)){
+	    if(p->call_list[i].v->fi->stack1>cstack) cstack=p->call_list[i].v->fi->stack1;
+          }else{
+            err_ic=p;if(f) error(317,p->call_list[i].v->identifier);
+            stack_valid=0;
+          }
+        }
+      }
+      if(!calc_regs(p,f!=0)&&v->fi) v->fi->flags&=~ALL_REGS;
+      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);
+	callee_push(cstack);
+      }else{
+	if(stackoffset==0&&!have_frame&&!(v->tattr&INTERRUPT)){
+	  struct IC *p2;
+	  jmp=1;
+	  for(p2=p->next;p2;p2=p2->next){
+	    if(p2->code!=FREEREG&&p2->code!=ALLOCREG&&p2->code!=LABEL&&p2->code!=NOP&&
+	       (p2->code!=GETRETURN||(p2->z.flags&(REG|DREFOBJ))!=REG||p2->q1.reg!=p2->z.reg)&&
+	       (p2->code!=SETRETURN||(p2->q1.flags&(REG|DREFOBJ))!=REG||p2->q1.reg!=p2->z.reg)){
+	      jmp=0;break;
+	    }
+	  }
+	}
+	if(p->q1.flags&DREFOBJ){
+	  int clabel=++label;
+	  if(ISLWORD(p->q1.dtyp)){
+	    ierror(0);
+	  }
+	  p->q1.flags&=~DREFOBJ;
+	  load_op(f,&p->q1,t,t1);
+	  if(!ISLWORD(p->q1.dtyp)){
+	    emit(f,"\t%s\t",jmp?jump:"asub");
+	    emit_obj(f,&p->q1,p->q1.dtyp);
+	    emit(f,",1\n");
+	    push(1);
+	    callee_push(cstack);
+	    pop(1);
+	  }else{
+	    ierror(0);
+	  }
+	}else{
+	  if(jmp){
+	    emit(f,"\t%s\t",jump);
+	    callee_push(cstack);
+	  }else{
+	    emit(f,"\t%s\t",call);
+	    if(TINY)
+	      push(1);
+	    else
+	      push(2);
+	    callee_push(cstack);
+	    if(TINY)
+	      pop(1);
+	    else
+	      pop(2);
+	  }
+	  emit_obj(f,&p->q1,t);
+	  emit(f,",1\n");
+	}
+      }
+      if(jmp&&!need_return) ret="";
+      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{
+	  emit(f,"\tadd\t%ld,%s\n",zm2l(p->q2.val.vmax),regnames[sp]);
+	  pop(zm2l(p->q2.val.vmax));
+	  notpopped-=zm2l(p->q2.val.vmax);cc=0;
+	}
+      }
+      continue;
+    }
+    if(c==ASSIGN||c==PUSH){
+      if(c==PUSH) dontpop+=zm2l(p->q2.val.vmax);
+
+      if(c==ASSIGN||c==PUSH){
+	long sz=zm2l(p->q2.val.vmax);
+	int qreg,zreg,creg,i;
+	if(sz==1){
+	  load_op(f,&p->q1,t,t1);
+	  if(c==ASSIGN){
+	    load_op(f,&p->z,t,t2);
+	    move(f,&p->q1,0,&p->z,0,t);
+	    cc=&p->z;cc_t=t;
+	  }else{
+	    emit(f,"\tmove\t");
+	    emit_obj(f,&p->q1,t);
+	    emit(f,",@--%s\n",regnames[sp]);
+	    push(zm2l(p->z.val.vmax));	
+	    cc=&p->q1;cc_t=t;
+	  }    
+	  continue;
+	}else if(ISLWORD(t)&&(isreg(q1)||isreg(z)||(p->q1.flags&(KONST|DREFOBJ))==KONST)){
+	  if(c==ASSIGN){
+	    move(f,&p->q1,0,&p->z,0,t);
+	  }else{
+	    load_op(f,&p->q1,t,t1);
+	    
+	    if((p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ))
+	      emit(f,"\tadd\t2,%s\n",regnames[p->q1.reg]);
+	    
+	    emit(f,"\tmove\t");
+	    emit_hword(f,&p->q1,t,"@--%s");
+	    emit(f,",@--%s\n",regnames[sp]);
+	    emit(f,"\tmove\t");
+	    emit_lword(f,&p->q1,t,"@--%s");
+	    emit(f,",@--%s\n",regnames[sp]);
+	    push(2);
+	  }	  
+	  cc=0;
+	  continue;
+	}else{
+	  static char cpstr[64];
+	  cc=0;
+	  load_op(f,&p->q1,t,t1);
+	  if((p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&scratchreg(p->q1.reg,p)){
+	    qreg=p->q1.reg;
+	  }else{
+	    if(!(p->q1.flags&REG))
+	      ierror(0);
+	    qreg=t1;
+	    move(f,0,p->q1.reg,0,qreg,INT);
+	  }
+	  if(c==ASSIGN){
+	    load_op(f,&p->z,t,t2);
+	    if((p->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&scratchreg(p->z.reg,p)){
+	      zreg=p->z.reg;
+	    }else{
+	      if(!(p->z.flags&REG))
+		ierror(0);
+	      if(qreg==t1) zreg=t2; else zreg=t1;
+	      move(f,0,p->z.reg,0,zreg,INT);
+	    }
+	    sprintf(cpstr,"\tmove\t@%s++,@%s++\n",regnames[qreg],regnames[zreg]);
+	  }else{
+	    zreg=sp;
+	    emit(f,"\tadd\t%ld,%s\n",sz,regnames[qreg]);
+	    sprintf(cpstr,"\tmove\t@--%s,@--%s\n",regnames[qreg],regnames[zreg]);
+	    push(zm2l(p->q2.val.vmax));
+	  }
+	  if(sz<=9){
+	    for(i=0;i<sz;i++)
+	      emit(f,cpstr);
+	  }else{
+	    int cntpushed=0;
+	    if(zreg!=t2)
+	      creg=t2;
+	    else{
+	      creg=get_reg(f,p);
+	      if(c==PUSH) ierror(0);
+	      creg=r8;
+	      emit(f,"\tmove\t%s,@--%s\n",regnames[creg],regnames[sp]);
+	      cntpushed=1;
+	    }
+	    emit(f,"\tmove\t%ld,%s\n",sz/4,regnames[creg]);
+	    emit(f,"%s%d:\n",labprefix,++label);
+	    emit(f,cpstr);
+	    emit(f,cpstr);
+	    emit(f,cpstr);
+	    emit(f,cpstr);
+	    emit(f,"\tsub\t1,%s\n",regnames[creg]);
+	    emit(f,"\trbra\t%s%d,!z\n",labprefix,label);
+	    for(i=0;i<sz%4;i++)
+	      emit(f,cpstr);
+	    if(cntpushed)
+	      emit(f,"\tmove\t@%s++,%s\n",regnames[sp],regnames[creg]);
+	  }
+	  continue;
+	}
+
+      }
+      ierror(0);
+    }
+    if(c==ADDRESS){
+      reg=0;
+      if(0/*reg_pair(reg,&rp)*/){
+	ierror(0);
+	emit(f,"\tmov\t%s,%s\n",regnames[rp.r1],regnames[sp]);
+	emit(f,"\tmov\t%s,#0\n",regnames[rp.r2]);
+	if(voff(&p->q1))
+	  emit(f,"\tadd\t%s,#%ld\n",regnames[rp.r1],voff(&p->q1)&0xffff);
+      }else{
+	if(isreg(z))
+	  reg=p->z.reg;
+	else{
+	  load_op(f,&p->z,t,t2);
+	}
+	if(voff(&p->q1)){
+	  if(!reg) reg=t1;
+	  emit(f,"\tmove\t%s,%s\n",regnames[sp],regnames[reg]);
+	  emit(f,"\tadd\t%ld,%s\n",voff(&p->q1),regnames[reg]);
+	}else
+	  reg=sp;
+	move(f,0,reg,&p->z,0,ztyp(p));
+      }
+      cc=&p->z;cc_t=ztyp(p);
+      continue;
+    }
+
+    if((c>=LSHIFT&&c<=MOD)||(c>=OR&&c<=AND)||c==COMPARE||c==ADDI2P||c==SUBIFP){
+      char *s;
+
+      if(c==MULT||c==DIV||c==MOD){
+	int code;
+	load_op(f,&p->q1,t,t1);
+	emit(f,"\tmove\t%ld,%s\n",(long)0xff1b,regnames[t2]);
+	emit(f,"\tmove\t");
+	emit_obj(f,&p->q1,t);
+	emit(f,",@%s++\n",regnames[t2]);
+	load_op(f,&p->q2,t,t1);
+	emit(f,"\tmove\t");
+	emit_obj(f,&p->q2,t);
+	emit(f,",@%s++\n",regnames[t2]);
+	emit(f,"\tmove\t%ld,%s\n",(long)0xff1f,regnames[t1]);
+	if(c==MULT) code=0; else code=2;
+	if(!(t&UNSIGNED)) code++;
+	emit(f,"\tmove\t%d,@%s\n",code,regnames[t1]);
+	if(c==MOD)
+	  emit(f,"\tmove\t%ld,%s\n",(long)0xff1e,regnames[t2]);
+	load_op(f,&p->z,t,t1);
+	emit(f,"\tmove\t@%s,",regnames[t2]);
+	emit_obj(f,&p->z,t);
+	emit(f,"\n");
+	cc=&p->z;cc_t=t;
+	continue;
+      }
+
+      if(c==LSHIFT&&isconst(q2)&&isreg(q1)){
+	eval_const(&p->q2.val,INT);
+	if(zmeqto(vmax,l2zm(1L))){
+	  p->code=c=ADD;
+	  p->q2=p->q1;
+	}
+      }
+
+      if(compare_objects(&p->q2,&p->z)){
+	if(!compare_objects(&p->q1,&p->z)){
+	  if(c==LSHIFT||c==RSHIFT){
+	    reg=get_reg(f,p);
+	    if(reg){
+	      move(f,&p->q2,0,0,reg,q2typ(p));
+	      p->q2.flags=REG;
+	      p->q2.reg=reg;
+	    }else{
+	      emit(f,"\tmove\t");
+	      emit_obj(f,&p->q2,q2typ(p));
+	      emit(f,",@--%s\n",regnames[sp]);
+	      p->q2.flags=REG|DREFOBJ;
+	      p->q2.reg=sp;
+	      p->q2.am=mymalloc(sizeof(*p->q2.am));
+	      p->q2.am->flags=POST_INC;
+	      p->q2.am->base=sp;
+	    }
+	  }else if(c==SUB||c==SUBPFP||c==SUBIFP){
+	    /* TODO: check pointer sizes subifp/subpfp */
+	    if(ISLWORD(t)){
+	      if(isreg(z)){
+		if(!reg_pair(p->z.reg,&rp)) ierror(0);
+		emit(f,"\tnot\t%s,%s\n",regnames[rp.r1],regnames[rp.r1]);
+		emit(f,"\tnot\t%s,%s\n",regnames[rp.r2],regnames[rp.r2]);
+		emit(f,"\tadd\t1,%s\n",regnames[rp.r1]);
+		emit(f,"\taddc\t0,%s\n",regnames[rp.r2]);
+		p->q2=p->q1;
+		p->q1=p->z;
+		p->code=c=ADD;
+	      }else
+		ierror(0);
+	    }else{
+	      load_op(f,&p->z,t,t1);
+	      emit(f,"\tnot\t");
+	      emit_obj(f,&p->z,t);
+	      emit(f,",");
+	      emit_obj(f,&p->z,t);
+	      emit(f,"\n");
+	      emit(f,"\tadd\t1,");
+	      emit_obj(f,&p->z,t);
+	      emit(f,"\n");
+	      load_op(f,&p->q1,t,t2);
+	      emit(f,"\tadd\t");
+	      emit_obj(f,&p->q1,t);
+	      emit(f,",");
+	      emit_obj(f,&p->z,t);
+	      emit(f,"\n");
+	      cc=&p->z;cc_t=t;
+	      continue;
+	    }
+	  }else{
+	    struct obj m;
+	    m=p->q1;p->q1=p->q2;p->q2=m;
+	  }
+	}
+      }
+
+      if(c>=OR&&c<=AND){
+	s=logicals[c-OR];
+      }else{
+	if(c==ADDI2P)
+	  s=arithmetics[ADD-LSHIFT];
+	else if(c==SUBIFP)
+	  s=arithmetics[SUB-LSHIFT];
+	else
+	  s=arithmetics[c-LSHIFT];
+      }
+
+      if(c==COMPARE){
+	lastcomp=t;
+	load_op(f,&p->q1,t,t1);
+	load_op(f,&p->q2,t,t2);
+
+	if(ISLWORD(t)){
+	  if((p->q1.flags&DREFOBJ)&&p->q1.reg!=t1){
+	    emit(f,"\tmove\t%s,%s\n",regnames[p->q1.reg],regnames[t1]);
+	    p->q1.reg=t1;
+	  }
+	  if((p->q2.flags&DREFOBJ)&&p->q2.reg!=t2){
+	    emit(f,"\tmove\t%s,%s\n",regnames[p->q2.reg],regnames[t2]);
+	    p->q2.reg=t2;
+	  }
+	  p2=p->next;
+	  while(p2&&p2->code==FREEREG) p2=p2->next;
+	  if(!p2||p2->code<BEQ||p2->code>BGT) ierror(0);
+	  c=p2->code;
+	  if(c==BEQ||c==BNE){
+	    emit(f,"\tcmp\t",s);
+	    emit_lword(f,&p->q1,t,"@%s++");
+	    emit(f,",");
+	    emit_lword(f,&p->q2,t,"@%s++");
+	    emit(f,"\n");
+	    if(c==BEQ)
+	      emit(f,"\trbra\t%s%d,!z\n",labprefix,elab=++label);
+	    else 
+	      emit(f,"\trbra\t%s%d,!z\n",labprefix,p2->typf);
+	    emit(f,"\tcmp\t",s);
+	    emit_hword(f,&p->q1,t,"@%s++");
+	    emit(f,",");
+	    emit_hword(f,&p->q2,t,"@%s++");
+	    emit(f,"\n");
+	    emit(f,"\trbra\t%s%d,%s\n",labprefix,p2->typf,ccs[c-BEQ]);
+	  }else{
+	    elab=++label;
+	    if(p->q1.flags&DREFOBJ) emit(f,"\tadd\t1,%s\n",regnames[p->q1.reg]);
+	    if(p->q2.flags&DREFOBJ) emit(f,"\tadd\t1,%s\n",regnames[p->q2.reg]);
+	    emit(f,"\tcmp\t",s);
+	    emit_hword(f,&p->q2,t,"@%s");
+	    emit(f,",");
+	    emit_hword(f,&p->q1,t,"@%s");
+	    emit(f,"\n");
+	    emit(f,"\trbra\t%s%d,%s\n",labprefix,c==BLT?p2->typf:elab,(t&UNSIGNED)?ccu[BLT-BEQ]:ccs[BLT-BEQ]);
+	    /* unfortunately flags are overwritten... */
+	    emit(f,"\tcmp\t",s);
+	    emit_hword(f,&p->q2,t,"@%s");
+	    emit(f,",");
+	    emit_hword(f,&p->q1,t,"@%s");
+	    emit(f,"\n");
+	    emit(f,"\trbra\t%s%d,!z\n",labprefix,c==BLT?elab:p2->typf);
+	    if(p->q1.flags&DREFOBJ) emit(f,"\tsub\t1,%s\n",regnames[p->q1.reg]);
+	    if(p->q2.flags&DREFOBJ) emit(f,"\tsub\t1,%s\n",regnames[p->q2.reg]);
+	    emit(f,"\tcmp\t",s);
+	    emit_lword(f,&p->q2,t,"@%s");
+	    emit(f,",");
+	    emit_lword(f,&p->q1,t,"@%s");
+	    emit(f,"\n");
+	    emit(f,"\trbra\t%s%d,%s\n",labprefix,p2->typf,ccu[c-BEQ]);
+	  }
+	  cc=0;
+#if 0
+	  /* last branch done in branch IC */
+	  lastcomp=UNSIGNED|INT;
+#else
+	  if(c!=BNE)
+	    emit(f,"%s%d:\n",labprefix,elab);
+	  p2->code=NOP;
+#endif
+	  continue;
+	}else{
+	  emit(f,"\tcmp\t",s);
+	  emit_obj(f,&p->q2,t);
+	  emit(f,",");
+	  emit_obj(f,&p->q1,t);
+	  emit(f,"\n");
+	}
+	cc=0;
+	continue;
+      }
+
+
+      if(!compare_objects(&p->q1,&p->z)){
+	load_op(f,&p->q1,t,t1);
+	load_op(f,&p->z,t,t2);
+	if((p->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&isreg(z)&&p->q2.reg==p->z.reg){
+	  move(f,0,p->q2.reg,0,t2,NPOINTER);
+	  p->q2.reg=t2;
+	}
+	move(f,&p->q1,0,&p->z,0,t);
+	/* cleanup postinc if necessary (not done by cleanup_lword */
+	if(p->z.reg==t2&&(p->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&ISLWORD(t))
+	  emit(f,"\tsub\t2,%s\n",regnames[t2]);
+      }else
+	load_op(f,&p->z,t,t2);
+      load_op(f,&p->q2,t,t1);
+
+      if(ISLWORD(t)){
+
+	emit(f,"\t%s\t",s);
+	emit_lword(f,&p->q2,t,"@%s++");
+	emit(f,",");
+	emit_lword(f,&p->z,t,"@%s++");
+	emit(f,"\n");
+	emit(f,"\t%s%s\t",s,!strcmp(s,"add")||!strcmp(s,"sub")?"c":"");
+	emit_hword(f,&p->q2,t,"@%s++");
+	emit(f,",");
+	emit_hword(f,&p->z,t,"@%s++");
+	emit(f,"\n");
+	cleanup_lword(f,&p->q2);
+	cleanup_lword(f,&p->z);
+	cc=0;
+
+      }else{
+
+	/* TODO: try to eliminate */
+	if(c==LSHIFT){
+	  emit(f,"\tcmp\t%s,%s\n",regnames[sp],regnames[sp]);
+	}else if(c==RSHIFT){
+	  if(t&UNSIGNED){
+	    emit(f,"\tor\t%s,%s\n",regnames[sp],regnames[sp]);
+	  }else{
+	    emit(f,"\tshl\t1,");
+	    emit_obj(f,&p->z,t);
+	    emit(f,"\n");
+	    emit(f,"\tshr\t1,");
+	    emit_obj(f,&p->z,t);
+	    emit(f,"\n");
+	  }
+	}
+	emit(f,"\t%s\t",s);
+	emit_obj(f,&p->q2,t);
+	emit(f,",");
+	emit_obj(f,&p->z,t);
+	emit(f,"\n");
+	cc=&p->z;cc_t=t;
+
+      }
+      if(ISLWORD(t)) cc=0;
+
+      continue;
+    }
+    ierror(0);
+  }
+  if(notpopped){
+    emit(f,"\tadd\t%ld,%s\n",notpopped,regnames[sp]);
+    pop(notpopped);notpopped=0;
+  }
+  function_bottom(f,v,loff);
+}
+
+int shortcut(int c,int t)
+{
+  if(c==COMPARE||c==AND||c==OR||c==XOR) return 1;
+  if(c==ADD||c==SUB) 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){
+      new_section(f,NDATA);
+      emit(f,"%s%d:\n\t%s\t",labprefix,p->label,dct[SHORT]);
+      ip=(unsigned char *)&p->val.vdouble;
+      emit(f,"0x%02x%02x,0x%02x%02x",ip[1],ip[0],ip[3],ip[2]);
+      if((p->typ&NQ)==DOUBLE||(p->typ&NQ)==LDOUBLE){
+	emit(f,",0x%02x%02x,0x%02x%02x",ip[5],ip[4],ip[7],ip[6]);
+      }
+      emit(f,"\n");
+    }
+    firstfpc=p->next;
+    free(p);
+  }
+}
+
+int reg_parm(struct reg_handle *p,struct Typ *t,int mode,struct Typ *fkt)
+{
+  int f=t->flags&NQ;
+  if(!ISSCALAR(f)) return 0;
+  if(p->gpr>2||mode) return 0;
+  if(f==LLONG||f==DOUBLE||f==LDOUBLE)
+    return 0;
+  else if(f==LONG||f==FLOAT||f==FPOINTER||f==HPOINTER){
+    if(p->gpr==0) {p->gpr=2;return r8r9;}
+    return 0;
+  }else
+    return r8+p->gpr++;
+}
+
+void insert_const(union atyps *p,int t)
+/*  Traegt Konstante in entprechendes Feld ein.       */
+{
+  if(!p) ierror(0);
+/*  *p = (union atyps) 0 ; /* rfi: clear unused bits */
+  t&=NU;
+  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==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==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){fprintf(f,"B");vmax=zc2zm(p->vchar);fprintf(f,"%d",!zmeqto(vmax,l2zm(0L)));}
+  if(t==(UNSIGNED|BIT)){fprintf(f,"UB");vumax=zuc2zum(p->vuchar);fprintf(f,"%d",!zumeqto(vmax,ul2zum(0UL)));}
+  if(t==CHAR){fprintf(f,"C");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)
+/*  Gibt atyps aus.                                     */
+{
+  t&=NU;
+  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(vumax,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)
+{
+}
+
+void cleanup_db(FILE *f)
+{
+}
+
+char *use_libcall(int c,int t,int t2)
+{
+  static char fname[16];
+  char *ret=0,*tt;
+
+  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])*16);
+      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])*16,(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])*16);
+        ret=fname;
+      }
+      if((t&NQ)==LLONG||(t2&NQ)==LLONG){
+	sprintf(fname,"__%cint%ldto%cint%ld",(t2&UNSIGNED)?'u':'s',zm2l(sizetab[t2&NQ])*16,(t&UNSIGNED)?'u':'s',zm2l(sizetab[t&NQ])*16);
+        ret=fname;
+      }
+    }
+    if(ISINT(t)&&ISLWORD(t)){
+      if(c==MINUS||c==KOMPLEMENT||c==ADD||c==SUB||c==OR||c==AND||c==XOR)
+	return 0;
+    }
+    if((t&NQ)==LONG||(t&NQ)==LLONG||ISFLOAT(t)||(SOFTMUL&&(c==MULT||c==DIV||c==MOD))){
+      if((c>=LSHIFT&&c<=MOD)||(c>=OR&&c<=AND)||c==KOMPLEMENT||c==MINUS){
+	if(c!=DIV&&c!=MOD&&c!=RSHIFT&&c!=COMPARE)
+	  t&=~UNSIGNED;
+	sprintf(fname,"__%s%s%s%ld",ename[c],(t&UNSIGNED)?"u":"",ISFLOAT(t)?"flt":"int",zm2l(sizetab[t&NQ])*16);
+	ret=fname;
+      }
+    }
+  }
+
+
+  return ret;
+}
diff --git a/machines/qnice/machine.dt b/machines/qnice/machine.dt
new file mode 100755
index 0000000..fa60647
--- /dev/null
+++ b/machines/qnice/machine.dt
@@ -0,0 +1,16 @@
+S16BSLE S16BSBE
+S16BULE S16BUBE
+S16BSLE S16BSBE
+S16BULE S16BUBE
+S16BSLE S16BSBE
+S16BULE S16BUBE
+S32BSLE S32BSBE
+S32BULE S32BUBE
+S64BSLE S64BSBE
+S64BULE S64BUBE
+S32BIEEELE
+S64BIEEELE
+S64BIEEELE
+S16BULE S16BUBE
+
+
diff --git a/machines/qnice/machine.h b/machines/qnice/machine.h
new file mode 100755
index 0000000..b9795a3
--- /dev/null
+++ b/machines/qnice/machine.h
@@ -0,0 +1,185 @@
+/*  Example of a code-generator for qnice cpu.*/
+
+#include "dt.h"
+
+/* We have extended types! What we have to do to support them:      */
+/* - #define HAVE_EXT_TYPES
+   - #undef all standard types
+   - #define all standard types plus new types
+   - write eval_const and insert_const
+   - write typedefs for zmax and zumax
+   - write typname[]
+   - write conv_typ()
+   - optionally #define ISPOINTER, ISARITH, ISINT etc.
+   - optionally #define HAVE_TGT_PRINTVAL and write printval
+   - optionally #define POINTER_TYPE
+   - optionally #define HAVE_TGT_FALIGN and write falign
+   - optionally #define HAVE_TGT_SZOF and write szof
+   - optionally add functions for attribute-handling
+*/
+#define HAVE_EXT_TYPES 1
+
+#define HAVE_TGT_PRINTVAL
+
+#undef CHAR
+#undef SHORT
+#undef INT
+#undef LONG
+#undef LLONG
+#undef FLOAT
+#undef DOUBLE
+#undef LDOUBLE
+#undef VOID
+#undef POINTER
+#undef ARRAY
+#undef STRUCT
+#undef UNION
+#undef ENUM
+#undef FUNKT
+#undef BOOL
+#undef MAXINT
+#undef MAX_TYPE
+
+#define BIT 1
+#define CHAR 2
+#define SHORT 3
+#define INT 4
+#define LONG 5
+#define LLONG 6
+#define FLOAT 7
+#define DOUBLE 8
+#define LDOUBLE 9
+#define VOID 10
+#define NPOINTER 11
+#define FPOINTER 12
+#define HPOINTER 13
+#define ARRAY 14
+#define STRUCT 15
+#define UNION 16
+#define ENUM 17
+#define FUNKT 18
+#define BOOL 19
+
+#define MAXINT 20
+
+#define MAX_TYPE MAXINT
+
+#define POINTER_TYPE(x) pointer_type(x)
+extern int pointer_type();
+#define ISPOINTER(x) ((x&NQ)>=NPOINTER&&(x&NQ)<=HPOINTER)
+#define ISSCALAR(x) ((x&NQ)>=BIT&&(x&NQ)<=HPOINTER)
+#define ISINT(x) ((x&NQ)>=BIT&&(x&NQ)<=LLONG)
+#define PTRDIFF_T(x) ((x)==HPOINTER?LONG:INT)
+
+typedef zllong zmax;
+typedef zullong zumax;
+
+union atyps{
+  zchar vchar;
+  zuchar vuchar;
+  zshort vshort;
+  zushort vushort;
+  zint vint;
+  zuint vuint;
+  zlong vlong;
+  zulong vulong;
+  zllong vllong;
+  zullong vullong;
+  zmax vmax;
+  zumax vumax;
+  zfloat vfloat;
+  zdouble vdouble;
+  zldouble vldouble;
+};
+
+/*  This struct can be used to implement machine-specific           */
+/*  addressing-modes.                                               */
+struct AddressingMode{
+    int flags;
+    int base;
+};
+
+/* This type will be added to every IC. Can be used by the cg.      */
+#define HAVE_EXT_IC 0
+struct ext_ic {
+  int flags;
+  int r;
+  long offset;
+};
+
+/*  The number of registers of the target machine.                  */
+#define MAXR 22
+
+/*  Number of commandline-options the code-generator accepts.       */
+#define MAXGF 20
+
+/*  If this is set to zero vbcc will not generate ICs where the     */
+/*  target operand is the same as the 2nd source operand.           */
+/*  This can sometimes simplify the code-generator, but usually     */
+/*  the code is better if the code-generator allows it.             */
+#define USEQ2ASZ 1
+
+/*  This specifies the smallest integer type that can be added to a */
+/*  pointer.                                                        */
+#define MINADDI2P CHAR
+
+/*  If the bytes of an integer are ordered most significant byte    */
+/*  byte first and then decreasing set BIGENDIAN to 1.              */
+#define BIGENDIAN 0
+
+/*  If the bytes of an integer are ordered lest significant byte    */
+/*  byte first and then increasing set LITTLEENDIAN to 1.           */
+#define LITTLEENDIAN 1
+
+/*  Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive.    */
+
+/*  If switch-statements should be generated as a sequence of       */
+/*  SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1.      */
+/*  This can yield better code on some machines.                    */
+#define SWITCHSUBS 0
+
+/*  In optimizing compilation certain library memcpy/strcpy-calls   */
+/*  with length known at compile-time will be inlined using an      */
+/*  ASSIGN-IC if the size is less or equal to INLINEMEMCPY.         */
+/*  The type used for the ASSIGN-IC will be UNSIGNED|CHAR.          */
+#define INLINEMEMCPY 1024
+
+#define HAVE_REGPARMS 1
+
+struct reg_handle {
+  int gpr;
+};
+
+/*  We use unsigned int as size_t rather than unsigned long which   */
+/*  is the default setting.                                         */
+#define HAVE_INT_SIZET 1
+
+/*  We have register pairs.                                         */
+#define HAVE_REGPAIRS 1
+
+/*  We keep track of all registers modified by a function.          */
+#define HAVE_REGS_MODIFIED 1
+
+#define HAVE_TARGET_RALLOC 1
+#define cost_load_reg(r,v) 4
+#define cost_save_reg(r,v) 4
+#define cost_move_reg(i,j) 2
+#define cost_pushpop_reg(r) 2
+
+/* size of buffer for asm-output */
+#define EMIT_BUF_LEN 1024 /* should be enough */
+/* number of asm-output lines buffered */
+#define EMIT_BUF_DEPTH 4
+
+/*  We have asm_peephole to optimize assembly-output */
+#define HAVE_TARGET_PEEPHOLE 1
+
+/*  We have some target-specific variable attributes.               */
+#define HAVE_TARGET_ATTRIBUTES 1
+
+/* We use builtin libcalls for some operations */
+#define HAVE_LIBCALLS 1
+
+#define HAVE_WANTBNE 1
+
+#define HAVE_POF2OPT 1
diff --git a/machines/qnice/sysdef.h b/machines/qnice/sysdef.h
new file mode 100644
index 0000000..bdc733e
--- /dev/null
+++ b/machines/qnice/sysdef.h
@@ -0,0 +1,461 @@
+//;
+//;  sysdef.asm: This file contains definitions to simplify assembler programming
+//;              and for accessing the various hardware registers via MMIO
+//;
+//
+//***************************************************************************************
+//*  Assembler macros which make life much easier:
+//***************************************************************************************
+//
+
+
+//
+//  Some register short names:
+//
+
+//
+//***************************************************************************************
+//*  IO-page addresses: Default: 8 registers per block
+//***************************************************************************************
+//
+#define IO_AREA_START  	0xFF00
+//
+//---------------------------------------------------------------------------------------
+//  Block FF00: FUNDAMENTAL IO
+//---------------------------------------------------------------------------------------
+//
+//  Switch-register:
+//
+#define IO_SWITCH_REG  	0xFF00 // 16 binary keys
+//
+//  Registers for TIL-display:
+//
+#define IO_TIL_DISPLAY 	0xFF01 // Address of TIL-display
+#define IO_TIL_MASK    	0xFF02 // Mask register of TIL display
+//
+//  USB-keyboard-registers:
+//
+#define IO_KBD_STATE   	0xFF04 // Status register of USB keyboard
+//    Bit  0 (read only):      New ASCII character avaiable for reading
+//                             (bits 7 downto 0 of Read register)
+//    Bit  1 (read only):      New special key available for reading
+//                             (bits 15 downto 8 of Read register)
+//    Bits 2..4 (read/write):  Locales: 000 = US English keyboard layout,
+//                             001 = German layout, others: reserved for more locales
+//    Bits 5..7 (read only):   Modifiers: 5 = shift, 6 = alt, 7 = ctrl
+//                             Only valid, when bits 0 and/or 1 are '1'
+//
+#define IO_KBD_DATA    	0xFF05 // Data register of USB keyboard
+//    Contains the ASCII character in bits 7 downto 0  or the special key code
+//    in 15 downto 8. The "or" is meant exclusive, i.e. it cannot happen that
+//    one transmission contains an ASCII character PLUS a special character.
+//
+//---------------------------------------------------------------------------------------
+//  Block FF08: SYSTEM COUNTERS
+//---------------------------------------------------------------------------------------
+//
+//  CYCLE-COUNT-registers       
+//
+#define IO_CYC_LO      	0xFF08     // low word of 48-bit counter
+#define IO_CYC_MID     	0xFF09     // middle word of 48-bit counter
+#define IO_CYC_HI      	0xFF0A     // high word of 48-bit counter
+#define IO_CYC_STATE   	0xFF0B     // status register
+//    Bit  0 (write only):     Reset counter to zero and start counting, i.e.
+//                             bit 1 is automatically set to 1 when resetting
+//    Bit  1 (read/write):     Start/stop counter
+//
+//  INSTRUCTION-COUNT-registers       
+//
+#define IO_INS_LO      	0xFF0C     // low word of 48-bit counter
+#define IO_INS_MID     	0xFF0D     // middle word of 48-bit counter
+#define IO_INS_HI      	0xFF0E     // high word of 48-bit counter
+#define IO_INS_STATE   	0xFF0F     // status register
+//    Bit  0 (write only):     Reset counter to zero and start counting, i.e.
+//                             bit 1 is automatically set to 1 when resetting
+//    Bit  1 (read/write):     Start/stop counter
+//
+//---------------------------------------------------------------------------------------
+//  Block FF10: UART
+//---------------------------------------------------------------------------------------
+//
+//  QNICE-FPGA supports: IO_UART_SRA, IO_UART_RHRA and IO_UART_THRA 
+//  The other registers are mentioned for completeness to map real hardware (16550)
+//
+#define IO_UART_BASE_ADDRESS   	0xFF10
+#define IO_UART_MR1A   	0xFF10 // n/a
+#define IO_UART_MR1B   	0xFF10 // n/a
+#define IO_UART_SRA    	0xFF11 // Status register (relative to base address)
+#define IO_UART_RHRA   	0xFF12 // Receiving register (relative to base address)
+#define IO_UART_THRA   	0xFF13 // Transmitting register (relative to base address)
+//
+//---------------------------------------------------------------------------------------
+//  Block FF18: EAE
+//---------------------------------------------------------------------------------------
+//
+//  EAE (Extended Arithmetic Element) registers:
+//
+#define IO_EAE_OPERAND_0   	0xFF18
+#define IO_EAE_OPERAND_1   	0xFF19
+#define IO_EAE_RESULT_LO   	0xFF1A
+#define IO_EAE_RESULT_HI   	0xFF1B
+#define IO_EAE_CSR         	0xFF1C // Command and Status Register
+//
+//  EAE-Opcodes (CSR):   0x0000  MULU  32-bit result in LO HI
+//                       0x0001  MULS  32-bit result in LO HI
+//                       0x0002  DIVU  result in LO, modulo in HI
+//                       0x0003  DIVS  result in LO, modulo in HI
+//  Bit 15 of CSR is the busy bit. If it is set, the EAE is still busy crunching numbers.
+//
+//---------------------------------------------------------------------------------------
+//  Block FF20: SD CARD
+//---------------------------------------------------------------------------------------
+//
+//  SD CARD INTERFACE registers
+//
+#define IO_SD_BASE_ADDRESS 	0xFF20
+#define IO_SD_ADDR_LO  	0xFF20 // low word of 32bit linear SD card block address
+#define IO_SD_ADDR_HI  	0xFF21 // high word of 32bit linear SD card block address
+#define IO_SD_DATA_POS 	0xFF22 // "Cursor" to navigate the 512-byte data buffer
+#define IO_SD_DATA     	0xFF23 // read/write 1 byte from/to the 512-byte data buffer
+#define IO_SD_ERROR    	0xFF24 // error code of last operation (read only)
+#define IO_SD_CSR      	0xFF25 // Command and Status Register (write to execute command)
+//
+//  SD-Opcodes (CSR):    0x0000  Reset SD card
+//                       0x0001  Read 512 bytes from the linear block address
+//                       0x0002  Write 512 bytes to the linear block address
+//  Bits 0 .. 2 are write-only (reading always returns 0)
+//  Bits 13 .. 12 return the card type: 00 = no card / unknown card
+//                                      01 = SD V1
+//                                      10 = SD V2
+//                                      11 = SDHC                       
+//  Bit 14 of the CSR is the error bit: 1, if the last operation failed. In such
+//                                      a case, the error code is in IO_SD_ERROR and
+//                                      you need to reset the controller to go on
+//  Bit 15 of the CSR is the busy bit: 1, if current operation is still running
+//
+//---------------------------------------------------------------------------------------
+//  Block FF28: TIMER 0 and 1
+//---------------------------------------------------------------------------------------
+//
+//  Interrupt timer: There are two timers capable of generating interrupts.
+//                   Each timer is controlled by three 16 bit registers:
+//
+//  IO_TIMER_x_PRE: The 100 kHz timer clock is divided by the value stored in
+//                  this device register. 100 (which corresponds to 0x0064 in
+//                  the prescaler register) yields a 1 millisecond pulse which
+//                  in turn is fed to the actual counter.
+//  IO_TIMER_x_CNT: When the number of output pulses from the prescaler circuit 
+//                  equals the number stored in this register, an interrupt will
+//                  be generated (if the interrupt address is 0x0000, the
+//                  interrupt will be suppressed).
+//  IO_TIMER_x_INT: This register contains the address of the desired interrupt 
+//                  service routine.
+//
+#define IO_TIMER_BASE_ADDRESS  	0xFF28
+#define IO_TIMER_0_PRE 	0xFF28
+#define IO_TIMER_0_CNT 	0xFF29
+#define IO_TIMER_0_INT 	0xFF2A
+#define IO_TIMER_1_PRE 	0xFF2B
+#define IO_TIMER_1_CNT 	0xFF2C
+#define IO_TIMER_1_INT 	0xFF2D
+//
+//---------------------------------------------------------------------------------------
+//  Block FF30: VGA (double block, 16 registers)
+//---------------------------------------------------------------------------------------
+//
+#define VGA_STATE          	0xFF30 // VGA status register
+    // Bits 11-10: Hardware scrolling / offset enable: Bit #10 enables the use
+    //             of the offset register #4 (display offset) and bit #11
+    //             enables the use of register #5 (read/write offset).
+    // Bit      9: Busy: VGA is currently busy, e.g. clearing the screen,
+    //             printing, etc. While busy, commands will be ignored, but
+    //             they can still be written into the registers, though
+    // Bit      8: Set bit to clear screen. Read bit to find out, if clear
+    //             screen is still active
+    // Bit      7: VGA enable (1 = on; 0: no VGA signal is generated)
+    // Bit      6: Hardware cursor enable
+    // Bit      5: Hardware cursor blink enable
+    // Bit      4: Hardware cursor mode: 1 - small
+    //                                   0 - large
+    // Bits   2-0: Output color for the whole screen, bits (2, 1, 0) = RGB
+#define VGA_CR_X           	0xFF31 // VGA cursor X position
+#define VGA_CR_Y           	0xFF32 // VGA cursor Y position
+#define VGA_CHAR           	0xFF33 // write: VGA character to be displayed
+                                // read: character "under" the cursor
+#define VGA_OFFS_DISPLAY   	0xFF34 // Offset in bytes that is used when displaying
+                                // the video RAM. Scrolling forward one line
+                                // means adding 0x50 to this register.
+                                // Only works, if bit #10 in VGA_STATE is set.
+#define VGA_OFFS_RW        	0xFF35 // Offset in bytes that is used, when you read
+                                // or write to the video RAM using VGA_CHAR.
+                                // Works independently from VGA_OFFS_DISPLAY.
+                                // Active, when bit #11 in VGA_STATE is set.
+#define VGA_HDMI_H_MIN     	0xFF36 // HDMI Data Enable: X: minimum valid column
+#define VGA_HDMI_H_MAX     	0xFF37 // HDMI Data Enable: X: maximum valid column
+#define VGA_HDMI_V_MAX     	0xFF38 // HDMI Data Enable: Y: maximum row (line)                                
+//
+//---------------------------------------------------------------------------------------
+//  Block FFF0: MEGA65 (double block, 16 registers)
+//---------------------------------------------------------------------------------------
+//
+//  HyperRAM
+//
+#define IO_M65HRAM_LO      	0xFFF0 // Low word of address  (15 downto 0)
+#define IO_M65HRAM_HI      	0xFFF1 // High word of address (26 downto 16)
+#define IO_M65HRAM_DATA8   	0xFFF2 // HyperRAM native 8-bit data in/out
+#define IO_M65HRAM_DATA16  	0xFFF3 // HyperRAM 16-bit data in/out
+
+//
+//***************************************************************************************
+//* Constant definitions
+//***************************************************************************************
+//
+
+// ========== VGA ==========
+
+#define VGA_MAX_X              	79                      // Max. X-coordinate in decimal!
+#define VGA_MAX_Y              	39                      // Max. Y-coordinate in decimal!
+#define VGA_MAX_CHARS          	3200                    // 80 * 40 chars
+#define VGA_CHARS_PER_LINE     	80  
+
+#define VGA_EN_HW_CURSOR       	0x0040                  // Show hardware cursor
+#define VGA_EN_HW_SCRL         	0x0C00                  // Hardware scrolling enable
+#define VGA_CLR_SCRN           	0x0100                  // Clear screen
+#define VGA_BUSY               	0x0200                  // VGA is currently performing a task
+
+#define VGA_COLOR_RED          	0x0004
+#define VGA_COLOR_GREEN        	0x0002
+#define VGA_COLOR_BLUE         	0x0001
+#define VGA_COLOR_WHITE        	0x0007
+
+// ========== CYCLE COUNTER ==========
+
+#define CYC_RESET              	0x0001                  // Reset cycle counter
+#define CYC_RUN                	0x0002                  // Start/stop counter
+
+// ========== CYCLE COUNTER ==========
+
+#define INS_RESET              	0x0001                  // Reset instruction counter
+#define INS_RUN                	0x0002                  // Start/stop counter
+
+// ========== EAE ==========
+
+#define EAE_MULU               	0x0000                  // Unsigned 16 bit multiplication
+#define EAE_MULS               	0x0001                  // Signed 16 bit multiplication
+#define EAE_DIVU               	0x0002                  // Unsigned 16 bit division with remainder
+#define EAE_DIVS               	0x0003                  // Signed 16 bit division with remainder
+#define EAE_BUSY               	0x8000                  // Busy flag (1 = operation still running)
+
+// ========== SD CARD ==========
+
+#define SD_CMD_RESET           	0x0000                  // Reset SD card
+#define SD_CMD_READ            	0x0001                  // Read 512 bytes from SD to internal buffer
+#define SD_CMD_WRITE           	0x0002                  // Write 512 bytes from int. buf. to SD
+#define SD_BIT_ERROR           	0x4000                  // Error flag: 1, if last operation failed
+#define SD_BIT_BUSY            	0x8000                  // Busy flag: 1, if current op. is still running
+#define SD_TIMEOUT_MID         	0x0479                  // equals ~75.000.000 cycles, i.e. 1.5sec @ 50 MHz
+
+#define SD_ERR_MASK            	0x00FF                  // AND mask for errors: HI byte = state machine info, so mask it for error checks 
+#define SD_ERR_R1_ERROR        	0x0001                  // SD Card R1 error (R1 bit 6-0)
+#define SD_ERR_CRC_OR_TIMEOUT  	0x0002                  // Read CRC error or Write Timeout error
+#define SD_ERR_RESPONSE_TOKEN  	0x0003                  // Data Response Token error (Token bit 3)
+#define SD_ERR_ERROR_TOKEN     	0x0004                  // Data Error Token error (Token bit 3-0)
+#define SD_ERR_WRITE_PROTECT   	0x0005                  // SD Card Write Protect switch
+#define SD_ERR_CARD_UNUSABLE   	0x0006                  // Unusable SD card
+#define SD_ERR_NO_CARD         	0x0007                  // No SD card (no response from CMD0)
+#define SD_ERR_READ_TIMEOUT    	0x0008                  // Timeout while trying to receive the read start token "FE"
+#define SD_ERR_TIMEOUT         	0xEEFF                  // General timeout
+
+#define SD_CT_SD_V1            	0x0001                  // Card type: SD Version 1
+#define SD_CT_SD_V2            	0x0002                  // Card type: SD Version 2
+#define SD_CT_SDHC             	0x0003                  // Card type: SDHC (or SDXC)
+
+// ========== FAT32 =============
+
+// FAT32 ERROR CODES
+
+#define FAT32_ERR_MBR          	0xEE10                  // no or illegal Master Boot Record (MBR) found
+#define FAT32_ERR_PARTITION_NO 	0xEE11                  // the partition number needs to be in the range 1 .. 4
+#define FAT32_ERR_PARTTBL      	0xEE12                  // no or illegal partition table entry found (e.g. no FAT32 partition)
+#define FAT32_ERR_NOTIMPL      	0xEE13                  // functionality is not implemented
+#define FAT32_ERR_SIZE         	0xEE14                  // partition size or volume size too large (see doc/constraints.txt)
+#define FAT32_ERR_NOFAT32      	0xEE15                  // illegal volume id (either not 512 bytes per sector, or not 2 FATs or wrong magic)
+#define FAT32_ERR_ILLEGAL_SIC  	0xEE16                  // trying to read/write a sector within a cluster that is out of range
+#define FAT32_ERR_ILLEGAL_CLUS 	0xEE17                  // trying to access an illegal cluster number
+#define FAT32_ERR_CORRUPT_DH   	0xEE18                  // corrupt directory handle (e.g. because current to-be-read offs > sector size)
+#define FAT32_ERR_DIRNOTFOUND  	0xEE19                  // directory not found (illegal path name passed to change directory command)
+#define FAT32_ERR_FILENOTFOUND 	0xEE20                  // file not found
+#define FAT23_ERR_SEEKTOOLARGE 	0xEE21                  // seek position > file size
+
+// FAT32 STATUS CODES
+
+#define FAT32_EOF              	0xEEEE                  // end of file reached
+
+// LAYOUT OF THE MOUNT DATA STRUCTURE (DEVICE HANDLE)
+
+#define FAT32_DEV_RESET        	0x0000                  // pointer to device reset function
+#define FAT32_DEV_BLOCK_READ   	0x0001                  // pointer to 512-byte block read function
+#define FAT32_DEV_BLOCK_WRITE  	0x0002                  // pointer to 512-byte block write function
+#define FAT32_DEV_BYTE_READ    	0x0003                  // pointer to 1-byte read function (within block buffer)
+#define FAT32_DEV_BYTE_WRITE   	0x0004                  // pointer to 1-byte write function (within block buffer)
+#define FAT32_DEV_PARTITION    	0x0005                  // number of partition to be mounted
+#define FAT32_DEV_FS_LO        	0x0006                  // file system start address (LBA): low word
+#define FAT32_DEV_FS_HI        	0x0007                  // file system start address (LBA): high word
+#define FAT32_DEV_FAT_LO       	0x0008                  // fat start address (LBA): low word
+#define FAT32_DEV_FAT_HI       	0x0009                  // fat start address (LBA): high word
+#define FAT32_DEV_CLUSTER_LO   	0x000A                  // cluster start address (LBA): low word
+#define FAT32_DEV_CLUSTER_HI   	0x000B                  // cluster start address (LBA): high word
+#define FAT32_DEV_SECT_PER_CLUS	0x000C                  // sectors per cluster
+#define FAT32_DEV_RD_1STCLUS_LO	0x000D                  // root directory first cluster: low word
+#define FAT32_DEV_RD_1STCLUS_HI	0x000E                  // root directory first cluster: high word
+#define FAT32_DEV_AD_1STCLUS_LO	0x000F                  // currently active directory first cluster: low word
+#define FAT32_DEV_AD_1STCLUS_HI	0x0010                  // currently active directory first cluster: high word
+#define FAT32_DEV_BUFFERED_FDH 	0x0011                  // FDH which is responsible for the current 512 byte hardware buffer filling
+
+#define FAT32_DEV_STRUCT_SIZE  	0x0012                  // size (words) of the mount data structure (device handle)
+
+// LAYOUT OF THE FILE HANDLE AND DIRECTORY HANDLE (FDH)
+
+#define FAT32_FDH_DEVICE       	0x0000                  // pointer to the device handle
+#define FAT32_FDH_CLUSTER_LO   	0x0001                  // current cluster (low word)
+#define FAT32_FDH_CLUSTER_HI   	0x0002                  // current cluster (high word)
+#define FAT32_FDH_SECTOR       	0x0003                  // current sector
+#define FAT32_FDH_INDEX        	0x0004                  // current byte index within current sector
+#define FAT32_FDH_SIZE_LO      	0x0005                  // only in case FDH is a file: low word of file size, otherwise undefined
+#define FAT32_FDH_SIZE_HI      	0x0006                  // only in case FDH is a file: high word of file size, otherwise undefined
+#define FAT32_FDH_READ_LO      	0x0007                  // only in case FDH is a file: low word of already read amount of bytes
+#define FAT32_FDH_READ_HI      	0x0008                  // only in case FDH is a file: high word of already read amount of bytes
+
+#define FAT32_FDH_STRUCT_SIZE  	0x0009                  // size of the directory handle structure
+
+// FILE ATTRIBUTES
+
+#define FAT32_FA_READ_ONLY     	0x0001                  // read only file
+#define FAT32_FA_HIDDEN        	0x0002                  // hidden file
+#define FAT32_FA_SYSTEM        	0x0004                  // system file
+#define FAT32_FA_VOLUME_ID     	0x0008                  // volume id (name of the volume)
+#define FAT32_FA_DIR           	0x0010                  // directory
+#define FAT32_FA_ARCHIVE       	0x0020                  // archive flag
+
+#define FAT32_FA_DEFAULT       	0x0035                  // browse for non hidden files and directories but not for the volume id
+#define FAT32_FA_ALL           	0x0037                  // browse for all files, but not for the volume id
+
+// LAYOUT OF THE DIRECTORY ENTRY STRUCTURE
+
+#define FAT32_DE_NAME          	0x0000                  // volume, file or directory name, zero terminated (max 256 characters)
+#define FAT32_DE_ATTRIB        	0x0101                  // file attributes (read-only, hidden, system, volume id, directory, archive)
+#define FAT32_DE_SIZE_LO       	0x0102                  // file size: low word
+#define FAT32_DE_SIZE_HI       	0x0103                  // file size: high word
+#define FAT32_DE_YEAR          	0x0104                  // last file write: year   (valid range 1980 .. 2107)
+#define FAT32_DE_MONTH         	0x0105                  // last file write: month
+#define FAT32_DE_DAY           	0x0106                  // last file write: day
+#define FAT32_DE_HOUR          	0x0107                  // last file write: hour
+#define FAT32_DE_MINUTE        	0x0108                  // last file write: minute
+#define FAT32_DE_SECOND        	0x0109                  // last file write: second (in 2 second steps, valid range 0 .. 58)
+#define FAT32_DE_CLUS_LO       	0x010A                  // start cluster: low word
+#define FAT32_DE_CLUS_HI       	0x010B                  // start cluster: high word
+
+#define FAT32_DE_STRUCT_SIZE   	0x010C                  // size (words) of the directory entry data structure of the
+
+// DISPLAY FLAGS FOR FILE ENTRY PRETTY PRINTER
+
+#define FAT32_PRINT_SHOW_DIR   	0x0001                  // show "<DIR>" indicator
+#define FAT32_PRINT_SHOW_ATTRIB	0x0002                  // show attributes as "HRSA"
+#define FAT32_PRINT_SHOW_SIZE  	0x0004                  // show file size
+#define FAT32_PRINT_SHOW_DATE  	0x0008                  // show file date as YYYY-MM-DD
+#define FAT32_PRINT_SHOW_TIME  	0x0010                  // show file time as HH:MM
+
+#define FAT32_PRINT_DEFAULT    	0x001D                  // print <DIR> indicator, size, date and time (no attributes)
+#define FAT32_PRINT_ALL        	0x001F                  // print all details
+
+// ========== KEYBOARD ==========
+
+// STATUS REGISTER
+
+#define KBD_NEW_ASCII          	0x0001                  // new ascii character available
+#define KBD_NEW_SPECIAL        	0x0002                  // new special key available
+#define KBD_NEW_ANY            	0x0003                  // any new key available 
+
+#define KBD_ASCII              	0x00FF                  // mask the special keys
+#define KBD_SPECIAL            	0xFF00                  // mask the ascii keys
+
+#define KBD_LOCALE             	0x001C                  // bit mask for checking locales
+#define KBD_LOCALE_US          	0x0000                  // default: US keyboard layout
+#define KBD_LOCALE_DE          	0x0004                  // DE: German keyboard layout
+
+#define KBD_MODIFIERS          	0x00E0                  // bit mask for checking modifiers
+#define KBD_SHIFT              	0x0020                  // modifier "SHIFT" pressed
+#define KBD_ALT                	0x0040                  // modifier "ALT" pressed
+#define KBD_CTRL               	0x0080                  // modifier "CTRL" pressed
+
+// READ REGISTER: COMMON ASCII CODES
+
+#define KBD_SPACE              	0x0020
+#define KBD_ENTER              	0x000D
+#define KBD_ESC                	0x001B
+#define KBD_TAB                	0x0009
+#define KBD_BACKSPACE          	0x0008
+
+// READ REGISTER: SPECIAL KEYS
+
+#define KBD_F1                 	0x0100
+#define KBD_F2                 	0x0200
+#define KBD_F3                 	0x0300
+#define KBD_F4                 	0x0400
+#define KBD_F5                 	0x0500
+#define KBD_F6                 	0x0600
+#define KBD_F7                 	0x0700
+#define KBD_F8                 	0x0800
+#define KBD_F9                 	0x0900
+#define KBD_F10                	0x0A00
+#define KBD_F11                	0x0B00
+#define KBD_F12                	0x0C00
+
+#define KBD_CUR_UP             	0x1000
+#define KBD_CUR_DOWN           	0x1100
+#define KBD_CUR_LEFT           	0x1200
+#define KBD_CUR_RIGHT          	0x1300
+#define KBD_PG_UP              	0x1400
+#define KBD_PG_DOWN            	0x1500
+#define KBD_HOME               	0x1600
+#define KBD_END                	0x1700
+#define KBD_INS                	0x1800
+#define KBD_DEL                	0x1900
+
+// READ REGISTER: CTRL + character is also mapped to an ASCII code
+
+#define KBD_CTRL_A             	0x0001 
+#define KBD_CTRL_B             	0x0002 
+#define KBD_CTRL_C             	0x0003 
+#define KBD_CTRL_D             	0x0004 
+#define KBD_CTRL_E             	0x0005 
+#define KBD_CTRL_F             	0x0006 
+#define KBD_CTRL_G             	0x0007 
+#define KBD_CTRL_H             	0x0008 
+#define KBD_CTRL_I             	0x0009 
+#define KBD_CTRL_J             	0x000A 
+#define KBD_CTRL_K             	0x000B 
+#define KBD_CTRL_L             	0x000C 
+#define KBD_CTRL_M             	0x000D 
+#define KBD_CTRL_N             	0x000E 
+#define KBD_CTRL_O             	0x000F 
+#define KBD_CTRL_P             	0x0010 
+#define KBD_CTRL_Q             	0x0011 
+#define KBD_CTRL_R             	0x0012 
+#define KBD_CTRL_S             	0x0013 
+#define KBD_CTRL_T             	0x0014 
+#define KBD_CTRL_U             	0x0015 
+#define KBD_CTRL_V             	0x0016 
+#define KBD_CTRL_W             	0x0017 
+#define KBD_CTRL_X             	0x0018 
+#define KBD_CTRL_Y             	0x0019 
+#define KBD_CTRL_Z             	0x001A 
+
+//
+//  Useful ASCII constants:
+//
+#define CHR_BELL       	0x0007 // ASCII-BELL character
+#define CHR_TAB        	0x0009 // ASCII-TAB character
+#define CHR_SPACE      	0x0020 // ASCII-Space
+#define CHR_CR         	0x000d // Carriage return
+#define CHR_LF         	0x000a // Line feed
diff --git a/machines/rf12/machine.c b/machines/rf12/machine.c
new file mode 100755
index 0000000..40c6bc9
--- /dev/null
+++ b/machines/rf12/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?)
+  struct-copy Problemfälle
+  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&REG){
+    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)&&section!=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&&regused[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&&regused[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&&regused[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&REG)||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&REG)&&p2->q1.reg==p->z.reg)||((p2->q2.flags&REG)&&p2->q2.reg==p->z.reg)||((p2->z.flags&REG)&&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&REG)||p->q2.reg!=r)&&(!(p->z.flags&REG)||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&REG)&&p2->q1.reg==r)||((p2->q2.flags&REG)&&p2->q2.reg==r)||((p2->z.flags&REG)&&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&REG)||p->q1.reg!=r)&&(!(p->z.flags&REG)||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&REG)&&p2->q1.reg==r)||((p2->q2.flags&REG)&&p2->q2.reg==r)||((p2->z.flags&REG)&&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&REG)||p->q1.reg!=r)&&(!(p->q2.flags&REG)||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&REG)&&p2->q1.reg==r)||((p2->q2.flags&REG)&&p2->q2.reg==r)||((p2->z.flags&REG)&&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&REG)&&ISACC(p->q2.reg)) ierror(0);
+    if(p->z.am)
+      if(p->z.am->flags==ACC_IND) ierror(0);
+    else
+      if((p->z.flags&REG)&&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&REG)||p->q1.reg!=r)&&
+	 (!(p->q2.flags&REG)||p->q2.reg!=r)&&
+	 (!(p->z.flags&REG)||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&REG)&&p->q1.reg==r) return 0;
+    if((p->q2.flags&REG)&&p->q2.reg==r) return 0;
+    if((p->z.flags&REG)&&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]=&ltyp;
+
+  /*  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)&&regok(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&&section!=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))&&section!=DATA){
+	emit(f,dataname);if(f) section=DATA;
+      }
+      if(v->clist&&constflag&&!(g_flags[3]&USEDFLAG)&&section!=RODATA){
+	emit(f,rodataname);if(f) section=RODATA;
+      }
+      if(!v->clist&&section!=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))&&section!=DATA){
+	  emit(f,dataname);if(f) section=DATA;
+	}
+	if(v->clist&&constflag&&!(g_flags[3]&USEDFLAG)&&section!=RODATA){
+	  emit(f,rodataname);if(f) section=RODATA;
+	}
+	if(!v->clist&&section!=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]&&regs[ix]&&regs[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&REG)&&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&REG)&&p->q2.reg==ix){
+	  if((p->z.flags&REG)&&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&REG)&&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)&&regs[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)&&regs[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]&&regs[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]&&regs[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]&&regs[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&REG)||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)&&regs[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)&&regs[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&&reg==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&&reg==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&&reg==ix&&CPU==6812){
+		emit(f,"\tinx\n");
+	      }else if(l==1&&reg==iy&&CPU==6812){
+		emit(f,"\tiny\n");
+	      }else if(l==-1&&reg==ix&&CPU==6812){
+		emit(f,"\tdex\n");
+	      }else if(l==-1&&reg==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)&&regs[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;
+} 
diff --git a/machines/rf12/machine.dt b/machines/rf12/machine.dt
new file mode 100755
index 0000000..7d54552
--- /dev/null
+++ b/machines/rf12/machine.dt
@@ -0,0 +1,14 @@
+S12BS
+S12BU
+S24BS
+S24BU
+S24BS
+S24BU
+S48BS
+S48BU
+S64BSLE S64BSBE
+S64BULE S64BUBE
+S32BIEEEBE
+S64BIEEEBE
+S64BIEEEBE
+S48BU
diff --git a/machines/rf12/machine.h b/machines/rf12/machine.h
new file mode 100755
index 0000000..a90ae8f
--- /dev/null
+++ b/machines/rf12/machine.h
@@ -0,0 +1,188 @@
+/*  Example of a code-generator for Motorola 68hc12 16bit microcontrollers.*/
+
+#include "dt.h"
+
+/* We have extended types! What we have to do to support them:      */
+/* - #define HAVE_EXT_TYPES
+   - #undef all standard types
+   - #define all standard types plus new types
+   - write eval_const and insert_const
+   - write typedefs for zmax and zumax
+   - write typname[]
+   - write conv_typ()
+   - optionally #define ISPOINTER, ISARITH, ISINT etc.
+   - optionally #define HAVE_TGT_PRINTVAL and write printval
+   - optionally #define POINTER_TYPE
+   - optionally #define HAVE_TGT_FALIGN and write falign
+   - optionally #define HAVE_TGT_SZOF and write szof
+   - optionally add functions for attribute-handling
+*/
+#define HAVE_EXT_TYPES 1
+
+#define HAVE_TGT_PRINTVAL
+
+#undef CHAR
+#undef SHORT
+#undef INT
+#undef LONG
+#undef LLONG
+#undef FLOAT
+#undef DOUBLE
+#undef LDOUBLE
+#undef VOID
+#undef POINTER
+#undef ARRAY
+#undef STRUCT
+#undef UNION
+#undef ENUM
+#undef FUNKT
+#undef MAXINT
+#undef MAX_TYPE
+
+#define BIT 1
+#define CHAR 2
+#define SHORT 3
+#define INT 4
+#define LONG 5
+#define LLONG 6
+#define FLOAT 7
+#define DOUBLE 8
+#define LDOUBLE 9
+#define VOID 10
+#define NPOINTER 11
+#define FPOINTER 12
+#define HPOINTER 13
+#define ARRAY 14
+#define STRUCT 15
+#define UNION 16
+#define ENUM 17
+#define FUNKT 18
+
+#define MAXINT 19
+
+#define MAX_TYPE MAXINT
+
+#define POINTER_TYPE(x) pointer_type(x)
+extern int pointer_type();
+#define ISPOINTER(x) ((x&NQ)>=NPOINTER&&(x&NQ)<=HPOINTER)
+#define ISSCALAR(x) ((x&NQ)>=BIT&&(x&NQ)<=HPOINTER)
+#define ISINT(x) ((x&NQ)>=BIT&&(x&NQ)<=LLONG)
+#define PTRDIFF_T(x) ((x)==HPOINTER?LONG:INT)
+
+typedef zllong zmax;
+typedef zullong zumax;
+
+union atyps{
+  zchar vchar;
+  zuchar vuchar;
+  zshort vshort;
+  zushort vushort;
+  zint vint;
+  zuint vuint;
+  zlong vlong;
+  zulong vulong;
+  zllong vllong;
+  zullong vullong;
+  zmax vmax;
+  zumax vumax;
+  zfloat vfloat;
+  zdouble vdouble;
+  zldouble vldouble;
+};
+
+/*  This struct can be used to implement machine-specific           */
+/*  addressing-modes.                                               */
+/*  Not used in this code-generrator.                               */
+struct AddressingMode{
+    int flags;
+    int base;
+    long offset;
+    struct Var *v;
+};
+
+/* This type will be added to every IC. Can be used by the cg.      */
+#define HAVE_EXT_IC 1
+struct ext_ic {
+  int flags;
+  int r;
+  long offset;
+};
+
+/*  The number of registers of the target machine.                  */
+#define MAXR 6
+
+/*  Number of commandline-options the code-generator accepts.       */
+#define MAXGF 20
+
+/*  If this is set to zero vbcc will not generate ICs where the     */
+/*  target operand is the same as the 2nd source operand.           */
+/*  This can sometimes simplify the code-generator, but usually     */
+/*  the code is better if the code-generator allows it.             */
+#define USEQ2ASZ 1
+
+/*  This specifies the smallest integer type that can be added to a */
+/*  pointer.                                                        */
+extern int MINADDI2P;
+
+/*  If the bytes of an integer are ordered most significant byte    */
+/*  byte first and then decreasing set BIGENDIAN to 1.              */
+#define BIGENDIAN 1
+
+/*  If the bytes of an integer are ordered lest significant byte    */
+/*  byte first and then increasing set LITTLEENDIAN to 1.           */
+#define LITTLEENDIAN 0
+
+/*  Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive.    */
+
+/*  If switch-statements should be generated as a sequence of       */
+/*  SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1.      */
+/*  This can yield better code on some machines.                    */
+extern int switchsubs;
+#define SWITCHSUBS switchsubs
+
+/*  In optimizing compilation certain library memcpy/strcpy-calls   */
+/*  with length known at compile-time will be inlined using an      */
+/*  ASSIGN-IC if the size is less or equal to INLINEMEMCPY.         */
+/*  The type used for the ASSIGN-IC will be UNSIGNED|CHAR.          */
+#define INLINEMEMCPY 1024
+
+#define HAVE_REGPARMS 1
+
+struct reg_handle {
+  int gpr;
+};
+
+/*  We use unsigned int as size_t rather than unsigned long which   */
+/*  is the default setting.                                         */
+#define HAVE_INT_SIZET 1
+
+/*  We have register pairs.                                         */
+#define HAVE_REGPAIRS 1
+
+/*  We keep track of all registers modified by a function.          */
+#define HAVE_REGS_MODIFIED 1
+
+#define HAVE_TARGET_RALLOC 1
+#define cost_load_reg(r,v) 4
+#define cost_save_reg(r,v) 4
+#define cost_move_reg(i,j) 2
+#define cost_pushpop_reg(r) 2
+
+/* size of buffer for asm-output */
+#define EMIT_BUF_LEN 1024 /* should be enough */
+/* number of asm-output lines buffered */
+#define EMIT_BUF_DEPTH 4
+
+/*  We have asm_peephole to optimize assembly-output */
+#define HAVE_TARGET_PEEPHOLE 1
+
+/*  We have some target-specific variable attributes.               */
+#define HAVE_TARGET_ATTRIBUTES 1
+
+/* We use builtin libcalls for some operations */
+#define HAVE_LIBCALLS 1
+
+/* We prefer BNE rather than BGT. */
+#define HAVE_WANTBNE 1
+
+#define HAVE_POF2OPT 1
diff --git a/machines/src/machine.c b/machines/src/machine.c
new file mode 100755
index 0000000..f4f25af
--- /dev/null
+++ b/machines/src/machine.c
@@ -0,0 +1,1092 @@
+/*  C src backend for vbcc
+ */
+
+#include "supp.h"
+
+static char FILE_[]=__FILE__;
+
+/*  Public data that MUST be there.                             */
+
+/* Name and copyright. */
+char cg_copyright[]="vbcc C source code-generator V0.1a (c) in 2011 by Volker Barthelmann";
+
+
+int g_flags[MAXGF]={0};
+
+/* the flag-name, do not use names beginning with l, L, I, D or U, because
+   they collide with the frontend */
+char *g_flags_name[MAXGF]={0};
+
+/* the results of parsing the command-line-flags will be stored here */
+union ppi g_flags_val[MAXGF];
+
+/*  Alignment-requirements for all types in bytes.              */
+zmax align[MAX_TYPE+1];
+
+/*  Alignment that is sufficient for every object.              */
+zmax maxalign;
+
+/*  CHAR_BIT for the target machine.                            */
+zmax char_bit;
+
+/*  sizes of the basic 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. will be initialized in init_cg(),
+    register number 0 is invalid, valid registers start at 1 */
+char *regnames[MAXR+1];
+
+/*  The Size of each register in bytes.                         */
+zmax regsize[MAXR+1];
+
+/*  a 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];
+
+/* specifies the priority for the register-allocator, if the same
+   estimated cost-saving can be obtained by several registers, the
+   one with the highest priority will be used */
+int reg_prio[MAXR+1];
+
+/* Names of target-specific variable attributes.                */
+char *g_attr_name[]={"__interrupt",0};
+
+
+/****************************************/
+/*  Private data and functions.         */
+/****************************************/
+
+/* alignment of basic data-types, used to initialize align[] */
+static long malign[MAX_TYPE+1]=  {1,1,2,4,4,4,4,8,8,1,4,1,1,1,4,1};
+/* sizes of basic data-types, used to initialize sizetab[] */
+static long msizetab[MAX_TYPE+1]={1,1,2,4,4,8,4,8,8,0,4,0,0,0,4,0};
+
+/* used to initialize regtyp[] */
+static struct Typ ltyp={LONG},ldbl={DOUBLE},lchar={CHAR};
+
+/* macros defined by the backend */
+static char *marray[]={"__section(x)=__vattr(\"section(\"#x\")\")",
+		       "__GENERIC__",
+		       0};
+
+
+#define dt(t) (((t)&UNSIGNED)?udt[(t)&NQ]:sdt[(t)&NQ])
+static char *sdt[MAX_TYPE+1]={"??","c","s","i","l","ll","f","d","ld","v","p"};
+static char *udt[MAX_TYPE+1]={"??","uc","us","ui","ul","ull","f","d","ld","v","p"};
+
+/* sections */
+#define DATA 0
+#define BSS 1
+#define CODE 2
+#define RODATA 3
+#define SPECIAL 4
+
+static long stack;
+static int stack_valid;
+static int section=-1,newobj;
+static char *codename="\t.text\n",
+  *dataname="\t.data\n",
+  *bssname="",
+  *rodataname="\t.section\t.rodata\n";
+
+/* return-instruction */
+static char *ret;
+
+/* label at the end of the function (if any) */
+static int exit_label;
+
+/* assembly-prefixes for labels and external identifiers */
+static char *labprefix="l",*idprefix="_";
+
+#if FIXED_SP
+/* variables to calculate the size and partitioning of the stack-frame
+   in the case of FIXED_SP */
+static long frameoffset,pushed,maxpushed,framesize;
+#else
+/* variables to keep track of the current stack-offset in the case of
+   a moving stack-pointer */
+static long notpopped,dontpop,stackoffset,maxpushed;
+#endif
+
+static long localsize,rsavesize,argsize;
+
+static void emit_obj(FILE *f,struct obj *p,int t);
+
+/* calculate the actual current offset of an object relativ to the
+   stack-pointer; we use a layout like this:
+   ------------------------------------------------
+   | arguments to this function                   |
+   ------------------------------------------------
+   | return-address [size=4]                      |
+   ------------------------------------------------
+   | caller-save registers [size=rsavesize]       |
+   ------------------------------------------------
+   | local variables [size=localsize]             |
+   ------------------------------------------------
+   | arguments to called functions [size=argsize] |
+   ------------------------------------------------
+   All sizes will be aligned as necessary.
+   In the case of FIXED_SP, the stack-pointer will be adjusted at
+   function-entry to leave enough space for the arguments and have it
+   aligned to 16 bytes. Therefore, when calling a function, the
+   stack-pointer is always aligned to 16 bytes.
+   For a moving stack-pointer, the stack-pointer will usually point
+   to the bottom of the area for local variables, but will move while
+   arguments are put on the stack.
+
+   This is just an example layout. Other layouts are also possible.
+*/
+
+static long real_offset(struct obj *o)
+{
+  long off=zm2l(o->v->offset);
+  if(off<0){
+    /* function parameter */
+    off=localsize+rsavesize+4-off-zm2l(maxalign);
+  }
+
+#if FIXED_SP
+  off+=argsize;
+#else
+  off+=stackoffset;
+#endif
+  off+=zm2l(o->val.vmax);
+  return off;
+}
+
+/*  Initializes an addressing-mode structure and returns a pointer to
+    that object. Will not survive a second call! */
+static struct obj *cam(int flags,int base,long offset)
+{
+  static struct obj obj;
+  static struct AddressingMode am;
+  obj.am=&am;
+  am.flags=flags;
+  am.base=base;
+  am.offset=offset;
+  return &obj;
+}
+
+/* changes to a special section, used for __section() */
+static int special_section(FILE *f,struct Var *v)
+{
+  char *sec;
+  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;
+}
+
+/* generate code to load the address of a variable into register r */
+static void load_address(FILE *f,int r,struct obj *o,int type)
+/*  Generates code to load the address of a variable into register r.   */
+{
+  if(!(o->flags&VAR)) ierror(0);
+  if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER){
+    long off=real_offset(o);
+    if(THREE_ADDR){
+      emit(f,"\tadd.%s\t%s,%s,%ld\n",dt(POINTER),regnames[r],regnames[sp],off);
+    }else{
+      emit(f,"\tmov.%s\t%s,%s\n",dt(POINTER),regnames[r],regnames[sp]);
+      if(off)
+	emit(f,"\tadd.%s\t%s,%ld\n",dt(POINTER),regnames[r],off);
+    }
+  }else{
+    emit(f,"\tmov.%s\t%s,",dt(POINTER),regnames[r]);
+    emit_obj(f,o,type);
+    emit(f,"\n");
+  }
+}
+/* Generates code to load a memory object into register r. tmp is a
+   general purpose register which may be used. tmp can be r. */
+static void load_reg(FILE *f,int r,struct obj *o,int type)
+{
+  type&=NU;
+  if(o->flags&VARADR){
+    load_address(f,r,o,POINTER);
+  }else{
+    if((o->flags&(REG|DREFOBJ))==REG&&o->reg==r)
+      return;
+    emit(f,"\tmov.%s\t%s,",dt(type),regnames[r]);
+    emit_obj(f,o,type);
+    emit(f,"\n");
+  }
+}
+
+/*  Generates code to store register r into memory object o. */
+static void store_reg(FILE *f,int r,struct obj *o,int type)
+{
+  type&=NQ;
+  emit(f,"\tmov.%s\t",dt(type));
+  emit_obj(f,o,type);
+  emit(f,",%s\n",regnames[r]);
+}
+
+/*  Yields log2(x)+1 or 0. */
+static long pof2(zumax x)
+{
+  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 struct IC *preload(FILE *,struct IC *);
+
+static void function_top(FILE *,struct Var *,long);
+static void function_bottom(FILE *f,struct Var *,long);
+
+#define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
+#define isconst(x) ((p->x.flags&(KONST|DREFOBJ))==KONST)
+
+static int q1reg,q2reg,zreg;
+
+static char *ccs[]={"eq","ne","lt","ge","le","gt",""};
+static char *logicals[]={"or","xor","and"};
+static char *arithmetics[]={"slw","srw","add","sub","mullw","divw","mod"};
+
+/* Does some pre-processing like fetching operands from memory to
+   registers etc. */
+static struct IC *preload(FILE *f,struct IC *p)
+{
+  int r;
+
+  if(isreg(q1))
+    q1reg=p->q1.reg;
+  else
+    q1reg=0;
+
+  if(isreg(q2))
+    q2reg=p->q2.reg;
+  else
+    q2reg=0;
+
+  if(isreg(z)){
+    zreg=p->z.reg;
+  }else{
+    if(ISFLOAT(ztyp(p)))
+      zreg=f1;
+    else
+      zreg=t1;
+  }
+  
+  if((p->q1.flags&(DREFOBJ|REG))==DREFOBJ&&!p->q1.am){
+    p->q1.flags&=~DREFOBJ;
+    load_reg(f,t1,&p->q1,q1typ(p));
+    p->q1.reg=t1;
+    p->q1.flags|=(REG|DREFOBJ);
+  }
+  if(p->q1.flags&&LOAD_STORE&&!isreg(q1)){
+    if(ISFLOAT(q1typ(p)))
+      q1reg=f1;
+    else
+      q1reg=t1;
+    load_reg(f,q1reg,&p->q1,q1typ(p));
+    p->q1.reg=q1reg;
+    p->q1.flags=REG;
+  }
+
+  if((p->q2.flags&(DREFOBJ|REG))==DREFOBJ&&!p->q2.am){
+    p->q2.flags&=~DREFOBJ;
+    load_reg(f,t1,&p->q2,q2typ(p));
+    p->q2.reg=t1;
+    p->q2.flags|=(REG|DREFOBJ);
+  }
+  if(p->q2.flags&&LOAD_STORE&&!isreg(q2)){
+    if(ISFLOAT(q2typ(p)))
+      q2reg=f2;
+    else
+      q2reg=t2;
+    load_reg(f,q2reg,&p->q2,q2typ(p));
+    p->q2.reg=q2reg;
+    p->q2.flags=REG;
+  }
+  return p;
+}
+
+/* save the result (in zreg) into p->z */
+void save_result(FILE *f,struct IC *p)
+{
+  if((p->z.flags&(REG|DREFOBJ))==DREFOBJ&&!p->z.am){
+    p->z.flags&=~DREFOBJ;
+    load_reg(f,t2,&p->z,POINTER);
+    p->z.reg=t2;
+    p->z.flags|=(REG|DREFOBJ);
+  }
+  if(isreg(z)){
+    if(p->z.reg!=zreg)
+      emit(f,"\tmov.%s\t%s,%s\n",dt(ztyp(p)),regnames[p->z.reg],regnames[zreg]);
+  }else{
+    store_reg(f,zreg,&p->z,ztyp(p));
+  }
+}
+
+/* prints an object */
+static void emit_obj(FILE *f,struct obj *p,int t)
+{
+  if(p->am){
+    if(p->am->flags&GPR_IND) emit(f,"(%s,%s)",regnames[p->am->offset],regnames[p->am->base]);
+    if(p->am->flags&IMM_IND) emit(f,"(%ld,%s)",p->am->offset,regnames[p->am->base]);
+    return;
+  }
+  if((p->flags&(KONST|DREFOBJ))==(KONST|DREFOBJ)){
+    emitval(f,&p->val,p->dtyp&NU);
+    return;
+  }
+  if(p->flags&DREFOBJ) emit(f,"(");
+  if(p->flags&REG){
+    emit(f,"%s",regnames[p->reg]);
+  }else if(p->flags&VAR) {
+    if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER)
+      emit(f,"%ld(%s)",real_offset(p),regnames[sp]);
+    else{
+      if(!zmeqto(l2zm(0L),p->val.vmax)){emitval(f,&p->val,LONG);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(p->flags&KONST){
+    emitval(f,&p->val,t&NU);
+  }
+  if(p->flags&DREFOBJ) emit(f,")");
+}
+
+/*  Test if there is a sequence of FREEREGs containing FREEREG reg.
+    Used by peephole. */
+static int exists_freereg(struct IC *p,int reg)
+{
+  while(p&&(p->code==FREEREG||p->code==ALLOCREG)){
+    if(p->code==FREEREG&&p->q1.reg==reg) return 1;
+    p=p->next;
+  }
+  return 0;
+}
+
+/* search for possible addressing-modes */
+static void peephole(struct IC *p)
+{
+  int c,c2,r;struct IC *p2;struct AddressingMode *am;
+
+  for(;p;p=p->next){
+    c=p->code;
+    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;
+
+    /* Try const(reg) */
+    if(IMM_IND&&(c==ADDI2P||c==SUBIFP)&&isreg(z)&&(p->q2.flags&(KONST|DREFOBJ))==KONST){
+      int base;zmax of;struct obj *o;
+      eval_const(&p->q2.val,p->typf);
+      if(c==SUBIFP) of=zmsub(l2zm(0L),vmax); else of=vmax;
+      if(1/*zmleq(l2zm(-32768L),vmax)&&zmleq(vmax,l2zm(32767L))*/){
+	r=p->z.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(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) break;
+	      o=&p2->q1;
+	    }
+	    if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
+	      if(o) break;
+	      o=&p2->q2;
+	    }
+	    if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
+	      if(o) 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);
+		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;
+	  }
+        }
+      }
+    }
+    /* Try reg,reg */
+    if(GPR_IND&&c==ADDI2P&&isreg(q2)&&isreg(z)&&(isreg(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||(q1typ(p2)&NQ)==LLONG) break;
+            o=&p2->q1;
+          }
+          if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
+            if(o||(q2typ(p2)&NQ)==LLONG) break;
+            o=&p2->q2;
+          }
+          if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
+            if(o||(ztyp(p2)&NQ)==LLONG) 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=GPR_IND;
+              am->base=base;
+              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;
+        }
+      }
+    }
+  }
+}
+
+/* generates the function entry code */
+static void function_top(FILE *f,struct Var *v,long offset)
+{
+  rsavesize=0;
+  if(!special_section(f,v)&&section!=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));
+}
+/* generates the function exit code */
+static void function_bottom(FILE *f,struct Var *v,long offset)
+{
+  emit(f,ret);
+}
+
+/****************************************/
+/*  End of private data and functions.  */
+/****************************************/
+
+/*  Does necessary initializations for the code-generator. Gets called  */
+/*  once at the beginning and should return 0 in case of problems.      */
+int init_cg(void)
+{
+  int i;
+  /*  Initialize some values which cannot be statically initialized   */
+  /*  because they are stored in the target's arithmetic.             */
+  maxalign=l2zm(8L);
+  char_bit=l2zm(8L);
+
+  for(i=0;i<=MAX_TYPE;i++){
+    sizetab[i]=l2zm(msizetab[i]);
+    align[i]=l2zm(malign[i]);
+  }
+
+  regnames[0]="noreg";
+  for(i=FIRST_GPR;i<=LAST_GPR;i++){
+    regnames[i]=mymalloc(10);
+    sprintf(regnames[i],"gpr%d",i-FIRST_GPR);
+    regsize[i]=l2zm(4L);
+    regtype[i]=&ltyp;
+  }
+  for(i=FIRST_FPR;i<=LAST_FPR;i++){
+    regnames[i]=mymalloc(10);
+    sprintf(regnames[i],"fpr%d",i-FIRST_FPR);
+    regsize[i]=l2zm(8L);
+    regtype[i]=&ldbl;
+  }
+  for(i=FIRST_CCR;i<=LAST_CCR;i++){
+    regnames[i]=mymalloc(10);
+    sprintf(regnames[i],"ccr%d",i-FIRST_CCR);
+    regsize[i]=l2zm(1L);
+    regtype[i]=&lchar;
+  }
+
+  /*  Use multiple ccs.   */
+  multiple_ccs=0;
+
+  /*  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.          */
+  t_min[CHAR]=l2zm(-128L);
+  t_min[SHORT]=l2zm(-32768L);
+  t_min[INT]=zmsub(l2zm(-2147483647L),l2zm(1L));
+  t_min[LONG]=t_min(INT);
+  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]=ul2zum(2147483647UL);
+  t_max[LONG]=t_max(INT);
+  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]=ul2zum(4294967295UL);
+  tu_max[LONG]=t_max(UNSIGNED|INT);
+  tu_max[LLONG]=zumkompl(ul2zum(0UL));
+  tu_max[MAXINT]=t_max(UNSIGNED|LLONG);
+  
+  /*  Reserve a few registers for use by the code-generator.      */
+  /*  This is not optimal but simple.                             */
+  sp=FIRST_GPR;
+  t1=FIRST_GPR+1;
+  t2=FIRST_GPR+2;
+  f1=FIRST_FPR;
+  f2=FIRST_FPR+1;
+  regsa[t1]=regsa[t2]=1;
+  regsa[f1]=regsa[f2]=1;
+  regsa[sp]=1;
+  regscratch[t1]=regscratch[t2]=0;
+  regscratch[f1]=regscratch[f2]=0;
+  regscratch[sp]=0;
+
+  for(i=FIRST_GPR;i<=LAST_GPR-VOL_GPRS;i++)
+    regscratch[i]=1;
+  for(i=FIRST_FPR;i<=LAST_FPR-VOL_FPRS;i++)
+    regscratch[i]=1;
+  for(i=FIRST_CCR;i<=LAST_CCR-VOL_CCRS;i++)
+    regscratch[i]=1;
+
+  target_macros=marray;
+
+
+  return 1;
+}
+
+void init_db(FILE *f)
+{
+}
+
+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.        */
+/*  A pointer MUST be returned in a register. The code-generator    */
+/*  has to simulate a pseudo register if necessary.                 */
+{
+  if(ISFLOAT(t->flags)) 
+    return FIRST_FPR+2;
+  if(ISSTRUCT(t->flags)||ISUNION(t->flags)) 
+    return 0;
+  if(zmleq(szof(t),l2zm(4L))) 
+    return FIRST_GPR+3;
+  else
+    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.                                            */
+{
+  return 0;
+}
+
+/* estimate the cost-saving if object o from IC p is placed in
+   register r */
+int cost_savings(struct IC *p,int r,struct obj *o)
+{
+  int c=p->code;
+  if(o->flags&VKONST){
+    if(!LOAD_STORE)
+      return 0;
+    if(o==&p->q1&&p->code==ASSIGN&&(p->z.flags&DREFOBJ))
+      return 4;
+    else
+      return 2;
+  }
+  if(o->flags&DREFOBJ)
+    return 4;
+  if(c==SETRETURN&&r==p->z.reg&&!(o->flags&DREFOBJ)) return 3;
+  if(c==GETRETURN&&r==p->q1.reg&&!(o->flags&DREFOBJ)) return 3;
+  return 2;
+}
+
+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(r==0)
+    return 0;
+  t&=NQ;
+  if(t==0&&r>=FIRST_CCR&&r<=LAST_CCR)
+    return 1;
+  if(ISFLOAT(t)&&r>=FIRST_FPR&&r<=LAST_FPR)
+    return 1;
+  if(t==POINTER&&r>=FIRST_GPR&&r<=LAST_GPR)
+    return 1;
+  if(t>=CHAR&&t<=LONG&&r>=FIRST_GPR&&r<=LAST_GPR)
+    return 1;
+  return 0;
+}
+
+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;
+}
+
+int must_convert(int o,int t,int const_expr)
+/*  Returns zero if code for converting np to type t    */
+/*  can be omitted.                                     */
+/*  On the PowerPC cpu pointers and 32bit               */
+/*  integers have the same representation and can use   */
+/*  the same registers.                                 */
+{
+  int op=o&NQ,tp=t&NQ;
+  if((op==INT||op==LONG||op==POINTER)&&(tp==INT||tp==LONG||tp==POINTER))
+    return 0;
+  if(op==DOUBLE&&tp==LDOUBLE) return 0;
+  if(op==LDOUBLE&&tp==DOUBLE) 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&&section!=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.              */
+{
+  if(zm2l(align)>1) emit(f,"\t.align\t2\n");
+}
+
+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;char *sec;
+  if(v->clist) constflag=is_const(v->vtyp);
+  if(v->storage_class==STATIC){
+    if(ISFUNC(v->vtyp->flags)) return;
+    if(!special_section(f,v)){
+      if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&&section!=DATA){emit(f,dataname);if(f) section=DATA;}
+      if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&&section!=RODATA){emit(f,rodataname);if(f) section=RODATA;}
+      if(!v->clist&&section!=BSS){emit(f,bssname);if(f) section=BSS;}
+    }
+    if(v->clist||section==SPECIAL){
+      gen_align(f,falign(v->vtyp));
+      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){
+    emit(f,"\t.globl\t%s%s\n",idprefix,v->identifier);
+    if(v->flags&(DEFINED|TENTATIVE)){
+      if(!special_section(f,v)){
+	if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&&section!=DATA){emit(f,dataname);if(f) section=DATA;}
+	if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&&section!=RODATA){emit(f,rodataname);if(f) section=RODATA;}
+	if(!v->clist&&section!=BSS){emit(f,bssname);if(f) section=BSS;}
+      }
+      if(v->clist||section==SPECIAL){
+	gen_align(f,falign(v->vtyp));
+        emit(f,"%s%s:\n",idprefix,v->identifier);
+      }else
+        emit(f,"\t.global\t%s%s\n\t.%scomm\t%s%s,",idprefix,v->identifier,(USE_COMMONS?"":"l"),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,"\tdc.%s\t",dt(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[0],ip[1],ip[2],ip[3]);
+      if((t&NQ)!=FLOAT){
+	emit(f,",0x%02x%02x%02x%02x",ip[4],ip[5],ip[6],ip[7]);
+      }
+    }else{
+      emitval(f,&p->val,t&NU);
+    }
+  }else{
+    emit_obj(f,&p->tree->o,t&NU);
+  }
+  emit(f,"\n");newobj=0;
+}
+
+
+/*  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 *p,struct Var *v,zmax offset)
+/*  The main code-generation.                                           */
+{
+  int c,t,i;
+  struct IC *m;
+  argsize=0;
+  if(DEBUG&1) printf("gen_code()\n");
+  for(c=1;c<=MAXR;c++) regs[c]=regsa[c];
+  maxpushed=0;
+
+  /*FIXME*/
+  ret="\trts\n";
+
+  for(m=p;m;m=m->next){
+    c=m->code;t=m->typf&NU;
+    if(c==ALLOCREG) {regs[m->q1.reg]=1;continue;}
+    if(c==FREEREG) {regs[m->q1.reg]=0;continue;}
+
+    /* convert MULT/DIV/MOD with powers of two */
+    if((t&NQ)<=LONG&&(m->q2.flags&(KONST|DREFOBJ))==KONST&&(t&NQ)<=LONG&&(c==MULT||((c==DIV||c==MOD)&&(t&UNSIGNED)))){
+      eval_const(&m->q2.val,t);
+      i=pof2(vmax);
+      if(i){
+        if(c==MOD){
+          vmax=zmsub(vmax,l2zm(1L));
+          m->code=AND;
+        }else{
+          vmax=l2zm(i-1);
+          if(c==DIV) m->code=RSHIFT; else m->code=LSHIFT;
+        }
+        c=m->code;
+	gval.vmax=vmax;
+	eval_const(&gval,MAXINT);
+	if(c==AND){
+	  insert_const(&m->q2.val,t);
+	}else{
+	  insert_const(&m->q2.val,INT);
+	  p->typf2=INT;
+	}
+      }
+    }
+#if FIXED_SP
+    if(c==CALL&&argsize<zm2l(m->q2.val.vmax)) argsize=zm2l(m->q2.val.vmax);
+#endif
+  }
+  peephole(p);
+
+  for(c=1;c<=MAXR;c++){
+    if(regsa[c]||regused[c]){
+      BSET(regs_modified,c);
+    }
+  }
+
+  localsize=(zm2l(offset)+3)/4*4;
+#if FIXED_SP
+  /*FIXME: adjust localsize to get an aligned stack-frame */
+#endif
+
+  function_top(f,v,localsize);
+  pushed=0;
+
+  for(;p;p=p->next){
+    c=p->code;t=p->typf;
+    if(c==NOP) {p->z.flags=0;continue;}
+    if(c==ALLOCREG) {regs[p->q1.reg]=1;continue;}
+    if(c==FREEREG) {regs[p->q1.reg]=0;continue;}
+    if(c==LABEL) {emit(f,"%s%d:\n",labprefix,t);continue;}
+    if(c==BRA){
+      if(t==exit_label&&framesize==0)
+	emit(f,ret);
+      else
+	emit(f,"\tb\t%s%d\n",labprefix,t);
+      continue;
+    }
+    if(c>=BEQ&&c<BRA){
+      emit(f,"\tb%s\t",ccs[c-BEQ]);
+      if(isreg(q1)){
+	emit_obj(f,&p->q1,0);
+	emit(f,",");
+      }
+      emit(f,"%s%d\n",labprefix,t);
+      continue;
+    }
+    if(c==MOVETOREG){
+      load_reg(f,p->z.reg,&p->q1,regtype[p->z.reg]->flags);
+      continue;
+    }
+    if(c==MOVEFROMREG){
+      store_reg(f,p->z.reg,&p->q1,regtype[p->z.reg]->flags);
+      continue;
+    }
+    if((c==ASSIGN||c==PUSH)&&((t&NQ)>POINTER||((t&NQ)==CHAR&&zm2l(p->q2.val.vmax)!=1))){
+      ierror(0);
+    }
+    p=preload(f,p);
+    c=p->code;
+    if(c==SUBPFP) c=SUB;
+    if(c==ADDI2P) c=ADD;
+    if(c==SUBIFP) c=SUB;
+    if(c==CONVERT){
+      if(ISFLOAT(q1typ(p))||ISFLOAT(ztyp(p))) ierror(0);
+      if(sizetab[q1typ(p)&NQ]<sizetab[ztyp(p)&NQ]){
+	if(q1typ(p)&UNSIGNED)
+	  emit(f,"\tzext.%s\t%s\n",dt(q1typ(p)),regnames[zreg]);
+	else
+	  emit(f,"\tsext.%s\t%s\n",dt(q1typ(p)),regnames[zreg]);
+      }
+      save_result(f,p);
+      continue;
+    }
+    if(c==KOMPLEMENT){
+      load_reg(f,zreg,&p->q1,t);
+      emit(f,"\tcpl.%s\t%s\n",dt(t),regnames[zreg]);
+      save_result(f,p);
+      continue;
+    }
+    if(c==SETRETURN){
+      load_reg(f,p->z.reg,&p->q1,t);
+      BSET(regs_modified,p->z.reg);
+      continue;
+    }
+    if(c==GETRETURN){
+      if(p->q1.reg){
+        zreg=p->q1.reg;
+	save_result(f,p);
+      }else
+        p->z.flags=0;
+      continue;
+    }
+    if(c==CALL){
+      int reg;
+      /*FIXME*/
+#if 0      
+      if(stack_valid&&(p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&(p->q1.v->fi->flags&ALL_STACK)){
+	if(framesize+zum2ul(p->q1.v->fi->stack1)>stack)
+	  stack=framesize+zum2ul(p->q1.v->fi->stack1);
+      }else
+	stack_valid=0;
+#endif
+      if((p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&p->q1.v->fi->inline_asm){
+        emit_inline_asm(f,p->q1.v->fi->inline_asm);
+      }else{
+	emit(f,"\tcall\t");
+	emit_obj(f,&p->q1,t);
+	emit(f,"\n");
+      }
+      /*FIXME*/
+#if FIXED_SP
+      pushed-=zm2l(p->q2.val.vmax);
+#endif
+      if((p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&(p->q1.v->fi->flags&ALL_REGS)){
+	bvunite(regs_modified,p->q1.v->fi->regs_modified,RSIZE);
+      }else{
+	int i;
+	for(i=1;i<=MAXR;i++){
+	  if(regscratch[i]) BSET(regs_modified,i);
+	}
+      }
+      continue;
+    }
+    if(c==ASSIGN||c==PUSH){
+      if(t==0) ierror(0);
+      if(c==PUSH){
+#if FIXED_SP
+	emit(f,"\tmov.%s\t%ld(%s),",dt(t),pushed,regnames[sp]);
+	emit_obj(f,&p->q1,t);
+	emit(f,"\n");
+	pushed+=zm2l(p->q2.val.vmax);
+#else
+	emit(f,"\tpush.%s\t",dt(t));
+	emit_obj(f,&p->q1,t);
+	emit(f,"\n");
+	push(zm2l(p->q2.val.vmax));
+#endif
+	continue;
+      }
+      if(c==ASSIGN){
+	load_reg(f,zreg,&p->q1,t);
+	save_result(f,p);
+      }
+      continue;
+    }
+    if(c==ADDRESS){
+      load_address(f,zreg,&p->q1,POINTER);
+      save_result(f,p);
+      continue;
+    }
+    if(c==MINUS){
+      load_reg(f,zreg,&p->q1,t);
+      emit(f,"\tneg.%s\t%s\n",dt(t),regnames[zreg]);
+      save_result(f,p);
+      continue;
+    }
+    if(c==TEST){
+      emit(f,"\ttst.%s\t",dt(t));
+      if(multiple_ccs)
+	emit(f,"%s,",regnames[zreg]);
+      emit_obj(f,&p->q1,t);
+      emit(f,"\n");
+      if(multiple_ccs)
+	save_result(f,p);
+      continue;
+    }
+    if(c==COMPARE){
+      emit(f,"\tcmp.%s\t",dt(t));
+      if(multiple_ccs)
+	emit(f,"%s,",regnames[zreg]);
+      emit_obj(f,&p->q1,t);
+      emit(f,",");
+      emit_obj(f,&p->q2,t);
+      emit(f,"\n");
+      if(multiple_ccs)
+	save_result(f,p);
+      continue;
+    }
+    if((c>=OR&&c<=AND)||(c>=LSHIFT&&c<=MOD)){
+      if(!THREE_ADDR)
+	load_reg(f,zreg,&p->q1,t);
+      if(c>=OR&&c<=AND)
+	emit(f,"\t%s.%s\t%s,",logicals[c-OR],dt(t),regnames[zreg]);
+      else
+	emit(f,"\t%s.%s\t%s,",arithmetics[c-LSHIFT],dt(t),regnames[zreg]);
+      if(THREE_ADDR){
+	emit_obj(f,&p->q1,t);
+	emit(f,",");
+      }
+      emit_obj(f,&p->q2,t);
+      emit(f,"\n");
+      save_result(f,p);
+      continue;
+    }
+    pric2(stdout,p);
+    ierror(0);
+  }
+  function_bottom(f,v,localsize);
+  if(stack_valid){
+    if(!v->fi) v->fi=new_fi();
+    v->fi->flags|=ALL_STACK;
+    v->fi->stack1=stack;
+  }
+  emit(f,"# stacksize=%lu%s\n",zum2ul(stack),stack_valid?"":"+??");
+}
+
+int shortcut(int code,int typ)
+{
+  return 0;
+}
+
+int reg_parm(struct reg_handle *m, struct Typ *t,int vararg,struct Typ *d)
+{
+  int f;
+  f=t->flags&NQ;
+  if(f<=LONG||f==POINTER){
+    if(m->gregs>=GPR_ARGS)
+      return 0;
+    else
+      return FIRST_GPR+3+m->gregs++;
+  }
+  if(ISFLOAT(f)){
+    if(m->fregs>=FPR_ARGS)
+      return 0;
+    else
+      return FIRST_FPR+2+m->fregs++;
+  }
+  return 0;
+}
+
+int handle_pragma(const char *s)
+{
+}
+void cleanup_cg(FILE *f)
+{
+}
+void cleanup_db(FILE *f)
+{
+  if(f) section=-1;
+}
+
diff --git a/machines/src/machine.dt b/machines/src/machine.dt
new file mode 100755
index 0000000..7ece518
--- /dev/null
+++ b/machines/src/machine.dt
@@ -0,0 +1,14 @@
+S8BS
+S8BU
+S16BSBE S16BSLE
+S16BUBE S16BULE
+S32BSBE S32BSLE
+S32BUBE S32BULE
+S32BSBE S32BSLE
+S32BUBE S32BULE
+S64BSBE S64BSLE
+S64BUBE S64BULE
+S32BIEEEBE
+S64BIEEEBE
+S64BIEEEBE
+S32BUBE S32BULE
diff --git a/machines/src/machine.h b/machines/src/machine.h
new file mode 100755
index 0000000..98a944f
--- /dev/null
+++ b/machines/src/machine.h
@@ -0,0 +1,125 @@
+/*  C src backend for vbcc
+*/
+
+/* buil-time configurable options: */
+#define SCHAR_REGS 64
+#define UCHAR_REGS 64
+#define SSHORT_REGS 64
+#define USHORT_REGS 64
+#define SINT_REGS 64
+#define UINT_REGS 64
+#define SLONG_REGS 64
+#define ULONG_REGS 64
+#define SLLONG_REGS 64
+#define ULLONG_REGS 64
+#define FLOAT_REGS 64
+#define DOUBLE_REGS 64
+#define LDOUBLE_REGS 64
+#define POINTER_REGS 64
+
+#include "dt.h"
+
+/* internally used by the backend */
+#define FIRST_SCHAR 1
+#define LAST_SCHAR (FIRST_SCHAR+SCHAR_REGS)
+#define FIRST_UCHAR (LAST_SCHAR+1)
+#define LAST_UCHAR (FIRST_UCHAR+UCHAR_REGS)
+
+#define FIRST_SSHORT (LAST_UCHAR+1)
+#define LAST_SSHORT (FIRST_SSHORT+SSHORT_REGS)
+#define FIRST_USHORT (LAST_SSHORT+1)
+#define LAST_USHORT (FIRST_USHORT+USHORT_REGS)
+
+#define FIRST_SINT (LAST_USHORT+1)
+#define LAST_SINT (FIRST_SINT+SINT_REGS)
+#define FIRST_UINT (LAST_SINT+1)
+#define LAST_UINT (FIRST_UINT+UINT_REGS)
+
+#define FIRST_SLONG (LAST_UINT+1)
+#define LAST_SLONG (FIRST_SLONG+SLONG_REGS)
+#define FIRST_ULONG (LAST_SLONG+1)
+#define LAST_ULONG (FIRST_ULONG+ULONG_REGS)
+
+#define FIRST_SLLONG (LAST_ULONG+1)
+#define LAST_SLLONG (FIRST_SLLONG+SLLONG_REGS)
+#define FIRST_ULLONG (LAST_SLLONG+1)
+#define LAST_ULLONG (FIRST_ULLONG+ULLONG_REGS)
+
+#define FIRST_FLOAT (LAST_ULLONG+1)
+#define LAST_FLOAT (FIRST_FLOAT+FLOAT_REGS)
+
+#define FIRST_DOUBLE (LAST_FLOAT+1)
+#define LAST_DOUBLE (DOUBLE_FLOAT+DOUBLE_REGS)
+
+#define FIRST_LDOUBLE (LAST_DOUBLE+1)
+#define LAST_LDOUBLE (LDOUBLE_FLOAT+LDOUBLE_REGS)
+
+#define FIRST_POINTER (LAST_LDOUBLE+1)
+#define LAST_POINTER (POINTER_FLOAT+POINTER_REGS)
+
+
+/*  This struct can be used to implement machine-specific           */
+/*  addressing-modes.                                               */
+/*  Currently possible are (const,gpr) and (gpr,gpr)                */
+struct AddressingMode{
+  int dummy;
+};
+
+/*  The number of registers of the target machine.                  */
+#define MAXR LAST_POINTER
+
+/*  Number of commandline-options the code-generator accepts.       */
+#define MAXGF 20
+
+/*  If this is set to zero vbcc will not generate ICs where the     */
+/*  target operand is the same as the 2nd source operand.           */
+/*  This can sometimes simplify the code-generator, but usually     */
+/*  the code is better if the code-generator allows it.             */
+#define USEQ2ASZ 1
+
+/*  This specifies the smallest integer type that can be added to a */
+/*  pointer.                                                        */
+#define MINADDI2P CHAR
+
+/*  If the bytes of an integer are ordered most significant byte    */
+/*  byte first and then decreasing set BIGENDIAN to 1.              */
+#define BIGENDIAN 1
+
+/*  If the bytes of an integer are ordered lest significant byte    */
+/*  byte first and then increasing set LITTLEENDIAN to 1.           */
+#define LITTLEENDIAN 0
+
+/*  Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive.    */
+
+/*  If switch-statements should be generated as a sequence of       */
+/*  SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1.      */
+/*  This can yield better code on some machines.                    */
+#define SWITCHSUBS 0
+
+/*  In optimizing compilation certain library memcpy/strcpy-calls   */
+/*  with length known at compile-time will be inlined using an      */
+/*  ASSIGN-IC if the size is less or equal to INLINEMEMCPY.         */
+/*  The type used for the ASSIGN-IC will be UNSIGNED|CHAR.          */
+#define INLINEMEMCPY 1024
+
+/*  Parameters are sometimes passed in registers without __reg.     */
+#define HAVE_REGPARMS 0
+
+/*  Parameters on the stack should be pushed in order rather than   */
+/*  in reverse order.                                               */
+#define ORDERED_PUSH FIXED_SP
+
+/* we only need the standard data types (no bit-types, different pointers
+   etc.) */
+#undef HAVE_EXT_TYPES
+#undef HAVE_TGT_PRINTVAL
+
+/* we do not need extra elements in the IC */
+#undef HAVE_EXT_IC
+
+/* we do not use unsigned int as size_t (but unsigned long, the default) */
+#undef HAVE_INT_SIZET
+
+/* we do not need register-pairs */
+#undef HAVE_REGPAIRS
+
diff --git a/machines/vidcore/machine.c b/machines/vidcore/machine.c
new file mode 100644
index 0000000..420a4d0
--- /dev/null
+++ b/machines/vidcore/machine.c
@@ -0,0 +1,1774 @@
+/*  Backend for VideoCore IV
+    (c) in 2013 by Volker Barthelmann
+*/
+
+/* TODO:
+   - extended registers
+   - floating point
+   - long long
+   - memcpy
+   - addcmp
+   - bcc reg
+   - cond. ins
+   - vector
+   - non-pc addressing
+*/
+
+#include "supp.h"
+
+static char FILE_[]=__FILE__;
+
+/*  Public data that MUST be there.                             */
+
+/* Name and copyright. */
+char cg_copyright[]="vbcc VideoCore IV code-generator V0.1 (c) in 2013 by Volker Barthelmann";
+
+/* the flag-name, do not use names beginning with l, L, I, D or U, because
+   they collide with the frontend */
+char *g_flags_name[MAXGF]={"use-commons","use-framepointer",
+			   "short-double","one-section",
+			   "no-delayed-popping"};
+
+int g_flags[MAXGF]={0,0,
+		    0};
+
+/* the results of parsing the command-line-flags will be stored here */
+union ppi g_flags_val[MAXGF];
+
+/*  Alignment-requirements for all types in bytes.              */
+zmax align[MAX_TYPE+1];
+
+/*  Alignment that is sufficient for every object.              */
+zmax maxalign;
+
+/*  CHAR_BIT for the target machine.                            */
+zmax char_bit;
+
+/*  sizes of the basic 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. will be initialized in init_cg(),
+    register number 0 is invalid, valid registers start at 1 */
+char *regnames[MAXR+1];
+
+/*  The Size of each register in bytes.                         */
+zmax regsize[MAXR+1];
+
+/*  a 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];
+
+/* specifies the priority for the register-allocator, if the same
+   estimated cost-saving can be obtained by several registers, the
+   one with the highest priority will be used */
+int reg_prio[MAXR+1];
+
+/* an empty reg-handle representing initial state */
+struct reg_handle empty_reg_handle={0};
+
+/* Names of target-specific variable attributes.                */
+char *g_attr_name[]={"__interrupt",0};
+
+
+/****************************************/
+/*  Private data and functions.         */
+/****************************************/
+
+/* addressing modes */
+#define AM_IMM_IND 1
+#define AM_GPR_IND 2
+#define AM_POSTINC 3
+#define AM_PREDEC  4
+
+#define USE_COMMONS (g_flags[0]&USEDFLAG)
+#define USE_FP      (g_flags[1]&USEDFLAG)
+#define SHORT_DOUBLE (g_flags[2]&USEDFLAG)
+#define ONESEC      (g_flags[3]&USEDFLAG)
+#define NODELAYEDPOP (g_flags[4]&USEDFLAG)
+
+
+/* alignment of basic data-types, used to initialize align[] */
+static long malign[MAX_TYPE+1]=  {1,1,2,4,4,4,4,8,8,1,4,1,1,1,4,1};
+/* sizes of basic data-types, used to initialize sizetab[] */
+static long msizetab[MAX_TYPE+1]={1,1,2,4,4,8,4,8,8,0,4,0,0,0,4,0};
+
+/* used to initialize regtyp[] */
+static struct Typ ltyp={LONG},ldbl={DOUBLE},lchar={CHAR};
+
+/* macros defined by the backend */
+static char *marray[]={"__section(x)=__vattr(\"section(\"#x\")\")",
+		       "__VIDEOCORE__",
+		       0, /* __SHORT_DOUBLE__ */
+		       0};
+
+/* special registers */
+enum{
+  r0=1,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14,r15,
+  r16,r17,r18,r19,r20,r21,r22,r23,r24,r25,r26,r27,r28,r29,r30,r31,
+  r0r1,r2r3,r4r5,r6r7,r8r9,r10r11,r12r13,r14r15,
+  r16r17,r18r19,r20r21,r22r23,r24r25,r26r27,r28r29,r30r31
+};
+
+static int sd=r24;
+static int sp=r25;
+static int lr=r26;
+static int sr=r30;
+static int pc=r31;
+static int t1=r15;
+static int t2=r14;
+
+static int last_saved;
+
+#define dt(t) (((t)&UNSIGNED)?udt[(t)&NQ]:sdt[(t)&NQ])
+#define sdt(t) (udt[(t)&NQ])
+static char *sdt[MAX_TYPE+1]={"??","b","hs","","","ll","","d","ld","v",""};
+static char *udt[MAX_TYPE+1]={"??","b","h","","","ull","","d","ld","v",""};
+
+static char *dct[]={"","byte","2byte","4byte","4byte","4byte","4byte","4byte","4byte"};
+
+static int no_suffix;
+
+/* sections */
+#define DATA 0
+#define BSS 1
+#define CODE 2
+#define RODATA 3
+#define SPECIAL 4
+
+static long stack;
+static int stack_valid;
+static int section=-1,newobj;
+static char *codename="\t.text\n",
+  *dataname="\t.data\n",
+  *bssname="",
+  *rodataname="\t.section\t.rodata\n";
+
+/* conditional execution */
+static char *cc;
+
+/* return-instruction */
+static char *ret;
+
+/* label at the end of the function (if any) */
+static int exit_label;
+
+/* assembly-prefixes for labels and external identifiers */
+static char *labprefix="l",*idprefix="_";
+
+#if 0
+/* variables to calculate the size and partitioning of the stack-frame
+   in the case of FIXED_SP */
+static long frameoffset,pushed,maxpushed,framesize;
+#else
+/* variables to keep track of the current stack-offset in the case of
+   a moving stack-pointer */
+static long notpopped,dontpop,stackoffset,maxpushed;
+#endif
+
+static long localsize,rsavesize,argsize;
+
+static void emit_obj(FILE *f,struct obj *p,int t);
+
+/* calculate the actual current offset of an object relativ to the
+   stack-pointer; we use a layout like this:
+   ------------------------------------------------
+   | arguments to this function                   |
+   ------------------------------------------------
+   | return-address [size=4]                      |
+   ------------------------------------------------
+   | caller-save registers [size=rsavesize]       |
+   ------------------------------------------------
+   | local variables [size=localsize]             |
+   ------------------------------------------------
+   | arguments to called functions [size=argsize] |
+   ------------------------------------------------
+   All sizes will be aligned as necessary.
+   In the case of FIXED_SP, the stack-pointer will be adjusted at
+   function-entry to leave enough space for the arguments and have it
+   aligned to 16 bytes. Therefore, when calling a function, the
+   stack-pointer is always aligned to 16 bytes.
+   For a moving stack-pointer, the stack-pointer will usually point
+   to the bottom of the area for local variables, but will move while
+   arguments are put on the stack.
+
+   This is just an example layout. Other layouts are also possible.
+*/
+
+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 long real_offset(struct obj *o)
+{
+  long off=zm2l(o->v->offset);
+  if(off<0){
+    /* function parameter */
+    off=localsize+rsavesize-off-zm2l(maxalign);
+  }
+
+  off-=stackoffset;
+
+  off+=zm2l(o->val.vmax);
+  return off;
+}
+
+/*  Initializes an addressing-mode structure and returns a pointer to
+    that object. Will not survive a second call! */
+static struct obj *cam(int flags,int base,long offset)
+{
+  static struct obj obj;
+  static struct AddressingMode am;
+  obj.am=&am;
+  am.flags=flags;
+  am.base=base;
+  am.offset=offset;
+  return &obj;
+}
+
+/* changes to a special section, used for __section() */
+static int special_section(FILE *f,struct Var *v)
+{
+  char *sec;
+  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 unsigned long pushmask;
+
+static int ic_uses_reg(struct IC *p,int r,int onlyuses)
+{
+  if(reg_pair(r,&rp)){
+    return ic_uses_reg(p,rp.r1,onlyuses)||ic_uses_reg(p,rp.r2,onlyuses);
+  }
+  /*FIXME: handle regpairs */
+  if((p->q1.flags&REG)&&p->q1.reg==r) return 1;
+  if((p->q2.flags&REG)&&p->q2.reg==r) return 1;
+  if(onlyuses){
+    if((p->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p->z.reg==r) return 1;
+  }else{
+    if((p->z.flags&REG)&&p->z.reg==r) return 1;
+  }
+  if(p->q1.am){
+    if(p->q1.am->base==r) return 1;
+    if(p->q1.am->flags==AM_GPR_IND&&p->q1.am->offset==r) return 1;
+  }
+  if(p->q2.am){
+    if(p->q2.am->base==r) return 1;
+    if(p->q2.am->flags==AM_GPR_IND&&p->q2.am->offset==r) return 1;
+  }
+  if(p->z.am){
+    if(p->z.am->base==r) return 1;
+    if(p->z.am->flags==AM_GPR_IND&&p->z.am->offset==r) return 1;
+  }
+  return 0;
+}
+
+static int reg_is_scratched(struct IC *p,int r)
+{
+  for(p=p->next;p;p=p->next){
+    int c=p->code;
+    if(c>=LABEL&&c<=BRA)
+      return 0;
+    if(c==FREEREG&&p->q1.reg==r)
+      return 1;
+    if(ic_uses_reg(p,r,1))
+      return 0;
+    if((p->q1.flags&(REG|DREFOBJ))==REG&&p->z.reg==r)
+      return 1;
+  }    
+  return 0;
+}
+
+static int get_reg(FILE *f,struct IC *p)
+{
+  int r;
+  for(r=r0;r<=r31;r++){
+    if(!regs[r]&&regused[r]&&!ic_uses_reg(p,r,0)){
+      regs[r]=1;
+      return r;
+    }
+  }
+  for(r=r0;r<=r31;r++){
+    if(!regs[r]&&!ic_uses_reg(p,r,0)){
+      regs[r]=1;
+      return r;
+    }
+  }
+  for(r=r0;r<=r31;r++){
+    if(!ic_uses_reg(p,r,0))
+      break;
+  }
+  argsize+=4;
+  emit(f,"\tst\t%s,--(%s)\n",regnames[r],regnames[sp]);
+  push(4);
+  pushmask|=(1<<(r-1));
+  regs[r]=1;
+  return r;
+}
+
+static void free_reg(FILE *f,int r)
+{
+  if(pushmask&(1<<(r-1))){
+    emit(f,"\tld\t%s,(%s)++\n",regnames[r],regnames[sp]);
+    pop(4);
+    argsize-=4;
+  }else
+    regs[r]=0;
+  pushmask&=~(1<<(r-1));
+}
+
+/* generate code to load the address of a variable into register r */
+static void load_address(FILE *f,int r,struct obj *o,int type)
+/*  Generates code to load the address of a variable into register r.   */
+{
+  if(!(o->flags&VAR)) ierror(0);
+  if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER){
+    long off=real_offset(o);
+    emit(f,"\tadd%s\t%s,%s,%ld\n",cc,regnames[r],regnames[sp],off);
+  }else{
+    emit(f,"\tlea%s\t%s,",cc,regnames[r]);
+    emit_obj(f,o,type);
+    emit(f,"\n");
+  }
+}
+/* Generates code to load a memory object into register r. tmp is a
+   general purpose register which may be used. tmp can be r. */
+static void load_reg(FILE *f,int r,struct obj *o,int type)
+{
+  type&=NU;
+  if(reg_pair(r,&rp)) ierror(0);
+  if(o->flags&VARADR){
+    load_address(f,r,o,POINTER);
+  }else if(o->flags&KONST){
+    emit(f,"\tmov%s\t%s,",cc,regnames[r]);
+    emit_obj(f,o,type);
+    emit(f,"\n");
+  }else{
+    if((o->flags&(REG|DREFOBJ))==REG){
+      if(o->reg!=r)
+	emit(f,"\tmov%s\t%s,%s\n",cc,regnames[r],regnames[o->reg]);
+    }else{
+      if(SHORT_DOUBLE&&ISFLOAT(type)) type=FLOAT;
+      emit(f,"\tld%s%s\t%s,",dt(type),cc,regnames[r]);
+      emit_obj(f,o,type);
+      emit(f,"\n");
+    }
+  }
+}
+
+/*  Generates code to store register r into memory object o. */
+static void store_reg(FILE *f,int r,struct obj *o,int type)
+{
+  if(reg_pair(r,&rp)) ierror(0);
+  type&=NQ;
+  if(SHORT_DOUBLE&&ISFLOAT(type)) type=FLOAT;
+  emit(f,"\tst%s%s\t%s,",sdt(type),cc,regnames[r]);
+  emit_obj(f,o,type);
+  emit(f,"\n");
+}
+
+/*  Yields log2(x)+1 or 0. */
+static long pof2(zumax x)
+{
+  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 struct IC *preload(FILE *,struct IC *);
+
+static void function_top(FILE *,struct Var *,long);
+static void function_bottom(FILE *f,struct Var *,long);
+
+#define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
+#define isconst(x) ((p->x.flags&(KONST|DREFOBJ))==KONST)
+
+static int q1reg,q2reg,zreg;
+
+static char *ccs[]={"eq","ne","lt","ge","le","gt",""};
+static char *ccu[]={"eq","ne","cs","cc","ls","hi",""};
+static char *logicals[]={"or","eor","and"};
+static char *arithmetics[]={"lsl","asr","add","sub","mul","divs","mod"};
+static char *uarithmetics[]={"lsl","lsr","add","sub","mul","divu","mod"};
+static char *farithmetics[]={"--","--","fadd","fsub","fmul","fdiv","--"};
+
+
+/* Does some pre-processing like fetching operands from memory to
+   registers etc. */
+static struct IC *preload(FILE *f,struct IC *p)
+{
+  int r,load;
+
+  if(isreg(q1))
+    q1reg=p->q1.reg;
+  else
+    q1reg=0;
+
+  if(isreg(q2))
+    q2reg=p->q2.reg;
+  else
+    q2reg=0;
+
+  if(isreg(z)){
+    zreg=p->z.reg;
+  }else{
+    zreg=t1;
+  }
+  
+  if((p->q1.flags&(DREFOBJ|REG))==DREFOBJ&&!p->q1.am){
+    p->q1.flags&=~DREFOBJ;
+    load_reg(f,t1,&p->q1,POINTER);
+    p->q1.reg=t1;
+    p->q1.flags|=(REG|DREFOBJ);
+  }
+  if(p->q1.flags&&!isreg(q1)&&p->code!=ASSIGN&&p->code!=PUSH&&p->code!=SETRETURN/*&&!(p->q1.flags&KONST)*/){
+    q1reg=zreg;
+    load_reg(f,q1reg,&p->q1,q1typ(p));
+    p->q1.reg=q1reg;
+    p->q1.flags=REG;
+  }
+
+  if((p->q2.flags&(DREFOBJ|REG))==DREFOBJ&&!p->q2.am){
+    p->q2.flags&=~DREFOBJ;
+    load_reg(f,t2,&p->q2,POINTER);
+    p->q2.reg=t2;
+    p->q2.flags|=(REG|DREFOBJ);
+  }
+
+  if(p->q2.flags){
+    load=1;
+    if(isreg(q2)) load=0;
+    if((p->q2.flags&KONST)&&!ISFLOAT(p->typf)&&(p->code==ADD||p->code==SUB||p->code==ADDI2P||p->code==COMPARE||p->code==SUBIFP||p->code==SUBPFP))
+      load=0;
+    if(p->code>=OR&&p->code<=MOD&&(p->q2.flags&KONST)&&!ISFLOAT(p->typf)){
+      unsigned long v;
+      eval_const(&p->q2.val,q2typ(p));
+      v=zum2ul(vumax);
+      if(v<=31) load=0;
+    }
+    if(load){
+      q2reg=t2;
+      load_reg(f,q2reg,&p->q2,q2typ(p));
+      p->q2.reg=q2reg;
+      p->q2.flags=REG;
+    }
+  }
+  return p;
+}
+
+/* save the result (in zreg) into p->z */
+void save_result(FILE *f,struct IC *p)
+{
+  if((p->z.flags&(REG|DREFOBJ))==DREFOBJ&&!p->z.am){
+    p->z.flags&=~DREFOBJ;
+    load_reg(f,t2,&p->z,POINTER);
+    p->z.reg=t2;
+    p->z.flags|=(REG|DREFOBJ);
+  }
+  if(isreg(z)){
+    if(p->z.reg!=zreg)
+      emit(f,"\tmov%s\t%s,%s\n",cc,regnames[p->z.reg],regnames[zreg]);
+  }else{
+    store_reg(f,zreg,&p->z,ztyp(p));
+  }
+}
+
+/* prints an object */
+static void emit_obj(FILE *f,struct obj *p,int t)
+{
+  if((p->flags&DREFOBJ)&&p->am){
+    if(p->am->flags==AM_GPR_IND) emit(f,"(%s,%s)",regnames[p->am->base],regnames[p->am->offset]);
+    if(p->am->flags==AM_IMM_IND) emit(f,"%ld(%s)",p->am->offset,regnames[p->am->base]);
+    if(p->am->flags==AM_POSTINC) emit(f,"(%s)++",regnames[p->am->base]);
+    if(p->am->flags==AM_PREDEC) emit(f,"--(%s)",regnames[p->am->base]);
+    return;
+  }
+  if((p->flags&(KONST|DREFOBJ))==(KONST|DREFOBJ)){
+    emitval(f,&p->val,p->dtyp&NU);
+    return;
+  }
+  if(p->flags&DREFOBJ) emit(f,"(");
+  if(p->flags&REG){
+    emit(f,"%s",regnames[p->reg]);
+  }else if(p->flags&VAR) {
+    if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER)
+      emit(f,"%ld(%s)",real_offset(p),regnames[sp]);
+    else{
+      if(!zmeqto(l2zm(0L),p->val.vmax)){emitval(f,&p->val,LONG);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(!no_suffix)
+	emit(f,"(%s)",regnames[pc]);
+    }
+  }
+  if(p->flags&KONST){
+    if(ISFLOAT(t)){
+      unsigned char *ip;
+      eval_const(&p->val,t);
+      ip=(unsigned char *)&vfloat;
+      emit(f,"0x%02x%02x%02x%02x",ip[0],ip[1],ip[2],ip[3]);
+    }else
+      emitval(f,&p->val,t&NU);
+  }
+  if(p->flags&DREFOBJ) emit(f,")");
+}
+
+/*  Test if there is a sequence of FREEREGs containing FREEREG reg.
+    Used by peephole. */
+static int exists_freereg(struct IC *p,int reg)
+{
+  while(p&&(p->code==FREEREG||p->code==ALLOCREG)){
+    if(p->code==FREEREG&&p->q1.reg==reg) return 1;
+    p=p->next;
+  }
+  return 0;
+}
+
+/* search for possible addressing-modes */
+static void peephole(struct IC *p)
+{
+  int c,c2,r;struct IC *p2;struct AddressingMode *am;
+
+  for(;p;p=p->next){
+    c=p->code;
+    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;
+
+    /* -(ax) */
+    if(c==SUBIFP&&isreg(q1)&&isreg(z)&&p->q1.reg==p->z.reg&&p->q1.reg<=8&&isconst(q2)){
+      zmax sz;
+      int t;
+      r=p->q1.reg;
+      eval_const(&p->q2.val,q2typ(p));
+      sz=zm2l(vmax);
+      if(sz==1||sz==2||sz==4){
+        for(p2=p->next;p2;p2=p2->next){
+          c2=p2->code;
+          if(!p2->q1.am&&(p2->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q1.reg==r&&(!(p2->q2.flags&REG)||p2->q2.reg!=r)&&(!(p2->z.flags&REG)||p2->z.reg!=r)&&(
+c2!=CONVERT||(q1typ(p2)&NQ)<=(ztyp(p2)&NQ))){
+            t=(q1typ(p2)&NQ);
+            if((ISINT(t)||ISPOINTER(t))&&t!=LLONG&&zmeqto(sizetab[q1typ(p2)&NQ],l2zm(sz))){
+              p2->q1.am=am=mymalloc(sizeof(*am));
+              p2->q1.val.vmax=l2zm(0L);
+              am->base=r;
+              am->flags=AM_PREDEC;
+              p->code=NOP;
+              p->q1.flags=p->q2.flags=p->z.flags=0;
+              break;
+            }
+          }
+         if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r&&(!(p2->q1.flags&REG)||p2->q1.reg!=r)&&(!(p2->z.flags&REG)||p2->z.reg!=r)){
+            t=(q2typ(p2)&NQ);
+            if((ISINT(t)||ISPOINTER(t))&&t!=LLONG&&zmeqto(sizetab[q2typ(p2)&NQ],l2zm(sz))){
+              p2->q2.am=am=mymalloc(sizeof(*am));
+              p2->q2.val.vmax=l2zm(0L);
+              am->base=r;
+              am->flags=AM_PREDEC;
+              p->code=NOP;
+              p->q1.flags=p->q2.flags=p->z.flags=0;
+              break;
+            }
+          }
+          if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r&&(!(p2->q2.flags&REG)||p2->q2.reg!=r)&&(!(p2->q1.flags&REG)||p2->q1.reg!=r)){
+            t=(ztyp(p2)&NQ);
+            if((ISINT(t)||ISPOINTER(t))&&t!=LLONG&&zmeqto(sizetab[ztyp(p2)&NQ],l2zm(sz))){
+              p2->z.am=am=mymalloc(sizeof(*am));
+              p2->z.val.vmax=l2zm(0L);
+              am->base=r;
+              am->flags=AM_PREDEC;
+              p->code=NOP;
+              p->q1.flags=p->q2.flags=p->z.flags=0;
+              break;
+            }
+          }
+          if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
+          if((p2->q1.flags&REG)&&p2->q1.reg==r) break;
+          if((p2->q2.flags&REG)&&p2->q2.reg==r) break;
+          if((p2->z.flags&REG)&&p2->z.reg==r) break;
+        }
+      }
+    }
+
+    /* (ax)+ in q1 */
+    if(!p->q1.am&&(p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&(c!=CONVERT||(q1typ(p)&NQ)<=(ztyp(p)&NQ))){
+      int t=(q1typ(p)&NQ);
+      long sz=zm2l(sizetab[t]);
+      r=p->q1.reg;
+      if((sz==1||sz==2||sz==4)&&(ISINT(t)||ISPOINTER(t)||ISFLOAT(t))&&(!(p->q2.flags&REG)||p->q2.reg!=r)&&(!(p->z.flags&REG)||p->z.reg!=r)){
+        for(p2=p->next;p2;p2=p2->next){
+          c2=p2->code;
+          if(c2==ADDI2P&&(p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r&&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg==r&&(p2->q2.flags&(KONST|DREFOBJ))==KONST){
+            eval_const(&p2->q2.val,q2typ(p2));
+            if(zmeqto(vmax,l2zm(sz))){
+              p->q1.am=am=mymalloc(sizeof(*am));
+              p->q1.val.vmax=l2zm(0L);
+	      am->flags=AM_POSTINC;
+              am->base=r;
+              am->offset=0;
+              p2->code=NOP;
+              p2->q1.flags=p2->q2.flags=p2->z.flags=0;
+              break;
+            }
+          }
+          if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
+          if((p2->q1.flags&REG)&&p2->q1.reg==r) break;
+          if((p2->q2.flags&REG)&&p2->q2.reg==r) break;
+          if((p2->z.flags&REG)&&p2->z.reg==r) break;
+        }
+      }
+    }
+    /* (ax)+ in q2 */
+    if(!p->q2.am&&(p->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&(c!=CONVERT||(q2typ(p)&NQ)<=(ztyp(p)&NQ))){
+      int t=(q2typ(p)&NQ);
+      long sz=zm2l(sizetab[t]);
+      r=p->q2.reg;
+      if((sz==1||sz==2||sz==4)&&(ISINT(t)||ISPOINTER(t)||ISFLOAT(t))&&(!(p->q1.flags&REG)||p->q1.reg!=r)&&(!(p->z.flags&REG)||p->z.reg!=r)){
+        for(p2=p->next;p2;p2=p2->next){
+          c2=p2->code;
+          if(c2==ADDI2P&&(p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r&&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg==r&&(p2->q2.flags&(KONST|DREFOBJ))==KONST){
+            eval_const(&p2->q2.val,q2typ(p2));
+            if(zmeqto(vmax,l2zm(sz))){
+              p->q2.am=am=mymalloc(sizeof(*am));
+              p->q2.val.vmax=l2zm(0L);
+	      am->flags=AM_POSTINC;
+              am->base=r;
+              am->offset=0;
+              p2->code=NOP;
+              p2->q1.flags=p2->q2.flags=p2->z.flags=0;
+              break;
+            }
+          }
+          if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
+          if((p2->q1.flags&REG)&&p2->q1.reg==r) break;
+          if((p2->q2.flags&REG)&&p2->q2.reg==r) break;
+          if((p2->z.flags&REG)&&p2->z.reg==r) break;
+        }
+      }
+    }
+    /* (ax)+ in z */
+    if(!p->z.am&&(p->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p->z.reg<=8&&(c!=CONVERT||(q2typ(p)&NQ)<=(ztyp(p)&NQ))){
+      int t=(ztyp(p)&NQ);
+      long sz=zm2l(sizetab[t]);
+      r=p->z.reg;
+      if((sz==1||sz==2||sz==4)&&(ISINT(t)||ISPOINTER(t)||ISFLOAT(t))&&(!(p->q1.flags&REG)||p->q1.reg!=r)&&(!(p->q2.flags&REG)||p->q2.reg!=r)){
+        for(p2=p->next;p2;p2=p2->next){
+          c2=p2->code;
+          if(c2==ADDI2P&&(p2->q1.flags&(REG|DREFOBJ))==REG&&p2->q1.reg==r&&(p2->z.flags&(REG|DREFOBJ))==REG&&p2->z.reg==r&&(p2->q2.flags&(KONST|DREFOBJ))==KONST){
+            eval_const(&p2->q2.val,q2typ(p2));
+            if(zmeqto(vmax,l2zm(sz))){
+              p->z.am=am=mymalloc(sizeof(*am));
+              p->z.val.vmax=l2zm(0L);
+	      am->flags=AM_POSTINC;
+              am->base=r;
+              am->offset=0;
+              p2->code=NOP;
+              p2->q1.flags=p2->q2.flags=p2->z.flags=0;
+              break;
+            }
+          }
+          if(c2==CALL||c2==LABEL||(c2>=BEQ&&c2<=BRA)) break;
+          if((p2->q1.flags&REG)&&p2->q1.reg==r) break;
+          if((p2->q2.flags&REG)&&p2->q2.reg==r) break;
+          if((p2->z.flags&REG)&&p2->z.reg==r) break;
+        }
+      }
+    }
+    /* Try const(reg) */
+    if((c==ADDI2P/*||c==SUBIFP*/)&&isreg(z)&&(p->q2.flags&(KONST|DREFOBJ))==KONST){
+      int base;zmax of;struct obj *o;
+      eval_const(&p->q2.val,p->typf);
+      if(c==SUBIFP) of=zmsub(l2zm(0L),vmax); else of=vmax;
+      if(1/*zmleq(l2zm(-32768L),vmax)&&zmleq(vmax,l2zm(32767L))*/){
+	r=p->z.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((c2==ASSIGN||c2==PUSH)&&(!ISSCALAR(p2->typf)||!zmeqto(p2->q2.val.vmax,sizetab[p2->typf&NQ]))){
+	    if((p->q1.flags&REG)&&p->q1.reg==base)
+	      break;
+	    if((p->z.flags&REG)&&p->z.reg==base)
+	      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) break;
+	      o=&p2->q1;
+	    }
+	    if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
+	      if(o) break;
+	      o=&p2->q2;
+	    }
+	    if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
+	      if(o) 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=AM_IMM_IND;
+		am->base=base;
+		am->offset=zm2l(of);
+		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;
+	  }
+        }
+      }
+    }
+    /* Try reg,reg */
+    if(c==ADDI2P&&isreg(q2)&&isreg(z)&&(isreg(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||(q1typ(p2)&NQ)!=CHAR) break;
+            o=&p2->q1;
+          }
+          if(!p2->q2.am&&(p2->q2.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->q2.reg==r){
+            if(o||(q2typ(p2)&NQ)!=CHAR) break;
+            o=&p2->q2;
+          }
+          if(!p2->z.am&&(p2->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&p2->z.reg==r){
+            if(o||(ztyp(p2)&NQ)!=CHAR) 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=AM_GPR_IND;
+              am->base=base;
+              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;
+        }
+      }
+    }
+  }
+}
+
+/* generates the function entry code */
+static void function_top(FILE *f,struct Var *v,long offset)
+{
+  int i;
+  rsavesize=0;
+  if(!special_section(f,v)&&section!=CODE){emit(f,codename);if(f) section=CODE;} 
+  emit(f,"\t.align\t1\n");
+  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));
+  last_saved=0;
+  for(i=r6;i<t2;i++){
+    if(regused[i])
+      last_saved=i;
+  }
+  if(last_saved){
+    emit(f,"\tpush\t%s-%s",regnames[r6],regnames[last_saved]);
+    rsavesize=(last_saved-r6+1)*4;
+    if(function_calls){
+      emit(f,",lr");
+      rsavesize+=4;
+    }
+    emit(f,"\n");
+  }else if(function_calls){
+    emit(f,"\tpush\t%s-%s,lr\n",regnames[r6],regnames[r6]);
+    rsavesize+=8;
+  }
+  if(offset){
+    emit(f,"\tsub\t%s,%ld\n",regnames[sp],offset);
+  }
+}
+/* generates the function exit code */
+static void function_bottom(FILE *f,struct Var *v,long offset)
+{
+  if(offset){
+    emit(f,"\tadd\t%s,%ld\n",regnames[sp],offset);
+  }
+  if(last_saved){
+    emit(f,"\tpop\t%s-%s",regnames[r6],regnames[last_saved]);
+    if(function_calls){
+      emit(f,",pc");
+    }
+    emit(f,"\n");
+  }else if(function_calls){
+    emit(f,"\tpop\t%s-%s,pc\n",regnames[r6],regnames[r6]);
+  }  
+  if(!function_calls)
+    emit(f,ret);
+}
+
+/****************************************/
+/*  End of private data and functions.  */
+/****************************************/
+
+/*  Does necessary initializations for the code-generator. Gets called  */
+/*  once at the beginning and should return 0 in case of problems.      */
+int init_cg(void)
+{
+  int i;
+  /*  Initialize some values which cannot be statically initialized   */
+  /*  because they are stored in the target's arithmetic.             */
+  maxalign=l2zm(4L);
+  char_bit=l2zm(8L);
+  stackalign=l2zm(4);
+
+  for(i=0;i<=MAX_TYPE;i++){
+    sizetab[i]=l2zm(msizetab[i]);
+    align[i]=l2zm(malign[i]);
+  }
+
+  if(SHORT_DOUBLE){
+    sizetab[DOUBLE]=sizetab[FLOAT];
+    align[DOUBLE]=align[FLOAT];
+    sizetab[LDOUBLE]=sizetab[FLOAT];
+    align[LDOUBLE]=align[FLOAT];
+  }
+
+  regnames[0]="noreg";
+  for(i=1;i<=32;i++){
+    regnames[i]=mymalloc(10);
+    sprintf(regnames[i],"r%d",i-1);
+    regsize[i]=l2zm(4L);
+    regtype[i]=&ltyp;
+  }
+  for(i=33;i<=48;i++){
+    regnames[i]=mymalloc(10);
+    sprintf(regnames[i],"r%d/r%d",i-33,i-32);
+    regsize[i]=l2zm(8L);
+    regtype[i]=&ldbl;
+  }
+
+  /*  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.          */
+  t_min[CHAR]=l2zm(-128L);
+  t_min[SHORT]=l2zm(-32768L);
+  t_min[INT]=zmsub(l2zm(-2147483647L),l2zm(1L));
+  t_min[LONG]=t_min(INT);
+  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]=ul2zum(2147483647UL);
+  t_max[LONG]=t_max(INT);
+  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]=ul2zum(4294967295UL);
+  tu_max[LONG]=t_max(UNSIGNED|INT);
+  tu_max[LLONG]=zumkompl(ul2zum(0UL));
+  tu_max[MAXINT]=t_max(UNSIGNED|LLONG);
+  
+  /*  Reserve a few registers for use by the code-generator.      */
+  /*  This is not optimal but simple.                             */
+  regsa[t1]=regsa[t2]=1;
+  regsa[pc]=regsa[lr]=regsa[sp]=regsa[sr]=1;
+  regscratch[t1]=regscratch[t2]=0;
+  regscratch[pc]=regscratch[lr]=regscratch[sp]=regscratch[sr]=1;
+
+  for(i=r16;i<=r31;i++)
+    regscratch[i]=regsa[i]=1;
+  
+  for(i=1;i<=6;i++)
+    regscratch[i]=1;
+
+  if(ONESEC){
+    bssname=codename;
+    dataname=codename;
+    rodataname=codename;
+  }
+
+  if(SHORT_DOUBLE) marray[2]="__SHORT_DOUBLE__=1";
+  target_macros=marray;
+
+
+  declare_builtin("__mulint64",LLONG,LLONG,r0r1,LLONG,r2r3,1,0);
+  declare_builtin("__addint64",LLONG,LLONG,r0r1,LLONG,r2r3,1,0);
+  declare_builtin("__subint64",LLONG,LLONG,r0r1,LLONG,r2r3,1,0);
+  declare_builtin("__andint64",LLONG,LLONG,r0r1,LLONG,r2r3,1,0);
+  declare_builtin("__orint64",LLONG,LLONG,r0r1,LLONG,r2r3,1,0);
+  declare_builtin("__eorint64",LLONG,LLONG,r0r1,LLONG,r2r3,1,0);
+  declare_builtin("__negint64",LLONG,LLONG,r0r1,0,0,1,0);
+  declare_builtin("__lslint64",LLONG,LLONG,r0r1,INT,r2,1,0);
+
+  declare_builtin("__divsint64",LLONG,LLONG,r0r1,LLONG,r2r3,1,0);
+  declare_builtin("__divuint64",UNSIGNED|LLONG,UNSIGNED|LLONG,r0r1,UNSIGNED|LLONG,r2r3,1,0);
+  declare_builtin("__modsint64",LLONG,LLONG,r0r1,LLONG,r2r3,1,0);
+  declare_builtin("__moduint64",UNSIGNED|LLONG,UNSIGNED|LLONG,r0r1,UNSIGNED|LLONG,r2r3,1,0);
+  declare_builtin("__lsrsint64",LLONG,LLONG,r0r1,INT,r2,1,0);
+  declare_builtin("__lsruint64",UNSIGNED|LLONG,UNSIGNED|LLONG,r0r1,INT,r2,1,0);
+  declare_builtin("__cmpsint64",INT,LLONG,r0r1,LLONG,r2r3,1,0);
+  declare_builtin("__cmpuint64",INT,UNSIGNED|LLONG,r0r1,UNSIGNED|LLONG,r2r3,1,0);
+  declare_builtin("__sint64toflt32",FLOAT,LLONG,r0r1,0,0,1,0);
+  declare_builtin("__uint64toflt32",FLOAT,UNSIGNED|LLONG,r0r1,0,0,1,0);
+  declare_builtin("__sint64toflt64",LDOUBLE,LLONG,r0r1,0,0,1,0);
+  declare_builtin("__uint64toflt64",LDOUBLE,UNSIGNED|LLONG,r0r1,0,0,1,0);
+  declare_builtin("__flt32tosint64",LLONG,FLOAT,r0,0,0,1,0);
+  declare_builtin("__flt32touint64",UNSIGNED|LLONG,FLOAT,r0,0,0,1,0);
+  declare_builtin("__flt64tosint64",LLONG,LDOUBLE,r0r1,0,0,1,0);
+  declare_builtin("__flt64touint64",UNSIGNED|LLONG,LDOUBLE,r0r1,0,0,1,0);
+
+  declare_builtin("__flt32toflt64",LDOUBLE,FLOAT,r0,0,0,1,0);
+  declare_builtin("__flt64toflt32",FLOAT,LDOUBLE,r0r1,0,0,1,0);
+
+  declare_builtin("__addflt64",LDOUBLE,LDOUBLE,r0r1,LDOUBLE,r2r3,1,0);
+  declare_builtin("__subflt64",LDOUBLE,LDOUBLE,r0r1,LDOUBLE,r2r3,1,0);
+  declare_builtin("__mulflt64",LDOUBLE,LDOUBLE,r0r1,LDOUBLE,r2r3,1,0);
+  declare_builtin("__divflt64",LDOUBLE,LDOUBLE,r0r1,LDOUBLE,r2r3,1,0);
+  declare_builtin("__negflt64",LDOUBLE,LDOUBLE,r0r1,LDOUBLE,r2r3,1,0);
+  declare_builtin("__cmpflt64",INT,LDOUBLE,r0r1,LDOUBLE,r2r3,1,0);
+
+
+  return 1;
+}
+
+void init_db(FILE *f)
+{
+}
+
+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.        */
+/*  A pointer MUST be returned in a register. The code-generator    */
+/*  has to simulate a pseudo register if necessary.                 */
+{
+  if(SHORT_DOUBLE&&ISFLOAT(t->flags)) return r0;
+  if(ISSTRUCT(t->flags)||ISUNION(t->flags)) 
+    return 0;
+  if(zmleq(szof(t),l2zm(4L))) 
+    return r0;
+  if(zmeqto(szof(t),l2zm(8L))) 
+    return r0r1;
+  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>=r0r1&&r<=r30r31){
+    p->r1=(r-r0r1)*2+r0;
+    p->r2=(r-r0r1)*2+r1;
+    return 1;
+  }
+  return 0;
+}
+
+/* estimate the cost-saving if object o from IC p is placed in
+   register r */
+int cost_savings(struct IC *p,int r,struct obj *o)
+{
+  int c=p->code;
+  if(o->flags&VKONST){
+    return 0;
+  }
+  if(o->flags&DREFOBJ)
+    return 4;
+  if(c==SETRETURN&&r==p->z.reg&&!(o->flags&DREFOBJ)) return 3;
+  if(c==GETRETURN&&r==p->q1.reg&&!(o->flags&DREFOBJ)) return 3;
+  return 2;
+}
+
+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(r==0)
+    return 0;
+  t&=NQ;
+  if(ISINT(t)||ISFLOAT(t)||ISPOINTER(t)){
+    if(zmeqto(sizetab[t],l2zm(8L))){
+      if(r>=r0r1&&r<=r30r31)
+	return 1;
+      else
+	return 0;
+    }
+    if(r>=r0&&r<=r31)
+      return 1;
+    else
+      return 0;
+  }
+  return 0;
+}
+
+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;
+}
+
+int must_convert(int o,int t,int const_expr)
+/*  Returns zero if code for converting np to type t    */
+/*  can be omitted.                                     */
+/*  On the VideCore IV pointers and 32bit               */
+/*  integers have the same representation and can use   */
+/*  the same registers.                                 */
+{
+  int op=o&NQ,tp=t&NQ;
+  if(SHORT_DOUBLE){
+    if(op==DOUBLE||op==LDOUBLE) op=FLOAT;
+    if(tp==DOUBLE||tp==LDOUBLE) tp=FLOAT;
+  }
+  if((op==INT||op==LONG||op==POINTER)&&(tp==INT||tp==LONG||tp==POINTER))
+    return 0;
+  if(op==FLOAT&&tp==FLOAT) return 0;
+  if(op==DOUBLE&&tp==LDOUBLE) return 0;
+  if(op==LDOUBLE&&tp==DOUBLE) 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&&!ONESEC&&section!=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.              */
+{
+  if(zm2l(align)>1) emit(f,"\t.align\t2\n");
+}
+
+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;char *sec;
+  if(v->clist) constflag=is_const(v->vtyp);
+  if(v->storage_class==STATIC){
+    if(ISFUNC(v->vtyp->flags)) return;
+    if(!special_section(f,v)){
+      if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&&section!=DATA){emit(f,dataname);if(f) section=DATA;}
+      if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&&section!=RODATA){emit(f,rodataname);if(f) section=RODATA;}
+      if(!v->clist&&section!=BSS){emit(f,bssname);if(f) section=BSS;}
+    }
+    if(v->clist||ONESEC||section==SPECIAL){
+      gen_align(f,falign(v->vtyp));
+      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){
+    emit(f,"\t.global\t%s%s\n",idprefix,v->identifier);
+    if(v->flags&(DEFINED|TENTATIVE)){
+      if(!special_section(f,v)){
+	if(v->clist&&(!constflag||(g_flags[2]&USEDFLAG))&&section!=DATA){emit(f,dataname);if(f) section=DATA;}
+	if(v->clist&&constflag&&!(g_flags[2]&USEDFLAG)&&section!=RODATA){emit(f,rodataname);if(f) section=RODATA;}
+	if(!v->clist&&section!=BSS){emit(f,bssname);if(f) section=BSS;}
+      }
+      if(v->clist||ONESEC||section==SPECIAL){
+	gen_align(f,falign(v->vtyp));
+        emit(f,"%s%s:\n",idprefix,v->identifier);
+      }else
+        emit(f,"\t.%scomm\t%s%s,",(USE_COMMONS?"":"l"),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.                      */
+{
+  if((t&NQ)==POINTER) t=UNSIGNED|LONG;
+  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;
+      if(SHORT_DOUBLE){
+	eval_const(&p->val,t);
+	ip=(unsigned char *)&vfloat;
+	t=FLOAT;
+      }else
+	ip=(unsigned char *)&p->val.vdouble;
+      emit(f,"0x%02x%02x%02x%02x",ip[0],ip[1],ip[2],ip[3]);
+      if((t&NQ)!=FLOAT){
+        emit(f,",0x%02x%02x%02x%02x",ip[4],ip[5],ip[6],ip[7]);
+      }
+    }else if((t&NQ)==LLONG){
+      zumax tmp;
+      eval_const(&p->val,t);
+      tmp=vumax;
+      vumax=zumand(zumrshift(vumax,ul2zum(32UL)),ul2zum(0xffffffff)); 
+      gval.vulong=zum2zul(vumax);
+      emitval(f,&gval,UNSIGNED|LONG);
+      emit(f,",");
+      vumax=zumand(tmp,ul2zum(0xffffffff)); 
+      gval.vulong=zum2zul(vumax);
+      emitval(f,&gval,UNSIGNED|LONG);
+    }else{
+      emitval(f,&p->val,t&NU);
+    }
+  }else{
+    no_suffix=1;
+    emit_obj(f,&p->tree->o,t&NU);
+    no_suffix=0;
+  }
+  emit(f,"\n");newobj=0;
+}
+
+
+/*  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 *p,struct Var *v,zmax offset)
+/*  The main code-generation.                                           */
+{
+  int c,t,i,lastcomp;
+  int q1wasreg,q2wasreg,zwasreg;
+  struct IC *m;
+  argsize=0;
+  if(DEBUG&1) printf("gen_code()\n");
+  for(c=1;c<=MAXR;c++) regs[c]=regsa[c];
+  stackoffset=notpopped=dontpop=maxpushed=0;
+
+
+  /*FIXME*/
+  ret="\trts\n";
+
+  cc="";
+
+  for(m=p;m;m=m->next){
+    c=m->code;t=m->typf&NU;
+    if(c==ALLOCREG) {regs[m->q1.reg]=1;continue;}
+    if(c==FREEREG) {regs[m->q1.reg]=0;continue;}
+
+    if(notpopped&&!dontpop){
+      int flag=0;
+      if(c==LABEL||c==COMPARE||c==TEST||c==BRA){
+        emit(f,"\tadd\t%s,%ld\n",regnames[sp],notpopped);
+        pop(notpopped);notpopped=0;
+      }
+    }
+
+
+    /* convert MULT/DIV/MOD with powers of two */
+    if((t&NQ)<=LONG&&(m->q2.flags&(KONST|DREFOBJ))==KONST&&(t&NQ)<=LONG&&(c==MULT||((c==DIV||c==MOD)&&(t&UNSIGNED)))){
+      eval_const(&m->q2.val,t);
+      i=pof2(vmax);
+      if(i){
+        if(c==MOD){
+          vmax=zmsub(vmax,l2zm(1L));
+          m->code=AND;
+        }else{
+          vmax=l2zm(i-1);
+          if(c==DIV) m->code=RSHIFT; else m->code=LSHIFT;
+        }
+        c=m->code;
+	gval.vmax=vmax;
+	eval_const(&gval,MAXINT);
+	if(c==AND){
+	  insert_const(&m->q2.val,t);
+	}else{
+	  insert_const(&m->q2.val,INT);
+	  p->typf2=INT;
+	}
+      }
+    }
+    if(c==CALL&&argsize<zm2l(m->q2.val.vmax)) argsize=zm2l(m->q2.val.vmax);
+  }
+  peephole(p);
+
+  for(c=1;c<=MAXR;c++){
+    if(regsa[c]||regused[c]){
+      BSET(regs_modified,c);
+    }
+  }
+
+  localsize=(zm2l(offset)+3)/4*4;
+#if FIXED_SP
+  /*FIXME: adjust localsize to get an aligned stack-frame */
+#endif
+
+  function_top(f,v,localsize);
+
+  for(;p;p=p->next){
+    c=p->code;t=p->typf;
+    if(c==NOP) {p->z.flags=0;continue;}
+    if(c==ALLOCREG) {regs[p->q1.reg]=1;continue;}
+    if(c==FREEREG) {regs[p->q1.reg]=0;continue;}
+
+    if(DEBUG&256){emit(f,"# "); pric2(f,p);}
+    if(DEBUG&512) emit(f,"# stackoffset=%ld, notpopped=%ld, dontpop=%ld\n",stackoffset,notpopped,dontpop);
+    if(notpopped&&!dontpop){
+      int flag=0;
+      if(c==LABEL||c==COMPARE||c==TEST||c==BRA){
+        emit(f,"\tadd\t%s,%ld\n",regnames[sp],notpopped);
+        pop(notpopped);notpopped=0;
+      }
+    }
+
+    if(c==LABEL) {emit(f,"%s%d:\n",labprefix,t);continue;}
+    if(c==BRA){
+      if(0/*t==exit_label&&framesize==0*/)
+	emit(f,ret);
+      else
+	emit(f,"\tb\t%s%d\n",labprefix,t);
+      continue;
+    }
+    if(c>=BEQ&&c<BRA){
+      if(lastcomp&UNSIGNED)
+	emit(f,"\tb%s\t",ccu[c-BEQ]);
+      else
+	emit(f,"\tb%s\t",ccs[c-BEQ]);
+      if(isreg(q1)){
+	emit_obj(f,&p->q1,0);
+	emit(f,",");
+      }
+      emit(f,"%s%d\n",labprefix,t);
+      continue;
+    }
+    if(c==MOVETOREG){
+      load_reg(f,p->z.reg,&p->q1,regtype[p->z.reg]->flags);
+      continue;
+    }
+    if(c==MOVEFROMREG){
+      store_reg(f,p->q1.reg,&p->z,regtype[p->q1.reg]->flags);
+      continue;
+    }
+    if(c==PUSH)
+      dontpop+=zm2l(p->q2.val.vmax);
+    if((c==ASSIGN||c==PUSH)&&((t&NQ)>POINTER||((t&NQ)==CHAR&&zm2l(p->q2.val.vmax)!=1))){
+      int i,cnt,unit,lab,treg,acnt=0,atreg=0;
+      long size;
+      char *ut;
+      if((p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&reg_is_scratched(p,p->q1.reg)){
+	q1reg=p->q1.reg;
+	if(p->q1.am) ierror(0);
+      }else{
+	q1reg=t1;
+	if(p->q1.flags&(REG|DREFOBJ)){
+	  p->q1.flags&=~DREFOBJ;
+	  load_reg(f,q1reg,&p->q1,POINTER);
+	}else
+	  load_address(f,q1reg,&p->q1,POINTER);
+      }
+      if((p->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&reg_is_scratched(p,p->z.reg)){
+	zreg=p->z.reg;
+	if(p->z.am) ierror(0);
+      }else if(c==PUSH){
+	zreg=sp;
+      }else{
+	if(q1reg==t1)
+	  zreg=t2;
+	else
+	  zreg=t1;
+	if(p->z.flags&(REG|DREFOBJ)){
+	  p->z.flags&=~DREFOBJ;
+	  load_reg(f,zreg,&p->z,POINTER);
+	}else
+	  load_address(f,zreg,&p->z,POINTER);
+      }      
+      if(zreg==t2){
+	treg=get_reg(f,p);
+	atreg=1;
+      }else if(zreg==t1||q1reg==t1)
+	treg=t2;
+      else
+	treg=t1;
+
+      unit=1;ut="b";
+      size=zm2l(p->q2.val.vmax);
+
+      if(c==PUSH)
+	emit(f,"\tadd\t%s,%ld\n",regnames[q1reg],size);
+
+      if(size/unit>=8){
+	if(treg!=t2&&zreg!=t2)
+	  cnt=t2;
+	else{
+	  cnt=get_reg(f,p);
+	  acnt=1;
+	}
+	emit(f,"\tmov\t%s,%ld\n",regnames[cnt],(size/unit)>>2);
+	emit(f,"%s%d:\n",labprefix,++label);
+      }
+
+      for(i=0;i<((size/unit>4)?4:size/unit);i++){
+	if(c!=PUSH){
+	  emit(f,"\tld%s\t%s,(%s)++\n",ut,regnames[treg],regnames[q1reg]);
+	  emit(f,"\tst%s\t%s,(%s)++\n",ut,regnames[treg],regnames[zreg]);
+	}else{
+	  emit(f,"\tld%s\t%s,--(%s)\n",ut,regnames[treg],regnames[q1reg]);
+	  emit(f,"\tst%s\t%s,--(%s)\n",ut,regnames[treg],regnames[zreg]);
+	}
+      }
+      if(size/unit>=8){
+	emit(f,"\taddcmpbne\t%s,-1,0,%s%d\n",regnames[cnt],labprefix,label);
+      }
+      for(i=0;i<((size/unit)&3);i++){
+	if(c!=PUSH){
+	  emit(f,"\tld%s\t%s,(%s)++\n",ut,regnames[treg],regnames[q1reg]);
+	  emit(f,"\tst%s\t%s,(%s)++\n",ut,regnames[treg],regnames[zreg]);
+	}else{
+	  emit(f,"\tld%s\t%s,--(%s)\n",ut,regnames[treg],regnames[q1reg]);
+	  emit(f,"\tst%s\t%s,--(%s)\n",ut,regnames[treg],regnames[zreg]);
+	}
+      }
+      if(c==PUSH)
+	push(size);
+      if(acnt) free_reg(f,cnt);
+      if(atreg) free_reg(f,treg);
+      continue;
+    }
+
+    if(c==CALL){
+      int reg;
+      /*FIXME*/
+#if 0      
+      if(stack_valid&&(p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&(p->q1.v->fi->flags&ALL_STACK)){
+	if(framesize+zum2ul(p->q1.v->fi->stack1)>stack)
+	  stack=framesize+zum2ul(p->q1.v->fi->stack1);
+      }else
+	stack_valid=0;
+#endif
+      /*FIXME: does not work with fixed parameters on stack */
+      if((p->q1.flags&(VAR|DREFOBJ))==VAR&&!strcmp("__va_start",p->q1.v->identifier)){
+	emit(f,"\tadd\t%s,%s,%ld\n",regnames[r0],regnames[sp],localsize+rsavesize-stackoffset);
+	continue;
+      }
+
+      if((p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&p->q1.v->fi->inline_asm){
+        emit_inline_asm(f,p->q1.v->fi->inline_asm);
+      }else{
+	if((p->q1.flags&(REG|DREFOBJ))==DREFOBJ){
+	  p->q1.flags&=~DREFOBJ;
+	  load_reg(f,t1,&p->q1,POINTER);
+	  p->q1.flags|=(DREFOBJ|REG);
+	  p->q1.reg=t1;
+	}
+	emit(f,"\tbl\t");
+	if((p->q1.flags&(REG|DREFOBJ))==(REG|DREFOBJ)){
+	  emit(f,"%s",regnames[p->q1.reg]);
+	}else{
+	  no_suffix=1;
+	  emit_obj(f,&p->q1,t);
+	  no_suffix=0;
+	}
+	emit(f,"\n");
+      }
+
+      if(!zmeqto(p->q2.val.vmax,l2zm(0L))){
+        notpopped+=zm2l(p->q2.val.vmax);
+        dontpop-=zm2l(p->q2.val.vmax);
+        if(!NODELAYEDPOP&&!vlas&&stackoffset==-notpopped){
+          /*  Entfernen der Parameter verzoegern  */
+        }else{
+	  emit(f,"\tadd\t%s,%ld\n",regnames[sp],zm2l(p->q2.val.vmax));
+          pop(zm2l(p->q2.val.vmax));
+          notpopped-=zm2l(p->q2.val.vmax);
+        }
+      }
+
+      if((p->q1.flags&(VAR|DREFOBJ))==VAR&&p->q1.v->fi&&(p->q1.v->fi->flags&ALL_REGS)){
+	bvunite(regs_modified,p->q1.v->fi->regs_modified,RSIZE);
+      }else{
+	int i;
+	for(i=1;i<=MAXR;i++){
+	  if(regscratch[i]) BSET(regs_modified,i);
+	}
+      }
+      continue;
+    }
+
+    if(c==ADDRESS){
+      if(isreg(z))
+	zreg=p->z.reg;
+      else
+	zreg=t1;
+      load_address(f,zreg,&p->q1,POINTER);
+      save_result(f,p);
+      continue;
+    }
+
+    if(isreg(q1)) q1wasreg=1; else q1wasreg=0;
+    if(isreg(q2)) q2wasreg=1; else q2wasreg=0;
+    if(isreg(z)) zwasreg=1; else zwasreg=0;
+
+    p=preload(f,p);
+    c=p->code;
+    if(c==SUBPFP) c=SUB;
+    if(c==ADDI2P) c=ADD;
+    if(c==SUBIFP) c=SUB;
+    if(c==CONVERT){
+      if(ISFLOAT(q1typ(p))){
+	if(ztyp(p)&UNSIGNED) ierror(0);
+	if(ISFLOAT(ztyp(p)))
+	  emit(f,"\tmov%s\t%s,%s\n",cc,regnames[zreg],regnames[q1reg]);
+	else
+	  emit(f,"\tftrunc%s\t%s,%s\n",cc,regnames[zreg],regnames[q1reg]);
+	save_result(f,p);
+	continue;
+      }
+      if(ISFLOAT(ztyp(p))){
+	emit(f,"\tflt%c%s\t%s,%s\n",(q1typ(p)&UNSIGNED)?'u':'s',cc,regnames[zreg],regnames[q1reg]);
+	save_result(f,p);
+	continue;
+      }
+      if(sizetab[q1typ(p)&NQ]<sizetab[ztyp(p)&NQ]){
+	int mask;
+	if((q1typ(p)&NQ)==CHAR)
+	  mask=7;
+	else
+	  mask=15;
+	if(q1typ(p)&UNSIGNED)
+	  mask++;
+	if(q1wasreg||(q1typ(p)&NU)==CHAR)
+	  emit(f,"\text%c%s\t%s,%s,%d\n",(q1typ(p)&UNSIGNED)?'u':'s',cc,regnames[zreg],regnames[q1reg],mask);
+      }else{
+	zreg=q1reg;
+      }	  
+      save_result(f,p);
+      continue;
+    }
+    if(c==KOMPLEMENT){
+      emit(f,"\tmvn%s\t%s,%s\n",cc,regnames[zreg],regnames[q1reg]);
+      save_result(f,p);
+      continue;
+    }
+    if(c==SETRETURN){
+      if(isreg(q1)){
+	if(p->q1.reg!=p->z.reg)
+	  emit(f,"\tmov%s\t%s,%s\n",cc,regnames[p->z.reg],regnames[p->q1.reg]);
+      }else
+	load_reg(f,p->z.reg,&p->q1,t);
+      BSET(regs_modified,p->z.reg);
+      continue;
+    }
+    if(c==GETRETURN){
+      if(p->q1.reg){
+        zreg=p->q1.reg;
+	save_result(f,p);
+      }else
+        p->z.flags=0;
+      continue;
+    }
+
+    if(c==ASSIGN||c==PUSH){
+      if(t==0) ierror(0);
+      if(c==PUSH){
+	if(!q1reg){
+	  q1reg=t1;
+	  load_reg(f,q1reg,&p->q1,t);
+	}
+	if(SHORT_DOUBLE&&ISFLOAT(t)) t=FLOAT;
+	emit(f,"\tst%s%s\t%s,--(%s)\n",sdt(t),cc,regnames[q1reg],regnames[sp]);
+	push(zm2l(p->q2.val.vmax));
+	continue;
+      }
+      if(c==ASSIGN){
+	if(isreg(q1)){
+	  if(isreg(z))
+	    emit(f,"\tmov%s\t%s,%s\n",cc,regnames[zreg],regnames[p->q1.reg]);
+	  else
+	    zreg=p->q1.reg;
+	}else
+	  load_reg(f,zreg,&p->q1,t);
+	save_result(f,p);
+      }
+      continue;
+    }
+    if(c==MINUS){
+      load_reg(f,zreg,&p->q1,t);
+      emit(f,"\tneg%s\t%s,%s\n",cc,regnames[zreg],regnames[zreg]);
+      save_result(f,p);
+      continue;
+    }
+    if(c==TEST){
+      emit(f,"\tcmp%s\t",cc);
+      emit_obj(f,&p->q1,t);
+      emit(f,",0\n");
+      lastcomp=t;
+      continue;
+    }
+    if(c==COMPARE){
+      if(ISFLOAT(t))
+	emit(f,"\tfcmp%s\t%s,",cc,regnames[t1]);
+      else
+	emit(f,"\tcmp%s\t",cc);
+      emit_obj(f,&p->q1,t);
+      emit(f,",");
+      emit_obj(f,&p->q2,t);
+      emit(f,"\n");
+      lastcomp=t;
+      continue;
+    }
+    if(c==MOD){
+      /* TODO: is there a faster way? */
+      int m;
+      if(q2reg!=t2)
+	m=t2;
+      else
+	m=get_reg(f,p);
+      if(!isreg(q1)||p->q1.reg!=zreg)
+	load_reg(f,zreg,&p->q1,t);
+      emit(f,"\tdiv%c%s\t%s,%s,",(t&UNSIGNED)?'u':'s',cc,regnames[m],regnames[zreg]);
+      emit_obj(f,&p->q2,t);
+      emit(f,"\n");
+      emit(f,"\tmul%s\t%s,",cc,regnames[m]);
+      emit_obj(f,&p->q2,t);
+      emit(f,"\n");
+      emit(f,"\tsub%s\t%s,%s,%s\n",cc,regnames[zreg],regnames[zreg],regnames[m]);
+      free_reg(f,m);
+      save_result(f,p);
+      continue;
+    }      
+    if((c>=OR&&c<=AND)||(c>=LSHIFT&&c<MOD)){
+      if(c>=OR&&c<=AND)
+	emit(f,"\t%s%s\t%s,",logicals[c-OR],cc,regnames[zreg]);
+      else{
+	if(ISFLOAT(t))
+	  emit(f,"\t%s%s\t%s,",farithmetics[c-LSHIFT],cc,regnames[zreg]);
+	else
+	  emit(f,"\t%s%s\t%s,",(t&UNSIGNED)?uarithmetics[c-LSHIFT]:arithmetics[c-LSHIFT],cc,regnames[zreg]);
+      }
+      if(!isreg(q1)||p->q1.reg!=zreg||*cc||c==DIV||ISFLOAT(t)){
+	emit_obj(f,&p->q1,t);
+	emit(f,",");
+      }
+      emit_obj(f,&p->q2,t);
+      emit(f,"\n");
+      save_result(f,p);
+      continue;
+    }
+    pric2(stdout,p);
+    ierror(0);
+  }
+
+  if(notpopped){
+    emit(f,"\tadd\t%s,%ld\n",regnames[sp],notpopped);
+    pop(notpopped);notpopped=0;
+  }
+
+  function_bottom(f,v,localsize);
+  if(stack_valid){
+    if(!v->fi) v->fi=new_fi();
+    v->fi->flags|=ALL_STACK;
+    v->fi->stack1=stack;
+  }
+  /*emit(f,"# stacksize=%lu%s\n",zum2ul(stack),stack_valid?"":"+??");*/
+}
+
+int shortcut(int code,int typ)
+{
+  return 0;
+}
+
+int reg_parm(struct reg_handle *m, struct Typ *t,int vararg,struct Typ *d)
+{
+  int f;
+
+  if(vararg)
+    return 0;
+
+  f=t->flags&NQ;
+  if(ISINT(f)||ISFLOAT(f)||f==POINTER){
+    if(zmeqto(sizetab[f],l2zm(8L))){
+      if(m->gregs<=r4){
+	m->gregs=(m->gregs+1)&0xfe;
+	m->gregs+=2;
+	if(m->gregs==r1)
+	  return r0r1;
+	else if(m->gregs==r3)
+	  return r2r3;
+	else if(m->gregs==r5)
+	  return r4r5;
+	else
+	  ierror(0);
+      }else
+	return 0;
+    }else{
+      if(m->gregs<=r4)
+	return ++m->gregs;
+      else
+	return 0;
+    }
+  }
+  return 0;
+}
+
+int handle_pragma(const char *s)
+{
+}
+void cleanup_cg(FILE *f)
+{
+}
+void cleanup_db(FILE *f)
+{
+  if(f) section=-1;
+}
+
+char *use_libcall(int c,int t,int t2)
+/* Return name of library function, if this node should be
+   implemented via libcall. */
+{
+  static char fname[16];
+  char *ret = NULL;
+
+  if(c==COMPARE){
+    if((t&NQ)==DOUBLE) t=(SHORT_DOUBLE)?FLOAT:LDOUBLE;
+    if((t&NQ)==LLONG||t==LDOUBLE){
+      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(SHORT_DOUBLE){
+      if(ISFLOAT(t)) t=FLOAT;
+      if(ISFLOAT(t2)) t2=FLOAT;
+    }else{
+      if(t==DOUBLE) t=LDOUBLE;
+      if(t2==DOUBLE) t2=LDOUBLE;
+    }
+    if(c==CONVERT){
+      if(t==t2) return 0;
+      if(t==FLOAT&&t2==LDOUBLE) return "__flt64toflt32";
+      if(t==LDOUBLE&&t2==FLOAT) return "__flt32toflt64";
+      if(t!=LDOUBLE&&t2!=LDOUBLE&&(t&NQ)!=LLONG&&(t2&NQ)!=LLONG) return 0;
+      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)&&(t&NU)==LLONG){
+        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||t==DOUBLE){
+      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{
+          sprintf(fname,"__%s%s%s%ld",ename[c],(t&UNSIGNED)?"u":"",ISFLOAT(t)?"flt":"int",zm2l(sizetab[t&NQ])*8);
+          ret=fname;
+        }
+      }
+    }
+  }
+
+  return ret;
+}
diff --git a/machines/vidcore/machine.dt b/machines/vidcore/machine.dt
new file mode 100644
index 0000000..526c8d4
--- /dev/null
+++ b/machines/vidcore/machine.dt
@@ -0,0 +1,16 @@
+S8BS
+S8BU
+S16BSBE S16BSLE
+S16BUBE S16BULE
+S32BSBE S32BSLE
+S32BUBE S32BULE
+S32BSBE S32BSLE
+S32BUBE S32BULE
+S64BSBE S64BSLE
+S64BUBE S64BULE
+S32BIEEEBE
+S64BIEEEBE
+S64BIEEEBE
+S32BUBE S32BULE
+
+
diff --git a/machines/vidcore/machine.h b/machines/vidcore/machine.h
new file mode 100644
index 0000000..408e581
--- /dev/null
+++ b/machines/vidcore/machine.h
@@ -0,0 +1,131 @@
+/*  Backend for VideoCore IV
+    (c) in 2013 by Volker Barthelmann
+*/
+
+/* buil-time configurable options: */
+#define NUM_GPRS 48
+
+#include "dt.h"
+
+
+/*  This struct can be used to implement machine-specific           */
+/*  addressing-modes.                                               */
+/*  Currently possible are (const,gpr) and (gpr,gpr)                */
+struct AddressingMode{
+    int flags;
+    int base;
+    long offset;
+};
+
+/*  The number of registers of the target machine.                  */
+#define MAXR 48
+
+/*  Number of commandline-options the code-generator accepts.       */
+#define MAXGF 20
+
+/*  If this is set to zero vbcc will not generate ICs where the     */
+/*  target operand is the same as the 2nd source operand.           */
+/*  This can sometimes simplify the code-generator, but usually     */
+/*  the code is better if the code-generator allows it.             */
+#define USEQ2ASZ 0
+
+/*  This specifies the smallest integer type that can be added to a */
+/*  pointer.                                                        */
+#define MINADDI2P INT
+
+/*  This specifies the smallest integer type that can be added to a */
+/*  pointer.                                                        */
+#define MAXADDI2P INT
+
+/*  If the bytes of an integer are ordered most significant byte    */
+/*  byte first and then decreasing set BIGENDIAN to 1.              */
+#define BIGENDIAN 0
+
+/*  If the bytes of an integer are ordered lest significant byte    */
+/*  byte first and then increasing set LITTLEENDIAN to 1.           */
+#define LITTLEENDIAN 1
+
+/*  Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive.    */
+
+/*  If switch-statements should be generated as a sequence of       */
+/*  SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1.      */
+/*  This can yield better code on some machines.                    */
+#define SWITCHSUBS 1
+
+/*  In optimizing compilation certain library memcpy/strcpy-calls   */
+/*  with length known at compile-time will be inlined using an      */
+/*  ASSIGN-IC if the size is less or equal to INLINEMEMCPY.         */
+/*  The type used for the ASSIGN-IC will be UNSIGNED|CHAR.          */
+#define INLINEMEMCPY 1024
+
+/*  Parameters are sometimes passed in registers without __reg.     */
+#define HAVE_REGPARMS 1
+
+/*  Parameters on the stack should be pushed in order rather than   */
+/*  in reverse order.                                               */
+#undef ORDERED_PUSH
+
+/*  Structure for reg_parm().                                       */
+struct reg_handle{
+    unsigned long gregs;
+};
+
+/*  We have some target-specific variable attributes.               */
+#define HAVE_TARGET_ATTRIBUTES
+
+/* We have target-specific pragmas */
+#define HAVE_TARGET_PRAGMAS
+
+/*  We keep track of all registers modified by a function.          */
+#define HAVE_REGS_MODIFIED 1
+
+/* We have a implement our own cost-functions to adapt 
+   register-allocation */
+#define HAVE_TARGET_RALLOC 1
+#define cost_move_reg(x,y) 1
+#define cost_load_reg(x,y) 2
+#define cost_save_reg(x,y) 2
+#define cost_pushpop_reg(x) 3
+
+/* size of buffer for asm-output, this can be used to do
+   peephole-optimizations of the generated assembly-output */
+#define EMIT_BUF_LEN 1024 /* should be enough */
+/* number of asm-output lines buffered */
+#define EMIT_BUF_DEPTH 4
+
+/*  We have no asm_peephole to optimize assembly-output */
+#define HAVE_TARGET_PEEPHOLE 0
+
+/* we do not have a mark_eff_ics function, this is used to prevent
+   optimizations on code which can already be implemented by efficient
+   assembly */
+#undef HAVE_TARGET_EFF_IC
+
+/* we only need the standard data types (no bit-types, different pointers
+   etc.) */
+#undef HAVE_EXT_TYPES
+#undef HAVE_TGT_PRINTVAL
+
+/* we do not need extra elements in the IC */
+#undef HAVE_EXT_IC
+
+/* we do use unsigned int as size_t (but unsigned long, the default) */
+#define HAVE_INT_SIZET 1
+
+/* we need register-pairs */
+#define HAVE_REGPAIRS 1
+
+
+/* do not create CONVERT ICs from integers smaller than int to floats */
+#define MIN_INT_TO_FLOAT_TYPE INT
+
+/* do not create CONVERT ICs from floats to ints smaller than int */
+#define MIN_FLOAT_TO_INT_TYPE INT
+
+/* do not create CONVERT_ICs from floats to unsigned integers */
+#define AVOID_FLOAT_TO_UNSIGNED 1
+
+/* do not create CONVERT_ICs from unsigned integers to floats */
+#define AVOID_UNSIGNED_TO_FLOAT 0
+
+#define HAVE_LIBCALLS 1
diff --git a/machines/z/machine.c b/machines/z/machine.c
new file mode 100755
index 0000000..a242fff
--- /dev/null
+++ b/machines/z/machine.c
@@ -0,0 +1,2719 @@
+/* z/machine.c
+ * Code generator for the Z-machine.
+ * (C) David Given 2001
+ * conversion to vbcc 0.8 by Volker Barthelmann
+ */
+
+/* This code is licensed under the MIT open source license.
+ *
+ * Copyright (c) 2001, David Given
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/* This code generator produces code for the Z-machine. The Z-machine is the
+ * highly peculiar virtual machine used for the old Infocom text adventures;
+ * these days, an extended form is still used in the interactive fiction genre
+ * of games. Usually, a dedicated compiler called Inform is used to generate
+ * code, but it would be nice to be able to use real C, so here we are.
+ *
+ * The Z-machine is (mostly) a semi-stack-based Harvard architecture machine.
+ * (Split code and data space, although they can share if you're clever. And
+ * mad.) It has no registers, but it does have procedure local variables which
+ * will do instead. It has a dedicated stack but as it's not accessible by
+ * ordinary memory it's not useful for C. It uses 8 and 16 bit words, so we'll
+ * have to emulate 32-bit arithmetic.
+ *
+ * For more information, including code for Inform, various interpreters, more
+ * documentation than you can shake a stick at, and the full technical reference
+ * for the Z-machine, check out the Interactive Fiction archive, at
+ * http://www.ifarchive.org.
+ *
+ * Things to note: there is no Z-machine assembler. (Well, there's zasm, but it's
+ * really just a rumour.) Luckily, Inform has an assembler mode, where it'll
+ * generate raw Z-machine opcodes. Unluckily, it's horribly buggy... So we're
+ * going to have to generate Inform source, which seems at first to be rather
+ * silly, but as Inform is quite a simple compiler we can make sure that it's
+ * only going to generate the instructions we want it to generate.
+ */
+
+/* vbcc-mandated header. */
+
+#include "supp.h"
+static char FILE_[]=__FILE__;
+char cg_copyright[]="vbcc code-generator for Z-machine V0.0a (c) in 2001 by David Given";
+
+/* Command-line flags. */
+
+int g_flags[MAXGF] = {
+	STRINGFLAG,
+	0,
+	0,
+	0,
+	0,
+	0
+};
+char *g_flags_name[MAXGF] = {
+	"module-name",
+	"trace-calls",
+	"trace-all",
+	"safe-branches",
+	"comment-ic",
+	"comment-misc"
+};
+union ppi g_flags_val[MAXGF];
+
+/* Type alignment. Much better code is generated if we can use even alignment.
+ */
+
+zmax align[MAX_TYPE+1] = {
+	0,	/* 0: unused */
+	1,	/* 1: CHAR */
+	2,	/* 2: SHORT */
+	2, 	/* 3: INT */
+	2,	/* 4: LONG */
+	2,      /* 5: LLONG */
+	2,	/* 6: FLOAT */
+	2,	/* 7: DOUBLE */
+	2,      /* 8: LDOUBLE */
+	2,	/* 9: VOID */
+	2,	/* 10: POINTER */
+	1,	/* 11: ARRAY */
+	1,	/* 12: STRUCT */
+	1,	/* 13: UNION */
+	1,	/* 14: ENUM */
+	1,	/* 15: FUNKT */
+};
+
+/* Alignment that is valid for all types. */
+
+zmax maxalign = 2;
+
+/* Number of bits in a char. */
+
+zmax char_bit = 8;
+
+/* Sizes of all elementary types, in bytes. */
+
+zmax sizetab[MAX_TYPE+1] = {
+	0,	/* 0: unused */
+	1,	/* 1: CHAR */
+	2,	/* 2: SHORT */
+	2, 	/* 3: INT */
+	4,	/* 4: LONG */
+        8,      /* 5: LLONG */
+	4,	/* 6: FLOAT */
+	8,	/* 7: DOUBLE */
+	8,      /* 8: LDOUBLE */
+	0,	/* 9: VOID */
+	2,	/* 10: POINTER */
+	0,	/* 11: ARRAY */
+	0,	/* 12: STRUCT */
+	0,	/* 13: UNION */
+	2,	/* 14: ENUM */
+	0,	/* 15: FUNKT */
+};
+
+/*  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 the registers.
+ * We can have 16 local variables per routine. Var 0 is always the C stack
+ * pointer, xp. All the others can be used by the compiler. xp doesn't actually
+ * appear in the register map, so we get 15 main registers. 
+ */
+
+char* regnames[] = {
+	"sp", /* vbcc doesn't use this, but we do */
+	"xp", 	"r0", 	"r1",  	"r2", 	"r3", 	"r4", 	"r5", 	"r6",
+	"r7", 	"r8", 	"r9",	"r10",	"r11",	"r12"};
+#define XP 1
+#define USERREG 2
+
+/* The size of each register, in byes. */
+
+zmax regsize[] = {
+	0,
+	2,	2,	2,	2,	2,	2,	2,	2,
+	2,	2,	2,	2,	2,	2};
+
+/* Type needed to store each register. */
+
+struct Typ ityp = {INT};
+struct Typ* regtype[] = {
+	NULL,
+	&ityp,	&ityp,	&ityp,	&ityp,	&ityp,	&ityp,	&ityp,	&ityp,
+	&ityp,	&ityp,	&ityp,	&ityp,	&ityp,	&ityp};
+	
+/* These registers are those dedicated for use by the backend. These ones will
+ * not be used by the code generator. */
+
+int regsa[] = {
+	0,
+	1,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0};
+
+/* Specifies which registers may be destroyed by function calls. As we're
+ * storing our registers in local variables so they're being automatically
+ * saved for us, none of them.
+ */
+
+int regscratch[] = {
+	0,
+	0,	0,	0,	0,	0,	0,	0,	0,
+	0,	0,	0,	0,	0,	0};
+
+/* Default state for register parameter passing. */
+
+struct reg_handle empty_reg_handle =
+	{USERREG};
+
+/* Prefix for labels. */
+
+static char* labelprefix = "L";
+
+/* Name of the current module; used for generating unique names for statics and
+ * the constant pool. */
+
+static char* modulename;
+
+/* Stack frame layout:
+ *
+ *  --------------
+ *      Arg 4        (Arguments being passed to this function)
+ *      Arg 3
+ *      Arg 2
+ *      Arg 1
+ *  -------------- xp + stackparamadjust + stackoffset
+ *     Local 4       (This function's temp space)
+ *     Local 3
+ *     Local 2
+ *     Local 1
+ *  -------------- xp + stackparamadjust
+ *      Arg 2        (Arguments this function has pushed to pass
+ *      Arg 1         to a called function)
+ *  -------------- xp
+ *
+ * Any area may be zero in size. (Although stackoffset is always at least 2 for
+ * some inadequately explained reason.)
+ */
+
+static int stackoffset;
+static int stackparamadjust;
+
+/* Represents something the Z-machine can use as an instruction operand. */
+
+struct zop {
+	int type;
+	union {
+		int reg;
+		zmax constant;
+		char* identifier;
+	} val;
+};
+
+enum {
+	ZOP_STACK,
+	ZOP_REG,
+	ZOP_CONSTANT,
+	ZOP_EXTERN,
+	ZOP_STATIC,
+	ZOP_CONSTANTADDR
+};
+
+/* Some useful zops. */
+
+struct zop zop_zero = {ZOP_CONSTANT, {constant: 0}};
+struct zop zop_xp = {ZOP_REG, {reg: XP}};
+struct zop zop_stack = {ZOP_STACK, 0};
+
+/* Temporaries used to store comparison register numbers. */
+
+static struct zop compare1;
+static struct zop compare2;
+
+/* Keeps track of whether we've emitted anything or not. Used to determine
+ * whether to emit the seperating ; or not. If it's 1, we haven't emitted
+ * anything. If it's -1, we're doing an array, so we need to emit a final (0)
+ * to finish it off if it's only one byte long. 0 for anything else. */
+
+static int virgin = 1;
+
+/* The current variable we're emitting data for. */
+
+struct variable {
+	int type;
+	union {
+		char* identifier;
+		int number;
+	} val;
+	zint offset;
+};
+
+struct variable currentvar;
+
+/* Inform can't emit variable references inside arrays. So when vbcc wants to
+ * put, say, the address of something in a global variable, we have to write it
+ * in later. A linked list of these structures keeps track of the items that
+ * need fixing up. */
+
+struct fixup {
+	struct fixup* next;
+	struct variable identifier;
+	struct variable value;
+	zmax offset;
+};
+
+static struct fixup* fixuplist = NULL;
+	
+/* 32-bit values are stored in a constant pool, for simplicity. It's kept track
+ * of in this linked list. */
+
+struct constant {
+	struct constant* next;
+	int id;
+	zmax value;
+};
+
+static struct constant* constantlist = NULL;
+static int constantnum = 0;
+
+/* The function we're currently compiling. */
+
+static struct Var* function;
+
+/* Function prototypes. */
+
+static void emit_add(FILE* fp, struct zop* q1, struct zop* q2, struct zop* z);
+static void read_reg(FILE* fp, struct obj* obj, int typf, int reg);
+static int addconstant(zmax value);
+
+/* Emit debugging info. */
+
+static void debugemit(FILE* fp, char* fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	if (g_flags[5] & USEDFLAG)
+		vfprintf(fp, fmt, ap);
+	va_end(ap);
+}
+
+/* Do we need to emit a ; before the next thing? */
+
+static void reflower(FILE* fp)
+{
+	if (!virgin)
+		fprintf(fp, ";\n");
+	if (virgin == -1)
+	{
+		if (currentvar.offset == 1)
+			fprintf(fp, "(0)");
+		fprintf(fp, ";");
+	}
+	virgin = 0;
+}
+
+/* Extract the sign extended byte n of a value. */
+
+static char xbyte(zmax val, int byte)
+{
+	val <<= (sizeof(val)*8) - (byte*8) - 8;
+	val >>= (sizeof(val)*8) - 8;
+	return (unsigned char) val;
+}
+
+/* Extract the sign extended word n of a value. */
+
+static zshort xword(zmax val, int word)
+{
+	val <<= (sizeof(val)*8) - (word*16) - 16;
+	val >>= (sizeof(val)*8) - 16;
+	return (zshort) val;
+}
+
+/* Debug function: prints the text name of a type. */
+
+static void dump_type(FILE* fp, int typf)
+{
+	switch (typf)
+	{
+		case VOID:	fprintf(fp, "VOID"); break;
+		case CHAR:	fprintf(fp, "CHAR"); break;
+		case SHORT:	fprintf(fp, "SHORT"); break;
+		case INT:	fprintf(fp, "INT"); break;
+		case LONG:	fprintf(fp, "LONG"); break;
+		case POINTER:	fprintf(fp, "POINTER"); break;
+		case STRUCT:	fprintf(fp, "STRUCT"); break;
+		case ARRAY:	fprintf(fp, "ARRAY"); break;
+		case UNION:	fprintf(fp, "UNION"); break;
+		case FUNKT:	fprintf(fp, "FUNKT"); break;
+		default:	fprintf(fp, "unknown %X", typf);
+	}
+}
+
+/* Debug function: outputs the obj. */
+
+static void dump_obj(FILE* fp, struct obj* obj, int typf)
+{
+	int f = obj->flags & (KONST|REG|VAR|DREFOBJ|VARADR);
+
+	if (f == 0)
+	{
+		fprintf(fp, "[]");
+		return;
+	}
+
+	if (f & DREFOBJ)
+		fprintf(fp, "*");
+
+	if (f & VARADR)
+		fprintf(fp, "&");
+
+	if (f == KONST)
+	{
+		switch (typf & NU)
+		{
+			case CHAR:
+				fprintf(fp, "[char #%d]", obj->val.vchar);
+				break;
+
+			case UNSIGNED|CHAR:
+				fprintf(fp, "[uchar #%u]", obj->val.vuchar);
+				break;
+
+			case SHORT:
+				fprintf(fp, "[short #%d]", obj->val.vshort);
+				break;
+
+			case UNSIGNED|SHORT:
+				fprintf(fp, "[ushort #%u]", obj->val.vushort);
+				break;
+
+			case INT:
+				fprintf(fp, "[int #%d]", obj->val.vint);
+				break;
+
+			case UNSIGNED|INT:
+				fprintf(fp, "[uint #%d]", obj->val.vuint);
+				break;
+
+			case LONG:
+				fprintf(fp, "[long #%d]", obj->val.vlong);
+				break;
+
+			case UNSIGNED|LONG:
+				fprintf(fp, "[ulong #%u]", obj->val.vulong);
+				break;
+
+			case FLOAT:
+				fprintf(fp, "[float #%04X]", obj->val.vfloat);
+				break;
+
+			case DOUBLE:
+				fprintf(fp, "[double #%08X]", obj->val.vdouble);
+				break;
+#if 0
+			case POINTER:
+				fprintf(fp, "[pointer #%04X]", obj->val.vpointer);
+				break;
+#endif
+		}
+	}
+	else if (f == REG)
+		fprintf(fp, "[reg %s]", regnames[obj->reg]);
+	else if (f == (REG|DREFOBJ))
+		fprintf(fp, "[deref reg %s]", regnames[obj->reg]);
+	//else if (f & VAR)
+	else
+	{
+		fprintf(fp, "[var ");
+		dump_type(fp, typf);
+		fprintf(fp, " %s", obj->v->identifier);
+
+		if ((obj->v->storage_class == AUTO) ||
+		    (obj->v->storage_class == REGISTER))
+		{
+			zmax offset = obj->v->offset;
+			//if (offset < 0)
+			//	offset = -(offset+maxalign);
+			fprintf(fp, " at fp%+d", offset);
+		}
+
+		fprintf(fp, "+%ld", obj->val.vlong);
+
+		if (f & REG)
+			fprintf(fp, " in %s", regnames[obj->reg]);
+		fprintf(fp, "]");
+	}
+}
+
+/* Debug function: outputs the ic, as a comment. */
+
+static void dump_ic(FILE* fp, struct IC* ic)
+{
+	char* p;
+
+	if (!ic)
+		return;
+
+	if (!(g_flags[4] & USEDFLAG))
+		return;
+
+	if (g_flags[2] & USEDFLAG)
+		fprintf(fp, "print \"");
+	else
+		fprintf(fp, "! ");
+	
+	switch (ic->code)
+	{
+		case ASSIGN:		p = "ASSIGN";		break;
+		case OR:		p = "OR";		break;
+		case XOR:		p = "XOR";		break;
+		case AND:		p = "AND";		break;
+		case LSHIFT:		p = "LSHIFT";		break;
+		case RSHIFT:		p = "RSHIFT";		break;
+		case ADD:		p = "ADD";		break;
+		case SUB:		p = "SUB";		break;
+		case MULT:		p = "MULT";		break;
+		case DIV:		p = "DIV";		break;
+		case MOD:		p = "MOD";		break;
+		case KOMPLEMENT:	p = "KOMPLEMENT";	break;
+		case MINUS:		p = "MINUS";		break;
+		case ADDRESS:		p = "ADDRESS";		break;
+		case CALL:		p = "CALL";		break;
+#if 0
+		case CONVCHAR:		p = "CONVCHAR";		break;
+		case CONVSHORT:		p = "CONVSHORT";	break;
+		case CONVINT:		p = "CONVINT";		break;
+		case CONVLONG:		p = "CONVLONG";		break;
+		case CONVFLOAT:		p = "CONVFLOAT";	break;
+		case CONVDOUBLE:	p = "CONVDOUBLE";	break;
+		case CONVPOINTER:	p = "CONVPOINTER";	break;
+		case CONVUCHAR:		p = "CONVUCHAR";	break;
+		case CONVUSHORT:	p = "CONVUSHORT";	break;
+		case CONVUINT:		p = "CONVUINT";		break;
+		case CONVULONG:		p = "CONVULONG";	break;
+#endif
+		case ALLOCREG:		p = "ALLOCREG";		break;
+		case FREEREG:		p = "FREEREG";		break;
+		case COMPARE:		p = "COMPARE";		break;
+		case TEST:		p = "TEST";		break;
+		case LABEL:		p = "LABEL";		break;
+		case BEQ:		p = "BEQ";		break;
+		case BNE:		p = "BNE";		break;
+		case BLT:		p = "BLT";		break;
+		case BGT:		p = "BGT";		break;
+		case BLE:		p = "BLE";		break;
+		case BGE:		p = "BGE";		break;
+		case BRA:		p = "BRA";		break;
+		case PUSH:		p = "PUSH";		break;
+		case ADDI2P:		p = "ADDI2P";		break;
+		case SUBIFP:		p = "SUBIFP";		break;
+		case SUBPFP:		p = "SUBPFP";		break;
+		case GETRETURN:		p = "GETRETURN";	break;
+		case SETRETURN:		p = "SETRETURN";	break;
+		case MOVEFROMREG:	p = "MOVEFROMREG";	break;
+		case MOVETOREG:		p = "MOVETOREG";	break;
+		case NOP:		p = "NOP";		break;
+		default:		p = "???";
+	}
+
+	fprintf(fp, "%s ", p);
+	dump_type(fp, ic->typf);
+	fprintf(fp, " ");
+
+	switch (ic->code)
+	{
+		case LABEL:
+		case BEQ:
+		case BNE:
+		case BLT:
+		case BGT:
+		case BLE:
+		case BGE:
+		case BRA:
+			fprintf(fp, "%d", ic->typf);
+			goto epilogue;
+	}
+	
+	dump_obj(fp, &ic->q1, ic->typf);
+	fprintf(fp, " ");
+	dump_obj(fp, &ic->q2, ic->typf);
+	fprintf(fp, " -> ");
+	dump_obj(fp, &ic->z, ic->typf);
+
+epilogue:
+	if (g_flags[2] & USEDFLAG)
+		fprintf(fp, "^\";\n");
+	else
+		fprintf(fp, "\n");
+}
+
+/* Initialise the code generator. This is called once. Returns 0 if things go
+ * wrong. */
+
+int init_cg(void)
+{
+	modulename = g_flags_val[0].p;
+	if (!modulename)
+		modulename = "";
+
+  /*  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.          */
+  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);
+
+	return 1;
+}
+
+/* Returns the register in which variables of type typ are returned (or 0 if it
+ * can't be done). */
+
+int freturn(struct Typ *typ)
+{
+	int s = sizetab[typ->flags & NQ];
+	if ((typ->flags & NQ) == VOID)
+		return USERREG;
+	if ((s <= sizetab[INT]) && (s > 0))
+		return USERREG;
+	return 0;
+}
+
+/* Returns 1 if register reg can store variables of type typ. mode is set
+ * if the register is a pointer and the register is going to be dereferenced.
+ */
+
+int regok(int reg, int typf, int mode)
+{
+	int s = sizetab[typf & NQ];
+	if ((typf & NQ) == VOID)
+		return 1;
+	if ((s <= sizetab[INT]) && (s > 0))
+		return 1;
+	return 0;
+}
+
+/* Returns zero if the IC ic can be safely executed without danger of
+ * exceptions or similar things; for example, divisions or pointer dereferences
+ * are dangerous. This is used by the optimiser for code reordering.
+ */
+
+int dangerous_IC(struct IC *ic)
+{
+	/* Check for dereferences. */
+
+	if ((ic->q1.flags & DREFOBJ) ||
+	    (ic->q2.flags & DREFOBJ) ||
+	    (ic->z.flags & DREFOBJ))
+		return 0;
+
+	/* Division or modulo? */
+
+	if ((ic->code == DIV) ||
+	    (ic->code == MOD))
+		return 0;
+
+	/* Safe, as far as we can tell. */
+
+	return 1;
+}
+
+/* Returns zero if the code for converting type p->ntyp to type typ is a noop.
+ */
+
+int must_convert(int otyp, int typ,int const_expr)
+{
+	int oldtype = otyp & NQ;
+	int newtype = typ & NQ;
+
+	/* ints and shorts are equivalent. */
+
+	if (oldtype == SHORT)
+		oldtype = INT;
+	if (newtype == SHORT)
+		newtype = INT;
+
+	/* Both the same type? */
+
+	if (oldtype == newtype)
+		return 0;
+
+#if 0
+	/* Converting two basic integers? */
+
+	if ((oldtype <= INT) && (newtype <= INT))
+	{
+		/* ... but char to short needs an AND. */
+
+		if ((oldtype == CHAR) && (newtype != CHAR))
+			return 1;
+		return 0;
+	}
+#endif
+
+	/* Pointer to/from int? */
+
+	if (((oldtype == INT) || (oldtype == POINTER)) &&
+	    ((newtype == INT) || (newtype == POINTER)))
+		return 0;
+
+	/* Everything else needs code. */
+
+	return 1;
+}
+
+/* Ensure the output is aligned. A noop on the Z-machine. */
+
+void gen_align(FILE* fp, zmax align)
+{
+}
+
+/* Generate the label part of a variable definition. */
+
+void gen_var_head(FILE* fp, struct Var* var)
+{
+	if (var->storage_class == EXTERN)
+		debugemit(fp, "! Var %s %X\n", var->identifier, var->flags);
+	if (var->storage_class == STATIC)
+		debugemit(fp, "! Var static %ld %s %X\n", var->offset, var->identifier, var->flags);
+
+	/* We only want to emit records for genuinely defined variables. For
+	 * some reason, TENTATIVE is defined for some of this. */
+
+	if ((var->storage_class == EXTERN) &&
+	    !(var->flags & DEFINED) &&
+	    !(var->flags & TENTATIVE))
+		return;
+	
+	reflower(fp);
+	virgin = -1;
+	switch (var->storage_class)
+	{
+		case EXTERN:
+			/* This doesn't actually mean external linkage; it
+			 * means a non-static global that may be referenced
+			 * externally. */
+			fprintf(fp, "Array _%s ->\n",
+				var->identifier);
+			currentvar.type = EXTERN;
+			currentvar.val.identifier = strdup(var->identifier);
+			currentvar.offset = 0;
+			break;
+			
+		case STATIC:
+			fprintf(fp, "Array STATIC_%s_%ld ->\n",
+				modulename, var->offset);
+			currentvar.type = STATIC;
+			currentvar.val.number = var->offset;
+			currentvar.offset = 0;
+			break;
+	}
+}
+
+/* Emit a certain number of bytes of bss data. No bss on the Z-machine,
+ * remember. */
+
+void gen_ds(FILE *fp, zmax size, struct Typ *typ)
+{
+	fprintf(fp, " %ld\n", size);
+	currentvar.offset += size;
+}
+
+/* Emit a certain number of bytes of initialised data. */
+
+void gen_dc(FILE *fp, int typf, struct const_list *p)
+{
+	switch (typf & NQ)
+	{
+		case CHAR:
+			fprintf(fp, " (%d)\n",
+				p->val.vuchar);
+			currentvar.offset += 1;
+			break;
+
+		case SHORT:
+		case INT:
+		reallyanint:
+			fprintf(fp, " (%d) (%d)\n",
+				xbyte(p->val.vint, 1),
+				xbyte(p->val.vint, 0));
+			currentvar.offset += 2;
+			break;
+				
+		case LONG:
+			fprintf(fp, " (%d) (%d) (%d) (%d)\n",
+				xbyte(p->val.vlong, 3),
+				xbyte(p->val.vlong, 2),
+				xbyte(p->val.vlong, 1),
+				xbyte(p->val.vlong, 0));
+			currentvar.offset += 4;
+			break;
+
+		case POINTER:
+			if (!p->tree)
+				goto reallyanint;
+			{
+				struct fixup* fixup = malloc(sizeof(struct fixup));
+				struct obj* obj = &p->tree->o;
+				fixup->next = fixuplist;
+				fixuplist = fixup;
+				fixup->identifier = currentvar;
+
+				switch (obj->v->storage_class)
+				{
+					case EXTERN:
+						fixup->value.type = EXTERN;
+						fixup->value.val.identifier = strdup(obj->v->identifier);
+						break;
+
+					case STATIC:
+						fixup->value.type = STATIC;
+						fixup->value.val.number = obj->v->offset;
+						break;
+
+					default:
+						ierror(0);
+				}
+				fixup->value.offset = 0;
+				fixup->offset = obj->val.vlong;
+				fprintf(fp, " (0) (0)\n");
+				currentvar.offset += 2;
+			}
+			break;
+
+		default:
+			printf("type %d\n", typf);
+			ierror(0);
+	}
+}
+
+/* Returns the offset of the (STATIC or AUTO) given object. */
+
+zmax voff(struct obj* obj)
+{
+	zmax offset = obj->v->offset;
+	if (offset < 0)
+		offset = stackparamadjust + stackoffset - offset - maxalign;
+	else
+		offset += stackparamadjust;
+
+	offset += obj->val.vlong;
+	return offset;
+}
+
+/* When a varargs function is called, we need to find where the parameters are
+ * on the stack in order to make the __va_start magic variable work. This
+ * function does that. */
+
+static int find_varargs(void)
+{
+	int offset = 0;
+	struct reg_handle rh = empty_reg_handle;
+	struct struct_declaration* sd = function->vtyp->exact;
+	int stackalign;
+	int i;
+
+	for (i=0; i<sd->count; i++)
+	{
+		/* Ignore the parameter if it's been assigned a register. */
+
+		if ((*sd->sl)[i].reg != 0)
+			continue;
+
+		/* void shouldn't happen. */
+
+		if (((*sd->sl)[i].styp->flags & NQ) == VOID)
+			ierror(0);
+
+		/* Does the backend want to assign it to a register? */
+
+		if (reg_parm(&rh, (*sd->sl)[i].styp, 0, 0))
+			continue;
+
+		/* Add on the size of this parameter. */
+
+		offset += sizetab[(*sd->sl)[i].styp->flags & NQ];
+
+		/* Stack align. */
+
+		stackalign = align[(*sd->sl)[i].styp->flags & NQ];
+		offset = ((offset+1) / stackalign) * stackalign;
+	}
+
+	return (offset + stackoffset);
+}
+
+/* Output the name of a global. */
+
+static void emit_identifier(FILE* fp, struct obj* obj)
+{
+	switch (obj->v->storage_class)
+	{
+		case STATIC:
+			fprintf(fp, "STATIC_%s_%ld",
+				modulename, obj->v->offset);
+			break;
+
+		case EXTERN:
+			fprintf(fp, "_%s", obj->v->identifier);
+			break;
+
+		default:
+			ierror(0);
+	}
+}
+
+/* Save a register. */
+
+static void write_reg(FILE* fp, struct obj* obj, int typf, int reg)
+{
+	int flags = obj->flags &
+		(KONST|REG|VAR|DREFOBJ|VARADR);
+
+	/* Constant? */
+
+	if (flags == KONST)
+		ierror(0);
+		
+	/* Dereference? */
+
+	if (flags & DREFOBJ)
+		goto dereference;
+
+	/* Register? */
+
+	if ((flags == REG) ||
+	    ((flags & VAR) && (flags & REG) && (obj->v->storage_class == AUTO)) ||
+	    ((flags & VAR) && (flags & REG) && (obj->v->storage_class == REGISTER)))
+	{
+		if (flags & DREFOBJ)
+			fprintf(fp, "\t@store%c %s 0 %s;\n",
+				((typf & NQ) == CHAR) ? 'b' : 'w',
+				regnames[obj->reg], regnames[reg]);
+		else
+		{
+			struct zop in;
+			struct zop out;
+			in.type = ZOP_REG;
+			in.val.reg = reg;
+			out.type = ZOP_REG;
+			out.val.reg = obj->reg;
+			emit_add(fp, &in, &zop_zero, &out);
+		}
+#if 0
+			fprintf(fp, "\t@add %s 0 -> %s;\n",
+				regnames[reg], regnames[obj->reg]);
+#endif
+		return;
+	}
+
+	/* It must be a variable. */
+
+	switch (obj->v->storage_class)
+	{
+		case AUTO:
+		case REGISTER: /* Local variable */
+		{
+			zmax offset = voff(obj);
+
+			if ((typf & NQ) == CHAR)
+				fprintf(fp, "\t@storeb xp 0%+ld %s;\n",
+					offset, regnames[reg]);
+			else
+			{
+				if (offset & 1)
+				{
+					struct zop c;
+					c.type = ZOP_CONSTANT;
+					c.val.constant = offset;
+					emit_add(fp, &zop_xp, &c, &zop_stack);
+					//fprintf(fp, "\t@add xp 0%+ld -> sp;\n", offset);
+					fprintf(fp, "\t@storew sp 0 %s;\n", regnames[reg]);
+				}
+				else
+					fprintf(fp, "\t@storew xp 0%+ld %s;\n",
+						offset >> 1, regnames[reg]);
+			}
+			return;
+		}
+
+		case EXTERN:
+		case STATIC:
+
+			/* Dereference object. */
+
+			if ((typf & NQ) == CHAR)
+			{
+				fprintf(fp, "\t@storeb ");
+				emit_identifier(fp, obj);
+				fprintf(fp, " 0%+ld %s;\n",
+					obj->val.vlong, regnames[reg]);
+			}
+			else
+			{
+				if (obj->val.vlong & 1)
+				{
+					fprintf(fp, "\t@add ");
+					emit_identifier(fp, obj);
+					fprintf(fp, " 0%+ld -> sp;\n",
+						obj->val.vlong);
+					fprintf(fp, "\t@storew sp 0 %s;\n",
+						regnames[reg]);
+				}
+				else
+				{
+					fprintf(fp, "\t@storew ");
+					emit_identifier(fp, obj);
+					fprintf(fp, " 0%+ld %s;\n",
+						obj->val.vlong >> 1, regnames[reg]);
+				}
+			}
+			return;
+#if 0
+		case EXTERN: /* External linkage */
+			if ((typf & NQ) == CHAR)
+				fprintf(fp, "\t@storeb _%s 0%+ld %s;\n",
+					obj->v->identifier, offset, regnames[reg]);
+			else
+			{
+
+				fprintf(fp, "\t@storew _%s 0 %s;\n",
+					obj->v->identifier, regnames[reg]);
+			return;
+
+		case STATIC: /* Static global */
+			if ((typf & NQ) == CHAR)
+				fprintf(fp, "\t@storeb STATIC_%s_%ld 0%+ld %s;\n",
+					modulename, obj->v->offset, offset, regnames[reg]);
+			else
+				fprintf(fp, "\t@storew STATIC_%s_%ld 0 %s;\n",
+					modulename, obj->v->offset, regnames[reg]);
+			return;
+#endif
+
+		default:
+			ierror(0);
+	}
+
+	ierror(0); // Not reached
+dereference:
+	/* These are a *pain*.
+	 *
+	 * The first thing we need to do is to read the old contents of the
+	 * memory cell, to work out the address we need to write to; and then
+	 * do the write. Hurray for the Z-machine stack. */
+
+	obj->flags &= ~DREFOBJ;
+	read_reg(fp, obj, POINTER, 0);
+	fprintf(fp, "\t@store%c sp 0 %s;\n",
+		((typf & NQ) == CHAR) ? 'b' : 'w',
+		regnames[reg]);
+}
+
+/* Move one register to another register. */
+
+static void move_reg(FILE* fp, int reg1, int reg2)
+{
+	struct zop r1;
+	struct zop r2;
+	r1.type = ZOP_REG;
+	r1.val.reg = reg1;
+	r2.type = ZOP_REG;
+	r2.val.reg = reg2;
+	emit_add(fp, &r1, &zop_zero, &r2);
+}
+/* Load a value into a zop. */
+
+static void read_reg(FILE* fp, struct obj* obj, int typf, int reg)
+{
+	int flags = obj->flags &
+		(KONST|REG|VAR|DREFOBJ|VARADR);
+
+	/* The only thing you can do with a function is to take the address of
+	 * it. */
+
+	if ((typf & NQ) == FUNKT)
+		flags &= ~DREFOBJ & ~VARADR;
+
+	/* Is this a memory dereference? */
+
+	if (flags & DREFOBJ)
+		goto dereference;
+	
+	/* Constant? */
+
+	if (flags == KONST)
+	{
+		struct zop c;
+		struct zop r;
+		c.type = ZOP_CONSTANT;
+		//fprintf(fp, "\t@add ");
+		switch (typf & NQ)
+		{
+			case CHAR:		c.val.constant = obj->val.vchar;	break;
+			case UNSIGNED|CHAR:	c.val.constant = obj->val.vuchar;	break;
+			case SHORT:		c.val.constant = obj->val.vshort;	break;
+			case UNSIGNED|SHORT:	c.val.constant = obj->val.vushort;	break;
+		case POINTER:	      ierror(0);
+			case INT:		c.val.constant = obj->val.vint;		break;
+			case UNSIGNED|INT:	c.val.constant = obj->val.vuint;	break;
+			default:
+				ierror(typf);
+		}
+		r.type = ZOP_REG;
+		r.val.reg = reg;
+		emit_add(fp, &c, &zop_zero, &r);
+		//fprintf(fp, " 0 -> %s;\n", regnames[reg]);
+	}
+	else if (flags == REG) /* Register? */
+	{
+		move_reg(fp, obj->reg, reg);
+		//fprintf(fp, "\t@add %s 0 -> %s;\n", regnames[obj->reg], regnames[reg]);
+	}
+	else if ((flags & REG) && ((typf & NQ) == FUNKT)) /* Function pointer? */
+	{
+		move_reg(fp, obj->reg, reg);
+		//fprintf(fp, "\t@add %s 0 -> %s;\n", regnames[obj->reg], regnames[reg]);
+	}
+	else
+	{
+		/* It must be a variable. */
+
+		switch (obj->v->storage_class)
+		{
+			case AUTO:
+			case REGISTER: /* Local variable */
+				if (flags & VARADR)
+				{
+					fprintf(fp, "\t@add xp 0%+ld -> %s;\n",
+						voff(obj), regnames[reg]);
+				}
+				else if (flags & REG)
+				{
+					move_reg(fp, obj->reg, reg);
+					//fprintf(fp, "\t@add %s 0 -> %s;\n",
+					//	regnames[obj->reg], regnames[reg]);
+				}
+				else
+				{
+					zmax offset = voff(obj);
+
+					if ((typf & NQ) == CHAR)
+						fprintf(fp, "\t@loadb xp 0%+ld -> %s;\n",
+							offset, regnames[reg]);
+					else
+					{
+						if (offset & 1)
+						{
+							fprintf(fp, "\t@add xp 0%+ld -> sp;\n", offset);
+							fprintf(fp, "\t@loadw sp 0 -> %s;\n", regnames[reg]);
+						}
+						else
+							fprintf(fp, "\t@loadw xp 0%+ld -> %s;\n",
+								offset >> 1, regnames[reg]);
+					}
+				}
+				break;
+
+			case STATIC:
+			case EXTERN: /* Global variable. Implicit dereference,
+					with the offset in obj->val.vlong. */
+
+				/* ...but functions are never dereferenced. */
+
+				if ((flags & VARADR) ||
+				    ((typf & NQ) == FUNKT))
+				{
+					/* Fetch address of object. */
+
+					fprintf(fp, "\t@add ");
+					emit_identifier(fp, obj);
+					fprintf(fp, " 0%+ld -> %s;\n",
+						obj->val.vlong, regnames[reg]);
+				}
+				else if (strcmp(obj->v->identifier, "__va_start") == 0)
+				{
+					fprintf(fp, "\t@add xp 0%+ld -> %s;\n",
+						find_varargs(), regnames[reg]);
+				}
+				else
+				{
+					/* Dereference object. */
+
+					if ((typf & NQ) == CHAR)
+					{
+						fprintf(fp, "\t@loadb ");
+						emit_identifier(fp, obj);
+						fprintf(fp, " 0%+ld -> %s;\n",
+							obj->val.vlong, regnames[reg]);
+					}
+					else
+					{
+						if (obj->val.vlong & 1)
+						{
+							fprintf(fp, "\t@add ");
+							emit_identifier(fp, obj);
+							fprintf(fp, " 0%+ld -> sp;\n",
+								obj->val.vlong);
+							fprintf(fp, "\t@loadw sp 0 -> %s;\n",
+								regnames[reg]);
+						}
+						else
+						{
+							fprintf(fp, "\t@loadw ");
+							emit_identifier(fp, obj);
+							fprintf(fp, " 0%+ld -> %s;\n",
+								obj->val.vlong >> 1, regnames[reg]);
+						}
+					}
+				}
+				break;
+
+			default:
+				ierror(obj->v->storage_class);
+		}
+	}
+	return;
+
+dereference:
+	/* Do we need to dereference the thing we just fetched? */
+
+	/* Fetch the value to dereference. */
+	obj->flags &= ~DREFOBJ;
+	read_reg(fp, obj, POINTER, 0);
+		
+	if (flags & DREFOBJ)
+	{
+		switch (typf & NQ)
+		{
+			case CHAR:
+				fprintf(fp, "\t@loadb sp 0 -> %s;\n",
+					regnames[reg], regnames[reg]);
+				break;
+
+			case SHORT:
+			case INT:
+			case POINTER:
+			case FUNKT:
+				fprintf(fp, "\t@loadw sp 0 -> %s;\n",
+					regnames[reg], regnames[reg]);
+				break;
+
+			default:
+				ierror(typf & NQ);
+		}
+	}
+}
+
+/* Returns the zop to use for an input parameter, pushing that parameter onto
+ * the stack if necessary. */
+
+static void push_value(FILE* fp, struct obj* obj, int typf, struct zop* op)
+{
+	int flags = obj->flags &
+		(KONST|REG|VAR|DREFOBJ|VARADR);
+
+	if (flags == KONST)
+	{
+		op->type = ZOP_CONSTANT;
+		switch (typf & NU)
+		{
+			case CHAR:		op->val.constant = obj->val.vchar;	break;
+			case UNSIGNED|CHAR:	op->val.constant = obj->val.vuchar;	break;
+			case SHORT:		op->val.constant = obj->val.vshort;	break;
+			case UNSIGNED|SHORT:	op->val.constant = obj->val.vushort;	break;
+			case INT:		op->val.constant = obj->val.vint;	break;
+			case UNSIGNED|INT:	op->val.constant = obj->val.vuint;	break;
+		case POINTER:		ierror(0);
+			default:
+				fprintf(fp, "XXX !!! bad konst type %X\n", typf);
+		}
+		return;
+	}
+
+	/* The only thing you can do with a function is to take the address of it. */
+
+	if ((typf & NQ) == FUNKT)
+		flags &= ~DREFOBJ & ~VARADR;
+
+	/* This is used by the long code. The longop functions can only operate
+	 * on pointers to longs; so if we need to pass in a constant, we have
+	 * to stash it on the stack and return a pointer. */
+
+	if (flags == (KONST|VARADR))
+	{
+		op->type = ZOP_CONSTANTADDR;
+		op->val.constant = addconstant(obj->val.vlong);
+		return;
+	}
+	
+	if (flags == REG)
+	{
+		debugemit(fp, "! zop reg %d\n", obj->reg);
+		op->type = ZOP_REG;
+		op->val.reg = obj->reg;
+		return;
+	}
+
+	if ((flags == (VAR|REG)) &&
+	    ((obj->v->storage_class == AUTO) ||
+	     (obj->v->storage_class == REGISTER)))
+	{
+		debugemit(fp, "! zop var reg %d\n", obj->reg);
+		op->type = ZOP_REG;
+		op->val.reg = obj->reg;
+		return;
+	}
+
+	if ((flags == (VAR|VARADR)) &&
+	    (obj->v->storage_class == EXTERN) &&
+	    (obj->v->offset == 0))
+	{
+		debugemit(fp, "! zop varaddr extern %s\n", obj->v->identifier);
+		op->type = ZOP_EXTERN;
+		op->val.identifier = obj->v->identifier;
+		return;
+	}
+
+	if ((flags == (VAR|VARADR)) &&
+	    (obj->v->storage_class == STATIC) &&
+	    (obj->v->offset == 0))
+	{
+		debugemit(fp, "! zop varaddr static %ld\n", obj->v->offset);
+		op->type = ZOP_STATIC;
+		op->val.constant = obj->v->offset;
+		return;
+	}
+
+	if ((flags & VAR) &&
+	    ((obj->v->vtyp->flags & NQ) == FUNKT))
+	{
+		if (obj->v->storage_class == EXTERN)
+		{
+			op->type = ZOP_EXTERN;
+			op->val.identifier = obj->v->identifier;
+		}
+		else
+		{
+			op->type = ZOP_STATIC;
+			op->val.constant = obj->v->offset;
+		}
+		return;
+	}
+	
+	read_reg(fp, obj, typf, 0);
+	op->type = ZOP_STACK;
+}
+
+/* Same as push_value(), but returns a zop for the *address* of the object, not
+ * the object itself. Used a lot by the long code. */
+
+static void push_addrof(FILE* fp, struct obj* obj, int typf, struct zop* op)
+{
+	if (obj->flags & DREFOBJ)
+		obj->flags &= ~DREFOBJ;
+	else
+		obj->flags |= VARADR;
+	push_value(fp, obj, POINTER, op);
+}
+
+/* Returns the zop to use for an output parameter. Unlike push_value, this does
+ * not emit a pop; that must be done later, if the return parameter is zero. */
+
+static void pop_value(FILE* fp, struct obj* obj, int typf, struct zop* op)
+{
+	int flags = obj->flags &
+		(KONST|REG|VAR|DREFOBJ|VARADR);
+
+	/* We don't even *try* to handle dereferences here. */
+
+	if (flags & DREFOBJ)
+		goto stack;
+
+	if (flags == REG)
+		goto reg;
+
+	if ((flags == (VAR|REG)) &&
+	    ((obj->v->storage_class == AUTO) ||
+	     (obj->v->storage_class == REGISTER)))
+		goto reg;
+
+stack:
+	op->type = ZOP_STACK;
+	return;
+
+reg:
+	op->type = ZOP_REG;
+	op->val.reg = obj->reg;
+}
+
+/* Writes code for a zop. */
+
+static void emit_zop(FILE* fp, struct zop* op)
+{
+	switch (op->type)
+	{
+		case ZOP_STACK:
+			fprintf(fp, "sp");
+			return;
+
+		case ZOP_REG:
+			fprintf(fp, "%s", regnames[op->val.reg]);
+			return;
+
+		case ZOP_CONSTANT:
+			fprintf(fp, "0%+ld", (zshort)op->val.constant);
+			return;
+
+		case ZOP_EXTERN:
+			fprintf(fp, "_%s", op->val.identifier);
+			return;
+
+		case ZOP_STATIC:
+			fprintf(fp, "STATIC_%s_%ld",
+				modulename, op->val.constant);
+			return;
+
+		case ZOP_CONSTANTADDR:
+			fprintf(fp, "CONSTANT_%s_%ld",
+				modulename, op->val.constant);
+			return;
+
+		default:
+			ierror(op->type);
+	}
+}
+
+/* This is used in conjunction with pop_value(). pop_value() returns a zop that
+ * represents the return value for a function. If that return value is the
+ * stack, the value on the stack needs to be written back into memory. That's
+ * what this function does. */
+
+static void fin_zop(FILE* fp, struct obj* obj, int typf, struct zop* op)
+{
+	switch (op->type)
+	{
+		case ZOP_STACK:
+			write_reg(fp, obj, typf, 0);
+			return;
+
+		case ZOP_REG:
+			return;
+
+		default:
+			ierror(0);
+	}
+}
+
+/* Emit a basic ADD instruction.
+ * This routine tests for all the various special cases, of which there are
+ * many, and attempts to produce optimal code.
+ */
+
+static void emit_add(FILE* fp, struct zop* q1, struct zop* q2, struct zop* z)
+{
+	/* Sometimes we get ZOP_REG with reg=0. This actually means the stack. */
+
+	if ((q1->type == ZOP_REG) && (q1->val.reg == 0))
+		q1 = &zop_stack;
+	if ((q2->type == ZOP_REG) && (q2->val.reg == 0))
+		q2 = &zop_stack;
+	if ((z->type == ZOP_REG) && (z->val.reg == 0))
+		z = &zop_stack;
+
+	/* If q2 is a constant and 0, then this might be a register move of
+	 * some kind. */
+
+	if ((q2->type == ZOP_CONSTANT) && (q2->val.constant == 0))
+	{
+		/* Left is a register? */
+		if (q1->type == ZOP_REG)
+		{
+			/* Right is a register? */
+			if (z->type == ZOP_REG)
+			{
+				/* They're the *same* register? */
+				if (q1->val.reg == z->val.reg)
+				{
+					/* No code need be emitted. */
+					return;
+				}
+
+				/* Emit a @store instruction. Unfortunately, I
+				 * can't work out the syntax for Inform's
+				 * @store opcode, so we emit a high-level
+				 * assignment instead and let Inform work it
+				 * out. */
+
+				fprintf(fp, "\t");
+				emit_zop(fp, z);
+				fprintf(fp, " = ");
+				emit_zop(fp, q1);
+				fprintf(fp, ";\n");
+				return;
+			}
+
+			/* Right is the stack? */
+			if (z->type == ZOP_STACK)
+			{
+				/* We're pushing the single parameter onto the
+				 * stack. */
+
+				fprintf(fp, "\t@push ");
+				emit_zop(fp, q1);
+				fprintf(fp, ";\n");
+				return;
+			}
+		}
+
+		/* Left is the stack? */
+		if (q1->type == ZOP_STACK)
+		{
+			/* Right is a register? */
+			if (z->type == ZOP_REG)
+			{
+				/* We're popping the single parameter off the
+				 * stack. */
+
+				fprintf(fp, "\t@pull ");
+				emit_zop(fp, z);
+				fprintf(fp, ";\n");
+				return;
+			}
+		}
+	}
+
+	/* Fall back on an ordinary @add. */
+
+	fprintf(fp, "\t@add ");
+	emit_zop(fp, q1);
+	fprintf(fp, " ");
+	emit_zop(fp, q2);
+	fprintf(fp, " -> ");
+	emit_zop(fp, z);
+	fprintf(fp, ";\n");
+}
+
+/* Copy a value from one zop to another. This is not quite as simple as you
+ * might think, because there are a number of optimisation cases to take into
+ * account.
+ *
+ * NOTE: for simplicity, this function will never emit just a single
+ * instruction --- the assignment is always done via the stack. FIXME. */
+
+static void move_value(FILE* fp, struct obj* q1o, struct obj* zo, int typf)
+{
+	struct zop q1;
+	struct zop z;
+
+	pop_value(fp, zo, typf, &z);
+	push_value(fp, q1o, typf, &q1);
+	debugemit(fp, "! L=%d R=%d\n", q1.type, z.type);
+	/* In all cases except when push_value() and fin_zop() *both* emit
+	 * code, we need to insert an assignment here. As they only emit code
+	 * in the ZOP_STACK case... */
+	if ((q1.type != ZOP_STACK) || (z.type != ZOP_STACK))
+	{
+		emit_add(fp, &q1, &zop_zero, &z);
+#if 0
+		fprintf(fp, "\t@add ");
+		emit_zop(fp, &q1);
+		fprintf(fp, " 0 -> ");
+		emit_zop(fp, &z);
+		fprintf(fp, ";\n");
+#endif
+	}
+	fin_zop(fp, zo, typf, &z);
+}
+	
+/* Copy a 32-bit value from one obj to another. */
+
+static void move_long_value(FILE* fp, struct obj* q1, struct obj* z, int typf)
+{
+	int flags = q1->flags &
+		(KONST|REG|VAR|DREFOBJ|VARADR);
+	struct zop q1z;
+	struct zop zz;
+	
+	if (flags == KONST)
+	{
+		int hi = xword(q1->val.vlong, 1);
+		int lo = xword(q1->val.vlong, 0);
+
+		push_addrof(fp, z, POINTER, &zz);
+		fprintf(fp, "\t@call_vn __long_loadconst ");
+		emit_zop(fp, &zz);
+		fprintf(fp, " 0%+ld 0%+ld;\n", (short)hi, (short)lo);
+		return;
+	}
+
+	push_addrof(fp, z, POINTER, &zz);
+	push_addrof(fp, q1, POINTER, &q1z);
+	fprintf(fp, "\t@copy_table ");
+	emit_zop(fp, &q1z);
+	fprintf(fp, " ");
+	emit_zop(fp, &zz);
+	fprintf(fp, " 4;\n");
+}
+
+/* The code generator itself.
+ * This big, complicated, hairy and scary function does the work to actually
+ * produce the code.  fp is the output stream, ic the beginning of the ic
+ * chain, func is a pointer to the actual function and stackframe is the size
+ * of the function's stack frame.
+ */
+
+void gen_code(FILE* fp, struct IC *ic, struct Var* func, zmax stackframe)
+{
+	int i;
+	struct zop q1;
+	struct zop q2;
+	struct zop z;
+	int code, typf; // ...of the IC under consideration
+
+    int c,t,lastcomp=0,reg;
+	    
+    	function = func;
+
+	/* r0..r5 are always used for parameter passing. */
+
+	regused[2] = 1;
+	regused[3] = 1;
+	regused[4] = 1;
+	regused[5] = 1;
+	regused[6] = 1;
+	regused[7] = 1;
+
+	/* This is the offset of the stack frame, relative to the current stack
+	 * pointer. */
+
+	stackoffset = stackframe;
+
+	/* No parameters pushed yet. */
+
+	stackparamadjust = 0;
+
+	reflower(fp);
+
+	if (func->storage_class == STATIC)
+		fprintf(fp, "[ STATIC_%s_%ld xp\n", modulename, func->offset);
+	else
+		fprintf(fp, "[ _%s xp\n", func->identifier);
+
+	/* Tell Inform what registers the function is using. */
+
+	for (i=1; i<=MAXR; i++)
+	{
+		//fprintf(fp, "! i=%d used %d scratch %d alloc %d\n",
+		//		i, regused[i], regscratch[i], regsa[i]);
+		if (regused[i] && !regsa[i])
+			fprintf(fp, "\t%s\n", regnames[i]);
+	}
+	fprintf(fp, ";\n");
+
+	/* Trace the function name. */
+
+	if (g_flags[1] & USEDFLAG)
+	{
+		if (func->storage_class == STATIC)
+			fprintf(fp, "print \"STATIC_%s_%ld^\";\n", modulename, func->offset);
+		else
+			fprintf(fp, "print \"_%s^\";\n", func->identifier);
+	}
+	
+	/* Adjust stack for locals. */
+
+	if (stackframe)
+		fprintf(fp, "\t@sub xp 0%+ld -> xp;\n", stackframe);
+	//if (stackoffset)
+	//	fprintf(fp, "\txp = xp - %ld\n", stackframe);
+
+    
+    	/* Iterate through all ICs. */
+
+	for (; dump_ic(fp, ic), ic; ic=ic->next)
+	{
+        c=ic->code;t=ic->typf;
+		code = ic->code;
+		typf = ic->typf;
+
+		/* Do nothing for NOPs. */
+
+		if (code == NOP)
+			continue;
+
+		/* Has the stack been adjusted due to a call? */
+
+#if 0
+		if (stackcalladjustment)
+		{
+			if ((code != GETRETURN) &&
+			    (code != FREEREG) &&
+			    (code != ALLOCREG))
+			{
+				debugemit(fp, "! stack reset %d %d\n",
+					stackparamadjust, stackcallparamsize);
+				fprintf(fp, "\t@add xp %d -> xp;\n",
+					stackparamadjust+stackcallparamsize);
+				stackparamadjust = 0;
+				stackcallparamsize = 0;
+				stackcalladjustment = 0;
+			}
+		}
+#endif
+
+#if 0
+        if(notpopped&&!dontpop){
+            int flag=0;
+            if(c==LABEL||c==COMPARE||c==TEST||c==BRA){
+                fprintf(fp,"\tadd\t%s,#%ld\n",regnames[sp],notpopped);
+                stackoffset+=notpopped;notpopped=0;
+            }
+        }
+#endif
+		/* These opcodes turn into other opcodes. */
+
+		switch (code)
+		{
+			case SUBPFP:
+			case SUBIFP:
+				code = SUB;
+				break;
+
+			case ADDI2P:
+				code = ADD;
+				break;
+		}
+
+		/* And now the big opcode switch. */
+
+		switch (code)
+		{
+			case ALLOCREG: /* Mark register in use */
+				regs[ic->q1.reg] = 1;
+				continue;
+
+			case FREEREG: /* Mark register not in use */
+				regs[ic->q1.reg] = 0;
+				continue;
+
+			case LABEL: /* Emit jump target */
+				fprintf(fp, ".%s%d;\n",
+					labelprefix, typf);
+				continue;
+
+			case BRA: /* Unconditional jump */
+				fprintf(fp, "\tjump %s%d;\n",
+					labelprefix, typf);
+				continue;
+
+			case GETRETURN: /* Read the last function call's return parameter */
+				switch (typf & NQ)
+				{
+					case CHAR:
+						//if (ic->q2.val.vlong != 1)
+						//	goto copy_struct;
+						/* fall through */
+					case SHORT:
+					case INT:
+					case POINTER:
+						write_reg(fp, &ic->z, typf, 2);
+						break;
+
+						/* Ignore the following; the
+						 * front-end will automatically
+						 * pass in an implicit
+						 * parameter to the function
+						 * containing the address of
+						 * the return parameter, so
+						 * GETRETURN ought to be a
+						 * noop. */
+					case LONG:
+					case STRUCT:
+					case VOID:
+					case ARRAY:
+						break;
+#if 0
+					copy_struct:
+						push_addrof(fp, &ic->z, typf, &z);
+						fprintf(fp, "\t@copy_table xp ");
+						emit_zop(fp, &z);
+						fprintf(fp, " %ld;\n", szof(ic->z.v->vtyp));
+						break;
+#endif
+
+					default:
+						ierror(typf & NQ);
+				}
+				//fprintf(fp, "\tr0 = ");
+				//emit_object(fp, &ic->q1, typf);
+				//fprintf(fp, ";\n");
+				//write_reg(fp, &ic->z, typf, 2);
+				continue;
+
+			case SETRETURN: /* Set this function's return parameter */
+				switch (typf & NQ)
+				{
+					case CHAR:
+						//if (ic->q2.val.vlong != 1)
+						//	goto setreturn_copy_struct;
+
+						/* fall through */
+					case SHORT:
+					case INT:
+					case POINTER:
+						read_reg(fp, &ic->q1, typf, 2);
+						break;
+
+					case LONG:
+					case STRUCT:
+					case VOID:
+					case ARRAY:
+#if 0
+					setreturn_copy_struct:
+						fprintf(fp, "\t@add xp %ld -> sp;\n",
+							stackoffset);
+						push_addrof(fp, &ic->q1, typf, &q1);
+						fprintf(fp, "\t@copy_table ");
+						emit_zop(fp, &q1);
+						fprintf(fp, " sp %ld;\n", szof(ic->q1.v->vtyp));
+						break;
+#endif
+
+					default:
+						ierror(typf & NQ);
+				}
+				//fprintf(fp, "\tr0 = ");
+				//emit_object(fp, &ic->q1, typf);
+				//fprintf(fp, ";\n");
+				continue;
+
+			case MINUS: /* Unary minus */
+				switch (typf & NQ)
+				{
+					case CHAR:
+					case SHORT:
+					case INT:
+						push_value(fp, &ic->q1, typf, &q1);
+						pop_value(fp, &ic->z, typf, &z);
+						fprintf(fp, "\t@sub 0 ");
+						emit_zop(fp, &q1);
+						fprintf(fp, " -> ");
+						emit_zop(fp, &z);
+						fprintf(fp, ";\n");
+						fin_zop(fp, &ic->z, typf, &z);
+						break;
+
+					case LONG:
+						push_addrof(fp, &ic->z, typf, &z);
+						push_addrof(fp, &ic->q1, typf, &q1);
+						fprintf(fp, "\t@call_vn __long_neg ");
+						emit_zop(fp, &q1);
+						fprintf(fp, " ");
+						emit_zop(fp, &z);
+						fprintf(fp, ";\n");
+						break;
+
+					default:
+						ierror(0);
+				}
+				continue;
+
+			case KOMPLEMENT: /* Unary komplement */
+				/* INFORM BUG! */
+				/* The @not opcode doesn't work. We have to use a
+				 * wrapper function instead. */
+				
+				push_value(fp, &ic->q1, typf, &q1);
+				pop_value(fp, &ic->z, typf, &z);
+				fprintf(fp, "\t@call_2s __not ");
+				emit_zop(fp, &q1);
+				fprintf(fp, " -> ");
+				emit_zop(fp, &z);
+				fprintf(fp, ";\n");
+				fin_zop(fp, &ic->z, typf, &z);
+				continue;
+
+			case MOVEFROMREG: /* Write a register to memory */
+				write_reg(fp, &ic->z, typf, ic->q1.reg);
+				continue;
+
+			case MOVETOREG: /* Read a register from memory */
+				read_reg(fp, &ic->q1, typf, ic->z.reg);
+				continue;
+
+			case ASSIGN: /* Move something to somewhere else */
+				debugemit(fp, "! ASSIGN size %d typf %d\n", ic->q2.val.vlong, typf & NQ);
+				switch (typf & NQ)
+				{
+					case CHAR:
+						if (ic->q2.val.vlong != 1)
+							goto assign_copy_struct;
+						/* fall through */
+					case SHORT:
+					case INT:
+					case POINTER:
+						move_value(fp, &ic->q1, &ic->z, typf);
+						break;
+
+					case LONG:
+						move_long_value(fp, &ic->q1, &ic->z, typf);
+						break;
+
+					case STRUCT:
+					case VOID:
+					case ARRAY:
+					assign_copy_struct:
+						push_addrof(fp, &ic->z, typf, &z);
+						push_addrof(fp, &ic->q1, typf, &q1);
+						fprintf(fp, "\t@copy_table ");
+						emit_zop(fp, &q1);
+						fprintf(fp, " ");
+						emit_zop(fp, &z);
+						fprintf(fp, " 0%+ld;\n", ic->q2.val.vlong);
+						break;
+
+					default:
+						ierror(typf & NQ);
+				}
+				continue;
+
+			case ADDRESS: /* Fetch the address of something, always
+					 AUTO or STATIC */
+				i = voff(&ic->q1);
+				pop_value(fp, &ic->z, typf, &z);
+				fprintf(fp, "\t@add xp 0%+ld -> ", i);
+				emit_zop(fp, &z);
+				fprintf(fp, ";\n");
+				fin_zop(fp, &ic->z, typf, &z);
+				continue;
+
+			case PUSH: /* Push a value onto the stack */
+				fprintf(fp, "\t@sub xp 0%+ld -> xp;\n",
+					ic->q2.val.vlong);
+				//stackoffset += ic->q2.val.vlong;
+				stackparamadjust += ic->q2.val.vlong;
+
+				switch (ic->q2.val.vlong)
+				{
+					case 1:
+						push_value(fp, &ic->q1, typf, &q1);
+						fprintf(fp, "\t@storeb xp 0 ");
+						emit_zop(fp, &q1);
+						fprintf(fp, ";\n");
+						break;
+
+					case 2:
+						push_value(fp, &ic->q1, typf, &q1);
+						fprintf(fp, "\t@storew xp 0 ");
+						emit_zop(fp, &q1);
+						fprintf(fp, ";\n");
+						break;
+
+					default:
+						push_addrof(fp, &ic->q1, typf, &q1);
+						fprintf(fp, "\t@copy_table ");
+						emit_zop(fp, &q1);
+						fprintf(fp, " xp 0%+ld;\n", ic->q2.val.vlong);
+						break;
+				}
+				continue;
+
+			case ADD: /* Add two numbers */
+			case SUB: /* Subtract two numbers */
+			case MULT: /* Multiply two numbers */
+			case DIV: /* Divide two numbers */
+			case MOD: /* Modulo two numbers */
+			case OR: /* Bitwise or */
+			case XOR: /* Bitwise xor */
+			case AND: /* Bitwise and */
+			case LSHIFT: /* Shift left */
+			case RSHIFT: /* Shift right */
+				switch (typf & NQ)
+				{
+					case CHAR:
+					case SHORT:
+					case INT:
+					case POINTER:
+						/* Second parameter first! */
+						push_value(fp, &ic->q2, typf, &q2);
+
+						if (code == RSHIFT)
+						{
+							fprintf(fp, "\t@sub 0 ");
+							emit_zop(fp, &q2);
+							fprintf(fp, " -> sp;\n");
+							q2.type = ZOP_STACK;
+						}
+
+						push_value(fp, &ic->q1, typf, &q1);
+						pop_value(fp, &ic->z, typf, &z);
+						//fprintf(fp, "\t");
+						//emit_object(fp, &ic->z, typf);
+						//fprintf(fp, " = ");
+						//emit_object(fp, &ic->q1, typf);
+						switch (code)
+						{
+							case ADD:
+								fprintf(fp, "\t@add ");
+								break;
+
+							case SUB:
+								fprintf(fp, "\t@sub ");
+								break;
+
+							case MULT:
+								fprintf(fp, "\t@mul ");
+								break;
+
+							case DIV:
+								if (typf & UNSIGNED)
+									fprintf(fp, "\t@call_vs __unsigned_div ");
+								else
+									fprintf(fp, "\t@div ");
+								break;
+
+							case MOD:
+								if (typf & UNSIGNED)
+									fprintf(fp, "\t@call_vs __unsigned_mod ");
+								else
+									fprintf(fp, "\t@mod ");
+								break;
+
+							case AND:
+								fprintf(fp, "\t@and ");
+								break;
+
+							case XOR:
+								fprintf(fp, "\t@call_vs __xor ");
+								break;
+
+							case OR:
+								fprintf(fp, "\t@or ");
+								break;
+
+							case LSHIFT:
+							case RSHIFT:
+								if (typf & UNSIGNED)
+									fprintf(fp, "\t@log_shift ");
+								else
+									fprintf(fp, "\t@art_shift ");
+								break;
+
+							default:
+								/* Should never get here! */
+								ierror(0);
+						}
+						emit_zop(fp, &q1);
+						fprintf(fp, " ");
+						emit_zop(fp, &q2);
+						fprintf(fp, " -> ");
+						emit_zop(fp, &z);
+						fprintf(fp, ";\n");
+						fin_zop(fp, &ic->z, typf, &z);
+						//emit_object(fp, &ic->q2, typf);
+						break;
+
+					case LONG:
+						/* Destination parameter first! */
+
+						push_addrof(fp, &ic->z, typf, &z);
+						push_addrof(fp, &ic->q2, typf, &q2);
+						push_addrof(fp, &ic->q1, typf, &q1);
+
+						fprintf(fp, "\t@call_vn __long_");
+						switch (code)
+						{
+							case ADD:
+								fprintf(fp, "add");
+								break;
+
+							case SUB:
+								fprintf(fp, "sub");
+								break;
+
+							case MULT:
+								fprintf(fp, "mul");
+								break;
+
+							case DIV:
+								if (typf & UNSIGNED)
+									fprintf(fp, "unsigned_div");
+								else
+									fprintf(fp, "div");
+								break;
+
+							case MOD:
+								if (typf & UNSIGNED)
+									fprintf(fp, "unsigned_mod");
+								else
+									fprintf(fp, "mod");
+								break;
+
+							case AND:
+								fprintf(fp, "and");
+								break;
+
+							case XOR:
+								fprintf(fp, "xor");
+								break;
+
+							case OR:
+								fprintf(fp, "or");
+								break;
+
+							case LSHIFT:
+								fprintf(fp, "lsl");
+								break;
+								
+							case RSHIFT:
+								if (typf & UNSIGNED)
+									fprintf(fp, "lsr");
+								else
+									fprintf(fp, "asr");
+								break;
+
+							default:
+								/* Should never get here! */
+								ierror(0);
+						}
+						fprintf(fp, " ");
+						emit_zop(fp, &q1);
+						fprintf(fp, " ");
+						emit_zop(fp, &q2);
+						fprintf(fp, " ");
+						emit_zop(fp, &z);
+						fprintf(fp, ";\n");
+						break;
+
+					default:
+						ierror(0);
+				}
+				continue;
+
+		case CONVERT:
+		  if((q1typ(ic)&NU)==CHAR){
+				switch (ztyp(ic) & NU)
+				{
+					case CHAR:
+					case UNSIGNED|CHAR:
+					case UNSIGNED|SHORT:
+					case UNSIGNED|INT:
+					case SHORT:
+					case INT:
+						push_value(fp, &ic->q1, CHAR, &q1);
+						pop_value(fp, &ic->z, typf, &z);
+						fprintf(fp, "\t@log_shift ");
+						emit_zop(fp, &q1);
+						fprintf(fp, " 8 -> sp;\n");
+						fprintf(fp, "\t@art_shift sp 0-8 -> ");
+						emit_zop(fp, &z);
+						fprintf(fp, ";\n");
+						fin_zop(fp, &ic->z, typf, &z);
+						break;
+					
+					case LONG:
+						push_value(fp, &ic->q1, INT, &q1);
+						push_addrof(fp, &ic->z, typf, &z);
+						fprintf(fp, "\t@call_vn __long_fromchar");
+						emit_zop(fp, &z);
+						fprintf(fp, " ");
+						emit_zop(fp, &q1);
+						fprintf(fp, ";\n");
+						break;
+
+					default:
+						ierror(0);
+				}
+				continue;
+		  }
+		  if((q1typ(ic)&NU)==(UNSIGNED|CHAR)){
+
+				switch (ztyp(ic) & NQ)
+				{
+					case CHAR:
+					case SHORT:
+					case INT:
+						push_value(fp, &ic->q1, UNSIGNED|CHAR, &q1);
+						pop_value(fp, &ic->z, typf, &z);
+						if ((z.type != ZOP_STACK) || (q1.type != ZOP_STACK))
+						{
+							emit_add(fp, &q1, &zop_zero, &z);
+#if 0
+							fprintf(fp, "\t@add ");
+							emit_zop(fp, &q1);
+							fprintf(fp, " 0 -> ");
+							emit_zop(fp, &z);
+							fprintf(fp, ";\n");
+#endif
+						}
+						fin_zop(fp, &ic->z, typf, &z);
+						break;
+					
+					case LONG:
+						push_value(fp, &ic->q1, UNSIGNED|CHAR, &q1);
+						push_addrof(fp, &ic->z, typf, &z);
+						fprintf(fp, "\t@call_vn __long_fromint");
+						emit_zop(fp, &z);
+						fprintf(fp, " 0 ");
+						emit_zop(fp, &q1);
+						fprintf(fp, ";\n");
+						break;
+						
+					default:
+						ierror(0);
+				}
+				continue;
+		  }
+		  if((q1typ(ic)&NU)==SHORT||(q1typ(ic)&NU)==INT){
+				switch (ztyp(ic) & NU)
+				{
+					case CHAR:
+					case UNSIGNED|CHAR:
+					case UNSIGNED|SHORT:
+					case UNSIGNED|INT:
+					case SHORT:
+					case INT:
+						push_value(fp, &ic->q1, INT, &q1);
+						pop_value(fp, &ic->z, typf, &z);
+						if ((z.type != ZOP_STACK) || (q1.type != ZOP_STACK))
+						{
+							emit_add(fp, &q1, &zop_zero, &z);
+#if 0
+							fprintf(fp, "\t@add ");
+							emit_zop(fp, &q1);
+							fprintf(fp, " 0 -> ");
+							emit_zop(fp, &z);
+							fprintf(fp, ";\n");
+#endif
+						}
+						fin_zop(fp, &ic->z, typf, &z);
+						break;
+
+					case LONG:
+						push_value(fp, &ic->q1, INT, &q1);
+						push_addrof(fp, &ic->z, typf, &z);
+						fprintf(fp, "\t@call_vn __long_fromint ");
+						emit_zop(fp, &z);
+						fprintf(fp, " ");
+						emit_zop(fp, &q1);
+						fprintf(fp, ";\n");
+						break;
+
+					case UNSIGNED|LONG:
+						push_value(fp, &ic->q1, INT, &q1);
+						push_addrof(fp, &ic->z, typf, &z);
+						fprintf(fp, "\t@call_vn __long_loadconst ");
+						emit_zop(fp, &z);
+						fprintf(fp, " 0 ");
+						emit_zop(fp, &q1);
+						fprintf(fp, ";\n");
+						break;
+					
+					default:
+						ierror(typf);
+				}
+				continue;
+		}
+		if((q1typ(ic)&NU)==(UNSIGNED|SHORT)||(q1typ(ic)&NU)==(UNSIGNED|INT)||(q1typ(ic)&NU)==POINTER){
+
+				switch (ztyp(ic) & NQ)
+				{
+					case CHAR:
+					case SHORT:
+					case INT:
+						push_value(fp, &ic->q1, INT, &q1);
+						pop_value(fp, &ic->z, typf, &z);
+						if ((z.type != ZOP_STACK) || (q1.type != ZOP_STACK))
+						{
+							emit_add(fp, &q1, &zop_zero, &z);
+#if 0
+							fprintf(fp, "\t@add ");
+							emit_zop(fp, &q1);
+							fprintf(fp, " 0 -> ");
+							emit_zop(fp, &z);
+							fprintf(fp, ";\n");
+#endif
+						}
+						fin_zop(fp, &ic->z, typf, &z);
+						break;
+
+					case LONG:
+						push_value(fp, &ic->q1, INT, &q1);
+						push_addrof(fp, &ic->z, typf, &z);
+						fprintf(fp, "\t@call_vn __long_loadconst ");
+						emit_zop(fp, &z);
+						fprintf(fp, " 0 ");
+						emit_zop(fp, &q1);
+						fprintf(fp, ";\n");
+						break;
+#if 0
+					case SHORT:
+					case INT:
+						fprintf(fp, "\t");
+						emit_object(fp, &ic->z, typf);
+						fprintf(fp, " = (");
+						emit_object(fp, &ic->q1, CHAR);
+						fprintf(fp, ") << 8 >> 8;\n");
+						break;
+#endif
+					
+					default:
+						printf("%X\n", typf);
+						ierror(0);
+				}
+				continue;
+		}
+		if((q1typ(ic)&NU)==(UNSIGNED|LONG)||(q1typ(ic)&NU)==LONG){
+
+				switch (ztyp(ic) & NQ)
+				{
+					case CHAR:
+						push_addrof(fp, &ic->q1, LONG, &q1);
+						pop_value(fp, &ic->z, typf, &z);
+						fprintf(fp, "\t@loadb ");
+						emit_zop(fp, &q1);
+						fprintf(fp, " 3 -> ");
+						emit_zop(fp, &z);
+						fprintf(fp, ";\n");
+						fin_zop(fp, &ic->z, typf, &z);
+						break;
+
+					case SHORT:
+					case INT:
+						push_addrof(fp, &ic->q1, LONG, &q1);
+						pop_value(fp, &ic->z, typf, &z);
+						fprintf(fp, "\t@loadw ");
+						emit_zop(fp, &q1);
+						fprintf(fp, " 1 -> ");
+						emit_zop(fp, &z);
+						fprintf(fp, ";\n");
+						fin_zop(fp, &ic->z, typf, &z);
+						break;
+					
+					default:
+						ierror(typf & NQ);
+				}
+				continue;
+		}
+			case COMPARE:
+				/* COMPARE is special. The next instruction is
+				 * always a branch.  The Z-machine does
+				 * branches in the form:
+				 *
+				 * @j{e,g,l} <var1> <var2> [~]@<label>
+				 *
+				 * However, we don't know what short of branch
+				 * to emit until the next instruction (which is
+				 * the IC for a branch). So we have to stash
+				 * the zops that we're using for the
+				 * compare here, for use later. This is done
+
+				 * using the globals compare1 and compare2.
+				 */
+
+				switch (typf & NU)
+				{
+					case CHAR:
+					case SHORT:
+					case INT:
+					case POINTER:
+						/* Second parameter first! */
+						push_value(fp, &ic->q2, typf, &compare2);
+						push_value(fp, &ic->q1, typf, &compare1);
+						break;
+
+					case UNSIGNED|CHAR:
+					case UNSIGNED|SHORT:
+					case UNSIGNED|INT:
+						/* Because the Z-machine only
+						 * has signed comparisons, we
+						 * need a dodgy algorithm to
+						 * do this, which works as
+						 * follows: in the signed
+						 * domain, 0-7FFF compares
+						 * greater than 8000-FFFF. In
+						 * the unsigned domain, it's
+						 * the other way around. So,
+						 * by flipping the sign bits
+						 * we do the logical
+						 * equivalent of shifting the
+						 * unsigned range up/down by
+						 * 8000 which makes it fit
+						 * the signed range. There.
+						 * Did you understand that?
+						 * Neither did I, the first
+						 * few times it was explained
+						 * to me. */
+						read_reg(fp, &ic->q2, typf, 0);
+						fprintf(fp, "\t@add sp $8000 -> sp;\n");
+						read_reg(fp, &ic->q1, typf, 0);
+						fprintf(fp, "\t@add sp $8000 -> sp;\n");
+						compare1.type = ZOP_STACK;
+						compare2.type = ZOP_STACK;
+						break;
+
+					case LONG:
+						push_addrof(fp, &ic->q2, typf, &q2);
+						push_addrof(fp, &ic->q1, typf, &q1);
+						fprintf(fp, "\t@call_vs __long_compare ");
+						emit_zop(fp, &q1);
+						fprintf(fp, " ");
+						emit_zop(fp, &q2);
+						fprintf(fp, " -> sp;\n");
+						compare1.type = ZOP_STACK;
+						compare2.type = ZOP_CONSTANT;
+						compare2.val.constant = 0;
+						break;
+
+					case UNSIGNED|LONG:
+						push_addrof(fp, &ic->q2, typf, &q2);
+						push_addrof(fp, &ic->q1, typf, &q1);
+						fprintf(fp, "\t@call_vs __long_unsigned_compare ");
+						emit_zop(fp, &q1);
+						fprintf(fp, " ");
+						emit_zop(fp, &q2);
+						fprintf(fp, " -> sp;\n");
+						compare1.type = ZOP_STACK;
+						compare2.type = ZOP_CONSTANT;
+						compare2.val.constant = 0;
+						break;
+
+					default:
+						ierror(typf & NQ);
+				}
+				continue;
+
+			case TEST:
+				/* TEST is a special COMPARE. It takes one
+				 * parameter and always tests it against 0; it
+				 * is guaranteed to be followed by BNE or BEQ.
+				 * */
+
+				switch (typf & NQ)
+				{
+					case CHAR:
+					case SHORT:
+					case INT:
+					case POINTER:
+						push_value(fp, &ic->q1, typf, &compare1);
+						compare2.type = ZOP_CONSTANT;
+						compare2.val.constant = 0;
+						break;
+
+					case LONG:
+						push_addrof(fp, &ic->q1, typf, &q1);
+						fprintf(fp, "\t@call_vs __long_compare ");
+						emit_zop(fp, &q1);
+						fprintf(fp, " ");
+						q2.type = ZOP_CONSTANTADDR;
+						q2.val.constant = addconstant(0);
+						emit_zop(fp, &q2);
+						fprintf(fp, " -> sp;\n", i);
+						compare1.type = ZOP_STACK;
+						compare2.type = ZOP_CONSTANT;
+						compare2.val.constant = 0;
+						break;
+
+					default:
+						ierror(typf & NQ);
+				}
+				continue;
+
+			case BEQ:
+			case BNE:
+			case BLT:
+			case BGE:
+			case BLE:
+			case BGT:
+			{
+				static int branchlabel = 0;
+
+				fprintf(fp, "\t@j");
+				switch (code)
+				{
+					case BNE:
+					case BEQ:	fprintf(fp, "e ");	break;
+					case BLT:
+					case BGE:	fprintf(fp, "l ");	break;
+					case BGT:
+					case BLE:	fprintf(fp, "g ");	break;
+				}
+
+				emit_zop(fp, &compare1);
+				fprintf(fp, " ");
+				emit_zop(fp, &compare2);
+				fprintf(fp, " ?");
+
+				if (g_flags[3] & USEDFLAG)
+				{
+					if (!((code == BNE) || (code == BGE) || (code == BLE)))
+						fprintf(fp, "~");
+					fprintf(fp, "LL%d;\n", branchlabel);
+					fprintf(fp, "\tjump %s%d;\n", labelprefix, typf);
+					fprintf(fp, ".LL%d;\n", branchlabel++);
+				}
+				else
+				{
+					if ((code == BNE) || (code == BGE) || (code == BLE))
+						fprintf(fp, "~");
+					fprintf(fp, "%s%d;\n", labelprefix, typf);
+				}
+				continue;
+			}
+
+			case CALL:
+			{
+#if 0
+				/* Calculate the amount of stack to reserve for
+				 * the return parameter. ints and smaller go in
+				 * the return register. */
+
+				stackcallparamsize = szof(ic->q1.v->vtyp->next);
+				if (stackcallparamsize <= sizetab[INT])
+					stackcallparamsize = 0;
+
+				if (stackcallparamsize)
+					fprintf(fp, "\t@sub xp %d -> xp;\n",
+						stackcallparamsize);
+#endif
+
+				/* Is this actually an inline assembly function? */
+
+				if ((ic->q1.flags & VAR) &&
+				    ic->q1.v->fi &&
+				    ic->q1.v->fi->inline_asm)
+				{
+					/* Yes. Emit the assembly code. */
+
+					fprintf(fp, "%s", ic->q1.v->fi->inline_asm);
+				}
+				else
+				{
+					/* No; so emit a call. */
+				
+					push_value(fp, &ic->q1, typf, &q1);
+					fprintf(fp, "\t@call_vs2 ");
+					emit_zop(fp, &q1);
+					fprintf(fp, " xp r0 r1 r2 r3 r4 r5 -> r0;\n");
+				}
+
+				//stackcalladjustment = 1;
+
+				/* If any parameters have been pushed, adjust
+				 * the stack to pop them. */
+
+				if (stackparamadjust)
+				{
+					fprintf(fp, "\t@add xp 0%+ld -> xp;\n",
+						stackparamadjust);
+					//stackoffset -= stackparamadjust;
+					stackparamadjust = 0;
+				}
+				continue;
+			}
+
+			default:
+				ierror(code);
+		}
+						
+	}
+
+	/* We really ought to tidy the stack up; but there's no need, because
+	 * the old value of xp will be restored when the function exits. */
+
+    	//if (stackframe)
+	//	fprintf(fp, "\t@add xp %ld -> xp;\n", stackframe);
+	
+	fprintf(fp, "\t@ret r0;\n");
+	fprintf(fp, "]\n");
+
+//    function_bottom(fp, func, loff);
+}
+
+int shortcut(int code, int typ)
+{
+    return(0);
+}
+
+// Add a constant to the constant pool.
+
+static int addconstant(zmax value)
+{
+	struct constant* c;
+	
+	/* Check to see if the constant's already in the pool. */
+
+	c = constantlist;
+	while (c)
+	{
+		if (c->value == value)
+			return c->id;
+		c = c->next;
+	}
+
+	/* It's not; add it. */
+	
+	c = malloc(sizeof(struct constant));
+	c->next = constantlist;
+	c->id = constantnum++;
+	c->value = value;
+	constantlist = c;
+	return c->id;
+}
+
+void cleanup_cg(FILE *fp)
+{
+	struct fixup* fixup = fixuplist;
+
+	/* Have we actually emitted anything? */
+
+	if (!fp)
+		return;
+
+	reflower(fp);
+
+	/* Emit the constant pool. */
+
+	{
+		struct constant* constant = constantlist;
+
+		while (constant)
+		{
+			fprintf(fp, "Array CONSTANT_%s_%ld -->\n",
+				modulename, constant->id);
+			fprintf(fp, " 0%+ld 0%+ld;\n",
+				xword(constant->value, 1),
+				xword(constant->value, 0));
+			constant = constant->next;
+		}
+	}
+
+	/* Emit the code to initialise the data area. */
+
+	{
+		struct fixup* fixup = fixuplist;
+
+		fprintf(fp, "[ __init_vars_%s;\n", modulename);
+		while (fixup)
+		{
+			fprintf(fp, "\t@add 0%+ld ", fixup->offset);
+
+			switch (fixup->value.type)
+			{
+				case STATIC:
+					fprintf(fp, "STATIC_%s_%ld -> sp;\n",
+						modulename, fixup->value.val.number);
+					break;
+
+				case EXTERN:
+					fprintf(fp, "_%s -> sp;\n",
+						fixup->value.val.identifier);
+					break;
+
+				default:
+					ierror(0);
+			}
+
+			switch (fixup->identifier.type)
+			{
+				case STATIC:
+					fprintf(fp, "\t@storew STATIC_%s_%ld 0%+ld sp;\n",
+						modulename, fixup->identifier.val.number,
+						fixup->identifier.offset);
+					break;
+
+				case EXTERN:
+					fprintf(fp, "\t@storew _%s 0%+ld sp;\n",
+						fixup->identifier.val.identifier,
+						fixup->identifier.offset);
+					break;
+
+				default:
+					ierror(0);
+			}
+
+			fixup = fixup->next;
+		}
+		fprintf(fp, "];\n");
+	}
+}
+
+/* The code generator's asking us to pass a parameter in a register. */
+
+int reg_parm(struct reg_handle *rh, struct Typ *typ, int vararg, struct Typ *ft)
+{
+	/* Vararg parameters never go in registers. */
+
+	if (vararg)
+		return 0;
+
+	/* Will the parameter fit? */
+
+	if (sizetab[typ->flags & NQ] > 2)
+		return 0;
+
+	/* Still enough registers? */
+
+	if (rh->reg >= NUM_REGPARMS+USERREG)
+		return 0;
+
+	return (rh->reg++);
+}
+
+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.                                            */
+{
+  return 0;
+}                                                                               
+void init_db(FILE *f)
+{
+}
+void cleanup_db(FILE *f)
+{
+}
diff --git a/machines/z/machine.dt b/machines/z/machine.dt
new file mode 100755
index 0000000..41828bc
--- /dev/null
+++ b/machines/z/machine.dt
@@ -0,0 +1,14 @@
+S8BS
+S8BU
+S16BSLE S16BSBE
+S16BULE S16BUBE
+S16BSLE S16BSBE
+S16BULE S16BUBE
+S32BSLE S32BSBE
+S32BULE S32BUBE
+S64BSLE S64BSBE
+S64BULE S64BUBE
+S32BIEEEBE S32BIEEELE
+S64BIEEEBE S64BIEEELE
+S64BIEEEBE S64BIEEELE
+S16BULE S16BUBE
diff --git a/machines/z/machine.h b/machines/z/machine.h
new file mode 100755
index 0000000..6f43fc8
--- /dev/null
+++ b/machines/z/machine.h
@@ -0,0 +1,81 @@
+/* Z-machine code generator
+ * David Given
+ */
+
+#include "dt.h"
+
+/* Machine specific addressing-modes. Not used. */
+
+struct AddressingMode{
+	int never_used;
+};
+
+/* The number of registers we support. We don't really have any, but we
+ * use local variables instead; we have 14.
+ */
+
+#define MAXR 14
+
+/* Number of command-line options we accept. */
+
+#define MAXGF 6
+
+/* If this is set to zero vbcc will not generate ICs where the target operand
+ * is the same as the 2nd source operand. This can sometimes simplify the
+ * code-generator, but usually the code is better if the code-generator allows
+ * it. 
+ */
+
+#define USEQ2ASZ 1
+
+/* The smallest and largest integer type that can be added to a pointer. */
+
+#define MINADDI2P INT
+#define MAXADDI2P INT
+
+/* Big-endian? */
+
+#define BIGENDIAN 1
+
+/* Little-endian? */
+
+#define LITTLEENDIAN 0
+
+/* If switch-statements should be generated as a sequence of SUB,TST,BEQ ICs
+ * rather than COMPARE,BEQ ICs set this to 1.  This can yield better code on
+ * some machines.
+ */
+
+#define SWITCHSUBS 0
+
+/* In optimizing compilation certain library memcpy/strcpy-calls with length
+ * known at compile-time will be inlined using an ASSIGN-IC if the size is less
+ * or equal to INLINEMEMCPY.  The type used for the ASSIGN-IC will be
+ * UNSIGNED|CHAR. On the Z-machine, memcpy can be done in `hardware' with the
+ * @copy_table opcode, so always inline them if possible.
+ */
+
+#define INLINEMEMCPY 65536
+
+/* Do we want to pass parameters to functions in registers? */
+
+#define HAVE_REGPARMS 1
+
+/* If so, how many? Max 7 due to the architecture, but one is always xp. */
+
+#define NUM_REGPARMS 6
+
+/* This structure is used to keep track of where register parameters go. */
+
+struct reg_handle {
+	int reg;
+};
+
+/* Do we want to use zuint for size_t rather than the default zulong? */
+
+#define HAVE_INT_SIZET 1
+
+/* size of buffer for asm-output */
+#define EMIT_BUF_LEN 1024 /* should be enough */
+/* number of asm-output lines buffered */
+#define EMIT_BUF_DEPTH 4