123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- /*
- * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
- * See the copyright notice in the ACK home directory, in the file "Copyright".
- */
- /* $Id$ */
- /* BITFIELD EXPRESSION EVALUATOR */
- #include "lint.h"
- #ifndef LINT
- #include "nobitfield.h"
- #ifndef NOBITFIELD
- #include <em.h>
- #include <em_reg.h>
- #include "debug.h"
- #include "arith.h"
- #include "type.h"
- #include "idf.h"
- #include "label.h"
- #include "code.h"
- #include "assert.h"
- #include "expr.h"
- #include "sizes.h"
- #include "align.h"
- #include "Lpars.h"
- #include "field.h"
- arith NewLocal(); /* util.c */
- char *symbol2str(); /* symbol2str.c */
- extern long full_mask[]; /* cstoper.c */
- /* Eval_field() evaluates expressions involving bit fields.
- The various instructions are not yet optimised in the expression
- tree and are therefore dealt with in this function.
- The actions taken at any operation are described clearly by the
- code for this actions.
- Notes
- [1] the bitfields are packed in target machine integers!
- [2] op is either an assignment operator or an increment/
- decrement operator
- [3] atype: the type in which the bitfield arithmetic is done;
- and in which bitfields are stored!
- */
- eval_field(expr, code)
- struct expr *expr;
- int code;
- {
- int op = expr->OP_OPER;
- register struct expr *leftop = expr->OP_LEFT;
- register struct expr *rightop = expr->OP_RIGHT;
- register struct field *fd = leftop->ex_type->tp_field;
- struct type *tp = leftop->ex_type->tp_up;
- arith tmpvar;
- struct type *atype = tp->tp_unsigned ? uword_type : word_type;
- arith asize = atype->tp_size;
- /* First some assertions to be sure that the rest is legal */
- ASSERT(asize == word_size); /* make sure that C_loc() is legal */
- ASSERT(leftop->ex_type->tp_fund == FIELD);
- leftop->ex_type = atype; /* this is cheating but it works... */
- if (op == '=') {
- /* F = E: f = ((E & mask)<<shift) | (~(mask<<shift) & f) */
- ASSERT(tp == rightop->ex_type);
- EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL);
- conversion(tp, atype);
- C_loc(fd->fd_mask);
- C_and(asize);
- if (code == TRUE)
- C_dup(asize);
- C_loc((arith)fd->fd_shift);
- if (atype->tp_unsigned)
- C_slu(asize);
- else
- C_sli(asize);
- C_loc(~((fd->fd_mask << fd->fd_shift) | ~full_mask[asize]));
- if (leftop->ex_depth == 0) { /* simple case */
- load_val(leftop, RVAL);
- C_and(asize);
- C_ior(asize);
- store_val(&(leftop->EX_VALUE), atype);
- }
- else { /* complex case */
- tmpvar = NewLocal(pointer_size, pointer_align,
- reg_pointer, 0);
- EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL);
- C_dup(pointer_size);
- StoreLocal(tmpvar, pointer_size);
- C_loi(asize);
- C_and(asize);
- C_ior(asize);
- LoadLocal(tmpvar, pointer_size);
- C_sti(asize);
- FreeLocal(tmpvar);
- }
- }
- else { /* treat ++F as F += 1 and --F as F -= 1 */
- /* F op= e: f = (((((f>>shift)&mask) op e)&mask)<<shift)|
- (f&~(mask<<shift))
- */
- if (leftop->ex_depth == 0) /* simple case */
- load_val(leftop, RVAL);
- else { /* complex case */
- tmpvar = NewLocal(pointer_size, pointer_align,
- reg_pointer, 0);
- EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL);
- C_dup(pointer_size);
- StoreLocal(tmpvar, pointer_size);
- C_loi(asize);
- }
- if (atype->tp_unsigned) {
- C_loc((arith)fd->fd_shift);
- C_sru(asize);
- C_loc(fd->fd_mask);
- C_and(asize);
- }
- else {
- arith bits_in_type = asize * 8;
- C_loc(bits_in_type - (fd->fd_width + fd->fd_shift));
- C_sli(asize);
- C_loc(bits_in_type - fd->fd_width);
- C_sri(asize);
- }
- if (code == TRUE && (op == POSTINCR || op == POSTDECR))
- C_dup(asize);
- conversion(atype, rightop->ex_type);
- EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL);
- /* the 'op' operation: */
- if (op == PLUSPLUS || op == POSTINCR)
- assop(rightop->ex_type, PLUSAB);
- else
- if (op == MINMIN || op == POSTDECR)
- assop(rightop->ex_type, MINAB);
- else
- assop(rightop->ex_type, op);
- conversion(rightop->ex_type, atype);
- C_loc(fd->fd_mask);
- C_and(asize);
- if (code == TRUE && op != POSTINCR && op != POSTDECR)
- C_dup(asize);
- C_loc((arith)fd->fd_shift);
- if (atype->tp_unsigned)
- C_slu(asize);
- else
- C_sli(asize);
- C_loc(~((fd->fd_mask << fd->fd_shift) | ~full_mask[asize]));
- if (leftop->ex_depth == 0) {
- load_val(leftop, RVAL);
- C_and(asize);
- C_ior(asize);
- store_val(&(leftop->EX_VALUE), atype);
- }
- else {
- LoadLocal(tmpvar, pointer_size);
- C_loi(asize);
- C_and(asize);
- C_ior(asize);
- LoadLocal(tmpvar, pointer_size);
- C_sti(asize);
- FreeLocal(tmpvar);
- }
- }
- if (code == TRUE) {
- /* Take care that the effective value stored in
- the bit field (i.e. the value that is got on
- retrieval) is on top of stack.
- */
- if (atype->tp_unsigned == 0) { /* sign extension */
- register arith shift = asize * 8 - fd->fd_width;
- C_loc(shift);
- C_sli(asize);
- C_loc(shift);
- C_sri(asize);
- }
- conversion(atype, expr->ex_type);
- }
- }
- #endif /* NOBITFIELD */
- #endif /* LINT */
|