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