Subversion Repositories tendra.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
7 7u83 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
 */
31
/*
2 7u83 32
    Copyright (c) 1993 Open Software Foundation, Inc.
33
 
34
 
35
    All Rights Reserved
36
 
37
 
38
    Permission to use, copy, modify, and distribute this software
39
    and its documentation for any purpose and without fee is hereby
40
    granted, provided that the above copyright notice appears in all
41
    copies and that both the copyright notice and this permission
42
    notice appear in supporting documentation.
43
 
44
 
45
    OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING
46
    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
47
    PARTICULAR PURPOSE.
48
 
49
 
50
    IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
51
    CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
52
    LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
53
    NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
54
    WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
55
*/
56
 
57
/*
58
    		 Crown Copyright (c) 1997
7 7u83 59
 
2 7u83 60
    This TenDRA(r) Computer Program is subject to Copyright
61
    owned by the United Kingdom Secretary of State for Defence
62
    acting through the Defence Evaluation and Research Agency
63
    (DERA).  It is made available to Recipients with a
64
    royalty-free licence for its use, reproduction, transfer
65
    to other parties and amendment for any purpose not excluding
66
    product development provided that any such use et cetera
67
    shall be deemed to be acceptance of the following conditions:-
7 7u83 68
 
2 7u83 69
        (1) Its Recipients shall ensure that this Notice is
70
        reproduced upon any copies or amended versions of it;
7 7u83 71
 
2 7u83 72
        (2) Any amended version of it shall be clearly marked to
73
        show both the nature of and the organisation responsible
74
        for the relevant amendment or amendments;
7 7u83 75
 
2 7u83 76
        (3) Its onward transfer from a recipient to another
77
        party shall be deemed to be that party's acceptance of
78
        these conditions;
7 7u83 79
 
2 7u83 80
        (4) DERA gives no warranty or assurance as to its
81
        quality or suitability for any purpose and DERA accepts
82
        no liability whatsoever in relation to any use to which
83
        it may be put.
84
*/
85
 
86
 
87
 
88
/**********************************************************************
89
$Author: release $
90
$Date: 1998/02/04 15:48:56 $
91
$Revision: 1.2 $
92
$Log: makecode.c,v $
93
 * Revision 1.2  1998/02/04  15:48:56  release
94
 * Added OSF copyright message.
95
 *
96
 * Revision 1.1.1.1  1998/01/17  15:55:57  release
97
 * First version to be checked into rolling release.
98
 *
99
 * Revision 1.5  1996/11/18  15:50:18  pwe
100
 * correct alias with bitfields, and case odds
101
 *
102
 * Revision 1.4  1996/10/15  15:59:19  pwe
103
 * local_alloc_check with unused result
104
 *
105
 * Revision 1.3  1996/10/14  17:31:51  pwe
106
 * include called callees in env_size
107
 *
108
 * Revision 1.2  1996/10/04  16:02:16  pwe
109
 * add banners and mod for PWE ownership
110
 *
111
**********************************************************************/
112
 
113
 
114
#include "config.h"
115
#include "memtdf.h"
116
#include "codegen.h"
117
#include "geninst.h"
118
 
119
#include "myassert.h"
120
#include "maxminmacs.h"
121
#include "comment.h"
122
#include "muldvrem.h"
123
#include "proc.h"
124
#include "flags.h"
125
#include "translat.h"
126
#include "eval.h"
127
 
128
#include "makecode.h"
129
#include "frames.h"
130
#include "stack.h"
131
#include "label_ops.h"
132
#include "instruct.h"
133
#include "installglob.h"
134
#include "externs.h"
135
#include "tempdecs.h"
136
#include "diag_fns.h"
137
#include "oprators.h"
138
#include "record_bit.h"
139
#include "mask.h"
140
#include "error.h"
141
#include "f64.h"
142
#ifdef DEBUG_POWERTRANS
143
#include "pp.h"
144
#endif
145
bool cr0_set;
146
 
147
where nowhere;	/* no particular destination, init in translat.c */
148
 
149
/* Function declarations */
150
void move_dlts PROTO_S ((int,int,int,int));/* Used by movecont_tag */
151
void move_dgts PROTO_S ((int,int,int,int));/* Used by movecont_tag */
7 7u83 152
int regfrmdest(where *,space);
153
freg fregfrmdest(bool,where *,space);
2 7u83 154
 
7 7u83 155
static int get_next_mlv_number(void);
156
void adjust_to_size(int,int,int,int,int);
2 7u83 157
 
158
 
159
 
160
/* branch table, branch code to instruction */
161
 
162
 
163
static Instruction_P branch_tab[] ={
164
  &INSTRUCTION_I_NIL,  /* not used */
165
  &INSTRUCTION_i_ble,  /* 1 */
166
  &INSTRUCTION_i_blt,  /* 2 */
167
  &INSTRUCTION_i_bge,  /* 3 */
168
  &INSTRUCTION_i_bgt,  /* 4 */
169
  &INSTRUCTION_i_bne,  /* 5 */
170
  &INSTRUCTION_i_beq   /* 6 */
171
};
172
 
173
 
174
#define branches(i)	(branch_tab[i])
175
 
176
 
177
						    /*  1  2  3  4  5  6 */
178
/* used to invert TDF tests */			    /* le lt ge gt ne eq */
7 7u83 179
prop notbranch[] =
2 7u83 180
{
181
  0,				/* NOT USED */
182
  4,				/* opposite of le is gt */
183
  3,				/* opposite of lt is ge */
184
  2,				/* opposite of ge is lt */
185
  1,				/* opposite of gt is le */
186
  6,				/* opposite of ne is eq */
187
  5				/* opposite of eq is ne */
188
};
189
						    /*  1  2  3  4  5  6 */
190
/* used to change TDF test when args commuted */    /* le lt ge gt ne eq */
7 7u83 191
prop combranch[] =
192
{
2 7u83 193
  0,				/* NOT USED */
194
  3,				/* reverse of le is ge */
195
  4,				/* reverse of lt is gt */
196
  1,				/* reverse of ge is le */
197
  2,				/* reverse of gt is lt */
198
  5,				/* reverse of ne is ne */
199
  6				/* reverse of eq is eq */
200
};
201
 
202
 
7 7u83 203
static void testsigned(int r, long lower, long upper, long lab)
2 7u83 204
{
205
  int creg1=next_creg();
206
  int creg2=next_creg();
207
  cmp_ri_ins(i_cmp,r,lower,creg1);
208
  bc_ins(i_blt,creg1,lab,UNLIKELY_TO_JUMP);
209
  cmp_ri_ins(i_cmp,r,upper,creg2);
210
  bc_ins(i_bgt,creg2,lab,UNLIKELY_TO_JUMP);
211
  return;
212
}
7 7u83 213
static void testusigned(int r, long maxval, long lab)
2 7u83 214
{
215
  int creg=next_creg();
216
  cmp_ri_ins(i_cmpl,r,maxval,creg);
217
  bc_ins(i_bgt,creg,lab,UNLIKELY_TO_JUMP);
218
  return;
219
}
220
 
221
 
222
/* find the last test in sequence e which is a branch to second, if any, otherwise nil */
7 7u83 223
static exp testlast(exp e, exp second)
2 7u83 224
{
225
  if (name(e) == test_tag && pt(e) == second)
226
  {
7 7u83 227
    return(e);
2 7u83 228
  }
229
  if (name(e) == seq_tag)
230
  {
7 7u83 231
 
2 7u83 232
    if (name(bro(son(e))) == test_tag && pt(bro(son(e))) == second)
233
    {
234
      /* is the last one of the sequence a test_tag pointing to second */
235
      return bro(son(e));
236
    }
237
    else if (name(bro(son(e))) == top_tag)
238
    {
239
      exp list = son(son(e));
240
      /* find the penultimate exp of the seq_tag */
241
      for (;;)
242
      {
243
	if (last(list))
244
	{
245
	  if (name(list) == test_tag && pt(list) == second)
246
	  {
247
	    return list;
248
	  }
249
	  else
250
	  {
251
	    return 0;
252
	  }
253
	}
254
	else
255
	{
256
	  list = bro(list);
257
	}
258
      }
259
    }
260
  }
261
  return 0;
262
}
263
 
264
 
265
 
266
/* Does e, or components of e contain a bitfield? */
267
/* +++ should detect this earlier and record in props(e) once-and-for-all */
7 7u83 268
static int has_bitfield(exp e)
2 7u83 269
{
270
  if (e == nilexp)
271
    return 0;
272
 
273
  switch (name(e))
274
  {
275
  case compound_tag:
276
    {
277
 
278
      /*
279
       * (compound_tag <offset> <initialiser> ... )
280
       */
281
      /* look at alignment of initialisers */
282
      e = bro(son(e));
283
      while (1)
284
      {
285
	if (has_bitfield(e))
286
	  return 1;		/* found bitfield */
287
 
288
	if (last(e))
289
	  return 0;		/* all done, no bitfield */
290
 
291
	e = bro(bro(e));	/* try next initialiser */
292
      }
293
      /*NOTREACHED*/
294
  default:
295
      {
296
	shape s = sh(e);
297
 
298
	FULLCOMMENT4("has_bitfield: compound field sz=%d als=%d,%d,%d",
299
		shape_size(s), shape_align(s), al1(s), al2(s));
7 7u83 300
	return shape_size(s)!= 0 && (shape_align(s) == 1 || al1(s) == 1 || al2(s) == 1);
2 7u83 301
      }
302
    }
303
  }
304
  /*NOTREACHED*/
305
}
306
 
307
 
308
/* Convert all NON-bitfields from byte-offsets back to bit-offsets, so
309
 * the compound can be output correctly by eval().
310
 * Permanently undoes the needscan.c:scan() case val_tag:.
311
 *
312
 * NB must do this EXACTLY ONCE.
313
 */
7 7u83 314
static void fix_nonbitfield(exp e)
2 7u83 315
{
316
  if (name(e) == compound_tag)
317
  {
318
    e = son(e);
319
    while (1)
320
    {
321
      if (name(e) == val_tag && name(sh(e)) == offsethd && al2(sh(e)) >= 8)
322
	  no(e) = no(e) << 3;	/* fix it */
7 7u83 323
 
2 7u83 324
      fix_nonbitfield(bro(e));	/* recursively fix the rest of the struct */
7 7u83 325
 
2 7u83 326
      if (last(bro(e)))
327
	  return;		/* all done */
7 7u83 328
 
2 7u83 329
      e = bro(bro(e));		/* next offset */
330
    }
331
  }
332
  /*NOTREACHED*/
333
}
334
 
335
 
336
 
337
/*
338
 * Some functions to build and maintain a queue of conditional branch
339
 * instuctions, so the generation of these instructions can be delayed.
340
 * This is so the compare instruction will not immediately follow
341
 * compare, thus reducing RS/6000 compare..branch delays.
342
 * No side effecting instructions should be emitted while
343
 * branches are queued.  Currently only used with case_tag.
344
 */
345
 
346
/* params of bc_ins() */
347
typedef struct
348
{
7 7u83 349
  Instruction_P branch;
2 7u83 350
  int	creg;
351
  int	lab;
352
} bc_info;
353
 
354
 
355
 
356
#define	NQUEUE			3	/* any number < nmumber
357
					 * next_creg() manages (0,1,6,7) */
358
#if !do_case_transforms
359
static bc_info bqueue[NQUEUE];
360
 
361
static int bqueuepos;		/* next free slot in queue */
362
 
363
 
7 7u83 364
static void clear_branch_queue(void)
2 7u83 365
{
366
  int i;
367
 
368
  bqueuepos = 0;
369
 
370
  for (i = 0; i < NQUEUE; i++)
371
  {
372
    bqueue[i].branch = I_NIL;
373
    bqueue[i].creg = -1;
374
  }
375
}
376
 
377
 
7 7u83 378
static void issue_bc_ins(int i)
2 7u83 379
{
380
  ASSERT(i >= 0 && i < NQUEUE);
381
  bc_ins(bqueue[i].branch, bqueue[i].creg, bqueue[i].lab,LIKELY_TO_JUMP);
382
}
383
 
384
 
7 7u83 385
static void queue_bc_ins(Instruction_P ins, int creg, int lab)
2 7u83 386
{
387
  int i;
388
 
7 7u83 389
  COMMENT2("queue_bc_ins(%s,%d,lab)",(int)ins, creg);
2 7u83 390
 
391
#ifdef DO_ASSERT
392
  /* check there is not a queued instruction using same creg (now corrupted) */
393
  for (i = 0; i < NQUEUE; i++)
394
    ASSERT(bqueue[i].creg != creg);
395
#endif
396
 
397
  i = bqueuepos;
398
 
399
  ASSERT(i >= 0 && i < NQUEUE);
400
 
401
  /* if queue full, clear one entry */
402
  if (bqueue[i].branch != I_NIL)
403
    issue_bc_ins(i);
404
 
405
  bqueue[i].branch = ins;
406
  bqueue[i].creg = creg;
407
  bqueue[i].lab = lab;
408
 
409
  bqueuepos++;
410
  if (bqueuepos == NQUEUE)
411
    bqueuepos = 0;		/* roll around to zero */
412
}
413
 
7 7u83 414
static void flush_branch_queue(void)
2 7u83 415
{
416
  int i;
417
 
418
  i = bqueuepos;
419
 
420
  do
421
  {
422
    if (bqueue[i].branch != I_NIL)
423
      issue_bc_ins(i);
424
 
425
    i++;
426
    if (i == NQUEUE)
427
      i = 0;			/* roll around to zero */
428
  } while (i != bqueuepos);
429
 
430
  clear_branch_queue();
431
}
432
#endif
433
 
434
#if do_case_transforms
7 7u83 435
static void case_tag_code(int caseint_reg, exp e, space sp)
2 7u83 436
{
437
 
438
  long u;
439
  long l;
440
  long n;
441
  exp z=bro(son(e));
442
  exp zt=z;
443
  int endlab = new_label();	/* +++ often another jump at endlab */
444
  int veclab = next_data_lab();
445
  char *veclabname;
446
  baseoff zeroveclab;
447
  int mr = getreg(sp.fixed);	/* no need to guardreg(caseint_reg) as mr not
448
				 * used until after lase use of caseint_reg */
7 7u83 449
 
2 7u83 450
  l=no(zt);
7 7u83 451
  while (bro(zt)!=nilexp)
2 7u83 452
  {
453
    zt=bro(zt);
454
  }
7 7u83 455
  u = (son(zt) ==nilexp)? no(zt): no(son(zt));
2 7u83 456
 
7 7u83 457
 
2 7u83 458
  zeroveclab.offset = 0;
459
  zeroveclab.base = veclab;
7 7u83 460
 
2 7u83 461
  if (l >= 0 && l <= 4)
462
  {
463
    /* between 0 and 4 dummy table entries used to avoid subtract */
464
    rir_ins(i_sl, caseint_reg, 2, mr);
465
    n = 0;
466
  }
467
  else
468
  {
469
    /* subtract to index jump vector */
470
    rir_ins(i_a, caseint_reg,-l, mr);
471
    rir_ins(i_sl, mr, 2, mr);
472
    n = l;
473
  }
474
  /* delayed branch */
475
  set_ins(zeroveclab, R_TMP0);
476
  ld_rr_ins(i_l, mr, R_TMP0, mr);
477
  rrr_ins(i_a, mr, R_TMP0, mr);
478
  mt_ins(i_mtctr, mr);
479
  z_ins(i_bctr);
480
 
481
  /* .toc entry for veclab */
482
  fprintf(as_file, "\t.toc\n");
483
  veclabname = ext_name(veclab);
484
  fprintf(as_file, "T.%s:\t.tc\t%s[TC],%s\n", veclabname, veclabname, veclabname);
485
  fprintf(as_file, "\t.csect\t[PR]\n");
7 7u83 486
 
2 7u83 487
  /* build the jump vector, can be to .text or .data */
488
  fprintf(as_file, "%s:\n", veclabname);
489
  for (;;)
490
  {
7 7u83 491
    for (; no(z)!= n; n++)
2 7u83 492
    {
493
      fprintf(as_file, "\t.long\tL.%d-%s\n", endlab, veclabname);
494
    }
7 7u83 495
    u = (son(z) == nilexp)? n : no(son(z));
2 7u83 496
    for (; u+1 != n; n++)	/* comparison independent of sign */
497
    {
498
	fprintf(as_file, "\t.long\tL.%d-%s\n", no(son(pt(z))), veclabname);
499
      }
500
    if (last(z))
501
    {
502
      break;
503
    }
504
    z = bro(z);
505
  }
506
  set_label(endlab);
507
  return;
508
}
509
 
510
 
7 7u83 511
 
2 7u83 512
#else
7 7u83 513
static void case_tag_code(int caseint_reg, exp e, space sp)
2 7u83 514
{
515
  mm lims;
516
  exp z = bro(son(e));
517
  exp zt = z;
518
  long n;
519
  long l;
520
  long u = 0x80000000;
521
  unsigned long approx_range;	/* max(u-l, 0x7fffffff) avoiding overflow */
522
  bool use_jump_vector;
523
 
524
  ASSERT(name(e) == case_tag);
525
 
526
  /* calculate crude criterion for using jump vector or branches */
527
  l = no(zt);
528
  for (n = 1;; n++)
529
  {
7 7u83 530
    if (u + 1 != no(zt) && son(zt)!= nilexp)
2 7u83 531
    {
532
      n++;
533
    }
534
    if (last(zt))
535
    {
7 7u83 536
      u = (son(zt)!= nilexp)? no(son(zt)): no(zt);
2 7u83 537
      break;
538
    }
7 7u83 539
    if (son(zt)!= nilexp)
2 7u83 540
    {
541
      u = no(son(zt));
542
    }
543
    else
544
    {
545
      if (u + 1 == no(zt))
546
	u += 1;
547
    }
548
 
549
    zt = bro(zt);
550
  }
551
 
552
 
553
  /* now l is lowest controlling value, u is highest and n is number of cases */
554
 
555
  if (u - l < 0)
556
    approx_range = 0x7fffffff;	/* u-l overflowed into -ve, use huge */
557
  else
7 7u83 558
    approx_range = (unsigned long)(u - l);
2 7u83 559
 
560
  if (approx_range < 16)
561
  {
562
    /* small jump vector needed, decide on instuctions executed only */
563
#define	MTCR_B_DELAY		4	/* fixed point mtctr..bctr delay */
564
#define	BR_TAKEN_DELAY		3	/* fixed point branch taken delay */
7 7u83 565
    unsigned jump_vector_cnt = ((l >= 0 && l <= 4)? 8 + MTCR_B_DELAY : 9 + MTCR_B_DELAY);
2 7u83 566
 
567
    unsigned cmp_jmp_step_cnt = 2 + (!IMM_SIZE(l)) + (!IMM_SIZE(u));
568
 
569
    /* cmp & jmp, delay slot filled plus possibly load of large consts */
570
    /* +++ assume default used as often as case, is this good ??? */
571
    unsigned default_weight = 1;/* likelyhood of default against single case */
572
    unsigned total_case_test_chain_cnt =
7 7u83 573
	((((n + 1)* cmp_jmp_step_cnt)* n) / 2) + BR_TAKEN_DELAY;
2 7u83 574
    unsigned default_test_chain_cnt =
575
	(n * cmp_jmp_step_cnt);
576
    unsigned average_test_chain_cnt =
577
	(total_case_test_chain_cnt + (default_test_chain_cnt * default_weight)) / (n + default_weight);
578
 
579
    use_jump_vector = jump_vector_cnt <= average_test_chain_cnt;
580
    FULLCOMMENT2("case_tag small jump vector: jump_vector_cnt=%d average_test_chain_cnt=%d",
581
		 jump_vector_cnt, average_test_chain_cnt);
582
  }
583
  else
584
  {
585
 
586
    /*
587
     * space-time product criterion for jump vector instead of tests and
588
     * branches
589
     */
590
    unsigned long range_factor = approx_range + 9;
7 7u83 591
    unsigned long n_factor = ((unsigned long)n * n) / 2;
2 7u83 592
 
593
    use_jump_vector = range_factor <= n_factor;
594
  }
595
 
596
  COMMENT4("case_tag: n=%d l,u=%d,%d approx_range=%d", n, l, u, approx_range);
597
  if (is_signed(sh(son(e)))) {
7 7u83 598
    ASSERT(l <= u);
2 7u83 599
  } else {
7 7u83 600
    ASSERT((unsigned long)l <= (unsigned long)u);
2 7u83 601
  }
602
  ASSERT(n >= 0);
603
 
604
  if (use_jump_vector)
605
  {
606
    /* use jump vector */
607
    int endlab = new_label();	/* +++ often another jump at endlab */
608
    int veclab = next_data_lab();
609
    char *veclabname;
610
    baseoff zeroveclab;
611
    int creg = next_creg();
612
    int mr = getreg(sp.fixed);	/* no need to guardreg(caseint_reg) as mr not
613
				 * used until after lase use of caseint_reg */
614
 
615
    zeroveclab.offset = 0;
616
    zeroveclab.base = veclab;
617
 
618
    if (l >= 0 && l <= 4)
619
    {
620
      /* between 0 and 4 dummy table entries used to avoid subtract */
621
      cmp_ri_ins(i_cmpl, caseint_reg, u + 1, creg);
622
      /* branch later, to reduce compare..barnch delay */
623
      rir_ins(i_sl, caseint_reg, 2, mr);
624
      n = 0;
625
    }
626
    else
627
    {
628
      /* subtract to index jump vector */
629
      rir_ins(i_a, caseint_reg,-l, mr);
630
      cmp_ri_ins(i_cmpl, mr, u - l + 1, creg);
631
      /* branch later, to reduce compare..branch taken delay */
632
      rir_ins(i_sl, mr, 2, mr);
633
      n = l;
634
    }
635
 
636
    /* delayed branch */
637
    bc_ins(i_bge, creg, endlab,UNLIKELY_TO_JUMP);
638
 
639
    set_ins(zeroveclab, R_TMP0);
640
 
641
    ld_rr_ins(i_l, mr, R_TMP0, mr);
642
    rrr_ins(i_a, mr, R_TMP0, mr);
643
 
644
    mt_ins(i_mtctr, mr);
645
    z_ins(i_bctr);
646
 
647
    /* .toc entry for veclab */
648
    fprintf(as_file, "\t.toc\n");
649
    veclabname = ext_name(veclab);
650
    fprintf(as_file, "T.%s:\t.tc\t%s[TC],%s\n", veclabname, veclabname, veclabname);
651
    fprintf(as_file, "\t.csect\t[PR]\n");
652
 
653
    /* build the jump vector, can be to .text or .data */
654
    fprintf(as_file, "%s:\n", veclabname);
655
    for (;;)
656
    {
7 7u83 657
      for (; no(z)!= n; n++)
2 7u83 658
      {
659
	fprintf(as_file, "\t.long\tL.%d-%s\n", endlab, veclabname);
660
      }
7 7u83 661
      u = (son(z) == nilexp)? n : no(son(z));
2 7u83 662
      for (; u+1 != n; n++)
663
      {
664
	fprintf(as_file, "\t.long\tL.%d-%s\n", no(son(pt(z))), veclabname);
665
      }
666
      if (last(z))
667
	break;
668
      z = bro(z);
669
    }
670
 
671
    set_label(endlab);
672
    return;
673
  }
674
  else
675
  if (is_signed(sh(son(e)))) {
676
    /* use branches - tests are ordered */
677
    int endlab = 0;
678
    lims = maxmin(sh(son(e)));
679
    clear_branch_queue();
680
 
681
    for (;;)
682
    {
683
      int lab = no(son(pt(z)));
684
      int creg = next_creg();
685
 
686
      long l = no(z);
687
      if (son(z) == nilexp)
688
      {
689
	/* only single test required */
690
	cmp_ri_ins(i_cmp, caseint_reg, l, creg);
691
	queue_bc_ins(i_beq, creg, lab);
692
	if (l == lims.maxi)
693
	  lims.maxi -= 1;
694
	else if (l == lims.mini)
695
	  lims.mini += 1;
696
      }
697
      else if (u = no(son(z)), l > lims.mini)
698
      {
699
	if (u >= lims.maxi)
700
	{
701
	  /* have already tested lower */
702
	  cmp_ri_ins(i_cmp, caseint_reg, l, creg);
703
	  queue_bc_ins(i_bge, creg, lab);
704
	  lims.maxi = l - 1;
705
	}
706
	else
707
	{
708
	  int creg2;
709
 
710
	  if (endlab == 0)
711
	    endlab = new_label();
712
 
713
	  cmp_ri_ins(i_cmp, caseint_reg, l, creg);
714
	  queue_bc_ins(i_blt, creg, endlab);
715
 
716
	  /*
717
	   * Note, must queue first bc_ins before second cmp_ins,
718
	   * which may use a creg already in the queue.
719
	   */
720
	  creg2 = next_creg();
721
	  cmp_ri_ins(i_cmp, caseint_reg, u, creg2);
722
	  queue_bc_ins(i_ble, creg2, lab);
723
 
724
	  lims.mini = u + 1;
725
	}
726
      }
727
      else if (u < lims.maxi)
728
      {
729
	/* lower is <= lower limit of shape */
730
	cmp_ri_ins(i_cmp, caseint_reg, u, creg);
731
	queue_bc_ins(i_ble, creg, lab);
732
	lims.mini = u + 1;
733
      }
734
      else
735
      {
736
	/* upper is >= upper limit of shape */
737
	flush_branch_queue();
738
	uncond_ins(i_b, lab);
739
      }
740
      if (last(z))
741
      {
742
	flush_branch_queue();
743
	if (endlab != 0)
744
	{
745
	  set_label(endlab);
746
	}
747
	return;
748
      }
749
      z = bro(z);
750
    }
751
  }
752
  else {
753
    /* unsigned, use branches - tests are ordered */
754
    int endlab = 0;
755
    unsigned long maxi;
756
    unsigned long mini;
757
    lims = maxmin(sh(son(e)));
758
    maxi = (unsigned)lims.maxi;
759
    mini = (unsigned)lims.mini;
760
    clear_branch_queue();
761
 
762
    for (;;)
763
    {
764
      int lab = no(son(pt(z)));
765
      int creg = next_creg();
766
 
767
      unsigned long l = no(z);
768
      if (son(z) == nilexp)
769
      {
770
	/* only single test required */
771
	cmp_ri_ins(i_cmpl, caseint_reg, l, creg);
772
	queue_bc_ins(i_beq, creg, lab);
773
	if (l == maxi)
774
	  maxi -= 1;
775
	else if (l == mini)
776
	  mini += 1;
777
      }
778
      else if (u = no(son(z)), l > mini)
779
      {
780
	if (u >= maxi)
781
	{
782
	  /* have already tested lower */
783
	  cmp_ri_ins(i_cmpl, caseint_reg, l, creg);
784
	  queue_bc_ins(i_bge, creg, lab);
785
	  maxi = l - 1;
786
	}
787
	else
788
	{
789
	  int creg2;
790
 
791
	  if (endlab == 0)
792
	    endlab = new_label();
793
 
794
	  cmp_ri_ins(i_cmpl, caseint_reg, l, creg);
795
	  queue_bc_ins(i_blt, creg, endlab);
796
 
797
	  /*
798
	   * Note, must queue first bc_ins before second cmp_ins,
799
	   * which may use a creg already in the queue.
800
	   */
801
	  creg2 = next_creg();
802
	  cmp_ri_ins(i_cmpl, caseint_reg, u, creg2);
803
	  queue_bc_ins(i_ble, creg2, lab);
804
 
805
	  mini = u + 1;
806
	}
807
      }
808
      else if (u < maxi)
809
      {
810
	/* lower is <= lower limit of shape */
811
	cmp_ri_ins(i_cmpl, caseint_reg, u, creg);
812
	queue_bc_ins(i_ble, creg, lab);
813
	mini = u + 1;
814
      }
815
      else
816
      {
817
	/* upper is >= upper limit of shape */
818
	flush_branch_queue();
819
	uncond_ins(i_b, lab);
820
      }
821
      if (last(z))
822
      {
823
	flush_branch_queue();
824
	if (endlab != 0)
825
	{
826
	  set_label(endlab);
827
	}
828
	return;
829
      }
830
      z = bro(z);
831
    }
832
  }
833
}
834
#endif
835
 
836
/*
837
 * Evaluate and generate the compare instruction for a test_tag,
838
 * and return a bcinfo describing the conditional branch required.
839
 */
7 7u83 840
static bc_info make_test_tag_cmp(exp e, space sp)
2 7u83 841
{
842
  exp l = son(e);
843
  exp r = bro(l);
844
  shape shl = sh(l);
845
  bc_info bcinfo;
846
 
7 7u83 847
  bcinfo.lab = (ptno(e) < 0)? -ptno(e): no(son(pt(e)));
2 7u83 848
					/* see frig in cond_tag */
849
  /* generate compare */
850
  if (is_floating(name(sh(l))))
851
  {
852
    /* float test */
853
    int a1;
854
    int a2;
855
    space nsp;
856
 
857
    if (IsRev(e))
858
    {
859
      a2 = freg_operand(r, sp, getfreg(sp.flt));
860
      nsp = guardfreg(a2, sp);
861
      a1 = freg_operand(l, nsp, getfreg(nsp.flt));
862
    }
863
    else
864
    {
865
      a1 = freg_operand(l, sp, getfreg(sp.flt));
866
      nsp = guardfreg(a1, sp);
867
      a2 = freg_operand(r, nsp, getfreg(nsp.flt));
868
    }
869
 
870
    bcinfo.creg = next_creg();
871
    rrf_cmp_ins(i_fcmpo, a1, a2, bcinfo.creg);
872
  }
873
  else
874
  {
875
    /* int test */
876
    bool sgned = is_signed(shl);
877
    int a1;
878
    int a2;
879
    Instruction_P cmp;
7 7u83 880
 
2 7u83 881
    cmp = sgned ? i_cmp : i_cmpl;
7 7u83 882
 
2 7u83 883
    cr0_set = 0;
884
    /* cr0_set is needed since l could be tracked by reg tracking and there
885
       fore not coded. In this case cr0_set should remain 0 */
886
    a1 = reg_operand(l, sp);
887
    if (record_bit_set(l) && cr0_set==1)
888
    {
889
      bcinfo.creg = 0;
890
      /* no need to generate the compare */
891
    }
892
    else
893
    {
894
      if (name(r) == val_tag)
895
      {
896
	bcinfo.creg = next_creg();
897
	cmp_ri_ins(cmp, a1, no(r), bcinfo.creg);
898
      }
899
      else
900
      {
901
	space nsp;
902
	nsp = guardreg(a1, sp);
903
	a2 = reg_operand(r, nsp);
904
	bcinfo.creg = next_creg();
905
	cmp_rr_ins(cmp, a1, a2, bcinfo.creg);
906
      }
907
    }
908
  }
909
  cr0_set = 0;
910
  bcinfo.branch = branches(test_number(e));
911
  return bcinfo;
912
}
913
 
914
/*
915
 * Produce code for expression e, putting its result in dest using t-regs
916
 * given by sp. If non-zero, exitlab is the label of where the code is to
917
 * continue.
918
 */
7 7u83 919
makeans make_code(exp e, space sp, where dest, int exitlab)
2 7u83 920
{
921
  long constval=0;
922
  makeans mka;
923
  static long exp_num = 0;  /* count of exps in order of evaluation */
924
 
925
  /*
926
   * A heuristic to estimate if conditional branch is close enough for
927
   * bc instruction, which can branch +-8k words.  Tests indicate
928
   * 13500 exp nodes generate 8k words of instructions.
929
   * We play safe and allow 1 instruction per exp.
930
   */
7 7u83 931
#define TEST_TAG_NEAR_BRANCH(e)	(ptno(e) < 0 || absval(ptno(son(pt(e))) -exp_num) < 8192)
932
 
2 7u83 933
 tailrecurse:
934
  exp_num++;
935
  mka.lab = exitlab;
936
  mka.regmove = NOREG;
937
 
938
  switch (name(e))
939
  {
940
  /*
941
   * Procedure related code selection is handled by make_XXX_tag_code()
942
   * functions in proc.c.
943
   */
944
   case proc_tag:		/* procedure definition */
945
   case general_proc_tag:
946
    {
947
      exp_num = 0;
948
      make_proc_tag_code(e, sp);
949
      return mka;
950
    }
951
/*****************************************************************************/
952
   case ident_tag:		/* ident/param definition within proc */
953
    {
954
      return make_ident_tag_code(e, sp, dest, exitlab);
955
    }
956
/*****************************************************************************/
957
   case untidy_return_tag:
958
   case res_tag:			/* procedure result */
959
    {
960
      make_res_tag_code(e, sp);
961
      return mka;
962
    }
963
/*****************************************************************************/
964
   case apply_tag:		/* procedure call */
965
    {
966
      return make_apply_tag_code(e, sp, dest, exitlab);
967
    }
968
/*****************************************************************************/
969
   case clear_tag:
970
    {
971
      if (dest.answhere.discrim == insomereg)
972
      {
973
	/*
974
	 * Must choose a fixed register to contain answer to clear
975
	 */
976
	int *sr = someregalt(dest.answhere);
7 7u83 977
 
978
	if (*sr != -1) {fail("somereg *2");}
2 7u83 979
	*sr = getreg(sp.fixed);
980
	setregalt(dest.answhere, *sr);
981
      }
7 7u83 982
      else if (dest.answhere.discrim==insomefreg)
2 7u83 983
      {
984
	/*
985
	 * Must choose a float register to contain answer to clear
986
	 */
987
	somefreg sfr;
988
	freg fr;
7 7u83 989
 
2 7u83 990
	sfr = somefregalt(dest.answhere);
7 7u83 991
	if (*sfr.fr != -1) {fail("somefreg *2");}
2 7u83 992
	*sfr.fr = getfreg(sp.flt);
993
	fr.fr = *sfr.fr;
994
	fr.dble = sfr.dble;
995
	setfregalt(dest.answhere, fr);
996
      }
997
 
998
      return mka;
999
    }
1000
/*****************************************************************************/
1001
   case seq_tag:
1002
    {
1003
      exp t = son(son(e));
7 7u83 1004
 
2 7u83 1005
      for (;;)
1006
      {
7 7u83 1007
	exp next = (last(t))?(bro(son(e))): bro(t);
2 7u83 1008
 
1009
	if (name(next) == goto_tag)	/* gotos end sequences */
1010
	{
1011
	  make_code(t, sp, nowhere, no(son(pt(next))));
1012
	}
1013
	else
1014
	{
1015
	  code_here(t, sp, nowhere);
1016
	}
1017
	if (last(t))
1018
	{
1019
	  exp l = bro(son(e));		/* last exp of sequence */
1020
 
1021
	  if (name(sh(t)) == bothd && name(l) == res_tag &&
7 7u83 1022
	     (name(son(l)) == clear_tag || name(son(l)) == top_tag))
2 7u83 1023
	  {
1024
	    /*
1025
	     * res_tag that cannot be reached.  Eg an extra one inserted at
1026
	     * end of proc.  Skip it.
1027
	     */
1028
	     COMMENT("make_code seq_tag: unreachable res_tag");
1029
	     return mka;
1030
	  }
1031
	  else
1032
	  {
1033
	    return make_code(l, sp, dest, exitlab);
1034
	  }
1035
	}
1036
	t = bro(t);
1037
      }
1038
    }				/* end seq */
1039
/*****************************************************************************/
1040
   case cond_tag:
1041
    {
1042
      exp first = son(e);
1043
      exp second = bro(son(e));
1044
      exp test;
7 7u83 1045
 
2 7u83 1046
      if (dest.answhere.discrim==insomereg)
1047
      {
1048
	/*
7 7u83 1049
	 * Must choose a fixed register to contain answer to cond
2 7u83 1050
	 */
1051
	int *sr = someregalt(dest.answhere);
7 7u83 1052
 
1053
	if (*sr != -1) {fail("somereg *2");}
2 7u83 1054
	*sr = getreg(sp.fixed);
1055
	setregalt(dest.answhere, *sr);
1056
      }
1057
      else if (dest.answhere.discrim==insomefreg)
1058
      {
1059
	/*
7 7u83 1060
	 * Must choose a float register to contain answer to cond
2 7u83 1061
	 */
1062
	somefreg sfr;
1063
	freg fr;
7 7u83 1064
 
2 7u83 1065
	sfr = somefregalt(dest.answhere);
7 7u83 1066
	if (*sfr.fr != -1) {fail("somefreg *2");}
2 7u83 1067
	*sfr.fr = getfreg(sp.flt);
1068
	fr.fr = *sfr.fr;
1069
	fr.dble = sfr.dble;
1070
	setfregalt(dest.answhere, fr);
1071
      }
1072
 
7 7u83 1073
      /*
1074
       * A few optimisations for cond_tag
2 7u83 1075
       */
1076
      if (name(first) == goto_tag && pt(first) == second)
1077
      {
1078
	/* first is goto second */
1079
	no(son(second)) = 0;
1080
	return make_code(second, sp, dest, exitlab);
1081
      }
1082
#if 0 /* could we do this better to prevent long branch problem?*/
1083
      else if (name(second) == labst_tag && name(bro(son(second))) == top_tag)
1084
      {
1085
	/* second is empty */
1086
 
7 7u83 1087
	int endl = (exitlab == 0)? new_label(): exitlab;
2 7u83 1088
 
1089
	no(son(second)) = endl;
1090
	make_code(first, sp, dest, endl);
1091
	mka.lab = endl;
1092
	return mka;
1093
      }
1094
#endif
1095
      else if (name(second) == labst_tag && name(bro(son(second))) == goto_tag)
1096
      {
1097
	/* second is goto */
1098
	exp g = bro(son(second));
1099
 
1100
	no(son(second)) = no(son(pt(g)));
1101
	return make_code(first, sp, dest, exitlab);
1102
      }
1103
 
1104
      test = testlast(first, second);
1105
      if (test != nilexp && TEST_TAG_NEAR_BRANCH(test))
1106
      {
1107
	/* effectively an empty then part */
7 7u83 1108
	int l = (exitlab != 0)? exitlab : new_label();
2 7u83 1109
 
1110
	ptno(test) = -l;	/* make test jump to exitlab - see test_tag: */
1111
	settest_number(test,obranch(test_number(test)));
1112
	/* settest_number preserves the Rev bit */
1113
	no(son(second)) = new_label();
1114
	make_code(first, sp, dest, l);
1115
	make_code(second, sp, dest, l);
1116
	mka.lab = l;
1117
	return mka;
1118
      }
1119
      else
1120
      {
1121
	int fl;
1122
	int l;
7 7u83 1123
 
2 7u83 1124
	no(son(second)) = new_label();
1125
	fl = make_code(first, sp, dest, exitlab).lab;
7 7u83 1126
	l = (fl != 0)? fl :((exitlab != 0)? exitlab : new_label());
1127
	if (name(sh(first))!= bothd)
2 7u83 1128
	{
1129
	  uncond_ins(i_b, l);
1130
	}
1131
	make_code(second, sp, dest, l);
1132
	clear_all();
1133
	mka.lab = l;
1134
	return mka;
1135
      }
7 7u83 1136
    }
2 7u83 1137
/*****************************************************************************/
1138
   case labst_tag:
1139
    {
1140
      ptno(son(e)) = exp_num;	/* update estimate made in scan() */
7 7u83 1141
      if (no(son(e))!= 0)
2 7u83 1142
      {
1143
	clear_all();
1144
	set_label(no(son(e)));
7 7u83 1145
 
2 7u83 1146
	if (is_loaded_lv(e) && p_save_all_sregs)
1147
	{
1148
	  /* It is long jumpabble to (potentially)*/
7 7u83 1149
	  if (p_has_tp)
2 7u83 1150
	  {
1151
	    /* restore tp */
1152
	    baseoff saved_tp;
1153
	    saved_tp.base = R_FP;
1154
	    saved_tp.offset = 0;
1155
	    ld_ro_ins(i_l,saved_tp,R_TP);comment("restore TP using FP");
1156
	  }
1157
	  if (p_has_saved_sp)
1158
	  {
1159
	    /* Variable frame size */
1160
	    get_sp_from_stack();
1161
	  }
7 7u83 1162
	  else
2 7u83 1163
	  {
1164
	    /* Fixed frame size */
1165
	    rir_ins(i_a,R_FP, - p_frame_size , R_SP);
1166
	  }
1167
	}
7 7u83 1168
 
2 7u83 1169
      }
1170
      return make_code(bro(son(e)), sp, dest, exitlab);
1171
    }				/* end labst */
1172
/*****************************************************************************/
1173
  case rep_tag:
1174
    {
1175
      exp first = son(e);
1176
      exp second = bro(first);
7 7u83 1177
 
2 7u83 1178
      code_here(first,sp,nowhere);
7 7u83 1179
      ASSERT(name(second) ==labst_tag);
2 7u83 1180
      no(son(second)) = new_label();
1181
#if 1
1182
      if (architecture != POWERPC_CODE)
1183
      {
7 7u83 1184
	exp last_test;
2 7u83 1185
	/*
1186
	 * Rearrange test and branch instructions
7 7u83 1187
	 * to reduce RS/6000 branch delays
2 7u83 1188
	 */
1189
	/* look for last test_tag of repeat exp */
1190
	last_test = bro(son(second));	/* under labst_tag */
1191
	/* dive down sequences */
1192
	while (name(last_test) == seq_tag)
1193
	{
1194
	  last_test = bro(son(last_test));
1195
	}
7 7u83 1196
 
1197
 
2 7u83 1198
	if (!diagnose && name(last_test) == test_tag)
1199
	{
1200
	  /* we found a test_tag, is it simple and jumps to rep_tag? */
7 7u83 1201
 
1202
	  if (ptno(last_test) >= 0 && pt(last_test) == second
2 7u83 1203
	      && TEST_TAG_NEAR_BRANCH(last_test))
1204
	  {
1205
	    /*
1206
	     * It jumps to head of repeat.  Generate code out of
1207
	     * order to reduce RS/6000 branch delays.  RS/6000
1208
	     * assumes fall-through conditional branches are
1209
	     * most common and speculatively executes non-branch
1210
	     * instructions ahaead.  Rearrange as follows:
1211
	     *
1212
	     *		b	start_of_rep_lab
1213
	     *	end_rep_test_lab:
1214
	     *		<reversed test_tag conditonal branch to end_rep_lab>
1215
	     *	start_of_rep_lab:
1216
	     #		<rest of rep>
1217
	     *		<reversed test_tag conditonal test>
1218
	     *		b	end_rep_test_lab
1219
	     *	end_rep_lab:
1220
	     */
1221
	    static int rep_org_labnos = 0;
1222
	    int rep_org_lab = 0;
1223
	    int end_rep_test_lab = new_label();
1224
	    int start_of_rep_lab = no(son(second));	/* labst_tag label */
7 7u83 1225
	    int end_rep_lab = (exitlab == 0)? new_label(): exitlab;
2 7u83 1226
	    bc_info bcinfo;
7 7u83 1227
 
2 7u83 1228
	    COMMENT("make_code rep_tag: last exp is rep_tag test_tag - evaluate out of order");
7 7u83 1229
 
2 7u83 1230
	    /* labst_tag label should be in use */
1231
	    ASSERT(start_of_rep_lab!=0);
7 7u83 1232
 
2 7u83 1233
	    /* allocate new label number for use with .org: L.R%d and L.S%d */
1234
	    rep_org_lab = ++rep_org_labnos;
7 7u83 1235
 
2 7u83 1236
	    uncond_ins(i_b, start_of_rep_lab);
7 7u83 1237
 
2 7u83 1238
	    set_label(end_rep_test_lab);
7 7u83 1239
 
2 7u83 1240
	    /* use .org to leave gap for brought forward bc ins */
1241
	    fprintf(as_file, "L.R%d:\n", rep_org_lab);
1242
	    fprintf(as_file, "\t.org\t$+4\t# loop bc ins\n");
7 7u83 1243
 
2 7u83 1244
	    /* we will do test_tag ourselves, nuke it out of loop */
1245
	    name(last_test) = top_tag;
7 7u83 1246
 
2 7u83 1247
	    /* set_label(start_of_rep_lab) done by labst_tag */
7 7u83 1248
 
2 7u83 1249
	    mka = make_code(second, sp, dest, exitlab);
7 7u83 1250
 
2 7u83 1251
	    /* reverse test, jump to end_rep_lab */
1252
	    ptno(last_test) = -end_rep_lab;
1253
	    settest_number(last_test,obranch(test_number(last_test)));
1254
	    /* generate compare */
1255
	    bcinfo = make_test_tag_cmp(last_test, sp);
7 7u83 1256
 
2 7u83 1257
	    uncond_ins(i_b, end_rep_test_lab);
7 7u83 1258
 
2 7u83 1259
	    if (end_rep_lab != exitlab)
1260
	      set_label(end_rep_lab);
7 7u83 1261
 
2 7u83 1262
	    /* fill in gap above with bc_ins */
1263
	    fprintf(as_file, "L.S%d:\n", rep_org_lab);
1264
	    fprintf(as_file, ".org\tL.R%d\t# loop bc ins\n", rep_org_lab);
1265
	    bc_ins(bcinfo.branch, bcinfo.creg, bcinfo.lab,UNLIKELY_TO_JUMP);
7 7u83 1266
 
2 7u83 1267
	    /* .org back */
1268
	    fprintf(as_file, ".org\tL.S%d\n", rep_org_lab);
7 7u83 1269
 
2 7u83 1270
	    return mka;
1271
	  }
7 7u83 1272
 
2 7u83 1273
	}
1274
      }
7 7u83 1275
#endif
2 7u83 1276
      /*
1277
       * We could not find last simple test_tag, must be complicated.
1278
       * Don't bother to move tests around.
1279
       * +++ handle cond_tag for more complex terminating condition.
1280
       */
1281
      return make_code(second, sp, dest, exitlab);
1282
    }				/* end rep */
1283
/*****************************************************************************/
1284
  case goto_tag:
1285
    {
1286
      exp gotodest = pt(e);
1287
      int lab;
7 7u83 1288
#if 0
2 7u83 1289
/* This would be a lovely optimisation, however silly people give me test
1290
   programs with L1:goto L1 so I despair */
7 7u83 1291
      while (name(bro(son(gotodest))) ==goto_tag)
2 7u83 1292
      {
1293
	/* goto to goto optimisation */
1294
	gotodest = pt(bro(son(gotodest)));
1295
      }
7 7u83 1296
#endif
2 7u83 1297
      lab = no(son(gotodest));
1298
      clear_all();
7 7u83 1299
      if (last(e) ==0 || name(bro(e))!=seq_tag || last(bro(e)) ||
1300
	  bro(bro(e))!= gotodest)
2 7u83 1301
      {
7 7u83 1302
	uncond_ins(i_b, lab);
2 7u83 1303
      }/* otherwise dest is next in sequence */
1304
      return mka;
1305
    }				/* end goto */
1306
/*****************************************************************************/
1307
  case test_tag:
1308
    {
1309
      bc_info bcinfo;
1310
      int branch_prediction=LIKELY_TO_JUMP;
7 7u83 1311
 
1312
      if (no(e)!=1000 && no(e) >=0 && no(e) <=100)
2 7u83 1313
      {
7 7u83 1314
	branch_prediction = (no(e) >=50)?UNLIKELY_TO_JUMP:LIKELY_TO_JUMP;
2 7u83 1315
      }
1316
      try_record_bit(e);
1317
      if (TEST_TAG_NEAR_BRANCH(e))
1318
      {
7 7u83 1319
	/*
2 7u83 1320
	 * Estimate close enough for bc_ins
1321
	 */
1322
	bcinfo = make_test_tag_cmp(e, sp);
1323
	bc_ins(bcinfo.branch, bcinfo.creg, bcinfo.lab,branch_prediction);
1324
      }
1325
      else
1326
      {
1327
	int newlab = new_label();
1328
	int oldlab = no(son(pt(e)));
1329
 
1330
	/*
7 7u83 1331
	 * Branch is too far away so we reverse branch to new label
2 7u83 1332
	 * and use an unconditional branch to the target destination
1333
	 */
1334
	ptno(e) = -newlab;
1335
	settest_number(e,obranch(test_number(e)));
1336
	bcinfo = make_test_tag_cmp(e, sp);
1337
	bc_ins(bcinfo.branch, bcinfo.creg, bcinfo.lab,1-branch_prediction);
1338
	uncond_ins(i_b, oldlab);	/* unconditional far jump OK */
1339
	set_label(newlab);
1340
      }
1341
      return mka;
1342
    }				/* end test */
1343
/*****************************************************************************/
1344
   case ass_tag:
1345
   case assvol_tag:
1346
    {
1347
      exp lhs = son(e);
1348
      exp rhs = bro(lhs);
1349
      where assdest;
1350
      space nsp;
1351
      int contreg = NOREG;
1352
      int hdrhs = name(sh(rhs));
1353
      bool is_float = is_floating(hdrhs);
1354
 
1355
      /* +++ lose chvar_tag on rhs if no result, remember to invalidate reg */
1356
      /* +++ remove name(e)==ass_tag tests now assbits_tag has gone */
1357
 
1358
      if (name(e) == assvol_tag)
1359
      {
1360
	/*
1361
	 * Assign to volatile location.
1362
	 * Disable register-location tracing. +++ is this really needed ???
1363
	 * Disable peep-hole optimisation (when implemented)
1364
	 */
1365
	COMMENT("make_code: Assign to volatile");
1366
	clear_all();
1367
      }
1368
 
1369
      if (name(e) == ass_tag && APPLYLIKE(rhs) &&
7 7u83 1370
	 ((is_float) || valregable(sh(rhs))))
2 7u83 1371
      {
1372
	where apply_res;
1373
	/* This is not an optimisation this is necessary */
1374
	/* Since if we have a procedure call doing the locate will make a pointer which
1375
	   will be trashed in the call*/
1376
	if (is_float)
1377
	{
1378
	  freg frg;
1379
	  COMMENT("make_code: ass_tag: apply result special handling:float");
1380
	  frg.fr = FR_RESULT;
1381
	  frg.dble = (hdrhs != shrealhd);
1382
	  setfregalt(apply_res.answhere, frg);
1383
	}
1384
	else
1385
	{
1386
	  COMMENT("make_code: ass_tag: apply result special handling:fixed");
1387
	  setregalt(apply_res.answhere, R_RESULT);
1388
	}
1389
	apply_res.ashwhere = ashof(sh(rhs));
1390
 
1391
	code_here(rhs, sp, apply_res);
1392
	nsp = guard(apply_res, sp);
7 7u83 1393
 
2 7u83 1394
	assdest = locate(lhs, nsp, sh(rhs), 0);
1395
 
1396
	move(apply_res.answhere, assdest, nsp.fixed, 1);
7 7u83 1397
	/* The evaluation of an assignment is the rhs so
2 7u83 1398
	   we move the rhs to dest as well */
1399
	move(apply_res.answhere, dest, nsp.fixed, 1);
1400
	clear_dep_reg(lhs);
7 7u83 1401
 
2 7u83 1402
#if 0
1403
	/* +++ remember that R_RESULT is lhs */
1404
	if (!is_float)
1405
	{
1406
	  keepcont(lhs,R_RESULT);
1407
	}
1408
#endif
1409
	return mka;
1410
      }
1411
 
1412
#ifndef NO_REGREG_ST
1413
      /* see if we can use [reg+reg] addressing for this store */
1414
      if (name(lhs) == addptr_tag)
1415
      {
1416
	exp addptr_sons = son(lhs);
1417
	ash a;
1418
	int ashsize;
1419
	a = ashof(sh(rhs));
1420
	ashsize = a.ashsize;
1421
 
1422
	if (last(bro(addptr_sons))
1423
	    && a.ashalign == ashsize
1424
	    && (ashsize==8 || ashsize==16 || ashsize==32 || is_float))
1425
	{
1426
	  int lhs_addptr_reg;
1427
	  int rhs_addptr_reg;
1428
	  ans aa;
1429
 
1430
	  COMMENT("make_code ass_tag: store suitable for [reg+reg] addressing");
1431
 
1432
	  lhs_addptr_reg = reg_operand(addptr_sons, sp);
1433
	  nsp = guardreg(lhs_addptr_reg, sp);
1434
	  rhs_addptr_reg = reg_operand(bro(addptr_sons), nsp);
1435
	  nsp = guardreg(rhs_addptr_reg, nsp);
1436
 
1437
	  if (is_float)
1438
	  {
1439
	    freg dfreg;
1440
 
1441
	    dfreg.fr = freg_operand(rhs, nsp, getfreg(nsp.flt));
1442
	    dfreg.dble = ashsize == 64;
1443
 
1444
	    stf_rr_ins((dfreg.dble?i_stfd:i_stfs),dfreg.fr,lhs_addptr_reg,rhs_addptr_reg);
1445
	    setfregalt(aa, dfreg);
1446
	  }
1447
	  else
1448
	  {
1449
	    int assreg;
7 7u83 1450
	    if (dest.answhere.discrim==inreg &&
2 7u83 1451
	       !IS_R_NO_REG(regalt(dest.answhere)))
1452
	    {
1453
	      assreg = regalt(dest.answhere);
1454
	      reg_operand_here(rhs,nsp,assreg);
1455
	    }
1456
	    else
1457
	    {
1458
	      assreg= reg_operand(rhs, nsp);
1459
	    }
1460
	    st_rr_ins(i_st_sz(ashsize), assreg, lhs_addptr_reg, rhs_addptr_reg);
1461
 
1462
	    setregalt(aa, assreg);
1463
	  }
1464
 
1465
	  move(aa, dest, sp.fixed, 1);		/* +++ nsp.fixed ? */
1466
 
1467
	  clear_dep_reg(lhs);
1468
	  return mka;
1469
	}
1470
      }
1471
#endif
1472
 
1473
      assdest = locate(lhs, sp, sh(rhs), 0);
1474
      nsp = guard(assdest, sp);
1475
      FULLCOMMENT("make_code: ass_tag: located lhs");
1476
      if (name(e) == ass_tag
1477
	  && assdest.answhere.discrim == notinreg
1478
	  && assdest.ashwhere.ashsize == assdest.ashwhere.ashalign)
1479
      {
1480
	instore is;
1481
 
1482
	is = insalt(assdest.answhere);
1483
	if (!is.adval)
1484
	{			/* this is an indirect assignment, so make it
1485
				 * direct by loading pointer into reg  (and
1486
				 * remember it) */
1487
	  int r = getreg(nsp.fixed);
1488
 
1489
	  ld_ins(i_l, is.b, r);
1490
	  nsp = guardreg(r, nsp);
1491
	  is.adval = 1;
1492
	  is.b.base = r;
1493
	  is.b.offset = 0;
1494
	  setinsalt(assdest.answhere, is);
1495
	  keepexp(lhs, assdest.answhere);
1496
	}
1497
      }
1498
 
1499
#if 1
1500
      if (name(e) == ass_tag && is_float && assdest.answhere.discrim == notinreg)
1501
      {
1502
	/*
1503
	 * Ensure floating point values assigned using floating point regs so
1504
	 * floating point reg tracking works better. move() uses fixed regs
1505
	 * for mem to mem, so must pre-load to floating point reg.
1506
	 */
1507
	int f = freg_operand(rhs, nsp, getfreg(nsp.flt));
1508
	freg frg;
1509
	ans aa;
1510
 
1511
	frg.fr = f;
1512
	frg.dble = (hdrhs != shrealhd);
1513
	setfregalt(aa, frg);
1514
	nsp = guardfreg(f, nsp);
1515
	move(aa, assdest, nsp.fixed, 1);
1516
	move(aa, dest, nsp.fixed, 1);
1517
	clear_dep_reg(lhs);
1518
	/* +++ frg in mka */
1519
	return mka;
1520
      }
1521
#endif
1522
 
1523
      contreg = code_here(rhs, nsp, assdest);
1524
      /* evaluate source into assignment destination .... */
1525
 
1526
 
1527
      /* ... and move it into dest - could use assignment as value */
1528
 
1529
      switch (assdest.answhere.discrim)
1530
      {
1531
      case inreg:
1532
	{
1533
	  int a = regalt(assdest.answhere);
1534
 
1535
	  keepreg(rhs, a);
1536
	  /* remember that source has been evaluated into a */
1537
	  clear_dep_reg(lhs);
1538
	  /* forget register dependencies on destination */
1539
	  move(assdest.answhere, dest, nsp.fixed, 1);
1540
	  break;
1541
	}
1542
      case infreg:
1543
	{
1544
	  freg frg;
1545
	  int r;
1546
 
1547
	  frg = fregalt(assdest.answhere);
1548
	  r = frg.fr + 32;
1549
	  if (frg.dble)
1550
	  {
1551
	    r = -r;
1552
	  };
1553
	  keepreg(rhs, r);
1554
	  /* remember that source has been evaluated into a */
1555
	  clear_dep_reg(lhs);
1556
	  /* forget register dependencies on destination */
1557
	  move(assdest.answhere, dest, nsp.fixed, 1);
1558
	  break;
1559
	}
1560
 
1561
       case notinreg:
1562
	{
1563
	  if (contreg != NOREG && name(e) == ass_tag)
1564
	  {
1565
	    ans aa;
1566
	    space nnsp;
1567
 
1568
	    if (contreg > 0 && contreg < 31)
1569
	    {
1570
	      setregalt(aa, contreg);
1571
	      nnsp = guardreg(contreg, sp);
1572
	    }
1573
	    else
1574
	    {
1575
	      freg frg;
1576
 
1577
	      frg.fr = absval(contreg) - 32;
1578
	      frg.dble = (contreg < 0);
1579
	      nnsp = nsp;
1580
	      setfregalt(aa, frg);
1581
	    }
1582
	    move(aa, dest, nnsp.fixed, 1);
1583
	    clear_dep_reg(lhs);/* Apply fix here from rw 27/10/94*/
1584
	    /* forget register dependencies on destination */
1585
#if 0
1586
	    if (name(lhs) == name_tag || !dependson(lhs, 0, lhs))
1587
 
1588
	      /*
1589
	       * remember that dest contains source, provided that it is not
1590
	       * dependent on it
1591
	       */
1592
#endif
1593
#if 1
7 7u83 1594
	    if (name(lhs) == name_tag) {
1595
	      exp dc = son(lhs);
1596
	      if (son(dc)!= nilexp)dc = son(dc);
1597
	      if (shape_size(sh(dc)) ==
1598
		  shape_size(sh(rhs))) {
1599
		keepcont(lhs, contreg);
2 7u83 1600
	      }
7 7u83 1601
	    } else if (!dependson(lhs, 0, lhs))
1602
#endif
2 7u83 1603
	    {
1604
	      keepcont(lhs, contreg);
1605
	    }
1606
	    return mka;
1607
	  }
1608
	  clear_dep_reg(lhs);
1609
	  /* forget register dependencies on destination */
1610
	  move(assdest.answhere, dest, nsp.fixed, 1);
1611
	  break;
1612
	}
1613
      case insomereg:
1614
	  {
1615
	    clear_dep_reg(lhs);
1616
	    /* forget register dependencies on destination */
1617
	    move(assdest.answhere, dest, guard(assdest, sp).fixed, 1);
1618
	    break;
1619
	  }
1620
      default:
1621
	  fail("make_code: unexpected answhere in assign");
1622
      }				/* end sw on answhere */
1623
 
1624
      return mka;
1625
    }				/* end ass */
1626
/*****************************************************************************/
1627
  case compound_tag:
1628
    {
1629
      exp t;
1630
      space nsp;
1631
      instore str;
1632
      int r;
1633
 
1634
      if (has_bitfield(e))
1635
      {
1636
	/*
1637
	 * Take the easy way out for bitfields, copy a constant.
1638
	 * +++ This only works for C, which does not permit non-const
1639
	 * expressions here.
1640
	 */
1641
	ans aa;
1642
 
1643
	COMMENT("make_code: compound containing bitfield");
1644
 
1645
	/* assume struct is small, set up data constant and move */
1646
 
1647
	fix_nonbitfield(e);		/* ensure all offsets are bit-offsets,
1648
					 * as evaluated_const() expects */
1649
 
1650
	setinsalt(aa, evaluated_const(e));
1651
	mka.regmove = move(aa, dest, sp.fixed, 0);
1652
 
1653
	return mka;
1654
      }
1655
 
1656
      nsp = sp;
1657
      t = son(e);
1658
      switch (dest.answhere.discrim)
1659
      {
1660
      case notinreg:
1661
	{
1662
	  str = insalt(dest.answhere);	/* it should be !! */
1663
	  if (!str.adval)
1664
	  {
1665
	    int r = getreg(sp.fixed);
1666
 
1667
	    nsp = guardreg(r, sp);
1668
	    ld_ins(i_l, str.b, r);
1669
	    str.adval = 1;
1670
	    str.b.base = r;
1671
	    str.b.offset = 0;
1672
	  }
1673
	  for (;;)
1674
	  {
1675
	    where newdest;
1676
	    instore newis;
1677
 
1678
	    newis = str;
1679
	    newis.b.offset += no(t);
1680
 
7 7u83 1681
	    FULLCOMMENT4("make_code compound_tag: name(t) =%d no(t) =%d al2=%d offset=%d",
2 7u83 1682
		name(t), no(t), al2(sh(t)), newis.b.offset);
1683
	    ASSERT(name(t) == val_tag && al2(sh(t)) >= 8);
1684
 
1685
	    setinsalt(newdest.answhere, newis);
1686
	    newdest.ashwhere = ashof(sh(bro(t)));
1687
 
1688
	    code_here(bro(t), nsp, newdest);
1689
 
1690
	    if (last(bro(t)))
1691
	      return mka;
1692
 
1693
	    t = bro(bro(t));
1694
	  }
1695
	}
1696
#if 1	/* we need in reg compound for ptr type conversion via regs */
1697
      case insomereg:
1698
	{
1699
	  int *sr = someregalt(dest.answhere);
1700
 
1701
	  if (*sr != -1)
1702
	  {
1703
	    fail("Somereg *2");
1704
	  }
1705
	  *sr = getreg(sp.fixed);
1706
	  setregalt(dest.answhere, *sr);
1707
	  /* FALLTHROUGH */
1708
	}
1709
      case inreg:
1710
	{
1711
	  code_here(bro(t), sp, dest);
1712
	  r = regalt(dest.answhere);
1713
	  ASSERT(name(t) == val_tag);
7 7u83 1714
	  if (no(t)!= 0)
1715
	    rir_ins(i_sl, r,((al2(sh(t)) >= 8)?(no(t) << 3): no(t)), r);
2 7u83 1716
	  nsp = guardreg(r, sp);
1717
	  while (!last(bro(t)))
1718
	  {
1719
	    int z;
1720
 
1721
	    t = bro(bro(t));
1722
	    ASSERT(name(t) == val_tag);
1723
	    z = reg_operand(bro(t), nsp);
7 7u83 1724
	    if (no(t)!= 0)
2 7u83 1725
	    {
7 7u83 1726
	      rir_ins(i_sl, z,((al2(sh(t)) >= 8)?(no(t) << 3): no(t)), z);
2 7u83 1727
	    }
1728
	    rrr_ins(i_or, r, z, r);
1729
	  }
1730
	  return mka;
1731
	}
1732
#endif
1733
      default:
1734
	fail("no compounds in float reg");
1735
      }
1736
    }				/* end tup */
1737
/*****************************************************************************/
1738
  case nof_tag:
1739
  case concatnof_tag:
1740
    {
1741
      exp t = son(e);
1742
      space nsp;
1743
      instore str;
1744
      int r, disp = 0;
1745
#if 1
7 7u83 1746
      if (t==nilexp)
2 7u83 1747
	return mka;
1748
#endif
1749
      nsp = sp;
1750
      switch (dest.answhere.discrim)
1751
      {
1752
      case notinreg:
1753
	{
1754
	  str = insalt(dest.answhere);	/* it should be !! */
1755
	  if (!str.adval)
1756
	  {
1757
	    int r = getreg(sp.fixed);
1758
 
1759
	    nsp = guardreg(r, sp);
1760
	    ld_ins(i_l, str.b, r);
1761
	    str.adval = 1;
1762
	    str.b.base = r;
1763
	    str.b.offset = 0;
1764
	  }
1765
	  for (;;)
1766
	  {
1767
	    where newdest;
1768
	    instore newis;
1769
 
1770
	    newis = str;
1771
	    newis.b.offset += disp;
1772
	    setinsalt(newdest.answhere, newis);
1773
	    newdest.ashwhere = ashof(sh(t));
1774
	    code_here(t, nsp, newdest);
1775
	    if (last(t))
1776
	    {
1777
	      return mka;
1778
	    }
1779
	    disp += (rounder(shape_size(sh(t)), shape_align(sh(bro(t)))) >> 3);
1780
	    t = bro(t);
1781
	  }
1782
	}
1783
      case insomereg:
1784
	{
1785
	  int *sr = someregalt(dest.answhere);
1786
 
1787
	  if (*sr != -1)
1788
	  {
1789
	    fail("Somereg *2");
1790
	  }
1791
	  *sr = getreg(sp.fixed);
1792
	  setregalt(dest.answhere, *sr);
1793
	  /* ,... */
1794
	}
1795
      case inreg:
1796
	{
1797
	  code_here(t, sp, dest);
1798
	  r = regalt(dest.answhere);
1799
	  nsp = guardreg(r, sp);
1800
	  while (!last(t))
1801
	  {
1802
	    int z;
1803
 
1804
	    disp += rounder(shape_size(sh(t)), shape_align(sh(bro(t))));
1805
	    t = bro(t);
1806
	    z = reg_operand(t, nsp);
1807
	    if (disp != 0)
1808
	    {
1809
	      rir_ins(i_sl, z, disp, z);
1810
	    }
1811
	    rrr_ins(i_or, r, z, r);
1812
	  }
1813
	  return mka;
1814
	}
1815
      default:
1816
	fail("No Tuples in freg");
1817
      }
1818
    }
1819
/*****************************************************************************/
1820
  case ncopies_tag:
1821
    {
1822
      exp t = son(e);
1823
      space nsp;
1824
      instore str;
1825
      int i, r, disp = 0;
1826
      int no_of_copies = no(e);
1827
      nsp = sp;
1828
 
1829
      switch (dest.answhere.discrim)
1830
      {
1831
       case notinreg:
1832
	{
1833
	  str = insalt(dest.answhere);	/* it should be !! */
1834
	  if (!str.adval)
1835
	  {
1836
	    int r = getreg(sp.fixed);
7 7u83 1837
 
2 7u83 1838
	    nsp = guardreg(r, sp);
1839
	    ld_ins(i_l, str.b, r);
1840
	    str.adval = 1;
1841
	    str.b.base = r;
1842
	    str.b.offset = 0;
1843
	  }
1844
	  for (i = 1; i <= no_of_copies; i++)
1845
	  {
1846
	    where newdest;
1847
	    instore newis;
7 7u83 1848
 
2 7u83 1849
	    newis = str;
1850
	    newis.b.offset += disp;
1851
	    setinsalt(newdest.answhere, newis);
1852
	    newdest.ashwhere = ashof(sh(t));
1853
	    code_here(t, nsp, newdest);
1854
	    disp += (rounder(shape_size(sh(t)), shape_align(sh(t))) >> 3);
1855
	  }
1856
	  return mka;
1857
	}
1858
      case insomereg:
1859
	{
1860
	  int *sr = someregalt(dest.answhere);
1861
 
1862
	  if (*sr != -1)
1863
	  {
1864
	    fail("Somereg *2");
1865
	  }
1866
	  *sr = getreg(sp.fixed);
1867
	  setregalt(dest.answhere, *sr);
1868
	  /*FALLTHROUGH*/
1869
	}
1870
      case inreg:
1871
	{
1872
	  code_here(t, sp, dest);
1873
	  r = regalt(dest.answhere);
1874
	  nsp = guardreg(r, sp);
1875
	  for (i = 1; i <= no_of_copies; i++)
1876
	  {
1877
	    int z;
1878
 
1879
	    disp += rounder(shape_size(sh(t)), shape_align(sh(t)));
1880
	    z = reg_operand(t, nsp);
1881
	    if (disp != 0)
1882
	    {
1883
	      rir_ins(i_sl, z, disp, z);
1884
	    }
1885
	    rrr_ins(i_or, r, z, r);
1886
	  }
1887
	  return mka;
1888
	}
1889
      default:
1890
	fail("no compounds in float reg");
1891
      }
1892
    }
1893
/*****************************************************************************/
1894
   case diagnose_tag:
1895
    {
1896
      output_diag(dno(e), 0, e);
1897
      mka = make_code(son(e), sp, dest, exitlab);
1898
      output_end_scope(dno(e), e);
1899
      return mka;
1900
    }
1901
/*****************************************************************************/
1902
  case solve_tag:
1903
    {
1904
      exp m = bro(son(e));
1905
      int l = exitlab;
7 7u83 1906
 
1907
      if (dest.answhere.discrim==insomereg)
2 7u83 1908
      {
1909
	/* Choose register for fixed result */
1910
	int *sr = someregalt(dest.answhere);
7 7u83 1911
	if (*sr != -1) {fail("somereg *2");}
2 7u83 1912
	*sr = getreg(sp.fixed);
1913
	setregalt(dest.answhere, *sr);
1914
      }
1915
      else if (dest.answhere.discrim==insomefreg)
1916
      {
1917
	/* Choose register for float result */
1918
	somefreg sfr;
1919
	freg fr;
1920
	sfr = somefregalt(dest.answhere);
7 7u83 1921
	if (*sfr.fr != -1) { fail("somefreg *2"); }
2 7u83 1922
	*sfr.fr = getfreg(sp.flt);
1923
	fr.fr = *sfr.fr;
1924
	fr.dble = sfr.dble;
1925
	setfregalt(dest.answhere, fr);
1926
      }
7 7u83 1927
 
2 7u83 1928
      /* Set up all the labels in the component labst_tags */
1929
      for (;;)
1930
      {
1931
	no(son(m)) = new_label();
1932
	if (last(m))
1933
	{
1934
	  break;
1935
	}
1936
	m = bro(m);
1937
      }
1938
      m = son(e);
1939
 
1940
      /* Evaluate all the component statements */
1941
      for (;;)
1942
      {
1943
	int fl = make_code(m, sp, dest, l).lab;
1944
 
1945
	clear_all();
1946
	if (fl != 0)
1947
	{
1948
	  l = fl;
1949
	}
1950
	if (!last(m))
1951
	{
1952
	  /* jump to end of solve */
1953
	  if (l == 0)
1954
	  {
1955
	    l = new_label();
1956
	  }
7 7u83 1957
	  if (name(sh(m))!= bothd)
2 7u83 1958
	  {
1959
	    uncond_ins(i_b, l);
1960
	  }
1961
	}
1962
	if (last(m))
1963
	{
1964
	  mka.lab = l;
1965
	  return mka;
1966
	};
1967
	m = bro(m);
1968
      }
1969
    }				/* end solve */
1970
/*****************************************************************************/
1971
  case case_tag:
1972
    {
1973
      exp control = son(e);
1974
      int control_reg;
1975
      control_reg = reg_operand(control,sp);
1976
      case_tag_code(control_reg, e, sp);
1977
      return mka;
1978
    }				/* end case */
1979
/*****************************************************************************/
1980
  case plus_tag:
1981
    {
1982
      if (!optop(e))
1983
      {
1984
	mka.regmove = plus_error_treatment(e,sp,dest);
7 7u83 1985
      }
2 7u83 1986
      else
1987
      {
1988
	if (isrecordbit(e))
1989
	{
1990
	  mka.regmove = comm_op(e, sp, dest, i_a_cr);
1991
	  cr0_set = 1;
1992
	}
1993
	else
1994
	{
1995
	  mka.regmove = comm_op(e, sp, dest, i_a);
1996
	}
1997
      }
1998
      return mka;
1999
    }				/* end plus */
2000
/*****************************************************************************/
2001
   case chvar_tag:
2002
    {
2003
      exp arg = son(e);			/* source of chvar, adjusted below   */
2004
      int size_e = shape_size(sh(e));	/* size of result                    */
2005
      int to = name(sh(e));		/* to hd                             */
2006
      int from;				/* from hd                           */
2007
      int sreg;			        /* source reg                        */
2008
      int dreg;  			/* dest reg, or temp for memory dest */
2009
      bool inmem_dest;		        /* is dest in memory ? */
2010
 
7 7u83 2011
 
2 7u83 2012
      /*
7 7u83 2013
       * For a series of chvar_tags, do large to small in one go
2 7u83 2014
       */
7 7u83 2015
      while (name(arg) == chvar_tag &&
2 7u83 2016
	     ashof(sh(arg)).ashsize >= size_e && NO_ERROR_TREATMENT(arg))
2017
      {
2018
	COMMENT1("make_code chvar_tag: skipping intermediate shape %d",name(sh(arg)));
2019
	arg = son(arg);
2020
      }
7 7u83 2021
 
2 7u83 2022
      if (ERROR_TREATMENT(e))
2023
      {
2024
	mka.regmove = chvar_error_treatment(e,sp,dest);
2025
	return mka;
2026
      }
2027
 
7 7u83 2028
 
2 7u83 2029
      from = name(sh(arg));
7 7u83 2030
      if (from == to ||
2 7u83 2031
	  to == slonghd ||
2032
	  to == ulonghd ||
7 7u83 2033
	 (to == uwordhd && from == ucharhd) ||
2034
	 (to == swordhd && (from == scharhd || from == ucharhd)) ||
2035
	 (to>=slonghd)
2036
	 )
2 7u83 2037
      {
7 7u83 2038
	/*
2039
	 * No changes required, so just move handling dest insomereg well
2 7u83 2040
	 */
2041
	ans aa;
7 7u83 2042
 
2 7u83 2043
	COMMENT("make_code chvar_tag: no change");
2044
	switch (dest.answhere.discrim)
2045
	{
2046
	 case inreg:
2047
	  sreg = regalt(dest.answhere);
2048
	  if (!IS_R_NO_REG(sreg))
2049
	  {
2050
	    reg_operand_here(arg, sp, sreg);
2051
	    break;
2052
	  }
2053
	  /* result being voided, treat as default */
2054
	  /*FALLTHROUGH*/
7 7u83 2055
 
2 7u83 2056
	 default:
2057
	  sreg = reg_operand(arg, sp);
2058
	}
7 7u83 2059
 
2 7u83 2060
	setregalt(aa, sreg);
7 7u83 2061
	mka.regmove = move(aa, dest, sp.fixed, is_signed(sh(e)));
2 7u83 2062
	return mka;
2063
      }
2064
 
2065
      switch (dest.answhere.discrim)
2066
      {
2067
      case inreg:
2068
	{
2069
	  /* +++ if same size, paste down signed/unsigned to op */
2070
	  /* +++ paste down and adjust address as per big-endian */
2071
	  /* +++ for big-endians, use locate() */
2072
 
2073
	  sreg = reg_operand(arg, sp);
2074
	  dreg = regalt(dest.answhere);
2075
	  if (IS_R_NO_REG(dreg))
2076
	    return mka;		/* dest void */
2077
	  inmem_dest = 0;
2078
	  break;
2079
	}
2080
 
2081
      case insomereg:
2082
	{
2083
	  int *dr = someregalt(dest.answhere);
2084
 
2085
	  COMMENT("make_code chvar_tag: dest insomereg");
2086
	  sreg = reg_operand(arg, sp);
2087
	  dreg = getreg(sp.fixed);
2088
	  *dr = dreg;
2089
	  inmem_dest = 0;
2090
	  break;
2091
	}
2092
 
2093
      default:
2094
	{
2095
	  sreg = reg_operand(arg, sp);
2096
	  dreg = getreg(sp.fixed);
2097
	  inmem_dest = 1;
2098
	}
2099
      }
2100
 
2101
      COMMENT2("make_code chvar_tag: shape %d to %d", from, to);
2102
 
2103
      if (inmem_dest && size_e <= shape_size(sh(arg)))
2104
      {
2105
	/* going to smaller sized memory, store will truncate */
2106
	ans aa;
2107
 
2108
	setregalt(aa, sreg);
2109
	sp=guardreg(sreg,sp);
2110
	move(aa, dest, sp.fixed, 1);
2111
	return mka;
2112
      }
2113
 
2114
      ASSERT(from != to);		/* done above */
2115
 
2116
      /* shorten to type if needed */
2117
      adjust_to_size(from,sreg,to,dreg,NO_ERROR_JUMP);
2118
      if (inmem_dest)
2119
      {
2120
	ans aa;
2121
 
2122
	setregalt(aa, dreg);
2123
	sp=guardreg(dreg,sp);
2124
	move(aa, dest, sp.fixed, 1);
2125
      }
2126
      else
2127
      {
2128
	mka.regmove = dreg;
2129
      }
2130
 
2131
      return mka;
2132
    }				/* end chvar */
2133
/*****************************************************************************/
2134
   case minus_tag:
2135
    {
7 7u83 2136
      if (ERROR_TREATMENT(e))
2 7u83 2137
      {
2138
	mka.regmove = minus_error_treatment(e,sp,dest);
2139
      }
2140
      else
2141
      {
2142
	mka.regmove = non_comm_op(e, sp, dest, i_s);
2143
      }
2144
      return mka;
2145
    }				/* end minus */
2146
/*****************************************************************************/
2147
   case mult_tag:
2148
   case offset_mult_tag:
2149
    {
2150
      bool sgned = is_signed(sh(e));
2151
      if (ERROR_TREATMENT(e))
2152
      {
2153
	mka.regmove = mult_error_treatment(e,sp,dest);
2154
      }
2155
      else
2156
      {
2157
	mka.regmove = do_mul_comm_op(e, sp, dest, sgned);
2158
      }
2159
      return mka;
2160
    }
2161
/*****************************************************************************/
2162
   case div0_tag:
2163
   case div1_tag:
2164
   case div2_tag:
2165
   case offset_div_by_int_tag:
2166
   case offset_div_tag:
2167
    {
2168
      bool sgned = is_signed(sh(e));
2169
 
2170
      mka.regmove = do_div_op(e, sp, dest, sgned);
2171
      return mka;
2172
    }				/* end div */
2173
/*****************************************************************************/
2174
   case mod_tag:
2175
   case rem0_tag:
2176
   case rem2_tag:
2177
    {
2178
      bool sgned = is_signed(sh(e));
7 7u83 2179
 
2 7u83 2180
      mka.regmove = do_rem_op(e, sp, dest, sgned);
2181
      return mka;
2182
    }				/* end rem */
2183
/*****************************************************************************/
2184
  case neg_tag:
2185
  case offset_negate_tag:
2186
    {
2187
      if (ERROR_TREATMENT(e))
2188
      {
2189
	mka.regmove = neg_error_treatment(e,sp,dest);
2190
      }
2191
      else
2192
      {
2193
	int r = reg_operand(son(e),sp);
2194
	int destr = regfrmdest(&dest,sp);
2195
	space nsp;
2196
	ans aa;
7 7u83 2197
 
2 7u83 2198
	nsp = guardreg(destr,sp);
2199
	rr_ins(i_neg, r, destr);
2200
#if 0
2201
  tidyshort(destr, e);
2202
#endif
2203
	setregalt(aa,destr);
2204
	mka.regmove = move(aa,dest,nsp.fixed,1);
2205
	return mka;
2206
      }
2207
      return mka;
2208
    }				/* end neg */
2209
/*****************************************************************************/
2210
   case abs_tag:
2211
    {
2212
      if (ERROR_TREATMENT(e))
2213
      {
2214
	mka.regmove = abs_error_treatment(e,sp,dest);
2215
        return mka;
2216
      }
2217
      else
2218
      {
2219
	int r = reg_operand(son(e),sp);
2220
	int destr = regfrmdest(&dest,sp);
2221
	space nsp;
2222
	ans aa;
7 7u83 2223
 
2 7u83 2224
	nsp = guardreg(destr,sp);
2225
	rr_ins(i_abs, r, destr);
2226
#if 0
2227
  tidyshort(destr, e);
2228
#endif
2229
	setregalt(aa,destr);
2230
	mka.regmove = move(aa,dest,nsp.fixed,1);
2231
	return mka;
2232
      }
2233
    }
2234
/*****************************************************************************/
2235
  case shl_tag:
2236
  case shr_tag:
2237
    {
2238
      exp s = son(e);
2239
      exp b = bro(s);
2240
      int a;
2241
      int d;
2242
      ans aa;
2243
      space nsp;
2244
      bool sgned = is_signed(sh(e));
2245
      Instruction_P shift_ins;
2246
      bool record_bit = isrecordbit(e);
2247
 
7 7u83 2248
 
2 7u83 2249
#if 1
2250
      int sz = shape_size(sh(s));
2251
#if 0
7 7u83 2252
      bool lded = ((name(s) == name_tag && regofval(s) >= 100)
2253
		   || (name(s) == cont_tag &&
2254
		      (name(son(s))!= name_tag || regofval(son(s)) > 0)
2255
		      )
2256
		  );
2 7u83 2257
#endif
2258
      bool signok = (sz == 32); /* better safe than sorry for the time being */
7 7u83 2259
      if (name(son(e)) ==shl_tag && shape_size(sh(son(s)))!=32)
2 7u83 2260
      {
2261
	signok=1;
2262
      }
2263
#endif
2264
      if (ERROR_TREATMENT(e))
2265
      {
2266
	fail("Unexpected error treatment for shl");
2267
      }
7 7u83 2268
      if (name(s) ==and_tag && name(b) ==val_tag &&
2269
	 name(bro(son(s))) ==val_tag &&
2 7u83 2270
	 is_a_mask(no(bro(son(s)))) &&
7 7u83 2271
	 shape_size(sh(e)) ==32)
2 7u83 2272
      {
2273
	unsigned int mask= (unsigned int)no(bro(son(s)));
2274
	int mask_left = left_of_mask(mask);
2275
	int rotation_left;
2276
	bool use_rlinm_ins = 0;
7 7u83 2277
 
2278
	if (name(e) ==shl_tag)
2 7u83 2279
	{
2280
	  int shift_left = no(b);
2281
	  mask = mask<<shift_left;
2282
	  rotation_left = shift_left;
2283
	  use_rlinm_ins = 1;
2284
	}
2285
	else
2286
	{
2287
	  if (mask_left == 31 && is_signed(sh(e)))
2288
	  {
2289
	    use_rlinm_ins = 0;
2290
	    /* sign extension */
2291
	  }
2292
	  else
2293
	  {
2294
	    int shift_right = no(b);
2295
	    mask = mask>>shift_right;
2296
	    rotation_left = 32 - shift_right;
2297
	  }
2298
	}
7 7u83 2299
 
2 7u83 2300
	if (use_rlinm_ins==1)
2301
	{
2302
	  a = reg_operand(son(s),sp);
2303
	  d = regfrmdest(&dest,sp);
2304
 
7 7u83 2305
	  if (isrecordbit(e))
2 7u83 2306
	  {
2307
	    rlinm_ins(i_rlinm_cr,a,rotation_left,mask,d);
2308
	  }
2309
	  else
2310
	  {
2311
	    rlinm_ins(i_rlinm,a,rotation_left,mask,d);
2312
	  }
2313
	  setregalt(aa,d);
2314
	  move(aa,dest,sp.fixed,0);
7 7u83 2315
	  return mka;
2 7u83 2316
	}
2317
      }
7 7u83 2318
 
2 7u83 2319
      a = reg_operand(s, sp);
2320
 
7 7u83 2321
      if (!signok && name(e) ==shr_tag)
2 7u83 2322
      {
7 7u83 2323
	/*
2324
	 * If doing a shift right we must sign extend
2 7u83 2325
	 * or truncate prior to shifting
2326
	 */
2327
	adjust_to_size(ulonghd,a,name(sh(e)),a,NO_ERROR_JUMP);
2328
      }
2329
      if (name(e) == shr_tag)
2330
      {
7 7u83 2331
	if (record_bit==1)
2 7u83 2332
	{
7 7u83 2333
	  shift_ins = (sgned)? i_sra_cr : i_sr_cr;
2 7u83 2334
	  cr0_set = 1;
2335
	}
2336
	else
2337
	{
7 7u83 2338
	  shift_ins = (sgned)? i_sra : i_sr;
2 7u83 2339
	}
2340
      }
2341
      else
2342
      {
2343
	shift_ins = i_sl;
2344
      }
2345
      nsp = guardreg(a, sp);
2346
      d = regfrmdest(&dest,nsp);
7 7u83 2347
 
2 7u83 2348
      if (name(b) == val_tag)
2349
      {
2350
	/* Only defined for shifts by 0..31 */
2351
	int n = no(b);
2352
	int n31 = n & 31;
2353
 
2354
	if (n == 0)
2355
	{
2356
	  mov_rr_ins(a, d);comment("shift by zero so just move");
2357
	}
2358
	else if (n == n31)
2359
	{
2360
	  rir_ins(shift_ins, a, n, d);	/* usual case */
2361
	}
2362
	else
2363
	{			/* Undefined, produce same effect as if */
2364
	  ld_const_ins(0, d);	/* not a constant,0 */
7 7u83 2365
	}
2 7u83 2366
      }
2367
      else
2368
      {
2369
	int ar = reg_operand(b, nsp);
2370
	rrr_ins(shift_ins, a, ar, d);
2371
      }
7 7u83 2372
      if (!signok && name(e) ==shl_tag)
2 7u83 2373
      {
7 7u83 2374
	/*
2375
	 * If doing a shift left we must sign extend
2 7u83 2376
	 * or truncate after the shift
2377
	 */
2378
	adjust_to_size(ulonghd,d,name(sh(e)),d,NO_ERROR_JUMP);
2379
      }
2380
      setregalt(aa, d);
2381
      move(aa, dest, nsp.fixed, 1);
2382
      mka.regmove = d;
2383
      return mka;
2384
    }				/* end shl, shr */
2385
/*****************************************************************************/
2386
   case minptr_tag:
2387
   case make_stack_limit_tag:
2388
    {
2389
      mka.regmove = non_comm_op(e, sp, dest, i_s);
2390
      return mka;
2391
    }
2392
/*****************************************************************************/
2393
   case fplus_tag:
2394
    {
2395
      mka.regmove =
7 7u83 2396
	fop(e, sp, dest, is_single_precision(sh(e))? i_fa : i_fa);
2 7u83 2397
      return mka;
2398
    }
2399
/*****************************************************************************/
2400
  case fminus_tag:
2401
    {
2402
      mka.regmove =
7 7u83 2403
	fop(e, sp, dest, is_single_precision(sh(e))? i_fs : i_fs);
2 7u83 2404
      return mka;
2405
    }
2406
/*****************************************************************************/
2407
  case fmult_tag:
2408
    {
2409
      mka.regmove =
7 7u83 2410
	fop(e, sp, dest, is_single_precision(sh(e))? i_fm : i_fm);
2 7u83 2411
      return mka;
2412
    }
2413
/*****************************************************************************/
2414
  case fdiv_tag:
2415
    {
2416
      mka.regmove =
7 7u83 2417
	fop(e, sp, dest, is_single_precision(sh(e))? i_fd : i_fd);
2 7u83 2418
      return mka;
2419
    }
2420
/*****************************************************************************/
2421
  case fneg_tag:
2422
    {
2423
      mka.regmove =
7 7u83 2424
	fmop(e, sp, dest, is_single_precision(sh(e))? i_fneg : i_fneg);
2 7u83 2425
      return mka;
2426
    }
2427
/*****************************************************************************/
2428
  case fabs_tag:
2429
    {
2430
      mka.regmove =
7 7u83 2431
	fmop(e, sp, dest, is_single_precision(sh(e))? i_fabs : i_fabs);
2 7u83 2432
      return mka;
2433
    }
2434
/*****************************************************************************/
2435
  case float_tag:
2436
    {
2437
      exp in = son(e);
7 7u83 2438
      int f = (dest.answhere.discrim == infreg)?
2 7u83 2439
		fregalt(dest.answhere).fr :
2440
		getfreg(sp.flt);
2441
      freg frg;
2442
      ans aa;
2443
      bool from_sgned = is_signed(sh(in));
2444
 
2445
      frg.fr = f;
2446
      frg.dble = is_double_precision(sh(e));
2447
 
2448
      if (from_sgned)
2449
      {
2450
	/* signed 32 bit to real */
2451
	int r = reg_operand(in, sp);
2452
	int f1 = getfreg(guardfreg(f, sp).flt);
2453
 
2454
	ld_const_ins(0x43300000, R_TMP0);
2455
	st_ro_ins(i_st, R_TMP0, mem_temp(0));comment(NIL);
2456
	ld_const_ins(0x80000000, R_TMP0);
2457
	st_ro_ins(i_st, R_TMP0, mem_temp(4));comment(NIL);
2458
	ldf_ro_ins(i_lfd, mem_temp(0), f);
2459
	rir_ins(i_xor, r, 0x80000000, R_TMP0);
2460
	st_ro_ins(i_st, R_TMP0, mem_temp(4));comment(NIL);
2461
	ldf_ro_ins(i_lfd, mem_temp(0), f1);
2462
	rrrf_ins(i_fs, f1, f, f);
2463
      }
2464
      else
2465
      {
2466
	/* unsigned 32 bit to real */
2467
	int r = reg_operand(in, sp);
2468
	int f1 = getfreg(guardfreg(f, sp).flt);
2469
 
2470
	ld_const_ins(0x43300000, R_TMP0);
2471
	st_ro_ins(i_st, R_TMP0, mem_temp(0));comment(NIL);
2472
	ld_const_ins(0x0, R_TMP0);
2473
	st_ro_ins(i_st, R_TMP0, mem_temp(4));comment(NIL);
2474
	ldf_ro_ins(i_lfd, mem_temp(0), f);
2475
	st_ro_ins(i_st, r, mem_temp(4));comment(NIL);
2476
	ldf_ro_ins(i_lfd, mem_temp(0), f1);
2477
	rrrf_ins(i_fs, f1, f, f);
2478
      }
2479
 
2480
      setfregalt(aa, frg);
2481
      move(aa, dest, sp.fixed, 1);
7 7u83 2482
      mka.regmove = (frg.dble)? - (f + 32):(f + 32);
2 7u83 2483
      return mka;
2484
    }
2485
/*****************************************************************************/
2486
  case chfl_tag:
2487
    {
2488
      int to = name(sh(e));
2489
      int from = name(sh(son(e)));
2490
      bool dto = (to != shrealhd);
2491
      bool dfrom = (from != shrealhd);
7 7u83 2492
 
2 7u83 2493
      if (dto==dfrom)
2494
      {
2495
	/* no change in representation */
2496
	return make_code(son(e), sp, dest, exitlab);
2497
      }
2498
      else
2499
      {
2500
	freg frg;
2501
	ans aa;
2502
	where w;
2503
 
2504
	frg = fregfrmdest(dfrom,&dest,sp);
2505
	setfregalt(aa, frg);
2506
	w.answhere = aa;
2507
	w.ashwhere = ashof(sh(son(e)));
2508
	code_here(son(e), sp, w);
7 7u83 2509
	if (to==shrealhd)
2 7u83 2510
	{
2511
	  if (ERROR_TREATMENT(e))
2512
	  {
2513
	    chfl_error_treatment(e,frg.fr);
2514
	  }
2515
	  else
2516
	  {
2517
	    rrf_ins(i_frsp,frg.fr,frg.fr);
2518
	  }
2519
	}
2520
	frg.dble = dto;
2521
	setfregalt(aa, frg);
2522
	move(aa, dest, sp.fixed, 1);
7 7u83 2523
	mka.regmove = (frg.dble)? - (frg.fr + 32):(frg.fr + 32);
2 7u83 2524
	return mka;
2525
      }
2526
    }
2527
/*****************************************************************************/
2528
  case and_tag:
2529
    {
2530
      exp arg1 = son(e);
2531
      exp arg2 = bro(arg1);
7 7u83 2532
 
2533
      if (name(arg2) ==val_tag &&
2 7u83 2534
	  is_a_mask(no(arg2)) &&
7 7u83 2535
	  shape_size(sh(e)) ==32 &&
2536
	 (name(arg1) ==shl_tag || name(arg1) ==shr_tag) &&
2537
	  name(bro(son(arg1))) ==val_tag)
2 7u83 2538
      {
2539
	unsigned int mask = (unsigned int)no(arg2);
2540
	int mask_left = left_of_mask(mask);
2541
	int mask_right = right_of_mask(mask);
2542
	bool use_rlinm_ins = 0;
2543
	long rotation_left;
7 7u83 2544
 
2545
	if (name(arg1) ==shl_tag)
2 7u83 2546
	{
2547
	  int shift_left = no(bro(son(arg1)));
2548
	  if (shift_left<=mask_right)
2549
	  {
2550
	    rotation_left = shift_left;
2551
	    use_rlinm_ins=1;
2552
	  }
2553
	}
7 7u83 2554
	else if (name(arg1) ==shr_tag)
2 7u83 2555
	{
2556
	  int shift_right = no(bro(son(arg1)));
7 7u83 2557
	  if (shift_right<= (31-mask_left))
2 7u83 2558
	  {
2559
	    rotation_left = 32 - shift_right;
2560
	    use_rlinm_ins=1;
2561
	  }
2562
	}
7 7u83 2563
 
2 7u83 2564
	if (use_rlinm_ins==1)
2565
	{
2566
	  int r = reg_operand(son(arg1),sp);
2567
	  int dr = regfrmdest(&dest,sp);
2568
	  ans aa;
7 7u83 2569
 
2570
	  if (isrecordbit(e))
2 7u83 2571
	  {
2572
	    rlinm_ins(i_rlinm_cr,r,rotation_left,mask,dr);
2573
	  }
2574
	  else
2575
	  {
2576
	    rlinm_ins(i_rlinm,r,rotation_left,mask,dr);
2577
	  }
2578
	  setregalt(aa,dr);
2579
	  move(aa,dest,sp.fixed,0);
2580
	  return mka;
2581
	}
2582
      }
7 7u83 2583
 
2584
 
2585
 
2586
      if (isrecordbit(e))
2 7u83 2587
      {
2588
	mka.regmove = comm_op(e, sp, dest, i_and_cr);
2589
	cr0_set = 1;
2590
      }
2591
      else
2592
      {
2593
	mka.regmove = comm_op(e, sp, dest, i_and);
2594
      }
7 7u83 2595
 
2 7u83 2596
      return mka;
2597
    }
2598
/*****************************************************************************/
2599
  case or_tag:
2600
    {
2601
      mka.regmove = comm_op(e, sp, dest, i_or);
2602
      return mka;
2603
    }
2604
/*****************************************************************************/
2605
  case xor_tag:
2606
    {
2607
      mka.regmove = comm_op(e, sp, dest, i_xor);
2608
      return mka;
2609
    }
2610
/*****************************************************************************/
2611
  case not_tag:
2612
    {
2613
      /* i_not is a pseudo instruction expanded to sfi dest,-1,src */
2614
      int a1=reg_operand(son(e),sp);
2615
      ans aa;
2616
      int d=regfrmdest(&dest,sp);
2617
 
2618
      rr_ins(i_not,a1,d);
2619
      adjust_to_size(ulonghd,d,name(sh(e)),d,NO_ERROR_JUMP);
2620
      setregalt(aa,d);
2621
      move(aa,dest,guardreg(d,sp).fixed,1);
7 7u83 2622
      mka.regmove =d;
2623
 
2 7u83 2624
      return mka;
2625
    }
2626
/*****************************************************************************/
2627
  case cont_tag:
2628
  case contvol_tag:
2629
    {
2630
      if (name(e) == contvol_tag)
2631
      {
2632
	/*
2633
	 * Load contents of volatile location. Diasble register-location
2634
	 * tracing. Disable peep-hole optimisation (not possible with POWER
2635
	 * assembler).
2636
	 */
2637
	COMMENT("make_code: Load volatile");
2638
	clear_all();
2639
      }
2640
      /*
7 7u83 2641
       * Check to see if we can use
2642
       * [reg+reg] addressing for this load
2 7u83 2643
       */
2644
      if (name(son(e)) == addptr_tag)
2645
      {
2646
	shape cont_shape = sh(e);
2647
	int cont_size = shape_size(cont_shape);
2648
	int cont_align = shape_align(cont_shape);
2649
	exp addptr_sons = son(son(e));
2650
	bool is_float = is_floating(name(cont_shape));
2651
 
2652
	if (last(bro(addptr_sons))
2653
	    && cont_align == cont_size
2654
	    && (cont_size==8 || cont_size==16 || cont_size==32 || is_float))
2655
	{
2656
	  int lhsreg;
2657
	  int rhsreg;
2658
	  bool sgned = (cont_size >= 32) || is_signed(cont_shape);
2659
	  ans aa;
2660
 
2661
	  COMMENT("make_code: load suitable for [reg+reg] addressing");
2662
 
2663
	  lhsreg = reg_operand(addptr_sons, sp);
2664
	  rhsreg = reg_operand(bro(addptr_sons), guardreg(lhsreg, sp));
2665
 
2666
	  if (is_float)
2667
	  {
2668
	    freg dfreg;
2669
 
2670
	    if (dest.answhere.discrim == infreg)
2671
	    {
2672
	      dfreg = fregalt(dest.answhere);
2673
	    }
2674
	    else
2675
	    {
2676
	      dfreg.fr = getfreg(sp.flt);
2677
	    }
2678
	    dfreg.dble = (cont_size==64);
2679
	    ldf_rr_ins((dfreg.dble?i_lfd :i_lfs), lhsreg, rhsreg, dfreg.fr);
2680
	    setfregalt(aa, dfreg);
2681
	  }
2682
	  else
2683
	  {
2684
	    int dreg = regfrmdest(&dest,sp);
7 7u83 2685
 
2 7u83 2686
	    ld_rr_ins(i_ld_sz(cont_size,sgned), lhsreg, rhsreg, dreg);
2687
	    if (sgned && cont_size==8)
2688
	    {
2689
	      /* No load signed byte instruction, so propagate sign
2690
	       */
2691
	      adjust_to_size(ulonghd,dreg,scharhd,dreg,NO_ERROR_JUMP);
2692
	    }
2693
	    setregalt(aa, dreg);
2694
	  }
2695
 
2696
	  mka.regmove = move(aa, dest, sp.fixed, sgned);
2697
	  if (name(e) == contvol_tag)
2698
	    mka.regmove = NOREG;
2699
	  return mka;
2700
	}
2701
      }
2702
    }
2703
    /*FALLTHROUGH*/
2704
   case name_tag:
2705
   case field_tag:
2706
   case reff_tag:
2707
   case addptr_tag:
2708
   case subptr_tag:
2709
    {
2710
      where w;
2711
      bool sgned;
7 7u83 2712
      int dr = (dest.answhere.discrim == inreg)? dest.answhere.val.regans : 0;
2 7u83 2713
      w = locate(e, sp, sh(e), dr);		/* address of arg */
2714
      sgned = (w.ashwhere.ashsize >= 32) || is_signed(sh(e));
2715
      /* +++ load real into float reg, move uses fixed reg */
7 7u83 2716
      mka.regmove = move(w.answhere, dest,(guard(w, sp)).fixed, sgned);
2 7u83 2717
      if (name(e) == contvol_tag)
2718
	mka.regmove = NOREG;
2719
      return mka;
2720
    }				/* end cont */
2721
/*****************************************************************************/
2722
  case string_tag:
2723
  case real_tag:
2724
    {
2725
      instore isa;
2726
      ans aa;
2727
      bool sgned = ((ashof(sh(e)).ashsize >= 32) || is_signed(sh(e)));
7 7u83 2728
 
2 7u83 2729
      /*
7 7u83 2730
       * Place constant in appropriate data segment
2 7u83 2731
       */
2732
      isa = evaluated_const(e);
2733
      setinsalt(aa, isa);
2734
      mka.regmove = move(aa, dest, sp.fixed, sgned);
2735
      return mka;
2736
    }				/* end eval */
2737
/*****************************************************************************/
2738
  case val_tag:
2739
    {
2740
      int size = shape_size(sh(e));
2741
 
7 7u83 2742
 
2743
      if (size == 64)
2 7u83 2744
      {
2745
        /* could be evaluating into nowhere so check
2746
           to see it is trying to evaluate into a genuine place */
7 7u83 2747
        if (dest.answhere.discrim==notinreg)
2 7u83 2748
        {
2749
          flt64 temp;
2750
          int ov;
2751
          int r = getreg(sp.fixed);
2752
          space nsp;
2753
          ans aa;
2754
          if (isbigval(e)) {
2755
	  temp = flt_to_f64(no(e), 0, &ov);
2756
          }
2757
          else {
7 7u83 2758
            temp.big = (is_signed(sh(e)) && no(e) <0)?-1:0;
2 7u83 2759
            temp.small = no(e);
2760
          }
2761
          nsp = guardreg(r, sp);
2762
          ld_const_ins(temp.small,r);
2763
          setregalt(aa,r);
2764
          dest.ashwhere.ashsize = 32;
2765
          dest.ashwhere.ashalign = 32;
2766
          move(aa,dest,nsp.fixed,1);
2767
          ld_const_ins(temp.big,r);
2768
          ASSERT(dest.answhere.discrim==notinreg);
2769
          dest.answhere.val.instoreans.b.offset+=4;
2770
          move(aa,dest,nsp.fixed,1);
2771
        }
7 7u83 2772
 
2773
	return mka;
2 7u83 2774
      }
2775
      else  if (no(e) == 0)
2776
      {
2777
	goto moveconst_zero;
2778
      }
2779
      else
2780
      {
2781
	if (size == 32 || !is_signed(sh(e)))
2782
	{
2783
	  /* 32 bit size or unsigned */
2784
	  constval = no(e);
2785
	}
2786
	else if (size == 8)
2787
	{
2788
	  constval = no(e) & 255;
2789
	  constval -= (constval & 128) << 1;
2790
	}
2791
	else if (size == 16)
2792
	{
2793
	  constval = no(e) & 65535;
2794
	  constval -= (constval & 32768) << 1;
2795
	}
2796
	else
2797
	{
2798
	  fail("make_code val_tag: unexpected bit size");
2799
	}
2800
	goto moveconst;
2801
      }
2802
    }
2803
/*****************************************************************************/
2804
    case top_tag:
2805
    case prof_tag:
2806
    {
2807
      return mka;
2808
    }
2809
/*****************************************************************************/
2810
  case null_tag:
2811
    {
2812
      goto moveconst_zero;
2813
    }
2814
/*****************************************************************************/
2815
  case round_tag:
2816
    {
2817
      int sfr;
2818
      int destr;
2819
      ans aa;
2820
      bool changed_mode = 0;
2821
      bool call_fctiwz =0;
2822
      int ifr = getfreg(sp.flt);
2823
 
2824
      sfr = freg_operand(son(e), sp, getfreg(sp.flt));
2825
      /* Doesn't matter if sfr and ifr same */
7 7u83 2826
      switch (round_number(e))
2 7u83 2827
      {
2828
        case R2ZERO:call_fctiwz=1;break;
2829
        case R2NEAR:break;
2830
        case R2PINF:mtfsb1_ins(30);mtfsb0_ins(31);changed_mode=1;break;
2831
        case R2NINF:mtfsb1_ins(30);mtfsb1_ins(31);changed_mode=1;break;
2832
        case 4: break;
2833
        default: fail("Unknown rounding mode");break;
2834
      }
2835
      /* can use fctiw command */
7 7u83 2836
 
2 7u83 2837
      destr=regfrmdest(&dest,sp);
2838
      rrf_ins(call_fctiwz?i_fctiwz:i_fctiw,sfr,ifr);
2839
      stf_ins(i_stfd,ifr,mem_temp(0));
2840
      ld_ro_ins(i_l,mem_temp(4),destr);comment(NIL);
2841
 
7 7u83 2842
      if (changed_mode)
2 7u83 2843
      {
2844
	/* put it back to round_to_nearest */
2845
	mtfsb0_ins(30);mtfsb0_ins(31);
2846
      }
2847
      adjust_to_size(ulonghd,destr,name(sh(e)),destr,NO_ERROR_JUMP);
7 7u83 2848
      setregalt(aa, destr);
2 7u83 2849
      mka.regmove = move(aa, dest, sp.fixed, 1);
2850
      return mka;
2851
    }
2852
/*****************************************************************************/
2853
     case int_to_bitf_tag:
2854
    {
2855
      int r;
2856
      int size_res = shape_size(sh(e));
2857
      int size_op = shape_size(sh(son(e)));
2858
      ans aa;
2859
      space nsp;
2860
 
2861
      r = reg_operand(son(e), sp);
2862
 
2863
      COMMENT2("make_code int_to_bitf_tag: size %d -> %d", size_op, size_res);
2864
 
2865
      /* maybe this not needed if going to memory +++ */
2866
      if (size_res != size_op && size_res != 32)
2867
      {
2868
	int destr;
2869
 
2870
	switch (dest.answhere.discrim)
2871
	{
2872
	case inreg:
2873
	  {
2874
	    destr = regalt(dest.answhere);
2875
	    break;
2876
	  }
2877
	default:
2878
	  {
2879
	    destr = getreg(sp.fixed);
2880
	  }
2881
	}
2882
 
7 7u83 2883
	rir_ins(i_and, r,(1 << size_res) - 1, destr);
2 7u83 2884
	r = destr;
2885
      }
2886
 
2887
      /* r is appropriately truncated operand */
2888
 
2889
      nsp = guardreg(r, sp);
2890
      setregalt(aa, r);
2891
      move(aa, dest, nsp.fixed, 0);
2892
      return mka;
2893
    }
2894
/*****************************************************************************/
2895
  case bitf_to_int_tag:
2896
    {
2897
      ash a;
2898
      int r;
2899
      where w;
2900
      bool src_sgned = name(sh(son(e))) & 1;
2901
      bool target_sgned = name(sh(e)) & 1;
2902
 
2903
      a = ashof(sh(son(e)));
2904
      switch (dest.answhere.discrim)
2905
      {
2906
      case inreg:
2907
	{
2908
	  r = regalt(dest.answhere);
2909
	  break;
2910
	}
2911
      default:
2912
	{
2913
	  r = getreg(sp.fixed);
2914
	}
2915
      }
2916
 
2917
      setregalt(w.answhere, r);
2918
      w.ashwhere = a;
2919
      code_here(son(e), sp, w);
2920
 
2921
      COMMENT1("make_code bitsint_tag: size=%d", a.ashsize);
2922
 
2923
      if (a.ashsize != 32 && src_sgned != target_sgned)
2924
      {
2925
	/* propogate/correct sign bits */
2926
	/* +++ make move() handle this by pasting sign down */
2927
	ash atarget;
2928
	atarget = ashof(sh(e));
2929
 
2930
	COMMENT4("make_code bitsint_tag: adjusting to sign/size %d/%d -> %d/%d",
2931
		src_sgned, a.ashsize,
2932
		target_sgned, atarget.ashsize);
2933
 
2934
	if (target_sgned)
2935
	{
2936
	  if (32 - a.ashsize == 16)
2937
	  {
2938
	    rr_ins(i_exts, r, r);
2939
	  }
2940
	  else
2941
	  {
2942
	    rir_ins(i_sl, r, 32 - a.ashsize, r);
2943
	    rir_ins(i_sra, r, 32 - a.ashsize, r);
2944
	  }
2945
	}
2946
	else
2947
	{
7 7u83 2948
	  rir_ins(i_and, r,((1 << a.ashsize) - 1), r);
2 7u83 2949
	}
2950
      }
2951
 
2952
      move(w.answhere, dest, guardreg(r, sp).fixed, 0);
2953
      keepreg(e, r);
2954
      return mka;
2955
    }
2956
/*****************************************************************************/
2957
   case movecont_tag:
2958
    {
2959
      exp szarg = bro(bro(son(e)));
2960
      int dr,sr,szr;
2961
      int lout=new_label();
2962
      int creg=next_creg();
2963
      space nsp;
2964
      int bytemove;
2965
      where w;
7 7u83 2966
 
2 7u83 2967
      sr = getreg(sp.fixed);
2968
      setregalt(w.answhere, sr);
2969
      w.ashwhere = ashof(sh(son(e)));
7 7u83 2970
      make_code(son(e), sp, w, 0);
2 7u83 2971
      nsp = guardreg(sr,sp);
2972
      dr = getreg(nsp.fixed);
2973
      setregalt(w.answhere, dr);
7 7u83 2974
      make_code(bro(son(e)), nsp, w, 0);
2 7u83 2975
      nsp = guardreg(dr,nsp);
2976
      w.ashwhere = ashof(sh(bro(bro(son(e)))));
2977
      szr = getreg(nsp.fixed);
2978
      setregalt(w.answhere, szr);
7 7u83 2979
     (void)make_code(szarg, nsp, w, 0);
2 7u83 2980
      nsp = guardreg(szr, nsp);
7 7u83 2981
      bytemove = (al2(sh(szarg)) >>3);
2 7u83 2982
#if 0
2983
      clear_dep_reg(son(e));
2984
      clear_dep_reg(bro(son(e)));
2985
#else
2986
      clear_all();
2987
#endif
7 7u83 2988
      if (name(szarg)!= val_tag || no(szarg) == 0) {
2 7u83 2989
	cmp_ri_ins(i_cmp, szr, 0, creg);
2990
	bc_ins(i_beq, creg, lout,UNLIKELY_TO_JUMP);
7 7u83 2991
      }
2 7u83 2992
      if (isnooverlap(e)) {
2993
	move_dlts(dr,sr,szr, bytemove);
2994
      }
2995
      else {
2996
	int gtlab = new_label();
2997
	int creg2 = next_creg();
2998
	cmp_rr_ins(i_cmp, dr, sr,creg2);
2999
	bc_ins(i_bgt, creg2, gtlab,LIKELY_TO_JUMP);
3000
	move_dlts(dr,sr,szr, bytemove);
3001
	uncond_ins(i_b, lout);
3002
	set_label(gtlab);
3003
	move_dgts(dr,sr,szr, bytemove);
7 7u83 3004
      }
2 7u83 3005
      set_label(lout);
3006
      return mka;
3007
    }
3008
 
3009
/*****************************************************************************/
3010
   case offset_pad_tag:
3011
    {
3012
      int r;
3013
      int v;
7 7u83 3014
      ans aa;
3015
      if (al2(sh(son(e))) >= al2(sh(e)))
2 7u83 3016
      {
7 7u83 3017
	if (al2(sh(e))!= 1 || al2(sh(son(e))) == 1)
2 7u83 3018
	{
3019
	  /*
7 7u83 3020
	   * Is already aligned correctly,
2 7u83 3021
	   * whether as bit or byte-offset
3022
	   */
3023
	  e = son(e); goto tailrecurse;
3024
	}
3025
	r = regfrmdest(&dest, sp);
3026
	v = reg_operand(son(e), sp);
7 7u83 3027
	rir_ins(i_sl,  v, 3 ,r);
2 7u83 3028
      }
3029
      else {
7 7u83 3030
	int al = (al2(sh(son(e))) ==1)?al2(sh(e)):(al2(sh(e)) /8);
2 7u83 3031
	r = regfrmdest(&dest, sp);
7 7u83 3032
	v = reg_operand(son(e), sp);
2 7u83 3033
	rir_ins(i_a, v, al-1, r);
3034
	rir_ins(i_and, r, -al ,r);
7 7u83 3035
	if (al2(sh(son(e))) ==1)
3036
	{ /*
2 7u83 3037
	   * operand is bit-offset,
7 7u83 3038
	   * byte-offset required
2 7u83 3039
	   */
3040
	  rir_ins(i_sra, r, 3 ,r);
3041
	}
3042
      }
3043
      setregalt(aa,r);
3044
      mka.regmove = move(aa, dest, guardreg(r,sp).fixed, 0);
3045
      return mka;
3046
    }
3047
/*****************************************************************************/
7 7u83 3048
 
2 7u83 3049
   case min_tag:
3050
   case max_tag:
3051
   case offset_max_tag:
3052
    {
3053
      ans aa;
3054
      int left;
3055
      int right;
3056
      int r=regfrmdest(&dest, sp);
3057
      int creg;
3058
      int lab;
7 7u83 3059
 
2 7u83 3060
      space nsp;
3061
      if (IsRev(e))
3062
      {
3063
	right=reg_operand(bro(son(e)),sp);
3064
	nsp=guardreg(right,sp);
3065
	left=reg_operand(son(e),nsp);
3066
      }
3067
      else
3068
      {
3069
	left=reg_operand(son(e),sp);
3070
	nsp=guardreg(left,sp);
3071
	right=reg_operand(bro(son(e)),nsp);
3072
      }
3073
      creg = next_creg();
3074
      lab = new_label();
3075
      cmp_rr_ins(i_cmp,left,right,creg);
3076
      mov_rr_ins(left,r);comment(NIL);
7 7u83 3077
      if (name(e) ==min_tag)
2 7u83 3078
      {
3079
	bc_ins(i_blt,creg,lab,LIKELY_TO_JUMP);
3080
      }
3081
      else
3082
      {
7 7u83 3083
	bc_ins(i_bgt,creg,lab,LIKELY_TO_JUMP);
2 7u83 3084
      }
3085
      mov_rr_ins(right,r);comment(NIL);
3086
      set_label(lab);
3087
      setregalt(aa,r);
3088
      move(aa, dest,guardreg(r,sp).fixed , 0);
3089
      mka.regmove = r;
3090
      return mka;
3091
    }
3092
/*****************************************************************************/
3093
   case offset_add_tag:
3094
    {
3095
      /*
7 7u83 3096
       * byte offset + bit offset
2 7u83 3097
       * all others converted to plus_tag by needscan
3098
       * The byte offset must be converted into bits for
3099
       * the addition
3100
       */
3101
      exp byte_offset = son(e);
3102
      exp bit_offset = bro(byte_offset);
3103
      int destr = regfrmdest(&dest,sp);
3104
      int byte_offset_reg = reg_operand(byte_offset, sp);
3105
      int bit_offset_reg;
3106
      space nsp;
3107
      ans aa;
3108
      nsp = guardreg(destr, sp);
3109
 
7 7u83 3110
      rir_ins(i_sl , byte_offset_reg , 3 , destr);
3111
      if (name(bit_offset) ==val_tag)
2 7u83 3112
      {
7 7u83 3113
	if (no(bit_offset)!=0)
2 7u83 3114
	{
7 7u83 3115
	  rir_ins(i_a, destr , no(bit_offset), destr);
2 7u83 3116
	}
3117
      }
7 7u83 3118
      else
2 7u83 3119
      {
3120
	bit_offset_reg = reg_operand(bit_offset, nsp);
3121
	rrr_ins(i_a, destr , bit_offset_reg , destr);
3122
      }
3123
      setregalt(aa, destr);
3124
      mka.regmove = move(aa, dest, nsp.fixed, 0);
3125
      return mka;
3126
    }
3127
/*****************************************************************************/
7 7u83 3128
   case offset_subtract_tag:
3129
    {
2 7u83 3130
     /*
3131
      * bit offset - byte offset
3132
      * all others converted to minus_tag by needscan
3133
      */
3134
     exp bit_offset = son(e);
3135
     exp byte_offset = bro(bit_offset);
7 7u83 3136
     int destr = regfrmdest(&dest, sp);
2 7u83 3137
     int byte_offset_reg = reg_operand(byte_offset, sp);
3138
     int bit_offset_reg;
3139
     space nsp;
3140
     ans aa;
7 7u83 3141
     nsp = guardreg(destr,sp);
3142
 
2 7u83 3143
     rir_ins(i_sl, byte_offset_reg , 3 , destr);
7 7u83 3144
     if (name(bit_offset) ==val_tag)
2 7u83 3145
     {
7 7u83 3146
       if (no(bit_offset)!=0)
2 7u83 3147
       {
3148
	 rir_ins(i_s,destr,no(bit_offset),destr);
3149
       }
3150
     }
3151
     else
3152
     {
3153
       bit_offset_reg = reg_operand(bit_offset, nsp);
3154
       rrr_ins(i_s, destr, bit_offset_reg, destr);
3155
     }
3156
     setregalt(aa, destr);
3157
     mka.regmove = move(aa, dest, nsp.fixed, 0);
3158
     return mka;
3159
   }
3160
/*****************************************************************************/
3161
   case current_env_tag:
3162
    {
3163
      int r=regfrmdest(&dest, sp);
3164
      ans aa;
7 7u83 3165
      if (p_has_fp)
2 7u83 3166
      {
3167
       	mov_rr_ins(R_FP,r);comment("move FP to register");
3168
      }
3169
      else
3170
      {
3171
	/* If we don't have a frame pointer we give the location
3172
	   of where the frame pointer would be anyway */
7 7u83 3173
	rir_ins(i_a , R_SP, p_frame_size , r);
2 7u83 3174
      }
3175
      setregalt(aa, r);
3176
      mka.regmove = move(aa, dest, sp.fixed, 0);
3177
      return mka;
3178
    }
3179
/*****************************************************************************/
3180
   case env_offset_tag:
3181
    {
3182
      /* NOTE: env_offset works in conjunction with current_env.
3183
	 So it must be consistent with current env */
3184
      constval = frame_offset(son(e));
3185
      goto moveconst;
3186
    }
3187
/*****************************************************************************/
3188
   case goto_lv_tag:
3189
    {
3190
      int r = reg_operand(son(e),sp);
3191
 
3192
      mt_ins(i_mtctr, r);
3193
      z_ins(i_bctr);
3194
      clear_all();
3195
      return mka;
3196
    }
3197
/*****************************************************************************/
3198
   case make_lv_tag:
3199
    {
3200
      int r = regfrmdest(&dest,sp);
3201
      int next_mlv_number = get_next_mlv_number();
3202
      ans aa;
3203
      long marked_label= no(son(pt(e)));
3204
 
3205
      fprintf(as_file,"\t.toc\n");
3206
      fprintf(as_file,"T.make_lv%d:\t.tc\tL.%d[TC],L.%d\n",
3207
	      next_mlv_number,(int)marked_label,(int)marked_label);
3208
      fprintf(as_file, "\t.csect\t[PR]\n");
3209
      fprintf(as_file, "\t%s\t%d,T.make_lv%d(2)\n",
3210
	      get_instruction(i_l),r,next_mlv_number);
3211
      clear_reg(r);
3212
      setregalt(aa,r);
3213
      move(aa,dest, guardreg(r,sp).fixed, 0);
3214
      mka.regmove = r;
3215
      return mka;
3216
    }
3217
/*****************************************************************************/
3218
   case long_jump_tag:
3219
    {
3220
     int fp = reg_operand(son(e), sp);
3221
     int labval = reg_operand(bro(son(e)), sp);
7 7u83 3222
     /*
3223
      * Long jumps are always done through the frame pointer
2 7u83 3224
      * since you cannot tell whether or not you are going in
3225
      * to a proc which needs a frame pointer or not
3226
      * so it is made sure that any procedure that has
3227
      * make_local_lv and current_env is forced to have a
3228
      * frame pointer.
3229
      */
3230
     FULLCOMMENT("long_jump");
3231
     mov_rr_ins(fp,R_FP);comment("move register to FP");
3232
     mt_ins(i_mtctr, labval);
3233
     z_ins(i_bctr);
3234
     clear_all();
3235
     return mka;
3236
   }
3237
/*****************************************************************************/
3238
   case alloca_tag:
3239
    {
3240
      int dreg = regfrmdest(&dest,sp);
3241
      ans aa;
7 7u83 3242
      int xdreg = (IS_R_TMP(dreg) && checkalloc(e))? getreg(sp.fixed): dreg;
3243
 
2 7u83 3244
      ASSERT(p_has_alloca);
3245
      ASSERT(p_has_fp);
3246
 
3247
 
7 7u83 3248
 
3249
      if (name(son(e)) ==val_tag)
2 7u83 3250
      {
3251
	/* allocate constant number of bytes on stack*/
3252
	int no_of_bytes = ALLOCA_ALIGNMENT(no(son(e)));
7 7u83 3253
	if (checkalloc(e))
2 7u83 3254
	{
7 7u83 3255
	  rir_ins(i_a,R_SP,- (long)no_of_bytes,xdreg);
2 7u83 3256
	}
3257
	else
3258
	{
7 7u83 3259
	  rir_ins(i_a,R_SP,- (long)no_of_bytes,R_SP);
2 7u83 3260
	}
3261
      }
3262
      else
3263
      {
3264
	int nreg = reg_operand(son(e),sp);
3265
	/* adjust to correct alignment, i.e mul of 8 */
3266
	rir_ins(i_a,nreg,7,R_TMP0);
3267
	rir_ins(i_and,R_TMP0,~7,R_TMP0);
3268
	if (checkalloc(e))
3269
	{
3270
	  rrr_ins(i_sf,R_TMP0,R_SP,xdreg);
3271
	}
3272
	else
3273
	{
3274
	  rrr_ins(i_sf,R_TMP0,R_SP,R_SP);
3275
	}
7 7u83 3276
 
2 7u83 3277
      }
3278
      if (checkalloc(e))
3279
      {
3280
	baseoff b;
3281
	int cr;
3282
	int slab;
3283
	b = find_tg("__TDFstacklim");
3284
	cr = next_creg();
7 7u83 3285
 
2 7u83 3286
	slab = get_stack_overflow_lab();
3287
	ld_ins(i_l,b,R_TMP0);
3288
	cmp_rr_ins(i_cmp,xdreg,R_TMP0,cr);
3289
	bc_ins(i_blt,cr,slab,UNLIKELY_TO_JUMP);
3290
	mov_rr_ins(xdreg,R_SP);comment(NIL);
3291
      }
3292
 
7 7u83 3293
 
3294
 
2 7u83 3295
      if (p_args_and_link_size==0)
3296
      {
3297
	mov_rr_ins(R_SP,dreg);comment(NIL);
3298
      }
3299
      else
3300
      {
3301
	rir_ins(i_a, R_SP, p_args_and_link_size,dreg);
3302
      }
7 7u83 3303
      if (p_has_back_chain)
2 7u83 3304
      {
3305
	save_back_chain_using_frame_pointer();
3306
      }
7 7u83 3307
      if (p_has_saved_sp)
2 7u83 3308
      {
3309
	save_sp_on_stack();
3310
      }
3311
      setregalt(aa,dreg);
3312
      move(aa,dest,guardreg(dreg,sp).fixed,0);
3313
      return mka;
3314
    }
3315
/*****************************************************************************/
3316
   case last_local_tag:
3317
    {
3318
      int r = regfrmdest(&dest, sp);
3319
      ans aa;
3320
      /* The last pointer returned by alloca is placed into r */
3321
 
7 7u83 3322
      if (p_args_and_link_size !=0)
2 7u83 3323
      {
3324
	rir_ins(i_a, R_SP, p_args_and_link_size, r);
3325
      }
3326
      else
3327
      {
7 7u83 3328
	mov_rr_ins(R_SP , r);comment(NIL);
2 7u83 3329
      }
3330
      setregalt(aa, r);
3331
      mka.regmove = move(aa, dest, sp.fixed, 1);
3332
      return mka;
3333
    }
3334
/*****************************************************************************/
3335
   case local_free_all_tag:
3336
    {
7 7u83 3337
      if (p_has_alloca)
2 7u83 3338
      {
3339
	/* The stack pointer is returned to how it was before
3340
	   any calls to alloca were made */
3341
	rir_ins(i_a , R_FP,- p_frame_size ,R_SP);
3342
	if (p_has_back_chain)
3343
	{
3344
	  save_back_chain_using_frame_pointer();
3345
	}
7 7u83 3346
	if (p_has_saved_sp)
2 7u83 3347
	{
3348
	  save_sp_on_stack();
3349
	}
3350
      }
3351
      return mka;
3352
    }
3353
/*****************************************************************************/
3354
   case local_free_tag:
3355
    {
3356
      int r;
3357
      int off;
3358
      space nsp;
7 7u83 3359
 
2 7u83 3360
      ASSERT(p_has_alloca);
7 7u83 3361
      r = reg_operand(son(e), sp);
2 7u83 3362
      /* r is a pointer returned by alloca
3363
	 off is the number of bytes to free up */
7 7u83 3364
      if (name(bro(son(e))) ==val_tag)
2 7u83 3365
      {
3366
	int displacement=ALLOCA_ALIGNMENT(no(bro(son(e))));
3367
	displacement -= p_args_and_link_size;
7 7u83 3368
	if (displacement!=0)
2 7u83 3369
	{
3370
	  rir_ins(i_a,r,displacement,R_SP);
3371
	}
3372
	else
3373
	{
3374
	  mov_rr_ins(r,R_SP);comment(NIL);
3375
	}
3376
      }
3377
      else
7 7u83 3378
      {
2 7u83 3379
	nsp=guardreg(r,sp);
3380
	off = reg_operand(bro(son(e)),nsp);
7 7u83 3381
 
2 7u83 3382
	rir_ins(i_a,off,7,off);
3383
	rir_ins(i_and,off,~7,off);
3384
	rrr_ins(i_a,r,off,R_SP);
3385
	if (p_args_and_link_size !=0)
3386
	{
3387
	  rir_ins(i_a , R_SP , - p_args_and_link_size , R_SP);
3388
	}
3389
      }
7 7u83 3390
      if (p_has_back_chain)
2 7u83 3391
      {
3392
	save_back_chain_using_frame_pointer();
3393
      }
7 7u83 3394
      if (p_has_saved_sp)
2 7u83 3395
      {
3396
	save_sp_on_stack();
3397
      }
3398
      return mka;
3399
    }
3400
/*****************************************************************************/
3401
/* SPEC 3.1 constructions */
3402
/**************************/
3403
   case locptr_tag:
3404
    {
7 7u83 3405
      /* this is the only way of accessing callers in a general proc
2 7u83 3406
       when calculating general_env_offset using current_env */
3407
      int destr = regfrmdest(&dest,sp);
3408
      int pr = reg_operand(son(e),sp);
3409
      space nsp;
3410
      baseoff b;
3411
      ans aa;
3412
      b.base = pr;
3413
      b.offset = 0; /* R_TP lives where R_FP is for general proc */
3414
      ld_ro_ins(i_l,b,destr);comment("locptr:get TP using FP");
3415
      setregalt(aa,destr);
3416
      nsp = guardreg(destr,sp);
3417
      mka.regmove = move(aa,dest,nsp.fixed,0);
3418
      return mka;
3419
    }
3420
/*****************************************************************************/
3421
   case apply_general_tag:		/* procedure call */
3422
    {
3423
      return make_apply_general_tag_code(e, sp, dest, exitlab);
3424
    }
3425
/*****************************************************************************/
3426
   case tail_call_tag:
3427
    {
3428
      make_tail_call_tag_code(e,sp);
3429
      return mka;
3430
    }
3431
/*****************************************************************************/
3432
   case make_callee_list_tag:
3433
    {
3434
      make_callee_list_tag_code(e,sp);
3435
      return mka;
7 7u83 3436
    }
2 7u83 3437
/*****************************************************************************/
3438
   case same_callees_tag:
3439
    {
3440
      make_same_callees_tag_code(e,sp);
3441
      return mka;
3442
    }
3443
/*****************************************************************************/
3444
   case make_dynamic_callee_tag:
3445
    {
3446
      make_dynamic_callee_tag_code(e,sp);
3447
      return mka;
3448
    }
3449
/*****************************************************************************/
3450
   case caller_name_tag:
3451
    {
3452
      return mka;
3453
    }
3454
/*****************************************************************************/
3455
   case return_to_label_tag:
3456
    {
3457
      make_return_to_label_tag_code(e,sp);
3458
      return mka;
3459
    }
3460
/*****************************************************************************/
3461
   case set_stack_limit_tag:
3462
    {
3463
      baseoff b;
3464
      int r = reg_operand(son(e),sp);
3465
      b = find_tg("__TDFstacklim");
3466
      st_ins(i_st,r,b);
3467
      return mka;
3468
    }
3469
/*****************************************************************************/
3470
   case env_size_tag:
3471
    {
3472
      exp tg = son(son(e));
3473
      procrec * pr = &procrecs[no(son(tg))];
7 7u83 3474
      constval = ((pr->frame_size) >>3) + pr->max_callee_bytes;
2 7u83 3475
      goto moveconst;
3476
    }
3477
/*****************************************************************************/
3478
   case trap_tag:
3479
    {
3480
      do_trap(e);
3481
      return mka;
3482
    }
3483
/*****************************************************************************/
3484
   default:
3485
    fail("TDF construct not done yet in make_code");
3486
  }				/* end outer switch */
3487
  ASSERT(0);			/* should have return/goto from switch */
3488
#ifdef DEBUG_POWERTRANS
3489
  showme(e,0,1);
3490
#endif
3491
  /*NOTREACHED*/
3492
 
3493
 
3494
 moveconst_zero:
3495
  constval = 0;
3496
 moveconst:
3497
  {
3498
    int r = regfrmdest(&dest,sp);
3499
    ans aa;
3500
    FULLCOMMENT1("load constval = %d",constval);
3501
    ld_const_ins(constval, r);
3502
    setregalt(aa, r);
3503
    move(aa, dest, guardreg(r, sp).fixed, 1);
3504
    mka.regmove = r;
3505
    return mka;
3506
  }
3507
}				/* end make_code */
3508
 
7 7u83 3509
void move_dlts(int dr, int sr, int szr, int bytemove)
2 7u83 3510
  /* move szr bytes to dr from sr (using R_TMP0)- either nooverlap or dr<=sr */
3511
{
3512
  baseoff sr_baseoff;
3513
  baseoff dr_baseoff;
3514
  int lin = new_label();
3515
 
3516
  sr_baseoff.base = sr;
3517
  sr_baseoff.offset = 1;
3518
  dr_baseoff.base = dr;
3519
  dr_baseoff.offset = 1;
3520
  /* +++ could do this word at a time? */
3521
  rir_ins(i_a,sr,-1,sr);               /* ai     sr,sr,-1 */
3522
  rir_ins(i_a,dr,-1,dr);               /* ai     dr,dr,-1 */
3523
  mt_ins(i_mtctr,szr);                 /* mtctr  szr      */
3524
  set_label(lin);                      /* L.???           */
3525
  ld_ro_ins(i_lbzu,sr_baseoff,R_TMP0); /* lbzu   0,1(sr)  */comment(NIL);
3526
  st_ro_ins(i_stbu,R_TMP0,dr_baseoff); /* stbu   0,1(dr)  */comment(NIL);
3527
  uncond_ins(i_bdn, lin);              /* bdn    L.???    */
3528
  rrr_ins( i_sf, szr , sr ,sr );       /* sf     sr,szr,sr*/
3529
  rir_ins( i_a , sr , 1, sr);          /* ai     sr,sr,1  */
3530
  rrr_ins( i_sf, szr , dr ,dr );       /* sf     dr,szr,dr*/
3531
  rir_ins( i_a ,dr , 1, dr );          /* ai     dr,dr,1  */
3532
  return;
3533
}
3534
 
7 7u83 3535
void move_dgts(int dr, int sr, int szr, int bytemove)
2 7u83 3536
	/* move szr bytes to dr from sr (using R_TMP0) with overlap and dr>sr */
7 7u83 3537
{
2 7u83 3538
  baseoff sr_baseoff;
3539
  baseoff dr_baseoff;
3540
  int lin = new_label();
7 7u83 3541
 
2 7u83 3542
  sr_baseoff.base = sr;
3543
  sr_baseoff.offset = -1;
3544
  dr_baseoff.base = dr;
3545
  dr_baseoff.offset = -1;
3546
  /* +++ could do this word at a time? */
3547
  rrr_ins(i_a,sr,szr,sr);              /* a      sr,szr,sr */
3548
  rrr_ins(i_a,dr,szr,dr);              /* a      dr,szr,dr */
3549
  mt_ins(i_mtctr,szr);                 /* mtctr  szr       */
3550
  set_label(lin);                      /* L.???            */
3551
  ld_ro_ins(i_lbzu,sr_baseoff,R_TMP0); /* lbzu   0,-1(sr)  */comment(NIL);
3552
  st_ro_ins(i_stbu,R_TMP0,dr_baseoff); /* stbu   0,-1(dr)  */comment(NIL);
3553
  uncond_ins(i_bdn, lin);              /* bdn    L.???     */
3554
  return;
3555
}
3556
 
7 7u83 3557
int regfrmdest(where * dest, space sp)
2 7u83 3558
{
3559
  switch (dest->answhere.discrim) {
7 7u83 3560
   case inreg:
2 7u83 3561
    {
7 7u83 3562
      return regalt(dest->answhere);
3563
 
2 7u83 3564
    }
7 7u83 3565
   default:
2 7u83 3566
    {
7 7u83 3567
      return getreg(sp.fixed);
2 7u83 3568
    }
3569
  }
7 7u83 3570
}
3571
freg fregfrmdest(bool dble, where * dest, space sp)
2 7u83 3572
{
3573
  freg fr;
7 7u83 3574
 
2 7u83 3575
  switch (dest->answhere.discrim)
3576
  {
3577
   case infreg:
3578
    {
3579
      fr = fregalt(dest->answhere);
3580
      fr.dble = dble;
3581
      return fr;
3582
    }
3583
   default:
3584
    {
3585
      fr.dble = dble;
3586
      fr.fr = getfreg(sp.flt);
3587
      return fr;
3588
    }
3589
 
3590
  }
3591
}
3592
 
7 7u83 3593
static int get_next_mlv_number(void)
2 7u83 3594
{
3595
  static next_lv_number=0;
3596
  next_lv_number++;
3597
  return next_lv_number;
3598
}
3599
 
3600
 
3601
 
7 7u83 3602
void adjust_to_size(int src_shpe, int sreg, int dest_shpe, int dreg, int trap)
2 7u83 3603
{
7 7u83 3604
 
3605
/*
2 7u83 3606
 
7 7u83 3607
 
2 7u83 3608
                      d   e   s   t
3609
 
3610
                  s   u   s   u   s   u
3611
                  c   c   w   w   l   l
3612
                  h   h   o   o   o   o
3613
                  a   a   r   r   n   n
3614
		  r   r   d   d   g   g
3615
 
3616
      schar       0   X   0   X   0   0
3617
      uchar       X   0   0   0   0   0
3618
 s    sword       X   X   0   X   0   0
3619
 r    uword       X   X   X   0   0   0
3620
 c    slong       X   X   X   X   0   0
3621
      ulong       X   X   X   X   0   0
3622
   */
3623
  /* Perform the options on the above table */
7 7u83 3624
  if (src_shpe == dest_shpe ||
3625
      dest_shpe == slonghd  ||
3626
      dest_shpe == ulonghd  ||
3627
     (src_shpe == scharhd && dest_shpe == swordhd) ||
3628
     (src_shpe == ucharhd && dest_shpe != scharhd))
2 7u83 3629
  {
3630
    /* Do no adjustment */
7 7u83 3631
    if (sreg!=dreg)
2 7u83 3632
    {
3633
      mov_rr_ins(sreg,dreg);comment(NIL);
3634
    }
3635
    return;
3636
  }
7 7u83 3637
 
3638
 
3639
  if (trap==NO_ERROR_JUMP)
2 7u83 3640
  {
7 7u83 3641
    switch (dest_shpe)
2 7u83 3642
    {
3643
     case scharhd:
7 7u83 3644
      if (architecture==POWERPC_CODE)
2 7u83 3645
      {
3646
	rr_ins(i_extsb,sreg,dreg);
3647
      }
3648
      else
3649
      {
3650
	rir_ins(i_sl, sreg, 24, dreg);
3651
	rir_ins(i_sra, dreg, 24, dreg);
3652
      }
3653
      break;
3654
     case ucharhd:
3655
      rir_ins(i_and, sreg, 0x000000ff, dreg);
3656
      break;
3657
     case swordhd:
3658
      rr_ins(i_exts, sreg, dreg);
3659
      break;
3660
     case uwordhd:
3661
      rir_ins(i_and, sreg, 0x0000ffff, dreg);
3662
      break;
3663
     case slonghd:
3664
     case ulonghd:
3665
      mov_rr_ins(sreg,dreg);comment(NIL);
3666
      break;
3667
     default:
3668
      fail("Unexpected integer shape in adjust_to_size");
3669
      break;
3670
    }
3671
  }
3672
  else
3673
  {
7 7u83 3674
    switch (dest_shpe)
2 7u83 3675
    {
3676
     case scharhd:
3677
      testsigned(sreg, -128, 127, trap);
7 7u83 3678
      if (sreg !=dreg) { mov_rr_ins(sreg,dreg);comment(NIL); }
2 7u83 3679
      break;
3680
     case ucharhd:
3681
      testusigned(sreg,255,trap);
7 7u83 3682
      if (sreg !=dreg) { mov_rr_ins(sreg,dreg);comment(NIL); }
2 7u83 3683
      break;
3684
     case swordhd:
3685
      testsigned(sreg,-0x8000,0x7fff,trap);
7 7u83 3686
      if (sreg !=dreg) { mov_rr_ins(sreg,dreg);comment(NIL); }
2 7u83 3687
      break;
3688
     case uwordhd:
3689
      testusigned(sreg,0xffff,trap);
7 7u83 3690
      if (sreg !=dreg) { mov_rr_ins(sreg,dreg);comment(NIL); }
2 7u83 3691
      break;
3692
     case slonghd:
3693
     case ulonghd:
3694
      mov_rr_ins(sreg,dreg);comment(NIL);
3695
      break;
3696
     default:
3697
      fail("Unexpected integer shape in adjust_to_size");
3698
      break;
3699
    }
3700
  }
3701
  return;
3702
}