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