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
$Log: move.c,v $
33
 * Revision 1.1.1.1  1998/01/17  15:56:03  release
34
 * First version to be checked into rolling release.
35
 *
36
 * Revision 1.4  1997/01/29  10:19:12  wfs
37
 *    Fixed a minor bug in "move.c" and "oprators.c" due to immediates of  >
38
 * 14 bits appearing in the field of ldo instrcutions.
39
 *
40
 * Revision 1.3  1996/01/11  14:46:29  wfs
41
 * Fixed bug in "ass_tag" case of scan(). Removed superfluous macro and comment.
42
 *
43
 * Revision 1.2  1995/12/18  13:12:02  wfs
44
 * Put hppatrans uder cvs control. Major Changes made since last release
45
 * include:
46
 * (i) PIC code generation.
47
 * (ii) Profiling.
48
 * (iii) Dynamic Initialization.
49
 * (iv) Debugging of Exception Handling and Diagnostics.
50
 *
51
 * Revision 5.2  1995/10/20  14:04:45  wfs
52
 * gcc compilation changes.
53
 *
54
 * Revision 5.1  1995/09/25  10:39:33  wfs
55
 * *** empty log message ***
56
 *
57
 * Revision 5.0  1995/08/25  13:42:58  wfs
58
 * Preperation for August 25 Glue release
59
 *
60
 * Revision 3.4  1995/08/25  09:54:19  wfs
61
 * register synonyms changed. Wingz bug fixed.
62
 *
63
 * Revision 3.4  1995/08/25  09:54:19  wfs
64
 * register synonyms changed. Wingz bug fixed.
65
 *
66
 * Revision 3.1  95/04/10  16:27:23  16:27:23  wfs (William Simmonds)
67
 * Apr95 tape version.
68
 * 
69
 * Revision 3.0  95/03/30  11:18:19  11:18:19  wfs (William Simmonds)
70
 * Mar95 tape version with CRCR95_178 bug fix.
71
 * 
72
 * Revision 2.0  95/03/15  15:28:09  15:28:09  wfs (William Simmonds)
73
 * spec 3.1 changes implemented, tests outstanding.
74
 * 
75
 * Revision 1.2  95/01/17  17:29:14  17:29:14  wfs (William Simmonds)
76
 * Changed name of an included header file.
77
 * 
78
 * Revision 1.1  95/01/11  13:13:14  13:13:14  wfs (William Simmonds)
79
 * Initial revision
80
 * 
81
*/
82
 
83
 
84
#define HPPATRANS_CODE
85
/**********************************************************************
86
		move.c
87
 
88
	The procedure move produces code to move a value from a to the
89
destination dest. This takes the form of a switch test on the parameter
90
a (type ans) which is either a reg, freg instore or bitad value. In
91
each of the three cases the ans field of the dest is similarly dealt
92
with to determine the necessary instructions for the move. Sizes and
93
alignment are taken from the ash field of the destination.
94
 
95
Delivers register used if 1-word destination is instore; otherwise NOREG.
96
 
97
**********************************************************************/
98
 
99
#include "config.h"
100
#include "myassert.h"
101
#include "hppains.h"
102
#include "inst_fmt.h"
103
#include "addrtypes.h"
104
#include "proctypes.h"
105
#include "proc.h"
106
#include "getregs.h"
107
#include "labels.h"
108
#include "comment.h"
109
#include "bitsmacs.h"
110
#include "common_types.h"
111
#include "regmacs.h"
112
#include "maxminmacs.h"
113
#include "makecode.h"
114
#include "move.h"
115
 
116
extern char reg_name_tab[32][5];
117
#define	MAX_STEPS_INLINE_MOVE	12	/* (was 8) 16 instructions */
118
 
119
 
120
#define NBITMASK(n)		((unsigned long)( (n)==32 ? 0L : ((1<<(n))-1) ))
121
 
122
 
123
/*
124
 *	ins_sgn_pair[FALSE]		unsigned instruction
125
 *	ins_sgn_pair[TRUE]		signed instruction
126
 */
127
typedef ins_p ins_sgn_pair[2 /* FALSE..TRUE */ ];
128
 
129
 
130
static CONST ins_sgn_pair st_ins_sz[] =
131
{
132
   /* 0 */ {I_NIL, I_NIL},
133
   /* 8 */ {i_stb, i_stb},
134
   /* 16 */ {i_sth, i_sth},
135
   /* 24 */ {I_NIL, I_NIL},
136
   /* 32 */ {i_stw, i_stw},
137
   /* 40 */ {I_NIL, I_NIL},
138
   /* 48 */ {I_NIL, I_NIL},
139
   /* 56 */ {I_NIL, I_NIL},
140
   /* 64 */ {I_NIL, I_NIL}
141
};
142
 
143
 
144
 
145
 
146
/* the st instruction for object sized bits */
147
ins_p i_st_sz 
148
    PROTO_N ( ( bits ) )
149
    PROTO_T ( int bits )
150
{
151
    return st_ins_sz[(bits) / 8][0];
152
}
153
 
154
 
155
 
156
/* load address represented by is into reg */
157
void ld_addr 
158
    PROTO_N ( ( is, reg ) )
159
    PROTO_T ( instore is X int reg )
160
{
161
  comment1("ld_addr: adval=%d", is.adval);
162
 
163
  if (is.adval)
164
  {
165
     if (IS_FIXREG(is.b.base))
166
	ld_ins(i_lo,0,is.b,reg);
167
     else
168
	set_ins("",is.b,reg);
169
  }
170
  else
171
     ld_ins(i_lw,1,is.b,reg);
172
}
173
 
174
 
175
/* get address represented by is */
176
int addr_reg 
177
    PROTO_N ( ( is, regs ) )
178
    PROTO_T ( instore is X long regs )
179
{
180
  int r;
181
 
182
  comment1("addr_reg: adval=%d", is.adval);
183
 
184
  if (is.adval && IS_FIXREG(is.b.base) && is.b.offset == 0)
185
  {
186
    /* simply return base reg */
187
    return is.b.base;
188
  }
189
 
190
  /* otherwise load address into reg */
191
  r = getreg(regs);
192
  ld_addr(is, r);
193
  return r;
194
}
195
 
196
 
197
 
198
int move 
199
    PROTO_N ( ( a, dest, regs, sgned ) )
200
    PROTO_T ( ans a X where dest X long regs X bool sgned )
201
{
202
  int al = dest.ashwhere.ashalign;
203
  if ( dest.ashwhere.ashsize == 0 )
204
     return NOREG ;
205
 
206
  FULLCOMMENT4("move: %s -> %s, dest ashsize,ashalign = %d,%d",
207
	       (int)ANSDISCRIM_NAME(discrim ( a )),
208
	       (int)ANSDISCRIM_NAME(discrim ( dest.answhere )),
209
	       dest.ashwhere.ashsize, dest.ashwhere.ashalign);
210
  assert((discrim ( dest.answhere ) == inreg && dest.answhere.val.regans == GR0)	/* nowhere */
211
	 || dest.ashwhere.ashsize > 0);	/* unitialised dest.ashwhere */
212
 
213
start:
214
 
215
  switch (discrim ( a ))
216
  {
217
  case insomereg:
218
  case insomefreg:
219
    {
220
      fail("move: source somereg not specified");
221
      return NOREG;
222
    }
223
#if USE_BITAD
224
  case bitad:
225
    /* source is bit address */
226
    {
227
      instore iss;
228
      int bpos;
229
      int bsize;
230
      int bshift;
231
      baseoff word_base;
232
      int reg;
233
      bool reg_is_dest;
234
 
235
      /* +++ bitad to bitad move, minimise shifts and masks */
236
 
237
      comment("move: source bit address");
238
 
239
      if (discrim ( dest.answhere ) == inreg)
240
      {
241
	reg = dest.answhere.val.regans;
242
	if (reg == 0)
243
	{
244
	  /* dest is nowhere, do nothing */
245
	  return NOREG;		/* nowhere */
246
	}
247
	reg_is_dest = 1;
248
      }
249
      else
250
      {
251
	reg = getreg(regs);
252
	reg_is_dest = 0;
253
      }
254
 
255
      iss = bitadalt(a);
256
 
257
      /* word_base is bit address of word containing source */
258
      word_base.base = iss.b.base;
259
      word_base.offset = iss.b.offset & ~31;
260
 
261
      /*
262
       * Set bpos, bsize, bshift to number of bits in a 32 bit word as in
263
       * following picture:
264
       *
265
       *		   < FIELD  >
266
       *	00000000000111111111100000000000
267
       *	<  bpos   >< bsize  >< bshift  >
268
       */
269
      bpos = iss.b.offset - word_base.offset;
270
      bsize = dest.ashwhere.ashsize;
271
      bshift = 32 - bpos - bsize;
272
 
273
      comment4("	dest ashsize,ashalign = %d,%d, iss.b.offset=%d (%%32=%d)",
274
	       dest.ashwhere.ashsize, dest.ashwhere.ashalign, iss.b.offset, iss.b.offset % 32);
275
      comment3("	bpos=%d, bsize=%d, bshift=%d", bpos, bsize, bshift);
276
 
277
      if (bpos + bsize > 32)
278
	fail("bit load > 32 ");
279
 
280
      {
281
	int tmp = bpos;
282
	bpos = bshift;
283
	bshift  = tmp;
284
      }
285
 
286
      /* now adjust word_base to be a byte address */
287
      word_base.offset /= 8;
288
 
289
#if 1
290
      /* optimise when word, half or byte loads are possible */
291
      if (!iss.adval && bsize == 8 && (bpos & 7) == 0)
292
      {
293
	/* byte load */
294
	word_base.offset += bpos / 8;
295
	ld_ins(i_lb,sgned,word_base,reg);
296
	bsize = 32;
297
      }
298
      else if (!iss.adval && bsize == 16 && (bpos & 15) == 0)
299
      {
300
	/* half load */
301
	word_base.offset += bpos / 8;
302
	ld_ins(i_lh,sgned,word_base,reg);
303
	bsize = 32;
304
      }
305
      else if (bsize == 32)
306
      {
307
	/* word load */
308
	ld_ins(i_lw,1,word_base,reg);
309
	bsize = 32;
310
      }
311
      else
312
#endif
313
	 ld_ins(i_lw,1,word_base,reg);
314
 
315
      if (bsize == 32)
316
      {
317
	/* field is entire word, nothing to do */
318
	;
319
      }
320
      else if (!sgned && bshift == 0)
321
	 /*
322
	  * Field is at right of word, and no need to propagate sign bit,
323
	  * simply mask.
324
	  */
325
	 riir_ins(i_dep,c_,0,31-bsize,32-bsize,reg);
326
      else
327
      {
328
 	 /* shift left than right, propagating sign if signed field */
329
	 if (sgned)
330
	    riir_ins(i_extrs,c_,reg,31-bshift,32-bpos-bshift,reg);
331
	 else 
332
	    riir_ins(i_extru,c_,reg,31-bshift,32-bpos-bshift,reg);
333
      }
334
 
335
      if (reg_is_dest)
336
      {
337
	/* already in its destination */
338
	return NOREG;
339
      }
340
 
341
      setregalt(a, reg);
342
 
343
      comment("move: source bit address now inreg");
344
 
345
      /*
346
       * Source 'a' adjusted into fixed point reg. Fall through to 'inreg'
347
       * code to process destination.
348
       */
349
 
350
    }				/* end bitad source */
351
 
352
    /* FALLTHROUGH */
353
#endif
354
 
355
  case inreg:
356
    /* source in fixed point register */
357
    {
358
      int r = regalt(a);
359
 
360
      switch (discrim ( dest.answhere ))
361
      {
362
      case inreg:
363
	/* source and dest in fixed register */
364
	{
365
	  int rd = regalt(dest.answhere);
366
 
367
	  if (rd != GR0 /* nowhere */ && rd != r)
368
 	     /* move reg r to reg rd */
369
	     rr_ins(i_copy,r,rd);
370
	  return NOREG;
371
	}			/* end inreg dest */
372
 
373
      case insomereg:
374
	/* source and dest in fixed register */
375
	{
376
	  int *sr = someregalt(dest.answhere);
377
 
378
	  if (*sr != -1)
379
	  {
380
	    fail("move: somereg already set");
381
	  }
382
	  *sr = r;
383
	  return NOREG;
384
	}
385
 
386
      case infreg:
387
	/* dest in floating point register */
388
	{
389
	  freg fr;
390
	  fr = fregalt(dest.answhere);
391
	  st_ins(i_sw, r, mem_temp(0));
392
	  ldf_ins(i_fldw, mem_temp(0), 3*fr.fr);
393
	  if (fr.dble)
394
	  {
395
	    /* +++ i_std when aligned wfs 27/1/94 change this */
396
	    st_ins(i_sw,r+1,mem_temp(4));
397
	    ldf_ins(i_fldw, mem_temp(4), 3*(fr.fr)+2);
398
	  }
399
	  return NOREG;
400
	}			/* end infreg dest */
401
 
402
      case notinreg:
403
	/* dest instore */
404
	{
405
	  int sz;
406
	  instore is;
407
 
408
#if USE_BITAD
409
	  if (al == 1)
410
  	     sz = dest.ashwhere.ashsize;
411
	  else
412
	  {
413
	     assert(al == dest.ashwhere.ashsize);
414
	     sz = al;
415
	  }
416
#else
417
	  sz = dest.ashwhere.ashsize;
418
	  if (al == 1)
419
	  {
420
	     if (sz<=8)
421
		al = 8;
422
	     else
423
	     if (sz<=16)
424
		al = 16;
425
	     else
426
		al = 32;
427
	  }
428
	  if ( al == 64 ) al = 32 ;
429
#endif
430
	  is = insalt(dest.answhere);
431
	  if (is.adval)		/* is the value an address? */
432
 	     st_ins( (sz==8 ? i_sb : (sz==16 ? i_sh : i_sw)), r, is.b );
433
	  else
434
	  {
435
 	     ld_ins(i_lw,1,is.b,GR1);
436
	     st_ir_ins( (sz==8 ? i_stbs : (sz==16 ? i_sths : i_stws)), cmplt_, r, fs_, empty_ltrl, 0, GR1);
437
	  }
438
 
439
	  return r;
440
	}			/* end notinreg dest */
441
#if USE_BITAD
442
      case bitad:
443
	/* source in fix reg, dest is bit address */
444
	{
445
	  instore is ;
446
	  int rsrc = r;
447
	  int rtmp;
448
	  int bpos;
449
	  int bsize;
450
	  int bshift;
451
	  baseoff word_base;
452
	  unsigned long mask_left;
453
	  unsigned long mask_right;
454
	  unsigned long mask;
455
	  is = bitadalt(dest.answhere);
456
 
457
	  /* +++ const to bit address */
458
 
459
	  comment("move: dest bit address");
460
 
461
	  if (!is.adval)
462
	  {
463
	    fail("no move to var bits");
464
	  }
465
 
466
	  /* word_base is bit address of word containing source */
467
	  word_base.base = is.b.base;
468
	  word_base.offset = is.b.offset & ~31;
469
 
470
	  /*
471
	   * Set bpos, bsize, bshift to number of bits in a 32 bit word as in
472
	   * following picture:
473
	   * 
474
	   */
475
	  bpos = is.b.offset - word_base.offset;
476
	  bsize = dest.ashwhere.ashsize;
477
	  bshift = 32 - bpos - bsize;
478
 
479
	  comment4("	dest ashsize,ashalign = %d,%d, is.b.offset=%d (%%32=%d)",
480
		   dest.ashwhere.ashsize, dest.ashwhere.ashalign, is.b.offset, is.b.offset % 32);
481
	  comment3("	bpos=%d, bsize=%d, bshift=%d", bpos, bsize, bshift);
482
 
483
	  if (bpos + bsize > 32)
484
	    fail("store bits over w-boundary");
485
 
486
	  {
487
	    int tmp = bpos;
488
	    bpos = bshift;
489
	    bshift  = tmp;
490
	  }
491
 
492
	  /* mask_left is all 1s to cover 'bpos' bits */
493
	  if (bpos == 0)
494
	    mask_left = 0;
495
	  else
496
	    mask_left = NBITMASK(bpos) << (32 - bpos);
497
 
498
	  /* mask_right is all 1s to cover 'bshift' bits */
499
	  if (bshift == 0)
500
	    mask_right = 0;
501
	  else
502
	    mask_right = NBITMASK(bshift);
503
 
504
	  mask = mask_left | mask_right;
505
 
506
	  comment2("	mask_left=%#x, mask_right=%#x", mask_left, mask_right);
507
 
508
 
509
	  /* now adjust word_base to be a byte address */
510
	  word_base.offset /= 8;
511
 
512
#if 1
513
	  /* optimise when word, half or byte stores are possible */
514
	  if (bsize == 32)
515
	  {
516
	    /* word store */
517
	    st_ins(i_sw, rsrc,word_base);
518
	    return NOREG;
519
	  }
520
	  else if (bsize == 16 && (bpos & 15) == 0)
521
	  {
522
	    /* half store */
523
	    word_base.offset += bpos / 8;
524
	    st_ins(i_sh, rsrc, word_base);
525
	    return NOREG;
526
	  }
527
	  else if (bsize == 16 && bpos == 8)
528
	  {
529
	    /* half store by two byte stores */
530
	    word_base.offset += bpos / 8 + 1;
531
	    st_ins(i_sb, rsrc, word_base);
532
	    word_base.offset -= 1;
533
	    /* cannot use GR1 as GR1 may be needed by st_ins() */
534
	    rtmp = getreg(regs);
535
	    rrir_ins(i_shd,c_,0,rsrc,8,rtmp);
536
	    st_ins(i_sb, rtmp, word_base);
537
	    return NOREG;
538
	  }
539
	  else if (bsize == 8 && (bpos & 7) == 0)
540
	  {
541
	    /* byte store */
542
	    word_base.offset += bpos / 8;
543
	    st_ins(i_sb, rsrc, word_base);
544
	    return NOREG;
545
	  }
546
#endif
547
 
548
	  /*
549
	   * cannot use GR1 as GR1 may be needed by st_ins() or for big
550
	   * mask
551
	   */
552
	  rtmp = getreg(regs);
553
	  regs |= RMASK(rtmp);
554
 
555
	  /* load dest word and mask out field */
556
	  ld_ins(i_lw,1,word_base,rtmp);
557
	  if (mask != ~0)
558
	  {
559
	     int l,p;
560
	     if (bshift==0 || bshift==32)
561
		p=31;
562
	     else
563
		p=31-bshift;
564
	     if (bpos==0 || bpos==32)
565
		l=p+1;
566
	     else
567
		l=p+1-bpos;
568
	     riir_ins(i_dep,c_,0,p,l,rtmp);
569
	  }
570
	  /* shift source to dest field position */
571
	  if (bshift != 0)
572
	  {
573
	     rrir_ins(i_shd,c_,rsrc,0,32-bshift,GR1);
574
 	     rsrc = GR1;
575
 	     /* safe to use GR1 as not needed for the st_ins() */
576
	  }
577
 
578
	  /* or source and dest and store out */
579
	  rrr_ins(i_or,c_,rsrc,rtmp,rtmp);
580
	  st_ins(i_sw, rtmp, word_base);
581
 
582
	  return NOREG;
583
	}
584
#endif
585
		default:
586
 		 fail("fixed -> wrong dest");
587
 
588
      }				/* end switch dest */
589
      /* NOTREACHED */
590
    }				/* end inreg a */
591
 
592
  case infreg:
593
    /* source in floating point register */
594
    {
595
      freg fr;
596
 
597
      fr = fregalt(a);
598
      switch (discrim ( dest.answhere ))
599
      {
600
      case inreg:
601
	/* dest in fixed point register */
602
	{
603
	  int rd = regalt(dest.answhere);
604
 
605
	  if (rd != 0)
606
	  {
607
	    /* store and load to move to fixed reg */
608
	    stf_ins(i_fstw, 3*fr.fr, mem_temp(0));
609
	    ld_ins(i_lw,1,mem_temp(0),rd);
610
	    if (fr.dble)
611
	    {
612
	       /* +++ i_std when aligned wfs, 27/1/94 must correect this */
613
	       stf_ins(i_fstw, (3*fr.fr)+2, mem_temp(4));
614
	       ld_ins(i_lw,1,mem_temp(4),rd+1);
615
	    }
616
	  }
617
	  return NOREG;
618
	}			/* end inreg dest */
619
 
620
      case insomereg:
621
	/* source in flt reg, can choose dest reg */
622
	{
623
	  int *sr = someregalt(dest.answhere);
624
 
625
	  if (*sr != -1)
626
	  {
627
	    fail("move: somereg already set");
628
	  }
629
	  *sr = getreg(regs);
630
	  setregalt(dest.answhere, *sr);
631
	  goto start;
632
	}
633
 
634
      case infreg:
635
	/* source and dest in floating point registers */
636
	{
637
	  freg frd;
638
 
639
	  frd = fregalt(dest.answhere);
640
	  if (fr.fr != frd.fr)
641
	  {
642
	      if (frd.dble)
643
		 rrf_ins(i_fcpy,f_dbl,"",3*(fr.fr)+1,3*(frd.fr)+1);
644
	      else
645
		 rrf_ins(i_fcpy,f_sgl,"",3*(fr.fr),3*(frd.fr));
646
	  };
647
	  return NOREG;
648
	}			/* end infreg dest */
649
 
650
      case notinreg:
651
	/* source in flt reg, dest instore */
652
	{
653
	  ins_p st = (fr.dble) ? i_fstd : i_fstw;
654
	  instore is;
655
 
656
	  if ((dest.ashwhere.ashsize == 64 && !fr.dble) ||
657
	      (dest.ashwhere.ashsize == 32 && fr.dble) )
658
	  {
659
	    fail("inconsistent sizes");
660
	  }
661
	  is = insalt(dest.answhere);
662
	  if (is.adval)
663
	  {
664
	    /* allow doubles not to be double aligned in mem, ie param */
665
	    /* wfs 27/1/94 must change */
666
	    if (fr.dble)
667
	    {
668
	      if ((is.b.offset & 7) == 0)	/* double aligned in mem */
669
		 stf_ins(i_fstd,(3*fr.fr)+1,is.b);
670
	      else
671
	      {
672
		/* not double aligned in mem, ie parameter */
673
		stf_ins(i_fstw, 3*fr.fr, is.b);
674
		is.b.offset += 4;
675
		stf_ins(i_fstw, (3*fr.fr)+2, is.b);
676
	      }
677
	    }
678
	    else
679
	       /* single */
680
	       stf_ins(i_fstw, 3*fr.fr, is.b);
681
	  }
682
	  else
683
	  {
684
	    baseoff b;
685
 
686
	    b.base = getreg(regs);
687
	    b.offset = 0;
688
	    ld_ins(i_lw,1,is.b,b.base);
689
	    if (st==i_fstw)
690
	       stf_ins(i_fstw,3*fr.fr,b);
691
	    else
692
	       stf_ins(i_fstd,(3*fr.fr)+1,b);
693
	  };
694
 
695
	  return ( fr.dble ? -(fr.fr + 32) : (fr.fr + 32) );
696
	}			/* end notinreg dest */
697
      default:{}
698
      }				/* end switch dest */
699
      /* NOTREACHED */
700
    }				/* end infreg a */
701
 
702
  case notinreg:
703
    /* source instore */
704
    {
705
      /* get into register and repeat */
706
      instore iss;
707
      int size = dest.ashwhere.ashsize;
708
      iss = insalt(a);
709
 
710
      if (iss.adval && iss.b.offset == 0 && IS_FIXREG(iss.b.base))
711
      {
712
	/* address of [base_reg+0] is base_reg */
713
	setregalt(a, iss.b.base);
714
	goto start;
715
      }
716
#if USE_BITAD
717
      if (al == 1)
718
      {
719
	iss.b.offset *= 8;
720
	setbitadalt(a, iss);
721
	goto start;
722
      }
723
#else
724
      if( al==1 )
725
      {
726
 	 if ( size<=8 )
727
	    al = 8;
728
	 else
729
	 if ( size<=16 )
730
 	    al = 16;
731
 	 else
732
 	   al = 32;
733
      }
734
      if (al == 64)
735
	al = 32;       /* +++ we cannot manage 64 bit int regs yet */
736
#endif
737
 
738
      /* determine which load instruction to use from al and adval */
739
 
740
      switch (discrim ( dest.answhere ))
741
      {
742
      case insomereg:
743
	/* source instore, can choose dest reg */
744
	{
745
	  int *sr = someregalt(dest.answhere);
746
 
747
	  if (*sr != -1)
748
	  {
749
	    fail("move: somereg already set");
750
	  }
751
	  *sr = getreg(regs);
752
	  setregalt(dest.answhere, *sr);
753
	  /* and continue to next case */
754
	}
755
 
756
	/* FALLTHROUGH */
757
 
758
      case inreg:
759
	/* source and dest in fixpnt reg */
760
	{
761
	  int rd = regalt(dest.answhere);
762
	  if (rd != GR0 /* nowhere */ )
763
	  {
764
	    if (iss.adval)
765
	    {
766
	       /* generate address of source */
767
	       if (IS_FIXREG(iss.b.base))
768
		  ld_ins(i_lo,0,iss.b,rd);
769
	       else
770
		  set_ins("",iss.b, rd);
771
	    }
772
	    else
773
	    {
774
	      /* load source */
775
		 ld_ins(al==8 ? i_lb : (al==16 ? i_lh : i_lw),sgned,iss.b,rd);
776
	    }
777
	  };
778
	  return NOREG;
779
	}			/* end inreg dest */
780
 
781
      case infreg:
782
	/* source instore, dest in floating pnt reg */
783
	{
784
	  freg frd ;
785
	  frd = fregalt(dest.answhere);
786
 
787
	  assert(!iss.adval);	/* address should never go to float reg */
788
	  /* allow doubles not to be double aligned in mem, ie param */
789
	  if (frd.dble)
790
	  {
791
	    if ((iss.b.offset & 7) == 0)	/* double aligned in mem */
792
	    {
793
	       ldf_ins(i_fldd, iss.b,(3*frd.fr)+1);
794
	    }
795
	    else
796
	    {
797
	       /* not double aligned in mem, ie parameter */
798
	       ldf_ins(i_fldw, iss.b, 3*frd.fr);
799
	       iss.b.offset += 4;
800
	       ldf_ins(i_fldw, iss.b, (3*frd.fr)+2);
801
	    }
802
	  }
803
	  else
804
	  {
805
	    /* single */
806
	    ldf_ins(i_fldw, iss.b, 3*frd.fr);
807
	  }
808
	  return NOREG;
809
	}			/* end infreg dest */
810
 
811
#if USE_BITAD
812
      case bitad:
813
	/* source instore, dest bitadd should be coped with elsewhere */
814
	{
815
	  fail("mem to mem bit move");
816
	  /* NOTREACHED */
817
	}
818
#endif
819
 
820
      case notinreg:
821
	/* source and dest instore */
822
	{
823
	  int bits;
824
	  int bits_per_step;
825
	  int bytes_per_step;
826
	  int no_steps;
827
	  ins_p i_l=I_NIL, i_s=I_NIL;
828
	  instore isd;
829
	  bool unalign = al < 32;
830
 
831
	  /* we are limited by 32 bit regs */
832
	  bits_per_step = MIN_OF(al, 32);
833
 
834
	  bytes_per_step = bits_per_step / 8;
835
 
836
	  /*
837
	   * .ashsize gives precise size in bits, not as rounded up as if
838
	   * object is an array element. So we round up bits to convenient
839
	   * size, less than alignement.
840
	   */
841
	  bits = (dest.ashwhere.ashsize + bits_per_step - 1) & ~(bits_per_step - 1);
842
 
843
	  no_steps = (bits + bits_per_step - 1) / bits_per_step;
844
 
845
	  comment2("move: mem to mem dest.ashwhere.ashsize,ashalign=%d,%d",
846
		   dest.ashwhere.ashsize, dest.ashwhere.ashalign);
847
	  comment4("move: mem to mem bits=%d align=%d, bytes_per_step=%d no_steps=%d",
848
		   bits, al, bytes_per_step, no_steps);
849
	  if ((al % 8) != 0 || (bits % 8) != 0)
850
	  {
851
	    fail("move: bits mem to mem move");
852
	    return NOREG;
853
	  }
854
 
855
	  /*
856
	   * we are assuming the following, eg 8 bit object cannot have 32 bit
857
	   * alignment
858
	   */
859
	  assert((bits % al) == 0);
860
 
861
	  assert(bytes_per_step > 0 && bytes_per_step <= 4);
862
	  assert(no_steps > 0);
863
	  assert((no_steps * bytes_per_step) == (bits / 8));
864
 
865
	  if (bits_per_step==8)
866
	  {
867
	     i_l=i_lb;
868
	     i_s=i_sb;
869
	  }
870
	  else if (bits_per_step==16)
871
	  {
872
	     i_l=i_lh;
873
	     i_s=i_sh;
874
	  }
875
	  else if (bits_per_step==32)
876
	  {
877
	     i_l=i_lw;
878
	     i_s=i_sw;
879
	  }
880
 
881
	  /* +++ use fp reg for float, except not passed free fp regs */
882
	  /* +++ use lss/std where poss */
883
 
884
	  /*
885
	   * +++ use actual alignment which may be better than nominal
886
	   * alignment
887
	   */
888
 
889
	  isd = insalt(dest.answhere);
890
 
891
	  if (no_steps <= MAX_STEPS_INLINE_MOVE)
892
	  {
893
	    /* move in line */
894
 
895
	    if (no_steps == 1)
896
	    {
897
	      int r = getreg(regs);	/* register for holding values
898
					 * transferred */
899
 
900
	      if (iss.adval)
901
	      {
902
		/* generate address of source */
903
		if (IS_FIXREG(iss.b.base))
904
		{
905
		  if (iss.b.offset == 0)
906
		  {
907
		    comment("move: using adval base reg directly");
908
		    r = iss.b.base;
909
		  }
910
		  else
911
		     ld_ins(i_lo,0,iss.b,r);
912
		}
913
		else
914
		  set_ins("",iss.b, r);
915
	      }
916
	      else
917
	      {
918
		 /* load source */
919
		 ld_ins(i_l,0,iss.b,r);
920
	      }
921
 
922
	      if (!isd.adval)
923
	      {
924
		/* +++ move away from use below, but care for GR1 */
925
		comment("move: !adval dest, using GR1");
926
		ld_ins(i_lw,1,isd.b,GR1);
927
		isd.b.base = GR1;
928
		isd.b.offset = 0;
929
	      }
930
 
931
	      st_ins(i_s, r, isd.b);
932
 
933
	      return (unalign) ? NOREG : r;
934
	    }
935
	    else
936
	    {
937
 
938
	      /*
939
	       * Move using 2 regs ensuring load delay slot not occupied.
940
	       */
941
	      int ld_steps = no_steps;
942
	      int st_steps = no_steps;
943
 
944
	      int r1, r2;	/* regs used to copy object */
945
 
946
	      comment("move: inline move");
947
 
948
	      assert(ld_steps >= 2);
949
 
950
	      /* moves of addresses not handled by this long move */
951
	      assert(!iss.adval);
952
 
953
	      assert(bits_per_step <= 32);	/* only using byte regs */
954
 
955
	      r1 = getreg(regs);
956
	      regs |= RMASK(r1);
957
 
958
	      r2 = getreg(regs);
959
	      regs |= RMASK(r2);
960
 
961
	      if (!IS_FIXREG(iss.b.base))
962
	      {
963
		/* load source ptr in reg, note GR1 possibly in use for dest */
964
 
965
		int pr = getreg(regs);
966
 
967
 
968
regs |= RMASK(pr);
969
 
970
		comment("move: load ptr to source");
971
 
972
		set_ins("",iss.b, pr);
973
		iss.b.base = pr;
974
		iss.b.offset = 0;
975
	      }
976
 
977
	      if (!isd.adval)
978
	      {
979
		int pr = getreg(regs);
980
 
981
		regs |= RMASK(pr);
982
 
983
		comment("move: dest !adval");
984
		ld_ins(i_lw,1,isd.b,pr);
985
		isd.b.base = pr;
986
		isd.b.offset = 0;
987
	      }
988
	      else if (!IS_FIXREG(isd.b.base))
989
	      {
990
		int pr = getreg(regs);
991
 
992
		regs |= RMASK(pr);
993
 
994
		comment("move: load ptr to dest");
995
 
996
		set_ins("",isd.b, pr);
997
		isd.b.base = pr;
998
		isd.b.offset = 0;
999
	      }
1000
 
1001
	      /* first, pre-load both regs */
1002
	      ld_ins(i_l,0,iss.b,r1);/* wfs 8/12/94 Changed sgned to 0 */ 
1003
	      ld_steps--;               
1004
	      iss.b.offset += bytes_per_step;
1005
 
1006
	      ld_ins(i_l,0,iss.b,r2);/* wfs 8/12/94 Changed sgned to 0 */ 
1007
	      ld_steps--;
1008
	      iss.b.offset += bytes_per_step;
1009
 
1010
	      /*
1011
	       * now generate overlapping sequence with ld rX seperated from
1012
	       * following st rX
1013
	       * 
1014
	       *	st	r1
1015
	       *	ld	r1
1016
	       *	st	r2
1017
	       *	ld	r2
1018
	       * 
1019
	       * while there's still data
1020
	       */
1021
	      while (st_steps > 0)
1022
	      {
1023
		/* st r1 */
1024
		st_ins(i_s,r1,isd.b);
1025
		st_steps--;
1026
		isd.b.offset += bytes_per_step;
1027
 
1028
		/* ld r1 */
1029
		if (ld_steps > 0)
1030
		{
1031
		  ld_ins(i_l,0,iss.b,r1);/* wfs 8/12/94 Changed sgned to 0 */
1032
		  ld_steps--;
1033
		  iss.b.offset += bytes_per_step;
1034
		}
1035
 
1036
		/* st r2 */
1037
		if (st_steps > 0)
1038
		{
1039
		  st_ins(i_s,r2,isd.b);
1040
		  st_steps--;
1041
		  isd.b.offset += bytes_per_step;
1042
		}
1043
 
1044
		/* ld r2 */
1045
		if (ld_steps > 0)
1046
		{
1047
		  ld_ins(i_l,0,iss.b,r2);/* wfs 8/12/94 Changed sgned to 0 */
1048
		  ld_steps--;
1049
		  iss.b.offset += bytes_per_step;
1050
		}
1051
	      }
1052
 
1053
	      comment("move: end inline move");
1054
 
1055
	      assert(ld_steps == 0);
1056
 
1057
	      return NOREG;
1058
	    }
1059
	  }			/* inline end */
1060
	  else
1061
	  {
1062
 
1063
	    /*
1064
	     * Copy with loop.
1065
	     * 
1066
	     * Currently generate:
1067
	     * 
1068
	     * !%srcptr and %destptr set mov	bytes,%cnt loop: subc
1069
	     * %cnt,bytes_per_step,%cnt ldX	%tmp,[%srcptr+%cnt] stX
1070
	     * %tmp,[%destptr+%cnt] bne	loop
1071
	     * 
1072
	     * +++ unroll, and use two copy regs to seperate ld and st using same
1073
	     * reg
1074
	     */
1075
 
1076
 
1077
	    int srcptr;
1078
	    int destptr;
1079
	    int count;
1080
	    int copy_reg;
1081
	    int loop = new_label();
1082
	    int blocksz;
1083
 
1084
	    comment("move: loop move");
1085
 
1086
	    /* moves of addresses not handled by this long move */
1087
	    assert(!iss.adval);
1088
 
1089
	    assert(bytes_per_step <= 4);	/* only using 1 word regs */
1090
 
1091
	    count = getreg(regs);
1092
	    regs |= RMASK(count);
1093
 
1094
	    assert(!iss.adval);
1095
	    iss.adval = 1;	/* we want address of value */
1096
	    srcptr = addr_reg(iss, regs);
1097
	    regs |= RMASK(srcptr);
1098
 
1099
	    destptr = addr_reg(isd, regs);
1100
	    regs |= RMASK(destptr);
1101
 
1102
	    copy_reg = GR1;
1103
	    blocksz = bytes_per_step*no_steps;
1104
	    if (SIMM14(blocksz))
1105
	    {
1106
	       ld_ir_ins(i_ldo,cmplt_,fs_,empty_ltrl,blocksz,srcptr,count);
1107
	       ld_ir_ins(i_ldo,cmplt_,fs_,empty_ltrl,blocksz,destptr,destptr);
1108
	    }
1109
	    else
1110
	    {
1111
	       imm_to_r(blocksz,GR1);
1112
	       rrr_ins(i_add,c_,GR1,srcptr,count);
1113
	       rrr_ins(i_add,c_,GR1,destptr,destptr);
1114
	    }
1115
	    outlab("L$$",loop);
1116
	    if (bytes_per_step==1)
1117
	    {
1118
	       ld_ir_ins(i_ldbs,cmplt_MB,fs_,empty_ltrl,-1,count,copy_reg);
1119
	       comb_ins(c_neq,count,srcptr,loop);
1120
	       st_ir_ins(i_stbs,cmplt_MB,copy_reg,fs_,empty_ltrl,-1,destptr);
1121
	    }
1122
	    else if (bytes_per_step==2)
1123
	    {
1124
	       ld_ir_ins(i_ldhs,cmplt_MB,fs_,empty_ltrl,-2,count,copy_reg);
1125
	       comb_ins(c_neq,count,srcptr,loop);
1126
	       st_ir_ins(i_sths,cmplt_MB,copy_reg,fs_,empty_ltrl,-2,destptr);
1127
	    }
1128
	    else if (bytes_per_step==4)
1129
	    {
1130
	       ld_ir_ins(i_ldwm,cmplt_,fs_,empty_ltrl,-4,count,copy_reg);
1131
	       comb_ins(c_neq,count,srcptr,loop);
1132
	       st_ir_ins(i_stwm,cmplt_,copy_reg,fs_,empty_ltrl,-4,destptr);
1133
	    }
1134
	    return NOREG;
1135
	  }			/* loop assign */
1136
	}			/* end notinreg dest */
1137
	default:{}
1138
      }				/* end switch dest */
1139
    }				/* end notinreg a */
1140
    default:{}
1141
  }				/* end switch a */
1142
 
1143
  fail("move not handled");
1144
  return 0;  /* NOTREACHED */
1145
}
1146
 
1147
 
1148
 
1149