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
/* 	$Id: move.c,v 1.2 1998/02/04 10:43:31 release Exp $	 */
32
 
33
#ifndef lint
34
static char vcid[] = "$Id: move.c,v 1.2 1998/02/04 10:43:31 release Exp $";
35
#endif /* lint */
36
 
37
/*
38
$Log: move.c,v $
39
 * Revision 1.2  1998/02/04  10:43:31  release
40
 * Changes during testing.
41
 *
42
 * Revision 1.1.1.1  1998/01/17  15:56:00  release
43
 * First version to be checked into rolling release.
44
 *
45
 * Revision 1.13  1996/02/15  09:54:57  john
46
 * Fix to word load/store
47
 *
48
 * Revision 1.12  1996/01/23  16:58:16  john
49
 * Fix to aligments
50
 *
51
 * Revision 1.11  1995/10/30  10:17:19  john
52
 * Fix to unaligned loads
53
 *
54
 * Revision 1.10  1995/10/16  12:08:23  john
55
 * Change to alignment calculation
56
 *
57
 * Revision 1.9  1995/08/21  08:45:41  john
58
 * Changed include files
59
 *
60
 * Revision 1.8  1995/07/27  10:09:29  john
61
 * Moved register allocation
62
 *
63
 * Revision 1.7  1995/06/28  10:25:35  john
64
 * Reformatting
65
 *
66
 * Revision 1.6  1995/06/13  14:01:25  john
67
 * Fixed a pair of bugs with reg <-> memory moves
68
 *
69
 * Revision 1.5  1995/05/25  15:33:16  john
70
 * Cosmetic changes
71
 *
72
 * Revision 1.4  1995/05/23  10:57:12  john
73
 * Reformatting
74
 *
75
 * Revision 1.3  1995/05/16  10:54:02  john
76
 * Cosmetic change
77
 *
78
 * Revision 1.2  1995/03/29  14:03:56  john
79
 * Changes to keep tcheck happy
80
 *
81
 * Revision 1.1.1.1  1995/03/23  10:39:13  john
82
 * Entered into CVS
83
 *
84
 * Revision 1.23  1995/03/23  09:55:17  john
85
 * Changed handling of bitfields
86
 *
87
 * Revision 1.22  1995/01/26  13:44:55  john
88
 * Removed unused variables
89
 *
90
 * Revision 1.21  1995/01/12  11:49:19  john
91
 * Fixed assertion
92
 *
93
*/
94
 
95
/*
96
  move.c
97
  This file contains code to move a value from src to dest, 
98
  where src can be in a general purpose register, a floating 
99
  point register, or in store.  Delivers register used if dest 
100
  in store, otherwise NOREG.
101
*/
102
 
103
#include "config.h"
104
#include "alpha_ins.h"
105
#include "inst_fmt.h"
106
#include "addresstypes.h"
107
#include "procrectypes.h"
108
#include "fail.h"
109
#include "bitsmacs.h"
110
#include "maxminmacs.h"
111
#include "main.h"
112
#include "reg_defs.h"
113
#include "guard.h"
114
#include "locate.h"
115
#include "regexps.h"
116
#include "guard.h"
117
#include "getregs.h"
118
#include "bool.h"
119
#include "expmacs.h"
120
#include "frames.h"
121
#include "pseudo.h"
122
#include "labels.h"
123
#include "move.h"
124
 
125
/* bit masks */
126
#if FS_64_BIT
127
extern int stack_top;
128
INT64 word_mask=0xffffL;
129
INT64 long_mask=0xffffffffL;
130
INT64 one_64=1L;
131
#else /* FS_64_BIT */
132
INT64 word_mask={
133
 
134
};
135
 
136
INT64 long_mask={
137
  0,0xffffffff
138
};
139
 
140
INT64 one_64 = {0,1};
141
#endif /* FS_64_BIT */
142
 
143
/*
144
  Returns TRUE if the data is aligned properly, false otherwise.
145
*/
146
static bool aligned
147
    PROTO_N ( ( address,al ) )
148
    PROTO_T ( baseoff address X int al )
149
{
150
  if((address.base<0) || (address.base > 31))
151
    return 1;
152
  return ((regexps[address.base].alignment>=al || (address.base==SP)||
153
	   ((address.base == FP)&&Has_fp)) && ((address.offset%al)==0));
154
}
155
 
156
/*
157
  produces a unary representation for the number in
158
*/
159
static int unary
160
    PROTO_N ( ( in ) )
161
    PROTO_T ( int in )
162
{
163
  int result=0;
164
  int loop;
165
  Assert(in<9);	/* in is a number of bytes */
166
  for(loop=0;loop<in;++loop){
167
    result <<= 1;
168
    result |= 1;
169
  }
170
  return result;
171
}
172
 
173
 
174
#define aligned_reg(X,al) (((X<0) || (X>31))?0:((regexps[X].alignment>=al)||(X==SP)||((X==FP)&&Has_fp)))
175
 
176
/* take account of adval here ? */
177
#if 1
178
#define address_equal(X,Y) ((X.b.base==Y.b.base) && (X.b.offset==Y.b.offset)\
179
			    && (((X.adval==Y.adval))||(Y.adval)))
180
#else
181
#define address_equal(X,Y) 0
182
#endif
183
 
184
 
185
int choose_block_size
186
    PROTO_N ( ( dest,al,size ) )
187
    PROTO_T ( where dest X int al )
188
{
189
  int bsize;
190
  if(!(insalt(dest.answhere).b.offset%8)){
191
    bsize = (dest.ashwhere.ashsize%64==0)?64:min(al,64);
192
  }
193
  else if(!(insalt(dest.answhere).b.offset%4)){
194
    bsize = (dest.ashwhere.ashsize%32==0)?32:min(al,32);
195
  }
196
  else if(!(insalt(dest.answhere).b.offset%2)){
197
    bsize = (dest.ashwhere.ashsize%16==0)?16:min(al,16);
198
  }
199
  else{
200
    bsize=8;
201
  }
202
  return bsize;
203
}
204
 
205
 
206
 
207
/*
208
  This function moves a piece of data from one location to another.
209
  The parameters are as follows:
210
  src	: 	the location of the source
211
  dest	:	the destination
212
  freeregs:	registers available for use 
213
  sgned:	TRUE if data is signed, FALSE otherwise
214
*/
215
int move
216
    PROTO_N ( ( src,dest,freeregs,sgned ) )
217
    PROTO_T ( ans src X where dest X space freeregs X bool sgned )
218
{
219
  int al=dest.ashwhere.ashalign;
220
  int size=dest.ashwhere.ashsize;
221
  enum {
222
    BYTE,WORD,LONGWORD,QUADWORD
223
  } datatype;
224
  switch(src.discrim){
225
    case insomereg :
226
    case insomefreg :{
227
      failer("Source reg not specified");
228
      break;
229
    }	
230
    case inreg :{
231
      int rsrc = regalt(src);
232
      freeregs = guardreg(rsrc,freeregs);
233
      switch(dest.answhere.discrim){
234
	case inreg:{
235
	  /* src & dest both in a general purpose register */
236
	  int rdest=regalt(dest.answhere);
237
	  if(rdest!=rsrc && rdest!=NO_REG){
238
	    operate_fmt(i_bis,rsrc,rsrc,rdest); /* dest = src OR src */
239
	  }  
240
	  return NOREG;
241
	}
242
	case insomereg:{
243
	  /* can choose dest register to be source register */
244
	  int *somereg = someregalt(dest.answhere);
245
	  if(*somereg!=-1) failer ("somereg!=-1");
246
	  *somereg=rsrc;
247
	  return NOREG;
248
	}
249
	case infreg:{
250
	  /* source in gen reg, dest in floating point */
251
	  /* must write onto stack, load into float register, convert*/
252
	  freg fr;
253
	  baseoff mem_loc;
254
	  mem_loc.base = SP;
255
	  /* should really check that space is available on stack */
256
	  mem_loc.offset = stack_top;		/* ? */
257
	  fr=fregalt(dest.answhere);
258
	  load_store((size==32)?i_stl:i_stq,rsrc,mem_loc);
259
	  float_load_store((size==32)?i_lds:i_ldt,fr.fr,mem_loc);
260
	  return NOREG;
261
	}
262
	case insomefreg:{
263
	  /* source in fixed, can choose flt dest */
264
	  somefreg sfr;
265
	  freg fr;
266
	  sfr = somefregalt(dest.answhere);
267
	  if(*sfr.fr != -1) failer("Somfreg *2");
268
	  *sfr.fr = getfreg(freeregs.flt);
269
	  fr.fr = *sfr.fr;
270
	  fr.type = sfr.type;
271
	  setfregalt(dest.answhere,fr);
272
	  return move(src,dest,freeregs,sgned);
273
	}
274
	case notinreg:{
275
	  instore is;
276
	  instruction st;
277
	  is=insalt(dest.answhere);
278
	  size=(size==0)?64:(size<8)?8:size;
279
	  if(al == 1) al = size;
280
	  if(size==32){
281
	    st = i_stl;
282
	  }
283
	  else {
284
	    st = aligned(is.b,8)?i_stq:i_stq_u;
285
	    st = i_stq;
286
	  }	
287
      /* add locking, etc */
288
      if(is.adval){
289
	switch(al){	/* changed from switch(size) */
290
	  case 8:{
291
	    /* source in register -> byte in memory */
292
	    int byte_address = AT;
293
	    /* use the assembler temp register to store the address.
294
	     The system compiler uses this scheme, not sure why 
295
	     though. */
296
	    space gsp = guardreg(rsrc,freeregs);
297
	    int word_containing_byte;
298
	    int t1;
299
	    baseoff a;
300
	    gsp = guardreg(is.b.base,gsp);
301
	    if(aligned_reg(is.b.base,4) && ((is.b.offset%4)==0 && 
302
					    is.b.offset>0)/*aligned(is.b,4)*/){
303
	      /*
304
		if the target address is aligned on a 4 byte boundary
305
		then we can use an optimised load sequence, 
306
		eliminating the lda instruction and replacing the
307
		ldq_u and stq_u with ldl and stl.
308
	   */
309
	      int r1 = getreg(gsp.fixed);
310
	      int r2 = getreg(gsp.fixed);
311
	      baseoff newbo;
312
	      newbo.base = is.b.base;
313
	      newbo.offset = (is.b.offset/4)*4;
314
	      load_store(i_ldl,r1,newbo);
315
	      operate_fmt_immediate(i_insbl,rsrc,is.b.offset%4,r2);
316
	      operate_fmt_immediate(i_mskbl,r1,is.b.offset%4,r1);
317
	      operate_fmt(i_bis,r2,r1,r1);
318
	      load_store(i_stl,r1,newbo);
319
	    }
320
	    else{
321
	      word_containing_byte = getreg(gsp.fixed);
322
	      t1 = getreg(gsp.fixed);
323
	      a.base = byte_address;
324
	      a.offset = 0;
325
	      setnoat();
326
	      load_store(i_lda,byte_address,is.b);
327
	      load_store(i_ldq_u,word_containing_byte,a);
328
	      operate_fmt(i_insbl,rsrc,byte_address,t1);
329
	      operate_fmt(i_mskbl,word_containing_byte,byte_address,
330
			  word_containing_byte);
331
	      operate_fmt(i_bis,word_containing_byte,t1,word_containing_byte);
332
	      load_store(i_stq_u,word_containing_byte,a);
333
	      setat();
334
	    }
335
	    break;
336
	  }
337
	  case 16:{
338
	    /* source in register -> word in memory */
339
	    int word_address=AT;
340
	    space ssp = guardreg(is.b.base,freeregs);
341
	    int qw_containing_word,tmp1,tmp2,tmp3;
342
	    ssp = guardreg(rsrc,ssp);
343
	    qw_containing_word=getreg(ssp.fixed);
344
	    ssp=guardreg(qw_containing_word,ssp);
345
	    tmp1=getreg(ssp.fixed);
346
	    ssp=guardreg(tmp1,ssp);
347
	    tmp2=getreg(ssp.fixed);
348
	    ssp=guardreg(tmp2,ssp);
349
	    if(aligned_reg(is.b.base,4) && ((is.b.offset%4) == 0) &&
350
	       is.b.offset>0) {
351
	      /*
352
		see byte case above for details.
353
		*/
354
	      baseoff newbo;
355
	      newbo.base = is.b.base;
356
	      newbo.offset = (is.b.offset/4)*4;
357
	      load_store(i_ldl,tmp1,newbo);
358
	      operate_fmt_immediate(i_inswl,rsrc,is.b.offset%4,tmp2);
359
	      operate_fmt_immediate(i_mskwl,tmp1,is.b.offset%4,tmp1);
360
	      operate_fmt(i_bis,tmp2,tmp1,tmp1);
361
	      load_store(i_stl,tmp1,newbo);
362
	    }
363
	    else{
364
	      tmp3=getreg(ssp.fixed);
365
	      setnoat();
366
	      load_store(i_lda,word_address,is.b);
367
	      is.b.offset++;
368
	      load_store(i_ldq_u,qw_containing_word,is.b);
369
	      is.b.offset--;
370
	      load_store(i_ldq_u,tmp1,is.b);
371
	      operate_fmt(i_inswh,rsrc,word_address,tmp2);
372
	      operate_fmt(i_inswl,rsrc,word_address,tmp3);
373
	      operate_fmt(i_mskwh,qw_containing_word,word_address,
374
			  qw_containing_word);
375
	      operate_fmt(i_mskwl,tmp1,word_address,tmp1);
376
	      setat();
377
	      operate_fmt(i_bis,qw_containing_word,tmp2,qw_containing_word);
378
	      operate_fmt(i_bis,tmp1,tmp3,tmp1);
379
	      is.b.offset++;
380
	      load_store(i_stq_u,qw_containing_word,is.b);
381
	      is.b.offset--;
382
	      load_store(i_stq_u,tmp1,is.b);
383
	      setat();
384
	    }
385
	    break;
386
	  }
387
	  case 32:
388
	  case 64:
389
	  load_store(st,rsrc,is.b);
390
	  break;
391
	  default:
392
	  failer("unsupported data size");
393
	}
394
      }
395
      else{
396
	ans newsrc;
397
	where newdest;
398
	baseoff tmploc;
399
	instore iss;
400
	tmploc.offset = 0;
401
	tmploc.base = getreg(freeregs.fixed);
402
	setinsalt(newsrc,is);
403
	setregalt(newdest.answhere,tmploc.base);
404
	newdest.ashwhere.ashsize=64;
405
	newdest.ashwhere.ashalign=64;
406
	(void)move(newsrc,newdest,guardreg(tmploc.base,freeregs),sgned);
407
	/* now src is evaluated into tmploc */
408
	iss.adval=1;
409
	iss.b = tmploc;
410
	newdest.ashwhere.ashsize=size;		/* ??? */
411
	newdest.ashwhere.ashalign=al;
412
	setinsalt(newdest.answhere,iss);
413
	setregalt(newsrc,rsrc);
414
	(void)move(newsrc,newdest,guardreg(tmploc.base,freeregs),sgned);
415
	return rsrc;
416
      }
417
      return NOREG;
418
    }
419
    }
420
    break;
421
  }
422
    case infreg:{
423
      freg fr;
424
      fr=fregalt(src);
425
      switch(dest.answhere.discrim){
426
	case inreg:{
427
	  /* source in floating point, dest in fixed */
428
	  int rdest = regalt(dest.answhere);
429
	  if(rdest != NO_REG){
430
	    freg fr=fregalt(src);
431
	    int r = regalt(dest.answhere);
432
	    baseoff mem_loc;
433
	    mem_loc.base = SP;
434
	    mem_loc.offset = stack_top;
435
	    float_load_store(i_stt,fr.fr,mem_loc);
436
	    load_store(i_ldq,r,mem_loc);
437
	  }
438
	  return NOREG;
439
	}
440
	case insomereg:{
441
	  somefreg sfr;
442
	  sfr = somefregalt(dest.answhere);
443
	  Assert(*(sfr.fr)== -1);
444
	  *(sfr.fr) = fr.fr;
445
	  return NOREG;
446
	}
447
	case insomefreg:{
448
	  /* simple - can choose destination freg */
449
	  somefreg sfr;
450
	  int res;
451
	  sfr = somefregalt(dest.answhere);
452
	  *(sfr.fr) = fregalt(src).fr;
453
	  fr.fr = *sfr.fr;
454
	  fr.type = sfr.type;
455
	  setfregalt(dest.answhere,fr);
456
	  res=move(src,dest,freeregs,sgned);
457
	  return res;		/* ?? */
458
	}
459
	case infreg:{
460
	  /* simple copy from one freg to another */
461
	  freg frd;
462
	  frd=fregalt(dest.answhere);
463
	  if(fr.fr != frd.fr){
464
	    float_op(i_cpys,fr.fr,fr.fr,frd.fr);
465
	  }	
466
	  return NOREG;
467
	}
468
	case notinreg:{
469
	  /* forget VAX floats for the moment */
470
	  /* src in float, dest in store */
471
	  instruction st=(fr.type==IEEE_double)?i_stt:i_sts;
472
	  instore is;
473
	  if(((dest.ashwhere.ashsize==64)&&(fr.type == IEEE_single)) 
474
	     || ((dest.ashwhere.ashsize==32) && (fr.type == IEEE_double))){
475
	    st = (dest.ashwhere.ashsize==64)?i_stt:i_sts;
476
	    if(dest.ashwhere.ashsize==32){
477
	      /* .t floats must be explicitly converted to .s */
478
	      freg frtmp;
479
	      frtmp.fr=getfreg(freeregs.flt);
480
	      frtmp.type = IEEE_single;
481
	      float_convert(i_cvtts,fr.fr,frtmp.fr);
482
	      fr=frtmp;
483
	    }
484
	  }
485
	  is = insalt(dest.answhere);
486
	  if(is.adval)
487
	    float_load_store(st,fr.fr,is.b);
488
	  else {
489
	    baseoff bo;
490
	    bo.base = getreg(freeregs.fixed);
491
	    bo.offset = 0;
492
	    load_store(i_ldq,bo.base,is.b);
493
	    float_load_store(st,fr.fr,bo);
494
	  }
495
	  return ((fr.type == IEEE_double)?-(fr.fr+32):(fr.fr+32));
496
	}
497
      }
498
      break;
499
    }
500
    case notinreg:{
501
      /* source instore */
502
      instore iss;
503
      instruction load;
504
      instruction store;
505
      iss=insalt(src);
506
      if(iss.adval && iss.b.offset==0 && iss.b.base>=0 && iss.b.base<31){
507
	setregalt(src,iss.b.base);
508
	return move(src,dest,freeregs,sgned); /* ?? */
509
      }	
510
      if((size==64)||(size%64==0)){
511
	load=(iss.adval)?i_lda:((aligned(iss.b,8))?i_ldq:i_ldq_u);
512
	load = (iss.adval)? i_lda:i_ldq;
513
	store=i_stq;
514
      }
515
      else{
516
	load = (iss.adval)?i_lda:((al==32)?i_ldl:i_ldq);
517
	store=(iss.adval)?i_stq:((al==32)?i_stl:i_stq);
518
      }
519
      switch(al){
520
	case 8:
521
	datatype = BYTE;
522
	break;
523
	case 16:
524
	datatype = WORD;
525
	break;
526
	case 32:
527
	datatype = LONGWORD;
528
	break;
529
	default:
530
	datatype = QUADWORD;
531
      }	
532
      switch(dest.answhere.discrim){
533
	case insomefreg:{
534
	  /* src in store, can choose freg for destination */
535
	  somefreg sfr;
536
	  freg fr;
537
	  sfr=somefregalt(dest.answhere);
538
	  if(*sfr.fr!=-1) failer("instore->some freg");
539
	  *sfr.fr=getfreg(freeregs.flt);
540
	  fr.fr=*sfr.fr;
541
	  fr.type=sfr.type;
542
	  setfregalt(dest.answhere,fr);
543
	  return move(src,dest,freeregs,sgned);
544
	}
545
	case insomereg:{
546
	  /* source instore, can choose destination register */
547
	  int *sr=someregalt(dest.answhere);
548
	  if(*sr!=-1) failer("somereg **");
549
	  *sr=getreg(freeregs.fixed);
550
	  setregalt(dest.answhere,*sr);
551
	  /* continue to next case */
552
	}
553
	FALL_THROUGH;
554
	case inreg:{
555
	  /* src instore, destination in general register */
556
	  int rdest=regalt(dest.answhere);
557
	  if(iss.b.base == rdest){
558
	    int newbase = getreg(guardreg(rdest,freeregs).fixed);
559
	    operate_fmt(i_bis,rdest,rdest,newbase);
560
	    iss.b.base = newbase;
561
	  }
562
	  if(rdest!=NO_REG){
563
	    if(((datatype == BYTE) || (datatype == WORD) 
564
	       ||((datatype == LONGWORD) && (iss.b.offset%4))
565
	       ||((datatype == QUADWORD) && (iss.b.offset%8)))
566
	       && !(iss.adval) ){
567
	      switch(datatype){
568
		case BYTE:{
569
		  space newspace=guardreg(rdest,freeregs);
570
		  int tmpreg;
571
		  newspace = guardreg(iss.b.base,newspace); /* error? */
572
		  tmpreg=getreg(newspace.fixed);
573
 
574
		  if(aligned_reg(iss.b.base,4) &&( iss.b.offset%4==0) &&
575
		     (iss.b.offset >= 0)){
576
		    /* if its address is 32 bit aligned an optimised 
577
		       load can be performed.  
578
		       (This doesn't win us much on the 21064).
579
		       */
580
		    baseoff newbo;
581
		    newbo.base=iss.b.base;
582
		    newbo.offset = (iss.b.offset/4)*4;
583
		    load_store(i_ldl,rdest,newbo);
584
		    if(sgned){
585
		      operate_fmt_immediate(i_sll,rdest,56-8*(iss.b.offset%4),
586
					    rdest);
587
		      operate_fmt_immediate(i_sra,rdest,56,rdest);
588
		    }
589
		    else{
590
		      operate_fmt_immediate(i_extbl,rdest,(iss.b.offset%4),rdest);
591
		    }
592
		  }
593
		  else{
594
		    load_store(i_ldq_u,rdest,iss.b); /* should it be iss.b ? */
595
		    if(sgned){
596
		      iss.b.offset++;
597
		      load_store(i_lda,tmpreg,iss.b);
598
		      operate_fmt(i_extqh,rdest,tmpreg,rdest);
599
		      operate_fmt_immediate(i_sra,rdest,56,rdest);
600
		    }
601
		    else{
602
		      load_store(i_lda,tmpreg,iss.b);
603
		      operate_fmt(i_extbl,rdest,tmpreg,rdest);
604
		    }
605
		  }
606
		  clear_reg(tmpreg);
607
		  break;
608
		}
609
		case WORD:{
610
#if 0
611
		  space msp = guardreg(rdest,freeregs);
612
		  int tmpreg1=getreg(msp.fixed);
613
		  int tmpreg2;
614
		  msp = guardreg(tmpreg1,msp);
615
		  tmpreg2=getreg(msp.fixed);
616
#endif
617
		  if(aligned_reg(iss.b.base,4) && (iss.b.offset>=0)){
618
		    /* if the base address is aligned on a 32 bit boundary
619
		       we can use an optimised load sequence.
620
		       */
621
		    baseoff alboff;
622
		    alboff.base = iss.b.base;
623
		    alboff.offset = (iss.b.offset/4)*4;
624
		    load_store(i_ldl,rdest,alboff);
625
		    if(sgned){
626
		      operate_fmt_immediate(i_sll,rdest,
627
					    48-8*(iss.b.offset%4),rdest);
628
		      operate_fmt_immediate(i_sra,rdest,48,rdest);
629
		    }
630
		    else{
631
		      operate_fmt_immediate(i_extwl,rdest,iss.b.offset%4,rdest);
632
		    }
633
		  }		
634
		  else{
635
		    setnoat();
636
		    iss.b.offset += 2;
637
		    load_store(i_lda,AT,iss.b);
638
		    iss.b.offset -= 2;
639
		    load_store(i_ldq_u,rdest,iss.b);
640
		    operate_fmt(i_extqh,rdest,AT,rdest);
641
		    operate_fmt_immediate(i_sra,rdest,48,rdest);
642
		    /* sgned ? */
643
		    if(!sgned) operate_fmt_immediate(i_zapnot,rdest,3,rdest);
644
		    setat();
645
		  }
646
		  /*
647
		  clear_reg(tmpreg1);
648
		  clear_reg(tmpreg2);
649
		  */
650
		  break;
651
		}
652
		case LONGWORD:{
653
		  int r2,r3;
654
		  space newspace = guardreg(rdest,freeregs);
655
		  /* treat unaligned longword access here */
656
		  newspace = guardreg(iss.b.base,newspace);
657
		  r2 = getreg(newspace.fixed);
658
		  r3 = getreg(newspace.fixed);
659
		  load_store(i_ldq_u,rdest,iss.b);
660
		  iss.b.offset += 3;
661
		  load_store(i_ldq_u,r2,iss.b);
662
		  iss.b.offset -= 3;
663
		  load_store(i_lda,r3,iss.b);
664
		  operate_fmt(i_extll,rdest,r3,rdest);
665
		  operate_fmt(i_extlh,r2,r3,r2);
666
		  operate_fmt(i_bis,r2,rdest,rdest);
667
		  if(sgned){
668
		    operate_fmt_immediate(i_sll,rdest,32,rdest);
669
		    operate_fmt_immediate(i_sra,rdest,32,rdest);
670
		  }
671
		  clear_reg(r2);
672
		  clear_reg(r3);
673
		  break;
674
		}
675
		case QUADWORD:{
676
		  int r2,r3;
677
		  space newspace = guardreg(rdest,freeregs);
678
		  newspace = guardreg(iss.b.base,newspace);
679
		  r2 = getreg(newspace.fixed);
680
		  r3 = getreg(newspace.fixed);
681
		  load_store(i_ldq_u,rdest,iss.b);
682
		  iss.b.offset += 7;
683
		  load_store(i_ldq_u,r2,iss.b);
684
		  iss.b.offset -= 7;
685
		  load_store(i_lda,r3,iss.b);
686
		  operate_fmt(i_extql,rdest,r3,rdest);
687
		  operate_fmt(i_extqh,r2,r3,r2);
688
		  operate_fmt(i_bis,r2,rdest,rdest);
689
		  clear_reg(r2);
690
		  clear_reg(r3);
691
		  break;
692
		}
693
	      }
694
	    }
695
	    else if (iss.adval){
696
	      load_store(i_lda,rdest,iss.b);
697
	      switch(datatype){
698
		case BYTE:
699
		operate_fmt_immediate(i_zapnot,rdest,1,rdest);
700
		break;
701
		case WORD:
702
		operate_fmt_immediate(i_zapnot,rdest,2,rdest);
703
		break;
704
		case LONGWORD:
705
		operate_fmt_immediate(i_addl,rdest,0,rdest);
706
		break;
707
		default:;
708
	      }
709
	    }
710
	    else{
711
	      int rt=getreg(guardreg(iss.b.base,freeregs).fixed);
712
	      if((size>64)&&((rdest<FIRST_INT_ARG)||(rdest>LAST_INT_ARG))){
713
		alphafail(ILLEGAL_BLOCK_COPY);
714
	      }
715
	      if(size>64){/* this should only occur with parameter regs */
716
		ans newsrc;
717
		where newdest;
718
		instore dis;
719
		if(al<64){
720
		  al=64;
721
		  load=i_ldq;
722
		}
723
		for(;(rdest<=LAST_INT_ARG)&&(size>0);++rdest,
724
		      iss.b.offset+=(al>>3)){
725
		  load_store(load,rdest,iss.b);	
726
		  size-=al;
727
		}
728
		/* once the registers have been filled, it's 
729
		   time to use the stack for the remaining parameters.  
730
		   The function calling move() must allow for 
731
		   this space to be used.*/
732
		if(size>0){
733
		  /*dis.b.base=(Has_fp)?FP:SP;*/
734
		  dis.b.base = SP;
735
		  dis.b.offset=0;
736
		  dis.adval=1;
737
		  setinsalt(newsrc,iss);
738
		  newdest.ashwhere.ashsize=size;
739
		  newdest.ashwhere.ashalign=64;
740
		  setinsalt(newdest.answhere,dis);
741
		  return move(newsrc,newdest,freeregs,sgned);
742
		}
743
		else{
744
		  return NOREG;
745
		}
746
	      }
747
	      else{
748
		load_store(load,rdest,iss.b);
749
	      }
750
	      if(ins_equal(load,i_lda) /*|| !sgned*/)
751
		switch(size){
752
		  case 8:
753
		  operate_fmt_immediate(i_and,rdest,0xff,rdest);
754
		  break;
755
		  case 16:
756
		  load_store_immediate(i_ldiq,rt,word_mask);
757
		  operate_fmt(i_and,rdest,rt,rdest);
758
		  break;
759
		  case 32:
760
		  operate_fmt_immediate(i_addl,rdest,0,rdest);
761
		  break;
762
		  default:;
763
		}
764
	    }			
765
	  }
766
	  return NOREG;
767
	}
768
	case infreg:{
769
	  /* src instore, dest in floating point reg */
770
	  freg frdest;
771
	  frdest=fregalt(dest.answhere);
772
	  switch(frdest.type){
773
	    case IEEE_single:
774
	    if(size==32){
775
	      float_load_store(i_lds,frdest.fr,iss.b);
776
	    }
777
	    else{
778
	      float_load_store(i_ldt,frdest.fr,iss.b);
779
	      float_convert(i_cvtts,frdest.fr,frdest.fr);
780
	    }
781
	    break;
782
	    case IEEE_double:   
783
	    if(size==32)
784
	      float_load_store(i_lds,frdest.fr,iss.b);
785
	    else
786
	      float_load_store(i_ldt,frdest.fr,iss.b);
787
	    break;
788
	    default:
789
	    failer("VAX floating point formats not supported");
790
	  }
791
	  return NOREG;
792
	}
793
	case notinreg:{
794
	  /* source and dest both instore */
795
	  instore isdest=insalt(dest.answhere);	  
796
	  int sunit = (size>64)?choose_block_size(dest,al):
797
	    ((dest.ashwhere.ashsize%64==0)?64:min(al,64));
798
	  /*int sunit= ((dest.ashwhere.ashsize%64==0)?64: min(al,64));*/
799
	  int step=sunit>>3;
800
	  int s=(dest.ashwhere.ashsize+sunit-1)/sunit;
801
	  bool unalign=0;
802
	  if(sunit>al) al=sunit;
803
	  if(al==8 && s>=8 && (aligned(isdest.b,8))){
804
	    int rtmp = getreg(freeregs.fixed);
805
	    unalign=1;
806
	    if(s<=32){
807
	      for(;s>=8;s -= 8){
808
		load_store(i_ldq,rtmp,iss.b);
809
		load_store(i_stq,rtmp,isdest.b);
810
		iss.b.offset += 8;
811
		isdest.b.offset += 8;
812
	      }
813
	      if(s){
814
		int rtmp2 = getreg(freeregs.fixed);
815
		load_store(i_ldq,rtmp,iss.b);
816
		load_store(i_ldq,rtmp2,isdest.b);
817
		operate_fmt_immediate(i_zap,rtmp2,unary(s),rtmp2);
818
		operate_fmt(i_bis,rtmp2,rtmp,rtmp2);
819
		load_store(i_stq,rtmp2,isdest.b);
820
	      }
821
 
822
	    }
823
	    else{
824
	      /* 
825
		 copy with loop, length in r1, to in2 from in r2 
826
		 if the data is aligned on 32/64 bit boundaries we can
827
		 do a fast copy. 
828
		 the code sequence produced is:
829
 
830
		 foreach complete 8 bytes of data
831
		   load/store quadword
832
		 foreach byte remaining
833
		   read bytes using ldq and zap 
834
		 */
835
	      int l=new_label();
836
	      int r1=getreg(freeregs.fixed | (1<<rtmp));
837
	      int r2=getreg(freeregs.fixed | (1<<rtmp)|(1<<r1));
838
	      int rd = getreg(freeregs.fixed|(1<<rtmp)|(1<<r1)|(1<<r2));
839
	      static baseoff src;
840
	      static baseoff dst;
841
	      int numberofquads;	/* number of quadwords in the data */
842
	      int numberofbytes;	/* number of remaining bytes */
843
	      load_store(i_lda,r1,iss.b);
844
	      numberofquads = size>>6;
845
	      load_store((isdest.adval)?i_lda:i_ldq,rd,isdest.b);
846
	      isdest.adval=1;
847
	      dst.base = rd;
848
	      dst.offset=0;
849
	      src.base = r1;
850
	      src.offset=0;	      
851
	      load_store_immediate(i_ldil,r2,numberofquads);
852
	      set_label(l);
853
	      operate_fmt_immediate(i_subq,r2,1,r2);
854
	      load_store(i_ldq,rtmp,src);
855
	      load_store(i_stq,rtmp,dst);
856
	      operate_fmt_immediate(i_addq,r1,8,r1);
857
	      operate_fmt_immediate(i_addq,rd,8,rd);
858
	      /*	     
859
			     dst.offset+=(8*numberofquads);
860
			     src.offset+=(8*numberofquads);
861
			     */
862
	      integer_branch(i_bne,r2,l);
863
	      /* now only single bytes remain */
864
	      numberofbytes = (size - (numberofquads<<6))>>3;
865
	      if(numberofbytes){
866
		/* we have trailing bytes. */
867
		load_store(i_ldq,r1,src);
868
		load_store(i_ldq,r2,dst);
869
		operate_fmt_immediate(i_zap,r2,unary(numberofbytes),r2);
870
		operate_fmt(i_bis,r2,r1,r2);
871
		load_store(i_stq,r2,dst);
872
	      }
873
	    }
874
	    return NOREG;
875
	  }
876
	  if(s<=inlineassign){
877
	    int r=getreg(freeregs.fixed);
878
	    if(!isdest.adval){
879
	      int rtmp = getreg(freeregs.fixed);
880
	      load_store(i_ldq,rtmp,isdest.b);/* fix: was load not i_ldq */
881
	      isdest.b.base=rtmp;
882
	      isdest.b.offset=0;
883
	      isdest.adval=1;		/* added (is this correct?) */
884
	    }
885
	    if(s==1){
886
	      ans newsrc;
887
	      where newdest;
888
	      setinsalt(newsrc,iss);
889
	      setregalt(newdest.answhere,r);
890
	      newdest.ashwhere.ashsize=size;
891
	      newdest.ashwhere.ashalign=al;
892
	      (void)move(newsrc,newdest,freeregs,sgned);
893
	      setregalt(newsrc,r);
894
	      setinsalt(newdest.answhere,isdest);
895
	      newdest.ashwhere.ashsize=size;
896
	      newdest.ashwhere.ashalign=al;
897
	      (void)move(newsrc,newdest,freeregs,sgned);
898
	      return (unalign)?NOREG:r;
899
	    }
900
	    else{
901
	      int er = getreg(freeregs.fixed|(1<<r));
902
	      int nr=r;
903
	      if(!address_equal(iss,isdest)){
904
		for(;s>0;--s){
905
		  ans newsrc;
906
		  where newdest;
907
		  setinsalt(newsrc,iss);
908
		  setregalt(newdest.answhere,r);
909
		  newdest.ashwhere.ashsize=sunit;	/* in 64 byte chunks */
910
		  newdest.ashwhere.ashalign=sunit;
911
		  /* put value into register r */
912
		  (void)move(newsrc,newdest,freeregs,sgned); 
913
		  setregalt(newsrc,r);
914
		  setinsalt(newdest.answhere,isdest);
915
		  (void)move(newsrc,newdest,freeregs,sgned);
916
		  /*load_store(load,nr,iss.b);
917
		    load_store(store,nr,isdest.b);*/
918
		  iss.b.offset += step;
919
		  isdest.b.offset += step;
920
		  if(nr == r){
921
		    nr = er;
922
		  }
923
		  else{
924
		    nr = r;
925
		  }
926
		}
927
	      }
928
	      return NOREG;
929
	    }
930
	  }	
931
	  else{
932
	    int a = getreg(freeregs.fixed);
933
	    int	address_reg = getreg(freeregs.fixed);
934
	    int rtmp = getreg(freeregs.fixed);
935
	    int l=new_label();
936
	    int r1=getreg(freeregs.fixed);
937
	    static baseoff src;
938
	    static baseoff dst;
939
	    INT64 loop_count;
940
	    src.base = address_reg;
941
	    src.offset = 0;
942
	    dst.base = rtmp;
943
	    dst.offset=0;
944
	    load_store((isdest.adval)?i_lda:i_ldq,rtmp,isdest.b);
945
	    load_store(i_lda,address_reg,iss.b);
946
	    loop_count=make_INT64((s&0x80000000)?0xffffffff:0,s);
947
	    load_store_immediate(i_ldiq,r1,loop_count);	/* loop counter */
948
	    set_label(l);
949
	    load_store(load,a,src);
950
	    operate_fmt_immediate(i_addq,address_reg,step,address_reg);
951
	    load_store(store,a,dst);
952
	    operate_fmt_immediate(i_addq,rtmp,step,rtmp);
953
	    operate_fmt_immediate(i_subq,r1,1,r1);
954
	    integer_branch(i_bgt,r1,l);
955
	    return NOREG;
956
	  }
957
	}
958
      }
959
    }
960
  }
961
  return NOREG;
962
}
963
 
964
 
965
 
966