1 #ifndef BYTECODE_H__
2 #define BYTECODE_H__ 1
3 
4 /*---------------------------------------------------------------------------
5  * Types and Macros used to describe bytecode
6  *
7  *---------------------------------------------------------------------------
8  * While topically part of exec.h, the actual bytecode types and macros
9  * have been exported into this file to reduce the coupling on exec.h.
10  * Most files only need to know about bytecode_t and bytecode_p, and not
11  * about all the other stuff in exec.h .
12  *
13  * Bytecode
14  * --------
15  *
16  * As the name conveys, the LPC programs are compiled into a bytecode,
17  * assuming 8-Bit-Bytes. Since we have more than 256 opcodes, the less
18  * often used instructions are encoded in two-byte opcodes: a prefix
19  * byte and an sub-opcode. The translation opcode -> prefix:sub-opcode
20  * is defined in the instrs[] table using the .prefix and .opcode
21  * fields.
22  *
23  * To achieve platform independance, the driver does not operate directly
24  * with 'char's and 'char *'s, but instead with 'bytecode_t' and
25  * 'bytecode_p's. Combined with some macros this allows the implementation
26  * even on platforms with CHAR_BITs != 8.
27  * TODO: This support is far from complete/comprehensive, and some values
28  * TODO:: in the bytecode are stored in host-sizes and -layouts.
29  *
30  * The bytecode itself is divided into functions: the code for every
31  * function is (except for absolute jumps) selfcontained and prepended
32  * by a header holding the name of the function, and the number and types
33  * of expected arguments. The advantage is that for a given function
34  * the driver does not need to know if it is part of a program or a
35  * lambda closure compiled at runtime: in both cases all necessary
36  * information about the function is right where its code is.
37  *
38  * The maximum size of a program is limited by the biggest offset
39  * that can be stored in the 'functions' array, currently 1 MByte.
40  * A lot of internal offset counters are shorts even, though so far
41  * this never caused a problem.
42  *---------------------------------------------------------------------------
43  */
44 
45 #include "driver.h"
46 #include "typedefs.h"
47 
48 
49 /* --- Byte code ---
50  *
51  * The program code is stored as byte code. The following definitions
52  * and macros allow its implementation even on platforms with more than
53  * 8 bits per character.
54  * TODO: This portability is far from complete, and not used everywhere,
55  * TODO:: not even in the compiler.
56  *
57  *   bytecode_t: an integral type holding the numbers 0..255.
58  *   bytecode_p: an integral type addressing a bytecode. This need not
59  *               be a pointer.
60  *
61  *   bytecode_t GET_CODE(bytecode_p p)
62  *   bytecode_t LOAD_CODE(bytecode_p p)
63  *     Return the bytecode from *p, the LOAD_ variant then increments p.
64  *
65  *   void PUT_CODE(bytecode_p p, bytecode_t c)
66  *   void STORE_CODE(bytecode_p p, bytecode_t c)
67  *   void RSTORE_CODE(bytecode_p p, bytecode_t c)
68  *     Store the bytecode c in *p, the STORE_ variant then increments p.
69  *     The RSTORE_ variant pre-decrements p.
70  *
71  *    char GET_INT8(p) , LOAD_INT8(p)
72  *   uchar GET_UINT8(p), LOAD_UINT8(p)
73  *     Return the 8-Bit (unsigned) int stored at <p>, the LOAD_ variants
74  *     then increment <p>.
75  *
76  *   void PUT_INT8(p, char c),   STORE_INT8(p, char c)
77  *   void PUT_UINT8(p, uchar c), STORE_UINT8(p, uchar c)
78  *     Store the 8-Bit (unsigned) int <c> into <p>, the STORE_ variants
79  *     then increment <p>.
80  *
81  *   void GET_SHORT ([unsigned] short d, bytecode_p p)
82  *   void LOAD_SHORT([unsigned] short d, bytecode_p p)
83  *     Load the (unsigned) short 'd' stored at <p>, the LOAD_ variant
84  *     then increments <p>.
85  *     TODO: Currently, all SHORTs must be 2 bytes.
86  *
87  *   void PUT_SHORT (bytecode_p p, [unsigned] short d)
88  *   void STORE_SHORT(bytecode_p p, [unsigned] short d)
89  *   void RSTORE_SHORT(bytecode_p p, [unsigned] short d)
90  *     Store the (unsigned) short <d> into <p>, the STORE_ variant
91  *     then increments <p>. The RSTORE_ variant pre-decrements <p>.
92  *     TODO: Currently, all SHORTs must be 2 bytes.
93  *
94  *   void GET_INT16 ([unsigned] int16 d, bytecode_p p)
95  *   void LOAD_INT16([unsigned] int16 d, bytecode_p p)
96  *     Load the (unsigned) int16 'd' stored at <p>, the LOAD_ variant
97  *     then increments <p>.
98  *
99  *   void GET_LONG ([unsigned] long d, bytecode_p p)
100  *   void LOAD_LONG([unsigned] long d, bytecode_p p)
101  *     Load the (unsigned) long 'd' stored at <p>, the LOAD_ variant
102  *     then increments <p>.
103  *     TODO: Currently, all LONGs must be 4 bytes.
104  *
105  *   void PUT_LONG (bytecode_p p, [unsigned] long d)
106  *   void STORE_LONG(bytecode_p p, [unsigned] long d)
107  *   void RSTORE_LONG(bytecode_p p, [unsigned] long d)
108  *     Store the (unsigned) long <d> into <p>, the STORE_ variant
109  *     then increments <p>. The RSTORE_ variant pre-decrements <p>.
110  *     TODO: Currently, all LONGs must be 4 bytes.
111  *
112  *   void LOAD_INT32([unsigned] int32 d, bytecode_p p)
113  *   void GET_INT32([unsigned] int32 d, bytecode_p p)
114  *     Load the (unsigned) in32 'd' stored at <p>, the LOAD_ variant
115  *     then increments <p>.
116  *
117  *   void STORE_INT32([unsigned] int32 d, bytecode_p p)
118  *   void PUT_INT32([unsigned] int32 d, bytecode_p p)
119  *     Store the (unsigned) int32 'd' at <p>, the STORE_ variant
120  *     then increments <p>.
121  */
122 
123 #if CHAR_BIT == 8
124 typedef unsigned char   bytecode_t;
125 typedef bytecode_t    * bytecode_p;
126 
127 #define GET_CODE(p)      (*(p))
128 #define LOAD_CODE(p)     (*(p)++)
129 
130 #define PUT_CODE(p,c)    (*(p) = (c))
131 #define STORE_CODE(p,c)  (*(p)++ = (c))
132 #define RSTORE_CODE(p,c)  (*--(p) = (c))
133 
134 /* TODO: all these casts yield rvalues, so they shouldn't compile
135  * TODO:: (and on xlc on AIX some of them indeed don't).
136  */
137 #define GET_UINT8(p)     (*((unsigned char *)(p)))
138 #define GET_INT8(p)      (*((signed char *)(p)))
139 #define LOAD_UINT8(p)    (*((unsigned char *)(p)++))
140 #define LOAD_INT8(p)     (*((signed char *)(p)++))
141 
142 #define PUT_UINT8(p,c)   (*((unsigned char *)(p)) = (c))
143 #define PUT_INT8(p,c)    (*((signed char *)(p)) = (c))
144 #define STORE_UINT8(p,c) (*((unsigned char *)(p)++) = (c))
145 #define STORE_INT8(p,c)  (*((signed char *)(p)++) = (c))
146 
147 /* TODO: These generic mem-macros should go into a macros.h. See also
148  * TODO:: how mudos does it.
149  * Note: the lowlevel BYTE macros can't use MACRO(), since this is
150  * needed on the next abstraction level, and a macro can't be nested
151  * into itself.
152  */
153 #define LOAD_2BYTE(d,p) ( ((char *)&(d))[0] = *(char *)(p)++, \
154                           ((char *)&(d))[1] = *(char *)(p)++)
155 
156 #define GET_2BYTE(d,p)  ( ((char *)&(d))[0] = ((char *)(p))[0], \
157                           ((char *)&(d))[1] = ((char *)(p))[1] )
158 
159 #define STORE_2BYTE(p,d) do {\
160                              unsigned char * _q, ** _qq; \
161                              _q = (unsigned char *)(p); \
162                              _qq = (unsigned char **)&(p); \
163                              _q[0] = ((unsigned char *)&(d))[0]; \
164                              _q[1] = ((unsigned char *)&(d))[1]; \
165                              *_qq += 2; \
166                          } while(0)
167 
168 #define RSTORE_2BYTE(p,d) do {\
169                              unsigned char * _q, ** _qq; \
170                              _q = (unsigned char *)(p); \
171                              _qq = (unsigned char **)&(p); \
172                              _q[-2] = ((unsigned char *)&(d))[0]; \
173                              _q[-1] = ((unsigned char *)&(d))[1]; \
174                              *_qq -= 2; \
175                          } while(0)
176 
177 #define PUT_2BYTE(p,d)  ( ((char *)(p))[0] = ((char *)&(d))[0], \
178                           ((char *)(p))[1] = ((char *)&(d))[1] )
179 
180 #define LOAD_3BYTE(d,p) ( (d) =   ((*(unsigned char *)(p)++) << 16) \
181                                 | ((*(unsigned char *)(p)++) <<  8) \
182                                 | (*(unsigned char *)(p)++) )
183 
184 #define GET_3BYTE(d,p) ( (d) =   ((((unsigned char *)(p))[0]) << 16) \
185                                | ((((unsigned char *)(p))[1]) <<  8) \
186                                | (((unsigned char *)(p))[2]) )
187 
188 #define STORE_3BYTE(p,d) do {\
189                              unsigned char * _q, ** _qq; \
190                              unsigned long _d = (unsigned long)(d); \
191                              _q = (unsigned char *)(p); \
192                              _qq = (unsigned char **)&(p); \
193                              _q[0] = (unsigned char) (_d >> 16) \
194                              _q[1] = (unsigned char) (_d >> 8) \
195                              _q[2] = (unsigned char) (_d) \
196                              *_qq += 3; \
197                          } while(0)
198 
199 #define PUT_3BYTE(p,d)  ( ((unsigned char *)(p))[0] = (unsigned char)((d) >> 16), \
200                           ((unsigned char *)(p))[1] = (unsigned char)((d) >> 8), \
201                           ((unsigned char *)(p))[2] = (unsigned char)(d) )
202 
203 #define LOAD_4BYTE(d,p) ( ((char *)&(d))[0] = *(char *)(p)++, \
204                           ((char *)&(d))[1] = *(char *)(p)++, \
205                           ((char *)&(d))[2] = *(char *)(p)++, \
206                           ((char *)&(d))[3] = *(char *)(p)++ )
207 
208 #define GET_4BYTE(d,p)  ( ((char *)&(d))[0] = ((char *)(p))[0], \
209                           ((char *)&(d))[1] = ((char *)(p))[1], \
210                           ((char *)&(d))[2] = ((char *)(p))[2], \
211                           ((char *)&(d))[3] = ((char *)(p))[3] )
212 
213 #define STORE_4BYTE(p,d) ( *(unsigned char *)(p)++ = ((char *)&(d))[0], \
214                            *(unsigned char *)(p)++ = ((char *)&(d))[1], \
215                            *(unsigned char *)(p)++ = ((char *)&(d))[2], \
216                            *(unsigned char *)(p)++ = ((char *)&(d))[3] )
217 
218 #define PUT_4BYTE(p,d)  ( ((char *)(p))[0] = ((char *)&(d))[0], \
219                           ((char *)(p))[1] = ((char *)&(d))[1], \
220                           ((char *)(p))[2] = ((char *)&(d))[2], \
221                           ((char *)(p))[3] = ((char *)&(d))[3] )
222 
223 
224 #if SIZEOF_SHORT == 2
225 #  define GET_SHORT(d,p)    GET_2BYTE(d,p)
226 #  define LOAD_SHORT(d,p)   LOAD_2BYTE(d,p)
227 #  define PUT_SHORT(p,d)    MACRO(unsigned short _us = (unsigned short)d; \
228                                   PUT_2BYTE(p,_us);)
229 #  define STORE_SHORT(p,d)  MACRO(unsigned short _us = (unsigned short)d; \
230                                  STORE_2BYTE(p,_us);)
231 #  define RSTORE_SHORT(p,d) MACRO(unsigned short _us = (unsigned short)d; \
232                                  RSTORE_2BYTE(p,_us);)
233 #else
234 #  error "Unsupported size of short."
235 #endif /* SIZEOF_SHORT */
236 
237 #if SIZEOF_LONG == 4
238 #  define GET_LONG(d,p)    GET_4BYTE(d,p)
239 #  define LOAD_LONG(d,p)   LOAD_4BYTE(d,p)
240 #  define PUT_LONG(p,d)    MACRO(unsigned long _us = (unsigned long)d; \
241                                  PUT_4BYTE(p,_us);)
242 #  define STORE_LONG(p,d)  MACRO(unsigned long _us = (unsigned long)d; \
243                                  STORE_4BYTE(p,_us);)
244 #  define RSTORE_LONG(p,d) MACRO(unsigned long _us = (unsigned long)d; \
245                                  RSTORE_4BYTE(p,_us);)
246 #elif SIZEOF_LONG == 8 && SIZEOF_INT == 4
247 #  define GET_LONG(d,p)    MACRO(int _ui; GET_4BYTE(_ui,p); \
248                                  d = _ui;)
249 #  define LOAD_LONG(d,p)   MACRO(int _ui; LOAD_4BYTE(_ui,p); \
250                                  d = _ui;)
251 #  define PUT_LONG(p,d)    MACRO(unsigned int _ui = (unsigned int)d; \
252                                  PUT_4BYTE(p,_ui);)
253 #  define STORE_LONG(p,d)  MACRO(unsigned int _ui = (unsigned int)d; \
254                                  STORE_4BYTE(p,_ui);)
255 #  define RSTORE_LONG(p,d) MACRO(unsigned int _ui = (unsigned int)d; \
256                                  RSTORE_4BYTE(p,_ui);)
257 #else
258 #  error "Unsupported size of long."
259 #endif /* SIZEOF_LONG */
260 
261 #define LOAD_INT16(d,p)  LOAD_2BYTE(d,p)
262 
263 #define LOAD_INT32(d,p)  LOAD_4BYTE(d,p)
264 #define GET_INT32(d,p)   GET_4BYTE(d,p)
265 #define PUT_INT32(p,d)   PUT_4BYTE(p,d)
266 #define STORE_INT32(p,d) STORE_4BYTE(p,d)
267 
268 #endif /* CHAR_BIT */
269 
270 #ifndef GET_CODE
271 #  error "No bytecode type defined."
272 #endif
273 
274 /***************************************************************************/
275 
276 #endif /* BYTECODE_H__ */
277