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/tendra4/src/installers/680x0/common/ops_float.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
			    VERSION INFORMATION
31
			    ===================
32
 
33
--------------------------------------------------------------------------
34
$Header: /u/g/release/CVSROOT/Source/src/installers/680x0/common/ops_float.c,v 1.1.1.1 1998/01/17 15:55:49 release Exp $
35
--------------------------------------------------------------------------
36
$Log: ops_float.c,v $
37
 * Revision 1.1.1.1  1998/01/17  15:55:49  release
38
 * First version to be checked into rolling release.
39
 *
40
Revision 1.3  1997/11/09 14:04:53  ma
41
round_with_mode rewritten.
42
 
43
Revision 1.2  1997/10/29 10:22:24  ma
44
Replaced use_alloca with has_alloca.
45
 
46
Revision 1.1.1.1  1997/10/13 12:42:56  ma
47
First version.
48
 
49
Revision 1.4  1997/10/13 08:49:44  ma
50
Made all pl_tests for general proc & exception handling pass.
51
 
52
Revision 1.3  1997/09/25 06:45:23  ma
53
All general_proc tests passed
54
 
55
Revision 1.2  1997/06/18 12:04:55  ma
56
Merged with Input Baseline changes.
57
 
58
 * Revision 1.3  1997/06/06  14:36:26  john
59
 * Fixed rounding modes
60
 *
61
 * Revision 1.2  1997/06/05  10:55:48  john
62
 * Fix to unsigned conversion
63
 *
64
 * Revision 1.1.1.1  1997/04/25  12:32:40  john
65
 *
66
 * Revision 1.2  1996/07/05  14:23:53  john
67
 * Changes for spec 3.1
68
 *
69
 * Revision 1.1.1.1  1996/03/26  15:45:15  john
70
 *
71
 * Revision 1.2  93/03/03  14:48:21  14:48:21  ra (Robert Andrews)
72
 * Started adding support for error treatments.
73
 *
74
 * Revision 1.1  93/02/22  17:16:17  17:16:17  ra (Robert Andrews)
75
 * Initial revision
76
 *
77
--------------------------------------------------------------------------
78
*/
79
 
80
 
81
#include "config.h"
82
#include "common_types.h"
83
#include "assembler.h"
84
#include "basicread.h"
85
#include "check.h"
86
#include "exp.h"
87
#include "expmacs.h"
88
#include "externs.h"
89
#include "install_fns.h"
90
#include "fbase.h"
91
#include "flpt.h"
92
#include "flpttypes.h"
93
#include "shapemacs.h"
94
#include "tags.h"
95
#include "mach.h"
96
#include "mach_ins.h"
97
#include "where.h"
98
#include "mach_op.h"
99
#include "instr.h"
100
#include "codex.h"
101
#include "instrs.h"
102
#include "coder.h"
103
#include "tests.h"
104
#include "operations.h"
105
#include "evaluate.h"
106
#include "utility.h"
107
#include "translate.h"
108
#include "ops_shared.h"
109
 
110
/*
111
    GIVE PROTOTYPE FOR MFW
112
*/
113
 
114
#if ( FBASE == 10 )
115
extern where mfw PROTO_S ( ( int, char *, int ) ) ;
116
#define FBASE_10
117
#else
118
extern where mfw PROTO_S ( ( int, long *, int ) ) ;
119
#undef FBASE_10
120
#endif
121
 
122
extern int need_dummy_double;
123
/************************************************************************
124
  Test for overflow.
125
 
126
  freg is a Freg which is moved to a dummy memory location to force the
127
  overflow (if any) before the test.
128
 ************************************************************************/
129
 
130
void test_float_overflow_reg
131
    PROTO_N ( ( freg, sz ) )
132
    PROTO_T ( where freg X long sz )
133
{
134
   if (have_overflow()) {
135
      ins2 ( insf ( sz, ml_fmove ), sz, sz, freg, dummy_double_dest, 1 ) ;
136
      test_overflow(ON_FP_OVERFLOW) ;
137
      need_dummy_double = 1 ;
138
   }
139
}
140
 
141
/************************************************************************
142
  Test for overflow.
143
 
144
  If dest is zero, freg is moved to a memory location to force the
145
  overflow (if any) before the test.
146
  ************************************************************************/
147
 
148
void test_float_overflow
149
    PROTO_N ( ( freg, dest, sz ) )
150
    PROTO_T ( where freg X where dest X long sz )
151
{
152
   if (have_overflow()) {
153
      if (eq_where(dest, zero)) {
154
         ins2 ( insf ( sz, ml_fmove ), sz, sz, freg, dummy_double_dest, 1 ) ;
155
         need_dummy_double = 1 ;
156
      }
157
      test_overflow(ON_FP_OVERFLOW) ;
158
   }
159
}
160
 
161
 
162
/*
163
    GENERAL PURPOSE FLOATING POINT ROUTINE
164
 
165
    The values a1 and a2 of shape sha have the binary floating-point
166
    operation indicated by the tag t applied to them and the result is
167
    stored in dest.
168
*/
169
 
170
void fl_binop
171
    PROTO_N ( ( t, sha, a1, a2, dest ) )
172
    PROTO_T ( int t X shape sha X where a1 X where a2 X where dest )
173
{
174
    int op, op1, op2 ;
175
    bool commutes = 0 ;
176
    int err = ON_FP_OVERFLOW ;
177
    long sz = shape_size ( sha ) ;
178
 
179
    switch ( t ) {
180
	case fplus_tag : {
181
	    commutes = 1 ;
182
	    op1 = insf ( sz, ml_fadd ) ;
183
	    op2 = m_faddx ;
184
	    break ;
185
	}
186
	case fminus_tag : {
187
	    op1 = insf ( sz, ml_fsub ) ;
188
	    op2 = m_fsubx ;
189
	    break ;
190
	}
191
	case fmult_tag : {
192
	    commutes = 1 ;
193
	    op1 = insf ( sz, ml_fmul ) ;
194
	    op2 = m_fmulx ;
195
	    break ;
196
	}
197
	case fdiv_tag : {
198
	    op1 = insf ( sz, ml_fdiv ) ;
199
	    op2 = m_fdivx ;
200
	    err = ON_FP_CARRY ;
201
	    break ;
202
	}
203
	default : {
204
	    error ( "Illegal floating operation" ) ;
205
	    return ;
206
	}
207
    }
208
 
209
    if ( whereis ( dest ) == Freg ) {
210
       if ( eq_where ( a1, dest ) ) {
211
          if ( commutes ) {
212
             op = ( whereis ( a2 ) == Freg ? op2 : op1 ) ;
213
             ins2 ( op, sz, sz, a2, dest, 1 ) ;
214
             if (t == fdiv_tag) test_overflow(ON_FP_OVERFLOW) ; /* divided by 0 ? */
215
             test_float_overflow_reg(dest, sz) ;
216
          }
217
          else {
218
             move ( sha, a2, FP0 ) ;
219
             ins2 ( op2, sz, sz, a1, FP0, 1 ) ;
220
             if (t == fdiv_tag) test_overflow(ON_FP_OVERFLOW) ; /* divided by 0 ? */
221
             move ( sha, FP0, dest ) ;
222
          }
223
       } else {
224
          move ( sha, a2, dest ) ;
225
          op = ( whereis ( a1 ) == Freg ? op2 : op1 ) ;
226
          ins2 ( op, sz, sz, a1, dest, 1 ) ;
227
          if (t == fdiv_tag) test_overflow(ON_FP_OVERFLOW) ; /* divided by 0 ? */
228
          test_float_overflow_reg(dest, sz) ;
229
       }
230
    }
231
    else {
232
       move ( sha, a2, FP0 ) ;
233
       op = ( whereis ( a1 ) == Freg ? op2 : op1 ) ;
234
       ins2 ( op, sz, sz, a1, FP0, 1 ) ;
235
       if (t == fdiv_tag) test_overflow(ON_FP_OVERFLOW) ; /* divided by 0 ? */
236
       move ( sha, FP0, dest ) ;
237
       test_float_overflow(FP0, dest, sz) ;
238
    }
239
    have_cond = 0 ;
240
    return ;
241
}
242
 
243
 
244
/*
245
    NEGATE A FLOATING-POINT NUMBER
246
 
247
    The floating-point value a of shape sha is negated and stored in dest.
248
*/
249
 
250
void negate_float
251
    PROTO_N ( ( sha, a, dest ) )
252
    PROTO_T ( shape sha X where a X where dest )
253
{
254
   if ( whereis ( a ) == Freg ) {
255
      if ( whereis ( dest ) == Freg ) {
256
         ins2 ( m_fnegx, L64, L64, a, dest, 1 ) ;
257
         test_float_overflow_reg(dest, L64) ;
258
      } else {
259
         negate_float ( sha, a, FP0 ) ;
260
         move ( sha, FP0, dest ) ;
261
      }
262
   }
263
   else {
264
      move ( sha, a, FP0 ) ;
265
      negate_float ( sha, FP0, FP0 ) ;
266
      move ( sha, FP0, dest ) ;
267
      test_float_overflow(FP0, dest, shape_size(sha)) ;
268
   }
269
   have_cond = 0 ;
270
}
271
 
272
 
273
/*
274
    FIND THE ABSOLUTE VALUE OF A FLOATING-POINT NUMBER
275
 
276
    The floating-point value a of shape sha is has its absolute value
277
    stored in dest.
278
*/
279
 
280
void abs_float
281
    PROTO_N ( ( sha, a, dest ) )
282
    PROTO_T ( shape sha X where a X where dest )
283
{
284
    if ( whereis ( a ) == Freg ) {
285
	if ( whereis ( dest ) == Freg ) {
286
	    ins2 ( m_fabsx, L64, L64, a, dest, 1 ) ;
287
            test_float_overflow_reg(dest, L64) ;
288
	} else {
289
	    abs_float ( sha, a, FP0 ) ;
290
	    move ( sha, FP0, dest ) ;
291
	}
292
    } else {
293
	move ( sha, a, FP0 ) ;
294
	abs_float ( sha, FP0, FP0 ) ;
295
	move ( sha, FP0, dest ) ;
296
    }
297
    have_cond = 0 ;
298
}
299
 
300
 
301
/*
302
    CHANGE FLOATING VARIETY
303
 
304
    The floating-point value from is converted to a value of shape sha
305
    and stored in to.
306
*/
307
 
308
void change_flvar
309
    PROTO_N ( ( sha, from, to ) )
310
    PROTO_T ( shape sha X where from X where to )
311
{
312
    shape shf = sh ( from.wh_exp ) ;
313
    if ( whereis ( to ) == Freg ) {
314
	if ( whereis ( from ) == Freg ) {
315
	    move ( realsh, from, to ) ;
316
	    return ;
317
	}
318
	if ( shape_size ( shf ) > shape_size ( sha ) ) {
319
	    move ( shf, from, to ) ;
320
	    move ( sha, to, D0 ) ;
321
	    move ( sha, D0, to ) ;
322
	    return ;
323
	}
324
	move ( shf, from, to ) ;
325
	return ;
326
    }
327
    if ( whereis ( from ) == Freg ) {
328
	move ( sha, from, to ) ;
329
        test_float_overflow_reg(to, shape_size(sha)) ;
330
	return ;
331
    }
332
    move ( shf, from, FP0 ) ;
333
    move ( sha, FP0, to ) ;
334
    test_float_overflow(FP0, to, shape_size(sha)) ;
335
}
336
 
337
 
338
/*
339
    CURRENT ROUNDING MODE
340
 
341
    This gives the rounding mode for round_float.
342
*/
343
 
344
int crt_rmode = R2NEAR ;
345
 
346
 
347
/* Make floating point representing range_min(sha) - adjustment
348
Where Adjustment(adj) is 0,1,0.5 when adj is 0,1,2
349
*/
350
 
351
where get_min_limit
352
    PROTO_N ( ( sha, adj ) )
353
    PROTO_T ( shape sha X int adj )
354
{
355
   long fmd[4], min;
356
 
357
   if (name(sha)==ulonghd) {
358
      switch (adj) {
359
      case 0:
360
         /* res = 0 */
361
         fmd[0] = 0;
362
         fmd[1] = -1;
363
         return mfw(0,fmd,0);
364
      case 1:
365
         /* res = -1 */
366
         fmd[0] = 1;
367
         fmd[1] = -1;
368
         return mfw(-1,fmd,1);
369
      case 2:
370
         /* res = - 0.5 */
371
         fmd[0] = 0x8000;
372
         fmd[1] = -1;
373
         return mfw(-1,fmd,-1);
374
      }
375
   }
376
   if (name(sha)==slonghd) {
377
      switch (adj) {
378
      case 0:
379
         break ;
380
      case 1:
381
         /* res = - 2**31 - 1 */
382
         fmd[0] = 0x8000;
383
         fmd[1] = 0x0001;
384
         fmd[2] = -1;
385
         return mfw(-1,fmd,1);
386
 
387
      case 2:
388
         /* res = - 2**31 - 0.5 */
389
         fmd[0] = 0x8000;
390
         fmd[1] = 0x0000;
391
         fmd[2] = 0x8000;
392
         fmd[3] = -1;
393
         return mfw(-1,fmd,-1);
394
      }
395
   }
396
 
397
   min = range_min(sha) ;
398
   switch (adj) {
399
   case 0:
400
   case 1:
401
      /* min - (0|1) */
402
      min -= adj ;
403
      fmd[0] = (min>>16) & 0xffff;
404
      fmd[1] = min & 0xffff;
405
      fmd[2] = -1;
406
      return mfw((is_signed(sha)||adj)? -1 : 0,fmd,1);
407
   case 2:
408
      /* min - 0.5 */
409
      min -= 1 ;
410
      fmd[0] = (min>>16) & 0xffff;
411
      fmd[1] = min & 0xffff;
412
      fmd[2] = 0x8000;
413
      fmd[3] = -1;
414
      return mfw(-1,fmd,-1);
415
   }
416
 
417
   /* Shouldn't happen */
418
   fmd[0] = 0;
419
   fmd[1] = -1;
420
   return mfw(0,fmd,0);
421
}
422
 
423
/* Make floating point representing range_max(sha) + adjustment
424
Where Adjustment(adj) is 0,1,0.5 when adj is 0,1,2
425
*/
426
 
427
where get_max_limit
428
    PROTO_N ( ( sha, adj ) )
429
    PROTO_T ( shape sha X int adj )
430
{
431
   long fmd[6];
432
   long max = range_max(sha) ;
433
   if (name(sha)==ulonghd) {
434
      switch (adj) {
435
      case 0:
436
         /* max */
437
         fmd[0] = 0xffff;
438
         fmd[1] = 0xffff;
439
         fmd[2] = -1;
440
         return mfw(1,fmd,1);
441
      case 1:
442
         /* max + 1 */
443
         fmd[0] = 1;
444
         fmd[1] = 0;
445
         fmd[2] = 0;
446
         fmd[3] = -1;
447
         return mfw(1,fmd,2);
448
      case 2:
449
         /* max + 0.5 */
450
         fmd[0] = 1;
451
         fmd[1] = 0;
452
         fmd[2] = 0;
453
         fmd[3] = 0;
454
         fmd[4] = 0x8000;
455
         fmd[5] = -1;
456
         return mfw(1,fmd,-1);
457
      }
458
   }
459
   else {
460
      switch (adj) {
461
      case 0:
462
      case 1:
463
         /* max + (0|1) */
464
         max += adj ;
465
         fmd[0] = (max>>16) & 0xffff;
466
         fmd[1] = max & 0xffff;
467
         fmd[2] = -1;
468
         return mfw(1,fmd,1);
469
      case 2:
470
         /* max + 0.5 */
471
         fmd[0] = (max>>16) & 0xffff;
472
         fmd[1] = max & 0xffff;
473
         fmd[2] = 0x8000;
474
         fmd[3] = -1;
475
         return mfw(1,fmd,-1);
476
      }
477
   }
478
 
479
   /* Shouldn't happen */
480
   fmd[0] = 0xffff;
481
   fmd[1] = 0xffff;
482
   fmd[2] = -1;
483
   return mfw(1,fmd,1);
484
}
485
 
486
/* Test number against limit */
487
void check_limit
488
    PROTO_N ( ( number, limit, tst ) )
489
    PROTO_T ( where number X where limit X int tst )
490
{
491
   int sw, instr ;
492
   move(realsh,limit,FP1);
493
   sw = cmp(realsh,number,FP1,tst);
494
   instr = branch_ins(tst,sw,1,1);
495
   test_overflow2(instr);
496
}
497
 
498
/*
499
  Check that the floating point value in 'from' will, when rounded, fall
500
  within the range of the integer variety given by 'sha'.
501
*/
502
static void check_float_round_overflow
503
    PROTO_N ( (sha,from,mode) )
504
    PROTO_T ( shape sha X where from X int mode )
505
{
506
  if (overflow_jump == -1) {
507
     make_comment("error_teatment is trap");
508
     return;
509
  }
510
 
511
  make_comment("check_float_round_overflow ...");
512
 
513
  /* Setup min and max limits & decide tests */
514
  switch (mode) {
515
  case R2PINF:
516
     make_comment(" (toward larger) min-1 < x <= max");
517
     /* error if x <= min-1 or x > max */
518
     check_limit(from, get_min_limit(sha,1),tst_le) ;
519
     check_limit(from, get_max_limit(sha,0),tst_gr) ;
520
     break;
521
  case R2NINF:
522
     make_comment(" (toward smaller) min <= x < max+1");
523
     /* error if x < min or x >= max+1 */
524
     check_limit(from, get_min_limit(sha,0),tst_ls) ;
525
     check_limit(from, get_max_limit(sha,1),tst_ge) ;
526
     break;
527
  case R2ZERO:
528
     make_comment(" (toward zero) min-1 < x < max+1")  ;
529
     /* error if x <= min-1 or x >= max+1 */
530
     check_limit(from, get_min_limit(sha,1),tst_le) ;
531
     check_limit(from, get_max_limit(sha,1),tst_ge) ;
532
     break;
533
  case R2NEAR:
534
     make_comment(" (to nearest) min-0.5 <= x < max+0.5");
535
     /* error if x < min-0.5 or x >= max+0.5 */
536
     check_limit(from, get_min_limit(sha,2),tst_le) ;
537
     check_limit(from, get_max_limit(sha,2),tst_gr) ;
538
     break;
539
  case 4:
540
     make_comment(" (internal mode) min <= x <= max");
541
     /* error if x < min or x > max */
542
     check_limit(from, get_min_limit(sha,0),tst_ls) ;
543
     check_limit(from, get_max_limit(sha,0),tst_gr) ;
544
     break;
545
  default:
546
     error("check_float_round_overflow: wrong rounding mode");
547
  }
548
 
549
  make_comment("check_float_round_overflow done");
550
}
551
 
552
 
553
/*
554
   SET_ROUND_MODE
555
 
556
   Changes the default floating point rounding mode.
557
   Set bits 4 & 5 of fpcr (floating point control register)
558
   according to rounding mode.
559
 
560
   The global flag changed_round_mode is set to TRUE.
561
*/
562
 
563
bool changed_round_mode = 0 ;
564
 
565
void set_round_mode
566
    PROTO_N ( (mode) )
567
    PROTO_T ( int mode )
568
{
569
/*
570
   if (mode == f_to_nearest && ! changed_round_mode ) return ;
571
*/
572
   changed_round_mode = 1 ;
573
 
574
   ins2(m_fmovel,32,32,RW[REG_FPCR],D0,1);
575
 
576
   switch(mode){
577
   case R2NEAR:
578
      make_comment("round mode to nearest");
579
      /* to nearest => bit 4 = 0, bit 5 = 0 */
580
      ins2n(m_bclr,4,32,D0,1);
581
      ins2n(m_bclr,5,32,D0,1);
582
      break;
583
   case R2PINF:
584
      make_comment("round mode to larger");
585
      /* to + INF  => bit 4 =1, bit5 = 1 */
586
      ins2n(m_bset,4,32,D0,1);
587
      ins2n(m_bset,5,32,D0,1);
588
      break;
589
   case R2NINF:
590
      make_comment("round mode to smaller");
591
      /* to - INF => bit 4 = 0, bit 5 = 1 */
592
      ins2n(m_bclr,4,32,D0,1);
593
      ins2n(m_bset,5,32,D0,1);
594
      break;
595
   case R2ZERO:
596
      make_comment("round mode to zero");
597
      /* to zero => bit 4 = 1, bit 5 = 0
598
         This should never occur, as fintrz is always used
599
         for round to zero */
600
      ins2n(m_bset,4,32,D0,1);
601
      ins2n(m_bclr,5,32,D0,1);
602
      break;
603
   default:
604
      error("wrong rounding mode");
605
   }
606
   ins2(m_fmovel,32,32,D0,RW[REG_FPCR],1);
607
}
608
 
609
void reset_round_mode
610
    PROTO_Z ()
611
{
612
   if ( changed_round_mode ) {
613
      set_round_mode ( f_to_nearest ) ;
614
      changed_round_mode = 0;
615
   }
616
}
617
 
618
 
619
/*
620
    ROUND A FLOATING POINT NUMBER TO AN INTEGER
621
 
622
    The floating-point value from is rounded to an integer value of shape
623
    sha and stored in to.  The rounding mode is given by crt_rmode.
624
*/
625
 
626
void round_float
627
    PROTO_N ( ( sha, from, to ) )
628
    PROTO_T ( shape sha X where from X where to )
629
{
630
    where fr ;
631
    where dest ;
632
    int mode = crt_rmode ;
633
 
634
    if ( name ( sha ) == ulonghd ) {
635
        if(have_overflow()) {
636
            /* This must be checked before a round operation is attempted
637
               because out-of-range values can cause an exception */
638
            check_float_round_overflow(sha,from,mode);
639
        }
640
 
641
	if ( mode == f_toward_zero|| mode == 4 ) {
642
 
643
#ifdef float_to_unsigned
644
	    change_flvar ( realsh, from, FP0 ) ;
645
	    push_float ( L64, FP0 ) ;
646
#ifdef float_to_unsigned_uses_fp1
647
	    if ( mode == 4 && eq_where ( from, FP1 ) {
648
		push_float ( L64, FP1 ) ;
649
		libcall ( float_to_unsigned ) ;
650
		pop_float ( L64, FP1 ) ;
651
	    } else
652
#endif
653
	    libcall ( float_to_unsigned ) ;
654
	    dec_stack ( -64 ) ;
655
	    have_cond = 0 ;
656
	    move ( ulongsh, D0, to ) ;
657
#else
658
	    where fm ;
659
	    long lab1 = next_lab () ;
660
	    long lab2 = next_lab () ;
661
	    exp jt = simple_exp ( 0 ) ;
662
	    ptno ( jt ) = lab1 ;
663
	    regsinproc |= regmsk ( REG_FP1 ) ;
664
#ifdef FBASE_10
665
	    fm = mfw ( 1, "2147483648", 9 ) ;
666
#else
667
	    {
668
		static long fmd [] = { 32768, 0, -1 } ;
669
		fm = mfw ( 1, fmd, 1 ) ;
670
	    }
671
#endif
672
	    change_flvar ( realsh, from, FP0 ) ;
673
	    move ( realsh, fm, FP1 ) ;
674
	    regsinproc |= regmsk ( REG_FP1 ) ;
675
	    ins2_cmp ( m_fcmpx, L64, L64, FP0, FP1, 0 ) ;
676
	    branch ( tst_gr, jt, 1, 1, 1 ) ;
677
	    ins2 ( m_fsubx, L64, L64, FP1, FP0, regmsk ( REG_FP0 ) ) ;
678
	    if ( whereis ( to ) == Dreg ) {
679
	      ins2 (m_fintrzx,L32,L32,FP0,FP0,1);
680
	      ins2 ( m_fmovel, L32, L32, FP0, to, 1 ) ;
681
	      or ( ulongsh, to, mnw ( (long)2147483648UL ), to ) ;
682
	    } else {
683
	       ins2 (m_fintrzx,L32,L32,FP0,FP0,1);
684
	       ins2 ( m_fmovel, L32, L32, FP0, D0, 1 ) ;
685
	       or ( ulongsh, D0, mnw ( (long)2147483648UL ), D0 ) ;
686
	       move ( ulongsh, D0, to ) ;
687
	    }
688
	    make_jump ( m_bra, lab2 ) ;
689
	    make_label ( lab1 ) ;
690
	    if ( whereis ( to ) == Dreg ) {
691
	      ins2 (m_fintrzx,L32,L32,FP0,FP0,1);
692
	      ins2 ( m_fmovel, L32, L32, FP0, to, 1 ) ;
693
	    } else {
694
	      ins2 (m_fintrzx,L32,L32,FP0,FP0,1);
695
	      ins2 ( m_fmovel, L32, L32, FP0, D0, 1 ) ;
696
	      move ( ulongsh, D0, to ) ;
697
	    }
698
	    make_label ( lab2 ) ;
699
	    have_cond = 0 ;
700
#endif
701
	    return ;
702
	}
703
 
704
    } else {
705
 
706
 
707
	if ( mode == 4 ) {
708
	    /* Special case - move FP0 into the register to */
709
	    ins2 ( m_fmovel, L32, L32, FP0, to, 1 ) ;
710
 
711
            /* This might generate operand error */
712
            test_overflow(ON_FP_OPERAND_ERROR);
713
 
714
	    have_cond = 0 ;
715
	    change_var_sh ( sha, slongsh, to, to ) ;
716
	    return ;
717
	}
718
 
719
	if(have_overflow()) {
720
	  /* This must be checked before a round operation is attempted
721
	     because out-of-range values can cause an exception */
722
	  check_float_round_overflow(sha,from,mode);
723
	}
724
 
725
	if ( mode == f_toward_zero || mode == f_to_nearest ) {
726
	    /* Rounding to nearest or towards zero are easy */
727
	    int instr ;
728
	    shape shf = sh ( from.wh_exp ) ;
729
	    long szf = shape_size ( shf ) ;
730
	    if ( mode == f_toward_zero ) {
731
		instr = m_fintrzx ;
732
		if ( whereis ( from ) != Freg ) {
733
		    instr = insf ( szf, ml_fint ) ;
734
		}
735
	    } else {
736
                set_round_mode(mode);
737
		instr = m_fintx ;
738
		if ( whereis ( from ) != Freg ) {
739
		    instr = insf ( szf, ml_fintrz ) ;
740
		}
741
	    }
742
	    ins2 ( instr, szf, szf, from, FP0, 1 ) ;
743
	    if ( whereis ( to ) == Dreg ) {
744
		dest = to ;
745
	    } else {
746
		dest = D0 ;
747
	    }
748
	    ins2 ( m_fmovel, L32, L32, FP0, dest, 1 ) ;
749
	    have_cond = 0 ;
750
	    change_var_sh ( sha, slongsh, dest, to ) ;
751
	    return ;
752
	}
753
    }
754
 
755
    /* Other modes : firstly find some registers */
756
    if ( whereis ( to ) == Dreg ) {
757
	dest = to ;
758
    } else {
759
	dest = D0 ;
760
    }
761
    if ( whereis ( from ) == Freg && !eq_where ( from, FP0 ) ) {
762
	fr = from ;
763
    } else {
764
	shape shf = sh ( from.wh_exp ) ;
765
	fr = FP1 ;
766
	regsinproc |= regmsk ( REG_FP1 ) ;
767
	move ( shf, from, fr ) ;
768
    }
769
 
770
    /* Round fr into FP0 */
771
    if ( mode == f_toward_zero ) {
772
       ins2 ( m_fintrzx, 64, 64, fr, FP0, 1 ) ;
773
    }
774
    else {
775
       set_round_mode(mode);
776
       ins2 ( m_fintx, 64, 64, fr, FP0, 1 ) ;
777
    }
778
 
779
    /* Move FP0 into dest */
780
    crt_rmode = 4 ;
781
    round_float ( sha, FP0, dest ) ;
782
    crt_rmode = mode ;
783
 
784
    /* Move result into place */
785
    have_cond = 0 ;
786
    move ( sha, dest, to ) ;
787
    return ;
788
}
789
 
790
 
791
/*
792
    CONVERT AN INTEGER TO A FLOATING POINT NUMBER
793
 
794
    The integer value from is converted to a floating-point value of
795
    shape sha and stored in to.  Unsigned longs are difficult.  Error
796
    treatments are ignored (they cannot occur at present).
797
*/
798
 
799
void int_to_float
800
    PROTO_N ( ( sha, from, to ) )
801
    PROTO_T ( shape sha X where from X where to )
802
{
803
    where fpr ;
804
    shape shf = sh ( from.wh_exp ) ;
805
#ifdef REJECT
806
    fpr = ( whereis ( to ) == Freg ? to : FP0 ) ;
807
#else
808
    fpr = FP0 ;
809
#endif
810
    if ( name ( shf ) == ulonghd ) {
811
#ifdef unsigned_to_float
812
	if ( whereis ( from ) == Dreg ) {
813
	    push ( slongsh, L32, from ) ;
814
	} else {
815
	    move ( shf, from, D0 ) ;
816
	    push ( slongsh, L32, D0 ) ;
817
	}
818
	libcall ( unsigned_to_float ) ;
819
	dec_stack ( -32 ) ;
820
	have_cond = 0 ;
821
	move ( realsh, D0_D1, fpr ) ;
822
	move ( sha, fpr, to ) ;
823
	return ;
824
#else
825
	where fm ;
826
	long lab = next_lab () ;
827
	exp jt = simple_exp ( 0 ) ;
828
	ptno ( jt ) = lab ;
829
#ifdef FBASE_10
830
	fm = mfw ( 1, "4294967296", 9 ) ;
831
#else
832
	{
833
	    static long fmd [] = { 1, 0, 0, -1 } ;
834
	    fm = mfw ( 1, fmd, 2 ) ;
835
	}
836
#endif
837
	if ( whereis ( from ) == Dreg ) {
838
	    ins2 ( m_fmovel, L32, L64, from, fpr, 1 ) ;
839
	} else {
840
	    move ( slongsh, from, D0 ) ;
841
	    ins2 ( m_fmovel, L32, L64, D0, fpr, 1 ) ;
842
	}
843
	branch ( tst_ge, jt, 1, 1, 1 ) ;
844
	add ( sha, fpr, fm, fpr ) ;
845
	make_label ( lab ) ;
846
	have_cond = 0 ;
847
	move ( sha, fpr, to ) ;
848
	return ;
849
#endif
850
    }
851
    if ( name ( shf ) == slonghd && whereis ( from ) == Dreg ) {
852
	ins2 ( m_fmovel, L32, L64, from, fpr, 1 ) ;
853
    } else {
854
	change_var_sh ( slongsh, shf, from, D0 ) ;
855
	ins2 ( m_fmovel, L32, L64, D0, fpr, 1 ) ;
856
    }
857
    move ( sha, fpr, to ) ;
858
    have_cond = 0 ;
859
    return ;
860
}