├── Makefile ├── Makefile.aos ├── alias.c ├── av.c ├── bin └── .dummy ├── bug.c ├── cp.c ├── cse.c ├── datatypes ├── datatypes.h ├── dtconv.h ├── dtf.c ├── dtgen.c ├── dtswap32f.c ├── dtswap32t.c ├── dtswap64f.c ├── dtswap64t.c ├── dtt.c └── dtwidths.h ├── declaration.c ├── doc ├── errors.texi ├── interface.texi ├── ucpp.texi ├── vbcc.texi ├── vbcc6502.texi ├── vbcc_main.texi ├── vbccalpha.texi ├── vbccc16x.texi ├── vbcchc12.texi ├── vbcci386.texi ├── vbccm68k.texi ├── vbccppc.texi ├── vbccvidcore.texi ├── vc.texi ├── vclib.texi ├── vcpr.texi ├── vprof.texi └── vsc.texi ├── dwarf2.c ├── errors.h ├── flow.c ├── frontend └── vc.c ├── ic.c ├── icn.c ├── loop.c ├── machines ├── 832 │ ├── addressingmodes.c │ ├── inlinememcpy.c │ ├── machine.c │ ├── machine.dt │ ├── machine.h │ └── tempregs.c ├── 6502 │ ├── compress.c │ ├── machine.c │ ├── machine.dt │ └── machine.h ├── alpha │ ├── machine.c │ ├── machine.dt │ ├── machine.h │ ├── schedule.c │ └── schedule.h ├── bi386 │ ├── machine.c │ ├── machine.dt │ └── machine.h ├── c16x │ ├── machine.c │ ├── machine.dt │ └── machine.h ├── generic │ ├── machine.c │ ├── machine.dt │ └── machine.h ├── hc12 │ ├── machine.c │ ├── machine.dt │ └── machine.h ├── i386 │ ├── machine.c │ ├── machine.dt │ └── machine.h ├── m68k │ ├── machine.c │ ├── machine.dt │ └── machine.h ├── m68ks │ ├── machine.c │ ├── machine.dt │ └── machine.h ├── ppc │ ├── machine.c │ ├── machine.dt │ ├── machine.h │ ├── schedule.c │ └── schedule.h ├── qnice │ ├── machine.c │ ├── machine.dt │ ├── machine.h │ └── sysdef.h ├── vidcore │ ├── machine.c │ ├── machine.dt │ └── machine.h └── z │ ├── machine.c │ ├── machine.dt │ └── machine.h ├── main.c ├── make.rules ├── mbasic.c ├── minicomp.c ├── minicomp.h ├── minicomp.tab.c ├── minicompg.tab.c ├── minicomplexer.c ├── misra_errors.h ├── opt.c ├── opt.h ├── osek_supp.h ├── osekrm.c ├── parse_expr.c ├── pp.c ├── pptst.h ├── preproc.c ├── range.c ├── rd.c ├── regs.c ├── statements.c ├── supp.c ├── supp.h ├── t1.h ├── t2.h ├── tasm.c ├── tt.h ├── type_expr.c ├── ucpp ├── README ├── assert.c ├── cpp.c ├── cpp.h ├── eval.c ├── hash.c ├── hash.h ├── lexer.c ├── macro.c ├── mem.c ├── mem.h ├── sample.c ├── tune.h └── ucppi.h ├── vars.c ├── vbc.h ├── vbcc_cpp.h ├── vbpp.h ├── vcpr ├── vcpr.c └── vcpr.h ├── vprof └── vprof.c └── vsc ├── vsc.c └── vsc.h /Makefile: -------------------------------------------------------------------------------- 1 | # Native Unix Makefile 2 | 3 | # may be used when cross-compiling binaries for multiple hosts 4 | HOSTID = 5 | 6 | # used to compile vbcc, vc, ucpp, etc. for the selected host 7 | CC = gcc -std=c9x -g -DHAVE_AOS4 #-fsanitize=address #-DHAVE_ECPP -DHAVE_MISRA 8 | LDFLAGS = -lm 9 | 10 | # used to compile dtgen and osekrm natively 11 | NCC = $(CC) 12 | NLDFLAGS = $(LDFLAGS) 13 | 14 | # emulator, may be used to run dtgen when cross-compiling for a different host 15 | EMUL = 16 | 17 | # OS-specific commands 18 | RM = rm -f 19 | MD = mkdir 20 | MV = mv 21 | 22 | include make.rules 23 | -------------------------------------------------------------------------------- /Makefile.aos: -------------------------------------------------------------------------------- 1 | # Cross-compiled for AmigaOS/68k 2 | HOSTID = _os3 3 | CC = vc +aos68k -rmcfg-amiga-softfloat -O1 -cpu=68020 -DAMIGA -DHAVE_AOS4 -Iucpp 4 | LDFLAGS = -lmsoft -lamiga 5 | NCC = $(CC) 6 | NLDFLAGS = $(LDFLAGS) 7 | EMUL = vamos -S -C 68020 -H disable -m 65536 -- 8 | 9 | RM = rm -f 10 | MD = mkdir 11 | MV = mv 12 | include make.rules 13 | -------------------------------------------------------------------------------- /bin/.dummy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leffmann/vbcc/dbc4a369692e2ef3739ab8da29fb1c264731b7e6/bin/.dummy -------------------------------------------------------------------------------- /bug.c: -------------------------------------------------------------------------------- 1 | /* $VER: vbcc (loop.c) V0.8 */ 2 | /* schleifenorientierte Optimierungen */ 3 | 4 | #include "opt.h" 5 | 6 | static char FILE_[]=__FILE__; 7 | 8 | #define MOVE_IC 1 9 | #define MOVE_COMP 2 10 | 11 | /* Liste, in die ICs eingetragen werden, die aus Schleifen */ 12 | /* gezogen werden sollen. */ 13 | struct movlist{ 14 | struct movlist *next; 15 | struct IC *IC; 16 | struct flowgraph *target_fg; 17 | int flags; 18 | }; 19 | 20 | struct movlist *first_mov,*last_mov; 21 | 22 | int report_weird_code,report_suspicious_loops; 23 | 24 | /* Bitvektoren fuer schleifeninvariante ICs */ 25 | bvtype *invariant,*inloop,*moved,*moved_completely; 26 | bvtype *fg_tmp; 27 | bvtype *not_movable; 28 | size_t bsize; 29 | 30 | 31 | /* Liste, in die ICs fuer strength-reduction eingetragen */ 32 | /* werden. */ 33 | struct srlist{ 34 | struct srlist *next; 35 | struct IC *ind_var; 36 | struct IC *IC; 37 | struct flowgraph *target_fg; 38 | /* Hilfsvariable, falls eine aequivalente Operation schon reduziert */ 39 | /* wurde. */ 40 | struct Var *hv; 41 | }; 42 | 43 | struct srlist *first_sr,*last_sr; 44 | 45 | /* Liste, in die Daten fuer loop-unrolling eingetragen werden. */ 46 | struct urlist{ 47 | int flags; 48 | long total,unroll; 49 | struct IC *cmp,*branch,*ind; 50 | struct flowgraph *start,*head; 51 | struct urlist *next; 52 | } *first_ur; 53 | 54 | #define UNROLL_COMPLETELY 1 55 | #define UNROLL_MODULO 2 56 | #define UNROLL_INVARIANT 4 57 | #define UNROLL_REVERSE 8 58 | #define IND_ONLY_COUNTS 16 59 | #define MULTIPLE_EXITS 32 60 | 61 | /* Hier werden Induktionsvariablen vermerkt */ 62 | struct IC **ind_vars; 63 | 64 | static struct flowgraph *first_fg; 65 | 66 | 67 | void calc_movable(struct flowgraph *start,struct flowgraph *end) 68 | /* Berechnet, welche Definitionen nicht aus der Schleife start-end */ 69 | /* verschoben werden duerfen. Eine Def. p von z darf nur verschoben */ 70 | /* werden, wenn keine andere Def. von p existiert und alle */ 71 | /* Verwendungen von z nur von p erreicht werden. */ 72 | /* Benutzt rd_defs. */ 73 | { 74 | struct flowgraph *g;struct IC *p; 75 | int i,j,k,d; 76 | bvtype *changed_vars; 77 | if(DEBUG&1024) printf("calculating not_movable for blocks %d to %d\n",start->index,end->index); 78 | if(0/*!(optflags&1024)*/){ 79 | memset(not_movable,UCHAR_MAX,dsize); 80 | return; 81 | } 82 | memset(not_movable,0,dsize); 83 | changed_vars=mymalloc(vsize); 84 | memset(changed_vars,0,vsize); 85 | for(i=0;ivtyp->flags&VOLATILE) BSET(changed_vars,i); 87 | if(ivtyp->next||(vilist[i]->vtyp->next->flags&VOLATILE)) BSET(changed_vars,i+vcount-rcount); 89 | } 90 | } 91 | for(g=start;g;g=g->normalout){ 92 | if(!g->rd_in) ierror(0); 93 | memcpy(rd_defs,g->rd_in,dsize); 94 | for(p=g->start;p;p=p->next){ 95 | for(j=0;jchange_cnt;j++){ 96 | i=p->change_list[j].v->index; 97 | if(p->change_list[j].flags&DREFOBJ) i+=vcount-rcount; 98 | if(i>=vcount) continue; 99 | if(BTST(changed_vars,i)||(q1typ(p)&VOLATILE)||(q2typ(p)&VOLATILE)||(ztyp(p)&VOLATILE)){ 100 | bvunite(not_movable,var_defs[i],dsize); 101 | }else{ 102 | BSET(changed_vars,i); 103 | } 104 | } 105 | for(k=0;kuse_cnt;k++){ 106 | i=p->use_list[k].v->index; 107 | if(p->use_list[k].flags&DREFOBJ) i+=vcount-rcount; 108 | if(i>=vcount) continue; 109 | for(d=-1,j=1;j<=dcount;j++){ 110 | if(BTST(rd_defs,j)&&BTST(var_defs[i],j)){ 111 | if(d>=0){ /* mehr als eine Def. */ 112 | bvunite(not_movable,var_defs[i],dsize); 113 | d=-1;break; 114 | }else d=j; 115 | } 116 | if(BTST(rd_defs,UNDEF(j))&&BTST(var_defs[i],UNDEF(j))){ 117 | bvunite(not_movable,var_defs[i],dsize); 118 | d=-1;break; 119 | } 120 | } 121 | } 122 | /* Das hier, um rd_defs zu aktualisieren. */ 123 | rd_change(p); 124 | if(p==g->end) break; 125 | } 126 | if(g==end) break; 127 | } 128 | free(changed_vars); 129 | } 130 | 131 | -------------------------------------------------------------------------------- /datatypes/datatypes.h: -------------------------------------------------------------------------------- 1 | /* elementary data types currently known to vbcc */ 2 | 3 | /* unsigned 8bit byte */ 4 | "S8BU", "standard unsigned 8bit byte", 5 | 6 | /* signed 8bit byte */ 7 | "S8BS", "standard 2-complement 8bit byte", 8 | 9 | /* typical unsigned integers, big-endian */ 10 | "S16BUBE", "standard 8bit-byte-based unsigned 16bit word, big-endian", 11 | "S32BUBE", "standard 8bit-byte-based unsigned 32bit word, big-endian", 12 | "S64BUBE", "standard 8bit-byte-based unsigned 64bit byte, big-endian", 13 | 14 | /* typical unsigned integers, little-endian */ 15 | "S16BULE", "standard 8bit-byte-based unsigned 16bit word, little-endian", 16 | "S32BULE", "standard 8bit-byte-based unsigned 32bit word, little-endian", 17 | "S64BULE", "standard 8bit-byte-based unsigned 64bit byte, little-endian", 18 | 19 | /* typical signed integers, big-endian */ 20 | "S16BSBE", "standard 8bit-byte-based 2-complement 16bit word, big-endian", 21 | "S32BSBE", "standard 8bit-byte-based 2-complement 32bit word, big-endian", 22 | "S64BSBE", "standard 8bit-byte-based 2-complement 64bit word, big-endian", 23 | 24 | /* typical signed integers, little-endian */ 25 | "S16BSLE", "standard 8bit-byte-based 2-complement 16bit word, little-endian", 26 | "S32BSLE", "standard 8bit-byte-based 2-complement 32bit word, little-endian", 27 | "S64BSLE", "standard 8bit-byte-based 2-complement 64bit word, little-endian", 28 | 29 | /* typical IEEE-floats, big-endian */ 30 | "S32BIEEEBE", "standard 8bit-byte-based 32bit IEEE floating-point, big-endian", 31 | "S64BIEEEBE", "standard 8bit-byte-based 64bit IEEE floating-point, big-endian", 32 | 33 | /* typical IEEE-floats, little-endian */ 34 | "S32BIEEELE", "standard 8bit-byte-based 32bit IEEE floating-point, little-endian", 35 | "S64BIEEELE", "standard 8bit-byte-based 64bit IEEE floating-point, little-endian", 36 | 37 | -------------------------------------------------------------------------------- /datatypes/dtconv.h: -------------------------------------------------------------------------------- 1 | "S16BSBE","S16BSLE","dtswap16f.c","dtswap16t.c",2, 2 | "S16BUBE","S16BULE","dtswap16f.c","dtswap16t.c",2, 3 | "S32BSBE","S32BSLE","dtswap32f.c","dtswap32t.c",4, 4 | "S32BUBE","S32BULE","dtswap32f.c","dtswap32t.c",4, 5 | "S64BSBE","S64BSLE","dtswap64f.c","dtswap64t.c",8, 6 | "S64BUBE","S64BULE","dtswap64f.c","dtswap64t.c",8, 7 | "S32BIEEEBE","S32BIEEELE","dtswap32f.c","dtswap32t.c",4, 8 | "S64BIEEEBE","S64BIEEELE","dtswap64f.c","dtswap64t.c",8, 9 | "S16BSLE","S16BSBE","dtswap16f.c","dtswap16t.c",2, 10 | "S16BULE","S16BUBE","dtswap16f.c","dtswap16t.c",2, 11 | "S32BSLE","S32BSBE","dtswap32f.c","dtswap32t.c",4, 12 | "S32BULE","S32BUBE","dtswap32f.c","dtswap32t.c",4, 13 | "S64BSLE","S64BSBE","dtswap64f.c","dtswap64t.c",8, 14 | "S64BULE","S64BUBE","dtswap64f.c","dtswap64t.c",8, 15 | "S32BIEEELE","S32BIEEEBE","dtswap32f.c","dtswap32t.c",4, 16 | "S64BIEEELE","S64BIEEEBE","dtswap64f.c","dtswap64t.c",8, 17 | 18 | #include "dtwidths.h" 19 | 20 | 21 | -------------------------------------------------------------------------------- /datatypes/dtf.c: -------------------------------------------------------------------------------- 1 | from) 2 | { 3 | DTTTYPE to=0; 4 | int i,j=0; 5 | for(i=sizeof(from.a)-1;i>=0;i--) 6 | to=(to<<8)|(from.a[i]&255); 7 | 8 | to<<=(sizeof(to)*8)-BITSIZE; 9 | to>>=(sizeof(to)*8)-BITSIZE; 10 | return to; 11 | } 12 | -------------------------------------------------------------------------------- /datatypes/dtswap32f.c: -------------------------------------------------------------------------------- 1 | from) 2 | { 3 | DTTTYPE to; 4 | unsigned char *fp=((unsigned char *)&from)+3,*tp=(unsigned char *)&to; 5 | *tp++=*fp--; 6 | *tp++=*fp--; 7 | *tp++=*fp--; 8 | *tp++=*fp--; 9 | return to; 10 | } 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /datatypes/dtswap32t.c: -------------------------------------------------------------------------------- 1 | from) 2 | { 3 | DTFTYPE to; 4 | unsigned char *fp=((unsigned char *)&from)+3,*tp=(unsigned char *)&to; 5 | *tp++=*fp--; 6 | *tp++=*fp--; 7 | *tp++=*fp--; 8 | *tp++=*fp--; 9 | return to; 10 | } 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /datatypes/dtswap64f.c: -------------------------------------------------------------------------------- 1 | from) 2 | { 3 | DTTTYPE to; 4 | unsigned char *fp=((unsigned char *)&from)+7,*tp=(unsigned char *)&to; 5 | *tp++=*fp--; 6 | *tp++=*fp--; 7 | *tp++=*fp--; 8 | *tp++=*fp--; 9 | *tp++=*fp--; 10 | *tp++=*fp--; 11 | *tp++=*fp--; 12 | *tp++=*fp--; 13 | return to; 14 | } 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /datatypes/dtswap64t.c: -------------------------------------------------------------------------------- 1 | from) 2 | { 3 | DTFTYPE to; 4 | unsigned char *fp=((unsigned char *)&from)+7,*tp=(unsigned char *)&to; 5 | *tp++=*fp--; 6 | *tp++=*fp--; 7 | *tp++=*fp--; 8 | *tp++=*fp--; 9 | *tp++=*fp--; 10 | *tp++=*fp--; 11 | *tp++=*fp--; 12 | *tp++=*fp--; 13 | return to; 14 | } 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /datatypes/dtt.c: -------------------------------------------------------------------------------- 1 | from) 2 | { 3 | DTFTYPE to; 4 | int i; 5 | from&=(((DTTTYPE)1)<>=8; 9 | } 10 | return to; 11 | } 12 | -------------------------------------------------------------------------------- /doc/ucpp.texi: -------------------------------------------------------------------------------- 1 | vbcc contains the C preprocessor ucpp by Thomas Pornin. 2 | 3 | Attached is the copyright notice from the ucpp-distribution (note that 4 | apart from ucpp no other part of this distribution falls under this 5 | license). 6 | 7 | 8 | Volker Barthelmann vb@compilers.de 9 | 10 | 11 | -------------- 12 | 13 | /* 14 | * (c) Thomas Pornin 1999, 2000 15 | * 16 | * Redistribution and use in source and binary forms, with or without 17 | * modification, are permitted provided that the following conditions 18 | * are met: 19 | * 1. Redistributions of source code must retain the above copyright 20 | * notice, this list of conditions and the following disclaimer. 21 | * 2. Redistributions in binary form must reproduce the above copyright 22 | * notice, this list of conditions and the following disclaimer in the 23 | * documentation and/or other materials provided with the distribution. 24 | * 4. The name of the authors may not be used to endorse or promote 25 | * products derived from this software without specific prior written 26 | * permission. 27 | * 28 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 29 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 30 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE 32 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 34 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 35 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 36 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 37 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 38 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 | * 40 | */ 41 | -------------------------------------------------------------------------------- /doc/vbccalpha.texi: -------------------------------------------------------------------------------- 1 | This chapter documents the Backend for the DEC Alpha processor family. 2 | 3 | @section Additional options for this version 4 | 5 | This backend provides the following additional options: 6 | 7 | @table @option 8 | 9 | 10 | @item -merge-constants 11 | Place identical floating point constants at the same 12 | memory location. This can reduce program size and increase 13 | compilation time. 14 | 15 | @item -const-in-data 16 | By default constant data will be placed in the code 17 | section (and therefore is accessable with faster pc-relative 18 | addressing modes). Using this option it will be placed in the 19 | data section. 20 | Note that on operating systems with memory protection this 21 | option will disable write-protection of constant data. 22 | 23 | @item -no-builtins 24 | Do not replace certain builtin functions by inline code. 25 | This may be useful if you use this code generator with 26 | another frontend than vbcc. 27 | stdarg.h will not work with -no-builtins. 28 | 29 | @item -stabs 30 | Generate stabs debug infos (if -g is specified) rather than 31 | DWARF2 which is the default. Consider this obsolete. 32 | 33 | @end table 34 | 35 | @section ABI 36 | 37 | 38 | This backend supports the following registers: 39 | 40 | @itemize @minus 41 | @item @code{$0} through @code{$31} for the general purpose registers and 42 | @item @code{$f0} through @code{$f31} for the floating point registers. 43 | @end itemize 44 | 45 | The current version generates assembly output for use with the GNU 46 | assembler. The generated code should work on systems with 21064, 47 | 21066, 21164 and higher Alpha CPUs. 48 | 49 | The registers @code{$0-$8, $16-$28, $f0, $f1} and @code{$f10-$f30} 50 | are used as scratch registers (i.e. they can be destroyed in function 51 | calls), all other registers are preserved. Of course @code{$31} and 52 | @code{$f31} cannot be used. 53 | 54 | The first 6 function arguments which have arithmetic or pointer types 55 | are passed in registers @code{$16/$f16} through @code{$21/$f21}. 56 | 57 | Integers and pointers are returned in @code{$0}, floats and doubles in 58 | @code{$f0}. 59 | All other types are returned by passing the function the address 60 | of the result as a hidden argument - so when you call such a function 61 | without a proper declaration in scope you can expect a crash. 62 | 63 | The elementary data types are represented like: 64 | 65 | @example 66 | type size in bits alignment in bytes 67 | 68 | char 8 1 69 | short 16 2 70 | int 32 4 71 | long 64 8 72 | long long 64 8 73 | all pointers 64 8 74 | float 32 4 75 | double 64 8 76 | @end example 77 | 78 | @section Predefined Macros 79 | 80 | This backend defines the following macros: 81 | 82 | @table @code 83 | @item __ALPHA__ 84 | 85 | @end table 86 | 87 | 88 | @section Stdarg 89 | 90 | A possible could look like this: 91 | 92 | @example 93 | 94 | typedef struct @{ 95 | char *regbase; 96 | char *membase; 97 | int arg; 98 | @} va_list; 99 | 100 | char *__va_start(void); 101 | int __va_fixargs(void); 102 | 103 | #define va_start(vl,dummy) \ 104 | (vl.arg=__va_fixargs(),vl.regbase=__va_start(),vl.membase=vl.regbase+(6-vl.arg)*16) 105 | 106 | #define va_end(vl) (vl.regbase=vl.membase=0) 107 | 108 | #define __va_size(type) ((sizeof(type)+7)/8*8) 109 | #define va_arg(vl,type) \ 110 | ( \ 111 | ((__typeof(type)&15)<=10&&++vl.arg<=6) ? \ 112 | ( \ 113 | ((__typeof(type)&15)>=6&&(__typeof(type)&15)<=8) ? \ 114 | (vl.regbase+=16,*(type *)(vl.regbase-8)) \ 115 | : \ 116 | (vl.regbase+=16,*(type *)(vl.regbase-16)) \ 117 | ) \ 118 | : \ 119 | (vl.membase+=__va_size(type),*(type *)(vl.membase-__va_size(type))) \ 120 | ) 121 | 122 | @end example 123 | 124 | 125 | @section Known problems 126 | 127 | @itemize @minus 128 | @item generated code is rather poor 129 | @item several other problems 130 | @end itemize 131 | 132 | 133 | -------------------------------------------------------------------------------- /doc/vbcchc12.texi: -------------------------------------------------------------------------------- 1 | This chapter documents the Backend for the 68hc12 and 6809/6309 microcontroller families. 2 | 3 | @section Additional options for this version 4 | 5 | This backend provides the following additional options: 6 | 7 | @table @option 8 | 9 | @item -merge-constants 10 | Place identical floating point constants at the same 11 | memory location. This can reduce program size and increase 12 | compilation time. (No fp support yet.) 13 | 14 | @item -const-in-data 15 | By default constant data will be placed in a read-only 16 | section. Using this option it will be placed in the 17 | data section. 18 | 19 | @item -no-delayed-popping 20 | By default arguments of function calls are not always popped 21 | from the stack immediately after the call, so that the 22 | arguments of several calls may be popped at once. 23 | With this option vbcc can be forced to pop them after every 24 | function call. 25 | This may simplify debugging and very slightly reduce the 26 | stack size needed by the compiled program. 27 | 28 | @item -no-peephole 29 | Do not perform peephole-optimizations. 30 | 31 | @item -mem-cse 32 | Try to hold values loaded from memory in registers and 33 | reuse them. Due to the small register-set of the hc12 34 | this is disabled by default as it increases register- 35 | pressure and tends to spill to the stack. 36 | 37 | @item -cpu= 38 | Specify the processor family. Currently supported values are: 39 | @itemize 40 | @item 6812: Generate code for the Motorola 68hc12 series (default). 41 | 42 | @item 6809: Generate code for the Motorola 6809 series. 43 | 44 | @item 6309: Generate code for the Hitachi 6309 series (currently identical to 6809). 45 | @end itemize 46 | 47 | 48 | @item -acc-glob 49 | Make the accumulator available for global register allocation. 50 | By default, the accumulator will only be used for register allocation 51 | within basic blocks. In many cases, global allocation will result in 52 | worse code, because the accumulator has to be pushed/popped many times. 53 | 54 | @item -pcrel 55 | Generate PC-relative code. May not fully work with 68hc12. 56 | 57 | @item -drel 58 | Generate code that accesses data relative to register @code{u}. Does not 59 | work with 68hc12. 60 | 61 | @end table 62 | 63 | @section ABI 64 | 65 | The current version generates assembly output for use with vasm6809_std or the GNU 66 | assembler using the non-banked model. 67 | 68 | This backend supports the following registers: 69 | 70 | @itemize @minus 71 | @item @code{d} for the accumulator (also used for byte, i.e. @code{b}) 72 | @item @code{x} for index register x 73 | @item @code{y} for index register y 74 | @item @code{u} for index register u (not on 68hc12) 75 | @item @code{sp} for the stack-pointer 76 | @end itemize 77 | 78 | The accumulator and @code{x} are caller-save. The @code{y} register is callee-save. 79 | The @code{u} register is used as data-page pointer with @code{-drel}. 80 | 81 | The first function argument which has integer or pointer type up to 16 bits 82 | is passed in the accumulator @code{d}. 83 | The remaining arguments are passed on the stack. 84 | 85 | Integers and pointers are returned in @code{d} or @code{d/x} (@code{x} contains the higher bits). 86 | All other types are returned by passing the function the address 87 | of the result as a hidden argument - so when you call such a function 88 | without a proper declaration in scope you can expect a crash. 89 | 90 | The elementary data types are represented like: 91 | @example 92 | type size in bits alignment in bytes 93 | 94 | char 8 1 95 | short 16 1 96 | int 16 1 97 | long 32 1 98 | near pointers 16 1 99 | far pointers 24 1 (not yet) 100 | huge pointers 24 1 (not yet) 101 | float 32 1 (not yet) 102 | double 64 1 (not yet) 103 | long double 64 1 (not yet) 104 | @end example 105 | 106 | 107 | @section Target-specific variable-attributes 108 | 109 | The 6809/hc12-backend offers the following variable attributes: 110 | 111 | @table @code 112 | @item __interrupt 113 | Return with @code{rti} rather than @code{rts}. 114 | 115 | @item __section("name","attr") 116 | Place this function/object in section "section" 117 | with attributes "attr". 118 | 119 | @item __dpage 120 | Place the variable in section @code{.dpage} and use direct addressing. 121 | 122 | @end table 123 | 124 | @section Predefined Macros 125 | 126 | This backend defines the following macros: 127 | 128 | @table @code 129 | @item __HC12__ 130 | If code for 68hc12 is generated. 131 | 132 | @item __6809__ 133 | If code for 6809 is generated. 134 | 135 | @item __6309__ 136 | If code for 6309 is generated. 137 | @ 138 | @end table 139 | 140 | @section Stack 141 | 142 | If the @option{-stack-check} option is used, every function-prologue will 143 | call the function @code{__stack_check} with the stacksize needed by this 144 | function in register @code{y}. This function has to consider its own 145 | stacksize and must restore all registers. 146 | 147 | 148 | @section Stdarg 149 | 150 | Stdarg is supported by the provided include. 151 | 152 | @section Known Problems 153 | 154 | @itemize @minus 155 | @item Support for floating point and long long is still missing. 156 | @item U register is not really used yet. 157 | @item No support for 6309 extensions yet. 158 | @item Many optimizations still missing. 159 | @item Some code generation bugs to be fixed. 160 | 161 | @end itemize 162 | 163 | 164 | -------------------------------------------------------------------------------- /doc/vbcci386.texi: -------------------------------------------------------------------------------- 1 | This chapter documents the Backend for the Intel i386 processor family. 2 | 3 | @section Additional options for this version 4 | 5 | This backend provides the following additional options: 6 | 7 | @table @option 8 | 9 | @item -longalign 10 | Align multibyte-values on 4-byte-boundaries. Needed by some 11 | operating systems. 12 | 13 | @item -elf 14 | Do not use a '_'-prefix in front of external identifiers. 15 | Use a '.'-prefix for label names. 16 | 17 | @item -merge-constants 18 | Place identical floating point constants at the same 19 | memory location. This can reduce program size and increase 20 | compilation time. 21 | 22 | @item -const-in-data 23 | By default constant data will be placed in a read-only 24 | section. Using this option it will be placed in the data section 25 | Note that on operating systems with memory protection this 26 | option will disable write-protection of constant data. 27 | 28 | @item -no-delayed-popping 29 | By default arguments of function calls are not always popped 30 | from the stack immediately after the call, so that the 31 | arguments of several calls may be popped at once. 32 | With this option vbcc can be forced to pop them after every 33 | function call. 34 | This may simplify debugging and very slightly reduce the 35 | stack size needed by the compiled program. 36 | 37 | @item -safe-fp 38 | Do not use the floating-point-stack for register variables. 39 | At the moment this is necessary as vbcci386 still has problems 40 | in some cases otherwise. 41 | @end table 42 | 43 | 44 | @section ABI 45 | 46 | This backend supports the following registers: 47 | 48 | @itemize @minus 49 | @item @code{%eax, %ebx, %ecx, %edx} 50 | @item @code{%esi, %edi, %ebp, %esp} 51 | @end itemize 52 | 53 | (And @code{%st(0)-%st(7)} for the floating point stack but these must not 54 | bes used for register variables because they cannot be handled like 55 | normal registers.) 56 | 57 | The current version generates assembly output for use with the GNU 58 | assembler. The generated code should work on systems with Intel 80386 59 | or higher CPUs with FPU and compatible chips. 60 | 61 | The registers @code{%eax, %ecx} and @code{%edx} (as well as the floating point stack) 62 | are used as scratch registers (i.e. they can be destroyed in function 63 | calls), all other registers are preserved. 64 | 65 | All elementary types up to 4 bytes are returned in register @code{%eax} 66 | Floating point values are returned in %st(0). 67 | All other types are returned by passing the function the address 68 | of the result as a hidden argument - so when you call such a function 69 | without a proper declaration in scope you can expect a crash. 70 | 71 | @code{vbcc} uses @code{%eax, %ebx, %ecx, %edx, %esi, %edi, %ebp} and the floating point 72 | stack for temporary results and register variables. Local variables 73 | are created on the stack and addressed via @code{%esp}. 74 | 75 | The elementary data types are represented like: 76 | 77 | @example 78 | type size in bits alignment in bytes (-longalign) 79 | 80 | char 8 1 (1) 81 | short 16 2 (4) 82 | int 32 2 (4) 83 | long 32 2 (4) 84 | long long n/a n/a 85 | all pointers 32 2 (4) 86 | float 32 2 (4) 87 | double 64 2 (4) 88 | @end example 89 | 90 | @section Predefined Macros 91 | 92 | This backend defines the following macros: 93 | 94 | @table @code 95 | @item __I386__ 96 | @item __X86__ 97 | 98 | @end table 99 | 100 | 101 | @section Stdarg 102 | 103 | A possible could look like this: 104 | 105 | @example 106 | typedef unsigned char *va_list; 107 | 108 | #define va_start(ap, lastarg) ((ap) = (va_list)(&lastarg + 1)) 109 | #define va_arg(ap, type) ((ap) += \ 110 | (sizeof(type) 45 | 46 | Set the limit (in number of intermediate code instructions) 47 | for the length of code-sequences considered for conditional 48 | execution (default: 2). 49 | 50 | 51 | @end table 52 | 53 | @section ABI 54 | 55 | This backend supports the following registers: 56 | 57 | @itemize @minus 58 | @item @code{r0} through @code{r31} for the general purpose registers 59 | @end itemize 60 | 61 | Additionally, the register pairs @code{r0/r1} @code{r2/r3, r4/r5, r6/r7, r8/r9, 62 | r10/r11, r12/r13, r14/r15, 63 | r16/r17, r18/r19, r20/r21, r22/r23} are 64 | available. 65 | 66 | @code{r14, r15, r24-r31} are currently reserved by the 67 | backend. 68 | 69 | 70 | 71 | The current version generates assembly output for use with @file{vasm}. 72 | 73 | 74 | The registers r0-r5 and r14-r15 are used as scratch registers 75 | (i.e. they can be destroyed in function calls), all other registers are 76 | preserved. r25 is the stack-pointer. 77 | 78 | The first 6 function arguments which have integer, float32 or pointer types 79 | are passed in registers r0 through r5. All other arguments 80 | are passed on the stack. 81 | 82 | Integers, float32 and pointers are returned in r0. 83 | All other types are returned by passing the function the address 84 | of the result as a hidden argument - so when you call such a function 85 | without a proper declaration in scope you can expect a crash. 86 | 87 | The elementary data types are represented like: 88 | 89 | @example 90 | type size in bits alignment in bytes 91 | 92 | char 8 1 93 | short 16 2 94 | int 32 4 95 | long 32 4 96 | long long 64 8 not yet supported 97 | all pointers 32 4 98 | float 32 4 99 | double 64 (32) 4 100 | long double 64 (32) 4 101 | @end example 102 | 103 | @section Target-specific variable-attributes 104 | 105 | The vidcore-backend offers the following variable-attributes: 106 | 107 | @table @code 108 | 109 | @item __section("name","attr") 110 | Place this function/object in section "name" with 111 | attributes "attr". 112 | @end table 113 | 114 | 115 | @section Target-specific pragmas 116 | 117 | The vidcore-backend offers the following #pragmas: 118 | 119 | @table @code 120 | 121 | @item none at the moment... 122 | 123 | @end table 124 | 125 | @section Predefined Macros 126 | 127 | This backend defines the following macros: 128 | 129 | @table @code 130 | @item __VIDEOCORE__ 131 | 132 | @item __SHORT_DOUBLE__ (if -short-double is used) 133 | @end table 134 | 135 | @section Stdarg 136 | 137 | stdarg-implementation is not yet fully working. One restriction is that 138 | when calling a varargs function, the prototype must be in scope (this is 139 | ISO C conforming). Another one is that the stdarg-macros only work as 140 | long as all fixed arguments are passed in registers. 141 | 142 | This will be fixed in the future. 143 | 144 | 145 | @section Known problems 146 | 147 | @itemize @minus 148 | @item no support for long long 149 | @item no support for 64bit floating point 150 | @item stdarg problems mentioned above 151 | @item suboptimal code quality 152 | @item ... 153 | @end itemize 154 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /doc/vcpr.texi: -------------------------------------------------------------------------------- 1 | vcpr - code compressor for vbcc (c) in 2020 by Volker Barthelmann 2 | 3 | 4 | @section Introduction 5 | 6 | vcpr is a code compressor which scans the assembly output of 7 | vbcc and tries to reduce code size of the generated code by 8 | moving common code sequences into separate subroutines. As a 9 | trade-off, the code will usually run slower. 10 | 11 | Like the compiler vbcc it is split into a target independent and a 12 | target dependent part. However there may be code-generators for vbcc 13 | which do not have a corresponding compressor. 14 | 15 | This document only deals with the target independent parts of vcpr. 16 | Be sure to read all the documents for your machine. 17 | 18 | 19 | @section Usage 20 | 21 | Usually @command{vcpr} will be called by a frontend. However if you call it 22 | directly, it has to be done like this: 23 | 24 | @example 25 | vcpr [options] input-file output-file 26 | @end example 27 | 28 | The following options are supported: 29 | 30 | @table @option 31 | @item -quiet 32 | Do not print the copyright notice. 33 | 34 | @item -debug= 35 | Set debug-level to . 36 | @end table 37 | 38 | 39 | Note that depending on the target @command{vbcc} may insert hints into the 40 | generated code. Assembly code that was not generated by @command{vbcc} 41 | may not work correctly after running it through @command{vcpr}. 42 | 43 | 44 | @section Known problems 45 | 46 | @itemize @minus 47 | @item still in early development 48 | @end itemize 49 | 50 | @section Backend Interface 51 | 52 | @subsection Building @code{vcpr} 53 | 54 | To write a backend for @code{vcpr}, the file @code{compress.c} has to be created 55 | in the machine subdirectory. The executable @code{vcpr} can be built 56 | using: 57 | 58 | @example 59 | make TARGET= bin/vcpr 60 | @end example 61 | 62 | @subsection Basic Function 63 | 64 | @code{vcpr} first reads the assembly source into a linked list of lines. It will 65 | call a backend function for each line to parse the line and fill in necessary 66 | information. 67 | 68 | The frontend looks for identical code sequences and calculates the 69 | savings that can be obtained by outlining the code. If code sequences are found 70 | that provide enough savings, they will be moved to subroutines using functions 71 | provided by the backend. 72 | 73 | Lines have to be textually identical to be considered for outlining. One exception 74 | are labels. The following sequences are considered equal as long as the labels 75 | are not used anywhere else: 76 | 77 | @example 78 | 79 | a 80 | bne l1 81 | b 82 | l1: 83 | c 84 | 85 | a 86 | bne l2 87 | b 88 | l2: 89 | c 90 | @end example 91 | 92 | Currently, @code{vcpr} only supports code sequences with one label. 93 | 94 | @subsection Data Types 95 | 96 | The main data type relevant for the backend represents the attributed source lines: 97 | 98 | @example 99 | typedef struct line @{ 100 | ... 101 | char *code; 102 | int flags; 103 | int size; 104 | ... 105 | int l1,l2; 106 | @} line; 107 | @end example 108 | 109 | The following members are relevant to the backend: 110 | 111 | @code{code} points to the assembly text of the line. 112 | 113 | @code{size} contains the (estimated) size of the instruction. 114 | 115 | @code{l1, l2} specify up to two labels referenced by this instruction. 116 | 117 | @code{flags} specifies the type of instruction and can be a combination of: 118 | 119 | @itemize 120 | @item @code{LABDEF}: This line defines a label. 121 | @item @code{LABUSE}: This line references a label. 122 | @item @code{BARRIER}: This line must not be moved into a subroutine. 123 | @item @code{LBARRIER}: Used by the frontend. 124 | @end itemize 125 | 126 | @subsection Backend Variables 127 | 128 | The following variables have to be defined and initialized by the backend: 129 | 130 | @itemize 131 | 132 | @item @code{const char tg_copyright[]} 133 | A copyright string. 134 | 135 | @item @code{int minsave;} 136 | The minimum size units saved by outlining a function. Should at least be larger 137 | than the size of the code for a subroutine call. 138 | 139 | @end itemize 140 | 141 | @subsection Backend Functions 142 | 143 | The following functions have to be provided by the backend: 144 | 145 | @itemize 146 | 147 | @item @code{void parse_line(char *s,line *p);} 148 | 149 | This function parses assembly line @code{s} and has to fill the 150 | members @code{flags}, @code{l1}, @code{l2} and @code{size} of the line structure 151 | @code{p}. 152 | 153 | @item @code{add_header(line *after);} 154 | 155 | This function creates a line for the header of outlined code and inserts it into the 156 | line list. 157 | 158 | @item @code{add_ret(line *after);} 159 | 160 | This function adds a return line and inserts it into the line list. 161 | 162 | @item @code{add_jsr(line *after);} 163 | 164 | This function adds a subroutine call to the subroutine corresponding to the last 165 | call of @code{add_header()}. 166 | 167 | @end itemize 168 | 169 | @subsection Frontend Functions 170 | 171 | The following functions are provided by the frontend and can be used by the 172 | backend: 173 | 174 | @itemize 175 | 176 | @item @code{void *mymalloc(size_t sz);} 177 | 178 | Allocate memory. 179 | 180 | @item @code{int new_label(void);} 181 | 182 | Create a new unused label number. 183 | 184 | @item @code{line *new_line(void);} 185 | 186 | Create a new line. 187 | 188 | @item @code{void insert_line(line *after, line *new);} 189 | 190 | Insert a line into the line list at a specified position. 191 | 192 | @end itemize 193 | -------------------------------------------------------------------------------- /doc/vprof.texi: -------------------------------------------------------------------------------- 1 | 2 | INTRODUCTION 3 | 4 | vprof is a portable utility to visualize the profiling information, 5 | which are usually stored in the file "mon.out". 6 | It shows the percentage of total time spent in a function, the 7 | total time in seconds, the number of function calls and the time 8 | by call in ms. 9 | 10 | 11 | LEGAL 12 | 13 | vprof is freeware. 14 | 15 | 16 | USAGE 17 | 18 | vprof [mon.out] 19 | 20 | If the profiling file has another name than "mon.out", you may 21 | specify it as an argument to vprof. 22 | 23 | Some vbcc code generators are able to create profiling information 24 | by compiling with the -prof option (vbccm68k, for example). 25 | 26 | 27 | BUGS 28 | 29 | The percentage column is still not working and will always 30 | display "n.a.". 31 | 32 | 33 | Frank Wille frank@phoenix.owl.de 34 | -------------------------------------------------------------------------------- /doc/vsc.texi: -------------------------------------------------------------------------------- 1 | vsc - scheduler for vbcc (c) in 1997-99 by Volker Barthelmann 2 | 3 | 4 | @section Introduction 5 | 6 | vsc is an instruction-scheduler which reorders the assembly output of 7 | vbcc and tries to improve performance of the generated code by avoiding 8 | pipeline stalls etc. 9 | 10 | Like the compiler vbcc it is split into a target independent and a 11 | target dependent part. However there may be code-generators for vbcc 12 | which do not have a corresponding scheduler. 13 | 14 | This document only deals with the target independent parts of vsc. 15 | Be sure to read all the documents for your machine. 16 | 17 | 18 | @section Usage 19 | 20 | Usually @command{vsc} will be called by a frontend. However if you call it 21 | directly, it has to be done like this: 22 | 23 | @example 24 | vsc [options] input-file output-file 25 | @end example 26 | 27 | The following options are supported: 28 | 29 | @table @option 30 | @item -quiet 31 | Do not print the copyright notice. 32 | 33 | @item -debug= 34 | Set debug-level to . 35 | @end table 36 | 37 | 38 | Note that depending on the target @command{vbcc} may insert hints into the 39 | generated code to tell vsc what CPU to schedule for. Code 40 | scheduled for a certain CPU may run much slower on slightly different 41 | CPUs. Therefore it is especially important to specify the correct 42 | target-CPU when compiling. 43 | 44 | 45 | @section Known problems 46 | 47 | @itemize @minus 48 | @item works only on basic-blocks 49 | @end itemize 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /ic.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leffmann/vbcc/dbc4a369692e2ef3739ab8da29fb1c264731b7e6/ic.c -------------------------------------------------------------------------------- /machines/6502/compress.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "vcpr.h" 7 | 8 | 9 | const char tg_copyright[]="6502 code compressor V0.1 (c) 2020 by Volker Barthelmann"; 10 | 11 | char *inst[]={ 12 | "lda","ldx","sta","stx","ldy","sty", 13 | "adc","sbc","and","ora","eor", 14 | "bne","beq","bcc","bcs","bvs","bvc","bpl","bmi", 15 | "clc","sec", 16 | /*"pla","pha",*/ 17 | "txa","tax","tya","tay", 18 | "inc","dec","dex","inx","iny","dey", 19 | /*"rts","rti",*/"jsr","jmp", 20 | "cmp","cpx","cpy", 21 | "asl","lsr","ror","rol" 22 | }; 23 | 24 | int minsave=5; 25 | 26 | void parse_line(char *s,line *p) 27 | { 28 | int l,i; 29 | static int secok=0; 30 | char buf[16],buf2[16],*e; 31 | 32 | if(sscanf(s," %8s %8s",buf,buf2)==2&&!strcmp(buf,"section")){ 33 | if(!strcmp(buf2,"text")) 34 | secok=1; 35 | else 36 | secok=0; 37 | p->flags=BARRIER; 38 | return; 39 | } 40 | 41 | if(sscanf(s,"l%d:",&l)==1){ 42 | p->flags|=LABDEF; 43 | p->l1=l; 44 | p->size=0; 45 | if(!secok) p->flags|=BARRIER; 46 | return; 47 | } 48 | 49 | if(!secok){ 50 | p->flags|=BARRIER; 51 | return; 52 | } 53 | 54 | if(!isspace((unsigned char)*s)){ 55 | p->flags=BARRIER; 56 | return; 57 | } 58 | while(isspace((unsigned char)*s)) 59 | s++; 60 | for(e=s;isalpha((unsigned char)*e);e++); 61 | 62 | for(i=0;isize=1; 67 | return; 68 | } 69 | p->size=2; 70 | if(sscanf(e,"l%d",&l)==1){ 71 | p->flags|=LABUSE; 72 | p->l1=l; 73 | } 74 | if(*s=='b'||!strncmp(s,"jmp",3)){ 75 | p->flags|=BRANCH; 76 | } 77 | return; 78 | } 79 | } 80 | p->flags=BARRIER; 81 | } 82 | 83 | static int nlab; 84 | 85 | #define SECTION "\tsection\ttext\n" 86 | 87 | void add_header(line *after) 88 | { 89 | nlab=new_label(); 90 | line *new; 91 | new=new_line(); 92 | new->flags=LABDEF; 93 | new->l1=nlab; 94 | new->code=mymalloc(16); /* TODO */ 95 | sprintf(new->code,"x%d:\n",nlab); 96 | insert_line(after,new); 97 | new=new_line(); 98 | new->flags=BARRIER; 99 | new->code=mymalloc(strlen(SECTION)+1); 100 | strcpy(new->code,SECTION); 101 | insert_line(after,new); 102 | } 103 | 104 | void add_ret(line *after) 105 | { 106 | line *new=new_line(); 107 | new->size=1; 108 | new->flags=BARRIER; 109 | new->code=mymalloc(8); /*TODO*/ 110 | strcpy(new->code,"\trts\n"); 111 | insert_line(after,new); 112 | } 113 | 114 | void add_jsr(line *after) 115 | { 116 | line *new=new_line(); 117 | new->flags=LABUSE; 118 | new->size=3; 119 | new->l1=nlab; 120 | new->code=mymalloc(24); /* TODO */ 121 | sprintf(new->code,"\tjsr\tx%d\n",nlab); 122 | insert_line(after,new); 123 | } 124 | -------------------------------------------------------------------------------- /machines/6502/machine.dt: -------------------------------------------------------------------------------- 1 | S8BS 2 | S8BU 3 | S16BSLE S16BSBE 4 | S16BULE S16BUBE 5 | S16BSLE S16BSBE 6 | S16BULE S16BUBE 7 | S32BSLE S32BSBE 8 | S32BULE S32BUBE 9 | S64BSLE S64BSBE 10 | S64BULE S64BUBE 11 | S32BIEEELE 12 | S64BIEEELE 13 | S64BIEEELE 14 | S16BULE S16BUBE 15 | 16 | 17 | -------------------------------------------------------------------------------- /machines/6502/machine.h: -------------------------------------------------------------------------------- 1 | /* 6502 backend for vbcc 2 | (c) Volker Barthelmann 2020 3 | 4 | */ 5 | 6 | /* buil-time configurable options: */ 7 | #define NUM_GPRS 32 8 | #define NUM_PAIRS (NUM_GPRS/2) 9 | #define NUM_BIG 4 10 | #define NUM_BIGP (NUM_BIG/2) 11 | #define FIXED_SP 1 12 | 13 | #include "dt.h" 14 | 15 | #undef CHAR 16 | #undef SHORT 17 | #undef INT 18 | #undef LONG 19 | #undef LLONG 20 | #undef FLOAT 21 | #undef DOUBLE 22 | #undef LDOUBLE 23 | #undef VOID 24 | #undef POINTER 25 | #undef ARRAY 26 | #undef STRUCT 27 | #undef UNION 28 | #undef ENUM 29 | #undef FUNKT 30 | #undef BOOL 31 | #undef MAXINT 32 | #undef MAX_TYPE 33 | 34 | #define CHAR 1 35 | #define SHORT 2 36 | #define INT 3 37 | #define LONG 4 38 | #define LLONG 5 39 | #define FLOAT 6 40 | #define DOUBLE 7 41 | #define LDOUBLE 8 42 | #define VOID 9 43 | #define POINTER 10 44 | #define FPOINTER 11 45 | #define HPOINTER 12 46 | #define ARRAY 13 47 | #define STRUCT 14 48 | #define UNION 15 49 | #define ENUM 16 50 | #define FUNKT 17 51 | #define BOOL 18 52 | 53 | #define MAXINT 19 54 | 55 | #define MAX_TYPE MAXINT 56 | 57 | 58 | #define POINTER_TYPE(x) pointer_type(x) 59 | #define POINTER_VARADR(x) pointer_varadr(x) 60 | extern int pointer_type(); 61 | extern int pointer_varadr(); 62 | #define ISPOINTER(x) ((x&NQ)>=POINTER&&(x&NQ)<=HPOINTER) 63 | #define ISSCALAR(x) ((x&NQ)>=CHAR&&(x&NQ)<=HPOINTER) 64 | #define ISINT(x) ((x&NQ)>=CHAR&&(x&NQ)<=LLONG) 65 | #define PTRDIFF_T(x) ((x)==HPOINTER?LONG:INT) 66 | 67 | typedef zllong zmax; 68 | typedef zullong zumax; 69 | 70 | union atyps{ 71 | zchar vchar; 72 | zuchar vuchar; 73 | zshort vshort; 74 | zushort vushort; 75 | zint vint; 76 | zuint vuint; 77 | zlong vlong; 78 | zulong vulong; 79 | zllong vllong; 80 | zullong vullong; 81 | zmax vmax; 82 | zumax vumax; 83 | zfloat vfloat; 84 | zdouble vdouble; 85 | zldouble vldouble; 86 | }; 87 | 88 | 89 | /* internally used by the backend */ 90 | #define FIRST_GPR 8 91 | #define LAST_GPR (FIRST_GPR+NUM_GPRS-1) 92 | #define FIRST_PAIR (LAST_GPR+1) 93 | #define LAST_PAIR (FIRST_PAIR+NUM_PAIRS-1) 94 | #define FIRST_BIG (LAST_PAIR+1) 95 | #define LAST_BIG (FIRST_BIG+NUM_BIG-1) 96 | #define FIRST_BIGP (LAST_BIG+1) 97 | #define LAST_BIGP (FIRST_BIGP+NUM_BIGP-1) 98 | 99 | /* This struct can be used to implement machine-specific */ 100 | /* addressing-modes. */ 101 | /* Currently possible are (const,gpr) and (gpr,gpr) */ 102 | struct AddressingMode{ 103 | int flags; 104 | int base; 105 | int idx; 106 | long offset; 107 | void *v; 108 | }; 109 | 110 | /* The number of registers of the target machine. */ 111 | #define MAXR LAST_BIGP 112 | 113 | /* Number of commandline-options the code-generator accepts. */ 114 | #define MAXGF 30 115 | 116 | /* If this is set to zero vbcc will not generate ICs where the */ 117 | /* target operand is the same as the 2nd source operand. */ 118 | /* This can sometimes simplify the code-generator, but usually */ 119 | /* the code is better if the code-generator allows it. */ 120 | #define USEQ2ASZ 1 121 | 122 | /* This specifies the smallest integer type that can be added to a */ 123 | /* pointer. */ 124 | #define MINADDI2P CHAR 125 | 126 | /* If the bytes of an integer are ordered most significant byte */ 127 | /* byte first and then decreasing set BIGENDIAN to 1. */ 128 | #define BIGENDIAN 0 129 | 130 | /* If the bytes of an integer are ordered lest significant byte */ 131 | /* byte first and then increasing set LITTLEENDIAN to 1. */ 132 | #define LITTLEENDIAN 1 133 | 134 | /* Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive. */ 135 | 136 | /* If switch-statements should be generated as a sequence of */ 137 | /* SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1. */ 138 | /* This can yield better code on some machines. */ 139 | #define SWITCHSUBS 0 140 | 141 | /* In optimizing compilation certain library memcpy/strcpy-calls */ 142 | /* with length known at compile-time will be inlined using an */ 143 | /* ASSIGN-IC if the size is less or equal to INLINEMEMCPY. */ 144 | /* The type used for the ASSIGN-IC will be UNSIGNED|CHAR. */ 145 | #define INLINEMEMCPY 1024 146 | 147 | /* Parameters are sometimes passed in registers without __reg. */ 148 | #define HAVE_REGPARMS 1 149 | 150 | /* Parameters on the stack should be pushed in order rather than */ 151 | /* in reverse order. */ 152 | #define ORDERED_PUSH FIXED_SP 153 | 154 | /* Structure for reg_parm(). */ 155 | struct reg_handle{ 156 | int regs; 157 | int bregs; 158 | }; 159 | 160 | /* We have some target-specific variable attributes. */ 161 | #define HAVE_TARGET_ATTRIBUTES 162 | 163 | /* We have target-specific pragmas */ 164 | #define HAVE_TARGET_PRAGMAS 165 | 166 | /* We keep track of all registers modified by a function. */ 167 | #define HAVE_REGS_MODIFIED 1 168 | 169 | /* We have a implement our own cost-functions to adapt 170 | register-allocation */ 171 | #define HAVE_TARGET_RALLOC 1 172 | #define cost_move_reg(x,y) 6 173 | #define cost_load_reg(x,y) 10 174 | #define cost_save_reg(x,y) 10 175 | #define cost_pushpop_reg(x) 12 176 | 177 | /* size of buffer for asm-output, this can be used to do 178 | peephole-optimizations of the generated assembly-output */ 179 | #define EMIT_BUF_LEN 1024 /* should be enough */ 180 | /* number of asm-output lines buffered */ 181 | #define EMIT_BUF_DEPTH 8 182 | 183 | /* We have no asm_peephole to optimize assembly-output */ 184 | #define HAVE_TARGET_PEEPHOLE 1 185 | 186 | /* we do not have a mark_eff_ics function, this is used to prevent 187 | optimizations on code which can already be implemented by efficient 188 | assembly */ 189 | #undef HAVE_TARGET_EFF_IC 190 | 191 | /* we have additional types */ 192 | #define HAVE_EXT_TYPES 193 | #define HAVE_TGT_PRINTVAL 194 | 195 | /* we do not need extra elements in the IC */ 196 | #undef HAVE_EXT_IC 197 | 198 | /* we do not use unsigned int as size_t (but unsigned long, the default) */ 199 | #define HAVE_INT_SIZET 1 200 | 201 | /* we do not need register-pairs */ 202 | #define HAVE_REGPAIRS 1 203 | 204 | 205 | /* do not create CONVERT ICs from integers smaller than int to floats */ 206 | #define MIN_INT_TO_FLOAT_TYPE INT 207 | 208 | /* do not create CONVERT ICs from floats to ints smaller than int */ 209 | #define MIN_FLOAT_TO_INT_TYPE INT 210 | 211 | /* do not create CONVERT_ICs from floats to unsigned integers */ 212 | #define AVOID_FLOAT_TO_UNSIGNED 0 213 | 214 | /* do not create CONVERT_ICs from unsigned integers to floats */ 215 | #define AVOID_UNSIGNED_TO_FLOAT 0 216 | 217 | /* convert multiplications/division by powers of two to shifts */ 218 | #define HAVE_POF2OPT 1 219 | 220 | /* We use builtin libcalls for some operations */ 221 | #define HAVE_LIBCALLS 1 222 | 223 | /* Use char for return of comparison libcalls */ 224 | #define LIBCALL_CMPTYPE CHAR 225 | 226 | /* We prefer BNE rather than BGT. */ 227 | #define HAVE_WANTBNE 1 228 | 229 | #define BESTCOPYT CHAR 230 | 231 | #define HAVE_AOS4 1 232 | 233 | #define CHARCONV(x) cbmconv(x) 234 | unsigned char cbmconv(unsigned char); 235 | 236 | #define ALLOCVLA_REG FIRST_PAIR 237 | #define ALLOCVLA_INLINEASM "\tlda\tsp\n"\ 238 | "\tsec\n"\ 239 | "\tsbc\tr0\n"\ 240 | "\tsta\tsp\n"\ 241 | "\tlda\tsp+1\n"\ 242 | "\tsbc\tr1\n"\ 243 | "\tsta\tsp+1\n"\ 244 | "\tlda\tsp\n"\ 245 | "\tclc\n"\ 246 | "\tldx\tsp+1\n"\ 247 | "\tadc\t#___fo\n"\ 248 | "\tbcc\t*+3\n"\ 249 | "\tinx\n" 250 | 251 | #define FREEVLA_REG FIRST_PAIR 252 | #define FREEVLA_INLINEASM "\tlda\tr0\n"\ 253 | "\tsta\tsp\n"\ 254 | "\tlda\tr1\n"\ 255 | "\tsta\tsp+1\n" 256 | 257 | #define OLDSPVLA_INLINEASM "\tlda\tsp+1\n"\ 258 | "\ttax\n"\ 259 | "\tlda\tsp" 260 | 261 | #define FPVLA_REG (LAST_PAIR-2) 262 | 263 | #define HAVE_TARGET_VARHOOK_POST 1 264 | 265 | #define HAVE_DECIDE_REVERSE 1 266 | 267 | #define HAVE_TARGET_EFF_IC 1 268 | -------------------------------------------------------------------------------- /machines/832/inlinememcpy.c: -------------------------------------------------------------------------------- 1 | /* FIXME - emit a memcpy function with weak linkage if -size is specified */ 2 | 3 | void emit_inlinememcpy(FILE *f,struct IC *p, int t) 4 | { 5 | int srctype=t; 6 | int srcr = t1; 7 | int dstr=0; 8 | int cntr=0; 9 | int savec=1; 10 | int saved=0; 11 | int wordcopy; 12 | int bytecopy; 13 | zmax copysize = opsize(p); 14 | int unrollwords=0; 15 | int unrollbytes=0; 16 | 17 | // Can we create larger code in the interests of speed? If so, partially unroll the copy. 18 | wordcopy = copysize & ~3; 19 | bytecopy = copysize - wordcopy; 20 | 21 | if (wordcopy < 32 && !optsize) 22 | unrollwords=1; 23 | if (bytecopy < 5) 24 | unrollbytes=1; 25 | 26 | cleartempobj(f,t1); 27 | cleartempobj(f,tmp); 28 | 29 | // Even if a register is available we still have to save it because the current function wouldn't 30 | // but the parent function may be using it. Therefore we might as well use a hardcoded register. 31 | dstr=t1+1; 32 | if(p->z.flags&(REG|DREFOBJ)==REG) 33 | dstr=p->z.reg; 34 | // FIXME - check this logic. If the target is a register, it may not be a scratch register. 35 | if(regs[dstr]) // Scratch register - only need to save if it's in use? 36 | { 37 | saved=1; 38 | emit(f,"\tmt\t%s\n",regnames[dstr]); 39 | emit(f,"\tstdec\t%s\n",regnames[sp]); 40 | pushed+=4; 41 | } 42 | 43 | cntr=t1+2; 44 | if(cntr==dstr) /* Use r1 instead of r2 if the dest pointer is in r2 already. */ 45 | cntr=t1+1; 46 | if(cntr==srcr) /* If cntr && srcr now clash, use r3 instead */ 47 | cntr=t1+3; 48 | 49 | if((unrollwords && unrollbytes) || regs[cntr]==0) 50 | savec=0; 51 | else { 52 | emit(f,"\tmt\t%s\n",regnames[cntr]); 53 | emit(f,"\tstdec\t%s\n",regnames[sp]); 54 | pushed+=4; 55 | } 56 | 57 | /* Prepare source register */ 58 | if ((t & NQ) == CHAR && (opsize(p) != 1)) { 59 | emit(f, "\t\t\t\t\t// (char with size!=1 -> array of unknown type)\n"); 60 | srctype = ARRAY; // FIXME - ugly hack 61 | } 62 | emit_objtoreg(f, &p->q1, srctype,srcr); 63 | 64 | /* Prepare destination register */ 65 | 66 | emit_prepobj(f, &p->z, t, dstr, 0); 67 | 68 | if (p->z.flags & REG) { 69 | if(p->z.reg!=dstr) {// Move target register to dstr 70 | emit(f, "\tmt\t%s\n", regnames[p->z.reg]); 71 | emit(f, "\tmr\t%s\n", regnames[dstr]); 72 | } 73 | } 74 | 75 | emit(f, "\t\t\t\t\t// Copying %d words and %d bytes to %s\n", wordcopy / 4, bytecopy, 76 | p->z.v ? p->z.v->identifier : "(null)"); 77 | // printf("memcpy: Copying %d words and %d bytes to %s\n", wordcopy / 4, bytecopy, 78 | // p->z.v ? p->z.v->identifier : "(null)"); 79 | 80 | // if(!p->z.v) 81 | // printf("No z->v: z flags: %x\n",p->z.flags); 82 | 83 | // Prepare the copy 84 | // FIXME - we don't necessarily have a valid z->v! If not, where does the target come from? 85 | // Stack based variable? 86 | 87 | if (unrollwords) { 88 | wordcopy >>= 2; 89 | if (wordcopy) { 90 | emit(f, "\t\t\t\t\t// Copying %d words to %s\n", wordcopy, p->z.v ? p->z.v->identifier : "(null)"); 91 | } 92 | while (wordcopy--) { 93 | emit(f, "\tldinc\t%s\n\tstinc\t%s\n", regnames[srcr], regnames[dstr]); 94 | } 95 | } else if(wordcopy) { 96 | emit(f, "\t\t\t\t\t// Copying %d words to %s\n", wordcopy / 4, p->z.v ? p->z.v->identifier : "(null)"); 97 | // Copy bytes... 98 | emit_constanttotemp(f, wordcopy); 99 | emit(f, "\taddt\t%s\n", regnames[dstr]); 100 | emit(f, "\tmr\t%s\n", regnames[cntr]); 101 | emit(f, ".cpy%swordloop%d:\n", p->z.v ? p->z.v->identifier : "null", loopid); 102 | emit(f, "\tldinc\t%s\n\tstinc\t%s\n", regnames[srcr], regnames[dstr]); 103 | emit(f, "\tmt\t%s\n\tcmp\t%s\n", regnames[dstr], regnames[cntr]); 104 | emit(f, "\tcond\tNEQ\n"); 105 | emit(f, "\t\t.lipcrel\t.cpy%swordloop%d\n", p->z.v ? p->z.v->identifier : "null", loopid); 106 | emit(f, "\t\tadd\t%s\n", regnames[pc]); 107 | } 108 | 109 | if (unrollbytes) { 110 | if (bytecopy) 111 | emit(f, "\t\t\t\t\t// Copying %d byte tail to %s\n", bytecopy,p->z.v ? p->z.v->identifier : "null"); 112 | while (bytecopy--) 113 | emit(f, "\tldbinc\t%s\n\tstbinc\t%s\n", regnames[srcr], regnames[dstr]); 114 | } else if (bytecopy) { 115 | emit(f, "\t\t\t\t\t// Copying %d bytes to %s\n", bytecopy, p->z.v ? p->z.v->identifier : "null"); 116 | // Copy bytes... 117 | emit_constanttotemp(f, bytecopy); 118 | emit(f, "\taddt\t%s\n", regnames[dstr]); 119 | emit(f, "\tmr\t%s\n", regnames[cntr]); 120 | emit(f, ".cpy%sloop%d:\n", p->z.v ? p->z.v->identifier : "null", loopid); 121 | emit(f, "\tldbinc\t%s\n\tstbinc\t%s\n", regnames[srcr], regnames[dstr]); 122 | emit(f, "\tmt\t%s\n\tcmp\t%s\n", regnames[dstr], regnames[cntr]); 123 | emit(f, "\tcond\tNEQ\n"); 124 | emit(f, "\t\t.lipcrel\t.cpy%sloop%d\n", p->z.v ? p->z.v->identifier : "null", loopid); 125 | emit(f, "\t\tadd\t%s\n", regnames[pc]); 126 | 127 | } 128 | // cleanup 129 | if(savec) { 130 | emit(f,"\tldinc\t%s\n",regnames[sp]); 131 | emit(f,"\tmr\t%s\n",regnames[cntr]); 132 | pushed-=4; 133 | } 134 | if(saved) { 135 | emit(f,"\tldinc\t%s\n",regnames[sp]); 136 | emit(f,"\tmr\t%s\n",regnames[dstr]); 137 | pushed-=4; 138 | } 139 | cleartempobj(f,t1); 140 | cleartempobj(f,tmp); 141 | loopid++; 142 | } 143 | 144 | 145 | /* Similar to inlinememcpy, but copies an array or struct to the stack */ 146 | 147 | void emit_inlinepush(FILE *f,struct IC *p, int t) 148 | { 149 | int srcr = t1; 150 | int dstr=0; 151 | int cntr=0; 152 | int savec=1; 153 | int saved=0; 154 | int wordcopy; 155 | int bytecopy; 156 | zmax copysize = opsize(p); 157 | int unrollwords=0; 158 | int unrollbytes=0; 159 | 160 | // Can we create larger code in the interests of speed? If so, partially unroll the copy. 161 | wordcopy = copysize & ~3; 162 | bytecopy = copysize - wordcopy; 163 | 164 | if ((wordcopy < 32 && !optsize) || (wordcopy<16)) 165 | unrollwords=1; 166 | if (bytecopy < 5) 167 | unrollbytes=1; 168 | 169 | cleartempobj(f,t1); 170 | cleartempobj(f,tmp); 171 | 172 | // Even if a register is available we still have to save it because the current function wouldn't 173 | // but the parent function may be using it. Therefore we might as well use a hardcoded register. 174 | dstr=sp; 175 | 176 | // FIXME - don't necessarily need the counter register if the copy is small... 177 | 178 | /* Is our source a register? If so, set srcr accordingly */ 179 | if (p->q1.flags & REG) { 180 | srcr=p->q1.reg; 181 | cntr=t1; 182 | } else 183 | cntr=t1+2; 184 | 185 | if((unrollwords && unrollbytes) || regs[cntr]==0) 186 | savec=0; 187 | else { 188 | emit(f,"\tmt\t%s\n",regnames[cntr]); 189 | emit(f,"\tstdec\t%s\n",regnames[sp]); 190 | pushed+=4; 191 | } 192 | 193 | emit(f, "\t\t\t\t\t// Copying %d words and %d bytes to stack\n", wordcopy / 4, bytecopy); 194 | 195 | // if(!p->z.v) 196 | // printf("No z->v: z flags: %x\n",p->z.flags); 197 | 198 | // Prepare the copy 199 | emit_prepobj(f, &p->q1, t,srcr,0); 200 | 201 | // Make room on the stack for the copied object 202 | 203 | emit(f,"\t.liconst\t%d\n",pushsize(p)); 204 | emit(f,"\tsub\t%s\n",regnames[sp]); 205 | 206 | if (unrollwords) { 207 | wordcopy >>= 2; 208 | if (wordcopy) { 209 | emit(f, "\t\t\t\t\t// Copying %d words to stack\n", wordcopy); 210 | } 211 | while (wordcopy--) { 212 | emit(f, "\tldinc\t%s\n\tstinc\t%s\n", regnames[srcr], regnames[dstr]); 213 | } 214 | } else { 215 | emit(f, "\t\t\t\t\t// Copying %d words to stack\n", wordcopy / 4); 216 | // Copy bytes... 217 | emit_constanttotemp(f, wordcopy); 218 | emit(f, "\taddt\t%s\n", regnames[dstr]); 219 | emit(f, "\tmr\t%s\n", regnames[cntr]); 220 | emit(f, ".cpystackwordloop%d:\n", loopid); 221 | emit(f, "\tldinc\t%s\n\tstinc\t%s\n", regnames[srcr], regnames[dstr]); 222 | emit(f, "\tmt\t%s\n\tcmp\t%s\n", regnames[dstr], regnames[cntr]); 223 | emit(f, "\tcond\tNEQ\n"); 224 | emit(f, "\t\t.lipcrel\t.cpystackwordloop%d\n", loopid); 225 | emit(f, "\t\tadd\t%s\n", regnames[pc]); 226 | } 227 | 228 | if (unrollbytes) { 229 | if (bytecopy) 230 | emit(f, "\t\t\t\t\t// Copying %d byte tail to stack\n", bytecopy); 231 | while (bytecopy--) 232 | emit(f, "\tldbinc\t%s\n\tstbinc\t%s\n", regnames[srcr], regnames[dstr]); 233 | } else { 234 | emit(f, "\t\t\t\t\t// Copying %d bytes to stack\n", bytecopy); 235 | // Copy bytes... 236 | emit_constanttotemp(f, bytecopy); 237 | emit(f, "\taddt\t%s\n", regnames[dstr]); 238 | emit(f, "\tmr\t%s\n", regnames[cntr]); 239 | emit(f, ".cpystackloop%d:\n", loopid); 240 | emit(f, "\tldbinc\t%s\n\tstbinc\t%s\n", regnames[srcr], regnames[dstr]); 241 | emit(f, "\tmt\t%s\n\tcmp\t%s\n", regnames[dstr], regnames[cntr]); 242 | emit(f, "\tcond\tNEQ\n"); 243 | emit(f, "\t\t.lipcrel\t.cpystackloop%d\n", loopid); 244 | emit(f, "\t\tadd\t%s\n", regnames[pc]); 245 | 246 | } 247 | // cleanup 248 | 249 | // Reset the stack pointer since we've been blithely post-incrementing it. 250 | emit(f,"\t.liconst\t%d\n",opsize(p)); 251 | emit(f,"\tsub\t%s\n",regnames[sp]); 252 | 253 | if(savec) { 254 | emit(f,"\tldinc\t%s\n",regnames[sp]); 255 | emit(f,"\tmr\t%s\n",regnames[cntr]); 256 | pushed-=4; 257 | } 258 | cleartempobj(f,t1); 259 | cleartempobj(f,tmp); 260 | loopid++; 261 | } 262 | 263 | -------------------------------------------------------------------------------- /machines/832/machine.dt: -------------------------------------------------------------------------------- 1 | S8BS 2 | S8BU 3 | S16BSBE S16BSLE 4 | S16BUBE S16BULE 5 | S32BSBE S32BSLE 6 | S32BUBE S32BULE 7 | S32BSBE S32BSLE 8 | S32BUBE S32BULE 9 | S64BSBE S64BSLE 10 | S64BUBE S64BULE 11 | S32BIEEEBE 12 | S64BIEEEBE 13 | S64BIEEEBE 14 | S32BUBE S32BULE 15 | 16 | 17 | -------------------------------------------------------------------------------- /machines/832/machine.h: -------------------------------------------------------------------------------- 1 | /* EightThirtyTwo backend for vbcc. 2 | Based on the "generic" backend. 3 | */ 4 | 5 | /* build-time configurable options: */ 6 | #define NUM_GPRS 9 7 | #define SCRATCH_GPRS 2 8 | #define NUM_FPRS 0 9 | #define NUM_CCRS 0 10 | #define FIXED_SP 0 11 | 12 | #include "dt.h" 13 | 14 | /* internally used by the backend */ 15 | #define FIRST_GPR 1 16 | #define LAST_GPR (FIRST_GPR+NUM_GPRS-1) 17 | #define FIRST_FPR (LAST_GPR+1) 18 | #define LAST_FPR (FIRST_FPR+NUM_FPRS-1) 19 | #define RESERVED_GPRS 1 20 | 21 | /* This struct can be used to implement machine-specific */ 22 | /* addressing-modes. */ 23 | /* Currently possible are (const,gpr) and (gpr,gpr) */ 24 | /* FIXME - we can make use of ldidx here */ 25 | enum AddressingMode_Type { AM_POSTINC=1, AM_PREDEC, AM_ADDT }; 26 | struct AddressingMode{ 27 | enum AddressingMode_Type type; 28 | int disposable; 29 | int deferredpop; 30 | }; 31 | 32 | /* The number of registers of the target machine. */ 33 | #define MAXR NUM_GPRS+NUM_FPRS+NUM_CCRS 34 | 35 | /* Number of commandline-options the code-generator accepts. */ 36 | #define MAXGF 1 37 | 38 | /* If this is set to zero vbcc will not generate ICs where the */ 39 | /* target operand is the same as the 2nd source operand. */ 40 | /* This can sometimes simplify the code-generator, but usually */ 41 | /* the code is better if the code-generator allows it. */ 42 | #define USEQ2ASZ 1 43 | 44 | /* This specifies the smallest integer type that can be added to a */ 45 | /* pointer. */ 46 | #define MINADDI2P INT 47 | 48 | /* If the bytes of an integer are ordered most significant byte */ 49 | /* byte first and then decreasing set BIGENDIAN to 1. */ 50 | #define BIGENDIAN 0 51 | 52 | /* If the bytes of an integer are ordered lest significant byte */ 53 | /* byte first and then increasing set LITTLEENDIAN to 1. */ 54 | #define LITTLEENDIAN 1 55 | 56 | /* Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive. */ 57 | 58 | /* If switch-statements should be generated as a sequence of */ 59 | /* SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1. */ 60 | /* This can yield better code on some machines. */ 61 | #define SWITCHSUBS 1 62 | 63 | /* In optimizing compilation certain library memcpy/strcpy-calls */ 64 | /* with length known at compile-time will be inlined using an */ 65 | /* ASSIGN-IC if the size is less or equal to INLINEMEMCPY. */ 66 | /* The type used for the ASSIGN-IC will be UNSIGNED|CHAR. */ 67 | #define INLINEMEMCPY 1024 68 | 69 | /* Parameters are sometimes passed in registers without __reg. */ 70 | #define HAVE_REGPARMS 1 71 | #define REGPARM_COUNT 1 72 | 73 | /* Parameters on the stack should be pushed in order rather than */ 74 | /* in reverse order. */ 75 | // #define ORDERED_PUSH 1 76 | // FIXED_SP 77 | 78 | /* Structure for reg_parm(). */ 79 | struct reg_handle{ 80 | unsigned long gregs; 81 | unsigned long fregs; 82 | }; 83 | 84 | /* We have some target-specific variable attributes. */ 85 | #define HAVE_TARGET_ATTRIBUTES 86 | 87 | /* We have target-specific pragmas */ 88 | #define HAVE_TARGET_PRAGMAS 89 | 90 | /* We keep track of all registers modified by a function. */ 91 | #define HAVE_REGS_MODIFIED 1 92 | 93 | /* We have implemented our own cost-functions to adapt 94 | register-allocation */ 95 | #define HAVE_TARGET_RALLOC 1 96 | #define cost_move_reg(x,y) 1 97 | #define cost_load_reg(x,y) 5 98 | #define cost_save_reg(x,y) 5 99 | #define cost_pushpop_reg(x) 1 100 | 101 | /* size of buffer for asm-output, this can be used to do 102 | peephole-optimizations of the generated assembly-output */ 103 | #define EMIT_BUF_LEN 1024 /* should be enough */ 104 | /* number of asm-output lines buffered */ 105 | #define EMIT_BUF_DEPTH 16 106 | 107 | /* We have no asm_peephole to optimize assembly-output */ 108 | #define HAVE_TARGET_PEEPHOLE 1 109 | 110 | /* we do not have a mark_eff_ics function, this is used to prevent 111 | optimizations on code which can already be implemented by efficient 112 | assembly */ 113 | #undef HAVE_TARGET_EFF_IC 114 | 115 | /* we only need the standard data types (no bit-types, different pointers 116 | etc.) */ 117 | #undef HAVE_EXT_TYPES 118 | #undef HAVE_TGT_PRINTVAL 119 | 120 | /* we do not need extra elements in the IC */ 121 | #undef HAVE_EXT_IC 122 | 123 | /* we use unsigned int as size_t (but unsigned long, the default) */ 124 | #define HAVE_INT_SIZET 1 125 | 126 | /* we do not need register-pairs */ 127 | #undef HAVE_REGPAIRS 128 | 129 | /* We (will eventually) use libcalls for 64-bit and float support */ 130 | /* Enabling this completely changes code generation - investigate. */ 131 | #define HAVE_LIBCALLS 0 132 | 133 | /* do not create CONVERT ICs from integers smaller than int to floats */ 134 | #define MIN_INT_TO_FLOAT_TYPE INT 135 | 136 | /* do not create CONVERT ICs from floats to ints smaller than int */ 137 | #define MIN_FLOAT_TO_INT_TYPE INT 138 | 139 | /* do not create CONVERT_ICs from floats to unsigned integers */ 140 | #define AVOID_FLOAT_TO_UNSIGNED 1 141 | 142 | /* do not create CONVERT_ICs from unsigned integers to floats */ 143 | #define AVOID_UNSIGNED_TO_FLOAT 1 144 | -------------------------------------------------------------------------------- /machines/alpha/machine.dt: -------------------------------------------------------------------------------- 1 | S8BS 2 | S8BU 3 | S16BSLE S16BSBE 4 | S16BULE S16BUBE 5 | S32BSLE S32BSBE 6 | S32BULE S32BUBE 7 | S64BSLE S64BSBE 8 | S64BULE S64BUBE 9 | S64BSLE S64BSBE 10 | S64BULE S64BUBE 11 | S32BIEEELE 12 | S64BIEEELE 13 | S64BIEEELE 14 | S64BULE S64BUBE 15 | 16 | 17 | -------------------------------------------------------------------------------- /machines/alpha/machine.h: -------------------------------------------------------------------------------- 1 | /* Example of a code-generator for a DEC Alpha */ 2 | 3 | #include "dt.h" 4 | 5 | /* This struct can be used to implement machine-specific */ 6 | /* addressing-modes. */ 7 | /* Not used in this code-generrator. */ 8 | struct AddressingMode{ 9 | int flags; 10 | int base; 11 | int align; 12 | long offset; 13 | }; 14 | 15 | /* The number of registers of the target machine. */ 16 | #define MAXR 64 17 | 18 | /* Number of commandline-options the code-generator accepts. */ 19 | #define MAXGF 10 20 | 21 | /* If this is set to zero vbcc will not generate ICs where the */ 22 | /* target operand is the same as the 2nd source operand. */ 23 | /* This can sometimes simplify the code-generator, but usually */ 24 | /* the code is better if the code-generator allows it. */ 25 | #define USEQ2ASZ 1 26 | 27 | /* This specifies the smallest integer type that can be added to a */ 28 | /* pointer. */ 29 | #define MINADDI2P LONG 30 | 31 | /* If the bytes of an integer are ordered most significant byte */ 32 | /* byte first and then decreasing set BIGENDIAN to 1. */ 33 | #define BIGENDIAN 0 34 | 35 | /* If the bytes of an integer are ordered lest significant byte */ 36 | /* byte first and then increasing set LITTLEENDIAN to 1. */ 37 | #define LITTLEENDIAN 1 38 | 39 | /* Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive. */ 40 | 41 | /* If switch-statements should be generated as a sequence of */ 42 | /* SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1. */ 43 | /* This can yield better code on some machines. */ 44 | #define SWITCHSUBS 1 45 | 46 | /* In optimizing compilation certain library memcpy/strcpy-calls */ 47 | /* with length known at compile-time will be inlined using an */ 48 | /* ASSIGN-IC if the size is less or equal to INLINEMEMCPY. */ 49 | /* The type used for the ASSIGN-IC will be UNSIGNED|CHAR. */ 50 | #define INLINEMEMCPY 1024 51 | 52 | /* Parameters are sometimes passed in registers without __reg. */ 53 | #define HAVE_REGPARMS 1 54 | 55 | /* Parameters on the stack should be pushed in order rather than */ 56 | /* in reverse order. */ 57 | #define ORDERED_PUSH 1 58 | 59 | /* Structure for reg_parm(). */ 60 | struct reg_handle{ 61 | int nextr; 62 | }; 63 | 64 | /* size of buffer for asm-output */ 65 | #define EMIT_BUF_LEN 1024 /* should be enough */ 66 | /* number of asm-output lines buffered */ 67 | #define EMIT_BUF_DEPTH 4 68 | 69 | /* We have no asm_peephole to optimize assembly-output */ 70 | #define HAVE_TARGET_PEEPHOLE 0 71 | -------------------------------------------------------------------------------- /machines/alpha/schedule.c: -------------------------------------------------------------------------------- 1 | #include "vsc.h" 2 | 3 | char tg_copyright[]="Alpha scheduler V0.0 (c) in 1997 by Volker Barthelmann"; 4 | 5 | int sched_init(void) 6 | { 7 | return 1; 8 | } 9 | void sched_cleanup(void) 10 | { 11 | } 12 | int sched_info(struct sinfo *p) 13 | { 14 | char buf[20];int q1,q2,z,i; 15 | if(sscanf(p->txt,"$C%d:",&i)==1){ 16 | p->label=i; 17 | p->flags=LABEL; 18 | return 1; 19 | } 20 | /* lda $r1,imm($r2) */ 21 | if(sscanf(p->txt,"lda $%d,%d($%d)",&z,&i,&q1)==3){ 22 | p->latency=1; 23 | BSET(p->pipes,0); 24 | BSET(p->pipes,1); 25 | BSET(p->uses,q1); 26 | BSET(p->modifies,z); 27 | return 1; 28 | } 29 | /* lda $r1,... */ 30 | if(sscanf(p->txt,"lda $%d,",&z)==1){ 31 | BSET(p->pipes,0); 32 | BSET(p->pipes,1); 33 | BSET(p->modifies,z); 34 | return 1; 35 | } 36 | /* op $r1,$r2,$r3 */ 37 | if(sscanf(p->txt,"%19s $%d,$%d,$%d",buf,&q1,&q2,&z)==4){ 38 | p->latency=1; 39 | BSET(p->pipes,0); 40 | BSET(p->pipes,1); 41 | BSET(p->uses,q1); 42 | BSET(p->uses,q2); 43 | BSET(p->modifies,z); 44 | return 1; 45 | } 46 | /* op $r1,$r2 */ 47 | if(sscanf(p->txt,"%19s $%d,$%d",buf,&q1,&z)==3){ 48 | p->latency=1; 49 | BSET(p->pipes,0); 50 | BSET(p->pipes,1); 51 | BSET(p->uses,q1); 52 | BSET(p->modifies,z); 53 | return 1; 54 | } 55 | /* op $r1,imm,$r2 */ 56 | if(sscanf(p->txt,"%19s $%d,%d,$%d",buf,&q1,&i,&z)==4){ 57 | p->latency=1; 58 | BSET(p->pipes,0); 59 | BSET(p->pipes,1); 60 | BSET(p->uses,q1); 61 | BSET(p->modifies,z); 62 | return 1; 63 | } 64 | /* op $fr1,$fr2,$fr3 */ 65 | if(sscanf(p->txt,"%19s $f%d,$f%d,$f%d",buf,&q1,&q2,&z)==4){ 66 | p->latency=1; 67 | BSET(p->pipes,2); 68 | BSET(p->pipes,3); 69 | BSET(p->uses,q1+32); 70 | BSET(p->uses,q2+32); 71 | BSET(p->modifies,z+32); 72 | return 1; 73 | } 74 | /* load/store $r1,c($r2) */ 75 | if(sscanf(p->txt,"%19s $%d,%d($%d)",buf,&z,&i,&q1)==4){ 76 | p->latency=3; 77 | BSET(p->pipes,0); 78 | BSET(p->uses,q1); 79 | if(*buf=='l'){ 80 | BSET(p->pipes,1); 81 | BSET(p->modifies,z); 82 | BSET(p->uses,MEM); 83 | }else{ 84 | BSET(p->uses,z); 85 | BSET(p->modifies,MEM); 86 | } 87 | return 1; 88 | } 89 | /* load/store $fr1,c($r2) */ 90 | if(sscanf(p->txt,"%19s $f%d,%d($%d)",buf,&z,&i,&q1)==4){ 91 | p->latency=3; 92 | BSET(p->pipes,0); 93 | BSET(p->uses,q1); 94 | if(*buf=='l'){ 95 | BSET(p->pipes,1); 96 | BSET(p->modifies,z+32); 97 | BSET(p->uses,MEM); 98 | }else{ 99 | BSET(p->uses,z+32); 100 | BSET(p->modifies,MEM); 101 | } 102 | return 1; 103 | } 104 | p->flags=BARRIER; 105 | return 1; 106 | } 107 | -------------------------------------------------------------------------------- /machines/alpha/schedule.h: -------------------------------------------------------------------------------- 1 | 2 | #define PIPES 4 3 | #define REGS 64 4 | 5 | -------------------------------------------------------------------------------- /machines/bi386/machine.dt: -------------------------------------------------------------------------------- 1 | S8BS 2 | S8BU 3 | S16BSBE S16BSLE 4 | S16BUBE S16BULE 5 | S32BSBE S32BSLE 6 | S32BUBE S32BULE 7 | S32BSBE S32BSLE 8 | S32BUBE S32BULE 9 | S32BIEEEBE 10 | S64BIEEEBE 11 | S32BUBE S32BULE 12 | 13 | 14 | -------------------------------------------------------------------------------- /machines/bi386/machine.h: -------------------------------------------------------------------------------- 1 | /* Example of a code-generator for an Intel 386 or higher. */ 2 | 3 | #include "dt.h" 4 | 5 | #define BEI386 6 | 7 | /* This struct can be used to implement machine-specific */ 8 | /* addressing-modes. */ 9 | /* Not used in this code-generrator. */ 10 | struct AddressingMode{ 11 | int never_used; 12 | }; 13 | 14 | /* The number of registers of the target machine. */ 15 | #define MAXR 16 16 | 17 | /* Number of commandline-options the code-generator accepts. */ 18 | #define MAXGF 10 19 | 20 | /* If this is set to zero vbcc will not generate ICs where the */ 21 | /* target operand is the same as the 2nd source operand. */ 22 | /* This can sometimes simplify the code-generator, but usually */ 23 | /* the code is better if the code-generator allows it. */ 24 | #define USEQ2ASZ 0 25 | 26 | /* This specifies the smallest integer type that can be added to a */ 27 | /* pointer. */ 28 | #define MINADDI2P INT 29 | 30 | /* If the bytes of an integer are ordered most significant byte */ 31 | /* byte first and then decreasing set BIGENDIAN to 1. */ 32 | #ifdef BEI386 33 | #define BIGENDIAN 1 34 | #else 35 | #define BIGENDIAN 0 36 | #endif 37 | 38 | /* If the bytes of an integer are ordered lest significant byte */ 39 | /* byte first and then increasing set LITTLEENDIAN to 1. */ 40 | #ifdef BEI386 41 | #define LITTLEENDIAN 0 42 | #else 43 | #define LITTLEENDIAN 1 44 | #endif 45 | 46 | /* Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive. */ 47 | 48 | /* If switch-statements should be generated as a sequence of */ 49 | /* SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1. */ 50 | /* This can yield better code on some machines. */ 51 | #define SWITCHSUBS 0 52 | 53 | /* In optimizing compilation certain library memcpy/strcpy-calls */ 54 | /* with length known at compile-time will be inlined using an */ 55 | /* ASSIGN-IC if the size is less or equal to INLINEMEMCPY. */ 56 | /* The type used for the ASSIGN-IC will be UNSIGNED|CHAR. */ 57 | #define INLINEMEMCPY 1024 58 | 59 | 60 | -------------------------------------------------------------------------------- /machines/c16x/machine.dt: -------------------------------------------------------------------------------- 1 | S8BS 2 | S8BU 3 | S16BSLE S16BSBE 4 | S16BULE S16BUBE 5 | S16BSLE S16BSBE 6 | S16BULE S16BUBE 7 | S32BSLE S32BSBE 8 | S32BULE S32BUBE 9 | S64BSLE S64BSBE 10 | S64BULE S64BUBE 11 | S32BIEEELE 12 | S64BIEEELE 13 | S64BIEEELE 14 | S16BULE S16BUBE 15 | 16 | 17 | -------------------------------------------------------------------------------- /machines/c16x/machine.h: -------------------------------------------------------------------------------- 1 | /* Example of a code-generator for SAB c16x 16bit microcontrollers.*/ 2 | 3 | #include "dt.h" 4 | 5 | /* We have extended types! What we have to do to support them: */ 6 | /* - #define HAVE_EXT_TYPES 7 | - #undef all standard types 8 | - #define all standard types plus new types 9 | - write eval_const and insert_const 10 | - write typedefs for zmax and zumax 11 | - write typname[] 12 | - write conv_typ() 13 | - optionally #define ISPOINTER, ISARITH, ISINT etc. 14 | - optionally #define HAVE_TGT_PRINTVAL and write printval 15 | - optionally #define POINTER_TYPE 16 | - optionally #define HAVE_TGT_FALIGN and write falign 17 | - optionally #define HAVE_TGT_SZOF and write szof 18 | - optionally add functions for attribute-handling 19 | */ 20 | #define HAVE_EXT_TYPES 1 21 | 22 | #define HAVE_TGT_PRINTVAL 23 | 24 | #undef CHAR 25 | #undef SHORT 26 | #undef INT 27 | #undef LONG 28 | #undef LLONG 29 | #undef FLOAT 30 | #undef DOUBLE 31 | #undef LDOUBLE 32 | #undef VOID 33 | #undef POINTER 34 | #undef ARRAY 35 | #undef STRUCT 36 | #undef UNION 37 | #undef ENUM 38 | #undef FUNKT 39 | #undef BOOL 40 | #undef MAXINT 41 | #undef MAX_TYPE 42 | 43 | #define BIT 1 44 | #define CHAR 2 45 | #define SHORT 3 46 | #define INT 4 47 | #define LONG 5 48 | #define LLONG 6 49 | #define FLOAT 7 50 | #define DOUBLE 8 51 | #define LDOUBLE 9 52 | #define VOID 10 53 | #define NPOINTER 11 54 | #define FPOINTER 12 55 | #define HPOINTER 13 56 | #define ARRAY 14 57 | #define STRUCT 15 58 | #define UNION 16 59 | #define ENUM 17 60 | #define FUNKT 18 61 | #define BOOL 19 62 | 63 | #define MAXINT 20 64 | 65 | #define MAX_TYPE MAXINT 66 | 67 | #define POINTER_TYPE(x) pointer_type(x) 68 | extern int pointer_type(); 69 | #define ISPOINTER(x) ((x&NQ)>=NPOINTER&&(x&NQ)<=HPOINTER) 70 | #define ISSCALAR(x) ((x&NQ)>=BIT&&(x&NQ)<=HPOINTER) 71 | #define ISINT(x) ((x&NQ)>=BIT&&(x&NQ)<=LLONG) 72 | #define PTRDIFF_T(x) ((x)==HPOINTER?LONG:INT) 73 | 74 | typedef zllong zmax; 75 | typedef zullong zumax; 76 | 77 | union atyps{ 78 | zchar vchar; 79 | zuchar vuchar; 80 | zshort vshort; 81 | zushort vushort; 82 | zint vint; 83 | zuint vuint; 84 | zlong vlong; 85 | zulong vulong; 86 | zllong vllong; 87 | zullong vullong; 88 | zmax vmax; 89 | zumax vumax; 90 | zfloat vfloat; 91 | zdouble vdouble; 92 | zldouble vldouble; 93 | }; 94 | 95 | /* This struct can be used to implement machine-specific */ 96 | /* addressing-modes. */ 97 | /* Not used in this code-generrator. */ 98 | struct AddressingMode{ 99 | int flags; 100 | int base; 101 | long offset; 102 | struct Var *v; 103 | }; 104 | 105 | /* This type will be added to every IC. Can be used by the cg. */ 106 | #define HAVE_EXT_IC 1 107 | struct ext_ic { 108 | int flags; 109 | int r; 110 | long offset; 111 | }; 112 | 113 | /* The number of registers of the target machine. */ 114 | #define MAXR 25 115 | 116 | /* Number of commandline-options the code-generator accepts. */ 117 | #define MAXGF 10 118 | 119 | /* If this is set to zero vbcc will not generate ICs where the */ 120 | /* target operand is the same as the 2nd source operand. */ 121 | /* This can sometimes simplify the code-generator, but usually */ 122 | /* the code is better if the code-generator allows it. */ 123 | #define USEQ2ASZ 1 124 | 125 | /* This specifies the smallest integer type that can be added to a */ 126 | /* pointer. */ 127 | #define MINADDI2P INT 128 | 129 | /* If the bytes of an integer are ordered most significant byte */ 130 | /* byte first and then decreasing set BIGENDIAN to 1. */ 131 | #define BIGENDIAN 0 132 | 133 | /* If the bytes of an integer are ordered lest significant byte */ 134 | /* byte first and then increasing set LITTLEENDIAN to 1. */ 135 | #define LITTLEENDIAN 1 136 | 137 | /* Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive. */ 138 | 139 | /* If switch-statements should be generated as a sequence of */ 140 | /* SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1. */ 141 | /* This can yield better code on some machines. */ 142 | #define SWITCHSUBS 0 143 | 144 | /* In optimizing compilation certain library memcpy/strcpy-calls */ 145 | /* with length known at compile-time will be inlined using an */ 146 | /* ASSIGN-IC if the size is less or equal to INLINEMEMCPY. */ 147 | /* The type used for the ASSIGN-IC will be UNSIGNED|CHAR. */ 148 | #define INLINEMEMCPY 1024 149 | 150 | #define HAVE_REGPARMS 1 151 | 152 | struct reg_handle { 153 | int gpr; 154 | }; 155 | 156 | /* We use unsigned int as size_t rather than unsigned long which */ 157 | /* is the default setting. */ 158 | #define HAVE_INT_SIZET 1 159 | 160 | /* We have register pairs. */ 161 | #define HAVE_REGPAIRS 1 162 | 163 | /* We keep track of all registers modified by a function. */ 164 | #define HAVE_REGS_MODIFIED 1 165 | 166 | #define HAVE_TARGET_RALLOC 1 167 | #define cost_load_reg(r,v) 4 168 | #define cost_save_reg(r,v) 4 169 | #define cost_move_reg(i,j) 2 170 | #define cost_pushpop_reg(r) 2 171 | 172 | /* size of buffer for asm-output */ 173 | #define EMIT_BUF_LEN 1024 /* should be enough */ 174 | /* number of asm-output lines buffered */ 175 | #define EMIT_BUF_DEPTH 4 176 | 177 | /* We have asm_peephole to optimize assembly-output */ 178 | #define HAVE_TARGET_PEEPHOLE 1 179 | 180 | /* We have some target-specific variable attributes. */ 181 | #define HAVE_TARGET_ATTRIBUTES 1 182 | 183 | /* We use builtin libcalls for some operations */ 184 | #define HAVE_LIBCALLS 1 185 | -------------------------------------------------------------------------------- /machines/generic/machine.dt: -------------------------------------------------------------------------------- 1 | S8BS 2 | S8BU 3 | S16BSBE S16BSLE 4 | S16BUBE S16BULE 5 | S32BSBE S32BSLE 6 | S32BUBE S32BULE 7 | S32BSBE S32BSLE 8 | S32BUBE S32BULE 9 | S64BSBE S64BSLE 10 | S64BUBE S64BULE 11 | S32BIEEEBE 12 | S64BIEEEBE 13 | S64BIEEEBE 14 | S32BUBE S32BULE 15 | 16 | 17 | -------------------------------------------------------------------------------- /machines/generic/machine.h: -------------------------------------------------------------------------------- 1 | /* Example backend for vbcc, it models a generic 32bit RISC or CISC 2 | CPU. 3 | 4 | Configurable at build-time are: 5 | - number of (32bit) general-purpose-registers 6 | - number of (64bit) floating-point-registers 7 | - number of (8bit) condition-code-registers 8 | - mechanism for stack-arguments (moving ot fixed sp) 9 | 10 | It allows to select as run-time-options: 11 | - two- or three-address code 12 | - memory operands or load-store-architecture 13 | - number of register-arguments 14 | - number of caller-save-registers 15 | */ 16 | 17 | /* buil-time configurable options: */ 18 | #define NUM_GPRS 32 19 | #define NUM_FPRS 32 20 | #define NUM_CCRS 8 21 | #define FIXED_SP 1 22 | 23 | #include "dt.h" 24 | 25 | /* internally used by the backend */ 26 | #define FIRST_GPR 1 27 | #define LAST_GPR (FIRST_GPR+NUM_GPRS-1) 28 | #define FIRST_FPR (LAST_GPR+1) 29 | #define LAST_FPR (FIRST_FPR+NUM_FPRS-1) 30 | #define FIRST_CCR (LAST_FPR+1) 31 | #define LAST_CCR (FIRST_CCR+NUM_CCRS-1) 32 | 33 | /* This struct can be used to implement machine-specific */ 34 | /* addressing-modes. */ 35 | /* Currently possible are (const,gpr) and (gpr,gpr) */ 36 | struct AddressingMode{ 37 | int flags; 38 | int base; 39 | long offset; 40 | }; 41 | 42 | /* The number of registers of the target machine. */ 43 | #define MAXR NUM_GPRS+NUM_FPRS+NUM_CCRS 44 | 45 | /* Number of commandline-options the code-generator accepts. */ 46 | #define MAXGF 20 47 | 48 | /* If this is set to zero vbcc will not generate ICs where the */ 49 | /* target operand is the same as the 2nd source operand. */ 50 | /* This can sometimes simplify the code-generator, but usually */ 51 | /* the code is better if the code-generator allows it. */ 52 | #define USEQ2ASZ 1 53 | 54 | /* This specifies the smallest integer type that can be added to a */ 55 | /* pointer. */ 56 | #define MINADDI2P INT 57 | 58 | /* If the bytes of an integer are ordered most significant byte */ 59 | /* byte first and then decreasing set BIGENDIAN to 1. */ 60 | #define BIGENDIAN 1 61 | 62 | /* If the bytes of an integer are ordered lest significant byte */ 63 | /* byte first and then increasing set LITTLEENDIAN to 1. */ 64 | #define LITTLEENDIAN 0 65 | 66 | /* Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive. */ 67 | 68 | /* If switch-statements should be generated as a sequence of */ 69 | /* SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1. */ 70 | /* This can yield better code on some machines. */ 71 | #define SWITCHSUBS 0 72 | 73 | /* In optimizing compilation certain library memcpy/strcpy-calls */ 74 | /* with length known at compile-time will be inlined using an */ 75 | /* ASSIGN-IC if the size is less or equal to INLINEMEMCPY. */ 76 | /* The type used for the ASSIGN-IC will be UNSIGNED|CHAR. */ 77 | #define INLINEMEMCPY 1024 78 | 79 | /* Parameters are sometimes passed in registers without __reg. */ 80 | #define HAVE_REGPARMS 1 81 | 82 | /* Parameters on the stack should be pushed in order rather than */ 83 | /* in reverse order. */ 84 | #define ORDERED_PUSH FIXED_SP 85 | 86 | /* Structure for reg_parm(). */ 87 | struct reg_handle{ 88 | unsigned long gregs; 89 | unsigned long fregs; 90 | }; 91 | 92 | /* We have some target-specific variable attributes. */ 93 | #define HAVE_TARGET_ATTRIBUTES 94 | 95 | /* We have target-specific pragmas */ 96 | #define HAVE_TARGET_PRAGMAS 97 | 98 | /* We keep track of all registers modified by a function. */ 99 | #define HAVE_REGS_MODIFIED 1 100 | 101 | /* We have a implement our own cost-functions to adapt 102 | register-allocation */ 103 | #define HAVE_TARGET_RALLOC 1 104 | #define cost_move_reg(x,y) 1 105 | #define cost_load_reg(x,y) 2 106 | #define cost_save_reg(x,y) 2 107 | #define cost_pushpop_reg(x) 3 108 | 109 | /* size of buffer for asm-output, this can be used to do 110 | peephole-optimizations of the generated assembly-output */ 111 | #define EMIT_BUF_LEN 1024 /* should be enough */ 112 | /* number of asm-output lines buffered */ 113 | #define EMIT_BUF_DEPTH 4 114 | 115 | /* We have no asm_peephole to optimize assembly-output */ 116 | #define HAVE_TARGET_PEEPHOLE 0 117 | 118 | /* we do not have a mark_eff_ics function, this is used to prevent 119 | optimizations on code which can already be implemented by efficient 120 | assembly */ 121 | #undef HAVE_TARGET_EFF_IC 122 | 123 | /* we only need the standard data types (no bit-types, different pointers 124 | etc.) */ 125 | #undef HAVE_EXT_TYPES 126 | #undef HAVE_TGT_PRINTVAL 127 | 128 | /* we do not need extra elements in the IC */ 129 | #undef HAVE_EXT_IC 130 | 131 | /* we do not use unsigned int as size_t (but unsigned long, the default) */ 132 | #undef HAVE_INT_SIZET 133 | 134 | /* we do not need register-pairs */ 135 | #undef HAVE_REGPAIRS 136 | 137 | 138 | /* do not create CONVERT ICs from integers smaller than int to floats */ 139 | #define MIN_INT_TO_FLOAT_TYPE INT 140 | 141 | /* do not create CONVERT ICs from floats to ints smaller than int */ 142 | #define MIN_FLOAT_TO_INT_TYPE INT 143 | 144 | /* do not create CONVERT_ICs from floats to unsigned integers */ 145 | #define AVOID_FLOAT_TO_UNSIGNED 1 146 | 147 | /* do not create CONVERT_ICs from unsigned integers to floats */ 148 | #define AVOID_UNSIGNED_TO_FLOAT 1 149 | 150 | /* convert multiplications/division by powers of two to shifts */ 151 | #define HAVE_POF2OPT 1 152 | -------------------------------------------------------------------------------- /machines/hc12/machine.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leffmann/vbcc/dbc4a369692e2ef3739ab8da29fb1c264731b7e6/machines/hc12/machine.c -------------------------------------------------------------------------------- /machines/hc12/machine.dt: -------------------------------------------------------------------------------- 1 | S8BS 2 | S8BU 3 | S16BSBE S16BSLE 4 | S16BUBE S16BULE 5 | S16BSBE S16BSLE 6 | S16BUBE S16BULE 7 | S32BSBE S32BSLE 8 | S32BUBE S32BULE 9 | S64BSBE S64BSLE 10 | S64BUBE S64BULE 11 | S32BIEEEBE 12 | S32BIEEEBE 13 | S32BIEEEBE 14 | S16BUbE S16BULE 15 | 16 | 17 | -------------------------------------------------------------------------------- /machines/hc12/machine.h: -------------------------------------------------------------------------------- 1 | /* Example of a code-generator for Motorola 68hc12 16bit microcontrollers.*/ 2 | 3 | #include "dt.h" 4 | 5 | /* We have extended types! What we have to do to support them: */ 6 | /* - #define HAVE_EXT_TYPES 7 | - #undef all standard types 8 | - #define all standard types plus new types 9 | - write eval_const and insert_const 10 | - write typedefs for zmax and zumax 11 | - write typname[] 12 | - write conv_typ() 13 | - optionally #define ISPOINTER, ISARITH, ISINT etc. 14 | - optionally #define HAVE_TGT_PRINTVAL and write printval 15 | - optionally #define POINTER_TYPE 16 | - optionally #define HAVE_TGT_FALIGN and write falign 17 | - optionally #define HAVE_TGT_SZOF and write szof 18 | - optionally add functions for attribute-handling 19 | */ 20 | #define HAVE_EXT_TYPES 1 21 | 22 | #define HAVE_TGT_PRINTVAL 23 | 24 | #undef CHAR 25 | #undef SHORT 26 | #undef INT 27 | #undef LONG 28 | #undef LLONG 29 | #undef FLOAT 30 | #undef DOUBLE 31 | #undef LDOUBLE 32 | #undef VOID 33 | #undef POINTER 34 | #undef ARRAY 35 | #undef STRUCT 36 | #undef UNION 37 | #undef ENUM 38 | #undef FUNKT 39 | #undef MAXINT 40 | #undef MAX_TYPE 41 | 42 | #define BIT 1 43 | #define CHAR 2 44 | #define SHORT 3 45 | #define INT 4 46 | #define LONG 5 47 | #define LLONG 6 48 | #define FLOAT 7 49 | #define DOUBLE 8 50 | #define LDOUBLE 9 51 | #define VOID 10 52 | #define NPOINTER 11 53 | #define FPOINTER 12 54 | #define HPOINTER 13 55 | #define ARRAY 14 56 | #define STRUCT 15 57 | #define UNION 16 58 | #define ENUM 17 59 | #define FUNKT 18 60 | 61 | #define MAXINT 19 62 | 63 | #define MAX_TYPE MAXINT 64 | 65 | #define POINTER_TYPE(x) pointer_type(x) 66 | extern int pointer_type(); 67 | #define ISPOINTER(x) ((x&NQ)>=NPOINTER&&(x&NQ)<=HPOINTER) 68 | #define ISSCALAR(x) ((x&NQ)>=BIT&&(x&NQ)<=HPOINTER) 69 | #define ISINT(x) ((x&NQ)>=BIT&&(x&NQ)<=LLONG) 70 | #define PTRDIFF_T(x) ((x)==HPOINTER?LONG:INT) 71 | 72 | typedef zllong zmax; 73 | typedef zullong zumax; 74 | 75 | union atyps{ 76 | zchar vchar; 77 | zuchar vuchar; 78 | zshort vshort; 79 | zushort vushort; 80 | zint vint; 81 | zuint vuint; 82 | zlong vlong; 83 | zulong vulong; 84 | zllong vllong; 85 | zullong vullong; 86 | zmax vmax; 87 | zumax vumax; 88 | zfloat vfloat; 89 | zdouble vdouble; 90 | zldouble vldouble; 91 | }; 92 | 93 | /* This struct can be used to implement machine-specific */ 94 | /* addressing-modes. */ 95 | /* Not used in this code-generrator. */ 96 | struct AddressingMode{ 97 | int flags; 98 | int base; 99 | long offset; 100 | struct Var *v; 101 | }; 102 | 103 | /* This type will be added to every IC. Can be used by the cg. */ 104 | #define HAVE_EXT_IC 1 105 | struct ext_ic { 106 | int flags; 107 | int r; 108 | long offset; 109 | }; 110 | 111 | /* The number of registers of the target machine. */ 112 | #define MAXR 6 113 | 114 | /* Number of commandline-options the code-generator accepts. */ 115 | #define MAXGF 20 116 | 117 | /* If this is set to zero vbcc will not generate ICs where the */ 118 | /* target operand is the same as the 2nd source operand. */ 119 | /* This can sometimes simplify the code-generator, but usually */ 120 | /* the code is better if the code-generator allows it. */ 121 | #define USEQ2ASZ 1 122 | 123 | /* This specifies the smallest integer type that can be added to a */ 124 | /* pointer. */ 125 | extern int MINADDI2P; 126 | 127 | /* If the bytes of an integer are ordered most significant byte */ 128 | /* byte first and then decreasing set BIGENDIAN to 1. */ 129 | #define BIGENDIAN 1 130 | 131 | /* If the bytes of an integer are ordered lest significant byte */ 132 | /* byte first and then increasing set LITTLEENDIAN to 1. */ 133 | #define LITTLEENDIAN 0 134 | 135 | /* Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive. */ 136 | 137 | /* If switch-statements should be generated as a sequence of */ 138 | /* SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1. */ 139 | /* This can yield better code on some machines. */ 140 | extern int switchsubs; 141 | #define SWITCHSUBS switchsubs 142 | 143 | /* In optimizing compilation certain library memcpy/strcpy-calls */ 144 | /* with length known at compile-time will be inlined using an */ 145 | /* ASSIGN-IC if the size is less or equal to INLINEMEMCPY. */ 146 | /* The type used for the ASSIGN-IC will be UNSIGNED|CHAR. */ 147 | #define INLINEMEMCPY 1024 148 | 149 | #define HAVE_REGPARMS 1 150 | 151 | struct reg_handle { 152 | int gpr; 153 | }; 154 | 155 | /* We use unsigned int as size_t rather than unsigned long which */ 156 | /* is the default setting. */ 157 | #define HAVE_INT_SIZET 1 158 | 159 | /* We have register pairs. */ 160 | #define HAVE_REGPAIRS 1 161 | 162 | /* We keep track of all registers modified by a function. */ 163 | #define HAVE_REGS_MODIFIED 1 164 | 165 | #define HAVE_TARGET_RALLOC 1 166 | #define cost_load_reg(r,v) 4 167 | #define cost_save_reg(r,v) 4 168 | #define cost_move_reg(i,j) 2 169 | #define cost_pushpop_reg(r) 2 170 | 171 | /* size of buffer for asm-output */ 172 | #define EMIT_BUF_LEN 1024 /* should be enough */ 173 | /* number of asm-output lines buffered */ 174 | #define EMIT_BUF_DEPTH 4 175 | 176 | /* We have asm_peephole to optimize assembly-output */ 177 | #define HAVE_TARGET_PEEPHOLE 1 178 | 179 | /* We have some target-specific variable attributes. */ 180 | #define HAVE_TARGET_ATTRIBUTES 1 181 | 182 | /* We use builtin libcalls for some operations */ 183 | #define HAVE_LIBCALLS 1 184 | 185 | /* We prefer BNE rather than BGT. */ 186 | #define HAVE_WANTBNE 1 187 | 188 | #define HAVE_POF2OPT 1 189 | 190 | /* Use char for return of comparison libcalls */ 191 | #define LIBCALL_CMPTYPE CHAR 192 | -------------------------------------------------------------------------------- /machines/i386/machine.dt: -------------------------------------------------------------------------------- 1 | S8BS 2 | S8BU 3 | S16BSLE S16BSBE 4 | S16BULE S16BUBE 5 | S32BSLE S32BSBE 6 | S32BULE S32BUBE 7 | S32BSLE S32BSBE 8 | S32BULE S32BUBE 9 | S64BSLE S64BSBE 10 | S64BULE S64BUBE 11 | S32BIEEELE 12 | S64BIEEELE 13 | S64BIEEELE 14 | S32BULE S32BUBE 15 | 16 | 17 | -------------------------------------------------------------------------------- /machines/i386/machine.h: -------------------------------------------------------------------------------- 1 | /* Example of a code-generator for an Intel 386 or higher. */ 2 | 3 | #include "dt.h" 4 | 5 | /* We have extended types! What we have to do to support them: */ 6 | /* - #define HAVE_EXT_TYPES 7 | - #undef all standard types 8 | - #define all standard types plus new types 9 | - write eval_const and insert_const 10 | - write typedefs for zmax and zumax 11 | - write typname[] 12 | - write conv_typ() 13 | - optionally #define ISPOINTER, ISARITH, ISINT etc. 14 | - optionally #define HAVE_TGT_PRINTVAL and write printval 15 | - optionally #define POINTER_TYPE 16 | - optionally #define HAVE_TGT_FALIGN and write falign 17 | - optionally #define HAVE_TGT_SZOF and write szof 18 | - optionally add functions for attribute-handling 19 | */ 20 | #define HAVE_EXT_TYPES 1 21 | 22 | #define HAVE_TGT_PRINTVAL 23 | 24 | #undef CHAR 25 | #undef SHORT 26 | #undef INT 27 | #undef LONG 28 | #undef LLONG 29 | #undef FLOAT 30 | #undef DOUBLE 31 | #undef LDOUBLE 32 | #undef VOID 33 | #undef POINTER 34 | #undef ARRAY 35 | #undef STRUCT 36 | #undef UNION 37 | #undef ENUM 38 | #undef FUNKT 39 | #undef MAXINT 40 | #undef MAX_TYPE 41 | 42 | #define CHAR 1 43 | #define SHORT 2 44 | #define BSHORT 3 45 | #define INT 4 46 | #define BINT 5 47 | #define LONG 6 48 | #define BLONG 7 49 | #define LLONG 8 50 | #define BLLONG 9 51 | #define FLOAT 10 52 | #define BFLOAT 11 53 | #define DOUBLE 12 54 | #define BDOUBLE 13 55 | #define LDOUBLE 14 56 | #define BLDOUBLE 15 57 | #define VOID 16 58 | #define POINTER 17 59 | #define BPOINTER 18 60 | #define ARRAY 19 61 | #define STRUCT 20 62 | #define UNION 21 63 | #define ENUM 22 64 | #define FUNKT 23 65 | 66 | #define MAXINT 24 /* should not be accesible to application */ 67 | 68 | #define MAX_TYPE MAXINT 69 | 70 | #define ISPOINTER(x) ((x&NQ)==POINTER||(x&NQ)==BPOINTER) 71 | #define ISSCALAR(x) ((x&NQ)>=CHAR&&(x&NQ)<=BPOINTER) 72 | #define ISINT(x) ((x&NQ)>=CHAR&&(x&NQ)<=BLLONG) 73 | 74 | typedef zllong zmax; 75 | typedef zullong zumax; 76 | 77 | union atyps{ 78 | zchar vchar; 79 | zuchar vuchar; 80 | zshort vshort; 81 | zushort vushort; 82 | zint vint; 83 | zuint vuint; 84 | zlong vlong; 85 | zulong vulong; 86 | zllong vllong; 87 | zullong vullong; 88 | zmax vmax; 89 | zumax vumax; 90 | zfloat vfloat; 91 | zdouble vdouble; 92 | zldouble vldouble; 93 | }; 94 | 95 | /* This struct can be used to implement machine-specific */ 96 | /* addressing-modes. */ 97 | /* Not used in this code-generrator. */ 98 | struct AddressingMode{ 99 | int mode; 100 | int base; 101 | int idx; 102 | int scal; 103 | zmax offset; 104 | struct Var *v; 105 | }; 106 | 107 | /* The number of registers of the target machine. */ 108 | #define MAXR 18 109 | 110 | /* Number of commandline-options the code-generator accepts. */ 111 | #define MAXGF 10 112 | 113 | /* If this is set to zero vbcc will not generate ICs where the */ 114 | /* target operand is the same as the 2nd source operand. */ 115 | /* This can sometimes simplify the code-generator, but usually */ 116 | /* the code is better if the code-generator allows it. */ 117 | #define USEQ2ASZ 1 118 | 119 | /* This specifies the smallest integer type that can be added to a */ 120 | /* pointer. */ 121 | #define MINADDI2P INT 122 | #define MAXADDI2P LONG 123 | 124 | /* If the bytes of an integer are ordered most significant byte */ 125 | /* byte first and then decreasing set BIGENDIAN to 1. */ 126 | #define BIGENDIAN 0 127 | 128 | /* If the bytes of an integer are ordered lest significant byte */ 129 | /* byte first and then increasing set LITTLEENDIAN to 1. */ 130 | #define LITTLEENDIAN 1 131 | 132 | /* Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive. */ 133 | 134 | /* If switch-statements should be generated as a sequence of */ 135 | /* SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1. */ 136 | /* This can yield better code on some machines. */ 137 | #define SWITCHSUBS 0 138 | 139 | /* In optimizing compilation certain library memcpy/strcpy-calls */ 140 | /* with length known at compile-time will be inlined using an */ 141 | /* ASSIGN-IC if the size is less or equal to INLINEMEMCPY. */ 142 | /* The type used for the ASSIGN-IC will be UNSIGNED|CHAR. */ 143 | #define INLINEMEMCPY 1024 144 | 145 | /* We keep track of all registers modified by a function. */ 146 | #define HAVE_REGS_MODIFIED 1 147 | 148 | /* size of buffer for asm-output */ 149 | #define EMIT_BUF_LEN 1024 /* should be enough */ 150 | /* number of asm-output lines buffered */ 151 | #define EMIT_BUF_DEPTH 4 152 | 153 | /* We have no asm_peephole to optimize assembly-output */ 154 | #define HAVE_TARGET_PEEPHOLE 0 155 | 156 | #define JUMP_TABLE_DENSITY 0.8 157 | #define JUMP_TABLE_LENGTH 4 158 | 159 | /* We use builtin libcalls for some operations */ 160 | #define HAVE_LIBCALLS 1 161 | 162 | /* support for variable-length arrays */ 163 | #define ALLOCVLA_REG 1 164 | #define ALLOCVLA_INLINEASM "\tsubl\t%eax,%esp\n\tandl\t$-5,%esp\n\tmovl\t%esp,%eax" 165 | /* TODO: find a better solution some time */ 166 | #define FREEVLA_REG 0 167 | #define FREEVLA_INLINEASM "\tmovl\t(%esp),%esp\n\tsubl\t$4,%esp" 168 | #define OLDSPVLA_INLINEASM "\tmovl\t%esp,%eax" 169 | #define FPVLA_REG 7 170 | 171 | /* do not create CONVERT_ICs from floats to unsigned integers */ 172 | #define AVOID_FLOAT_TO_UNSIGNED 1 173 | 174 | /* do not create CONVERT_ICs from unsigned integers to floats */ 175 | #define AVOID_UNSIGNED_TO_FLOAT 1 176 | -------------------------------------------------------------------------------- /machines/m68k/machine.dt: -------------------------------------------------------------------------------- 1 | S8BS 2 | S8BU 3 | S16BSBE S16BSLE 4 | S16BUBE S16BULE 5 | S32BSBE S32BSLE 6 | S32BUBE S32BULE 7 | S32BSBE S32BSLE 8 | S32BUBE S32BULE 9 | S64BSBE S64BSLE 10 | S64BUBE S64BULE 11 | S32BIEEEBE 12 | S64BIEEEBE 13 | S64BIEEEBE 14 | S32BUBE S32BULE 15 | 16 | 17 | -------------------------------------------------------------------------------- /machines/m68k/machine.h: -------------------------------------------------------------------------------- 1 | /* $VER: vbcc (m68k/machine.h) $Revision: 1.13 $ */ 2 | 3 | #include "dt.h" 4 | 5 | /* This struct can be used to implement machine-specific */ 6 | /* addressing-modes. */ 7 | typedef struct AddressingMode{ 8 | int basereg; 9 | long dist; 10 | int skal; 11 | int dreg; 12 | } AddressingMode; 13 | 14 | /* The number of registers of the target machine. */ 15 | #define MAXR 28 16 | 17 | /* Number of commandline-options the code-generator accepts. */ 18 | #define MAXGF 35 19 | 20 | /* If this is set to zero vbcc will not generate ICs where the */ 21 | /* target operand is the same as the 2nd source operand. */ 22 | /* This can sometimes simplify the code-generator, but usually */ 23 | /* the code is better if the code-generator allows it. */ 24 | #define USEQ2ASZ 1 25 | 26 | /* This specifies the smallest integer type that can be added to a */ 27 | /* pointer. */ 28 | extern int MINADDI2P; 29 | 30 | /* This specifies the smallest unsigned type that can be added to a */ 31 | /* pointer. */ 32 | #define MINADDUI2P (UNSIGNED|INT) 33 | 34 | 35 | /* This specifies the biggest integer type that can be added to a */ 36 | /* pointer. */ 37 | #define MAXADDI2P LONG 38 | 39 | /* If the bytes of an integer are ordered most significant byte */ 40 | /* byte first and then decreasing set BIGENDIAN to 1. */ 41 | #define BIGENDIAN 1 42 | 43 | /* If the bytes of an integer are ordered lest significant byte */ 44 | /* byte first and then increasing set LITTLEENDIAN to 1. */ 45 | #define LITTLEENDIAN 0 46 | 47 | /* Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive. */ 48 | 49 | /* If switch-statements should be generated as a sequence of */ 50 | /* SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1. */ 51 | /* This can yield better code on some machines. */ 52 | #define SWITCHSUBS 1 53 | 54 | /* In optimizing compilation certain library memcpy/strcpy-calls */ 55 | /* with length known at compile-time will be inlined using an */ 56 | /* ASSIGN-IC if the size is less or equal to INLINEMEMCPY. */ 57 | /* The type used for the ASSIGN-IC will be UNSIGNED|CHAR. */ 58 | #define INLINEMEMCPY 256 59 | 60 | /* We have some target-specific variable attributes. */ 61 | #define HAVE_TARGET_ATTRIBUTES 1 62 | 63 | /* We keep track of all registers modified by a function. */ 64 | #define HAVE_REGS_MODIFIED 1 65 | 66 | #define HAVE_TARGET_RALLOC 1 67 | #define cost_move_reg(x,y) 1 68 | #define cost_load_reg(x,y) 2 69 | #define cost_save_reg(x,y) 2 70 | #define cost_pushpop_reg(x) 2 71 | 72 | /* size of buffer for asm-output */ 73 | #define EMIT_BUF_LEN 1024 /* should be enough */ 74 | /* number of asm-output lines buffered */ 75 | #define EMIT_BUF_DEPTH 4 76 | 77 | /* We have no asm_peephole to optimize assembly-output */ 78 | #define HAVE_TARGET_PEEPHOLE 1 79 | 80 | /* we have a mark_eff_ics function */ 81 | #define HAVE_TARGET_EFF_IC 1 82 | 83 | /* we have register-pairs */ 84 | #define HAVE_REGPAIRS 1 85 | 86 | #define HAVE_REGPARMS 1 87 | 88 | struct reg_handle { 89 | int dr,ar,fr; 90 | }; 91 | 92 | 93 | #define JUMP_TABLE_DENSITY 0.8 94 | #define JUMP_TABLE_LENGTH 8 95 | 96 | /* support for variable-length arrays */ 97 | #define ALLOCVLA_REG 9 98 | #define ALLOCVLA_INLINEASM "\taddq.l\t#3,d0\n\tand.b\t#252,d0\n\tsub.l\td0,a7\n\tmove.l\ta7,d0" 99 | #define FREEVLA_REG 0 100 | /* TODO: find a better solution some time */ 101 | #define FREEVLA_INLINEASM "\tmove.l\t(a7),a7\n\tsubq.l\t#4,a7" 102 | #define OLDSPVLA_INLINEASM "\tmove.l\ta7,d0" 103 | #define FPVLA_REG 6 104 | 105 | /* We use builtin libcalls for some operations */ 106 | #define HAVE_LIBCALLS 1 107 | 108 | /* We have target-specific pragmas */ 109 | #define HAVE_TARGET_PRAGMAS 110 | 111 | /* We have a target-specific add_var hook */ 112 | #define HAVE_TARGET_VARHOOK_PRE 113 | 114 | #define HAVE_POF2OPT 1 115 | 116 | #ifndef M68K_16BIT_INT 117 | #define HAVE_INT_SIZET 1 118 | #endif 119 | -------------------------------------------------------------------------------- /machines/m68ks/machine.c: -------------------------------------------------------------------------------- 1 | /* Code generator for Motorola 680x0 CPUs. Supports 68000-68060+68881/2 */ 2 | /* and ColdFire. */ 3 | /* PhxAss and the GNU assembler is supported. */ 4 | 5 | /* stub for ST version with 16bit int */ 6 | 7 | #include "machines/m68k/machine.c" 8 | -------------------------------------------------------------------------------- /machines/m68ks/machine.dt: -------------------------------------------------------------------------------- 1 | S8BS 2 | S8BU 3 | S16BSBE S16BSLE 4 | S16BUBE S16BULE 5 | S16BSBE S16BSLE 6 | S16BUBE S16BULE 7 | S32BSBE S32BSLE 8 | S32BUBE S32BULE 9 | S64BSBE S64BSLE 10 | S64BUBE S64BULE 11 | S32BIEEEBE 12 | S64BIEEEBE 13 | S64BIEEEBE 14 | S32BUBE S32BULE 15 | 16 | 17 | -------------------------------------------------------------------------------- /machines/m68ks/machine.h: -------------------------------------------------------------------------------- 1 | /* Code generator for Motorola 680x0 CPUs. Supports 68000-68060+68881/2 */ 2 | /* and ColdFire. */ 3 | /* PhxAss and the GNU assembler is supported. */ 4 | 5 | /* stub for ST version with 16bit int */ 6 | 7 | #define M68K_16BIT_INT 8 | 9 | #define PTRDIFF_T(x) LONG 10 | 11 | #define BESTCOPYT LONG 12 | 13 | #include "dt.h" 14 | #include "../m68k/machine.h" 15 | -------------------------------------------------------------------------------- /machines/ppc/machine.dt: -------------------------------------------------------------------------------- 1 | S8BS 2 | S8BU 3 | S16BSBE S16BSLE 4 | S16BUBE S16BULE 5 | S32BSBE S32BSLE 6 | S32BUBE S32BULE 7 | S32BSBE S32BSLE 8 | S32BUBE S32BULE 9 | S64BSBE S64BSLE 10 | S64BUBE S64BULE 11 | S32BIEEEBE 12 | S64BIEEEBE 13 | S64BIEEEBE 14 | S32BUBE S32BULE 15 | 16 | 17 | -------------------------------------------------------------------------------- /machines/ppc/machine.h: -------------------------------------------------------------------------------- 1 | /* Example of a code-generator for a PowerPC */ 2 | 3 | #include "dt.h" 4 | 5 | /* This struct can be used to implement machine-specific */ 6 | /* addressing-modes. */ 7 | /* Not used in this code-generrator. */ 8 | struct AddressingMode{ 9 | int flags; 10 | int base; 11 | long offset; 12 | }; 13 | 14 | /* The number of registers of the target machine. */ 15 | #define MAXR 87 16 | 17 | /* Number of commandline-options the code-generator accepts. */ 18 | #define MAXGF 30 19 | 20 | /* If this is set to zero vbcc will not generate ICs where the */ 21 | /* target operand is the same as the 2nd source operand. */ 22 | /* This can sometimes simplify the code-generator, but usually */ 23 | /* the code is better if the code-generator allows it. */ 24 | #define USEQ2ASZ 1 25 | 26 | /* This specifies the smallest integer type that can be added to a */ 27 | /* pointer. */ 28 | #define MINADDI2P INT 29 | 30 | /* This specifies the largest integer type that can be added to a */ 31 | /* pointer. */ 32 | #define MAXADDI2P LONG 33 | 34 | #define HAVE_INT_SIZET 1 35 | 36 | /* If the bytes of an integer are ordered most significant byte */ 37 | /* byte first and then decreasing set BIGENDIAN to 1. */ 38 | #define BIGENDIAN 1 39 | 40 | /* If the bytes of an integer are ordered lest significant byte */ 41 | /* byte first and then increasing set LITTLEENDIAN to 1. */ 42 | #define LITTLEENDIAN 0 43 | 44 | /* Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive. */ 45 | 46 | /* If switch-statements should be generated as a sequence of */ 47 | /* SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1. */ 48 | /* This can yield better code on some machines. */ 49 | #define SWITCHSUBS 0 50 | 51 | /* In optimizing compilation certain library memcpy/strcpy-calls */ 52 | /* with length known at compile-time will be inlined using an */ 53 | /* ASSIGN-IC if the size is less or equal to INLINEMEMCPY. */ 54 | /* The type used for the ASSIGN-IC will be UNSIGNED|CHAR. */ 55 | #define INLINEMEMCPY 256 56 | 57 | /* Parameters are sometimes passed in registers without __reg. */ 58 | #define HAVE_REGPARMS 1 59 | 60 | /* Parameters on the stack should be pushed in order rather than */ 61 | /* in reverse order. */ 62 | #define ORDERED_PUSH 1 63 | 64 | /* Structure for reg_parm(). */ 65 | struct reg_handle{ 66 | unsigned long gregs; 67 | unsigned long fregs; 68 | }; 69 | 70 | /* We have some target-specific variable attributes. */ 71 | #define HAVE_TARGET_ATTRIBUTES 72 | 73 | /* We have target-specific pragmas */ 74 | #define HAVE_TARGET_PRAGMAS 75 | 76 | /* We keep track of all registers modified by a function. */ 77 | #define HAVE_REGS_MODIFIED 1 78 | 79 | #define HAVE_TARGET_RALLOC 1 80 | #define cost_move_reg(x,y) 1 81 | #define cost_load_reg(x,y) 2 82 | #define cost_save_reg(x,y) 2 83 | #define cost_pushpop_reg(x) 3 84 | 85 | /* size of buffer for asm-output */ 86 | #define EMIT_BUF_LEN 1024 /* should be enough */ 87 | /* number of asm-output lines buffered */ 88 | #define EMIT_BUF_DEPTH 4 89 | 90 | /* We have no asm_peephole to optimize assembly-output */ 91 | #define HAVE_TARGET_PEEPHOLE 0 92 | 93 | /* we have a mark_eff_ics function */ 94 | #define HAVE_TARGET_EFF_IC 1 95 | 96 | /* we have register-pairs */ 97 | #define HAVE_REGPAIRS 1 98 | 99 | #define JUMP_TABLE_DENSITY 0.8 100 | #define JUMP_TABLE_LENGTH 12 101 | 102 | /* This type will be added to every IC. Can be used by the cg. */ 103 | #define HAVE_EXT_IC 1 104 | struct ext_ic { 105 | int setcc; 106 | }; 107 | 108 | /* OSEK support */ 109 | #define HAVE_OSEK 1 110 | 111 | /* We use builtin libcalls for some operations */ 112 | #define HAVE_LIBCALLS 1 113 | 114 | /* support for variable-length arrays */ 115 | #define ALLOCVLA_REG 4 116 | #if 0 117 | #define ALLOCVLA_INLINEASM "\tlwz\t0,0(1)\n"\ 118 | "\taddi\t3,3,7\n"\ 119 | "\tsrwi\t3,3,3\n"\ 120 | "\tslwi\t3,3,3\n"\ 121 | "\tneg\t11,3\n"\ 122 | "\tsub\t3,1,3\n"\ 123 | "\tsubi\t11,11,8\n"\ 124 | "\tstwux\t0,1,11" 125 | #endif 126 | #define ALLOCVLA_INLINEASM "\tlwz\t0,0(1)\n"\ 127 | "\tneg\t3,3\n"\ 128 | "\tsrwi\t3,3,3\n"\ 129 | "\tslwi\t3,3,3\n"\ 130 | "\tstwux\t0,1,3\n"\ 131 | "\taddi\t3,1,____fo" 132 | #define FREEVLA_REG 6 133 | #define FREEVLA_INLINEASM "\tlwz\t0,0(1)\n"\ 134 | "\tmr\t1,5\n"\ 135 | "\tstw\t0,0(1)" 136 | #define OLDSPVLA_INLINEASM "\tmr\t3,1" 137 | #define FPVLA_REG 32 138 | -------------------------------------------------------------------------------- /machines/ppc/schedule.h: -------------------------------------------------------------------------------- 1 | /* 2 | * vscppc 3 | * 4 | * vbcc PowerPC scheduler 5 | * (C)1998 by Frank Wille 6 | * 7 | * vscppc is freeware and part of the portable and retargetable ANSI C 8 | * compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann. 9 | * vscppc may be freely redistributed as long as no modifications are 10 | * made and nothing is charged for it. Non-commercial usage is allowed 11 | * without any restrictions. 12 | * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE 13 | * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR. 14 | * 15 | * History: 16 | * V0.3 20-Jul-98 17 | * Differentiation between 603 and 604. Now, scheduling takes 18 | * place with regard to the real PowerPC architecture. 19 | * V0.1 10-Jul-98 20 | * vscppc seems to be stable enough, after some tests. 21 | * However, it still needs a lot of fine tuning. 22 | * A differentiation between the PPC CPUs (603e, 604e) is missing. 23 | * V0.0 09-Jul-98 24 | * File created. 25 | * 26 | */ 27 | 28 | #define PIPES 7 /* the max. number of pipes, as required by the 604 */ 29 | 30 | /* Pipe Names 603 */ 31 | #define BPU 0 /* Branch Prediction Unit */ 32 | #define SRU 1 /* Special Reg. Unit */ 33 | #define IU 2 /* Integer Unit */ 34 | #define FPU 5 /* Floating Point Unit */ 35 | #define LSU 6 /* Load Store Unit */ 36 | 37 | /* Pipe Names 604 */ 38 | #define CRU 1 /* Condition Register Unit */ 39 | #define SCIU1 2 /* Single Cycle Integer Unit #1 */ 40 | #define SCIU2 3 /* Single Cycle Integer Unit #2 */ 41 | #define MCIU 4 /* Multiple Cycle Integer Unit */ 42 | 43 | 44 | #define REGS 76 /* 32 GPR, 32 FPR, 8 CCR, LR, CTR, XER, FPSCR */ 45 | 46 | /* REG-offsets */ 47 | #define GPR 0 48 | #define FPR 32 49 | #define CCR 64 50 | #define XER 72 51 | #define CTR 73 52 | #define LR 74 53 | #define FPSCR 75 54 | -------------------------------------------------------------------------------- /machines/qnice/machine.dt: -------------------------------------------------------------------------------- 1 | S16BSLE S16BSBE 2 | S16BULE S16BUBE 3 | S16BSLE S16BSBE 4 | S16BULE S16BUBE 5 | S16BSLE S16BSBE 6 | S16BULE S16BUBE 7 | S32BSLE S32BSBE 8 | S32BULE S32BUBE 9 | S64BSLE S64BSBE 10 | S64BULE S64BUBE 11 | S32BIEEELE 12 | S64BIEEELE 13 | S64BIEEELE 14 | S16BULE S16BUBE 15 | 16 | 17 | -------------------------------------------------------------------------------- /machines/qnice/machine.h: -------------------------------------------------------------------------------- 1 | /* Example of a code-generator for qnice cpu.*/ 2 | 3 | #include "dt.h" 4 | 5 | /* We have extended types! What we have to do to support them: */ 6 | /* - #define HAVE_EXT_TYPES 7 | - #undef all standard types 8 | - #define all standard types plus new types 9 | - write eval_const and insert_const 10 | - write typedefs for zmax and zumax 11 | - write typname[] 12 | - write conv_typ() 13 | - optionally #define ISPOINTER, ISARITH, ISINT etc. 14 | - optionally #define HAVE_TGT_PRINTVAL and write printval 15 | - optionally #define POINTER_TYPE 16 | - optionally #define HAVE_TGT_FALIGN and write falign 17 | - optionally #define HAVE_TGT_SZOF and write szof 18 | - optionally add functions for attribute-handling 19 | */ 20 | #define HAVE_EXT_TYPES 1 21 | 22 | #define HAVE_TGT_PRINTVAL 23 | 24 | #undef CHAR 25 | #undef SHORT 26 | #undef INT 27 | #undef LONG 28 | #undef LLONG 29 | #undef FLOAT 30 | #undef DOUBLE 31 | #undef LDOUBLE 32 | #undef VOID 33 | #undef POINTER 34 | #undef ARRAY 35 | #undef STRUCT 36 | #undef UNION 37 | #undef ENUM 38 | #undef FUNKT 39 | #undef BOOL 40 | #undef MAXINT 41 | #undef MAX_TYPE 42 | 43 | #define BIT 1 44 | #define CHAR 2 45 | #define SHORT 3 46 | #define INT 4 47 | #define LONG 5 48 | #define LLONG 6 49 | #define FLOAT 7 50 | #define DOUBLE 8 51 | #define LDOUBLE 9 52 | #define VOID 10 53 | #define NPOINTER 11 54 | #define FPOINTER 12 55 | #define HPOINTER 13 56 | #define ARRAY 14 57 | #define STRUCT 15 58 | #define UNION 16 59 | #define ENUM 17 60 | #define FUNKT 18 61 | #define BOOL 19 62 | 63 | #define MAXINT 20 64 | 65 | #define MAX_TYPE MAXINT 66 | 67 | #define POINTER_TYPE(x) pointer_type(x) 68 | extern int pointer_type(); 69 | #define ISPOINTER(x) ((x&NQ)>=NPOINTER&&(x&NQ)<=HPOINTER) 70 | #define ISSCALAR(x) ((x&NQ)>=BIT&&(x&NQ)<=HPOINTER) 71 | #define ISINT(x) ((x&NQ)>=BIT&&(x&NQ)<=LLONG) 72 | #define PTRDIFF_T(x) ((x)==HPOINTER?LONG:INT) 73 | 74 | typedef zllong zmax; 75 | typedef zullong zumax; 76 | 77 | union atyps{ 78 | zchar vchar; 79 | zuchar vuchar; 80 | zshort vshort; 81 | zushort vushort; 82 | zint vint; 83 | zuint vuint; 84 | zlong vlong; 85 | zulong vulong; 86 | zllong vllong; 87 | zullong vullong; 88 | zmax vmax; 89 | zumax vumax; 90 | zfloat vfloat; 91 | zdouble vdouble; 92 | zldouble vldouble; 93 | }; 94 | 95 | /* This struct can be used to implement machine-specific */ 96 | /* addressing-modes. */ 97 | struct AddressingMode{ 98 | int flags; 99 | int base; 100 | }; 101 | 102 | /* This type will be added to every IC. Can be used by the cg. */ 103 | #define HAVE_EXT_IC 0 104 | struct ext_ic { 105 | int flags; 106 | int r; 107 | long offset; 108 | }; 109 | 110 | /* The number of registers of the target machine. */ 111 | #define MAXR 22 112 | 113 | /* Number of commandline-options the code-generator accepts. */ 114 | #define MAXGF 20 115 | 116 | /* If this is set to zero vbcc will not generate ICs where the */ 117 | /* target operand is the same as the 2nd source operand. */ 118 | /* This can sometimes simplify the code-generator, but usually */ 119 | /* the code is better if the code-generator allows it. */ 120 | #define USEQ2ASZ 1 121 | 122 | /* This specifies the smallest integer type that can be added to a */ 123 | /* pointer. */ 124 | #define MINADDI2P CHAR 125 | 126 | /* If the bytes of an integer are ordered most significant byte */ 127 | /* byte first and then decreasing set BIGENDIAN to 1. */ 128 | #define BIGENDIAN 0 129 | 130 | /* If the bytes of an integer are ordered lest significant byte */ 131 | /* byte first and then increasing set LITTLEENDIAN to 1. */ 132 | #define LITTLEENDIAN 1 133 | 134 | /* Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive. */ 135 | 136 | /* If switch-statements should be generated as a sequence of */ 137 | /* SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1. */ 138 | /* This can yield better code on some machines. */ 139 | #define SWITCHSUBS 0 140 | 141 | /* In optimizing compilation certain library memcpy/strcpy-calls */ 142 | /* with length known at compile-time will be inlined using an */ 143 | /* ASSIGN-IC if the size is less or equal to INLINEMEMCPY. */ 144 | /* The type used for the ASSIGN-IC will be UNSIGNED|CHAR. */ 145 | #define INLINEMEMCPY 1024 146 | 147 | #define HAVE_REGPARMS 1 148 | 149 | struct reg_handle { 150 | int gpr; 151 | }; 152 | 153 | /* We use unsigned int as size_t rather than unsigned long which */ 154 | /* is the default setting. */ 155 | #define HAVE_INT_SIZET 1 156 | 157 | /* We have register pairs. */ 158 | #define HAVE_REGPAIRS 1 159 | 160 | /* We keep track of all registers modified by a function. */ 161 | #define HAVE_REGS_MODIFIED 1 162 | 163 | #define HAVE_TARGET_RALLOC 1 164 | #define cost_load_reg(r,v) 4 165 | #define cost_save_reg(r,v) 4 166 | #define cost_move_reg(i,j) 2 167 | #define cost_pushpop_reg(r) 2 168 | 169 | /* size of buffer for asm-output */ 170 | #define EMIT_BUF_LEN 1024 /* should be enough */ 171 | /* number of asm-output lines buffered */ 172 | #define EMIT_BUF_DEPTH 4 173 | 174 | /* We have asm_peephole to optimize assembly-output */ 175 | #define HAVE_TARGET_PEEPHOLE 1 176 | 177 | /* We have some target-specific variable attributes. */ 178 | #define HAVE_TARGET_ATTRIBUTES 1 179 | 180 | /* We use builtin libcalls for some operations */ 181 | #define HAVE_LIBCALLS 1 182 | 183 | #define HAVE_WANTBNE 1 184 | 185 | #define HAVE_POF2OPT 1 186 | -------------------------------------------------------------------------------- /machines/vidcore/machine.dt: -------------------------------------------------------------------------------- 1 | S8BS 2 | S8BU 3 | S16BSBE S16BSLE 4 | S16BUBE S16BULE 5 | S32BSBE S32BSLE 6 | S32BUBE S32BULE 7 | S32BSBE S32BSLE 8 | S32BUBE S32BULE 9 | S64BSBE S64BSLE 10 | S64BUBE S64BULE 11 | S32BIEEEBE 12 | S64BIEEEBE 13 | S64BIEEEBE 14 | S32BUBE S32BULE 15 | 16 | 17 | -------------------------------------------------------------------------------- /machines/vidcore/machine.h: -------------------------------------------------------------------------------- 1 | /* Backend for VideoCore IV 2 | (c) in 2013 by Volker Barthelmann 3 | */ 4 | 5 | /* buil-time configurable options: */ 6 | #define NUM_GPRS 48 7 | 8 | #include "dt.h" 9 | 10 | 11 | /* This struct can be used to implement machine-specific */ 12 | /* addressing-modes. */ 13 | /* Currently possible are (const,gpr) and (gpr,gpr) */ 14 | struct AddressingMode{ 15 | int flags; 16 | int base; 17 | long offset; 18 | }; 19 | 20 | /* The number of registers of the target machine. */ 21 | #define MAXR 48 22 | 23 | /* Number of commandline-options the code-generator accepts. */ 24 | #define MAXGF 20 25 | 26 | /* If this is set to zero vbcc will not generate ICs where the */ 27 | /* target operand is the same as the 2nd source operand. */ 28 | /* This can sometimes simplify the code-generator, but usually */ 29 | /* the code is better if the code-generator allows it. */ 30 | #define USEQ2ASZ 0 31 | 32 | /* This specifies the smallest integer type that can be added to a */ 33 | /* pointer. */ 34 | #define MINADDI2P INT 35 | 36 | /* This specifies the smallest integer type that can be added to a */ 37 | /* pointer. */ 38 | #define MAXADDI2P INT 39 | 40 | /* If the bytes of an integer are ordered most significant byte */ 41 | /* byte first and then decreasing set BIGENDIAN to 1. */ 42 | #define BIGENDIAN 0 43 | 44 | /* If the bytes of an integer are ordered lest significant byte */ 45 | /* byte first and then increasing set LITTLEENDIAN to 1. */ 46 | #define LITTLEENDIAN 1 47 | 48 | /* Note that BIGENDIAN and LITTLEENDIAN are mutually exclusive. */ 49 | 50 | /* If switch-statements should be generated as a sequence of */ 51 | /* SUB,TST,BEQ ICs rather than COMPARE,BEQ ICs set this to 1. */ 52 | /* This can yield better code on some machines. */ 53 | #define SWITCHSUBS 1 54 | 55 | /* In optimizing compilation certain library memcpy/strcpy-calls */ 56 | /* with length known at compile-time will be inlined using an */ 57 | /* ASSIGN-IC if the size is less or equal to INLINEMEMCPY. */ 58 | /* The type used for the ASSIGN-IC will be UNSIGNED|CHAR. */ 59 | #define INLINEMEMCPY 1024 60 | 61 | /* Parameters are sometimes passed in registers without __reg. */ 62 | #define HAVE_REGPARMS 1 63 | 64 | /* Parameters on the stack should be pushed in order rather than */ 65 | /* in reverse order. */ 66 | #undef ORDERED_PUSH 67 | 68 | /* Structure for reg_parm(). */ 69 | struct reg_handle{ 70 | unsigned long gregs; 71 | }; 72 | 73 | /* We have some target-specific variable attributes. */ 74 | #define HAVE_TARGET_ATTRIBUTES 75 | 76 | /* We have target-specific pragmas */ 77 | #define HAVE_TARGET_PRAGMAS 78 | 79 | /* We keep track of all registers modified by a function. */ 80 | #define HAVE_REGS_MODIFIED 1 81 | 82 | /* We have a implement our own cost-functions to adapt 83 | register-allocation */ 84 | #define HAVE_TARGET_RALLOC 1 85 | #define cost_move_reg(x,y) 1 86 | #define cost_load_reg(x,y) 2 87 | #define cost_save_reg(x,y) 2 88 | #define cost_pushpop_reg(x) 3 89 | 90 | /* size of buffer for asm-output, this can be used to do 91 | peephole-optimizations of the generated assembly-output */ 92 | #define EMIT_BUF_LEN 1024 /* should be enough */ 93 | /* number of asm-output lines buffered */ 94 | #define EMIT_BUF_DEPTH 4 95 | 96 | /* We have no asm_peephole to optimize assembly-output */ 97 | #define HAVE_TARGET_PEEPHOLE 0 98 | 99 | /* we do not have a mark_eff_ics function, this is used to prevent 100 | optimizations on code which can already be implemented by efficient 101 | assembly */ 102 | #undef HAVE_TARGET_EFF_IC 103 | 104 | /* we only need the standard data types (no bit-types, different pointers 105 | etc.) */ 106 | #undef HAVE_EXT_TYPES 107 | #undef HAVE_TGT_PRINTVAL 108 | 109 | /* we do not need extra elements in the IC */ 110 | #undef HAVE_EXT_IC 111 | 112 | /* we do use unsigned int as size_t (but unsigned long, the default) */ 113 | #define HAVE_INT_SIZET 1 114 | 115 | /* we need register-pairs */ 116 | #define HAVE_REGPAIRS 1 117 | 118 | 119 | /* do not create CONVERT ICs from integers smaller than int to floats */ 120 | #define MIN_INT_TO_FLOAT_TYPE INT 121 | 122 | /* do not create CONVERT ICs from floats to ints smaller than int */ 123 | #define MIN_FLOAT_TO_INT_TYPE INT 124 | 125 | /* do not create CONVERT_ICs from floats to unsigned integers */ 126 | #define AVOID_FLOAT_TO_UNSIGNED 1 127 | 128 | /* do not create CONVERT_ICs from unsigned integers to floats */ 129 | #define AVOID_UNSIGNED_TO_FLOAT 0 130 | 131 | #define HAVE_LIBCALLS 1 132 | -------------------------------------------------------------------------------- /machines/z/machine.dt: -------------------------------------------------------------------------------- 1 | S8BS 2 | S8BU 3 | S16BSLE S16BSBE 4 | S16BULE S16BUBE 5 | S16BSLE S16BSBE 6 | S16BULE S16BUBE 7 | S32BSLE S32BSBE 8 | S32BULE S32BUBE 9 | S64BSLE S64BSBE 10 | S64BULE S64BUBE 11 | S32BIEEEBE S32BIEEELE 12 | S64BIEEEBE S64BIEEELE 13 | S64BIEEEBE S64BIEEELE 14 | S16BULE S16BUBE 15 | -------------------------------------------------------------------------------- /machines/z/machine.h: -------------------------------------------------------------------------------- 1 | /* Z-machine code generator 2 | * David Given 3 | */ 4 | 5 | #include "dt.h" 6 | 7 | /* Machine specific addressing-modes. Not used. */ 8 | 9 | struct AddressingMode{ 10 | int never_used; 11 | }; 12 | 13 | /* The number of registers we support. We don't really have any, but we 14 | * use local variables instead; we have 14. 15 | */ 16 | 17 | #define MAXR 14 18 | 19 | /* Number of command-line options we accept. */ 20 | 21 | #define MAXGF 6 22 | 23 | /* If this is set to zero vbcc will not generate ICs where the target operand 24 | * is the same as the 2nd source operand. This can sometimes simplify the 25 | * code-generator, but usually the code is better if the code-generator allows 26 | * it. 27 | */ 28 | 29 | #define USEQ2ASZ 1 30 | 31 | /* The smallest and largest integer type that can be added to a pointer. */ 32 | 33 | #define MINADDI2P INT 34 | #define MAXADDI2P INT 35 | 36 | /* Big-endian? */ 37 | 38 | #define BIGENDIAN 1 39 | 40 | /* Little-endian? */ 41 | 42 | #define LITTLEENDIAN 0 43 | 44 | /* If switch-statements should be generated as a sequence of SUB,TST,BEQ ICs 45 | * rather than COMPARE,BEQ ICs set this to 1. This can yield better code on 46 | * some machines. 47 | */ 48 | 49 | #define SWITCHSUBS 0 50 | 51 | /* In optimizing compilation certain library memcpy/strcpy-calls with length 52 | * known at compile-time will be inlined using an ASSIGN-IC if the size is less 53 | * or equal to INLINEMEMCPY. The type used for the ASSIGN-IC will be 54 | * UNSIGNED|CHAR. On the Z-machine, memcpy can be done in `hardware' with the 55 | * @copy_table opcode, so always inline them if possible. 56 | */ 57 | 58 | #define INLINEMEMCPY 65536 59 | 60 | /* Do we want to pass parameters to functions in registers? */ 61 | 62 | #define HAVE_REGPARMS 1 63 | 64 | /* If so, how many? Max 7 due to the architecture, but one is always xp. */ 65 | 66 | #define NUM_REGPARMS 6 67 | 68 | /* This structure is used to keep track of where register parameters go. */ 69 | 70 | struct reg_handle { 71 | int reg; 72 | }; 73 | 74 | /* Do we want to use zuint for size_t rather than the default zulong? */ 75 | 76 | #define HAVE_INT_SIZET 1 77 | 78 | /* size of buffer for asm-output */ 79 | #define EMIT_BUF_LEN 1024 /* should be enough */ 80 | /* number of asm-output lines buffered */ 81 | #define EMIT_BUF_DEPTH 4 82 | -------------------------------------------------------------------------------- /mbasic.c: -------------------------------------------------------------------------------- 1 | /* Test-language for vbcc. */ 2 | 3 | #include "supp.h" 4 | 5 | #include 6 | #include 7 | 8 | struct Var *fv; 9 | 10 | struct Typ tint,mfunc; 11 | struct struct_declaration msd; /* initialized to zero */ 12 | 13 | FILE *file; 14 | char *next; 15 | 16 | struct obj expression(),factor(),scalar(); 17 | 18 | void raus(void) 19 | { 20 | while(fv){ 21 | struct Var *m=fv->next; 22 | free(fv); 23 | fv=m; 24 | } 25 | while(first_ic){ 26 | struct IC *m=first_ic->next; 27 | free(first_ic); 28 | first_ic=m; 29 | } 30 | exit(0); 31 | } 32 | void add_IC(struct IC *new) 33 | { 34 | new->next=0; 35 | new->prev=last_ic; 36 | new->change_cnt=new->use_cnt=0; 37 | new->change_list=new->use_list=0; 38 | new->line=0; 39 | new->file=0; 40 | new->q1.am=new->q2.am=new->z.am=0; 41 | if(!last_ic){ 42 | first_ic=new; 43 | }else{ 44 | last_ic->next=new; 45 | } 46 | last_ic=new; 47 | } 48 | struct Var *add_var(char *name,struct Typ *t,int sc) 49 | { 50 | struct Var *v=mymalloc(sizeof(*v)); 51 | v->vtyp=t; 52 | v->storage_class=sc; 53 | v->reg=0; 54 | v->identifier=name; 55 | v->offset=max_offset; 56 | if(sc==AUTO) max_offset=zmadd(max_offset,sizetab[t->flags&NQ]); 57 | v->priority=1; 58 | v->flags=0; 59 | v->next=fv; 60 | v->clist=0; 61 | v->fi=0; 62 | v->inline_copy=0; 63 | v->nesting=1; 64 | fv=v; 65 | return v; 66 | } 67 | struct Var *add_tmp_var(struct Typ *t) 68 | { 69 | return add_var(empty,t,AUTO); 70 | } 71 | struct Var *get_var(char *name) 72 | { 73 | struct Var *v;char *buf; 74 | puts("getvar"); 75 | for(v=fv;v;v=v->next){ 76 | if(!strcmp(name,v->identifier)) return v; 77 | } 78 | buf=mymalloc(strlen(name)+1); 79 | strcpy(buf,name); 80 | return add_var(buf,&tint,AUTO); 81 | } 82 | 83 | char *identifier(void) 84 | { 85 | static char id[1024]; 86 | char *s=id; 87 | puts("identifier"); 88 | while(isalnum(*next)) *s++=*next++; 89 | puts("done"); 90 | return id; 91 | } 92 | struct obj scalar(void) 93 | { 94 | struct obj o; 95 | zmax val; 96 | puts("scalar"); 97 | if(isdigit(*next)){ 98 | o.flags=KONST; 99 | val=l2zm(0L); 100 | while(isdigit(*next)){ 101 | val=zmmult(val,l2zm(10L)); 102 | val=zmadd(val,l2zm((long)(*next-'0'))); 103 | next++; 104 | } 105 | o.val.vint=zm2zi(val); 106 | return o; 107 | } 108 | if(*next=='('){ 109 | next++; 110 | o=expression(); 111 | next++; 112 | return o; 113 | } 114 | o.flags=VAR; 115 | o.val.vmax=l2zm(0L); 116 | o.v=get_var(identifier()); 117 | return o; 118 | } 119 | struct obj factor(void) 120 | { 121 | struct obj o; 122 | struct IC *new; 123 | puts("factor"); 124 | o=scalar(); 125 | while(*next=='*'||*next=='/'){ 126 | new=new_IC(); 127 | if(*next=='*') new->code=MULT; else new->code=DIV; 128 | next++; 129 | new->typf=INT; 130 | new->q1=o; 131 | new->q2=scalar(); 132 | o.flags=VAR; 133 | o.v=add_tmp_var(&tint); 134 | o.val.vmax=l2zm(0L); 135 | new->z=o; 136 | add_IC(new); 137 | } 138 | return o; 139 | } 140 | struct obj expression(void) 141 | { 142 | struct obj o; 143 | struct IC *new; 144 | puts("expression"); 145 | o=factor(); 146 | while(*next=='+'||*next=='-'){ 147 | new=new_IC(); 148 | if(*next=='+') new->code=ADD; else new->code=SUB; 149 | next++; 150 | new->typf=INT; 151 | new->q1=o; 152 | new->q2=factor(); 153 | o.flags=VAR; 154 | o.v=add_tmp_var(&tint); 155 | o.val.vmax=l2zm(0L); 156 | new->z=o; 157 | add_IC(new); 158 | } 159 | return o; 160 | } 161 | void compile(void) 162 | { 163 | struct IC *new; 164 | char line[1024],*s; 165 | struct obj o,last; 166 | puts("compile"); 167 | while(fgets(line,1023,file)){ 168 | next=line; 169 | s=identifier(); 170 | if(*next=='='){ 171 | struct Var *v=get_var(s); 172 | next++; 173 | o=expression(); 174 | new=new_IC(); 175 | new->code=ASSIGN; 176 | new->typf=INT; 177 | new->q1=o; 178 | new->z.flags=VAR; 179 | new->z.v=v; 180 | new->z.val.vmax=l2zm(0L); 181 | new->q2.flags=0; 182 | new->q2.val.vmax=sizetab[INT]; 183 | last=new->z; 184 | add_IC(new); 185 | continue; 186 | } 187 | } 188 | new=new_IC(); 189 | new->code=SETRETURN; 190 | new->typf=INT; 191 | new->q1=last; 192 | new->q2.flags=new->z.flags=0; 193 | new->q2.val.vmax=sizetab[INT]; 194 | new->z.reg=freturn(&tint); 195 | if(!new->z.reg) puts("problem!"); 196 | add_IC(new); 197 | } 198 | void error(int n,...) 199 | { 200 | printf("error %d\n",n); 201 | raus(); 202 | } 203 | void savescratch() 204 | {} 205 | 206 | main(int argc,char **argv) 207 | { 208 | struct Var *main; 209 | max_offset=l2zm(0L); 210 | if(!init_cg()) raus(); 211 | tint.flags=INT; 212 | tint.next=0; 213 | mfunc.flags=FUNKT; 214 | mfunc.next=∭ 215 | mfunc.exact=&msd; 216 | main=add_var("main",&mfunc,EXTERN); 217 | file=fopen(argv[1],"r"); 218 | if(!file) {printf("Error opening file\n");raus();} 219 | compile(); 220 | scanf("%ld",&optflags); 221 | pric(stdout,first_ic); 222 | vl1=vl3=0; 223 | vl2=fv; 224 | optimize(optflags,main); 225 | pric(stdout,first_ic); 226 | gen_code(stdout,first_ic,main,max_offset); 227 | raus(); 228 | } 229 | 230 | -------------------------------------------------------------------------------- /minicomp.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "supp.h" 8 | 9 | extern FILE *infile; 10 | #define MAXLEN 1024 11 | extern char tkname[MAXLEN]; 12 | extern int label; 13 | extern int nesting; 14 | extern int local_offset,parm_offset,framesize; 15 | 16 | #define REAL DOUBLE 17 | #define FUNCTION FUNKT 18 | 19 | #define YYERROR_VERBOSE 1 20 | 21 | enum nodeflags { 22 | NVARIABLE,NNUMBER,NADD,NMUL,NSUB,NDIV,NINDEX, 23 | NEQUALS,NLT,NGT,NLEQ,NGEQ,NNEQ,NAND,NOR, 24 | NI2R,NR2I,NASSGN,NCALL,NARG 25 | }; 26 | 27 | extern char *nodename[]; 28 | 29 | typedef struct Typ type; 30 | 31 | typedef struct obj operand; 32 | 33 | typedef struct var { 34 | int nesting; 35 | char *name; 36 | struct Typ *type; 37 | struct var *next; 38 | int offset; 39 | struct Var *vbccvar; 40 | } var; 41 | 42 | #define MAXNESTING 128 43 | extern var *first_var[128]; 44 | 45 | typedef struct { 46 | int flags; 47 | char *name; 48 | } *stype; 49 | 50 | typedef struct mnode { 51 | enum nodeflags flags; 52 | struct mnode *left,*right; 53 | type *type; 54 | var *var; 55 | int ivalue; 56 | double rvalue; 57 | } node; 58 | 59 | void enter_block(void); 60 | void leave_block(void); 61 | void enter_func(char *,type *); 62 | void leave_func(void); 63 | var *find_var(char *,int); 64 | var *add_var(char *,type *); 65 | var *new_temp(int); 66 | char *add_string(char *); 67 | void error(int,...); 68 | void *getmem(size_t); 69 | node *number_node(void); 70 | node *var_node(void); 71 | node *conv_tree(node *,int); 72 | node *binary_node(enum nodeflags,node *,node *); 73 | void print_tree(node *); 74 | void simplify_tree(node *); 75 | void free_tree(node *); 76 | type *new_type(int); 77 | type *new_array(type *,node *); 78 | void return_statement(node *); 79 | void while_statement(node *); 80 | void while_end(void); 81 | void if_statement(node *); 82 | void if_end(void); 83 | void if_else(void); 84 | void assign_statement(node *,node *); 85 | void push_int(int); 86 | int pop_int(void); 87 | void push_name(char *); 88 | char *pop_name(void); 89 | operand *gen_tree(node *); 90 | void gen_cond(node *,int,int); 91 | void gen_label(int); 92 | int push_arg(node *); 93 | void gen_global(char *,int); 94 | -------------------------------------------------------------------------------- /minicomplexer.c: -------------------------------------------------------------------------------- 1 | 2 | FILE *infile; 3 | static int cur_char=' '; 4 | 5 | char tkname[MAXLEN]; 6 | 7 | int yylex() 8 | { 9 | char *p=tkname; 10 | int tmp; 11 | 12 | while(isspace(cur_char)) 13 | cur_char=getc(infile); 14 | 15 | if(isdigit(cur_char)){ 16 | do{ 17 | *p++=cur_char; 18 | cur_char=getc(infile); 19 | }while(isdigit(cur_char)); 20 | if(cur_char=='.'){ 21 | *p++=cur_char; 22 | cur_char=getc(infile); 23 | while(isdigit(cur_char)){ 24 | *p++=cur_char; 25 | cur_char=getc(infile); 26 | } 27 | } 28 | *p++=0; 29 | return TKNUMBER; 30 | } 31 | if(isalpha(cur_char)){ 32 | do{ 33 | *p++=cur_char; 34 | cur_char=getc(infile); 35 | }while(isalnum(cur_char)); 36 | *p++=0; 37 | if(!strcmp(tkname,"int")) 38 | return TKINT; 39 | if(!strcmp(tkname,"real")) 40 | return TKREAL; 41 | if(!strcmp(tkname,"if")) 42 | return TKIF; 43 | if(!strcmp(tkname,"else")) 44 | return TKELSE; 45 | if(!strcmp(tkname,"while")) 46 | return TKWHILE; 47 | if(!strcmp(tkname,"return")) 48 | return TKRETURN; 49 | return TKIDENTIFIER; 50 | } 51 | tmp=cur_char; 52 | cur_char=getc(infile); 53 | if(tmp=='!'&&cur_char=='='){ 54 | cur_char=getc(infile); 55 | return TKNEQ; 56 | } 57 | if(tmp=='<'&&cur_char=='='){ 58 | cur_char=getc(infile); 59 | return TKLEQ; 60 | } 61 | if(tmp=='>'&&cur_char=='='){ 62 | cur_char=getc(infile); 63 | return TKGEQ; 64 | } 65 | if(tmp=='&'&&cur_char=='&'){ 66 | cur_char=getc(infile); 67 | return TKAND; 68 | } 69 | if(tmp=='|'&&cur_char=='|'){ 70 | cur_char=getc(infile); 71 | return TKOR; 72 | } 73 | if(tmp==':'&&cur_char=='='){ 74 | cur_char=getc(infile); 75 | return TKASSIGN; 76 | } 77 | return tmp; 78 | } 79 | 80 | -------------------------------------------------------------------------------- /misra_errors.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leffmann/vbcc/dbc4a369692e2ef3739ab8da29fb1c264731b7e6/misra_errors.h -------------------------------------------------------------------------------- /opt.h: -------------------------------------------------------------------------------- 1 | /* $VER: vbcc (opt.h) $Revision: 1.4 $ */ 2 | 3 | #include "supp.h" 4 | 5 | extern int gchanged; /* Merker, ob Optimierungslauf etwas geaendert hat */ 6 | extern int norek; /* diese Funktion wird nicht rekursiv auf */ 7 | extern int nocall; /* diese Funktion kehrt nicht zum Caller zurueck */ 8 | extern int inr; /* number of num_Vars iteration */ 9 | 10 | /* temporary fuer verschiedene Bitvektoren */ 11 | extern bvtype *tmp; 12 | 13 | /* fuer aktive Variablen */ 14 | extern Var **vilist; 15 | extern unsigned int vcount; /* 0..vcount-rcount-1: vars, vcount-rcount..vcount: DREFOBJs */ 16 | extern unsigned int rcount; 17 | extern size_t vsize; 18 | extern bvtype *av_globals,*av_address,*av_statics,*av_drefs; 19 | extern int report_dead_statements; 20 | 21 | /* fuer verfuegbare Definitionen */ 22 | extern unsigned int dcount; 23 | extern size_t dsize; 24 | extern IC **dlist; 25 | extern bvtype **var_defs,**var_undefs; 26 | extern bvtype **defs_kill,**defs_gen; 27 | extern bvtype *rd_defs,*rd_tmp; 28 | extern bvtype *rd_matrix; 29 | #define UNDEF(x) (x+dcount) 30 | 31 | /* fuer verfuegbare Ausdruecke */ 32 | extern IC **elist; 33 | extern unsigned int ecount; 34 | extern size_t esize; 35 | extern bvtype *ae_globals,*ae_address,*ae_statics,*ae_drefs; 36 | 37 | /* fuer verfuegbare Kopien */ 38 | extern unsigned int ccount; 39 | extern size_t csize; 40 | extern IC **clist; 41 | 42 | /* fuer frequency-reduction */ 43 | extern bvtype *inloop,*invariant; 44 | 45 | /* alle Assignments, globaler oder Adr. fuer propagation etc. */ 46 | extern bvtype *cp_globals,*cp_address,*cp_statics,*cp_drefs,*cp_act,*cp_dest; 47 | /* alle Kopieranweisungen, die eine best. Variable als Quelle haben */ 48 | extern bvtype **copies; 49 | 50 | extern int have_alias; 51 | extern int static_cse,dref_cse; 52 | 53 | typedef struct { 54 | union atyps min,max; 55 | } range; 56 | 57 | extern range *rangebuf; 58 | 59 | typedef struct flowgraph{ 60 | IC *start,*end; 61 | struct flowgraph *normalout,*branchout; 62 | struct flowlist *in; 63 | int index; 64 | /* Letzter Block der Schleife, falls Block Start einer Schleife ist */ 65 | struct flowgraph *loopend; 66 | /* Anzahl Funktionsaufrufe im Block/der Schleife */ 67 | int calls,loop_calls; 68 | /* Bitvektoren fuer aktive Variablen, reaching-definitions, 69 | available-expressions und available-copies */ 70 | bvtype *av_in,*av_out,*av_gen,*av_kill; 71 | bvtype *rd_in,*rd_out,*rd_gen,*rd_kill; 72 | bvtype *ae_in,*ae_out,*ae_gen,*ae_kill; 73 | bvtype *cp_in,*cp_out,*cp_gen,*cp_kill; 74 | /* points-to-info */ 75 | bvtype **pt; 76 | /* range-info */ 77 | range *ra_normalout,*ra_branchout; 78 | /* Registervariablen */ 79 | Var *regv[MAXR+1]; 80 | /* Merker, ob Register gebraucht wurde; MACR+1 Bits */ 81 | bvtype regused[RSIZE/sizeof(bvtype)]; 82 | #ifdef ALEX_REG 83 | int loop_depth; /* schleifentiefe des blocks. Wird nur fuer echte Schleifen gezaehlt. */ 84 | #endif 85 | } flowgraph; 86 | 87 | extern unsigned int basic_blocks; 88 | 89 | typedef struct flowlist{ 90 | flowgraph *graph; 91 | struct flowlist *next; 92 | } flowlist; 93 | 94 | int compare_const(union atyps *q1,union atyps *q2,int t); 95 | int compare_objs(obj *o1,obj *o2,int t); 96 | void simple_regs(void); 97 | void load_simple_reg_parms(void); 98 | void remove_IC_fg(flowgraph *g,IC *p); 99 | 100 | extern int lastlabel; 101 | 102 | flowgraph *new_flowgraph(void); 103 | flowgraph *construct_flowgraph(void); 104 | void print_av(bvtype *bitvector); 105 | void print_rd(bvtype *bitvector); 106 | void print_ae(bvtype *bitvector); 107 | void print_cp(bvtype *bitvector); 108 | void print_flowgraph(flowgraph *g); 109 | void free_flowgraph(flowgraph *g); 110 | void num_vars(void); 111 | void print_vi(void); 112 | void av_change(IC *p,bvtype *use,bvtype *def); 113 | void av_update(IC *,bvtype *); 114 | void active_vars(flowgraph *fg); 115 | int dead_assignments(flowgraph *fg); 116 | void insert_IC(IC *p,IC *new); 117 | void insert_IC_fg(flowgraph *fg,IC *p,IC *new); 118 | void insert_allocreg(flowgraph *fg,IC *p,int code,int reg); 119 | void used_objects(Var *); 120 | void used_clist(type *,const_list *); 121 | void fix_shortop(flowgraph *,IC *); 122 | 123 | extern Var *lregv[MAXR+1],*first_const,*last_const; 124 | extern flowgraph *lfg; 125 | 126 | extern int report_weird_code,report_suspicious_loops,pointer_call; 127 | 128 | int replace_local_reg(obj *); 129 | void local_regs(flowgraph *); 130 | void local_combine(flowgraph *); 131 | void create_const_vars(flowgraph *); 132 | void free_const_vars(void); 133 | void loop_regs(flowgraph *,int); 134 | void block_regs(flowgraph *); 135 | void insert_saves(flowgraph *); 136 | flowgraph *jump_optimization(void); 137 | void num_defs(void); 138 | void reaching_definitions(flowgraph *); 139 | void rd_change(IC *); 140 | void calc(int c,int t,union atyps *q1,union atyps *q2,union atyps *z,IC *p); 141 | int fold(IC *p); 142 | int peephole(void); 143 | int propagate(IC *p,obj *o,int replace,int global); 144 | int constant_propagation(flowgraph *fg,int global); 145 | int compare_exp(const void *a1,const void *a2); 146 | void num_exp(void); 147 | void available_expressions(flowgraph *fg); 148 | void available_copies(flowgraph *fg); 149 | int cse(flowgraph *fg,int global); 150 | void num_copies(void); 151 | int copy_propagation(flowgraph *fg,int global); 152 | int loops(flowgraph *fg,int mode); 153 | flowgraph *create_loop_headers(flowgraph *fg,int av); 154 | flowgraph *create_loop_footers(flowgraph *fg,int av); 155 | void insert_regs(flowgraph *fg); 156 | void recalc_offsets(flowgraph *fg); 157 | void optimize(long flags,Var *function); 158 | int loop_optimizations(flowgraph *fg); 159 | int decide_reverse(zmax); 160 | void range_analysis(flowgraph *fg); 161 | void ic_uses(IC *p,bvtype *result); 162 | void ic_changes(IC *p,bvtype *result); 163 | void create_alias(flowgraph *fg); 164 | void free_alias(flowgraph *fg); 165 | void update_alias(Var *old,Var *new); 166 | void print_pt(bvtype **); 167 | void free_pt(bvtype **); 168 | #define CALC_CALLS 1 169 | #define CALC_USES 2 170 | #define CALC_CHANGES 4 171 | void calc_finfo(Var *,int); 172 | -------------------------------------------------------------------------------- /osek_supp.h: -------------------------------------------------------------------------------- 1 | /* used for special operating system support */ 2 | extern bvtype task_preempt_regs[],task_schedule_regs[]; 3 | typedef struct tasklist { 4 | struct Var *v; 5 | int prio; 6 | int taskid; 7 | enum {NON_PREEMPTIVE=1,DOES_BLOCK=2,CALLS_SCHED=4,ISR=8} flags; 8 | bvtype context[BVSIZE(MAXR+1)/sizeof(bvtype)]; 9 | bvtype preempt_context[BVSIZE(MAXR+1)/sizeof(bvtype)]; 10 | bvtype schedule_context[BVSIZE(MAXR+1)/sizeof(bvtype)]; 11 | bvtype unsaved_context[BVSIZE(MAXR+1)/sizeof(bvtype)]; 12 | } tasklist; 13 | 14 | -------------------------------------------------------------------------------- /osekrm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define BSIZE 4196 6 | char buf[BSIZE]; 7 | 8 | int main() 9 | { 10 | int nest=0; 11 | while(fgets(buf,BSIZE,stdin)){ 12 | if(nest==0){ 13 | fputs(buf,stdout); 14 | if(!strncmp(buf,"#if HAVE_OSEK",12)||!strncmp(buf,"#ifdef HAVE_MISRA",17)||!strncmp(buf,"#ifdef HAVE_ECPP",16)) 15 | nest++; 16 | }else{ 17 | if(!strncmp(buf,"#endif",6)) 18 | nest--; 19 | if(!strncmp(buf,"#if",3)) 20 | nest++; 21 | if(nest==1&&!strncmp(buf,"#else",5)) 22 | fputs("illegal #else found",stderr); 23 | if(nest==1&&!strncmp(buf,"#elif",5)) 24 | fputs("illegal #elif found",stderr); 25 | if(nest==0) 26 | fputs(buf,stdout); 27 | else 28 | puts("/* removed */"); 29 | } 30 | } 31 | return 0; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /pptst.h: -------------------------------------------------------------------------------- 1 | test 2 | hello 3 | con\ 4 | catenated 5 | not\ 6 | concatenated 7 | ??= 8 | ??( 9 | ??/ 10 | ??) 11 | ??' 12 | ??< 13 | ??! 14 | ??> 15 | ??- 16 | From standard: printf("Eh???/n"); 17 | con??/ 18 | catenated with trigraph 19 | 20 | # /* */ define fail succeed 21 | fail 22 | #undef fail 23 | #define fail succeed 24 | fail 25 | 26 | #define x(a,b) a+b 27 | 28 | x(12 29 | 23 30 | , 31 | 34 32 | 45 33 | ) 34 | 35 | -------------------------------------------------------------------------------- /range.c: -------------------------------------------------------------------------------- 1 | /* $VER: vbcc (range.c) $Revision: 1.1 $ */ 2 | /* range analysis and related optimizations */ 3 | 4 | #include "opt.h" 5 | 6 | static char FILE_[]=__FILE__; 7 | 8 | 9 | #define RANGESIZE (sizeof(range)*(vcount+1)) 10 | 11 | range *rangebuf; 12 | 13 | static void clear_range(range *p,int i) 14 | { 15 | Var *v; 16 | int t; 17 | 18 | v=vilist[i]; 19 | t=v->vtyp->flags; 20 | if(ISINT(t)){ 21 | if(t&UNSIGNED){ 22 | p[i].min.vumax=Z0; 23 | p[i].max.vumax=tu_max[t&NQ]; 24 | }else{ 25 | p[i].min.vmax=t_min[t&NQ]; 26 | p[i].max.vmax=t_max[t&NQ]; 27 | } 28 | } 29 | } 30 | 31 | void print_ranges(FILE *f,range *p) 32 | { 33 | int i,t; 34 | Var *v; 35 | for(i=0;ivtyp->flags; 38 | if(ISINT(t)){ 39 | fprintf(f,"%03d %s (%p): ",i,v->identifier,v); 40 | if(t&UNSIGNED){ 41 | printzum(f,p[i].min.vumax); 42 | fprintf(f,"..."); 43 | printzum(f,p[i].max.vumax); 44 | }else{ 45 | printzm(f,p[i].min.vmax); 46 | fprintf(f,"..."); 47 | printzm(f,p[i].max.vmax); 48 | } 49 | fprintf(f,"\n"); 50 | } 51 | } 52 | } 53 | 54 | static void combine_ranges(range *d,range *n) 55 | { 56 | int i,t; 57 | Var *v; 58 | for(i=0;ivtyp->flags; 61 | if(ISINT(t)){ 62 | if(t&UNSIGNED){ 63 | if(zumleq(n[i].min.vumax,d[i].min.vumax)) 64 | d[i].min.vumax=n[i].min.vumax; 65 | if(zumleq(d[i].max.vumax,n[i].max.vumax)) 66 | d[i].max.vumax=n[i].max.vumax; 67 | }else{ 68 | if(zmleq(n[i].min.vmax,d[i].min.vmax)) 69 | d[i].min.vmax=n[i].min.vmax; 70 | if(zmleq(d[i].max.vmax,n[i].max.vmax)) 71 | d[i].max.vmax=n[i].max.vmax; 72 | } 73 | } 74 | } 75 | } 76 | 77 | static int update_ranges(range *d,range *n) 78 | { 79 | int i,t,change=0; 80 | Var *v; 81 | for(i=0;ivtyp->flags; 84 | if(ISINT(t)){ 85 | if(t&UNSIGNED){ 86 | if(!zumeqto(n[i].min.vumax,d[i].min.vumax)){ 87 | d[i].min.vumax=n[i].min.vumax; 88 | change=1; 89 | } 90 | if(!zumeqto(d[i].max.vumax,n[i].max.vumax)){ 91 | d[i].max.vumax=n[i].max.vumax; 92 | change=1; 93 | } 94 | }else{ 95 | if(!zmeqto(n[i].min.vmax,d[i].min.vmax)){ 96 | d[i].min.vmax=n[i].min.vmax; 97 | change=1; 98 | } 99 | if(!zmeqto(d[i].max.vmax,n[i].max.vmax)){ 100 | d[i].max.vmax=n[i].max.vmax; 101 | change=1; 102 | } 103 | } 104 | } 105 | } 106 | return change; 107 | } 108 | 109 | void do_ranges(range *d,IC *p) 110 | { 111 | int i,j,t,c=p->code; 112 | if((p->z.flags&(VAR|DREFOBJ))==VAR){ 113 | i=p->z.v->index; 114 | t=p->z.v->vtyp->flags; 115 | if(c==ASSIGN){ 116 | if((p->typf&NU)!=(t&NU)){ 117 | clear_range(d,i); 118 | }else if((p->q1.flags&(KONST|DREFOBJ))==KONST){ 119 | eval_const(&p->q1.val,t); 120 | if(t&UNSIGNED) 121 | d[i].min.vumax=d[i].max.vumax=vumax; 122 | else 123 | d[i].min.vmax=d[i].max.vmax=vmax; 124 | }else if((p->q1.flags&(VAR|DREFOBJ))==VAR&&(p->q1.v->vtyp->flags&NU)==(t&NU)){ 125 | j=p->q1.v->index; 126 | d[i].min=d[j].min; 127 | d[i].max=d[j].max; 128 | }else 129 | clear_range(d,i); 130 | }else{ 131 | clear_range(d,i); 132 | } 133 | }else{ 134 | j=p->change_cnt; 135 | for(i=0;ichange_list[i].flags&DREFOBJ)) 137 | clear_range(d,p->change_list[i].v->index); 138 | } 139 | } 140 | } 141 | 142 | static void insert_max(range *p,int t) 143 | { 144 | if(t&UNSIGNED){ 145 | if(!zumleq(p->max.vumax,vumax)) 146 | p->max.vumax=vumax; 147 | if(!zumleq(p->min.vumax,p->max.vumax)) 148 | p->min.vumax=vumax; 149 | }else{ 150 | if(!zmleq(p->max.vmax,vmax)) 151 | p->max.vmax=vmax; 152 | if(!zmleq(p->min.vmax,p->max.vmax)) 153 | p->min.vmax=vmax; 154 | } 155 | } 156 | 157 | static void insert_min(range *p,int t) 158 | { 159 | if(t&UNSIGNED){ 160 | if(!zumleq(vumax,p->min.vumax)) 161 | p->min.vumax=vumax; 162 | if(!zumleq(p->min.vumax,p->max.vumax)) 163 | p->max.vumax=vumax; 164 | }else{ 165 | if(!zmleq(vmax,p->min.vmax)) 166 | p->min.vmax=vmax; 167 | if(!zmleq(p->min.vmax,p->max.vmax)) 168 | p->max.vmax=vmax; 169 | } 170 | } 171 | 172 | static void inc_val(int t) 173 | { 174 | if(t&UNSIGNED){ 175 | if(!zumeqto(vumax,tu_max[t&NU])) 176 | vumax=zumadd(vumax,ZU1); 177 | }else{ 178 | if(!zmeqto(vmax,t_max[t&NU])) 179 | vmax=zmadd(vmax,Z1); 180 | } 181 | } 182 | 183 | static void dec_val(int t) 184 | { 185 | if(t&UNSIGNED){ 186 | if(!zumeqto(vumax,ZU0)) 187 | vumax=zumsub(vumax,ZU1); 188 | }else{ 189 | if(!zmeqto(vmax,t_min[t&NU])) 190 | vmax=zmsub(vmax,Z1); 191 | } 192 | } 193 | 194 | void range_analysis(flowgraph *fg) 195 | { 196 | flowgraph *g; 197 | range *bp,*erange,*crange; 198 | Var *v; 199 | int i,t,done,pass; 200 | rangebuf=mymalloc(RANGESIZE*(2*basic_blocks+3)); 201 | bp=rangebuf; 202 | for(i=0;inormalout){ 207 | g->ra_normalout=bp; 208 | memcpy(bp,erange,RANGESIZE); 209 | bp+=RANGESIZE; 210 | g->ra_branchout=bp; 211 | memcpy(bp,erange,RANGESIZE); 212 | bp+=RANGESIZE; 213 | } 214 | crange=bp; 215 | 216 | pass=1; 217 | do{ 218 | if(DEBUG&1024) printf("range analysis pass %d\n",pass); 219 | done=1; 220 | for(g=fg;g;g=g->normalout){ 221 | flowlist *lp; 222 | IC *p; 223 | int c,first=1; 224 | memcpy(crange,erange,RANGESIZE); 225 | for(lp=g->in;lp;lp=lp->next){ 226 | if(lp->graph->normalout==g&&(!lp->graph->end||lp->graph->end->code!=BRA)){ 227 | if(first){ 228 | memcpy(crange,lp->graph->ra_normalout,RANGESIZE); 229 | first=0; 230 | }else 231 | combine_ranges(crange,lp->graph->ra_normalout); 232 | } 233 | if(lp->graph->branchout==g){ 234 | if(first) { 235 | memcpy(crange,lp->graph->ra_branchout,RANGESIZE); 236 | first=0; 237 | }else 238 | combine_ranges(crange,lp->graph->ra_branchout); 239 | } 240 | } 241 | if(DEBUG&131072){ 242 | printf("block %d, input:\n",g->index); 243 | print_ranges(stdout,crange); 244 | } 245 | for(p=g->start;p;p=p->next){ 246 | do_ranges(crange,p); 247 | if(p==g->end||p->code==TEST||p->code==COMPARE) break; 248 | } 249 | if(p) c=p->code; else c=0; 250 | if(c==COMPARE||c==TEST){ 251 | if((p->q1.flags&(VAR|DREFOBJ))==VAR&&(c==TEST||(p->q2.flags&(KONST|DREFOBJ))==KONST)){ 252 | IC *b=p->next; 253 | range tmp; 254 | while(b&&b->codecode>BGT) b=b->next; 255 | if(!b) ierror(0); 256 | if(c==TEST){ 257 | vmax=Z0; 258 | vumax=ZU0; 259 | }else 260 | eval_const(&p->q2.val,p->typf); 261 | i=p->q1.v->index; 262 | t=p->q1.v->vtyp->flags; 263 | if(b->code==BEQ){ 264 | if(update_ranges(g->ra_normalout,crange)) done=0; 265 | if(t&UNSIGNED) 266 | crange[i].min.vumax=crange[i].max.vumax=vumax; 267 | else 268 | crange[i].min.vmax=crange[i].max.vmax=vmax; 269 | if(update_ranges(g->ra_branchout,crange)) done=0; 270 | }else if(b->code==BNE){ 271 | if(update_ranges(g->ra_branchout,crange)) done=0; 272 | if(t&UNSIGNED) 273 | crange[i].min.vumax=crange[i].min.vumax=vumax; 274 | else 275 | crange[i].max.vumax=crange[i].max.vumax=vumax; 276 | if(update_ranges(g->ra_normalout,crange)) done=0; 277 | }else if(b->code==BLT||b->code==BLE){ 278 | tmp=crange[i]; 279 | if(b->code==BLT) dec_val(t); 280 | insert_max(&crange[i],t); 281 | if(update_ranges(g->ra_branchout,crange)) done=0; 282 | crange[i]=tmp; 283 | inc_val(t); 284 | insert_min(&crange[i],t); 285 | if(update_ranges(g->ra_normalout,crange)) done=0; 286 | }else if(b->code==BGE||b->code==BGT){ 287 | tmp=crange[i]; 288 | if(b->code==BGT) inc_val(t); 289 | insert_min(&crange[i],t); 290 | if(update_ranges(g->ra_branchout,crange)) done=0; 291 | crange[i]=tmp; 292 | dec_val(t); 293 | insert_max(&crange[i],t); 294 | if(update_ranges(g->ra_normalout,crange)) done=0; 295 | }else 296 | ierror(0); 297 | }else{ 298 | if(update_ranges(g->ra_branchout,crange)) done=0; 299 | if(update_ranges(g->ra_normalout,crange)) done=0; 300 | } 301 | }else{ 302 | if(g->branchout){ 303 | /* must be BRA as we checked for COMPARE/TEST above */ 304 | if(update_ranges(g->ra_branchout,crange)) 305 | done=0; 306 | }else{ 307 | if(update_ranges(g->ra_normalout,crange)) 308 | done=0; 309 | } 310 | } 311 | if(DEBUG&131072){ 312 | printf("ra_branchout:\n"); 313 | print_ranges(stdout,g->ra_branchout); 314 | printf("ra_normalout:\n"); 315 | print_ranges(stdout,g->ra_normalout); 316 | } 317 | } 318 | pass++; 319 | }while(!done); 320 | 321 | 322 | } 323 | -------------------------------------------------------------------------------- /t1.h: -------------------------------------------------------------------------------- 1 | /* $Revision: 1.2 $ */ 2 | 3 | #include "t2.h" 4 | 5 | -------------------------------------------------------------------------------- /t2.h: -------------------------------------------------------------------------------- 1 | t2 is here 2 | 3 | -------------------------------------------------------------------------------- /tasm.c: -------------------------------------------------------------------------------- 1 | /* Test-language for vbcc. */ 2 | 3 | #include "supp.h" 4 | 5 | struct Var *fv; 6 | 7 | struct Typ tint,mfunc; 8 | struct struct_declaration msd; /* initialized to zero */ 9 | 10 | void raus(void) 11 | { 12 | while(fv){ 13 | struct Var *m=fv->next; 14 | free(fv); 15 | fv=m; 16 | } 17 | while(first_ic){ 18 | struct IC *m=first_ic->next; 19 | free(first_ic); 20 | first_ic=m; 21 | } 22 | exit(0); 23 | } 24 | void add_IC(struct IC *new) 25 | { 26 | new->next=0; 27 | new->prev=last_ic; 28 | new->change_cnt=new->use_cnt=0; 29 | new->change_list=new->use_list=0; 30 | new->line=0; 31 | new->file=0; 32 | if(!last_ic){ 33 | first_ic=new; 34 | }else{ 35 | last_ic->next=new; 36 | } 37 | last_ic=new; 38 | } 39 | struct Var *add_var(char *name,struct Typ *t,int sc) 40 | { 41 | struct Var *v=mymalloc(sizeof(*v)); 42 | v->vtyp=t; 43 | v->storage_class=sc; 44 | v->reg=0; 45 | v->identifier=name; 46 | v->offset=max_offset; 47 | if(sc==AUTO) max_offset=zmadd(max_offset,sizetab[t->flags&NQ]); 48 | v->priority=1; 49 | v->flags=0; 50 | v->next=fv; 51 | v->clist=0; 52 | v->fi=0; 53 | v->inline_copy=0; 54 | fv=v; 55 | return v; 56 | } 57 | struct Var *add_tmp_var(struct Typ *t) 58 | { 59 | return add_var(empty,t,AUTO); 60 | } 61 | struct Var *get_var(char *name) 62 | { 63 | struct Var *v;char *buf; 64 | for(v=fv;v;v=v->next){ 65 | if(!strcmp(name,v->identifier)) return v; 66 | } 67 | buf=mymalloc(strlen(name)+1); 68 | strcpy(buf,name); 69 | return add_var(buf,&tint,AUTO); 70 | } 71 | 72 | void read_ics() 73 | { 74 | char s[400],q1[100],q2[100],z[100],op; 75 | struct IC *new; 76 | gets(s); 77 | while(sscanf(s,"%99s = %99s %c %99s",z,q1,&op,q2)==4){ 78 | new=new_IC(); 79 | switch(op){ 80 | case '+': new->code=ADD;break; 81 | case '*': new->code=MULT;break; 82 | case '-': new->code=SUB;break; 83 | case '/': new->code=DIV;break; 84 | default: return; 85 | } 86 | new->typf=INT; 87 | new->q1.flags=new->q2.flags=new->z.flags=VAR; 88 | new->q1.am=new->q2.am=new->z.am=0; 89 | new->q1.val.vmax=l2zm(0L); 90 | new->q2.val.vmax=l2zm(0L); 91 | new->z.val.vmax=l2zm(0L); 92 | new->q1.v=get_var(q1); 93 | new->q2.v=get_var(q2); 94 | new->z.v=get_var(z); 95 | add_IC(new); 96 | gets(s); 97 | } 98 | } 99 | void error(int n,...) 100 | { 101 | printf("error %d\n",n); 102 | raus(); 103 | } 104 | void savescratch() 105 | {} 106 | 107 | main() 108 | { 109 | struct Var *main; 110 | max_offset=l2zm(0L); 111 | if(!init_cg()) raus(); 112 | tint.flags=INT; 113 | tint.next=0; 114 | mfunc.flags=FUNKT; 115 | mfunc.next=∭ 116 | mfunc.exact=&msd; 117 | main=add_var("main",&mfunc,EXTERN); 118 | read_ics(); 119 | printf("optflags: "); 120 | scanf("%ld",&optflags); 121 | pric(stdout,first_ic); 122 | vl1=vl3=0; 123 | vl2=fv; 124 | optimize(optflags,main); 125 | pric(stdout,first_ic); 126 | gen_code(stdout,first_ic,main,max_offset); 127 | raus(); 128 | } 129 | -------------------------------------------------------------------------------- /tt.h: -------------------------------------------------------------------------------- 1 | test1 2 | test2 3 | 4 | -------------------------------------------------------------------------------- /type_expr.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leffmann/vbcc/dbc4a369692e2ef3739ab8da29fb1c264731b7e6/type_expr.c -------------------------------------------------------------------------------- /ucpp/README: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leffmann/vbcc/dbc4a369692e2ef3739ab8da29fb1c264731b7e6/ucpp/README -------------------------------------------------------------------------------- /ucpp/hash.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Generic hash table routines. 3 | * (c) Thomas Pornin 1998, 1999, 2000 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 4. The name of the authors may not be used to endorse or promote 14 | * products derived from this software without specific prior written 15 | * permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 23 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 27 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | * 29 | */ 30 | 31 | #include 32 | #include "hash.h" 33 | #include "mem.h" 34 | 35 | /* 36 | * hash_string() is a sample hash function for strings 37 | */ 38 | int hash_string(char *s) 39 | { 40 | unsigned char h = 0; 41 | 42 | for (; *s; s ++) h ^= (unsigned char)(*s); 43 | return ((int)h); 44 | } 45 | 46 | /* 47 | * struct hash_item is the basic data type to internally handle hash tables 48 | */ 49 | struct hash_item { 50 | void *data; 51 | struct hash_item *next; 52 | }; 53 | 54 | /* 55 | * This function adds an entry to the struct hash_item list 56 | */ 57 | static struct hash_item *add_entry(struct hash_item *blist, void *data) 58 | { 59 | struct hash_item *t = getmem(sizeof(struct hash_item)); 60 | 61 | t->data = data; 62 | t->next = blist; 63 | return t; 64 | } 65 | 66 | /* 67 | * This function finds a struct hash_item in a list, using the 68 | * comparison function provided as cmpdata (*cmpdata() returns 69 | * non-zero if the two parameters are to be considered identical). 70 | * 71 | * It returns 0 if the item is not found. 72 | */ 73 | static struct hash_item *get_entry(struct hash_item *blist, void *data, 74 | int (*cmpdata)(void *, void *)) 75 | { 76 | while (blist) { 77 | if ((*cmpdata)(data, blist->data)) return blist; 78 | blist = blist->next; 79 | } 80 | return 0; 81 | } 82 | 83 | /* 84 | * This function acts like get_entry but deletes the found item, using 85 | * the provided function deldata(); it returns 0 if the given data was 86 | * not found. 87 | */ 88 | static struct hash_item *del_entry(struct hash_item *blist, void *data, 89 | int (*cmpdata)(void *, void *), void (*deldata)(void *)) 90 | { 91 | struct hash_item *prev = 0, *save = blist; 92 | 93 | while (blist) { 94 | if ((*cmpdata)(data, blist->data)) { 95 | (*deldata)(blist->data); 96 | if (prev) prev->next = blist->next; 97 | if (save == blist) save = blist->next; 98 | freemem(blist); 99 | return save; 100 | } 101 | prev = blist; 102 | blist = blist->next; 103 | } 104 | return 0; 105 | } 106 | 107 | /* 108 | * This function creates a new hashtable, with the hashing and comparison 109 | * functions given as parameters 110 | */ 111 | struct HT *newHT(int n, int (*cmpdata)(void *, void *), int (*hash)(void *), 112 | void (*deldata)(void *)) 113 | { 114 | struct HT *t = getmem(sizeof(struct HT)); 115 | int i; 116 | 117 | t->lists = getmem(n * sizeof(struct hash_item *)); 118 | for (i = 0; i < n; i ++) t->lists[i] = 0; 119 | t->nb_lists = n; 120 | t->cmpdata = cmpdata; 121 | t->hash = hash; 122 | t->deldata = deldata; 123 | return t; 124 | } 125 | 126 | /* 127 | * This function adds a new entry in the hashtable ht; it returns 0 128 | * on success, or a pointer to the already present item otherwise. 129 | */ 130 | void *putHT(struct HT *ht, void *data) 131 | { 132 | int h; 133 | struct hash_item *d; 134 | 135 | h = ((*(ht->hash))(data)) % ht->nb_lists; 136 | if ((d = get_entry(ht->lists[h], data, ht->cmpdata))) 137 | return d->data; 138 | ht->lists[h] = add_entry(ht->lists[h], data); 139 | return 0; 140 | } 141 | 142 | /* 143 | * This function adds a new entry in the hashtable ht, even if an equal 144 | * entry is already there. Exercise caution ! 145 | * The new entry will "hide" the old one, which means that the new will be 146 | * found upon lookup/delete, not the old one. 147 | */ 148 | void *forceputHT(struct HT *ht, void *data) 149 | { 150 | int h; 151 | 152 | h = ((*(ht->hash))(data)) % ht->nb_lists; 153 | ht->lists[h] = add_entry(ht->lists[h], data); 154 | return 0; 155 | } 156 | 157 | /* 158 | * This function finds the entry corresponding to *data in the 159 | * hashtable ht (using the comparison function given as argument 160 | * to newHT) 161 | */ 162 | void *getHT(struct HT *ht, void *data) 163 | { 164 | int h; 165 | struct hash_item *t; 166 | 167 | h = ((*(ht->hash))(data)) % ht->nb_lists; 168 | if ((t = get_entry(ht->lists[h], data, ht->cmpdata)) == 0) 169 | return 0; 170 | return (t->data); 171 | } 172 | 173 | /* 174 | * This function finds and delete the entry corresponding to *data 175 | * in the hashtable ht (using the comparison function given as 176 | * argument to newHT). 177 | */ 178 | 179 | int delHT(struct HT *ht, void *data) 180 | { 181 | int h; 182 | 183 | h = ((*(ht->hash))(data)) % ht->nb_lists; 184 | ht->lists[h] = del_entry(ht->lists[h], data, ht->cmpdata, ht->deldata); 185 | return 1; 186 | } 187 | 188 | /* 189 | * This function duplicates a given hash table; the data is not copied 190 | */ 191 | struct HT *copyHT(struct HT *ht) 192 | { 193 | struct HT *nht = newHT(ht->nb_lists, ht->cmpdata, ht->hash, 194 | ht->deldata); 195 | struct hash_item *t; 196 | int i, j; 197 | 198 | for (i = 0; i < nht->nb_lists; i ++) { 199 | j = 0; 200 | t = ht->lists[i]; 201 | while (t) { 202 | t = t->next; 203 | j ++; 204 | } 205 | if (j != 0) { 206 | nht->lists[i] = getmem(j * sizeof(struct hash_item)); 207 | mmv(nht->lists[i], ht->lists[i], 208 | j * sizeof(struct hash_item)); 209 | } 210 | } 211 | return nht; 212 | } 213 | 214 | /* 215 | * This function completely eradicates from memory a given hash table, 216 | * releasing all objects 217 | */ 218 | void killHT(struct HT *ht) 219 | { 220 | int i; 221 | struct hash_item *t, *n; 222 | 223 | for (i = 0; i < ht->nb_lists; i ++) for (t = ht->lists[i]; t;) { 224 | n = t->next; 225 | (*(ht->deldata))(t->data); 226 | freemem(t); 227 | t = n; 228 | } 229 | freemem(ht); 230 | } 231 | 232 | /* 233 | * This function stores a backup of the hash table, for context stacking 234 | */ 235 | void saveHT(struct HT *ht, void **buffer) 236 | { 237 | struct hash_item **b = (struct hash_item **)buffer; 238 | int i; 239 | 240 | for (i = 0; i < ht->nb_lists; i ++) b[i] = ht->lists[i]; 241 | } 242 | 243 | /* 244 | * This function restores the saved state of the hash table. 245 | * Do NOT use if some of the entries that were present before the backup 246 | * have been removed (even temporarily). 247 | */ 248 | void restoreHT(struct HT *ht, void **buffer) 249 | { 250 | struct hash_item **b = (struct hash_item **)buffer; 251 | int i; 252 | 253 | for (i = 0; i < ht->nb_lists; i ++) { 254 | struct hash_item *t = ht->lists[i], *n; 255 | 256 | while (t != b[i]) { 257 | n = t->next; 258 | (*(ht->deldata))(t->data); 259 | freemem(t); 260 | t = n; 261 | } 262 | ht->lists[i] = b[i]; 263 | } 264 | } 265 | 266 | /* 267 | * This function scans the whole table and calls the given function on 268 | * each entry. 269 | */ 270 | void scanHT(struct HT *ht, void (*action)(void *)) 271 | { 272 | int i; 273 | 274 | for (i = 0; i < ht->nb_lists; i ++) { 275 | struct hash_item *t = ht->lists[i]; 276 | 277 | while (t) { 278 | (*action)(t->data); 279 | t = t->next; 280 | } 281 | } 282 | } 283 | 284 | /* 285 | * The two following fonctions are generic for storing structures 286 | * uniquely identified by their name, which must be the first 287 | * field of the structure. 288 | */ 289 | int hash_struct(void *m) 290 | { 291 | char *n = *(char **)m; 292 | 293 | return hash_string(n) & 127; 294 | } 295 | 296 | int cmp_struct(void *m1, void *m2) 297 | { 298 | char *n1 = *(char **)m1, *n2 = *(char **)m2; 299 | 300 | return !strcmp(n1, n2); 301 | } 302 | -------------------------------------------------------------------------------- /ucpp/hash.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Thomas Pornin 1998, 1999, 2000 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions 6 | * are met: 7 | * 1. Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * 2. Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * 4. The name of the authors may not be used to endorse or promote 13 | * products derived from this software without specific prior written 14 | * permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 22 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 26 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | */ 29 | 30 | #ifndef UCPP__HASH__ 31 | #define UCPP__HASH__ 32 | 33 | struct hash_item; 34 | 35 | struct HT { 36 | struct hash_item **lists; 37 | int nb_lists; 38 | int (*cmpdata)(void *, void *); 39 | int (*hash)(void *); 40 | void (*deldata)(void *); 41 | }; 42 | 43 | int hash_string(char *); 44 | struct HT *newHT(int, int (*)(void *, void *), int (*)(void *), 45 | void (*)(void *)); 46 | void *putHT(struct HT *, void *); 47 | void *forceputHT(struct HT *, void *); 48 | void *getHT(struct HT *, void *); 49 | int delHT(struct HT *, void *); 50 | struct HT *copyHT(struct HT *); 51 | void killHT(struct HT *); 52 | void saveHT(struct HT *, void **); 53 | void restoreHT(struct HT *, void **); 54 | void scanHT(struct HT *, void (*)(void *)); 55 | int hash_struct(void *); 56 | int cmp_struct(void *, void *); 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /ucpp/mem.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Memory manipulation routines 3 | * (c) Thomas Pornin 1998, 1999, 2000 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 4. The name of the authors may not be used to endorse or promote 14 | * products derived from this software without specific prior written 15 | * permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 23 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 27 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | * 29 | */ 30 | 31 | #include "mem.h" 32 | #include 33 | #include 34 | #include 35 | 36 | #ifdef AUDIT 37 | void die(void) 38 | { 39 | abort(); 40 | } 41 | 42 | static void suicide(unsigned long e) 43 | { 44 | fprintf(stderr, "ouch: Schrodinger's beef is not dead ! %lx\n", e); 45 | die(); 46 | } 47 | #else 48 | void die(void) 49 | { 50 | exit(1); 51 | } 52 | #endif 53 | 54 | #if defined AUDIT || defined MEM_CHECK 55 | /* 56 | * This function is equivalent to a malloc(), but will display an error 57 | * message and exit if the wanted memory is not available 58 | */ 59 | void *getmem(size_t x) 60 | { 61 | void *m; 62 | 63 | #ifdef AUDIT 64 | m = malloc(x + 8); 65 | #else 66 | m = malloc(x); 67 | #endif 68 | if (m == 0) { 69 | fprintf(stderr, "ouch: malloc() failed\n"); 70 | die(); 71 | } 72 | #ifdef AUDIT 73 | *((unsigned long *)m) = 0xdeadbeefUL; 74 | return (void *)(((char *)m) + 8); 75 | #else 76 | return m; 77 | #endif 78 | } 79 | #endif 80 | 81 | /* 82 | * This function is equivalent to a realloc(); if the realloc() call 83 | * fails, it will try a malloc() and a memcpy(). If not enough memory is 84 | * available, the program exits with an error message 85 | */ 86 | void *incmem(void *m, size_t x, size_t nx) 87 | { 88 | void *nm; 89 | 90 | #ifdef AUDIT 91 | m = (void *)(((char *)m) - 8); 92 | if (*((unsigned long *)m) != 0xdeadbeefUL) 93 | suicide(*((unsigned long *)m)); 94 | x += 8; nx += 8; 95 | #endif 96 | if (!(nm = realloc(m, nx))) { 97 | if (x > nx) x = nx; 98 | nm = getmem(nx); 99 | memcpy(nm, m, x); 100 | /* free() and not freemem(), because of the Schrodinger beef */ 101 | free(m); 102 | } 103 | #ifdef AUDIT 104 | return (void *)(((char *)nm) + 8); 105 | #else 106 | return nm; 107 | #endif 108 | } 109 | 110 | #ifdef AUDIT 111 | /* 112 | * This function frees the given block 113 | */ 114 | void freemem(void *x) 115 | { 116 | #ifdef AUDIT 117 | void *y = (void *)(((char *)x) - 8); 118 | 119 | if ((*((unsigned long *)y)) != 0xdeadbeefUL) 120 | suicide(*((unsigned long *)y)); 121 | *((unsigned long *)y) = 0xfeedbabeUL; 122 | free(y); 123 | #else 124 | free(x); 125 | #endif 126 | } 127 | #endif 128 | 129 | #ifdef AUDIT 130 | /* 131 | * This function copies n bytes from src to dest 132 | */ 133 | void *mmv(void *dest, void *src, size_t n) 134 | { 135 | return memcpy(dest, src, n); 136 | } 137 | 138 | /* 139 | * This function copies n bytes from src to dest 140 | */ 141 | void *mmvwo(void *dest, void *src, size_t n) 142 | { 143 | return memmove(dest, src, n); 144 | } 145 | #endif 146 | 147 | /* 148 | * This function creates a new char * and fills it with a copy of src 149 | */ 150 | char *sdup(char *src) 151 | { 152 | size_t n = 1 + strlen(src); 153 | char *x = getmem(n); 154 | 155 | mmv(x, src, n); 156 | return x; 157 | } 158 | -------------------------------------------------------------------------------- /ucpp/mem.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Thomas Pornin 1998, 1999, 2000 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions 6 | * are met: 7 | * 1. Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * 2. Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * 4. The name of the authors may not be used to endorse or promote 13 | * products derived from this software without specific prior written 14 | * permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 22 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 26 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | */ 29 | 30 | #ifndef UCPP__MEM__ 31 | #define UCPP__MEM__ 32 | 33 | #include 34 | 35 | void die(void); 36 | void *incmem(void *, size_t, size_t); 37 | char *sdup(char *); 38 | 39 | #if defined AUDIT || defined MEM_CHECK 40 | void *getmem(size_t); 41 | #else 42 | #define getmem malloc 43 | #endif 44 | 45 | #ifdef AUDIT 46 | void freemem(void *); 47 | #else 48 | #define freemem free 49 | #endif 50 | 51 | #ifdef AUDIT 52 | void *mmv(void *, void *, size_t); 53 | void *mmvwo(void *, void *, size_t); 54 | #else 55 | #define mmv memcpy 56 | #define mmvwo memmove 57 | #endif 58 | 59 | /* 60 | * this macro adds the object obj at the end of the array list, handling 61 | * memory allocation when needed; ptr contains the number of elements in 62 | * the array, and memg is the granularity of memory allocations (a power 63 | * of 2 is recommanded, for optimization reasons) 64 | * 65 | * list and ptr may be updated, and thus need to be lvalues 66 | */ 67 | #define aol(list,ptr,obj,memg) do { \ 68 | if (((ptr) % (memg)) == 0) { \ 69 | if ((ptr) != 0) { \ 70 | (list) = incmem((list), (ptr) * sizeof(obj), \ 71 | ((ptr) + (memg)) * sizeof(obj)); \ 72 | } else { \ 73 | (list) = getmem((memg) * sizeof(obj)); \ 74 | } \ 75 | } \ 76 | (list)[(ptr) ++] = (obj); \ 77 | } while (0) 78 | 79 | /* 80 | * bol() does the same as aol(), but adds the new item at the beginning 81 | * of the list; beware, the computational cost is greater. 82 | */ 83 | #define bol(list,ptr,obj,memg) do { \ 84 | if (((ptr) % (memg)) == 0) { \ 85 | if ((ptr) != 0) { \ 86 | (list) = incmem((list), (ptr) * sizeof(obj), \ 87 | ((ptr) + (memg)) * sizeof(obj)); \ 88 | } else { \ 89 | (list) = getmem((memg) * sizeof(obj)); \ 90 | } \ 91 | } \ 92 | if ((ptr) != 0) \ 93 | mmvwo((list) + 1, (list), (ptr) * sizeof(obj)); \ 94 | (ptr) ++; \ 95 | (list)[0] = (obj); \ 96 | } while (0) 97 | 98 | /* 99 | * mbol() does the same as bol(), but adds the new item at the given 100 | * emplacement; bol() is equivalent to mbol with 0 as last argument. 101 | */ 102 | #define mbol(list,ptr,obj,memg,n) do { \ 103 | if (((ptr) % (memg)) == 0) { \ 104 | if ((ptr) != 0) { \ 105 | (list) = incmem((list), (ptr) * sizeof(obj), \ 106 | ((ptr) + (memg)) * sizeof(obj)); \ 107 | } else { \ 108 | (list) = getmem((memg) * sizeof(obj)); \ 109 | } \ 110 | } \ 111 | if ((ptr) > n) \ 112 | mmvwo((list) + n + 1, (list) + n, \ 113 | ((ptr) - n) * sizeof(obj)); \ 114 | (ptr) ++; \ 115 | (list)[n] = (obj); \ 116 | } while (0) 117 | 118 | /* 119 | * this macro adds the object obj at the end of the array list, doubling 120 | * the size of list when needed; as for aol(), ptr and list must be 121 | * lvalues, and so must be llng 122 | */ 123 | 124 | #define wan(list,ptr,obj,llng) do { \ 125 | if ((ptr) == (llng)) { \ 126 | (llng) += (llng); \ 127 | (list) = incmem((list), (ptr) * sizeof(obj), \ 128 | (llng) * sizeof(obj)); \ 129 | } \ 130 | (list)[(ptr) ++] = (obj); \ 131 | } while (0) 132 | 133 | #endif 134 | -------------------------------------------------------------------------------- /ucpp/sample.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Sample code showing how to use ucpp as an integrated lexer. 3 | * This file is public domain. 4 | */ 5 | 6 | /* 7 | * This is an example of how to use ucpp as a preprocessor and lexer 8 | * into another project. The steps are those described in ucpp README 9 | * file. To use this code, compile the ucpp source files with 10 | * STAND_ALONE not defined, and link them with this code. The resulting 11 | * binary will take a C source file as standard input, preprocess it, 12 | * and output each non-whitespace token on stdout, with its numerical 13 | * value (defined as an enum in cpp.h) and its contents. This code 14 | * defines no system include path. 15 | * 16 | * This code supposes that the ucpp files are compiled with PRAGMA_TOKENIZE 17 | * enabled (see the tune.h file). 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include "mem.h" 24 | #include "cpp.h" 25 | 26 | int main(int argc, char *argv[]) 27 | { 28 | int i, r; 29 | struct lexer_state ls; 30 | 31 | /* step 1 */ 32 | init_cpp(); 33 | 34 | /* step 2 */ 35 | no_special_macros = 0; 36 | emit_defines = emit_assertions = 0; 37 | 38 | /* step 3 -- with assertions */ 39 | init_tables(1); 40 | 41 | /* step 4 -- no default include path */ 42 | init_include_path(0); 43 | 44 | /* step 5 -- no need to reset the two emit_* variables set in 2 */ 45 | emit_dependencies = 0; 46 | 47 | /* step 6 -- we work with stdin, this is not a real filename */ 48 | set_init_filename("[stdin]", 0); 49 | 50 | /* step 7 -- we make sure that assertions are on, and pragma are 51 | handled */ 52 | init_lexer_state(&ls); 53 | init_lexer_mode(&ls); 54 | ls.flags |= HANDLE_ASSERTIONS | HANDLE_PRAGMA | LINE_NUM; 55 | 56 | /* step 8 -- input is from stdin */ 57 | ls.input = stdin; 58 | 59 | /* step 9 -- we do not have any macro to define, but we add any 60 | argument as an include path */ 61 | for (i = 1; i < argc; i ++) add_incpath(argv[i]); 62 | 63 | /* step 10 -- we are a lexer and we want CONTEXT tokens */ 64 | enter_file(&ls, ls.flags); 65 | 66 | /* read tokens until end-of-input is reached -- errors (non-zero 67 | return values different from CPPERR_EOF) are ignored */ 68 | while ((r = lex(&ls)) < CPPERR_EOF) { 69 | if (r) { 70 | /* error condition -- no token was retrieved */ 71 | continue; 72 | } 73 | /* we print each token: its numerical value, and its 74 | string content; if this is a PRAGMA token, the 75 | string content is in fact a compressed token list, 76 | that we uncompress and print. */ 77 | if (ls.ctok->type == PRAGMA) { 78 | unsigned char *c = (unsigned char *)(ls.ctok->name); 79 | 80 | printf("line %ld: <#pragma>\n", ls.line); 81 | for (; *c; c ++) { 82 | int t = *c; 83 | 84 | if (STRING_TOKEN(t)) { 85 | printf(" <%2d> ", t); 86 | for (c ++; *c != PRAGMA_TOKEN_END; 87 | c ++) putchar(*c); 88 | putchar('\n'); 89 | } else { 90 | printf(" <%2d> `%s'\n", t, 91 | operators_name[t]); 92 | } 93 | } 94 | } else if (ls.ctok->type == CONTEXT) { 95 | printf("new context: file '%s', line %ld\n", 96 | ls.ctok->name, ls.ctok->line); 97 | } else if (ls.ctok->type == NEWLINE) { 98 | printf("[newline]\n"); 99 | } else { 100 | printf("line %ld: <%2d> `%s'\n", ls.ctok->line, 101 | ls.ctok->type, 102 | STRING_TOKEN(ls.ctok->type) ? ls.ctok->name 103 | : operators_name[ls.ctok->type]); 104 | } 105 | } 106 | return 0; 107 | } 108 | -------------------------------------------------------------------------------- /ucpp/ucppi.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Thomas Pornin 1999, 2000 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions 6 | * are met: 7 | * 1. Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * 2. Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * 4. The name of the authors may not be used to endorse or promote 13 | * products derived from this software without specific prior written 14 | * permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 22 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 26 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | */ 29 | 30 | #ifndef UCPP__UCPPI__ 31 | #define UCPP__UCPPI__ 32 | 33 | #include "cpp.h" 34 | #include "tune.h" 35 | 36 | /* 37 | * A macro represented in a compact form; simple tokens are represented 38 | * by one byte, containing their number. Tokens with a string value are 39 | * followed by the value (string finished by a 0). Macro arguments are 40 | * followed by the argument number (in one byte -- thus implying a hard 41 | * limit of 254 arguments (number 255 is for __VA_ARGS__). 42 | */ 43 | struct comp_token_fifo { 44 | size_t length; 45 | size_t rp; 46 | unsigned char *t; 47 | }; 48 | 49 | /* These declarations are used only internally by ucpp */ 50 | 51 | /* 52 | * S_TOKEN(x) checks whether x is a token type with an embedded string 53 | * ttMWS(x) checks whether x is macro whitespace (space, comment...) 54 | * ttWHI(x) checks whether x is whitespace (MWS or newline) 55 | */ 56 | #define S_TOKEN(x) STRING_TOKEN(x) 57 | #define ttMWS(x) ((x) == NONE || (x) == COMMENT || (x) == OPT_NONE) 58 | #define ttWHI(x) (ttMWS(x) || (x) == NEWLINE) 59 | 60 | /* 61 | * Function prototypes 62 | */ 63 | /* 64 | * from lexer.c 65 | */ 66 | #define init_cppm ucpp_init_cppm 67 | #define put_char ucpp_put_char 68 | #define discard_char ucpp_discard_char 69 | #define next_token ucpp_next_token 70 | #define grap_char ucpp_grap_char 71 | #define space_char ucpp_space_char 72 | 73 | void init_cppm(void); 74 | void put_char(struct lexer_state *, unsigned char); 75 | void discard_char(struct lexer_state *); 76 | int next_token(struct lexer_state *); 77 | int grap_char(struct lexer_state *); 78 | int space_char(int); 79 | 80 | /* 81 | * from assert.c 82 | */ 83 | struct assert { 84 | char *name; /* this must be the first field */ 85 | size_t nbval; 86 | struct token_fifo *val; 87 | }; 88 | 89 | #define cmp_token_list ucpp_cmp_token_list 90 | #define handle_assert ucpp_handle_assert 91 | #define handle_unassert ucpp_handle_unassert 92 | #define get_assertion ucpp_get_assertion 93 | 94 | int cmp_token_list(struct token_fifo *, struct token_fifo *); 95 | int handle_assert(struct lexer_state *); 96 | int handle_unassert(struct lexer_state *); 97 | struct assert *get_assertion(char *); 98 | 99 | /* 100 | * from macro.c 101 | */ 102 | struct macro { 103 | char *name; /* this must be the first field */ 104 | int narg; 105 | char **arg; 106 | int nest; 107 | int vaarg; 108 | #ifdef LOW_MEM 109 | struct comp_token_fifo cval; 110 | #else 111 | struct token_fifo val; 112 | #endif 113 | }; 114 | 115 | #define print_token ucpp_print_token 116 | #define handle_define ucpp_handle_define 117 | #define handle_undef ucpp_handle_undef 118 | #define handle_ifdef ucpp_handle_ifdef 119 | #define handle_ifndef ucpp_handle_ifndef 120 | #define substitute_macro ucpp_substitute_macro 121 | #define get_macro ucpp_get_macro 122 | #define dsharp_lexer ucpp_dsharp_lexer 123 | #define compile_time ucpp_compile_time 124 | #define compile_date ucpp_compile_date 125 | #define compile_adate ucpp_compile_adate 126 | #ifdef PRAGMA_TOKENIZE 127 | #define tokenize_lexer ucpp_tokenize_lexer 128 | #endif 129 | 130 | void print_token(struct lexer_state *, struct token *, long); 131 | int handle_define(struct lexer_state *); 132 | int handle_undef(struct lexer_state *); 133 | int handle_ifdef(struct lexer_state *); 134 | int handle_ifndef(struct lexer_state *); 135 | int substitute_macro(struct lexer_state *, struct macro *, 136 | struct token_fifo *, int, int, long); 137 | struct macro *get_macro(char *); 138 | 139 | extern struct lexer_state dsharp_lexer; 140 | extern char compile_time[], compile_date[], compile_adate[]; 141 | #ifdef PRAGMA_TOKENIZE 142 | extern struct lexer_state tokenize_lexer; 143 | #endif 144 | 145 | /* 146 | * from eval.c 147 | */ 148 | #define strtoconst ucpp_strtoconst 149 | #define eval_expr ucpp_eval_expr 150 | #define eval_line ucpp_eval_line 151 | 152 | unsigned long strtoconst(char *); 153 | unsigned long eval_expr(struct token_fifo *, int *, int); 154 | extern long eval_line; 155 | 156 | #define eval_exception ucpp_eval_exception 157 | 158 | #ifdef POSIX_JMP 159 | #define JMP_BUF sigjmp_buf 160 | #define catch(x) sigsetjmp((x), 0) 161 | #define throw(x) siglongjmp((x), 1) 162 | #else 163 | #define JMP_BUF jmp_buf 164 | #define catch(x) setjmp((x)) 165 | #define throw(x) longjmp((x), 1) 166 | #endif 167 | extern JMP_BUF eval_exception; 168 | 169 | /* 170 | * from cpp.c 171 | */ 172 | #define token_name ucpp_token_name 173 | #define throw_away ucpp_throw_away 174 | #define garbage_collect ucpp_garbage_collect 175 | #define init_buf_lexer_state ucpp_init_buf_lexer_state 176 | #ifdef PRAGMA_TOKENIZE 177 | #define compress_token_list ucpp_compress_token_list 178 | #endif 179 | 180 | char *token_name(struct token *); 181 | void throw_away(struct garbage_fifo *, char *); 182 | void garbage_collect(struct garbage_fifo *); 183 | void init_buf_lexer_state(struct lexer_state *, int); 184 | #ifdef PRAGMA_TOKENIZE 185 | struct comp_token_fifo compress_token_list(struct token_fifo *); 186 | #endif 187 | 188 | #define ouch ucpp_ouch 189 | #define error ucpp_error 190 | #define warning ucpp_warning 191 | 192 | #endif 193 | -------------------------------------------------------------------------------- /vars.c: -------------------------------------------------------------------------------- 1 | /* $VER: vbcc (vars.c) $Revision: 1.40 $ */ 2 | #include "vbc.h" 3 | #ifdef AMIGA 4 | static const char *__ver="$VER: vbcc 0.9h (12.02.2022)\r\n"; 5 | long __stack=65536; 6 | #endif 7 | char *s,*ident; 8 | char number[MAXI],buff[MAXI]; 9 | tunit *first_tunit,*last_tunit; 10 | struct_declaration *first_sd[MAXN],*last_sd[MAXN],*merk_sdf,*merk_sdl; 11 | struct_identifier *first_si[MAXN],*last_si[MAXN],*merk_sif,*merk_sil; 12 | identifier_list *first_ilist[MAXN],*last_ilist[MAXN],*merk_ilistf,*merk_ilistl; 13 | llist *first_llist,*last_llist; 14 | int nesting; 15 | hashtable *hash_ext; 16 | Var *first_var[MAXN],*last_var[MAXN],*merk_varf,*merk_varl,*first_ext,*last_ext; 17 | Var *block_vla[MAXN]; 18 | llist *vladeflabels[MAXN],*vlajmplabels[MAXN]; 19 | vlaadjust_list *vlaadjusts[MAXN]; 20 | rpair rp; 21 | FILE *out,*ic1,*ic2,*ppout,*cmdfile; 22 | int c99=1; 23 | int force_statics,prefer_statics; 24 | int range_opt; 25 | int merge_strings; 26 | int sec_per_obj; 27 | int opencl; 28 | int disallow_statics; 29 | int header_cnt; 30 | int wpo,wpo_key; 31 | FILE *input_wpo; 32 | int nocode,dontdelete; 33 | int const_expr,for_decl; 34 | int registerpri=200,currentpri,looppri=10; 35 | int return_value,break_label,switch_typ,switch_count,switch_act; 36 | int pointer_call; 37 | int softfloat; 38 | int ecpp; 39 | type *return_typ; 40 | Var *return_var; 41 | zmax local_offset[MAXN]; 42 | int c_flags[MAXCF]={ 43 | VALFLAG,STRINGFLAG,0,0, 44 | VALFLAG,0,0,0, 45 | VALFLAG,FUNCFLAG,FUNCFLAG,VALFLAG, 46 | VALFLAG,0,0,0, 47 | 0,0,0,0, 48 | 0,0,0,0,0, 49 | VALFLAG,0,0,0,0, 50 | 0,VALFLAG,0,0,0,STRINGFLAG,0, 51 | VALFLAG,VALFLAG,0,VALFLAG,0, 52 | FUNCFLAG,FUNCFLAG,FUNCFLAG,0, 53 | 0,0,0,0, 54 | 0,0,0,VALFLAG, 55 | 0, 56 | VALFLAG,VALFLAG,VALFLAG,VALFLAG, 57 | STRINGFLAG 58 | }; 59 | char *c_flags_name[MAXCF]={ 60 | "O","o","ic1","ic2", 61 | "debug","noasm","quiet","ansi", 62 | "maxerrors","dontwarn","warn","maxoptpasses", 63 | "inline-size","+","cpp-comments","no-trigraphs", 64 | "no-inline-peephole","final","E","dontkeep-initialized-data", 65 | "strip-path","fp-associative","iso","no-alias-opt","no-multiple-ccs", 66 | "unroll-size","double-push","speed","size","unroll-all", 67 | "stack-check","inline-depth","g","c99","wpo","cmd","noitra", 68 | "misra","coloring","dmalloc","disable","soft-float", 69 | "misrawarn","misradontwarn","reserve-reg","ecpp", 70 | "short-push","unsigned-char","opencl","no-include-stack", 71 | "deps","deps-for-libs","no-cpp-warn","hash-size", 72 | "warnings-as-errors", 73 | "clist-copy-stack","clist-copy-static","clist-copy-pointer","inline-memcpy", 74 | "depobj","c89","force-statics","prefer-statics","range-opt","merge-strings", 75 | "sec-per-obj","no-eff-ics","early-eff-ics" 76 | }; 77 | union ppi c_flags_val[MAXCF]; 78 | char *inname; 79 | char **target_macros; 80 | Var *regsbuf[MAXR+1]; 81 | int regbnesting[MAXR+1]; 82 | const_list *first_clist,*last_clist; 83 | int afterlabel; 84 | terr_out err_out[]={ 85 | #include "errors.h" 86 | "",0 87 | }; 88 | int err_num=sizeof(err_out)/sizeof(err_out[0])-1; 89 | 90 | tmisra_err_out misra_err_out[]={ 91 | #include "misra_errors.h" 92 | 0,0,"",0 93 | }; 94 | 95 | #ifdef HAVE_ECPP 96 | struct_declaration *current_class=0; 97 | type *current_func=0; 98 | ecpp_dtor_list *ecpp_dlist[MAXN]; 99 | #endif 100 | 101 | char *cur_func="shouldn't happen!"; 102 | Var *cur_funcv; 103 | char *copyright="vbcc V0.9h (c) in 1995-2022 by Volker Barthelmann"; 104 | -------------------------------------------------------------------------------- /vbcc_cpp.h: -------------------------------------------------------------------------------- 1 | /* $VER: vbcc (vbcc_cpp.h) $Revision: 1.2 $ */ 2 | 3 | 4 | /* fix some name clashes between vbcc and ucpp and include cpp.h */ 5 | /* has to be include prior to other vbcc includes */ 6 | 7 | 8 | #define STRING T_STRING 9 | #define CHAR T_CHAR 10 | #define CAST T_CAST 11 | #define AND T_AND 12 | #define OR T_OR 13 | #define COLON T_COLON 14 | #define LOR T_LOR 15 | #define LAND T_LAND 16 | #define MINUS T_MINUS 17 | 18 | #define NO_UCPP_ERROR_FUNCTIONS 1 19 | #include "ucpp/cpp.h" 20 | 21 | typedef struct token token; 22 | typedef struct lexer_state lexer_state; 23 | typedef struct stack_context stack_context; 24 | 25 | extern token *ctok; 26 | extern lexer_state ls; 27 | 28 | #undef STRING 29 | #undef CHAR 30 | #undef CAST 31 | #undef AND 32 | #undef OR 33 | #undef COLON 34 | #undef LOR 35 | #undef LAND 36 | #undef MINUS 37 | 38 | #define next_token vbcc_next_token 39 | #undef error 40 | 41 | #undef S_TOKEN 42 | #define S_TOKEN(x) ((x) >= NUMBER && (x) <= T_CHAR) 43 | 44 | #define ttMWS(x) ((x) == NONE || (x) == COMMENT || (x) == OPT_NONE) 45 | #define ttWHI(x) (ttMWS(x) || (x) == NEWLINE) 46 | 47 | char *ucpp_token_name(); 48 | -------------------------------------------------------------------------------- /vbpp.h: -------------------------------------------------------------------------------- 1 | #ifndef _VBPP_H 2 | #define _VBPP_H 1 3 | 4 | /* vbpp.h 5 | * last change: 17.08.1995 Thorsten Schaaps 6 | */ 7 | 8 | /* strnode-types */ 9 | #define NORMAL 0 /* anything: brackets,+,-,/,*, etc.. */ 10 | #define PP_IDENT 1 /* possible identifier */ 11 | #define ARGUMENT 2 /* argument: see number */ 12 | #define PP_STR 3 /* strings */ 13 | #define NUMBER 4 /* numbers (123,0x00,0L,..) */ 14 | #define SPACE 5 /* spaces, tabs, etc. */ 15 | #define SPECIAL 6 /* flags=1->#,flags=2->## */ 16 | 17 | /* flags for type==SPECIAL */ 18 | #define NONE 0 19 | #define TOSTRING 1 /* #define t(c) #c */ 20 | #define KILLSPACES 2 /* #define t(a,b) a##b */ 21 | 22 | struct strnode{ 23 | char *str; /* the string =8) ah, you guessed that. */ 24 | int len; /* the length of the string */ 25 | int flags; /* flags: see above */ 26 | int type; /* type: see above */ 27 | int number; /* only valid if type==ARGUMENT */ 28 | struct strnode *prev,*next; /* pointers to previous and next node or NULL */ 29 | }; 30 | 31 | /* Macro-Node-Flags */ 32 | #define FUNCTION 1 /* for macros changing from line to line, e.g. */ 33 | /* __LINE__, __FILE__, __TIME__ etc.. */ 34 | #define PARAMETER 2 /* Macro has arguments */ 35 | #define NODELETE 4 /* Macro cannot be UNDEFined, e.g. __TIME__, */ 36 | /* __DATE__, __STDC__ */ 37 | #define NOREDEF 8 /* Macro cannot be reDEFINED, (s. above, but */ 38 | /* not __STDC__) */ 39 | 40 | /* Function-Numbers for FUNCTION-Macros */ 41 | #define FUNCLINE 1 /* __LINE__ */ 42 | #define FUNCFILE 2 /* __FILE__ */ 43 | #define FUNCDATE 3 /* __DATE__ */ 44 | #define FUNCTIME 4 /* __TIME__ */ 45 | /* __STDC__ is a normal macro, but cannot be deleted */ 46 | 47 | struct mnode{ 48 | char *name; /* name, e.g. SQR */ 49 | char *args; /* arguments, e.g. (x) */ 50 | char *token; /* definition as string, e.g. ((x)*(x)) */ 51 | /* BE CAREFULL: may be NULL in the future */ 52 | struct strnode *tokenlist; /* definition as list */ 53 | int flags; /* flags, see above */ 54 | int numargs; /* number of arguments */ 55 | int funcnum; /* number of function (see above) */ 56 | struct mnode *prev,*next; /* pointers to previos and next node or NULL */ 57 | }; 58 | 59 | /* Return-Codes for ExpandList/ExpandArgMakro/CloneArg-Functions */ 60 | #define OK 0 61 | #define OUT_OF_MEM -1 62 | #define NUM_OF_ARGS -2 63 | #define ARG_EXPECTED -3 64 | 65 | void AddMakroNode(struct mnode **, struct mnode *); 66 | void InsertMakroNode(struct mnode **, struct mnode *, struct mnode *); 67 | void RemMakroNode(struct mnode **, struct mnode *); 68 | struct mnode *FindMakroNode(struct mnode *, char *, int); 69 | void DelMakroNode(struct mnode **, struct mnode *); 70 | void DelMakroList(struct mnode **); 71 | 72 | void AddStrNode(struct strnode **, struct strnode *, char *); 73 | void RemStrNode(struct strnode **, struct strnode *); 74 | /* struct strnode *FindStrNode(struct strnode *, char *, int); */ 75 | void DelStrNode(struct strnode **, struct strnode *); 76 | void DelStrList(struct strnode **); 77 | struct strnode *CloneStrList(struct strnode *, struct strnode *); 78 | struct strnode *DoMakroFunction(struct mnode *); 79 | 80 | struct strnode *Str2List(char *); 81 | int List2Str(struct strnode *, char *, int); 82 | 83 | int ExpandList(struct strnode **); 84 | 85 | struct mnode *ParseIdentifier(char *); 86 | int PreParse(void); 87 | 88 | #endif 89 | 90 | -------------------------------------------------------------------------------- /vcpr/vcpr.h: -------------------------------------------------------------------------------- 1 | #define LABDEF 1 2 | #define LABUSE 2 3 | #define BARRIER 4 4 | #define LBARRIER 8 5 | #define BRANCH 16 /* only move if target also moved */ 6 | 7 | typedef struct line { 8 | struct line *next,*prev; 9 | char *code; 10 | int flags; 11 | int size; 12 | int idx; 13 | int l1,l2; 14 | } line; 15 | 16 | #define MAXMLEN 64 17 | 18 | typedef struct match { 19 | struct match *next; 20 | line *start; 21 | int max; 22 | int size[MAXMLEN]; 23 | } match; 24 | 25 | typedef struct { 26 | int usecnt; 27 | } labinfo; 28 | 29 | #define LABNUM 10000 30 | 31 | #define MAXLEN 1024 32 | 33 | 34 | /* functions available to backend */ 35 | void *mymalloc(size_t sz); 36 | int new_label(void); 37 | void extend_labinfos(int n); 38 | line *new_line(void); 39 | void insert_line(line *after, line *new); 40 | void remove_line(line *p); 41 | void free_line(line *p); 42 | 43 | /* functions provided by the backend */ 44 | extern int minsave; 45 | extern const char tg_copyright[]; 46 | 47 | void parse_line(char *s,line *p); 48 | void add_header(line *after); 49 | void add_ret(line *after); 50 | void add_jsr(line *after); 51 | -------------------------------------------------------------------------------- /vprof/vprof.c: -------------------------------------------------------------------------------- 1 | /* 2 | * vprof 3 | * 4 | * vbcc profiler. Displays the contents of "mon.out" files. 5 | * (C)1998,2010 by Frank Wille 6 | * 7 | * vprof is freeware and part of the portable and retargetable ANSI C 8 | * compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann. 9 | * vprof may be freely redistributed as long as no modifications are 10 | * made and nothing is charged for it. Non-commercial usage is allowed 11 | * without any restrictions. 12 | * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE 13 | * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR. 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | #define VERSION 0 21 | #define REVISION 2 22 | #define PLEVEL 0 23 | #define DEFAULTNAME "mon.out" 24 | 25 | struct profdata { 26 | char *funcname; 27 | unsigned long ncalls; 28 | unsigned long tottime; 29 | unsigned long loctime; 30 | }; 31 | 32 | 33 | static void show(struct profdata *pdata,int n) 34 | /* write profdata records to stdout */ 35 | { 36 | struct profdata *p; 37 | unsigned long runtime; 38 | int i; 39 | 40 | for (i=0,p=pdata,runtime=0; iloctime; 42 | 43 | printf(" %% total local local total\n" 44 | " time seconds seconds calls ms/call ms/call name\n"); 45 | for (i=0,p=pdata; iloctime/(double)runtime)*100.0, 48 | (double)p->tottime/1000000.0, 49 | (double)p->loctime/1000000.0, 50 | p->ncalls, 51 | ((double)p->loctime/(double)p->ncalls)/1000.0, 52 | ((double)p->tottime/(double)p->ncalls)/1000.0, 53 | p->funcname); 54 | } 55 | } 56 | 57 | 58 | static int cmp_total(const void *pd1,const void *pd2) 59 | { 60 | return ((int)(((struct profdata *)pd2)->loctime - 61 | ((struct profdata *)pd1)->loctime)); 62 | } 63 | 64 | 65 | static void show_local(struct profdata *pd,int n) 66 | /* show profiling data, sorted according to the local time */ 67 | /* spent in each function */ 68 | { 69 | qsort(pd,n,sizeof(struct profdata),cmp_total); 70 | show(pd,n); 71 | } 72 | 73 | 74 | static char *skipname(char *p) 75 | /* skip name and alignment bytes and return pointer to profile data */ 76 | { 77 | int n = strlen(p)+1; 78 | 79 | p += n; 80 | if (n &= 3) 81 | p += 4-n; 82 | return (p); 83 | } 84 | 85 | 86 | int main(int argc,char *argv[]) 87 | { 88 | char *mname; 89 | FILE *fp; 90 | long size,len; 91 | char *buf,*p; 92 | int i,nrecs = 0; 93 | struct profdata *pdata,*pd; 94 | 95 | if (argc >= 2) { 96 | if (*argv[1]=='-' || *argv[1]=='?') { 97 | printf("%s V%d.%d%c (c)1998,2010 by Frank Wille\n" 98 | "Usage:\n %s [mon.out]\n",argv[0], 99 | VERSION,REVISION,PLEVEL?('a'+PLEVEL-1):' ',argv[0]); 100 | exit(1); 101 | } 102 | else 103 | mname = argv[1]; 104 | } 105 | else 106 | mname = DEFAULTNAME; 107 | 108 | if (fp = fopen(mname,"r")) { 109 | /* determine file size */ 110 | fseek(fp,0,SEEK_END); 111 | size = ftell(fp); 112 | fseek(fp,0,SEEK_SET); 113 | if (size < 0) { 114 | fclose(fp); 115 | fprintf(stderr,"%s: Seek error on %s!\n",argv[0],mname); 116 | exit(EXIT_FAILURE); 117 | } 118 | 119 | /* allocate buffer and read file */ 120 | if (!(buf = malloc(size))) { 121 | fclose(fp); 122 | fprintf(stderr,"%s: Not enough memory!\n",argv[0]); 123 | exit(EXIT_FAILURE); 124 | } 125 | if (fread(buf,1,size,fp) != size) { 126 | fclose(fp); 127 | fprintf(stderr,"%s: %s had a read error!\n",argv[0],mname); 128 | exit(EXIT_FAILURE); 129 | } 130 | fclose(fp); 131 | 132 | /* count number of entries in mon.out and allocate profdata array */ 133 | p = buf; 134 | while (p < buf+size) { 135 | nrecs++; 136 | p = skipname(p) + 3*sizeof(unsigned long); 137 | } 138 | if (p!=buf+size || nrecs==0) { 139 | fprintf(stderr,"%s: %s: Corrupted file format.\n",argv[0],mname); 140 | exit(EXIT_FAILURE); 141 | } 142 | if (!(pdata = malloc(nrecs * sizeof(struct profdata)))) { 143 | fprintf(stderr,"%s: Not enough memory!\n",argv[0]); 144 | exit(EXIT_FAILURE); 145 | } 146 | 147 | /* fill profdata array */ 148 | for (i=0,p=buf,pd=pdata; ifuncname = p; 150 | p = skipname(p); 151 | pd->ncalls = *(unsigned long *)p; 152 | pd->tottime = *(unsigned long *)(p+sizeof(unsigned long)); 153 | pd->loctime = *(unsigned long *)(p+2*sizeof(unsigned long)); 154 | p += 3*sizeof(unsigned long); 155 | } 156 | 157 | /* display */ 158 | show_local(pdata,nrecs); 159 | } 160 | else { 161 | fprintf(stderr,"%s: Can't open %s.\n",argv[0],mname); 162 | exit(EXIT_FAILURE); 163 | } 164 | 165 | return 0; 166 | } 167 | -------------------------------------------------------------------------------- /vsc/vsc.c: -------------------------------------------------------------------------------- 1 | /* vsc - portable instruction scheduler for vbcc. */ 2 | /* (c) 1997-99 by Volker Barthelmann. */ 3 | 4 | #include "vsc.h" 5 | 6 | char vs_copyright[]="vsc scheduler V0.1 (c) 1997-99 by Volker Barthelmann"; 7 | 8 | #define MAX_INS 128 9 | #define LINELENGTH 1024 10 | 11 | #ifndef DEBUG 12 | int DEBUG; 13 | #endif 14 | 15 | struct sinfo silist[MAX_INS]; 16 | int si_count; 17 | int done; 18 | 19 | int bvcmp(unsigned char *dest,unsigned char *src,size_t len) 20 | /* vergleicht zwei Bitvektoren */ 21 | { 22 | for(;len>0;len--) 23 | if(*dest++!=*src++) return(0); 24 | return(1); 25 | } 26 | void bvunite(unsigned char *dest,unsigned char *src,size_t len) 27 | /* berechnet Vereinigung zweier Bitvektoren */ 28 | { 29 | for(;len>0;len--) 30 | *dest++|=*src++; 31 | } 32 | void bvintersect(unsigned char *dest,unsigned char *src,size_t len) 33 | /* berechnet Durchschnitt zweier Bitvektoren */ 34 | { 35 | for(;len>0;len--) 36 | *dest++&=*src++; 37 | } 38 | void bvdiff(unsigned char *dest,unsigned char *src,size_t len) 39 | /* berechnet 'Differenz' zweier Bitvektoren */ 40 | { 41 | for(;len>0;len--) 42 | *dest++&=~(*src++); 43 | } 44 | 45 | void raus(void) 46 | { 47 | sched_cleanup(); 48 | if(DEBUG&1) printf("raus\n"); 49 | if(done) 50 | exit(EXIT_SUCCESS); 51 | else 52 | exit(EXIT_FAILURE); 53 | } 54 | void *mymalloc(size_t sz) 55 | { 56 | void *p=malloc(sz); 57 | if(!p){ 58 | puts("Out of memory!"); 59 | raus(); 60 | } 61 | return p; 62 | } 63 | void print_sinfo(void) 64 | { 65 | struct sinfo *p;int i,j; 66 | if(DEBUG&2) 67 | printf("print_sinfo\n"); 68 | else 69 | return; 70 | for(j=0;jtxt); 73 | printf("flags=%u, label=%u latency=%u\n",p->flags,p->label,p->latency); 74 | printf("available pipelines: "); 75 | for(i=0;ipipes,i)) 77 | printf("%d ",i); 78 | printf("\nuses registers (%d=mem): ",MEM); 79 | for(i=0;i<=MEM;i++) 80 | if(BTST(p->uses,i)) 81 | printf("%d ",i); 82 | printf("\nmodifies registers (%d=MEM): ",MEM); 83 | for(i=0;i<=MEM;i++) 84 | if(BTST(p->modifies,i)) 85 | printf("%d ",i); 86 | printf("\n\n"); 87 | } 88 | } 89 | void free_sinfo(void) 90 | { 91 | int j; 92 | for(j=0;j0) printf("latency[%d]=%d\n",i,latency[i]); 108 | } 109 | /* Mark all instructions which are ready. */ 110 | memset(modified,0,REGS_SIZE); 111 | memset(used,0,REGS_SIZE); 112 | for(i=0;i0) k=1; 125 | } 126 | if(!k) silist[i].flags|=READY; 127 | } 128 | } 129 | bvunite(modified,silist[i].modifies,REGS_SIZE); 130 | bvunite(used,silist[i].uses,REGS_SIZE); 131 | } 132 | 133 | /* Fill pipeline slots with ready instructions. */ 134 | for(i=0;isilist[pipes[j]].latency){ 150 | pipes[j]=i; 151 | k=1; 152 | } 153 | } 154 | } 155 | if(DEBUG&4) printf("instructions for cycle %d:\n",cycle); 156 | for(i=0;i=0){ 158 | if(DEBUG&4) printf("%3d: %s",i,silist[pipes[i]].txt); 159 | fprintf(f,"%s",silist[pipes[i]].txt); 160 | silist[pipes[i]].flags|=OUT; 161 | remaining--; 162 | for(j=0;j<=MEM;j++){ 163 | if(BTST(silist[pipes[i]].modifies,j)) latency[j]=silist[pipes[i]].latency; 164 | } 165 | } 166 | } 167 | for(i=0;i<=MEM;i++) 168 | if(latency[i]>0) latency[i]--; 169 | } 170 | } 171 | int main(int argc,char *argv[]) 172 | { 173 | char s[LINELENGTH];int i,quiet=0; 174 | FILE *in,*out; char *inname=0,*outname=0; 175 | for(i=1;i=MAX_INS){ 226 | if(DEBUG&1) printf("MAX_INS reached: %s",silist[si_count].txt); 227 | output_scheduled(out); 228 | free_sinfo(); 229 | si_count=0; 230 | } 231 | } 232 | } 233 | output_scheduled(out); 234 | free_sinfo(); 235 | done=1; 236 | raus(); 237 | } 238 | 239 | 240 | -------------------------------------------------------------------------------- /vsc/vsc.h: -------------------------------------------------------------------------------- 1 | /* vsc portable scheduler (c) 1997-99 by Volker Barthelmann */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define BSET(array,bit) (array)[(bit)/CHAR_BIT]|=1<<((bit)%CHAR_BIT) 9 | #define BCLR(array,bit) (array)[(bit)/CHAR_BIT]&=~(1<<((bit)%CHAR_BIT)) 10 | #define BTST(array,bit) ((array)[(bit)/CHAR_BIT]&(1<<((bit)%CHAR_BIT))) 11 | 12 | /* An instruction with LABEL set is preceded with a numbered label. */ 13 | /* The number is in