Subversion Repositories tendra.SVN

Rev

Rev 5 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 5 Rev 6
Line -... Line 1...
-
 
1
/*
-
 
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
 */
1
/*
31
/*
2
    		 Crown Copyright (c) 1997
32
    		 Crown Copyright (c) 1997
3
 
33
 
4
    This TenDRA(r) Computer Program is subject to Copyright
34
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
35
    owned by the United Kingdom Secretary of State for Defence
Line 109... Line 139...
109
 
139
 
110
/*
140
/*
111
    GIVE PROTOTYPE FOR MFW
141
    GIVE PROTOTYPE FOR MFW
112
*/
142
*/
113
 
143
 
114
#if ( FBASE == 10 )
144
#if (FBASE == 10)
115
extern where mfw PROTO_S ( ( int, char *, int ) ) ;
145
extern where mfw(int, char *, int);
116
#define FBASE_10
146
#define FBASE_10
117
#else
147
#else
118
extern where mfw PROTO_S ( ( int, long *, int ) ) ;
148
extern where mfw(int, long *, int);
119
#undef FBASE_10
149
#undef FBASE_10
120
#endif
150
#endif
121
 
151
 
122
extern int need_dummy_double;
152
extern int need_dummy_double;
123
/************************************************************************
153
/************************************************************************
Line 126... Line 156...
126
  freg is a Freg which is moved to a dummy memory location to force the
156
  freg is a Freg which is moved to a dummy memory location to force the
127
  overflow (if any) before the test.
157
  overflow (if any) before the test.
128
 ************************************************************************/
158
 ************************************************************************/
129
 
159
 
130
void test_float_overflow_reg
160
void test_float_overflow_reg
131
    PROTO_N ( ( freg, sz ) )
-
 
132
    PROTO_T ( where freg X long sz )
161
(where freg, long sz)
133
{
162
{
134
   if (have_overflow()) {
163
   if (have_overflow()) {
135
      ins2 ( insf ( sz, ml_fmove ), sz, sz, freg, dummy_double_dest, 1 ) ;
164
      ins2(insf(sz, ml_fmove), sz, sz, freg, dummy_double_dest, 1);
136
      test_overflow(ON_FP_OVERFLOW) ;
165
      test_overflow(ON_FP_OVERFLOW);
137
      need_dummy_double = 1 ;
166
      need_dummy_double = 1;
138
   }
167
   }
139
}
168
}
140
 
169
 
141
/************************************************************************
170
/************************************************************************
142
  Test for overflow.
171
  Test for overflow.
Line 144... Line 173...
144
  If dest is zero, freg is moved to a memory location to force the
173
  If dest is zero, freg is moved to a memory location to force the
145
  overflow (if any) before the test.
174
  overflow (if any) before the test.
146
  ************************************************************************/
175
  ************************************************************************/
147
 
176
 
148
void test_float_overflow
177
void test_float_overflow
149
    PROTO_N ( ( freg, dest, sz ) )
-
 
150
    PROTO_T ( where freg X where dest X long sz )
178
(where freg, where dest, long sz)
151
{
179
{
152
   if (have_overflow()) {
180
   if (have_overflow()) {
153
      if (eq_where(dest, zero)) {
181
      if (eq_where(dest, zero)) {
154
         ins2 ( insf ( sz, ml_fmove ), sz, sz, freg, dummy_double_dest, 1 ) ;
182
         ins2(insf(sz, ml_fmove), sz, sz, freg, dummy_double_dest, 1);
155
         need_dummy_double = 1 ;
183
         need_dummy_double = 1;
156
      }
184
      }
157
      test_overflow(ON_FP_OVERFLOW) ;
185
      test_overflow(ON_FP_OVERFLOW);
158
   }
186
   }
159
}
187
}
160
 
188
 
161
 
189
 
162
/*
190
/*
Line 166... Line 194...
166
    operation indicated by the tag t applied to them and the result is
194
    operation indicated by the tag t applied to them and the result is
167
    stored in dest.
195
    stored in dest.
168
*/
196
*/
169
 
197
 
170
void fl_binop
198
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 )
199
(int t, shape sha, where a1, where a2, where dest)
173
{
200
{
174
    int op, op1, op2 ;
201
    int op, op1, op2;
175
    bool commutes = 0 ;
202
    bool commutes = 0;
176
    int err = ON_FP_OVERFLOW ;
203
    int err = ON_FP_OVERFLOW;
177
    long sz = shape_size ( sha ) ;
204
    long sz = shape_size(sha);
178
 
205
 
179
    switch ( t ) {
206
    switch (t) {
180
	case fplus_tag : {
207
	case fplus_tag: {
181
	    commutes = 1 ;
208
	    commutes = 1;
182
	    op1 = insf ( sz, ml_fadd ) ;
209
	    op1 = insf(sz, ml_fadd);
183
	    op2 = m_faddx ;
210
	    op2 = m_faddx;
184
	    break ;
211
	    break;
185
	}
212
	}
186
	case fminus_tag : {
213
	case fminus_tag: {
187
	    op1 = insf ( sz, ml_fsub ) ;
214
	    op1 = insf(sz, ml_fsub);
188
	    op2 = m_fsubx ;
215
	    op2 = m_fsubx;
189
	    break ;
216
	    break;
190
	}
217
	}
191
	case fmult_tag : {
218
	case fmult_tag: {
192
	    commutes = 1 ;
219
	    commutes = 1;
193
	    op1 = insf ( sz, ml_fmul ) ;
220
	    op1 = insf(sz, ml_fmul);
194
	    op2 = m_fmulx ;
221
	    op2 = m_fmulx;
195
	    break ;
222
	    break;
196
	}
223
	}
197
	case fdiv_tag : {
224
	case fdiv_tag: {
198
	    op1 = insf ( sz, ml_fdiv ) ;
225
	    op1 = insf(sz, ml_fdiv);
199
	    op2 = m_fdivx ;
226
	    op2 = m_fdivx;
200
	    err = ON_FP_CARRY ;
227
	    err = ON_FP_CARRY;
201
	    break ;
228
	    break;
202
	}
229
	}
203
	default : {
230
	default : {
204
	    error ( "Illegal floating operation" ) ;
231
	    error("Illegal floating operation");
205
	    return ;
232
	    return;
206
	}
233
	}
207
    }
234
    }
208
 
235
 
209
    if ( whereis ( dest ) == Freg ) {
236
    if (whereis(dest) == Freg) {
210
       if ( eq_where ( a1, dest ) ) {
237
       if (eq_where(a1, dest)) {
211
          if ( commutes ) {
238
          if (commutes) {
212
             op = ( whereis ( a2 ) == Freg ? op2 : op1 ) ;
239
             op = (whereis(a2) == Freg ? op2 : op1);
213
             ins2 ( op, sz, sz, a2, dest, 1 ) ;
240
             ins2(op, sz, sz, a2, dest, 1);
214
             if (t == fdiv_tag) test_overflow(ON_FP_OVERFLOW) ; /* divided by 0 ? */
241
             if (t == fdiv_tag) test_overflow(ON_FP_OVERFLOW) ; /* divided by 0 ? */
215
             test_float_overflow_reg(dest, sz) ;
242
             test_float_overflow_reg(dest, sz);
216
          }
243
          }
217
          else {
244
          else {
218
             move ( sha, a2, FP0 ) ;
245
             move(sha, a2, FP0);
219
             ins2 ( op2, sz, sz, a1, FP0, 1 ) ;
246
             ins2(op2, sz, sz, a1, FP0, 1);
220
             if (t == fdiv_tag) test_overflow(ON_FP_OVERFLOW) ; /* divided by 0 ? */
247
             if (t == fdiv_tag) test_overflow(ON_FP_OVERFLOW) ; /* divided by 0 ? */
221
             move ( sha, FP0, dest ) ;
248
             move(sha, FP0, dest);
222
          }
249
          }
223
       } else {
250
       } else {
224
          move ( sha, a2, dest ) ;
251
          move(sha, a2, dest);
225
          op = ( whereis ( a1 ) == Freg ? op2 : op1 ) ;
252
          op = (whereis(a1) == Freg ? op2 : op1);
226
          ins2 ( op, sz, sz, a1, dest, 1 ) ;
253
          ins2(op, sz, sz, a1, dest, 1);
227
          if (t == fdiv_tag) test_overflow(ON_FP_OVERFLOW) ; /* divided by 0 ? */
254
          if (t == fdiv_tag) test_overflow(ON_FP_OVERFLOW) ; /* divided by 0 ? */
228
          test_float_overflow_reg(dest, sz) ;
255
          test_float_overflow_reg(dest, sz);
229
       }
256
       }
230
    }
257
    }
231
    else {
258
    else {
232
       move ( sha, a2, FP0 ) ;
259
       move(sha, a2, FP0);
233
       op = ( whereis ( a1 ) == Freg ? op2 : op1 ) ;
260
       op = (whereis(a1) == Freg ? op2 : op1);
234
       ins2 ( op, sz, sz, a1, FP0, 1 ) ;
261
       ins2(op, sz, sz, a1, FP0, 1);
235
       if (t == fdiv_tag) test_overflow(ON_FP_OVERFLOW) ; /* divided by 0 ? */
262
       if (t == fdiv_tag) test_overflow(ON_FP_OVERFLOW) ; /* divided by 0 ? */
236
       move ( sha, FP0, dest ) ;
263
       move(sha, FP0, dest);
237
       test_float_overflow(FP0, dest, sz) ;
264
       test_float_overflow(FP0, dest, sz);
238
    }
265
    }
239
    have_cond = 0 ;
266
    have_cond = 0;
240
    return ;
267
    return;
241
}
268
}
242
 
269
 
243
 
270
 
244
/*
271
/*
245
    NEGATE A FLOATING-POINT NUMBER
272
    NEGATE A FLOATING-POINT NUMBER
246
 
273
 
247
    The floating-point value a of shape sha is negated and stored in dest.
274
    The floating-point value a of shape sha is negated and stored in dest.
248
*/
275
*/
249
 
276
 
250
void negate_float
277
void negate_float
251
    PROTO_N ( ( sha, a, dest ) )
-
 
252
    PROTO_T ( shape sha X where a X where dest )
278
(shape sha, where a, where dest)
253
{
279
{
254
   if ( whereis ( a ) == Freg ) {
280
   if (whereis(a) == Freg) {
255
      if ( whereis ( dest ) == Freg ) {
281
      if (whereis(dest) == Freg) {
256
         ins2 ( m_fnegx, L64, L64, a, dest, 1 ) ;
282
         ins2(m_fnegx, L64, L64, a, dest, 1);
257
         test_float_overflow_reg(dest, L64) ;
283
         test_float_overflow_reg(dest, L64);
258
      } else {
284
      } else {
259
         negate_float ( sha, a, FP0 ) ;
285
         negate_float(sha, a, FP0);
260
         move ( sha, FP0, dest ) ;
286
         move(sha, FP0, dest);
261
      }
287
      }
262
   }
288
   }
263
   else {
289
   else {
264
      move ( sha, a, FP0 ) ;
290
      move(sha, a, FP0);
265
      negate_float ( sha, FP0, FP0 ) ;
291
      negate_float(sha, FP0, FP0);
266
      move ( sha, FP0, dest ) ;
292
      move(sha, FP0, dest);
267
      test_float_overflow(FP0, dest, shape_size(sha)) ;
293
      test_float_overflow(FP0, dest, shape_size(sha));
268
   }
294
   }
269
   have_cond = 0 ;
295
   have_cond = 0;
270
}
296
}
271
 
297
 
272
 
298
 
273
/*
299
/*
274
    FIND THE ABSOLUTE VALUE OF A FLOATING-POINT NUMBER
300
    FIND THE ABSOLUTE VALUE OF A FLOATING-POINT NUMBER
Line 276... Line 302...
276
    The floating-point value a of shape sha is has its absolute value
302
    The floating-point value a of shape sha is has its absolute value
277
    stored in dest.
303
    stored in dest.
278
*/
304
*/
279
 
305
 
280
void abs_float
306
void abs_float
281
    PROTO_N ( ( sha, a, dest ) )
-
 
282
    PROTO_T ( shape sha X where a X where dest )
307
(shape sha, where a, where dest)
283
{
308
{
284
    if ( whereis ( a ) == Freg ) {
309
    if (whereis(a) == Freg) {
285
	if ( whereis ( dest ) == Freg ) {
310
	if (whereis(dest) == Freg) {
286
	    ins2 ( m_fabsx, L64, L64, a, dest, 1 ) ;
311
	    ins2(m_fabsx, L64, L64, a, dest, 1);
287
            test_float_overflow_reg(dest, L64) ;
312
            test_float_overflow_reg(dest, L64);
288
	} else {
313
	} else {
289
	    abs_float ( sha, a, FP0 ) ;
314
	    abs_float(sha, a, FP0);
290
	    move ( sha, FP0, dest ) ;
315
	    move(sha, FP0, dest);
291
	}
316
	}
292
    } else {
317
    } else {
293
	move ( sha, a, FP0 ) ;
318
	move(sha, a, FP0);
294
	abs_float ( sha, FP0, FP0 ) ;
319
	abs_float(sha, FP0, FP0);
295
	move ( sha, FP0, dest ) ;
320
	move(sha, FP0, dest);
296
    }
321
    }
297
    have_cond = 0 ;
322
    have_cond = 0;
298
}
323
}
299
 
324
 
300
 
325
 
301
/*
326
/*
302
    CHANGE FLOATING VARIETY
327
    CHANGE FLOATING VARIETY
Line 304... Line 329...
304
    The floating-point value from is converted to a value of shape sha
329
    The floating-point value from is converted to a value of shape sha
305
    and stored in to.
330
    and stored in to.
306
*/
331
*/
307
 
332
 
308
void change_flvar
333
void change_flvar
309
    PROTO_N ( ( sha, from, to ) )
-
 
310
    PROTO_T ( shape sha X where from X where to )
334
(shape sha, where from, where to)
311
{
335
{
312
    shape shf = sh ( from.wh_exp ) ;
336
    shape shf = sh(from.wh_exp);
313
    if ( whereis ( to ) == Freg ) {
337
    if (whereis(to) == Freg) {
314
	if ( whereis ( from ) == Freg ) {
338
	if (whereis(from) == Freg) {
315
	    move ( realsh, from, to ) ;
339
	    move(realsh, from, to);
316
	    return ;
340
	    return;
317
	}
341
	}
318
	if ( shape_size ( shf ) > shape_size ( sha ) ) {
342
	if (shape_size(shf) > shape_size(sha)) {
319
	    move ( shf, from, to ) ;
343
	    move(shf, from, to);
320
	    move ( sha, to, D0 ) ;
344
	    move(sha, to, D0);
321
	    move ( sha, D0, to ) ;
345
	    move(sha, D0, to);
322
	    return ;
346
	    return;
323
	}
347
	}
324
	move ( shf, from, to ) ;
348
	move(shf, from, to);
325
	return ;
349
	return;
326
    }
350
    }
327
    if ( whereis ( from ) == Freg ) {
351
    if (whereis(from) == Freg) {
328
	move ( sha, from, to ) ;
352
	move(sha, from, to);
329
        test_float_overflow_reg(to, shape_size(sha)) ;
353
        test_float_overflow_reg(to, shape_size(sha));
330
	return ;
354
	return;
331
    }
355
    }
332
    move ( shf, from, FP0 ) ;
356
    move(shf, from, FP0);
333
    move ( sha, FP0, to ) ;
357
    move(sha, FP0, to);
334
    test_float_overflow(FP0, to, shape_size(sha)) ;
358
    test_float_overflow(FP0, to, shape_size(sha));
335
}
359
}
336
 
360
 
337
 
361
 
338
/*
362
/*
339
    CURRENT ROUNDING MODE
363
    CURRENT ROUNDING MODE
340
 
364
 
341
    This gives the rounding mode for round_float.
365
    This gives the rounding mode for round_float.
342
*/
366
*/
343
 
367
 
344
int crt_rmode = R2NEAR ;
368
int crt_rmode = R2NEAR;
345
 
369
 
346
 
370
 
347
/* Make floating point representing range_min(sha) - adjustment
371
/* Make floating point representing range_min(sha) - adjustment
348
Where Adjustment(adj) is 0,1,0.5 when adj is 0,1,2
372
Where Adjustment(adj) is 0,1,0.5 when adj is 0,1,2
349
*/
373
*/
350
 
374
 
351
where get_min_limit
375
where get_min_limit
352
    PROTO_N ( ( sha, adj ) )
-
 
353
    PROTO_T ( shape sha X int adj )
376
(shape sha, int adj)
354
{
377
{
355
   long fmd[4], min;
378
   long fmd[4], min;
356
 
379
 
357
   if (name(sha)==ulonghd) {
380
   if (name(sha) ==ulonghd) {
358
      switch (adj) {
381
      switch (adj) {
359
      case 0:
382
      case 0:
360
         /* res = 0 */
383
         /* res = 0 */
361
         fmd[0] = 0;
384
         fmd[0] = 0;
362
         fmd[1] = -1;
385
         fmd[1] = -1;
Line 371... Line 394...
371
         fmd[0] = 0x8000;
394
         fmd[0] = 0x8000;
372
         fmd[1] = -1;
395
         fmd[1] = -1;
373
         return mfw(-1,fmd,-1);
396
         return mfw(-1,fmd,-1);
374
      }
397
      }
375
   }
398
   }
376
   if (name(sha)==slonghd) {
399
   if (name(sha) ==slonghd) {
377
      switch (adj) {
400
      switch (adj) {
378
      case 0:
401
      case 0:
379
         break ;
402
         break;
380
      case 1:
403
      case 1:
381
         /* res = - 2**31 - 1 */
404
         /* res = - 2**31 - 1 */
382
         fmd[0] = 0x8000;
405
         fmd[0] = 0x8000;
383
         fmd[1] = 0x0001;
406
         fmd[1] = 0x0001;
384
         fmd[2] = -1;
407
         fmd[2] = -1;
Line 392... Line 415...
392
         fmd[3] = -1;
415
         fmd[3] = -1;
393
         return mfw(-1,fmd,-1);
416
         return mfw(-1,fmd,-1);
394
      }
417
      }
395
   }
418
   }
396
 
419
 
397
   min = range_min(sha) ;
420
   min = range_min(sha);
398
   switch (adj) {
421
   switch (adj) {
399
   case 0:
422
   case 0:
400
   case 1:
423
   case 1:
401
      /* min - (0|1) */
424
      /* min - (0|1) */
402
      min -= adj ;
425
      min -= adj;
403
      fmd[0] = (min>>16) & 0xffff;
426
      fmd[0] = (min>>16) & 0xffff;
404
      fmd[1] = min & 0xffff;
427
      fmd[1] = min & 0xffff;
405
      fmd[2] = -1;
428
      fmd[2] = -1;
406
      return mfw((is_signed(sha)||adj)? -1 : 0,fmd,1);
429
      return mfw((is_signed(sha) ||adj)? -1 : 0,fmd,1);
407
   case 2:
430
   case 2:
408
      /* min - 0.5 */
431
      /* min - 0.5 */
409
      min -= 1 ;
432
      min -= 1;
410
      fmd[0] = (min>>16) & 0xffff;
433
      fmd[0] = (min>>16) & 0xffff;
411
      fmd[1] = min & 0xffff;
434
      fmd[1] = min & 0xffff;
412
      fmd[2] = 0x8000;
435
      fmd[2] = 0x8000;
413
      fmd[3] = -1;
436
      fmd[3] = -1;
414
      return mfw(-1,fmd,-1);
437
      return mfw(-1,fmd,-1);
Line 423... Line 446...
423
/* Make floating point representing range_max(sha) + adjustment
446
/* Make floating point representing range_max(sha) + adjustment
424
Where Adjustment(adj) is 0,1,0.5 when adj is 0,1,2
447
Where Adjustment(adj) is 0,1,0.5 when adj is 0,1,2
425
*/
448
*/
426
 
449
 
427
where get_max_limit
450
where get_max_limit
428
    PROTO_N ( ( sha, adj ) )
-
 
429
    PROTO_T ( shape sha X int adj )
451
(shape sha, int adj)
430
{
452
{
431
   long fmd[6];
453
   long fmd[6];
432
   long max = range_max(sha) ;
454
   long max = range_max(sha);
433
   if (name(sha)==ulonghd) {
455
   if (name(sha) ==ulonghd) {
434
      switch (adj) {
456
      switch (adj) {
435
      case 0:
457
      case 0:
436
         /* max */
458
         /* max */
437
         fmd[0] = 0xffff;
459
         fmd[0] = 0xffff;
438
         fmd[1] = 0xffff;
460
         fmd[1] = 0xffff;
Line 459... Line 481...
459
   else {
481
   else {
460
      switch (adj) {
482
      switch (adj) {
461
      case 0:
483
      case 0:
462
      case 1:
484
      case 1:
463
         /* max + (0|1) */
485
         /* max + (0|1) */
464
         max += adj ;
486
         max += adj;
465
         fmd[0] = (max>>16) & 0xffff;
487
         fmd[0] = (max>>16) & 0xffff;
466
         fmd[1] = max & 0xffff;
488
         fmd[1] = max & 0xffff;
467
         fmd[2] = -1;
489
         fmd[2] = -1;
468
         return mfw(1,fmd,1);
490
         return mfw(1,fmd,1);
469
      case 2:
491
      case 2:
Line 483... Line 505...
483
   return mfw(1,fmd,1);
505
   return mfw(1,fmd,1);
484
}
506
}
485
 
507
 
486
/* Test number against limit */
508
/* Test number against limit */
487
void check_limit
509
void check_limit
488
    PROTO_N ( ( number, limit, tst ) )
-
 
489
    PROTO_T ( where number X where limit X int tst )
510
(where number, where limit, int tst)
490
{
511
{
491
   int sw, instr ;
512
   int sw, instr;
492
   move(realsh,limit,FP1);
513
   move(realsh,limit,FP1);
493
   sw = cmp(realsh,number,FP1,tst);
514
   sw = cmp(realsh,number,FP1,tst);
494
   instr = branch_ins(tst,sw,1,1);
515
   instr = branch_ins(tst,sw,1,1);
495
   test_overflow2(instr);
516
   test_overflow2(instr);
496
}
517
}
Line 498... Line 519...
498
/*
519
/*
499
  Check that the floating point value in 'from' will, when rounded, fall
520
  Check that the floating point value in 'from' will, when rounded, fall
500
  within the range of the integer variety given by 'sha'.
521
  within the range of the integer variety given by 'sha'.
501
*/
522
*/
502
static void check_float_round_overflow
523
static void check_float_round_overflow
503
    PROTO_N ( (sha,from,mode) )
-
 
504
    PROTO_T ( shape sha X where from X int mode )
524
(shape sha, where from, int mode)
505
{
525
{
506
  if (overflow_jump == -1) {
526
  if (overflow_jump == -1) {
507
     make_comment("error_teatment is trap");
527
     make_comment("error_teatment is trap");
508
     return;
528
     return;
509
  }
529
  }
Line 513... Line 533...
513
  /* Setup min and max limits & decide tests */
533
  /* Setup min and max limits & decide tests */
514
  switch (mode) {
534
  switch (mode) {
515
  case R2PINF:
535
  case R2PINF:
516
     make_comment(" (toward larger) min-1 < x <= max");
536
     make_comment(" (toward larger) min-1 < x <= max");
517
     /* error if x <= min-1 or x > max */
537
     /* error if x <= min-1 or x > max */
518
     check_limit(from, get_min_limit(sha,1),tst_le) ;
538
     check_limit(from, get_min_limit(sha,1),tst_le);
519
     check_limit(from, get_max_limit(sha,0),tst_gr) ;
539
     check_limit(from, get_max_limit(sha,0),tst_gr);
520
     break;
540
     break;
521
  case R2NINF:
541
  case R2NINF:
522
     make_comment(" (toward smaller) min <= x < max+1");
542
     make_comment(" (toward smaller) min <= x < max+1");
523
     /* error if x < min or x >= max+1 */
543
     /* error if x < min or x >= max+1 */
524
     check_limit(from, get_min_limit(sha,0),tst_ls) ;
544
     check_limit(from, get_min_limit(sha,0),tst_ls);
525
     check_limit(from, get_max_limit(sha,1),tst_ge) ;
545
     check_limit(from, get_max_limit(sha,1),tst_ge);
526
     break;
546
     break;
527
  case R2ZERO:
547
  case R2ZERO:
528
     make_comment(" (toward zero) min-1 < x < max+1")  ;
548
     make_comment(" (toward zero) min-1 < x < max+1");
529
     /* error if x <= min-1 or x >= max+1 */
549
     /* error if x <= min-1 or x >= max+1 */
530
     check_limit(from, get_min_limit(sha,1),tst_le) ;
550
     check_limit(from, get_min_limit(sha,1),tst_le);
531
     check_limit(from, get_max_limit(sha,1),tst_ge) ;
551
     check_limit(from, get_max_limit(sha,1),tst_ge);
532
     break;
552
     break;
533
  case R2NEAR:
553
  case R2NEAR:
534
     make_comment(" (to nearest) min-0.5 <= x < max+0.5");
554
     make_comment(" (to nearest) min-0.5 <= x < max+0.5");
535
     /* error if x < min-0.5 or x >= max+0.5 */
555
     /* error if x < min-0.5 or x >= max+0.5 */
536
     check_limit(from, get_min_limit(sha,2),tst_le) ;
556
     check_limit(from, get_min_limit(sha,2),tst_le);
537
     check_limit(from, get_max_limit(sha,2),tst_gr) ;
557
     check_limit(from, get_max_limit(sha,2),tst_gr);
538
     break;
558
     break;
539
  case 4:
559
  case 4:
540
     make_comment(" (internal mode) min <= x <= max");
560
     make_comment(" (internal mode) min <= x <= max");
541
     /* error if x < min or x > max */
561
     /* error if x < min or x > max */
542
     check_limit(from, get_min_limit(sha,0),tst_ls) ;
562
     check_limit(from, get_min_limit(sha,0),tst_ls);
543
     check_limit(from, get_max_limit(sha,0),tst_gr) ;
563
     check_limit(from, get_max_limit(sha,0),tst_gr);
544
     break;
564
     break;
545
  default:
565
  default:
546
     error("check_float_round_overflow: wrong rounding mode");
566
     error("check_float_round_overflow: wrong rounding mode");
547
  }
567
  }
548
 
568
 
Line 558... Line 578...
558
   according to rounding mode.
578
   according to rounding mode.
559
 
579
 
560
   The global flag changed_round_mode is set to TRUE.
580
   The global flag changed_round_mode is set to TRUE.
561
*/
581
*/
562
 
582
 
563
bool changed_round_mode = 0 ;
583
bool changed_round_mode = 0;
564
 
584
 
565
void set_round_mode
585
void set_round_mode
566
    PROTO_N ( (mode) )
-
 
567
    PROTO_T ( int mode )
586
(int mode)
568
{
587
{
569
/*
588
/*
570
   if (mode == f_to_nearest && ! changed_round_mode ) return ;
589
   if (mode == f_to_nearest && ! changed_round_mode ) return ;
571
*/
590
*/
572
   changed_round_mode = 1 ;
591
   changed_round_mode = 1;
573
 
592
 
574
   ins2(m_fmovel,32,32,RW[REG_FPCR],D0,1);
593
   ins2(m_fmovel,32,32,RW[REG_FPCR],D0,1);
575
 
594
 
576
   switch(mode){
595
   switch (mode) {
577
   case R2NEAR:
596
   case R2NEAR:
578
      make_comment("round mode to nearest");
597
      make_comment("round mode to nearest");
579
      /* to nearest => bit 4 = 0, bit 5 = 0 */
598
      /* to nearest => bit 4 = 0, bit 5 = 0 */
580
      ins2n(m_bclr,4,32,D0,1);
599
      ins2n(m_bclr,4,32,D0,1);
581
      ins2n(m_bclr,5,32,D0,1);
600
      ins2n(m_bclr,5,32,D0,1);
Line 605... Line 624...
605
   }
624
   }
606
   ins2(m_fmovel,32,32,D0,RW[REG_FPCR],1);
625
   ins2(m_fmovel,32,32,D0,RW[REG_FPCR],1);
607
}
626
}
608
 
627
 
609
void reset_round_mode
628
void reset_round_mode
610
    PROTO_Z ()
629
(void)
611
{
630
{
612
   if ( changed_round_mode ) {
631
   if (changed_round_mode) {
613
      set_round_mode ( f_to_nearest ) ;
632
      set_round_mode(f_to_nearest);
614
      changed_round_mode = 0;
633
      changed_round_mode = 0;
615
   }
634
   }
616
}
635
}
617
 
636
 
618
 
637
 
Line 622... Line 641...
622
    The floating-point value from is rounded to an integer value of shape
641
    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.
642
    sha and stored in to.  The rounding mode is given by crt_rmode.
624
*/
643
*/
625
 
644
 
626
void round_float
645
void round_float
627
    PROTO_N ( ( sha, from, to ) )
-
 
628
    PROTO_T ( shape sha X where from X where to )
646
(shape sha, where from, where to)
629
{
647
{
630
    where fr ;
648
    where fr;
631
    where dest ;
649
    where dest;
632
    int mode = crt_rmode ;
650
    int mode = crt_rmode;
633
 
651
 
634
    if ( name ( sha ) == ulonghd ) {
652
    if (name(sha) == ulonghd) {
635
        if(have_overflow()) {
653
        if (have_overflow()) {
636
            /* This must be checked before a round operation is attempted
654
            /* This must be checked before a round operation is attempted
637
               because out-of-range values can cause an exception */
655
               because out-of-range values can cause an exception */
638
            check_float_round_overflow(sha,from,mode);
656
            check_float_round_overflow(sha,from,mode);
639
        }
657
        }
640
 
658
 
641
	if ( mode == f_toward_zero|| mode == 4 ) {
659
	if (mode == f_toward_zero|| mode == 4) {
642
 
660
 
643
#ifdef float_to_unsigned
661
#ifdef float_to_unsigned
644
	    change_flvar ( realsh, from, FP0 ) ;
662
	    change_flvar(realsh, from, FP0);
645
	    push_float ( L64, FP0 ) ;
663
	    push_float(L64, FP0);
646
#ifdef float_to_unsigned_uses_fp1
664
#ifdef float_to_unsigned_uses_fp1
647
	    if ( mode == 4 && eq_where ( from, FP1 ) {
665
	    if (mode == 4 && eq_where(from, FP1) {
648
		push_float ( L64, FP1 ) ;
666
		push_float(L64, FP1);
649
		libcall ( float_to_unsigned ) ;
667
		libcall(float_to_unsigned);
650
		pop_float ( L64, FP1 ) ;
668
		pop_float(L64, FP1);
651
	    } else
669
	    } else
652
#endif
670
#endif
653
	    libcall ( float_to_unsigned ) ;
671
	    libcall(float_to_unsigned);
654
	    dec_stack ( -64 ) ;
672
	    dec_stack(-64);
655
	    have_cond = 0 ;
673
	    have_cond = 0;
656
	    move ( ulongsh, D0, to ) ;
674
	    move(ulongsh, D0, to);
657
#else
675
#else
658
	    where fm ;
676
	    where fm;
659
	    long lab1 = next_lab () ;
677
	    long lab1 = next_lab();
660
	    long lab2 = next_lab () ;
678
	    long lab2 = next_lab();
661
	    exp jt = simple_exp ( 0 ) ;
679
	    exp jt = simple_exp(0);
662
	    ptno ( jt ) = lab1 ;
680
	    ptno(jt) = lab1;
663
	    regsinproc |= regmsk ( REG_FP1 ) ;
681
	    regsinproc |= regmsk(REG_FP1);
664
#ifdef FBASE_10
682
#ifdef FBASE_10
665
	    fm = mfw ( 1, "2147483648", 9 ) ;
683
	    fm = mfw(1, "2147483648", 9);
666
#else
684
#else
667
	    {
685
	    {
668
		static long fmd [] = { 32768, 0, -1 } ;
686
		static long fmd[] = { 32768, 0, -1 };
669
		fm = mfw ( 1, fmd, 1 ) ;
687
		fm = mfw(1, fmd, 1);
670
	    }
688
	    }
671
#endif
689
#endif
672
	    change_flvar ( realsh, from, FP0 ) ;
690
	    change_flvar(realsh, from, FP0);
673
	    move ( realsh, fm, FP1 ) ;
691
	    move(realsh, fm, FP1);
674
	    regsinproc |= regmsk ( REG_FP1 ) ;
692
	    regsinproc |= regmsk(REG_FP1);
675
	    ins2_cmp ( m_fcmpx, L64, L64, FP0, FP1, 0 ) ;
693
	    ins2_cmp(m_fcmpx, L64, L64, FP0, FP1, 0);
676
	    branch ( tst_gr, jt, 1, 1, 1 ) ;
694
	    branch(tst_gr, jt, 1, 1, 1);
677
	    ins2 ( m_fsubx, L64, L64, FP1, FP0, regmsk ( REG_FP0 ) ) ;
695
	    ins2(m_fsubx, L64, L64, FP1, FP0, regmsk(REG_FP0));
678
	    if ( whereis ( to ) == Dreg ) {
696
	    if (whereis(to) == Dreg) {
679
	      ins2 (m_fintrzx,L32,L32,FP0,FP0,1);
697
	      ins2(m_fintrzx,L32,L32,FP0,FP0,1);
680
	      ins2 ( m_fmovel, L32, L32, FP0, to, 1 ) ;
698
	      ins2(m_fmovel, L32, L32, FP0, to, 1);
681
	      or ( ulongsh, to, mnw ( (long)2147483648UL ), to ) ;
699
	      or(ulongsh, to, mnw((long)2147483648UL), to);
682
	    } else {
700
	    } else {
683
	       ins2 (m_fintrzx,L32,L32,FP0,FP0,1);
701
	       ins2(m_fintrzx,L32,L32,FP0,FP0,1);
684
	       ins2 ( m_fmovel, L32, L32, FP0, D0, 1 ) ;
702
	       ins2(m_fmovel, L32, L32, FP0, D0, 1);
685
	       or ( ulongsh, D0, mnw ( (long)2147483648UL ), D0 ) ;
703
	       or(ulongsh, D0, mnw((long)2147483648UL), D0);
686
	       move ( ulongsh, D0, to ) ;
704
	       move(ulongsh, D0, to);
687
	    }
705
	    }
688
	    make_jump ( m_bra, lab2 ) ;
706
	    make_jump(m_bra, lab2);
689
	    make_label ( lab1 ) ;
707
	    make_label(lab1);
690
	    if ( whereis ( to ) == Dreg ) {
708
	    if (whereis(to) == Dreg) {
691
	      ins2 (m_fintrzx,L32,L32,FP0,FP0,1);
709
	      ins2(m_fintrzx,L32,L32,FP0,FP0,1);
692
	      ins2 ( m_fmovel, L32, L32, FP0, to, 1 ) ;
710
	      ins2(m_fmovel, L32, L32, FP0, to, 1);
693
	    } else {
711
	    } else {
694
	      ins2 (m_fintrzx,L32,L32,FP0,FP0,1);
712
	      ins2(m_fintrzx,L32,L32,FP0,FP0,1);
695
	      ins2 ( m_fmovel, L32, L32, FP0, D0, 1 ) ;
713
	      ins2(m_fmovel, L32, L32, FP0, D0, 1);
696
	      move ( ulongsh, D0, to ) ;
714
	      move(ulongsh, D0, to);
697
	    }
715
	    }
698
	    make_label ( lab2 ) ;
716
	    make_label(lab2);
699
	    have_cond = 0 ;
717
	    have_cond = 0;
700
#endif
718
#endif
701
	    return ;
719
	    return;
702
	}
720
	}
703
 
721
 
704
    } else {
722
    } else {
705
 
723
 
706
 
724
 
707
	if ( mode == 4 ) {
725
	if (mode == 4) {
708
	    /* Special case - move FP0 into the register to */
726
	    /* Special case - move FP0 into the register to */
709
	    ins2 ( m_fmovel, L32, L32, FP0, to, 1 ) ;
727
	    ins2(m_fmovel, L32, L32, FP0, to, 1);
710
 
728
 
711
            /* This might generate operand error */
729
            /* This might generate operand error */
712
            test_overflow(ON_FP_OPERAND_ERROR);
730
            test_overflow(ON_FP_OPERAND_ERROR);
713
 
731
 
714
	    have_cond = 0 ;
732
	    have_cond = 0;
715
	    change_var_sh ( sha, slongsh, to, to ) ;
733
	    change_var_sh(sha, slongsh, to, to);
716
	    return ;
734
	    return;
717
	}
735
	}
718
 
736
 
719
	if(have_overflow()) {
737
	if (have_overflow()) {
720
	  /* This must be checked before a round operation is attempted
738
	  /* This must be checked before a round operation is attempted
721
	     because out-of-range values can cause an exception */
739
	     because out-of-range values can cause an exception */
722
	  check_float_round_overflow(sha,from,mode);
740
	  check_float_round_overflow(sha,from,mode);
723
	}
741
	}
724
 
742
 
725
	if ( mode == f_toward_zero || mode == f_to_nearest ) {
743
	if (mode == f_toward_zero || mode == f_to_nearest) {
726
	    /* Rounding to nearest or towards zero are easy */
744
	    /* Rounding to nearest or towards zero are easy */
727
	    int instr ;
745
	    int instr;
728
	    shape shf = sh ( from.wh_exp ) ;
746
	    shape shf = sh(from.wh_exp);
729
	    long szf = shape_size ( shf ) ;
747
	    long szf = shape_size(shf);
730
	    if ( mode == f_toward_zero ) {
748
	    if (mode == f_toward_zero) {
731
		instr = m_fintrzx ;
749
		instr = m_fintrzx;
732
		if ( whereis ( from ) != Freg ) {
750
		if (whereis(from)!= Freg) {
733
		    instr = insf ( szf, ml_fint ) ;
751
		    instr = insf(szf, ml_fint);
734
		}
752
		}
735
	    } else {
753
	    } else {
736
                set_round_mode(mode);
754
                set_round_mode(mode);
737
		instr = m_fintx ;
755
		instr = m_fintx;
738
		if ( whereis ( from ) != Freg ) {
756
		if (whereis(from)!= Freg) {
739
		    instr = insf ( szf, ml_fintrz ) ;
757
		    instr = insf(szf, ml_fintrz);
740
		}
758
		}
741
	    }
759
	    }
742
	    ins2 ( instr, szf, szf, from, FP0, 1 ) ;
760
	    ins2(instr, szf, szf, from, FP0, 1);
743
	    if ( whereis ( to ) == Dreg ) {
761
	    if (whereis(to) == Dreg) {
744
		dest = to ;
762
		dest = to;
745
	    } else {
763
	    } else {
746
		dest = D0 ;
764
		dest = D0;
747
	    }
765
	    }
748
	    ins2 ( m_fmovel, L32, L32, FP0, dest, 1 ) ;
766
	    ins2(m_fmovel, L32, L32, FP0, dest, 1);
749
	    have_cond = 0 ;
767
	    have_cond = 0;
750
	    change_var_sh ( sha, slongsh, dest, to ) ;
768
	    change_var_sh(sha, slongsh, dest, to);
751
	    return ;
769
	    return;
752
	}
770
	}
753
    }
771
    }
754
 
772
 
755
    /* Other modes : firstly find some registers */
773
    /* Other modes : firstly find some registers */
756
    if ( whereis ( to ) == Dreg ) {
774
    if (whereis(to) == Dreg) {
757
	dest = to ;
775
	dest = to;
758
    } else {
776
    } else {
759
	dest = D0 ;
777
	dest = D0;
760
    }
778
    }
761
    if ( whereis ( from ) == Freg && !eq_where ( from, FP0 ) ) {
779
    if (whereis(from) == Freg && !eq_where(from, FP0)) {
762
	fr = from ;
780
	fr = from;
763
    } else {
781
    } else {
764
	shape shf = sh ( from.wh_exp ) ;
782
	shape shf = sh(from.wh_exp);
765
	fr = FP1 ;
783
	fr = FP1;
766
	regsinproc |= regmsk ( REG_FP1 ) ;
784
	regsinproc |= regmsk(REG_FP1);
767
	move ( shf, from, fr ) ;
785
	move(shf, from, fr);
768
    }
786
    }
769
 
787
 
770
    /* Round fr into FP0 */
788
    /* Round fr into FP0 */
771
    if ( mode == f_toward_zero ) {
789
    if (mode == f_toward_zero) {
772
       ins2 ( m_fintrzx, 64, 64, fr, FP0, 1 ) ;
790
       ins2(m_fintrzx, 64, 64, fr, FP0, 1);
773
    }
791
    }
774
    else {
792
    else {
775
       set_round_mode(mode);
793
       set_round_mode(mode);
776
       ins2 ( m_fintx, 64, 64, fr, FP0, 1 ) ;
794
       ins2(m_fintx, 64, 64, fr, FP0, 1);
777
    }
795
    }
778
 
796
 
779
    /* Move FP0 into dest */
797
    /* Move FP0 into dest */
780
    crt_rmode = 4 ;
798
    crt_rmode = 4;
781
    round_float ( sha, FP0, dest ) ;
799
    round_float(sha, FP0, dest);
782
    crt_rmode = mode ;
800
    crt_rmode = mode;
783
 
801
 
784
    /* Move result into place */
802
    /* Move result into place */
785
    have_cond = 0 ;
803
    have_cond = 0;
786
    move ( sha, dest, to ) ;
804
    move(sha, dest, to);
787
    return ;
805
    return;
788
}
806
}
789
 
807
 
790
 
808
 
791
/*
809
/*
792
    CONVERT AN INTEGER TO A FLOATING POINT NUMBER
810
    CONVERT AN INTEGER TO A FLOATING POINT NUMBER
Line 795... Line 813...
795
    shape sha and stored in to.  Unsigned longs are difficult.  Error
813
    shape sha and stored in to.  Unsigned longs are difficult.  Error
796
    treatments are ignored (they cannot occur at present).
814
    treatments are ignored (they cannot occur at present).
797
*/
815
*/
798
 
816
 
799
void int_to_float
817
void int_to_float
800
    PROTO_N ( ( sha, from, to ) )
-
 
801
    PROTO_T ( shape sha X where from X where to )
818
(shape sha, where from, where to)
802
{
819
{
803
    where fpr ;
820
    where fpr;
804
    shape shf = sh ( from.wh_exp ) ;
821
    shape shf = sh(from.wh_exp);
805
#ifdef REJECT
822
#ifdef REJECT
806
    fpr = ( whereis ( to ) == Freg ? to : FP0 ) ;
823
    fpr = (whereis(to) == Freg ? to : FP0);
807
#else
824
#else
808
    fpr = FP0 ;
825
    fpr = FP0;
809
#endif
826
#endif
810
    if ( name ( shf ) == ulonghd ) {
827
    if (name(shf) == ulonghd) {
811
#ifdef unsigned_to_float
828
#ifdef unsigned_to_float
812
	if ( whereis ( from ) == Dreg ) {
829
	if (whereis(from) == Dreg) {
813
	    push ( slongsh, L32, from ) ;
830
	    push(slongsh, L32, from);
814
	} else {
831
	} else {
815
	    move ( shf, from, D0 ) ;
832
	    move(shf, from, D0);
816
	    push ( slongsh, L32, D0 ) ;
833
	    push(slongsh, L32, D0);
817
	}
834
	}
818
	libcall ( unsigned_to_float ) ;
835
	libcall(unsigned_to_float);
819
	dec_stack ( -32 ) ;
836
	dec_stack(-32);
820
	have_cond = 0 ;
837
	have_cond = 0;
821
	move ( realsh, D0_D1, fpr ) ;
838
	move(realsh, D0_D1, fpr);
822
	move ( sha, fpr, to ) ;
839
	move(sha, fpr, to);
823
	return ;
840
	return;
824
#else
841
#else
825
	where fm ;
842
	where fm;
826
	long lab = next_lab () ;
843
	long lab = next_lab();
827
	exp jt = simple_exp ( 0 ) ;
844
	exp jt = simple_exp(0);
828
	ptno ( jt ) = lab ;
845
	ptno(jt) = lab;
829
#ifdef FBASE_10
846
#ifdef FBASE_10
830
	fm = mfw ( 1, "4294967296", 9 ) ;
847
	fm = mfw(1, "4294967296", 9);
831
#else
848
#else
832
	{
849
	{
833
	    static long fmd [] = { 1, 0, 0, -1 } ;
850
	    static long fmd[] = { 1, 0, 0, -1 };
834
	    fm = mfw ( 1, fmd, 2 ) ;
851
	    fm = mfw(1, fmd, 2);
835
	}
852
	}
836
#endif
853
#endif
837
	if ( whereis ( from ) == Dreg ) {
854
	if (whereis(from) == Dreg) {
838
	    ins2 ( m_fmovel, L32, L64, from, fpr, 1 ) ;
855
	    ins2(m_fmovel, L32, L64, from, fpr, 1);
839
	} else {
856
	} else {
840
	    move ( slongsh, from, D0 ) ;
857
	    move(slongsh, from, D0);
841
	    ins2 ( m_fmovel, L32, L64, D0, fpr, 1 ) ;
858
	    ins2(m_fmovel, L32, L64, D0, fpr, 1);
842
	}
859
	}
843
	branch ( tst_ge, jt, 1, 1, 1 ) ;
860
	branch(tst_ge, jt, 1, 1, 1);
844
	add ( sha, fpr, fm, fpr ) ;
861
	add(sha, fpr, fm, fpr);
845
	make_label ( lab ) ;
862
	make_label(lab);
846
	have_cond = 0 ;
863
	have_cond = 0;
847
	move ( sha, fpr, to ) ;
864
	move(sha, fpr, to);
848
	return ;
865
	return;
849
#endif
866
#endif
850
    }
867
    }
851
    if ( name ( shf ) == slonghd && whereis ( from ) == Dreg ) {
868
    if (name(shf) == slonghd && whereis(from) == Dreg) {
852
	ins2 ( m_fmovel, L32, L64, from, fpr, 1 ) ;
869
	ins2(m_fmovel, L32, L64, from, fpr, 1);
853
    } else {
870
    } else {
854
	change_var_sh ( slongsh, shf, from, D0 ) ;
871
	change_var_sh(slongsh, shf, from, D0);
855
	ins2 ( m_fmovel, L32, L64, D0, fpr, 1 ) ;
872
	ins2(m_fmovel, L32, L64, D0, fpr, 1);
856
    }
873
    }
857
    move ( sha, fpr, to ) ;
874
    move(sha, fpr, to);
858
    have_cond = 0 ;
875
    have_cond = 0;
859
    return ;
876
    return;
860
}
877
}