Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – tendra.SVN – Blame – /branches/tendra5/src/installers/hppa/common/oprators.c – Rev 2

Subversion Repositories tendra.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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