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: move.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.3  1995/09/12  10:59:35  currie
40
 * gcc pedanttry
41
 *
42
 * Revision 1.2  1995/08/16  16:06:55  currie
43
 * Shortened some .h names
44
 *
45
 * Revision 1.1  1995/04/13  09:08:06  currie
46
 * Initial revision
47
 *
48
***********************************************************************/
49
/**********************************************************************
50
		move.c
51
 
52
	The procedure move produces code to move a value from a to the
53
destination dest. This takes the form of a switch test on the parameter a (type
54
ans) which is either a reg, freg or instore value. In each of the three cases the
55
ans field of the dest is similarly dealt with to determine the necessary
56
instructions for the move. Sizes and alignment are taken from the ash field of
57
the destination.
58
Delivers register used if 1-word destination is instore; otherwise NOREG.
59
 
60
**********************************************************************/
61
 
62
#include "config.h"
63
#include "mips_ins.h"
64
#include "inst_fmt.h"
65
#include "addrtypes.h"
66
#include "procrectypes.h"
67
#include "getregs.h"
68
#include "labels.h"
69
#include "psu_ops.h"
70
#include "bitsmacs.h"
71
#include "common_types.h"
72
#include "main.h"
73
#include "guard.h"
74
#include "maxminmacs.h"
75
#include "basicread.h"
76
#include "move.h"
77
 
78
 
79
int   move
80
    PROTO_N ( (a, dest, freeregs, sgned) )
81
    PROTO_T ( ans a X where dest X space freeregs X bool sgned )
82
{
83
  long regs = freeregs.fixed;
84
  long fregs = freeregs.flt;
85
  int   al = dest.ashwhere.ashalign;
86
  int size = dest.ashwhere.ashsize;
87
 
88
  if (size==0) return NOREG;
89
 
90
start:
91
  switch (a.discrim) {
92
    case insomereg:
93
    case insomefreg: {
94
	failer ("Source reg not specified");
95
      }
96
 
97
    case inreg:
98
/***************** source in fixed point register ********************/
99
      {
100
	int   r = regalt (a);
101
	switch (dest.answhere.discrim) {
102
	  case inreg:
103
	    /* ******* source and dest in fixed register ************ */
104
	    {
105
	      int   rd = regalt (dest.answhere);
106
	      if (rd != 0 /* nowhere */ && rd != r) {
107
				/* move reg r to reg rd */
108
		mon_ins (i_move, rd, r);
109
	      }
110
	      return NOREG;
111
	    }			/* end inreg dest */
112
 
113
	  case insomereg:
114
	    /* **** can choose dest register to be source reg **** */
115
	    {
116
	      int  *sr = someregalt (dest.answhere);
117
	      if (*sr != -1) {
118
		failer ("Somereg *2");
119
	      }
120
	      *sr = r;
121
	      return NOREG;
122
	    }
123
 
124
	  case infreg:
125
	    /* ***source in fix reg,  dest in floating point register **********
126
	    */
127
	    {
128
	      freg fr;
129
	      fr = fregalt (dest.answhere);
130
	      cop_ins (i_mtc1, r, fr.fr << 1);
131
	      if (fr.dble) {
132
		cop_ins (i_mtc1, r + 1, (fr.fr << 1) + 1);
133
	      };
134
	      return NOREG;
135
	    }			/* end infreg dest */
136
 
137
    	   case insomefreg: {
138
	      /* source in fixed, can choose flt dest */
139
	       somefreg sfr;
140
	       freg fr;
141
   	       sfr = somefregalt(dest.answhere);
142
	       if (*sfr.fr != -1) { failer ("Somefreg *2"); }
143
	       *sfr.fr = getfreg(fregs);
144
	       fr.fr = *sfr.fr;
145
	       fr.dble = sfr.dble;
146
	       setfregalt(dest.answhere, fr);
147
	       goto start;
148
	  }
149
	  case notinreg:
150
	    /* **source in fix reg, dest instore ******************* */
151
	    {
152
	      char *st = (size==al) ?(
153
	           	(size <= 8) ? i_sb : ((size <= 16) ? i_sh : i_sw)):
154
	           	((size<=8)? i_sb : ((size <= 16) ? i_ush : i_usw));
155
	      instore is;
156
	      is = insalt (dest.answhere);
157
	      if (is.adval) {
158
		ls_ins (st, r, is.b);
159
	      }			/* is the value an address? */
160
	      else {
161
		baseoff b;
162
		b.base = getreg(regs);
163
		b.offset = 0;
164
		ls_ins (i_lw, b.base, is.b);
165
		ls_ins (st, r, b);
166
	      };
167
 
168
	      return r;
169
	    }			/* end notinreg dest */
170
 
171
 
172
	}			/* end switch dest */
173
      }				/* end inreg a */
174
    case infreg:
175
/****************** source in floating point register ******************/
176
      {
177
	freg fr;
178
	fr = fregalt (a);
179
	switch (dest.answhere.discrim) {
180
	  case inreg:
181
	    /* *source in float reg, dest in fixed point register ********
182
	    */
183
	    {
184
	      int   rd = regalt (dest.answhere);
185
	      if (rd != 0) {
186
		if (BIGEND) {
187
			if (fr.dble) {
188
		  	  cop_ins (i_mfc1, rd, (fr.fr << 1) + 1);
189
			}
190
			cop_ins (i_mfc1, rd+1, fr.fr << 1);
191
		}
192
		else {
193
			cop_ins (i_mfc1, rd, fr.fr << 1);
194
			if (fr.dble) {
195
		  	  cop_ins (i_mfc1, rd + 1, (fr.fr << 1) + 1);
196
			}
197
		}
198
	      };
199
	      return NOREG;
200
	    }			/* end inreg dest */
201
	  case insomereg:
202
	    /* *** source in flt reg, can choose dest reg ***** */
203
	    {
204
	      int  *sr = someregalt (dest.answhere);
205
	      if (*sr != -1) {
206
		failer ("Somereg *2");
207
	      }
208
	      *sr = getreg (regs);
209
	      setregalt (dest.answhere, *sr);
210
	      goto start;
211
	    }
212
	   case insomefreg: {
213
		/* can choose dest reg to be source reg */
214
	       somefreg sfr;
215
	       sfr = somefregalt(dest.answhere);
216
	       if (*(sfr.fr) !=-1) failer("some freg * 2");
217
	       *(sfr.fr) = fr.fr;
218
	        return NOREG;
219
	   }
220
	  case infreg:
221
	    /* ******* source and dest in floating point registers *******
222
	    */
223
	    {
224
	      freg frd;
225
	      frd = fregalt (dest.answhere);
226
	      if (fr.fr != frd.fr) {
227
		rrfp_ins ((frd.dble) ? i_mov_d : i_mov_s, frd.fr << 1, fr.fr << 1);
228
	      };
229
	      return NOREG;
230
	    }			/* end infreg dest */
231
	  case notinreg:
232
	    /* ********** source in flt reg, dest instore ******************
233
	    */
234
	    {
235
	      char *st = (fr.dble) ? i_s_d : i_s_s;
236
	      instore is;
237
 
238
	      if ((dest.ashwhere.ashsize == 64 && !fr.dble) ||
239
		  (dest.ashwhere.ashsize == 32 && fr.dble)) {
240
		st = (dest.ashwhere.ashsize==64) ? i_s_d:i_s_s;
241
		/* failer ("INCONSISTENT SIZES"); */
242
	      }
243
 
244
	      is = insalt (dest.answhere);
245
	      if (is.adval) {
246
		lsfp_ins (st, fr.fr << 1, is.b);
247
	      }
248
	      else {
249
		baseoff b;
250
		b.base = getreg (regs);
251
		b.offset = 0;
252
		ls_ins (i_lw, b.base, is.b);
253
		lsfp_ins (st, fr.fr << 1, b);
254
	      };
255
 
256
	      return ((fr.dble) ? -(fr.fr + 32) : (fr.fr + 32));
257
	    }			/* end notinreg dest */
258
	}			/* end switch dest */
259
      }				/* end infreg a */
260
 
261
 
262
 
263
    case notinreg:
264
/*********************** source instore *************************/
265
      {
266
	instore iss;
267
	char *ld;
268
	iss = insalt (a);
269
	if (iss.adval && iss.b.offset == 0 && iss.b.base > 0 && iss.b.base <= 31) {
270
	  setregalt (a, iss.b.base);
271
	  goto start;
272
	}
273
 
274
	if (al==1) { /* contained size for naked bitfields */
275
		al = (size<=8)? 8: ((size<=16)? 16:32);
276
	}
277
	ld = (iss.adval) ? i_la : ((al <= 8) ? ((sgned) ? i_lb : i_lbu) :
278
	    ((al <= 16) ? ((sgned) ? i_lh : i_lhu) : i_lw));
279
	/* determine which load instruction to use from al and adval */
280
 
281
	switch (dest.answhere.discrim) {
282
	  case insomefreg: {
283
	     /* source in store can choose dest freg */
284
	       somefreg sfr;
285
	       freg fr;
286
   	       sfr = somefregalt(dest.answhere);
287
	       if (*sfr.fr != -1) { failer ("Somefreg *2"); }
288
	       *sfr.fr = getfreg(fregs);
289
	       fr.fr = *sfr.fr;
290
	       fr.dble = sfr.dble;
291
	       setfregalt(dest.answhere, fr);
292
	       goto start;
293
	  }
294
	  case insomereg:
295
	    /* **** source instore, can choose dest reg ***** */
296
	    {
297
	      int  *sr = someregalt (dest.answhere);
298
	      if (*sr != -1) {
299
		failer ("Somereg *2");
300
	      }
301
	      *sr = getreg (regs);
302
	      setregalt (dest.answhere, *sr);
303
	      /* and continue to next case */
304
	    }
305
	  case inreg:
306
	    /* ********** source and dest in fixpnt reg ************* */
307
	    {
308
	      int   rd = regalt (dest.answhere);
309
	      if (rd != 0 /* nowhere */ ) {
310
		ls_ins (ld, rd, iss.b);
311
	      };
312
	      return NOREG;
313
	    }			/* end inreg dest */
314
 
315
 
316
	  case infreg:
317
	    /* *********** source instore, dest in floating pnt reg ********
318
	    */
319
	    {
320
	      freg frd;
321
	      frd = fregalt (dest.answhere);
322
	      if (iss.b.base == 0 && iss.b.offset == 0) {
323
		cop_ins (i_mtc1, 0, frd.fr << 1);
324
	        if (frd.dble) {
325
		cop_ins (i_mtc1, 0, (frd.fr << 1) + 1);
326
	        };
327
		return NOREG;
328
	      }
329
	      lsfp_ins ((frd.dble) ? i_l_d : i_l_s, frd.fr << 1, iss.b);
330
	      return NOREG;
331
	    }			/* end infreg dest */
332
 
333
 
334
	  case notinreg:
335
	    /* *********** source and dest  instore ************* */
336
	    {
337
	      char *st = (al <= 8) ? i_sb : ((al <= 16) ? i_sh : i_sw);
338
	      /* determine which store instruction from al (align from
339
	         dest) */
340
	      instore isd;
341
	      int   sunit = min (al, 32);
342
	      int   step = sunit >> 3;
343
	      int   s = (dest.ashwhere.ashsize + sunit - 1) / sunit;
344
	      bool unalign = 0;
345
	      isd = insalt (dest.answhere);
346
	      if (al == 8 && s >= 4) {
347
		int   r = getreg (regs);
348
		freeregs = guardreg(r,freeregs);
349
		/* register for holding values transferred */
350
		unalign = 1;
351
		if (s <= 16) {	/* in line unalligned move */
352
		  if (!isd.adval) {
353
		    int r3 = getreg(freeregs.fixed);
354
		    ls_ins (i_lw, r3, isd.b);
355
		    isd.b.base = r3;
356
		    isd.b.offset = 0;
357
		    isd.adval = 1;
358
		  }
359
		  for (; s >= 4; s -= 4) {
360
		    ls_ins (i_ulw, r, iss.b);
361
		    ls_ins (i_usw, r, isd.b);
362
		    iss.b.offset += 4;
363
		    isd.b.offset += 4;
364
		  }
365
 
366
		}
367
		else {		/* unaligned loop move *//* copy with
368
				   loop, length in r1, to in 2, from in 3
369
				*/
370
		  int   l = new_label ();
371
		  int   r1 = getreg (freeregs.fixed);
372
		  int r3, r2;
373
		  baseoff src;
374
		  baseoff dst;
375
		  freeregs = guardreg(r1,freeregs);
376
		  r3 = getreg(freeregs.fixed);
377
		  r2 = getreg(guardreg(r3,freeregs).fixed);
378
 
379
		  src.base = r3; src.offset = 0;
380
		  dst.base = r2; dst.offset = 0;
381
 
382
		  ls_ins ((isd.adval) ? i_la : i_lw, r2, isd.b);
383
		  isd.adval = 1;
384
		  ls_ins (i_la, r3, iss.b);
385
 
386
 
387
		  rri_ins (i_addu, r1, r3, (s & ~3));
388
		  /* output instruction to initialise counter */
389
		  set_label (l);
390
		  ls_ins (i_ulw, r, src);
391
		  rri_ins (i_addu, r3, r3, 4);
392
		  ls_ins (i_usw, r, dst);
393
		  rri_ins (i_addu, r2, r2, 4);
394
		  condrr_ins (i_bne, r1, r3, l);
395
		  /* instruction to test end of loop */
396
 
397
		  s = s & 3;
398
		  iss.b = src;
399
		  isd.b = dst;
400
		}
401
 
402
		for(; s>0; s--) {
403
			ls_ins(i_lb, r, iss.b);
404
			ls_ins(i_sb, r, isd.b);
405
			iss.b.offset += 1;
406
		    	isd.b.offset += 1;
407
		};
408
		return NOREG;
409
	      }
410
 
411
	      if (s <= inlineassign) {/* move in line */
412
		int   r = getreg (regs);
413
		/* register for holding values transferred */
414
 
415
		if (!isd.adval) {
416
		  int r3 = getreg(guardreg(r,freeregs).fixed);
417
		  freeregs = guardreg(r3,freeregs);
418
		  ls_ins (i_lw, r3, isd.b);
419
		  isd.b.base = r3;
420
		  isd.b.offset = 0;
421
		}
422
		if (s == 1) {
423
		  ls_ins (ld, r, iss.b);
424
		  ls_ins (st, r, isd.b);
425
 
426
		  return (unalign) ? NOREG : r;
427
		}
428
		else {
429
		  int   er = getreg (freeregs.fixed);
430
		  int   nr = r;
431
		  for (; s > 0; --s) {
432
		    ls_ins (ld, nr, iss.b);
433
		    ls_ins (st, nr, isd.b);
434
		    iss.b.offset += step;
435
		    isd.b.offset += step;
436
		    if (nr == r) {
437
		      nr = er;
438
		    }
439
		    else {
440
		      nr = r;
441
		    }
442
		  }
443
		  return NOREG;
444
		}
445
	      }			/* inline end */
446
	      else {		/* copy with loop, length in r1, to in r2,
447
				   from in r3 */
448
		int   a = getreg (regs);
449
				/* get register for transferring values */
450
		int   l = new_label ();
451
		int   r1, r2, r3;
452
		baseoff src;
453
		baseoff dst;
454
		freeregs = guardreg(a,freeregs);
455
		r1 = getreg(freeregs.fixed);
456
		freeregs = guardreg(r1,freeregs);
457
		r2 = getreg(freeregs.fixed);
458
		freeregs = guardreg(r2,freeregs);
459
		r3 = getreg(freeregs.fixed);
460
		src.base = r3; src.offset = 0;
461
		dst.base = r2; dst.offset = 0;
462
 
463
 
464
		ls_ins ((isd.adval) ? i_la : i_lw, r2, isd.b);
465
		ls_ins (i_la, r3, iss.b);
466
 
467
		ri_ins (i_li, r1, s);
468
		/* output instruction to initialise counter */
469
		set_label (l);
470
		ls_ins (ld, a, src);
471
		rri_ins (i_addu, r3, r3, step);
472
		ls_ins (st, a, dst);
473
		rri_ins (i_addu, r2, r2, step);
474
		rri_ins (i_subu, r1, r1, 1);
475
		/* instruction to decrement counter */
476
		condr_ins (i_bgtz, r1, l);
477
		/* instruction to test end of loop */
478
 
479
		return NOREG;
480
	      }			/* loop assign */
481
	    }			/* end notinreg dest */
482
	}			/* end switch dest */
483
      }				/* end notinreg a */
484
  }				/* end switch a */
485
}