1 /* Id: code.c,v 1.8 2009/02/08 16:55:08 ragge Exp */ 2 /* $NetBSD: code.c,v 1.1.1.3 2010/06/03 18:57:32 plunky Exp $ */ 3 /* 4 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * Redistributions of source code and documentation must retain the above 11 * copyright notice, this list of conditions and the following disclaimer. 12 * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditionsand the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed or owned by Caldera 18 * International, Inc. 19 * Neither the name of Caldera International, Inc. nor the names of other 20 * contributors may be used to endorse or promote products derived from 21 * this software without specific prior written permission. 22 * 23 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA 24 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR 25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE 28 * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, 32 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 33 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * POSSIBILITY OF SUCH DAMAGE. 35 */ 36 37 # include "pass1.h" 38 39 short log2tab[] = {0, 0, 1, 2, 2, 3, 3, 3, 3}; 40 #define LOG2SZ 9 41 42 void 43 defalign(n) { 44 /* cause the alignment to become a multiple of n */ 45 n /= SZCHAR; 46 if( lastloc != PROG && n > 1 ) printf( " .align %d\n", n >= 0 && n < LOG2SZ ? log2tab[n] : 0 ); 47 } 48 49 /* 50 * output something to define the current position as label n 51 */ 52 void 53 deflab1(int n) 54 { 55 printf(LABFMT ":\n", n); 56 } 57 58 void 59 efcode(){ 60 /* code for the end of a function */ 61 if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN) 62 return; 63 cerror("efcode"); 64 65 #ifdef notyet 66 if( strftn ){ /* copy output (in R2) to caller */ 67 register NODE *l, *r; 68 register struct symtab *p; 69 register TWORD t; 70 register int j; 71 int i; 72 73 p = &stab[curftn]; 74 t = p->stype; 75 t = DECREF(t); 76 77 deflab( retlab ); 78 79 i = getlab(); /* label for return area */ 80 printf(" .data\n" ); 81 printf(" .align 2\n" ); 82 deflab1(i); 83 printf("\t.space %d\n", tsize(t, p->dimoff, p->sizoff)/SZCHAR); 84 printf(" .text\n" ); 85 psline(); 86 printf(" movab " LABFMT ",r1\n", i); 87 88 reached = 1; 89 l = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff ); 90 l->rval = 1; /* R1 */ 91 l->lval = 0; /* no offset */ 92 r = block( REG, NIL, NIL, PTR|t, p->dimoff, p->sizoff ); 93 r->rval = 0; /* R0 */ 94 r->lval = 0; 95 l = buildtree( UNARY MUL, l, NIL ); 96 r = buildtree( UNARY MUL, r, NIL ); 97 l = buildtree( ASSIGN, l, r ); 98 l->op = FREE; 99 ecomp( l->left ); 100 printf( " movab " LABFMT ",r0\n", i ); 101 /* turn off strftn flag, so return sequence will be generated */ 102 strftn = 0; 103 } 104 branch( retlab ); 105 printf( " .set .R%d,0x%x\n", ftnno, ent_mask[reg_use] ); 106 reg_use = 11; 107 p2bend(); 108 fdefflag = 0; 109 #endif 110 } 111 112 void 113 bfcode(struct symtab **a, int n) 114 { 115 int i; 116 117 if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN) 118 return; 119 /* Function returns struct, adjust arg offset */ 120 for (i = 0; i < n; i++) 121 a[i]->soffset += SZPOINT(INT); 122 } 123 124 void 125 bccode(){ /* called just before the first executable statment */ 126 /* by now, the automatics and register variables are allocated */ 127 SETOFF( autooff, SZINT ); 128 #if 0 129 /* set aside store area offset */ 130 p2bbeg( autooff, regvar ); 131 reg_use = (reg_use > regvar ? regvar : reg_use); 132 #endif 133 } 134 135 void 136 ejobcode( flag ){ 137 /* called just before final exit */ 138 /* flag is 1 if errors, 0 if none */ 139 } 140 141 void 142 bjobcode() 143 { 144 } 145 146 #if 0 147 aobeg(){ 148 /* called before removing automatics from stab */ 149 } 150 151 aocode(p) struct symtab *p; { 152 /* called when automatic p removed from stab */ 153 } 154 155 aoend(){ 156 /* called after removing all automatics from stab */ 157 } 158 #endif 159 160 void 161 defnam( p ) register struct symtab *p; { 162 /* define the current location as the name p->sname */ 163 char *n; 164 165 n = p->soname ? p->soname : exname(p->sname); 166 if( p->sclass == EXTDEF ){ 167 printf( " .globl %s\n", n ); 168 } 169 printf( "%s:\n", n ); 170 171 } 172 173 void 174 bycode( t, i ){ 175 /* put byte i+1 in a string */ 176 177 i &= 07; 178 if( t < 0 ){ /* end of the string */ 179 if( i != 0 ) printf( "\n" ); 180 } 181 182 else { /* stash byte t into string */ 183 if( i == 0 ) printf( " .byte " ); 184 else printf( "," ); 185 printf( "0x%x", t ); 186 if( i == 07 ) printf( "\n" ); 187 } 188 } 189 190 int 191 fldal( t ) unsigned t; { /* return the alignment of field of type t */ 192 uerror( "illegal field type" ); 193 return( ALINT ); 194 } 195 196 void 197 fldty( p ) struct symtab *p; { /* fix up type of field p */ 198 ; 199 } 200 201 /* 202 * XXX - fix genswitch. 203 */ 204 int 205 mygenswitch(int num, TWORD type, struct swents **p, int n) 206 { 207 return 0; 208 } 209 210 #ifdef notyet 211 struct sw heapsw[SWITSZ]; /* heap for switches */ 212 213 genswitch(p,n) register struct sw *p;{ 214 /* p points to an array of structures, each consisting 215 of a constant value and a label. 216 The first is >=0 if there is a default label; 217 its value is the label number 218 The entries p[1] to p[n] are the nontrivial cases 219 */ 220 register i; 221 register CONSZ j, range; 222 register dlab, swlab; 223 224 range = p[n].sval-p[1].sval; 225 226 if( range>0 && range <= 3*n && n>=4 ){ /* implement a direct switch */ 227 228 swlab = getlab(); 229 dlab = p->slab >= 0 ? p->slab : getlab(); 230 231 /* already in r0 */ 232 printf(" casel r0,$%ld,$%ld\n", p[1].sval, range); 233 deflab1(swlab); 234 for( i=1,j=p[1].sval; i<=n; j++) { 235 printf(" .word " LABFMT "-" LABFMT "\n", 236 (j == p[i].sval ? ((j=p[i++].sval), p[i-1].slab) : dlab), 237 swlab); 238 } 239 240 if( p->slab >= 0 ) branch( dlab ); 241 else deflab1(dlab); 242 return; 243 244 } 245 246 if( n>8 ) { /* heap switch */ 247 248 heapsw[0].slab = dlab = p->slab >= 0 ? p->slab : getlab(); 249 makeheap(p, n, 1); /* build heap */ 250 251 walkheap(1, n); /* produce code */ 252 253 if( p->slab >= 0 ) 254 branch( dlab ); 255 else 256 deflab1(dlab); 257 return; 258 } 259 260 /* debugging code */ 261 262 /* out for the moment 263 if( n >= 4 ) werror( "inefficient switch: %d, %d", n, (int) (range/n) ); 264 */ 265 266 /* simple switch code */ 267 268 for( i=1; i<=n; ++i ){ 269 /* already in r0 */ 270 271 printf( " cmpl r0,$" ); 272 printf( CONFMT, p[i].sval ); 273 printf( "\n jeql " LBLFMT "\n", p[i].slab ); 274 } 275 276 if( p->slab>=0 ) branch( p->slab ); 277 } 278 279 makeheap(p, m, n) 280 register struct sw *p; 281 { 282 register int q; 283 284 q = select(m); 285 heapsw[n] = p[q]; 286 if( q>1 ) makeheap(p, q-1, 2*n); 287 if( q<m ) makeheap(p+q, m-q, 2*n+1); 288 } 289 290 select(m) { 291 register int l,i,k; 292 293 for(i=1; ; i*=2) 294 if( (i-1) > m ) break; 295 l = ((k = i/2 - 1) + 1)/2; 296 return( l + (m-k < l ? m-k : l)); 297 } 298 299 walkheap(start, limit) 300 { 301 int label; 302 303 304 if( start > limit ) return; 305 printf(" cmpl r0,$%d\n", heapsw[start].sval); 306 printf(" jeql " LBLFMT "\n", heapsw[start].slab); 307 if( (2*start) > limit ) { 308 printf(" jbr " LBLFMT "\n", heapsw[0].slab); 309 return; 310 } 311 if( (2*start+1) <= limit ) { 312 label = getlab(); 313 printf(" jgtr " LBLFMT "\n", label); 314 } else 315 printf(" jgtr " LBLFMT "\n", heapsw[0].slab); 316 walkheap( 2*start, limit); 317 if( (2*start+1) <= limit ) { 318 deflab1(label); 319 walkheap( 2*start+1, limit); 320 } 321 } 322 #endif 323 /* 324 * Called with a function call with arguments as argument. 325 * This is done early in buildtree() and only done once. 326 */ 327 NODE * 328 funcode(NODE *p) 329 { 330 return p; 331 } 332