Pristine Ack-5.5
[Ack-5.5.git] / lang / cem / cemcom / 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 3.12 1994/06/24 12:03:48 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        "arith.h"
18 #include        "type.h"
19 #include        "idf.h"
20 #include        "label.h"
21 #include        "code.h"
22 #include        "assert.h"
23 #include        "expr.h"
24 #include        "sizes.h"
25 #include        "align.h"
26 #include        "Lpars.h"
27 #include        "field.h"
28
29 arith NewLocal();               /* util.c       */
30 char *symbol2str();             /* symbol2str.c */
31 extern long 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;
55         struct type *atype = tp->tp_unsigned ? uword_type : word_type;
56         arith asize = atype->tp_size;
57
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... */
62         if (op == '=') {
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);
67                 C_loc(fd->fd_mask);
68                 C_and(asize);
69                 if (code == TRUE)
70                         C_dup(asize);
71                 C_loc((arith)fd->fd_shift);
72                 if (atype->tp_unsigned)
73                         C_slu(asize);
74                 else
75                         C_sli(asize);
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);
79                         C_and(asize);
80                         C_ior(asize);
81                         store_val(&(leftop->EX_VALUE), atype);
82                 }
83                 else    {                       /* complex case */
84                         tmpvar = NewLocal(pointer_size, pointer_align, 
85                                           reg_pointer, 0);
86                         EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL);
87                         C_dup(pointer_size);
88                         StoreLocal(tmpvar, pointer_size);
89                         C_loi(asize);
90                         C_and(asize);
91                         C_ior(asize);
92                         LoadLocal(tmpvar, pointer_size);
93                         C_sti(asize);
94                         FreeLocal(tmpvar);
95                 }
96         }
97         else {          /* treat ++F as F += 1 and --F as F -= 1        */
98                 /*      F op= e: f = (((((f>>shift)&mask) op e)&mask)<<shift)|
99                                         (f&~(mask<<shift))
100                 */
101                 if (leftop->ex_depth == 0)      /* simple case  */
102                         load_val(leftop, RVAL);
103                 else    {                       /* complex case */
104                         tmpvar = NewLocal(pointer_size, pointer_align, 
105                                           reg_pointer, 0);
106                         EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL);
107                         C_dup(pointer_size);
108                         StoreLocal(tmpvar, pointer_size);
109                         C_loi(asize);
110                 }
111                 if (atype->tp_unsigned) {
112                         C_loc((arith)fd->fd_shift);
113                         C_sru(asize);
114                         C_loc(fd->fd_mask);
115                         C_and(asize);
116                 }
117                 else {
118                         arith bits_in_type = asize * 8;
119                         C_loc(bits_in_type - (fd->fd_width + fd->fd_shift));
120                         C_sli(asize);
121                         C_loc(bits_in_type - fd->fd_width);
122                         C_sri(asize);
123                 }
124                 if (code == TRUE && (op == POSTINCR || op == POSTDECR))
125                         C_dup(asize);
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);
131                 else
132                 if (op == MINMIN || op == POSTDECR)
133                         assop(rightop->ex_type, MINAB);
134                 else
135                         assop(rightop->ex_type, op);
136                 conversion(rightop->ex_type, atype);
137                 C_loc(fd->fd_mask);
138                 C_and(asize);
139                 if (code == TRUE && op != POSTINCR && op != POSTDECR)
140                         C_dup(asize);
141                 C_loc((arith)fd->fd_shift);
142                 if (atype->tp_unsigned)
143                         C_slu(asize);
144                 else
145                         C_sli(asize);
146                 C_loc(~((fd->fd_mask << fd->fd_shift) | ~full_mask[asize]));
147                 if (leftop->ex_depth == 0)      {
148                         load_val(leftop, RVAL);
149                         C_and(asize);
150                         C_ior(asize);
151                         store_val(&(leftop->EX_VALUE), atype);
152                 }
153                 else    {
154                         LoadLocal(tmpvar, pointer_size);
155                         C_loi(asize);
156                         C_and(asize);
157                         C_ior(asize);
158                         LoadLocal(tmpvar, pointer_size);
159                         C_sti(asize);
160                         FreeLocal(tmpvar);
161                 }
162         }
163         if (code == TRUE) {
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.
167                 */
168                 if (atype->tp_unsigned == 0) {  /* sign extension */
169                         register arith shift = asize * 8 - fd->fd_width;
170
171                         C_loc(shift);
172                         C_sli(asize);
173                         C_loc(shift);
174                         C_sri(asize);
175                 }
176                 conversion(atype, expr->ex_type);
177         }
178 }
179 #endif /* NOBITFIELD */
180
181 #endif  /* LINT */
182