Pristine Ack-5.5
[Ack-5.5.git] / lang / cem / cemcom.ansi / conversion.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: conversion.c,v 1.7 1994/06/27 07:58:51 ceriel Exp $ */
6 /*      C O N V E R S I O N - C O D E  G E N E R A T O R        */
7
8 #include        "lint.h"
9 #ifndef LINT
10
11 #include        <em.h>
12 #include        "arith.h"
13 #include        "type.h"
14 #include        "sizes.h"
15 #include        "Lpars.h"
16
17 #define T_SIGNED                1
18 #define T_UNSIGNED              2
19 #define T_FLOATING              3
20
21 /*      conversion() generates the EM code for a conversion between
22         the types char, short, int, long, float, double and pointer.
23         There are three conversion types: signed, unsigned and floating.
24         The EM code to obtain this conversion looks like:
25                 LOC sizeof(from_type)
26                 LOC sizeof(to_type)
27                 C??
28 */
29
30 static int convtype();
31
32 conversion(from_type, to_type)
33         register struct type *from_type, *to_type;
34 {
35         register arith from_size = from_type->tp_size;
36         register arith to_size = to_type->tp_size;
37         int from_cnvtype = convtype(from_type);
38         int to_cnvtype = convtype(to_type);
39
40         if ((int)to_size < (int)word_size) to_size = word_size;
41         if ((int)from_size != (int)to_size || from_cnvtype != to_cnvtype) {
42             switch (from_cnvtype)       {
43             case T_SIGNED:
44                 switch (to_cnvtype)     {
45                 case T_SIGNED:
46                         C_loc(from_size);
47                         C_loc(to_size);
48                         C_cii();
49                         break;
50                 case T_UNSIGNED:
51                 case T_FLOATING:
52                         if ((int)from_size < (int)word_size) {
53                                 C_loc(from_size);
54                                 C_loc(word_size);
55                                 C_cii();
56                                 from_size = word_size;
57                         }
58                         /* 3.2.1.2 */
59                         if (to_cnvtype == T_UNSIGNED
60                             && (int)from_size < (int)to_size) {
61                                 C_loc(from_size);
62                                 C_loc(to_size);
63                                 C_cii();
64                                 from_size = to_size;
65                         }
66                         C_loc(from_size);
67                         C_loc(to_size);
68                         if (to_cnvtype == T_UNSIGNED) C_ciu();
69                         else C_cif();
70                         break;
71                 }
72                 break;
73             case T_UNSIGNED:
74                 if ((int)from_size < (int)word_size) from_size = word_size;
75                 C_loc(from_size);
76                 C_loc(to_size);
77                 switch (to_cnvtype)     {
78                 case T_SIGNED:
79                         C_cui();
80                         break;
81                 case T_UNSIGNED:
82                         C_cuu();
83                         break;
84                 case T_FLOATING:
85                         C_cuf();
86                         break;
87                 }
88                 break;
89             case T_FLOATING:
90                 C_loc(from_size);
91                 C_loc(to_size);
92                 switch (to_cnvtype)     {
93                 case T_SIGNED:
94                         C_cfi();
95                         break;
96                 case T_UNSIGNED:
97                         C_cfu();
98                         break;
99                 case T_FLOATING:
100                         C_cff();
101                         break;
102                 }
103                 break;
104             default:
105                 crash("(conversion) illegal type conversion");
106                 /*NOTREACHED*/
107             }
108         }
109         if ((int)(to_type->tp_size) < (int)word_size
110             && to_cnvtype != T_FLOATING
111             ) {
112                 extern arith full_mask[];
113
114                 if (to_cnvtype == T_SIGNED) {
115                         C_loc(to_type->tp_size);
116                         C_loc(word_size);
117                         C_cii();
118                 }
119                 else {
120                         C_loc((arith) full_mask[(int)(to_type->tp_size)]);
121                         C_and(word_size);
122                 }
123         }
124 }
125
126 /*      convtype() returns in which category a given type falls:
127         signed, unsigned or floating
128 */
129 static int
130 convtype(tp)
131         register struct type *tp;
132 {
133         switch (tp->tp_fund)    {
134         case CHAR:
135         case SHORT:
136         case INT:
137         case ERRONEOUS:
138         case LONG:
139         case ENUM:
140                 return tp->tp_unsigned ? T_UNSIGNED : T_SIGNED;
141         case FLOAT:
142         case DOUBLE:
143         case LNGDBL:
144                 return T_FLOATING;
145         case POINTER:
146                 return T_UNSIGNED;
147         }
148         return 0;
149 }
150
151 #endif  /* LINT */
152