Subversion Repositories tendra.SVN

Rev

Rev 5 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 5 Rev 6
Line -... Line 1...
-
 
1
/*
-
 
2
 * Copyright (c) 2002-2005 The TenDRA Project <http://www.tendra.org/>.
-
 
3
 * All rights reserved.
-
 
4
 *
-
 
5
 * Redistribution and use in source and binary forms, with or without
-
 
6
 * modification, are permitted provided that the following conditions are met:
-
 
7
 *
-
 
8
 * 1. Redistributions of source code must retain the above copyright notice,
-
 
9
 *    this list of conditions and the following disclaimer.
-
 
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
-
 
11
 *    this list of conditions and the following disclaimer in the documentation
-
 
12
 *    and/or other materials provided with the distribution.
-
 
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
-
 
14
 *    may be used to endorse or promote products derived from this software
-
 
15
 *    without specific, prior written permission.
-
 
16
 *
-
 
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
-
 
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-
 
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-
 
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
-
 
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-
 
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-
 
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-
 
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-
 
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-
 
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-
 
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
 
28
 *
-
 
29
 * $Id$
-
 
30
 */
1
/*
31
/*
2
    		 Crown Copyright (c) 1997
32
    		 Crown Copyright (c) 1997
3
    
33
 
4
    This TenDRA(r) Computer Program is subject to Copyright
34
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
35
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
36
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
37
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
38
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
39
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
40
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
41
    shall be deemed to be acceptance of the following conditions:-
12
    
42
 
13
        (1) Its Recipients shall ensure that this Notice is
43
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
44
        reproduced upon any copies or amended versions of it;
15
    
45
 
16
        (2) Any amended version of it shall be clearly marked to
46
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
47
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
48
        for the relevant amendment or amendments;
19
    
49
 
20
        (3) Its onward transfer from a recipient to another
50
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
51
        party shall be deemed to be that party's acceptance of
22
        these conditions;
52
        these conditions;
23
    
53
 
24
        (4) DERA gives no warranty or assurance as to its
54
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
55
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
56
        no liability whatsoever in relation to any use to which
27
        it may be put.
57
        it may be put.
28
*/
58
*/
Line 93... Line 123...
93
 *
123
 *
94
 * Revision 1.6  93/09/27  14:49:35  14:49:35  ra (Robert Andrews)
124
 * Revision 1.6  93/09/27  14:49:35  14:49:35  ra (Robert Andrews)
95
 * clear_sun_call_divrem_regs is now global rather than static.  Extended
125
 * clear_sun_call_divrem_regs is now global rather than static.  Extended
96
 * is_muldivrem_call to deal with those long double operations which
126
 * is_muldivrem_call to deal with those long double operations which
97
 * are implemented using system calls.
127
 * are implemented using system calls.
98
 * 
128
 *
99
 * Revision 1.5  93/08/27  11:32:37  11:32:37  ra (Robert Andrews)
129
 * Revision 1.5  93/08/27  11:32:37  11:32:37  ra (Robert Andrews)
100
 * Added a number of explicit integer casts.  Use pnset etc to set
130
 * Added a number of explicit integer casts.  Use pnset etc to set
101
 * needs properties.
131
 * needs properties.
102
 * 
132
 *
103
 * Revision 1.4  93/08/18  11:13:26  11:13:26  ra (Robert Andrews)
133
 * Revision 1.4  93/08/18  11:13:26  11:13:26  ra (Robert Andrews)
104
 * Only the whitespace has changed ...
134
 * Only the whitespace has changed ...
105
 * 
135
 *
106
 * Revision 1.3  93/08/13  14:41:32  14:41:32  ra (Robert Andrews)
136
 * Revision 1.3  93/08/13  14:41:32  14:41:32  ra (Robert Andrews)
107
 * Reformatted.
137
 * Reformatted.
108
 * 
138
 *
109
 * Revision 1.2  93/07/12  15:15:41  15:15:41  ra (Robert Andrews)
139
 * Revision 1.2  93/07/12  15:15:41  15:15:41  ra (Robert Andrews)
110
 * Added partial support for div1 and rem1.  Changed system calls to use
140
 * Added partial support for div1 and rem1.  Changed system calls to use
111
 * call_special_routine.
141
 * call_special_routine.
112
 * 
142
 *
113
 * Revision 1.1  93/06/24  14:58:50  14:58:50  ra (Robert Andrews)
143
 * Revision 1.1  93/06/24  14:58:50  14:58:50  ra (Robert Andrews)
114
 * Initial revision
144
 * Initial revision
115
 * 
145
 *
116
--------------------------------------------------------------------------
146
--------------------------------------------------------------------------
117
*/
147
*/
118
 
148
 
119
 
149
 
120
#define SPARCTRANS_CODE
150
#define SPARCTRANS_CODE
Line 158... Line 188...
158
#define BITS_PER_WORD		32
188
#define BITS_PER_WORD		32
159
 
189
 
160
 
190
 
161
/*
191
/*
162
  MULTIPLICATION LIMITS
192
  MULTIPLICATION LIMITS
163
  MAX_MUL_POW2_OFFSET is the maximum m such that 2**n +/- m is a 
193
  MAX_MUL_POW2_OFFSET is the maximum m such that 2**n +/- m is a
164
  simple multiplication.  NOT_MUL_CONST_SIMPLE is any value larger 
194
  simple multiplication.  NOT_MUL_CONST_SIMPLE is any value larger
165
  than this and is used as an error return.
195
  than this and is used as an error return.
166
*/
196
*/
167
 
197
 
168
#define MAX_MUL_POW2_OFFSET	2
198
#define MAX_MUL_POW2_OFFSET	2
169
#define NOT_MUL_CONST_SIMPLE	( MAX_MUL_POW2_OFFSET + 1 )
199
#define NOT_MUL_CONST_SIMPLE	(MAX_MUL_POW2_OFFSET + 1)
170
 
200
 
171
 
201
 
172
/*
202
/*
173
  IS c A POWER OF TWO?
203
  IS c A POWER OF TWO?
174
*/
204
*/
175
 
205
 
176
#define IS_POW2( c )	( ( c ) != 0 && ( ( c ) & ( ( c ) - 1 ) ) == 0 )
206
#define IS_POW2(c)	((c)!= 0 && ((c) & ((c) - 1)) == 0)
177
 
207
 
178
 
208
 
179
/*
209
/*
180
  GIVEN A POWER OF TWO, c, FIND n WHERE c = 2**n
210
  GIVEN A POWER OF TWO, c, FIND n WHERE c = 2**n
181
*/
211
*/
182
 
212
 
183
#define IS_TRAP 1
213
#define IS_TRAP 1
184
 
214
 
185
static int bit_no 
215
static int bit_no
186
    PROTO_N ( ( c ) )
-
 
187
    PROTO_T ( long c ){
216
(long c) {
188
  int n ;
217
  int n;
189
  unsigned long m ;
218
  unsigned long m;
190
  assert ( IS_POW2 ( c ) ) ;
219
  assert(IS_POW2(c));
191
  for ( m = 1, n = 0 ; m != ( unsigned long ) c ; m = m << 1 ) n++ ;
220
  for (m = 1, n = 0; m != (unsigned long)c; m = m << 1)n++;
192
  return ( n ) ;
221
  return(n);
193
}	
222
}
194
 
223
 
195
 
224
 
196
/*
225
/*
197
  VERSION OF rir_ins WITH CAST
226
  VERSION OF rir_ins WITH CAST
198
*/
227
*/
199
 
228
 
200
#define rcr_ins( a, b, c, d )	rir_ins ( a, b, ( long ) ( c ), d )
229
#define rcr_ins(a, b, c, d)	rir_ins(a, b,(long)(c), d)
201
 
230
 
202
 
231
 
203
#if 0
232
#if 0
204
/*
233
/*
205
  CLEAR REGISTERS USED BY MULTIPLICATION SYSTEM CALL ETC
234
  CLEAR REGISTERS USED BY MULTIPLICATION SYSTEM CALL ETC
206
 
235
 
207
  According to the System V ABI only registers %o0,...,%o7 are 
236
  According to the System V ABI only registers %o0,...,%o7 are
208
  clobbered by the system calls .mul, .div etc.  However :
237
  clobbered by the system calls .mul, .div etc.  However :
209
  1.  SunOS 4.1.1 does not follow SPARC ABI.
238
  1.  SunOS 4.1.1 does not follow SPARC ABI.
210
  2.  Even if it did, the assembler -O optimiser does not regard
239
  2.  Even if it did, the assembler -O optimiser does not regard
211
  %g1..%g7 as alive after a call and so does not preserve them,
240
  %g1..%g7 as alive after a call and so does not preserve them,
212
  or renumber them as needed after any call, even to .mul.
241
  or renumber them as needed after any call, even to .mul.
213
  Note that it does regard float regs alive after a call.
242
  Note that it does regard float regs alive after a call.
214
*/
243
*/
215
 
244
 
216
static void clear_abi_call_muldivrem_regs 
245
static void clear_abi_call_muldivrem_regs
217
    PROTO_N ( ( sp ) )
-
 
218
    PROTO_T ( space sp ){
246
(space sp) {
219
  int r ;
247
  int r;
220
  for ( r = R_O0 ; r != R_O7 + 1 ; r++ ) {
248
  for (r = R_O0; r != R_O7 + 1; r++) {
221
    /* grab remaining param regs for safety test for bad code */
249
    /* grab remaining param regs for safety test for bad code */
222
    if ( !( r == R_O0 || r == R_TMP || r == R_SP ) ) {
250
    if (!(r == R_O0 || r == R_TMP || r == R_SP)) {
223
      /* already done or special */
251
      /* already done or special */
224
      sp = needreg ( r, sp ) ;
252
      sp = needreg(r, sp);
225
    }
253
    }
226
    /* clear regs modified by .mul/.umul */
254
    /* clear regs modified by .mul/.umul */
227
    clear_reg ( r ) ;
255
    clear_reg(r);
228
  }
256
  }
229
  return ;
257
  return;
230
}
258
}
231
#endif
259
#endif
232
 
260
 
233
 
261
 
234
/*
262
/*
235
  CLEAR REGISTERS ACTUALLY USED BY MULTIPLICATION SYSTEM CALL ETC
263
  CLEAR REGISTERS ACTUALLY USED BY MULTIPLICATION SYSTEM CALL ETC
236
  
264
 
237
  This is the version of the routine above which reflect reality.
265
  This is the version of the routine above which reflect reality.
238
  Registers %o0,...,%o7 and %g1,...,%g_reg_max are clobbered.
266
  Registers %o0,...,%o7 and %g1,...,%g_reg_max are clobbered.
239
*/
267
*/
240
 
268
 
241
void clear_sun_call_divrem_regs 
269
void clear_sun_call_divrem_regs
242
    PROTO_N ( ( sp ) )
-
 
243
    PROTO_T ( space sp ){
270
(space sp) {
244
  int r ;
271
  int r;
245
  for ( r = R_G1 ; r != R_O7 + 1 ;
272
  for (r = R_G1; r != R_O7 + 1;
246
	  r = ( ( r == R_G0 + g_reg_max ) ? R_O0 : r + 1 ) ) {
273
	  r = ((r == R_G0 + g_reg_max)? R_O0 : r + 1)) {
247
	/* grab remaining param regs for safety test for bad code */
274
	/* grab remaining param regs for safety test for bad code */
248
    if ( !( r == R_O0 || r == R_TMP || r == R_SP ) ) {
275
    if (!(r == R_O0 || r == R_TMP || r == R_SP)) {
249
      /* already done or special */
276
      /* already done or special */
250
      sp = needreg ( r, sp ) ;
277
      sp = needreg(r, sp);
251
    }
278
    }
252
    /* clear regs modified by .mul/.umul */
279
    /* clear regs modified by .mul/.umul */
253
    clear_reg ( r ) ;
280
    clear_reg(r);
254
  }
281
  }
255
  return ;
282
  return;
256
}
283
}
257
 
284
 
258
 
285
 
259
/*
286
/*
260
  CALL A MULTIPLICATION/DIVISION/REMAINDER SYSTEM ROUTINE
287
  CALL A MULTIPLICATION/DIVISION/REMAINDER SYSTEM ROUTINE
261
*/
288
*/
262
 
289
 
263
int call_muldivrem 
290
int call_muldivrem
264
    PROTO_N ( ( lhs, rhs, sp, proc, err_t ) )
-
 
265
    PROTO_T ( exp lhs X exp rhs X space sp X int proc X int err_t ){
291
(exp lhs, exp rhs, space sp, int proc, int err_t) {
266
  int lhs_reg = -1;
292
  int lhs_reg = -1;
267
  int rhs_reg = -1;
293
  int rhs_reg = -1;
268
  if(err_t) {
294
  if (err_t) {
269
    /* division has error treatment, so check -MAXINT-1/-1 */
295
    /* division has error treatment, so check -MAXINT-1/-1 */
270
    if((name(sh(lhs)) == slonghd) &&
296
    if ((name(sh(lhs)) == slonghd) &&
271
       ( (name(lhs) !=val_tag) || (no(lhs) == -0x80000000)) &&
297
      ((name(lhs)!=val_tag) || (no(lhs) == -0x80000000)) &&
272
       ( (name(rhs) != val_tag) || (no(rhs) == -1))) {
298
      ((name(rhs)!= val_tag) || (no(rhs) == -1))) {
273
      int ok_lab = new_label();
299
      int ok_lab = new_label();
274
      lhs_reg = reg_operand(lhs,sp);
300
      lhs_reg = reg_operand(lhs,sp);
275
      rhs_reg = reg_operand(rhs,guardreg(lhs_reg,sp));
301
      rhs_reg = reg_operand(rhs,guardreg(lhs_reg,sp));
276
      if(name(rhs) == val_tag) {
302
      if (name(rhs) == val_tag) {
277
	if(no(rhs) != -1) {
303
	if (no(rhs)!= -1) {
278
	  uncond_ins(i_b,ok_lab);
304
	  uncond_ins(i_b,ok_lab);
279
	}
305
	}
280
      }
306
      }
281
      if(name(lhs) == val_tag) {
307
      if (name(lhs) == val_tag) {
282
	if(no(lhs) != -0x80000000) {
308
	if (no(lhs)!= -0x80000000) {
283
	  uncond_ins(i_b,ok_lab);
309
	  uncond_ins(i_b,ok_lab);
284
	}
310
	}
285
      }
311
      }
286
      condri_ins(i_bne,rhs_reg,-1,ok_lab);
312
      condri_ins(i_bne,rhs_reg,-1,ok_lab);
287
      condri_ins(i_bne,lhs_reg,-0x80000000,ok_lab);
313
      condri_ins(i_bne,lhs_reg,-0x80000000,ok_lab);
288
      if(err_t == IS_TRAP){
314
      if (err_t == IS_TRAP) {
289
	do_exception(f_overflow);
315
	do_exception(f_overflow);
290
      }
316
      }
291
      else{
317
      else{
292
	uncond_ins(i_b,-err_t);
318
	uncond_ins(i_b,-err_t);
293
      }
319
      }
294
      set_label(ok_lab);
320
      set_label(ok_lab);
295
    }
321
    }
296
  }
322
  }
297
  if (lhs_reg != R_O0) reg_operand_here ( lhs, sp, R_O0 ) ;
323
  if (lhs_reg != R_O0)reg_operand_here(lhs, sp, R_O0);
298
  sp = needreg ( R_O0, sp ) ;
324
  sp = needreg(R_O0, sp);
299
  if (rhs_reg != R_O1) reg_operand_here ( rhs, sp, R_O1 ) ;
325
  if (rhs_reg != R_O1)reg_operand_here(rhs, sp, R_O1);
300
  call_special_routine ( proc ) ;
326
  call_special_routine(proc);
301
  clear_sun_call_divrem_regs ( sp ) ;
327
  clear_sun_call_divrem_regs(sp);
302
  /* result left in R_O0 */
328
  /* result left in R_O0 */
303
  return ( R_O0 ) ;
329
  return(R_O0);
304
}
330
}
305
 
331
 
306
 
332
 
307
/*
333
/*
308
  GENERATE CODE FOR MULTIPLICATION BY A COMPLEX CONSTANT
334
  GENERATE CODE FOR MULTIPLICATION BY A COMPLEX CONSTANT
309
  This algorithm is not optimal, but it's not bad.
335
  This algorithm is not optimal, but it's not bad.
310
*/
336
*/
311
 
337
 
312
static void mul_const_complex 
338
static void mul_const_complex
313
    PROTO_N ( ( src, constval, dest, sp, sgned ) )
-
 
314
    PROTO_T ( int src X long constval X int dest X space sp X bool sgned ){
339
(int src, long constval, int dest, space sp, bool sgned) {
315
  struct {
340
  struct {
316
    unsigned char bsl ;		/* bit-string of 1's length */
341
    unsigned char bsl ;		/* bit-string of 1's length */
317
    unsigned char shift ;		/* shift from right of word */
342
    unsigned char shift ;		/* shift from right of word */
318
  } bs_tab [ BITS_PER_WORD / 2 ] ;
343
  } bs_tab[BITS_PER_WORD / 2];
319
 
344
 
320
  int bs_tab_len = 0 ;
345
  int bs_tab_len = 0;
321
  int bsl_1_tab = -1 ;
346
  int bsl_1_tab = -1;
322
  int max_bsl = 0 ;
347
  int max_bsl = 0;
323
  /* special case ~0 cannot be handled by the general algorithm */
348
  /* special case ~0 cannot be handled by the general algorithm */
324
  if ( constval == ~0 ) {
349
  if (constval == ~0) {
325
    if ( sgned ) {
350
    if (sgned) {
326
      /* X * -1 => -X */
351
      /* X * -1 => -X */
327
      assert ( constval == -1 ) ;
352
      assert(constval == -1);
328
      rr_ins ( i_neg, src, dest ) ;
353
      rr_ins(i_neg, src, dest);
329
    } 
354
    }
330
    else {
355
    else {
331
      rr_ins ( i_neg, src, dest ) ;
356
      rr_ins(i_neg, src, dest);
332
    }
357
    }
333
    return ;
358
    return;
334
  }
359
  }
335
  /* set up bs_tab from constval */
360
  /* set up bs_tab from constval */
336
  {
361
  {
337
    unsigned long c = ( unsigned long ) constval ;
362
    unsigned long c = (unsigned long)constval;
338
    int bsl = 0, sby ;
363
    int bsl = 0, sby;
339
    for ( sby = 0 ; sby <= BITS_PER_WORD ; sby++, c >>= 1 ) {
364
    for (sby = 0; sby <= BITS_PER_WORD; sby++, c >>= 1) {
340
      if ( c & 1 ) {
365
      if (c & 1) {
341
	bsl++ ;
366
	bsl++;
342
      } 
367
      }
343
      else if ( bsl != 0 ) {
368
      else if (bsl != 0) {
344
	/* a complete all-1's bit-string */
369
	/* a complete all-1's bit-string */
345
	assert ( bs_tab_len < BITS_PER_WORD / 2 ) ;
370
	assert(bs_tab_len < BITS_PER_WORD / 2);
346
	bs_tab [ bs_tab_len ].bsl = ( unsigned char ) bsl ;
371
	bs_tab[bs_tab_len].bsl = (unsigned char)bsl;
347
	bs_tab [ bs_tab_len ].shift = ( unsigned char ) ( sby - bsl ) ;
372
	bs_tab[bs_tab_len].shift = (unsigned char)(sby - bsl);
348
	if ( bsl == 1 ) bsl_1_tab = bs_tab_len ;
373
	if (bsl == 1)bsl_1_tab = bs_tab_len;
349
	if ( bsl > max_bsl ) max_bsl = bsl ;
374
	if (bsl > max_bsl)max_bsl = bsl;
350
	bs_tab_len++ ;
375
	bs_tab_len++;
351
	bsl = 0 ;
376
	bsl = 0;
352
      }
377
      }
353
    }
378
    }
354
  }
379
  }
355
  assert ( bs_tab_len > 0 ) ;	/* shouldn't be here otherwise */
380
  assert ( bs_tab_len > 0 ) ;	/* shouldn't be here otherwise */
356
  assert ( max_bsl >= 1 ) ;
381
  assert(max_bsl >= 1);
357
  assert ( max_bsl <= 31 ) ;	/* shifts by 32 don't work */
382
  assert ( max_bsl <= 31 ) ;	/* shifts by 32 don't work */
358
 
383
 
359
    /* generate the code */
384
    /* generate the code */
360
  {
385
  {
361
    int bsl ;
386
    int bsl;
362
    int bsl_laststep_tab ;
387
    int bsl_laststep_tab;
363
    int tmp = R_TMP ;
388
    int tmp = R_TMP;
364
    int accum ;
389
    int accum;
365
    bool accum_init = 0 ;
390
    bool accum_init = 0;
366
    
391
 
367
    /* allocate regs */
392
    /* allocate regs */
368
    assert ( src != R_TMP ) ;
393
    assert(src != R_TMP);
369
    assert ( dest != R_TMP ) ;
394
    assert(dest != R_TMP);
370
    
395
 
371
    if ( src != dest ) {
396
    if (src != dest) {
372
      accum = dest ;
397
      accum = dest;
373
    } 
398
    }
374
    else {
399
    else {
375
      accum = getreg ( sp.fixed ) ;
400
      accum = getreg(sp.fixed);
376
    }
401
    }
377
    assert ( src != accum ) ;
402
    assert(src != accum);
378
    
403
 
379
    /* init accum if useful */
404
    /* init accum if useful */
380
    if ( bsl_1_tab >= 0 && bs_tab [ bsl_1_tab ].shift != 0 ) {
405
    if (bsl_1_tab >= 0 && bs_tab[bsl_1_tab].shift != 0) {
381
      /* Usefully do one of the 1 bit strings with simple shift to
406
      /* Usefully do one of the 1 bit strings with simple shift to
382
	 accum.  If left to general algorithm 2 instructions, shift
407
	 accum.  If left to general algorithm 2 instructions, shift
383
	 and move/add, would often be used */
408
	 and move/add, would often be used */
384
      assert ( bs_tab [ bsl_1_tab ].bsl == 1 ) ;
409
      assert(bs_tab[bsl_1_tab].bsl == 1);
385
      rcr_ins ( i_sll, src, bs_tab [ bsl_1_tab ].shift, accum ) ;
410
      rcr_ins(i_sll, src, bs_tab[bsl_1_tab].shift, accum);
386
      bs_tab [ bsl_1_tab ].bsl = 0 ;
411
      bs_tab[bsl_1_tab].bsl = 0;
387
      accum_init = 1 ;
412
      accum_init = 1;
388
    }
413
    }
389
    
414
 
390
    /* find last cond generation step, so we can move to dest then */
415
    /* find last cond generation step, so we can move to dest then */
391
    bsl_laststep_tab = -1 ;
416
    bsl_laststep_tab = -1;
392
    for ( bsl = max_bsl ; bsl > 0 ; bsl-- ) {
417
    for (bsl = max_bsl; bsl > 0; bsl--) {
393
      int i ;
418
      int i;
394
      for ( i = 0 ; i < bs_tab_len ; i++ ) {
419
      for (i = 0; i < bs_tab_len; i++) {
395
	if ( bs_tab [i].bsl == (unsigned char)bsl ) bsl_laststep_tab = i ;
420
	if (bs_tab[i].bsl == (unsigned char)bsl)bsl_laststep_tab = i;
396
      }
421
      }
397
    }
422
    }
398
    assert ( bsl_laststep_tab != -1 ) ;
423
    assert(bsl_laststep_tab != -1);
399
 
424
 
400
    /* accumulate handle all bit strings of same length together, so
425
    /* accumulate handle all bit strings of same length together, so
401
       'src * ( ( 2 ** bsl ) - 1 )' can be shared */
426
       'src * ( ( 2 ** bsl ) - 1 )' can be shared */
402
    for ( bsl = max_bsl ; bsl > 0 ; bsl-- ) {
427
    for (bsl = max_bsl; bsl > 0; bsl--) {
403
      int i ;
428
      int i;
404
      int tmp_shifted ;
429
      int tmp_shifted;
405
      bool found_bsl = 0 ;
430
      bool found_bsl = 0;
406
      for ( i = 0 ; i < bs_tab_len ; i++ ) {
431
      for (i = 0; i < bs_tab_len; i++) {
407
	if ( bs_tab [i].bsl == (unsigned char)bsl ) {
432
	if (bs_tab[i].bsl == (unsigned char)bsl) {
408
	  int to_accum_reg ;
433
	  int to_accum_reg;
409
	  int step_accum_dest = ( i == bsl_laststep_tab ?
434
	  int step_accum_dest = (i == bsl_laststep_tab ?
410
				  dest : accum ) ;
435
				  dest : accum);
411
	  assert ( accum != R_NO_REG ) ;
436
	  assert(accum != R_NO_REG);
412
	  /* amount to accum into tmp reg */
437
	  /* amount to accum into tmp reg */
413
	  if ( bsl == 1 ) {
438
	  if (bsl == 1) {
414
	    /* accumulate src << shift */
439
	    /* accumulate src << shift */
415
	    if ( bs_tab [i].shift == 0 ) {
440
	    if (bs_tab[i].shift == 0) {
416
	      /* simple add */
441
	      /* simple add */
417
	      to_accum_reg = src ;
442
	      to_accum_reg = src;
418
	    } 
443
	    }
419
	    else {
444
	    else {
420
	      /* simple shift and add */
445
	      /* simple shift and add */
421
	      rcr_ins ( i_sll, src, bs_tab [i].shift, tmp ) ;
446
	      rcr_ins(i_sll, src, bs_tab[i].shift, tmp);
422
	      to_accum_reg = tmp ;
447
	      to_accum_reg = tmp;
423
	    }
448
	    }
424
	  } 
449
	  }
425
	  else {
450
	  else {
426
	    /* accumulate ( src * ( ( 2**bsl ) - 1 ) ) << shift */
451
	    /* accumulate ( src * ( ( 2**bsl ) - 1 ) ) << shift */
427
	    if ( !found_bsl ) {
452
	    if (!found_bsl) {
428
	      rcr_ins ( i_sll, src, bsl, tmp ) ;
453
	      rcr_ins(i_sll, src, bsl, tmp);
429
	      rrr_ins ( i_sub, tmp, src, tmp ) ;
454
	      rrr_ins(i_sub, tmp, src, tmp);
430
	      tmp_shifted = 0 ;
455
	      tmp_shifted = 0;
431
	      found_bsl = 1 ;
456
	      found_bsl = 1;
432
	    }
457
	    }
433
	    if ( bs_tab [i].shift != (unsigned char)tmp_shifted ) {
458
	    if (bs_tab[i].shift != (unsigned char)tmp_shifted) {
434
	      int extra_shift = bs_tab [i].shift - (unsigned char)tmp_shifted ;
459
	      int extra_shift = bs_tab[i].shift - (unsigned char)tmp_shifted;
435
	      assert ( extra_shift > 0 && extra_shift <= 31 ) ;
460
	      assert(extra_shift > 0 && extra_shift <= 31);
436
	      rcr_ins ( i_sll, tmp, extra_shift, tmp ) ;
461
	      rcr_ins(i_sll, tmp, extra_shift, tmp);
437
	      tmp_shifted += extra_shift ;
462
	      tmp_shifted += extra_shift;
438
	    }
463
	    }
439
	    /* else tmp already shifted to correct position */
464
	    /* else tmp already shifted to correct position */
440
	    to_accum_reg = tmp ;
465
	    to_accum_reg = tmp;
441
	  }
466
	  }
442
	  /* accumulate into accum, or on last step to dest */
467
	  /* accumulate into accum, or on last step to dest */
443
	  if ( accum_init ) {
468
	  if (accum_init) {
444
	    rrr_ins ( i_add, accum, to_accum_reg,step_accum_dest ) ;
469
	    rrr_ins(i_add, accum, to_accum_reg,step_accum_dest);
445
	  } 	
470
	  }
446
	  else {
471
	  else {
447
	    rr_ins ( i_mov, to_accum_reg, step_accum_dest ) ;
472
	    rr_ins(i_mov, to_accum_reg, step_accum_dest);
448
	    accum_init = 1 ;
473
	    accum_init = 1;
449
	  }
474
	  }
450
	  if ( i == bsl_laststep_tab ) {
475
	  if (i == bsl_laststep_tab) {
451
	    /* error check */
476
	    /* error check */
452
	    accum = R_NO_REG ;
477
	    accum = R_NO_REG;
453
	  }
478
	  }
454
	}
479
	}
455
      }
480
      }
456
    }
481
    }
457
    assert ( accum_init ) ;
482
    assert(accum_init);
458
    assert ( accum == R_NO_REG ) ;
483
    assert(accum == R_NO_REG);
459
    /* result in dest, due to step_accum_dest above */
484
    /* result in dest, due to step_accum_dest above */
460
  }
485
  }
461
  return ;
486
  return;
462
}
487
}
463
 
488
 
464
 
489
 
465
/*
490
/*
466
  IS A CONSTANT SIMPLE FOR MULTIPLICATION?
491
  IS A CONSTANT SIMPLE FOR MULTIPLICATION?
467
  
492
 
468
  A simple constant is one of the form +/- 2**n +/- m where m is at 
493
  A simple constant is one of the form +/- 2**n +/- m where m is at
469
  most MAX_MUL_POW2_OFFSET.  If constval is of this form, m is 
494
  most MAX_MUL_POW2_OFFSET.  If constval is of this form, m is
470
  returned, otherwise NOT_MUL_CONST_SIMPLE is returned.
495
  returned, otherwise NOT_MUL_CONST_SIMPLE is returned.
471
*/
496
*/
472
 
497
 
473
static int offset_mul_const_simple 
498
static int offset_mul_const_simple
474
    PROTO_N ( ( constval, sgned ) )
-
 
475
    PROTO_T ( long constval X bool sgned ){
499
(long constval, bool sgned) {
476
  int i ;
500
  int i;
477
  if ( constval < 0 ) {
501
  if (constval < 0) {
478
    if ( sgned ) {
502
    if (sgned) {
479
      constval = -constval ;
503
      constval = -constval;
480
    } 
504
    }
481
    else {
505
    else {
482
      /* very rare case */
506
      /* very rare case */
483
      return ( NOT_MUL_CONST_SIMPLE ) ;
507
      return(NOT_MUL_CONST_SIMPLE);
484
    }
508
    }
485
  }
509
  }
486
  for ( i = 0 ; i <= MAX_MUL_POW2_OFFSET ; i++ ) {
510
  for (i = 0; i <= MAX_MUL_POW2_OFFSET; i++) {
487
    long c ;	/* power of two close to constval */
511
    long c ;	/* power of two close to constval */
488
    /* check for add offsets, avoiding overflow confusion */
512
    /* check for add offsets, avoiding overflow confusion */
489
    c = constval - i ;
513
    c = constval - i;
490
    if ( IS_POW2 ( c ) && c + i == constval ) return ( i ) ;
514
    if (IS_POW2(c) && c + i == constval) return(i);
491
    /* check for sub offset of 1 only, avoiding overflow confusion */
515
    /* check for sub offset of 1 only, avoiding overflow confusion */
492
    if ( i == 1 ) {
516
    if (i == 1) {
493
      c = constval + i ;
517
      c = constval + i;
494
      if ( IS_POW2 ( c ) && c - i == constval ) return ( -i ) ;
518
      if (IS_POW2(c) && c - i == constval) return(-i);
495
    }
519
    }
496
  }
520
  }
497
  return ( NOT_MUL_CONST_SIMPLE ) ;
521
  return(NOT_MUL_CONST_SIMPLE);
498
}
522
}
499
 
523
 
500
 
524
 
501
/*
525
/*
502
  MULTIPLICATION BY A SIMPLE CONSTANT
526
  MULTIPLICATION BY A SIMPLE CONSTANT
503
*/
527
*/
504
 
528
 
505
static void mul_const_simple 
529
static void mul_const_simple
506
    PROTO_N ( ( src, constval, dest, sgned ) )
-
 
507
    PROTO_T ( int src X long constval X int dest X bool sgned ){
530
(int src, long constval, int dest, bool sgned) {
508
  long c ;		/* power of two close to constval */
531
  long c ;		/* power of two close to constval */
509
  int add_sub ;	/* difference from power of two */
532
  int add_sub ;	/* difference from power of two */
510
  int shift_const ;
533
  int shift_const;
511
 
534
 
512
  if ( sgned && constval < 0 ) {
535
  if (sgned && constval < 0) {
513
    if ( constval == -1 ) {
536
    if (constval == -1) {
514
      /* X * -1 => -X */
537
      /* X * -1 => -X */
515
      rr_ins ( i_neg, src, dest ) ;
538
      rr_ins(i_neg, src, dest);
516
      return ;
539
      return;
517
    }
540
    }
518
    constval = -constval ;
541
    constval = -constval;
519
    /* incorrect to modify source */
542
    /* incorrect to modify source */
520
    rr_ins ( i_neg, src, R_TMP ) ;
543
    rr_ins(i_neg, src, R_TMP);
521
    src = R_TMP ;
544
    src = R_TMP;
522
  }
545
  }
523
  
546
 
524
  if ( constval == 1 ) {
547
  if (constval == 1) {
525
    if ( src != dest ){
548
    if (src != dest) {
526
      rr_ins ( i_mov, src, dest ) ;
549
      rr_ins(i_mov, src, dest);
527
    }
550
    }
528
    return ;
551
    return;
529
  } 
552
  }
530
  else if ( constval == 2 ) {
553
  else if (constval == 2) {
531
    /* use add, which can be peephole optimised to addcc later */
554
    /* use add, which can be peephole optimised to addcc later */
532
    rrr_ins ( i_add, src, src, dest ) ;
555
    rrr_ins(i_add, src, src, dest);
533
    return ;
556
    return;
-
 
557
  }
-
 
558
  add_sub = offset_mul_const_simple(constval, sgned);
-
 
559
  c = constval - add_sub;
-
 
560
 
-
 
561
  assert(constval == c + add_sub);
-
 
562
  shift_const = bit_no(c);
-
 
563
  assert(constval == (1 << shift_const) + add_sub);
-
 
564
  if (add_sub == 0) {
-
 
565
    rcr_ins(i_sll, src, shift_const, dest);
534
  }
566
  }
535
  add_sub = offset_mul_const_simple ( constval, sgned ) ;
-
 
536
  c = constval - add_sub ;
-
 
537
  
-
 
538
  assert ( constval == c + add_sub ) ;
-
 
539
  shift_const = bit_no ( c ) ;
-
 
540
  assert ( constval == ( 1 << shift_const ) + add_sub ) ;
-
 
541
  if ( add_sub == 0 ) {
-
 
542
    rcr_ins ( i_sll, src, shift_const, dest ) ;
-
 
543
  } 
-
 
544
  else {
567
  else {
545
    /* add_sub != 0 */
568
    /* add_sub != 0 */
546
    int i ;
569
    int i;
547
    int n ;		/* number of add_sub instructions */
570
    int n ;		/* number of add_sub instructions */
548
    int inter_reg ;	/* for partial result */
571
    int inter_reg ;	/* for partial result */
549
    ins_p i_add_sub ;
572
    ins_p i_add_sub;
550
    
573
 
551
    if ( add_sub > 0 ) {
574
    if (add_sub > 0) {
552
      i_add_sub = i_add ;
575
      i_add_sub = i_add;
553
      n = add_sub ;
576
      n = add_sub;
554
    } 
577
    }
555
    else {
578
    else {
556
      i_add_sub = i_sub ;
579
      i_add_sub = i_sub;
557
      n = -add_sub ;
580
      n = -add_sub;
558
    }
581
    }
559
    if ( src == dest ) {
582
    if (src == dest) {
560
      /* must preserve src for add/sub */
583
      /* must preserve src for add/sub */
561
      inter_reg = R_TMP ;
584
      inter_reg = R_TMP;
562
    } 
585
    }
563
    else {
586
    else {
564
      inter_reg = dest ;
587
      inter_reg = dest;
565
    }
588
    }
566
    assert ( src != inter_reg ) ;
589
    assert(src != inter_reg);
567
    rcr_ins ( i_sll, src, shift_const, inter_reg ) ;
590
    rcr_ins(i_sll, src, shift_const, inter_reg);
568
    /* all but final add_sub */
591
    /* all but final add_sub */
569
    for ( i = 1 ; i < n ; i++ ) {
592
    for (i = 1; i < n; i++) {
570
      rrr_ins ( i_add_sub, inter_reg, src, inter_reg ) ;
593
      rrr_ins(i_add_sub, inter_reg, src, inter_reg);
571
    }
594
    }
572
    
595
 
573
    /* final add_sub to dest reg */
596
    /* final add_sub to dest reg */
574
    rrr_ins ( i_add_sub, inter_reg, src, dest ) ;
597
    rrr_ins(i_add_sub, inter_reg, src, dest);
575
  }
598
  }
576
  return ;
599
  return;
577
}
600
}
578
 
601
 
579
 
602
 
580
/*
603
/*
581
  CODE GENERATION ROUTINE FOR MULTIPLICATION BY A CONSTANT
604
  CODE GENERATION ROUTINE FOR MULTIPLICATION BY A CONSTANT
582
*/
605
*/
583
 
606
 
584
static void mul_const 
607
static void mul_const
585
    PROTO_N ( ( src, constval, dest, sp, sgned ) )
-
 
586
    PROTO_T ( int src X long constval X int dest X space sp X bool sgned ){
608
(int src, long constval, int dest, space sp, bool sgned) {
587
  if ( constval == 0 ) {
609
  if (constval == 0) {
588
    /* rare case not handled by mul_const_X () */
610
    /* rare case not handled by mul_const_X () */
589
    ir_ins ( i_mov, 0, dest ) ;
611
    ir_ins(i_mov, 0, dest);
590
  } 
-
 
591
  else if ( offset_mul_const_simple ( constval, sgned ) ==
-
 
592
	    NOT_MUL_CONST_SIMPLE ) {
-
 
593
    mul_const_complex ( src, constval, dest, sp, sgned ) ;
-
 
594
  } 
-
 
595
  else {
-
 
596
    mul_const_simple ( src, constval, dest, sgned ) ;
-
 
597
  }
612
  }
-
 
613
  else if (offset_mul_const_simple(constval, sgned) ==
-
 
614
	    NOT_MUL_CONST_SIMPLE) {
-
 
615
    mul_const_complex(src, constval, dest, sp, sgned);
-
 
616
  }
-
 
617
  else {
-
 
618
    mul_const_simple(src, constval, dest, sgned);
-
 
619
  }
598
  return ;
620
  return;
599
}
621
}
600
 
622
 
601
 
623
 
602
/*
624
/*
603
  CODE GENERATION ROUTINE FOR MULTIPLICATION OPERATIONS
625
  CODE GENERATION ROUTINE FOR MULTIPLICATION OPERATIONS
604
*/
626
*/
605
static int do_mul_comm 
627
static int do_mul_comm
606
    PROTO_N ( ( seq, sp, final_reg, sgned ) )
-
 
607
    PROTO_T ( exp seq X space sp X int final_reg X bool sgned ){
628
(exp seq, space sp, int final_reg, bool sgned) {
608
  space nsp ;	
629
  space nsp;
609
  int mul_proc ;
630
  int mul_proc;
610
  exp arg2 = bro ( seq ) ;
631
  exp arg2 = bro(seq);
611
  int has_error_treatment = !optop(father(seq));
632
  int has_error_treatment = !optop(father(seq));
612
  if ( name ( arg2 ) == val_tag && !has_error_treatment) {
633
  if (name(arg2) == val_tag && !has_error_treatment) {
613
    /* const optim */
634
    /* const optim */
614
    int lhs_reg = reg_operand ( seq, sp ) ;
635
    int lhs_reg = reg_operand(seq, sp);
615
    sp = guardreg ( lhs_reg, sp ) ;
636
    sp = guardreg(lhs_reg, sp);
616
    /* check () & scan () should move const to last */
637
    /* check () & scan () should move const to last */
617
    assert ( last ( arg2 ) ) ;
638
    assert(last(arg2));
618
    if ( final_reg == R_NO_REG || final_reg == R_G0) {
639
    if (final_reg == R_NO_REG || final_reg == R_G0) {
619
      /* better code from mul_const if src != dest reg */
640
      /* better code from mul_const if src != dest reg */
620
      final_reg = getreg ( sp.fixed ) ;
641
      final_reg = getreg(sp.fixed);
621
      sp = guardreg ( final_reg, sp ) ;
642
      sp = guardreg(final_reg, sp);
622
    }
643
    }
623
    mul_const ( lhs_reg, ( long ) no ( arg2 ), final_reg, sp, sgned ) ;
644
    mul_const(lhs_reg,(long)no(arg2), final_reg, sp, sgned);
624
    return ( final_reg ) ;
645
    return(final_reg);
625
  }
646
  }
626
  /* need to call .mul/.umul */
647
  /* need to call .mul/.umul */
627
  mul_proc = ( sgned ? SPECIAL_MUL : SPECIAL_UMUL ) ;
648
  mul_proc = (sgned ? SPECIAL_MUL : SPECIAL_UMUL);
628
  reg_operand_here ( seq, sp, R_O0 ) ;
649
  reg_operand_here(seq, sp, R_O0);
629
  nsp = needreg ( R_O0, sp ) ;
650
  nsp = needreg(R_O0, sp);
630
  for ( ; ; ) {
651
  for (; ;) {
631
    /* should have break out below by now */
652
    /* should have break out below by now */
632
    assert ( !last ( seq ) ) ;
653
    assert(!last(seq));
633
    seq = bro ( seq ) ;
654
    seq = bro(seq);
634
    if ( !has_error_treatment && name ( seq ) == val_tag &&
655
    if (!has_error_treatment && name(seq) == val_tag &&
635
	 offset_mul_const_simple ( ( long ) no ( seq ), sgned ) !=
656
	 offset_mul_const_simple((long)no(seq), sgned)!=
636
	 NOT_MUL_CONST_SIMPLE) {
657
	 NOT_MUL_CONST_SIMPLE) {
637
      /* const optim */
658
      /* const optim */
638
      /* check () & scan () should move const to last */
659
      /* check () & scan () should move const to last */
639
      assert ( last ( seq ) ) ;
660
      assert(last(seq));
640
      if ( final_reg == R_NO_REG ) {
661
      if (final_reg == R_NO_REG) {
641
	/* better code from mul_const if src != dest reg */
662
	/* better code from mul_const if src != dest reg */
642
	final_reg = R_O1 ;
663
	final_reg = R_O1;
643
      }
664
      }
644
      mul_const ( R_O0, ( long ) no ( seq ), final_reg, nsp, sgned ) ;
665
      mul_const(R_O0,(long)no(seq), final_reg, nsp, sgned);
645
      break ;
666
      break;
646
    } 
667
    }
647
    else {
668
    else {
648
      reg_operand_here ( seq, nsp, R_O1 ) ;
669
      reg_operand_here(seq, nsp, R_O1);
649
      if(has_error_treatment){
670
      if (has_error_treatment) {
650
	rrr_ins(sgned?i_smulcc:i_umulcc,R_O0,R_O1,R_O0);
671
	rrr_ins(sgned?i_smulcc:i_umulcc,R_O0,R_O1,R_O0);
651
      }
672
      }
652
      else{
673
      else{
653
	call_special_routine ( mul_proc ) ;
674
	call_special_routine(mul_proc);
654
      }
675
      }
655
      clear_sun_call_divrem_regs ( nsp ) ;
676
      clear_sun_call_divrem_regs(nsp);
656
      if ( last ( seq ) ) {
677
      if (last(seq)) {
657
	if ( final_reg == R_NO_REG || final_reg == R_G0 ) {
678
	if (final_reg == R_NO_REG || final_reg == R_G0) {
658
	  final_reg = R_O0 ;
679
	  final_reg = R_O0;
659
	} 
680
	}
660
	else {
681
	else {
661
	  rr_ins ( i_mov, R_O0, final_reg ) ;
682
	  rr_ins(i_mov, R_O0, final_reg);
662
	}
683
	}
663
	break ;
684
	break;
664
      }
685
      }
665
    }
686
    }
666
  }
687
  }
667
  return ( final_reg ) ;
688
  return(final_reg);
668
}
689
}
669
 
690
 
670
 
691
 
671
/*
692
/*
672
  FLAG : ALTERNATIVE DIVISION
693
  FLAG : ALTERNATIVE DIVISION
673
 
694
 
674
  There are two division and remainder operations.  In the first the
695
  There are two division and remainder operations.  In the first the
675
  remainder has the same sign as the denominator, and in the second
696
  remainder has the same sign as the denominator, and in the second
676
  the same sign as the numerator.  The second is the default.  This
697
  the same sign as the numerator.  The second is the default.  This
677
  flag is set to indicate that the first form should be used.
698
  flag is set to indicate that the first form should be used.
678
*/
699
*/
679
 
700
 
680
/* using a flag is unsafe, lest the lhs itself contains a div. 
701
/* using a flag is unsafe, lest the lhs itself contains a div.
681
   Instead recompute otherdiv when needed*/
702
   Instead recompute otherdiv when needed*/
682
/*static bool other_div = 0 ;*/
703
/*static bool other_div = 0 ;*/
683
 
704
 
684
 
705
 
685
/*
706
/*
686
  CODE GENERATION ROUTINE FOR DIVISION OPERATIONS
707
  CODE GENERATION ROUTINE FOR DIVISION OPERATIONS
687
*/
708
*/
688
 
709
 
689
static int do_div 
710
static int do_div
690
    PROTO_N ( ( seq, sp, final_reg, sgned ) )
-
 
691
    PROTO_T ( exp seq X space sp X int final_reg X bool sgned ){
711
(exp seq, space sp, int final_reg, bool sgned) {
692
  int p ;
712
  int p;
693
  exp lhs = seq ;
713
  exp lhs = seq;
694
  exp rhs = bro ( lhs ) ;
714
  exp rhs = bro(lhs);
695
  int has_error_treatment = !optop(father(seq)) && !error_treatment_is_trap(father(seq));
715
  int has_error_treatment = !optop(father(seq)) && !error_treatment_is_trap(father(seq));
696
  int et;
716
  int et;
697
  assert ( last ( rhs ) ) ;	/* so bro(rhs) == the div exp  */
717
  assert ( last ( rhs ) ) ;	/* so bro(rhs) == the div exp  */
698
  if ( !has_error_treatment && name ( rhs ) == val_tag && 
718
  if (!has_error_treatment && name(rhs) == val_tag &&
699
       IS_POW2 ( no ( rhs )) && no(rhs) > 0)  {
719
       IS_POW2(no(rhs)) && no(rhs) > 0) {
700
    long constval = no ( rhs ) ;
720
    long constval = no(rhs);
701
    /* const optim, replace div by 2**n by shift right */
721
    /* const optim, replace div by 2**n by shift right */
702
    int lhs_reg = reg_operand ( lhs, sp ) ;
722
    int lhs_reg = reg_operand(lhs, sp);
703
    int shift_const = bit_no ( constval ) ;
723
    int shift_const = bit_no(constval);
704
    sp = guardreg ( lhs_reg, sp ) ;
724
    sp = guardreg(lhs_reg, sp);
705
    if ( final_reg == R_NO_REG ) {
725
    if (final_reg == R_NO_REG) {
706
      final_reg = getreg ( sp.fixed ) ;
726
      final_reg = getreg(sp.fixed);
707
      sp = guardreg ( final_reg, sp ) ;
727
      sp = guardreg(final_reg, sp);
708
    }	
728
    }
709
    if ( constval == 1 ) {
729
    if (constval == 1) {
710
      /* result always lhs */
730
      /* result always lhs */
711
      rr_ins ( i_mov, lhs_reg, final_reg ) ;
731
      rr_ins(i_mov, lhs_reg, final_reg);
712
      return ( final_reg ) ;
732
      return(final_reg);
713
    }
733
    }
714
 
734
 
715
    if (!sgned) {
735
    if (!sgned) {
716
				/* unsigned, easy, just shift */
736
				/* unsigned, easy, just shift */
717
      rcr_ins ( i_srl, lhs_reg, shift_const, final_reg ) ;
737
      rcr_ins(i_srl, lhs_reg, shift_const, final_reg);
718
      return ( final_reg ) ;
738
      return(final_reg);
719
    }
739
    }
720
 
740
 
721
    if (name(bro(rhs)) == div2_tag) /* shift and fix up for sgned div2 */
741
    if (name(bro(rhs)) == div2_tag) /* shift and fix up for sgned div2 */
722
    {
742
    {
723
      /* signed, adjust lhs before shift */
743
      /* signed, adjust lhs before shift */
724
      int tmp_reg = R_TMP ;
744
      int tmp_reg = R_TMP;
725
      assert ( shift_const > 0 ) ; /* assumed below */
745
      assert ( shift_const > 0 ) ; /* assumed below */
726
      if ( shift_const - 1 != 0 ) {
746
      if (shift_const - 1 != 0) {
727
	rcr_ins ( i_sra, lhs_reg, shift_const - 1, tmp_reg ) ;
747
	rcr_ins(i_sra, lhs_reg, shift_const - 1, tmp_reg);
728
	rcr_ins ( i_srl, tmp_reg, 32 - shift_const, tmp_reg ) ;
748
	rcr_ins(i_srl, tmp_reg, 32 - shift_const, tmp_reg);
729
      } else {
749
      } else {
730
	rcr_ins ( i_srl, lhs_reg, 32 - shift_const, tmp_reg ) ;
750
	rcr_ins(i_srl, lhs_reg, 32 - shift_const, tmp_reg);
731
      }
751
      }
732
      rrr_ins ( i_add, lhs_reg, tmp_reg, tmp_reg ) ;
752
      rrr_ins(i_add, lhs_reg, tmp_reg, tmp_reg);
733
      rcr_ins ( i_sra, tmp_reg, shift_const, final_reg ) ;
753
      rcr_ins(i_sra, tmp_reg, shift_const, final_reg);
734
      return (final_reg);
754
      return(final_reg);
735
    } 
755
    }
736
				/* must be signed div1, a simple shift */
756
				/* must be signed div1, a simple shift */
737
    rcr_ins ( i_sra, lhs_reg, shift_const, final_reg ) ;
757
    rcr_ins(i_sra, lhs_reg, shift_const, final_reg);
738
    return ( final_reg ) ;
758
    return(final_reg);
739
  }
759
  }
740
  if(0 /*has_error_treatment*/) {
760
  if(0 /*has_error_treatment*/) {
741
    ins_p dop;
761
    ins_p dop;
742
    reg_operand_here(lhs,sp,R_O0);
762
    reg_operand_here(lhs,sp,R_O0);
743
    reg_operand_here(rhs,sp,R_O1);
763
    reg_operand_here(rhs,sp,R_O1);
744
    if(error_treatment_is_trap(father(seq))){
764
    if (error_treatment_is_trap(father(seq))) {
745
      if(sgned){
765
      if (sgned) {
746
	dop = i_sdiv;
766
	dop = i_sdiv;
747
      }
767
      }
748
      else{
768
      else{
749
	dop = i_udiv;
769
	dop = i_udiv;
750
      }
770
      }
751
    }
771
    }
752
    else{
772
    else{
753
      if(sgned){
773
      if (sgned) {
754
	dop = i_sdivcc;
774
	dop = i_sdivcc;
755
      }
775
      }
756
      else{
776
      else{
757
	dop = i_udivcc;
777
	dop = i_udivcc;
758
      }
778
      }
759
    }
779
    }
760
    rrr_ins(dop,R_O0,R_O1,R_O0);
780
    rrr_ins(dop,R_O0,R_O1,R_O0);
761
    return R_O0;
781
    return R_O0;
762
    /* otherwise need to call .div/.udiv */
782
    /* otherwise need to call .div/.udiv */
763
  }
783
  }
764
  else if ( sgned && name(bro(rhs)) == div1_tag ) {
784
  else if (sgned && name(bro(rhs)) == div1_tag) {
765
    p = SPECIAL_DIV1 ;
785
    p = SPECIAL_DIV1;
766
  } 
786
  }
767
  else {
787
  else {
768
    p = ( sgned ? SPECIAL_DIV2 : SPECIAL_UDIV2 ) ;
788
    p = (sgned ? SPECIAL_DIV2 : SPECIAL_UDIV2);
769
  }
789
  }
770
  if(error_treatment_is_trap(father(seq))) {
790
  if (error_treatment_is_trap(father(seq))) {
771
    et = IS_TRAP;
791
    et = IS_TRAP;
772
  }
792
  }
773
  else if(has_error_treatment) {
793
  else if (has_error_treatment) {
774
    et = -no(son(pt(father(seq))));
794
    et = -no(son(pt(father(seq))));
775
  }
795
  }
776
  else {
796
  else {
777
    et = 0;
797
    et = 0;
778
  }
798
  }
779
  return ( call_muldivrem ( lhs, rhs, sp, p, et ) ) ;
799
  return(call_muldivrem(lhs, rhs, sp, p, et));
780
}
800
}
781
 
801
 
782
 
802
 
783
/*
803
/*
784
  CODE GENERATION ROUTINE FOR REMAINDER OPERATIONS
804
  CODE GENERATION ROUTINE FOR REMAINDER OPERATIONS
785
*/
805
*/
786
 
806
 
787
static int do_rem 
807
static int do_rem
788
    PROTO_N ( ( seq, sp, final_reg, sgned ) )
-
 
789
    PROTO_T ( exp seq X space sp X int final_reg X bool sgned ){
808
(exp seq, space sp, int final_reg, bool sgned) {
790
  int p ;
809
  int p;
791
  exp lhs = seq ;
810
  exp lhs = seq;
792
  exp rhs = bro ( lhs ) ;
811
  exp rhs = bro(lhs);
793
  
812
 
794
  assert ( last ( rhs ) ) ;
813
  assert(last(rhs));
795
  
814
 
796
  if ( name ( rhs ) == val_tag && IS_POW2 ( no ( rhs ) ) && (no(rhs) > 0) ) {
815
  if (name(rhs) == val_tag && IS_POW2(no(rhs)) && (no(rhs) > 0)) {
797
    long constval = no ( rhs ) ;
816
    long constval = no(rhs);
798
    
817
 
799
    /* const optim, replace rem by 2**n by and with mask */
818
    /* const optim, replace rem by 2**n by and with mask */
800
    int lhs_reg = reg_operand ( lhs, sp ) ;
819
    int lhs_reg = reg_operand(lhs, sp);
801
    sp = guardreg ( lhs_reg, sp ) ;
820
    sp = guardreg(lhs_reg, sp);
802
    
821
 
803
    if ( final_reg == R_NO_REG ) {
822
    if (final_reg == R_NO_REG) {
804
      final_reg = getreg ( sp.fixed ) ;
823
      final_reg = getreg(sp.fixed);
805
    }
824
    }
806
    
825
 
807
    if ( constval == 1 ) {
826
    if (constval == 1) {
808
      /* result always 0 */
827
      /* result always 0 */
809
      ir_ins ( i_mov, 0, final_reg ) ;
828
      ir_ins(i_mov, 0, final_reg);
810
      return final_reg;
829
      return final_reg;
811
    }
830
    }
812
    if ( !sgned ) {
831
    if (!sgned) {
813
		/* unsigned by mask */
832
		/* unsigned by mask */
814
      rcr_ins ( i_and, lhs_reg, constval - 1, final_reg ) ;
833
      rcr_ins(i_and, lhs_reg, constval - 1, final_reg);
815
      return final_reg;
834
      return final_reg;
816
    }
835
    }
817
    if (name(bro(rhs)) == rem2_tag){
836
    if (name(bro(rhs)) == rem2_tag) {
818
      /* signed, need to allow for negative lhs. Treat l % c
837
      /* signed, need to allow for negative lhs. Treat l % c
819
	 as l - ( l / c ) * c */
838
	 as l - ( l / c ) * c */
820
      int tmp_reg = R_TMP ;
839
      int tmp_reg = R_TMP;
821
      int shift_const = bit_no ( constval ) ;
840
      int shift_const = bit_no(constval);
822
      assert ( shift_const > 0 ) ; /* assumed below */
841
      assert ( shift_const > 0 ) ; /* assumed below */
823
      /* do the divide, as in do_div */
842
      /* do the divide, as in do_div */
824
      if ( shift_const - 1 != 0 ) {
843
      if (shift_const - 1 != 0) {
825
	rcr_ins ( i_sra, lhs_reg, shift_const - 1, tmp_reg ) ;
844
	rcr_ins(i_sra, lhs_reg, shift_const - 1, tmp_reg);
826
	rcr_ins ( i_srl, tmp_reg, 32 - shift_const, tmp_reg ) ;
845
	rcr_ins(i_srl, tmp_reg, 32 - shift_const, tmp_reg);
827
      } 
846
      }
828
      else {
847
      else {
829
	rcr_ins ( i_srl, lhs_reg, 32 - shift_const, tmp_reg ) ;
848
	rcr_ins(i_srl, lhs_reg, 32 - shift_const, tmp_reg);
830
      }
849
      }
831
      rrr_ins ( i_add, lhs_reg, tmp_reg, tmp_reg ) ;
850
      rrr_ins(i_add, lhs_reg, tmp_reg, tmp_reg);
832
      rcr_ins ( i_sra, tmp_reg, shift_const, tmp_reg ) ;
851
      rcr_ins(i_sra, tmp_reg, shift_const, tmp_reg);
833
		/* multiply */
852
		/* multiply */
834
      rcr_ins ( i_sll, tmp_reg, shift_const, tmp_reg ) ;
853
      rcr_ins(i_sll, tmp_reg, shift_const, tmp_reg);
835
      /* subtract */
854
      /* subtract */
836
      rrr_ins ( i_sub, lhs_reg, tmp_reg, final_reg ) ;
855
      rrr_ins(i_sub, lhs_reg, tmp_reg, final_reg);
837
      return final_reg;
856
      return final_reg;
838
    }
857
    }
839
    rcr_ins ( i_and, lhs_reg, constval - 1, final_reg ) ;
858
    rcr_ins(i_and, lhs_reg, constval - 1, final_reg);
840
    return final_reg;
859
    return final_reg;
841
  }
860
  }
842
  
861
 
843
  /* otherwise need to call .rem/.urem */
862
  /* otherwise need to call .rem/.urem */
844
  if ( sgned && name(bro(rhs)) == mod_tag) {
863
  if (sgned && name(bro(rhs)) == mod_tag) {
845
    p = SPECIAL_REM1 ;
864
    p = SPECIAL_REM1;
846
  } 
865
  }
847
  else {
866
  else {
848
    p = ( sgned ? SPECIAL_REM2 : SPECIAL_UREM2 ) ;
867
    p = (sgned ? SPECIAL_REM2 : SPECIAL_UREM2);
849
  }
868
  }
850
  return ( call_muldivrem ( lhs, rhs, sp, p, 0 ) ) ;
869
  return(call_muldivrem(lhs, rhs, sp, p, 0));
851
}
870
}
852
 
871
 
853
 
872
 
854
/*
873
/*
855
  FUNCTION TYPE
874
  FUNCTION TYPE
856
*/
875
*/
857
 
876
 
858
typedef int ( *find_fn ) PROTO_S ( ( exp, space, int, bool ) ) ;
877
typedef int(*find_fn)(exp, space, int, bool);
859
 
878
 
860
 
879
 
861
/*
880
/*
862
  GENERATE CODE FOR e USING do_fn
881
  GENERATE CODE FOR e USING do_fn
863
*/
882
*/
864
 
883
 
865
static int find_reg_and_apply 
884
static int find_reg_and_apply
866
    PROTO_N ( ( e, sp, dest, sgned, do_fn ) )
-
 
867
    PROTO_T ( exp e X space sp X where dest X bool sgned X find_fn do_fn ){
885
(exp e, space sp, where dest, bool sgned, find_fn do_fn) {
868
  ans a ;
886
  ans a;
869
  int dest_reg ;
887
  int dest_reg;
870
  exp seq = son ( e ) ;
888
  exp seq = son(e);
871
  /* tidyshort ( dest, sh ( e ) ) ; ??? */
889
  /* tidyshort ( dest, sh ( e ) ) ; ??? */
872
  switch ( discrim ( dest.answhere ) ) {
890
  switch (discrim(dest.answhere)) {
873
    case inreg : {
891
    case inreg: {
874
      dest_reg = ( *do_fn ) ( seq, sp, regalt ( dest.answhere ),
892
      dest_reg = (*do_fn)(seq, sp, regalt(dest.answhere),
875
			    sgned ) ;
893
			    sgned);
876
      break ;
894
      break;
877
    }
895
    }
878
    case insomereg : {
896
    case insomereg: {
879
      /* leave ( *do_fn ) () to allocate reg */
897
      /* leave ( *do_fn ) () to allocate reg */
880
      int *dr = someregalt ( dest.answhere ) ;
898
      int *dr = someregalt(dest.answhere);
881
      *dr = ( *do_fn ) ( seq, sp, R_NO_REG, sgned ) ;
899
      *dr = (*do_fn)(seq, sp, R_NO_REG, sgned);
882
      /* no need for move */
900
      /* no need for move */
883
      return ( *dr ) ;
901
      return(*dr);
884
    }
902
    }
885
    default : {
903
    default : {
886
      /* leave ( *do_fn ) () to allocate reg */
904
      /* leave ( *do_fn ) () to allocate reg */
887
      dest_reg = ( *do_fn ) ( seq, sp, R_NO_REG, sgned ) ;
905
      dest_reg = (*do_fn)(seq, sp, R_NO_REG, sgned);
888
      break ;
906
      break;
889
    }
907
    }
890
  }
908
  }
891
  assert ( dest_reg != R_NO_REG ) ;
909
  assert(dest_reg != R_NO_REG);
892
  setregalt ( a, dest_reg ) ;
910
  setregalt(a, dest_reg);
893
  sp = guardreg ( dest_reg, sp ) ;
911
  sp = guardreg(dest_reg, sp);
894
  ( void ) move ( a, dest, sp.fixed, sgned ) ;
912
 (void)move(a, dest, sp.fixed, sgned);
895
  return ( dest_reg ) ;
913
  return(dest_reg);
896
}
914
}
897
 
915
 
898
 
916
 
899
/*
917
/*
900
  GENERATE CODE FOR A MULTIPLICATION OPERATION
918
  GENERATE CODE FOR A MULTIPLICATION OPERATION
901
*/
919
*/
902
 
920
 
903
int do_mul_comm_op 
921
int do_mul_comm_op
904
    PROTO_N ( ( e, sp, dest, sgned ) )
-
 
905
    PROTO_T ( exp e X space sp X where dest X bool sgned ){
922
(exp e, space sp, where dest, bool sgned) {
906
  return ( find_reg_and_apply ( e, sp, dest, sgned, do_mul_comm ) ) ;
923
  return(find_reg_and_apply(e, sp, dest, sgned, do_mul_comm));
907
}
924
}
908
 
925
 
909
 
926
 
910
/*
927
/*
911
  GENERATE CODE FOR A DIVISION OPERATION
928
  GENERATE CODE FOR A DIVISION OPERATION
912
*/
929
*/
913
 
930
 
914
int do_div_op 
931
int do_div_op
915
    PROTO_N ( ( e, sp, dest, sgned ) )
-
 
916
    PROTO_T ( exp e X space sp X where dest X bool sgned ){
932
(exp e, space sp, where dest, bool sgned) {
917
/*    other_div = ( bool ) ( ( name ( e ) == div1_tag && sgned ) ? 1 : 0 ) ;*/
933
/*    other_div = ( bool ) ( ( name ( e ) == div1_tag && sgned ) ? 1 : 0 ) ;*/
918
  return ( find_reg_and_apply ( e, sp, dest, sgned, do_div ) ) ;
934
  return(find_reg_and_apply(e, sp, dest, sgned, do_div));
919
}
935
}
920
 
936
 
921
 
937
 
922
/*
938
/*
923
  GENERATE CODE FOR A REMAINDER OPERATION
939
  GENERATE CODE FOR A REMAINDER OPERATION
924
*/
940
*/
925
 
941
 
926
int do_rem_op 
942
int do_rem_op
927
    PROTO_N ( ( e, sp, dest, sgned ) )
-
 
928
    PROTO_T ( exp e X space sp X where dest X bool sgned ){
943
(exp e, space sp, where dest, bool sgned) {
929
/*    other_div = ( bool ) ( ( name ( e ) == mod_tag && sgned ) ? 1 : 0 ) ;*/
944
/*    other_div = ( bool ) ( ( name ( e ) == mod_tag && sgned ) ? 1 : 0 ) ;*/
930
  return ( find_reg_and_apply ( e, sp, dest, sgned, do_rem ) ) ;
945
  return(find_reg_and_apply(e, sp, dest, sgned, do_rem));
931
}
946
}
932
 
947
 
933
 
948
 
934
/*
949
/*
935
  IS AN EXPRESSION IMPLEMENTED BY A SYSTEM CALL?
950
  IS AN EXPRESSION IMPLEMENTED BY A SYSTEM CALL?
936
  Multiplications, divisions and remainders, except in simple cases,
951
  Multiplications, divisions and remainders, except in simple cases,
937
  are implemented by means of system calls.  This routine checks if
952
  are implemented by means of system calls.  This routine checks if
938
  an expression represents one of these calls.
953
  an expression represents one of these calls.
939
*/
954
*/
940
 
955
 
941
bool is_muldivrem_call 
956
bool is_muldivrem_call
942
    PROTO_N ( ( e ) )
-
 
943
    PROTO_T ( exp e ){
957
(exp e) {
944
  switch ( name ( e ) ) {
958
  switch (name(e)) {
945
 
959
 
946
#if use_long_double
960
#if use_long_double
947
    case test_tag:
961
    case test_tag:
948
    case chfl_tag:
962
    case chfl_tag:
949
    case round_tag: {
963
    case round_tag: {
950
      exp s = son ( e ) ;
964
      exp s = son(e);
951
      if ( name ( sh ( s ) ) == doublehd ) return ( 1 ) ;
965
      if (name(sh(s)) == doublehd) return(1);
952
      /* FALL THROUGH */
966
      /* FALL THROUGH */
953
    }
967
    }
954
    case fplus_tag:
968
    case fplus_tag:
955
    case fminus_tag:
969
    case fminus_tag:
956
    case fmult_tag:
970
    case fmult_tag:
957
    case fdiv_tag:
971
    case fdiv_tag:
958
    case fneg_tag:
972
    case fneg_tag:
959
    case fabs_tag:
973
    case fabs_tag:
960
    case float_tag: {
974
    case float_tag: {
961
      if ( name ( sh ( e ) ) == doublehd ) return ( 1 ) ;
975
      if (name(sh(e)) == doublehd) return(1);
962
      return ( 0 ) ;
976
      return(0);
963
    }
977
    }
964
#endif
978
#endif
965
    
979
 
966
    case mult_tag:
980
    case mult_tag:
967
    case offset_mult_tag: {
981
    case offset_mult_tag: {
968
      /*multneeds - simple cases don't need a call */
982
      /*multneeds - simple cases don't need a call */
969
      exp arg2 = bro ( son ( e ) ) ;
983
      exp arg2 = bro(son(e));
970
      if ( last ( arg2 ) && name ( arg2 ) == val_tag && optop(e) ) {
984
      if (last(arg2) && name(arg2) == val_tag && optop(e)) {
971
	return ( 0 ) ;
985
	return(0);
972
      }	
986
      }
973
      return ( 1 ) ;
987
      return(1);
974
    }
988
    }
975
    case div0_tag:
989
    case div0_tag:
976
    case rem0_tag:
990
    case rem0_tag:
977
    case div1_tag:
991
    case div1_tag:
978
    case mod_tag:
992
    case mod_tag:
979
    case div2_tag:
993
    case div2_tag:
980
    case rem2_tag:
994
    case rem2_tag:
981
    case offset_div_tag:
995
    case offset_div_tag:
982
    case offset_div_by_int_tag: {
996
    case offset_div_by_int_tag: {
983
      /*remneeds, divneeds - simple cases don't need a call */
997
      /*remneeds, divneeds - simple cases don't need a call */
984
      exp arg2 = bro ( son ( e ) ) ;
998
      exp arg2 = bro(son(e));
985
      if ( last ( arg2 ) && name ( arg2 ) == val_tag && optop(e) ) {
999
      if (last(arg2) && name(arg2) == val_tag && optop(e)) {
986
	long constval = no ( arg2 ) ;
1000
	long constval = no(arg2);
987
	if ( constval > 0 && IS_POW2 ( constval ))
1001
	if (constval > 0 && IS_POW2(constval))
988
	  return ( 0 ) ;
1002
	  return(0);
989
      }
1003
      }
990
      return ( 1 ) ;
1004
      return(1);
991
    }
1005
    }
992
    case movecont_tag:
1006
    case movecont_tag:
993
    return 1;			/* at present */
1007
    return 1;			/* at present */
994
    default: {
1008
    default: {
995
      return ( 0 ) ;
1009
      return(0);
996
    }
1010
    }
997
  }
1011
  }
998
}
1012
}
999
 
1013
 
1000
 
1014
 
1001
/*
1015
/*
1002
  ESTIMATE NEEDS FOR MULTIPLICATION
1016
  ESTIMATE NEEDS FOR MULTIPLICATION
1003
*/
1017
*/
1004
 
1018
 
1005
needs multneeds 
1019
needs multneeds
1006
    PROTO_N ( ( e, at ) )
-
 
1007
    PROTO_T ( exp * e X exp ** at ){
1020
(exp * e, exp ** at) {
1008
  needs n ;
1021
  needs n;
1009
  exp arg1 = son ( *e ) ;
1022
  exp arg1 = son(*e);
1010
  exp arg2 = bro ( arg1 ) ;
1023
  exp arg2 = bro(arg1);
1011
  n = likeplus ( e, at ) ;
1024
  n = likeplus(e, at);
1012
 
1025
 
1013
  /* remember that mult may have more than two args after 
1026
  /* remember that mult may have more than two args after
1014
     optimisation */
1027
     optimisation */
1015
  if ( last ( arg2 ) && name ( arg2 ) == val_tag && optop(*e) ) {
1028
  if (last(arg2) && name(arg2) == val_tag && optop(*e)) {
1016
    /* const optim, additional reg only needed where src and dest are
1029
    /* const optim, additional reg only needed where src and dest are
1017
       same reg, in which case it has already been allowed for */
1030
       same reg, in which case it has already been allowed for */
1018
    return ( n ) ;
1031
    return(n);
1019
  }
1032
  }
1020
  /* default, call .mul */
1033
  /* default, call .mul */
1021
  n.fixneeds = maxfix ;
1034
  n.fixneeds = maxfix;
1022
  pnset ( n, hasproccall ) ;
1035
  pnset(n, hasproccall);
1023
  return ( n ) ;
1036
  return(n);
1024
}
1037
}
1025
 
1038
 
1026
 
1039
 
1027
/*
1040
/*
1028
  ESTIMATE NEEDS FOR DIVISION
1041
  ESTIMATE NEEDS FOR DIVISION
1029
*/
1042
*/
1030
needs divneeds 
1043
needs divneeds
1031
    PROTO_N ( ( e, at ) )
-
 
1032
    PROTO_T ( exp * e X exp ** at ){
1044
(exp * e, exp ** at) {
1033
  needs n ;
1045
  needs n;
1034
  exp lhs = son ( *e ) ;
1046
  exp lhs = son(*e);
1035
  exp rhs = bro ( lhs ) ;
1047
  exp rhs = bro(lhs);
1036
 
1048
 
1037
  assert ( last ( rhs ) ) ;	/* after likediv may not be so */
1049
  assert ( last ( rhs ) ) ;	/* after likediv may not be so */
1038
 
1050
 
1039
  n = likediv ( e, at ) ;
1051
  n = likediv(e, at);
1040
  if ( name ( rhs ) == val_tag && optop(*e) ) {
1052
  if (name(rhs) == val_tag && optop(*e)) {
1041
    long constval = no ( rhs ) ;
1053
    long constval = no(rhs);
1042
    if ( constval > 0 && IS_POW2 ( constval ) ) {
1054
    if (constval > 0 && IS_POW2(constval)) {
1043
      /* const optim, replace div by shift */
1055
      /* const optim, replace div by shift */
1044
      return ( n ) ;
1056
      return(n);
1045
    }
1057
    }
1046
  }
1058
  }
1047
  /* default, call .div */
1059
  /* default, call .div */
1048
  n.fixneeds = maxfix ;
1060
  n.fixneeds = maxfix;
1049
  pnset ( n, hasproccall ) ;
1061
  pnset(n, hasproccall);
1050
  return ( n ) ;
1062
  return(n);
1051
}
1063
}
1052
 
1064
 
1053
 
1065
 
1054
/*
1066
/*
1055
  ESTIMATE NEEDS FOR REMAINDER
1067
  ESTIMATE NEEDS FOR REMAINDER
1056
*/
1068
*/
1057
needs remneeds 
1069
needs remneeds
1058
    PROTO_N ( ( e, at ) )
-
 
1059
    PROTO_T ( exp * e X exp ** at ){
1070
(exp * e, exp ** at) {
1060
  needs n ;
1071
  needs n;
1061
  exp lhs = son ( *e ) ;
1072
  exp lhs = son(*e);
1062
  exp rhs = bro ( lhs ) ;
1073
  exp rhs = bro(lhs);
1063
  assert ( last ( rhs ) ) ;	/* after likediv may not be so */
1074
  assert ( last ( rhs ) ) ;	/* after likediv may not be so */
1064
  n = likediv ( e, at ) ;
1075
  n = likediv(e, at);
1065
  if ( name ( rhs ) == val_tag && optop(*e) ) {
1076
  if (name(rhs) == val_tag && optop(*e)) {
1066
    long constval = no ( rhs ) ;
1077
    long constval = no(rhs);
1067
    if ( constval > 0 && IS_POW2 ( constval ) ) {
1078
    if (constval > 0 && IS_POW2(constval)) {
1068
      /* const optim of rem by positive, non-zero, 2**n */
1079
      /* const optim of rem by positive, non-zero, 2**n */
1069
      return ( n ) ;
1080
      return(n);
1070
    }
1081
    }
1071
  }
1082
  }
1072
  /* default, call .rem */
1083
  /* default, call .rem */
1073
  n.fixneeds = maxfix ;
1084
  n.fixneeds = maxfix;
1074
  pnset ( n, hasproccall ) ;
1085
  pnset(n, hasproccall);
1075
  return ( n ) ;
1086
  return(n);
1076
}
1087
}