Subversion Repositories tendra.SVN

Rev

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

Rev Author Line No. Line
2 7u83 1
/*
6 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
    		 Crown Copyright (c) 1997
6 7u83 33
 
2 7u83 34
    This TenDRA(r) Computer Program is subject to Copyright
35
    owned by the United Kingdom Secretary of State for Defence
36
    acting through the Defence Evaluation and Research Agency
37
    (DERA).  It is made available to Recipients with a
38
    royalty-free licence for its use, reproduction, transfer
39
    to other parties and amendment for any purpose not excluding
40
    product development provided that any such use et cetera
41
    shall be deemed to be acceptance of the following conditions:-
6 7u83 42
 
2 7u83 43
	(1) Its Recipients shall ensure that this Notice is
44
	reproduced upon any copies or amended versions of it;
6 7u83 45
 
2 7u83 46
	(2) Any amended version of it shall be clearly marked to
47
	show both the nature of and the organisation responsible
48
	for the relevant amendment or amendments;
6 7u83 49
 
2 7u83 50
	(3) Its onward transfer from a recipient to another
51
	party shall be deemed to be that party's acceptance of
52
	these conditions;
6 7u83 53
 
2 7u83 54
	(4) DERA gives no warranty or assurance as to its
55
	quality or suitability for any purpose and DERA accepts
56
	no liability whatsoever in relation to any use to which
57
	it may be put.
58
*/
59
 
60
 
61
/*
62
$Log: oprators.c,v $
63
 * Revision 1.1.1.1  1998/01/17  15:56:03  release
64
 * First version to be checked into rolling release.
65
 *
66
 * Revision 1.9  1997/01/29  10:19:14  wfs
67
 *    Fixed a minor bug in "move.c" and "oprators.c" due to immediates of  >
68
 * 14 bits appearing in the field of ldo instrcutions.
69
 *
70
 * Revision 1.8  1996/11/25  13:43:25  wfs
71
 *    Fixed the comm_op register tracking bug in "oprators.c" and removed a
72
 * few superfluous "#if 0"s.
73
 *
74
 * Revision 1.7  1996/08/30  09:02:30  wfs
75
 * Various fixes of bugs arising from avs and pl_tdf tests.
76
 *
77
 * Revision 1.6  1996/02/15  10:09:40  wfs
78
 * Incorrect decrement - which I introduced in last bug fix - removed.
79
 *
80
 * Revision 1.5  1996/02/14  17:19:20  wfs
81
 * "next_caller_offset" and "next_callee_offset" have become special tokens
82
 * defined in "spec_tok.c". Bug fix to a "and_tag" optimization in
83
 * "oprators.c". A few bug fixes in "makecode.c" arising from the variable
84
 * caller tests. "promote_pars" defined in "config.h".
85
 *
86
 * Revision 1.4  1996/01/22  17:26:02  wfs
87
 * Bug fix to "make_stack_limit_tag".
88
 *
89
 * Revision 1.3  1996/01/17  13:51:02  wfs
90
 * Another adjustment to "round_tag" - avoid "_U_Qfcnvfxt_dbl_to_sgl" if the
91
 * error_treatment is "continue".
92
 *
93
 * Revision 1.2  1995/12/18  13:12:14  wfs
94
 * Put hppatrans uder cvs control. Major Changes made since last release
95
 * include:
96
 * (i) PIC code generation.
97
 * (ii) Profiling.
98
 * (iii) Dynamic Initialization.
99
 * (iv) Debugging of Exception Handling and Diagnostics.
100
 *
101
 * Revision 5.6  1995/10/20  14:08:29  wfs
102
 * gcc compilation changes.
103
 *
104
 * Revision 5.5  1995/10/13  10:44:34  wfs
105
 * Partial fix of a "round_with_mode" bug.
106
 *
107
 * Revision 5.4  1995/10/12  17:22:21  wfs
108
 * A "=" where there should have been "==".
109
 *
110
 * Revision 5.3  1995/10/10  16:50:25  wfs
111
 * There is a problem in the common code which means that floating_test's
112
 * error_treatment cannot be implemented for the time being.
113
 *
114
 * Revision 5.2  1995/10/09  13:09:29  wfs
115
 * Cosmetic changes.
116
 *
117
 * Revision 5.1  1995/09/15  13:04:52  wfs
118
 * Rewrote "quad_op" to ease reading and implementation of the quad
119
 * error jumps.
120
 *
121
 * Revision 5.0  1995/08/25  13:42:58  wfs
122
 * Preperation for August 25 Glue release
123
 *
124
 * Revision 3.4  1995/08/25  10:19:50  wfs
125
 * Register synonyms changed
126
 *
127
 * Revision 3.4  1995/08/25  10:19:50  wfs
128
 * Register synonyms changed
129
 *
130
 * Revision 3.1  95/04/10  16:27:38  16:27:38  wfs (William Simmonds)
131
 * Apr95 tape version.
6 7u83 132
 *
2 7u83 133
 * Revision 3.0  95/03/30  11:18:31  11:18:31  wfs (William Simmonds)
134
 * Mar95 tape version with CRCR95_178 bug fix.
6 7u83 135
 *
2 7u83 136
 * Revision 2.0  95/03/15  15:28:22  15:28:22  wfs (William Simmonds)
137
 * spec 3.1 changes implemented, tests outstanding.
6 7u83 138
 *
2 7u83 139
 * Revision 1.7  95/02/10  11:41:20  11:41:20  wfs (William Simmonds)
140
 * Removed call to evaluated() - initialising expressions are now
141
 * stored in a linked list and written to outf after the procedure
142
 * body has been translated (c.f. translate_capsule).
6 7u83 143
 *
2 7u83 144
 * Revision 1.6  95/01/25  13:37:44  13:37:44  wfs (William Simmonds)
145
 * Refined error_jump of float plus, minus, mult, div.
6 7u83 146
 *
2 7u83 147
 * Revision 1.5  95/01/25  10:31:56  10:31:56  wfs (William Simmonds)
148
 * First attempt at installing error_jump in the float plus, minus, mult
149
 * and div tags.
6 7u83 150
 *
2 7u83 151
 * Revision 1.4  95/01/23  18:58:04  18:58:04  wfs (William Simmonds)
152
 * Cosmetic changes to do_comm and non_comm_op.
6 7u83 153
 *
2 7u83 154
 * Revision 1.3  95/01/17  17:30:00  17:30:00  wfs (William Simmonds)
155
 * Changed name of an included header file.
6 7u83 156
 *
2 7u83 157
 * Revision 1.2  95/01/12  11:27:16  11:27:16  wfs (William Simmonds)
158
 * Corrected bug in `logical_op' which was causing hppatrans
159
 * to fail to bootstrap.
6 7u83 160
 *
2 7u83 161
 * Revision 1.1  95/01/11  13:14:24  13:14:24  wfs (William Simmonds)
162
 * Initial revision
6 7u83 163
 *
2 7u83 164
*/
165
 
166
 
167
#define HPPATRANS_CODE
168
#include "config.h"
169
#include "codehere.h"
170
#include "expmacs.h"
171
#include "addrtypes.h"
172
#include "inst_fmt.h"
173
#include "move.h"
174
#include "maxminmacs.h"
175
#include "getregs.h"
176
#include "guard.h"
177
#include "tags.h"
178
#include "shapemacs.h"
179
#include "bitsmacs.h"
180
#include "common_types.h"
181
#include "myassert.h"
182
#include "labels.h"
183
#include "frames.h"
184
#include "oprators.h"
185
 
6 7u83 186
#define isdbl(e)((bool)(name(e)!= shrealhd))
2 7u83 187
 
188
 
189
#if use_long_double
190
#include "externs.h"
191
#include "install_fns.h"
192
#include "regmacs.h"
193
#include "exp.h"
194
#include "out.h"
195
#include "locate.h"
196
#include "eval.h"
197
#include "muldvrem.h"
198
#include "proc.h"
199
#include "basicread.h"
200
#include "inst_fmt.h"
201
#endif
202
 
6 7u83 203
extern long trap_label(exp);
204
extern void trap_handler(baseoff,int,int);
205
extern baseoff zero_exception_register(space);
2 7u83 206
extern labexp current,first;
207
 
208
 
209
int long_double_0 = 0;
210
 
211
/* corrects possible overflows of chars and shorts in reg r */
6 7u83 212
void tidyshort
213
(int r, shape s)
2 7u83 214
{
215
  if (name(s) == ucharhd)
216
     riir_ins(i_dep,c_,0,23,24,r);
217
  else if (name(s) == uwordhd)
218
     riir_ins(i_dep,c_,0,15,16,r);
219
}
220
 
221
 
222
 /*
223
  * given a list of expressions seq which contains one whose value is in
224
  * register reg, removes that exp from seq and delivers 1; otherwise delivers
225
  * 0
226
  */
6 7u83 227
bool regremoved
228
(exp * seq, int reg)
2 7u83 229
{
230
  exp s = *seq;
231
  exp t = bro(s);
232
 
233
  if (ABS_OF(regofval(s)) == reg)
234
  {
6 7u83 235
   (*seq) = t;
2 7u83 236
    return 1;
237
  }
238
  for (;;)
239
  {
240
    if (ABS_OF(regofval(t)) == reg)
241
    {
242
      bro(s) = bro(t);
243
      if (last(t))
244
	setlast(s);
245
      return 1;
246
    }
247
    if (last(t))
248
    {
249
      return 0;
250
    }
251
    s = t;
252
    t = bro(t);
253
  }
254
}
255
 
256
 
257
 
258
/*
259
 *   logical operation, lop, with operands immediate, i, and register, r
260
 */
261
void logical_op
6 7u83 262
(CONST char *lop, long i, int r, int d)
2 7u83 263
{
264
   int t;
265
   if (r==d)
6 7u83 266
      t=GR1;
2 7u83 267
   else
268
      t=d;
269
   if (lop==i_and && i==-1)
270
   {
271
      if (r!=d)
272
	 rr_ins(i_copy,r,d);
273
      return;
274
   }
6 7u83 275
   else if (lop==i_and && IS_POW2((i+1)))
2 7u83 276
   {
277
      int p=0;
6 7u83 278
      while (i & (1<<p))p++;
2 7u83 279
      if (r==d)
280
	 iiir_ins(i_depi,c_,0,31-p,32-p,d);
281
      else
282
	 riir_ins(i_extru,c_,r,31,p,d);
283
      return;
284
   }
6 7u83 285
   else if (lop==i_and && IS_POW2((-i)))
2 7u83 286
   {
287
      int p=0;
6 7u83 288
      while ((i & (1<<p)) ==0)p++;
2 7u83 289
      if (r!=d)
290
	 rr_ins(i_copy,r,d);
291
      iiir_ins(i_depi,c_,0,31,p,d);
292
      return;
293
   }
6 7u83 294
   else if (lop==i_or)
2 7u83 295
   {
296
      if (r==0)
297
      {
298
	 imm_to_r(i,d);
299
	 return;
300
      }
6 7u83 301
      else
2 7u83 302
      if (i==-1)
303
      {
304
	 ir_ins(i_ldi,fs_,"",-1,d);
305
	 return;
306
      }
307
      else
308
      {
309
	 int j=0;
310
	 unsigned int p=i;
6 7u83 311
	 while ((p & (1<<j)) ==0)j++;
2 7u83 312
	 p=p>>j;
6 7u83 313
	 if (((p+1) &p) ==0)
2 7u83 314
	 {
315
	    int k=0;
6 7u83 316
	    while (p & (1<<k))k++;
2 7u83 317
	    if (r!=d)
318
	       rr_ins(i_copy,r,d);
319
	    iiir_ins(i_depi,c_,-1,31-j,k,d);
320
	    return;
321
	 }
322
      }
323
   }
324
   if (SIMM14(i))
325
   {
326
      ir_ins(i_ldi,fs_,"",i,t);
327
      rrr_ins(lop,c_,r,t,d);
328
   }
329
   else
330
   if (SIMM14(~i) && lop==i_and)
331
   {
332
      ir_ins(i_ldi,fs_,"",~i,t);
333
      rrr_ins(i_andcm,c_,r,t,d);
334
   }
335
   else
6 7u83 336
   if (((i& (i+1)) ==0) && lop==i_and)
2 7u83 337
   {
338
       unsigned long ui = i;
339
       int nbits=0;
340
       while (ui != 0)
341
       {
342
	 nbits++;
343
	 ui=ui>>1;
344
       }
345
       riir_ins(i_zdep,c_,r,31,nbits,d);
346
   }
347
   else
348
   {
349
      imm_to_r(i,t);
350
      rrr_ins(lop,c_,r,t,d);
351
   }
352
}
353
 
354
 
355
 
356
 /*
357
  * evaluates the fixed operation seq1 rins seq 2 rins...., into reg final,
358
  * using sp as free t-regs
359
  */
6 7u83 360
void do_comm
361
(exp seq, space sp, int final, ins_p rins)
2 7u83 362
{
363
  int r = 0;
364
  space nsp;
365
  int a1;
366
  int a2;
367
  exp next = bro(seq);
368
 
6 7u83 369
  if (name(seq) ==not_tag &&
2 7u83 370
       last(next) &&
371
       rins==i_and &&
6 7u83 372
       name(next)!=val_tag)
2 7u83 373
  {
374
     a1=reg_operand(son(seq), sp);
375
     nsp = guardreg(a1, sp);
376
     a2=reg_operand(next, nsp);
377
     rrr_ins(i_andcm,c_,a2,a1,final);
378
     return;
379
  }
380
 
6 7u83 381
  if (name(next) ==not_tag &&
382
      last(next) &&
2 7u83 383
      rins==i_and &&
6 7u83 384
      name(seq)!=val_tag)
2 7u83 385
  {
386
     a1=reg_operand(seq, sp);
387
     nsp = guardreg(a1, sp);
388
     a2=reg_operand(son(next), nsp);
389
     rrr_ins(i_andcm,c_,a1,a2,final);
390
     return;
391
  }
392
 
6 7u83 393
  if (name(next) ==val_tag &&
2 7u83 394
       last(next) &&
395
       rins==i_and &&
6 7u83 396
       name(seq) ==shr_tag)
2 7u83 397
  {
398
     exp shift=bro(son(seq));
6 7u83 399
     if (name(shift) ==val_tag)
400
     {
2 7u83 401
	int n,s;
402
	n=no(next);
403
	s=no(shift);
6 7u83 404
	if (IS_POW2((n+1)))
2 7u83 405
	{
406
	   int p=0;
407
	   a1=reg_operand(son(seq), sp);
6 7u83 408
	   while (n & (1<<p))p++;
409
	   if (p > (32-s))
2 7u83 410
	      p = 32-s;
411
	   riir_ins(i_extru,c_,a1,31-s,p,final);
412
	   return;
413
	}
414
     }
415
  }
416
 
417
 
418
  /* evaluate 1st operand into a1 */
6 7u83 419
 
420
  if (name(seq) ==cont_tag && name(bro(seq)) ==val_tag && last(bro(seq))
421
       && !(props(son(seq)) & inreg_bits))
2 7u83 422
  {
423
     reg_operand_here(seq, sp, final);
424
     a1 = final;
425
  }
426
  else
427
     a1 = reg_operand(seq, sp);
428
 
6 7u83 429
  if (name(father(seq)) ==make_stack_limit_tag)
2 7u83 430
  {
431
     baseoff b;
432
     b.offset = FP_BOFF.offset;
433
     b.base = a1;
434
     ld_ins(i_lw,0,b,b.base);
435
  }
436
 
437
  for (;;)
438
  {
439
    nsp = guardreg(a1, sp);
440
    seq = bro(seq);
441
    if (name(seq) == val_tag)	/* next operand is a constant */
442
    {
443
      int n=no(seq);
444
      if (last(seq))
445
      {
446
	if (rins==i_add)
447
	{
448
	   if (SIMM14(n))
449
	      ld_ir_ins(i_ldo,cmplt_,fs_,empty_ltrl,n,a1,final);
450
	   else
451
	   {
452
	      ir_ins(i_addil,fs_L,empty_ltrl,n,a1);
453
	      ld_ir_ins(i_ldo,cmplt_,fs_R,empty_ltrl,n,GR1,final);
454
	   }
455
	}
456
	else
457
	   logical_op(rins,n,a1,final);
458
	return;
459
      }
460
      else
461
      {
462
	 if (r == 0)
463
	     r = getreg(sp.fixed);
464
	 if (rins==i_add)
465
	 {
466
	   if (SIMM14(n))
467
	      ld_ir_ins(i_ldo,cmplt_,fs_,empty_ltrl,n,a1,r);
468
	   else
469
	   {
470
	      ir_ins(i_addil,fs_L,empty_ltrl,n,a1);
471
	      ld_ir_ins(i_ldo,cmplt_,fs_R,empty_ltrl,n,GR1,r);
472
	   }
473
	 }
474
	 else
475
	    logical_op(rins,n,a1,r);
476
      }
477
    }
478
    else
479
    {
480
       exp sq = seq;
481
       CONST char *ins = rins;
482
 
483
       a2 = reg_operand(sq, nsp);
484
       /* evaluate next operand */
485
       if (last(seq))
486
       {
487
 	  rrr_ins(ins,c_,a1,a2,final);
488
	  return;
489
       }
490
       else
491
       {
492
	  if (r == 0)
493
	     r = getreg(sp.fixed);
494
	  rrr_ins(ins,c_,a1,a2,r);
495
       }
496
    }
497
    a1 = r;
498
  }
499
}
500
 
501
 
502
 
503
/* evaluate commutative operation rrins given by e into d, using sp to get t-regs */
6 7u83 504
int comm_op
505
(exp e, space sp, where d, ins_p rrins)
2 7u83 506
{
507
  CONST char *rins = rrins;
508
 
6 7u83 509
  switch (discrim(d.answhere))
2 7u83 510
  {
511
  case inreg:
512
    {
513
      int dest = regalt(d.answhere);
514
      bool usesdest = regremoved(&son(e), dest);
515
      exp seq = son(e);
516
 
517
      /*
518
       * the destination is in a register; take care that we dont alter it
519
       * before possible use as an operand ....
520
       */
521
      if (usesdest && last(seq))
522
      {
523
	/* used, but there is only one other operand */
6 7u83 524
	if (name(seq) ==val_tag)
2 7u83 525
	{
526
	   int n = no(seq);
527
	   if (rrins==i_add)
528
	   {
529
	      if (SIMM14(n))
530
		 ld_ir_ins(i_ldo,cmplt_,fs_,empty_ltrl,n,dest,dest);
531
	      else
532
	      {
533
		 ir_ins(i_addil,fs_L,empty_ltrl,n,dest);
534
		 ld_ir_ins(i_ldo,cmplt_,fs_R,empty_ltrl,n,GR1,dest);
535
	      }
536
	   }
537
	   else
538
	      logical_op(rins,n,dest,dest);
539
	}
540
	else
541
	   rrr_ins(rins,c_,dest,reg_operand(seq,sp),dest);
542
	if (optop(e))
543
	   tidyshort(dest, sh(e));
544
	return dest;
545
      }
546
      else if (usesdest)
547
      {
548
	/* dest used, use temp */
549
	int r = getreg(sp.fixed);
550
 
551
	do_comm(seq, sp, r, rins);
552
	rrr_ins(rins,c_,dest,r,dest);
553
	if (optop(e))
554
	   tidyshort(dest, sh(e));
555
	return dest;
556
      }
557
      else
558
      {
559
	/* dest not used, evaluate into dest */
560
	do_comm(seq, sp, dest,rins);
561
	if (optop(e))
562
	   tidyshort(dest, sh(e));
563
	return dest;
564
      }
565
    }				/* end inreg */
566
  default:
567
    {
568
      ans a;
569
      int r = getreg(sp.fixed);
570
      space nsp;
571
      bool rok = 1;
572
      setregalt(a, r);
573
      do_comm(son(e), sp, r, rins);
574
      /* evaluate the expression into r ... */
6 7u83 575
      if (discrim(d.answhere)!= notinreg)
2 7u83 576
      {
577
	 if (optop(e))
578
	    tidyshort(r, sh(e));
579
      }
580
      else
6 7u83 581
	 rok = shape_size(sh(e)) ==32;
2 7u83 582
      nsp = guardreg(r, sp);
583
      move(a, d, nsp.fixed, 1);
584
      /* ... and move into a */
6 7u83 585
      return((rok)?r:NOREG);
2 7u83 586
    }				/* notinreg */
587
  }				/* end switch */
588
}
589
 
590
 
591
 
6 7u83 592
int non_comm_op
593
(exp e, space sp, where dest, ins_p rins)
2 7u83 594
 /* evalate binary operation e with rins into dest */
595
{
596
   exp l = son(e);
597
   exp r = bro(l);
598
   int a1 = reg_operand(l, sp);
599
   space nsp;
600
   int a2;
601
   CONST char *ins;
602
   ins=rins;
603
   nsp = guardreg(a1, sp);
604
   a2 = reg_operand(r, nsp);
6 7u83 605
   if (discrim(dest.answhere) ==inreg)
2 7u83 606
   {
607
      int d = regalt(dest.answhere);
608
      rrr_ins(ins,c_,a1,a2,d);
609
      if (optop(e))
610
	 tidyshort(d, sh(e));
611
      return d;
612
   }
613
   else
614
   {
615
      /* destination elsewhere */
616
      ans a;
617
      int r1 = getreg(nsp.fixed);
618
      setregalt(a, r1);
619
      rrr_ins(ins,c_,a1,a2,r1);
620
      if (optop(e))
621
	 tidyshort(r1, sh(e));
622
      nsp = guardreg(r1, sp);
623
      move(a, dest, nsp.fixed, 1);
624
      return r1;
625
   }
626
}
627
 
6 7u83 628
int monop
629
(exp e, space sp, where dest, ins_p ins)
2 7u83 630
 /* evaluate fixed monadic operation e using ins into dest */
631
{
632
   int r1 = getreg(sp.fixed);
633
   int a1 = reg_operand(son(e), sp);
634
 
635
   /* operand in reg a1 */
636
   space nsp;
637
 
6 7u83 638
   if (discrim(dest.answhere) == inreg)
2 7u83 639
   {
640
      /* destination in register */
641
      int d = regalt(dest.answhere);
642
      if (ins==i_subi)
643
	 rrr_ins(i_sub,c_,0,a1,d);
644
      else
645
      if (ins==i_sub)
646
	 rrr_ins(i_sub,c_,0,a1,d);
647
      else
648
	 rrr_ins(i_uaddcm,c_,0,a1,d);
649
      if (optop(e))
650
	 tidyshort(d,sh(e));
651
      return d;
652
   }
653
   else
654
   {
655
      /* destination elsewhere */
656
      ans a;
657
      setregalt(a, r1);
658
      if (ins==i_subi)
659
	 rrr_ins(i_sub,c_,0,a1,r1);
660
      else
661
      if (ins==i_sub)
662
	 rrr_ins(i_sub,c_,0,a1,r1);
663
      else
664
	 rrr_ins(i_uaddcm,c_,0,a1,r1);
665
      if (optop(e))
666
	 tidyshort(r1, sh(e));
667
      nsp = guardreg(r1, sp);
668
      move(a, dest, nsp.fixed, 1);
669
      return r1;
670
   }
671
}
672
 
673
 
674
#if use_long_double
675
 
676
/*
677
    GET THE ADDRESS OF A LONG DOUBLE
678
*/
679
static void quad_addr
6 7u83 680
(exp e, int r, space sp)
2 7u83 681
{
6 7u83 682
    instore is;
683
    if (name(e) ==real_tag)
2 7u83 684
    {
685
	labexp next;
6 7u83 686
	next  = (labexp)malloc(sizeof(struct labexp_t));
2 7u83 687
	next->e = e;
688
	next->lab = next_data_lab();
6 7u83 689
	next->next = (labexp)0;
2 7u83 690
	current->next = next;
691
	current = next;
692
	is.adval = 0;
693
	is.b.offset = 0;
694
	is.b.base = next->lab;
695
    }
696
    else
697
    {
6 7u83 698
       where w;
699
       w=locate1(e,sp,sh(e),0);
700
       if (discrim(w.answhere)!=notinreg)
701
	  failer("Illegal expression in quad_addr");
702
       is=insalt(w.answhere);
2 7u83 703
    }
704
    if (is.adval)
705
    {
6 7u83 706
	failer("Illegal expression in quad_addr");
2 7u83 707
    }
708
    if (IS_FIXREG(is.b.base))
709
    {
710
       if (is.b.offset==0)
711
       {
712
	  if (is.b.base!=r)
6 7u83 713
	     rr_ins(i_copy,is.b.base,r);
2 7u83 714
       }
715
       else
6 7u83 716
	  ld_ins(i_lo,1,is.b,r);
2 7u83 717
    }
718
    else
6 7u83 719
       set_ins("",is.b,r);
720
    return;
2 7u83 721
}
722
 
723
 
724
/*
725
    LONG DOUBLE LIBRARY
726
*/
727
 
728
static struct {
6 7u83 729
		  CONST char proc_name[32];
730
		  bool called;
731
	      } long_double_lib[14] =
2 7u83 732
	      {
733
		  { "_U_Qfcmp", 0 },
734
		  { "_U_Qfadd", 0 },
735
		  { "_U_Qfsub", 0 },
736
		  { "_U_Qfmpy", 0 },
737
		  { "_U_Qfdiv", 0 },
738
		  { "_U_Qfcnvff_dbl_to_quad", 0 },
739
		  { "_U_Qfcnvff_sgl_to_quad", 0 },
740
		  { "_U_Qfcnvxf_dbl_to_quad", 0 },
741
		  { "_U_Qfcnvxf_sgl_to_quad", 0 },
742
		  { "_U_Qfcnvff_quad_to_dbl", 0 },
743
		  { "_U_Qfcnvff_quad_to_sgl", 0 },
744
		  { "_U_Qfabs", 0 },
745
		  { "_U_Qfcnvfxt_quad_to_sgl", 0 },
746
		  { "_U_Qfrnd", 0 }
6 7u83 747
	      };
2 7u83 748
 
749
 
750
void import_long_double_lib
6 7u83 751
(void)
2 7u83 752
{
753
   int n;
6 7u83 754
   for (n=0; n<14; n++)
755
      if (long_double_lib[n].called)
2 7u83 756
	 fprintf(outf,"\t.IMPORT\t%s,CODE\n",long_double_lib[n].proc_name);
757
   if (long_double_0)
758
   {
759
      outnl();
760
      outs("\t.DATA\n");
761
      outs("$qfp_lit_sym$\n");
762
      outs("\t.ALIGN\t8\n");
763
      outs("\t.STRINGZ \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n");
764
      outs("\t.STRINGZ \"?\\xFF\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n");
765
   }
766
}
767
 
768
 
769
/*
770
    DO A QUAD FLOAT OPERATION
771
*/
772
void quad_op
6 7u83 773
(exp e, space sp, where dest)
2 7u83 774
{
775
   char *s=0,*stub=0;
6 7u83 776
   bool quad_ret = 1;
2 7u83 777
 
6 7u83 778
   switch (name(e))
2 7u83 779
   {
780
      case test_tag:
781
      {
782
	 /* Quad comparisons */
783
	 exp l,r;
784
	 int tn;
6 7u83 785
	 quad_ret = 0;
2 7u83 786
	 s = "_U_Qfcmp";
787
	 stub = "ARGW0=GR,ARGW1=GR,ARGW2=GR";
788
	 long_double_lib[0].called=1;
789
	 sp = guardreg(ARG2,sp);
790
	 tn = (int)test_number(e);
6 7u83 791
	 if (tn < 1 || tn > 6)
2 7u83 792
	 {
6 7u83 793
	    fail("Illegal floating-point test");
2 7u83 794
	 }
795
	 ir_ins(i_ldi, fs_, empty_ltrl, tn==1 ? 17 : tn==2 ? 21 : tn==3 ? 9 : tn==4 ? 13 : tn==5 ? 4 : 25,               ARG2);
6 7u83 796
	 if (IsRev(e))
2 7u83 797
	 {
798
	    r = son(e);
799
	    l = bro(r);
800
	 }
801
	 else
802
	 {
803
	    l = son(e);
804
	    r = bro(l);
805
	 }
6 7u83 806
	 quad_addr(l,ARG0,sp);
807
	 sp = guardreg(ARG0,sp);
808
	 quad_addr(r,ARG1,sp);
2 7u83 809
	 break;
810
      }
6 7u83 811
      case fneg_tag:
2 7u83 812
      {
813
	 baseoff b;
814
	 b.base=0; b.offset=0;
6 7u83 815
	 s = "_U_Qfsub";
2 7u83 816
	 long_double_lib[2].called=1;
817
	 set_ins("$qfp_lit_sym$",b,ARG0);
818
	 sp = guardreg(ARG0,sp);
6 7u83 819
	 quad_addr(son(e),ARG1,sp);
2 7u83 820
	 sp = guardreg(ARG1,sp);
821
	 stub = "ARGW0=GR,ARGW1=GR";
822
	 long_double_0 = 1;
6 7u83 823
	 break;
2 7u83 824
      }
6 7u83 825
      case fabs_tag:
2 7u83 826
      {
6 7u83 827
	 s = "_U_Qfabs";
2 7u83 828
	 long_double_lib[11].called=1;
829
	 stub = "ARGW0=GR";
6 7u83 830
	 quad_addr(son(e),ARG0,sp);
831
	 break;
2 7u83 832
      }
6 7u83 833
      case chfl_tag:
2 7u83 834
      {
6 7u83 835
 	 ans aa;
836
	 where w;
837
	 freg frg;
2 7u83 838
	 exp l;
6 7u83 839
	 if (name(sh(e)) == doublehd)
2 7u83 840
	 {
841
	    baseoff b;
842
	    b.base=SP;
843
	    l = son(e);
6 7u83 844
	    if (name(sh(l)) == doublehd)
2 7u83 845
	       return;
6 7u83 846
	    else
847
	    if (name(sh(l)) ==realhd)
2 7u83 848
	    {
6 7u83 849
	       s = "_U_Qfcnvff_dbl_to_quad";
2 7u83 850
	       long_double_lib[5].called=1;
851
	       frg.dble=1;
852
	       frg.fr=5;
853
	       stub = "ARGW0=FR,ARGW1=FU";
854
	    }
855
	    else
856
	    {
6 7u83 857
	       s = "_U_Qfcnvff_sgl_to_quad";
2 7u83 858
	       long_double_lib[6].called=1;
859
	       frg.dble=0;
860
	       frg.fr=4;
861
	       stub = "ARGW0=FR";
862
	    }
6 7u83 863
	    setfregalt(aa, frg);
864
	    w.answhere = aa;
865
	    w.ashwhere = ashof(sh(l));
2 7u83 866
	    code_here(l,sp,w);
867
	    if (frg.dble)
868
	    {
869
	       b.offset=-40;
6 7u83 870
	       stf_ins(i_fstd,(5*3) +1,b);
2 7u83 871
	       ld_ins(i_ldw,1,b,ARG1);
872
	       b.offset+=4;
873
	       ld_ins(i_ldw,1,b,ARG0);
874
	    }
875
	    else
876
	    {
877
	       b.offset=-36;
6 7u83 878
	       stf_ins(i_fstw,(4*3) +0,b);
2 7u83 879
	       ld_ins(i_ldw,1,b,ARG0);
880
	    }
881
	 }
882
	 else
883
	 {
6 7u83 884
	    if (isdbl(sh(e)))
2 7u83 885
	    {
886
	       s = "_U_Qfcnvff_quad_to_dbl";
887
	       long_double_lib[9].called=1;
888
	    }
889
	    else
890
	    {
891
	       s = "_U_Qfcnvff_quad_to_sgl";
892
	       long_double_lib[10].called=1;
893
	    }
894
	    stub = "ARGW0=GR";
895
	    quad_ret = 0;
6 7u83 896
	    quad_addr(son(e),ARG0,sp);
2 7u83 897
	 }
6 7u83 898
	 break;
2 7u83 899
      }
6 7u83 900
      case float_tag:
2 7u83 901
      {
902
	 exp l = son(e);
903
	 reg_operand_here(l,sp,ARG0);
904
	 sp = guardreg(ARG0,sp);
6 7u83 905
	 if (name(sh(l)) ==ulonghd)
2 7u83 906
	 {
907
	    rr_ins(i_copy,0,ARG1);
908
	    long_double_lib[7].called=1;
6 7u83 909
	    s = "_U_Qfcnvxf_dbl_to_quad";
2 7u83 910
	    stub = "ARGW0=GR,ARGW1=GR";
911
	 }
912
	 else
913
	 {
6 7u83 914
	    s = "_U_Qfcnvxf_sgl_to_quad";
2 7u83 915
	    long_double_lib[8].called=1;
916
	    stub = "ARGW0=GR";
917
	 }
6 7u83 918
	 break;
2 7u83 919
      }
6 7u83 920
      case round_tag:
2 7u83 921
      {
6 7u83 922
	 if (round_number(e) ==3 && errhandle(e) <2)
2 7u83 923
	 {
924
	    s = "_U_Qfcnvfxt_quad_to_sgl";
925
	    long_double_lib[12].called=1;
926
	 }
927
	 else
928
	 {
929
	    s = "_U_Qfcnvff_quad_to_dbl";
930
	    long_double_lib[9].called=1;
931
	 }
932
	 stub = "ARGW0=GR";
933
	 quad_ret = 0;
6 7u83 934
	 quad_addr(son(e),ARG0,sp);
2 7u83 935
	 break;
936
      }
937
#if 0
938
      /* Binary operations */
939
      {
940
	 stub = "ARGW0=GR,ARGW1=GR";
6 7u83 941
	 break;
2 7u83 942
      }
943
#endif
6 7u83 944
      case fplus_tag:
945
      case fminus_tag:
946
      case fmult_tag:
947
      case fdiv_tag:
2 7u83 948
      {
949
	 exp l,r;
6 7u83 950
	 if (name(e) == fplus_tag)
2 7u83 951
	 {
6 7u83 952
	    s = "_U_Qfadd";
2 7u83 953
	    long_double_lib[1].called=1;
954
	 }
955
	 else
6 7u83 956
	 if (name(e) == fminus_tag)
2 7u83 957
	 {
6 7u83 958
	   s = "_U_Qfsub";
2 7u83 959
	   long_double_lib[2].called=1;
960
	 }
961
	 else
6 7u83 962
	 if (name(e) == fmult_tag)
2 7u83 963
	 {
6 7u83 964
	    s = "_U_Qfmpy";
2 7u83 965
	    long_double_lib[3].called=1;
966
	 }
967
	 else
968
	 {
6 7u83 969
	    s = "_U_Qfdiv";
2 7u83 970
	    long_double_lib[4].called=1;
971
	 }
972
	 stub = "ARGW0=GR,ARGW1=GR";
6 7u83 973
	 if (IsRev(e))
2 7u83 974
	 {
975
	    r = son(e);
976
	    l = bro(r);
977
	 }
978
	 else
979
	 {
980
	    l = son(e);
981
	    r = bro(l);
982
	 }
6 7u83 983
	 quad_addr(l,ARG0,sp);
984
	 sp = guardreg(ARG0,sp);
985
	 quad_addr(r,ARG1,sp);
986
	 break;
2 7u83 987
      }
988
      default :
6 7u83 989
	fail("Illegal floating-point operation");
2 7u83 990
   }
991
   if (quad_ret)
992
   {
6 7u83 993
      instore is;
2 7u83 994
      is = insalt(dest.answhere);
995
      if (discrim(dest.answhere)!=notinreg)
996
	  failer("Illegal expression in quad_op");
997
      if (is.adval)
998
      {
999
	 if (IS_FIXREG(is.b.base))
1000
	 {
1001
	    if (is.b.offset==0)
6 7u83 1002
	       rr_ins(i_copy,is.b.base,RET0);
2 7u83 1003
	    else
6 7u83 1004
	       ld_ins(i_lo,1,is.b,RET0);
1005
	 }
2 7u83 1006
	 else
6 7u83 1007
	    set_ins("",is.b,RET0);
2 7u83 1008
      }
1009
      else
6 7u83 1010
	 ld_ins(i_lw,1,is.b,RET0);
2 7u83 1011
   }
1012
   /* ..and make call */
6 7u83 1013
   call_ins(cmplt_,s,RP,stub);
2 7u83 1014
#if 1
1015
   if (!optop(e) && name(e)!=test_tag)
1016
   {
1017
      int trap = trap_label(e);
1018
      baseoff b;
1019
      int end;
1020
      if (quad_ret)
1021
      {
6 7u83 1022
	 instore is;
2 7u83 1023
	 end=new_label();
1024
	 is = insalt(dest.answhere);
1025
	 if (discrim(dest.answhere)!=notinreg)
1026
	    failer("Illegal expression in quad_op");
1027
	 if (is.adval)
1028
	 {
1029
	    if (IS_FIXREG(is.b.base))
1030
	    {
1031
	       if (is.b.offset==0)
6 7u83 1032
		  rr_ins(i_copy,is.b.base,RET0);
2 7u83 1033
	       else
6 7u83 1034
		  ld_ins(i_lo,1,is.b,RET0);
1035
	    }
2 7u83 1036
	    else
6 7u83 1037
	       set_ins("",is.b,RET0);
2 7u83 1038
	 }
1039
	 else
6 7u83 1040
	    ld_ins(i_lw,1,is.b,RET0);
2 7u83 1041
	 b.base =  RET0; b.offset = 4;
1042
	 ld_ins(i_lw,1,b,T3);
6 7u83 1043
	 cj_ins(c_neq, 0, T3, end);
2 7u83 1044
	 b.offset+=4;
1045
	 ld_ins(i_lw,1,b,T3);
6 7u83 1046
	 cj_ins(c_neq, 0, T3, end);
2 7u83 1047
	 b.offset+=4;
1048
	 ld_ins(i_lw,1,b,T3);
6 7u83 1049
	 cj_ins(c_neq, 0, T3, end);
2 7u83 1050
	 b.offset=0;
1051
	 ld_ins(i_lw,1,b,T3);
1052
	 imm_to_r(2147418112,T4);
6 7u83 1053
	 cj_ins(c_eq, T4, T3, trap);
2 7u83 1054
	 imm_to_r(-65536,T4);
6 7u83 1055
	 cj_ins(c_eq, T4, T3, trap);
2 7u83 1056
	 outlab("L$$",end);
1057
      }
1058
      else
6 7u83 1059
      if (name(e) == chfl_tag)
2 7u83 1060
      {
6 7u83 1061
	 if (isdbl(sh(e)))
2 7u83 1062
	 {
1063
	    baseoff b;
1064
	    b = mem_temp(0);
1065
	    end = new_label();
1066
	    stf_ins(i_fstd,3*4+1,b);
1067
	    b.offset+=4;
1068
	    ld_ins(i_lw,1,b,T3);
6 7u83 1069
	    cj_ins(c_neq, 0, T3, end);
2 7u83 1070
	    b.offset-=4;
1071
	    ld_ins(i_lw,1,b,T3);
1072
	    imm_to_r(2146435072,T4);
6 7u83 1073
	    cj_ins(c_eq, T4, T3, trap);
2 7u83 1074
	    imm_to_r(-1048576,T4);
6 7u83 1075
	    cj_ins(c_eq, T4, T3, trap);
2 7u83 1076
	    outlab("L$$",end);
1077
	 }
1078
	 else
1079
	 {
1080
	    baseoff b;
1081
	    b = mem_temp(0);
1082
	    stf_ins(i_fstw,3*4,b);
1083
	    ld_ins(i_lw,1,b,T3);
1084
	    imm_to_r(2139095040,T4);
6 7u83 1085
	    cj_ins(c_eq, T4, T3, trap);
2 7u83 1086
	    imm_to_r(-8388608,T4);
6 7u83 1087
	    cj_ins(c_eq, T4, T3, trap);
2 7u83 1088
	 }
1089
      }
1090
   }
1091
#endif
6 7u83 1092
   clear_t_regs();
1093
   return;
2 7u83 1094
}
1095
 
1096
#endif
1097
 
1098
 
1099
int fop
6 7u83 1100
(exp e, space sp, where dest, ins_p ins)
2 7u83 1101
{
1102
   /* Evaluate floating dyadic operation e using ins into dest. If
1103
      !optop(e), then we have two fixed point registers at our disposal */
1104
   exp l = son(e);
1105
   exp r = bro(l);
1106
   int a1,a2,dble;
1107
   space nsp;
1108
   freg fr;
1109
   ans aa;
1110
   baseoff b;
1111
 
1112
#if use_long_double
6 7u83 1113
   if (name(sh(e)) ==doublehd)
2 7u83 1114
   {
1115
      /* i.e. quads */
6 7u83 1116
      quad_op(e, sp, dest);
1117
      return(NOREG);
2 7u83 1118
   }
1119
#endif
1120
 
1121
 
6 7u83 1122
   dble= (name(sh(e)) ==realhd ? 1 : 0);
2 7u83 1123
   if (IsRev(e))
1124
   {
1125
      a2 = freg_operand(r, sp, getfreg(sp.flt));
1126
      nsp = guardfreg(a2, sp);
1127
      a1 = freg_operand(l, nsp, getfreg(nsp.flt));
1128
   }
1129
   else
1130
   {
1131
      a1 = freg_operand(l, sp, getfreg(sp.flt));
1132
      nsp = guardfreg(a1, sp);
1133
      a2 = freg_operand(r, nsp, getfreg(nsp.flt));
1134
   }
6 7u83 1135
   if ((discrim(dest.answhere)) == infreg)
2 7u83 1136
      fr = fregalt(dest.answhere);
1137
   else
1138
   {
1139
      fr.fr = getfreg(nsp.flt);
6 7u83 1140
      fr.dble = (dest.ashwhere.ashsize == 64)? 1 : 0;
2 7u83 1141
      setfregalt(aa, fr);
1142
   }
1143
   if (!optop(e))
1144
   {
1145
      b = zero_exception_register(nsp);
1146
   }
1147
   if (dble)
6 7u83 1148
      rrrf_ins(ins,f_dbl,(3*a1) +1,(3*a2) +1,(3*fr.fr) +1);
2 7u83 1149
   else
1150
      rrrf_ins(ins,f_sgl,3*a1,3*a2,3*fr.fr);
1151
   if (!optop(e))
1152
   {
1153
      trap_handler(b,trap_label(e),EXCEPTION_CODE);
1154
   }
6 7u83 1155
   if ((discrim(dest.answhere))!= infreg)
2 7u83 1156
      move(aa, dest, sp.fixed, 1);
6 7u83 1157
   return(dble ? - (fr.fr + 32):(fr.fr + 32));
2 7u83 1158
}