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 1.11 1994/06/27 07:59:52 ceriel Exp $ */
6 /* BITFIELD EXPRESSION EVALUATOR */
11 #include "nobitfield.h"
17 #include <flt_arith.h>
30 arith NewLocal(); /* util.c */
31 extern arith 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
56 && fd->fd_width >= 8 * (int)word_size)
60 /* First some assertions to be sure that the rest is legal */
61 ASSERT(atype->tp_size == word_size); /* make sure that C_loc() is legal */
62 ASSERT(leftop->ex_type->tp_fund == FIELD);
63 leftop->ex_type = atype; /* this is cheating but it works... */
65 /* F = E: f = ((E & mask)<<shift) | (~(mask<<shift) & f) */
66 ASSERT(tp == rightop->ex_type);
67 EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL);
68 conversion(tp, atype);
69 store_field(fd, tp->tp_unsigned, code, leftop, (arith) 0);
71 else { /* treat ++F as F += 1 and --F as F -= 1 */
72 /* F op= e: f = (((((f>>shift)&mask) op e)&mask)<<shift)|
75 if (leftop->ex_depth == 0) /* simple case */
76 load_val(leftop, RVAL);
77 else { /* complex case */
78 tmpvar = NewLocal(pointer_size, pointer_align,
80 EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL);
82 StoreLocal(tmpvar, pointer_size);
85 if (tp->tp_unsigned) {
86 C_loc((arith)fd->fd_shift);
92 arith sft = (int)word_size * 8 - fd->fd_width;
93 C_loc(sft - fd->fd_shift);
98 if (code == TRUE && (op == POSTINCR || op == POSTDECR))
100 conversion(atype, rightop->ex_type);
101 EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL);
102 /* the 'op' operation: */
103 if (op == PLUSPLUS || op == POSTINCR)
104 assop(rightop->ex_type, PLUSAB);
106 if (op == MINMIN || op == POSTDECR)
107 assop(rightop->ex_type, MINAB);
109 assop(rightop->ex_type, op);
110 conversion(rightop->ex_type, atype);
111 store_field(fd, atype->tp_unsigned,
112 code == TRUE && op != POSTINCR && op != POSTDECR,
116 /* Take care that the effective value stored in
117 the bit field (i.e. the value that is got on
118 retrieval) is on top of stack.
120 if (tp->tp_unsigned == 0) { /* sign extension */
121 register arith shift = (int)word_size * 8 - fd->fd_width;
128 conversion(atype, expr->ex_type);
132 store_field(fd, uns, code, leftop, tmpvar)
133 register struct field *fd;
136 register struct expr *leftop;
143 C_loc((arith)fd->fd_shift);
148 C_loc(~((fd->fd_mask << fd->fd_shift) | ~full_mask[(int)word_size]));
149 if (leftop->ex_depth == 0) { /* simple case */
150 load_val(leftop, RVAL);
153 store_val(&(leftop->EX_VALUE), uns ? uword_type : word_type);
155 else { /* complex case */
157 tmpvar = NewLocal(pointer_size, pointer_align,
159 EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL);
160 StoreLocal(tmpvar, pointer_size);
162 LoadLocal(tmpvar, pointer_size);
166 LoadLocal(tmpvar, pointer_size);
171 #endif /* NOBITFIELD */