Subversion Repositories tendra.SVN

Rev

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

Rev 2 Rev 7
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) 1996
32
    		 Crown Copyright (c) 1996
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 131... Line 161...
131
#include "operations.h"
161
#include "operations.h"
132
#include "evaluate.h"
162
#include "evaluate.h"
133
#include "utility.h"
163
#include "utility.h"
134
#include "translate.h"
164
#include "translate.h"
135
#include "ops_shared.h"
165
#include "ops_shared.h"
136
extern void add_const PROTO_S ( ( shape, long, where ) ) ;
166
extern void add_const(shape, long, where);
137
 
167
 
138
/*
168
/*
139
    DO AN ADD BY A LOAD EFFECTIVE ADDRESS
169
    DO AN ADD BY A LOAD EFFECTIVE ADDRESS
140
 
170
 
141
    The m_lea instruction is used to add the constant offset to the value
171
    The m_lea instruction is used to add the constant offset to the value
142
    a and put the result into dest.  The flag psh is true to indicate
172
    a and put the result into dest.  The flag psh is true to indicate
143
    that the result should be pushed onto the stack.
173
    that the result should be pushed onto the stack.
144
*/
174
*/
145
 
175
 
146
void load_ea
176
void load_ea
147
    PROTO_N ( ( sha, offset, a, dest, psh ) )
-
 
148
    PROTO_T ( shape sha X long offset X where a X where dest X bool psh )
177
(shape sha, long offset, where a, where dest, bool psh)
149
{
178
{
150
    if ( have_overflow () ) {
179
    if (have_overflow()) {
151
	move ( sha, a, D0 ) ;
180
	move(sha, a, D0);
152
	add_const ( sha, offset, D0 ) ;
181
	add_const(sha, offset, D0);
153
	move ( sha, D0, dest ) ;
182
	move(sha, D0, dest);
154
	have_cond = 0 ;
183
	have_cond = 0;
155
    } else {
184
    } else {
156
	exp ra = simple_exp ( dummy_tag ) ;
185
	exp ra = simple_exp(dummy_tag);
157
	son ( ra ) = a.wh_exp ;
186
	son(ra) = a.wh_exp;
158
	no ( ra ) = 8 * offset ;
187
	no(ra) = 8 * offset;
159
	if ( psh ) {
188
	if (psh) {
160
	    ins1 ( m_pea, L32, zw ( ra ), 0 ) ;
189
	    ins1(m_pea, L32, zw(ra), 0);
161
	    stack_size -= 32 ;
190
	    stack_size -= 32;
162
	} else {
191
	} else {
163
	    ins2 ( m_lea, L32, L32, zw ( ra ), dest, 1 ) ;
192
	    ins2(m_lea, L32, L32, zw(ra), dest, 1);
164
	}
193
	}
165
	retcell ( ra ) ;
194
	retcell(ra);
166
	have_cond = 0 ;
195
	have_cond = 0;
167
    }
196
    }
168
    return ;
197
    return;
169
}
198
}
170
 
199
 
171
 
200
 
172
/*
201
/*
173
    INCREASE BY A CONSTANT
202
    INCREASE BY A CONSTANT
174
 
203
 
175
    The value dest is increased or decreased by the constant n.
204
    The value dest is increased or decreased by the constant n.
176
*/
205
*/
177
 
206
 
178
void addsub_const
207
void addsub_const
179
    PROTO_N ( ( sha, n, dest, use_sub ) )
-
 
180
    PROTO_T ( shape sha X long n X where dest X bool use_sub )
208
(shape sha, long n, where dest, bool use_sub)
181
{
209
{
182
    int instr ;
210
    int instr;
183
    bool negate = 0, use_quick = 0 ;
211
    bool negate = 0, use_quick = 0;
184
 
212
 
185
    long sz = shape_size ( sha ) ;
213
    long sz = shape_size(sha);
186
    if ( n == 0 ) return ;
214
    if (n == 0) return;
187
 
215
 
188
    /* If destination is a value we just have to test for overflow */
216
    /* If destination is a value we just have to test for overflow */
189
 
217
 
190
    if ( whereis ( dest ) == Value ) {
218
    if (whereis(dest) == Value) {
191
       long v = nw ( dest ) ;
219
       long v = nw(dest);
192
       if ( is_signed(sha) ) {
220
       if (is_signed(sha)) {
193
          if ( use_sub )
221
          if (use_sub)
194
             n = -n ;
222
             n = -n;
195
          if (v>0 && n>0) {
223
          if (v>0 && n>0) {
196
             if (v > range_max(sha) - n)
224
             if (v > range_max(sha) - n)
197
                test_overflow(UNCONDITIONAL) ;
225
                test_overflow(UNCONDITIONAL);
198
          }
226
          }
199
          else if (v<0 && n<0) {
227
          else if (v<0 && n<0) {
200
             if (v < range_min(sha) - n)
228
             if (v < range_min(sha) - n)
201
                test_overflow(UNCONDITIONAL) ;
229
                test_overflow(UNCONDITIONAL);
202
          }
230
          }
203
       }
231
       }
204
       else { /* unsigned addition */
232
       else { /* unsigned addition */
205
          if (use_sub) {
233
          if (use_sub) {
206
             /* will v - n underflow ? */
234
             /* will v - n underflow ? */
207
             if ((unsigned)v < (unsigned) range_min(sha) - (unsigned) n)
235
             if ((unsigned)v < (unsigned)range_min(sha) - (unsigned)n)
208
                test_overflow(UNCONDITIONAL) ;
236
                test_overflow(UNCONDITIONAL);
209
          }
237
          }
210
          else {
238
          else {
211
             if ((unsigned)v > (unsigned) range_max(sha) - (unsigned) n)
239
             if ((unsigned)v > (unsigned)range_max(sha) - (unsigned)n)
212
                test_overflow(UNCONDITIONAL) ;
240
                test_overflow(UNCONDITIONAL);
213
          }
241
          }
214
       }
242
       }
215
       return ;
243
       return;
216
    }
244
    }
217
 
245
 
218
 
246
 
219
    /* Destination is not just a value */
247
    /* Destination is not just a value */
220
 
248
 
221
    /* If we don't have to test for overflow, we can chose wheter to add/sub */
249
    /* If we don't have to test for overflow, we can chose wheter to add/sub */
222
    /* Changeing add and sub might allow us to use quick add or sub */
250
    /* Changeing add and sub might allow us to use quick add or sub */
223
    if ( ! have_overflow() ) {
251
    if (! have_overflow()) {
224
       /* But -(INT_MIN) can't be represented in signed shape */
252
       /* But -(INT_MIN) can't be represented in signed shape */
225
       if (n != INT_MIN) {
253
       if (n != INT_MIN) {
226
          if (n < 0)
254
          if (n < 0)
227
             negate = 1 ;
255
             negate = 1;
228
          if ((n < 8) && (n > -8))
256
          if ((n < 8) && (n > -8))
229
             use_quick = 1 ;
257
             use_quick = 1;
230
       }
258
       }
231
    }
259
    }
232
    else {
260
    else {
233
       if ((unsigned long)n < 8)
261
       if ((unsigned long)n < 8)
234
          use_quick = 1 ;
262
          use_quick = 1;
235
    }
263
    }
236
 
264
 
237
    /* Special handling for address regs. */
265
    /* Special handling for address regs. */
238
    if ( whereis ( dest ) == Areg ) {
266
    if (whereis(dest) == Areg) {
239
       if (use_quick) {
267
       if (use_quick) {
240
          have_cond = 0 ;
268
          have_cond = 0;
241
       }
269
       }
242
       else {
270
       else {
243
          if (use_sub)
271
          if (use_sub)
244
             n = -n ;
272
             n = -n;
245
          load_ea ( sha, n, dest, dest, 0 ) ;
273
          load_ea(sha, n, dest, dest, 0);
246
          return ;
274
          return;
247
       }
275
       }
248
    }
276
    }
249
 
277
 
250
    /* Find appropriate ADD/SUB */
278
    /* Find appropriate ADD/SUB */
251
    if (negate) {
279
    if (negate) {
252
       n = -n ;
280
       n = -n;
253
       use_sub = ! use_sub ;
281
       use_sub = ! use_sub;
254
    }
282
    }
255
 
283
 
256
    if (use_sub) {
284
    if (use_sub) {
257
       if (use_quick)
285
       if (use_quick)
258
          instr = ins ( sz, ml_subq ) ;
286
          instr = ins(sz, ml_subq);
259
       else
287
       else
260
          instr = ins ( sz, ml_sub ) ;
288
          instr = ins(sz, ml_sub);
261
    }
289
    }
262
    else {
290
    else {
263
       if (use_quick)
291
       if (use_quick)
264
          instr = ins ( sz, ml_addq ) ;
292
          instr = ins(sz, ml_addq);
265
       else
293
       else
266
          instr = ins ( sz, ml_add ) ;
294
          instr = ins(sz, ml_add);
267
    }
295
    }
268
 
296
 
269
    ins2n ( instr, n, sz, dest, 1 ) ;
297
    ins2n(instr, n, sz, dest, 1);
270
    set_cond ( dest, sz ) ;
298
    set_cond(dest, sz);
271
    test_overflow(ON_SHAPE ( sha )) ;
299
    test_overflow(ON_SHAPE(sha));
272
}
300
}
273
 
301
 
274
void add_const
302
void add_const
275
    PROTO_N ( ( sha, n, dest) )
-
 
276
    PROTO_T ( shape sha X long n X where dest )
303
(shape sha, long n, where dest)
277
{
304
{
278
   addsub_const ( sha, n, dest, 0);
305
   addsub_const(sha, n, dest, 0);
279
}
306
}
280
 
307
 
281
void sub_const
308
void sub_const
282
    PROTO_N ( ( sha, n, dest) )
-
 
283
    PROTO_T ( shape sha X long n X where dest )
309
(shape sha, long n, where dest)
284
{
310
{
285
   addsub_const ( sha, n, dest, 1);
311
   addsub_const(sha, n, dest, 1);
286
}
312
}
287
 
313
 
288
/*
314
/*
289
    AUXILIARY ADD ROUTINE
315
    AUXILIARY ADD ROUTINE
290
 
316
 
291
    The value inc (of shape sha and size sz) is added to dest.
317
    The value inc (of shape sha and size sz) is added to dest.
292
*/
318
*/
293
 
319
 
294
static void add_aux
320
static void add_aux
295
    PROTO_N ( ( sha, sz, inc, dest ) )
-
 
296
    PROTO_T ( shape sha X long sz X where inc X where dest )
321
(shape sha, long sz, where inc, where dest)
297
{
322
{
298
    int instr ;
323
    int instr;
299
    long whi = whereis ( inc ) ;
324
    long whi = whereis(inc);
300
    long whd = whereis ( dest ) ;
325
    long whd = whereis(dest);
301
    if ( whd == Freg ) {
326
    if (whd == Freg) {
302
	move ( sha, dest, D0 ) ;
327
	move(sha, dest, D0);
303
	add_aux ( sha, sz, inc, D0 ) ;
328
	add_aux(sha, sz, inc, D0);
304
	move ( sha, D0, dest ) ;
329
	move(sha, D0, dest);
305
	return ;
-
 
306
    }
-
 
307
    if ( whi == Value ) {
-
 
308
	long v = nw ( inc ) ;
-
 
309
	if ( is_offset ( inc.wh_exp ) ) v /= 8 ;
-
 
310
	add_const ( sha, v, dest) ;
-
 
311
	return ;
330
	return;
312
    }
331
    }
-
 
332
    if (whi == Value) {
-
 
333
	long v = nw(inc);
-
 
334
	if (is_offset(inc.wh_exp))v /= 8;
-
 
335
	add_const(sha, v, dest);
-
 
336
	return;
-
 
337
    }
313
    if ( whi == Freg ) {
338
    if (whi == Freg) {
314
	move ( sha, inc, D0 ) ;
339
	move(sha, inc, D0);
315
	add_aux ( sha, sz, D0, dest ) ;
340
	add_aux(sha, sz, D0, dest);
316
	return ;
341
	return;
317
    }
342
    }
318
 
343
 
319
    if ( have_overflow () && whd == Areg ) {
344
    if (have_overflow() && whd == Areg) {
320
	/* Skip to end */
345
	/* Skip to end */
321
    } else if ( whi == Dreg || whd == Dreg || whd == Areg ) {
346
    } else if (whi == Dreg || whd == Dreg || whd == Areg) {
322
	instr = ins ( sz, ml_add ) ;
347
	instr = ins(sz, ml_add);
323
	ins2 ( instr, sz, sz, inc, dest, 1 ) ;
348
	ins2(instr, sz, sz, inc, dest, 1);
324
	if ( whd == Areg ) {
349
	if (whd == Areg) {
325
	    have_cond = 0 ;
350
	    have_cond = 0;
326
	} else {
351
	} else {
327
	    set_cond ( dest, sz ) ;
352
	    set_cond(dest, sz);
328
	}
353
	}
329
        test_overflow(ON_SHAPE ( sha )) ;
354
        test_overflow(ON_SHAPE(sha));
330
	return ;
355
	return;
331
    }
356
    }
332
    move ( sha, inc, D0 ) ;
357
    move(sha, inc, D0);
333
    add_aux ( sha, sz, D0, dest ) ;
358
    add_aux(sha, sz, D0, dest);
334
    return ;
359
    return;
335
}
360
}
336
 
361
 
337
 
362
 
338
/*
363
/*
339
    ADD CONSTANT ROUTINE
364
    ADD CONSTANT ROUTINE
340
 
365
 
341
    The constant c is added to the value inc, and the result is stored
366
    The constant c is added to the value inc, and the result is stored
342
    in dest.
367
    in dest.
343
*/
368
*/
344
 
369
 
345
static void addsub_const_3_args
370
static void addsub_const_3_args
346
    PROTO_N ( ( sha, sz, c, inc, dest, use_sub ) )
-
 
347
    PROTO_T ( shape sha X long sz X long c X where inc X where dest X bool use_sub )
371
(shape sha, long sz, long c, where inc, where dest, bool use_sub)
348
{
372
{
349
    if ( c == 0 ) {
373
    if (c == 0) {
350
	move ( sha, inc, dest ) ;
374
	move(sha, inc, dest);
351
	return ;
375
	return;
352
    }
376
    }
353
    switch ( whereis ( dest ) ) {
377
    switch (whereis(dest)) {
354
	case Dreg : {
378
	case Dreg: {
355
	    move ( sha, inc, dest ) ;
379
	    move(sha, inc, dest);
356
	    addsub_const ( sha, c, dest, use_sub ) ;
380
	    addsub_const(sha, c, dest, use_sub);
357
	    return ;
381
	    return;
358
	}
382
	}
359
	case Areg : {
383
	case Areg: {
360
	    if ( whereis ( inc ) == Areg ) {
384
	    if (whereis(inc) == Areg) {
361
		load_ea ( sha, c, inc, dest, 0 ) ;
385
		load_ea(sha, c, inc, dest, 0);
362
		return ;
386
		return;
363
	    }
387
	    }
364
	    move ( sha, inc, dest ) ;
388
	    move(sha, inc, dest);
365
	    addsub_const ( sha, c, dest, use_sub ) ;
389
	    addsub_const(sha, c, dest, use_sub);
366
	    return ;
390
	    return;
367
	}
391
	}
368
	default : {
392
	default : {
369
	    long whi = whereis ( inc ) ;
393
	    long whi = whereis(inc);
370
	    if ( whi == Dreg && last_use ( inc ) ) {
394
	    if (whi == Dreg && last_use(inc)) {
371
		addsub_const ( sha, c, inc, use_sub ) ;
395
		addsub_const(sha, c, inc, use_sub);
372
		move ( sha, inc, dest ) ;
396
		move(sha, inc, dest);
373
		set_cond ( dest, sz ) ;
397
		set_cond(dest, sz);
374
		return ;
398
		return;
375
	    }
399
	    }
376
	    if ( whi == Areg && (   name ( dest.wh_exp ) == apply_tag
400
	    if (whi == Areg && (  name(dest.wh_exp) == apply_tag
377
                                 || name ( dest.wh_exp ) == apply_general_tag
401
                                 || name(dest.wh_exp) == apply_general_tag
378
                                 || name ( dest.wh_exp ) == tail_call_tag )) {
402
                                 || name(dest.wh_exp) == tail_call_tag)) {
379
		load_ea ( sha, c, inc, dest, 1 ) ;
403
		load_ea(sha, c, inc, dest, 1);
380
		return ;
404
		return;
381
	    }
405
	    }
382
	    addsub_const_3_args ( sha, sz, c, inc, D0, use_sub ) ;
406
	    addsub_const_3_args(sha, sz, c, inc, D0, use_sub);
383
	    move ( sha, D0, dest ) ;
407
	    move(sha, D0, dest);
384
	    set_cond ( dest, sz ) ;
408
	    set_cond(dest, sz);
385
	    return ;
409
	    return;
386
	}
410
	}
387
    }
411
    }
388
}
412
}
389
 
413
 
390
 
414
 
Line 394... Line 418...
394
    The values a1 and a2 of shape sha are added and the result stored in
418
    The values a1 and a2 of shape sha are added and the result stored in
395
    dest.
419
    dest.
396
*/
420
*/
397
 
421
 
398
void add
422
void add
399
    PROTO_N ( ( sha, a1, a2, dest ) )
-
 
400
    PROTO_T ( shape sha X where a1 X where a2 X where dest )
423
(shape sha, where a1, where a2, where dest)
401
{
424
{
402
    long sz = shape_size ( sha ) ;
425
    long sz = shape_size(sha);
403
    long rt = shtype ( sha ) ;
426
    long rt = shtype(sha);
404
    long wh1, wh2, whd ;
427
    long wh1, wh2, whd;
405
 
428
 
406
    if ( rt == Freg ) {
429
    if (rt == Freg) {
407
	fl_binop ( fplus_tag, sha, a1, a2, dest ) ;
430
	fl_binop(fplus_tag, sha, a1, a2, dest);
408
	return ;
431
	return;
409
    }
432
    }
410
 
433
 
411
    if ( eq_where ( a1, dest ) ) {
434
    if (eq_where(a1, dest)) {
412
	add_aux ( sha, sz, a2, dest ) ;
435
	add_aux(sha, sz, a2, dest);
413
	return ;
436
	return;
414
    }
437
    }
415
 
438
 
416
    if ( eq_where ( a2, dest ) ) {
439
    if (eq_where(a2, dest)) {
417
	add_aux ( sha, sz, a1, dest ) ;
440
	add_aux(sha, sz, a1, dest);
418
	return ;
441
	return;
419
    }
442
    }
420
 
443
 
421
    wh1 = whereis ( a1 ) ;
444
    wh1 = whereis(a1);
422
    wh2 = whereis ( a2 ) ;
445
    wh2 = whereis(a2);
423
    whd = whereis ( dest ) ;
446
    whd = whereis(dest);
424
 
447
 
425
    if ( wh1 == Value ) {
448
    if (wh1 == Value) {
426
	long v1 = nw ( a1 ) ;
449
	long v1 = nw(a1);
427
	if ( is_offset ( a1.wh_exp ) ) v1 /= 8 ;
450
	if (is_offset(a1.wh_exp))v1 /= 8;
428
	if ( wh2 == Value && !have_overflow () ) {
451
	if (wh2 == Value && !have_overflow()) {
429
	    long v2 = nw ( a2 ) ;
452
	    long v2 = nw(a2);
430
	    if ( is_offset ( a2.wh_exp ) ) v2 /= 8 ;
453
	    if (is_offset(a2.wh_exp))v2 /= 8;
431
	    move ( sha, mnw ( v1 + v2 ), dest ) ;
454
	    move(sha, mnw(v1 + v2), dest);
432
	    return ;
455
	    return;
433
	}
456
	}
434
	addsub_const_3_args ( sha, sz, v1, a2, dest, 0 ) ;
457
	addsub_const_3_args(sha, sz, v1, a2, dest, 0);
435
	return ;
458
	return;
436
    }
459
    }
437
 
460
 
438
    if ( wh2 == Value ) {
461
    if (wh2 == Value) {
439
	long v2 = nw ( a2 ) ;
462
	long v2 = nw(a2);
440
	if ( is_offset ( a2.wh_exp ) ) v2 /= 8 ;
463
	if (is_offset(a2.wh_exp))v2 /= 8;
441
	addsub_const_3_args ( sha, sz, v2, a1, dest, 0 ) ;
464
	addsub_const_3_args(sha, sz, v2, a1, dest, 0);
442
	return ;
465
	return;
443
    }
466
    }
444
 
467
 
445
    if ( whd == Dreg ) {
468
    if (whd == Dreg) {
446
	if ( !interfere ( a2, dest ) ) {
469
	if (!interfere(a2, dest)) {
447
	    move ( sha, a1, dest ) ;
470
	    move(sha, a1, dest);
448
	    add_aux ( sha, sz, a2, dest ) ;
471
	    add_aux(sha, sz, a2, dest);
449
	    return ;
472
	    return;
450
	}
473
	}
451
	if ( !interfere ( a1, dest ) ) {
474
	if (!interfere(a1, dest)) {
452
	    move ( sha, a2, dest ) ;
475
	    move(sha, a2, dest);
453
	    add_aux ( sha, sz, a1, dest ) ;
476
	    add_aux(sha, sz, a1, dest);
454
	    return ;
477
	    return;
455
	}
478
	}
456
    }
479
    }
457
 
480
 
458
    if ( wh1 == Dreg && last_use ( a1 ) ) {
481
    if (wh1 == Dreg && last_use(a1)) {
459
	add_aux ( sha, sz, a2, a1 ) ;
482
	add_aux(sha, sz, a2, a1);
460
	move ( sha, a1, dest ) ;
483
	move(sha, a1, dest);
461
	set_cond ( dest, sz ) ;
484
	set_cond(dest, sz);
462
	return ;
485
	return;
463
    }
486
    }
464
 
487
 
465
    if ( wh2 == Dreg && last_use ( a2 ) ) {
488
    if (wh2 == Dreg && last_use(a2)) {
466
	add_aux ( sha, sz, a1, a2 ) ;
489
	add_aux(sha, sz, a1, a2);
467
	move ( sha, a2, dest ) ;
490
	move(sha, a2, dest);
468
	set_cond ( dest, sz ) ;
491
	set_cond(dest, sz);
469
	return ;
492
	return;
470
    }
493
    }
471
 
494
 
472
    if ( wh1 == Dreg ) {
495
    if (wh1 == Dreg) {
473
	move ( sha, a2, D0 ) ;
496
	move(sha, a2, D0);
474
	add_aux ( sha, sz, a1, D0 ) ;
497
	add_aux(sha, sz, a1, D0);
475
    } else {
498
    } else {
476
	move ( sha, a1, D0 ) ;
499
	move(sha, a1, D0);
477
	add_aux ( sha, sz, a2, D0 ) ;
500
	add_aux(sha, sz, a2, D0);
478
    }
501
    }
479
    move ( sha, D0, dest ) ;
502
    move(sha, D0, dest);
480
    set_cond ( dest, sz ) ;
503
    set_cond(dest, sz);
481
    return ;
504
    return;
482
}
505
}
483
 
506
 
484
 
507
 
485
/*
508
/*
486
    AUXILIARY SUBTRACT ROUTINE
509
    AUXILIARY SUBTRACT ROUTINE
487
 
510
 
488
    The value a is subtracted from dest.
511
    The value a is subtracted from dest.
489
*/
512
*/
490
 
513
 
491
static void sub_aux
514
static void sub_aux
492
    PROTO_N ( ( sha, sz, a, dest ) )
-
 
493
    PROTO_T ( shape sha X long sz X where a X where dest )
515
(shape sha, long sz, where a, where dest)
494
{
516
{
495
    long wha = whereis ( a ) ;
517
    long wha = whereis(a);
496
    long whd = whereis ( dest ) ;
518
    long whd = whereis(dest);
497
    if ( whd == Freg ) {
519
    if (whd == Freg) {
498
	move ( sha, dest, D0 ) ;
520
	move(sha, dest, D0);
499
	sub_aux ( sha, sz, a, D0 ) ;
521
	sub_aux(sha, sz, a, D0);
500
	move ( sha, D0, dest ) ;
522
	move(sha, D0, dest);
501
	return ;
523
	return;
502
    }
524
    }
503
 
525
 
504
    if ( wha == Value ) {
526
    if (wha == Value) {
505
	long v = nw ( a ) ;
527
	long v = nw(a);
506
	if ( is_offset ( a.wh_exp ) ) v /= 8 ;
528
	if (is_offset(a.wh_exp))v /= 8;
507
	sub_const ( sha, v, dest ) ;
529
	sub_const(sha, v, dest);
508
	return ;
530
	return;
509
    }
531
    }
510
 
532
 
511
    if ( wha != Freg ) {
533
    if (wha != Freg) {
512
	if ( have_overflow () && whd == Areg ) {
534
	if (have_overflow() && whd == Areg) {
513
	    /* Skip to end */
535
	    /* Skip to end */
514
	} else if ( whd == Dreg || whd == Areg || wha == Dreg ) {
536
	} else if (whd == Dreg || whd == Areg || wha == Dreg) {
515
	    int instr = ins ( sz, ml_sub ) ;
537
	    int instr = ins(sz, ml_sub);
516
	    ins2 ( instr, sz, sz, a, dest, 1 ) ;
538
	    ins2(instr, sz, sz, a, dest, 1);
517
	    if ( whd == Areg ) {
539
	    if (whd == Areg) {
518
		have_cond = 0 ;
540
		have_cond = 0;
519
	    } else {
541
	    } else {
520
		set_cond ( dest, sz ) ;
542
		set_cond(dest, sz);
521
	    }
543
	    }
522
            test_overflow(ON_SHAPE ( sha )) ;
544
            test_overflow(ON_SHAPE(sha));
523
	    return ;
545
	    return;
524
	}
546
	}
525
    }
547
    }
526
    move ( sha, a, D0 ) ;
548
    move(sha, a, D0);
527
    sub_aux ( sha, sz, D0, dest ) ;
549
    sub_aux(sha, sz, D0, dest);
528
    set_cond ( dest, sz ) ;
550
    set_cond(dest, sz);
529
    return ;
551
    return;
530
}
552
}
531
 
553
 
532
 
554
 
533
/*
555
/*
534
    MAIN SUBTRACT ROUTINE
556
    MAIN SUBTRACT ROUTINE
535
 
557
 
536
    The value a2 of shape sha is subtracted from a1 and the result is
558
    The value a2 of shape sha is subtracted from a1 and the result is
537
    stored in dest.
559
    stored in dest.
538
*/
560
*/
539
 
561
 
540
void sub
562
void sub
541
    PROTO_N ( ( sha, a1, a2, dest ) )
-
 
542
    PROTO_T ( shape sha X where a1 X where a2 X where dest )
563
(shape sha, where a1, where a2, where dest)
543
{
564
{
544
    long sz = shape_size ( sha ) ;
565
    long sz = shape_size(sha);
545
    long wh1, wh2, whd ;
566
    long wh1, wh2, whd;
546
 
-
 
547
    if ( eq_where ( a1, a2 ) ) {
-
 
548
	move ( sha, zero, dest ) ;
-
 
549
	return ;
-
 
550
    }
-
 
551
 
-
 
552
    if ( eq_where ( a2, dest ) && !eq_where(dest,zero)) {
-
 
553
	sub_aux ( sha, sz, a1, dest ) ;
-
 
554
	return ;
-
 
555
    }
-
 
556
 
567
 
-
 
568
    if (eq_where(a1, a2)) {
-
 
569
	move(sha, zero, dest);
-
 
570
	return;
-
 
571
    }
-
 
572
 
-
 
573
    if (eq_where(a2, dest) && !eq_where(dest,zero)) {
-
 
574
	sub_aux(sha, sz, a1, dest);
-
 
575
	return;
-
 
576
    }
-
 
577
 
557
    wh1 = whereis ( a1 ) ;
578
    wh1 = whereis(a1);
558
    wh2 = whereis ( a2 ) ;
579
    wh2 = whereis(a2);
559
    whd = whereis ( dest ) ;
580
    whd = whereis(dest);
-
 
581
 
-
 
582
    if (wh1 == Value) {
-
 
583
	long v1 = nw(a1);
-
 
584
	if (is_offset(a1.wh_exp))v1 /= 8;
-
 
585
	if (wh2 == Value) {
-
 
586
	    long v2 = nw(a2);
-
 
587
	    if (is_offset(a2.wh_exp))v2 /= 8;
560
 
588
 
561
    if ( wh1 == Value ) {
-
 
562
	long v1 = nw ( a1 ) ;
-
 
563
	if ( is_offset ( a1.wh_exp ) ) v1 /= 8 ;
-
 
564
	if ( wh2 == Value ) {
-
 
565
	    long v2 = nw ( a2 ) ;
-
 
566
	    if ( is_offset ( a2.wh_exp ) ) v2 /= 8 ;
-
 
567
 
-
 
568
            if ( is_signed(sha) ) {
589
            if (is_signed(sha)) {
569
               if (v2>0 && v1<0) {
590
               if (v2>0 && v1<0) {
570
                  if (-v1 > range_max(sha) - v2)
591
                  if (-v1 > range_max(sha) - v2)
571
                  test_overflow(UNCONDITIONAL) ;
592
                  test_overflow(UNCONDITIONAL);
572
               }
593
               }
573
               else if (v2<0 && v1>0) {
594
               else if (v2<0 && v1>0) {
574
                  if (v2 < range_min(sha) + v1 )
595
                  if (v2 < range_min(sha) + v1)
575
                  test_overflow(UNCONDITIONAL) ;
596
                  test_overflow(UNCONDITIONAL);
576
               }
597
               }
577
            }
598
            }
578
            else {
599
            else {
579
               if ((unsigned)v1>(unsigned)v2)
600
               if ((unsigned)v1> (unsigned)v2)
580
               test_overflow(UNCONDITIONAL) ;
601
               test_overflow(UNCONDITIONAL);
581
            }
602
            }
582
 
603
 
583
	    move ( sha, mnw ( v2 - v1 ), dest ) ;
604
	    move(sha, mnw(v2 - v1), dest);
584
	    return ;
605
	    return;
585
	}
606
	}
586
	addsub_const_3_args ( sha, sz, v1, a2, dest, 1 ) ;
607
	addsub_const_3_args(sha, sz, v1, a2, dest, 1);
587
	return ;
608
	return;
588
    }
609
    }
589
 
610
 
590
    if ( wh2 == Value && nw ( a2 ) == 0 ) {
611
    if (wh2 == Value && nw(a2) == 0) {
591
	negate ( sha, a1, dest ) ;
612
	negate(sha, a1, dest);
592
	return ;
613
	return;
593
    }
614
    }
594
 
615
 
595
    if ( ( whd == Dreg || whd == Areg ) && !interfere ( a1, dest ) ) {
616
    if ((whd == Dreg || whd == Areg) && !interfere(a1, dest)) {
596
	move ( sha, a2, dest ) ;
617
	move(sha, a2, dest);
597
	sub_aux ( sha, sz, a1, dest ) ;
618
	sub_aux(sha, sz, a1, dest);
598
	return ;
619
	return;
599
    }
620
    }
600
 
621
 
601
    move ( sha, a2, D0 ) ;
622
    move(sha, a2, D0);
602
    sub_aux ( sha, sz, a1, D0 ) ;
623
    sub_aux(sha, sz, a1, D0);
603
    move ( sha, D0, dest ) ;
624
    move(sha, D0, dest);
604
    set_cond ( dest, sz ) ;
625
    set_cond(dest, sz);
605
    return ;
626
    return;
606
}
627
}
607
 
628
 
608
 
629
 
609
/*
630
/*
610
    NEGATE ROUTINE
631
    NEGATE ROUTINE
611
 
632
 
612
    The value a of shape sha is negated and the result is stored in dest.
633
    The value a of shape sha is negated and the result is stored in dest.
613
*/
634
*/
614
 
635
 
615
void negate
636
void negate
616
    PROTO_N ( ( sha, a, dest ) )
-
 
617
    PROTO_T ( shape sha X where a X where dest )
637
(shape sha, where a, where dest)
618
{
638
{
619
    int instr ;
639
    int instr;
620
    long sz = shape_size ( sha ) ;
640
    long sz = shape_size(sha);
621
    long rt = shtype ( sha ) ;
641
    long rt = shtype(sha);
622
    long wha = whereis ( a ) ;
642
    long wha = whereis(a);
623
    long whd = whereis ( dest ) ;
643
    long whd = whereis(dest);
624
 
644
 
625
    if ( rt == Freg ) {
645
    if (rt == Freg) {
626
	negate_float ( sha, a, dest ) ;
646
	negate_float(sha, a, dest);
627
	return ;
647
	return;
628
    }
648
    }
629
 
649
 
630
    if ( wha == Value ) {
650
    if (wha == Value) {
631
	long c = nw ( a ) ;
651
	long c = nw(a);
632
        bool overflow = 0 ;
652
        bool overflow = 0;
633
 
653
 
634
	if ( is_offset ( a.wh_exp ) ) c /= 8 ;
654
	if (is_offset(a.wh_exp))c /= 8;
635
 
655
 
636
        if ( is_signed(sha) ) {
656
        if (is_signed(sha)) {
637
           if (c < - range_max(sha))
657
           if (c < - range_max(sha))
638
           overflow = 1 ;
658
           overflow = 1;
639
        }
659
        }
640
        else {
660
        else {
641
           if ( c != 0 ) {
661
           if (c != 0) {
642
              make_comment("negation of unsigned shape");
662
              make_comment("negation of unsigned shape");
643
              overflow = 1 ;
663
              overflow = 1;
644
           }
664
           }
645
        }
665
        }
646
 
666
 
647
        /* If there is overflow and we have an error treatment, do it */
667
        /* If there is overflow and we have an error treatment, do it */
648
        if ( overflow && have_overflow () ) {
668
        if (overflow && have_overflow()) {
649
           test_overflow( UNCONDITIONAL ) ;
669
           test_overflow(UNCONDITIONAL);
650
        }
670
        }
651
        /* No, so move the value in place */
671
        /* No, so move the value in place */
652
        else {
672
        else {
653
           move ( sha, mnw ( -c ), dest ) ;
673
           move(sha, mnw(-c), dest);
654
        }
674
        }
655
 
675
 
656
	return ;
676
	return;
657
    }
-
 
658
 
-
 
659
    if ( eq_where ( a, dest ) && whd != Areg ) {
-
 
660
	instr = ins ( sz, ml_neg ) ;
-
 
661
	ins1 ( instr, sz, dest, 1 ) ;
-
 
662
	set_cond ( dest, sz ) ;
-
 
663
        test_overflow(ON_SHAPE ( sha )) ;
-
 
664
 
-
 
665
	return ;
-
 
666
    }
-
 
667
 
-
 
668
    if ( whd == Dreg ) {
-
 
669
	move ( sha, a, dest ) ;
-
 
670
	negate ( sha, dest, dest ) ;
-
 
671
	return ;
-
 
672
    }
-
 
673
 
-
 
674
    if ( wha == Dreg && last_use ( a ) ) {
-
 
675
	negate ( sha, a, a ) ;
-
 
676
	move ( sha, a, dest ) ;
-
 
677
	return ;
-
 
678
    }
677
    }
679
 
678
 
-
 
679
    if (eq_where(a, dest) && whd != Areg) {
-
 
680
	instr = ins(sz, ml_neg);
-
 
681
	ins1(instr, sz, dest, 1);
-
 
682
	set_cond(dest, sz);
-
 
683
        test_overflow(ON_SHAPE(sha));
-
 
684
 
-
 
685
	return;
-
 
686
    }
-
 
687
 
-
 
688
    if (whd == Dreg) {
-
 
689
	move(sha, a, dest);
-
 
690
	negate(sha, dest, dest);
-
 
691
	return;
-
 
692
    }
-
 
693
 
-
 
694
    if (wha == Dreg && last_use(a)) {
-
 
695
	negate(sha, a, a);
-
 
696
	move(sha, a, dest);
-
 
697
	return;
-
 
698
    }
-
 
699
 
680
    move ( sha, a, D0 ) ;
700
    move(sha, a, D0);
681
    negate ( sha, D0, D0 ) ;
701
    negate(sha, D0, D0);
682
    move ( sha, D0, dest ) ;
702
    move(sha, D0, dest);
683
    return ;
703
    return;
684
}
704
}
685
 
705
 
686
 
706
 
687
/*
707
/*
688
    AUXILIARY MULTIPLY ROUTINE
708
    AUXILIARY MULTIPLY ROUTINE
689
 
709
 
690
    The value dest of shape sha is multiplied by a.
710
    The value dest of shape sha is multiplied by a.
691
*/
711
*/
692
 
712
 
693
static void mult_aux
713
static void mult_aux
694
    PROTO_N ( ( sha, a, dest ) )
-
 
695
    PROTO_T ( shape sha X where a X where dest )
714
(shape sha, where a, where dest)
696
{
715
{
697
    bool sg = is_signed ( sha ) ;
716
    bool sg = is_signed(sha);
698
    long sz = shape_size ( sha ) ;
717
    long sz = shape_size(sha);
699
    int instr = ( sg ? m_mulsl : m_mulul ) ;
718
    int instr = (sg ? m_mulsl : m_mulul);
700
    shape lsha = ( sg ? slongsh : ulongsh ) ;
719
    shape lsha = (sg ? slongsh : ulongsh);
701
 
720
 
702
    if ( whereis ( a ) == Freg ) {
721
    if (whereis(a) == Freg) {
703
	move ( sha, a, D0 ) ;
722
	move(sha, a, D0);
704
	mult_aux ( sha, D0, dest ) ;
723
	mult_aux(sha, D0, dest);
705
	return ;
724
	return;
706
    }
725
    }
707
 
726
 
708
    if ( sz == 8 || (have_overflow() && (sz == 16))) {
727
    if (sz == 8 || (have_overflow() && (sz == 16))) {
709
	change_var_sh ( lsha, sha, dest, dest ) ;
728
	change_var_sh(lsha, sha, dest, dest);
710
	change_var_sh ( lsha, sha, a, D0 ) ;
729
	change_var_sh(lsha, sha, a, D0);
711
	ins2 ( instr, L32, L32, dest, D0, 1 ) ;
730
	ins2(instr, L32, L32, dest, D0, 1);
712
        test_overflow( ON_OVERFLOW ) ;
731
        test_overflow(ON_OVERFLOW);
713
	change_var_sh ( sha, lsha, D0, dest ) ;
732
	change_var_sh(sha, lsha, D0, dest);
714
	set_cond ( dest, sz ) ;
733
	set_cond(dest, sz);
715
	return ;
734
	return;
716
    }
735
    }
717
 
736
 
718
    if ( sz == 16 ) instr = ( sg ? m_mulsw : m_muluw ) ;
737
    if (sz == 16)instr = (sg ? m_mulsw : m_muluw);
719
 
738
 
720
    if ( whereis ( dest ) == Dreg ) {
739
    if (whereis(dest) == Dreg) {
721
	if ( whereis ( a ) == Areg ) {
740
	if (whereis(a) == Areg) {
722
	    if ( eq_where ( dest, D0 ) ) {
741
	    if (eq_where(dest, D0)) {
723
		move ( sha, a, D1 ) ;
742
		move(sha, a, D1);
724
		regsinproc |= regmsk ( REG_D1 ) ;
743
		regsinproc |= regmsk(REG_D1);
725
		ins2 ( instr, sz, sz, D1, dest, 1 ) ;
744
		ins2(instr, sz, sz, D1, dest, 1);
726
	    } else {
745
	    } else {
727
		move ( sha, a, D0 ) ;
746
		move(sha, a, D0);
728
		ins2 ( instr, sz, sz, D0, dest, 1 ) ;
747
		ins2(instr, sz, sz, D0, dest, 1);
729
	    }
748
	    }
730
	} else {
749
	} else {
731
	    ins2 ( instr, sz, sz, a, dest, 1 ) ;
750
	    ins2(instr, sz, sz, a, dest, 1);
732
	}
751
	}
733
        test_overflow( ON_OVERFLOW ) ;
752
        test_overflow(ON_OVERFLOW);
734
	set_cond ( dest, sz ) ;
753
	set_cond(dest, sz);
735
	return ;
754
	return;
736
    }
755
    }
737
 
756
 
738
    move ( sha, dest, D0 ) ;
757
    move(sha, dest, D0);
739
    if ( whereis ( a ) == Areg ) {
758
    if (whereis(a) == Areg) {
740
	move ( sha, a, D1 ) ;
759
	move(sha, a, D1);
741
	regsinproc |= regmsk ( REG_D1 ) ;
760
	regsinproc |= regmsk(REG_D1);
742
	ins2 ( instr, sz, sz, D1, D0, 1 ) ;
761
	ins2(instr, sz, sz, D1, D0, 1);
743
    } else {
762
    } else {
744
	ins2 ( instr, sz, sz, a, D0, 1 ) ;
763
	ins2(instr, sz, sz, a, D0, 1);
745
    }
764
    }
746
    test_overflow( ON_OVERFLOW ) ;
765
    test_overflow(ON_OVERFLOW);
747
    move ( sha, D0, dest ) ;
766
    move(sha, D0, dest);
748
    set_cond ( dest, sz ) ;
767
    set_cond(dest, sz);
749
    return ;
768
    return;
750
}
769
}
751
 
770
 
752
 
771
 
753
/*
772
/*
754
    MULTIPLY USING LOAD EFFECTIVE ADDRESS
773
    MULTIPLY USING LOAD EFFECTIVE ADDRESS
755
 
774
 
756
    The m_lea instruction is used to multiply a by the constant sf + 1
775
    The m_lea instruction is used to multiply a by the constant sf + 1
757
    where sf is 1, 2, 4 or 8.  If d is true then a further add instruction
776
    where sf is 1, 2, 4 or 8.  If d is true then a further add instruction
758
    is used to multiply further by 2.  The result is stored in dest.
777
    is used to multiply further by 2.  The result is stored in dest.
759
    This routine only applies to values of size 32.
778
    This routine only applies to values of size 32.
760
*/
779
*/
761
 
780
 
762
static void mult_clever
781
static void mult_clever
763
    PROTO_N ( ( a, dest, sf, d ) )
-
 
764
    PROTO_T ( where a X where dest X long sf X bool d )
782
(where a, where dest, long sf, bool d)
765
{
783
{
766
    int r ;
784
    int r;
767
    where ar ;
785
    where ar;
768
    mach_op *op1, *op2 ;
786
    mach_op *op1, *op2;
769
    if ( whereis ( dest ) == Areg ) {
787
    if (whereis(dest) == Areg) {
770
	ar = dest ;
788
	ar = dest;
771
	r = reg ( dest.wh_regs ) ;
789
	r = reg(dest.wh_regs);
772
    } else {
790
    } else {
773
	r = next_tmp_reg () ;
791
	r = next_tmp_reg();
774
	regsinproc |= regmsk ( r ) ;
792
	regsinproc |= regmsk(r);
775
	ar = register ( r ) ;
793
	ar = register(r);
776
    }
794
    }
777
    move ( slongsh, a, ar ) ;
795
    move(slongsh, a, ar);
778
    op1 = make_reg_index ( r, r, 0, sf ) ;
796
    op1 = make_reg_index(r, r, 0, sf);
779
    op2 = make_register ( r ) ;
797
    op2 = make_register(r);
780
    make_instr ( m_lea, op1, op2, regmsk ( r ) ) ;
798
    make_instr(m_lea, op1, op2, regmsk(r));
781
    have_cond = 0 ;
799
    have_cond = 0;
782
    if ( d ) {
800
    if (d) {
783
	op1 = make_register ( r ) ;
801
	op1 = make_register(r);
784
	op2 = make_register ( r ) ;
802
	op2 = make_register(r);
785
	make_instr ( m_addl, op1, op2, regmsk ( r ) ) ;
803
	make_instr(m_addl, op1, op2, regmsk(r));
786
    }
804
    }
787
    tmp_reg_status = 1 ;
805
    tmp_reg_status = 1;
788
    move ( slongsh, ar, dest ) ;
806
    move(slongsh, ar, dest);
789
    return ;
807
    return;
790
}
808
}
791
 
809
 
792
 
810
 
793
/*
811
/*
794
    MULTIPLY A REGISTER BY A POWER OF 2
812
    MULTIPLY A REGISTER BY A POWER OF 2
Line 796... Line 814...
796
    The register r is multiplied by 2 to the power of p.  The flag
814
    The register r is multiplied by 2 to the power of p.  The flag
797
    D1_used is passed on to shift_aux if necessary.
815
    D1_used is passed on to shift_aux if necessary.
798
*/
816
*/
799
 
817
 
800
static void mult_power2
818
static void mult_power2
801
    PROTO_N ( ( p, r, D1_used ) )
-
 
802
    PROTO_T ( long p X where r X bool D1_used )
819
(long p, where r, bool D1_used)
803
{
820
{
804
    switch ( p ) {
821
    switch (p) {
805
	case 0 : return ;
822
	case 0: return;
806
	case 1 : ins2 ( m_addl, L32, L32, r, r, 1 ) ; return ;
823
	case 1: ins2(m_addl, L32, L32, r, r, 1); return;
807
	default : {
824
	default : {
808
	    shift_aux ( slongsh, mnw ( p ), r, r, 0, D1_used ) ;
825
	    shift_aux(slongsh, mnw(p), r, r, 0, D1_used);
809
	    return ;
826
	    return;
810
	}
827
	}
811
    }
828
    }
812
}
829
}
813
 
830
 
814
 
831
 
815
/*
832
/*
816
    MULTIPLICATION UTILITY ROUTINE
833
    MULTIPLICATION UTILITY ROUTINE
817
 
834
 
818
    This routine is used by mult_const.  The values r1 and r2 represent
835
    This routine is used by mult_const.  The values r1 and r2 represent
819
    registers.  If P denotes 2 to the power of p and Q denotes 2 to the
836
    registers.  If P denotes 2 to the power of p and Q denotes 2 to the
Line 826... Line 843...
826
 
843
 
827
    The flag D1_used is passed onto mult_power2 if necessary.
844
    The flag D1_used is passed onto mult_power2 if necessary.
828
*/
845
*/
829
 
846
 
830
static void mult_utility
847
static void mult_utility
831
    PROTO_N ( ( p, q, r1, r2, D1_used, first_time ) )
-
 
832
    PROTO_T ( long p X long q X where r1 X where r2 X bool D1_used X bool first_time )
848
(long p, long q, where r1, where r2, bool D1_used, bool first_time)
833
{
849
{
834
    if ( first_time ) {
850
    if (first_time) {
835
	switch ( p ) {
851
	switch (p) {
836
 
852
 
837
	    case 0 : return ;		/* Doesn't occur */
853
	    case 0 : return ;		/* Doesn't occur */
838
	    case 1 : return ;		/* Multiply by one */
854
	    case 1 : return ;		/* Multiply by one */
839
 
855
 
840
	    case 2 : {
856
	    case 2: {
841
		/* Multiply by 3 */
857
		/* Multiply by 3 */
842
		ins2 ( m_addl, L32, L32, r1, r1, 1 ) ;
858
		ins2(m_addl, L32, L32, r1, r1, 1);
843
		ins2 ( m_addl, L32, L32, r2, r1, 1 ) ;
859
		ins2(m_addl, L32, L32, r2, r1, 1);
844
		return ;
860
		return;
845
	    }
861
	    }
846
 
862
 
847
	    default : {
863
	    default : {
848
		mult_power2 ( p, r1, D1_used ) ;
864
		mult_power2(p, r1, D1_used);
849
		ins2 ( m_subl, L32, L32, r2, r1, 1 ) ;
865
		ins2(m_subl, L32, L32, r2, r1, 1);
850
		return ;
866
		return;
851
	    }
867
	    }
852
	}
868
	}
853
    } else {
869
    } else {
854
	switch ( p ) {
870
	switch (p) {
855
 
871
 
856
	    case 0 : {
872
	    case 0: {
857
		/* P = 1 => r1 = ( Q * r1 ) */
873
		/* P = 1 => r1 = ( Q * r1 ) */
858
		mult_power2 ( q, r1, D1_used ) ;
874
		mult_power2(q, r1, D1_used);
859
		return ;
875
		return;
860
	    }
876
	    }
861
 
877
 
862
	    case 1 : {
878
	    case 1: {
863
		/* P = 2 => r1 = ( 2 * Q * r1 + r2 ) */
879
		/* P = 2 => r1 = ( 2 * Q * r1 + r2 ) */
864
		mult_power2 ( q + 1, r1, D1_used ) ;
880
		mult_power2(q + 1, r1, D1_used);
865
		ins2 ( m_addl, L32, L32, r2, r1, 1 ) ;
881
		ins2(m_addl, L32, L32, r2, r1, 1);
866
		return ;
882
		return;
867
	    }
883
	    }
868
 
884
 
869
	    case 2 : {
885
	    case 2: {
870
		/* P = 4 => r1 = ( 4 * Q * r1 + 3 * r2 ) */
886
		/* P = 4 => r1 = ( 4 * Q * r1 + 3 * r2 ) */
871
		mult_power2 ( q + 1, r1, D1_used ) ;
887
		mult_power2(q + 1, r1, D1_used);
872
		ins2 ( m_addl, L32, L32, r2, r1, 1 ) ;
888
		ins2(m_addl, L32, L32, r2, r1, 1);
873
		ins2 ( m_addl, L32, L32, r1, r1, 1 ) ;
889
		ins2(m_addl, L32, L32, r1, r1, 1);
874
		ins2 ( m_addl, L32, L32, r2, r1, 1 ) ;
890
		ins2(m_addl, L32, L32, r2, r1, 1);
875
		return ;
891
		return;
876
	    }
892
	    }
877
 
893
 
878
	    default : {
894
	    default : {
879
		mult_power2 ( q, r1, D1_used ) ;
895
		mult_power2(q, r1, D1_used);
880
		ins2 ( m_addl, L32, L32, r2, r1, 1 ) ;
896
		ins2(m_addl, L32, L32, r2, r1, 1);
881
		mult_power2 ( p, r1, D1_used ) ;
897
		mult_power2(p, r1, D1_used);
882
		ins2 ( m_subl, L32, L32, r2, r1, 1 ) ;
898
		ins2(m_subl, L32, L32, r2, r1, 1);
883
		return ;
899
		return;
884
	    }
900
	    }
885
	}
901
	}
886
    }
902
    }
887
}
903
}
888
 
904
 
889
 
905
 
890
/*
906
/*
891
    MULTIPLY BY A CONSTANT
907
    MULTIPLY BY A CONSTANT
892
 
908
 
893
    The value a1 of shape sha is multiplied by the constant value a2
909
    The value a1 of shape sha is multiplied by the constant value a2
894
    and the result is stored in dest.  All constant multiplications
910
    and the result is stored in dest.  All constant multiplications
895
    are done by means of shifts, adds and subtracts.  Certain small
911
    are done by means of shifts, adds and subtracts.  Certain small
896
    cases and powers of 2 are dealt with separately.  The main algorithm
912
    cases and powers of 2 are dealt with separately.  The main algorithm
897
    is to split the constant into sections of the form 00...0011...11.
913
    is to split the constant into sections of the form 00...0011...11.
898
*/
914
*/
899
 
915
 
900
static void mult_const
916
static void mult_const
901
    PROTO_N ( ( sha, a1, a2, dest ) )
-
 
902
    PROTO_T ( shape sha X where a1 X where a2 X where dest )
917
(shape sha, where a1, where a2, where dest)
903
{
918
{
904
    long n = nw ( a2 ), m, p, q, n0 ;
919
    long n = nw(a2), m, p, q, n0;
905
    where reg1, reg2 ;
920
    where reg1, reg2;
906
    bool D1_used, dont_move = 0 ;
921
    bool D1_used, dont_move = 0;
907
    bool started = 0, first_time = 1 ;
922
    bool started = 0, first_time = 1;
908
 
-
 
909
    long sz = shape_size ( sha ) ;
-
 
910
 
-
 
911
    long wh1 = whereis ( a1 ) ;
-
 
912
    long whd = whereis ( dest ) ;
-
 
913
 
923
 
914
    if ( is_offset ( a2.wh_exp ) ) n /= 8 ;
924
    long sz = shape_size(sha);
915
    switch ( n ) {
-
 
916
 
925
 
-
 
926
    long wh1 = whereis(a1);
-
 
927
    long whd = whereis(dest);
-
 
928
 
-
 
929
    if (is_offset(a2.wh_exp))n /= 8;
-
 
930
    switch (n) {
-
 
931
 
917
	case 0 : {
932
	case 0: {
918
	    /* Multiply by zero = Load zero */
933
	    /* Multiply by zero = Load zero */
919
	    move ( sha, zero, dest ) ;
934
	    move(sha, zero, dest);
920
	    return ;
935
	    return;
921
	}
936
	}
922
 
937
 
923
	case 1 : {
938
	case 1: {
924
	    /* Multiply by one = Move */
939
	    /* Multiply by one = Move */
925
	    move ( sha, a1, dest ) ;
940
	    move(sha, a1, dest);
926
	    return ;
941
	    return;
927
	}
942
	}
928
 
943
 
929
	case -1 : {
944
	case -1: {
930
	    /* Multiply by minus one = Negate */
945
	    /* Multiply by minus one = Negate */
931
	    negate ( sha, a1, dest ) ;
946
	    negate(sha, a1, dest);
932
	    return ;
947
	    return;
933
	}
948
	}
934
 
949
 
935
	case 2 : {
950
	case 2: {
936
	    /* Multiply by two = Add */
951
	    /* Multiply by two = Add */
937
	    add ( sha, a1, a1, dest ) ;
952
	    add(sha, a1, a1, dest);
938
	    return ;
953
	    return;
939
	}
954
	}
940
 
955
 
941
	case 5 : {
956
	case 5: {
942
	    if ( sz == 32 ) {
957
	    if (sz == 32) {
943
		mult_clever ( a1, dest, L4, 0 ) ;
958
		mult_clever(a1, dest, L4, 0);
944
		return ;
959
		return;
945
	    }
960
	    }
946
	    break ;
961
	    break;
947
	}
962
	}
948
 
963
 
949
	case 9 : {
964
	case 9: {
950
	    if ( sz == 32 ) {
965
	    if (sz == 32) {
951
		mult_clever ( a1, dest, L8, 0 ) ;
966
		mult_clever(a1, dest, L8, 0);
952
		return ;
967
		return;
953
	    }
968
	    }
954
	    break ;
969
	    break;
955
	}
970
	}
956
 
971
 
957
	case 10 : {
972
	case 10: {
958
	    if ( sz == 32 ) {
973
	    if (sz == 32) {
959
		mult_clever ( a1, dest, L4, 1 ) ;
974
		mult_clever(a1, dest, L4, 1);
960
		return ;
975
		return;
961
	    }
976
	    }
962
	    break ;
977
	    break;
963
	}
978
	}
964
 
979
 
965
	case 18 : {
980
	case 18: {
966
	    if ( sz == 32 ) {
981
	    if (sz == 32) {
967
		mult_clever ( a1, dest, L8, 1 ) ;
982
		mult_clever(a1, dest, L8, 1);
968
		return ;
983
		return;
969
	    }
984
	    }
970
	    break ;
985
	    break;
971
	}
986
	}
972
    }
987
    }
973
 
988
 
974
    /* Find two registers */
989
    /* Find two registers */
975
    if ( whd == Dreg && !eq_where ( dest, D0 ) ) {
990
    if (whd == Dreg && !eq_where(dest, D0)) {
976
	reg1 = dest ;
991
	reg1 = dest;
977
	reg2 = D0 ;
992
	reg2 = D0;
978
	D1_used = 0 ;
993
	D1_used = 0;
979
    } else {
994
    } else {
980
	reg1 = D0 ;
995
	reg1 = D0;
981
	reg2 = D1 ;
996
	reg2 = D1;
982
	D1_used = 1 ;
997
	D1_used = 1;
983
    }
998
    }
984
    if ( wh1 == Dreg && !eq_where ( a1, reg1 ) ) {
999
    if (wh1 == Dreg && !eq_where(a1, reg1)) {
985
	reg2 = a1 ;
1000
	reg2 = a1;
986
	D1_used = 0 ;
1001
	D1_used = 0;
987
	dont_move = 1 ;
1002
	dont_move = 1;
988
    }
1003
    }
989
 
1004
 
990
    /* Deal with multiplications of less than 32 bits */
1005
    /* Deal with multiplications of less than 32 bits */
991
    if ( sz < 32 ) {
1006
    if (sz < 32) {
992
	shape lsha = ( is_signed ( sha ) ? slongsh : ulongsh ) ;
1007
	shape lsha = (is_signed(sha)? slongsh : ulongsh);
993
	change_var_sh ( lsha, sha, a1, reg1 ) ;
1008
	change_var_sh(lsha, sha, a1, reg1);
994
    	mult_const ( lsha, reg1, a2, reg1 ) ;
1009
    	mult_const(lsha, reg1, a2, reg1);
995
	change_var_sh ( sha, lsha, reg1, dest ) ;
1010
	change_var_sh(sha, lsha, reg1, dest);
996
	return ;
1011
	return;
997
    }
1012
    }
998
 
1013
 
999
    /* Now prepare to multiply by |n| */
1014
    /* Now prepare to multiply by |n| */
1000
    n0 = n ;
1015
    n0 = n;
1001
    if ( n < 0 ) n = -n ;
1016
    if (n < 0)n = -n;
1002
 
1017
 
1003
    if ( is_pow2 ( n ) ) {
1018
    if (is_pow2(n)) {
1004
	/* Powers of two are easy */
1019
	/* Powers of two are easy */
1005
	p = log2 ( n ) ;
1020
	p = log2(n);
1006
	if ( wh1 == Dreg && last_use ( a1 ) ) {
1021
	if (wh1 == Dreg && last_use(a1)) {
1007
	    reg1 = a1 ;
1022
	    reg1 = a1;
1008
	    D1_used = 0 ;
1023
	    D1_used = 0;
1009
	} else {
1024
	} else {
1010
	    move ( sha, a1, reg1 ) ;
1025
	    move(sha, a1, reg1);
1011
	}
1026
	}
1012
	mult_power2 ( p, reg1, D1_used ) ;
1027
	mult_power2(p, reg1, D1_used);
1013
    } else {
1028
    } else {
1014
	/* The thing we are multiplying goes in reg1 */
1029
	/* The thing we are multiplying goes in reg1 */
1015
	move ( sha, a1, reg1 ) ;
1030
	move(sha, a1, reg1);
1016
	/* Copy reg1 into reg2 if necessary */
1031
	/* Copy reg1 into reg2 if necessary */
1017
	if ( !dont_move ) move ( slongsh, reg1, reg2 ) ;
1032
	if (!dont_move)move(slongsh, reg1, reg2);
1018
	if ( D1_used ) regsinproc |= regmsk ( REG_D1 ) ;
1033
	if (D1_used)regsinproc |= regmsk(REG_D1);
1019
	/* p will count consecutive ones and q consecutive zeros */
1034
	/* p will count consecutive ones and q consecutive zeros */
1020
	p = 0 ;
1035
	p = 0;
1021
	q = 0 ;
1036
	q = 0;
1022
	/* Scan through the 31 bits of n (the sign bit is zero), MSB first */
1037
	/* Scan through the 31 bits of n (the sign bit is zero), MSB first */
1023
	for ( m = pow2 ( 30 ) ; m ; m >>= 1 ) {
1038
	for (m = pow2(30); m; m >>= 1) {
1024
	    if ( m & n ) {
1039
	    if (m & n) {
1025
		/* Set bit - record this */
1040
		/* Set bit - record this */
1026
		started = 1 ;
1041
		started = 1;
1027
		p++ ;
1042
		p++;
1028
	    } else {
1043
	    } else {
1029
		/* Reset bit - record this */
1044
		/* Reset bit - record this */
1030
		if ( p ) {
1045
		if (p) {
1031
		    /* We have read q 0's, then p 1's, before this 0 */
1046
		    /* We have read q 0's, then p 1's, before this 0 */
1032
		    mult_utility ( p, q, reg1, reg2, 1, first_time ) ;
1047
		    mult_utility(p, q, reg1, reg2, 1, first_time);
1033
		    first_time = 0 ;
1048
		    first_time = 0;
1034
		    /* Restart counts */
1049
		    /* Restart counts */
1035
		    p = 0 ;
1050
		    p = 0;
1036
		    q = 0 ;
1051
		    q = 0;
1037
		}
1052
		}
1038
		/* Record reset bit, ignoring initial zeros */
1053
		/* Record reset bit, ignoring initial zeros */
1039
		if ( started ) q++ ;
1054
		if (started)q++;
1040
	    }
1055
	    }
1041
	}
1056
	}
1042
	/* Deal with last batch of digits */
1057
	/* Deal with last batch of digits */
1043
	if ( p || q ) mult_utility ( p, q, reg1, reg2, 1, first_time ) ;
1058
	if (p || q)mult_utility(p, q, reg1, reg2, 1, first_time);
1044
    }
1059
    }
1045
    /* Now put the result into dest - take care of sign of n now */
1060
    /* Now put the result into dest - take care of sign of n now */
1046
    if ( n0 < 0 ) {
1061
    if (n0 < 0) {
1047
	negate ( slongsh, reg1, dest ) ;
1062
	negate(slongsh, reg1, dest);
1048
    } else {
1063
    } else {
1049
	move ( slongsh, reg1, dest ) ;
1064
	move(slongsh, reg1, dest);
1050
    }
1065
    }
1051
    set_cond ( dest, L32 ) ;
1066
    set_cond(dest, L32);
1052
    return ;
1067
    return;
1053
}
1068
}
1054
 
1069
 
1055
 
1070
 
1056
/*
1071
/*
1057
    MAIN MULTIPLICATION ROUTINE
1072
    MAIN MULTIPLICATION ROUTINE
Line 1059... Line 1074...
1059
    The values a1 and a2 of shape sha are multiplied and the result is
1074
    The values a1 and a2 of shape sha are multiplied and the result is
1060
    stored in dest.
1075
    stored in dest.
1061
*/
1076
*/
1062
 
1077
 
1063
void mult
1078
void mult
1064
    PROTO_N ( ( sha, a1, a2, dest ) )
-
 
1065
    PROTO_T ( shape sha X where a1 X where a2 X where dest )
1079
(shape sha, where a1, where a2, where dest)
1066
{
1080
{
1067
    where w ;
1081
    where w;
1068
    long wh1 = whereis ( a1 ) ;
1082
    long wh1 = whereis(a1);
1069
    long wh2 = whereis ( a2 ) ;
1083
    long wh2 = whereis(a2);
1070
    long whd = whereis ( dest ) ;
1084
    long whd = whereis(dest);
1071
 
1085
 
1072
    if ( !have_overflow () ) {
1086
    if (!have_overflow()) {
1073
	/* Constant multiplication */
1087
	/* Constant multiplication */
1074
	if ( wh1 == Value ) {
1088
	if (wh1 == Value) {
1075
	    if ( wh2 == Value ) {
1089
	    if (wh2 == Value) {
1076
		long v1 = nw ( a1 ) ;
1090
		long v1 = nw(a1);
1077
		long v2 = nw ( a2 ) ;
1091
		long v2 = nw(a2);
1078
		if ( is_offset ( a1.wh_exp ) ) v1 /= 8 ;
1092
		if (is_offset(a1.wh_exp))v1 /= 8;
1079
		if ( is_offset ( a2.wh_exp ) ) v2 /= 8 ;
1093
		if (is_offset(a2.wh_exp))v2 /= 8;
1080
		move ( sha, mnw ( v1 * v2 ), dest ) ;
1094
		move(sha, mnw(v1 * v2), dest);
1081
		return ;
1095
		return;
1082
	    }
1096
	    }
1083
	    mult_const ( sha, a2, a1, dest ) ;
1097
	    mult_const(sha, a2, a1, dest);
1084
	    return ;
1098
	    return;
1085
	}
1099
	}
1086
 
1100
 
1087
	if ( wh2 == Value ) {
1101
	if (wh2 == Value) {
1088
	    mult_const ( sha, a1, a2, dest ) ;
1102
	    mult_const(sha, a1, a2, dest);
1089
	    return ;
1103
	    return;
1090
	}
1104
	}
1091
    }
1105
    }
1092
 
1106
 
1093
    if ( eq_where ( a1, a2 ) ) {
1107
    if (eq_where(a1, a2)) {
1094
	if ( whd == Dreg ) {
1108
	if (whd == Dreg) {
1095
	    move ( sha, a1, dest ) ;
1109
	    move(sha, a1, dest);
1096
	    mult_aux ( sha, dest, dest ) ;
1110
	    mult_aux(sha, dest, dest);
1097
	    return ;
1111
	    return;
1098
	} else {
1112
	} else {
1099
	    move ( sha, a1, D0 ) ;
1113
	    move(sha, a1, D0);
1100
	    mult_aux ( sha, D0, D0 ) ;
1114
	    mult_aux(sha, D0, D0);
1101
	    move ( sha, D0, dest ) ;
1115
	    move(sha, D0, dest);
1102
	    return ;
1116
	    return;
1103
	}
1117
	}
1104
    }
1118
    }
1105
 
1119
 
1106
    if ( eq_where ( a1, dest ) ) {
1120
    if (eq_where(a1, dest)) {
1107
	mult_aux ( sha, a2, dest ) ;
1121
	mult_aux(sha, a2, dest);
1108
	return ;
1122
	return;
1109
    }
1123
    }
1110
 
1124
 
1111
    if ( eq_where ( a2, dest ) ) {
1125
    if (eq_where(a2, dest)) {
1112
	mult_aux ( sha, a1, dest ) ;
1126
	mult_aux(sha, a1, dest);
1113
	return ;
1127
	return;
1114
    }
1128
    }
1115
 
1129
 
1116
    if ( whd == Dreg ) {
1130
    if (whd == Dreg) {
1117
	if ( !interfere ( a2, dest ) ) {
1131
	if (!interfere(a2, dest)) {
1118
	    move ( sha, a1, dest ) ;
1132
	    move(sha, a1, dest);
1119
	    mult_aux ( sha, a2, dest ) ;
1133
	    mult_aux(sha, a2, dest);
1120
	    return ;
1134
	    return;
1121
	}
1135
	}
1122
	if ( !interfere ( a1, dest ) ) {
1136
	if (!interfere(a1, dest)) {
1123
	    move ( sha, a2, dest ) ;
1137
	    move(sha, a2, dest);
1124
	    mult_aux ( sha, a1, dest ) ;
1138
	    mult_aux(sha, a1, dest);
1125
	    return ;
1139
	    return;
1126
	}
1140
	}
1127
    }
1141
    }
1128
 
1142
 
1129
    if ( shape_size ( sha ) == 8 ||
1143
    if (shape_size(sha) == 8 ||
1130
	((shape_size(sha)==16) && (have_overflow()))) {
1144
	((shape_size(sha) ==16) && (have_overflow()))) {
1131
	w = D1 ;
1145
	w = D1;
1132
	regsinproc |= regmsk ( REG_D1 ) ;
1146
	regsinproc |= regmsk(REG_D1);
1133
    } else {
1147
    } else {
1134
	w = D0 ;
1148
	w = D0;
1135
    }
1149
    }
1136
    if ( whereis ( a2 ) == Areg ) {
1150
    if (whereis(a2) == Areg) {
1137
	move ( sha, a2, w ) ;
1151
	move(sha, a2, w);
1138
	mult_aux ( sha, a1, w ) ;
1152
	mult_aux(sha, a1, w);
1139
	move ( sha, w, dest ) ;
1153
	move(sha, w, dest);
1140
    } else {
1154
    } else {
1141
	move ( sha, a1, w ) ;
1155
	move(sha, a1, w);
1142
	mult_aux ( sha, a2, w ) ;
1156
	mult_aux(sha, a2, w);
1143
	move ( sha, w, dest ) ;
1157
	move(sha, w, dest);
1144
    }
1158
    }
1145
    return ;
1159
    return;
1146
}
1160
}
1147
 
1161
 
1148
 
1162
 
1149
/*
1163
/*
1150
    DIVISION BY A POWER OF 2
1164
    DIVISION BY A POWER OF 2
1151
 
1165
 
1152
    The value top of shape sha is divided by the constant v which is a
1166
    The value top of shape sha is divided by the constant v which is a
1153
    power of 2.  The result is stored in dest.
1167
    power of 2.  The result is stored in dest.
1154
*/
1168
*/
1155
 
1169
 
1156
static void div_power2
1170
static void div_power2
1157
    PROTO_N ( ( sha, v, top, dest ) )
-
 
1158
    PROTO_T ( shape sha X long v X where top X where dest )
1171
(shape sha, long v, where top, where dest)
1159
{
1172
{
1160
    long n = log2 ( v ) ;
1173
    long n = log2(v);
1161
    if ( is_signed ( sha ) ) {
1174
    if (is_signed(sha)) {
1162
	bool sw ;
1175
	bool sw;
1163
	where w ;
1176
	where w;
1164
	int instr ;
1177
	int instr;
1165
	long sz = shape_size ( sha ) ;
1178
	long sz = shape_size(sha);
1166
	long lab = next_lab () ;
1179
	long lab = next_lab();
1167
	exp jt = simple_exp ( 0 ) ;
1180
	exp jt = simple_exp(0);
1168
	ptno ( jt ) = lab ;
1181
	ptno(jt) = lab;
1169
 
1182
 
1170
	if ( whereis ( dest ) == Dreg ) {
1183
	if (whereis(dest) == Dreg) {
1171
	    w = dest ;
1184
	    w = dest;
1172
	} else if ( whereis ( top ) == Dreg && last_use ( top ) ) {
1185
	} else if (whereis(top) == Dreg && last_use(top)) {
1173
	    w = top ;
1186
	    w = top;
1174
	} else {
1187
	} else {
1175
	    w = D0 ;
1188
	    w = D0;
1176
	}
1189
	}
1177
	move ( sha, top, w ) ;
1190
	move(sha, top, w);
1178
	sw = cmp ( sha, w, zero, tst_ge ) ;
1191
	sw = cmp(sha, w, zero, tst_ge);
1179
	branch ( tst_ge, jt, 1, sw, 0 ) ;
1192
	branch(tst_ge, jt, 1, sw, 0);
1180
	add ( sha, w, mnw ( v - 1 ), w ) ;
1193
	add(sha, w, mnw(v - 1), w);
1181
	make_label ( lab ) ;
1194
	make_label(lab);
1182
	instr = ins ( sz, ml_asr ) ;
1195
	instr = ins(sz, ml_asr);
1183
	while ( n ) {
1196
	while (n) {
1184
	    long m = ( n > 8 ? 7 : n ) ;
1197
	    long m = (n > 8 ? 7 : n);
1185
	    ins2n ( instr, m, sz, w, 1 ) ;
1198
	    ins2n(instr, m, sz, w, 1);
1186
	    n -= m ;
1199
	    n -= m;
1187
	}
1200
	}
1188
	move ( sha, w, dest ) ;
1201
	move(sha, w, dest);
1189
	set_cond ( dest, sz ) ;
1202
	set_cond(dest, sz);
1190
    } else {
1203
    } else {
1191
	shift_aux ( sha, mnw ( n ), top, dest, 1, 0 ) ;
1204
	shift_aux(sha, mnw(n), top, dest, 1, 0);
1192
    }
1205
    }
1193
    return ;
1206
    return;
1194
}
1207
}
1195
 
1208
 
1196
 
1209
 
1197
/*
1210
/*
1198
    REMAINDER MODULO A POWER OF 2
1211
    REMAINDER MODULO A POWER OF 2
Line 1200... Line 1213...
1200
    The remainder of the value top of shape sha when divided by the
1213
    The remainder of the value top of shape sha when divided by the
1201
    constant v (which is a power of 2) is stored in dest.
1214
    constant v (which is a power of 2) is stored in dest.
1202
*/
1215
*/
1203
 
1216
 
1204
static void rem_power2
1217
static void rem_power2
1205
    PROTO_N ( ( sha, v, top, dest ) )
-
 
1206
    PROTO_T ( shape sha X long v X where top X where dest )
1218
(shape sha, long v, where top, where dest)
1207
{
1219
{
1208
    if ( is_signed ( sha ) ) {
1220
    if (is_signed(sha)) {
1209
	bool sw ;
1221
	bool sw;
1210
	where w ;
1222
	where w;
1211
	long lab = next_lab () ;
1223
	long lab = next_lab();
1212
	long end = next_lab () ;
1224
	long end = next_lab();
1213
	exp jt = simple_exp ( 0 ) ;
1225
	exp jt = simple_exp(0);
1214
	exp je = simple_exp ( 0 ) ;
1226
	exp je = simple_exp(0);
1215
	ptno ( jt ) = lab ;
1227
	ptno(jt) = lab;
1216
	ptno ( je ) = end ;
1228
	ptno(je) = end;
1217
 
1229
 
1218
	if ( whereis ( dest ) == Dreg ) {
1230
	if (whereis(dest) == Dreg) {
1219
	    w = dest ;
1231
	    w = dest;
1220
	} else if ( whereis ( top ) == Dreg && last_use ( top ) ) {
1232
	} else if (whereis(top) == Dreg && last_use(top)) {
1221
	    w = top ;
1233
	    w = top;
1222
	} else {
1234
	} else {
1223
	    w = D0 ;
1235
	    w = D0;
1224
	}
1236
	}
1225
	move ( sha, top, w ) ;
1237
	move(sha, top, w);
1226
	sw = cmp ( sha, w, zero, tst_ge ) ;
1238
	sw = cmp(sha, w, zero, tst_ge);
1227
	branch ( tst_ge, jt, 1, sw, 0 ) ;
1239
	branch(tst_ge, jt, 1, sw, 0);
1228
	negate ( sha, w, w ) ;
1240
	negate(sha, w, w);
1229
	and ( sha, mnw ( v - 1 ), w, w ) ;
1241
	and(sha, mnw(v - 1), w, w);
1230
	negate ( sha, w, w ) ;
1242
	negate(sha, w, w);
1231
	make_jump ( m_bra, end ) ;
1243
	make_jump(m_bra, end);
1232
	make_label ( lab ) ;
1244
	make_label(lab);
1233
	and ( sha, mnw ( v - 1 ), w, w ) ;
1245
	and(sha, mnw(v - 1), w, w);
1234
	make_label ( end ) ;
1246
	make_label(end);
1235
	move ( sha, w, dest ) ;
1247
	move(sha, w, dest);
1236
	set_cond ( dest, shape_size ( sha ) ) ;
1248
	set_cond(dest, shape_size(sha));
1237
    } else {
1249
    } else {
1238
	and ( sha, mnw ( v - 1 ), top, dest ) ;
1250
	and(sha, mnw(v - 1), top, dest);
1239
    }
1251
    }
1240
    return ;
1252
    return;
1241
}
1253
}
1242
 
1254
 
1243
 
1255
 
1244
/*
1256
/*
1245
    REMAINDER MODULO A POWER OF 2 MINUS 1
1257
    REMAINDER MODULO A POWER OF 2 MINUS 1
1246
 
1258
 
1247
    The remainder of the value top of shape sha when divided by the
1259
    The remainder of the value top of shape sha when divided by the
1248
    constant v (which is a power of 2 minus 1) is stored in dest.  The
1260
    constant v (which is a power of 2 minus 1) is stored in dest.  The
1249
    algorithm used is a modification of "casting out the nines".
1261
    algorithm used is a modification of "casting out the nines".
1250
*/
1262
*/
1251
 
1263
 
1252
static bool rem_power2_1
1264
static bool rem_power2_1
1253
    PROTO_N ( ( sha, v, top, dest ) )
-
 
1254
    PROTO_T ( shape sha X long v X where top X where dest )
1265
(shape sha, long v, where top, where dest)
1255
{
1266
{
1256
    bool sw ;
1267
    bool sw;
1257
    where d0, d1 ;
1268
    where d0, d1;
1258
    long loop, end, tst ;
1269
    long loop, end, tst;
1259
    exp jloop, jend, jtst ;
1270
    exp jloop, jend, jtst;
1260
    bool s = is_signed ( sha ) ;
1271
    bool s = is_signed(sha);
1261
 
1272
 
1262
    if ( s && ( eq_where ( top, D0 ) || eq_where ( top, D1 ) ) ) return ( 0 ) ;
1273
    if (s && (eq_where(top, D0) || eq_where(top, D1))) return(0);
1263
 
1274
 
1264
    if ( whereis ( dest ) == Dreg ) {
1275
    if (whereis(dest) == Dreg) {
1265
	d1 = dest ;
1276
	d1 = dest;
1266
    } else {
-
 
1267
	d1 = D1 ;
-
 
1268
	regsinproc |= regmsk ( REG_D1 ) ;
-
 
1269
    }
-
 
1270
 
-
 
1271
    if ( eq_where ( d1, D0 ) ) {
-
 
1272
	d0 = D1 ;
-
 
1273
	regsinproc |= regmsk ( REG_D1 ) ;
-
 
1274
    } else {
1277
    } else {
-
 
1278
	d1 = D1;
-
 
1279
	regsinproc |= regmsk(REG_D1);
-
 
1280
    }
-
 
1281
 
-
 
1282
    if (eq_where(d1, D0)) {
-
 
1283
	d0 = D1;
-
 
1284
	regsinproc |= regmsk(REG_D1);
-
 
1285
    } else {
1275
	d0 = D0 ;
1286
	d0 = D0;
1276
    }
1287
    }
1277
 
1288
 
1278
    loop = next_lab () ;
1289
    loop = next_lab();
1279
    jloop = simple_exp ( 0 ) ;
1290
    jloop = simple_exp(0);
1280
    ptno ( jloop ) = loop ;
1291
    ptno(jloop) = loop;
1281
    end = next_lab () ;
1292
    end = next_lab();
1282
    jend = simple_exp ( 0 ) ;
1293
    jend = simple_exp(0);
1283
    ptno ( jend ) = end ;
1294
    ptno(jend) = end;
1284
    tst = next_lab () ;
1295
    tst = next_lab();
1285
    jtst = simple_exp ( 0 ) ;
1296
    jtst = simple_exp(0);
1286
    ptno ( jtst ) = tst ;
1297
    ptno(jtst) = tst;
1287
 
1298
 
1288
    move ( sha, top, d1 ) ;
1299
    move(sha, top, d1);
1289
    if ( s ) {
1300
    if (s) {
1290
	sw = cmp ( sha, d1, zero, tst_ge ) ;
1301
	sw = cmp(sha, d1, zero, tst_ge);
1291
	branch ( tst_ge, jloop, s, sw, 0 ) ;
1302
	branch(tst_ge, jloop, s, sw, 0);
1292
	negate ( sha, d1, d1 ) ;
-
 
1293
    }
-
 
1294
    make_label ( loop ) ;
-
 
1295
    move ( sha, mnw ( v ), d0 ) ;
-
 
1296
    sw = cmp ( ulongsh, d1, d0, tst_le ) ;
-
 
1297
    branch ( tst_le, jend, s, sw, 0 ) ;
-
 
1298
    and ( ulongsh, d1, d0, d0 ) ;
-
 
1299
    rshift ( ulongsh, mnw ( log2 ( v + 1 ) ), d1, d1 ) ;
-
 
1300
    add ( ulongsh, d0, d1, d1 ) ;
-
 
1301
    make_jump ( m_bra, loop ) ;
-
 
1302
    make_label ( end ) ;
-
 
1303
    branch ( tst_neq, jtst, s, sw, 0 ) ;
-
 
1304
    move ( sha, zero, d1 ) ;
-
 
1305
    make_label ( tst ) ;
-
 
1306
    if ( s ) {
-
 
1307
	long ntst = next_lab () ;
-
 
1308
	exp jntst = simple_exp ( 0 ) ;
-
 
1309
	ptno ( jntst ) = ntst ;
-
 
1310
	sw = cmp ( sha, top, zero, tst_ge ) ;
-
 
1311
	branch ( tst_ge, jntst, 1, sw, 0 ) ;
-
 
1312
	negate ( sha, d1, d1 ) ;
1303
	negate(sha, d1, d1);
1313
	make_label ( ntst ) ;
-
 
1314
    }
1304
    }
-
 
1305
    make_label(loop);
-
 
1306
    move(sha, mnw(v), d0);
-
 
1307
    sw = cmp(ulongsh, d1, d0, tst_le);
-
 
1308
    branch(tst_le, jend, s, sw, 0);
-
 
1309
    and(ulongsh, d1, d0, d0);
-
 
1310
    rshift(ulongsh, mnw(log2(v + 1)), d1, d1);
-
 
1311
    add(ulongsh, d0, d1, d1);
-
 
1312
    make_jump(m_bra, loop);
-
 
1313
    make_label(end);
-
 
1314
    branch(tst_neq, jtst, s, sw, 0);
-
 
1315
    move(sha, zero, d1);
-
 
1316
    make_label(tst);
-
 
1317
    if (s) {
-
 
1318
	long ntst = next_lab();
-
 
1319
	exp jntst = simple_exp(0);
-
 
1320
	ptno(jntst) = ntst;
-
 
1321
	sw = cmp(sha, top, zero, tst_ge);
-
 
1322
	branch(tst_ge, jntst, 1, sw, 0);
-
 
1323
	negate(sha, d1, d1);
-
 
1324
	make_label(ntst);
-
 
1325
    }
1315
    have_cond = 0 ;
1326
    have_cond = 0;
1316
    move ( sha, d1, dest ) ;
1327
    move(sha, d1, dest);
1317
    return ( 1 ) ;
1328
    return(1);
1318
}
1329
}
1319
 
1330
 
1320
 
1331
 
1321
/*
1332
/*
1322
    MARKERS FOR DIVISION AND REMAINDER
1333
    MARKERS FOR DIVISION AND REMAINDER
1323
 
1334
 
1324
    Division, remainder and combined division-remainder operations are
1335
    Division, remainder and combined division-remainder operations are
1325
    all handled by a single routine.  The following values are used to
1336
    all handled by a single routine.  The following values are used to
1326
    indicate to the routine the operation type.
1337
    indicate to the routine the operation type.
1327
*/
1338
*/
1328
 
1339
 
1329
#define  DIV		0
1340
#define  DIV		0
1330
#define  REM		1
1341
#define  REM		1
1331
#define  BOTH		2
1342
#define  BOTH		2
1332
 
1343
 
1333
 
1344
 
1334
/*
1345
/*
1335
    MAIN DIVISION AND REMAINDER ROUTINE
1346
    MAIN DIVISION AND REMAINDER ROUTINE
1336
 
1347
 
1337
    The value top of shape sha is divided by bottom and, depending on
1348
    The value top of shape sha is divided by bottom and, depending on
1338
    the value of type, the quotient is stored in quot and the remainder
1349
    the value of type, the quotient is stored in quot and the remainder
1339
    in rem.  Which of the two possible division types used is determined
1350
    in rem.  Which of the two possible division types used is determined
1340
    by form : for example, if form is 1 then :
1351
    by form : for example, if form is 1 then :
1341
 
1352
 
1342
		    5 = ( -2 ) * ( -3 ) - 1
1353
		    5 = ( -2 ) * ( -3 ) - 1
1343
 
1354
 
1344
    whereas if form is 2 :
1355
    whereas if form is 2 :
1345
 
1356
 
1346
		    5 = ( -1 ) * ( -3 ) + 2
1357
		    5 = ( -1 ) * ( -3 ) + 2
1347
 
1358
 
1348
    The second form is the standard one.
1359
    The second form is the standard one.
1349
*/
1360
*/
1350
 
1361
 
1351
static void euclid
1362
static void euclid
1352
    PROTO_N ( ( sha, bottom, top, quot, rem, type, form ) )
-
 
1353
    PROTO_T ( shape sha X where bottom X where top X where quot X where rem X int type X int form )
1363
(shape sha, where bottom, where top, where quot, where rem, int type, int form)
1354
{
1364
{
1355
    long v ;
1365
    long v;
1356
    bool b_const = 0 ;
1366
    bool b_const = 0;
1357
    bool save_d1 = 0 ;
1367
    bool save_d1 = 0;
1358
    bool d1_pending = 0 ;
1368
    bool d1_pending = 0;
1359
    where qreg, rreg, breg ;
1369
    where qreg, rreg, breg;
1360
    long sz = shape_size ( sha ) ;
1370
    long sz = shape_size(sha);
1361
    bool sg = is_signed ( sha ) ;
1371
    bool sg = is_signed(sha);
1362
    shape lsha = ( sg ? slongsh : ulongsh ) ;
1372
    shape lsha = (sg ? slongsh : ulongsh);
1363
 
1373
 
1364
    /* The two forms are the same for unsigned division */
1374
    /* The two forms are the same for unsigned division */
1365
    if ( !sg ) form = 2 ;
1375
    if (!sg) form = 2;
1366
 
1376
 
1367
    /* Deal with division by constants */
1377
    /* Deal with division by constants */
1368
    if ( name ( bottom.wh_exp ) == val_tag ) {
1378
    if (name(bottom.wh_exp) == val_tag) {
1369
	b_const = 1 ;
1379
	b_const = 1;
1370
	v = nw ( bottom ) ;
1380
	v = nw(bottom);
1371
	if ( is_offset ( bottom.wh_exp ) ) v /= 8 ;
1381
	if (is_offset(bottom.wh_exp))v /= 8;
1372
	switch ( v ) {
1382
	switch (v) {
1373
 
1383
 
1374
	    case 0 : {
1384
	    case 0: {
1375
		warning ( "Division by zero" ) ;
1385
		warning("Division by zero");
1376
                if ( have_overflow () ) {
1386
                if (have_overflow()) {
1377
                   test_overflow( UNCONDITIONAL ) ;
1387
                   test_overflow(UNCONDITIONAL);
1378
                }
1388
                }
1379
                else {
1389
                else {
1380
                   if ( type != REM ) move ( sha, zero, quot ) ;
1390
                   if (type != REM)move(sha, zero, quot);
1381
                   if ( type != DIV ) move ( sha, zero, rem ) ;
1391
                   if (type != DIV)move(sha, zero, rem);
1382
                }
1392
                }
1383
		return ;
1393
		return;
1384
	    }
1394
	    }
1385
 
1395
 
1386
	    case 1 : {
1396
	    case 1: {
1387
		if ( type != REM ) move ( sha, top, quot ) ;
1397
		if (type != REM)move(sha, top, quot);
1388
		if ( type != DIV ) move ( sha, zero, rem ) ;
1398
		if (type != DIV)move(sha, zero, rem);
1389
		return ;
1399
		return;
1390
	    }
1400
	    }
1391
 
1401
 
1392
	    case -1 : {
1402
	    case -1: {
1393
                if (is_signed(sha)) { /* is it really negative */
1403
                if (is_signed(sha)) { /* is it really negative */
1394
                    if ( type != REM || have_overflow() ) negate ( sha, top, quot ) ;
1404
                    if (type != REM || have_overflow())negate(sha, top, quot);
1395
                    if ( type != DIV ) move ( sha, zero, rem ) ;
1405
                    if (type != DIV)move(sha, zero, rem);
1396
                    return ;
1406
                    return;
1397
                }
1407
                }
1398
                /* fall through */
1408
                /* fall through */
1399
	    }
1409
	    }
1400
 
1410
 
1401
	    default : {
1411
	    default : {
1402
		if ( form != 1 ) {
1412
		if (form != 1) {
1403
                    if ( (!is_signed(sha) || v > 0) && is_pow2 ( v ) && sz == 32 ) {
1413
                    if ((!is_signed(sha) || v > 0) && is_pow2(v) && sz == 32) {
1404
                        if ( type == DIV ) {
1414
                        if (type == DIV) {
1405
			    div_power2 ( sha, v, top, quot ) ;
1415
			    div_power2(sha, v, top, quot);
1406
			    return ;
1416
			    return;
1407
			}
1417
			}
1408
			if ( type == REM ) {
1418
			if (type == REM) {
1409
			    rem_power2 ( sha, v, top, rem ) ;
1419
			    rem_power2(sha, v, top, rem);
1410
			    return ;
1420
			    return;
1411
			}
1421
			}
1412
		    }
1422
		    }
1413
		    if ( v > 7 && is_pow2 ( v + 1 ) && sz == 32 ) {
1423
		    if (v > 7 && is_pow2(v + 1) && sz == 32) {
1414
			if ( type == REM &&
1424
			if (type == REM &&
1415
			     rem_power2_1 ( sha, v, top, rem ) ) {
1425
			     rem_power2_1(sha, v, top, rem)) {
1416
			    return ;
1426
			    return;
1417
			}
1427
			}
1418
		    }
1428
		    }
1419
		}
1429
		}
1420
		break ;
1430
		break;
1421
	    }
1431
	    }
1422
	}
1432
	}
1423
    }
1433
    }
1424
 
1434
 
1425
    /* Check on pointless divisions */
1435
    /* Check on pointless divisions */
1426
    if ( eq_where ( top, bottom ) ) {
1436
    if (eq_where(top, bottom)) {
1427
	if ( type != REM ) move ( sha, mnw ( 1 ), quot ) ;
1437
	if (type != REM)move(sha, mnw(1), quot);
1428
	if ( type != DIV ) move ( sha, zero, rem ) ;
1438
	if (type != DIV)move(sha, zero, rem);
1429
	return ;
1439
	return;
1430
    }
1440
    }
1431
 
1441
 
1432
    /* Now find two registers */
1442
    /* Now find two registers */
1433
    if ( type == BOTH && interfere ( quot, rem ) ) {
1443
    if (type == BOTH && interfere(quot, rem)) {
1434
	qreg = D0 ;
1444
	qreg = D0;
1435
	rreg = D1 ;
1445
	rreg = D1;
1436
	regsinproc |= regmsk ( REG_D1 ) ;
1446
	regsinproc |= regmsk(REG_D1);
1437
	if ( D1_is_special ) save_d1 = 1 ;
1447
	if (D1_is_special)save_d1 = 1;
1438
    } else {
1448
    } else {
1439
	if ( type != REM && whereis ( quot ) == Dreg &&
1449
	if (type != REM && whereis(quot) == Dreg &&
1440
	     !interfere ( quot, bottom ) ) {
1450
	     !interfere(quot, bottom)) {
1441
	    qreg = quot ;
1451
	    qreg = quot;
1442
	} else {
1452
	} else {
1443
	    qreg = D0 ;
1453
	    qreg = D0;
1444
	}
1454
	}
1445
	if ( type != DIV && whereis ( rem ) == Dreg ) {
1455
	if (type != DIV && whereis(rem) == Dreg) {
1446
	    if ( eq_where ( rem, D0 ) ) {
1456
	    if (eq_where(rem, D0)) {
1447
		qreg = D1 ;
1457
		qreg = D1;
1448
		rreg = D0 ;
1458
		rreg = D0;
1449
		regsinproc |= regmsk ( REG_D1 ) ;
1459
		regsinproc |= regmsk(REG_D1);
1450
		if ( D1_is_special ) save_d1 = 1 ;
1460
		if (D1_is_special)save_d1 = 1;
1451
	    } else {
1461
	    } else {
1452
		rreg = rem ;
1462
		rreg = rem;
1453
	    }
1463
	    }
1454
	} else {
1464
	} else {
1455
	    if ( eq_where ( qreg, D0 ) ) {
1465
	    if (eq_where(qreg, D0)) {
1456
		rreg = D1 ;
1466
		rreg = D1;
1457
		if ( type == DIV ) {
1467
		if (type == DIV) {
1458
		    d1_pending = 1 ;
1468
		    d1_pending = 1;
1459
		} else {
1469
		} else {
1460
		    regsinproc |= regmsk ( REG_D1 ) ;
1470
		    regsinproc |= regmsk(REG_D1);
1461
		    if ( D1_is_special ) save_d1 = 1 ;
1471
		    if (D1_is_special)save_d1 = 1;
1462
		}
1472
		}
1463
	    } else {
1473
	    } else {
1464
		rreg = D0 ;
1474
		rreg = D0;
1465
	    }
1475
	    }
1466
	}
1476
	}
1467
    }
1477
    }
1468
 
1478
 
1469
    /* Save D1 if necessary */
1479
    /* Save D1 if necessary */
1470
    if ( save_d1 ) push ( slongsh, L32, D1 ) ;
1480
    if (save_d1)push(slongsh, L32, D1);
1471
#if 0
1481
#if 0
1472
    /* Keep the denominator in form 1 */
1482
    /* Keep the denominator in form 1 */
1473
    if ( form == 1 && !b_const ) push ( slongsh, L32, bottom ) ;
1483
    if (form == 1 && !b_const)push(slongsh, L32, bottom);
1474
#endif
1484
#endif
1475
    /* Get the arguments into the correct positions */
1485
    /* Get the arguments into the correct positions */
1476
    if ( sz != 32 ) {
1486
    if (sz != 32) {
1477
       bool d0_pushed = 0 ;
1487
       bool d0_pushed = 0;
1478
 
-
 
1479
       make_comment("change variety top -> qreg") ;
-
 
1480
       change_var_sh ( lsha, sha, top, qreg ) ;
-
 
1481
 
-
 
1482
       if ( eq_where ( qreg, D0 ) ) {
-
 
1483
          push ( slongsh, L32, D0 ) ;
-
 
1484
          d0_pushed = 1 ;
-
 
1485
       }
-
 
1486
 
1488
 
1487
       make_comment("change variety bottom -> rreg") ;
1489
       make_comment("change variety top -> qreg");
1488
       change_var_sh ( lsha, sha, bottom, rreg ) ;
1490
       change_var_sh(lsha, sha, top, qreg);
1489
 
1491
 
-
 
1492
       if (eq_where(qreg, D0)) {
-
 
1493
          push(slongsh, L32, D0);
-
 
1494
          d0_pushed = 1;
-
 
1495
       }
-
 
1496
 
-
 
1497
       make_comment("change variety bottom -> rreg");
-
 
1498
       change_var_sh(lsha, sha, bottom, rreg);
-
 
1499
 
1490
       if ( d0_pushed )
1500
       if (d0_pushed)
1491
          pop(slongsh,L32,D0);
1501
          pop(slongsh,L32,D0);
1492
 
1502
 
1493
       breg = rreg ;
1503
       breg = rreg;
1494
    } else {
1504
    } else {
1495
	move ( sha, top, qreg ) ;
1505
	move(sha, top, qreg);
1496
	if ( whereis ( bottom ) == Areg || whereis ( bottom ) == Freg ) {
1506
	if (whereis(bottom) == Areg || whereis(bottom) == Freg) {
1497
	    if ( d1_pending ) {
1507
	    if (d1_pending) {
1498
		regsinproc |= regmsk ( REG_D1 ) ;
1508
		regsinproc |= regmsk(REG_D1);
1499
		if ( D1_is_special ) {
1509
		if (D1_is_special) {
1500
		    save_d1 = 1 ;
1510
		    save_d1 = 1;
1501
		    push ( slongsh, L32, D1 ) ;
1511
		    push(slongsh, L32, D1);
1502
		}
1512
		}
1503
	    }
1513
	    }
1504
	    move ( sha, bottom, rreg ) ;
1514
	    move(sha, bottom, rreg);
1505
	    breg = rreg ;
1515
	    breg = rreg;
1506
	} else {
1516
	} else {
1507
	    breg = bottom ;
1517
	    breg = bottom;
1508
	}
1518
	}
1509
    }
1519
    }
1510
 
1520
 
1511
    if (have_overflow()) {
1521
    if (have_overflow()) {
1512
       if(save_d1) {
1522
       if (save_d1) {
1513
          pop(slongsh,L32,D1);
1523
          pop(slongsh,L32,D1);
1514
       }
1524
       }
1515
       cmp_zero ( sha, sz, breg );
1525
       cmp_zero(sha, sz, breg);
1516
       test_overflow2( m_beq ) ;
1526
       test_overflow2(m_beq);
1517
       if(save_d1) {
1527
       if (save_d1) {
1518
          push(slongsh,L32,D1);
1528
          push(slongsh,L32,D1);
1519
       }
1529
       }
1520
    }
1530
    }
1521
 
1531
 
1522
    /* Keep the denominator in form 1 */
1532
    /* Keep the denominator in form 1 */
1523
    if ( form == 1 && !b_const ) push ( slongsh, L32, breg ) ;
1533
    if (form == 1 && !b_const)push(slongsh, L32, breg);
1524
 
1534
 
1525
    /* Create the actual division instruction */
1535
    /* Create the actual division instruction */
1526
    if ( type == DIV && form != 1 ) {
1536
    if (type == DIV && form != 1) {
1527
	long qn = reg ( qreg.wh_regs ) ;
1537
	long qn = reg(qreg.wh_regs);
1528
	int instr = ( sg ? m_divsl : m_divul ) ;
1538
	int instr = (sg ? m_divsl : m_divul);
1529
	mach_op *op1 = operand ( L32, breg ) ;
1539
	mach_op *op1 = operand(L32, breg);
1530
	mach_op *op2 = make_register ( qn ) ;
1540
	mach_op *op2 = make_register(qn);
1531
	make_instr ( instr, op1, op2, regmsk ( qn ) ) ;
1541
	make_instr(instr, op1, op2, regmsk(qn));
1532
    } else {
1542
    } else {
1533
	long qn = reg ( qreg.wh_regs ) ;
1543
	long qn = reg(qreg.wh_regs);
1534
	long rn = reg ( rreg.wh_regs ) ;
1544
	long rn = reg(rreg.wh_regs);
1535
	int instr = ( sg ? m_divsll : m_divull ) ;
1545
	int instr = (sg ? m_divsll : m_divull);
1536
	mach_op *op1 = operand ( L32, breg ) ;
1546
	mach_op *op1 = operand(L32, breg);
1537
	mach_op *op2 = make_reg_pair ( rn, qn ) ;
1547
	mach_op *op2 = make_reg_pair(rn, qn);
1538
	make_instr ( instr, op1, op2, ( regmsk ( qn ) | regmsk ( rn ) ) ) ;
1548
	make_instr(instr, op1, op2,(regmsk(qn) | regmsk(rn)));
1539
    }
1549
    }
1540
    if(have_overflow()) {
1550
    if (have_overflow()) {
1541
      if(save_d1) {
1551
      if (save_d1) {
1542
	pop(slongsh,L32,D1);
1552
	pop(slongsh,L32,D1);
1543
      }
1553
      }
1544
      if( form == 1 && !b_const ) {
1554
      if (form == 1 && !b_const) {
1545
	dec_stack(-32);
1555
	dec_stack(-32);
1546
      }
1556
      }
1547
      test_overflow( ON_SHAPE(sha) ) ;
1557
      test_overflow(ON_SHAPE(sha));
1548
      if( form == 1 && !b_const ) {
1558
      if (form == 1 && !b_const) {
1549
	dec_stack(32);
1559
	dec_stack(32);
1550
      }
1560
      }
1551
 
1561
 
1552
 
1562
 
1553
    }
1563
    }
1554
 
1564
 
1555
 
1565
 
1556
    /* Apply hacks for form 1 */
1566
    /* Apply hacks for form 1 */
1557
    if ( form == 1 && is_signed(sha) ) {
1567
    if (form == 1 && is_signed(sha)) {
1558
	mach_op *op1, *op2 ;
1568
	mach_op *op1, *op2;
1559
	long lab1 = next_lab () ;
1569
	long lab1 = next_lab();
1560
	long lab2 = next_lab () ;
1570
	long lab2 = next_lab();
1561
	long qn = reg ( qreg.wh_regs ) ;
1571
	long qn = reg(qreg.wh_regs);
1562
	long rn = reg ( rreg.wh_regs ) ;
1572
	long rn = reg(rreg.wh_regs);
1563
	if ( !b_const ) {
1573
	if (!b_const) {
1564
	    op1 = make_indirect ( REG_SP, 0 ) ;
1574
	    op1 = make_indirect(REG_SP, 0);
1565
	    make_instr ( m_tstl, op1, null, 0 ) ;
1575
	    make_instr(m_tstl, op1, null, 0);
1566
	    make_jump ( m_bge, lab1 ) ;
1576
	    make_jump(m_bge, lab1);
1567
	}
1577
	}
1568
 
1578
 
1569
	/* Denominator is negative ? */
1579
	/* Denominator is negative ? */
1570
	if ( !( b_const && v >= 0 ) ) {
1580
	if (!(b_const && v >= 0)) {
1571
	    op1 = make_register ( rn ) ;
1581
	    op1 = make_register(rn);
1572
	    make_instr ( m_tstl, op1, null, 0 ) ;
1582
	    make_instr(m_tstl, op1, null, 0);
1573
	    make_jump ( m_ble, lab2 ) ;
1583
	    make_jump(m_ble, lab2);
1574
	    if ( type != REM ) {
1584
	    if (type != REM) {
1575
		op1 = make_value ( 1 ) ;
1585
		op1 = make_value(1);
1576
		op2 = make_register ( qn ) ;
1586
		op2 = make_register(qn);
1577
		make_instr ( m_subql, op1, op2, regmsk ( qn ) ) ;
1587
		make_instr(m_subql, op1, op2, regmsk(qn));
1578
	    }
1588
	    }
1579
	    if ( type != DIV ) {
1589
	    if (type != DIV) {
1580
		if ( b_const ) {
1590
		if (b_const) {
1581
		    op1 = make_value ( v ) ;
1591
		    op1 = make_value(v);
1582
		} else {
1592
		} else {
1583
		    op1 = make_indirect ( REG_SP, 0 ) ;
1593
		    op1 = make_indirect(REG_SP, 0);
1584
		}
1594
		}
1585
		op2 = make_register ( rn ) ;
1595
		op2 = make_register(rn);
1586
		make_instr ( m_addl, op1, op2, regmsk ( rn ) ) ;
1596
		make_instr(m_addl, op1, op2, regmsk(rn));
1587
	    }
1597
	    }
1588
	    if ( !b_const ) make_jump ( m_bra, lab2 ) ;
1598
	    if (!b_const)make_jump(m_bra, lab2);
1589
	}
1599
	}
1590
 
1600
 
1591
	/* Denominator is positive ? */
1601
	/* Denominator is positive ? */
1592
	if ( !( b_const && v < 0 ) ) {
1602
	if (!(b_const && v < 0)) {
1593
	    if ( !b_const ) make_label ( lab1 ) ;
1603
	    if (!b_const)make_label(lab1);
1594
	    op1 = make_register ( rn ) ;
1604
	    op1 = make_register(rn);
1595
	    make_instr ( m_tstl, op1, null, 0 ) ;
1605
	    make_instr(m_tstl, op1, null, 0);
1596
	    make_jump ( m_bge, lab2 ) ;
1606
	    make_jump(m_bge, lab2);
1597
	    if ( type != REM ) {
1607
	    if (type != REM) {
1598
		op1 = make_value ( 1 ) ;
1608
		op1 = make_value(1);
1599
		op2 = make_register ( qn ) ;
1609
		op2 = make_register(qn);
1600
		make_instr ( m_subql, op1, op2, regmsk ( qn ) ) ;
1610
		make_instr(m_subql, op1, op2, regmsk(qn));
1601
	    }
1611
	    }
1602
	    if ( type != DIV ) {
1612
	    if (type != DIV) {
1603
		if ( b_const ) {
1613
		if (b_const) {
1604
		    op1 = make_value ( v ) ;
1614
		    op1 = make_value(v);
1605
		} else {
1615
		} else {
1606
		    op1 = make_indirect ( REG_SP, 0 ) ;
1616
		    op1 = make_indirect(REG_SP, 0);
1607
		}
1617
		}
1608
		op2 = make_register ( rn ) ;
1618
		op2 = make_register(rn);
1609
		make_instr ( m_addl, op1, op2, regmsk ( rn ) ) ;
1619
		make_instr(m_addl, op1, op2, regmsk(rn));
1610
	    }
1620
	    }
1611
	}
1621
	}
1612
 
1622
 
1613
	make_label ( lab2 ) ;
1623
	make_label(lab2);
1614
	if ( !b_const ) dec_stack ( -32 ) ;
1624
	if (!b_const)dec_stack(-32);
1615
    }
1625
    }
1616
 
1626
 
1617
    /* Move results into place */
1627
    /* Move results into place */
1618
    if ( sz == 32 ) {
1628
    if (sz == 32) {
1619
	if ( type != REM ) move ( sha, qreg, quot ) ;
1629
	if (type != REM)move(sha, qreg, quot);
1620
	if ( type != DIV ) move ( sha, rreg, rem ) ;
1630
	if (type != DIV)move(sha, rreg, rem);
1621
    } else {
1631
    } else {
1622
	if ( type != REM ) change_var_sh ( sha, lsha, qreg, quot ) ;
1632
	if (type != REM)change_var_sh(sha, lsha, qreg, quot);
1623
	if ( type != DIV ) change_var_sh ( sha, lsha, rreg, rem ) ;
1633
	if (type != DIV)change_var_sh(sha, lsha, rreg, rem);
1624
    }
1634
    }
1625
 
1635
 
1626
    /* Restore D1 */
1636
    /* Restore D1 */
1627
    if ( save_d1 ) {
1637
    if (save_d1) {
1628
	pop ( slongsh, L32, D1 ) ;
1638
	pop(slongsh, L32, D1);
1629
	debug_warning ( "D1 saved on stack during division" ) ;
1639
	debug_warning("D1 saved on stack during division");
1630
    }
1640
    }
1631
    have_cond = 0 ;
1641
    have_cond = 0;
1632
    return ;
1642
    return;
1633
}
1643
}
1634
 
1644
 
1635
 
1645
 
1636
/*
1646
/*
1637
    DIVISION INSTRUCTION - FORM ONE
1647
    DIVISION INSTRUCTION - FORM ONE
Line 1639... Line 1649...
1639
    The value top of shape sha is divided by bottom and the result is
1649
    The value top of shape sha is divided by bottom and the result is
1640
    stored in dest.  This is the alternative division operation.
1650
    stored in dest.  This is the alternative division operation.
1641
*/
1651
*/
1642
 
1652
 
1643
void div1
1653
void div1
1644
    PROTO_N ( ( sha, bottom, top, dest ) )
-
 
1645
    PROTO_T ( shape sha X where bottom X where top X where dest )
1654
(shape sha, where bottom, where top, where dest)
1646
{
1655
{
1647
    euclid ( sha, bottom, top, dest, zero, DIV, 1 ) ;
1656
    euclid(sha, bottom, top, dest, zero, DIV, 1);
1648
    return ;
1657
    return;
1649
}
1658
}
1650
 
1659
 
1651
 
1660
 
1652
/*
1661
/*
1653
    DIVISION INSTRUCTION - FORM TWO
1662
    DIVISION INSTRUCTION - FORM TWO
Line 1655... Line 1664...
1655
    The value top of shape sha is divided by bottom and the result is
1664
    The value top of shape sha is divided by bottom and the result is
1656
    stored in dest.  This is the standard division operation.
1665
    stored in dest.  This is the standard division operation.
1657
*/
1666
*/
1658
 
1667
 
1659
void div2
1668
void div2
1660
    PROTO_N ( ( sha, bottom, top, dest ) )
-
 
1661
    PROTO_T ( shape sha X where bottom X where top X where dest )
1669
(shape sha, where bottom, where top, where dest)
1662
{
1670
{
1663
    euclid ( sha, bottom, top, dest, zero, DIV, 2 ) ;
1671
    euclid(sha, bottom, top, dest, zero, DIV, 2);
1664
    return ;
1672
    return;
1665
}
1673
}
1666
 
1674
 
1667
 
1675
 
1668
/*
1676
/*
1669
    REMAINDER INSTRUCTION - FORM ONE
1677
    REMAINDER INSTRUCTION - FORM ONE
Line 1671... Line 1679...
1671
    The value top of shape sha is divided by bottom and the remainder is
1679
    The value top of shape sha is divided by bottom and the remainder is
1672
    stored in dest.  This is the alternative remainder operation.
1680
    stored in dest.  This is the alternative remainder operation.
1673
*/
1681
*/
1674
 
1682
 
1675
void rem1
1683
void rem1
1676
    PROTO_N ( ( sha, bottom, top, dest ) )
-
 
1677
    PROTO_T ( shape sha X where bottom X where top X where dest )
1684
(shape sha, where bottom, where top, where dest)
1678
{
1685
{
1679
    euclid ( sha, bottom, top, zero, dest, REM, 1 ) ;
1686
    euclid(sha, bottom, top, zero, dest, REM, 1);
1680
    return ;
1687
    return;
1681
}
1688
}
1682
 
1689
 
1683
 
1690
 
1684
/*
1691
/*
1685
    REMAINDER INSTRUCTION - FORM TWO
1692
    REMAINDER INSTRUCTION - FORM TWO
Line 1687... Line 1694...
1687
    The value top of shape sha is divided by bottom and the remainder is
1694
    The value top of shape sha is divided by bottom and the remainder is
1688
    stored in dest.  This is the standard remainder operation.
1695
    stored in dest.  This is the standard remainder operation.
1689
*/
1696
*/
1690
 
1697
 
1691
void rem2
1698
void rem2
1692
    PROTO_N ( ( sha, bottom, top, dest ) )
-
 
1693
    PROTO_T ( shape sha X where bottom X where top X where dest )
1699
(shape sha, where bottom, where top, where dest)
1694
{
1700
{
1695
    euclid ( sha, bottom, top, zero, dest, REM, 2 ) ;
1701
    euclid(sha, bottom, top, zero, dest, REM, 2);
1696
    return ;
1702
    return;
1697
}
1703
}
1698
 
1704
 
1699
 
1705
 
1700
/*
1706
/*
1701
    DO AN EXACT DIVISION
1707
    DO AN EXACT DIVISION
1702
 
1708
 
1703
    The value top is divided by bottom and the result is stored in dest.
1709
    The value top is divided by bottom and the result is stored in dest.
1704
*/
1710
*/
1705
 
1711
 
1706
void exactdiv
1712
void exactdiv
1707
    PROTO_N ( ( sha, bottom, top, dest ) )
-
 
1708
    PROTO_T ( shape sha X where bottom X where top X where dest )
1713
(shape sha, where bottom, where top, where dest)
1709
{
1714
{
1710
    euclid ( slongsh, bottom, top, dest, zero, DIV, 2 ) ;
1715
    euclid(slongsh, bottom, top, dest, zero, DIV, 2);
1711
    return ;
1716
    return;
1712
}
1717
}
1713
 
1718
 
1714
 
1719
 
1715
/*
1720
/*
1716
    DO A MAXIMUM OR MINIMUM INSTRUCTION
1721
    DO A MAXIMUM OR MINIMUM INSTRUCTION
1717
*/
1722
*/
1718
 
1723
 
1719
static void maxmin
1724
static void maxmin
1720
    PROTO_N ( ( sha, a1, a2, dest, tst ) )
-
 
1721
    PROTO_T ( shape sha X where a1 X where a2 X where dest X int tst )
1725
(shape sha, where a1, where a2, where dest, int tst)
1722
{
1726
{
1723
    where d ;
1727
    where d;
1724
    bool sw ;
1728
    bool sw;
1725
    long sz = shape_size ( sha ) ;
1729
    long sz = shape_size(sha);
1726
    long lab = next_lab () ;
1730
    long lab = next_lab();
1727
    exp jt = simple_exp ( 0 ) ;
1731
    exp jt = simple_exp(0);
1728
    ptno ( jt ) = lab ;
1732
    ptno(jt) = lab;
1729
    if ( whereis ( dest ) == Dreg && !interfere ( a1, dest ) &&
1733
    if (whereis(dest) == Dreg && !interfere(a1, dest) &&
1730
	 !interfere ( a2, dest ) ) {
1734
	 !interfere(a2, dest)) {
1731
	d = dest ;
1735
	d = dest;
1732
    } else {
1736
    } else {
1733
	d = D0 ;
1737
	d = D0;
1734
    }
1738
    }
1735
    make_comment("maxmin ...");
1739
    make_comment("maxmin ...");
1736
    move ( sha, a1, d ) ;
1740
    move(sha, a1, d);
1737
    sw = cmp ( sha, d, a2, tst ) ;
1741
    sw = cmp(sha, d, a2, tst);
1738
    branch ( tst, jt, is_signed(sha), sw, 0 ) ;
1742
    branch(tst, jt, is_signed(sha), sw, 0);
1739
    move ( sha, a2, d ) ;
1743
    move(sha, a2, d);
1740
    make_label ( lab ) ;
1744
    make_label(lab);
1741
    move ( sha, d, dest ) ;
1745
    move(sha, d, dest);
1742
    make_comment("maxmin done");
1746
    make_comment("maxmin done");
1743
    return ;
1747
    return;
1744
}
1748
}
1745
 
1749
 
1746
 
1750
 
1747
/*
1751
/*
1748
    DO A MAXIMUM INSTRUCTION
1752
    DO A MAXIMUM INSTRUCTION
1749
*/
1753
*/
1750
 
1754
 
1751
void maxop
1755
void maxop
1752
    PROTO_N ( ( sha, a1, a2, dest ) )
-
 
1753
    PROTO_T ( shape sha X where a1 X where a2 X where dest )
1756
(shape sha, where a1, where a2, where dest)
1754
{
1757
{
1755
    maxmin ( sha, a1, a2, dest, tst_ge ) ;
1758
    maxmin(sha, a1, a2, dest, tst_ge);
1756
    return ;
1759
    return;
1757
}
1760
}
1758
 
1761
 
1759
 
1762
 
1760
/*
1763
/*
1761
    DO A MINIMUM INSTRUCTION
1764
    DO A MINIMUM INSTRUCTION
1762
*/
1765
*/
1763
 
1766
 
1764
void minop
1767
void minop
1765
    PROTO_N ( ( sha, a1, a2, dest ) )
-
 
1766
    PROTO_T ( shape sha X where a1 X where a2 X where dest )
1768
(shape sha, where a1, where a2, where dest)
1767
{
1769
{
1768
    maxmin ( sha, a1, a2, dest, tst_le ) ;
1770
    maxmin(sha, a1, a2, dest, tst_le);
1769
    return ;
1771
    return;
1770
}
1772
}
1771
 
1773
 
1772
 
1774
 
1773
/*
1775
/*
1774
    DO AN ABSOLUTE OPERATION
1776
    DO AN ABSOLUTE OPERATION
1775
*/
1777
*/
1776
 
1778
 
1777
void absop
1779
void absop
1778
    PROTO_N ( ( sha, a, dest ) )
-
 
1779
    PROTO_T ( shape sha X where a X where dest )
1780
(shape sha, where a, where dest)
1780
{
1781
{
1781
    if ( is_signed ( sha ) ) {
1782
    if (is_signed(sha)) {
1782
	where d ;
1783
	where d;
1783
	bool sw ;
1784
	bool sw;
1784
	long lab = next_lab () ;
1785
	long lab = next_lab();
1785
	exp jt = simple_exp ( 0 ) ;
1786
	exp jt = simple_exp(0);
1786
	ptno ( jt ) = lab ;
1787
	ptno(jt) = lab;
1787
	if ( whereis ( dest ) == Dreg ) {
1788
	if (whereis(dest) == Dreg) {
1788
	    d = dest ;
1789
	    d = dest;
1789
	} else {
1790
	} else {
1790
	    d = D0 ;
1791
	    d = D0;
1791
	}
1792
	}
1792
	move ( sha, a, d ) ;
1793
	move(sha, a, d);
1793
	sw = cmp ( sha, d, zero, tst_ge ) ;
1794
	sw = cmp(sha, d, zero, tst_ge);
1794
	branch ( tst_ge, jt, 1, sw, 0 ) ;
1795
	branch(tst_ge, jt, 1, sw, 0);
1795
	negate ( sha, d, d ) ;
1796
	negate(sha, d, d);
1796
	make_label ( lab ) ;
1797
	make_label(lab);
1797
	move ( sha, d, dest ) ;
1798
	move(sha, d, dest);
1798
    } else {
1799
    } else {
1799
	move ( sha, a, dest ) ;
1800
	move(sha, a, dest);
1800
    }
1801
    }
1801
    return ;
1802
    return;
1802
}
1803
}
1803
 
1804