Subversion Repositories tendra.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
2
    		 Crown Copyright (c) 1997
3
 
4
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
12
 
13
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
15
 
16
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
19
 
20
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
22
        these conditions;
23
 
24
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
27
        it may be put.
28
*/
29
 
30
 
31
/**********************************************************************
32
$Author: release $
33
$Date: 1998/01/17 15:56:06 $
34
$Revision: 1.1.1.1 $
35
$Log: operators.c,v $
36
 * Revision 1.1.1.1  1998/01/17  15:56:06  release
37
 * First version to be checked into rolling release.
38
 *
39
 * Revision 1.4  1995/09/21  15:42:55  currie
40
 * silly reordering by as again
41
 *
42
 * Revision 1.3  1995/09/20  14:23:06  currie
43
 * callee-list blunder + fix for silliness in ultrix assembler
44
 *
45
 * Revision 1.2  1995/08/16  16:07:04  currie
46
 * Shortened some .h names
47
 *
48
 * Revision 1.1  1995/04/13  09:08:06  currie
49
 * Initial revision
50
 *
51
***********************************************************************/
52
/* operators.c
53
	produces code for common operations
54
*/
55
 
56
 
57
#include "config.h"
58
#include "code_here.h"
59
#include "expmacs.h"
60
#include "addrtypes.h"
61
#include "inst_fmt.h"
62
#include "move.h"
63
#include "maxminmacs.h"
64
#include "getregs.h"
65
#include "guard.h"
66
#include "tags.h"
67
#include "shapemacs.h"
68
#include "bitsmacs.h"
69
#include "common_types.h"
70
#include "mips_ins.h"
71
#include "operators.h"
72
#include "psu_ops.h"
73
 
74
bool testover = 0;		/* always 0 for C */
75
 
76
static void tidyshort
77
    PROTO_N ( (r, s, ins) )
78
    PROTO_T ( int r X shape s X char* ins )
79
{/* corrects possible overflows of chars
80
				   and shorts in reg r */
81
  int sz = shape_size(s);
82
  if (sz == 32) return;
83
  if (!is_signed(s)) {
84
	rri_ins(i_and, r, r, (1<<sz)-1);
85
  }
86
  else
87
  if (ins == i_not || ins == i_nor) {
88
	rri_ins(i_sll, r, r, 32-sz);
89
	rri_ins(i_sra, r, r, 32-sz);
90
  }
91
}
92
 
93
bool regremoved
94
    PROTO_N ( (seq, reg) )
95
    PROTO_T ( exp * seq X int reg )
96
{
97
				/* given a list of expressions seq which
98
				   contains one whose value is in
99
				   register reg, removes that exp from seq
100
				   and delivers 1; otherwise delivers 0 */
101
  exp s = *seq;
102
  exp t = bro (s);
103
  if (abs (regofval (s)) == reg) {
104
    (*seq) = t;
105
    return 1;
106
  }
107
  for (;;) {
108
    if (abs (regofval (t)) == reg) {
109
      bro (s) = bro (t);
110
      if (last (t))
111
	setlast (s);
112
      return 1;
113
    }
114
    if (last (t)) {
115
      return 0;
116
    }
117
    s = t;
118
    t = bro (t);
119
  }
120
}
121
 
122
void do_comm
123
    PROTO_N ( (seq, sp, final, rins) )
124
    PROTO_T ( exp seq X space sp X int final X char *rins )
125
{
126
				/* evaluates the fixed operation seq1 rins
127
				   seq 2 rins...., into reg final, using
128
				   sp as free t-regs */
129
  int   r = 0;
130
  space nsp;
131
  int   a1;
132
  int   a2;
133
 
134
  a1 = reg_operand (seq, sp);
135
  /* evaluate 1st operand into a1 */
136
  for (;;) {
137
    nsp = guardreg (a1, sp);
138
    seq = bro (seq);
139
    if (name (seq) == val_tag) {/* next operand is a constant */
140
      if (last (seq)) {
141
	rri_ins (rins, final, a1, no (seq));
142
	return;
143
      }
144
      else {
145
	if (r == 0)
146
	  r = getreg (sp.fixed);
147
	rri_ins (rins, r, a1, no (seq));
148
      }
149
    }
150
    else {
151
      exp sq = seq;
152
      char *ins = rins;
153
      a2 = reg_operand (sq, nsp);
154
      /* evaluate next operand */
155
      if (last (seq)) {
156
	rrr_ins (ins, final, a1, a2);
157
	return;
158
      }
159
      else {
160
	if (r == 0)
161
	  r = getreg (sp.fixed);
162
	rrr_ins (ins, r, a1, a2);
163
      }
164
    }
165
    a1 = r;
166
  }
167
}
168
 
169
 
170
int   comm_op
171
    PROTO_N ( (e, sp, d, rrins) )
172
    PROTO_T ( exp e X space sp X where d X char *rrins )
173
{
174
				/* evaluate commutative operation rrins
175
				   given by e into d, using sp to get
176
				   t-regs */
177
  char *rins = rrins;
178
 
179
 
180
  switch (d.answhere.discrim) {
181
    case inreg:
182
      {
183
	int   dest = regalt (d.answhere);
184
	bool usesdest = regremoved (&son (e), dest);
185
	exp seq = son (e);
186
	/* the destination is in a register; take care that we dont alter
187
	   it before possible use as an operand .... */
188
	if (usesdest && last (seq)) {
189
				/* ...it was used, but there is only one
190
				   other operand */
191
	  if (name (seq) == val_tag) {
192
	    rri_ins (rins, dest, dest, no (seq));
193
	  }
194
	  else {
195
	    rrr_ins (rins, dest, dest, reg_operand (seq, sp));
196
	  }
197
	  tidyshort (dest, sh (e), rins);
198
	  return dest;
199
	}
200
	else
201
	  if (usesdest) {	/* ... it was used so ... */
202
	    int   r = getreg (sp.fixed);
203
	    do_comm (seq, sp, r, rins);
204
	    /* ... evaluate the remainder of the expression into r... */
205
	    rrr_ins (rins, dest, dest, r);
206
	    /* ... and do dest = dest rins r */
207
	    tidyshort (dest, sh (e), rins);
208
	    return dest;
209
	  }
210
	  else {		/* ... it wasn't used */
211
	    do_comm (seq, sp, dest, rins);
212
	    tidyshort (dest, sh (e), rins);
213
	    return dest;
214
	  }
215
      }				/* end inreg */
216
 
217
    default:
218
      {
219
	ans a;
220
	int   r = getreg (sp.fixed);
221
	space nsp;
222
        bool rok =1;
223
	setregalt (a, r);
224
	do_comm (son (e), sp, r, rins);
225
	/* evaluate the expression into r ... */
226
	if(d.answhere.discrim != notinreg) {
227
		tidyshort (r, sh (e), rins);
228
        } else rok = shape_size(sh(e))==32;
229
	nsp = guardreg (r, sp);
230
	move (a, d, nsp, 1);
231
	/* ... and move into a */
232
	return ((rok)?r:NOREG);
233
      }				/* notinreg */
234
  }				/* end switch */
235
}
236
 
237
int   non_comm_op
238
    PROTO_N ( (e, sp, dest, rins) )
239
    PROTO_T ( exp e X space sp X where dest X char *rins )
240
{
241
				/* evalate binary operation e with rins
242
				   into dest */
243
        exp l = son (e);
244
  exp r = bro (l);
245
  int   a1 = reg_operand (l, sp);
246
  space nsp;
247
  int   a2;
248
  char *ins = rins;
249
 
250
 
251
  nsp = guardreg (a1, sp);
252
  a2 = reg_operand (r, nsp);
253
  /* regs a1 and a2 contain the operands */
254
  switch (dest.answhere.discrim) {
255
    case inreg: 		/* destination in register */
256
      {
257
	int   d = regalt (dest.answhere);
258
	rrr_ins (ins, d, a1, a2);
259
	tidyshort (d, sh (e), rins);
260
	return d;
261
      }
262
 
263
    default: 			/* destination elsewhere */
264
      {
265
	ans a;
266
	int   r1 = getreg (nsp.fixed);
267
        int rok = 1;
268
	setregalt (a, r1);
269
	rrr_ins (ins, r1, a1, a2);
270
	if(dest.answhere.discrim != notinreg){
271
		tidyshort (r1, sh (e), rins);
272
	} else rok = shape_size(sh(e))==32;
273
	nsp = guardreg (r1, sp);
274
	move (a, dest, nsp, 1);
275
	return (rok)?r1:NOREG;
276
      }
277
  }
278
}
279
 
280
int   monop
281
    PROTO_N ( (e, sp, dest, ins) )
282
    PROTO_T ( exp e X space sp X where dest X char *ins )
283
{
284
				/* evaluate fixed monadic operation e
285
				   using ins into dest */
286
  int   r1 = getreg (sp.fixed);
287
  int   a1 = reg_operand (son (e), sp);
288
  /* operand in reg a1 */
289
  space nsp;
290
  switch (dest.answhere.discrim) {
291
    case inreg: 		/* destination in register */
292
      {
293
	int   d = regalt (dest.answhere);
294
	mon_ins (ins, d, a1);
295
	tidyshort (d, sh (e), ins);
296
	return d;
297
      }
298
 
299
    default: 			/* destination elsewhere */
300
      {
301
	ans a;
302
	int rok = 1;
303
	setregalt (a, r1);
304
	mon_ins (ins, r1, a1);
305
	if(dest.answhere.discrim != notinreg){
306
		tidyshort (r1, sh (e), ins);
307
	} else rok = shape_size(sh(e))==32;
308
	nsp = guardreg (r1, sp);
309
	move (a, dest, nsp, 1);
310
	return ((rok)?r1:NOREG);
311
      }
312
  }
313
}
314
 
315
int   fop
316
    PROTO_N ( (e, sp, dest, ins) )
317
    PROTO_T ( exp e X space sp X where dest X char *ins )
318
{
319
				/* evaluate floating dyadic operation e
320
				   using ins into dest */
321
        exp l = son (e);
322
  exp r = bro (l);
323
  int   a1;
324
  space nsp;
325
  int   a2;
326
  freg fr;
327
 
328
   if (IsRev(e)) {
329
	a2 = freg_operand (r, sp);
330
  	nsp = guardfreg (a2, sp);
331
	a1 = freg_operand(l, nsp);
332
   }
333
   else {
334
	a1 = freg_operand (l, sp);
335
  	nsp = guardfreg (a1, sp);
336
	a2 = freg_operand(r, nsp);
337
   }
338
 
339
  if (!optop(e)) setnoreorder();
340
 
341
  switch (dest.answhere.discrim) {
342
    case infreg: 		/* dest in register */
343
      {
344
	fr = fregalt (dest.answhere);
345
	rrrfp_ins (ins, fr.fr << 1, a1 << 1, a2 << 1);
346
        break;
347
      }
348
    default: 			/* destinationelsewhere */
349
      {
350
	ans a;
351
	int   r1 = getfreg (nsp.flt);
352
	fr.fr = r1;
353
	fr.dble = (dest.ashwhere.ashsize == 64) ? 1 : 0;
354
	setfregalt (a, fr);
355
	rrrfp_ins (ins, r1 << 1, a1 << 1, a2 << 1);
356
	move (a, dest, sp, 1);
357
      }
358
  }
359
  if (!optop(e)) setreorder();
360
  return ((fr.dble) ? -(fr.fr + 32) : (fr.fr + 32));
361
}
362
 
363
int   fmop
364
    PROTO_N ( (e, sp, dest, ins) )
365
    PROTO_T ( exp e X space sp X where dest X char *ins )
366
{
367
				/* evaluate floating monadic operation e
368
				   using ins into dest */
369
  int   a1 = freg_operand (son (e), sp);
370
  freg fr;
371
  if (!optop(e)) setnoreorder();
372
  switch (dest.answhere.discrim) {
373
    case infreg:
374
      {
375
	fr = fregalt (dest.answhere);
376
	rrfp_ins (ins, fr.fr << 1, a1 << 1);
377
        break;
378
      }
379
 
380
    default:
381
      {
382
	ans a;
383
	fr.fr = getfreg(sp.flt);
384
	fr.dble = (dest.ashwhere.ashsize == 64) ? 1 : 0;
385
	setfregalt (a, fr);
386
	rrfp_ins (ins, fr.fr << 1, a1 << 1);
387
	move (a, dest, sp, 1);
388
      }
389
  }
390
  if(!optop(e)) setreorder();
391
  return ((fr.dble) ? -(fr.fr + 32) : (fr.fr + 32));
392
}