home *** CD-ROM | disk | FTP | other *** search
- /*
- oxccb.c -- v1.430 architecture neutral format (anf) to bytecode generator
-
- Copyright (c) 1995
- Norman D. Culver dba
- Oxbow Software
- 1323 S.E. 17th Street #662
- Ft. Lauderdale, FL 33316
- (954) 463-4754
- ndc@icanect.net
- All rights reserved.
-
- * Redistribution and use in source and binary forms are permitted
- * provided that: (1) source distributions retain this entire copyright
- * notice and comment, and (2) distributions including binaries display
- * the following acknowledgement: ``This product includes software
- * developed by Norman D. Culver dba Oxbow Software''
- * in the documentation or other materials provided with the distribution
- * and in all advertising materials mentioning features or use of this
- * software.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-
- */
- #define MAJOR_VERSION 1
- #define MINOR_VERSION 433
-
- void oxcc_debug();
- int __builtin_iv();
- void bterpdebug(void);
-
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
- #include <setjmp.h>
- #include <time.h>
-
- #define SUPPORT_LONG_DOUBLE 1
- #define SUPPORT_LONG_LONG 1
-
- #define NEED_SPELLING 1
- #define NEED_BYTECODES 1
- #define NEED_AOUT_FORMAT 1
- #include "oxbytes.h"
-
- #define NEED_FUNCTHUNK 1
- #define NEED_ANFDEFS 1
- #include "oxanf.h"
-
- #define PROG oxccb
- #define USING_FRAMEWORK 1
- #define HOST_IS_LITTLE_ENDIAN 1
- #define REALLY_NEED_OFFSETS 1
- #define FUNCDATA (iv->category+1)
-
- #define VFPRINTF(a,b) vfprintf(stderr,a,b)
- #define PERROR prerror
- #define PWARN prwarn
- #define PRINTF info
- static void prerror(const char *, ...);
- static void prwarn(const char *, ...);
- static void info(const char *, ...);
- int cfeprintf(const char *, ...);
-
- #define FILEWRITE(buf, cnt)\
- {if(!iv->errors){if(fwrite(buf, 1, cnt, iv->outfile) != cnt)iv->errors = 12;}}
-
- #define ROUNDING(a,b) ((a+(b-1))&~(b-1))
- #define ROUNDUP(a,b) a += ROUNDING(a,b)
-
- #define KEYEQ(a,b) ((a)[0] == (b)[0] && (a)[1] == (b)[1])
- #define KEYLT(a,b) (((a)[1] < (b)[1]) || ((a)[1] == (b)[1] && (a)[0] < (b)[0]))
- #define MIN(a,b) (((a) < (b)) ? (a) : (b))
-
- /* ======================== CONCATENIZATION MACROS ==================== */
-
- #define _cat2_(a, b) a##b
- #define _cat_(a, b) _cat2_(a, b)
- #define Global(a) _cat_(PROG, a)
-
- #define _pname2_(x) #x
- #define _pname1_(x) _pname2_(x)
- #define pName _pname1_(PROG)
-
-
- /* ============== ENDIAN MACROS (input format is litle endian) ==== */
-
- #if HOST_IS_LITTLE_ENDIAN
- #define GL(a) a
- #define GS(a) a
- #define PL(a) a
- #define PS(a) a
- #else
- #endif
-
- /* =================== INPUT DATA FORMATS ========================== */
-
- #define INFILE_SYMNUM 1
- #define OUTFILE_SYMNUM 2
-
- static unsigned char binops[] = {0,0,
- ADD,SUB,MUL,DIV,LSH,RSH,MOD,OR,XOR,AND,EQ,NE,LT,GT,LE,GE,
- NEG,COMP,NOT
- };
- /* ====================== STRUCTURES AND TYPEDEFS ======================== */
- typedef struct _jl {
- struct _jl *next;
- void *p;
- char *q;
- long *plabelval;
- long offset;
- } *PJL;
-
- typedef struct _el {
- struct _el *next;
- long spot;
- short symnum;
- } *PEL;
-
- typedef struct _afile {
- unsigned char *file_p;
- PopI header_p;
- PopI size_p;
- unsigned char *symtext_p;
- unsigned char *prog_p;
- unsigned char *data_p;
- unsigned char *switch_p;
- unsigned char *decl_p;
- unsigned char *maxtemp_p;
- unsigned char *seg_p;
- unsigned char **symaddr;
- unsigned char **decladdr;
- unsigned long thunk_offset;
- unsigned long bss_offset;
- int maxtemp;
- int maxtempclass;
- void *datatbl;
- short *symtran;
- unsigned short *decltran;
- int filenum;
- int numsyms;
- int numdecls;
- int numrelocs;
- int numsegs;
- } *Pafile;
-
- typedef struct _iv {
- int category;
- FILE *outfile;
- struct exec *header;
- unsigned char **symaddr;
- unsigned char **decladdr;
- int remove_infile;
- int argc;
- char **argv;
- int numfiles;
- int lastlabel;
- int errors;
- int numsyms;
- int numdecls;
- int numsegs;
- int maxtemp;
- int maxtempclass;
- unsigned long total_size;
- unsigned long thunk_offset;
- unsigned long bss_offset;
-
- struct _nodeO *ob_usedhead;
- struct _nodeO *ob_usedtail;
- struct _nodeO *ob;
- unsigned char *ob_buf;
- int ob_bufcnt;
- struct _nodeO *first_ob;
-
- struct _nodeC *cod_usedhead;
- struct _nodeC *cod_usedtail;
- struct _nodeC *cod;
- unsigned char *cod_buf;
- int cod_bufcnt;
- struct _nodeC *first_cod;
- struct _nodeC *regcode;
-
- long first_temp;
- long killop;
- long stackdepth;
- long maxdepth;
- long mindepth;
- long numnested;
- long lastline;
- void *reloctbl;
- void *extrntbl;
- void *gbltbl;
- void *symtbl;
- void *labeltbl;
- void *newlabeltbl;
- void *tmptbl;
- void *segtbl;
- void *functbl;
- void *finalsymtbl;
- void *finalstringpack;
- long finalpacksize;
- void *datatbl;
- void *builtintbl;
- int in_builtin;
- int has_structret;
- int temps_written;
- unsigned char *obuf;
- unsigned char *obufstart;
- PEL extbuf;
- void *extbufstart;
- int extcnt;
- int extbufcnt;
- PEL finextbuf;
- void *finextbufstart;
- int finextcnt;
- int finextbufcnt;
- PJL jbuf;
- void *jbufstart;
- int jmpcnt;
- int jbufcnt;
- long obufcnt;
- long out_offset;
- long func_offset;
- int extmark;
- short markedsym[10];
- char *markedbuf[10];
- int filenum;
- Pafile files[1024];
- char debug;
- char only_debug;
- char strip;
- char listing_wanted;
- } *Piv;
-
- struct _gloval {
- char *symname;
- int symnum;
- unsigned char *p;
- Pafile pf;
- };
- struct _rkey {/* key area of reloctbl node */
- unsigned long spot;
- short fileno;
- unsigned char opcode;
- char rsize;
- };
- struct _rval {/* value area of reloctbl node */
- unsigned char *p;
- unsigned long *base;
- long offset;
- short rsym;
- };
-
-
- /* Internal User API */
- static void *Cmalloc(int category, unsigned amount);
- static void *Ccalloc(int category, unsigned nelems, unsigned elemsize);
- static void *Crealloc(int category, void* buf, unsigned newsize);
- static void Cfree(int category, void* buf);
- static void Cfreecat(int category);
- static int Cmemrange(int category, unsigned* minp, unsigned* maxp);
- static int Cusedrange(int category, unsigned* minp, unsigned* maxp);
- static void Ctotrange(unsigned* minp,unsigned* maxp);
- static int Cnewcat(void);
- static void Cguard(int category);
- static void* NewSymTable(int category, int nbins);
- static int SymFind(void *tbl, void *key, void *result);
- static int SymFindRange(void *tbl, void *key, void *result);
- static void *SymInsert(void *tbl, void *key, void *value, int datsiz);
- static int StringInsert(void *tbl, char *string, void *result);
- static int StringFind(void *tbl, char *string, void *result);
- static void SymDelete(void *tbl, void *key);
- static int SymHead(void *tbl);
- static int SymNext(void *tbl);
- static void SymGetMark(void *tbl, void *markptr);
- static int SymMarkNext(void *tbl, void *mark);
- static void SymSetMark(void *tbl, void *markptr);
- static void SymKey(void *tbl, void *keyptr);
- static void SymValue(void *tbl, void *datptr);
- static void *seg_find(Piv iv, int id);
- static char *filenameof(char *path);
- static char *propernameof(Piv iv, char *name);
-
- /* END: User API */
-
- /* ====================== PUT UNIQUE CODE HERE ========================= */
- static void newlabel_insert(Piv iv, long label);
- static long newlabel_fix(Piv iv, long label);
- static void *do_stmt(Piv iv, unsigned char *p);
- static void *do_expr(Piv iv, unsigned char *p);
- static void do_bracket(Piv iv, unsigned char *p, unsigned char *q);
- static void *do_something(Piv iv, unsigned char *p);
- extern char *ctime();
-
- /* ===================== BYTECODE OUTPUT GENERATOR ======================= */
- struct _nodeOBUF
- {
- struct _nodeOBUF *next;
- long cnt;
- char buf[1];
- };
- typedef struct _nodeC
- {
- struct _nodeC *next;
- struct _nodeOBUF *ee;
- } NODEC, *PNODEC;
-
- typedef struct _nodeO
- {
- struct _nodeO *next;
- unsigned char *p;
- ND d;
- ND l;
- ND r;
- PNODEC startinst;
- PNODEC endinst;
- } NODEO, *PNODEO;
-
- static unsigned char get_datasize(unsigned char, PND);
- static void link_cod(Piv);
-
- static char *notice =
- " Generated by Oxbow Software Bytecode Backend version %d.%d\n*/\n\n";
-
- static struct _nd longtype = {D_SIGNED,0,B4,0,4,0,0};
- static struct _nd longlongtype = {D_SIGNED,0,B8,0,8,0,0};
- static char padit[8]; /* in bss */
-
- void
- bterpdebug(){}
-
- static long
- symnumof(Piv iv, char *symb)
- {
- struct _gloval *valp;
-
- if(StringFind(iv->gbltbl, symb, &valp))
- return (long)valp->pf->symtran[valp->symnum];
- return 0;
- }
- static void
- buildin(Piv iv, char *symb, unsigned char code)
- {
- long key[2];
-
- if((key[0] = symnumof(iv, symb)))
- {
- key[1] = 0;
- SymInsert(iv->builtintbl, key, &code, 1);
- }
- }
- static void
- install_builtins(Piv iv)
- {/* USE THIS TO INSTALL WHATEVER BUILTINS ARE IN THE TARGET INTERPRETER */
- #define BUILDIN(a,b) buildin(iv,#a,b)
-
- iv->builtintbl = NewSymTable(iv->category, 191);
-
- BUILDIN(alloca,ALLOCA);
- BUILDIN(strlen,STRLEN);
- BUILDIN(strcpy,STRCPY);
- BUILDIN(strcat,STRCAT);
- BUILDIN(memcpy,MEMCPY);
- BUILDIN(memmove,MEMMOVE);
- BUILDIN(bzero,BZERO);
- BUILDIN(malloc,MALLOC);
- BUILDIN(calloc,CALLOC);
- BUILDIN(realloc,REALLOC);
- BUILDIN(setjmp,SETJMP);
- BUILDIN(longjmp,LONGJMP);
- BUILDIN(abort,ABORT);
- BUILDIN(exit, EXIT);
- BUILDIN(_exit,EXIT);
- BUILDIN(bterpdebug,DEBUG);
- BUILDIN(bterpnodebug,NODEBUG);
-
- #undef BUILDIN
- }
- static long
- final_strofs(Piv iv, char *string)
- {
- long *result;
-
- if(StringFind(iv->finalsymtbl, string, &result))
- return result[2];
- return 0;
- }
- static short
- final_symnum(Piv iv, short symnum)
- {
- long *result;
-
- if(StringFind(iv->finalsymtbl, iv->symaddr[symnum], &result)) {
- return result[1]-1;
- }
- return 0;
- }
- static void
- make_final_symtab(Piv iv)
- {
- int i;
- iv->finalsymtbl = NewSymTable(iv->category, 0);
- if(SymHead(iv->gbltbl))
- {
- i = 0;
- while(SymNext(iv->gbltbl))
- {
- long *result;
- struct _gloval *valp;
-
- SymValue(iv->gbltbl, &valp);
- if(*(valp->p))
- {
- long key[2];
- key[0] = valp->pf->symtran[valp->symnum];
- key[1] = 0;
- if(!SymFind(iv->builtintbl, key, NULL))
- {
- if(!StringInsert(iv->finalsymtbl, valp->symname, &result))
- {/* New Entry */
- result[1] = ++i;
- }
- }
- }
- }
- }
- }
- static void
- adjust_labels(Piv iv, long base, long adjust)
- {
- long *key;
- long *val;
- if(SymHead(iv->newlabeltbl))
- {
- while(SymNext(iv->newlabeltbl))
- {
- SymKey(iv->newlabeltbl, &key);
- SymValue(iv->newlabeltbl, &val);
- if(key[1] == iv->filenum && val[0] > base) {
- val[0] += adjust;
- }
- }
- }
- }
- static void
- addto_extlist(Piv iv, char *buf)
- {
- void *next;
- while(iv->extmark > 0)
- {
- long offset = iv->markedbuf[iv->extmark] - buf;
- next = iv->extbuf;
- if(iv->extbufcnt >= sizeof(struct _el))
- {
- iv->extbuf++;
- }
- else
- {
- iv->extbufcnt = 4080;
- iv->extbuf = Ccalloc(FUNCDATA, 1, iv->extbufcnt);
- }
- *((void**)next) = iv->extbuf;
- iv->extbuf->spot = iv->out_offset+iv->func_offset+offset;
- iv->extbuf->symnum = iv->markedsym[iv->extmark];
- ++iv->extcnt;
- --iv->extmark;
- iv->extbufcnt -= sizeof(struct _el);
- }
- }
- static void
- save_extlocs(Piv iv)
- {
- PEL pel = iv->extbufstart;
- void *next;
-
- while(pel)
- {
- next = iv->finextbuf;
- if(iv->finextbufcnt >= sizeof(struct _el))
- {
- iv->finextbuf++;
- }
- else
- {
- iv->finextbufcnt = 4080;
- iv->finextbuf = Ccalloc(iv->category, 1, iv->finextbufcnt);
- }
- *((void**)next) = iv->finextbuf;
- iv->finextbuf->spot = pel->spot;
- iv->finextbuf->symnum = pel->symnum;
- ++iv->finextcnt;
- iv->finextbufcnt -= sizeof(struct _el);
- pel = pel->next;
- }
- }
- static void
- adjust_externs(Piv iv, long base, long adjust)
- {
- PEL pel = iv->extbufstart;
-
- while(pel)
- {
- if(pel->spot > base)
- pel->spot += adjust;
- pel = pel->next;
- }
- }
-
- static int
- shorten_jmps(Piv iv)
- {
- int scnt;
- PJL jp;
- long jmp_offset;
- long label_offset;
- long diff;
- long offset_adjust;
- int sign;
- unsigned char *q, *osiz;
- int cursize, newsize;
-
- scnt = 0;
- jp = iv->jbufstart;
- offset_adjust = 0;
- while(jp)
- {
- osiz = jp->q+4; /* points to size in obuf */
- q = osiz+4; /* points to the JMP inst in obuf */
- cursize = *q & 3; /* from the output bytecode */
- jmp_offset = jp->offset + offset_adjust;
- jp->offset = jmp_offset; /* reset the offset for this inst */
- label_offset = *jp->plabelval;
- diff = label_offset - jmp_offset;
-
- sign = 1;
- if(diff < 0)
- {
- sign = -1;
- diff = -diff;
- }
- if(diff < 0x7fL)
- newsize = 0;
- else if(diff < 0x7fffL)
- newsize = 1;
- else if(diff < 0x007fffffL)
- newsize = 2;
- else
- newsize = 3;
- if(cursize != newsize)
- {/* DO SOMETHING */
- long adj;
- static long codesize[4] = {2L,3L,4L,5L};
- ++scnt; /* something changed */
- *q &= 0xfc; /* mask opcode */
- *q |= newsize; /* set size in opcode */
- *((long*)osiz) = codesize[newsize]; /* set new output size */
- adj = codesize[newsize] - codesize[cursize];
- offset_adjust += adj; /* jmps below this point have new offset */
- if(sign > 0) diff += adj; /* label is below this point */
-
- /* Adjust all labels below this point */
- adjust_labels(iv, jmp_offset, adj);
- /* adjust all external address spots (text relocs) below this point */
- adjust_externs(iv, jmp_offset, adj);
- }
- diff *= sign; /* restore sign to the relative address */
-
- /* generate the pc relative address */
-
- ++q; /* points the the address field of the JMP inst */
- if(newsize == 0)
- *((signed char*)q) = (signed char)(diff & 0xff);
- else if(newsize == 1)
- *((short*)q) = (short)(diff & 0xffff);
- else if(newsize == 2)
- *((long*)q) = diff<<8;
- else
- *((long*)q) = diff;
- jp = jp->next;
- }/* END: while (jp) */
-
- return scnt;
- }
-
- static void
- setup_jmps(Piv iv, unsigned char *pdef)
- {
- struct {
- long k1;
- long k2;
- } key;
- long *result;
- PJL jp;
- unsigned char *p;
-
- jp = iv->jbufstart;
- while(jp)
- {
- p = jp->p;
- key.k1 = GL( POP->data ); /* label number from source code */
- key.k2 = iv->filenum; /* source file number */
- if(SymFind(iv->newlabeltbl, &key, &result))
- {
- jp->plabelval = result; /* save pointer to label value */
- }
- else
- {
- PERROR(pName ":SYSERROR: jmp setup failed for `%s' label=%d file=%d p=%x code=%d\n",
- iv->symaddr[GL(((Pop)pdef)->data)], key.k1, key.k2, p, *p);
- }
- jp = jp->next;
- }
- }
- static void
- addto_jmplist(Piv iv, unsigned char *p, void *q)
- {
- void *next = iv->jbuf;
-
- if(iv->jbufcnt >= sizeof(struct _jl))
- {
- iv->jbuf++;
- }
- else
- {
- iv->jbufcnt = 4080;
- iv->jbuf = Ccalloc(FUNCDATA, 1, iv->jbufcnt);
- }
- *((void**)next) = iv->jbuf;
- iv->jbuf->p = p;
- iv->jbuf->q = q;
- iv->jbuf->offset = iv->out_offset+iv->func_offset-5;
- iv->jbufcnt -= sizeof(struct _jl);
- }
- static void
- save_maxdepth(Piv iv, long symnum)
- {
- long key[2];
- long val[3];
-
- if(iv->functbl == 0)
- {
- iv->functbl = NewSymTable(iv->category, 277);
- }
- key[0] = symnum;
- key[1] = 0;
- val[0] = iv->maxdepth + (4*iv->numnested);
- val[1] = iv->mindepth;
- val[2] = 0;
- SymInsert(iv->functbl, key, val, 12);
- }
- static long
- get_maxdepth(Piv iv, short symnum)
- {
- long key[2];
- long *result;
-
- key[0] = symnum;
- key[1] = 0;
- if(SymFind(iv->functbl, key, &result))
- {
- return result[0];
- }
- return 0;
- }
- static void
- printline(Piv iv, void *ptr)
- {
- fprintf(iv->outfile, "Line:%ld:\n", *((long*)ptr));
- }
- static int
- print8(Piv iv, unsigned char *ptr, int size, long offset, int lf)
- {
- char buf[40];
- int i, j=0;
-
- i = sprintf(buf, "%8.8lx: ", offset);
- while(j < size && j < 8)
- {
- i += sprintf(&buf[i], "%2.2x ", *ptr++);
- ++j;
- }
- if(lf)
- buf[i++] = '\n';
- else
- {
- while(i < 35)
- buf[i++] = ' ';
- }
- buf[i] = 0;
- fprintf(iv->outfile, buf);
- return j;
- }
- static void
- printinst(Piv iv, unsigned char *pc, long size)
- {
- int i, bufcnt;
- unsigned char *epc;
- char *pbuf[20];
-
- bufcnt = 0;
- epc = pc + size;
- for( ;pc < epc; ++pc)
- {
- switch(*pc)
- {
- case LOCATE|J1:
- case LOCATE|J2:
- case LOCATE|J3:
- case LOCATE|J4:
- pbuf[bufcnt++] = "locate|";
- pbuf[bufcnt++] = Jbuf[*pc & 0x03];
- pc += Jcnt[*pc & 0x03];
- break;
- case LS|A1|B1:
- case LS|A1|B2:
- case LS|A1|B4:
- case LS|A1|B8:
- case LS|A2|B1:
- case LS|A2|B2:
- case LS|A2|B4:
- case LS|A2|B8:
- case LS|A3|B1:
- case LS|A3|B2:
- case LS|A3|B4:
- case LS|A3|B8:
- pbuf[bufcnt++] = "ls|";
- pbuf[bufcnt++] = ABbuf[*pc & 0x0f];
- pc += Acnt[(*pc>>2) & 0x03];
- break;
- case NEG|BYTE:
- case NEG|SHORT:
- case NEG|LONG:
- case NEG|UBYTE:
- case NEG|USHORT:
- case NEG|ULONG:
- case NEG|FLOAT:
- case NEG|DOUBLE:
- pbuf[bufcnt++] = "neg|";
- pbuf[bufcnt++] = Tbuf[*pc & 0x07];
- break;
-
- case LM|A1|B1:
- case LM|A1|B2:
- case LM|A1|B4:
- case LM|A1|B8:
- case LM|A2|B1:
- case LM|A2|B2:
- case LM|A2|B4:
- case LM|A2|B8:
- case LM|A3|B1:
- case LM|A3|B2:
- case LM|A3|B4:
- case LM|A3|B8:
- case LM|A4|B1:
- case LM|A4|B2:
- case LM|A4|B4:
- case LM|A4|B8:
- pbuf[bufcnt++] = "lm|";
- pbuf[bufcnt++] = ABbuf[*pc & 0x0f];
- pc += Acnt[(*pc>>2) & 0x03];
- break;
-
- case COMP|B1:
- case COMP|B2:
- case COMP|B4:
- case COMP|B8:
- pbuf[bufcnt++] = "comp|";
- pbuf[bufcnt++] = Bbuf[*pc & 0x03];
- break;
-
- case JMP|J1:
- case JMP|J2:
- case JMP|J3:
- case JMP|J4:
- pbuf[bufcnt++] = "jmp|";
- pbuf[bufcnt++] = Jbuf[*pc & 0x03];
- pc += Jcnt[*pc & 0x03];
- break;
-
- case JMPT|J1:
- case JMPT|J2:
- case JMPT|J3:
- case JMPT|J4:
- pbuf[bufcnt++] = "jmpt|";
- pbuf[bufcnt++] = Jbuf[*pc & 0x03];
- pc += Jcnt[*pc & 0x03];
- break;
-
- case LJMPT|J1:
- case LJMPT|J2:
- case LJMPT|J3:
- case LJMPT|J4:
- pbuf[bufcnt++] = "ljmpt|";
- pbuf[bufcnt++] = Jbuf[*pc & 0x03];
- pc += Jcnt[*pc & 0x03];
- break;
-
- case JMPF|J1:
- case JMPF|J2:
- case JMPF|J3:
- case JMPF|J4:
- pbuf[bufcnt++] = "jmpf|";
- pbuf[bufcnt++] = Jbuf[*pc & 0x03];
- pc += Jcnt[*pc & 0x03];
- break;
-
- case LJMPF|J1:
- case LJMPF|J2:
- case LJMPF|J3:
- case LJMPF|J4:
- pbuf[bufcnt++] = "ljmpf|";
- pbuf[bufcnt++] = Jbuf[*pc & 0x03];
- pc += Jcnt[*pc & 0x03];
- break;
-
- case NOT|B1:
- case NOT|B2:
- case NOT|B4: /* also FLOAT */
- case NOT|B8: /* also DOUBLE */
- pbuf[bufcnt++] = "not|";
- pbuf[bufcnt++] = Bbuf[*pc & 0x03];
- break;
-
- case SS|A1|B1:
- case SS|A1|B2:
- case SS|A1|B4:
- case SS|A1|B8:
- case SS|A2|B1:
- case SS|A2|B2:
- case SS|A2|B4:
- case SS|A2|B8:
- case SS|A3|B1:
- case SS|A3|B2:
- case SS|A3|B4:
- case SS|A3|B8:
- pbuf[bufcnt++] = "ss|";
- pbuf[bufcnt++] = ABbuf[*pc & 0x0f];
- pc += Acnt[(*pc>>2) & 0x03];
- break;
-
- case TRUTHOF|B2:
- case TRUTHOF|B4:
- case TRUTHOF|B8:
- pbuf[bufcnt++] = "truthof|";
- pbuf[bufcnt++] = Bbuf[*pc & 0x03];
- break;
- case CVT:
- {
- unsigned char cvs,cvd;
- pbuf[bufcnt++] = "cvt ";
- ++pc;
- cvs = (*pc & 0x70)>>4;
- cvd = (*pc & 0x07);
- pbuf[bufcnt++] = Tbuf[cvd];
- pbuf[bufcnt++] = "<-";
- pbuf[bufcnt++] = Tbuf[cvs];
- break;
- }
- case LI|B1:
- case LI|B2:
- case LI|B4:
- case LI|B8:
- pbuf[bufcnt++] = "li|";
- pbuf[bufcnt++] = Bbuf[*pc & 0x03];
- pc += Bcnt[*pc & 0x03];
- break;
-
- case LAI|D1:
- case LAI|D2:
- case LAI|D3:
- case LAI|D4:
- pbuf[bufcnt++] = "lai|";
- pbuf[bufcnt++] = Dbuf[*pc & 0x03];
- pc += Dcnt[*pc & 0x03];
- break;
-
- case LUI|B1:
- case LUI|B2:
- case LUI|B4:
- case LUI|B8:
- pbuf[bufcnt++] = "lui|";
- pbuf[bufcnt++] = Bbuf[*pc & 0x03];
- pc += Bcnt[*pc & 0x03];
- break;
-
- case IMMED:
- {
- ++pc;
- switch(*pc)
- {
- case SMI|A1|B1:
- case SMI|A1|B2:
- case SMI|A1|B4:
- case SMI|A1|B8:
- case SMI|A2|B1:
- case SMI|A2|B2:
- case SMI|A2|B4:
- case SMI|A2|B8:
- case SMI|A3|B1:
- case SMI|A3|B2:
- case SMI|A3|B4:
- case SMI|A3|B8:
- case SMI|A4|B1:
- case SMI|A4|B2:
- case SMI|A4|B4:
- case SMI|A4|B8:
- pbuf[bufcnt++] = "smi|";
- pbuf[bufcnt++] = ABbuf[*pc & 0x0f];
- pc += ABcnt[*pc & 0x0f];
- break;
-
- case SSI|A1|B1:
- case SSI|A1|B2:
- case SSI|A1|B4:
- case SSI|A1|B8:
- case SSI|A2|B1:
- case SSI|A2|B2:
- case SSI|A2|B4:
- case SSI|A2|B8:
- case SSI|A3|B1:
- case SSI|A3|B2:
- case SSI|A3|B4:
- case SSI|A3|B8:
- pbuf[bufcnt++] = "ssi|";
- pbuf[bufcnt++] = ABbuf[*pc & 0x0f];
- pc += ABcnt[*pc & 0x0f];
- break;
-
- case MODI|BYTE:
- case MODI|SHORT:
- case MODI|LONG:
- case MODI|UBYTE:
- case MODI|USHORT:
- case MODI|ULONG:
- pbuf[bufcnt++] = "modi|";
- pbuf[bufcnt++] = Tbuf[*pc & 0x07];
- pc += 2;
- break;
-
- case DEREF|BYTE:
- case DEREF|SHORT:
- case DEREF|LONG:
- case DEREF|UBYTE:
- case DEREF|USHORT:
- case DEREF|ULONG:
- case DEREF|FLOAT:
- case DEREF|DOUBLE:
- pbuf[bufcnt++] = "deref|";
- pbuf[bufcnt++] = Tbuf[*pc & 0x07];
- break;
-
- case DEREF1|BYTE:
- case DEREF1|SHORT:
- case DEREF1|LONG:
- case DEREF1|UBYTE:
- case DEREF1|USHORT:
- case DEREF1|ULONG:
- case DEREF1|FLOAT:
- case DEREF1|DOUBLE:
- pbuf[bufcnt++] = "deref1|";
- pbuf[bufcnt++] = Tbuf[*pc & 0x07];
- break;
- }
- break;
- }
- case SM|A1|B1:
- case SM|A1|B2:
- case SM|A1|B4:
- case SM|A1|B8:
- case SM|A2|B1:
- case SM|A2|B2:
- case SM|A2|B4:
- case SM|A2|B8:
- case SM|A3|B1:
- case SM|A3|B2:
- case SM|A3|B4:
- case SM|A3|B8:
- case SM|A4|B1:
- case SM|A4|B2:
- case SM|A4|B4:
- case SM|A4|B8:
- pbuf[bufcnt++] = "sm|";
- pbuf[bufcnt++] = ABbuf[*pc & 0x0f];
- pc += Acnt[(*pc>>2) & 3];
- break;
-
- case ADD|BYTE:
- case ADD|SHORT:
- case ADD|LONG:
- case ADD|UBYTE:
- case ADD|USHORT:
- case ADD|ULONG:
- case ADD|FLOAT:
- case ADD|DOUBLE:
- pbuf[bufcnt++] = "add|";
- pbuf[bufcnt++] = Tbuf[*pc & 0x07];
- break;
-
- case SUB|BYTE:
- case SUB|SHORT:
- case SUB|LONG:
- case SUB|UBYTE:
- case SUB|USHORT:
- case SUB|ULONG:
- case SUB|FLOAT:
- case SUB|DOUBLE:
- pbuf[bufcnt++] = "sub|";
- pbuf[bufcnt++] = Tbuf[*pc & 0x07];
- break;
-
- case MUL|BYTE:
- case MUL|SHORT:
- case MUL|LONG:
- case MUL|UBYTE:
- case MUL|USHORT:
- case MUL|ULONG:
- case MUL|FLOAT:
- case MUL|DOUBLE:
- pbuf[bufcnt++] = "mul|";
- pbuf[bufcnt++] = Tbuf[*pc & 0x07];
- break;
-
- case DIV|BYTE:
- case DIV|SHORT:
- case DIV|LONG:
- case DIV|UBYTE:
- case DIV|USHORT:
- case DIV|ULONG:
- case DIV|FLOAT:
- case DIV|DOUBLE:
- pbuf[bufcnt++] = "div|";
- pbuf[bufcnt++] = Tbuf[*pc & 0x07];
- break;
-
- case OR|B1:
- case OR|B2:
- case OR|B4:
- case OR|B8:
- pbuf[bufcnt++] = "or|";
- pbuf[bufcnt++] = Bbuf[*pc & 0x03];
- break;
-
- case AND|B1:
- case AND|B2:
- case AND|B4:
- case AND|B8:
- pbuf[bufcnt++] = "and|";
- pbuf[bufcnt++] = Bbuf[*pc & 0x03];
- break;
-
- case MOD|BYTE:
- case MOD|SHORT:
- case MOD|LONG:
- case MOD|UBYTE:
- case MOD|USHORT:
- case MOD|ULONG:
- pbuf[bufcnt++] = "mod|";
- pbuf[bufcnt++] = Tbuf[*pc & 0x07];
- break;
-
- case XTD:
- {
- ++pc;
- switch(*pc)
- {
- case LI:
- pbuf[bufcnt++] = "li";
- pc += XSZ;
- break;
-
- case LSH|B1:
- case LSH|B2:
- case LSH|B4:
- case LSH|B8:
- pbuf[bufcnt++] = "lsh|";
- pbuf[bufcnt++] = Bbuf[*pc & 0x03];
- break;
-
- case LSHI|B1:
- case LSHI|B2:
- case LSHI|B4:
- case LSHI|B8:
- pbuf[bufcnt++] = "lshi|";
- pbuf[bufcnt++] = Bbuf[*pc & 0x03];
- ++pc;
- break;
-
- case RSH|BYTE:
- case RSH|SHORT:
- case RSH|LONG:
- case RSH|UBYTE:
- case RSH|USHORT:
- case RSH|ULONG:
- pbuf[bufcnt++] = "rsh|";
- pbuf[bufcnt++] = Tbuf[*pc & 0x07];
- break;
-
- case RSHI|BYTE:
- case RSHI|SHORT:
- case RSHI|LONG:
- case RSHI|UBYTE:
- case RSHI|USHORT:
- case RSHI|ULONG:
- pbuf[bufcnt++] = "rshi|";
- pbuf[bufcnt++] = Tbuf[*pc & 0x07];
- ++pc;
- break;
-
- case BUILTIN:
- {
- pbuf[bufcnt++] = "builtin ";
- ++pc;
- pbuf[bufcnt++] = BUbuf[*pc];
- break;
- } /* END: XTD BUILTIN */
- case CLRDAT:
- pbuf[bufcnt++] = "clrdat";
- break;
- case SWITCH:
- pbuf[bufcnt++] = "switch";
- pc += 2;
- break;
- case CALLSETUP:
- pbuf[bufcnt++] = "callsetup";
- pc += 4;
- break;
- case RETSTRUCT:
- pbuf[bufcnt++] = "retstruct";
- pc += 4;
- break;
- case PRUNESTRUCT:
- pbuf[bufcnt++] = "prunestruct";
- break;
- case GETBITFIELD:
- pbuf[bufcnt++] = "getbitfield";
- pc += 3;
- break;
- case PUTBITFIELD:
- pbuf[bufcnt++] = "putbitfield";
- pc += 3;
- break;
- case IMMED:
- {
- ++pc;
- switch(*pc)
- {
- case SMI|A1:
- case SMI|A2:
- case SMI|A3:
- case SMI|A4:
- pbuf[bufcnt++] = "smi|";
- pbuf[bufcnt++] = Abuf[(*pc>>2) & 0x03];
- pc += Acnt[(*pc>>2) & 0x03] + XSZ;
- break;
-
- case SSI|A1:
- case SSI|A2:
- case SSI|A3:
- pbuf[bufcnt++] = "ssi|";
- pbuf[bufcnt++] = Abuf[(*pc>>2) & 0x03];
- pc += Acnt[(*pc>>2) & 0x03] + XSZ;
- break;
-
- case MODI|LONGLONG:
- case MODI|ULONGLONG:
- pbuf[bufcnt++] = "modi|";
- pbuf[bufcnt++] = XTbuf[*pc & 0x03];
- pc += 2;
- break;
-
- case DEREF|LONGLONG:
- case DEREF|ULONGLONG:
- case DEREF|LONGDOUBLE:
- pbuf[bufcnt++] = "deref|";
- pbuf[bufcnt++] = XTbuf[*pc & 0x03];
- break;
-
- case DEREF1|LONGLONG:
- case DEREF1|ULONGLONG:
- case DEREF1|LONGDOUBLE:
- pbuf[bufcnt++] = "deref1|";
- pbuf[bufcnt++] = XTbuf[*pc & 0x03];
- break;
- }
- break;
- }/* END: XTD IMMED */
-
- case ADD|LONGLONG:
- case ADD|ULONGLONG:
- case ADD|LONGDOUBLE:
- pbuf[bufcnt++] = "add|";
- pbuf[bufcnt++] = XTbuf[*pc & 0x03];
- break;
- case SUB|LONGLONG:
- case SUB|ULONGLONG:
- case SUB|LONGDOUBLE:
- pbuf[bufcnt++] = "sub|";
- pbuf[bufcnt++] = XTbuf[*pc & 0x03];
- case MUL|LONGLONG:
- case MUL|ULONGLONG:
- case MUL|LONGDOUBLE:
- pbuf[bufcnt++] = "mul|";
- pbuf[bufcnt++] = XTbuf[*pc & 0x03];
- break;
- case DIV|LONGLONG:
- case DIV|ULONGLONG:
- case DIV|LONGDOUBLE:
- pbuf[bufcnt++] = "div|";
- pbuf[bufcnt++] = XTbuf[*pc & 0x03];
- break;
- case LT|LONGLONG:
- case LT|ULONGLONG:
- case LT|LONGDOUBLE:
- pbuf[bufcnt++] = "lt|";
- pbuf[bufcnt++] = XTbuf[*pc & 0x03];
- break;
- case GT|LONGLONG:
- case GT|ULONGLONG:
- case GT|LONGDOUBLE:
- pbuf[bufcnt++] = "gt|";
- pbuf[bufcnt++] = XTbuf[*pc & 0x03];
- break;
- case LE|LONGLONG:
- case LE|ULONGLONG:
- case LE|LONGDOUBLE:
- pbuf[bufcnt++] = "le|";
- pbuf[bufcnt++] = XTbuf[*pc & 0x03];
- break;
- case GE|LONGLONG:
- case GE|ULONGLONG:
- case GE|LONGDOUBLE:
- pbuf[bufcnt++] = "ge|";
- pbuf[bufcnt++] = XTbuf[*pc & 0x03];
- break;
- case NE|LONGLONG:
- case NE|ULONGLONG:
- case NE|LONGDOUBLE:
- pbuf[bufcnt++] = "ne|";
- pbuf[bufcnt++] = XTbuf[*pc & 0x03];
- break;
- case EQ|LONGLONG:
- case EQ|ULONGLONG:
- case EQ|LONGDOUBLE:
- pbuf[bufcnt++] = "eq|";
- pbuf[bufcnt++] = XTbuf[*pc & 0x03];
- break;
- case NEG|LONGLONG:
- case NEG|ULONGLONG:
- case NEG|LONGDOUBLE:
- pbuf[bufcnt++] = "neg|";
- pbuf[bufcnt++] = XTbuf[*pc & 0x03];
- break;
- case NOT|BX:
- pbuf[bufcnt++] = "not|BX";
- break;
- case COMP|LONGLONG:
- case COMP|ULONGLONG:
- pbuf[bufcnt++] = "comp|";
- pbuf[bufcnt++] = XTbuf[*pc & 0x03];
- break;
- case RSH|SLONGLONG:
- case RSH|SULONGLONG:
- pbuf[bufcnt++] = "rsh|";
- pbuf[bufcnt++] = XTbuf[*pc & 0x03];
- break;
-
- case MOD|LONGLONG:
- case MOD|ULONGLONG:
- pbuf[bufcnt++] = "mod|";
- pbuf[bufcnt++] = XTbuf[*pc & 0x03];
- break;
- case RSHI|SLONGLONG:
- case RSHI|SULONGLONG:
- pbuf[bufcnt++] = "rshi|";
- pbuf[bufcnt++] = XTbuf[*pc & 0x07];
- ++pc;
- break;
- case TRUTHOF|BX:
- pbuf[bufcnt++] = "truthof|BX";
- break;
-
- case LS|A1:
- case LS|A2:
- case LS|A3:
- pbuf[bufcnt++] = "xtd ls|";
- pbuf[bufcnt++] = Abuf[(*pc>>2) & 0x03];
- pc += Acnt[(*pc>>2) & 0x03];
- break;
-
- case LM|A1:
- case LM|A2:
- case LM|A3:
- case LM|A4:
- pbuf[bufcnt++] = "xtd lm|";
- pbuf[bufcnt++] = Abuf[(*pc>>2) & 0x03];
- pc += Acnt[(*pc>>2) & 0x03];
- break;
-
- case SS|A1:
- case SS|A2:
- case SS|A3:
- pbuf[bufcnt++] = "xtd ss|";
- pbuf[bufcnt++] = Abuf[(*pc>>2) & 0x03];
- pc += Acnt[(*pc>>2) & 0x03];
- break;
-
- case SM|A1:
- case SM|A2:
- case SM|A3:
- case SM|A4:
- pbuf[bufcnt++] = "xtd sm|";
- pbuf[bufcnt++] = Abuf[(*pc>>2) & 0x03];
- pc += Acnt[(*pc>>2) & 0x03];
- break;
-
- case MOVSS:
- pbuf[bufcnt++] = "xtd movss";
- ++pc;
- pbuf[bufcnt++] = SDbuf[*pc & 0x0f];
- pc += SDcnt[*pc & 0x0f];
- break;
- case MOVSM:
- pbuf[bufcnt++] = "xtd movsm";
- ++pc;
- pbuf[bufcnt++] = SDbuf[*pc & 0x0f];
- pc += SDcnt[*pc & 0x0f];
- break;
- case MOVMS:
- pbuf[bufcnt++] = "xtd movms";
- ++pc;
- pbuf[bufcnt++] = SDbuf[*pc & 0x0f];
- pc += SDcnt[*pc & 0x0f];
- break;
- case MOVMM:
- pbuf[bufcnt++] = "xtd movmm";
- ++pc;
- pbuf[bufcnt++] = SDbuf[*pc & 0x0f];
- pc += SDcnt[*pc & 0x0f];
- break;
- }
- break;
- }/* END: XTD */
-
- case XOR|B1:
- case XOR|B2:
- case XOR|B4:
- case XOR|B8:
- pbuf[bufcnt++] = "xor|";
- pbuf[bufcnt++] = Bbuf[*pc & 0x03];
- break;
-
- case GT|BYTE:
- case GT|SHORT:
- case GT|LONG:
- case GT|UBYTE:
- case GT|USHORT:
- case GT|ULONG:
- case GT|FLOAT:
- case GT|DOUBLE:
- pbuf[bufcnt++] = "gt|";
- pbuf[bufcnt++] = Tbuf[*pc & 0x07];
- break;
-
- case LT|BYTE:
- case LT|SHORT:
- case LT|LONG:
- case LT|UBYTE:
- case LT|USHORT:
- case LT|ULONG:
- case LT|FLOAT:
- case LT|DOUBLE:
- pbuf[bufcnt++] = "lt|";
- pbuf[bufcnt++] = Tbuf[*pc & 0x07];
- break;
-
- case GE|BYTE:
- case GE|SHORT:
- case GE|LONG:
- case GE|UBYTE:
- case GE|USHORT:
- case GE|ULONG:
- case GE|FLOAT:
- case GE|DOUBLE:
- pbuf[bufcnt++] = "ge|";
- pbuf[bufcnt++] = Tbuf[*pc & 0x07];
- break;
-
- case LE|BYTE:
- case LE|SHORT:
- case LE|LONG:
- case LE|UBYTE:
- case LE|USHORT:
- case LE|ULONG:
- case LE|FLOAT:
- case LE|DOUBLE:
- pbuf[bufcnt++] = "le|";
- pbuf[bufcnt++] = Tbuf[*pc & 0x07];
- break;
-
- case NE|BYTE:
- case NE|SHORT:
- case NE|LONG:
- case NE|UBYTE:
- case NE|USHORT:
- case NE|ULONG:
- case NE|FLOAT:
- case NE|DOUBLE:
- pbuf[bufcnt++] = "ne|";
- pbuf[bufcnt++] = Tbuf[*pc & 0x07];
- break;
-
- case EQ|BYTE:
- case EQ|SHORT:
- case EQ|LONG:
- case EQ|UBYTE:
- case EQ|USHORT:
- case EQ|ULONG:
- case EQ|FLOAT:
- case EQ|DOUBLE:
- pbuf[bufcnt++] = "eq|";
- pbuf[bufcnt++] = Tbuf[*pc & 0x07];
- break;
-
- case ARG:
- pbuf[bufcnt++] = "arg";
- break;
- case ARGA:
- pbuf[bufcnt++] = "arga";
- break;
- case ARGF:
- pbuf[bufcnt++] = "argf";
- break;
-
- case MOVSS|B1:
- case MOVSS|B2:
- case MOVSS|B4:
- case MOVSS|B8:
- pbuf[bufcnt++] = "movss|";
- pbuf[bufcnt++] = Bbuf[*pc & 0x03];
- ++pc;
- pbuf[bufcnt++] = SDbuf[*pc & 0x0f];
- pc += SDcnt[*pc & 0x0f];
- break;
-
- case MOVSM|B1:
- case MOVSM|B2:
- case MOVSM|B4:
- case MOVSM|B8:
- pbuf[bufcnt++] = "movsm|";
- pbuf[bufcnt++] = Bbuf[*pc & 0x03];
- ++pc;
- pbuf[bufcnt++] = SDbuf[*pc & 0x0f];
- pc += SDcnt[*pc & 0x0f];
- break;
-
- case MOVMS|B1:
- case MOVMS|B2:
- case MOVMS|B4:
- case MOVMS|B8:
- pbuf[bufcnt++] = "movms|";
- pbuf[bufcnt++] = Bbuf[*pc & 0x03];
- ++pc;
- pbuf[bufcnt++] = SDbuf[*pc & 0x0f];
- pc += SDcnt[*pc & 0x0f];
- break;
-
- case MOVMM|B1:
- case MOVMM|B2:
- case MOVMM|B4:
- case MOVMM|B8:
- pbuf[bufcnt++] = "movmm|";
- pbuf[bufcnt++] = Bbuf[*pc & 0x03];
- ++pc;
- pbuf[bufcnt++] = SDbuf[*pc & 0x0f];
- pc += SDcnt[*pc & 0x0f];
- break;
-
- case DUMP:
- pbuf[bufcnt++] = "dump ";
- break;
- case REGAIN:
- pbuf[bufcnt++] = "regain ";
- break;
- case CALL:
- pbuf[bufcnt++] = "call ";
- break;
- case RET:
- pbuf[bufcnt++] = "ret ";
- break;
- case SWAP:
- pbuf[bufcnt++] = "swap ";
- break;
- case SWAP4:
- pbuf[bufcnt++] = "swap4 ";
- break;
- case SWAP4DEEP:
- pbuf[bufcnt++] = "swap4deep ";
- break;
- case DUP:
- pbuf[bufcnt++] = "dup ";
- break;
- case DUP4:
- pbuf[bufcnt++] = "dup4 ";
- break;
- case ABSMEM:
- pbuf[bufcnt++] = "absmem ";
- break;
- case ABSSTK:
- pbuf[bufcnt++] = "absstk ";
- break;
- case MOVDA1:
- pbuf[bufcnt++] = "movda1 ";
- break;
- case MOVDA2:
- pbuf[bufcnt++] = "movda2 ";
- break;
- case MOVDA4:
- pbuf[bufcnt++] = "movda4 ";
- break;
- case MOVDA8:
- pbuf[bufcnt++] = "movda8 ";
- break;
- case MOVDAX:
- pbuf[bufcnt++] = "movdax ";
- break;
- case MOVAA1:
- pbuf[bufcnt++] = "movaa1 ";
- break;
- case MOVAA2:
- pbuf[bufcnt++] = "movaa2 ";
- break;
- case MOVAA4:
- pbuf[bufcnt++] = "movaa4 ";
- break;
- case MOVAA8:
- pbuf[bufcnt++] = "movaa8 ";
- break;
- case MOVAAX:
- pbuf[bufcnt++] = "movaax ";
- break;
- case MOVAAC:
- pbuf[bufcnt++] = "movaac ";
- break;
- case NOP:
- pbuf[bufcnt++] = "nop ";
- break;
- } /* END: switch(*pc) */
- }/* END: for() */
- for(i = 0; i < bufcnt; ++i)
- fwrite(pbuf[i], 1, strlen(pbuf[i]), iv->outfile);
- fwrite("\n", 1, 1, iv->outfile);
- }/* END: printinst() */
- static void
- disassemble(Piv iv, void *ptr, long size)
- {
- int x;
- long offset = iv->out_offset;
-
- x = print8(iv, ptr, size, offset, 0);
- printinst(iv, ptr, size);
- while((size -= x) > 0)
- {
- offset += x;
- ((char*)ptr) += x;
- x = print8(iv, ptr, size, offset, 1);
- }
- }
- static void
- reset_funcdata(Piv iv)
- {
- iv->obuf = (char*)&iv->obufstart;
- iv->obufstart = 0;
- iv->obufcnt = 0;
- iv->func_offset = 0;
- iv->jbuf = (PJL)&iv->jbufstart;
- iv->jmpcnt = 0;
- iv->jbufcnt = 0;
- iv->jbufstart = 0;
- iv->extbuf = (PEL)&iv->extbufstart;
- iv->extcnt = 0;
- iv->extbufcnt = 0;
- iv->extbufstart = 0;
- iv->stackdepth = 0;
- iv->maxdepth = 0;
- iv->mindepth = 0;
- iv->numnested = 0;
- iv->cod_bufcnt = 0;
- iv->ob_bufcnt = 0;
- iv->cod_usedhead = 0;
- iv->ob_usedhead = 0;
- iv->first_cod = 0;
- iv->first_ob = 0;
- Cfreecat(FUNCDATA);
- }
- static void
- write_funcdata(Piv iv, unsigned char *pdef)
- {
- long *p;
- if((p = (long*)iv->obufstart))
- {
- setup_jmps(iv, pdef);
- while(shorten_jmps(iv))
- ;
- while(p)
- {
- if(iv->listing_wanted)
- {
- if(((unsigned char*)p)[8] == LINENO)
- {
- printline(iv, &((unsigned char*)p)[9]);
- }
- else if(((unsigned char*)p)[8] == NFUNC)
- {
- char *funcname = *((char**)&(((char*)p)[9]));
- fprintf(iv->outfile, "\n%8.8lx: .nested .function _%s\n",
- iv->out_offset, funcname);
- }
- else
- {
- disassemble(iv, &p[2], p[1]);
- iv->out_offset += p[1];
- }
- }
- else
- {
- FILEWRITE(&p[2],p[1]);
- iv->out_offset += p[1];
- }
- p = (void*)p[0];
- }
- }
- if(iv->debug >= '1')
- cfeprintf("MAXDEPTH=%d MINDEPTH=%d func=%s\n",
- iv->maxdepth, iv->mindepth, iv->symaddr[GL( ((Pop)pdef)->data )]);
-
- save_maxdepth(iv, GL( ((Pop)pdef)->data ));
- }
- static void *
- write_obuf(Piv iv, unsigned char *buf, long cnt)
- {/* Output first goes to a linked list */
- void *next = iv->obuf;
-
- if(iv->obuf != (unsigned char*)&iv->obufstart)
- {/* Suppress duplicate RETs */
- if(buf[0] == RET && (iv->obuf[8] == RET || iv->obuf[9] == RETSTRUCT) )
- {
- return iv->obuf;
- }
- }
- if(iv->obufcnt >= cnt+8)
- {/* There is sufficient room in the current chunk */
- long size = ((long*)iv->obuf)[1];
- iv->obuf += size+8;
- }
- else
- {/* Allocate a new chunk of linked list space */
- iv->obufcnt = 4080;
- iv->obuf = Ccalloc(FUNCDATA, 1, iv->obufcnt);
- }
-
- *((void**)next) = iv->obuf; /* link back to old entry */
- ((long*)iv->obuf)[1] = cnt; /* record the size of the data */
- iv->obufcnt -= cnt+8; /* deduct data size plus overhead */
- memcpy(&((long*)iv->obuf)[2], buf, cnt); /* copy the data to this area */
- if(buf[0] != LINENO && buf[0] != NFUNC)
- {/* A line number record is an anomoly */
- if(iv->extmark)
- addto_extlist(iv, buf); /* reference to external variable here */
- iv->func_offset += cnt; /* increase the program counter */
- }
-
- iv->cod->ee = (struct _nodeOBUF *)iv->obuf; /* points to obuf chunks */
- link_cod(iv);
-
- return iv->obuf; /* return the address of this sub chunk */
- }
- static void
- do_conversion(Piv iv, PND dst, PND src)
- {
- unsigned char obuf[2];
- int dsize = dst->size;
- int ssize = src->size;
- unsigned char ddtype = dst->dtype;
- unsigned char sdtype = src->dtype;
- #define SRC(a) (a<<4)
-
- if(src->atype & (A_ABSOLUTE|A_POINTER|A_VALUE) == (A_POINTER|A_VALUE))
- {
- if(src->atype & A_DATA)
- obuf[0] = ABSMEM;
- else if(src->atype & (A_AUTO|A_PARAM))
- obuf[0] = ABSSTK;
- else
- PERROR(pName ":ERROR: Line:%d bad conversion0\n", iv->lastline);
- write_obuf(iv, obuf, 1);
- return;
- }
- obuf[0] = CVT;
- switch(ddtype)
- {
- case D_SIGNED: /* dest is signed integer */
- {
- if(dsize == 1)
- obuf[1] = BYTE;
- else if(dsize == 2)
- obuf[1] = SHORT;
- else if(dsize == 4)
- obuf[1] = LONG;
- else if(dsize == 8)
- obuf[1] = CLONGLONG;
- switch(sdtype)
- {
- case D_SIGNED:
- {/* src is signed integer */
- if(dsize <= ssize)
- return;
- if(ssize == 1)
- obuf[1] |= SRC(BYTE);
- else if(ssize == 2)
- obuf[1] |= SRC(SHORT);
- else if(ssize == 4)
- obuf[1] |= SRC(LONG);
- else if(ssize == 8)
- obuf[1] |= SRC(CLONGLONG);
- break;
- }
- case D_UNSIGNED:
- case D_SEGMENT:
- {/* src is unsigned integer */
- if(dsize <= ssize)
- return;
- if(ssize == 1)
- obuf[1] |= SRC(UBYTE);
- else if(ssize == 2)
- obuf[1] |= SRC(USHORT);
- else if(ssize == 4)
- obuf[1] |= SRC(ULONG);
- else if(ssize == 8)
- obuf[1] |= SRC(CULONGLONG);
- break;
- }
- case D_FLOAT:
- {/* src is floating point */
- if(ssize == 4)
- obuf[1] |= SRC(FLOAT);
- else if(ssize == 8)
- obuf[1] |= SRC(DOUBLE);
- else
- obuf[1] |= SRC(CLONGDOUBLE);
- break;
- }
- case D_POINTER:
- case D_FUNCPTR:
- {/* src is unsigned int */
- if(dsize <= ssize)
- return;
- if(ssize == 1)
- obuf[1] |= SRC(UBYTE);
- else if(ssize == 2)
- obuf[1] |= SRC(USHORT);
- else if(ssize == 4)
- obuf[1] |= SRC(ULONG);
- else if(ssize == 8)
- obuf[1] |= SRC(CULONGLONG);
- break;
- }
- default:
- PERROR(pName ":ERROR: Line:%d bad conversion1\n", iv->lastline);
- }
- break;
- }
- case D_UNSIGNED: /* dest is unsigned integer */
- case D_SEGMENT:
- {
- if(dsize == 1)
- obuf[1] = UBYTE;
- else if(dsize == 2)
- obuf[1] = USHORT;
- else if(dsize == 4)
- obuf[1] = ULONG;
- else if(dsize == 8)
- obuf[1] = CULONGLONG;
- switch(sdtype)
- {
- case D_SIGNED:
- {/* src is signed integer */
- if(dsize <= ssize)
- return;
- if(ssize == 1)
- obuf[1] |= SRC(BYTE);
- else if(ssize == 2)
- obuf[1] |= SRC(SHORT);
- else if(ssize == 4)
- obuf[1] |= SRC(LONG);
- else if(ssize == 8)
- obuf[1] |= SRC(CLONGLONG);
- break;
- }
- case D_UNSIGNED:
- case D_SEGMENT:
- {/* src is unsigned integer */
- if(dsize <= ssize)
- return;
- if(ssize == 1)
- obuf[1] |= SRC(UBYTE);
- else if(ssize == 2)
- obuf[1] |= SRC(USHORT);
- else if(ssize == 4)
- obuf[1] |= SRC(ULONG);
- else if(ssize == 8)
- obuf[1] |= SRC(CULONGLONG);
- break;
- }
- case D_FLOAT:
- {/* src is floating point */
- if(ssize == 4)
- obuf[1] |= SRC(FLOAT);
- else if(ssize == 8)
- obuf[1] |= SRC(DOUBLE);
- else
- obuf[1] |= SRC(CLONGDOUBLE);
- break;
- }
- case D_POINTER:
- case D_FUNCPTR:
- {/* src is unsigned integer */
- if(dsize <= ssize)
- return;
- if(ssize == 1)
- obuf[1] |= SRC(UBYTE);
- else if(ssize == 2)
- obuf[1] |= SRC(USHORT);
- else if(ssize == 4)
- obuf[1] |= SRC(ULONG);
- else if(ssize == 8)
- obuf[1] |= SRC(CULONGLONG);
- break;
- }
- default:
- PERROR(pName ":ERROR: Line:%d bad conversion2\n", iv->lastline);
- }
- break;
- }
- case D_FLOAT: /* dest is float, double, long double */
- {
- if(dsize == 4)
- obuf[1] = FLOAT;
- else if(dsize == 8)
- obuf[1] = DOUBLE;
- else
- obuf[1] = CLONGDOUBLE;
- switch(sdtype)
- {
- case D_SIGNED:
- {/* src is signed integer */
- if(ssize == 1)
- obuf[1] |= SRC(BYTE);
- else if(ssize == 2)
- obuf[1] |= SRC(SHORT);
- else if(ssize == 4)
- obuf[1] |= SRC(LONG);
- else if(ssize == 8)
- obuf[1] |= SRC(CLONGLONG);
- break;
- }
- case D_UNSIGNED:
- case D_SEGMENT:
- {/* src is unsigned integer */
- if(ssize == 1)
- obuf[1] |= SRC(UBYTE);
- else if(ssize == 2)
- obuf[1] |= SRC(USHORT);
- else if(ssize == 4)
- obuf[1] |= SRC(ULONG);
- else if(ssize == 8)
- obuf[1] |= SRC(CULONGLONG);
- break;
- }
- case D_FLOAT:
- {/* src is floating point */
- if(dsize == ssize)
- return;
- if(ssize == 4)
- obuf[1] |= SRC(FLOAT);
- else if(ssize == 8)
- obuf[1] |= SRC(DOUBLE);
- else
- obuf[1] |= SRC(CLONGDOUBLE);
- break;
- }
- case D_POINTER:
- case D_FUNCPTR:
- {/* src is unsigned integer */
- if(ssize == 1)
- obuf[1] |= SRC(UBYTE);
- else if(ssize == 2)
- obuf[1] |= SRC(USHORT);
- else if(ssize == 4)
- obuf[1] |= SRC(ULONG);
- else if(ssize == 8)
- obuf[1] |= SRC(CULONGLONG);
- break;
- }
- default:
- PERROR(pName ":ERROR: Line:%d bad conversion3\n", iv->lastline);
- }
- break;
- }
- case D_POINTER:
- case D_FUNCPTR:
- {/* dest is unsigned integer */
- if(dsize == 1)
- obuf[1] = BYTE;
- else if(dsize == 2)
- obuf[1] = SHORT;
- else if(dsize == 4)
- obuf[1] = LONG;
- else if(dsize == 8)
- obuf[1] = CLONGLONG;
- switch(sdtype)
- {
- case D_SIGNED:
- {/* src is signed integer */
- if(dsize <= ssize)
- return;
- if(ssize == 1)
- obuf[1] |= SRC(BYTE);
- else if(ssize == 2)
- obuf[1] |= SRC(SHORT);
- else if(ssize == 4)
- obuf[1] |= SRC(LONG);
- else if(ssize == 8)
- obuf[1] |= SRC(CLONGLONG);
- break;
- }
- case D_UNSIGNED:
- case D_SEGMENT:
- {/* src is unsigned integer */
- if(dsize <= ssize)
- return;
- if(ssize == 1)
- obuf[1] |= SRC(UBYTE);
- else if(ssize == 2)
- obuf[1] |= SRC(USHORT);
- else if(ssize == 4)
- obuf[1] |= SRC(ULONG);
- else if(ssize == 8)
- obuf[1] |= SRC(CULONGLONG);
- break;
- }
- case D_FLOAT:
- {/* src is floating point */
- if(ssize == 4)
- obuf[1] |= SRC(FLOAT);
- else if(ssize == 8)
- obuf[1] |= SRC(DOUBLE);
- else
- obuf[1] |= SRC(CLONGDOUBLE);
- break;
- }
- case D_POINTER:
- case D_FUNCPTR:
- {/* src is unsigned integer */
- if(dsize <= ssize)
- return;
- if(ssize == 1)
- obuf[1] |= SRC(UBYTE);
- else if(ssize == 2)
- obuf[1] |= SRC(USHORT);
- else if(ssize == 4)
- obuf[1] |= SRC(ULONG);
- else if(ssize == 8)
- obuf[1] |= SRC(CULONGLONG);
- break;
- }
- default:
- PERROR(pName ":ERROR: Line:%d bad conversion4\n", iv->lastline);
- }
- break;
- }
- default:
- PRINTF("Line:%d no conversion\n", iv->lastline);
- return;
- }
- write_obuf(iv, obuf, 2);
- #undef SRC
- }
- static int
- check_assignment_conversion(PND dst, PND src)
- {
- long dsize = dst->size;
- long ssize = src->size;
- unsigned char ddtype = dst->dtype;
- unsigned char sdtype = src->dtype;
- int ret = 0;
-
- if(src->atype & (A_ABSOLUTE|A_POINTER|A_VALUE) == (A_POINTER|A_VALUE))
- return 1;
- switch(ddtype)
- {
- case D_SIGNED: /* dest is signed integer */
- {
- switch(sdtype)
- {
- case D_SIGNED:
- case D_UNSIGNED:
- case D_SEGMENT:
- case D_POINTER:
- case D_FUNCPTR:
- {
- if(dsize > ssize)
- ret = 1;
- break;
- }
- case D_FLOAT:
- {
- ret = 1;
- break;
- }
- }
- break;
- }
- case D_UNSIGNED: /* dest is unsigned integer */
- case D_SEGMENT:
- {
- switch(sdtype)
- {
- case D_SIGNED:
- case D_UNSIGNED:
- case D_SEGMENT:
- case D_POINTER:
- case D_FUNCPTR:
- {
- if(dsize > ssize)
- ret = 1;
- break;
- }
- case D_FLOAT:
- {
- ret = 1;
- break;
- }
- }
- break;
- }
- case D_FLOAT: /* dest is float, double, long double */
- {
- if(sdtype == D_FLOAT)
- {
- if(dsize != ssize)
- ret = 1;
- }
- else ret = 1;
- break;
- }
- case D_POINTER:
- case D_FUNCPTR: /* dest is pointer */
- {
- switch(sdtype)
- {
- case D_SIGNED:
- case D_UNSIGNED:
- case D_SEGMENT:
- case D_POINTER:
- case D_FUNCPTR:
- {
- if(dsize > ssize)
- ret = 1;
- break;
- }
- case D_FLOAT:
- {
- ret = 1;
- break;
- }
- }
- break;
- }
- }
- return ret;
- }
- static int
- check_binop_conversion(PND dst, PND src)
- {
- long dsize = dst->size;
- long ssize = src->size;
- unsigned char ddtype = dst->dtype;
- unsigned char sdtype = src->dtype;
- int ret = 0;
-
- switch(ddtype)
- {
- case D_SIGNED: /* dest is signed integer */
- {
- switch(sdtype)
- {
- case D_SIGNED:
- case D_UNSIGNED:
- case D_SEGMENT:
- case D_POINTER:
- case D_FUNCPTR:
- {
- if(dsize > ssize)
- ret = 1;
- break;
- }
- }
- break;
- }
- case D_UNSIGNED: /* dest is unsigned integer */
- case D_SEGMENT:
- {
- switch(sdtype)
- {
- case D_SIGNED:
- case D_UNSIGNED:
- case D_SEGMENT:
- case D_POINTER:
- case D_FUNCPTR:
- {
- if(dsize > ssize)
- ret = 1;
- break;
- }
- }
- break;
- }
- case D_FLOAT: /* dest is float, double, long double */
- {
- if(sdtype == D_FLOAT)
- {
- if(dsize > ssize)
- ret = 1;
- }
- else ret = 1;
- break;
- }
- case D_POINTER:
- case D_FUNCPTR: /* dest is pointer */
- {
- switch(sdtype)
- {
- case D_SIGNED:
- case D_UNSIGNED:
- case D_SEGMENT:
- case D_POINTER:
- case D_FUNCPTR:
- {
- if(dsize > ssize)
- ret = 1;
- break;
- }
- }
- break;
- }
- }
- return ret;
- }
- static int
- get_size(int type, int size)
- {
- switch(type)
- {
- case D_ARRAY:
- case D_STRUCT:
- case D_FUNCTION:
- return B4;
-
- default:
- switch(size)
- {
- case 1:
- return B1;
- case 2:
- return B2;
- case 4:
- return B4;
- case 8:
- return B8;
- default:
- #if SUPPORT_LONG_DOUBLE
- return BX;
- #endif
- }
- }
- return 0;
- }
- static int
- load_addr(Piv iv, unsigned char *poc, void *buf, PND pnd, int shft)
- {/* Use the shortest possible representation */
- long offset = pnd->OFFSET;
- long ofs = offset >> 2;
-
- if(pnd->atype & (A_EXTERN|A_ABSOLUTE))
- {/* 4 bytes for absolute values */
- *poc |= 3<<shft;
- *((long*)buf) = offset;
- iv->extmark += 1;
- iv->markedsym[iv->extmark] = pnd->SYMNUM;
- iv->markedbuf[iv->extmark] = buf;
- return 4;
- }
- if(offset & 0xff000000)
- {/* Relative values are restricted to 28 bits max */
- PERROR(pName ":ERROR: Line:%d offset too large %x\n", iv->lastline, ofs);
- return 0;
- }
- if(offset & 0xffff0000 || offset & 0x00000003)
- {/* 3 bytes for large values and non-aligned values */
- *poc |= 2<<shft;
- *((long*)buf) = offset;
- return 3;
- }
- else if(ofs & 0xffffff00)
- {/* 2 or fewer bytes for small aligned values */
- *poc |= 1<<shft;
- *((short*)buf) = (short)ofs;
- return 2;
- }
- else
- {
- *((char*)buf) = (char)ofs;
- return 1;
- }
-
- }
- static void
- load_val(Piv iv, unsigned long val)
- {
- unsigned char obuf[10];
-
- obuf[0] = LUI;
- ++iv->stackdepth;
- if(val & 0xffff0000)
- {
- obuf[0] |= 2;
- *((unsigned long*)&obuf[1]) = val;
- write_obuf(iv, obuf, 5);
- }
- else if(val & 0xffffff00)
- {
- obuf[0] |= 1;
- *((unsigned short*)&obuf[1]) = (unsigned short)val;
- write_obuf(iv, obuf, 3);
- }
- else
- {
- obuf[1] = (unsigned char)val;
- write_obuf(iv, obuf, 2);
- }
- }
- static int
- load_immed(Piv iv, unsigned char *poc, void *obuf, PND pnd, int osize)
- {
- unsigned short dtype = pnd->dtype;
- unsigned char mosize = pnd->opsize;
- void *ibuf = pnd->data;
-
- if(osize >= 0)
- {/* force the immediate value to conform to osize */
- if(osize == mosize)
- {
- switch(osize)
- {
- case B1:
- *((char*)obuf) = *((char*)ibuf);
- return 1;
- case B2:
- *((short*)obuf) = *((short*)ibuf);
- return 2;
- case B4:
- *((long*)obuf) = *((long*)ibuf);
- return 4;
- case B8:
- *((double*)obuf) = *((double*)ibuf);
- return 8;
- case BX:
- #if SUPPORT_LONG_DOUBLE
- *((long double*)obuf) = *((long double*)ibuf);
- #else
- memcpy(obuf, ibuf, XSZ);
- #endif
- return XSZ;
- default:
- PERROR(pName ":ERROR: Line:%d LOAD IMMED SYSERR osize=%d\n", iv->lastline, osize);
- }
- }
- else /* osize != mosize */
- {
- if(dtype == D_FLOAT)
- {
- float f;
- double d;
- #if SUPPORT_LONG_DOUBLE
- long double ld;
- #endif
- switch(osize)
- {
- case B4:
- switch(mosize)
- {
- case B8:
- f = (float)*((double*)ibuf);
- *((float*)obuf) = f;
- return 4;
- case BX:
- #if SUPPORT_LONG_DOUBLE
- f = (float)*((long double*)ibuf);
- *((float*)obuf) = f;
- return 4;
- #else
- PERROR(pName ":ERROR: Line:%d long double conversion not supported\n", iv->lastline);
- #endif
- default:
- PERROR(pName ":ERROR: Line:%d bad floating immediate input\n",iv->lastline);
- }
- case B8:
- switch(mosize)
- {
- case B4:
- d = (double)*((float*)ibuf);
- *((double*)obuf) = d;
- return 8;
- case BX:
- #if SUPPORT_LONG_DOUBLE
- d = (double)*((long double*)ibuf);
- *((double*)obuf) = d;
- return 8;
- #else
- PERROR(pName ":ERROR: Line:%d long double conversion not supported\n", iv->lastline);
- #endif
- default:
- PERROR(pName ":ERROR: Line:%d bad floating immediate input\n", iv->lastline);
- }
- case BX:
- #if SUPPORT_LONG_DOUBLE
- switch(mosize)
- {
- case B4:
- ld = (long double)*((float*)ibuf);
- *((long double*)obuf) = ld;
- return XSZ;
- case B8:
- ld = (long double)*((double*)ibuf);
- *((long double*)obuf) = ld;
- return XSZ;
- default:
- PERROR(pName ":ERROR: Line:%d bad floating immediate input\n", iv->lastline);
- }
- break;
- #else
- PERROR(pName ":ERROR: Line:%d long double conversion not supported\n", iv->lastline);
- #endif
- break;
- default:
- PERROR(pName ":ERROR: Line:%d bad floating immediate output\n", iv->lastline);
- }
- }/* END: dtype == D_FLOAT */
- else if(dtype == D_UNSIGNED || dtype == D_POINTER)
- {
- switch(osize)
- {
- case B1:
- *((unsigned char*)obuf) = *((unsigned char *)ibuf);
- return 1;
- case B2:
- switch(mosize)
- {
- case B1:
- *((unsigned short*)obuf) = *((unsigned char*)ibuf);
- return 2;
- case B4:
- case B8:
- *((unsigned short*)obuf) = *((unsigned short*)ibuf);
- return 2;
- case BX:
- PERROR(pName ":ERROR: Line:%d invalid integer size\n", iv->lastline);
- default:
- PERROR(pName ":ERROR: Line:%d invalid immediate input\n", iv->lastline);
- }
- case B4:
- switch(mosize)
- {
- case B1:
- *((unsigned long*)obuf) = *((unsigned char*)ibuf);
- return 4;
- case B2:
- *((unsigned long*)obuf) = *((unsigned short*)ibuf);
- return 4;
- case B8:
- *((unsigned long*)obuf) = *((unsigned long*)ibuf);
- return 4;
- case BX:
- PERROR(pName ":ERROR: Line: invalid integer size\n", iv->lastline);
- default:
- PERROR(pName ":ERROR: Line:%d invalid immediate input\n", iv->lastline);
- }
- case B8:
- {
- unsigned long l[2];
- l[0] = 0;
- l[1] = 0;
- if(mosize == B4)
- l[0] = *((unsigned long*)ibuf);
- else if(mosize == B2)
- l[0] = *((unsigned short*)ibuf);
- else if(mosize == B1)
- l[0] = *((unsigned char*)ibuf);
- else
- PERROR(pName ":ERROR: Line:%d invalid integer size\n", iv->lastline);
- memcpy(obuf, l, 8);
- return 8;
- }
- default:
- PERROR(pName ":ERROR: Line:%d invalid integer size=%d\n",
- iv->lastline, osize);
- }
- }
- else /* signed integer */
- {
- switch(osize)
- {
- case B1:
- *((char*)obuf) = *((char *)ibuf);
- return 1;
- case B2:
- switch(mosize)
- {
- case B1:
- *((short*)obuf) = *((char*)ibuf);
- return 2;
- case B4:
- case B8:
- *((short*)obuf) = *((short*)ibuf);
- return 2;
- case BX:
- PERROR(pName ":ERROR: Line:%d invalid integer size\n", iv->lastline);
- default:
- PERROR(pName ":ERROR: Line:%d invalid immediate input\n",iv->lastline);
- }
- case B4:
- switch(mosize)
- {
- case B1:
- *((long*)obuf) = *((char*)ibuf);
- return 4;
- case B2:
- *((long*)obuf) = *((short*)ibuf);
- return 4;
- case B8:
- *((long*)obuf) = *((long*)ibuf);
- return 4;
- case BX:
- PERROR(pName ":ERROR: Line:%d invalid integer size\n", iv->lastline);
- default:
- PERROR(pName ":ERROR: Line:%d invalid immediate input\n", iv->lastline);
- }
- case B8:
- {
- long l[2];
- l[0] = 0;
- l[1] = 0;
- if(mosize == B4)
- l[0] = *((long*)ibuf);
- else if(mosize == B2)
- l[0] = *((short*)ibuf);
- else if(mosize == B1)
- l[0] = *((char*)ibuf);
- else
- PERROR(pName ":ERROR: Line:%d invalid integer size\n", iv->lastline);
- if(l[0] < 0)
- l[1] = -1;
- memcpy(obuf, l, 8);
- return 8;
- }
- default:
- PERROR(pName ":ERROR: Line:%d invalid integer size=%d\n",
- iv->lastline, osize);
- }
- }/* END: signed integer */
- }/* END: osize != mosize */
- /* NOT REACHED */
- PERROR(pName ":ERROR: Line:%d LOAD IMMED SYSERR1 osize=%d mosize=%d\n", iv->lastline, osize, mosize);
- return 0; /* suppress compiler warning */
- }
- else
- {/* generate the shortest possible immediate value */
- int thesize = 0;
- if(dtype == D_FLOAT)
- {
- switch(mosize)
- {
- case B4:
- *((float*)obuf) = *((float*)ibuf);
- thesize = 4;
- break;
- case B8:
- *((double*)obuf) = *((double*)ibuf);
- thesize = 8;
- break;
- case BX:
- #if SUPPORT_LONG_DOUBLE
- *((long double*)obuf) = *((long double*)ibuf);
- #else
- memcpy(obuf, ibuf, XSZ);
- #endif
- thesize = XSZ;
- break;
- default:
- PERROR(pName ":ERROR: Line:%d wrong sized floating immediate\n", iv->lastline);
- }
- }
- else /* dtype not D_FLOAT */
- {
- int negative;
- int sgned;
- unsigned long ul[2];
- long *sl;
-
- ul[1] = 0;
- negative = 0;
- sl = ul;
- if(dtype == D_UNSIGNED || dtype == D_POINTER)
- {
- sgned = 0;
- if(mosize == B8)
- {
- ul[0] = *((unsigned long*)ibuf);
- ul[1] = *((unsigned long*)(((char*)ibuf)+4));
- }
- else
- {
- if(mosize == B4)
- ul[0] = *((unsigned long*)ibuf);
- else if(mosize == B2)
- ul[0] = *((unsigned short*)ibuf);
- else if(mosize == B1)
- ul[0] = *((unsigned char*)ibuf);
- else
- PERROR(pName ":ERROR: Line:%d invalid integer immediate\n", iv->lastline);
- }
- }
- else /* sgned */
- {
- sgned = 1;
- if(mosize == B8)
- {
- sl[0] = *((long*)ibuf);
- sl[1] = *((long*)(((char*)ibuf)+4));
- if(sl[1] < 0)
- {
- negative = 1;
- ul[1] = ~ul[1];
- ul[0] = ~ul[0];
- if(ul[0] == 0xffffffff)
- {
- ul[0] = 0;
- ul[1] += 1;
- }
- else ul[0] += 1;
- }
- }
- else
- {
- if(mosize == B4)
- sl[0] = *((long*)ibuf);
- else if(mosize == B2)
- sl[0] = *((short*)ibuf);
- else if(mosize == B1)
- sl[0] = *((char*)ibuf);
- else
- PERROR(pName ":ERROR: Line:%d invalid integer immediate\n",iv->lastline);
- if(sl[0] < 0)
- {
- negative = 1;
- sl[0] = -sl[0];
- }
- }
- } /* END: sgned */
- if(negative)
- {
- if(ul[1])
- mosize = B8;
- else if(ul[0] & 0xffff8000)
- mosize = B4;
- else if(ul[0] & 0xffffff80)
- mosize = B2;
- else
- mosize = B1;
- }
- else
- {
- if(sgned)
- {
- if(ul[1])
- mosize = B8;
- else if(ul[0] & 0xffff8000)
- {
- if(!(ul[0] & 0xffff0000))
- {
- *poc = LUI;
- mosize = B2;
- }
- else
- mosize = B4;
- }
- else if(ul[0] & 0xffffff80)
- {
- if(!(ul[0] & 0xffffff00))
- {
- *poc = LUI;
- mosize = B1;
- }
- else
- mosize = B2;
- }
- else
- mosize = B1;
- }
- else /* unsigned */
- {
- if(ul[1])
- mosize = B8;
- else if(ul[0] & 0xffff0000)
- mosize = B4;
- else if(ul[0] & 0xffffff00)
- mosize = B2;
- else
- mosize = B1;
- }
- }
- if(negative)
- {
- ul[1] = ~ul[1];
- ul[0] = ~ul[0];
- if(ul[0] == 0xffffffff)
- {
- ul[0] = 0;
- ul[1] += 1;
- }
- else ul[0] += 1;
- }
- switch(mosize)
- {
- case B1:
- *((char*)obuf) = *((char*)sl);
- thesize = 1;
- break;
- case B2:
- *((short*)obuf) = *((short*)sl);
- thesize = 2;
- break;
- case B4:
- *((long*)obuf) = *((long*)sl);
- thesize = 4;
- break;
- case B8:
- *((double*)obuf) = *((double*)sl);
- thesize = 8;
- break;
- }
- }/* END: not D_FLOAT */
- *poc |= mosize;
- return thesize;
- }
- }
- static void
- addr_toevalstack(Piv iv, PND pnd)
- {
- unsigned char obuf[20];
- int atype = pnd->atype;
-
- if(atype & (A_AUTO|A_PARAM|A_DATA))
- {
- int l;
- obuf[0] = LAI;
- l = 1;
- l += load_addr(iv, &obuf[0], &obuf[1], pnd, 0);
-
- write_obuf(iv, obuf, l);
- if(atype & (A_AUTO|A_PARAM))
- {
- obuf[0] = ABSSTK;
- write_obuf(iv, obuf, 1);
- }
- else if(l < 5)
- {
- obuf[0] = ABSMEM;
- write_obuf(iv, obuf, 1);
- }
- ++iv->stackdepth;
- }
- }
- static void
- data_toevalstack(Piv iv, PND pnd, PND dst)
- {
- unsigned char obuf[20];
- int xtra, oc;
- unsigned short dtype, atype;
- unsigned char osize;
-
- atype = pnd->atype;
- dtype = pnd->dtype;
- if(atype & A_IMMED)
- {
- if(dtype == D_UNSIGNED)
- obuf[0] = LUI;
- else
- obuf[0] = LI;
- xtra = load_immed(iv, &obuf[0], &obuf[1], pnd, -1);
- write_obuf(iv, obuf, 1+xtra);
- ++iv->stackdepth;
- return;
- }
- xtra = oc = 0;
- osize = pnd->opsize;
- if(osize == BX)
- {
- obuf[0] = XTD;
- osize = 0;
- oc = 1;
- xtra = 1;
- }
- if(atype & (A_TEMP|A_RET))
- {
- if(atype & A_MEMADDR)
- {
- unsigned char xsize = get_datasize(0, pnd);
- if(osize == B8 && dtype < D_FLOAT)
- obuf[xtra++] = XTD;
-
- if( dst
- && (pnd->TMPNUM == dst->TMPNUM)
- && ((dst->atype & (A_ABSOLUTE|A_MEMADDR))
- == (A_ABSOLUTE|A_MEMADDR))
- )
- {/* generally used for a += b etc. */
- obuf[xtra++] = IMMED;
- obuf[xtra] = DEREF1|xsize;
- write_obuf(iv, obuf, 1+xtra);
- ++iv->stackdepth;
- }
- else
- {
- obuf[xtra++] = IMMED;
- obuf[xtra] = DEREF|get_datasize(0, pnd);
- write_obuf(iv, obuf, 1+xtra);
- }
- pnd->atype &= ~A_MEMADDR;
- pnd->atype |= A_VALUE;
- }
- return;
- }
-
- if(atype & (A_AUTO|A_PARAM))
- {
- if(atype & (A_POINTER|A_VALUE) == (A_POINTER|A_VALUE))
- {/* Put address on eval stack */
- addr_toevalstack(iv, pnd);
- pnd->atype |= A_ABSOLUTE;
- return;
- }
- else
- {
- obuf[oc] = LS|osize;
- xtra += load_addr(iv, &obuf[oc], &obuf[oc+1], pnd, 2);
- ++iv->stackdepth;
- }
- }
- else if(atype & A_DATA)
- {
- if(atype & (A_POINTER|A_VALUE) == (A_POINTER|A_VALUE))
- {/* Put address on eval stack */
- addr_toevalstack(iv, pnd);
- pnd->atype |= A_ABSOLUTE;
- return;
- }
- else
- {
- obuf[oc] = LM|osize;
- xtra += load_addr(iv,&obuf[oc], &obuf[oc+1], pnd, 2);
- ++iv->stackdepth;
- }
- }
- write_obuf(iv, obuf, 1+xtra);
- }
- static void
- promote_arg(Piv iv, PND pnd, long argsize)
- {
- long dsize = pnd->size;
- struct _nd dst;
-
- if(dsize != argsize)
- {
- dst.size = argsize;
- dst.dtype = pnd->dtype;
- dst.atype = 0;
- do_conversion(iv, &dst, pnd);
- }
- }
- static unsigned char
- arg_toevalstack(Piv iv, PND pnd, long argsize)
- {
- unsigned char dtype;
-
- if(pnd->atype & A_IMMED)
- {
- data_toevalstack(iv, pnd, 0);
- return ARG;
- }
- dtype = pnd->dtype;
- if(dtype == D_STRUCT)
- {
- addr_toevalstack(iv, pnd);
- return ARGA;
- }
- else if(dtype == D_FUNCTION)
- {
- addr_toevalstack(iv, pnd);
- return ARGF;
- }
- else if(dtype == D_FUNCPTR)
- {
- data_toevalstack(iv, pnd, 0);
- return ARGF;
- }
- else if(dtype == D_ARRAY)
- {
- addr_toevalstack(iv, pnd);
- }
- else
- {
- data_toevalstack(iv, pnd, 0);
- promote_arg(iv, pnd, argsize);
- }
- return ARG;
- }
- static void
- mov_esdata(Piv iv, unsigned short atype, int size)
- {
- unsigned char obuf[2];
-
- if(atype & A_MEMADDR)
- {
- if(size == B1)
- obuf[0] = MOVAA1;
- else if(size == B2)
- obuf[0] = MOVAA2;
- else if(size == B4)
- obuf[0] = MOVAA4;
- else if(size == B8)
- obuf[0] = MOVAA8;
- #if SUPPORT_LONG_DOUBLE
- else if(size == BX)
- obuf[0] = MOVAAX;
- #endif
- else {obuf[0] = MOVAAC; size = XSZ;}
- }
- else
- {
- if(size == B1)
- obuf[0] = MOVDA1;
- else if(size == B2)
- obuf[0] = MOVDA2;
- else if(size == B4)
- obuf[0] = MOVDA4;
- else if(size == B8)
- obuf[0] = MOVDA8;
- #if SUPPORT_LONG_DOUBLE
- else if(size == BX)
- obuf[0] = MOVDAX;
- #endif
- else
- PERROR(pName ":ERROR: Line:%d illegal mov data size=%d\n", iv->lastline, size);
- }
- if(obuf[0] == MOVAAC)
- {
- load_val(iv, size);
- --iv->stackdepth;
- }
- write_obuf(iv, obuf, 1);
- iv->stackdepth -= 2;
- }
- static void
- from_evalstack(Piv iv, PND d, PND s)
- {
- unsigned char obuf[20];
- int xtra, oc;
- unsigned short datype = d->atype;
- unsigned char osize = d->opsize;
-
- xtra = oc = 0;
-
- if(datype & (A_TEMP|A_RET))
- {
- if(datype & A_MEMADDR)
- {
- mov_esdata(iv, s->atype, osize);
- }
- return;
- }
-
- if(osize == BX)
- {
- obuf[0] = XTD;
- oc = 1;
- osize = 0;
- xtra = 1;
- }
- if(datype & (A_AUTO|A_PARAM))
- {
- obuf[oc] = SS|osize;
- xtra += load_addr(iv, &obuf[oc], &obuf[oc+1], d, 2);
- --iv->stackdepth;
- }
- else if(datype & OPDATA)
- {
- obuf[oc] = SM|osize;
- xtra += load_addr(iv, &obuf[oc], &obuf[oc+1], d, 2);
- --iv->stackdepth;
- }
- write_obuf(iv, obuf, 1+xtra);
- }
- static unsigned char
- get_datasize(unsigned char opcode, PND pnd)
- {
- unsigned char dtype = pnd->dtype;
- long dsize = pnd->size;
-
- switch(dtype)
- {
- case D_ARRAY:
- case D_FUNCTION:
- case D_STRUCT:
- return LONG;
- }
-
- if( opcode == orop
- || opcode == andop
- || opcode == notop
- || opcode == lshop
- || opcode == complop
- || opcode == xorop
- )
- {
- if(dsize == 1)
- return B1;
- else if(dsize == 2)
- return B2;
- else if(dsize == 4)
- return B4;
- else if(dsize == 8)
- return B8;
- else
- return BX;
- }
- else
- {
- if(dtype == D_UNSIGNED)
- {
- if(dsize == 1)
- return UBYTE;
- else if(dsize == 2)
- return USHORT;
- else if(dsize == 4)
- return ULONG;
- else
- {
- if(opcode == rshop)
- return SULONGLONG;
- return ULONGLONG;
- }
- }
- else if(dtype == D_FLOAT)
- {
- if(dsize == 4)
- return FLOAT;
- else if(dsize == 8)
- return DOUBLE;
- else
- return LONGDOUBLE;
- }
- else
- {
- if(dsize == 1)
- return BYTE;
- else if(dsize == 2)
- return SHORT;
- else if(dsize == 4)
- return LONG;
- else
- {
- if(opcode == rshop)
- return SLONGLONG;
- return LONGLONG;
- }
- }
- }
- return 0;
- }
- static void *
- new_nodeO(Piv iv)
- {
- PNODEO p;
-
- if(iv->ob_bufcnt < sizeof(NODEO))
- {/* Allocate a new chunk of linked list space */
- iv->ob_bufcnt = 4080;
- iv->ob_buf = Ccalloc(FUNCDATA, 1, iv->ob_bufcnt);
- }
- p = (PNODEO)iv->ob_buf;
- iv->ob_buf += sizeof(NODEO);
- iv->ob_bufcnt -= sizeof(NODEO);
- return p;
- }
- static void
- link_ob(Piv iv)
- {/* Attach to the used list */
-
- if(!iv->ob_usedhead)
- {
- iv->ob_usedhead = iv->ob;
- iv->ob_usedtail = iv->ob;
- }
- else
- {
- iv->ob_usedtail->next = iv->ob;
- iv->ob_usedtail = iv->ob;
- }
- iv->ob = new_nodeO(iv);
- }
- static void *
- new_nodeC(Piv iv)
- {
- PNODEC p;
-
- if(iv->cod_bufcnt < sizeof(NODEC))
- {/* Allocate a new chunk of linked list space */
- iv->cod_bufcnt = 4080;
- iv->cod_buf = Ccalloc(FUNCDATA, 1, iv->cod_bufcnt);
- }
- p = (PNODEC)iv->cod_buf;
- iv->cod_buf += sizeof(NODEC);
- iv->cod_bufcnt -= sizeof(NODEC);
- return p;
- }
- static void
- link_cod(Piv iv)
- {/* Attach to the used list */
-
- if(!iv->cod_usedhead)
- {
- iv->cod_usedhead = iv->cod;
- iv->cod_usedtail = iv->cod;
- }
- else
- {
- iv->cod_usedtail->next = iv->cod;
- iv->cod_usedtail = iv->cod;
- }
- iv->cod = new_nodeC(iv);
- }
- static PNODEC
- gen_inst(Piv iv, PNODEO pnode)
- {
- unsigned char *p;
- unsigned char obuf[40];
- int xtra, oc;
- unsigned char opcode;
- PND d,l,r;
-
- d = &pnode->d;
- l = &pnode->l;
- r = &pnode->r;
- p = pnode->p;
- opcode = *p;
-
- xtra = oc = 0;
-
- switch(opcode)
- {
- case regainop:
- obuf[0] = REGAIN;
- write_obuf(iv, obuf, 1);
- ++iv->stackdepth;
- break;
- case grabop:
- obuf[0] = SWAP4DEEP;
- write_obuf(iv, obuf, 1);
- break;
- case getvalop:
- case derefop:
- case assignop:
- case duptmpop:
- {
- if( opcode == getvalop
- && !(l->atype & A_IMMED)
- && l->dtype == D_FUNCTION)
- {
- addr_toevalstack(iv, l);
- }
- else if( opcode != derefop
- && !(l->atype & A_IMMED)
- && check_assignment_conversion(d, l))
- {/* Must move data through evaluation stack */
- data_toevalstack(iv, l, d);
- do_conversion(iv, d, l);
- l->atype &= ~A_MEMADDR;
- l->atype |= A_VALUE;
- if(opcode == assignop)
- from_evalstack(iv, d, l);
- }
- else
- {/* Can move data directly from memory to memory */
- unsigned char ddtype = d->dtype;
- unsigned char osize = d->opsize;
- unsigned short latype = l->atype;
- unsigned short datype = d->atype;
- if(osize == BX)
- {
- obuf[0] = XTD;
- oc = 1;
- osize = 0;
- xtra = 1;
- }
- if(latype & A_IMMED)
- {
- if(datype & (A_TEMP|A_RET))
- {
- if(l->dtype == D_UNSIGNED)
- obuf[oc] = LUI;
- else
- obuf[oc] = LI;
- xtra += load_immed(iv, &obuf[oc], &obuf[oc+1], l, -1);
- ++iv->stackdepth;
- if(datype & A_MEMADDR)
- {
- write_obuf(iv, obuf, 1+xtra);
- mov_esdata(iv, 0, osize);
- break;
- }
- }
- else if(datype & (A_AUTO|A_PARAM))
- {
- int lx;
- obuf[0] = IMMED;
- oc = 1;
- xtra = 1;
- obuf[oc] = SSI|osize;
- lx = load_addr(iv, &obuf[oc], &obuf[oc+1], d, 2);
- lx += load_immed(iv, &obuf[oc], &obuf[oc+1+lx], l, osize);
- xtra += lx;
- }
- else if(datype & A_DATA)
- {
- int lx;
- obuf[0] = IMMED;
- oc = 1;
- xtra = 1;
- obuf[oc] = SMI|osize;
- lx = load_addr(iv, &obuf[oc], &obuf[oc+1], d, 2);
- lx += load_immed(iv, &obuf[oc], &obuf[oc+1+lx], l, osize);
- xtra += lx;
- }
- else
- {
- return iv->cod_usedtail;
- }
- }
- else if(latype & (A_TEMP|A_RET))
- {
- if(datype & (A_TEMP|A_RET))
- {
- if(opcode == duptmpop)
- {
- if(osize <= B4)
- obuf[0] = DUP4;
- else
- obuf[0] = DUP;
- xtra = 0;
- ++iv->stackdepth;
- }
- else if(opcode == getvalop || opcode == derefop)
- {
- if(latype & A_MEMADDR)
- {
- unsigned char xsize = get_datasize(0, l);
- if(osize == B8 && ddtype < D_FLOAT)
- obuf[xtra++] = XTD;
- if(datype & A_MEMADDR)
- xsize = ULONG;
- obuf[xtra++] = IMMED;
- obuf[xtra] = DEREF|xsize;
- }
- else return iv->cod_usedtail; /* nop */
- }
- else if(datype & A_MEMADDR)
- {
- mov_esdata(iv, latype, osize);
- break;
- }
- else
- {/* move a value temp to a value temp, effective nop */
- return iv->cod_usedtail;
- }
- }
- else if(datype & (A_AUTO|A_PARAM))
- {
- if(latype & A_MEMADDR)
- {
- unsigned char xsize = get_datasize(0, l);
- int qc = 1;
- if( osize == BX
- || (osize == B8 && ddtype < D_FLOAT))
- obuf[qc++] = XTD;
- obuf[qc++] = IMMED;
- obuf[qc] = DEREF|xsize;
- write_obuf(iv, obuf+1, qc);
- }
- obuf[oc] = SS|osize;
- xtra += load_addr(iv, &obuf[oc], &obuf[oc+1], d, 2);
- --iv->stackdepth;
- }
- else if(datype & A_DATA)
- {
- if(latype & A_MEMADDR)
- {
- unsigned char xsize = get_datasize(0, l);
- int qc = 1;
- if( osize == BX
- || (osize == B8 && ddtype < D_FLOAT))
- obuf[qc++] = XTD;
- obuf[qc++] = IMMED;
- obuf[qc] = DEREF|xsize;
- write_obuf(iv, obuf+1, qc);
- }
- obuf[oc] = SM|osize;
- xtra += load_addr(iv, &obuf[oc], &obuf[oc+1], d, 2);
- --iv->stackdepth;
- }
- else
- {
- return iv->cod_usedtail;
- }
- }
- else if(latype & (A_AUTO|A_PARAM))
- {
- int lx;
- if((latype & (A_POINTER|A_VALUE)) == (A_POINTER|A_VALUE))
- {/* Put address on eval stack */
- addr_toevalstack(iv, l);
- if(opcode == assignop)
- from_evalstack(iv, d, l);
- break;
- }
- if(datype & (A_TEMP|A_RET))
- {
- if(opcode == derefop)
- osize = B4;
- obuf[oc] = LS|osize;
- xtra += load_addr(iv, &obuf[oc], &obuf[oc+1], l, 2);
- ++iv->stackdepth;
- if(opcode == assignop)
- {
- /* Here we need a 'store from stack addr' inst */
- if(datype & A_MEMADDR)
- {/* Address was on the eval stack */
- write_obuf(iv, obuf, 1+xtra);
- mov_esdata(iv, 0, osize);
- break;
- }
- }
- }
- else if(datype & (A_AUTO|A_PARAM))
- {
- obuf[oc] = MOVSS|osize;
- obuf[++oc] = 0;
- lx = load_addr(iv, &obuf[oc], &obuf[oc+1], l, 2);
- lx += load_addr(iv, &obuf[oc], &obuf[oc+1+lx], d, 0);
- xtra += lx+1;
- }
- else if(datype & A_DATA)
- {
- obuf[oc] = MOVSM|osize;
- obuf[++oc] = 0;
- lx = load_addr(iv, &obuf[oc], &obuf[oc+1], l, 2);
- lx += load_addr(iv, &obuf[oc], &obuf[oc+1+lx], d, 0);
- xtra += lx+1;
- }
- else
- {
- return iv->cod_usedtail;
- }
- }
- else if(latype & A_DATA)
- {
- int lx;
- if((latype & (A_POINTER|A_VALUE)) == (A_POINTER|A_VALUE))
- {/* Put address on eval stack */
- addr_toevalstack(iv, l);
- if(opcode == assignop)
- from_evalstack(iv, d, l);
- break;
- }
- if(datype & (A_TEMP|A_RET))
- {
- if(opcode == derefop)
- osize = B4;
- obuf[oc] = LM|osize;
- xtra += load_addr(iv, &obuf[oc], &obuf[oc+1], l, 2);
- ++iv->stackdepth;
- if(opcode == assignop)
- {
- /* Here we need a 'store from stack addr' inst */
- if(datype & A_MEMADDR)
- {/* Address was on the eval stack */
- write_obuf(iv, obuf, 1+xtra);
- mov_esdata(iv, 0, osize);
- break;
- }
- }
- }
- else if(datype & (A_AUTO|A_PARAM))
- {
- obuf[oc] = MOVMS|osize;
- obuf[++oc] = 0;
- lx = load_addr(iv, &obuf[oc], &obuf[oc+1], l, 2);
- lx += load_addr(iv, &obuf[oc], &obuf[oc+1+lx], d, 0);
- xtra += lx+1;
- }
- else if(datype & A_DATA)
- {
- obuf[oc] = MOVMM|osize;
- obuf[++oc] = 0;
- lx = load_addr(iv, &obuf[oc], &obuf[oc+1], l, 2);
- lx += load_addr(iv, &obuf[oc], &obuf[oc+1+lx], d, 0);
- xtra += lx+1;
- }
- else
- {
- return iv->cod_usedtail;
- }
- }
- else
- {
- return iv->cod_usedtail;
- }
- write_obuf(iv, obuf, 1+xtra);
- }/* END: move data directly */
- if(opcode == assignop && iv->has_structret)
- {
- obuf[0] = XTD;
- obuf[1] = PRUNESTRUCT;
- write_obuf(iv, obuf, 2);
- iv->has_structret = 0;
- }
- break;
- }
- case plusop:
- case minusop:
- case mulop:
- case divop:
- case orop:
- case xorop:
- case andop:
- case eqop:
- case neqop:
- case ltop:
- case gtop:
- case leop:
- case geop:
- {/* BINOPS */
- unsigned char ddtype;
- unsigned char osize;
- unsigned short latype = l->atype;
- unsigned short ratype = r->atype;
- PND bestptr = 0;
-
- if(latype & A_IMMED || ratype & A_IMMED)
- {
- if(ratype & A_IMMED)
- {/* IMMEDIATE IS ON THE RIGHT */
- bestptr = l;
-
- data_toevalstack(iv, l, d);
- if(check_binop_conversion(r, l))
- do_conversion(iv, r, l);
-
- data_toevalstack(iv, r, d);
-
- ddtype = bestptr->dtype;
- osize = l->opsize;
-
- if(osize == BX || (osize == B8 && ddtype != D_FLOAT))
- obuf[oc++] = XTD;
- obuf[oc++] = binops[opcode]|get_datasize(opcode, l);
- --iv->stackdepth;
- write_obuf(iv, obuf, oc);
- }
- else /* IMMEDIATE IS ON THE LEFT */
- {
- bestptr = r;
- if(ratype & (A_TEMP|A_RET))
- {
- data_toevalstack(iv, r, d);
- if(check_binop_conversion(l, r))
- do_conversion(iv, l, r);
- data_toevalstack(iv, l, d);
-
- ddtype = bestptr->dtype;
- osize = r->opsize;
-
- if( opcode != plusop
- && opcode != eqop
- && opcode != neqop
- && opcode != andop
- && opcode != orop
- && opcode != mulop
- && opcode != xorop
- )
- {/* stack order relevant */
- if(osize <= B4)
- obuf[0] = SWAP4;
- else
- obuf[0] = SWAP;
- write_obuf(iv, obuf, 1);
- }
- }
- else
- {
- data_toevalstack(iv, l, d);
- data_toevalstack(iv, r, d);
- if(check_binop_conversion(l, r))
- do_conversion(iv, l, r);
-
- ddtype = r->dtype;
- osize = r->opsize;
- }
-
- if(osize == BX || (osize == B8 && ddtype != D_FLOAT))
- obuf[oc++] = XTD;
- obuf[oc++] = binops[opcode]|get_datasize(opcode, l);
- write_obuf(iv, obuf, oc);
- --iv->stackdepth;
- }/* END: IMMEDIATE IS ON LEFT */
- }/* IMMEDIATES */
- else
- {/* NOT IMMEDIATES */
-
- if(ratype & (A_TEMP|A_RET))
- {/* RIGHT HAND SIDE IS ALREADY ON STACK */
-
- data_toevalstack(iv, r, d);
-
- if(latype & (A_TEMP|A_RET))
- {/* LEFT HAND SIDE WAS ALSO ON STACK */
-
- /* Is it the same data as right hand side ?? */
- if(l->TMPNUM == r->TMPNUM)
- {
- if(r->opsize <= B4)
- obuf[0] = DUP4;
- else
- obuf[0] = DUP;
- write_obuf(iv, obuf, 1);
- ++iv->stackdepth;
- l->atype = r->atype;
- }
- else
- {
- unsigned char lltype = l->dtype;
- unsigned lsize = l->opsize;
- if(latype & A_MEMADDR)
- {
- unsigned char xsize = get_datasize(0, l);
- int qc = 0;
-
- if( (l->TMPNUM == d->TMPNUM)
- && ((d->atype & (A_ABSOLUTE|A_MEMADDR))
- == (A_ABSOLUTE|A_MEMADDR))
- )
- {/* it must expand with a DEREF1 */
- if(lsize <= B4)
- obuf[0] = DUP4;
- else
- obuf[0] = DUP;
- obuf[1] = DUMP;
- obuf[2] = DUMP;
- write_obuf(iv, obuf, 3);
-
- if( lsize == BX
- || (lsize == B8 && lltype < D_FLOAT))
- obuf[qc++] = XTD;
- obuf[qc++] = IMMED;
- obuf[qc++] = DEREF1|xsize;
- write_obuf(iv, obuf, qc);
- ++iv->stackdepth;
- }
- else
- {
- obuf[0] = DUMP;
- write_obuf(iv, obuf, 1);
-
- if( lsize == BX
- || (lsize == B8 && lltype < D_FLOAT))
- obuf[qc++] = XTD;
- obuf[qc++] = IMMED;
- obuf[qc++] = DEREF|xsize;
- write_obuf(iv, obuf, qc);
- }
- l->atype &= ~A_MEMADDR;
- l->atype |= A_VALUE;
-
- if(check_binop_conversion(r, l))
- {
- bestptr = r;
- do_conversion(iv, r, l);
- }
- obuf[0] = REGAIN;
- write_obuf(iv, obuf, 1);
-
- if(!bestptr)
- if(check_binop_conversion(l, r))
- {
- bestptr = l;
- do_conversion(iv, l, r);
- }
- }
- }
- }
- else
- {/* LEFT HAND SIDE IS NOT ON STACK */
-
- if(check_binop_conversion(l, r))
- {
- bestptr = l;
- do_conversion(iv, l, r);
- }
- data_toevalstack(iv, l, d);
- if(!bestptr)
- if(check_binop_conversion(r, l))
- {
- bestptr = r;
- do_conversion(iv, r, l);
- }
- if( opcode != plusop
- && opcode != eqop
- && opcode != neqop
- && opcode != andop
- && opcode != orop
- && opcode != mulop
- && opcode != xorop
- )
- {/* stack order relevant */
- if(r->opsize <= B4)
- obuf[0] = SWAP4;
- else
- obuf[0] = SWAP;
- write_obuf(iv, obuf, 1);
- }
- }
- }
- else /* ONLY LEFT HAND SIDE CAN BE ON STACK */
- {
- data_toevalstack(iv, l, d);
- if(check_binop_conversion(r, l))
- {
- bestptr = r;
- do_conversion(iv, r, l);
- }
-
- data_toevalstack(iv, r, d);
- if(!bestptr)
- if(check_binop_conversion(l, r))
- {
- bestptr = l;
- do_conversion(iv, l, r);
- }
- }
- if(!bestptr)
- bestptr = l;
-
- ddtype = bestptr->dtype;
- osize = bestptr->opsize;
-
- if(osize == BX || (osize==B8 && ddtype != D_FLOAT))
- obuf[oc++] = XTD;
- obuf[oc++] = binops[opcode]|get_datasize(opcode, bestptr);
- write_obuf(iv, obuf, oc);
- --iv->stackdepth;
- }/* END: NOT IMMEDIATES */
-
- if(opcode >= eqop)
- {
- bestptr = &longtype;
- }
-
- if(check_assignment_conversion(d, bestptr))
- do_conversion(iv, d, bestptr);
- bestptr->atype &= ~A_MEMADDR;
- bestptr->atype |= A_VALUE;
- from_evalstack(iv, d, bestptr);
-
- break;
- }/* END: BINOPS */
-
- case lshop:
- case rshop:
- {/* SHIFTS */
- unsigned short latype = l->atype;
- unsigned short ratype = r->atype;
- PND bestptr;
-
-
- if(latype & A_IMMED || ratype & A_IMMED)
- {
- if(ratype & A_IMMED)
- {/* IMMEDIATE IS ON THE RIGHT */
- data_toevalstack(iv, l, d);
-
- obuf[0] = XTD;
- if(opcode == lshop)
- {
- obuf[1] = LSHI|get_datasize(opcode, l);
- obuf[2] = r->data->Uuchar;
- }
- else if(opcode == rshop)
- {
- obuf[1] = RSHI|get_datasize(opcode, l);
- obuf[2] = r->data->Uuchar;
- }
- write_obuf(iv, obuf, 3);
- }
- else /* IMMEDIATE IS ON THE LEFT */
- {
- if(ratype & (A_TEMP|A_RET))
- {
- data_toevalstack(iv, r, d);
- data_toevalstack(iv, l, d);
- if(r->opsize <= B4)
- obuf[0] = SWAP4;
- else
- obuf[0] = SWAP;
- write_obuf(iv, obuf, 1);
- }
- else
- {
- data_toevalstack(iv, l, d);
- data_toevalstack(iv, r, d);
- }
-
- obuf[0] = XTD;
- obuf[1] = binops[opcode]|get_datasize(opcode, l);
- write_obuf(iv, obuf, 2);
- --iv->stackdepth;
- }
- }
- else
- {/* NOT IMMEDIATES */
-
- if(ratype & (A_TEMP|A_RET))
- {/* RIGHT HAND SIDE IS ALREADY ON STACK */
-
- data_toevalstack(iv, r, d);
-
- if(latype & (A_TEMP|A_RET))
- {/* LEFT HAND SIDE WAS ALSO ON STACK */
-
- /* Is it the same data as right hand side ?? */
- if(l->TMPNUM == r->TMPNUM)
- {
- if(l->opsize <= B4 && r->opsize <= B4)
- obuf[0] = DUP4;
- else
- obuf[0] = DUP;
- write_obuf(iv, obuf, 1);
- ++iv->stackdepth;
- l->atype = r->atype;
- }
- else
- {/* reversed stack and not same data */
-
- if(latype & A_MEMADDR)
- {
- unsigned char xsize = l->opsize;
- int qc = 0;
-
- if( (l->TMPNUM == d->TMPNUM)
- && ((d->atype & (A_ABSOLUTE|A_MEMADDR))
- == (A_ABSOLUTE|A_MEMADDR))
- )
- {/* it must expand with a DEREF1 */
- if(l->opsize <= B4)
- obuf[0] = DUP4;
- else
- obuf[0] = DUP;
- obuf[1] = DUMP;
- obuf[2] = DUMP;
- write_obuf(iv, obuf, 3);
-
- if(l->opsize == B8)
- obuf[qc++] = XTD;
- obuf[qc++] = IMMED;
- obuf[qc++] = DEREF1|xsize;
- write_obuf(iv, obuf, qc);
- ++iv->stackdepth;
- }
- else
- {
- obuf[0] = DUMP;
- write_obuf(iv, obuf, 1);
-
- if(l->opsize == B8)
- obuf[qc++] = XTD;
- obuf[qc++] = IMMED;
- obuf[qc++] = DEREF|xsize;
- write_obuf(iv, obuf, qc);
- }
- l->atype &= ~A_MEMADDR;
- l->atype |= A_VALUE;
-
- obuf[0] = REGAIN;
- write_obuf(iv, obuf, 1);
- }
- }
- }
- else
- {/* LEFT HAND SIDE IS NOT ON STACK */
-
- data_toevalstack(iv, l, d);
- if(r->opsize <= B4 && l->opsize <= B4)
- obuf[0] = SWAP4;
- else
- obuf[0] = SWAP;
- write_obuf(iv, obuf, 1);
- }
- }
- else /* ONLY LEFT HAND SIDE CAN BE ON STACK */
- {
- data_toevalstack(iv, l, d);
- data_toevalstack(iv, r, d);
- }
-
- /* ENSURE THAT THE RIGHT SIDE IS A LONG OR A LONG LONG */
- bestptr = (l->size > 4) ? &longlongtype : &longtype;
- if(check_assignment_conversion(bestptr, r))
- do_conversion(iv, bestptr, r);
-
- obuf[0] = XTD;
- obuf[1] = binops[opcode]|get_datasize(opcode, l);
- write_obuf(iv, obuf, 2);
- --iv->stackdepth;
- }/* END: NOT IMMEDIATES */
-
- if(check_assignment_conversion(d, l))
- do_conversion(iv, d, l);
- l->atype &= ~A_MEMADDR;
- l->atype |= A_VALUE;
- from_evalstack(iv, d, l);
-
- break;
- }/* END: SHIFTS */
- case modop:
- {/* MODULUS */
- unsigned short latype = l->atype;
- unsigned short ratype = r->atype;
- PND bestptr;
-
- if(latype & A_IMMED || ratype & A_IMMED)
- {
- if(ratype & A_IMMED)
- {/* IMMEDIATE IS ON THE RIGHT */
- data_toevalstack(iv, l, d);
-
- if(l->opsize == B8)
- {
- obuf[oc++] = XTD;
- }
- if(d->size == 2)
- {
- obuf[oc++] = IMMED;
- obuf[oc++] = MODI|get_datasize(opcode, l);
- *((short*)&obuf[oc]) = r->data->Uushort;
- xtra = 2;
- }
- else
- {/* no fast instructions available */
- data_toevalstack(iv, r, d);
- obuf[oc++] = binops[opcode]|get_datasize(opcode, l);
- --iv->stackdepth;
- }
- write_obuf(iv, obuf, oc+xtra);
- }
- else /* IMMEDIATE IS ON THE LEFT */
- {
-
- if(ratype & (A_TEMP|A_RET))
- {
- data_toevalstack(iv, r, d);
- data_toevalstack(iv, l, d);
- if(r->opsize <= B4)
- obuf[0] = SWAP4;
- else
- obuf[0] = SWAP;
- write_obuf(iv, obuf, 1);
- }
- else
- {/* load eval stack without regard for conversion */
- data_toevalstack(iv, l, d);
- data_toevalstack(iv, r, d);
- }
-
- if(r->opsize == B8)
- {
- obuf[oc++] = XTD;
- }
- obuf[oc++] = binops[opcode]|get_datasize(opcode, l);
- write_obuf(iv, obuf, oc);
- --iv->stackdepth;
- }
- }
- else
- {/* NOT IMMEDIATES */
- if(ratype & (A_TEMP|A_RET))
- {/* RIGHT HAND SIDE IS ALREADY ON STACK */
-
- data_toevalstack(iv, r, d);
-
- if(latype & (A_TEMP|A_RET))
- {/* LEFT HAND SIDE WAS ALSO ON STACK */
-
- /* Is it the same data as right hand side ?? */
- if(l->TMPNUM == r->TMPNUM)
- {
- if(l->opsize <= B4 && r->opsize <= B4)
- obuf[0] = DUP4;
- else
- obuf[0] = DUP;
- write_obuf(iv, obuf, 1);
- ++iv->stackdepth;
- l->atype = r->atype;
- }
- else
- {/* reversed stack and not same data */
-
- if(latype & A_MEMADDR)
- {
- unsigned char xsize = get_datasize(0, l);
- int qc = 0;
-
- if( (l->TMPNUM == d->TMPNUM)
- && ((d->atype & (A_ABSOLUTE|A_MEMADDR))
- == (A_ABSOLUTE|A_MEMADDR))
- )
- {/* it must expand with a DEREF1 */
- if(r->opsize <= B4)
- obuf[0] = DUP4;
- else
- obuf[0] = DUP;
- obuf[1] = DUMP;
- obuf[2] = DUMP;
- write_obuf(iv, obuf, 3);
-
- if(r->opsize == B8)
- obuf[qc++] = XTD;
- obuf[qc++] = IMMED;
- obuf[qc++] = DEREF1|xsize;
- write_obuf(iv, obuf, qc);
- ++iv->stackdepth;
- }
- else
- {
- obuf[0] = DUMP;
- write_obuf(iv, obuf, 1);
-
- if(r->opsize == B8)
- obuf[qc++] = XTD;
- obuf[qc++] = IMMED;
- obuf[qc++] = DEREF|xsize;
- write_obuf(iv, obuf, qc);
- }
- l->atype &= ~A_MEMADDR;
- l->atype |= A_VALUE;
-
- obuf[0] = REGAIN;
- write_obuf(iv, obuf, 1);
- }
- }
- }
- else
- {/* LEFT HAND SIDE IS NOT ON STACK */
-
- data_toevalstack(iv, l, d);
- if(r->opsize <= B4 && l->opsize <= B4)
- obuf[0] = SWAP4;
- else
- obuf[0] = SWAP;
- write_obuf(iv, obuf, 1);
- }
- }
- else /* ONLY LEFT HAND SIDE CAN BE ON STACK */
- {
- data_toevalstack(iv, l, d);
- data_toevalstack(iv, l, d);
- }
-
- /* ENSURE THAT THE RIGHT SIDE IS A LONG OR A LONG LONG */
- bestptr = (l->size > 4) ? &longlongtype : &longtype;
- if(check_assignment_conversion(bestptr, r))
- do_conversion(iv, bestptr, r);
-
- if(l->opsize == B8)
- {
- obuf[oc++] = XTD;
- }
- obuf[oc++] = binops[opcode]|get_datasize(opcode, l);
- write_obuf(iv, obuf, oc);
- --iv->stackdepth;
- }/* END: NOT IMMEDIATES */
-
- if(check_assignment_conversion(d, l))
- do_conversion(iv, d, l);
- l->atype &= ~A_MEMADDR;
- l->atype |= A_VALUE;
- from_evalstack(iv, d, l);
-
- break;
- }/* END: MODULUS */
- case truthop:
- case aliastmpop:
- {/* no immediates */
-
- data_toevalstack(iv, l, d);
-
- if(l->opsize != B1)
- {/* no need to get truth of byte sized elements */
- if(l->opsize == BX)
- {
- obuf[oc++] = XTD;
- }
- obuf[oc++] = TRUTHOF|l->opsize;
- write_obuf(iv, obuf, oc);
- }
- break;
- }
- case complop:
- case notop:
- {/* no immediates */
- unsigned char osize = get_datasize(opcode, l);
-
- data_toevalstack(iv, l, d);
- if(osize == BX)
- {/* only notop can operate on long double */
- obuf[oc++] = XTD;
- }
- obuf[oc++] = binops[opcode]|osize;
- write_obuf(iv, obuf, oc);
- break;
- }
- case negop:
- {/* no immediates */
-
- data_toevalstack(iv, l, d);
- if(l->opsize == BX || (l->opsize==B8 && l->dtype != D_FLOAT))
- {
- obuf[oc++] = XTD;
- }
- obuf[oc++] = binops[opcode]|get_datasize(opcode, l);
- write_obuf(iv, obuf, oc);
- break;
- }
- case copyop:
- {
- if(d->atype & (A_TEMP|A_RET))
- {
- if(!(l->atype & (A_TEMP|A_RET)))
- {
- data_toevalstack(iv, l, d);
- }
- }
- else
- {
- if(!(l->atype & (A_TEMP|A_RET)))
- {
- data_toevalstack(iv, d, d);
- data_toevalstack(iv, l, d);
- }
- else
- {
- data_toevalstack(iv, d, d);
- obuf[0] = SWAP4;
- write_obuf(iv, obuf, 1);
- }
- }
- load_val(iv, d->size);
- obuf[0] = MOVAAC;
- write_obuf(iv, obuf, 1);
- iv->stackdepth -= 3;
- break;
- }
- case castop:
- {
- data_toevalstack(iv, l, d);
- if(check_assignment_conversion(d, l))
- do_conversion(iv, d, l);
- break;
- }
- case jmploopop:
- case jmpcontinueop:
- case jmpbreakop:
- case jmpgotoop:
- case ljmptrueop:
- case jmptrueop:
- case ljmpfalseop:
- case jmpfalseop:
- case funcstartop:
- case funcstopop:
- {/* start with max sized jmps, they will be shortened later */
- void *fixjmp;
- if(opcode == jmptrueop)
- {
- obuf[0] = JMPT|J4;
- --iv->stackdepth;
- }
- else if(opcode == ljmptrueop)
- {
- obuf[0] = LJMPT|J4;
- }
- else if(opcode == jmpfalseop)
- {
- obuf[0] = JMPF|J4;
- --iv->stackdepth;
- }
- else if(opcode == ljmpfalseop)
- {
- obuf[0] = LJMPF|J4;
- }
- else if(opcode == funcstartop || opcode == funcstopop)
- {
- obuf[0] = LOCATE|J4;
- }
- else
- obuf[0] = JMP|J4;
- fixjmp = write_obuf(iv, obuf, 5);
- addto_jmplist(iv, p, fixjmp);
- break;
- }
- case clrdatop:
- {
- addr_toevalstack(iv, d);
- data_toevalstack(iv, l, 0);
- obuf[0] = XTD;
- obuf[1] = CLRDAT;
- write_obuf(iv, obuf, 2);
- iv->stackdepth -= 2;
- break;
- }
- case getbitfieldop:
- {
- data_toevalstack(iv, r, d);
- obuf[0] = XTD;
- obuf[1] = GETBITFIELD;
- obuf[2] = l->data->uchr.d[0]; /* shift */
- obuf[3] = l->data->uchr.d[1]; /* size */
- obuf[4] = l->data->uchr.d[2]; /* sign */
- write_obuf(iv, obuf, 5);
- break;
- }
- case putbitfieldop:
- {
- if(!(d->atype & (A_TEMP|A_RET)))
- {/* destination address to stack */
- addr_toevalstack(iv, d);
-
- if(!(r->atype & (A_TEMP|A_RET)))
- {
- data_toevalstack(iv, r, d);
- }
- else
- {/* data was on stack */
- obuf[0] = SWAP;
- write_obuf(iv, obuf, 1);
- }
- }
- else
- {/* destination address is on stack */
- data_toevalstack(iv, r, d);
- }
- if(check_assignment_conversion(d, r))
- do_conversion(iv, d, r);
-
- obuf[0] = XTD;
- obuf[1] = PUTBITFIELD;
- obuf[2] = l->data->uchr.d[0]; /* shift */
- obuf[3] = l->data->uchr.d[1]; /* size */
- obuf[4] = d->size;
- write_obuf(iv, obuf, 5);
- iv->stackdepth -= 2;
- break;
- }
- case retstructop:
- {
- addr_toevalstack(iv, d);
- obuf[0] = XTD;
- obuf[1] = RETSTRUCT;
- *((unsigned short*)&obuf[2]) = l->data->ulng.d[0] >>2; /* size */
- *((unsigned short*)&obuf[4]) = l->data->ulng.d[1] >>2; /* offset */
- write_obuf(iv, obuf, 6);
- break;
- }
- case retdataop:
- case retvoidop:
- {
- obuf[0] = RET;
- write_obuf(iv, obuf, 1);
- break;
- }
- case callfuncop:
- {
- obuf[0] = XTD;
- obuf[1] = CALLSETUP;
- *((long*)&obuf[2]) = l->data->ulng.d[0]; /* argsize */
- write_obuf(iv, obuf, 6);
- break;
- }
- case switchop:
- {
- void *fixjmp;
- obuf[0] = XTD;
- obuf[1] = SWITCH;
- *((short*)(&obuf[2])) = d->data->ulng.d[1]; /* swnode */
- write_obuf(iv, obuf, 4);
-
- /* Default jmp */
- obuf[0] = JMP|D4;
- fixjmp = write_obuf(iv, obuf, 5);
- addto_jmplist(iv, p, fixjmp);
- --iv->stackdepth;
- break;
- }
- case compsavop:
- case totmpop:
- {
- data_toevalstack(iv, l, d);
- break;
- }
- case argop:
- {
- unsigned char op = arg_toevalstack(iv, l, d->ARGSIZE);
- if(!(iv->in_builtin))
- {
- load_val(iv, d->ARGOFS);
- load_val(iv, d->ARGSIZE);
- obuf[0] = op;
- write_obuf(iv, obuf, 1);
- iv->stackdepth -= 3;
- }
- break;
- }
- default:
- {
- #if 0
- obuf[0] = NOP;
- write_obuf(iv, obuf, 1);
- #endif
- break;
- }
- }/* END: switch(opcode) */
- if(iv->stackdepth > iv->maxdepth)
- iv->maxdepth = iv->stackdepth;
- if(iv->stackdepth < iv->mindepth)
- iv->mindepth = iv->stackdepth;
-
- return iv->cod_usedtail;
- }/* END: gen_inst() */
-
- static void
- set_op(PND pnd, PopA ptr, unsigned char otype)
- {
- unsigned char optype = otype & 0xe0;
- unsigned char isize = otype & 0x1f;
-
- pnd->data = (DATUM *)ptr;
- if(optype <= OPIMMED4)
- {
- pnd->dtype = optype >> 5;
- pnd->quals = Q_CONST;
- pnd->size = isize;
- pnd->opsize = get_size(pnd->dtype, isize);
- pnd->atype = A_IMMED;
- } /* END: OPIMMED */
- else
- {
- unsigned short type = GS(ptr->dtype);
- pnd->dtype = type & 0xff;
- pnd->quals = (type >> 8) & 0xff;
- pnd->size = GL(ptr->dsize);
- pnd->opsize = get_size(pnd->dtype, pnd->size);
- pnd->atype = GS(ptr->atype);
-
- if(optype == OPAUTO)
- {
- if(GL(ptr->pofs) >= 0)
- {
- pnd->atype &= ~A_AUTO;
- pnd->atype |= A_PARAM;
- }
- }
- }
- }/* END: set_op() */
- static void *
- decode_anf(Piv iv, unsigned char *p)
- {
- void *dptr;
- void *lptr;
- void *rptr;
-
- if(iv->debug >= '4')
- cfeprintf("DECODE inst(%u) `%s'\n", *p, oxgenops[*p]);
-
- if(*p == 0)
- return POP->next;
-
-
- iv->ob->p = p;
- switch(*p)
- {
- case regainop:
- case grabop:
- case retvoidop:
- {/* 0 address mode */
- break;
- }
- case jmploopop:
- case jmpcontinueop:
- case jmpbreakop:
- case jmpgotoop:
- case ljmptrueop:
- case jmptrueop:
- case ljmpfalseop:
- case jmpfalseop:
- case funcstartop:
- case funcstopop:
- case retdataop:
- {/* 1 address mode */
- dptr = (p+8);
- set_op(&iv->ob->d, dptr, p[1]);
- break;
- }
- case getvalop:
- case derefop:
- case assignop:
- case duptmpop:
- case truthop:
- case aliastmpop:
- case negop:
- case complop:
- case notop:
- case copyop:
- case castop:
- case clrdatop:
- case compsavop:
- case totmpop:
- case retstructop:
- case switchop:
- case argop:
- {/* 2 address mode */
- dptr = (p+8);
- lptr = (((char*)dptr) + (p[1] & 0x1f));
- set_op(&iv->ob->d, dptr, p[1]);
- set_op(&iv->ob->l, lptr, p[2]);
- break;
- }
- case plusop:
- case minusop:
- case mulop:
- case divop:
- case modop:
- case orop:
- case xorop:
- case andop:
- case eqop:
- case neqop:
- case ltop:
- case gtop:
- case leop:
- case geop:
- case lshop:
- case rshop:
- case getbitfieldop:
- case callfuncop:
- case putbitfieldop:
- {/* 3 address mode */
- dptr = (p+8);
- lptr = (((char*)dptr) + (p[1] & 0x1f));
- rptr = (((char*)lptr) + (p[2] & 0x1f));
- set_op(&iv->ob->d, dptr, p[1]);
- set_op(&iv->ob->l, lptr, p[2]);
- set_op(&iv->ob->r, rptr, p[3]);
- break;
- }
- default:
- {
- return POP->next;
- }
- }/* END: switch(*p) */
-
- /* Save pointers to the machine instructions generated by this ANF code */
- iv->ob->startinst = iv->cod;
- iv->ob->endinst = gen_inst(iv, iv->ob);
-
- if(iv->cod != iv->ob->startinst)
- {/* instructions were generated */
- link_ob(iv);
- }
- return POP->next;
- }/* END: decode_anf() */
-
- static void *
- skip_bracket(unsigned char *p)
- {
- long opcode = *p;
- int opcount = 0;
-
- for(;;)
- {
- if(*p == opcode)
- ++opcount;
- else if(*p == endop && GL(POP->data) == opcode)
- {
- if(--opcount == 0) {
- return p;
- }
- }
- else if(*p == endfileop || *p == endallop)
- {
- PERROR(pName ":ERROR: Malformed input file3=%u=%p",*p, p);
- }
- p = POP->next;
- }
- return 0;
- }
- static void *
- do_strelem(Piv iv, unsigned char *p)
- {
- void *sp = p;
- unsigned char *q = skip_bracket(p);
- void *elem[20];
- void *elemq[20];
- int elemcnt, i;
-
- elemcnt = 0;
- p = POP->next;
- while(p < q)
- {/* Pick up nested elements */
- unsigned char opcode = *p;
- if(opcode == strelemop || opcode == ptrelemop || opcode == arrayelemop)
- {
- void *qq = skip_bracket(p);
- elem[elemcnt] = p;
- elemq[elemcnt++] = qq;
- p = qq;
- }
- p = POP->next;
- }
-
- /* Dump the nested elements in the order encountered */
- for(i = 0; i < elemcnt; ++i)
- {
- do_something(iv, elem[i]);
- }
-
- /* Dump the remainder of bracket */
- p = sp;
- elemcnt = 0;
- p = POP->next;
- while(p < q)
- {
- unsigned char opcode = *p;
- if(opcode == strelemop || opcode == ptrelemop || opcode == arrayelemop)
- p = ((Pop)elemq[elemcnt++])->next;
- else
- p = do_something(iv, p);
- }
- return ((Pop)q)->next;
- }
- static void *
- do_ptrelem(Piv iv, unsigned char *p)
- {
- void *sp = p;
- unsigned char *q = skip_bracket(p);
- void *elem[20];
- void *elemq[20];
- int elemcnt, i;
-
- elemcnt = 0;
- p = POP->next;
- while(p < q)
- {/* Pick up nested elements */
- unsigned char opcode = *p;
- if(opcode == arrayelemop || opcode == ptrelemop || opcode == strelemop)
- {
- void *qq = skip_bracket(p);
- elem[elemcnt] = p;
- elemq[elemcnt++] = qq;
- p = qq;
- }
- p = POP->next;
- }
-
- /* Dump the nested elements in the order encountered */
- for(i = 0; i < elemcnt; ++i)
- {
- do_something(iv, elem[i]);
- }
-
- /* Dump the remainder of bracket */
- p = sp;
- elemcnt = 0;
- p = POP->next;
- while(p < q)
- {
- unsigned char opcode = *p;
- if(opcode == arrayelemop || opcode == strelemop || opcode == ptrelemop)
- p = ((Pop)elemq[elemcnt++])->next;
- else
- p = do_something(iv, p);
- }
- return ((Pop)q)->next;
- }
- static void *
- do_arrayelem(Piv iv, unsigned char *p)
- {/* Arrange output for the stack machine */
- void *sp = p;
- unsigned char *q = skip_bracket(p);
- void *sadims[10];
- void *sadimsq[10];
- void *spdims[10];
- void *spdimsq[10];
- void *elem[20];
- void *elemq[20];
- int sacnt, spcnt, elemcnt, i;
-
- /* Scan over the bracket and pick up the dimension computations */
- elemcnt= sacnt = spcnt = 0;
- p = POP->next;
- while(p < q)
- {
- unsigned char opcode = *p;
- if(opcode == arraydimsop)
- {
- void *qq = skip_bracket(p);
- sadims[sacnt] = p;
- sadimsq[sacnt++] = qq;
- p = qq;
- }
- else if(opcode == ptrdimsop)
- {
- void *qq = skip_bracket(p);
- spdims[spcnt] = p;
- spdimsq[spcnt++] = qq;
- p = qq;
- }
- else if(opcode==arrayelemop || opcode==ptrelemop || opcode==strelemop)
- {
- void *qq = skip_bracket(p);
- elem[elemcnt] = p;
- elemq[elemcnt++] = qq;
- p = qq;
- }
- p = POP->next;
- }
-
- /* Dump the dimension computations in stack order */
- for(i = spcnt-1; i >= 0; --i)
- {
- do_bracket(iv, spdims[i], spdimsq[i]);
- }
- for(i = sacnt-1; i >= 0; --i)
- {
- do_bracket(iv, sadims[i], sadimsq[i]);
- }
-
- /* Dump the nested elements in the order encountered */
- for(i = 0; i < elemcnt; ++i)
- {
- do_something(iv, elem[i]);
- }
-
- /* Dump the remainder of the bracket */
- p = sp;
- elemcnt = sacnt = spcnt = 0;
- p = POP->next;
- while(p < q)
- {
- unsigned char opcode = *p;
- if(opcode == arraydimsop)
- p = ((Pop)sadimsq[sacnt++])->next;
- else if(opcode == ptrdimsop)
- p = ((Pop)spdimsq[spcnt++])->next;
- else if(opcode==arrayelemop || opcode==ptrelemop || opcode==strelemop)
- p = ((Pop)elemq[elemcnt++])->next;
- else
- p = do_something(iv, p);
- }
- return ((Pop)q)->next;
- }
- static int
- funcret_used(PopT op, unsigned char *p)
- {
- long tmpnum;
- if( op->dtype == 0
- && op->dsize == 0)
- {
- return 1; /* void function */
- }
- tmpnum = op->tmpnum;
-
- while(*p != funcexitop)
- {
- if(*p && *p <= (unsigned char)100)
- {
- unsigned char *qp = p+8;
- if(*p == callfuncop)
- {/* function using same temp */
- if(GL(((PopT)qp)->tmpnum) == tmpnum)
- {
- return 1; /* not used earlier */
- }
- }
- else
- {
- if((p[1]&0xe0) == OPRET)
- {
- if(GL(((PopT)qp)->tmpnum) == tmpnum)
- {
- return 0; /* ret used */
- }
- }
- qp += p[1]&0x1f;
- if((p[2]&0xe0) == OPRET)
- {
- if(GL(((PopT)qp)->tmpnum) == tmpnum)
- {
- return 0; /* ret used */
- }
- }
- qp += p[2]&0x1f;
- if((p[3]&0xe0) == OPRET)
- {
- if(GL(((PopT)qp)->tmpnum) == tmpnum)
- {
- return 0; /* ret used */
- }
- }
- }
- }
- p = POP->next;
- }
- return 1; /* ret not used */
- }
- static unsigned char
- check_for_builtin(Piv iv, unsigned char *p, int flag)
- {
- short symnum;
- long key[2];
- unsigned char *result;
-
- if(flag == 0)
- {
- symnum = GS(((PopA)(p+20))->symnum);
- }
- else if(flag == 1)
- {
- symnum = GS(((PopI)(p+16))->s.symnum);
- }
- else if(flag == 2)
- {
- symnum = GS(POPI->s.symnum);
- }
- else return 0;
-
- key[0] = symnum;
- key[1] = 0;
- if(SymFind(iv->builtintbl, key, &result))
- return *result;
- return 0;
- }
- static void *
- do_funcall(Piv iv, unsigned char *p)
- {/* Arrange output for the stack machine */
- char obuf[4];
- void *sp = p;
- unsigned char *q = skip_bracket(p);
- int argcnt, i, dump;
- void *argloads[100];
- void *argloadsq[100];
- char *callop = 0;
- unsigned char builtin = 0;
-
- /* Scan over the bracket and pick up argument loads */
- argcnt = 0;
- p = POP->next;
- while(p < q)
- {
- if(*p == getvalop && callop == 0)
- {
- builtin = check_for_builtin(iv, p, 0);
- }
- else if(*p == callfuncop)
- callop = p;
- else if(*p == argloadop)
- {
- void *qq = skip_bracket(p);
- argloads[argcnt] = p;
- argloadsq[argcnt++] = qq;
- p = qq;
- }
- p = POP->next;
- }
-
- /* Check out whether the function return is used */
- dump = funcret_used((PopT)(callop+8), q);
-
- /* Calling an interpreter builtin ?? */
- if(builtin)
- {
- iv->in_builtin = 1;
-
- /* Dump the argument loads in order */
- /* The ARG instruction will be suppressed because iv->in_builtin > 0 */
- for(i = 0; i < argcnt; ++i)
- {
- do_bracket(iv, argloads[i], argloadsq[i]);
- }
- iv->stackdepth -= argcnt;
-
- /* Generate the BUILTIN instruction */
- i = 3;
- ++iv->stackdepth;
- obuf[0] = XTD;
- obuf[1] = BUILTIN;
- obuf[2] = builtin;
- if(dump)
- {
- obuf[3] = DUMP;
- --iv->stackdepth;
- i = 4;
- }
- write_obuf(iv, obuf, i);
- iv->in_builtin = 0;
- }
- else
- {
- /* Generate the CALLSETUP instruction */
- p = sp;
- p = POP->next;
- while(p < q)
- {
- if(*p == argloadop)
- break;
- else
- p = do_something(iv, p);
- }
-
- /* Dump the argument loads in order */
- for(i = 0; i < argcnt; ++i)
- {
- do_bracket(iv, argloads[i], argloadsq[i]);
- }
- /* Generate the CALL instruction */
- i = 1;
- obuf[0] = CALL;
- if(dump)
- {
- obuf[1] = DUMP;
- --iv->stackdepth;
- i = 2;
- }
- write_obuf(iv, obuf, i);
- if((GL(((Pop)(callop))->data1) & 0xff) == D_STRUCT)
- {
- ++iv->has_structret;
- }
- }
- return ((Pop)q)->next;
- }
- static void *
- do_expr(Piv iv, unsigned char *p)
- {
- unsigned char *q = skip_bracket(p);
-
- if(iv->debug >= '2')
- cfeprintf("EXPR inst(%u) `%s'\n", *p, oxgenops[*p]);
-
- while(p < q)
- {
- switch(*p)
- {
- case arrayelemop:
- p = do_arrayelem(iv, p);
- break;
- case strelemop:
- p = do_strelem(iv, p);
- break;
- case ptrelemop:
- p = do_ptrelem(iv, p);
- break;
- case funcallop:
- p = do_funcall(iv, p);
- break;
- case condop:
- case twopathop:
- case logicalop:
- case binopop:
- case argloadop:
- case preincrdecop:
- case postincrdecop:
- case compoundop:
- case unopop:
- p = POP->next;
- break;
- default:
- p = do_something(iv, p);
- break;
- }
- }
- return ((Pop)q)->next;
- }
- static void *
- do_expstmt(Piv iv, unsigned char *p)
- {
- unsigned char *q = skip_bracket(p);
-
- p = POP->next;
- while(p < q)
- {
- p = do_something(iv, p);
- }
- return q;
- }
- static void *
- do_ifstmt(Piv iv, unsigned char *p)
- {
- unsigned char *q = skip_bracket(p);
-
- p = POP->next;
- while(p < q)
- {
- p = do_something(iv, p);
- }
-
- return ((Pop)q)->next;
- }
- static void *
- do_ifelsestmt(Piv iv, unsigned char *p)
- {
- unsigned char *q = skip_bracket(p);
-
- p = POP->next;
- while(p < q)
- {
- p = do_something(iv, p);
- }
-
- return ((Pop)q)->next;
- }
- static void *
- do_switchstmt(Piv iv, unsigned char *p)
- {
- unsigned char *q = skip_bracket(p);
-
- p = POP->next;
- while(p < q)
- {
- p = do_something(iv, p);
- }
-
- return ((Pop)q)->next;
- }
- static void *
- do_whilestmt(Piv iv, unsigned char *p)
- {
- unsigned char *q = skip_bracket(p);
-
- p = POP->next;
- while(p < q)
- {
- p = do_something(iv, p);
- }
- return ((Pop)q)->next;
- }
- static void *
- do_dostmt(Piv iv, unsigned char *p)
- {
- unsigned char *q = skip_bracket(p);
-
- p = POP->next;
- while(p < q)
- {
- p = do_something(iv, p);
- }
- return ((Pop)q)->next;
- }
- static void *
- do_forstmt(Piv iv, unsigned char *p)
- {
- unsigned char *q = skip_bracket(p);
-
- p = POP->next;
- while(p < q)
- {
- p = do_something(iv, p);
- }
- return ((Pop)q)->next;
- }
- static void *
- do_asmstmt(Piv iv, unsigned char *p)
- {
- unsigned char *q = skip_bracket(p);
-
- p = POP->next;
- while(p < q)
- {
- p = do_something(iv, p);
- }
- return ((Pop)q)->next;
- }
- static void *
- do_initstmt(Piv iv, unsigned char *p)
- {
- unsigned char *q = skip_bracket(p);
-
- p = POP->next;
- while(p < q)
- {
- p = do_something(iv, p);
- }
- return ((Pop)q)->next;
- }
- static void *
- do_anfblock(Piv iv, unsigned char *p)
- {
- unsigned char *q = skip_bracket(p);
-
- p = POP->next;
- while(p < q)
- {
- p = do_something(iv, p);
- }
- return ((Pop)q)->next;
- }
- static char *
- nodot(Piv iv, char *name)
- {
- char *cp;
- if((cp = strchr(name, '.')))
- {
- char *newname;
- newname = Cmalloc(iv->category, strlen(name)+1);
- strcpy(newname,name);
- cp = strchr(newname, '.');
- *cp = 0;
- return newname;
- }
- return name;
- }
- static void
- printfunc(Piv iv, unsigned char *p)
- {
- char *funcname = nodot(iv, iv->symaddr[GS(POPI->funcdef.symnum)]);
-
- if(*p == gfuncdefop)
- {
- fprintf(iv->outfile, "\n%8.8lx: .global .function _%s\n",
- iv->out_offset, funcname);
- }
- else if(*p == sfuncdefop)
- {
- fprintf(iv->outfile, "\n%8.8lx: .local .function _%s\n",
- iv->out_offset, funcname);
- }
- }
- static void *
- do_stmt(Piv iv, unsigned char *p)
- {
- void *q;
-
- if(iv->debug >= '2')
- cfeprintf("STMT inst(%u) `%s'\n", *p, oxgenops[*p]);
-
- q = POP->next;
-
- switch(*p)
- {
- case labelop:
- newlabel_insert(iv, GL( POP->data));
- break;
- case gfuncdefop:
- case sfuncdefop:
- case funcexitop:
- PERROR(pName ":ERROR: Malformed input file1=%u=%p",*p, p);
- case nestedfuncdefop:
- {
- if(iv->listing_wanted)
- {
- char obuf[8];
- obuf[0] = NFUNC;
- *((char**)&obuf[1]) = nodot(iv, iv->symaddr[GS(POPI->funcdef.symnum)]);
- write_obuf(iv, obuf, 5);
- }
- iv->numnested += 1;
- break;
- }
- case nestedfuncexitop:
- {
- char obuf[2];
- obuf[0] = RET;
- write_obuf(iv, obuf, 1);
- break;
- }
- case anfblockop:
- q = do_anfblock(iv, p);
- break;
- case expstmtop:
- q = do_expstmt(iv, p);
- break;
- case ifstmtop:
- q = do_ifstmt(iv, p);
- break;
- case ifelsestmtop:
- q = do_ifelsestmt(iv, p);
- break;
- case switchstmtop:
- q = do_switchstmt(iv, p);
- break;
- case whilestmtop:
- q = do_whilestmt(iv, p);
- break;
- case dostmtop:
- q = do_dostmt(iv, p);
- break;
- case forstmtop:
- q = do_forstmt(iv, p);
- break;
- case asmstmtop:
- q = do_asmstmt(iv, p);
- break;
- case initstmtop:
- q = do_initstmt(iv, p);
- break;
- case lineop:
- if(iv->debug >= '3')
- {
- cfeprintf("Line=%u depth=%d\n", GL(POP->data), iv->stackdepth);
- }
- if(iv->listing_wanted)
- {
- char obuf[8];
- obuf[0] = LINENO;
- *((long*)&obuf[1]) = GL(POP->data);
- write_obuf(iv, obuf, 5);
- }
- iv->lastline = GL(POP->data);
- break;
- default:
- break;
- }
- return q;
- }
- static void *
- do_something(Piv iv, unsigned char *p)
- {
- if(*p < labelop)
- return decode_anf(iv, p);
- else if(*p >= condop && *p < symbop)
- return do_expr(iv, p);
- else
- return do_stmt(iv, p);
- }
- static void
- do_bracket(Piv iv, unsigned char *p, unsigned char *q)
- {
- p = POP->next;
- while(p < q)
- {
- p = do_something(iv, p);
- }
- }
- static void *
- dumpa_func(Piv iv, unsigned char *p)
- {
- unsigned char obuf[2];
- Pafile pf;
- unsigned char *pdef = p;
-
- iv->ob = new_nodeO(iv); /* setup first intermediate output node */
- link_ob(iv); /* null node never unlinked */
- iv->first_ob = iv->ob_usedtail;
-
- iv->cod = new_nodeC(iv); /* setup first code node */
- link_cod(iv); /* null node never unlinked */
- iv->first_cod = iv->cod_usedtail;
-
- pf = iv->files[iv->filenum];
- if(iv->listing_wanted)
- {
- printfunc(iv, p);
- }
- p = POP->next;
-
- for(;;)
- {
- if(*p == funcexitop)
- {
- obuf[0] = RET;
- write_obuf(iv, obuf, 1);
- write_funcdata(iv, pdef);
- break;
- }
- else
- p = do_something(iv, p);
- }
- save_extlocs(iv);
- reset_funcdata(iv);
- return p;
- }
- static void
- dump_funcs(Piv iv)
- {
- long pad;
- Pafile pf;
- unsigned char *p;
- int i;
-
- #if 0
- oxcc_debug(__builtin_iv(),0x40040);
- #endif
-
- reset_funcdata(iv);
- for(i = 0; i < iv->numfiles; ++i)
- {
- iv->filenum = i;
- pf = iv->files[i];
- p = pf->file_p;
- if(iv->listing_wanted)
- fprintf(iv->outfile, "\n\nFile:%s:\n\n", pf->symaddr[1]);
-
- while(*p != endfileop)
- {
- if(*p == labelop)
- {
- newlabel_insert(iv, GL( POP->data ));
- }
- else if(*p == lineop)
- {
- iv->lastline = GL(POP->data);
- if(iv->debug >= '3')
- {
- cfeprintf("Line=%u depth=%d\n", iv->lastline, iv->stackdepth);
- }
- if(iv->listing_wanted)
- fprintf(iv->outfile, "Line:%ld:\n", iv->lastline);
- }
- else if(*p == gfuncdefop || *p == sfuncdefop)
- {
- p = dumpa_func(iv, p);
- }
- else if(*p == anfblockop)
- {
- PERROR(pName ": Sorry, Outer anf blocks not handled.\n");
- }
- p = POP->next;;
- }
- }
-
- /* Start the data area on an 8 byte boundary */
- if((pad = iv->out_offset & 7))
- pad = 8-pad;
- iv->out_offset += pad;
-
- if(pad && !iv->listing_wanted)
- FILEWRITE(padit, pad);
- iv->header->a_text = iv->out_offset;
- }
- static void
- fix_thunks(Piv iv)
- {
- Pafile pf;
- int i;
- unsigned char **vp;
- unsigned char *p;
-
- for(i = 0; i < iv->numfiles; ++i)
- {
- iv->filenum = i;
- pf = iv->files[i];
- if(SymHead(pf->datatbl))
- {
- while(SymNext(pf->datatbl))
- {
- SymValue(pf->datatbl, &vp);
- p = vp[1];
- if(*p == thunkblockop)
- {/* rearrange the FUNCTHUNK */
- unsigned short mods;
- mods = GS(POP->data7);
- mods &= 0xc000;
- mods |= GS(POP->data9) & 0x1f1f;
- PS( POP->data7 ) = mods;
- PS( POP->data9) = get_maxdepth(iv, GS( POP->data2 ));
- if(mods & Fextern)
- {/* Put symbol number in the offset slot */
- PL( POP->data5 ) = final_symnum(iv, GS( POP->data2 ));
- }
- else
- {/* Put function offset in the offset slot */
- PL( POP->data5 ) = newlabel_fix(iv, GL( POP->data5 ));
- }
- }
- }
- }
- }
- }
- static void
- printdata(Piv iv, char *sym, char *msg, void *ptr, int size,
- long offset, int locid)
- {
- int x;
-
- x = print8(iv, ptr, size, offset, 0);
- if(locid > 0)
- fprintf(iv->outfile," _%s.%d (%s)\n", sym, locid, msg);
- else
- fprintf(iv->outfile," _%s (%s)\n", sym, msg);
- while((size -= x) > 0)
- {
- offset += x;
- ((char*)ptr) += x;
- x = print8(iv, ptr, size, offset, 1);
- }
- }
- static void
- printbss(Piv iv, char *sym, int size, int offset, unsigned char prevopcode,
- int locid)
- {
- if(prevopcode == globssop)
- fprintf(iv->outfile, "%8.8x: _%s (BSS %d)\n", offset, sym, size);
- else
- fprintf(iv->outfile, "%8.8x: _%s.%d (bss %d)\n", offset, sym, locid, size);
- }
- static void
- dump_data(Piv iv)
- {
- struct _val {
- unsigned long size;
- unsigned char *p;
- unsigned char *prevp;
- long locid;
- };
- struct _val *val;
- unsigned long *key;
- long datsize = 0;
- long bsssize = 0;
- long curr_offset = iv->out_offset;
- unsigned char opcode, prevopcode = 0;
-
- if(SymHead(iv->datatbl))
- {
- void *savaddr;
- if(iv->listing_wanted)
- {
- fprintf(iv->outfile, "\n\t.data\n\n");
- savaddr = iv->symaddr[0];
- iv->symaddr[0] = "STRING_";
- }
- while(SymNext(iv->datatbl))
- {
- unsigned char *p;
- long size;
- long pad;
- SymKey(iv->datatbl, &key);
- SymValue(iv->datatbl, &val);
- p = val->p;
- opcode = *p;
- if(val->prevp)
- prevopcode = *(val->prevp);
- size = val->size;
- if((pad = size & 3)) /* the interpreter requires 4 byte alignment */
- pad = 4-pad;
-
- if( opcode == datablockop
- || opcode == mallocblockop
- || opcode == thunkblockop
- || opcode == stringblockop)
- {
- if(iv->listing_wanted)
- {
- char *msg;
-
- if( opcode == datablockop
- || opcode == stringblockop)
- {
- if(prevopcode == glodatop)
- msg = "DATA";
- else
- {
- msg = "data";
- }
- }
- else if(opcode == mallocblockop)
- {
- msg = "alloced";
- }
- else /* thunkblockop */
- {
- if(prevopcode == extfuncop)
- {
- long bu;
- if((bu = check_for_builtin(iv, p, 2)))
- {
- Pft ft = (Pft)(p+24);
- ft->funcaddr = bu;
- ft->fmods |= Fbuiltin;
- ft->fmods &= ~Fextern;
- *(val->prevp) = 0xff;
- msg = "thunk";
- }
- else
- msg = "EXTHUNK";
- }
- else if(prevopcode == glofuncop)
- msg = "THUNK";
- else
- {
- msg = "thunk";
- }
- }
- printdata(iv, iv->symaddr[GS(POP->data2)],
- msg, p+24, size, GL(POP->data1), val->locid);
- }
- else
- {
- if(opcode == thunkblockop)
- {
- if(prevopcode == extfuncop)
- {
- long bu;
- if((bu = check_for_builtin(iv, p, 2)))
- {
- Pft ft = (Pft)(p+24);
- ft->funcaddr = bu;
- ft->fmods |= Fbuiltin;
- ft->fmods &= ~Fextern;
- *(val->prevp) = 0xff;
- }
- }
- }
- FILEWRITE(p+24, size);
- if(pad > 0)
- FILEWRITE(padit, pad);
- }
- datsize += size+pad;
- iv->out_offset += size+pad;
- }
- else if(opcode == bssblockop)
- {
- if(iv->listing_wanted)
- {
- printbss(iv, iv->symaddr[GS(POP->data2)], size,
- GL(POP->data1), prevopcode, val->locid);
- }
- bsssize += size+pad;
- }
- }
- if(iv->listing_wanted)
- {
- iv->symaddr[0] = savaddr;
- }
- }
- iv->header->a_data = iv->out_offset - curr_offset;
- if(datsize != iv->header->a_data)
- PERROR(pName,":SYSERROR: data size incorrect (%d)!=(%d)\n",
- datsize, iv->header->a_data);
- }
- static void
- dump_bss(Piv iv)
- {
- iv->header->a_bss = iv->total_size - iv->bss_offset;
- }
- static void
- make_final_string_pack(Piv iv)
- {
- long strsize = 0;
- int strcnt = 0;
- char *pack;
- char *cp;
- struct {
- char *str;
- long symnum;
- long symofs;
- } *val;
-
- if(SymHead(iv->finalsymtbl))
- {
- while(SymNext(iv->finalsymtbl))
- {
- SymValue(iv->finalsymtbl, &val);
- ++strcnt;
- val->symofs = strsize+4;
- strsize += strlen(val->str)+2;
- }
- }
- pack = Ccalloc(iv->category, 1, strsize+4);
- *((long*)pack) = strsize + 4;
- cp = pack + 4;
- if(SymHead(iv->finalsymtbl))
- {
- while(SymNext(iv->finalsymtbl))
- {
- SymValue(iv->finalsymtbl, &val);
- *cp++ = '_';
- strcpy(cp, val->str);
- cp += strlen(val->str)+1;
- }
- }
- iv->finalstringpack = pack;
- iv->finalpacksize = strsize+4;
- }
- static unsigned char *
- dump_switch(Piv iv, unsigned char *p, int filenum)
- {
- struct nlist nl;
- unsigned char *q = skip_bracket(p);
-
- nl.n_type = N_SWTAB;
- nl.n_other = 0;
- while(p < q)
- {
- if(*p == switchidop)
- {
- nl.n_desc = GS(POP->data1); /* id */
- }
- else if(*p == casevalop)
- {
- long key[2];
- long *result;
- nl.n_un.n_strx = GL(POP->data1); /* value */
- key[0] = GL(POP->data); /* label number */
- key[1] = filenum;
- if(SymFind(iv->newlabeltbl, &key, &result))
- {
- nl.n_value = *result; /* offset */
- }
- else
- {
- PERROR(pName ":SYSERROR: case label not found\n");
- }
- if(iv->listing_wanted)
- {
- /* print nothing */
- }
- else
- {
- FILEWRITE(&nl, sizeof(struct nlist));
- iv->out_offset += sizeof(struct nlist);
- }
- }
- p = POP->next;
- }
- return ((Pop)q)->next;
- }
- static void
- dump_symbols(Piv iv)
- {
- long curr_offset = iv->out_offset;
- int i;
- struct nlist nl;
-
- nl.n_other = 0;
- nl.n_desc = 0;
-
- make_final_string_pack(iv);
-
- if(SymHead(iv->gbltbl))
- {
- if(iv->listing_wanted)
- {
- fprintf(iv->outfile, "\n\t.symbols\n\n");
- }
- while(SymNext(iv->gbltbl))
- {
- struct _gloval *valp;
- unsigned char opcode;
-
- SymValue(iv->gbltbl, &valp);
- if((opcode = *(valp->p)))
- {
- PopI pp;
- pp = (PopI) (((Pop)(valp->p))->next+8);
- nl.n_un.n_strx = final_strofs(iv, valp->symname);
- if(opcode == glodatop)
- {
- nl.n_type = N_DATA|N_EXT;
- nl.n_value = pp->s.offset + iv->header->a_text;
- }
- else if(opcode == globssop)
- {
- nl.n_type = N_BSS|N_EXT;
- nl.n_value = pp->s.offset + iv->header->a_text;
- }
- else if(opcode == glofuncop || opcode == extfuncop)
- {/* The symbol is really a thunk in the data section */
- nl.n_type = N_NDC|N_EXT;
- nl.n_value = pp->s.offset;
- }
- else if(opcode == extvarop)
- {
- nl.n_type = N_UNDF|N_EXT;
- nl.n_value = 0;
- }
- else if(opcode == 0xff)
- {/* Builtin thunk */
- continue;
- }
- if(iv->listing_wanted)
- {
- int symval = nl.n_value;
- if(nl.n_type & (N_DATA|N_BSS))
- symval -= iv->header->a_text;
- fprintf(iv->outfile, "%8.8x: _%s\n", symval, valp->symname);
- }
- else
- {
- FILEWRITE(&nl, sizeof(struct nlist));
- }
- iv->out_offset += sizeof(struct nlist);
- }
- }
- }
- /* DUMP SWITCH TABLE INFO */
- for(i = 0; i < iv->numfiles; ++i)
- {
- Pafile pf = iv->files[i];
- unsigned char *p;
- if((p = pf->switch_p))
- {
- while(*p != endfileop)
- {
- if(*p == switchidop)
- {
- p = dump_switch(iv, p, i);
- }
- else p = POP->next;
- }
- }
- }
- iv->header->a_syms = iv->out_offset - curr_offset;;
- }/* END: dump_symbols() */
-
- static void
- dump_text_relocs(Piv iv)
- {
- long curr_offset = iv->out_offset;
- PEL pel = iv->finextbufstart;
- struct relocation_info r;
-
- r.r_pcrel = 0;
- r.r_extern = 1;
- r.r_length = 2;
- r.r_pad = 0;
- if(pel && iv->listing_wanted)
- {
- fprintf(iv->outfile,"\n\t.textrels\n\n");
- }
- while(pel)
- {
- r.r_symbolnum = final_symnum(iv, pel->symnum);
- r.r_address = pel->spot;
- if(pel->symnum > 0)
- {
- if(iv->listing_wanted)
- {
- fprintf(iv->outfile,"%8.8lx: .extern _%s\n",
- r.r_address, iv->symaddr[pel->symnum]);
- }
- else
- {
- FILEWRITE(&r, sizeof(struct relocation_info));
- }
- iv->out_offset += sizeof(struct relocation_info);
- }
- pel = pel->next;
- }
- iv->header->a_trsize = iv->out_offset - curr_offset;
-
- }/* END: dump_text_relocs() */
-
- static void
- dump_data_relocs(Piv iv)
- {
- long curr_offset = iv->out_offset;
- struct relocation_info r;
-
- r.r_pcrel = 0;
- r.r_length = 2;
- r.r_pad = 0;
- if(SymHead(iv->reloctbl))
- {
- if(iv->listing_wanted)
- {
- fprintf(iv->outfile,"\n\t.datarels\n\n");
- }
- while(SymNext(iv->reloctbl))
- {
- struct _rkey *kp;
- struct _rval *vp;
- unsigned char *p;
- int symnum;
- SymKey(iv->reloctbl, &kp);
- SymValue(iv->reloctbl, &vp);
- p = vp->p; /* pointer to relocop in input buffer */
- symnum = GS(POPI->reloc.rsym);
-
- if(kp->rsize == 1)
- r.r_length = 0;
- else if(kp->rsize == 2)
- r.r_length = 1;
- else if(kp->rsize == 4)
- r.r_length = 2;
- else PERROR(pName ":ERROR: reloc size too large\n");
-
- r.r_address = GL( POPI->reloc.spot );
- if(*p == extlocop)
- {/* External variable */
- r.r_extern = 1;
- r.r_symbolnum = final_symnum(iv, symnum);
- }
- else if(*p)
- {
- r.r_extern = 0;
- r.r_symbolnum = N_DATA;
- }
- if(*p)
- {
- if(iv->listing_wanted)
- {
- if(r.r_extern)
- {
- if(vp->rsym <= 0)
- {/* an absolute value */
- continue;
- }
- fprintf(iv->outfile,"%8.8lx: .extern _%s\n",
- r.r_address, iv->symaddr[symnum]);
- }
- else
- {
- fprintf(iv->outfile, "%8.8lx: .segrel\n", r.r_address);
- }
- }
- else
- {
- if(r.r_extern && vp->rsym <= 0)
- {/* an absolute value */
- continue;
- }
- FILEWRITE(&r, sizeof(struct relocation_info));
- }
- iv->out_offset += sizeof(struct relocation_info);
- }
- }
- }
- iv->header->a_drsize = iv->out_offset - curr_offset;
-
- }/* END: dump_data_relocs() */
-
- static void
- prepare_data_relocs(Piv iv)
- {
- if(SymHead(iv->reloctbl))
- {
- while(SymNext(iv->reloctbl))
- {
- struct _rkey *kp;
- struct _rval *vp;
- unsigned char *p;
- SymKey(iv->reloctbl, &kp);
- SymValue(iv->reloctbl, &vp);
- p = vp->p; /* pointer to relocop in input buffer */
-
- if(*p == extlocop)
- {/* External variable */
- }
- else if(*p)
- {/* a.out format requires a flat address space for relocations */
- if(kp->rsize == 1)
- {
- *((char*)vp->base) += iv->header->a_text;
- }
- else if(kp->rsize == 2)
- {
- *((short*)vp->base) += iv->header->a_text;
- }
- else if(kp->rsize == 4)
- {
- *(vp->base) += iv->header->a_text;
- }
- else PERROR(pName ":ERROR: reloc size too large\n");
-
- }
- }
- }
- }/* END: prepare_data_relocs() */
-
- static void
- dump_symbol_strings(Piv iv)
- {
- if(iv->listing_wanted)
- {
- /* print nothing */
- }
- else
- {
- FILEWRITE(iv->finalstringpack, iv->finalpacksize);
- }
- }/* END: dump_symbol_strings() */
-
- static int
- gen_output(Piv iv, char *outpath)
- {/* Bytecode output */
- char *cp;
- int i;
- char outname[256];
-
- strcpy(outname, outpath);
- if((cp = strrchr(outname, '.')))
- {
- #if 0
- if(iv->listing_wanted)
- strcpy(cp, ".lst");
- else
- strcpy(cp, ".byt");
- #endif
- }
- else
- {
- if(iv->listing_wanted)
- strcat(outname, ".lst");
- else
- strcat(outname, ".byt");
- }
- for(i = 1; i < iv->argc; ++i)
- {
- if(!strcmp(outname, iv->argv[i]))
- {
- PERROR(pName ":ERROR: output file `%s' is same as input file\n", outname);
- }
- }
- if(!(iv->outfile = fopen(outname, "wb")))
- {
- PERROR(pName ":ERROR: Cannot open output file %s\n", outname);
- }
-
- /* Allocate a header struct */
- iv->header = Ccalloc(iv->category, 1, sizeof(struct exec));
-
- if(iv->listing_wanted)
- {
- long tim = time(0);
- char *date = ctime(&tim);
- fprintf(iv->outfile,"/*\n `%s' %s", outname, date);
- fprintf(iv->outfile,notice,MAJOR_VERSION,MINOR_VERSION);
- }
- else
- {/* Seek past the header area */
- iv->header->a_info = OMAGIC;
- fseek(iv->outfile, sizeof(struct exec), SEEK_SET);
- }
- install_builtins(iv);
- make_final_symtab(iv);
-
- #if 0
- if(iv->debug)
- bterpdebug();
- #endif
- dump_funcs(iv);
- fix_thunks(iv);
- prepare_data_relocs(iv); /* adjust addresses for flat space */
- dump_data(iv);
- dump_bss(iv);
- dump_text_relocs(iv);
- dump_data_relocs(iv);
- dump_symbols(iv);
- dump_symbol_strings(iv);
-
- /* Update the header block */
- if(!iv->listing_wanted)
- {
- fseek(iv->outfile, 0, SEEK_SET);
- FILEWRITE(iv->header, sizeof(struct exec));
- }
- fclose(iv->outfile);
- iv->outfile = 0;
- return iv->errors;
- }
- /* ======================= END BYTECODE OUTPUT GENERATOR ==================== */
-
- /* ===================== GENERIC CODE BELOW THIS POINT ================== */
- static jmp_buf run_env;
- static void
- prerror(const char *fmt, ...)
- {
- VFPRINTF(fmt, (char *)(((int *)(&fmt))+1));
- longjmp(run_env, 3);
- }
- static void
- prwarn(const char *fmt, ...)
- {
- VFPRINTF(fmt, (char *)(((int *)(&fmt))+1));
- }
- static void
- info(const char *fmt, ...)
- {
- vfprintf(stdout, fmt, (char *)(((int *)(&fmt))+1));
- }
- /* ========================= MULTI HEAP MALLOC ========================== */
- #define LOCAL static
-
- #if USING_FRAMEWORK
- #define THEWELL(a) mallocC(local_category, a)
- static int local_category;
- static int num_instance;
- extern void *mallocC(int, int);
- extern void freecat(int);
- extern void oxlink_clear_bss();
- extern int NewMallocCategory();
- #endif /* USING_FRAMEWORK */
-
- #define BASE_CATEGORY 0
- #define MEMORY_BUG 0
- #define PRINT_RAWDATA 0
-
- #if MEMORY_BUG == 1
- #define MPRINTF printf
- #else
- #define MPRINTF(args...)
- #endif
-
- #define PAGESIZE (4096) /* can use `pagesize' function in OS */
- #define ALIGNMENTM (sizeof(unsigned long))
- #define MAL_MAXLEVEL (12)
- #define ROUNDINGM(a) ((a+(ALIGNMENTM-1))&~(ALIGNMENTM-1))
- #define ALLOCSIZE (4096)
- #define FRNTGUARD (0x544e5246UL)
- #define BACKGUARD (0x48434142UL)
- #ifndef THEWELL
- #define THEWELL do_sbrk
- #endif
-
- #define NUMTYPES 3
- #define SIZEH 0
- #define FREEH 1
- #define USEDH 2
-
- #define SKIPVARS NodePM update[MAL_MAXLEVEL+1];NodePM node,prev;int level
-
- #define DELETENODE(TYPE) \
- {for(level=0;level<=bp->TYPE##level; level++)\
- {if(update[level]->fptr[level] == node)\
- update[level]->fptr[level] = node->fptr[level];else break;}\
- while(bp->TYPE##level>0 && bp->TYPE##header->fptr[bp->TYPE##level]==_NILLL)\
- bp->TYPE##level--;free_Mnode(bp,node,TYPE);}
-
- #define INSERT() \
- {while(level >= 0){\
- node->fptr[level] = update[level]->fptr[level];\
- update[level]->fptr[level] = node;level--;}}
-
- #define SETLEVEL(TYPE) \
- {level = getMlevel(bp, bp->TYPE##level);\
- while(bp->TYPE##level < level)update[++bp->TYPE##level]=bp->TYPE##header;}
-
- #define FINDKEY(TYPE, KEYVAL)\
- {node = bp->TYPE##header;\
- for(level = bp->TYPE##level; level >= 0; level--){\
- while(node->fptr[level]->key < KEYVAL)\
- node = node->fptr[level];\
- update[level] = node;}prev=node;node=node->fptr[0];}
-
- #define DETACH(SN)\
- {SN->bptr->fptr=SN->fptr;if(SN->fptr)SN->fptr->bptr=SN->bptr;}
-
- #define UNLINK(SN, N)\
- {if(!sp->fptr&&sp->bptr->bptr<=(AddrP)(MAL_MAXLEVEL+1))dsize[N]=sp->size;\
- DETACH(SN);free_addr(bp,SN);}
-
- #define CHECKGUARDS(MSG)\
- {if(bp->guarded){\
- unsigned *p2;\
- p2 = (void*)((char*)address+cursize-ALIGNMENTM);\
- if(*address != FRNTGUARD)\
- PERROR(pName #MSG ":%d: corrupted at 0x%x\n", bp->bincat, addr);\
- if(*p2 != BACKGUARD)\
- PERROR(pName #MSG ":%d: corrupted by 0x%x\n", bp->bincat, addr);}}
-
- #if MEMORY_BUG == 1
- #define HEAPCHECK \
- {void *lastaddr;\
- if(category > 0){\
- guardC(category);\
- if((lastaddr = heapcheckC(category, NULL))){\
- FINDKEY(USEDH, (unsigned)lastaddr-ALIGNMENTM)\
- MPRINTF("bad heap at %x c:%u size=%u\n", lastaddr, category, node->value);\
- (void)print_rawdata(lastaddr-ALIGNMENTM, node->value);\
- abort();}}}
- #else
- #define HEAPCHECK
- #endif
-
- struct _catlocs {
- void *addr;
- struct _catlocs *fptr;
- };
-
- typedef struct _nodeM
- {
- unsigned key;
- unsigned value;
- unsigned levels; /* must always be after value */
- struct _nodeM *fptr[1];
- } NodeM, *NodePM;
-
- typedef struct _addr
- {
- struct _addr *fptr;
- struct _addr *bptr;
- NodePM maddr;
- unsigned size;
- } *AddrP;
-
- struct _bins {
- unsigned bits;
- unsigned nbits;
- NodePM SIZEHheader;
- int SIZEHlevel;
- NodePM FREEHheader;
- int FREEHlevel;
- NodePM USEDHheader;
- int USEDHlevel;
-
- unsigned bincat;
- unsigned maxloc;
- unsigned minloc;
- struct _catlocs *catlocs;
- struct _bins *fptr;
- NodePM freenodes[NUMTYPES][MAL_MAXLEVEL+2];
- struct _addr *freeaddrlocs;
- char *chunkbase[NUMTYPES];
- int chunksize[NUMTYPES];
- int guarded;
- int addrbump;
- };
-
- static struct _bins zbp;
- static struct _bins *hmap[1009];
- static struct _nodeM _nilll = {0xffffffff,0,0,{0}};
- static struct _nodeM *_NILLL = &_nilll;
- static unsigned maxloc;
- static unsigned minloc;
- static struct _bins *freebinlocs;
- static struct _catlocs *freecatlocs;
- static char *binbase;
- static int binsize;
- static int chunksizes[] = {ALLOCSIZE,3*ALLOCSIZE,2*ALLOCSIZE};
-
-
- static long randtbl[32] = { 0L,
- 0x9a319039L, 0x32d9c024L, 0x9b663182L, 0x5da1f342L,
- 0xde3b81e0L, 0xdf0a6fb5L, 0xf103bc02L, 0x48f340fbL,
- 0x7449e56bL, 0xbeb1dbb0L, 0xab5c5918L, 0x946554fdL,
- 0x8c2e680fL, 0xeb3d799fL, 0xb11ee0b7L, 0x2d436b86L,
- 0xda672e2aL, 0x1588ca88L, 0xe369735dL, 0x904f35f7L,
- 0xd7158fd6L, 0x6fa6f051L, 0x616e6b96L, 0xac94efdcL,
- 0x36413f93L, 0xc622c298L, 0xf5a42ab8L, 0x8a88d77bL,
- 0xf5ad9d0eL, 0x8999220bL, 0x27fb47b9L
- };
-
- static long *fptr = &randtbl[4];
- static long *rptr = &randtbl[1];
-
- /* ======================== START OF CODE =========================== */
- #if PRINT_RAWDATA == 1
- static char
- hexbyte(unsigned int c)
- {
- char x = c & 0xf;
-
- return x + ((x>9) ? 55 : 48);
- }
- static void
- print_rawdata(void *rawdata, long size)
- {
- unsigned long vaddr = 0;
- unsigned char *d = rawdata;
- int i,j;
- char addr[9];
- char hex1[24];
- char hex2[24];
- char side1[9];
- char side2[9];
-
- addr[8] = 0;
- hex1[23] = 0;
- hex2[23] = 0;
- side1[8] = 0;
- side2[8] = 0;
- while(size > 0)
- {
- unsigned long qaddr = vaddr;
- memset(addr, '0', 8);
- memset(hex1, ' ', 23);
- memset(hex2, ' ', 23);
- memset(side1, ' ', 8);
- memset(side2, ' ', 8);
- i = 7;
- while(qaddr)
- {
- addr[i--] = hexbyte(qaddr);
- qaddr >>= 4;
- }
- for(i=0,j=0; i < 8; ++i)
- {
- if(--size >= 0)
- {
- unsigned int c = *d++;
- if(isprint(c))
- side1[i] = c;
- else
- side1[i] = '.';
- hex1[j++] = hexbyte(c>>4);
- hex1[j++] = hexbyte(c);
- ++j;
- }
- else break;
- }
- for(i=0,j=0; i < 8; ++i)
- {
- if(--size >= 0)
- {
- unsigned int c = *d++;
- if(isprint(c))
- side2[i] = c;
- else
- side2[i] = '.';
- hex2[j++] = hexbyte(c>>4);
- hex2[j++] = hexbyte(c);
- ++j;
- }
- else break;
- }
- VPRINTF("%s %s%s%s %s%s%s\n",addr,hex1," | ",hex2,side1,"|",side2);
- vaddr += 16;
- }
- }
- #endif
-
- /*
- * Returns a really good 31-bit random number.
- */
- static long
- lrandom()
- {
- long i;
-
- *fptr += *rptr;
- i = (*fptr >> 1) & 0x7fffffffUL;
- if(++fptr > &randtbl[31])
- {
- fptr = &randtbl[1];
- ++rptr;
- }
- else
- {
- if(++rptr > &randtbl[31])
- rptr = &randtbl[1];
- }
- return( i );
- }
- #if !USING_FRAMEWORK
- static void *
- do_sbrk(unsigned amount)
- {
- void *address;
-
- address = sbrk(amount); /* OR WHATEVER TO ACCESS THE OPERATING SYSTEM */
- if(address == (void*)-1)
- {
- PERROR(pName "\nsystem out of memory, requested %u bytes\n", amount);
- }
- return address;
- }
- #endif
- static struct _catlocs *
- new_catloc(void)
- {
- struct _catlocs *p;
- if((p=freecatlocs))
- {
- freecatlocs = p->fptr;
- return p;
- }
- if(binsize < sizeof(struct _catlocs))
- {
- binbase = THEWELL(4096);
- binsize = 4096;
- }
- binsize -= sizeof(struct _catlocs);
- p = (void*)binbase;
- binbase += sizeof(struct _catlocs);
- return p;
- }
- static void
- free_catloc(struct _catlocs *p)
- {
- p->fptr = freecatlocs;
- freecatlocs = p;
- }
- static void *
- new_chunk(struct _bins *bp, int size, int type)
- {
- char *p;
- if(bp->chunksize[type] < size)
- {
- if(bp->bincat == 0) {
- bp->chunkbase[type] = THEWELL(chunksizes[type]);
- bp->chunksize[type] = chunksizes[type];
- }
- else {
- struct _catlocs *cl;
- bp->chunkbase[type] = Cmalloc(0,chunksizes[type]-zbp.guarded);
- bp->chunksize[type] = chunksizes[type]-zbp.guarded;
- cl = new_catloc();
- cl->addr = bp->chunkbase[type];
- cl->fptr = bp->catlocs;
- bp->catlocs = cl;
- }
- }
- bp->chunksize[type] -= size;
- p = bp->chunkbase[type];
- bp->chunkbase[type] += size;
- return p;
- }
- static void *
- new_Mnode(struct _bins *bp, int levels, int type)
- {
- int size;
- NodePM p;
-
- if((p=bp->freenodes[type][levels]))
- {
- bp->freenodes[type][levels] = p->fptr[0];
- p->value = 0;
- return p;
- }
- size = sizeof(struct _nodeM) + levels * sizeof(void*);
- p = new_chunk(bp, size, type);
- p->levels = levels;
- p->value = 0;
- return p;
- }
- static void
- free_Mnode(struct _bins *bp, NodePM p, int type)
- {
- p->fptr[0] = bp->freenodes[type][p->levels];
- bp->freenodes[type][p->levels] = p;
- }
- static struct _addr *
- new_addr(struct _bins *bp)
- {
- struct _addr *p;
- if((p=bp->freeaddrlocs))
- {
- bp->freeaddrlocs = p->fptr;
- return p;
- }
- return new_chunk(bp, sizeof(struct _addr), FREEH);
- }
- static void
- free_addr(struct _bins *bp, struct _addr *p)
- {
- p->fptr = bp->freeaddrlocs;
- bp->freeaddrlocs = p;
- }
- static struct _bins *
- new_bins(void)
- {
- struct _bins *p;
- if((p=freebinlocs))
- {
- freebinlocs = p->fptr;
- return p;
- }
- if(binsize < sizeof(struct _bins))
- {
- binbase = THEWELL(4096);
- binsize = 4096;
- }
- binsize -= sizeof(struct _bins);
- p = (struct _bins*)binbase;
- binbase += sizeof(struct _bins);
- return p;
- }
- static void
- free_bins(struct _bins *p)
- {
- p->fptr = freebinlocs;
- freebinlocs = p;
- }
- static int
- getMlevel (struct _bins *p, int binlevel)
- {
- int level = -1;
- int bits = 0;
-
- while(bits == 0)
- {
- if (p->nbits == 0)
- {
- p->bits = lrandom();
- p->nbits = 15;
- }
- bits = p->bits & 3;
- p->bits >>= 2;
- p->nbits--;
-
- if(++level > binlevel)
- break;
- }
- return (level > MAL_MAXLEVEL) ? MAL_MAXLEVEL : level;
- }
-
- static void
- init_bins(struct _bins *bp, int category)
- {
- int i;
- int binnum = category % 1009;
-
- bzero(bp, sizeof(struct _bins));
- bp->bincat = category;
- bp->minloc = 0xffffffff;
- bp->fptr = hmap[binnum];
- hmap[binnum] = bp;
- bp->SIZEHheader = new_Mnode(bp, MAL_MAXLEVEL+1, SIZEH);
- bp->FREEHheader = new_Mnode(bp, MAL_MAXLEVEL+1, FREEH);
- bp->USEDHheader = new_Mnode(bp, MAL_MAXLEVEL+1, USEDH);
-
- for(i = 0; i <= MAL_MAXLEVEL; ++i)
- {
- bp->SIZEHheader->fptr[i] = _NILLL;
- bp->FREEHheader->fptr[i] = _NILLL;
- bp->USEDHheader->fptr[i] = _NILLL;
- }
- }
-
- static struct _bins*
- getcat(int category)
- {
- struct _bins *hbp;
-
- hbp = hmap[category % 1009];
- while(hbp)
- {
- if(hbp->bincat == category)
- return hbp;
- hbp = hbp->fptr;
- }
- return 0;
- }
- static struct _bins *
- initcat(int category)
- {
- struct _bins *bp;
-
- if(category == 0)
- {
- bp = &zbp;
- if(zbp.SIZEHheader == 0)
- init_bins(bp, category);
- return bp;
- }
- /* do this to set zbp.guarded properly on startup */
- if(zbp.SIZEHheader == 0)
- initcat(0);
-
- if((bp = new_bins()))
- {
- init_bins(bp, category);
- return bp;
- }
- return 0;
- }
- static void *
- getspace(struct _bins *bp, unsigned size, unsigned *remainder)
- {
- unsigned desired;
- void *address;
-
- desired = ((size+ALLOCSIZE-1)/ALLOCSIZE)*ALLOCSIZE;
- if(bp->bincat == 0)
- {
- address = THEWELL(desired);
- *remainder = desired - size;
- }
- else
- {
- struct _catlocs *cl;
-
- if((desired-size) > zbp.guarded)
- desired -= zbp.guarded;
-
- address = Cmalloc(0, desired);
- *remainder = desired - size;
-
- /* save the gross allocations for the category */
- cl = new_catloc();
- cl->addr = address;
- cl->fptr = bp->catlocs;
- bp->catlocs = cl;
- }
- /* maintain address range info */
- if((unsigned)address < bp->minloc)
- bp->minloc = (unsigned)address;
- if(((unsigned)address + desired) > bp->maxloc)
- bp->maxloc = (unsigned)address + desired;
- if(bp->minloc < minloc)
- minloc = bp->minloc;
- if(bp->maxloc > maxloc)
- maxloc = bp->maxloc;
- return address;
- }
- static void
- addto_sizelist(struct _bins *bp, AddrP ap)
- {
- SKIPVARS;
-
- /* INSERT IN SIZE LIST */
- FINDKEY(SIZEH, ap->size)
-
- if(node->key == ap->size)
- {/* size node exists */
- ap->fptr = (AddrP)node->value;
- ap->bptr = (AddrP)&node->value;
- if(ap->fptr) ap->fptr->bptr = ap;
- node->value = (unsigned)ap;
- }
- else
- {/* create new size node */
- SETLEVEL(SIZEH)
- node = new_Mnode(bp, level, SIZEH);
- node->key = ap->size;
- node->value = (unsigned)ap;
- ap->fptr = 0;
- ap->bptr = (AddrP)&node->value;
- INSERT()
- }
- }
- static void
- addto_freelist(struct _bins *bp, void *addr, unsigned size)
- {
- SKIPVARS;
- AddrP ap,sp;
- unsigned dsize[2];
-
- /* GET NEW ADDR STRUCT */
- ap = new_addr(bp);
- ap->size = size;
-
- dsize[1] = dsize[0] = 0; /* sizenode deletion markers */
-
- /* CHECK FREE LIST */
- FINDKEY(FREEH, (unsigned)addr)
-
- /* CHECK FOR MERGE OR INSERT */
- if(prev->value && prev->key+((AddrP)prev->value)->size == (unsigned)addr)
- {/* merge with previous block */
- ap->size += ((AddrP)prev->value)->size;
-
- if(prev->key + ap->size == node->key)
- {/* merge with previous and next block */
- sp = (AddrP) node->value;;
- ap->size += sp->size;
-
- /* delete size struct for next block */
- UNLINK(sp, 0)
-
- /* delete next block */
- DELETENODE(FREEH);
- }
- /* delete size struct for prev block */
- sp = (AddrP)prev->value;
- UNLINK(sp, 1)
-
- /* set new address struct */
- prev->value = (unsigned)ap;
- ap->maddr = prev;
- }
- else if(node->value && (char*)addr + size == (void*)node->key)
- {/* merge with next block */
- sp = (AddrP) node->value;;
- node->key = (unsigned)addr;
- ap->size += sp->size;
-
- /* unlink size struct for next block */
- UNLINK(sp,0)
-
- /* set new address struct */
- node->value = (unsigned)ap;
- ap->maddr = node;
- }
- else
- {/* insert in free list */
-
- SETLEVEL(FREEH)
- node = new_Mnode(bp, level, FREEH);
- node->key = (unsigned)addr;
- node->value = (unsigned)ap;
- ap->maddr = node;
- INSERT()
- }
- addto_sizelist(bp, ap);
-
- /* Remove sizenodes eliminated by merge */
- if(dsize[0])
- {
- FINDKEY(SIZEH, dsize[0])
- if(node->value == 0)
- DELETENODE(SIZEH)
- }
- if(dsize[1])
- {
- FINDKEY(SIZEH, dsize[1])
- if(node->value == 0)
- DELETENODE(SIZEH)
- }
- }
-
- LOCAL void*
- Cmemalign(int category, unsigned alignment, unsigned req)
- {
- SKIPVARS;
- NodePM fnode;
- unsigned remainder;
- unsigned *address;
- struct _bins *bp;
- unsigned mask, size;
-
-
- if(!(bp = getcat(category)))
- if(!(bp = initcat(category)))
- return 0;
- HEAPCHECK
- if(req == 0)
- req = ALIGNMENTM;
- else
- req += ROUNDINGM(req);
- size = req += bp->guarded;
-
- if(alignment)
- {
- alignment += ROUNDINGM(alignment);
- if(alignment > ALIGNMENTM)
- {
- mask = alignment -1;
- size = req + alignment + bp->guarded;
- }
- else
- {
- alignment = 0;
- }
- }
-
- /* check sizelist for candidate */
- FINDKEY(SIZEH, size)
- fnode = node;
- trynext:
- if(node->key != 0xffffffff)
- {/* found an appropriately sized block */
- AddrP sp = (AddrP)node->value;
-
- if(!sp && node == fnode)
- {
- NodePM q;
- q = node->fptr[0];
- DELETENODE(SIZEH)
- node = q;
- goto trynext;
- }
- if(!sp)
- {/* no available space at this size */
- node = node->fptr[0];
- goto trynext;
- }
-
- /* extract some space from this block */
- remainder = node->key - size;
- address = (void*)sp->maddr->key;
- sp->maddr->key += size;
- DETACH(sp);
-
- if(node->value == 0)
- {/* no more blocks of this size, delete sizenode */
- if(node != fnode)
- FINDKEY(SIZEH, size)
- DELETENODE(SIZEH)
- }
-
- if(remainder == 0)
- {/* no remaining space,the node in freelist is exhausted, delete it */
- FINDKEY(FREEH, sp->maddr->key)
- DELETENODE(FREEH)
- free_addr(bp, sp);
- }
- else
- {/* space remains in block, move it to new size loc */
- sp->size = remainder;
- addto_sizelist(bp, sp);
- }
- }
- else
- {
- address = getspace(bp, size, &remainder);
- if(remainder)
- addto_freelist(bp, ((char*)address)+size, remainder);
- }
- if(alignment)
- {
- unsigned diff;
- if((diff = (unsigned)address & mask))
- {/* move address forward */
- char *naddress;
- unsigned lose;
- lose = alignment - diff;
- naddress = (char*)address + lose;
- addto_freelist(bp, address, lose);
- address = (unsigned*)naddress;
- }
- }
- if(bp->guarded)
- {
- *address = FRNTGUARD;
- *((unsigned*)(((char*)address)+req-ALIGNMENTM)) = BACKGUARD;
-
- }
-
- FINDKEY(USEDH, (unsigned)address)
-
- if(node->key == (unsigned)address) {
- PERROR(pName ":ERROR:allocC:%d: bookkeeping nodes corrupted at:0x%x\n",
- category, address);
- }
- SETLEVEL(USEDH)
- node = new_Mnode(bp, level, USEDH);
- node->key = (unsigned)address;
- node->value = req;
- INSERT()
-
- return address+bp->addrbump;
- }
- LOCAL void*
- Ccalloc(int category, unsigned cnt, unsigned elem_size)
- {
- unsigned size = cnt * elem_size;
- void* buf;;
-
- if((buf = Cmalloc(category, size)))
- bzero(buf, size);
- return buf;
- };
- LOCAL void
- Cfree(int category, void* addr)
- {
- unsigned cursize;
- unsigned *address;
- struct _bins *bp;
- SKIPVARS;
- if(addr)
- {
- if(!(bp = getcat(category))) {
- PERROR(pName ":ERROR:Cfree:%d: non-existant category at:0x%x\n",category,addr);
- }
- HEAPCHECK
- address = (void*) ((unsigned*)addr - bp->addrbump);
- FINDKEY(USEDH, (unsigned)address)
- if(node->key != (unsigned)address) {
- PERROR(pName ":ERROR:Cfree:%d: bogus address=0x%x\n", category, addr);
- }
- cursize = node->value;
- CHECKGUARDS(Cfree)
- DELETENODE(USEDH)
-
- addto_freelist(bp, address, cursize);
- }
- else PERROR(pName ":ERROR:Cfree:%d: null pointer\n", category);
- }
- LOCAL void*
- Crealloc(int category, void* addr, unsigned newsize)
- {
- SKIPVARS;
- unsigned cursize;
- unsigned *address;
- struct _bins *bp;
- NodePM onode;
-
- if(addr == 0)
- return Cmalloc(category, newsize);
- else
- {
- if(!(bp = getcat(category))) {
- PERROR(pName ":ERROR:reallocC:%d: non-existant category at:%x\n",category,addr);
- }
- HEAPCHECK
- if(newsize == 0)
- newsize = ALIGNMENTM;
- else
- newsize += ROUNDINGM(newsize);
- newsize += bp->guarded;
-
- address = (void*)(((char*)addr)-(bp->guarded/2));
- FINDKEY(USEDH, (unsigned)address)
- if(node->key != (unsigned)address) {
- PERROR(pName ":ERROR:reallocC:%d: bogus address=0x%x\n", category, addr);
- }
- cursize = node->value;
- node->value = newsize;
- onode = node;
-
- CHECKGUARDS(reallocC)
-
- if(newsize == cursize)
- return addr;
- if(newsize > cursize)
- {/* check if block can be extended */
- void *taddr = ((char*)address) + cursize;
- unsigned extendsize = newsize-cursize;
-
- /* check freelist for an available block at the right address */
- FINDKEY(FREEH, (unsigned)taddr)
- if(node->key == (unsigned)taddr)
- {
- AddrP sp = (AddrP)node->value;
- if(sp->size >= extendsize)
- {/* BLOCK CAN BE EXTENDED INTERNALLY */
- node->key += extendsize;
- sp->size -= extendsize;
- DETACH(sp)
- if(sp->size == 0)
- {/* the extension block is used up, delete this node */
- free_addr(bp, sp);
- DELETENODE(FREEH)
- }
- else
- {/* shift the remainder in the sizelist */
- addto_sizelist(bp, sp);
- }
- /* SUCCESS */
- if(bp->guarded)
- {
- *((unsigned*)(((char*)address)+newsize-ALIGNMENTM))
- = BACKGUARD;
- }
- return addr;
- }
- }
- /* HERE WE COULD CHECK OTHER SOURCES OF SPACE */
-
- /* can't extend block, malloc some new space */
- if((taddr = Cmalloc(category,newsize-bp->guarded)))
- {
- memmove(taddr,addr,cursize-bp->guarded);
- onode->value = cursize;
- Cfree(category, addr);
- }
- /* SUCCESS */
- return taddr;
- }
- else
- {/* shrink block */
- if(bp->guarded)
- {
- *((unsigned*)(((char*)address)+newsize-ALIGNMENTM))
- = BACKGUARD;
- }
- addto_freelist(bp, ((char*)address)+newsize, cursize-newsize);
- return addr;
- }
- }
- }
- LOCAL void
- Cfreecat(int category)
- {
- struct _bins *bp;
-
- if(category == 0)
- return;
-
- if((bp = getcat(category)))
- {
- struct _catlocs *cl = bp->catlocs;
- struct _bins *hbp;
- struct _bins *prev;
-
- while(cl)
- {/* Space allocated to the category is moved to category 0 */
- void *ql = cl->fptr;
-
- Cfree(0, cl->addr);
- free_catloc(cl);
- cl = ql;
- }
- /* space for the _bins struct is placed on a free list */
- hbp = hmap[category % 1009];
- prev = 0;
- while(hbp)
- {
- if(hbp->bincat == category)
- {
- if(prev == 0)
- hmap[category % 1009] = hbp->fptr;
- else
- prev->fptr = hbp->fptr;
- free_bins(hbp);
- return;
- }
- prev = hbp;
- hbp = hbp->fptr;
- }
- }
- }
- LOCAL int
- Cmemrange(int category, unsigned *min, unsigned *max)
- {
- struct _bins *bp;
-
- if((bp = getcat(category)))
- {
- *min = bp->minloc;
- *max = bp->maxloc;
- return 1;
- }
- return 0;
- }
- LOCAL int
- Cusedrange(int category, unsigned *min, unsigned *max)
- {
- struct _bins *bp;
- NodePM node;
- int level;
-
- if((bp = getcat(category)))
- {
- node = bp->USEDHheader;
- *min = node->fptr[0]->key;
- for(level = bp->USEDHlevel; level >= 0; level--)
- while(node->fptr[level]->key < 0xffffffff)
- node = node->fptr[level];
- *max = node->key;
- return 1;
- }
- return 0;
- }
- LOCAL void
- Ctotrange(unsigned *min, unsigned *max)
- {
- *min = minloc;
- *max = maxloc;
- }
- LOCAL void
- Cguard(int category)
- {
- struct _bins *bp;
-
- if(!(bp = getcat(category)))
- if(!(bp = initcat(category)))
- return;
-
- if(!bp->guarded)
- {
- bp->guarded = 2*ALIGNMENTM;
- bp->addrbump = 1;
- }
- }
- LOCAL void*
- Cheapcheck(int category, void *start)
- {
- struct _bins *bp;
- NodePM node,prev;
- unsigned *p1,*p2;
-
- if((bp = getcat(category)))
- {
- if(bp->guarded)
- {
- prev = 0;
- node = bp->USEDHheader;
- while( (node = node->fptr[0]) != (NodePM)0xffffffff
- && node->key != 0xffffffffUL)
- {
- if((void*)node->key > start)
- {
- p1 = (unsigned*)node->key;
- if(*p1 != FRNTGUARD)
- {
- if(prev)
- return (char*)prev->key+ALIGNMENTM;
- else
- return (void*)1;
- }
- p2 = (unsigned*)(((char*)p1)+node->value-ALIGNMENTM);
- if(*p2 != BACKGUARD)
- return (char*)node->key+ALIGNMENTM;
- }
- prev = node;
- }
- }
- }
- return 0;
- }
- LOCAL void*
- Cmalloc(int category, unsigned size)
- {
- return Cmemalign(category, 0, size);
- }
-
- LOCAL void*
- Cvalloc(int category, unsigned bytes)
- {
- return Cmemalign (category, PAGESIZE, bytes);
- }
- LOCAL unsigned
- Cmallocsize(int category, void* addr)
- {
- struct _bins *bp;
- SKIPVARS;
-
- if(addr && (bp = getcat(category)))
- {
- unsigned address = (unsigned)((unsigned*)addr - bp->addrbump);
- FINDKEY(USEDH, address)
- if(node->key == address)
- return node->value - bp->guarded;
- }
- return 0;
- }
-
- LOCAL int
- Cnewcat()
- {
- static unsigned int cat = BASE_CATEGORY;
- return ++cat;
- }
- /* ====================== END MULTI-HEAP MALLOC ============================ */
-
-
- /* ====================== SYMBOL TABLE HANDLERS ============================ */
-
- typedef struct _key
- {
- unsigned long k[2];
- unsigned long hv;
- } KEY, *KEYP;
-
- typedef struct _nodeS
- {/* 40 bytes -- adjust size to suit application */
- unsigned long value[4]; /* 16 bytes */
- unsigned long key[2]; /* 8 bytes */
- struct _nodeS *fptr[4]; /* 16 bytes */
- } NodeS, *NodePS;
-
- typedef struct _pbuf
- {/* symbol table object */
- int nbins; /* number of bins in dictionary */
- int lastbin; /* for seq access */
- NodePS lastptr; /* ditto */
- int category; /* heap number */
- char *chunkbase; /* node allocation base */
- int chunksize; /* number of bytes available in current chunk */
- NodePS freelist; /* list of freed nodes for allocation */
- int level; /* sorted level */
- int bits; /* sorted bits */
- int bitcnt; /* sorted bitcnt */
- NodePS header; /* sorted header */
- NodePS bins[0]; /* bins if hashed dictionary */
- } *PbufP;
-
- #define SYM_MAXLEVEL 12
- #define TBL ((PbufP)tbl)
-
- static struct _nodeS _nnil = {{0,0,0,0},{0xffffffff,0xffffffff},{0,0,0,0}};
- static struct _nodeS *_NNIL = &_nnil;
-
- static int
- getSlevel (PbufP tbl)
- {
- int level = -1;
- int bits = 0;
-
- while (bits == 0)
- {
- if (tbl->bitcnt == 0)
- {
- tbl->bits = lrandom();
- tbl->bitcnt = 15;
- }
-
- bits = tbl->bits & 3;
- tbl->bits >>= 2;
- tbl->bitcnt--;
-
- if(++level > tbl->level)
- break;
- }
- return (level > SYM_MAXLEVEL) ? SYM_MAXLEVEL : level;
-
- }
-
- static void
- hash(void *key, KEY *cat)
- {
- cat->k[0] = ((unsigned long*)key)[0];
- cat->k[1] = ((unsigned long*)key)[1];
- cat->hv = ((cat->k[0] ^ cat->k[1]) * 1103515245UL) + 12345;
- }
- static void
- sym_hash(unsigned long *key, char *symb)
- {
- int len = strlen(symb);
- int i;
- for(i = 0; i < len; ++i)
- ((unsigned char *)key)[i & 7] ^= symb[i];
- key[0] = ((key[0] ^ key[1]) * 1103515245UL) + 12345;
- key[1] = len;
- }
- static void *
- new_Snode(PbufP tbl, int levels)
- {
- NodePS p;
- int size;
- if(levels <= 3)
- {
- if(tbl->freelist)
- {
- p = tbl->freelist;
- tbl->freelist = p->fptr[0];
- p->fptr[0] = 0;
- return p;
- }
- }
- size = sizeof(struct _nodeS) + ((levels-3) * sizeof(void*));
- if(tbl->chunksize < size)
- {
- tbl->chunkbase = Ccalloc(tbl->category, 1, 4080);
- tbl->chunksize = 4080;
- }
- tbl->chunksize -= size;
- p = (NodePS)tbl->chunkbase;
- tbl->chunkbase += size;
- return p;
- }
- static void
- free_Snode(PbufP tbl, NodePS node)
- {
- bzero(node, sizeof(struct _nodeS));
- node->fptr[0] = tbl->freelist;
- tbl->freelist = node;
- }
-
- static void*
- NewSymTable(int category, int nbins)
- {
- PbufP tbl;
-
- tbl = Ccalloc(category, 1, nbins*sizeof(NodePS) + sizeof(struct _pbuf));
- if(nbins == 0)
- {/* sorted dictionary */
- int i;
- tbl->header = new_Snode(tbl, SYM_MAXLEVEL+1);
- for(i = 0; i <= SYM_MAXLEVEL; ++i)
- tbl->header->fptr[i] = _NNIL;
- }
- tbl->nbins = nbins;
- tbl->category = category;
- return tbl;
- }
- static int
- SymFind(void *tbl, void *key, void *result)
- {
- NodePS node;
-
- if(tbl && key)
- {
- if(TBL->nbins)
- {/* hashed dictionary */
- KEY cat;
-
- hash(key, &cat);
- if((node = TBL->bins[cat.hv % TBL->nbins]))
- {
- do {
- if( node->key[0] == cat.k[0]
- && node->key[1] == cat.k[1])
- {
- if(result)
- *((NodePS *)result) = node;
- TBL->lastbin = cat.hv % TBL->nbins;
- TBL->lastptr = node;
- return 1;
- }
- } while((node = node->fptr[0]));
- }
- return 0;
- }
- else
- {/* sorted dictionary */
- int level;
-
- node = TBL->header;
- for(level = TBL->level; level >= 0; level--)
- {
- while( KEYLT(node->fptr[level]->key, ((unsigned long*)key)) )
- node = node->fptr[level];
- }
- node = node->fptr[0];
-
- TBL->lastptr = node;
- if(result)
- *((NodePS *)result) = node;
- return (KEYEQ(node->key, ((unsigned long*)key))) ? 1 : 0;
- }
- }
- return 0;
- }
- static int
- SymFindRange(void *tbl, void *key, void *result)
- {/* assumes 4 byte key and value (the value can be bigger) */
- NodePS node;
-
- if(tbl && key)
- {
- if(TBL->nbins)
- {/* hashed dictionary */
- return 0;
- }
- else
- {/* sorted dictionary */
- NodePS prev;
- int level;
-
- node = TBL->header;
- for(level = TBL->level; level >= 0; level--)
- {
- while ( node->fptr[level]->key[0] < ((unsigned long*)key)[0] )
- node = node->fptr[level];
- }
- prev = node;
- node = node->fptr[0];
-
- if( node->key[0] == ((unsigned long*)key)[0] )
- {
- TBL->lastptr = node;
- if(result)
- *((NodePS *)result) = node;
- return 1;
- }
- if( ((unsigned long*)key)[0] < prev->key[0]+prev->value[0] )
- {
- TBL->lastptr = prev;
- if(result)
- *((NodePS *)result) = prev;
- return 1;
- }
- return 0;
- }
- }
- return 0;
- }
- static void *
- SymInsert(void *tbl, void *key, void *value, int datsiz)
- {
- NodePS node;
-
- if(tbl && key)
- {
- if(TBL->nbins)
- {/* hashed dictionary */
- KEY cat;
- NodePS *binp;
- hash(key, &cat);
- node = new_Snode(tbl, 0);
- TBL->lastbin = cat.hv % TBL->nbins;
- TBL->lastptr = node;
- binp = &TBL->bins[TBL->lastbin];
- if(value && datsiz)
- memcpy(node, value, MIN(datsiz,16));
- node->key[0] = cat.k[0];
- node->key[1] = cat.k[1];
- node->fptr[0] = *binp;
- *binp = node;
- return node;
- }
- else
- {/* sorted dictionary */
- int level;
- NodePS update[SYM_MAXLEVEL+1];
-
- node = TBL->header;
- for (level = TBL->level; level >= 0; level--)
- {
- while ( KEYLT(node->fptr[level]->key,((unsigned long*)key)) )
- node = node->fptr[level];
- update[level] = node;
- }
-
- level = getSlevel(tbl);
-
- while(TBL->level < level)
- update[++TBL->level] = TBL->header;
-
- node = new_Snode(tbl, level);
-
- if(value && datsiz)
- memcpy(node, value, MIN(datsiz,16));
- node->key[0] = ((unsigned long*)key)[0];
- node->key[1] = ((unsigned long*)key)[1];
-
- while(level >= 0)
- {
- node->fptr[level] = update[level]->fptr[level];
- update[level]->fptr[level] = node;
- level--;
- }
- TBL->lastptr = node;
- return node;
- }
- }
- return 0;
- }
- static int
- StringFind(void *tbl, char *string, void *result)
- {
- unsigned long key[2];
- struct {
- char *symname;
- } *valp;
-
- key[0] = 0;
- key[1] = 0;
- sym_hash(key, string);
-
- if(SymFind(tbl, key, &valp))
- {
- unsigned long *key1;
- do {
- if(!strcmp(string, valp->symname))
- {
- if(result)
- *((void**)result) = valp;
- return 1;
- }
- /* Check duplicates */
- if(!SymNext(tbl))
- break;
- SymKey(tbl, &key1);
- SymValue(tbl, &valp);
- } while(KEYEQ(key, key1));
- }
- return 0;
- }
- static int
- StringInsert(void *tbl, char *string, void *result)
- {
- unsigned long key[2];
- struct {
- char *symname;
- } *valp;
-
- key[0] = 0;
- key[1] = 0;
- sym_hash(key, string);
- if(SymFind(tbl, key, &valp))
- {/* hash keys match */
- unsigned long *key1;
- do {
- if(!strcmp(string, valp->symname))
- {
- if(result)
- *((void**)result) = valp;
- return 1;
- }
- /* Check duplicates */
- if(!SymNext(tbl))
- break;
- SymKey(tbl, &key1);
- SymValue(tbl, &valp);
- } while(KEYEQ(key, key1));
- }
- /* NOMATCH */
- valp = SymInsert(tbl, key, &string, 4);
- if(result)
- *((void**)result) = valp;
- return 0;
- }
- static void
- SymDelete(void *tbl, void *key)
- {
- NodePS node;
-
- if(tbl && key)
- {
- if(TBL->nbins)
- {/* hashed dictionary */
- KEY cat;
- NodePS *binp;
- NodePS prev = 0;
-
- hash(key, &cat);
- binp = &TBL->bins[cat.hv % TBL->nbins];
- if((node = *binp))
- {
- do {
- if( node->key[0] == cat.k[0]
- && node->key[0] == cat.k[1])
- {
- if(prev)
- prev->fptr[0] = node->fptr[0];
- else
- *binp = node->fptr[0];
-
- free_Snode(tbl, node);
- if(TBL->lastptr == node)
- {
- TBL->lastptr = 0;
- TBL->lastbin = TBL->nbins;
- }
- return;
- }
- prev = node;
- } while((node = node->fptr[0]));
- }
- }
- else
- {/* sorted dictionary */
- int level;
- NodePS update[SYM_MAXLEVEL+1];
-
- node = TBL->header;
- for(level = TBL->level; level >= 0; level--)
- {
- while ( KEYLT(node->fptr[level]->key, ((unsigned long*)key)) )
- node = node->fptr[level];
- update[level] = node;
- }
- node = node->fptr[0];
-
- if( KEYEQ(node->key, ((unsigned long*)key)) )
- {
- for(level = 0; level <= TBL->level; level++)
- {
- if (update[level]->fptr[level] == node)
- update[level]->fptr[level] = node->fptr[level];
- else break;
- }
-
- while((TBL->level > 0) && (TBL->header->fptr[TBL->level] == _NNIL))
- TBL->level--;
-
- if(TBL->lastptr == node)
- TBL->lastptr = 0;
- free_Snode(tbl, node);
- }
- }
- }
- }
- static int
- SymHead(void *tbl)
- {/* Set up for sequential access */
- int nbins;
-
- if(tbl)
- {
- if((nbins = TBL->nbins))
- {/* hashed dictionary */
- NodePS node;
- int i;
- TBL->lastptr = 0;
- for(i = 0; i < nbins; ++i)
- {
- if( (node = TBL->bins[i]) != 0)
- {
- TBL->lastbin = i;
- return 1;
- }
- }
- TBL->lastbin = nbins;
- return 0; /* empty */
- }
- else
- {/* sorted dictionary */
- TBL->lastptr = TBL->header;
- return (TBL->lastptr->fptr[0] == _NNIL) ? 0 : 1;
- }
- }
- return 0;
- }
- static int
- SymNext(void *tbl)
- {/* Move to next sequential entry */
- int nbins;
-
- if(tbl)
- {
- if((nbins = TBL->nbins))
- {/* hashed dictionary */
- if(TBL->lastptr && ((TBL->lastptr = TBL->lastptr->fptr[0])))
- return 1;
- else
- {
- int i;
- for(i = TBL->lastbin; i < nbins; ++i)
- {
- if((TBL->lastptr = TBL->bins[i]) != 0)
- {
- TBL->lastbin = i+1;
- return 1;
- }
- }
- return 0;
- }
- }
- else
- {/* sorted dictionary */
- if(TBL->lastptr)
- {
- if(TBL->lastptr != _NNIL)
- TBL->lastptr = TBL->lastptr->fptr[0];
- return (TBL->lastptr == _NNIL) ? 0 : 1;
- }
- }
- }
- return 0;
- }
- static void
- SymGetMark(void *tbl, void *markptr)
- {
- if(tbl && markptr)
- {
- ((long*)markptr)[0] = TBL->lastbin;
- ((long*)markptr)[1] = (long)TBL->lastptr;
- }
- }
- static int
- SymMarkNext(void *tbl, void *mark)
- {/* Mark current position, and move to next sequential entry */
- SymGetMark(tbl, mark);
- return SymNext(tbl);
- }
- static void
- SymSetMark(void *tbl, void *markptr)
- {
- if(tbl && markptr)
- {
- TBL->lastbin = ((long*)markptr)[0];
- TBL->lastptr = (NodePS)((long*)markptr)[1];
- }
- }
- static void
- SymKey(void *tbl, void *keyptr)
- {/* Retrieve key info pointer for current spot */
-
- if(tbl && keyptr && TBL->lastptr)
- *((unsigned long**)keyptr) = &TBL->lastptr->key[0];
- }
- static void
- SymValue(void *tbl, void *datptr)
- {/* Retrieve value pointer for current spot */
-
- if(tbl && datptr && TBL->lastptr)
- *((unsigned long**)datptr) = &TBL->lastptr->value[0];
- }
-
- /* ==================== END SYMBOL TABLE HANDLERS ========================== */
-
- /* ========================== OPTIMIZATION ================================= */
- static int
- forward(unsigned char *p)
- {
- unsigned char *next;
-
- do {
- next = (void*)((Pop)p)->next;
- while( *next == 0
- || *next == lineop
- || *next == labelop)
- next = (void*)((Pop)next)->next;
-
- if(*next == endop)
- {
- if(*p == *(next+8))
- {
- *p = 0;
- *next = 0;
- return 1;
- }
- return 0;
- }
- } while(forward(next));
-
- return 0;
- }
- static void
- eliminate_extraneous_infops(Piv iv, int level)
- {
- Pafile pf;
- unsigned char *p;
- int i;
- for(i = 0; i < iv->numfiles; ++i)
- {
- iv->filenum = i;
- pf = iv->files[i];
- if(!(p = pf->prog_p))
- continue;
- if(pf->header_p->hdr.opt_level >= level)
- continue;
- pf->header_p->hdr.opt_level = level;
- while(*p != endfileop)
- {
- switch(*p)
- {
- case unopop:
- case arrayelemop:
- case ptrelemop:
- case strelemop:
- case ptrdimsop:
- case arraydimsop:
- forward(p);
- break;
- }
- p = POP->next;
- }
- }
- }
- static void
- clean_temps(Piv iv)
- {
- long *key;
- long *val;
- long hitemp = iv->first_temp & 0xffff0000;
-
- if(iv->temps_written == 0)
- return;
-
- if(SymHead(iv->tmptbl))
- {
- while(SymNext(iv->tmptbl))
- {
- SymKey(iv->tmptbl, &key);
-
- if((key[0] & 0xffff0000) == hitemp)
- {
- char *ptr;
- long saveit;
-
- SymValue(iv->tmptbl, &val);
- saveit = val[1];
- ptr = (void*)val[0];
- val[0] = 0; /* allow reuse of this slot */
- val[1] = 0;
-
- while(ptr)
- {
- void *nptr = (void*)((PopT)ptr)->tmpnum;
- ((PopT)ptr)->tmpnum = key[0];
-
- if(!saveit)
- {
- unsigned char *p = ptr-8;
- unsigned char op = *p;
-
- *p = 0;
- ++iv->killop;
- if(op == duptmpop)
- {/* special test for post increment */
- p = POP->next;
- p = POP->next;
- if(*p == grabop)
- *p = 0;
- }
- }
- ptr = nptr;
- }
- }
- }
- if(!hitemp)
- iv->temps_written = 0;
- }
- }
-
- static void
- read_temp(Piv iv, PopT ptr, unsigned long last)
- {
- unsigned long key[2];
- long *result;
-
- if(last == ptr->tmpnum)
- return;
-
- key[0] = ptr->tmpnum;
- key[1] = 0;
-
- if(SymFind(iv->tmptbl, key, &result))
- {
- result[1] = 1;
- }
- else PERROR(pName ":SYSERROR: read temp %d not found\n", key[0]);
- }
- static int
- reading_self(unsigned char *p, long tmpnum)
- {
- if((p[2]&0xe0) == OPTEMP || (p[2]&0xe0) == OPRET)
- {
- return 1;
- }
- if((p[3]&0xe0) == OPTEMP || (p[3]&0xe0) == OPRET)
- {
- return 1;
- }
- return 0;
- }
- static long
- write_temp(Piv iv, PopT ptr, unsigned char opcode)
- {
- long key[2];
- long val[2];
- long *result;
- long hitemp = ptr->tmpnum & 0xffff0000;
-
- if(ptr->atype & A_MEMADDR && opcode < duptmpop)
- {/* actually reading from this destination slot */
- read_temp(iv, ptr, 0);
- return 0;
- }
-
- if(hitemp > (iv->first_temp & 0xffff0000))
- {/* Inner block, CompoundExp or NestedFunc */
- iv->first_temp = hitemp + 1;
- }
- else if(hitemp < (iv->first_temp & 0xffff0000))
- {/* Exit inner block */
- if(!reading_self(((char*)ptr)-8, ptr->tmpnum))
- {
- while(hitemp < (iv->first_temp & 0xffff0000))
- {
- clean_temps(iv);
- iv->first_temp -= 0x00010000;
- }
- }
- }
- if(ptr->tmpnum == iv->first_temp)
- {
- if(!reading_self(((char*)ptr)-8, ptr->tmpnum))
- clean_temps(iv);
- }
- ++iv->temps_written;
- key[0] = ptr->tmpnum;
- key[1] = 0;
-
- if(SymFind(iv->tmptbl, key, &result))
- {
- PopT optr = (PopT)result[0];
- result[0] = (long)ptr;
- ptr->tmpnum = (long)optr;
- }
- else
- {
- val[0] = (long)ptr;
- val[1] = 0;
-
- SymInsert(iv->tmptbl, key, val, 8);
- ptr->tmpnum = 0;
- }
- return key[0];
- }
- static void
- eliminate_unused_temps(Piv iv, int level)
- {
- Pafile pf;
- unsigned char *p;
- int i;
- long last_write;
-
- iv->tmptbl = NewSymTable(iv->category, 111);
- for(i = 0; i < iv->numfiles; ++i)
- {
- iv->filenum = i;
- pf = iv->files[i];
- if(pf->header_p->hdr.opt_level >= level)
- continue;
- pf->header_p->hdr.opt_level = level;
- rekill:
- if(!(p = pf->prog_p))
- continue;
- iv->first_temp = 1;
- iv->temps_written = 0;
- iv->killop = 0;
- while(*p != endfileop)
- {
- while(*p < labelop)
- {
- if(*p == truthop)
- {/* truthops of single chars are unnecessary */
- if((p[2]&0xe0) == OPTEMP)
- {
- if(((PopT)(p+20))->dsize == 1)
- {
- if(((PopT)(p+8))->tmpnum == ((PopT)(p+20))->tmpnum)
- {
- if(!(((PopT)(p+20))->atype & A_MEMADDR))
- *p = 0;
- break;
- }
- else
- {/* may be needed for code generation */
- *p = aliastmpop;
- }
- }
- }
- }
- if(*p)
- {
- if( *p == jmptrueop
- || *p == jmpfalseop
- || *p == ljmptrueop
- || *p == ljmpfalseop)
- read_temp(iv,(PopT)(p+4), 0);
- if(*p == retdataop)
- {
- read_temp(iv, (PopT)p, 0);
- }
- else
- {
- last_write = 0;
- if((p[1]&0xe0) == OPTEMP)
- last_write = write_temp(iv, (PopT)(p+8), *p);
- if((p[2]&0xe0) == OPTEMP || (p[2]&0xe0) == OPRET)
- read_temp(iv, (PopT)((p+8+(p[1]&0x1f))), last_write);
- if((p[3]&0xe0) == OPTEMP || (p[3]&0xe0) == OPRET)
- read_temp(iv, (PopT)((p+8+(p[1]&0x1f))+(p[2]&0x1f)), last_write);
- }
- }
- break;
- }
- p = POP->next;
- }
- do {
- clean_temps(iv);
- iv->first_temp -= 0x00010000;
- } while(iv->first_temp > 0);
- if(iv->killop)
- {
- goto rekill;
- }
- }
- }
- static void
- retarget_jmps(Piv iv, int level)
- {
- Pafile pf;
- unsigned char *p;
- int i;
- for(i = 0; i < iv->numfiles; ++i)
- {
- iv->filenum = i;
- pf = iv->files[i];
- if(!(p = pf->prog_p))
- continue;
- if(pf->header_p->hdr.opt_level >= level)
- continue;
- }
- }
-
-
- static void
- optimize(Piv iv)
- {
- eliminate_extraneous_infops(iv, 50);
- eliminate_unused_temps(iv, 51);
- retarget_jmps(iv, 52);
- }
- /* ========================== END OPTIMIZATION ============================= */
- /* ====================== BASIC INPUT FILE PROCESSING ====================== */
- static long
- label_insert(Piv iv, long label, int filenum, unsigned char *p)
- {
- long *result;
- struct {
- long k1;
- long k2;
- } key;
-
- struct {
- long newlabel;
- } val;
-
- key.k1 = label;
- key.k2 = filenum;
-
- /* check for duplicate label -- they happen */
- if(SymFind(iv->labeltbl, &key, &result))
- {
- if(*p == labelop)
- *p = 0; /* kill the instruction */
- return 0;
- }
-
- val.newlabel = ++iv->lastlabel;
- SymInsert(iv->labeltbl, &key, &val, 4);
-
- #if REALLY_NEED_OFFSETS
- key.k1 = val.newlabel;
- val.newlabel = -1;
- SymInsert(iv->newlabeltbl, &key, &val, 4);
- #endif
-
- return iv->lastlabel;
- }
- static long
- label_find(Piv iv, long label, int filenum)
- {
- struct {
- long k1;
- long k2;
- } key;
-
- long *result;
-
- key.k1 = label;
- key.k2 = filenum;
-
- if(SymFind(iv->labeltbl, &key, &result))
- return *result;
- else
- return 0;
- }
- #if REALLY_NEED_OFFSETS
- static void
- newlabel_insert(Piv iv, long label)
- {
- struct {
- long k1;
- long k2;
- } key;
-
- long *result;
-
- key.k1 = label;
- key.k2 = iv->filenum;
- if(SymFind(iv->newlabeltbl, &key, &result))
- {
- *result = iv->out_offset + iv->func_offset;
- }
- else PERROR(pName ":SYSERROR: Label %d not found\n", label);
- }
- static long
- newlabel_fix(Piv iv, long label)
- {
- if(label)
- {
- struct {
- long k1;
- long k2;
- } key ;
-
- long *val;
-
- key.k1 = label;
- key.k2 = iv->filenum;
- if(SymFind(iv->newlabeltbl, &key, &val))
- {
- return val[0];
- }
- }
- return label;
- }
- #endif /* REALLY_NEED_OFFSETS */
-
- static void
- extern_insert(Piv iv, unsigned char *p, int filenum)
- {
- struct {
- short k1;
- short k2;
- long k3;
- } key;
- struct {
- unsigned char *p;
- } val;
-
- key.k1 = GS(POPI->s.symnum);
- key.k2 = filenum;
- key.k3 = 0;
-
- val.p = p;
- SymInsert(iv->extrntbl, &key, &val, 4);
- }
- static void
- reloc_insert(Piv iv, int fileno, unsigned char *p)
- {
- struct _rkey key;
- struct _rval val;
-
- key.spot = GL(POPI->reloc.spot); /* reloc target offset */
- key.fileno = (short)fileno; /* fileno */
- key.opcode = *p; /* opcode */
- key.rsize = GL(POPI->reloc.rsize); /* reloc size */
-
- val.p = p; /* pointer to input buffer */
- val.base = (void*)GL(POPI->reloc.base); /* base of data object pointed to */
- val.offset = GL(POPI->reloc.offset); /* offset to be added to base */
- val.rsym = GS(POPI->reloc.rsym); /* symbol number if external */
- SymInsert(iv->reloctbl, &key, &val, 14);
- }
- static void
- data_insert(void *tbl, unsigned long offset,
- unsigned long size, void *p, void *prevp)
- {
- static long locid = 1;
- struct {
- unsigned long k1;
- long k2;
- } key;
- struct {
- unsigned long size;
- void *p;
- void *prevp;
- long locid;
- } val;
- unsigned char opcode, prevopcode = 0;
-
- key.k1 = offset;
- key.k2 = 0;
-
- val.size = size;
- val.p = p;
- val.prevp = prevp;
- val.locid = 0;
- opcode = *((unsigned char *)p);
- if(prevp)
- {
- prevopcode = *((unsigned char*)prevp);
- if( prevopcode != glodatop
- && prevopcode != glofuncop
- && prevopcode != extfuncop
- && prevopcode != globssop)
- {
- val.locid = locid++;
- }
- }
- SymInsert(tbl, &key, &val, sizeof(val));
- }
-
- static void
- global_insert(Piv iv, Pafile pf, unsigned char *p)
- {
- unsigned long key[2];
- struct _gloval val;
- PopI pp;
- unsigned char opcode = *p;
-
- if(opcode == extvarop)
- pp = POPI;
- else
- pp = (PopI)(POP->next+8);
-
- key[0] = 0;
- key[1] = 0;
-
- val.symnum = GS(pp->s.symnum);
- val.symname = pf->symaddr[val.symnum];
- val.p = p;
- val.pf = pf;
- if(val.symnum < 0 || val.symnum >= pf->numsyms)
- {
- PERROR(pName ":SYSERROR: BAD SYMNUM=%d opcode=%d\n", val.symnum, opcode);
- }
- sym_hash(key, val.symname);
-
- /* Duplicate entries are allowed */
- SymInsert(iv->gbltbl, key, &val, sizeof(val));
- }
-
- static int
- setup_nodelinks(Piv iv, char *infile_name, void *inbuf, int insize)
- {
- unsigned char *p = inbuf;
- unsigned char *endbuf = inbuf+insize;
- Pafile pf=0;
- int lastline = 0;
- unsigned char *funcp;
- unsigned char *nfuncp;
-
- while(p < endbuf && *p != endallop)
- {
- unsigned char *q = p;
- if(iv->debug >= '5')
- {
- cfeprintf("OP(%u '%s' p=%p line=%d)\n", *p, oxgenops[*p], p, lastline);
- }
- switch(*p)
- {
- case headerop:
- if(iv->numfiles >= 1024) {
- PERROR(pName ": Sorry, too many files\n");
- }
- pf = iv->files[iv->numfiles] =
- Ccalloc(iv->category, 1, sizeof(struct _afile));
- pf->filenum = iv->numfiles++;
- pf->file_p = p;
- pf->header_p = POPI;
- if(iv->strip)
- {/* Gonna strip declarations and line numbers */
- pf->header_p->hdr.target_debugger = 0;
- }
- break;
-
- case dataop:
- pf->size_p = POPI;
- pf->thunk_offset = GL(POPI->dat.thunk_offset);
- pf->bss_offset = GL(POPI->dat.bss_offset);
- break;
- case gfuncdefop:
- case sfuncdefop:
- if(pf->prog_p == 0)
- pf->prog_p = p;
- funcp = p;
- break;
- case funcexitop:
- PS(((PopI)(funcp+8))->funcdef.tempmax) = GL(POPI->funcexit.tempmax);
- break;
- case nestedfuncdefop:
- nfuncp = p;
- break;
- case nestedfuncexitop:
- PS(((PopI)(nfuncp+8))->funcdef.tempmax) = GL(POPI->funcexit.tempmax);
- break;
- case segdefop:
- if(pf->seg_p == 0)
- pf->seg_p = p;
- pf->numsegs += 1;
- iv->numsegs += 1;
- break;
- case lineop:
- lastline = GL( POPI->line.line );
- if(iv->strip)
- *p = 0; /* strip line numbers */
- break;
- case declop:
- if(iv->strip)
- {/* strip declarations */
- do {
- *p = 0;
- q += (long)GL(POP->next);
- POP->next = q;
- p = q;
- } while(*p != endop);
- *p = 0;
- }
- else
- {
- if(pf->decl_p == 0)
- pf->decl_p = p;
- pf->numdecls += 1;
- iv->numdecls += 1;
- }
- break;
- case switchidop:
- if(pf->switch_p == 0)
- pf->switch_p = p;
- break;
- case labelop:
- PL( POP->data ) =
- label_insert(iv, GL( POP->data ), pf->filenum, p);
- break;
- case symbop:
- pf->numsyms = GL(POP->data);
- iv->numsyms += pf->numsyms;
- break;
- case symblockop:
- pf->symtext_p = p + 12;
- goto blka;
- case stringblockop:
- case datablockop:
- case mallocblockop:
- case thunkblockop:
- {
- long size;
- if(pf->data_p == 0)
- pf->data_p = p;
- blka:
- size = GL(POP->data);
- q += size+((4-(size&3))&3);
- break;
- }
- case glofuncop:
- case extfuncop:
- case glodatop:
- case globssop:
- case extvarop:
- case bssblockop:
- if(pf->data_p == 0)
- pf->data_p = p;
- break;
- case maxtempop:
- pf->maxtemp = GL(POP->data);
- pf->maxtempclass = GL(POP->data1);
- pf->maxtemp_p = p;
- break;
- }
- q += (long)GL(POP->next);
- POP->next = q;
- p = q;
- }
- if(*p != endallop)
- {
- PERROR(pName ":ERROR: Malformed input file: %s\n", infile_name);
- }
- return 0;
- }
- static void
- setup_syms_decls(Piv iv)
- {
- int i;
-
- for(i = 0; i < iv->numfiles; ++i)
- {
- int symnum = 0;
- Pafile pf = iv->files[i];
- unsigned char *p = pf->file_p;
- unsigned char *prevp = 0;
-
- pf->symaddr = Ccalloc(iv->category, sizeof(void*), pf->numsyms+1);
- pf->decladdr = Ccalloc(iv->category, sizeof(void*), pf->numdecls+1);
-
- while(*p != endfileop)
- {
- switch(*p)
- {
- case symoffsetop:
- pf->symaddr[symnum] = pf->symtext_p + GL(POP->data);
- ++symnum;
- break;
-
- case declop:
- pf->decladdr[GS(POPI->dcl.declnum)] = p;
- break;
-
- case relocop:
- case extlocop:
- ++pf->numrelocs;
- reloc_insert(iv, i, p);
- break;
-
- case glodatop:
- case globssop:
- case glofuncop:
- case extfuncop:
- global_insert(iv, pf, p);
- break;
-
- case extvarop:
- extern_insert(iv, p, i);
- global_insert(iv, pf, p);
- break;
-
- case stringblockop:
- case datablockop:
- case mallocblockop:
- case thunkblockop:
- case bssblockop:
- if(!pf->datatbl)
- pf->datatbl = NewSymTable(iv->category, 0); /* sorted */
-
- data_insert(pf->datatbl,GL(DATI.offset),GL(DATI.size),
- p, prevp);
- if(*p == thunkblockop) {
- PL(POP->data5) = label_find(iv, GL(POP->data5), i);
- }
- break;
-
- case jmploopop:
- case jmpcontinueop:
- case jmpbreakop:
- case jmpgotoop:
- case jmptrueop:
- case jmpfalseop:
- case ljmptrueop:
- case ljmpfalseop:
- case funcstartop:
- case funcstopop:
- case casevalop:
- case switchop:
- PL(POP->data) = label_find(iv, GL(POP->data), i);
- break;
- }
- prevp = p;
- p = POP->next;
- }
- }
- }
- static int
- sym_insert(Piv iv, char *symname, int symnum)
- {/* Used only for combining symbols in link phase */
- struct {
- char *symname;
- int symnum;
- } *valp;
-
- if(StringInsert(iv->symtbl, symname, &valp))
- return -valp->symnum; /* MATCH */
- valp->symnum = symnum;
- return symnum;
- }
- static void
- combine_syms_decls(Piv iv)
- {
- int i,j;
- Pafile pf;
- int numsyms;
- int numdecls;
-
- /* COMBINE SYMBOLS */
- pf = iv->files[0];
- numsyms = pf->numsyms;
- pf->symtran = Ccalloc(iv->category, sizeof(short), pf->numsyms+1);
- memcpy(iv->symaddr, pf->symaddr, sizeof(void*) * numsyms);
-
-
- for(i = 0; i < numsyms; ++i)
- {/* file 0 */
- sym_insert(iv, pf->symaddr[i], i);
- pf->symtran[i] = i;
- }
- for(i = 1; i < iv->numfiles; ++i)
- {
- int start;
-
- pf = iv->files[i];
- pf->symtran = Ccalloc(iv->category, sizeof(short), pf->numsyms+1);
- if(pf->header_p->hdr.target_debugger)
- start = 1;
- else
- start = 3;
- for(j = start; j < pf->numsyms; ++j)
- {
- int k;
- if((k = sym_insert(iv, pf->symaddr[j], numsyms)) > 0)
- { /* new entry */
- iv->symaddr[numsyms++] = pf->symaddr[j];
- pf->symtran[j] = k;
- }
- else pf->symtran[j] = -k;
- }
- }
- iv->numsyms = numsyms;
-
- /* COMBINE DECLARATIONS */
- pf = iv->files[0];
- numdecls = pf->numdecls;
- pf->decltran = Ccalloc(iv->category, sizeof(short), numdecls+1);
- memcpy(iv->decladdr, pf->decladdr, sizeof(void*) * numdecls);
- for(i = 0; i < numdecls; ++i)
- {/* file 0 */
- pf->decltran[i] = i;
- }
- for(i = 1; i < iv->numfiles; ++i)
- {
- pf = iv->files[i];
- pf->decltran = Ccalloc(iv->category, sizeof(short), pf->numdecls+1);
- if(pf->numdecls < 21)
- continue;
- for(j = 1; j <= 21; ++j)
- pf->decltran[j] = j;
- for(j = 22; j < pf->numdecls; ++j) {
- iv->decladdr[numdecls] = pf->decladdr[j];
- pf->decltran[j] = numdecls++;
- }
- }
- iv->numdecls = numdecls;
- }
-
- static void
- link_dups(Piv iv, int dupcnt, struct _gloval *valp[])
- {
- int i;
- int vars[5] = {0,0,0,0,0};
- unsigned long cdsize = 0;
- unsigned long cdoffset = 0;
- short cdfile = 0;
- int cdnum = 0;
- short segid = 0;
-
- #define GDAT vars[0]
- #define GBSS vars[1]
- #define GFUNC vars[2]
- #define EVAR vars[3]
- #define EFUNC vars[4]
-
- /* Count the types of matches */
- for(i = 0; i <= dupcnt; ++i)
- vars[*(valp[i]->p) - glodatop] += 1;
-
- /* Check for errors */
- if( GDAT > 1
- || GFUNC > 1
- || (GFUNC && (GDAT || GBSS || EVAR))
- || (EFUNC && (GDAT || GBSS || EVAR)))
- {
- ++iv->errors;
- for(i = 0; i < dupcnt; ++i)
- {
- PWARN(pName ": Symbol `%s' multiply defined or mistyped.\n",
- valp[i]->symname);
- PWARN(pName": In file: `%s'\n", valp[i]->pf->symaddr[INFILE_SYMNUM]);
- }
- return;
- }
- if(EFUNC && GFUNC)
- {/* match up functions */
- Pop dp;
- for(i = 0; i <= dupcnt; ++i)
- if(*(valp[i]->p) == glofuncop)
- break;
- dp = (Pop)((Pop)valp[i]->p)->next; /* points to thunkblockop */
-
- cdoffset = GL(dp->data1); /* save this offset */
- cdfile = valp[i]->pf->filenum; /* save this file */
- for(i = 0; i <= dupcnt; ++i)
- {
- if(*(valp[i]->p) == extfuncop)
- {
- *(valp[i]->p) = 0; /* convert to nilop */
- dp = (Pop)((Pop)valp[i]->p)->next; /* points to thunkblockop */
-
- /* Kill the thunkblock */
- *((char*)dp) = 0;
- PL(dp->data4) = cdoffset; /* use this offset for access */
- PS(((short*)dp)[1]) = cdfile; /* fileno to unused slots */
- }
- }
- }
- else if(EFUNC)
- {/* multiple references to external function */
- Pop dp = (Pop)((Pop)valp[0]->p)->next; /* points to first thunkblockop */
-
- cdoffset = GL(dp->data1); /* save first offset */
- cdfile = valp[0]->pf->filenum; /* save first file */
- for(i = 1; i <= dupcnt; ++i)
- {/* Kill all thunkblocks except the first */
- *(valp[i]->p) = 0; /* convert to nilop */
- dp = (Pop)((Pop)valp[i]->p)->next; /* points to thunkblockop */
- *((char*)dp) = 0;
- PL(dp->data4) = cdoffset; /* use this offset for access */
- PS(((short*)dp)[1]) = cdfile; /* fileno to unused slots */
- }
- }
- else if(GBSS)
- {/* comdefs */
- int multsize = 0;
-
- /* PICK THE BIGGEST GLOBAL BSS (comdef) */
- for(i = 0; i <= dupcnt; ++i)
- {
- Pop dp = (Pop)((Pop)valp[i]->p)->next; /* points to bssblockop */
- if((short)dp->data4 && segid == 0)
- {
- segid = (short)dp->data4;
- }
- else if((short)dp->data4 && (short)dp->data4 != segid)
- {
- ++iv->errors;
- PWARN(pName ": Variable `%s' defined in multiple segments.\n",
- valp[i]->symname);
- PWARN(pName ": In file: `%s'\n", valp[i]->pf->symaddr[INFILE_SYMNUM]);
- }
- if(*(valp[i]->p) == globssop)
- {
- long size = GL(dp->data);
- if(cdsize && size != cdsize)
- multsize = 1;
- if(size > cdsize) {
- cdsize = size;
- cdoffset = GL(dp->data1);
- cdfile = valp[i]->pf->filenum;
- cdnum = i;
- }
- }
- }
- if(GDAT)
- {
- /* INITIALIZED DATA WILL ALWAYS OVERRIDE BSS */
- for(i = 0; i <= dupcnt; ++i)
- {
- if(*(valp[i]->p) == glodatop)
- {
- Pop dp = (Pop)((Pop)valp[i]->p)->next; /* points to datablockop */
- long size = GL(dp->data);
- if(cdsize && size != cdsize)
- multsize = 1;
- if(size < cdsize)
- {
- ++iv->errors;
- PWARN(pName ": Initialized variable `%s' of size (%d)\n",
- valp[i]->symname, size);
- PWARN(pName ": In file: `%s'\n",
- valp[i]->pf->symaddr[INFILE_SYMNUM]);
- PWARN(pName ": Is incommensurate with common size (%d).\n",
- cdsize);
- }
- else
- {
- cdsize = size;
- cdoffset = GL(dp->data1);
- cdfile = valp[i]->pf->filenum;
- cdnum = i;
- }
- }
- }
- }
- if(multsize)
- {
- PWARN(pName ":warning: Common Variable `%s' has multiple sizes.\n",
- valp[0]->symname);
- for(i = 0; i <= dupcnt; ++i)
- {
- unsigned char opcode = *(valp[i]->p);
- if(opcode == globssop || opcode == glodatop)
- {
- PWARN(pName ":warning:Size=%d in file: `%s'\n",
- GL(((Pop)((Pop)valp[i]->p)->next)->data),
- valp[i]->pf->symaddr[INFILE_SYMNUM]);
- }
- }
- }
- /* FINALLY, LINK COMMONS TO THE CHOSEN ONE */
- for(i = 0; i <= dupcnt; ++i)
- {
- if(i != cdnum && *(valp[i]->p) == globssop)
- {
- Pop dp = (Pop)((Pop)valp[i]->p)->next; /* points to bssblockop */
-
- *(valp[i]->p) = 0; /* globssop becomes nilop */
- *((char*)dp) = 0; /* bssblockop becomes nilop */
- PL(dp->data4) = cdoffset; /* use this new offset for access */
- PS(((short*)dp)[1]) = cdfile; /* put fileno in unused slots */
- }
- }
- }
- else if(GDAT)
- {
- for(i = 0; i <= dupcnt; ++i)
- {
- Pop dp = (Pop)((Pop)valp[i]->p)->next; /* points to datablockop */
- if((short)dp->data4 && segid == 0)
- {
- segid = (short)dp->data4;
- }
- else if((short)dp->data4 && (short)dp->data4 != segid)
- {
- ++iv->errors;
- PWARN(pName ": Variable `%s' defined in multiple segments.\n",
- valp[i]->symname);
- PWARN(pName ": In file: `%s'\n", valp[i]->pf->symaddr[INFILE_SYMNUM]);
- }
- if(*(valp[i]->p) == glodatop)
- {
- cdsize = GL(dp->data);
- cdoffset = GL(dp->data1);
- cdfile = valp[i]->pf->filenum;
- cdnum = i;
- break;
- }
- }
- }
- if(EVAR && (GDAT || GBSS))
- {/* match up variables */
- /* LINK EXTERNS TO THE CHOSEN ONE */
- for(i = 0; i <= dupcnt; ++i)
- {
- if(*(valp[i]->p) == extvarop)
- {
- Pop dp = (Pop)valp[i]->p;
-
- *((char*)dp) = 0; /* extvarop becomes nilop */
- PL(dp->data1) = cdoffset; /* use this new offset for access */
- PS(((short*)dp)[1]) = cdfile; /* put fileno in unused slots */
- PS(dp->data4) = segid;
- break;
- }
- }
- }
- #undef GDAT
- #undef GBSS
- #undef GFUNC
- #undef EVAR
- #undef EFUNC
-
- }
- static void
- link_globals(Piv iv)
- {
- if(SymHead(iv->gbltbl))
- {
- struct _gloval *valp[1024]; /* pointers to symtable value structs */
-
- /* Pass over the sorted symbol table and process duplicate entries */
- while(SymNext(iv->gbltbl))
- {
- unsigned long *key;
- long mark[2]; /* Table position saver */
- int dupcnt = 0;
- SymKey(iv->gbltbl, &key); /* Pointer to first key */
- SymValue(iv->gbltbl, &valp[0]); /* Pointer to first value */
-
- while(SymMarkNext(iv->gbltbl, mark))
- {/* Look forward for duplicates */
- unsigned long *key1;
- SymKey(iv->gbltbl, &key1); /* Pointer to next key */
- if(KEYEQ(key, key1))
- {/* Hashed keys match, check the strings */
- SymValue(iv->gbltbl, &valp[dupcnt+1]); /* Pointer to next value */
- if(!strcmp(valp[dupcnt]->symname, valp[dupcnt+1]->symname))
- {/* Duplicate entry found */
- ++dupcnt;
- continue;
- }
- }
- break;
- }
- if(dupcnt > 0)
- {/* Process a collection of duplicate symbol names */
- link_dups(iv, dupcnt, valp);
- }
- SymSetMark(iv->gbltbl, mark);
-
- }/* END: while(SymNext) */
- }/* END: if(SymHead) */
- }
- static void
- realloc_data(Piv iv)
- {
- int i;
- Pafile pf;
- unsigned char *p, *prevp;
- unsigned long offset = 0;
-
- iv->datatbl = NewSymTable(iv->category, 0); /* sorted table */
-
- for(i = 0; i < iv->numfiles; ++i)
- {
- pf = iv->files[i];
- p = pf->data_p;
- prevp = 0;
- while(*p != endfileop)
- {
- if( *p == datablockop
- || *p == mallocblockop
- || *p == stringblockop)
- {
- PL(POP->data1) = offset;
- data_insert(iv->datatbl, offset, GL(POP->data), p, prevp);
- offset += GL(POP->data);
- ROUNDUP(offset, 4);
- }
- prevp = p;
- p = POP->next;
- }
- }
- iv->thunk_offset = offset;
-
- for(i = 0; i < iv->numfiles; ++i)
- {
- pf = iv->files[i];
- p = pf->data_p;
- prevp = 0;
- while(*p != endfileop)
- {
- if(*p == thunkblockop)
- {
- PL(POP->data1) = offset;
- data_insert(iv->datatbl, offset, GL(POP->data), p, prevp);
- offset += GL(POP->data);
- ROUNDUP(offset, 4);
- }
- prevp = p;
- p = POP->next;
- }
- }
- iv->bss_offset = offset;
-
- for(i = 0; i < iv->numfiles; ++i)
- {
- pf = iv->files[i];
- p = pf->data_p;
- prevp = 0;
- while(*p != endfileop)
- {
- if(*p == bssblockop)
- {
- PL(POP->data1) = offset;
- data_insert(iv->datatbl, offset, GL(POP->data), p, prevp);
- offset += GL(POP->data);
- ROUNDUP(offset, 4);
- }
- prevp = p;
- p = POP->next;
- }
- }
- iv->total_size = offset;
- }
- static void
- reset_data_relocs(Piv iv)
- {/* Pass over initialized data and set new offsets in each relocatable slot */
- struct _data {/* datatbl node */
- /* value area 16 bytes */
- unsigned long size;
- unsigned char *p;
- unsigned char opcode;
- unsigned char unused[7];
- /* key area 8 bytes */
- unsigned long offset;
- long unused1;
- };
- /* PASS OVER ALL THE ENTRIES IN `reloctbl' */
- if(SymHead(iv->reloctbl))
- {
- while(SymNext(iv->reloctbl))
- {
- struct _rkey *kp;
- struct _rval *vp;
- struct _data *dp, *ndp;
- unsigned char *p;
- Pafile pf, npf;
- unsigned long object_base;
- int noset = 0;
-
- SymKey(iv->reloctbl, &kp);
- SymValue(iv->reloctbl, &vp);
- npf = pf = iv->files[kp->fileno]; /* pointer to file struct */
- p = vp->p; /* pointer to relocop in input buffer */
-
- if(kp->opcode == extlocop)
- {/* External variable */
- short key[4];
- struct {
- unsigned char *p; /* pointer to extvarop in input buffer */
- } *ep;
- key[0] = vp->rsym; /* external symbol number */
- key[1] = pf->filenum;
- key[2] = 0;
- key[3] = 0;
-
- /* LOOK UP THE EXTERNAL SYMBOL */
- if(SymFind(iv->extrntbl, key, &ep) && *(ep->p) == 0)
- {/* symbol exists and the extvarop was filled in */
-
- npf = iv->files[GS( ((short*)(ep->p))[1] )];
- PL( POPI->reloc.base ) = GL( ((Pop)(ep->p))->data1 );
- *p = relocop; /* switch input file from `extlocop' */
- }
- else
- {/* Not found or not filled in, leave it alone */
- noset = 1;
- }
- }
-
- /* RESET THE ENTRY IN THE INITIALIZED DATA SLOT */
- if(SymFindRange(pf->datatbl, &kp->spot, &dp))
- {/* This entry describes a block of data containg the reloc target */
- unsigned char *ip = dp->p; /* points to input buffer */
- unsigned long extra = kp->spot - dp->offset; /* offset into data */
-
-
- /* Reset the relocop target in the input file */
-
- PL( POPI->reloc.spot ) = GL( ((PopI)(ip+8))->s.offset ) + extra;
- if(noset)
- continue;
-
- if(kp->rsize == 4)
- {/* 32 bit relocation */
- unsigned long *lp;
-
- lp = (unsigned long*)(ip+24+extra); /* pointer to target */
- object_base = GL( POPI->reloc.base );
-
- /* Find the object that the target points to */
- relink32:
- if(SymFindRange(npf->datatbl, &object_base, &ndp))
- {
- if(*(ndp->p) == 0)
- {/* The found object is a discarded thunkblock, relink */
- npf = iv->files[GS( ((short*)(ndp->p))[1] )];
- object_base = GL( ((Pop)(ndp->p))->data4 );
- goto relink32;
- }
- else
- {/* Use the new offset in the input file */
-
- object_base = GL( ((Pop)(ndp->p))->data1 );
- }
- PL( POPI->reloc.base ) = object_base; /* the `relocop' */
- PL(*lp) = object_base + GL( POPI->reloc.offset );/* data */
- vp->base = lp;
- }
- else
- {
- ++iv->errors;
- PWARN(pName ":syserr: 32 bit object at offset %d not found\n",object_base);
- }
- }
- else if(kp->rsize == 2)
- {/* 16 bit relocation (MORE WORK NEEDED) */
- unsigned short *sp;
-
- sp = (unsigned short*)(ip+24+extra); /* pointer to target */
- object_base = GL( POPI->reloc.base );
- relink16:
- if(SymFindRange(npf->datatbl, &object_base, &ndp))
- {
- if(*(ndp->p) == 0)
- {/* The found object is a discarded thunkblock, relink */
- npf = iv->files[GS( ((short*)(ndp->p))[1] )];
- object_base = GL( ((Pop)(ndp->p))->data4 );
- goto relink16;
- }
- else
- {/* Use the new offset in the input file */
-
- object_base = GL( ((Pop)(ndp->p))->data1 );
- }
- PL( POPI->reloc.base ) = object_base; /* the `relocop' */
- PS(*sp) = object_base + GL( POPI->reloc.offset );/* data */
- }
- else
- {
- ++iv->errors;
- PWARN(pName ":syserr: 16 bit object at offset %d not found\n", object_base);
- }
-
- }
- }
- else /* !SymFindRange */
- {
- ++iv->errors;
- PWARN(pName ":syserr: reloc not found at %d in file %d\n",
- kp->spot, kp->fileno);
- }
- }/* END: While(SymNext) */
- }/* END: if(SymHead) */
- }
- static void
- reset_offset(Piv iv, Pafile pf, PopA pa)
- {/* All offsets are guaranteed to be inside objects */
- struct _data {/* datatbl node */
- /* value area 16 bytes */
- unsigned long size;
- unsigned char *p;
- unsigned long unused[2];
- /* key area 8 bytes */
- unsigned long offset;
- long unused1;
- };
-
- unsigned long offset;
- struct _data *dp;
- unsigned long object_base;
- long extra;
- unsigned short atype;
- short symnum;
-
- offset = GL( pa->offset );
- atype = GS( pa->atype );
- symnum = GS( pa->symnum );
-
- PS( pa->symnum ) = pf->symtran[symnum];
- PS( pa->declnum ) = pf->decltran[GS(pa->declnum)];
-
- if(atype & A_EXTERN)
- {
- short key[4];
- struct {
- unsigned char *p; /* pointer to extvarop in input buffer */
- } *ep;
- key[0] = symnum; /* external symbol number */
- key[1] = pf->filenum;
- key[2] = 0;
- key[3] = 0;
-
- /* LOOK UP THE EXTERNAL SYMBOL */
- if(!SymFind(iv->extrntbl, key, &ep) && *(ep->p))
- {/* symbol exists and the extvarop was filled in */
-
- pf = iv->files[GS( ((short*)(ep->p))[1] )];
- offset += GL( ((Pop)(ep->p))->data1 );
- }
- else
- {/* Not found or not filled in, leave it alone */
-
- return;
- }
- }
- extra = 0; /* first time through */
-
- /* Find the object that the offset points to */
- relink:
- if(SymFindRange(pf->datatbl, &offset, &dp))
- {
- if(extra == 0)
- extra = offset - dp->offset;
- object_base = dp->offset;
-
- if(*(dp->p) == 0)
- {/* The found object is a discarded block, relink */
- pf = iv->files[GS( ((short*)(dp->p))[1] )];
- offset = GL( ((Pop)(dp->p))->data4 );
- goto relink;
- }
- else
- {/* Use the adjusted offset in the input buffer */
-
- object_base = GL( ((Pop)(dp->p))->data1 );
- }
- PL( pa->offset ) = object_base + extra;
- if(atype & A_EXTERN)
- {
- PS( pa->atype ) = atype & ~A_EXTERN;
- }
- }
- else
- {
- ++iv->errors;
- PWARN(pName ":syserr: object `%s' at offset %d not found\n",
- pf->symaddr[symnum], offset);
- }
- }
- static void
- reset_text_relocs(Piv iv)
- {/* Pass over text and set new offsets in instructions that reference data */
- int i;
-
- for(i = 0; i < iv->numfiles; ++i)
- {
- Pafile pf;
- unsigned char *p;
-
- pf = iv->files[i];
- if(!(p = pf->prog_p))
- continue;
-
- while(*p != endfileop)
- {
- if(*p && *p <= (unsigned char)100)
- {/* instruction */
- int inc = 8;
- if((p[1]&0xe0) == OPDATA)
- reset_offset(iv, pf, POPA);
- inc += (p[1]&0x1f);
- if((p[2]&0xe0) == OPDATA)
- reset_offset(iv, pf, POPA);
- inc += (p[2]&0x1f);
- if((p[3]&0xe0) == OPDATA)
- reset_offset(iv, pf, POPA);
- }
- p = POP->next;
- }
- }
-
- }
- static void *
- seg_find(Piv iv, int id)
- {
- long key[2];
- void **result;
-
- if(iv->segtbl)
- {
- key[0] = id;
- key[1] = 0;
- if(SymFind(iv->segtbl, key, &result))
- return *result;
- }
- return 0;
- }
- static void
- check_seg(Piv iv, unsigned char *p, Pafile pf)
- {
- PopI np, op;
- if(!(iv->segtbl))
- {
- iv->segtbl = NewSymTable(iv->category, 111);
- }
- if((op = seg_find(iv, GS(POPI->segdef.segid))))
- {
- np = POPI;
- if( GL(np->segdef.v1) == GL(op->segdef.v1)
- && GL(np->segdef.v2) == GL(op->segdef.v2)
- && GL(np->segdef.v3) == GL(op->segdef.v3))
- {/* segments of same name have the same values */
- *p = 0; /* kill the new definition */
- return;
- }
- else
- {/* segments of same name have different values */
- ++iv->errors;
- PWARN(pName ":Segment `%s' defined differently.\n",
- iv->symaddr[GS(POPI->segdef.segid)]);
- PWARN(pName ": In file: `%s'\n", pf->symaddr[INFILE_SYMNUM]);
- return;
- }
- }
- else
- {
- long key[2];
- PopI pp = POPI;
- key[0] = GS(POPI->segdef.segid);
- key[1] = 0;
- SymInsert(iv->segtbl, key, &pp, 4);
- }
- }
- static void
- reset_syms_decls(Piv iv)
- {
- int i;
- for(i = 0; i < iv->numfiles; ++i)
- {
- Pafile pf;
- unsigned char *p;
-
- pf = iv->files[i];
- p = pf->file_p;
-
- while(*p != endfileop)
- {
- if(*p == segdefop)
- {
- PS(POPI->segdef.segid) = pf->symtran[GS(POPI->segdef.segid)];
- check_seg(iv, p, pf);
- }
- else if(i > 0)
- {
- switch(*p)
- {
- case declop:
- if(GS(POPI->dcl.declnum) < 22)
- {/* kill the base declarations */
- *p = 0;
- p = POP->next;
- *p = 0;
- }
- else
- PS(POPI->dcl.declnum)=pf->decltran[GS(POPI->dcl.declnum)];
- break;
- case extlocop:
- PS(POPI->reloc.rsym) = pf->symtran[GS(POPI->reloc.rsym)];
- break;
- case gfuncdefop:
- case sfuncdefop:
- if(pf->numsegs)
- PS(POPI->funcdef.segid) = pf->symtran[GS(POPI->funcdef.segid)];
- case nestedfuncdefop:
- PL(POPI->funcdef.symnum) = pf->symtran[GL(POPI->funcdef.symnum)];
- break;
- case bssblockop:
- case datablockop:
- if(pf->numsegs)
- PS( POPI->s.segid ) = pf->symtran[GS(POPI->s.segid)];
- case stringblockop:
- case mallocblockop:
- case thunkblockop:
- case extvarop:
- PS( POPI->s.symnum ) = pf->symtran[GS(POPI->s.symnum)];
- PS( POPI->s.declnum ) = pf->decltran[GS(POPI->s.declnum)];
- break;
- case memberinfop:
- case bfieldinfop:
- PS(POPI->memb.symnum) = pf->symtran[GS(POPI->memb.symnum)];
- PS(POPI->memb.declnum) = pf->decltran[GS(POPI->memb.declnum)];
- PS(POPI->memb.cdeclnum) = pf->decltran[GS(POPI->memb.cdeclnum)];
- break;
- case structinfop:
- PS(POPI->suinf.symnum) = pf->symtran[GS(POPI->suinf.symnum)];
- break;
- case funcptrinfop:
- case ptrinfop:
- PS(POPI->ptrinf.declnum) = pf->decltran[GS(POPI->ptrinf.declnum)];
- break;
- case funcinfop:
- PS(POPI->funcd.declnum) = pf->decltran[GS(POPI->funcd.declnum)];
- PS(POPI->funcd.symnum) = pf->symtran[GS(POPI->funcd.symnum)];
- break;
- case arrayinfop:
- PS(POPI->ary.declnum) = pf->decltran[GS(POPI->ary.declnum)];
- break;
- case lineop:
- PL(POPI->line.filenamenum) = pf->symtran[GL(POPI->line.filenamenum)];
- break;
- }/* END: switch(*p) */
- }/* END: i > 0 */
- p = POP->next;
- }
- }
- }
- static int
- link_files(Piv iv)
- {
- iv->extrntbl = NewSymTable(iv->category, 4092); /* hashed table */
- iv->reloctbl = NewSymTable(iv->category, 4092); /* hashed table */
- iv->gbltbl = NewSymTable(iv->category, 0); /* sorted table */
-
- setup_syms_decls(iv);
-
- if(iv->numfiles > 1)
- {
- iv->symaddr = Ccalloc(iv->category, sizeof(void*), iv->numsyms+1);
- iv->decladdr = Ccalloc(iv->category, sizeof(void*), iv->numdecls+1);
- iv->symtbl = NewSymTable(iv->category, 0); /* sorted table */
- combine_syms_decls(iv);
-
- link_globals(iv);
- realloc_data(iv);
- reset_data_relocs(iv);
- reset_text_relocs(iv);
-
- reset_syms_decls(iv);
- }
- else
- {
- iv->symaddr = iv->files[0]->symaddr;
- iv->decladdr = iv->files[0]->decladdr;
- iv->symtbl = NewSymTable(iv->category, 0); /* sorted table */
- combine_syms_decls(iv);
-
- realloc_data(iv);
- reset_data_relocs(iv);
- reset_text_relocs(iv);
- }
- return iv->errors;
- }
-
- /* ======================== GLOBAL ROUTINES ========================== */
- int
- Global(readfile) (Piv iv, char *infile_name)
- {
- FILE *infile;
- long infile_size;
- char *inbuf;
-
- if(!(infile = fopen(infile_name, "rb")))
- {
- PERROR(pName ":ERROR: Can't open input file: %s\n", infile_name);
- }
- fseek(infile, 0, SEEK_END);
- infile_size = ftell(infile);
- fseek(infile, 0, SEEK_SET);
-
- if(infile_size == 0)
- {
- PERROR(pName ":ERROR: Empty input file: %s\n", infile_name);
- }
- inbuf = Cmalloc(iv->category, infile_size);
-
- if(fread(inbuf, 1, infile_size, infile) != infile_size)
- {
- fclose(infile);
- PERROR(pName ":ERROR: reading input file: %s\n", infile_name);
- }
- fclose(infile);
-
- if(setup_nodelinks(iv, infile_name, inbuf, infile_size))
- return 4;
- return 0;
- }
- int
- Global(proc_files) (Piv iv, void *name)
- {
- int ret;
-
- if(!(ret = link_files(iv)))
- {
- optimize(iv);
- if(name)
- iv->symaddr[2] = name; /* symbol 2 is the output filename */
-
- ret = gen_output(iv, iv->symaddr[2]);
- }
- return ret;
- }
- void *
- Global(open_instance) (void)
- {
- Piv iv;
- int category;
- #if USING_FRAMEWORK
- if(num_instance <= 0)
- {
- oxlink_clear_bss(pName ".o"); /* reset global storage */
- local_category = NewMallocCategory();
- }
- ++num_instance;
- #endif
- category = Cnewcat();
- iv = Ccalloc(category, 1, sizeof(struct _iv));
- iv->category = category;
- iv->finextbuf = (PEL)&iv->finextbufstart;
- return iv;
- }
- void
- Global(close_instance) (Piv iv)
- {
- if(iv->outfile)
- fclose(iv->outfile);
- if(iv->remove_infile)
- {
- int i;
- for(i = 1; i < iv->argc; ++i)
- unlink(propernameof(iv, iv->argv[i]));
- }
- Cfreecat(iv->category);
- #if USING_FRAMEWORK
- if(--num_instance == 0)
- freecat(local_category);
- #endif
- }
-
- /* =========================== THE MAIN PROGRAM ======================= */
-
- static char *
- filenameof(char *path)
- {
- char *ret = path;
- int i;
-
- for(i = 0; path[i]; ++i)
- if(path[i] == '/')
- ret = &path[i+1];
- return ret;
- }
-
- static char *
- propernameof(Piv iv, char *path)
- {
- char *name = filenameof(path);
- int namlen = strlen(name);
- int i;
- for(i = namlen-1; i >= 0; --i)
- {
- if(name[i] == '/' || name[i] == '\\')
- break;
- else if(name[i] == '.')
- return path;
- }
- name = Cmalloc(iv->category, strlen(path)+8);
- strcpy(name, path);
- strcat(name, ".anf");
- return name;
- }
- static void
- Usage()
- {
- fputs(
- "Usage: " pName " [-odsDLR?] [infile...]\n"
- " -o outfile == name of output file\n"
- " -d == print debug output\n"
- " -D == only print debug output\n"
- " -s == strip declarations and line numbers\n"
- " -L == generate listing only (to .lst)\n"
- " -R == remove input file\n"
- " -? == print this message\n"
- " Default input file is `code.anf'.\n"
- " Default output file is specified by the input.\n"
- ,stderr);
- }
-
- #if USING_FRAMEWORK
- int
- PROG (int argc, char **argv)
- #else
- int
- main (int argc, char **argv)
- #endif
- {
- int i,j;
- char *outfilename = 0;
- volatile Piv iv;
- char debug, only_debug, strip, listing_wanted, remove_infile;
- int ret;
-
- remove_infile = listing_wanted = strip = debug = only_debug = 0;
-
- /* Get options */
- for(i = 1; i < argc; ++i)
- {
- int trimsize = 1;
-
- if(argv[i][0] == '-')
- {
- for (j=1; argv[i][j]; j++)
- {
- switch(argv[i][j])
- {
- case 'D':
- only_debug = 1;
- /* FALL THROUGH */
- case 'd':
- debug = argv[i][++j];
- break;
- case 's':
- strip = 1;
- break;
- case 'o':
- if(argv[i][j+1]) {
- outfilename = &argv[i][j+1];
- }
- else if(i < argc-1) {
- outfilename = argv[i+1];
- trimsize = 2;
- } else {
- PWARN(pName ": no output filename\n");
- Usage();
- return 0;
- }
- goto trim;
- break;
- case 'L':
- listing_wanted = 1;
- break;
- case 'R':
- remove_infile = 1;
- break;
- case '?':
- Usage();
- return 0;
- default:
- PWARN(pName ": Invalid switch: 0x%x\n", argv[i][j]);
- Usage();
- return 0;
- }
- }/* END: for(j) */
- trim:
- /* Trim switch */
- for(j = i; j < argc-trimsize; ++j)
- argv[j] = argv[j+trimsize];
- argc -= trimsize;
- --i;
- }/* END: if('-') */
- }/* END: for(argc) */
-
- #if 0
- oxcc_debug(__builtin_iv(),0x40000);
- #endif
-
- iv = Global(open_instance) ();
- if((ret = setjmp(run_env))) {
- Global(close_instance) (iv);
- #if USING_FRAMEWORK
- return ret;
- #else
- exit(ret);
- #endif
- }
- iv->debug = debug;
- iv->only_debug = only_debug;
- iv->labeltbl = NewSymTable(iv->category, 4092);
- #if REALLY_NEED_OFFSETS
- iv->newlabeltbl = NewSymTable(iv->category, 4092);
- #endif
- iv->strip = strip;
- iv->listing_wanted = listing_wanted;
- iv->remove_infile = remove_infile;
- iv->argc = argc;
- iv->argv = argv;
-
- if(argc < 2)
- {/* Default input filename is 'code.anf' */
- ret = Global(readfile) (iv, "code.anf");
- }
- else
- {/* READ EACH INPUT FILE */
- for(i = 1; i < argc; ++i)
- if((ret = Global(readfile) (iv, propernameof(iv,argv[i]))))
- break;
- }
- if(!ret && !iv->only_debug)
- {
- ret = Global(proc_files) (iv, outfilename);
- }
- Global(close_instance) (iv);
- #if USING_FRAMEWORK
- return ret;
- #else
- exit(ret);
- #endif
- }
-
-