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