2 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3 * See the copyright notice in the ACK home directory, in the file "Copyright".
5 /* $Id: field.c,v 3.12 1994/06/24 12:03:48 ceriel Exp $ */
6 /* BITFIELD EXPRESSION EVALUATOR */
11 #include "nobitfield.h"
29 arith NewLocal(); /* util.c */
30 char *symbol2str(); /* symbol2str.c */
31 extern long full_mask[]; /* cstoper.c */
33 /* Eval_field() evaluates expressions involving bit fields.
34 The various instructions are not yet optimised in the expression
35 tree and are therefore dealt with in this function.
36 The actions taken at any operation are described clearly by the
37 code for this actions.
39 [1] the bitfields are packed in target machine integers!
40 [2] op is either an assignment operator or an increment/
42 [3] atype: the type in which the bitfield arithmetic is done;
43 and in which bitfields are stored!
45 eval_field(expr, code)
49 int op = expr->OP_OPER;
50 register struct expr *leftop = expr->OP_LEFT;
51 register struct expr *rightop = expr->OP_RIGHT;
52 register struct field *fd = leftop->ex_type->tp_field;
53 struct type *tp = leftop->ex_type->tp_up;
55 struct type *atype = tp->tp_unsigned ? uword_type : word_type;
56 arith asize = atype->tp_size;
58 /* First some assertions to be sure that the rest is legal */
59 ASSERT(asize == word_size); /* make sure that C_loc() is legal */
60 ASSERT(leftop->ex_type->tp_fund == FIELD);
61 leftop->ex_type = atype; /* this is cheating but it works... */
63 /* F = E: f = ((E & mask)<<shift) | (~(mask<<shift) & f) */
64 ASSERT(tp == rightop->ex_type);
65 EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL);
66 conversion(tp, atype);
71 C_loc((arith)fd->fd_shift);
72 if (atype->tp_unsigned)
76 C_loc(~((fd->fd_mask << fd->fd_shift) | ~full_mask[asize]));
77 if (leftop->ex_depth == 0) { /* simple case */
78 load_val(leftop, RVAL);
81 store_val(&(leftop->EX_VALUE), atype);
83 else { /* complex case */
84 tmpvar = NewLocal(pointer_size, pointer_align,
86 EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL);
88 StoreLocal(tmpvar, pointer_size);
92 LoadLocal(tmpvar, pointer_size);
97 else { /* treat ++F as F += 1 and --F as F -= 1 */
98 /* F op= e: f = (((((f>>shift)&mask) op e)&mask)<<shift)|
101 if (leftop->ex_depth == 0) /* simple case */
102 load_val(leftop, RVAL);
103 else { /* complex case */
104 tmpvar = NewLocal(pointer_size, pointer_align,
106 EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL);
108 StoreLocal(tmpvar, pointer_size);
111 if (atype->tp_unsigned) {
112 C_loc((arith)fd->fd_shift);
118 arith bits_in_type = asize * 8;
119 C_loc(bits_in_type - (fd->fd_width + fd->fd_shift));
121 C_loc(bits_in_type - fd->fd_width);
124 if (code == TRUE && (op == POSTINCR || op == POSTDECR))
126 conversion(atype, rightop->ex_type);
127 EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL);
128 /* the 'op' operation: */
129 if (op == PLUSPLUS || op == POSTINCR)
130 assop(rightop->ex_type, PLUSAB);
132 if (op == MINMIN || op == POSTDECR)
133 assop(rightop->ex_type, MINAB);
135 assop(rightop->ex_type, op);
136 conversion(rightop->ex_type, atype);
139 if (code == TRUE && op != POSTINCR && op != POSTDECR)
141 C_loc((arith)fd->fd_shift);
142 if (atype->tp_unsigned)
146 C_loc(~((fd->fd_mask << fd->fd_shift) | ~full_mask[asize]));
147 if (leftop->ex_depth == 0) {
148 load_val(leftop, RVAL);
151 store_val(&(leftop->EX_VALUE), atype);
154 LoadLocal(tmpvar, pointer_size);
158 LoadLocal(tmpvar, pointer_size);
164 /* Take care that the effective value stored in
165 the bit field (i.e. the value that is got on
166 retrieval) is on top of stack.
168 if (atype->tp_unsigned == 0) { /* sign extension */
169 register arith shift = asize * 8 - fd->fd_width;
176 conversion(atype, expr->ex_type);
179 #endif /* NOBITFIELD */