Pristine Ack-5.5
[Ack-5.5.git] / lang / cem / cemcom.ansi / field.c
1 /*
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".
4  */
5 /* $Id: field.c,v 1.11 1994/06/27 07:59:52 ceriel Exp $ */
6 /*      BITFIELD EXPRESSION EVALUATOR   */
7
8 #include        "lint.h"
9 #ifndef LINT
10
11 #include        "nobitfield.h"
12
13 #ifndef NOBITFIELD
14 #include        <em.h>
15 #include        <em_reg.h>
16 #include        "debug.h"
17 #include        <flt_arith.h>
18 #include        "arith.h"
19 #include        "type.h"
20 #include        "idf.h"
21 #include        "label.h"
22 #include        "code.h"
23 #include        "assert.h"
24 #include        "expr.h"
25 #include        "sizes.h"
26 #include        "align.h"
27 #include        "Lpars.h"
28 #include        "field.h"
29
30 arith NewLocal();               /* util.c       */
31 extern arith full_mask[];       /* cstoper.c    */
32
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.
38         Notes
39         [1]     the bitfields are packed in target machine integers!
40         [2]     op is either an assignment operator or an increment/
41                 decrement operator
42         [3]     atype: the type in which the bitfield arithmetic is done;
43                 and in which bitfields are stored!
44 */
45 eval_field(expr, code)
46         struct expr *expr;
47         int code;
48 {
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;
54         arith tmpvar = 0;
55         struct type *atype = ( tp->tp_unsigned
56                                 && fd->fd_width >= 8 * (int)word_size)
57                                     ? uword_type
58                                     : word_type;
59
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... */
64         if (op == '=') {
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);
70         }
71         else {          /* treat ++F as F += 1 and --F as F -= 1        */
72                 /*      F op= e: f = (((((f>>shift)&mask) op e)&mask)<<shift)|
73                                         (f&~(mask<<shift))
74                 */
75                 if (leftop->ex_depth == 0)      /* simple case  */
76                         load_val(leftop, RVAL);
77                 else    {                       /* complex case */
78                         tmpvar = NewLocal(pointer_size, pointer_align, 
79                                           reg_pointer, 0);
80                         EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL);
81                         C_dup(pointer_size);
82                         StoreLocal(tmpvar, pointer_size);
83                         C_loi(word_size);
84                 }
85                 if (tp->tp_unsigned) {
86                         C_loc((arith)fd->fd_shift);
87                         C_sru(word_size);
88                         C_loc(fd->fd_mask);
89                         C_and(word_size);
90                 }
91                 else {
92                         arith sft = (int)word_size * 8 - fd->fd_width;
93                         C_loc(sft - fd->fd_shift);
94                         C_sli(word_size);
95                         C_loc(sft);
96                         C_sri(word_size);
97                 }
98                 if (code == TRUE && (op == POSTINCR || op == POSTDECR))
99                         C_dup(word_size);
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);
105                 else
106                 if (op == MINMIN || op == POSTDECR)
107                         assop(rightop->ex_type, MINAB);
108                 else
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,
113                             leftop, tmpvar);
114         }
115         if (code == TRUE) {
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.
119                 */
120                 if (tp->tp_unsigned == 0) {     /* sign extension */
121                         register arith shift = (int)word_size * 8 - fd->fd_width;
122
123                         C_loc(shift);
124                         C_sli(word_size);
125                         C_loc(shift);
126                         C_sri(word_size);
127                 }
128                 conversion(atype, expr->ex_type);
129         }
130 }
131
132 store_field(fd, uns, code, leftop, tmpvar)
133         register struct field *fd;
134         int uns;
135         int code;
136         register struct expr *leftop;
137         arith tmpvar;
138 {
139         C_loc(fd->fd_mask);
140         C_and(word_size);
141         if (code == TRUE)
142                 C_dup(word_size);
143         C_loc((arith)fd->fd_shift);
144         if (uns)
145                 C_slu(word_size);
146         else
147                 C_sli(word_size);
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);
151                 C_and(word_size);
152                 C_ior(word_size);
153                 store_val(&(leftop->EX_VALUE), uns ? uword_type : word_type);
154         }
155         else    {                       /* complex case */
156                 if (! tmpvar) {
157                         tmpvar = NewLocal(pointer_size, pointer_align, 
158                                   reg_pointer, 0);
159                         EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL);
160                         StoreLocal(tmpvar, pointer_size);
161                 }
162                 LoadLocal(tmpvar, pointer_size);
163                 C_loi(word_size);
164                 C_and(word_size);
165                 C_ior(word_size);
166                 LoadLocal(tmpvar, pointer_size);
167                 C_sti(word_size);
168                 FreeLocal(tmpvar);
169         }
170 }
171 #endif /* NOBITFIELD */
172
173 #endif  /* LINT */
174