Subversion Repositories tendra.SVN

Rev

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

Rev 2 Rev 7
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
    Copyright (c) 1993 Open Software Foundation, Inc.
32
    Copyright (c) 1993 Open Software Foundation, Inc.
3
 
33
 
4
 
34
 
5
    All Rights Reserved
35
    All Rights Reserved
6
 
36
 
7
 
37
 
8
    Permission to use, copy, modify, and distribute this software
38
    Permission to use, copy, modify, and distribute this software
9
    and its documentation for any purpose and without fee is hereby
39
    and its documentation for any purpose and without fee is hereby
10
    granted, provided that the above copyright notice appears in all
40
    granted, provided that the above copyright notice appears in all
11
    copies and that both the copyright notice and this permission
41
    copies and that both the copyright notice and this permission
12
    notice appear in supporting documentation.
42
    notice appear in supporting documentation.
Line 14... Line 44...
14
 
44
 
15
    OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING
45
    OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING
16
    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
46
    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
17
    PARTICULAR PURPOSE.
47
    PARTICULAR PURPOSE.
18
 
48
 
19
 
49
 
20
    IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
50
    IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
21
    CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
51
    CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
22
    LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
52
    LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
23
    NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
53
    NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
24
    WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
54
    WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25
*/
55
*/
26
 
56
 
27
/*
57
/*
28
    		 Crown Copyright (c) 1997
58
    		 Crown Copyright (c) 1997
29
    
59
 
30
    This TenDRA(r) Computer Program is subject to Copyright
60
    This TenDRA(r) Computer Program is subject to Copyright
31
    owned by the United Kingdom Secretary of State for Defence
61
    owned by the United Kingdom Secretary of State for Defence
32
    acting through the Defence Evaluation and Research Agency
62
    acting through the Defence Evaluation and Research Agency
33
    (DERA).  It is made available to Recipients with a
63
    (DERA).  It is made available to Recipients with a
34
    royalty-free licence for its use, reproduction, transfer
64
    royalty-free licence for its use, reproduction, transfer
35
    to other parties and amendment for any purpose not excluding
65
    to other parties and amendment for any purpose not excluding
36
    product development provided that any such use et cetera
66
    product development provided that any such use et cetera
37
    shall be deemed to be acceptance of the following conditions:-
67
    shall be deemed to be acceptance of the following conditions:-
38
    
68
 
39
        (1) Its Recipients shall ensure that this Notice is
69
        (1) Its Recipients shall ensure that this Notice is
40
        reproduced upon any copies or amended versions of it;
70
        reproduced upon any copies or amended versions of it;
41
    
71
 
42
        (2) Any amended version of it shall be clearly marked to
72
        (2) Any amended version of it shall be clearly marked to
43
        show both the nature of and the organisation responsible
73
        show both the nature of and the organisation responsible
44
        for the relevant amendment or amendments;
74
        for the relevant amendment or amendments;
45
    
75
 
46
        (3) Its onward transfer from a recipient to another
76
        (3) Its onward transfer from a recipient to another
47
        party shall be deemed to be that party's acceptance of
77
        party shall be deemed to be that party's acceptance of
48
        these conditions;
78
        these conditions;
49
    
79
 
50
        (4) DERA gives no warranty or assurance as to its
80
        (4) DERA gives no warranty or assurance as to its
51
        quality or suitability for any purpose and DERA accepts
81
        quality or suitability for any purpose and DERA accepts
52
        no liability whatsoever in relation to any use to which
82
        no liability whatsoever in relation to any use to which
53
        it may be put.
83
        it may be put.
54
*/
84
*/
Line 90... Line 120...
90
					 * constant multiply */
120
					 * constant multiply */
91
 
121
 
92
#define NOT_MUL_CONST_SIMPLE	(MAX_MUL_POW2_OFFSET+1)
122
#define NOT_MUL_CONST_SIMPLE	(MAX_MUL_POW2_OFFSET+1)
93
 /* any constant larger than permissable X offset in 2**n +- X */
123
 /* any constant larger than permissable X offset in 2**n +- X */
94
 
124
 
95
#define IS_POW2(c)		((c) != 0 && ((c) & ((c)-1)) == 0)
125
#define IS_POW2(c)		((c)!= 0 && ((c) & ((c) -1)) == 0)
96
 
126
 
97
 
127
 
98
 
128
 
99
 
129
 
100
/*
130
/*
101
 * Utility functions.
131
 * Utility functions.
102
 */
132
 */
103
 
133
 
104
/* return bit number 0..31 from right of word of 'c' which has one bit set */
134
/* return bit number 0..31 from right of word of 'c' which has one bit set */
105
static int bit_no PROTO_N ((c)) PROTO_T (unsigned long c)
135
static int bit_no(unsigned long c)
106
{
136
{
107
  int shift_const;
137
  int shift_const;
108
  unsigned long mask;
138
  unsigned long mask;
109
 
139
 
110
  ASSERT(IS_POW2(c));
140
  ASSERT(IS_POW2(c));
Line 124... Line 154...
124
 * Multiply.
154
 * Multiply.
125
 */
155
 */
126
 
156
 
127
 
157
 
128
/* is constval +ve const 2**n or 2**(n +- X) where abs(X) <= MAX_MUL_POW2_OFFSET */
158
/* is constval +ve const 2**n or 2**(n +- X) where abs(X) <= MAX_MUL_POW2_OFFSET */
129
static int offset_mul_const_simple PROTO_N ((constval,sgned)) PROTO_T (long constval X bool sgned)
159
static int offset_mul_const_simple(long constval, bool sgned)
130
{
160
{
131
  int i;
161
  int i;
132
 
162
 
133
  FULLCOMMENT1("offset_mul_const_simple: %ld", constval);
163
  FULLCOMMENT1("offset_mul_const_simple: %ld", constval);
134
 
164
 
Line 157... Line 187...
157
	return -i;
187
	return -i;
158
    }
188
    }
159
  }
189
  }
160
 
190
 
161
  return NOT_MUL_CONST_SIMPLE;
191
  return NOT_MUL_CONST_SIMPLE;
162
}
192
}
163
 
193
 
164
 
194
 
165
/* generate code for multiply by constant */
195
/* generate code for multiply by constant */
166
static void mul_const_simple PROTO_N ((src,constval,dest,sgned)) PROTO_T (int src X long constval X int dest X bool sgned)
196
static void mul_const_simple(int src, long constval, int dest, bool sgned)
167
{
197
{
168
  int shift_const;
198
  int shift_const;
169
  long c;			/* power of two close to constval */
199
  long c;			/* power of two close to constval */
170
  int add_sub;			/* difference from power of two: +N add, 0
200
  int add_sub;			/* difference from power of two: +N add, 0
171
				 * nop, -N sub */
201
				 * nop, -N sub */
Line 179... Line 209...
179
      return;
209
      return;
180
    }
210
    }
181
    constval = -constval;
211
    constval = -constval;
182
    rr_ins(i_neg, src, R_TMP0);	/* incorrect to modify source */
212
    rr_ins(i_neg, src, R_TMP0);	/* incorrect to modify source */
183
    src = R_TMP0;
213
    src = R_TMP0;
184
  }
214
  }
185
 
215
 
186
  if (constval == 0)
216
  if (constval == 0)
187
  {
217
  {
188
    ld_const_ins(0, dest);	/* rare case not handled by mul_const_X() */
218
    ld_const_ins(0, dest);	/* rare case not handled by mul_const_X() */
189
    return;
219
    return;
190
  }
220
  }
191
  else if (constval == 1)
221
  else if (constval == 1)
192
  {
222
  {
193
    if (src != dest)
223
    if (src != dest)
194
    {
224
    {
195
      mov_rr_ins(src, dest);comment(NIL);
225
      mov_rr_ins(src, dest);comment(NIL);
196
    }
226
    }
197
    return;
227
    return;
198
  }
228
  }
199
  else if (constval == 2)
229
  else if (constval == 2)
200
  {
230
  {
201
    /* use add, which can be peep-hole optimised to addcc later */
231
    /* use add, which can be peep-hole optimised to addcc later */
202
    rrr_ins(i_a, src, src, dest);
232
    rrr_ins(i_a, src, src, dest);
203
    return;
233
    return;
204
  }
234
  }
205
 
235
 
206
  add_sub = offset_mul_const_simple(constval, sgned);
236
  add_sub = offset_mul_const_simple(constval, sgned);
207
  c = constval - add_sub;
237
  c = constval - add_sub;
208
 
238
 
209
  ASSERT(constval == c + add_sub);
239
  ASSERT(constval == c + add_sub);
Line 237... Line 267...
237
    }
267
    }
238
 
268
 
239
    if (src == dest)
269
    if (src == dest)
240
    {
270
    {
241
      inter_reg = R_TMP0;	/* must preserve src for add/sub */
271
      inter_reg = R_TMP0;	/* must preserve src for add/sub */
242
    }
272
    }
243
    else
273
    else
244
    {
274
    {
245
      inter_reg = dest;
275
      inter_reg = dest;
246
    }
276
    }
247
 
277
 
Line 255... Line 285...
255
      rrr_ins(i_add_sub, inter_reg, src, inter_reg);
285
      rrr_ins(i_add_sub, inter_reg, src, inter_reg);
256
    }
286
    }
257
 
287
 
258
    /* final add_sub to dest reg */
288
    /* final add_sub to dest reg */
259
    rrr_ins(i_add_sub, inter_reg, src, dest);
289
    rrr_ins(i_add_sub, inter_reg, src, dest);
260
  }
290
  }
261
}
291
}
262
 
292
 
263
 
293
 
264
 
294
 
265
/* generate code for multiply using i_muls unless simple constant */
295
/* generate code for multiply using i_muls unless simple constant */
266
static int do_mul_comm_const PROTO_N ((seq,sp,final_reg,sgned)) PROTO_T (exp seq X space sp X int final_reg X bool sgned)
296
static int do_mul_comm_const(exp seq, space sp, int final_reg, bool sgned)
267
{
297
{
268
  exp arg2 = bro(seq);
298
  exp arg2 = bro(seq);
269
  int lhs_reg = reg_operand(seq, sp);
299
  int lhs_reg = reg_operand(seq, sp);
270
 
300
 
271
  ASSERT(name(arg2) == val_tag && offset_mul_const_simple(no(arg2), sgned) != NOT_MUL_CONST_SIMPLE);
301
  ASSERT(name(arg2) == val_tag && offset_mul_const_simple(no(arg2), sgned)!= NOT_MUL_CONST_SIMPLE);
272
 
302
 
273
 
303
 
274
  sp = guardreg(lhs_reg, sp);
304
  sp = guardreg(lhs_reg, sp);
275
 
305
 
276
  ASSERT(last(arg2));			/* check() & scan() should move const to last */
306
  ASSERT(last(arg2));			/* check() & scan() should move const to last */
277
 
307
 
278
  if (final_reg == R_NO_REG)
308
  if (final_reg == R_NO_REG)
Line 283... Line 313...
283
  return final_reg;
313
  return final_reg;
284
}
314
}
285
 
315
 
286
 
316
 
287
/* generate code for divide using i_divs/i_div unless simple constant */
317
/* generate code for divide using i_divs/i_div unless simple constant */
288
static int do_div PROTO_N ((seq,sp,final_reg,sgned)) PROTO_T (exp seq X space sp X int final_reg X bool sgned)
318
static int do_div(exp seq, space sp, int final_reg, bool sgned)
289
{
319
{
290
  exp lhs = seq;
320
  exp lhs = seq;
291
  exp rhs = bro(lhs);
321
  exp rhs = bro(lhs);
292
  exp e = bro(rhs);
322
  exp e = bro(rhs);
293
  
323
 
294
  int div_type=name(bro(rhs));
324
  int div_type=name(bro(rhs));
295
  
325
 
296
  int lhs_reg = reg_operand(lhs, sp);
326
  int lhs_reg = reg_operand(lhs, sp);
297
  int rhs_reg;
327
  int rhs_reg;
298
  
328
 
299
  sp = guardreg(lhs_reg, sp);
329
  sp = guardreg(lhs_reg, sp);
300
 
330
 
301
  if (final_reg == R_NO_REG)
331
  if (final_reg == R_NO_REG)
302
  {
332
  {
303
    final_reg = getreg(sp.fixed);
333
    final_reg = getreg(sp.fixed);
304
    sp = guardreg(final_reg, sp);
334
    sp = guardreg(final_reg, sp);
305
  }
335
  }
306
 
336
 
307
  ASSERT(last(rhs));
337
  ASSERT(last(rhs));
308
  
338
 
309
  if (name(rhs) == val_tag && IS_POW2(no(rhs)) )
339
  if (name(rhs) == val_tag && IS_POW2(no(rhs)))
310
  {
340
  {
311
    /* 
341
    /*
312
     * OPTIMISATION: Division by power of 2 can be done as a shift
342
     * OPTIMISATION: Division by power of 2 can be done as a shift
313
     */
343
     */
314
    long constval = no(rhs);
344
    long constval = no(rhs);
315
    if (!optop(e) && constval == 0)
345
    if (!optop(e) && constval == 0)
316
    {
346
    {
Line 319... Line 349...
319
      return final_reg;
349
      return final_reg;
320
    }
350
    }
321
    if (constval>0 && IS_POW2(constval))
351
    if (constval>0 && IS_POW2(constval))
322
    {
352
    {
323
      /* const optim, replace div by 2**n by shift right */
353
      /* const optim, replace div by 2**n by shift right */
324
      
354
 
325
      int shift_const = bit_no(constval);
355
      int shift_const = bit_no(constval);
326
      
356
 
327
      if (constval==1)
357
      if (constval==1)
328
      {
358
      {
329
	/* result always lhs */
359
	/* result always lhs */
330
	mov_rr_ins(lhs_reg, final_reg);comment(NIL);
360
	mov_rr_ins(lhs_reg, final_reg);comment(NIL);
331
      }
361
      }
332
      else if (sgned && div_type!=div1_tag)
362
      else if (sgned && div_type!=div1_tag)
333
      {
363
      {
334
	/* signed, adjust lhs before shift */
364
	/* signed, adjust lhs before shift */
335
	
365
 
336
	/* +++ the divide instructions rounds to zero, but the shift
366
	/* +++ the divide instructions rounds to zero, but the shift
337
	 * instruction sets the carry bit if the result is negative so a
367
	 * instruction sets the carry bit if the result is negative so a
338
	 * shift follwed by an add-with-carry instruction is equivalent to
368
	 * shift follwed by an add-with-carry instruction is equivalent to
339
	 * a round-to-zero divide.
369
	 * a round-to-zero divide.
340
	 */
370
	 */
341
 
371
 
342
	int tmp_reg = R_TMP0;
372
	int tmp_reg = R_TMP0;
343
	
373
 
344
	ASSERT(shift_const>0);			/* assumed below */
374
	ASSERT(shift_const>0);			/* assumed below */
345
 
375
 
346
	if (shift_const-1 != 0)
376
	if (shift_const-1 != 0)
347
	{
377
	{
348
	  rir_ins(i_sra, lhs_reg, shift_const-1, tmp_reg);
378
	  rir_ins(i_sra, lhs_reg, shift_const-1, tmp_reg);
349
	  rir_ins(i_sr, tmp_reg, 32-shift_const, tmp_reg);
379
	  rir_ins(i_sr, tmp_reg, 32-shift_const, tmp_reg);
Line 368... Line 398...
368
	}
398
	}
369
      }
399
      }
370
      return final_reg;
400
      return final_reg;
371
    }
401
    }
372
  }
402
  }
373
  
403
 
374
  rhs_reg = reg_operand(rhs,sp);
404
  rhs_reg = reg_operand(rhs,sp);
375
  if (ERROR_TREATMENT(e))
405
  if (ERROR_TREATMENT(e))
376
  {
406
  {
377
    div_error_treatment( lhs_reg, rhs_reg, e);
407
    div_error_treatment(lhs_reg, rhs_reg, e);
378
  }
408
  }
379
 
409
 
380
  if (architecture==POWERPC_CODE)
410
  if (architecture==POWERPC_CODE)
381
  {
411
  {
382
    /* PowerPC has nicer divide instructions */
412
    /* PowerPC has nicer divide instructions */
Line 387... Line 417...
387
    else
417
    else
388
    {
418
    {
389
      int creg = next_creg();
419
      int creg = next_creg();
390
      int creg2 = next_creg();
420
      int creg2 = next_creg();
391
      int lab =new_label();
421
      int lab =new_label();
392
      
422
 
393
      /* signed div1_tag needs special care */
423
      /* signed div1_tag needs special care */
394
      rrr_ins(i_xor,lhs_reg,rhs_reg,R_TMP0);
424
      rrr_ins(i_xor,lhs_reg,rhs_reg,R_TMP0);
395
      rir_ins(i_and,R_TMP0,0x80000000,R_TMP0);
425
      rir_ins(i_and,R_TMP0,0x80000000,R_TMP0);
396
      cmp_ri_ins(i_cmp,R_TMP0,0,creg);
426
      cmp_ri_ins(i_cmp,R_TMP0,0,creg);
397
      rrr_ins(i_divw,lhs_reg,rhs_reg,final_reg);
427
      rrr_ins(i_divw,lhs_reg,rhs_reg,final_reg);
Line 401... Line 431...
401
      cmp_ri_ins(i_cmp,R_TMP0,0,creg2);
431
      cmp_ri_ins(i_cmp,R_TMP0,0,creg2);
402
      bc_ins(i_beq,creg2,lab,UNLIKELY_TO_JUMP); /* 0 remainder jump over */
432
      bc_ins(i_beq,creg2,lab,UNLIKELY_TO_JUMP); /* 0 remainder jump over */
403
      rir_ins(i_a,final_reg,-1,final_reg); /* subtract one from answer */
433
      rir_ins(i_a,final_reg,-1,final_reg); /* subtract one from answer */
404
      set_label(lab);
434
      set_label(lab);
405
    }
435
    }
406
    
436
 
407
  }
437
  }
408
  else
438
  else
409
  {
439
  {
410
    /* RS/6000 and Common code */
440
    /* RS/6000 and Common code */
411
    if (sgned)
441
    if (sgned)
Line 413... Line 443...
413
      if (div_type==div1_tag)
443
      if (div_type==div1_tag)
414
      {
444
      {
415
	int creg = next_creg();
445
	int creg = next_creg();
416
	int creg2 = next_creg();
446
	int creg2 = next_creg();
417
	int lab =new_label();
447
	int lab =new_label();
418
	
448
 
419
	/* signed div1_tag needs special care */
449
	/* signed div1_tag needs special care */
420
	rrr_ins(i_xor,lhs_reg,rhs_reg,R_TMP0);
450
	rrr_ins(i_xor,lhs_reg,rhs_reg,R_TMP0);
421
	rir_ins(i_and,R_TMP0,0x80000000,R_TMP0);
451
	rir_ins(i_and,R_TMP0,0x80000000,R_TMP0);
422
	cmp_ri_ins(i_cmp,R_TMP0,0,creg);
452
	cmp_ri_ins(i_cmp,R_TMP0,0,creg);
423
	rrr_ins(i_divs,lhs_reg,rhs_reg,final_reg);
453
	rrr_ins(i_divs,lhs_reg,rhs_reg,final_reg);
Line 431... Line 461...
431
      }
461
      }
432
      else
462
      else
433
      {
463
      {
434
	/* signed divide is easy */
464
	/* signed divide is easy */
435
	rrr_ins(i_divs, lhs_reg, rhs_reg, final_reg);
465
	rrr_ins(i_divs, lhs_reg, rhs_reg, final_reg);
436
      }
466
      }
437
    }
467
    }
438
    else
468
    else
439
    {
469
    {
440
      /* unsigned divide */
470
      /* unsigned divide */
441
      int safe_rhs_reg;
471
      int safe_rhs_reg;
442
      int creg1 = next_creg();
472
      int creg1 = next_creg();
443
      int creg2 = next_creg();
473
      int creg2 = next_creg();
444
      int endlab = new_label();
474
      int endlab = new_label();
445
      
475
 
446
      ASSERT(creg1 != creg2);
476
      ASSERT(creg1 != creg2);
447
      
477
 
448
      if (final_reg != rhs_reg)
478
      if (final_reg != rhs_reg)
449
      {
479
      {
450
	safe_rhs_reg = rhs_reg;
480
	safe_rhs_reg = rhs_reg;
451
      }
481
      }
452
      else
482
      else
453
      {
483
      {
454
	/* early setting of final_reg will clobber rhs_reg so make safe copy */
484
	/* early setting of final_reg will clobber rhs_reg so make safe copy */
455
	safe_rhs_reg = getreg(sp.fixed);
485
	safe_rhs_reg = getreg(sp.fixed);
456
	mov_rr_ins(rhs_reg, safe_rhs_reg);comment(NIL);
486
	mov_rr_ins(rhs_reg, safe_rhs_reg);comment(NIL);
457
      }
487
      }
458
      
488
 
459
      /* compares as early as possible to minimise cr def-use delay */
489
      /* compares as early as possible to minimise cr def-use delay */
460
      cmp_rr_ins(i_cmpl, rhs_reg, lhs_reg, creg1);
490
      cmp_rr_ins(i_cmpl, rhs_reg, lhs_reg, creg1);
461
      cmp_ri_ins(i_cmp, rhs_reg, 0, creg2);
491
      cmp_ri_ins(i_cmp, rhs_reg, 0, creg2);
462
      
492
 
463
      /* maximise cr def-use delay by loading mq early for following div */
493
      /* maximise cr def-use delay by loading mq early for following div */
464
      mt_ins(i_mtmq, lhs_reg);
494
      mt_ins(i_mtmq, lhs_reg);
465
      
495
 
466
      /* if rhs > lhs then result is 0 */
496
      /* if rhs > lhs then result is 0 */
467
      ld_const_ins(0, final_reg);
497
      ld_const_ins(0, final_reg);
468
      bc_ins(i_bgt, creg1, endlab,LIKELY_TO_JUMP);
498
      bc_ins(i_bgt, creg1, endlab,LIKELY_TO_JUMP);
469
      
499
 
470
      /* otherwise if rhs has top bit set then result is 1 */
500
      /* otherwise if rhs has top bit set then result is 1 */
471
      ld_const_ins(1, final_reg);
501
      ld_const_ins(1, final_reg);
472
      bc_ins(i_blt, creg2, endlab,LIKELY_TO_JUMP);
502
      bc_ins(i_blt, creg2, endlab,LIKELY_TO_JUMP);
473
      
503
 
474
      /* do the extended div */
504
      /* do the extended div */
475
      ld_const_ins(0, R_TMP0);
505
      ld_const_ins(0, R_TMP0);
476
      rrr_ins(i_div, R_TMP0, safe_rhs_reg, final_reg);
506
      rrr_ins(i_div, R_TMP0, safe_rhs_reg, final_reg);
477
      
507
 
478
      set_label(endlab);
508
      set_label(endlab);
479
    }
509
    }
480
  }
510
  }
481
    
511
 
482
  return final_reg;
512
  return final_reg;
483
}
513
}
484
 
514
 
485
 
515
 
486
/* generate code for rem using i_divs/i_div unless simple constant */
516
/* generate code for rem using i_divs/i_div unless simple constant */
487
static int do_rem PROTO_N ((seq,sp,final_reg,sgned)) PROTO_T (exp seq X space sp X int final_reg X bool sgned)
517
static int do_rem(exp seq, space sp, int final_reg, bool sgned)
488
{
518
{
489
  exp lhs = seq;
519
  exp lhs = seq;
490
  exp rhs = bro(lhs);
520
  exp rhs = bro(lhs);
491
  exp e = bro(rhs);
521
  exp e = bro(rhs);
492
  int lhs_reg;
522
  int lhs_reg;
493
  int rem_type=name(bro(rhs));
523
  int rem_type=name(bro(rhs));
494
  int rhs_reg ;  
524
  int rhs_reg;
495
  ASSERT(last(rhs));
525
  ASSERT(last(rhs));
496
 
526
 
497
  lhs_reg = reg_operand(lhs, sp);
527
  lhs_reg = reg_operand(lhs, sp);
498
 
528
 
499
  sp = guardreg(lhs_reg, sp);
529
  sp = guardreg(lhs_reg, sp);
500
 
530
 
501
  if (final_reg == R_NO_REG)
531
  if (final_reg == R_NO_REG)
502
  {
532
  {
503
    final_reg = getreg(sp.fixed);
533
    final_reg = getreg(sp.fixed);
504
  }
534
  }
505
 
535
 
506
  if (name(rhs) == val_tag && IS_POW2(no(rhs)))
536
  if (name(rhs) == val_tag && IS_POW2(no(rhs)))
507
  {
537
  {
508
    long constval = no(rhs);
538
    long constval = no(rhs);
509
 
539
 
510
    if (constval>0 && IS_POW2(constval))
540
    if (constval>0 && IS_POW2(constval))
511
    {
541
    {
512
      /* const optim, replace rem by 2**n by and with mask */
542
      /* const optim, replace rem by 2**n by and with mask */
513
 
543
 
514
      if (constval==1)
544
      if (constval==1)
515
      {
545
      {
516
	/* result always 0 */
546
	/* result always 0 */
517
	ld_const_ins(0, final_reg);
547
	ld_const_ins(0, final_reg);
518
      }
548
      }
519
      else if (sgned && rem_type!=mod_tag)
549
      else if (sgned && rem_type!=mod_tag)
520
      {
550
      {
521
	/*
551
	/*
522
	 * signed, need to allow for negative lhs.
552
	 * signed, need to allow for negative lhs.
523
	 * Treat l%c as l-(l/c)*c
553
	 * Treat l%c as l-(l/c)*c
524
	 */
554
	 */
525
 
555
 
Line 545... Line 575...
545
	rir_ins(i_sl, tmp_reg, shift_const, tmp_reg);
575
	rir_ins(i_sl, tmp_reg, shift_const, tmp_reg);
546
 
576
 
547
	/* subtract */
577
	/* subtract */
548
	rrr_ins(i_s, lhs_reg, tmp_reg, final_reg);
578
	rrr_ins(i_s, lhs_reg, tmp_reg, final_reg);
549
      }
579
      }
550
      else 
580
      else
551
      {
581
      {
552
	/* mod_tag and unsigned */
582
	/* mod_tag and unsigned */
553
	rir_ins(i_and, lhs_reg, constval-1, final_reg);
583
	rir_ins(i_and, lhs_reg, constval-1, final_reg);
554
      }
584
      }
555
      return final_reg;
585
      return final_reg;
556
    }
586
    }
557
  }
587
  }
558
  rhs_reg = reg_operand(rhs,sp);
588
  rhs_reg = reg_operand(rhs,sp);
559
  if(ERROR_TREATMENT(e))
589
  if (ERROR_TREATMENT(e))
560
  {
590
  {
561
    rem_error_treatment(lhs_reg,rhs_reg,e);
591
    rem_error_treatment(lhs_reg,rhs_reg,e);
562
  }
592
  }
563
  if(architecture==POWERPC_CODE)
593
  if (architecture==POWERPC_CODE)
564
  {
594
  {
565
    if (!sgned || rem_type !=mod_tag)
595
    if (!sgned || rem_type !=mod_tag)
566
    {
596
    {
567
 
597
 
568
      rrr_ins(sgned?i_divw:i_divwu,lhs_reg,rhs_reg,R_TMP0);
598
      rrr_ins(sgned?i_divw:i_divwu,lhs_reg,rhs_reg,R_TMP0);
Line 573... Line 603...
573
    {
603
    {
574
      /* signed and rem1 */
604
      /* signed and rem1 */
575
      int creg = next_creg();
605
      int creg = next_creg();
576
      int creg2 = next_creg();
606
      int creg2 = next_creg();
577
      int lab =new_label();
607
      int lab =new_label();
578
      
608
 
579
      /* signed div1_tag needs special care */
609
      /* signed div1_tag needs special care */
580
      rrr_ins(i_xor,lhs_reg,rhs_reg,R_TMP0);
610
      rrr_ins(i_xor,lhs_reg,rhs_reg,R_TMP0);
581
      rir_ins(i_and,R_TMP0,0x80000000,R_TMP0);
611
      rir_ins(i_and,R_TMP0,0x80000000,R_TMP0);
582
      cmp_ri_ins(i_cmp,R_TMP0,0,creg);
612
      cmp_ri_ins(i_cmp,R_TMP0,0,creg);
583
      rrr_ins(i_divw,lhs_reg,rhs_reg,R_TMP0);
613
      rrr_ins(i_divw,lhs_reg,rhs_reg,R_TMP0);
Line 597... Line 627...
597
      if (rem_type==mod_tag)
627
      if (rem_type==mod_tag)
598
      {
628
      {
599
	int creg = next_creg();
629
	int creg = next_creg();
600
	int creg2 = next_creg();
630
	int creg2 = next_creg();
601
	int lab =new_label();
631
	int lab =new_label();
602
	
632
 
603
	/* signed div1_tag needs special care */
633
	/* signed div1_tag needs special care */
604
	rrr_ins(i_xor,lhs_reg,rhs_reg,R_TMP0);
634
	rrr_ins(i_xor,lhs_reg,rhs_reg,R_TMP0);
605
	rir_ins(i_and,R_TMP0,0x80000000,R_TMP0);
635
	rir_ins(i_and,R_TMP0,0x80000000,R_TMP0);
606
	cmp_ri_ins(i_cmp,R_TMP0,0,creg);
636
	cmp_ri_ins(i_cmp,R_TMP0,0,creg);
607
	rrr_ins(i_divs,lhs_reg,rhs_reg,R_TMP0);
637
	rrr_ins(i_divs,lhs_reg,rhs_reg,R_TMP0);
Line 610... Line 640...
610
	bc_ins(i_beq,creg,lab,LIKELY_TO_JUMP); /* both the same sign same as div2 so jump over*/
640
	bc_ins(i_beq,creg,lab,LIKELY_TO_JUMP); /* both the same sign same as div2 so jump over*/
611
	cmp_ri_ins(i_cmp,final_reg,0,creg2);
641
	cmp_ri_ins(i_cmp,final_reg,0,creg2);
612
	bc_ins(i_beq,creg2,lab,UNLIKELY_TO_JUMP); /* 0 remainder jump over */
642
	bc_ins(i_beq,creg2,lab,UNLIKELY_TO_JUMP); /* 0 remainder jump over */
613
	rrr_ins(i_a,final_reg,rhs_reg,final_reg); /* add quotinent to answer */
643
	rrr_ins(i_a,final_reg,rhs_reg,final_reg); /* add quotinent to answer */
614
	set_label(lab);
644
	set_label(lab);
615
      }
645
      }
616
      else
646
      else
617
      {
647
      {
618
	rrr_ins(i_divs, lhs_reg, rhs_reg, R_TMP0);
648
	rrr_ins(i_divs, lhs_reg, rhs_reg, R_TMP0);
619
	mf_ins(i_mfmq, final_reg);
649
	mf_ins(i_mfmq, final_reg);
620
      }
650
      }
621
    }
651
    }
622
    else
652
    else
623
    {
653
    {
624
      int safe_rhs_reg;
654
      int safe_rhs_reg;
625
      int creg1 = next_creg();
655
      int creg1 = next_creg();
626
      int creg2 = next_creg();
656
      int creg2 = next_creg();
627
      int endlab = new_label();
657
      int endlab = new_label();
628
      
658
 
629
      ASSERT(creg1 != creg2);
659
      ASSERT(creg1 != creg2);
630
      
660
 
631
      if (final_reg != rhs_reg)
661
      if (final_reg != rhs_reg)
632
      {
662
      {
633
	safe_rhs_reg = rhs_reg;
663
	safe_rhs_reg = rhs_reg;
634
      }
664
      }
635
      else
665
      else
636
      {
666
      {
637
	/* early setting of final_reg will clobber rhs_reg so make safe copy */
667
	/* early setting of final_reg will clobber rhs_reg so make safe copy */
638
	safe_rhs_reg = getreg(sp.fixed);
668
	safe_rhs_reg = getreg(sp.fixed);
639
	mov_rr_ins(rhs_reg, safe_rhs_reg);comment(NIL);
669
	mov_rr_ins(rhs_reg, safe_rhs_reg);comment(NIL);
640
      }
670
      }
641
      
671
 
642
      /* compares as early as possible to minimise cr def-use delay */
672
      /* compares as early as possible to minimise cr def-use delay */
643
      cmp_rr_ins(i_cmpl, rhs_reg, lhs_reg, creg1);
673
      cmp_rr_ins(i_cmpl, rhs_reg, lhs_reg, creg1);
644
      cmp_ri_ins(i_cmp, rhs_reg, 0, creg2);
674
      cmp_ri_ins(i_cmp, rhs_reg, 0, creg2);
645
      
675
 
646
      /* maximise cr def-use delay by loading mq early for following div */
676
      /* maximise cr def-use delay by loading mq early for following div */
647
      mt_ins(i_mtmq, lhs_reg);
677
      mt_ins(i_mtmq, lhs_reg);
648
      
678
 
649
      /* if rhs > lhs then result is lhs */
679
      /* if rhs > lhs then result is lhs */
650
      mov_rr_ins(lhs_reg, final_reg);comment(NIL);
680
      mov_rr_ins(lhs_reg, final_reg);comment(NIL);
651
      bc_ins(i_bgt, creg1, endlab,LIKELY_TO_JUMP);
681
      bc_ins(i_bgt, creg1, endlab,LIKELY_TO_JUMP);
652
      
682
 
653
      /* otherwise if rhs has top bit set then result is lhs - rhs */
683
      /* otherwise if rhs has top bit set then result is lhs - rhs */
654
      if (lhs_reg == final_reg)
684
      if (lhs_reg == final_reg)
655
      {
685
      {
656
	/* lhs has been clobbered, recover from MQ */
686
	/* lhs has been clobbered, recover from MQ */
657
	mf_ins(i_mfmq, lhs_reg);
687
	mf_ins(i_mfmq, lhs_reg);
658
      }
688
      }
659
      rrr_ins(i_s, lhs_reg, safe_rhs_reg, final_reg);
689
      rrr_ins(i_s, lhs_reg, safe_rhs_reg, final_reg);
660
      bc_ins(i_blt, creg2, endlab,LIKELY_TO_JUMP);
690
      bc_ins(i_blt, creg2, endlab,LIKELY_TO_JUMP);
661
      
691
 
662
      /* do the extended div */
692
      /* do the extended div */
663
      ld_const_ins(0, R_TMP0);
693
      ld_const_ins(0, R_TMP0);
664
      rrr_ins(i_div, R_TMP0, safe_rhs_reg, R_TMP0);
694
      rrr_ins(i_div, R_TMP0, safe_rhs_reg, R_TMP0);
665
      mf_ins(i_mfmq, final_reg);
695
      mf_ins(i_mfmq, final_reg);
666
      
696
 
667
      set_label(endlab);
697
      set_label(endlab);
668
    }
698
    }
669
  }
699
  }
670
  
700
 
671
  return final_reg;
701
  return final_reg;
672
}
702
}
673
 
703
 
674
 
704
 
675
 
705
 
676
/* choose regs and generate code using do_fn */
706
/* choose regs and generate code using do_fn */
677
static int find_reg_and_apply
707
static int find_reg_and_apply
678
    PROTO_N ((e,sp,dest,sgned,do_fn))
-
 
679
    PROTO_T (exp e X space sp X where dest X bool sgned X
-
 
680
	     int (*do_fn)PROTO_S((exp, space, int, bool)))
708
(exp e, space sp, where dest, bool sgned,	     int(*do_fn)PROTO_S((exp, space, int, bool)))
681
{
709
{
682
  exp seq = son(e);
710
  exp seq = son(e);
683
  ans a;
711
  ans a;
684
  int dest_reg;
712
  int dest_reg;
685
 
713
 
Line 711... Line 739...
711
}
739
}
712
 
740
 
713
 
741
 
714
 
742
 
715
/* choose regs and generate code for multiply */
743
/* choose regs and generate code for multiply */
716
int do_mul_comm_op PROTO_N ((e,sp,dest,sgned)) PROTO_T (exp e X space sp X where dest X bool sgned)
744
int do_mul_comm_op(exp e, space sp, where dest, bool sgned)
717
{
745
{
718
  exp arg2 = bro(son(e));
746
  exp arg2 = bro(son(e));
719
 
747
 
720
  if (name(arg2) == val_tag &&
748
  if (name(arg2) == val_tag &&
721
      offset_mul_const_simple(no(arg2), sgned) != NOT_MUL_CONST_SIMPLE)
749
      offset_mul_const_simple(no(arg2), sgned)!= NOT_MUL_CONST_SIMPLE)
722
  {
750
  {
723
    return find_reg_and_apply(e, sp, dest, sgned, do_mul_comm_const);
751
    return find_reg_and_apply(e, sp, dest, sgned, do_mul_comm_const);
724
  }
752
  }
725
  else
753
  else
726
  {
754
  {
727
    return comm_op(e, sp, dest, i_muls);	
755
    return comm_op(e, sp, dest, i_muls);
728
    /* i_muls for both signed and unsigned with no error treatment */
756
    /* i_muls for both signed and unsigned with no error treatment */
729
  }
757
  }
730
}
758
}
731
 
759
 
732
 
760
 
733
/* choose regs and generate code for divide */
761
/* choose regs and generate code for divide */
734
int do_div_op PROTO_N ((e,sp,dest,sgned)) PROTO_T (exp e X space sp X where dest X bool sgned)
762
int do_div_op(exp e, space sp, where dest, bool sgned)
735
{
763
{
736
  return find_reg_and_apply(e, sp, dest, sgned, do_div);
764
  return find_reg_and_apply(e, sp, dest, sgned, do_div);
737
}
765
}
738
 
766
 
739
 
767
 
740
/* choose regs and generate code for rem */
768
/* choose regs and generate code for rem */
741
int do_rem_op PROTO_N ((e,sp,dest,sgned)) PROTO_T (exp e X space sp X where dest X bool sgned)
769
int do_rem_op(exp e, space sp, where dest, bool sgned)
742
{
770
{
743
  return find_reg_and_apply(e, sp, dest, sgned, do_rem);
771
  return find_reg_and_apply(e, sp, dest, sgned, do_rem);
744
}
772
}
745
 
773
 
746
 
774
 
Line 748... Line 776...
748
/*
776
/*
749
 * Needs estimation
777
 * Needs estimation
750
 */
778
 */
751
 
779
 
752
 
780
 
753
needs multneeds PROTO_N ((e,at)) PROTO_T (exp *e X exp **at)
781
needs multneeds(exp *e, exp **at)
754
{
782
{
755
  needs n = likeplus(e, at);	/* has had comm_ass() treatment */
783
  needs n = likeplus(e, at);	/* has had comm_ass() treatment */
756
  exp arg1 = son(*e);
784
  exp arg1 = son(*e);
757
  exp arg2 = bro(arg1);
785
  exp arg2 = bro(arg1);
758
 
786
 
Line 769... Line 797...
769
 
797
 
770
  return n;
798
  return n;
771
}
799
}
772
 
800
 
773
 
801
 
774
needs divneeds PROTO_N ((e,at)) PROTO_T (exp *e X exp **at)
802
needs divneeds(exp *e, exp **at)
775
{
803
{
776
  needs n = likeminus(e, at);
804
  needs n = likeminus(e, at);
777
  exp lhs = son(*e);
805
  exp lhs = son(*e);
778
  exp rhs = bro(lhs);
806
  exp rhs = bro(lhs);
779
  bool sgned = name(sh(*e)) & 1;
807
  bool sgned = name(sh(*e)) & 1;
780
 
808
 
781
  ASSERT(last(rhs));
809
  ASSERT(last(rhs));
782
 
810
 
783
  if (name(rhs)==val_tag)
811
  if (name(rhs) ==val_tag)
784
  {
812
  {
785
    long constval = no(rhs);
813
    long constval = no(rhs);
786
 
814
 
787
    if (constval>0 && IS_POW2(constval))
815
    if (constval>0 && IS_POW2(constval))
788
    {
816
    {
Line 798... Line 826...
798
 
826
 
799
  return n;
827
  return n;
800
}
828
}
801
 
829
 
802
 
830
 
803
needs remneeds PROTO_N ((e,at)) PROTO_T (exp *e X exp **at)
831
needs remneeds(exp *e, exp **at)
804
{
832
{
805
  needs n = likeminus(e, at);
833
  needs n = likeminus(e, at);
806
  exp lhs = son(*e);
834
  exp lhs = son(*e);
807
  exp rhs = bro(lhs);
835
  exp rhs = bro(lhs);
808
  bool sgned = name(sh(*e)) & 1;
836
  bool sgned = name(sh(*e)) & 1;
809
 
837
 
810
  ASSERT(last(rhs));
838
  ASSERT(last(rhs));
811
 
839
 
812
  if (name(rhs)==val_tag)
840
  if (name(rhs) ==val_tag)
813
  {
841
  {
814
    long constval = no(rhs);
842
    long constval = no(rhs);
815
 
843
 
816
    if (constval>0 && IS_POW2(constval))
844
    if (constval>0 && IS_POW2(constval))
817
    {
845
    {