1: // Copyright (C) 1985-1998 by Symantec
2: // Copyright (C) 2000-2011 by Digital Mars
3: // All Rights Reserved
4: // http://www.digitalmars.com
5: // Written by Walter Bright
6: /*
7: * This source file is made available for personal use
8: * only. The license is in /dmd/src/dmd/backendlicense.txt
9: * or /dm/src/dmd/backendlicense.txt
10: * For any other uses, please contact Digital Mars.
11: */
12:
13: #if !SPP
14:
15: #include <math.h>
16: #include <stdlib.h>
17: #include <stdio.h>
18: #include <string.h>
19: #include <float.h>
20: #include <time.h>
21:
22: #if !defined(__OpenBSD__) && !defined(_MSC_VER)
23: // Mysteriously missing from OpenBSD
24: #include <fenv.h>
25: #endif
26:
27: #if __DMC__
28: #include <fp.h>
29: #endif
30:
31: #if __FreeBSD__ || __OpenBSD__
32: #define fmodl fmod
33: #endif
34:
35: #include "cc.h"
36: #include "oper.h" /* OPxxxx definitions */
37: #include "global.h"
38: #include "el.h"
39: #include "type.h"
40: #include "root.h"
41:
42: #if SCPP
43: #include "parser.h"
44: #include "cpp.h"
45: #endif
46:
47: static char __file__[] = __FILE__; /* for tassert.h */
48: #include "tassert.h"
49:
50: extern void error(const char *filename, unsigned linnum, const char *format, ...);
51:
52: #if linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4
53: int _status87()
54: {
55: return fetestexcept(FE_ALL_EXCEPT);
56: }
57:
58: void _clear87()
59: {
60: feclearexcept(FE_ALL_EXCEPT);
61: }
62: #endif
63:
64: CEXTERN elem * evalu8(elem *);
65:
66: /* When this !=0, we do constant folding on floating point constants
67: * even if they raise overflow, underflow, invalid, etc. exceptions.
68: */
69:
70: static int ignore_exceptions;
71:
72: /* When this is !=0, we try to fold out OPsizeof expressions.
73: */
74:
75: static int resolve_sizeof;
76:
77: /************************************
78: * Helper to do % for long doubles.
79: */
80:
81: #if __DMC__
82: long double _modulo(long double x, long double y)
83: { short sw;
84:
85: __asm
86: {
87: fld tbyte ptr y
88: fld tbyte ptr x // ST = x, ST1 = y
89: FM1: // We don't use fprem1 because for some inexplicable
90: // reason we get -5 when we do _modulo(15, 10)
91: fprem // ST = ST % ST1
92: fstsw word ptr sw
93: fwait
94: mov AH,byte ptr sw+1 // get msb of status word in AH
95: sahf // transfer to flags
96: jp FM1 // continue till ST < ST1
97: fstp ST(1) // leave remainder on stack
98: }
99: }
100: #endif
101:
102: /**********************
103: * Return boolean result of constant elem.
104: */
105:
106: HINT boolres(elem *e)
107: { int b;
108:
109: //printf("boolres()\n");
110: //elem_print(e);
111: elem_debug(e);
112: // assert((_status87() & 0x3800) == 0);
113: switch (e->Eoper)
114: {
115: case OPrelconst:
116: case OPstring:
117: return TRUE;
118:
119: #if SCPP
120: case OPvar:
121: assert(CPP && PARSER);
122: el_toconst(e);
123: assert(e->Eoper == OPconst);
124: #endif
125: case OPconst:
126: switch (tybasic(typemask(e)))
127: { case TYchar:
128: case TYuchar:
129: case TYschar:
130: case TYchar16:
131: case TYshort:
132: case TYushort:
133: case TYint:
134: case TYuint:
135: case TYbool:
136: case TYwchar_t:
137: case TYenum:
138: case TYmemptr:
139: case TYlong:
140: case TYulong:
141: case TYdchar:
142: case TYllong:
143: case TYullong:
144: #if TX86
145: #if JHANDLE
146: case TYjhandle:
147: #endif
148: //case TYnullptr:
149: case TYnptr:
150: case TYsptr:
151: case TYcptr:
152: case TYhptr:
153: #endif
154: case TYfptr:
155: case TYvptr:
156: b = el_tolong(e) != 0;
157: break;
158: case TYfloat:
159: case TYifloat:
160: case TYdouble:
161: case TYidouble:
162: case TYdouble_alias:
163: case TYildouble:
164: case TYldouble:
165: { targ_ldouble ld = el_toldouble(e);
166:
167: if (isnan((double)ld))
168: b = 1;
169: else
170: b = (ld != 0);
171: break;
172: }
173: case TYcfloat:
174: if (isnan(e->EV.Vcfloat.re) || isnan(e->EV.Vcfloat.im))
175: b = 1;
176: else
177: b = e->EV.Vcfloat.re != 0 || e->EV.Vcfloat.im != 0;
178: break;
179: case TYcdouble:
180: if (isnan(e->EV.Vcdouble.re) || isnan(e->EV.Vcdouble.im))
181: b = 1;
182: else
183: b = e->EV.Vcdouble.re != 0 || e->EV.Vcdouble.im != 0;
184: break;
185: case TYcldouble:
186: if (isnan(e->EV.Vcldouble.re) || isnan(e->EV.Vcldouble.im))
187: b = 1;
188: else
189: b = e->EV.Vcldouble.re != 0 || e->EV.Vcldouble.im != 0;
190: break;
191: case TYstruct: // happens on syntax error of (struct x)0
192: #if SCPP
193: assert(errcnt);
194: #else
195: assert(0);
196: #endif
197: case TYvoid: /* happens if we get syntax errors or
198: on RHS of && || expressions */
199: b = 0;
200: break;
201:
202: case TYcent:
203: case TYucent:
204: b = e->EV.Vcent.lsw || e->EV.Vcent.msw;
205: break;
206:
207: default:
208: #ifdef DEBUG
209: WRTYxx(typemask(e));
210: #endif
211: assert(0);
212: }
213: break;
214: default:
215: assert(0);
216: }
217: return b;
218: }
219:
220: /***************************
221: * Return TRUE if expression will always evaluate to TRUE.
222: */
223:
224: HINT iftrue(elem *e)
225: {
226: while (1)
227: {
228: assert(e);
229: elem_debug(e);
230: switch (e->Eoper)
231: { case OPcomma:
232: case OPinfo:
233: e = e->E2;
234: break;
235: case OPrelconst:
236: case OPconst:
237: case OPstring:
238: return boolres(e);
239: default:
240: return FALSE;
241: }
242: }
243: }
244:
245: /***************************
246: * Return TRUE if expression will always evaluate to FALSE.
247: */
248:
249: HINT iffalse(elem *e)
250: {
251: while (1)
252: { assert(e);
253: elem_debug(e);
254: switch (e->Eoper)
255: { case OPcomma:
256: case OPinfo:
257: e = e->E2;
258: break;
259: case OPconst:
260: return !boolres(e);
261: //case OPstring:
262: //case OPrelconst:
263: default:
264: return FALSE;
265: }
266: }
267: }
268:
269: /******************************
270: * Constant fold expression tree.
271: * Calculate &symbol and &*e1 if we can.
272: */
273:
274: #if SCPP
275:
276: elem *poptelem2(elem *e)
277: {
278: // Same as poptelem(), but we ignore floating point exceptions
279: ignore_exceptions++;
280: e = poptelem(e);
281: ignore_exceptions--;
282: return e;
283: }
284:
285: elem *poptelem3(elem *e)
286: {
287: resolve_sizeof++;
288: e = poptelem(e);
289: resolve_sizeof--;
290: return e;
291: }
292:
293: elem *poptelem4(elem *e)
294: {
295: resolve_sizeof++;
296: ignore_exceptions++;
297: e = poptelem(e);
298: ignore_exceptions--;
299: resolve_sizeof--;
300: return e;
301: }
302:
303: elem *poptelem(elem *e)
304: {
305: elem *e1,*e2;
306: unsigned op;
307:
308: //dbg_printf("poptelem(e = %p)\n", e); elem_print(e);
309: #ifdef DEBUG
310: assert(PARSER);
311: assert(e && e->ET);
312:
313: if (controlc_saw)
314: exit(1);
315: // static int xxx; if (++xxx == 1000) *(char *)0 = 0;
316: #endif
317: elem_debug(e);
318: type_debug(e->ET);
319:
320: op = e->Eoper;
321:
322: #ifdef DEBUG
323: if (OTunary(op))
324: assert(!e->E2 || op == OPinfo);
325: #endif
326:
327: switch (op)
328: {
329: case OPvar:
330: if (CPP && e->EV.sp.Vsym->Sflags & SFLvalue)
331: el_toconst(e);
332: break;
333:
334: case OPsizeof:
335: if (resolve_sizeof)
336: {
337: e->Eoper = OPconst;
338: e->EV.Vlong = type_size(e->EV.sp.Vsym->Stype);
339: }
340: break;
341:
342: case OPconst:
343: case OPrelconst:
344: case OPstring:
345: break;
346:
347: case OPaddr:
348: e1 = e->E1;
349: if (e1->Eoper == OPvar)
350: goto L3;
351: e->E1 = e1 = poptelem(e1);
352: if (e1->Eoper == OPind) /* if &*exp */
353: { type *t;
354:
355: L6:
356: t = e->ET;
357: e1->E1 = cast(e1->E1,t);
358: e = selecte1(selecte1(e,t),t);
359: }
360: else if (e1->Eoper == OPvar)
361: { /* convert &var to relconst */
362: L3:
363: e = selecte1(e,e->ET);
364: e->Eoper = OPrelconst;
365: #if 1
366: // If this is an address of a function template,
367: // try to expand the template if it's got an explicit
368: // parameter list.
369: if (e->PEFflags & PEFtemplate_id)
370: { symbol *s;
371:
372: s = e->EV.sp.Vsym;
373: s = cpp_lookformatch(s, NULL, NULL,NULL,NULL,NULL,
374: e->EV.sp.spu.Vtal, 1|8, NULL, NULL);
375: if (s)
376: {
377: e->EV.sp.Vsym = s;
378: param_free(&e->EV.sp.spu.Vtal);
379: e->PEFflags &= ~PEFtemplate_id;
380: type_settype(&e->ET, newpointer(s->Stype));
381: }
382: }
383: #endif
384: }
385: break;
386: case OPind:
387: e->E1 = e1 = poptelem(e->E1);
388: #if TX86
389: if (e1->Eoper == OPrelconst)
390: { /* convert *(&var) to var */
391:
392: e = selecte1(e,e->ET);
393: e->Eoper = OPvar;
394: }
395: #else
396: if (e1->Eoper == OPrelconst)
397: {
398: unsigned to_sz = tysize(tym_conv(e->ET));
399: unsigned frm_sz = tysize(tym_conv(e1->ET));
400:
401: if (tyfunc(tybasic(e->ET->Tty)))
402: to_sz = LONGSIZE;
403: else if (tybasic(e->ET->Tty) == TYstruct || tybasic(e->ET->Tty) == TYarray)
404: {
405: to_sz = LONGSIZE;
406: e1->ET = e->ET;
407: }
408: if(to_sz == frm_sz)
409: { /* convert *(&var) to var */
410: doit:
411: e = selecte1(e,e->ET);
412: e->Eoper = OPvar;
413: }
414: else /* handle the most common cases for now */
415: { unsigned offset = e1->Eoffset;
416: switch(to_sz)
417: {
418: case SHORTSIZE:
419: if (frm_sz == LONGSIZE && (offset%LONGSIZE) == SHORTSIZE)
420: goto doit;
421: break;
422: case CHARSIZE:
423: if (frm_sz == LONGSIZE &&
424: offset%(LONGSIZE-CHARSIZE) == CHARSIZE)
425: goto doit;
426: if (frm_sz == SHORTSIZE && offset&1)
427: goto doit;
428: break;
429: }
430: }
431: }
432: #endif
433: break;
434: #if TX86
435: case OPptrlptr:
436: e->E1 = e1 = poptelem(e->E1);
437: // If casting a non-NULL constant pointer
438: if (e1->Eoper == OPconst && el_tolong(e1) != 0)
439: break;
440: goto L5;
441: case OPoffset:
442: e->E1 = e1 = poptelem(e->E1);
443: if (e1->Eoper == OPptrlptr)
444: goto L6;
445: goto L5;
446: #endif
447: case OPlngsht:
448: e->E1 = e1 = poptelem(e->E1);
449: L5:
450: if (e1->Eoper == OPrelconst || e1->Eoper == OPstring)
451: e = selecte1(e,e->ET);
452: else
453: goto eval;
454: break;
455: case OPandand:
456: e->E1 = e1 = poptelem(e->E1);
457: if (iffalse(e1))
458: goto L2;
459: else
460: goto def;
461: case OPoror:
462: e->E1 = e1 = poptelem(e->E1);
463: if (iftrue(e1))
464: {
465: L2: el_free(e->E2);
466: e->E2 = NULL;
467: e->Eoper = OPbool;
468: e = poptelem(e);
469: }
470: else
471: goto def;
472: break;
473: case OPcond:
474: e->E1 = e1 = poptelem(e->E1);
475: if (e1->Eoper == OPconst)
476: {
477: e2 = e->E2;
478: type_free(e->ET);
479: if (boolres(e1))
480: { el_copy(e,e2->E1);
481: e2->E1->Eoper = OPunde;
482: e2->E1->ET = NULL;
483: e2->E1->E1 = NULL;
484: e2->E1->E2 = NULL;
485: el_free(e2->E1);
486: e2->E1 = NULL;
487: }
488: else
489: { el_copy(e,e2->E2);
490: e2->E2->Eoper = OPunde;
491: e2->E2->ET = NULL;
492: e2->E2->E1 = NULL;
493: e2->E2->E2 = NULL;
494: el_free(e2->E2);
495: e2->E2 = NULL;
496: }
497: el_free(e2);
498: el_free(e1);
499: e = poptelem(e);
500: }
501: else
502: goto def;
503: break;
504: case OPadd:
505: e->E1 = e1 = poptelem(e->E1);
506: e->E2 = e2 = poptelem(e->E2);
507: if (e1->Eoper == OPconst)
508: { /* swap leaves */
509: e->E1 = e2;
510: e2 = e->E2 = e1;
511: e1 = e->E1;
512: }
513: goto L4;
514: case OPmin:
515: e->E1 = e1 = poptelem(e->E1);
516: e->E2 = e2 = poptelem(e->E2);
517: L4:
518: if (e1->Eoper == OPrelconst || e1->Eoper == OPstring)
519: {
520: if (e2->Eoper == OPconst)
521: { targ_int i = e2->EV.Vint;
522:
523: #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
524: if (i && e1->EV.sp.Vsym->Sfl == FLgot)
525: break;
526: #endif
527: if (e->Eoper == OPmin)
528: i = -i;
529: e1->EV.sp.Voffset += i;
530: e = selecte1(e,e->ET);
531: break;
532: }
533: }
534: goto eval;
535: default:
536: if (OTleaf(op))
537: goto ret;
538: e->E1 = poptelem(e->E1);
539: def:
540: if (OTbinary(op)) // if binary node
541: {
542: e->E2 = poptelem(e->E2);
543: }
544: eval:
545: e = evalu8(e);
546: break;
547: }
548: ret:
549: return e;
550: }
551:
552: /********************
553: * Select E1 leaf of e, and give it type t.
554: */
555:
556: elem *selecte1(elem *e,type *t)
557: { elem *e1;
558:
559: elem_debug(e);
560: assert(EOP(e));
561: e1 = e->E1;
562: el_settype(e1,t);
563: e->E1 = NULL;
564: el_free(e);
565: return e1;
566: }
567:
568: #endif
569:
570: /******************************
571: * Evaluate a node with only constants as leaves.
572: * Return with the result.
573: */
574:
575: elem * evalu8(elem *e)
576: { elem *e1,*e2;
577: tym_t tym,tym2,uns;
578: unsigned op;
579: targ_int i1,i2;
580: int i;
581: targ_llong l1,l2;
582: targ_ldouble d1,d2;
583: elem esave;
584:
585: // assert((_status87() & 0x3800) == 0);
586: assert(e && EOP(e));
587: op = e->Eoper;
588: elem_debug(e);
589: e1 = e->E1;
590:
591: //printf("evalu8(): "); elem_print(e);
592: elem_debug(e1);
593: if (e1->Eoper == OPconst)
594: {
595: tym2 = 0;
596: e2 = NULL;
597: if (EBIN(e))
598: { e2 = e->E2;
599: elem_debug(e2);
600: if (e2->Eoper == OPconst)
601: {
602: i2 = l2 = el_tolong(e2);
warning C4244: '=' : conversion from 'targ_llong' to 'targ_int', possible loss of data
603: d2 = el_toldouble(e2);
604: }
605: else
606: return e;
607: tym2 = tybasic(typemask(e2));
608: }
609: else
610: {
611: tym2 = 0;
612: e2 = NULL;
613: i2 = 0; // not used, but static analyzer complains
614: l2 = 0; // "
615: d2 = 0; // "
616: }
617: i1 = l1 = el_tolong(e1);
warning C4244: '=' : conversion from 'targ_llong' to 'targ_int', possible loss of data
618: d1 = el_toldouble(e1);
619: tym = tybasic(typemask(e1)); /* type of op is type of left child */
620:
621: #if TX86 && SCPP
622: // Huge pointers are always evaluated at runtime
623: if (tym == TYhptr && (l1 != 0 || l2 != 0))
624: return e;
625: #endif
626: esave = *e;
627: #if !__OpenBSD__
628: _clear87();
629: #endif
630: }
631: else
632: return e;
633:
634: /* if left or right leaf is unsigned, this is an unsigned operation */
635: uns = tyuns(tym) | tyuns(tym2);
636:
637: /*elem_print(e);*/
638: /*dbg_printf("x%lx ",l1); WROP(op); dbg_printf("x%lx = ",l2);*/
639: #if 0
640: if (0 && e2)
641: {
642: dbg_printf("d1 = %Lg, d2 = %Lg, op = %d, OPne = %d, tym = x%lx\n",d1,d2,op,OPne,tym);
643: dbg_printf("tym1 = x%lx, tym2 = x%lx, e2 = %g\n",tym,tym2,e2->EV.Vdouble);
644:
645: union eve u;
646: dbg_printf("d1 = x%16llx\n", (u.Vldouble = d1, u.Vullong));
647: dbg_printf("d2 = x%16llx\n", (u.Vldouble = d2, u.Vullong));
648: }
649: #endif
650: i = 0;
651: switch (op)
652: {
653: case OPadd:
654: switch (tym)
655: {
656: case TYfloat:
657: switch (tym2)
658: {
659: case TYfloat:
660: e->EV.Vfloat = e1->EV.Vfloat + e2->EV.Vfloat;
661: break;
662: case TYifloat:
663: e->EV.Vcfloat.re = e1->EV.Vfloat;
664: e->EV.Vcfloat.im = e2->EV.Vfloat;
665: break;
666: case TYcfloat:
667: e->EV.Vcfloat.re = e1->EV.Vfloat + e2->EV.Vcfloat.re;
668: e->EV.Vcfloat.im = 0 + e2->EV.Vcfloat.im;
669: break;
670: default:
671: assert(0);
672: }
673: break;
674: case TYdouble:
675: case TYdouble_alias:
676: switch (tym2)
677: {
678: case TYdouble:
679: case TYdouble_alias:
680: e->EV.Vdouble = e1->EV.Vdouble + e2->EV.Vdouble;
681: break;
682: case TYidouble:
683: e->EV.Vcdouble.re = e1->EV.Vdouble;
684: e->EV.Vcdouble.im = e2->EV.Vdouble;
685: break;
686: case TYcdouble:
687: e->EV.Vcdouble.re = e1->EV.Vdouble + e2->EV.Vcdouble.re;
688: e->EV.Vcdouble.im = 0 + e2->EV.Vcdouble.im;
689: break;
690: default:
691: assert(0);
692: }
693: break;
694: case TYldouble:
695: switch (tym2)
696: {
697: case TYldouble:
698: e->EV.Vldouble = d1 + d2;
699: break;
700: case TYildouble:
701: e->EV.Vcldouble.re = d1;
702: e->EV.Vcldouble.im = d2;
703: break;
704: case TYcldouble:
705: e->EV.Vcldouble.re = d1 + e2->EV.Vcldouble.re;
706: e->EV.Vcldouble.im = 0 + e2->EV.Vcldouble.im;
707: break;
708: default:
709: assert(0);
710: }
711: break;
712: case TYifloat:
713: switch (tym2)
714: {
715: case TYfloat:
716: e->EV.Vcfloat.re = e2->EV.Vfloat;
717: e->EV.Vcfloat.im = e1->EV.Vfloat;
718: break;
719: case TYifloat:
720: e->EV.Vfloat = e1->EV.Vfloat + e2->EV.Vfloat;
721: break;
722: case TYcfloat:
723: e->EV.Vcfloat.re = 0 + e2->EV.Vcfloat.re;
724: e->EV.Vcfloat.im = e1->EV.Vfloat + e2->EV.Vcfloat.im;
725: break;
726: default:
727: assert(0);
728: }
729: break;
730: case TYidouble:
731: switch (tym2)
732: {
733: case TYdouble:
734: e->EV.Vcdouble.re = e2->EV.Vdouble;
735: e->EV.Vcdouble.im = e1->EV.Vdouble;
736: break;
737: case TYidouble:
738: e->EV.Vdouble = e1->EV.Vdouble + e2->EV.Vdouble;
739: break;
740: case TYcdouble:
741: e->EV.Vcdouble.re = 0 + e2->EV.Vcdouble.re;
742: e->EV.Vcdouble.im = e1->EV.Vdouble + e2->EV.Vcdouble.im;
743: break;
744: default:
745: assert(0);
746: }
747: break;
748: case TYildouble:
749: switch (tym2)
750: {
751: case TYldouble:
752: e->EV.Vcldouble.re = d2;
753: e->EV.Vcldouble.im = d1;
754: break;
755: case TYildouble:
756: e->EV.Vldouble = d1 + d2;
757: break;
758: case TYcldouble:
759: e->EV.Vcldouble.re = 0 + e2->EV.Vcldouble.re;
760: e->EV.Vcldouble.im = d1 + e2->EV.Vcldouble.im;
761: break;
762: default:
763: assert(0);
764: }
765: break;
766: case TYcfloat:
767: switch (tym2)
768: {
769: case TYfloat:
770: e->EV.Vcfloat.re = e1->EV.Vcfloat.re + e2->EV.Vfloat;
771: e->EV.Vcfloat.im = e1->EV.Vcfloat.im;
772: break;
773: case TYifloat:
774: e->EV.Vcfloat.re = e1->EV.Vcfloat.re;
775: e->EV.Vcfloat.im = e1->EV.Vcfloat.im + e2->EV.Vfloat;
776: break;
777: case TYcfloat:
778: e->EV.Vcfloat.re = e1->EV.Vcfloat.re + e2->EV.Vcfloat.re;
779: e->EV.Vcfloat.im = e1->EV.Vcfloat.im + e2->EV.Vcfloat.im;
780: break;
781: default:
782: assert(0);
783: }
784: break;
785: case TYcdouble:
786: switch (tym2)
787: {
788: case TYdouble:
789: e->EV.Vcdouble.re = e1->EV.Vcdouble.re + e2->EV.Vdouble;
790: e->EV.Vcdouble.im = e1->EV.Vcdouble.im;
791: break;
792: case TYidouble:
793: e->EV.Vcdouble.re = e1->EV.Vcdouble.re;
794: e->EV.Vcdouble.im = e1->EV.Vcdouble.im + e2->EV.Vdouble;
795: break;
796: case TYcdouble:
797: e->EV.Vcdouble.re = e1->EV.Vcdouble.re + e2->EV.Vcdouble.re;
798: e->EV.Vcdouble.im = e1->EV.Vcdouble.im + e2->EV.Vcdouble.im;
799: break;
800: default:
801: assert(0);
802: }
803: break;
804: case TYcldouble:
805: switch (tym2)
806: {
807: case TYldouble:
808: e->EV.Vcldouble.re = e1->EV.Vcldouble.re + d2;
809: e->EV.Vcldouble.im = e1->EV.Vcldouble.im;
810: break;
811: case TYildouble:
812: e->EV.Vcldouble.re = e1->EV.Vcldouble.re;
813: e->EV.Vcldouble.im = e1->EV.Vcldouble.im + d2;
814: break;
815: case TYcldouble:
816: e->EV.Vcldouble.re = e1->EV.Vcldouble.re + e2->EV.Vcldouble.re;
817: e->EV.Vcldouble.im = e1->EV.Vcldouble.im + e2->EV.Vcldouble.im;
818: break;
819: default:
820: assert(0);
821: }
822: break;
823:
824: default:
825: #if TX86
826: if (intsize == 2)
827: { if (tyfv(tym))
828: e->EV.Vlong = (l1 & 0xFFFF0000) |
829: (targ_ushort) ((targ_ushort) l1 + i2);
830: else if (tyfv(tym2))
831: e->EV.Vlong = (l2 & 0xFFFF0000) |
832: (targ_ushort) (i1 + (targ_ushort) l2);
833: else if (tyintegral(tym) || typtr(tym))
834: e->EV.Vllong = l1 + l2;
835: else
836: assert(0);
837: }
838: else
839: #endif
840: if (tyintegral(tym) || typtr(tym))
841: e->EV.Vllong = l1 + l2;
842: else
843: assert(0);
844: break;
845: }
846: break;
847:
848: case OPmin:
849: switch (tym)
850: {
851: case TYfloat:
852: switch (tym2)
853: {
854: case TYfloat:
855: e->EV.Vfloat = e1->EV.Vfloat - e2->EV.Vfloat;
856: break;
857: case TYifloat:
858: e->EV.Vcfloat.re = e1->EV.Vfloat;
859: e->EV.Vcfloat.im = -e2->EV.Vfloat;
860: break;
861: case TYcfloat:
862: e->EV.Vcfloat.re = e1->EV.Vfloat - e2->EV.Vcfloat.re;
863: e->EV.Vcfloat.im = 0 - e2->EV.Vcfloat.im;
864: break;
865: default:
866: assert(0);
867: }
868: break;
869: case TYdouble:
870: case TYdouble_alias:
871: switch (tym2)
872: {
873: case TYdouble:
874: case TYdouble_alias:
875: e->EV.Vdouble = e1->EV.Vdouble - e2->EV.Vdouble;
876: break;
877: case TYidouble:
878: e->EV.Vcdouble.re = e1->EV.Vdouble;
879: e->EV.Vcdouble.im = -e2->EV.Vdouble;
880: break;
881: case TYcdouble:
882: e->EV.Vcdouble.re = e1->EV.Vdouble - e2->EV.Vcdouble.re;
883: e->EV.Vcdouble.im = 0 - e2->EV.Vcdouble.im;
884: break;
885: default:
886: assert(0);
887: }
888: break;
889: case TYldouble:
890: switch (tym2)
891: {
892: case TYldouble:
893: e->EV.Vldouble = d1 - d2;
894: break;
895: case TYildouble:
896: e->EV.Vcldouble.re = d1;
897: e->EV.Vcldouble.im = -d2;
898: break;
899: case TYcldouble:
900: e->EV.Vcldouble.re = d1 - e2->EV.Vcldouble.re;
901: e->EV.Vcldouble.im = 0 - e2->EV.Vcldouble.im;
902: break;
903: default:
904: assert(0);
905: }
906: break;
907: case TYifloat:
908: switch (tym2)
909: {
910: case TYfloat:
911: e->EV.Vcfloat.re = -e2->EV.Vfloat;
912: e->EV.Vcfloat.im = e1->EV.Vfloat;
913: break;
914: case TYifloat:
915: e->EV.Vfloat = e1->EV.Vfloat - e2->EV.Vfloat;
916: break;
917: case TYcfloat:
918: e->EV.Vcfloat.re = 0 - e2->EV.Vcfloat.re;
919: e->EV.Vcfloat.im = e1->EV.Vfloat - e2->EV.Vcfloat.im;
920: break;
921: default:
922: assert(0);
923: }
924: break;
925: case TYidouble:
926: switch (tym2)
927: {
928: case TYdouble:
929: e->EV.Vcdouble.re = -e2->EV.Vdouble;
930: e->EV.Vcdouble.im = e1->EV.Vdouble;
931: break;
932: case TYidouble:
933: e->EV.Vdouble = e1->EV.Vdouble - e2->EV.Vdouble;
934: break;
935: case TYcdouble:
936: e->EV.Vcdouble.re = 0 - e2->EV.Vcdouble.re;
937: e->EV.Vcdouble.im = e1->EV.Vdouble - e2->EV.Vcdouble.im;
938: break;
939: default:
940: assert(0);
941: }
942: break;
943: case TYildouble:
944: switch (tym2)
945: {
946: case TYldouble:
947: e->EV.Vcldouble.re = -d2;
948: e->EV.Vcldouble.im = d1;
949: break;
950: case TYildouble:
951: e->EV.Vldouble = d1 - d2;
952: break;
953: case TYcldouble:
954: e->EV.Vcldouble.re = 0 - e2->EV.Vcldouble.re;
955: e->EV.Vcldouble.im = d1 - e2->EV.Vcldouble.im;
956: break;
957: default:
958: assert(0);
959: }
960: break;
961: case TYcfloat:
962: switch (tym2)
963: {
964: case TYfloat:
965: e->EV.Vcfloat.re = e1->EV.Vcfloat.re - e2->EV.Vfloat;
966: e->EV.Vcfloat.im = e1->EV.Vcfloat.im;
967: break;
968: case TYifloat:
969: e->EV.Vcfloat.re = e1->EV.Vcfloat.re;
970: e->EV.Vcfloat.im = e1->EV.Vcfloat.im - e2->EV.Vfloat;
971: break;
972: case TYcfloat:
973: e->EV.Vcfloat.re = e1->EV.Vcfloat.re - e2->EV.Vcfloat.re;
974: e->EV.Vcfloat.im = e1->EV.Vcfloat.im - e2->EV.Vcfloat.im;
975: break;
976: default:
977: assert(0);
978: }
979: break;
980: case TYcdouble:
981: switch (tym2)
982: {
983: case TYdouble:
984: e->EV.Vcdouble.re = e1->EV.Vcdouble.re - e2->EV.Vdouble;
985: e->EV.Vcdouble.im = e1->EV.Vcdouble.im;
986: break;
987: case TYidouble:
988: e->EV.Vcdouble.re = e1->EV.Vcdouble.re;
989: e->EV.Vcdouble.im = e1->EV.Vcdouble.im - e2->EV.Vdouble;
990: break;
991: case TYcdouble:
992: e->EV.Vcdouble.re = e1->EV.Vcdouble.re - e2->EV.Vcdouble.re;
993: e->EV.Vcdouble.im = e1->EV.Vcdouble.im - e2->EV.Vcdouble.im;
994: break;
995: default:
996: assert(0);
997: }
998: break;
999: case TYcldouble:
1000: switch (tym2)
1001: {
1002: case TYldouble:
1003: e->EV.Vcldouble.re = e1->EV.Vcldouble.re - d2;
1004: e->EV.Vcldouble.im = e1->EV.Vcldouble.im;
1005: break;
1006: case TYildouble:
1007: e->EV.Vcldouble.re = e1->EV.Vcldouble.re;
1008: e->EV.Vcldouble.im = e1->EV.Vcldouble.im - d2;
1009: break;
1010: case TYcldouble:
1011: e->EV.Vcldouble.re = e1->EV.Vcldouble.re - e2->EV.Vcldouble.re;
1012: e->EV.Vcldouble.im = e1->EV.Vcldouble.im - e2->EV.Vcldouble.im;
1013: break;
1014: default:
1015: assert(0);
1016: }
1017: break;
1018:
1019: default:
1020: #if TX86
1021: if (intsize == 2 &&
1022: tyfv(tym) && tysize[tym2] == 2)
1023: e->EV.Vllong = (l1 & 0xFFFF0000) |
1024: (targ_ushort) ((targ_ushort) l1 - i2);
1025: else
1026: #endif
1027: if (tyintegral(tym) || typtr(tym))
1028: e->EV.Vllong = l1 - l2;
1029: else
1030: assert(0);
1031: break;
1032: }
1033: break;
1034: case OPmul:
1035: if (tyintegral(tym) || typtr(tym))
1036: e->EV.Vllong = l1 * l2;
1037: else
1038: { switch (tym)
1039: {
1040: case TYfloat:
1041: switch (tym2)
1042: {
1043: case TYfloat:
1044: case TYifloat:
1045: e->EV.Vfloat = e1->EV.Vfloat * e2->EV.Vfloat;
1046: break;
1047: case TYcfloat:
1048: e->EV.Vcfloat.re = e1->EV.Vfloat * e2->EV.Vcfloat.re;
1049: e->EV.Vcfloat.im = e1->EV.Vfloat * e2->EV.Vcfloat.im;
1050: break;
1051: default:
1052: assert(0);
1053: }
1054: break;
1055: case TYdouble:
1056: case TYdouble_alias:
1057: switch (tym2)
1058: {
1059: case TYdouble:
1060: case TYdouble_alias:
1061: case TYidouble:
1062: e->EV.Vdouble = e1->EV.Vdouble * e2->EV.Vdouble;
1063: break;
1064: case TYcdouble:
1065: e->EV.Vcdouble.re = e1->EV.Vdouble * e2->EV.Vcdouble.re;
1066: e->EV.Vcdouble.im = e1->EV.Vdouble * e2->EV.Vcdouble.im;
1067: break;
1068: default:
1069: assert(0);
1070: }
1071: break;
1072: case TYldouble:
1073: switch (tym2)
1074: {
1075: case TYldouble:
1076: case TYildouble:
1077: e->EV.Vldouble = d1 * d2;
1078: break;
1079: case TYcldouble:
1080: e->EV.Vcldouble.re = d1 * e2->EV.Vcldouble.re;
1081: e->EV.Vcldouble.im = d1 * e2->EV.Vcldouble.im;
1082: break;
1083: default:
1084: assert(0);
1085: }
1086: break;
1087: case TYifloat:
1088: switch (tym2)
1089: {
1090: case TYfloat:
1091: e->EV.Vfloat = e1->EV.Vfloat * e2->EV.Vfloat;
1092: break;
1093: case TYifloat:
1094: e->EV.Vfloat = -e1->EV.Vfloat * e2->EV.Vfloat;
1095: break;
1096: case TYcfloat:
1097: e->EV.Vcfloat.re = -e1->EV.Vfloat * e2->EV.Vcfloat.im;
1098: e->EV.Vcfloat.im = e1->EV.Vfloat * e2->EV.Vcfloat.re;
1099: break;
1100: default:
1101: assert(0);
1102: }
1103: break;
1104: case TYidouble:
1105: switch (tym2)
1106: {
1107: case TYdouble:
1108: e->EV.Vdouble = e1->EV.Vdouble * e2->EV.Vdouble;
1109: break;
1110: case TYidouble:
1111: e->EV.Vdouble = -e1->EV.Vdouble * e2->EV.Vdouble;
1112: break;
1113: case TYcdouble:
1114: e->EV.Vcdouble.re = -e1->EV.Vdouble * e2->EV.Vcdouble.im;
1115: e->EV.Vcdouble.im = e1->EV.Vdouble * e2->EV.Vcdouble.re;
1116: break;
1117: default:
1118: assert(0);
1119: }
1120: break;
1121: case TYildouble:
1122: switch (tym2)
1123: {
1124: case TYldouble:
1125: e->EV.Vldouble = d1 * d2;
1126: break;
1127: case TYildouble:
1128: e->EV.Vldouble = -d1 * d2;
1129: break;
1130: case TYcldouble:
1131: e->EV.Vcldouble.re = -d1 * e2->EV.Vcldouble.im;
1132: e->EV.Vcldouble.im = d1 * e2->EV.Vcldouble.re;
1133: break;
1134: default:
1135: assert(0);
1136: }
1137: break;
1138: case TYcfloat:
1139: switch (tym2)
1140: {
1141: case TYfloat:
1142: e->EV.Vcfloat.re = e1->EV.Vcfloat.re * e2->EV.Vfloat;
1143: e->EV.Vcfloat.im = e1->EV.Vcfloat.im * e2->EV.Vfloat;
1144: break;
1145: case TYifloat:
1146: e->EV.Vcfloat.re = -e1->EV.Vcfloat.im * e2->EV.Vfloat;
1147: e->EV.Vcfloat.im = e1->EV.Vcfloat.re * e2->EV.Vfloat;
1148: break;
1149: case TYcfloat:
1150: e->EV.Vcfloat = Complex_f::mul(e1->EV.Vcfloat, e2->EV.Vcfloat);
1151: break;
1152: default:
1153: assert(0);
1154: }
1155: break;
1156: case TYcdouble:
1157: switch (tym2)
1158: {
1159: case TYdouble:
1160: e->EV.Vcdouble.re = e1->EV.Vcdouble.re * e2->EV.Vdouble;
1161: e->EV.Vcdouble.im = e1->EV.Vcdouble.im * e2->EV.Vdouble;
1162: break;
1163: case TYidouble:
1164: e->EV.Vcdouble.re = -e1->EV.Vcdouble.im * e2->EV.Vdouble;
1165: e->EV.Vcdouble.im = e1->EV.Vcdouble.re * e2->EV.Vdouble;
1166: break;
1167: case TYcdouble:
1168: e->EV.Vcdouble = Complex_d::mul(e1->EV.Vcdouble, e2->EV.Vcdouble);
1169: break;
1170: default:
1171: assert(0);
1172: }
1173: break;
1174: case TYcldouble:
1175: switch (tym2)
1176: {
1177: case TYldouble:
1178: e->EV.Vcldouble.re = e1->EV.Vcldouble.re * d2;
1179: e->EV.Vcldouble.im = e1->EV.Vcldouble.im * d2;
1180: break;
1181: case TYildouble:
1182: e->EV.Vcldouble.re = -e1->EV.Vcldouble.im * d2;
1183: e->EV.Vcldouble.im = e1->EV.Vcldouble.re * d2;
1184: break;
1185: case TYcldouble:
1186: e->EV.Vcldouble = Complex_ld::mul(e1->EV.Vcldouble, e2->EV.Vcldouble);
1187: break;
1188: default:
1189: assert(0);
1190: }
1191: break;
1192: default:
1193: #ifdef DEBUG
1194: dbg_printf("tym = x%x\n",tym);
1195: elem_print(e);
1196: #endif
1197: assert(0);
1198: }
1199: }
1200: break;
1201: case OPdiv:
1202: if (!boolres(e2)) // divide by 0
1203: {
1204: #if SCPP
1205: if (!tyfloating(tym))
1206: #endif
1207: goto div0;
1208: }
1209: if (uns)
1210: e->EV.Vullong = ((targ_ullong) l1) / ((targ_ullong) l2);
1211: else
1212: { switch (tym)
1213: {
1214: case TYfloat:
1215: switch (tym2)
1216: {
1217: case TYfloat:
1218: e->EV.Vfloat = e1->EV.Vfloat / e2->EV.Vfloat;
1219: break;
1220: case TYifloat:
1221: e->EV.Vfloat = -e1->EV.Vfloat / e2->EV.Vfloat;
1222: break;
1223: case TYcfloat:
1224: e->EV.Vcfloat.re = d1;
warning C4244: '=' : conversion from 'targ_ldouble' to 'float', possible loss of data
1225: e->EV.Vcfloat.im = 0;
1226: e->EV.Vcfloat = Complex_f::div(e->EV.Vcfloat, e2->EV.Vcfloat);
1227: break;
1228: default:
1229: assert(0);
1230: }
1231: break;
1232: case TYdouble:
1233: case TYdouble_alias:
1234: switch (tym2)
1235: {
1236: case TYdouble:
1237: case TYdouble_alias:
1238: e->EV.Vdouble = e1->EV.Vdouble / e2->EV.Vdouble;
1239: break;
1240: case TYidouble:
1241: e->EV.Vdouble = -e1->EV.Vdouble / e2->EV.Vdouble;
1242: break;
1243: case TYcdouble:
1244: e->EV.Vcdouble.re = d1;
1245: e->EV.Vcdouble.im = 0;
1246: e->EV.Vcdouble = Complex_d::div(e->EV.Vcdouble, e2->EV.Vcdouble);
1247: break;
1248: default:
1249: assert(0);
1250: }
1251: break;
1252: case TYldouble:
1253: switch (tym2)
1254: {
1255: case TYldouble:
1256: e->EV.Vldouble = d1 / d2;
1257: break;
1258: case TYildouble:
1259: e->EV.Vldouble = -d1 / d2;
1260: break;
1261: case TYcldouble:
1262: e->EV.Vcldouble.re = d1;
1263: e->EV.Vcldouble.im = 0;
1264: e->EV.Vcldouble = Complex_ld::div(e->EV.Vcldouble, e2->EV.Vcldouble);
1265: break;
1266: default:
1267: assert(0);
1268: }
1269: break;
1270: case TYifloat:
1271: switch (tym2)
1272: {
1273: case TYfloat:
1274: case TYifloat:
1275: e->EV.Vfloat = e1->EV.Vfloat / e2->EV.Vfloat;
1276: break;
1277: case TYcfloat:
1278: e->EV.Vcfloat.re = 0;
1279: e->EV.Vcfloat.im = e1->EV.Vfloat;
1280: e->EV.Vcfloat = Complex_f::div(e->EV.Vcfloat, e2->EV.Vcfloat);
1281: break;
1282: default:
1283: assert(0);
1284: }
1285: break;
1286: case TYidouble:
1287: switch (tym2)
1288: {
1289: case TYdouble:
1290: case TYidouble:
1291: e->EV.Vdouble = e1->EV.Vdouble / e2->EV.Vdouble;
1292: break;
1293: case TYcdouble:
1294: e->EV.Vcdouble.re = 0;
1295: e->EV.Vcdouble.im = e1->EV.Vdouble;
1296: e->EV.Vcdouble = Complex_d::div(e->EV.Vcdouble, e2->EV.Vcdouble);
1297: break;
1298: default:
1299: assert(0);
1300: }
1301: break;
1302: case TYildouble:
1303: switch (tym2)
1304: {
1305: case TYldouble:
1306: case TYildouble:
1307: e->EV.Vldouble = d1 / d2;
1308: break;
1309: case TYcldouble:
1310: e->EV.Vcldouble.re = 0;
1311: e->EV.Vcldouble.im = d1;
1312: e->EV.Vcldouble = Complex_ld::div(e->EV.Vcldouble, e2->EV.Vcldouble);
1313: break;
1314: default:
1315: assert(0);
1316: }
1317: break;
1318: case TYcfloat:
1319: switch (tym2)
1320: {
1321: case TYfloat:
1322: e->EV.Vcfloat.re = e1->EV.Vcfloat.re / e2->EV.Vfloat;
1323: e->EV.Vcfloat.im = e1->EV.Vcfloat.im / e2->EV.Vfloat;
1324: break;
1325: case TYifloat:
1326: e->EV.Vcfloat.re = e1->EV.Vcfloat.im / e2->EV.Vfloat;
1327: e->EV.Vcfloat.im = -e1->EV.Vcfloat.re / e2->EV.Vfloat;
1328: break;
1329: case TYcfloat:
1330: e->EV.Vcfloat = Complex_f::div(e1->EV.Vcfloat, e2->EV.Vcfloat);
1331: break;
1332: default:
1333: assert(0);
1334: }
1335: break;
1336: case TYcdouble:
1337: switch (tym2)
1338: {
1339: case TYdouble:
1340: e->EV.Vcdouble.re = e1->EV.Vcdouble.re / e2->EV.Vdouble;
1341: e->EV.Vcdouble.im = e1->EV.Vcdouble.im / e2->EV.Vdouble;
1342: break;
1343: case TYidouble:
1344: e->EV.Vcdouble.re = e1->EV.Vcdouble.im / e2->EV.Vdouble;
1345: e->EV.Vcdouble.im = -e1->EV.Vcdouble.re / e2->EV.Vdouble;
1346: break;
1347: case TYcdouble:
1348: e->EV.Vcdouble = Complex_d::div(e1->EV.Vcdouble, e2->EV.Vcdouble);
1349: break;
1350: default:
1351: assert(0);
1352: }
1353: break;
1354: case TYcldouble:
1355: switch (tym2)
1356: {
1357: case TYldouble:
1358: e->EV.Vcldouble.re = e1->EV.Vcldouble.re / d2;
1359: e->EV.Vcldouble.im = e1->EV.Vcldouble.im / d2;
1360: break;
1361: case TYildouble:
1362: e->EV.Vcldouble.re = e1->EV.Vcldouble.im / d2;
1363: e->EV.Vcldouble.im = -e1->EV.Vcldouble.re / d2;
1364: break;
1365: case TYcldouble:
1366: e->EV.Vcldouble = Complex_ld::div(e1->EV.Vcldouble, e2->EV.Vcldouble);
1367: break;
1368: default:
1369: assert(0);
1370: }
1371: break;
1372: default:
1373: e->EV.Vllong = l1 / l2;
1374: break;
1375: }
1376: }
1377: break;
1378: case OPmod:
1379: if (!boolres(e2))
1380: {
1381: div0:
1382: #if SCPP
1383: synerr(EM_divby0);
1384: #else // MARS
1385: //error(e->Esrcpos.Sfilename, e->Esrcpos.Slinnum, "divide by zero");
1386: #endif
1387: break;
1388: }
1389: if (uns)
1390: e->EV.Vullong = ((targ_ullong) l1) % ((targ_ullong) l2);
1391: else
1392: {
1393: // BUG: what do we do for imaginary, complex?
1394: switch (tym)
1395: { case TYdouble:
1396: case TYidouble:
1397: case TYdouble_alias:
1398: e->EV.Vdouble = fmod(e1->EV.Vdouble,e2->EV.Vdouble);
1399: break;
1400: case TYfloat:
1401: case TYifloat:
1402: e->EV.Vfloat = fmodf(e1->EV.Vfloat,e2->EV.Vfloat);
1403: break;
1404: case TYldouble:
1405: case TYildouble:
1406: #if __DMC__
1407: e->EV.Vldouble = _modulo(d1, d2);
1408: #else
1409: e->EV.Vldouble = fmodl(d1, d2);
1410: #endif
1411: break;
1412: case TYcfloat:
1413: switch (tym2)
1414: {
1415: case TYfloat:
1416: case TYifloat:
1417: e->EV.Vcfloat.re = fmodf(e1->EV.Vcfloat.re, e2->EV.Vfloat);
1418: e->EV.Vcfloat.im = fmodf(e1->EV.Vcfloat.im, e2->EV.Vfloat);
1419: break;
1420: default:
1421: assert(0);
1422: }
1423: break;
1424: case TYcdouble:
1425: switch (tym2)
1426: {
1427: case TYdouble:
1428: case TYidouble:
1429: e->EV.Vcdouble.re = fmod(e1->EV.Vcdouble.re, e2->EV.Vdouble);
1430: e->EV.Vcdouble.im = fmod(e1->EV.Vcdouble.im, e2->EV.Vdouble);
1431: break;
1432: default:
1433: assert(0);
1434: }
1435: break;
1436: case TYcldouble:
1437: switch (tym2)
1438: {
1439: case TYldouble:
1440: case TYildouble:
1441: #if __DMC__
1442: e->EV.Vcldouble.re = _modulo(e1->EV.Vcldouble.re, d2);
1443: e->EV.Vcldouble.im = _modulo(e1->EV.Vcldouble.im, d2);
1444: #else
1445: e->EV.Vcldouble.re = fmodl(e1->EV.Vcldouble.re, d2);
1446: e->EV.Vcldouble.im = fmodl(e1->EV.Vcldouble.im, d2);
1447: #endif
1448: break;
1449: default:
1450: assert(0);
1451: }
1452: break;
1453: default:
1454: e->EV.Vllong = l1 % l2;
1455: break;
1456: }
1457: }
1458: break;
1459: case OPremquo:
1460: {
1461: targ_llong rem, quo;
1462:
1463: if (!boolres(e2))
1464: goto div0;
1465: if (uns)
1466: {
1467: rem = ((targ_ullong) l1) % ((targ_ullong) l2);
1468: quo = ((targ_ullong) l1) / ((targ_ullong) l2);
1469: }
1470: else
1471: {
1472: rem = l1 % l2;
1473: quo = l1 / l2;
1474: }
1475: switch (tysize(tym))
1476: {
1477: case 2:
1478: e->EV.Vllong = (rem << 16) | (quo & 0xFFFF);
1479: break;
1480: case 4:
1481: e->EV.Vllong = (rem << 32) | (quo & 0xFFFFFFFF);
1482: break;
1483: case 8:
1484: e->EV.Vcent.lsw = quo;
1485: e->EV.Vcent.msw = rem;
1486: break;
1487: default:
1488: assert(0);
1489: break;
1490: }
1491: break;
1492: }
1493: case OPand:
1494: e->EV.Vllong = l1 & l2;
1495: break;
1496: case OPor:
1497: e->EV.Vllong = l1 | l2;
1498: break;
1499: case OPxor:
1500: e->EV.Vllong = l1 ^ l2;
1501: break;
1502: case OPnot:
1503: e->EV.Vint = boolres(e1) ^ TRUE;
1504: break;
1505: case OPcom:
1506: e->EV.Vllong = ~l1;
1507: break;
1508: case OPcomma:
1509: e->EV = e2->EV;
1510: break;
1511: case OPoror:
1512: e->EV.Vint = boolres(e1) || boolres(e2);
1513: break;
1514: case OPandand:
1515: e->EV.Vint = boolres(e1) && boolres(e2);
1516: break;
1517: case OPshl:
1518: if ((targ_ullong) i2 < sizeof(targ_ullong) * 8)
1519: e->EV.Vllong = l1 << i2;
1520: else
1521: e->EV.Vllong = 0;
1522: break;
1523: case OPshr:
1524: if ((targ_ullong) i2 > sizeof(targ_ullong) * 8)
1525: i2 = sizeof(targ_ullong) * 8;
1526: #if SCPP
1527: if (tyuns(tym))
1528: { //printf("unsigned\n");
1529: e->EV.Vullong = ((targ_ullong) l1) >> i2;
1530: }
1531: else
1532: { //printf("signed\n");
1533: e->EV.Vllong = l1 >> i2;
1534: }
1535: #endif
1536: #if MARS
1537: // Always unsigned
1538: e->EV.Vullong = ((targ_ullong) l1) >> i2;
1539: #endif
1540: break;
1541:
1542: #if MARS
1543: case OPashr:
1544: if ((targ_ullong) i2 > sizeof(targ_ullong) * 8)
1545: i2 = sizeof(targ_ullong) * 8;
1546: // Always signed
1547: e->EV.Vllong = l1 >> i2;
1548: break;
1549: #endif
1550:
1551: case OPpair:
1552: switch (tysize[tym])
1553: {
1554: case 2:
1555: e->EV.Vlong = (i2 << 16) | (i1 & 0xFFFF);
1556: break;
1557: case 4:
1558: e->EV.Vllong = (l2 << 32) | (l1 & 0xFFFFFFFF);
1559: break;
1560: case 8:
1561: e->EV.Vcent.lsw = l1;
1562: e->EV.Vcent.msw = l2;
1563: break;
1564: default:
1565: assert(0);
1566: }
1567: break;
1568:
1569: case OPneg:
1570: #if TX86
1571: // Avoid converting NANS to NAN
1572: memcpy(&e->EV.Vcldouble,&e1->EV.Vcldouble,sizeof(e->EV.Vcldouble));
1573: switch (tym)
1574: { case TYdouble:
1575: case TYidouble:
1576: case TYdouble_alias:
1577: e->EV.Vdouble = -e->EV.Vdouble;
1578: break;
1579: case TYfloat:
1580: case TYifloat:
1581: e->EV.Vfloat = -e->EV.Vfloat;
1582: break;
1583: case TYldouble:
1584: case TYildouble:
1585: e->EV.Vldouble = -e->EV.Vldouble;
1586: break;
1587: case TYcfloat:
1588: e->EV.Vcfloat.re = -e->EV.Vcfloat.re;
1589: e->EV.Vcfloat.im = -e->EV.Vcfloat.im;
1590: break;
1591: case TYcdouble:
1592: e->EV.Vcdouble.re = -e->EV.Vcdouble.re;
1593: e->EV.Vcdouble.im = -e->EV.Vcdouble.im;
1594: break;
1595: case TYcldouble:
1596: e->EV.Vcldouble.re = -e->EV.Vcldouble.re;
1597: e->EV.Vcldouble.im = -e->EV.Vcldouble.im;
1598: break;
1599: default:
1600: e->EV.Vllong = -l1;
1601: break;
1602: }
1603: #else
1604: switch (tym)
1605: { case TYdouble:
1606: e->EV.Vdouble = -e1->EV.Vdouble;
1607: break;
1608: case TYfloat:
1609: e->EV.Vfloat = -e1->EV.Vfloat;
1610: break;
1611: case TYldouble:
1612: e->EV.Vldouble = -d1;
1613: break;
1614: default:
1615: e->EV.Vllong = -l1;
1616: break;
1617: }
1618: #endif
1619: break;
1620: case OPabs:
1621: #if 1
1622: switch (tym)
1623: {
1624: case TYdouble:
1625: case TYidouble:
1626: case TYdouble_alias:
1627: e->EV.Vdouble = fabs(e1->EV.Vdouble);
1628: break;
1629: case TYfloat:
1630: case TYifloat:
1631: #if __SC__
1632: e->EV.Vfloat = fabsf(e1->EV.Vfloat);
1633: #else
1634: e->EV.Vfloat = fabs(e1->EV.Vfloat);
1635: #endif
1636: break;
1637: case TYldouble:
1638: case TYildouble:
1639: e->EV.Vldouble = fabsl(d1);
1640: break;
1641: case TYcfloat:
1642: e->EV.Vfloat = Complex_f::abs(e1->EV.Vcfloat);
warning C4244: '=' : conversion from 'long double' to 'targ_float', possible loss of data
1643: break;
1644: case TYcdouble:
1645: e->EV.Vdouble = Complex_d::abs(e1->EV.Vcdouble);
1646: break;
1647: case TYcldouble:
1648: e->EV.Vldouble = Complex_ld::abs(e1->EV.Vcldouble);
1649: break;
1650: default:
1651: e->EV.Vllong = labs(l1);
warning C4244: 'argument' : conversion from 'targ_llong' to 'long', possible loss of data
1652: break;
1653: }
1654: break;
1655: #endif
1656: case OPsqrt:
1657: case OPrndtol:
1658: case OPsin:
1659: case OPcos:
1660: case OPrint:
1661: return e;
1662: case OPngt:
1663: i++;
1664: case OPgt:
1665: if (!tyfloating(tym))
1666: goto Lnle;
1667: i ^= d1 > d2;
1668: e->EV.Vint = i;
1669: break;
1670:
1671: case OPnle:
1672: Lnle:
1673: i++;
1674: case OPle:
1675: if (uns)
1676: {
1677: i ^= ((targ_ullong) l1) <= ((targ_ullong) l2);
1678: }
1679: else
1680: {
1681: if (tyfloating(tym))
1682: i ^= d1 <= d2;
1683: else
1684: i ^= l1 <= l2;
1685: }
1686: e->EV.Vint = i;
1687: break;
1688:
1689: case OPnge:
1690: i++;
1691: case OPge:
1692: if (!tyfloating(tym))
1693: goto Lnlt;
1694: i ^= d1 >= d2;
1695: e->EV.Vint = i;
1696: break;
1697:
1698: case OPnlt:
1699: Lnlt:
1700: i++;
1701: case OPlt:
1702: if (uns)
1703: {
1704: i ^= ((targ_ullong) l1) < ((targ_ullong) l2);
1705: }
1706: else
1707: {
1708: if (tyfloating(tym))
1709: i ^= d1 < d2;
1710: else
1711: i ^= l1 < l2;
1712: }
1713: e->EV.Vint = i;
1714: break;
1715:
1716: case OPne:
1717: i++;
1718: case OPeqeq:
1719: if (tyfloating(tym))
1720: {
1721: switch (tybasic(tym))
1722: {
1723: case TYcfloat:
1724: if (isnan(e1->EV.Vcfloat.re) || isnan(e1->EV.Vcfloat.im) ||
1725: isnan(e2->EV.Vcfloat.re) || isnan(e2->EV.Vcfloat.im))
1726: i ^= 1;
1727: else
1728: i ^= (e1->EV.Vcfloat.re == e2->EV.Vcfloat.re) &&
1729: (e1->EV.Vcfloat.im == e2->EV.Vcfloat.im);
1730: break;
1731: case TYcdouble:
1732: if (isnan(e1->EV.Vcdouble.re) || isnan(e1->EV.Vcdouble.im) ||
1733: isnan(e2->EV.Vcdouble.re) || isnan(e2->EV.Vcdouble.im))
1734: i ^= 1;
1735: else
1736: i ^= (e1->EV.Vcdouble.re == e2->EV.Vcdouble.re) &&
1737: (e1->EV.Vcdouble.im == e2->EV.Vcdouble.im);
1738: break;
1739: case TYcldouble:
1740: if (isnan(e1->EV.Vcldouble.re) || isnan(e1->EV.Vcldouble.im) ||
1741: isnan(e2->EV.Vcldouble.re) || isnan(e2->EV.Vcldouble.im))
1742: i ^= 1;
1743: else
1744: i ^= (e1->EV.Vcldouble.re == e2->EV.Vcldouble.re) &&
1745: (e1->EV.Vcldouble.im == e2->EV.Vcldouble.im);
1746: break;
1747: default:
1748: i ^= d1 == d2;
1749: break;
1750: }
1751: //printf("%Lg + %Lgi, %Lg + %Lgi\n", e1->EV.Vcldouble.re, e1->EV.Vcldouble.im, e2->EV.Vcldouble.re, e2->EV.Vcldouble.im);
1752: }
1753: else
1754: i ^= l1 == l2;
1755: e->EV.Vint = i;
1756: break;
1757:
1758: #if __DMC__
1759: case OPord:
1760: i++;
1761: case OPunord:
1762: // BUG: complex numbers
1763: i ^= d1 !<>= d2;
1764: e->EV.Vint = i;
1765: break;
1766:
1767: case OPnlg:
1768: i++;
1769: case OPlg:
1770: // BUG: complex numbers
1771: i ^= d1 <> d2;
1772: e->EV.Vint = i;
1773: break;
1774:
1775: case OPnleg:
1776: i++;
1777: case OPleg:
1778: // BUG: complex numbers
1779: i ^= d1 <>= d2;
1780: e->EV.Vint = i;
1781: break;
1782:
1783: case OPnule:
1784: i++;
1785: case OPule:
1786: // BUG: complex numbers
1787: i ^= d1 !> d2;
1788: e->EV.Vint = i;
1789: break;
1790:
1791: case OPnul:
1792: i++;
1793: case OPul:
1794: // BUG: complex numbers
1795: i ^= d1 !>= d2;
1796: e->EV.Vint = i;
1797: break;
1798:
1799: case OPnuge:
1800: i++;
1801: case OPuge:
1802: // BUG: complex numbers
1803: i ^= d1 !< d2;
1804: e->EV.Vint = i;
1805: break;
1806:
1807: case OPnug:
1808: i++;
1809: case OPug:
1810: // BUG: complex numbers
1811: i ^= d1 !<= d2;
1812: e->EV.Vint = i;
1813: break;
1814:
1815: case OPnue:
1816: i++;
1817: case OPue:
1818: // BUG: complex numbers
1819: i ^= d1 !<> d2;
1820: e->EV.Vint = i;
1821: break;
1822:
1823: #endif
1824: case OPshtlng:
1825: e->EV.Vlong = (targ_short) i1;
1826: break;
1827: #if TX86
1828: case OPptrlptr:
1829: #endif
1830: case OPu16_32:
1831: e->EV.Vulong = (targ_ushort) i1;
1832: break;
1833: case OPd_u32:
1834: e->EV.Vulong = (targ_ulong)d1;
1835: //printf("OPd_u32: dbl = %g, ulng = x%lx\n",d1,e->EV.Vulong);
1836: break;
1837: case OPd_s32:
1838: e->EV.Vlong = (targ_long)d1;
1839: break;
1840: case OPu32_d:
1841: e->EV.Vdouble = (unsigned) l1;
1842: break;
1843: case OPs32_d:
1844: e->EV.Vdouble = (int) l1;
1845: break;
1846: case OPd_s16:
1847: e->EV.Vint = (targ_int)d1;
1848: break;
1849: case OPs16_d:
1850: e->EV.Vdouble = (targ_short) i1;
1851: break;
1852: case OPdbluns:
1853: e->EV.Vushort = (targ_ushort)d1;
1854: break;
1855: case OPu16_d:
1856: e->EV.Vdouble = (targ_ushort) i1;
1857: break;
1858: case OPd_s64:
1859: e->EV.Vllong = (targ_llong)d1;
1860: break;
1861: case OPd_u64:
1862: case OPld_u64:
1863: e->EV.Vullong = (targ_ullong)d1;
1864: break;
1865: case OPs64_d:
1866: e->EV.Vdouble = l1;
warning C4244: '=' : conversion from 'targ_llong' to 'targ_double', possible loss of data
1867: break;
1868: case OPu64_d:
1869: e->EV.Vdouble = (targ_ullong) l1;
warning C4244: '=' : conversion from 'targ_ullong' to 'targ_double', possible loss of data
1870: break;
1871: case OPd_f:
1872: //assert((_status87() & 0x3800) == 0);
1873: e->EV.Vfloat = e1->EV.Vdouble;
warning C4244: '=' : conversion from 'targ_double' to 'targ_float', possible loss of data
1874: if (tycomplex(tym))
1875: e->EV.Vcfloat.im = e1->EV.Vcdouble.im;
warning C4244: '=' : conversion from 'double' to 'float', possible loss of data
1876: //assert((_status87() & 0x3800) == 0);
1877: break;
1878: case OPf_d:
1879: e->EV.Vdouble = e1->EV.Vfloat;
1880: if (tycomplex(tym))
1881: e->EV.Vcdouble.im = e1->EV.Vcfloat.im;
1882: break;
1883: case OPd_ld:
1884: e->EV.Vldouble = e1->EV.Vdouble;
1885: if (tycomplex(tym))
1886: e->EV.Vcldouble.im = e1->EV.Vcdouble.im;
1887: break;
1888: case OPld_d:
1889: e->EV.Vdouble = e1->EV.Vldouble;
1890: if (tycomplex(tym))
1891: e->EV.Vcdouble.im = e1->EV.Vcldouble.im;
1892: break;
1893: case OPc_r:
1894: e->EV = e1->EV;
1895: break;
1896: case OPc_i:
1897: switch (tym)
1898: {
1899: case TYcfloat:
1900: e->EV.Vfloat = e1->EV.Vcfloat.im;
1901: break;
1902: case TYcdouble:
1903: e->EV.Vdouble = e1->EV.Vcdouble.im;
1904: break;
1905: case TYcldouble:
1906: e->EV.Vldouble = e1->EV.Vcldouble.im;
1907: break;
1908: default:
1909: assert(0);
1910: }
1911: break;
1912: case OPs8int:
1913: e->EV.Vint = (targ_schar) i1;
1914: break;
1915: case OPu8int:
1916: e->EV.Vint = i1 & 0xFF;
1917: break;
1918: case OPint8:
1919: e->EV.Vint = i1;
1920: break;
1921: case OPbool:
1922: e->EV.Vint = boolres(e1);
1923: break;
1924: case OPlngsht:
1925: #if TX86
1926: case OPoffset:
1927: #endif
1928: e->EV.Vint = l1;
warning C4244: '=' : conversion from 'targ_llong' to 'targ_int', possible loss of data
1929: break;
1930:
1931: case OP64_32:
1932: e->EV.Vlong = l1;
warning C4244: '=' : conversion from 'targ_llong' to 'targ_long', possible loss of data
1933: break;
1934: case OPs32_64:
1935: e->EV.Vllong = (targ_long) l1;
1936: break;
1937: case OPu32_64:
1938: e->EV.Vllong = (targ_ulong) l1;
1939: break;
1940:
1941: case OP128_64:
1942: e->EV.Vllong = e1->EV.Vcent.lsw;
1943: break;
1944: case OPs64_128:
1945: e->EV.Vcent.lsw = e1->EV.Vllong;
1946: e->EV.Vcent.msw = 0;
1947: if ((targ_llong)e->EV.Vcent.lsw < 0)
1948: e->EV.Vcent.msw = ~(targ_ullong)0;
1949: break;
1950: case OPu64_128:
1951: e->EV.Vcent.lsw = e1->EV.Vullong;
1952: e->EV.Vcent.msw = 0;
1953: break;
1954:
1955: case OPmsw:
1956: switch (tysize(tym))
1957: {
1958: case 4:
1959: e->EV.Vllong = (l1 >> 16) & 0xFFFF;
1960: break;
1961: case 8:
1962: e->EV.Vllong = (l1 >> 32) & 0xFFFFFFFF;
1963: break;
1964: case 16:
1965: e->EV.Vllong = e1->EV.Vcent.msw;
1966: break;
1967: default:
1968: assert(0);
1969: }
1970: break;
1971: case OPb_8:
1972: e->EV.Vlong = i1 & 1;
1973: break;
1974: case OPbswap:
1975: e->EV.Vint = ((i1 >> 24) & 0x000000FF) |
1976: ((i1 >> 8) & 0x0000FF00) |
1977: ((i1 << 8) & 0x00FF0000) |
1978: ((i1 << 24) & 0xFF000000);
1979: break;
1980: case OProl:
1981: case OPror:
1982: { unsigned n = i2;
1983: if (op == OPror)
1984: n = -n;
warning C4146: unary minus operator applied to unsigned type, result still unsigned
1985: switch (tysize(tym))
1986: {
1987: case 1:
1988: n &= 7;
1989: e->EV.Vuchar = (unsigned char)((i1 << n) | ((i1 & 0xFF) >> (8 - n)));
1990: break;
1991: case 2:
1992: n &= 0xF;
1993: e->EV.Vushort = (targ_ushort)((i1 << n) | ((i1 & 0xFFFF) >> (16 - n)));
1994: break;
1995: case 4:
1996: n &= 0x1F;
1997: e->EV.Vulong = (targ_ulong)((i1 << n) | ((i1 & 0xFFFFFFFF) >> (32 - n)));
1998: break;
1999: case 8:
2000: n &= 0x3F;
2001: e->EV.Vullong = (targ_ullong)((l1 << n) | ((l1 & 0xFFFFFFFFFFFFFFFFLL) >> (64 - n)));
2002: break;
2003: //case 16:
2004: default:
2005: assert(0);
2006: }
2007: break;
2008: }
2009: case OPind:
2010: #if 0 && MARS
2011: /* The problem with this is that although the only reaching definition
2012: * of the variable is null, it still may never get executed, as in:
2013: * int* p = null; if (p) *p = 3;
2014: * and the error will be spurious.
2015: */
2016: if (l1 >= 0 && l1 < 4096)
2017: {
2018: error(e->Esrcpos.Sfilename, e->Esrcpos.Slinnum, "dereference of null pointer");
2019: e->E1->EV.Vlong = 4096; // suppress redundant messages
2020: }
2021: #endif
2022: return e;
2023: default:
2024: return e;
2025: }
2026: #if TX86
2027: int flags;
warning C4101: 'flags' : unreferenced local variable
2028:
2029: if (!ignore_exceptions &&
2030: (config.flags4 & CFG4fastfloat) == 0 &&
2031: #if __OpenBSD__
2032: 1 // until OpenBSD supports C standard fenv.h
2033: #else
2034: _status87() & 0x3F
2035: #endif
2036: )
2037: {
2038: // Exceptions happened. Do not fold the constants.
2039: *e = esave;
2040: return e;
2041: }
2042: #if SCPP
2043: else if ((flags = _status87()) & 0x3F)
2044: { // Should also give diagnostic warning for:
2045: // overflow, underflow, denormal, invalid
2046: if (flags & 0x04)
2047: warerr(WM_divby0);
2048: // else if (flags & 0x08) // overflow
2049: // warerr(WM_badnumber);
2050: }
2051: #endif
2052: #endif
2053:
2054: /*dbg_printf("result = x%lx\n",e->EV.Vlong);*/
2055: e->Eoper = OPconst;
2056: el_free(e1);
2057: if (e2)
2058: el_free(e2);
2059: #if !__GNUC__
2060: //printf("2: %x\n", _status87());
2061: assert((_status87() & 0x3800) == 0);
2062: #endif
2063: //printf("evalu8() returns: "); elem_print(e);
2064: return e;
2065: }
2066:
2067: #endif /* !SPP */
2068: