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
    		 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 70... Line 100...
70
 * Revision 3.4  1995/08/25  09:56:26  wfs
100
 * Revision 3.4  1995/08/25  09:56:26  wfs
71
 * register synonyms changed. bug fixes to error jump's
101
 * register synonyms changed. bug fixes to error jump's
72
 *
102
 *
73
 * Revision 3.1  95/04/10  16:27:27  16:27:27  wfs (William Simmonds)
103
 * Revision 3.1  95/04/10  16:27:27  16:27:27  wfs (William Simmonds)
74
 * Apr95 tape version.
104
 * Apr95 tape version.
75
 * 
105
 *
76
 * Revision 3.0  95/03/30  11:18:22  11:18:22  wfs (William Simmonds)
106
 * Revision 3.0  95/03/30  11:18:22  11:18:22  wfs (William Simmonds)
77
 * Mar95 tape version with CRCR95_178 bug fix.
107
 * Mar95 tape version with CRCR95_178 bug fix.
78
 * 
108
 *
79
 * Revision 2.0  95/03/15  15:28:11  15:28:11  wfs (William Simmonds)
109
 * Revision 2.0  95/03/15  15:28:11  15:28:11  wfs (William Simmonds)
80
 * spec 3.1 changes implemented, tests outstanding.
110
 * spec 3.1 changes implemented, tests outstanding.
81
 * 
111
 *
82
 * Revision 1.3  95/02/02  15:45:02  15:45:02  wfs (William Simmonds)
112
 * Revision 1.3  95/02/02  15:45:02  15:45:02  wfs (William Simmonds)
83
 * Implemented rem1 and div1.
113
 * Implemented rem1 and div1.
84
 * 
114
 *
85
 * Revision 1.2  95/01/17  17:29:42  17:29:42  wfs (William Simmonds)
115
 * Revision 1.2  95/01/17  17:29:42  17:29:42  wfs (William Simmonds)
86
 * Changed name of an included header file.
116
 * Changed name of an included header file.
87
 * 
117
 *
88
 * Revision 1.1  95/01/11  13:13:34  13:13:34  wfs (William Simmonds)
118
 * Revision 1.1  95/01/11  13:13:34  13:13:34  wfs (William Simmonds)
89
 * Initial revision
119
 * Initial revision
90
 * 
120
 *
91
*/
121
*/
92
 
122
 
93
 
123
 
94
#define HPPATRANS_CODE
124
#define HPPATRANS_CODE
95
#include "config.h"
125
#include "config.h"
Line 132... Line 162...
132
					 * constant multiply */
162
					 * constant multiply */
133
 
163
 
134
#define NOT_MUL_CONST_SIMPLE	(MAX_MUL_POW2_OFFSET+1)
164
#define NOT_MUL_CONST_SIMPLE	(MAX_MUL_POW2_OFFSET+1)
135
 /* any constant larger than permissable X offset in 2**n +- X */
165
 /* any constant larger than permissable X offset in 2**n +- X */
136
 
166
 
137
#define IS_POW2(c)		((c) != 0 && ((c) & ((c)-1)) == 0)
167
#define IS_POW2(c)		((c)!= 0 && ((c) & ((c) -1)) == 0)
138
 
168
 
139
extern long trap_label PROTO_S ((exp));
169
extern long trap_label(exp);
140
extern comib_ins PROTO_S ((ins_p,int,int,int));
170
extern comib_ins(ins_p,int,int,int);
141
/*
171
/*
142
 * Utility functions.
172
 * Utility functions.
143
 */
173
 */
144
 
174
 
145
/* return bit number 0..31 from right of word of 'c' which has one bit set */
175
/* return bit number 0..31 from right of word of 'c' which has one bit set */
146
static int bit_no 
176
static int bit_no
147
    PROTO_N ( ( c ) )
-
 
148
    PROTO_T ( unsigned long c )
177
(unsigned long c)
149
{
178
{
150
  int shift_const;
179
  int shift_const;
151
  unsigned long mask;
180
  unsigned long mask;
152
 
181
 
153
  assert(IS_POW2(c));
182
  assert(IS_POW2(c));
Line 160... Line 189...
160
  return shift_const;
189
  return shift_const;
161
}
190
}
162
 
191
 
163
 
192
 
164
void clear_t_regs
193
void clear_t_regs
165
    PROTO_Z ()
194
(void)
166
{
195
{
167
  /* clear t-regs, i.e. GR2,GR19,GR20..,GR31, which might be modified by a
196
  /* clear t-regs, i.e. GR2,GR19,GR20..,GR31, which might be modified by a
168
     call */
197
     call */
169
  int r;
198
  int r;
170
  clear_reg(GR2);
199
  clear_reg(GR2);
Line 174... Line 203...
174
  }
203
  }
175
}
204
}
176
 
205
 
177
 
206
 
178
/* call millicode library procedure for complicated operation */
207
/* call millicode library procedure for complicated operation */
179
int call_muldivrem 
208
int call_muldivrem
180
    PROTO_N ( ( lhs, rhs, sp, proc ) )
-
 
181
    PROTO_T ( exp lhs X exp rhs X space sp X int proc )
209
(exp lhs, exp rhs, space sp, int proc)
182
{
210
{
183
    char *stub="ARGW0=GR ARGW1=GR";
211
    char *stub="ARGW0=GR ARGW1=GR";
184
    reg_operand_here(lhs, sp, ARG0);
212
    reg_operand_here(lhs, sp, ARG0);
185
    sp = needreg(ARG0, sp);
213
    sp = needreg(ARG0, sp);
186
 
214
 
Line 200... Line 228...
200
 */
228
 */
201
 
229
 
202
 
230
 
203
/* generate code for multiply by constant */
231
/* generate code for multiply by constant */
204
static void mul_const_complex
232
static void mul_const_complex
205
    PROTO_N ( ( src, constval, dest, sp, sgned ) )
-
 
206
    PROTO_T ( int src X long constval X int dest X space sp X bool sgned )
233
(int src, long constval, int dest, space sp, bool sgned)
207
{
234
{
208
  struct
235
  struct
209
  {
236
  {
210
    unsigned char bsl;		/* bit-string of 1s length */
237
    unsigned char bsl;		/* bit-string of 1s length */
211
    unsigned char shift;	/* shift from right of word */
238
    unsigned char shift;	/* shift from right of word */
Line 231... Line 258...
231
    {
258
    {
232
 
259
 
233
      /*
260
      /*
234
       * only 2 non overflowing cases to consider 0 * ~0 == 0 1 * ~0 == ~0 ==
261
       * only 2 non overflowing cases to consider 0 * ~0 == 0 1 * ~0 == ~0 ==
235
       * -1
262
       * -1
236
       * 
263
       *
237
       * negate handles these two correctly
264
       * negate handles these two correctly
238
       */
265
       */
239
      rrr_ins(i_sub,c_,0,src,dest);
266
      rrr_ins(i_sub,c_,0,src,dest);
240
    }
267
    }
241
    return;
268
    return;
Line 262... Line 289...
262
	bs_tab[bs_tab_len].shift = shift - bsl;	/* .shift is from right */
289
	bs_tab[bs_tab_len].shift = shift - bsl;	/* .shift is from right */
263
	if (bsl == 1)
290
	if (bsl == 1)
264
	  bsl_1_tab = bs_tab_len;
291
	  bsl_1_tab = bs_tab_len;
265
	if (bsl > max_bsl)
292
	if (bsl > max_bsl)
266
	  max_bsl = bsl;
293
	  max_bsl = bsl;
267
	comment4("mul_const_complex: bs_tab[%d]=%d,%d c=%d", bs_tab_len, bs_tab[bs_tab_len].bsl, bs_tab[bs_tab_len].shift, c);
294
	comment4("mul_const_complex: bs_tab[%d] =%d,%d c=%d", bs_tab_len, bs_tab[bs_tab_len].bsl, bs_tab[bs_tab_len].shift, c);
268
	bs_tab_len++;
295
	bs_tab_len++;
269
	bsl = 0;
296
	bsl = 0;
270
      }
297
      }
271
    }
298
    }
272
  }
299
  }
Line 410... Line 437...
410
	      tmp_shifted = 0;
437
	      tmp_shifted = 0;
411
	      found_bsl = 1;
438
	      found_bsl = 1;
412
	    }
439
	    }
413
 
440
 
414
	    if (bs_tab[i].shift != tmp_shifted)
441
	    if (bs_tab[i].shift != tmp_shifted)
415
	    {
442
	    {
416
	      int extra_shift = bs_tab[i].shift - tmp_shifted;
443
	      int extra_shift = bs_tab[i].shift - tmp_shifted;
417
 
444
 
418
	      assert(extra_shift > 0 && extra_shift <= 31);
445
	      assert(extra_shift > 0 && extra_shift <= 31);
419
	      rrir_ins(i_shd,c_,tmp,0,32-extra_shift,tmp);
446
	      rrir_ins(i_shd,c_,tmp,0,32-extra_shift,tmp);
420
	      tmp_shifted += extra_shift;
447
	      tmp_shifted += extra_shift;
Line 447... Line 474...
447
 
474
 
448
  comment1("end multiply by %ld", constval);
475
  comment1("end multiply by %ld", constval);
449
}
476
}
450
 
477
 
451
/* is constval +ve const 2**n or 2**(n +- X) where abs(X) <= MAX_MUL_POW2_OFFSET */
478
/* is constval +ve const 2**n or 2**(n +- X) where abs(X) <= MAX_MUL_POW2_OFFSET */
452
static int offset_mul_const_simple 
479
static int offset_mul_const_simple
453
    PROTO_N ( ( constval, sgned ) )
-
 
454
    PROTO_T ( long constval X bool sgned )
480
(long constval, bool sgned)
455
{
481
{
456
  int i;
482
  int i;
457
 
483
 
458
  FULLCOMMENT1("offset_mul_const_simple: %ld", constval);
484
  FULLCOMMENT1("offset_mul_const_simple: %ld", constval);
459
 
485
 
Line 487... Line 513...
487
}
513
}
488
 
514
 
489
 
515
 
490
/* generate code for multiply by constant */
516
/* generate code for multiply by constant */
491
static void mul_const_simple
517
static void mul_const_simple
492
    PROTO_N ( ( src, constval, dest, sgned ) )
-
 
493
    PROTO_T ( int src X long constval X int dest X bool sgned )
518
(int src, long constval, int dest, bool sgned)
494
{
519
{
495
  int shift_const;
520
  int shift_const;
496
  long c;			/* power of two close to constval */
521
  long c;			/* power of two close to constval */
497
  int add_sub;			/* difference from power of two: +N add, 0
522
  int add_sub;			/* difference from power of two: +N add, 0
498
				 * nop, -N sub */
523
				 * nop, -N sub */
Line 564... Line 589...
564
    }
589
    }
565
 
590
 
566
    assert(src != inter_reg);
591
    assert(src != inter_reg);
567
 
592
 
568
    rrir_ins(i_shd,c_,src,0,32-shift_const,inter_reg);
593
    rrir_ins(i_shd,c_,src,0,32-shift_const,inter_reg);
569
  
594
 
570
    if (i_add_sub==i_add)
595
    if (i_add_sub==i_add)
571
    {
596
    {
572
       i=1;
597
       i=1;
573
       while (i<n)
598
       while (i<n)
574
       {
599
       {
575
	  if (i+7<n)
600
	  if (i+7<n)
576
	  {
601
	  {
577
	     rrr_ins(i_sh3add,c_,src,inter_reg,inter_reg);
602
	     rrr_ins(i_sh3add,c_,src,inter_reg,inter_reg);
578
	     i+=8;
603
	     i+=8;
579
	  }   
604
	  }
580
	  else if (i+3<n)
605
	  else if (i+3<n)
581
	  {
606
	  {
582
	     rrr_ins(i_sh2add,c_,src,inter_reg,inter_reg);
607
	     rrr_ins(i_sh2add,c_,src,inter_reg,inter_reg);
583
	     i+=4;
608
	     i+=4;
584
	  }   
609
	  }
585
	  else if (i+1<n)
610
	  else if (i+1<n)
586
	  {
611
	  {
587
	     rrr_ins(i_sh1add,c_,src,inter_reg,inter_reg);
612
	     rrr_ins(i_sh1add,c_,src,inter_reg,inter_reg);
588
	     i+=2;
613
	     i+=2;
589
	  }   
614
	  }
590
	  else 
615
	  else
591
	  {
616
	  {
592
	     rrr_ins(i_add,c_,src,inter_reg,inter_reg);
617
	     rrr_ins(i_add,c_,src,inter_reg,inter_reg);
593
	     i++;
618
	     i++;
594
	  }   
619
	  }
595
       }
620
       }
596
    }
621
    }
597
    else
622
    else
598
       for (i = 1; i < n; i++)
623
       for (i = 1; i < n; i++)
599
	   rrr_ins(i_add_sub,c_,inter_reg,src,inter_reg);
624
	   rrr_ins(i_add_sub,c_,inter_reg,src,inter_reg);
Line 605... Line 630...
605
}
630
}
606
 
631
 
607
 
632
 
608
/* generate code for multiply by constant */
633
/* generate code for multiply by constant */
609
static void mul_const
634
static void mul_const
610
    PROTO_N ( ( src, constval, dest, sp, sgned ) )
-
 
611
    PROTO_T ( int src X long constval X int dest X space sp X bool sgned )
635
(int src, long constval, int dest, space sp, bool sgned)
612
{
636
{
613
  if (constval == 0)
637
  if (constval == 0)
614
     /* rare case not handled by mul_const_X() */
638
     /* rare case not handled by mul_const_X() */
615
     rr_ins(i_copy,0,dest);
639
     rr_ins(i_copy,0,dest);
616
  else if (offset_mul_const_simple(constval, sgned) == NOT_MUL_CONST_SIMPLE)
640
  else if (offset_mul_const_simple(constval, sgned) == NOT_MUL_CONST_SIMPLE)
Line 621... Line 645...
621
 
645
 
622
 
646
 
623
/*
647
/*
624
 *   Generate code for multiply .
648
 *   Generate code for multiply .
625
 */
649
 */
626
static int do_mul_comm 
650
static int do_mul_comm
627
    PROTO_N ( ( e, sp, final_reg, sgned ) )
-
 
628
    PROTO_T ( exp e X space sp X int final_reg X bool sgned )
651
(exp e, space sp, int final_reg, bool sgned)
629
{
652
{
630
  exp seq = son(e);
653
  exp seq = son(e);
631
  exp arg2 = bro(seq);
654
  exp arg2 = bro(seq);
632
  char *mul_proc;
655
  char *mul_proc;
633
  int arg = 1;
656
  int arg = 1;
Line 667... Line 690...
667
    seq = bro(seq);
690
    seq = bro(seq);
668
    arg++;
691
    arg++;
669
 
692
 
670
    FULLCOMMENT1("do_mul_comm: name(seq) = %d", name(seq));
693
    FULLCOMMENT1("do_mul_comm: name(seq) = %d", name(seq));
671
 
694
 
672
    if (name(seq) == val_tag && offset_mul_const_simple(no(seq), sgned) != NOT_MUL_CONST_SIMPLE)
695
    if (name(seq) == val_tag && offset_mul_const_simple(no(seq), sgned)!= NOT_MUL_CONST_SIMPLE)
673
    {
696
    {
674
      /* const optim */
697
      /* const optim */
675
      assert(last(seq)); /* check() & scan() should move const to last */
698
      assert(last(seq)); /* check() & scan() should move const to last */
676
 
699
 
677
      stf_ins(i_fstw,14,b);
700
      stf_ins(i_fstw,14,b);
678
      ld_ins(i_lw,SIGNED,b,ARG0);
701
      ld_ins(i_lw,SIGNED,b,ARG0);
679
 
702
 
680
      if (final_reg == R_NO_REG)
703
      if (final_reg == R_NO_REG)
681
	 final_reg = RET0;	
704
	 final_reg = RET0;
682
	 /* better code from mul_const if src != dest register */
705
	 /* better code from mul_const if src != dest register */
683
 
706
 
684
      mul_const(ARG0, no(seq), final_reg, sp, sgned);
707
      mul_const(ARG0, no(seq), final_reg, sp, sgned);
685
 
708
 
686
      break;
709
      break;
Line 698... Line 721...
698
       if (arg==2)
721
       if (arg==2)
699
	  ldf_ins(i_fldd,b,13);
722
	  ldf_ins(i_fldd,b,13);
700
       else
723
       else
701
	  ldf_ins(i_fldw,b,12);
724
	  ldf_ins(i_fldw,b,12);
702
       rrrf_ins(i_xmpyu,f_,12,14,13);
725
       rrrf_ins(i_xmpyu,f_,12,14,13);
703
  
726
 
704
       clear_t_regs();
727
       clear_t_regs();
705
 
728
 
706
       if (last(seq))
729
       if (last(seq))
707
       {
730
       {
708
	  stf_ins(i_fstw,14,b);
731
	  stf_ins(i_fstw,14,b);
709
	  if (final_reg == R_NO_REG || final_reg == RET0)
732
	  if (final_reg == R_NO_REG || final_reg == RET0)
710
	  {
733
	  {
711
	     ld_ins(i_lw,SIGNED,b,RET0);
734
	     ld_ins(i_lw,SIGNED,b,RET0);
712
 	     final_reg = RET0;  
735
 	     final_reg = RET0;
713
	  }
736
	  }
714
	  else
737
	  else
715
	     ld_ins(i_lw,SIGNED,b,final_reg);
738
	     ld_ins(i_lw,SIGNED,b,final_reg);
716
	  break;
739
	  break;
717
       }
740
       }
Line 723... Line 746...
723
 
746
 
724
/*
747
/*
725
 *   Generate code for div0, div1 and div2 by calling divI or divU unless
748
 *   Generate code for div0, div1 and div2 by calling divI or divU unless
726
 *   dividing by a simple constant.
749
 *   dividing by a simple constant.
727
 */
750
 */
728
static int do_div 
751
static int do_div
729
    PROTO_N ( ( e, sp, final_reg, sgned ) )
-
 
730
    PROTO_T ( exp e X space sp X int final_reg X bool sgned )
752
(exp e, space sp, int final_reg, bool sgned)
731
{
753
{
732
   exp seq = son(e);
754
   exp seq = son(e);
733
   exp lhs = seq;
755
   exp lhs = seq;
734
   exp rhs = bro(lhs);
756
   exp rhs = bro(lhs);
735
   space nsp;
757
   space nsp;
736
   int trap = 0;
758
   int trap = 0;
737
   int sz = shape_size(sh(e));
759
   int sz = shape_size(sh(e));
738
   char *stub="ARGW0=GR ARGW1=GR";
760
   char *stub="ARGW0=GR ARGW1=GR";
739
   if ( !optop(e) )
761
   if (!optop(e))
740
      trap = trap_label(e);
762
      trap = trap_label(e);
741
   assert(last(rhs));
763
   assert(last(rhs));
742
   /*
764
   /*
743
    *   ov_err can only occur when calculating p div1 q with p == variety's
765
    *   ov_err can only occur when calculating p div1 q with p == variety's
744
    *   minimum and q==-1 
766
    *   minimum and q==-1
745
    */
767
    */
746
   if ( name(rhs)==val_tag )
768
   if (name(rhs) ==val_tag)
747
   {
769
   {
748
      /*   nb. div_by_zero_err handled by common code  */
770
      /*   nb. div_by_zero_err handled by common code  */
749
      int n = no(rhs);
771
      int n = no(rhs);
750
      if ( n > 0 && IS_POW2(n) )
772
      if (n > 0 && IS_POW2(n))
751
      {
773
      {
752
	 int lhs_reg = reg_operand(lhs, sp);
774
	 int lhs_reg = reg_operand(lhs, sp);
753
	 int shift_const = bit_no(n);
775
	 int shift_const = bit_no(n);
754
	 sp = guardreg(lhs_reg, sp);
776
	 sp = guardreg(lhs_reg, sp);
755
	 if ( final_reg == R_NO_REG )
777
	 if (final_reg == R_NO_REG)
756
	 {
778
	 {
757
	   final_reg = getreg(sp.fixed);
779
	   final_reg = getreg(sp.fixed);
758
	 }
780
	 }
759
	 if ( n==1)
781
	 if (n==1)
760
	 {
782
	 {
761
	    /*
783
	    /*
762
	     *   div = lhs
784
	     *   div = lhs
763
	     */
785
	     */
764
 	    rr_ins(i_copy,lhs_reg,final_reg);
786
 	    rr_ins(i_copy,lhs_reg,final_reg);
765
	    return final_reg;
787
	    return final_reg;
766
	 }
788
	 }
767
	 else 
789
	 else
768
	 if (sgned)
790
	 if (sgned)
769
	 {
791
	 {
770
	   /* signed, adjust lhs before shift */
792
	   /* signed, adjust lhs before shift */
771
 	   assert(shift_const > 0);/* assumed below */
793
 	   assert(shift_const > 0);/* assumed below */
772
	   if ( n==-1 && !optop(e) )
794
	   if (n==-1 && !optop(e))
773
	   {
795
	   {
774
	      if (sz==8)
796
	      if (sz==8)
775
		 iiir_ins(i_zdepi,c_,-1,24,25,GR1);
797
		 iiir_ins(i_zdepi,c_,-1,24,25,GR1);
776
	      else
798
	      else
777
	      if (sz==16)
799
	      if (sz==16)
Line 801... Line 823...
801
   reg_operand_here(lhs, sp, ARG0);
823
   reg_operand_here(lhs, sp, ARG0);
802
   nsp = guardreg(ARG0,sp);
824
   nsp = guardreg(ARG0,sp);
803
   reg_operand_here(rhs,nsp,ARG1);
825
   reg_operand_here(rhs,nsp,ARG1);
804
 
826
 
805
 
827
 
806
   if ( !optop(e) )
828
   if (!optop(e))
807
   {
829
   {
808
      cj_ins(c_eq,GR0,ARG1,trap);
830
      cj_ins(c_eq,GR0,ARG1,trap);
809
      if (sgned)
831
      if (sgned)
810
      {
832
      {
811
	 comib_ins(c_neq,-1,ARG1,-16);        
833
	 comib_ins(c_neq,-1,ARG1,-16);
812
	 z_ins(i_nop);
834
	 z_ins(i_nop);
813
	 if (sz==8)
835
	 if (sz==8)
814
	    iiir_ins(i_zdepi,c_,-1,24,25,GR1);
836
	    iiir_ins(i_zdepi,c_,-1,24,25,GR1);
815
	 else
837
	 else
816
	 if (sz==16)
838
	 if (sz==16)
Line 859... Line 881...
859
 
881
 
860
 
882
 
861
/*
883
/*
862
 *   Generate code for remainder using remI or remU unless  simple constant.
884
 *   Generate code for remainder using remI or remU unless  simple constant.
863
 */
885
 */
864
static int do_rem 
886
static int do_rem
865
    PROTO_N ( ( e, sp, final_reg, sgned ) )
-
 
866
    PROTO_T ( exp e X space sp X int final_reg X bool sgned )
887
(exp e, space sp, int final_reg, bool sgned)
867
{
888
{
868
   exp seq = son(e);
889
   exp seq = son(e);
869
   exp lhs = seq;
890
   exp lhs = seq;
870
   exp rhs = bro(lhs);
891
   exp rhs = bro(lhs);
871
   int p=0;
892
   int p=0;
Line 873... Line 894...
873
   int trap = 0;
894
   int trap = 0;
874
   baseoff b;
895
   baseoff b;
875
   char *stub="ARGW0=GR ARGW1=GR";
896
   char *stub="ARGW0=GR ARGW1=GR";
876
   assert(last(rhs));
897
   assert(last(rhs));
877
   b = mem_temp(0);
898
   b = mem_temp(0);
878
   if ( !optop(e) )
899
   if (!optop(e))
879
      trap = trap_label(e);
900
      trap = trap_label(e);
880
   if (name(rhs) == val_tag)
901
   if (name(rhs) == val_tag)
881
   {
902
   {
882
      int n = no(rhs);
903
      int n = no(rhs);
883
      if ( n==0 )
904
      if (n==0)
884
      {
905
      {
885
	 if ( !optop(e) )
906
	 if (!optop(e))
886
	    ub_ins(cmplt_N,trap);        
907
	    ub_ins(cmplt_N,trap);
887
	 return GR0;
908
	 return GR0;
888
      }
909
      }
889
      else 
910
      else
890
      if ( IS_POW2(n) )
911
      if (IS_POW2(n))
891
      {
912
      {
892
	 int lhs_reg = reg_operand(lhs, sp);
913
	 int lhs_reg = reg_operand(lhs, sp);
893
	 sp = guardreg(lhs_reg, sp);
914
	 sp = guardreg(lhs_reg, sp);
894
	 if (final_reg == R_NO_REG)
915
	 if (final_reg == R_NO_REG)
895
	 {
916
	 {
896
	    final_reg = getreg(sp.fixed);
917
	    final_reg = getreg(sp.fixed);
897
	 }
918
	 }
898
	 if (n == 1)
919
	 if (n == 1)
899
	 {
920
	 {
900
	    /*
921
	    /*
901
	     *   rem = 0
922
	     *   rem = 0
902
	     */
923
	     */
903
 	    rr_ins(i_copy,0,final_reg);
924
 	    rr_ins(i_copy,0,final_reg);
904
	    return final_reg;
925
	    return final_reg;
905
	 }
926
	 }
906
	 while (((1<<(++p)) & n)==0);
927
	 while (((1<< (++p)) & n) ==0);
907
	 if (sgned && name(bro(rhs)) == rem2_tag)
928
	 if (sgned && name(bro(rhs)) == rem2_tag)
908
	 {
929
	 {
909
	    /*
930
	    /*
910
	     *   Allow for negative lhs. Calculate lhs % n ( = 2**p ) by
931
	     *   Allow for negative lhs. Calculate lhs % n ( = 2**p ) by
911
	     *   anding lhs with mask, negating lhs before and after anding
932
	     *   anding lhs with mask, negating lhs before and after anding
912
	     *   if lhs<0.
933
	     *   if lhs<0.
913
	     */
934
	     */
914
	    if (lhs_reg==final_reg)
935
	    if (lhs_reg==final_reg)
Line 931... Line 952...
931
	 else
952
	 else
932
	 {
953
	 {
933
	    /*
954
	    /*
934
	     *   Calculate lhs % n ( = 2**p ) by anding with mask.
955
	     *   Calculate lhs % n ( = 2**p ) by anding with mask.
935
	     */
956
	     */
936
	    if (lhs_reg==final_reg)   
957
	    if (lhs_reg==final_reg)
937
	       riir_ins(i_dep,c_,0,31-p,32-p,final_reg);
958
	       riir_ins(i_dep,c_,0,31-p,32-p,final_reg);
938
	    else
959
	    else
939
	       riir_ins(i_zdep,c_,lhs_reg,31,p,final_reg);
960
	       riir_ins(i_zdep,c_,lhs_reg,31,p,final_reg);
940
	 }
961
	 }
941
	 return final_reg;
962
	 return final_reg;
Line 959... Line 980...
959
		  else
980
		  else
960
		  if (n<0)
981
		  if (n<0)
961
		     rrr_ins(i_comclr,c_leq,RET1,0,0);
982
		     rrr_ins(i_comclr,c_leq,RET1,0,0);
962
		  ld_ir_ins(i_ldo,cmplt_,fs_,empty_ltrl,n,RET1,RET1);
983
		  ld_ir_ins(i_ldo,cmplt_,fs_,empty_ltrl,n,RET1,RET1);
963
	       }
984
	       }
964
	       else 
985
	       else
965
	       {
986
	       {
966
		  imm_to_r(n,ARG1);
987
		  imm_to_r(n,ARG1);
967
		  if (n>0)
988
		  if (n>0)
968
		     rrr_ins(i_comclr,c_geq,RET1,0,0);
989
		     rrr_ins(i_comclr,c_geq,RET1,0,0);
969
		  else
990
		  else
Line 985... Line 1006...
985
    *   Need to call remI/.urem
1006
    *   Need to call remI/.urem
986
    */
1007
    */
987
   reg_operand_here(lhs, sp, ARG0);
1008
   reg_operand_here(lhs, sp, ARG0);
988
   nsp = guardreg(ARG0, sp);
1009
   nsp = guardreg(ARG0, sp);
989
   reg_operand_here(rhs, nsp, ARG1);
1010
   reg_operand_here(rhs, nsp, ARG1);
990
   if ( !optop(e) )
1011
   if (!optop(e))
991
      cj_ins(c_eq,GR0,ARG1,trap);
1012
      cj_ins(c_eq,GR0,ARG1,trap);
992
 
1013
 
993
   if (name(bro(rhs)) == mod_tag && sgned)
1014
   if (name(bro(rhs)) == mod_tag && sgned)
994
   {
1015
   {
995
      st_ins(i_sw,ARG1,b);
1016
      st_ins(i_sw,ARG1,b);
Line 999... Line 1020...
999
      rrr_ins(i_xor,c_geq,RET1,ARG1,0);
1020
      rrr_ins(i_xor,c_geq,RET1,ARG1,0);
1000
      rrr_ins(i_add,c_,RET1,ARG1,RET1);
1021
      rrr_ins(i_add,c_,RET1,ARG1,RET1);
1001
   }
1022
   }
1002
   else
1023
   else
1003
   {
1024
   {
1004
      call_millicode( sgned ? MILLI_REMI : MILLI_REMU, RP, stub,1 );
1025
      call_millicode(sgned ? MILLI_REMI : MILLI_REMU, RP, stub,1);
1005
   }
1026
   }
1006
   clear_t_regs();
1027
   clear_t_regs();
1007
   return RET1;  /* result left in RET1 */
1028
   return RET1;  /* result left in RET1 */
1008
}
1029
}
1009
 
1030
 
1010
 
1031
 
1011
typedef int ( *find_fn ) PROTO_S ( ( exp, space, int, bool ) ) ;
1032
typedef int(*find_fn)(exp, space, int, bool);
1012
 
1033
 
1013
/* choose regs and generate code using do_fn */
1034
/* choose regs and generate code using do_fn */
1014
static int find_reg_and_apply
1035
static int find_reg_and_apply
1015
    PROTO_N ( ( e, sp, dest, sgned, do_fn ) )
-
 
1016
    PROTO_T ( exp e X space sp X where dest X bool sgned X find_fn do_fn )
1036
(exp e, space sp, where dest, bool sgned, find_fn do_fn)
1017
{
1037
{
1018
  ans a;
1038
  ans a;
1019
  int dest_reg;
1039
  int dest_reg;
1020
 
1040
 
1021
  /* +++ mips has tidyshort(dest, sh(e)); check not needed on HPPA */
1041
  /* +++ mips has tidyshort(dest, sh(e)); check not needed on HPPA */
1022
 
1042
 
1023
  switch (discrim ( dest.answhere ) )
1043
  switch (discrim(dest.answhere))
1024
  {
1044
  {
1025
  case inreg:
1045
  case inreg:
1026
    dest_reg = (*do_fn) (e, sp, regalt(dest.answhere), sgned);
1046
    dest_reg = (*do_fn)(e, sp, regalt(dest.answhere), sgned);
1027
    break;
1047
    break;
1028
 
1048
 
1029
  case insomereg:
1049
  case insomereg:
1030
    {
1050
    {
1031
      int *dr = someregalt(dest.answhere);
1051
      int *dr = someregalt(dest.answhere);
Line 1050... Line 1070...
1050
}
1070
}
1051
 
1071
 
1052
 
1072
 
1053
 
1073
 
1054
/* choose regs and generate code for multiply using multiply proc */
1074
/* choose regs and generate code for multiply using multiply proc */
1055
int do_mul_comm_op 
1075
int do_mul_comm_op
1056
    PROTO_N ( ( e, sp, dest, sgned ) )
-
 
1057
    PROTO_T ( exp e X space sp X where dest X bool sgned )
1076
(exp e, space sp, where dest, bool sgned)
1058
{
1077
{
1059
   return find_reg_and_apply(e, sp, dest, sgned, do_mul_comm);
1078
   return find_reg_and_apply(e, sp, dest, sgned, do_mul_comm);
1060
}
1079
}
1061
 
1080
 
1062
 
1081
 
1063
/* choose regs and generate code for divide using divide proc */
1082
/* choose regs and generate code for divide using divide proc */
1064
int do_div_op 
1083
int do_div_op
1065
    PROTO_N ( ( e, sp, dest, sgned ) )
-
 
1066
    PROTO_T ( exp e X space sp X where dest X bool sgned )
1084
(exp e, space sp, where dest, bool sgned)
1067
{
1085
{
1068
  return find_reg_and_apply(e, sp, dest, sgned, do_div);
1086
  return find_reg_and_apply(e, sp, dest, sgned, do_div);
1069
}
1087
}
1070
 
1088
 
1071
 
1089
 
1072
/* choose regs and generate code for rem using rem proc */
1090
/* choose regs and generate code for rem using rem proc */
1073
int do_rem_op 
1091
int do_rem_op
1074
    PROTO_N ( ( e, sp, dest, sgned ) )
-
 
1075
    PROTO_T ( exp e X space sp X where dest X bool sgned )
1092
(exp e, space sp, where dest, bool sgned)
1076
{
1093
{
1077
  return find_reg_and_apply(e, sp, dest, sgned, do_rem);
1094
  return find_reg_and_apply(e, sp, dest, sgned, do_rem);
1078
}
1095
}
1079
 
1096
 
1080
 
1097
 
1081
 
1098
 
1082
/* is exp mul, div or rem that may call */
1099
/* is exp mul, div or rem that may call */
1083
bool is_muldivrem_call 
1100
bool is_muldivrem_call
1084
    PROTO_N ( ( e ) )
-
 
1085
    PROTO_T ( exp e )
1101
(exp e)
1086
{
1102
{
1087
 
1103
 
1088
  switch (name(e))
1104
  switch (name(e))
1089
  {
1105
  {
1090
 
1106
 
Line 1092... Line 1108...
1092
     case test_tag:
1108
     case test_tag:
1093
     case chfl_tag:
1109
     case chfl_tag:
1094
     case round_tag:
1110
     case round_tag:
1095
     {
1111
     {
1096
	 exp s = son(e);
1112
	 exp s = son(e);
1097
	 if ( name(sh(s))==doublehd )
1113
	 if (name(sh(s)) ==doublehd)
1098
	    return (1) ;
1114
	    return(1);
1099
	 /* FALL THROUGH */
1115
	 /* FALL THROUGH */
1100
     }      
1116
     }
1101
 
1117
 
1102
     case fplus_tag:
1118
     case fplus_tag:
1103
     case fminus_tag:
1119
     case fminus_tag:
1104
     case fmult_tag:
1120
     case fmult_tag:
1105
     case fdiv_tag:
1121
     case fdiv_tag:
1106
     case fneg_tag:
1122
     case fneg_tag:
1107
     case fabs_tag:
1123
     case fabs_tag:
1108
     case float_tag:
1124
     case float_tag:
1109
     {
1125
     {
1110
	if ( name(sh(e))==doublehd)
1126
	if (name(sh(e)) ==doublehd)
1111
	   return(1);
1127
	   return(1);
1112
	else
1128
	else
1113
	   return(0);
1129
	   return(0);
1114
     }
1130
     }
1115
#endif
1131
#endif
1116
#if 0
1132
#if 0
1117
   case chvar_tag:
1133
   case chvar_tag:
1118
     e = son(e);		/* fall through, look at arg */
1134
     e = son(e);		/* fall through, look at arg */
1119
#endif
1135
#endif
1120
      case mult_tag:
1136
      case mult_tag:
Line 1125... Line 1141...
1125
	if (last(arg2) && name(arg2) == val_tag)
1141
	if (last(arg2) && name(arg2) == val_tag)
1126
	{
1142
	{
1127
	  return 0;
1143
	  return 0;
1128
	}
1144
	}
1129
	return 1;
1145
	return 1;
1130
      }    
1146
      }
1131
 
1147
 
1132
    case div0_tag:
1148
    case div0_tag:
1133
    case rem0_tag:
1149
    case rem0_tag:
1134
    case div1_tag:
1150
    case div1_tag:
1135
    case div2_tag:
1151
    case div2_tag:
1136
    case mod_tag:
1152
    case mod_tag:
1137
    case rem2_tag:
1153
    case rem2_tag:
1138
    case offset_div_tag:
1154
    case offset_div_tag:
1139
    case offset_div_by_int_tag: 
1155
    case offset_div_by_int_tag:
1140
      {
1156
      {
1141
	/*remneeds, divneeds - simple cases don't need a call */
1157
	/*remneeds, divneeds - simple cases don't need a call */
1142
	exp arg2 = bro(son(e));
1158
	exp arg2 = bro(son(e));
1143
 
1159
 
1144
	if (last(arg2) && name(arg2) == val_tag)
1160
	if (last(arg2) && name(arg2) == val_tag)
Line 1160... Line 1176...
1160
/*
1176
/*
1161
 * Needs estimation
1177
 * Needs estimation
1162
 */
1178
 */
1163
 
1179
 
1164
 
1180
 
1165
needs multneeds 
1181
needs multneeds
1166
    PROTO_N ( ( e, at ) )
-
 
1167
    PROTO_T ( exp * e X exp ** at )
1182
(exp * e, exp ** at)
1168
{
1183
{
1169
  needs n ;
1184
  needs n;
1170
  exp arg1 = son(*(e));
1185
  exp arg1 = son(*(e));
1171
  exp arg2 = bro(arg1);
1186
  exp arg2 = bro(arg1);
1172
  n = likeplus(e, at);	/* has had comm_ass() treatment */
1187
  n = likeplus(e, at);	/* has had comm_ass() treatment */
1173
 
1188
 
1174
  /* remember that mult may have more than two args after optimisation */
1189
  /* remember that mult may have more than two args after optimisation */
Line 1190... Line 1205...
1190
#endif
1205
#endif
1191
  return n;
1206
  return n;
1192
}
1207
}
1193
 
1208
 
1194
 
1209
 
1195
needs divneeds 
1210
needs divneeds
1196
    PROTO_N ( ( e, at ) )
-
 
1197
    PROTO_T ( exp * e X exp ** at )
1211
(exp * e, exp ** at)
1198
{
1212
{
1199
  needs n ;
1213
  needs n;
1200
  exp lhs = son(*(e));
1214
  exp lhs = son(*(e));
1201
  exp rhs = bro(lhs);
1215
  exp rhs = bro(lhs);
1202
  n = likediv(e, at);
1216
  n = likediv(e, at);
1203
 
1217
 
1204
  assert(last(rhs));
1218
  assert(last(rhs));
Line 1221... Line 1235...
1221
 
1235
 
1222
  return n;
1236
  return n;
1223
}
1237
}
1224
 
1238
 
1225
 
1239
 
1226
needs remneeds 
1240
needs remneeds
1227
    PROTO_N ( ( e, at ) )
-
 
1228
    PROTO_T ( exp * e X exp ** at )
1241
(exp * e, exp ** at)
1229
{
1242
{
1230
  needs n ;
1243
  needs n;
1231
  exp lhs = son(*(e));
1244
  exp lhs = son(*(e));
1232
  exp rhs = bro(lhs);
1245
  exp rhs = bro(lhs);
1233
  n = likediv(e, at);
1246
  n = likediv(e, at);
1234
 
1247
 
1235
  assert(last(rhs));
1248
  assert(last(rhs));