Subversion Repositories tendra.SVN

Rev

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

Rev Author Line No. Line
2 7u83 1
/*
7 7u83 2
 * Copyright (c) 2002-2006 The TenDRA Project <http://www.tendra.org/>.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific, prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * $Id$
30
 */
31
/*
2 7u83 32
    		 Crown Copyright (c) 1996
33
 
34
    This TenDRA(r) Computer Program is subject to Copyright
35
    owned by the United Kingdom Secretary of State for Defence
36
    acting through the Defence Evaluation and Research Agency
37
    (DERA).  It is made available to Recipients with a
38
    royalty-free licence for its use, reproduction, transfer
39
    to other parties and amendment for any purpose not excluding
40
    product development provided that any such use et cetera
41
    shall be deemed to be acceptance of the following conditions:-
42
 
43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
45
 
46
        (2) Any amended version of it shall be clearly marked to
47
        show both the nature of and the organisation responsible
48
        for the relevant amendment or amendments;
49
 
50
        (3) Its onward transfer from a recipient to another
51
        party shall be deemed to be that party's acceptance of
52
        these conditions;
53
 
54
        (4) DERA gives no warranty or assurance as to its
55
        quality or suitability for any purpose and DERA accepts
56
        no liability whatsoever in relation to any use to which
57
        it may be put.
58
*/
59
/*
60
			    VERSION INFORMATION
61
			    ===================
62
 
63
--------------------------------------------------------------------------
64
$Header: /u/g/release/CVSROOT/Source/src/installers/680x0/common/ops_logic.c,v 1.1.1.1 1998/01/17 15:55:49 release Exp $
65
--------------------------------------------------------------------------
66
$Log: ops_logic.c,v $
67
 * Revision 1.1.1.1  1998/01/17  15:55:49  release
68
 * First version to be checked into rolling release.
69
 *
70
Revision 1.2  1997/11/09 14:23:43  ma
71
Now is_signed is used instead of issigned.
72
 
73
Revision 1.1.1.1  1997/10/13 12:42:57  ma
74
First version.
75
 
76
Revision 1.2  1997/09/25 06:45:26  ma
77
All general_proc tests passed
78
 
79
Revision 1.1.1.1  1997/03/14 07:50:15  ma
80
Imported from DRA
81
 
82
 * Revision 1.1.1.1  1996/09/20  10:57:00  john
83
 *
84
 * Revision 1.2  1996/07/05  14:24:36  john
85
 * Changes for spec 3.1
86
 *
87
 * Revision 1.1.1.1  1996/03/26  15:45:16  john
88
 *
89
 * Revision 1.6  94/06/29  14:23:47  14:23:47  ra (Robert Andrews)
90
 * Changed a few moves to change_varieties (consequent to changes in
91
 * bitfields).
92
 *
93
 * Revision 1.5  94/02/21  16:01:48  16:01:48  ra (Robert Andrews)
94
 * A couple of arguments should be int, not long.
95
 *
96
 * Revision 1.4  93/11/19  16:22:37  16:22:37  ra (Robert Andrews)
97
 * Minor correction to bitfields of complex operands.
98
 *
99
 * Revision 1.3  93/03/08  15:30:22  15:30:22  ra (Robert Andrews)
100
 * Emulate cc by mapping ( a << b ) to ( a << ( b % 64 ) ) when b is
101
 * a constant.
102
 *
103
 * Revision 1.2  93/03/03  14:49:37  14:49:37  ra (Robert Andrews)
104
 * Started adding support for error treatments.
105
 *
106
 * Revision 1.1  93/02/22  17:16:23  17:16:23  ra (Robert Andrews)
107
 * Initial revision
108
 *
109
--------------------------------------------------------------------------
110
*/
111
 
112
 
113
#include "config.h"
114
#include "common_types.h"
115
#include "assembler.h"
116
#include "basicread.h"
117
#include "check.h"
118
#include "exp.h"
119
#include "expmacs.h"
120
#include "externs.h"
121
#include "install_fns.h"
122
#include "shapemacs.h"
123
#include "tags.h"
124
#include "mach.h"
125
#include "mach_ins.h"
126
#include "where.h"
127
#include "mach_op.h"
128
#include "instr.h"
129
#include "codex.h"
130
#include "instrs.h"
131
#include "coder.h"
132
#include "tests.h"
133
#include "operations.h"
134
#include "evaluate.h"
135
#include "utility.h"
136
#include "translate.h"
137
#include "ops_shared.h"
138
 
139
 
140
/*
141
    MARKERS FOR AND, OR AND XOR
142
 
143
    The logical operations, and, or and xor are handled by a single
144
    routine with a flag to indicate which is meant.  The flag can take
145
    the following values.
146
*/
147
 
148
#define  AND		0
149
#define  OR		1
150
#define  XOR		2
151
 
152
 
153
/*
154
    AND/OR/XOR BY A CONSTANT
155
 
156
    The value a of shape sha and size sz has the logical operator indicated
157
    by logop applied to it and the constant c.  The result is stored in
158
    dest.  instr is one of m_andl, m_orl, eorl.
159
*/
160
 
7 7u83 161
static void
162
andetc_const(int instr, shape sha, long sz, long c, where a, where dest,
163
	     int logop)
2 7u83 164
{
7 7u83 165
	long whd;
2 7u83 166
 
7 7u83 167
	/* First check that a is not a constant */
168
	if (whereis(a) == Value) {
169
		long ca = nw(a);
170
		switch (logop) {
171
		case AND:
172
			ca &= c;
173
			break;
174
		case OR:
175
			ca |= c;
176
			break;
177
		case XOR:
178
			ca ^= c;
179
			break;
180
		}
181
		move(sha, mnw(ca), dest);
182
		return;
2 7u83 183
	}
184
 
7 7u83 185
	/* Now look for some special values of c */
186
	switch (logop) {
187
	case AND: {
188
		long cc;
189
		if (c == 0) {
190
			move(sha, zero, dest);
191
			return;
2 7u83 192
		}
7 7u83 193
		cc = ~c;
194
		if (sz == 32) {
195
			if (cc == 0) {
196
				change_var(sha, a, dest);
197
				return;
198
			}
199
			if (is_pow2(cc)) {
200
				long p = log2(cc);
201
				if (whereis(dest) == Dreg) {
202
					change_var(sha, a, dest);
203
					ins2n(m_bclr, p, sz, dest, 1);
204
					have_cond = 0;
205
					return;
206
				}
207
			}
2 7u83 208
		}
7 7u83 209
		break;
2 7u83 210
	}
7 7u83 211
	case OR:
212
		if (c == 0) {
213
			change_var(sha, a, dest);
214
			return;
2 7u83 215
		}
7 7u83 216
		if (is_pow2(c)) {
217
			long p = log2(c);
218
			if (whereis(dest) == Dreg) {
219
				change_var(sha, a, dest);
220
				ins2n(m_bset, p, sz, dest, 1);
221
				have_cond = 0;
222
				return;
223
			}
224
		}
225
		break;
226
	case XOR:
227
		if (c == 0) {
228
			change_var(sha, a, dest);
229
			return;
230
		}
231
		break;
2 7u83 232
	}
233
 
7 7u83 234
	whd = whereis(dest);
235
	if (whd != Areg && eq_where(a, dest)) {
236
		ins2h(instr, c, sz, dest, 1);
237
		set_cond(dest, sz);
238
		return;
2 7u83 239
	}
7 7u83 240
	if (whd == Dreg) {
241
		change_var(sha, a, dest);
242
		ins2h(instr, c, sz, dest, 1);
243
		set_cond(dest, sz);
244
		return;
245
	}
246
	if (whereis(a) == Dreg && last_use(a)) {
247
		ins2h(instr, c, sz, a, 1);
248
		change_var(sha, a, dest);
249
		set_cond(dest, sz);
250
		return;
251
	}
252
	change_var(sha, a, D0);
253
	ins2h(instr, c, sz, D0, 1);
254
	move(sha, D0, dest);
255
	set_cond(dest, sz);
256
	return;
2 7u83 257
}
258
 
259
 
260
/*
261
    AUXILLARY ROUTINE FOR AND/OR/XOR
262
 
263
    The values a1 and a2 of shape sha have the logical operation indicated
264
    by logop applied to them and the result is stored in dest.  ( opb,
265
    opw, opl ) is an ordered triple giving the byte, word and long forms of
266
    the appropriate machine instruction.
267
*/
268
 
7 7u83 269
static void
270
andetc(int opb, int opw, int opl, shape sha, where a1, where a2, where dest,
271
       int logop)
2 7u83 272
{
7 7u83 273
	int instr;
274
	long wha, whb, whd;
275
	long sz = shape_size(sha);
2 7u83 276
 
7 7u83 277
	if (eq_where(a1, a2)) {
278
		switch (logop) {
279
		case AND:
280
			move(sha, a1, dest);
281
			return;
282
		case OR:
283
			move(sha, a1, dest);
284
			return;
285
		case XOR:
286
			move(sha, zero, dest);
287
			return;
288
		}
2 7u83 289
	}
290
 
7 7u83 291
	instr = ins(sz, opb, opw, opl);
2 7u83 292
 
7 7u83 293
	wha = whereis(a1);
294
	whb = whereis(a2);
2 7u83 295
 
7 7u83 296
	if (wha == Freg) {
297
		move(sha, a1, D0);
298
		andetc(opb, opw, opl, sha, D0, a2, dest, logop);
299
		return;
300
	}
2 7u83 301
 
7 7u83 302
	if (whb == Freg) {
303
		move(sha, a2, D0);
304
		andetc(opb, opw, opl, sha, a1, D0, dest, logop);
305
		return;
306
	}
2 7u83 307
 
7 7u83 308
	if (wha == Value) {
309
		long c = nw(a1);
310
		andetc_const(instr, sha, sz, c, a2, dest, logop);
311
		return;
312
	}
2 7u83 313
 
7 7u83 314
	if (whb == Value) {
315
		long c = nw(a2);
316
		andetc_const(instr, sha, sz, c, a1, dest, logop);
317
		return;
318
	}
2 7u83 319
 
7 7u83 320
	whd = whereis(dest);
2 7u83 321
 
7 7u83 322
	if (eq_where(a1, dest) && whd != Areg) {
323
		if (whb == Dreg) {
324
			ins2(instr, sz, sz, a2, dest, 1);
325
			return;
326
		}
327
		if (whd == Dreg) {
328
			if (logop == XOR || whb == Areg) {
329
				if (eq_where(dest, D0)) {
330
					regsinproc |= regmsk(REG_D1);
331
					move(sha, a2, D1);
332
					ins2(instr, sz, sz, D1, dest, 1);
333
					set_cond(dest, sz);
334
					return;
335
				} else {
336
					move(sha, a2, D0);
337
					ins2(instr, sz, sz, D0, dest, 1);
338
					set_cond(dest, sz);
339
					return;
340
				}
341
			} else {
342
				ins2(instr, sz, sz, a2, dest, 1);
343
				set_cond(dest, sz);
344
				return;
345
			}
2 7u83 346
		} else {
7 7u83 347
			move(sha, a2, D0);
348
			ins2(instr, sz, sz, D0, dest, 1);
349
			set_cond(dest, sz);
350
			return;
2 7u83 351
		}
352
	}
353
 
7 7u83 354
	if (eq_where(a2, dest) && whd != Areg) {
355
		if (wha == Dreg) {
356
			ins2(instr, sz, sz, a1, dest, 1);
357
			set_cond(dest, sz);
358
			return;
359
		}
360
		if (whd == Dreg) {
361
			if (logop == XOR || wha == Areg || wha == Freg) {
362
				if (eq_where(dest, D0)) {
363
					regsinproc |= regmsk(REG_D1);
364
					move(sha, a1, D1);
365
					ins2(instr, sz, sz, D1, dest, 1);
366
				} else {
367
					move(sha, a1, D0);
368
					ins2(instr, sz, sz, D0, dest, 1);
369
				}
370
			} else {
371
				ins2(instr, sz, sz, a1, dest, 1);
372
			}
2 7u83 373
		} else {
7 7u83 374
			move(sha, a1, D0);
375
			ins2(instr, sz, sz, D0, dest, 1);
2 7u83 376
		}
7 7u83 377
		set_cond(dest, sz);
378
		return;
2 7u83 379
	}
380
 
7 7u83 381
	if (whd == Dreg) {
382
		if (!interfere(a2, dest)) {
383
			move(sha, a1, dest);
384
			andetc(opb, opw, opl, sha, a2, dest, dest, logop);
385
			return;
386
		}
387
		if (!interfere(a1, dest)) {
388
			move(sha, a2, dest);
389
			andetc(opb, opw, opl, sha, a1, dest, dest, logop);
390
			return;
391
		}
2 7u83 392
	}
393
 
7 7u83 394
	move(sha, a1, D0);
395
	andetc(opb, opw, opl, sha, a2, D0, D0, logop);
396
	move(sha, D0, dest);
397
	return;
2 7u83 398
}
399
 
400
 
401
/*
402
    AND INSTRUCTION
403
 
404
    The values a1 and a2 of shape sha are anded and the result is stored
405
    in dested.
406
*/
407
 
7 7u83 408
void
409
and(shape sha, where a1, where a2, where dest)
2 7u83 410
{
7 7u83 411
	andetc(ml_and, sha, a1, a2, dest, AND);
412
	return;
2 7u83 413
}
414
 
415
 
416
/*
417
    OR INSTRUCTION
418
 
419
    The values a1 and a2 of shape sha are ored and the result is stored
420
    in dested.
421
*/
422
 
7 7u83 423
void
424
or(shape sha, where a1, where a2, where dest)
2 7u83 425
{
7 7u83 426
	andetc(ml_or, sha, a1, a2, dest, OR);
427
	return;
2 7u83 428
}
429
 
430
 
431
/*
432
    XOR INSTRUCTION
433
 
434
    The values a1 and a2 of shape sha are xored and the result is stored
435
    in dested.
436
*/
437
 
7 7u83 438
void
439
xor(shape sha, where a1, where a2, where dest)
2 7u83 440
{
7 7u83 441
	andetc(ml_eor, sha, a1, a2, dest, XOR);
442
	return;
2 7u83 443
}
444
 
445
 
446
/*
447
    LOGICAL NEGATION INSTRUCTION
448
 
449
    The value a of shape sha is logically negated and the result is stored
450
    in dest.
451
*/
452
 
7 7u83 453
void
454
not(shape sha, where a, where dest)
2 7u83 455
{
7 7u83 456
	int instr;
457
	long sz = shape_size(sha);
458
	long wha = whereis(a);
459
	long whd = whereis(dest);
2 7u83 460
 
7 7u83 461
	if (wha == Value) {
462
		long c = nw(a);
463
		move(sha, mnw(~c), dest);
464
		return;
465
	}
2 7u83 466
 
7 7u83 467
	if (eq_where(a, dest) && whd != Areg) {
468
		instr = ins(sz, ml_not);
469
		ins1(instr, sz, dest, 1);
470
		set_cond(dest, sz);
471
		return;
472
	}
2 7u83 473
 
7 7u83 474
	if (whd == Dreg) {
475
		move(sha, a, dest);
476
		not(sha, dest, dest);
477
		return;
478
	}
2 7u83 479
 
7 7u83 480
	if (wha == Dreg && last_use(a)) {
481
		not(sha, a, a);
482
		move(sha, a, dest);
483
		return;
484
	}
2 7u83 485
 
7 7u83 486
	move(sha, a, D0);
487
	not(sha, D0, D0);
488
	move(sha, D0, dest);
489
	return;
2 7u83 490
}
491
 
492
 
493
/*
494
    LOW LEVEL SHIFT
495
 
496
    This routine outputs a simple shift instruction, taking overflow
497
    into account if necessary (not right yet).
498
*/
499
 
7 7u83 500
static void
501
shift_it(shape sha, shape shb, int instr, where by, where to)
2 7u83 502
{
7 7u83 503
	long sz = shape_size(sha);
504
	ins2(instr, L8, sz, by, to, 1);
505
	have_cond = 0;
506
	test_overflow(ON_OVERFLOW);
507
	return;
2 7u83 508
}
509
 
510
 
511
/*
512
    AUXILIARY SHIFT ROUTINE
513
 
514
    The value from of shape sha is shifted, either left if sw is 0, or
515
    right otherwise, by the value by.  The result is stored in to.
516
    The dont_use_D1 flag indicates that register D1 should not be used.
517
    It is always false for simple shifts, but may be true for certain
518
    multiplications which are done by shifts.
519
*/
520
 
7 7u83 521
void
522
shift_aux(shape sha, where by, where from, where to, int sw, int dont_use_D1)
2 7u83 523
{
7 7u83 524
	where w;
525
	long whb, wht;
526
	int instr, shift_plus, shift_minus;
2 7u83 527
 
7 7u83 528
	shape shb = sh(by.wh_exp);
529
	long sz = shape_size(sha);
530
	bool sig = is_signed(sha);
2 7u83 531
 
7 7u83 532
	switch (sz) {
533
	case 8:
534
		shift_plus = (sig ? m_aslb : m_lslb);
535
		shift_minus = (sig ? m_asrb : m_lsrb);
536
		break;
537
	case 16:
538
		shift_plus = (sig ? m_aslw : m_lslw);
539
		shift_minus = (sig ? m_asrw : m_lsrw);
540
		break;
541
	default:
542
		shift_plus = (sig ? m_asll : m_lsll);
543
		shift_minus = (sig ? m_asrl : m_lsrl);
544
		break;
2 7u83 545
	}
7 7u83 546
 
547
	if (sw) {
548
		/* Switch shift_plus and shift_minus for right shifts */
549
		instr = shift_plus;
550
		shift_plus = shift_minus;
551
		shift_minus = instr;
2 7u83 552
	}
553
 
7 7u83 554
	whb = whereis(by);
555
	wht = whereis(to);
2 7u83 556
 
7 7u83 557
	if (whb == Value && !have_overflow()) {
558
		long p = nw(by);
559
		if (p == 0) {
560
			/* A shift by 0 is a move */
561
			move(sha, from, to);
562
			return;
563
		}
564
		/* Reduce mod 64 to emulate instruction */
565
		p &= 0x3f;
566
		instr = shift_plus;
567
		/* Do the shift, at most eight at a time */
568
		if (p <= 8 || D1_is_special || dont_use_D1) {
569
			w = (wht == Dreg ? to : D0);
570
			move(sha, from, w);
571
			while (p) {
572
				long q = (p > 8 ? 7 : p);
573
				ins2n(instr, q, sz, w, 1);
574
				p -= q;
575
			}
576
			have_cond = 0;
577
			move(sha, w, to);
578
			return;
579
		}
580
		/* Fall through otherwise */
581
		shb = slongsh;
2 7u83 582
	}
583
 
7 7u83 584
	if (wht == Dreg) {
585
		if (whb == Dreg && !eq_where(by, to)) {
586
			move(sha, from, to);
587
			shift_it(sha, shb, shift_plus, by, to);
588
			return;
589
		}
590
		if (eq_where(D0, to)) {
591
			w = D1;
592
			regsinproc |= regmsk(REG_D1);
593
		} else {
594
			w = D0;
595
		}
596
		move(shb, by, w);
597
		move(sha, from, to);
598
		shift_it(sha, shb, shift_plus, w, to);
599
		return;
2 7u83 600
	}
601
 
7 7u83 602
	if (whb == Dreg) {
603
		if (eq_where(D0, by)) {
604
			w = D1;
605
			regsinproc |= regmsk(REG_D1);
606
		} else {
607
			w = D0;
608
		}
609
		move(sha, from, w);
610
		shift_it(sha, shb, shift_plus, by, w);
611
		move(sha, w, to);
612
		return;
2 7u83 613
	}
614
 
7 7u83 615
	regsinproc |= regmsk(REG_D1);
616
	move(shb, by, D0);
617
	move(sha, from, D1);
618
	shift_it(sha, shb, shift_plus, D0, D1);
619
	move(sha, D1, to);
620
	return;
2 7u83 621
}
622
 
623
 
624
/*
625
    MAIN LEFT SHIFT ROUTINE
626
 
627
    The value from of shape sha is shifted left by the value by.  The
628
    result is stored in to.
629
*/
630
 
7 7u83 631
void
632
shift(shape sha, where by, where from, where to)
2 7u83 633
{
7 7u83 634
	shift_aux(sha, by, from, to, 0, 0);
635
	return;
2 7u83 636
}
637
 
638
 
639
/*
640
    MAIN RIGHT SHIFT ROUTINE
641
 
642
    The value from of shape sha is shifted right by the value by.  The
643
    result is stored in to.
644
*/
645
 
7 7u83 646
void
647
rshift(shape sha, where by, where from, where to)
2 7u83 648
{
7 7u83 649
	shift_aux(sha, by, from, to, 1, 0);
650
	return;
2 7u83 651
}
652
 
653
 
654
/*
655
    ADJUST AN EXPRESSION READY FOR A BITFIELD OPERATION
656
 
657
    The value in the no field of e is rounded down to a multiple of 32.
658
    The remainder is the bitfield offset and is returned.
659
*/
660
 
7 7u83 661
static long
662
adjust_bitf(exp e)
2 7u83 663
{
7 7u83 664
	long boff = no(e)% 32;
665
	no(e) -= boff;
666
	return (boff);
2 7u83 667
}
668
 
669
 
670
/*
671
    FIND POSITION OF A CONTENTS BITFIELD
672
*/
673
 
7 7u83 674
static long
675
contents_bitf(exp e)
2 7u83 676
{
7 7u83 677
	char n = name(e);
678
	if (n == name_tag || n == reff_tag) {
679
		return (adjust_bitf(e));
2 7u83 680
	}
7 7u83 681
	if (n == ident_tag) {
682
		exp s = son(e);
683
		exp b = bro(s);
684
		if (name(b) == reff_tag) {
685
			return (adjust_bitf(b));
686
		}
687
		if (name(b) == ident_tag) {
688
			return (contents_bitf(b));
689
		}
690
		if (name(b) == name_tag && son(b) == e &&
691
		    name(s) == name_tag) {
692
			return (contents_bitf(son(s)));
693
		}
694
		if (name(s) == name_tag) {
695
			return (adjust_bitf(s));
696
		}
697
	}
698
	error("Illegal bitfield operation");
699
	return (0);
2 7u83 700
}
701
 
702
 
703
/*
704
    FIND POSITION OF A BITFIELD OPERATION
705
*/
706
 
7 7u83 707
static long
708
bitf_posn(exp e)
2 7u83 709
{
7 7u83 710
	char n = name(e);
711
	if (n == name_tag) {
712
		return (adjust_bitf(e));
713
	}
714
	if (n == cont_tag || n == ass_tag) {
715
		return (bitf_posn(son(e)));
716
	}
717
	if (n == ident_tag) {
718
		return (0);
719
	}
720
	error("Illegal bitfield operation");
721
	return (0);
2 7u83 722
}
723
 
724
 
725
/*
726
    EXTRACT A BITFIELD
727
 
728
    The bitfield e of shape sha is extracted into dest.  The current state
729
    of the stack is also given.
730
*/
731
 
7 7u83 732
void
733
bitf_to_int(exp e, shape sha, where dest, ash stack)
2 7u83 734
{
7 7u83 735
	where bf, d;
736
	exp t = dest.wh_exp;
737
	shape dsha = sh(t);
2 7u83 738
 
7 7u83 739
	int extend = (is_signed(sha)? 1 : 0);
740
	int instr = (extend ? m_bfexts : m_bfextu);
2 7u83 741
 
7 7u83 742
	long off, sz, bstart;
743
	bitpattern pmask;
744
	long nbits = shape_size(sha);
745
	long boff = bitf_posn(e);
2 7u83 746
 
7 7u83 747
	off = 8 *(boff / 8);
748
	sz = 8 *((boff + nbits - 1) / 8) + 8 - off;
749
	if (sz == 24) {
750
		sz = 32;
751
		off -= 8;
752
	}
753
	bstart = boff - off;
2 7u83 754
 
7 7u83 755
	pmask = ((hi_bits[nbits]) >> bstart) >> (32 - sz);
2 7u83 756
 
7 7u83 757
	switch (name(t)) {
758
	case ident_tag:
759
		dsha = sh(son(t));
760
		break;
761
	case ass_tag:
762
		dsha = sh(bro(son(t)));
763
		break;
764
	}
765
	if (name(dsha) == bitfhd) {
766
		dsha = (extend ? slongsh : ulongsh);
767
	}
768
	if (name(dsha) == tophd) {
769
		warning("Top in bitfield assignment");
770
	}
2 7u83 771
 
7 7u83 772
	bf = mw(e, off);
2 7u83 773
 
7 7u83 774
	if (bstart == 0 && nbits == sz) {
775
		shape bsha;
776
		switch (sz) {
777
		case 8:
778
			bsha = scharsh;
779
			break;
780
		case 16:
781
			bsha = swordsh;
782
			break;
783
		case 32:
784
			bsha = slongsh;
785
			break;
786
		}
787
		change_var_sh(dsha, bsha, bf, dest);
788
		return;
2 7u83 789
	}
790
 
7 7u83 791
	if (whereis(bf) == Dreg) {
792
		bitpattern m = (lo_bits[nbits] <<  boff);
793
		d = (whereis(dest) == Dreg ? dest : D0);
794
		and(slongsh, bf, mnw(m), d);
795
		if (extend) {
796
			long r = 32 - nbits - boff;
797
			if (r) {
798
				if (r <= 8) {
799
					ins2n(m_lsll, r, L32, d, 1);
800
					ins2n(m_asrl, r, L32, d, 1);
801
				} else {
802
					regsinproc |= regmsk(REG_D1);
803
					ins2n(m_moveq, r, L32, D1, 1);
804
					ins2(m_lsll, L32, L32, D1, d, 1);
805
					ins2(m_asrl, L32, L32, D1, d, 1);
806
				}
807
			}
2 7u83 808
		}
7 7u83 809
		have_cond = 0;
810
		change_var_sh(dsha, slongsh, d, dest);
811
		return;
812
	} else {
813
		mach_op *op1, *op2;
814
		d = (whereis(dest) == Dreg ? dest : D0);
815
		op1 = operand(L32, bf);
816
		op1 = make_bitfield_op(op1,(int)bstart,(int)nbits);
817
		op2 = operand(L32, d);
818
		make_instr(instr, op1, op2, regs_changed(op2, 1));
819
		have_cond = 0;
820
		change_var_sh(dsha, slongsh, d, dest);
821
		return;
2 7u83 822
	}
823
}
824
 
825
 
826
/*
827
    INSERT A BITFIELD
828
 
829
    The value e is inserted into the bitfield d.  The state of the stack
830
    is also given.
831
*/
832
 
7 7u83 833
void
834
int_to_bitf(exp e, exp d, ash stack)
2 7u83 835
{
7 7u83 836
	shape sha;
837
	where dest, f;
2 7u83 838
 
7 7u83 839
	long off, sz, bstart, bend;
840
	bitpattern pmask, nmask, v;
841
	long nbits = shape_size(sh(e));
842
	long boff = bitf_posn(d);
2 7u83 843
 
7 7u83 844
	off = 8 *(boff / 8);
845
	sz = 8 *((boff + nbits - 1) / 8) + 8 - off;
846
	if (sz == 24) {
847
		sz = 32;
848
		off -= 8;
849
	}
850
	bstart = boff - off;
851
	bend = sz - nbits - bstart;
2 7u83 852
 
7 7u83 853
	pmask = ((hi_bits[nbits]) >> bstart) >> (32 - sz);
854
	nmask = ~pmask;
2 7u83 855
 
7 7u83 856
	switch (sz) {
857
	case 8:
858
		nmask &= 0xff;
859
		sha = scharsh;
860
		break;
861
	case 16:
862
		nmask &= 0xffff;
863
		sha = swordsh;
864
		break;
865
	default:
866
		sha = slongsh;
867
		break;
868
	}
2 7u83 869
 
7 7u83 870
	if (name(e) == int_to_bitf_tag) {
871
		exp s = son(e);
872
		if (is_o(name(s))) {
873
			e = s;
874
		} else {
875
			regsinproc |= regmsk(REG_D1);
876
			coder(D1, stack, s);
877
			if (shape_size(sh(s)) < 32) {
878
				warning("Think again!");
879
			}
880
			e = D1.wh_exp;
881
		}
2 7u83 882
	}
883
 
7 7u83 884
	dest = mw(d, off);
2 7u83 885
 
7 7u83 886
	if (bstart == 0 && nbits == sz) {
887
		change_var_sh(sha, sh(e), zw(e), dest);
888
		return;
889
	}
2 7u83 890
 
7 7u83 891
	if ((bstart + nbits > 32) || (name(e)!= val_tag)) {
892
		where dd;
893
		bitpattern ch;
894
		mach_op *op1, *op2;
895
		dd = zw(e);
896
		if (whereis(dd)!= Dreg || shape_size(sh(e))!= 32) {
897
			change_var_sh(slongsh, sh(e), dd, D0);
898
			dd = D0;
899
		}
900
		op1 = operand(L32, dd);
901
		op2 = operand(L32, dest);
902
		ch = regs_changed(op2, 1);
903
		op2 = make_bitfield_op(op2,(int)bstart,(int)nbits);
904
		make_instr(m_bfins, op1, op2, ch);
905
		have_cond = 0;
906
		return;
2 7u83 907
	}
908
 
7 7u83 909
	v = (bitpattern)no(e);
910
	v = ((v << bend) & pmask);
2 7u83 911
 
7 7u83 912
	if (v == 0) {
913
		and(sha, mnw(nmask), dest, dest);
914
		return;
915
	}
2 7u83 916
 
7 7u83 917
	if (v == pmask) {
918
		or(sha, mnw(pmask), dest, dest);
919
		return;
920
	}
2 7u83 921
 
7 7u83 922
	f = ((whereis(dest) == Dreg)? dest : D0);
923
	and(sha, mnw(nmask), dest, f);
924
	or(sha, mnw(v), f, dest);
925
	return;
2 7u83 926
}
927
 
928
 
929
/*
930
    TEST A NUMBER OF BITS
931
 
932
    The value a1 of shape sha is tested to see if the bits indicated by
933
    the value a2 are set.  If a2 is a constant power of 2 then a bit
934
    test operation is used.  Otherwise a1 is anded with a2 and the
935
    result is stored in an unwanted D-register.
936
*/
937
 
7 7u83 938
void
939
bit_test(shape sha, where a1, where a2)
2 7u83 940
{
7 7u83 941
	long sz = shape_size(sha);
942
	long wh1 = whereis(a1);
943
	long wh2 = whereis(a2);
944
	if (wh2 == Value) {
945
		if (wh1 == External || wh1 == Parameter || wh1 == RegInd) {
946
			long v = nw(a2);
947
			if (is_pow2(v)) {
948
				where w;
949
				long n = log2(v);
950
				long off = sz - 8 *(1 + (n / 8));
951
				w = mw(a1.wh_exp, a1.wh_off + off);
952
				ins2n(m_btstb, n % 8, 8, w, 1);
953
				have_cond = 0;
954
				return;
955
			}
956
		}
957
		if (wh1 == Dreg) {
958
			long v = nw(a2);
959
			if (last_use(a1)) {
960
				and(sha, a2, a1, a1);
961
				return;
962
			}
963
			if (is_pow2(v) && sz == 32) {
964
				long n = log2(v);
965
				ins2n(m_btstl, n, sz, a1, 1);
966
				have_cond = 0;
967
				return;
968
			}
969
		}
2 7u83 970
	}
7 7u83 971
	if (wh1 == Dreg && last_use(a1)) {
972
		and(sha, a2, a1, a1);
973
		return;
2 7u83 974
	}
7 7u83 975
	if (wh2 == Dreg && last_use(a2)) {
976
		and(sha, a1, a2, a2);
977
		return;
978
	}
979
	move(sha, a1, D0);
980
	and(sha, a2, D0, D0);
981
	return;
2 7u83 982
}