Pristine Ack-5.5
[Ack-5.5.git] / lang / cem / cemcom / eval.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: eval.c,v 3.39 1994/06/24 12:03:33 ceriel Exp $ */
6 /* EXPRESSION-CODE GENERATOR */
7
8 #include        "lint.h"
9 #ifndef LINT
10
11 #include        "nofloat.h"
12 #include        <em.h>
13 #include        <em_reg.h>
14 #include        "debug.h"
15 #include        "nobitfield.h"
16 #include        "dataflow.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        "def.h"
24 #include        "expr.h"
25 #include        "sizes.h"
26 #include        "Lpars.h"
27 #include        "level.h"
28 #include        "stack.h"
29 #include        "align.h"
30 #include        "mes.h"
31 #include        "atw.h"
32 #include        "specials.h"
33
34 #define CRASH()         crash("EVAL: CRASH at line %u", __LINE__)
35
36 char *symbol2str();
37 char *long2str();
38 arith NewLocal();       /* util.c */
39 #define LocalPtrVar()   NewLocal(pointer_size, pointer_align, reg_pointer, REGISTER)
40
41 /*      EVAL() is the main expression-tree evaluator, which turns
42         any legal expression tree into EM code. Parameters:
43
44         struct expr *expr
45                 pointer to root of the expression tree to be evaluated
46
47         int val
48                 indicates whether the resulting expression is to be
49                 dereferenced (if val == RVAL and expr->ex_lvalue == 1)
50                 or not (val == LVAL).  The latter case indicates that
51                 the resulting expression is an lvalue expression which
52                 should not be dereferenced by EVAL
53         
54         int code
55                 indicates whether the expression tree must be turned
56                 into EM code or not. E.g. the expression statement "12;"
57                 delivers the expression "12" to EVAL while this should
58                 not result in any EM code
59         
60         label false_label, label true_label
61                 if the expression is a logical or relational expression
62                 and if the loop of the program depends on the resulting
63                 value then EVAL generates jumps to the specified program
64                 labels, in case they are specified (i.e. are non-zero)
65 */
66
67 EVAL(expr, val, code, true_label, false_label)
68         register struct expr *expr;
69         int val, code;
70         label true_label, false_label;
71 {
72         register int gencode = (code == TRUE && expr->ex_type->tp_size > 0);
73
74         switch (expr->ex_class) {
75         case Value:     /* just a simple value  */
76                 if (gencode) {
77                         if (true_label) {
78                                 /* can only result from ','-expressions with
79                                    constant right-hand sides ???
80                                 */
81                                 ASSERT(is_cp_cst(expr));
82                                 C_bra(expr->VL_VALUE == 0 ? false_label : true_label);
83                         }
84                         else load_val(expr, val);
85                 }
86                 break;
87         case String:    /* a string constant    */
88                 if (gencode) {
89                         string2pointer(expr);
90                         C_lae_dlb(expr->VL_LBL, expr->VL_VALUE);
91                 }
92                 break;
93 #ifndef NOFLOAT
94         case Float:     /* a floating constant  */
95                 if (gencode) {
96                         label datlab = data_label();
97                         
98                         C_df_dlb(datlab);
99                         C_rom_fcon(expr->FL_VALUE, expr->ex_type->tp_size);
100                         C_lae_dlb(datlab, (arith)0);
101                         C_loi(expr->ex_type->tp_size);
102                 }
103                 break;
104 #endif /* NOFLOAT */
105         case Oper:      /* compound expression  */
106         {
107                 int oper = expr->OP_OPER;
108                 register struct expr *left = expr->OP_LEFT;
109                 register struct expr *right = expr->OP_RIGHT;
110                 register struct type *tp = expr->OP_TYPE;
111
112                 if (tp->tp_fund == ERRONEOUS || (expr->ex_flags & EX_ERROR)) {
113                         /* stop immediately */
114                         break;
115                 }
116                 if (tp->tp_fund == VOID)
117                         gencode = 0;
118                 switch (oper) {
119                 case '+':
120                         /*      We have the following possibilities :
121                                 int + int, pointer + int, pointer + long,
122                                 long + long, double + double
123                         */
124                         EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
125                         EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
126                         if (gencode) {
127                                 switch (tp->tp_fund) {
128                                 case INT:
129                                 case LONG:
130                                         if (tp->tp_unsigned)
131                                                 C_adu(tp->tp_size);
132                                         else
133                                                 C_adi(tp->tp_size);
134                                         break;
135                                 case POINTER:
136                                         C_loc(right->ex_type->tp_size);
137                                         C_loc(pointer_size);
138                                         C_cuu();
139                                         C_ads(pointer_size);
140                                         break;
141 #ifndef NOFLOAT
142                                 case DOUBLE:
143                                         C_adf(tp->tp_size);
144                                         break;
145 #endif /* NOFLOAT */
146                                 default:
147                                         crash("bad type +");
148                                 }
149                         }
150                         break;
151                 case '-':
152                         if (left == 0) {        /* unary        */
153                                 EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
154                                 if (gencode) {
155                                         switch (tp->tp_fund) {
156                                         case INT:
157                                         case LONG:
158                                         case POINTER:
159                                                 C_ngi(tp->tp_size);
160                                                 break;
161 #ifndef NOFLOAT
162                                         case DOUBLE:
163                                                 C_ngf(tp->tp_size);
164                                                 break;
165 #endif /* NOFLOAT */
166                                         default:
167                                                 CRASH();
168                                         }
169                                 }
170                                 break;
171                         }
172                         /*      else binary; we have the following flavours:
173                                 int - int, pointer - int, pointer - long,
174                                 pointer - pointer, long - long, double - double
175                         */
176                         EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
177                         EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
178                         if (!gencode)
179                                 break;
180                         switch (tp->tp_fund) {
181                         case INT:
182                         case LONG:
183                                 if (tp->tp_unsigned)
184                                         C_sbu(tp->tp_size);
185                                 else
186                                         C_sbi(tp->tp_size);
187                                 break;
188                         case POINTER:
189                                 if (right->ex_type->tp_fund == POINTER)
190                                         C_sbs(pointer_size);
191                                 else {
192                                         C_ngi(right->ex_type->tp_size);
193                                         C_loc(right->ex_type->tp_size);
194                                         C_loc(pointer_size);
195                                         C_cuu();
196                                         C_ads(pointer_size);
197                                 }
198                                 break;
199 #ifndef NOFLOAT
200                         case DOUBLE:
201                                 C_sbf(tp->tp_size);
202                                 break;
203 #endif /* NOFLOAT */
204                         default:
205                                 crash("bad type -");
206                         }
207                         break;
208                 case '*':
209                         if (left == 0) { /* unary */
210                                 EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
211                                 if (gencode && right->ex_class == String) {
212                                         C_loi((arith)1);
213                                 }
214                         }
215                         else { /* binary */
216                                 EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
217                                 EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
218                                 if (gencode)
219                                         switch (tp->tp_fund) {
220                                         case INT:
221                                         case LONG:
222                                         case POINTER:
223                                                 if (tp->tp_unsigned)
224                                                         C_mlu(tp->tp_size);
225                                                 else
226                                                         C_mli(tp->tp_size);
227                                                 break;
228 #ifndef NOFLOAT
229                                         case DOUBLE:
230                                                 C_mlf(double_size);
231                                                 break;
232 #endif /* NOFLOAT */
233                                         default:
234                                                 crash("bad type *");
235                                         }
236                         }
237                         break;
238                 case '/':
239                         EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
240                         EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
241                         if (gencode)
242                                 switch (tp->tp_fund) {
243                                 case INT:
244                                 case LONG:
245                                 case POINTER:
246                                         if (tp->tp_unsigned)
247                                                 C_dvu(tp->tp_size);
248                                         else
249                                                 C_dvi(tp->tp_size);
250                                         break;
251 #ifndef NOFLOAT
252                                 case DOUBLE:
253                                         C_dvf(double_size);
254                                         break;
255 #endif /* NOFLOAT */
256                                 default:
257                                         crash("bad type /");
258                                 }
259                         break;
260                 case '%':
261                         EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
262                         EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
263                         ASSERT(tp->tp_fund==INT || tp->tp_fund==LONG);
264                         if (gencode)
265                                 if (tp->tp_unsigned)
266                                         C_rmu(tp->tp_size);
267                                 else
268                                         C_rmi(tp->tp_size);
269                         break;
270                 case LEFT:
271                         EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
272                         EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
273                         if (gencode)
274                                 if (tp->tp_unsigned)
275                                         C_slu(tp->tp_size);
276                                 else
277                                         C_sli(tp->tp_size);
278                         break;
279                 case RIGHT:
280                         EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
281                         EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
282                         if (gencode)
283                                 if (tp->tp_unsigned)
284                                         C_sru(tp->tp_size);
285                                 else
286                                         C_sri(tp->tp_size);
287                         break;
288                 case '<':
289                 case LESSEQ:
290                 case '>':
291                 case GREATEREQ:
292                 case EQUAL:
293                 case NOTEQUAL:
294                         EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
295                         EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
296                         if (gencode) {
297                                 /* The operands have the same type */
298                                 arith size = left->ex_type->tp_size;
299                                 
300                                 switch (tp->tp_fund) {
301                                 case INT:
302                                 case LONG:
303                                         if (left->ex_type->tp_unsigned)
304                                                 C_cmu(size);
305                                         else
306                                                 C_cmi(size);
307                                         break;
308 #ifndef NOFLOAT
309                                 case FLOAT: /* thought they were converted??? */
310                                 case DOUBLE:
311                                         C_cmf(size);
312                                         break;
313 #endif /* NOFLOAT */
314                                 case POINTER:
315                                         C_cmp();
316                                         break;
317                                 case ENUM:
318                                         C_cmi(size);
319                                         break;
320                                 default:
321                                         CRASH();
322                                 }
323                                 if (true_label != 0) {
324                                         compare(oper, true_label);
325                                         C_bra(false_label);
326                                 }
327                                 else {
328                                         truthvalue(oper);
329                                 }
330                         }
331                         break;
332                 case '&':
333                 case '|':
334                 case '^':
335                         /* both operands should have type int   */
336                         EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
337                         EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
338                         if (gencode) {
339                                 arith size = tp->tp_size;
340
341                                 if ((int)size < (int)word_size)
342                                         size = word_size;
343                                 switch (oper) {
344                                 case '&':
345                                         C_and(size);
346                                         break;
347                                 case '|':
348                                         C_ior(size);
349                                         break;
350                                 case '^':
351                                         C_xor(size);
352                                         break;
353                                 }
354                         }
355                         break;
356                 case '=': {
357                         int newcode = tp->tp_size > 0;  /* CJ */
358 #ifndef NOBITFIELD
359                         if (left->ex_type->tp_fund == FIELD) {
360                                 eval_field(expr, gencode);
361                                 break;
362                         }
363 #endif /* NOBITFIELD */
364                         EVAL(right, RVAL, newcode, NO_LABEL, NO_LABEL);
365                         if (gencode)
366                                 C_dup(ATW(tp->tp_size));
367                         if (left->ex_class != Value) {
368                                 EVAL(left, LVAL, newcode, NO_LABEL, NO_LABEL);
369                                 if (newcode)
370                                         store_block(tp->tp_size, tp->tp_align);
371                         }
372                         else if (newcode)
373                                 store_val(&(left->EX_VALUE), left->ex_type);
374                         }
375                         break;
376                 case PLUSAB:
377                 case MINAB:
378                 case TIMESAB:
379                 case DIVAB:
380                 case MODAB:
381                 case LEFTAB:
382                 case RIGHTAB:
383                 case ANDAB:
384                 case XORAB:
385                 case ORAB:
386                 case POSTINCR:
387                 case POSTDECR:
388                 case PLUSPLUS:
389                 case MINMIN:
390                 {
391                         arith tmp;
392                         int compl;      /* Complexity of left operand */
393                         int newcode = left->ex_type->tp_size > 0; /* CJ */
394                         int right_done = 0;
395 #ifndef NOBITFIELD
396                         if (left->ex_type->tp_fund == FIELD) {
397                                 eval_field(expr, gencode);
398                                 break;
399                         }
400 #endif /* NOBITFIELD */
401                         if (newcode && left->ex_class == Value) {
402                                 compl = 0; /* Value */
403                         }
404                         else if (left->ex_depth == 1 &&
405                             !(left->ex_flags & EX_SIDEEFFECTS)) {
406                                 compl = 1;
407                         }
408                         else    compl = 2;
409
410                         /* evaluate right-hand side first when possible,
411                            but not for POSTINCR or PLUSPLUS, because then
412                            we might miss a chance for increment instructions.
413                         */
414                         if (compl != 2 &&
415                             tp->tp_fund != POINTER &&
416                             (oper == PLUSAB || oper == TIMESAB ||
417                              oper == ANDAB || oper == XORAB || oper == ORAB)) {
418                                 right_done = 1;
419                                 EVAL(right, RVAL, newcode, NO_LABEL, NO_LABEL);
420                         }
421                         if (compl == 0) {
422                                 load_val(left, RVAL);
423                         }
424                         else
425                         if (compl == 1) {
426                                 EVAL(left, RVAL, newcode, NO_LABEL, NO_LABEL);
427                         }
428                         else {
429                                 EVAL(left, LVAL, newcode, NO_LABEL, NO_LABEL);
430                                 if (newcode) {
431                                         tmp = LocalPtrVar();
432                                         C_dup(pointer_size);
433                                         StoreLocal(tmp, pointer_size);
434                                         C_loi(left->ex_type->tp_size);
435                                 }
436                         }
437                         if (newcode) {
438                                 if (gencode && (oper == POSTINCR ||
439                                                 oper == POSTDECR))
440                                         C_dup(ATW(left->ex_type->tp_size));
441                                 conversion(left->ex_type, tp);
442                         }
443                         if (! right_done) {
444                                 EVAL(right, RVAL, newcode, NO_LABEL, NO_LABEL);
445                         }
446                         if (newcode) {
447                                 int dupval = gencode && oper != POSTINCR &&
448                                                 oper != POSTDECR;
449                                 assop(tp, oper);
450                                 conversion(tp, left->ex_type);
451                                 if (compl == 0) {
452                                         store_val(&(left->EX_VALUE),
453                                                 left->ex_type);
454                                         if (dupval) load_val(left, RVAL);
455                                 }
456                                 else if (compl == 1) {
457                                         EVAL(left, LVAL,1, NO_LABEL, NO_LABEL);
458                                         C_sti(left->ex_type->tp_size);
459                                         if (dupval) {
460                                                 EVAL(left, LVAL, 1, NO_LABEL,
461                                                         NO_LABEL);
462                                                 C_loi(left->ex_type->tp_size);
463                                         }
464                                 }
465                                 else {
466                                         LoadLocal(tmp, pointer_size);
467                                         C_sti(left->ex_type->tp_size);
468                                         if (dupval) {
469                                                 LoadLocal(tmp, pointer_size);
470                                                 C_loi(left->ex_type->tp_size);
471                                         }
472                                         FreeLocal(tmp);
473                                 }
474                         }
475                         break;
476                 }
477                 case '(':
478                 {
479                         register struct expr *ex;
480                         arith ParSize = (arith)0;
481                         label setjmp_label = 0;
482
483                         if (ISNAME(left)) {
484                                 if (left->VL_IDF->id_special == SP_SETJMP) {
485                                         label addr_label = data_label();
486
487                                         setjmp_label = text_label();
488                                         C_df_dlb(addr_label);
489                                         C_rom_ilb(setjmp_label);
490                                         C_lae_dlb(addr_label, (arith) 0);
491                                         C_loi(pointer_size);
492                                         ParSize += pointer_size;
493                                 }
494                         }
495                         if ((ex = right) != NILEXPR) {
496                                 /* function call with parameters*/
497                                 while ( ex->ex_class == Oper &&
498                                         ex->OP_OPER == PARCOMMA
499                                 ) {
500                                         register struct expr *rght = ex->OP_RIGHT;
501                                         EVAL(rght, RVAL,
502                                              rght->ex_type->tp_size > 0,
503                                                         NO_LABEL, NO_LABEL);
504                                         ParSize += ATW(rght->ex_type->tp_size);
505                                         ex = ex->OP_LEFT;
506                                 }
507                                 EVAL(ex, RVAL, ex->ex_type->tp_size > 0,
508                                                 NO_LABEL, NO_LABEL);
509                                 ParSize += ATW(ex->ex_type->tp_size);
510                         }
511                         if (ISNAME(left)) {
512                                 /* e.g., main() { (*((int (*)())0))(); } */
513                                 C_cal(left->VL_IDF->id_text);
514                                 if (setjmp_label) {
515                                         C_df_ilb(setjmp_label);
516                                 }
517 #ifdef  DATAFLOW
518                                 {       extern char options[];
519                                         if (options['d'])
520                                                 DfaCallFunction(
521                                                         left->VL_IDF->id_text);
522                                 }
523 #endif  /* DATAFLOW */
524                         }
525                         else {
526                                 EVAL(left, LVAL, TRUE, NO_LABEL, NO_LABEL);
527                                 C_cai();
528                         }
529                         /* remove parameters from stack */
530                         if (ParSize > (arith)0)
531                                 C_asp(ParSize);
532                         if (gencode) {
533                                 if (is_struct_or_union(tp->tp_fund)) {
534                                         C_lfr(pointer_size);
535                                         load_block(tp->tp_size, (int) word_size);
536                                 }
537                                 else
538                                         C_lfr(ATW(tp->tp_size));
539                         }
540                         break;
541                 }
542                 case '.':
543                         EVAL(left, LVAL, gencode, NO_LABEL, NO_LABEL);
544                         ASSERT(is_cp_cst(right));
545                         if (gencode)
546                                 C_adp(right->VL_VALUE);
547                         break;
548                 case ARROW:
549                         EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
550                         ASSERT(is_cp_cst(right));
551                         if (gencode)
552                                 C_adp(right->VL_VALUE);
553                         break;
554                 case ',':
555                         EVAL(left, RVAL, FALSE, NO_LABEL, NO_LABEL);
556                         EVAL(right, RVAL, gencode, true_label, false_label);
557                         break;
558                 case '~':
559                         EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
560                         if (gencode)
561                                 C_com(tp->tp_size);
562                         break;
563                 case '?':       /* must be followed by ':'      */
564                 {
565                         label l_true = text_label();
566                         label l_false = text_label();
567                         label l_end = text_label();
568
569                         EVAL(left, RVAL, TRUE, l_true, l_false);
570                         C_df_ilb(l_true);
571                         EVAL(right->OP_LEFT, RVAL, gencode, NO_LABEL, NO_LABEL);
572                         C_bra(l_end);
573                         C_df_ilb(l_false);
574                         EVAL(right->OP_RIGHT, RVAL, gencode, NO_LABEL, NO_LABEL);
575                         C_df_ilb(l_end);
576                         break;
577                 }
578                 case OR:
579                 case AND: {
580                         label l_false, l_true, l_maybe;
581
582                         l_maybe = text_label();
583                         if (true_label) {
584                                 l_false = false_label;
585                                 l_true = true_label;
586                         }
587                         else {
588                                 l_false = text_label();
589                                 l_true = gencode ? text_label(): l_false;
590                         }
591
592                         EVAL(left, RVAL, TRUE, oper == AND ? l_maybe : l_true,
593                                                oper == AND ? l_false : l_maybe);
594                         C_df_ilb(l_maybe);
595                         EVAL(right, RVAL, gencode, l_true, l_false);
596                         if (gencode && !true_label) {
597                                 label l_end = text_label();
598
599                                 C_df_ilb(l_true);
600                                 C_loc((arith)1);
601                                 C_bra(l_end);
602                                 C_df_ilb(l_false);
603                                 C_loc((arith)0);
604                                 C_df_ilb(l_end);
605                         }
606                         else {
607                                 if (! true_label) C_df_ilb(l_false);
608                         }
609                         }
610                         break;
611                 case '!':
612                         if (true_label == 0) {
613                                 EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
614                                 if (gencode) {
615                                         C_teq();
616                                 }
617                         }
618                         else
619                                 EVAL(right, RVAL, gencode, false_label,
620                                                                 true_label);
621                         break;
622                 case INT2INT:
623 #ifndef NOFLOAT
624                 case INT2FLOAT:
625                 case FLOAT2INT:
626                 case FLOAT2FLOAT:
627 #endif /* NOFLOAT */
628                         EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
629                         if (gencode)
630                                 conversion(right->ex_type, left->ex_type);
631                         break;
632                 default:
633                         crash("(EVAL) bad operator %s\n", symbol2str(oper));
634                 }
635                 /*      If the rvalue of the expression is required but
636                         only its lvalue is evaluated, its rvalue is
637                         loaded by the following statements:
638                 */
639                 if (gencode && val == RVAL && expr->ex_lvalue == 1)
640                         load_block(expr->ex_type->tp_size,
641                                 expr->ex_type->tp_align);
642                 break;
643         }
644         default:
645                 crash("(EVAL) bad expression class");
646         }
647 }
648
649 /*      compare() serves as an auxiliary function of EVAL       */
650 compare(relop, lbl)
651         int relop;
652         label lbl;
653 {
654         switch (relop) {
655         case '<':
656                 C_zlt(lbl);
657                 break;
658         case LESSEQ:
659                 C_zle(lbl);
660                 break;
661         case '>':
662                 C_zgt(lbl);
663                 break;
664         case GREATEREQ:
665                 C_zge(lbl);
666                 break;
667         case EQUAL:
668                 C_zeq(lbl);
669                 break;
670         case NOTEQUAL:
671                 C_zne(lbl);
672                 break;
673         default:
674                 CRASH();
675         }
676 }
677
678 /*      truthvalue() serves as an auxiliary function of EVAL    */
679 truthvalue(relop)
680         int relop;
681 {
682         switch (relop)  {
683         case '<':
684                 C_tlt();
685                 break;
686         case LESSEQ:
687                 C_tle();
688                 break;
689         case '>':
690                 C_tgt();
691                 break;
692         case GREATEREQ:
693                 C_tge();
694                 break;
695         case EQUAL:
696                 C_teq();
697                 break;
698         case NOTEQUAL:
699                 C_tne();
700                 break;
701         default:
702                 CRASH();
703         }
704 }
705
706
707 /*      assop() generates the opcode of an assignment operators op=     */
708 assop(type, oper)
709         register struct type *type;
710         int oper;
711 {
712         register arith size;
713         register uns = type->tp_unsigned;
714
715         if ((int)(size = type->tp_size) < (int)word_size)
716                 size = word_size;
717         switch (type->tp_fund) {
718         case CHAR:
719         case SHORT:
720         case INT:
721         case LONG:
722         case ENUM:
723                 switch (oper) {
724                 case PLUSAB:
725                 case PLUSPLUS:
726                 case POSTINCR:
727                         if (uns)
728                                 C_adu(size);
729                         else
730                                 C_adi(size);
731                         break;
732                 case MINAB:
733                 case MINMIN:
734                 case POSTDECR:
735                         if (uns)
736                                 C_sbu(size);
737                         else
738                                 C_sbi(size);
739                         break;
740                 case TIMESAB:
741                         if (uns)
742                                 C_mlu(size);
743                         else
744                                 C_mli(size);
745                         break;
746                 case DIVAB:
747                         if (uns)
748                                 C_dvu(size);
749                         else
750                                 C_dvi(size);
751                         break;
752                 case MODAB:
753                         if (uns)
754                                 C_rmu(size);
755                         else
756                                 C_rmi(size);
757                         break;
758                 case LEFTAB:
759                         if (uns)
760                                 C_slu(size);
761                         else
762                                 C_sli(size);
763                         break;
764                 case RIGHTAB:
765                         if (uns)
766                                 C_sru(size);
767                         else
768                                 C_sri(size);
769                         break;
770                 case ANDAB:
771                         C_and(size);
772                         break;
773                 case XORAB:
774                         C_xor(size);
775                         break;
776                 case ORAB:
777                         C_ior(size);
778                         break;
779                 }
780                 break;
781 #ifndef NOFLOAT
782         case FLOAT:
783         case DOUBLE:
784                 switch (oper) {
785                 case PLUSAB:
786                 case PLUSPLUS:
787                 case POSTINCR:
788                         C_adf(size);
789                         break;
790                 case MINAB:
791                 case MINMIN:
792                 case POSTDECR:
793                         C_sbf(size);
794                         break;
795                 case TIMESAB:
796                         C_mlf(size);
797                         break;
798                 case DIVAB:
799                         C_dvf(size);
800                         break;
801                 }
802                 break;
803 #endif /* NOFLOAT */
804         case POINTER:
805                 if (oper == MINAB || oper == MINMIN || oper == POSTDECR)
806                         C_ngi(size);
807                 C_loc(size);
808                 C_loc(pointer_size);
809                 C_cuu();
810                 C_ads(pointer_size);
811                 break;
812         case ERRONEOUS:
813                 break;
814         default:
815                 crash("(assop) bad type %s\n", symbol2str(type->tp_fund));
816         }
817 }
818
819 /*      store_val() generates code for a store operation.
820         There are four ways of storing data:
821         - into a global variable
822         - into an automatic local variable
823         - into a local static variable
824         - absolute addressing
825 */
826 store_val(vl, tp)
827         register struct value *vl;
828         struct type *tp;
829 {
830         arith size = tp->tp_size;
831         int tpalign = tp->tp_align;
832         int al_on_word;
833         register int inword;
834         register int indword;
835         arith val = vl->vl_value;
836
837         if (vl->vl_class == Const) {    /* absolute addressing */
838                 load_cst(val, pointer_size);
839                 store_block(size, tpalign);
840                 return;
841         }
842         al_on_word = (tpalign % word_align == 0);
843         if (!(inword = (size == word_size && al_on_word)))
844                 indword = (size == dword_size && al_on_word);
845         if (vl->vl_class == Name) {
846                 register struct idf *id = vl->vl_data.vl_idf;
847                 register struct def *df = id->id_def;
848
849                 if (df->df_level == L_GLOBAL) {
850                         if (inword)
851                                 C_ste_dnam(id->id_text, val);
852                         else
853                         if (indword)
854                                 C_sde_dnam(id->id_text, val);
855                         else {
856                                 C_lae_dnam(id->id_text, val);
857                                 store_block(size, tpalign);
858                         }
859                 }
860                 else {
861                         ASSERT(df->df_sc != STATIC);
862                         if (inword || indword)
863                                 StoreLocal(df->df_address + val, size);
864                         else {
865                                 AddrLocal(df->df_address + val);
866                                 store_block(size, tpalign);
867                         }
868                 }
869         }
870         else {  
871                 label dlb = vl->vl_data.vl_lbl;
872
873                 ASSERT(vl->vl_class == Label);
874                 if (inword)
875                         C_ste_dlb(dlb, val);
876                 else
877                 if (indword)
878                         C_sde_dlb(dlb, val);
879                 else {
880                         C_lae_dlb(dlb, val);
881                         store_block(size, tpalign);
882                 }
883         }
884 }
885
886
887 /*      load_val() generates code for stacking a certain value (from ex),
888         which can be obtained in one of the following ways:
889         - value from absolute addressed memory
890         - constant value
891         - function result
892         - global variable
893         - static variable
894         - local variable
895 */
896 load_val(expr, rlval)
897         register struct expr *expr; /* expression containing the value  */
898         int rlval;              /* generate either LVAL or RVAL         */
899 {
900         register struct type *tp = expr->ex_type;
901         int rvalue = (rlval == RVAL && expr->ex_lvalue != 0);
902         arith size = tp->tp_size;
903         int tpalign = tp->tp_align;
904         int al_on_word;
905         register int inword, indword;
906         register arith val = expr->VL_VALUE;
907
908         if (expr->VL_CLASS == Const) {
909                 if (rvalue) { /* absolute addressing */
910                         load_cst(val, pointer_size);
911                         load_block(size, tpalign);
912                 }
913                 else    /* integer, unsigned, long, enum etc    */
914                         load_cst(val, size);
915                 return;
916         }
917         if (rvalue) {
918                 al_on_word = (tpalign % word_align == 0);
919                 if (!(inword = (size == word_size && al_on_word)))
920                         indword = (size == dword_size && al_on_word);
921         }
922         if (expr->VL_CLASS == Label) {
923                 if (rvalue) {
924                         if (inword)
925                                 C_loe_dlb(expr->VL_LBL, val);
926                         else
927                         if (indword)
928                                 C_lde_dlb(expr->VL_LBL, val);
929                         else {
930                                 C_lae_dlb(expr->VL_LBL, val);
931                                 load_block(size, tpalign);
932                         }
933
934                 }
935                 else {
936                         C_lae_dlb(expr->VL_LBL, (arith)0);
937                         C_adp(val);
938                 }
939         }
940         else {
941                 register struct idf *id = expr->VL_IDF;
942                 register struct def *df = id->id_def;
943
944                 ASSERT(ISNAME(expr));
945                 if (df->df_type->tp_fund == FUNCTION) {
946                         /*      the previous statement tried to catch a function
947                                 identifier, which may be cast to a pointer to a
948                                 function.
949                                 ASSERT(!(rvalue)); ???
950                         */
951                         C_lpi(id->id_text);
952                 }
953                 else
954                 if (df->df_level == L_GLOBAL) {
955                         if (rvalue) {
956                                 if (inword)
957                                         C_loe_dnam(id->id_text, val);
958                                 else
959                                 if (indword)
960                                         C_lde_dnam(id->id_text, val);
961                                 else {
962                                         C_lae_dnam(id->id_text, val);
963                                         load_block(size, tpalign);
964                                 }
965                         }
966                         else {
967                                 C_lae_dnam(id->id_text, (arith)0);
968                                 C_adp(val);
969                         }
970                 }
971                 else {
972                         ASSERT(df->df_sc != STATIC);
973                         if (rvalue) {
974                                 if (inword || indword)
975                                         LoadLocal(df->df_address + val, size);
976                                 else {
977                                         AddrLocal(df->df_address + val);
978                                         load_block(size, tpalign);
979                                 }
980                         }
981                         else {
982                                 AddrLocal(df->df_address);
983                                 C_adp(val);
984                         }
985                 }
986         }
987 }
988
989 load_cst(val, siz)
990         arith val, siz;
991 {
992         if (siz <= word_size)
993                 C_loc(val);
994         else
995         if (siz == dword_size)
996                 C_ldc(val);
997         else {
998                 label datlab;
999
1000                 C_df_dlb(datlab = data_label());
1001                 C_rom_icon(long2str((long)val, 10), siz);
1002                 C_lae_dlb(datlab, (arith)0);
1003                 C_loi(siz);
1004         }
1005 }
1006
1007 #endif  /* LINT */
1008