Merge pull request #654 from pcercuei/lightrec-mmap-zero
[pcsx_rearmed.git] / deps / lightning / check / lightning.c
1 /*
2  * Copyright (C) 2012-2019  Free Software Foundation, Inc.
3  *
4  * This file is part of GNU lightning.
5  *
6  * GNU lightning is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published
8  * by the Free Software Foundation; either version 3, or (at your option)
9  * any later version.
10  *
11  * GNU lightning is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14  * License for more details.
15  *
16  * Authors:
17  *      Paulo Cesar Pereira de Andrade
18  */
19
20 #if HAVE_CONFIG_H
21 # include "config.h"
22 #endif
23
24 #if HAVE_GETOPT_H
25 #  include <getopt.h>
26 #else
27 #  include <unistd.h>
28 #endif
29 #include <stdio.h>
30 #include <stdarg.h>
31 #include <lightning.h>
32 #include <dlfcn.h>
33
34 #if defined(__linux__) && (defined(__i386__) || defined(__x86_64__))
35 #  include <fpu_control.h>
36 #endif
37
38 /* The label_t identifier clashes with a system definitions */
39 #if defined(_AIX) || defined(__sun__) || defined(__osf__)
40 #  define label_t               l_label_t
41 #endif
42
43 #if defined(__hpux)
44 #  define DL_HANDLE             RTLD_NEXT
45 #elif defined(__sgi)
46 static void                     *DL_HANDLE;
47 #elif defined(__osf__)
48 #  define DL_HANDLE             NULL
49 #else
50 #  define DL_HANDLE             RTLD_DEFAULT
51 #endif
52
53 #if defined(__GNUC__)
54 #  define noreturn              __attribute__ ((noreturn))
55 #  define printf_format(f, v)   __attribute__ ((format (printf, f, v)))
56 #  define maybe_unused          __attribute__ ((unused))
57 #else
58 #  define noreturn              /**/
59 #  define printf_format(f, v)   /**/
60 #  define maybe_unused          /**/
61 #endif
62
63 #define check_data(length)                                              \
64     do {                                                                \
65         if (data_offset + length > data_length)                         \
66             error(".data too small (%ld < %ld)",                        \
67                   data_length, data_offset + length);                   \
68     } while (0)
69
70 #define get_label_by_name(name) ((label_t *)get_hash(labels, name))
71
72 #define PARSING_NONE            0
73 #define PARSING_DATA            1
74 #define PARSING_CODE            2
75 #define MAX_IDENTIFIER          256
76
77 /*
78  * Types
79  */
80 typedef struct instr              instr_t;
81 typedef union value               value_t;
82 typedef struct parser             parser_t;
83 typedef struct label              label_t;
84 typedef struct patch              patch_t;
85 typedef struct symbol             symbol_t;
86 typedef struct hash               hash_t;
87 typedef struct entry              entry_t;
88 typedef int                     (*function_t)(int argc, char *argv[]);
89
90 typedef enum {
91     tok_eof = -1,
92     tok_symbol,
93     tok_char,
94     tok_int,
95     tok_float,
96     tok_pointer,
97     tok_string,
98     tok_register,
99     tok_dot,
100     tok_newline,
101     tok_semicollon,
102 } token_t;
103
104 typedef enum {
105     skip_none,
106     skip_ws,
107     skip_nl,
108 } skip_t;
109
110 typedef enum {
111     type_none,
112     type_c,
113     type_s,
114     type_i,
115     type_l,
116     type_f,
117     type_d,
118     type_p,
119 } type_t;
120
121 #define compose(a, b)           (((a) << 8) | b)
122 typedef enum {
123     expr_inc     = compose('+', '+'),
124     expr_dec     = compose('-', '-'),
125     expr_not     = '!',
126     expr_com     = '~',
127     expr_mul     = '*',
128     expr_div     = '/',
129     expr_rem     = '%',
130     expr_add     = '+',
131     expr_sub     = '-',
132     expr_lsh     = compose('<', '<'),
133     expr_rsh     = compose('>', '>'),
134     expr_and     = '&',
135     expr_or      = '|',
136     expr_xor     = '^',
137     expr_set     = '=',
138     expr_mulset  = compose('*', '='),
139     expr_divset  = compose('/', '='),
140     expr_remset  = compose('%', '='),
141     expr_addset  = compose('+', '='),
142     expr_subset  = compose('-', '='),
143     expr_lshset  = compose(expr_lsh, '='),
144     expr_rshset  = compose(expr_rsh, '='),
145     expr_andset  = compose('&', '='),
146     expr_orset   = compose('|', '='),
147     expr_xorset  = compose('^', '='),
148     expr_lt      = '<',
149     expr_le      = compose('<', '='),
150     expr_eq      = compose('=', '='),
151     expr_ne      = compose('!', '='),
152     expr_gt      = '>',
153     expr_ge      = compose('>', '='),
154     expr_andand  = compose('&', '&'),
155     expr_oror    = compose('|', '|'),
156     expr_lparen  = '(',
157     expr_rparen  = ')',
158     expr_int     = '0',
159     expr_float   = '.',
160     expr_pointer = '@',
161     expr_symbol  = '$',
162 } expr_t;
163 #undef compose
164
165 struct instr {
166     instr_t              *next;
167     const char           *name;
168     void                (*function)(void);
169     int                   flag;
170 };
171
172 union value {
173     jit_word_t           i;
174     jit_uword_t          ui;
175     float                f;
176     double               d;
177     void                *p;
178     char                *cp;
179     label_t             *label;
180     patch_t             *patch;
181 };
182
183 struct parser {
184     FILE                *fp;
185     char                 name[256];
186     int                  line;
187     int                  regval;
188     type_t               regtype;
189     expr_t               expr;
190     type_t               type;
191     value_t              value;
192
193     /* variable length string buffer */
194     char                *string;
195     int                  length;
196     int                  offset;
197
198     int                  newline;
199     expr_t               putback;
200     int                  short_circuit;
201     int                  parsing;
202
203     struct {
204         unsigned char    buffer[4096];
205         int              offset;
206         int              length;
207     } data;
208 };
209
210 typedef enum {
211     label_kind_data,
212     label_kind_code,
213     label_kind_code_forward,
214     label_kind_dynamic,
215 } label_kind_t;
216
217 struct hash {
218     entry_t             **entries;
219     int                   size;
220     int                   count;
221 };
222
223 struct entry {
224     entry_t              *next;
225     char                 *name;
226     void                 *value;
227     int                   flag;
228 };
229
230 struct label {
231     label_t             *next;
232     char                *name;
233     void                *value;
234     label_kind_t         kind;
235 };
236
237 typedef enum {
238     patch_kind_jmp,
239     patch_kind_mov,
240     patch_kind_call,
241 } patch_kind_t;
242
243 struct patch {
244     patch_t             *next;
245     label_t             *label;
246     void                *value;
247     patch_kind_t         kind;
248 };
249
250 /* minor support for expressions */
251 struct symbol {
252     symbol_t            *next;
253     char                *name;
254     value_t              value;
255     type_t               type;
256 };
257
258 /*
259  * Prototypes
260  */
261 static jit_gpr_t get_ireg(void);
262 static jit_fpr_t get_freg(void);
263 static symbol_t *get_symbol(void);
264 static void jmp_forward(void *value, label_t *label);
265 static void mov_forward(void *value, label_t *label);
266 static void call_forward(void *value, label_t *label);
267 static void make_arg(void *value);
268 static jit_pointer_t get_arg(void);
269 static jit_word_t get_imm(void);
270 static void live(void);
271 static void align(void);        static void name(void);
272 static void prolog(void);
273 static void frame(void);        static void tramp(void);
274 static void ellipsis(void);
275 static void allocai(void);      static void allocar(void);
276 static void arg(void);
277 static void getarg_c(void);     static void getarg_uc(void);
278 static void getarg_s(void);     static void getarg_us(void);
279 static void getarg_i(void);
280 #if __WORDSIZE == 64
281 static void getarg_ui(void);    static void getarg_l(void);
282 #endif
283 static void getarg(void);
284 static void putargr(void);      static void putargi(void);
285 static void addr(void);         static void addi(void);
286 static void addxr(void);        static void addxi(void);
287 static void addcr(void);        static void addci(void);
288 static void subr(void);         static void subi(void);
289 static void subxr(void);        static void subxi(void);
290 static void subcr(void);        static void subci(void);
291 static void rsbr(void);         static void rsbi(void);
292 static void mulr(void);         static void muli(void);
293 static void qmulr(void);        static void qmuli(void);
294 static void qmulr_u(void);      static void qmuli_u(void);
295 static void divr(void);         static void divi(void);
296 static void divr_u(void);       static void divi_u(void);
297 static void qdivr(void);        static void qdivi(void);
298 static void qdivr_u(void);      static void qdivi_u(void);
299 static void remr(void);         static void remi(void);
300 static void remr_u(void);       static void remi_u(void);
301 static void andr(void);         static void andi(void);
302 static void orr(void);          static void ori(void);
303 static void xorr(void);         static void xori(void);
304 static void lshr(void);         static void lshi(void);
305 static void rshr(void);         static void rshi(void);
306 static void rshr_u(void);       static void rshi_u(void);
307 static void negr(void);         static void comr(void);
308 static void ltr(void);          static void lti(void);
309 static void ltr_u(void);        static void lti_u(void);
310 static void ler(void);          static void lei(void);
311 static void ler_u(void);        static void lei_u(void);
312 static void eqr(void);          static void eqi(void);
313 static void ger(void);          static void gei(void);
314 static void ger_u(void);        static void gei_u(void);
315 static void gtr(void);          static void gti(void);
316 static void gtr_u(void);        static void gti_u(void);
317 static void ner(void);          static void nei(void);
318 static void movr(void);         static void movi(void);
319 static void extr_c(void);       static void extr_uc(void);
320 static void extr_s(void);       static void extr_us(void);
321 #if __WORDSIZE == 64
322 static void extr_i(void);       static void extr_ui(void);
323 #endif
324 static void htonr_us(void);     static void ntohr_us(void);
325 static void htonr_ui(void);     static void ntohr_ui(void);
326 #if __WORDSIZE == 64
327 static void htonr_ul(void);     static void ntohr_ul(void);
328 #endif
329 static void htonr(void);        static void ntohr(void);
330 static void movnr(void);        static void movzr(void);
331 static void ldr_c(void);        static void ldi_c(void);
332 static void ldr_uc(void);       static void ldi_uc(void);
333 static void ldr_s(void);        static void ldi_s(void);
334 static void ldr_us(void);       static void ldi_us(void);
335 static void ldr_i(void);        static void ldi_i(void);
336 #if __WORDSIZE == 64
337 static void ldr_ui(void);       static void ldi_ui(void);
338 static void ldr_l(void);        static void ldi_l(void);
339 #endif
340 static void ldr(void);          static void ldi(void);
341 static void ldxr_c(void);       static void ldxi_c(void);
342 static void ldxr_uc(void);      static void ldxi_uc(void);
343 static void ldxr_s(void);       static void ldxi_s(void);
344 static void ldxr_us(void);      static void ldxi_us(void);
345 static void ldxr_i(void);       static void ldxi_i(void);
346 #if __WORDSIZE == 64
347 static void ldxr_ui(void);      static void ldxi_ui(void);
348 static void ldxr_l(void);       static void ldxi_l(void);
349 #endif
350 static void ldxr(void);         static void ldxi(void);
351 static void str_c(void);        static void sti_c(void);
352 static void str_s(void);        static void sti_s(void);
353 static void str_i(void);        static void sti_i(void);
354 #if __WORDSIZE == 64
355 static void str_l(void);        static void sti_l(void);
356 #endif
357 static void str(void);          static void sti(void);
358 static void stxr_c(void);       static void stxi_c(void);
359 static void stxr_s(void);       static void stxi_s(void);
360 static void stxr_i(void);       static void stxi_i(void);
361 #if __WORDSIZE == 64
362 static void stxr_l(void);       static void stxi_l(void);
363 #endif
364 static void stxr(void);         static void stxi(void);
365 static void bltr(void);         static void blti(void);
366 static void bltr_u(void);       static void blti_u(void);
367 static void bler(void);         static void blei(void);
368 static void bler_u(void);       static void blei_u(void);
369 static void beqr(void);         static void beqi(void);
370 static void bger(void);         static void bgei(void);
371 static void bger_u(void);       static void bgei_u(void);
372 static void bgtr(void);         static void bgti(void);
373 static void bgtr_u(void);       static void bgti_u(void);
374 static void bner(void);         static void bnei(void);
375 static void bmsr(void);         static void bmsi(void);
376 static void bmcr(void);         static void bmci(void);
377 static void boaddr(void);       static void boaddi(void);
378 static void boaddr_u(void);     static void boaddi_u(void);
379 static void bxaddr(void);       static void bxaddi(void);
380 static void bxaddr_u(void);     static void bxaddi_u(void);
381 static void bosubr(void);       static void bosubi(void);
382 static void bosubr_u(void);     static void bosubi_u(void);
383 static void bxsubr(void);       static void bxsubi(void);
384 static void bxsubr_u(void);     static void bxsubi_u(void);
385 static void jmpr(void);         static void jmpi(void);
386 static void callr(void);        static void calli(void);
387 static void prepare(void);
388 static void pushargr(void);     static void pushargi(void);
389 static void finishr(void);      static void finishi(void);
390 static void ret(void);
391 static void retr(void);         static void reti(void);
392 static void retval_c(void);     static void retval_uc(void);
393 static void retval_s(void);     static void retval_us(void);
394 static void retval_i(void);
395 #if __WORDSIZE == 64
396 static void retval_ui(void);    static void retval_l(void);
397 #endif
398 static void retval(void);
399 static void epilog(void);
400 static void arg_f(void);        static void getarg_f(void);
401 static void putargr_f(void);    static void putargi_f(void);
402 static void addr_f(void);       static void addi_f(void);
403 static void subr_f(void);       static void subi_f(void);
404 static void rsbr_f(void);       static void rsbi_f(void);
405 static void mulr_f(void);       static void muli_f(void);
406 static void divr_f(void);       static void divi_f(void);
407 static void negr_f(void);       static void absr_f(void);
408 static void sqrtr_f(void);
409 static void ltr_f(void);        static void lti_f(void);
410 static void ler_f(void);        static void lei_f(void);
411 static void eqr_f(void);        static void eqi_f(void);
412 static void ger_f(void);        static void gei_f(void);
413 static void gtr_f(void);        static void gti_f(void);
414 static void ner_f(void);        static void nei_f(void);
415 static void unltr_f(void);      static void unlti_f(void);
416 static void unler_f(void);      static void unlei_f(void);
417 static void uneqr_f(void);      static void uneqi_f(void);
418 static void unger_f(void);      static void ungei_f(void);
419 static void ungtr_f(void);      static void ungti_f(void);
420 static void ltgtr_f(void);      static void ltgti_f(void);
421 static void ordr_f(void);       static void ordi_f(void);
422 static void unordr_f(void);     static void unordi_f(void);
423 static void truncr_f_i(void);
424 #if __WORDSIZE == 64
425 static void truncr_f_l(void);
426 #endif
427 static void truncr_f(void);
428 static void extr_f(void);       static void extr_d_f(void);
429 static void movr_f(void);       static void movi_f(void);
430 static void ldr_f(void);        static void ldi_f(void);
431 static void ldxr_f(void);       static void ldxi_f(void);
432 static void str_f(void);        static void sti_f(void);
433 static void stxr_f(void);       static void stxi_f(void);
434 static void bltr_f(void);       static void blti_f(void);
435 static void bler_f(void);       static void blei_f(void);
436 static void beqr_f(void);       static void beqi_f(void);
437 static void bger_f(void);       static void bgei_f(void);
438 static void bgtr_f(void);       static void bgti_f(void);
439 static void bner_f(void);       static void bnei_f(void);
440 static void bunltr_f(void);     static void bunlti_f(void);
441 static void bunler_f(void);     static void bunlei_f(void);
442 static void buneqr_f(void);     static void buneqi_f(void);
443 static void bunger_f(void);     static void bungei_f(void);
444 static void bungtr_f(void);     static void bungti_f(void);
445 static void bltgtr_f(void);     static void bltgti_f(void);
446 static void bordr_f(void);      static void bordi_f(void);
447 static void bunordr_f(void);    static void bunordi_f(void);
448 static void pushargr_f(void);   static void pushargi_f(void);
449 static void retr_f(void);       static void reti_f(void);
450 static void retval_f(void);
451 static void arg_d(void);        static void getarg_d(void);
452 static void putargr_d(void);    static void putargi_d(void);
453 static void addr_d(void);       static void addi_d(void);
454 static void subr_d(void);       static void subi_d(void);
455 static void rsbr_d(void);       static void rsbi_d(void);
456 static void mulr_d(void);       static void muli_d(void);
457 static void divr_d(void);       static void divi_d(void);
458 static void negr_d(void);       static void absr_d(void);
459 static void sqrtr_d(void);
460 static void ltr_d(void);        static void lti_d(void);
461 static void ler_d(void);        static void lei_d(void);
462 static void eqr_d(void);        static void eqi_d(void);
463 static void ger_d(void);        static void gei_d(void);
464 static void gtr_d(void);        static void gti_d(void);
465 static void ner_d(void);        static void nei_d(void);
466 static void unltr_d(void);      static void unlti_d(void);
467 static void unler_d(void);      static void unlei_d(void);
468 static void uneqr_d(void);      static void uneqi_d(void);
469 static void unger_d(void);      static void ungei_d(void);
470 static void ungtr_d(void);      static void ungti_d(void);
471 static void ltgtr_d(void);      static void ltgti_d(void);
472 static void ordr_d(void);       static void ordi_d(void);
473 static void unordr_d(void);     static void unordi_d(void);
474 static void truncr_d_i(void);
475 #if __WORDSIZE == 64
476 static void truncr_d_l(void);
477 #endif
478 static void truncr_d(void);
479 static void extr_d(void);       static void extr_f_d(void);
480 static void movr_d(void);       static void movi_d(void);
481 static void ldr_d(void);        static void ldi_d(void);
482 static void ldxr_d(void);       static void ldxi_d(void);
483 static void str_d(void);        static void sti_d(void);
484 static void stxr_d(void);       static void stxi_d(void);
485 static void bltr_d(void);       static void blti_d(void);
486 static void bler_d(void);       static void blei_d(void);
487 static void beqr_d(void);       static void beqi_d(void);
488 static void bger_d(void);       static void bgei_d(void);
489 static void bgtr_d(void);       static void bgti_d(void);
490 static void bner_d(void);       static void bnei_d(void);
491 static void bunltr_d(void);     static void bunlti_d(void);
492 static void bunler_d(void);     static void bunlei_d(void);
493 static void buneqr_d(void);     static void buneqi_d(void);
494 static void bunger_d(void);     static void bungei_d(void);
495 static void bungtr_d(void);     static void bungti_d(void);
496 static void bltgtr_d(void);     static void bltgti_d(void);
497 static void bordr_d(void);      static void bordi_d(void);
498 static void bunordr_d(void);    static void bunordi_d(void);
499 static void pushargr_d(void);   static void pushargi_d(void);
500 static void retr_d(void);       static void reti_d(void);
501 static void retval_d(void);
502 static void vastart(void);      static void vapush(void);
503 static void vaarg(void);        static void vaarg_d(void);
504 static void vaend(void);
505
506 static void error(const char *format, ...) noreturn printf_format(1, 2);
507 static void warn(const char *format, ...) printf_format(1, 2) maybe_unused;
508 static void message(const char *kind, const char *format, va_list ap);
509
510 static int getch(void);
511 static int getch_noeof(void);
512 static int ungetch(int ch);
513 static int skipws(void);
514 static int skipnl(void);
515 static int skipct(void);
516 static int skipcp(void);
517 static jit_word_t get_int(skip_t skip);
518 static jit_uword_t get_uint(skip_t skip);
519 static double get_float(skip_t skip);
520 static float make_float(double d);
521 static void *get_pointer(skip_t skip);
522 static label_t *get_label(skip_t skip);
523 static token_t regname(void);
524 static token_t identifier(int ch);
525 static void get_data(type_t type);
526 static void dot(void);
527 static token_t number(int ch);
528 static int escape(int ch);
529 static token_t string(void);
530 static token_t dynamic(void);
531 static token_t character(void);
532 static void expression_prim(void);
533 static void expression_inc(int pre);
534 static void expression_dec(int pre);
535 static void expression_unary(void);
536 static void expression_mul(void);
537 static void expression_add(void);
538 static void expression_shift(void);
539 static void expression_bit(void);
540 static void expression_rel(void);
541 static void expression_cond(void);
542 static token_t expression(void);
543 static token_t primary(skip_t skip);
544 static void parse(void);
545 static int execute(int argc, char *argv[]);
546
547 static void *xmalloc(size_t size);
548 static void *xrealloc(void *pointer, size_t size);
549 static void *xcalloc(size_t nmemb, size_t size);
550
551 static label_t *new_label(label_kind_t kind, char *name, void *value);
552 static patch_t *new_patch(patch_kind_t kind, label_t *label, void *value);
553 static int bcmp_symbols(const void *left, const void *right);
554 static int qcmp_symbols(const void *left, const void *right);
555 static symbol_t *new_symbol(char *name);
556 static symbol_t *get_symbol_by_name(char *name);
557
558 static hash_t *new_hash(void);
559 static int hash_string(char *name);
560 static void put_hash(hash_t *hash, entry_t *entry);
561 static entry_t *get_hash(hash_t *hash, char *name);
562 static void rehash(hash_t *hash);
563
564 /*
565  * Initialization
566  */
567 static jit_state_t       *_jit;
568 static int                flag_verbose;
569 static int                flag_data;
570 static int                flag_disasm;
571 static char              *progname;
572 static parser_t           parser;
573 static hash_t            *labels;
574 static int                label_offset;
575 static patch_t           *patches;
576 static symbol_t         **symbols;
577 static int                symbol_length;
578 static int                symbol_offset;
579 static hash_t            *instrs;
580 static char              *data;
581 static size_t             data_offset, data_length;
582 static instr_t            instr_vector[] = {
583 #define entry(value)    { NULL, #value, value }
584 #define entry2(name, function)  { NULL, name, function }
585     entry(live),
586     entry(align),       entry(name),
587     entry(prolog),
588     entry(frame),       entry(tramp),
589     entry(ellipsis),
590     entry(allocai),     entry(allocar),
591     entry(arg),
592     entry(getarg_c),    entry(getarg_uc),
593     entry(getarg_s),    entry(getarg_us),
594     entry(getarg_i),
595 #if __WORDSIZE == 64
596     entry(getarg_ui),   entry(getarg_l),
597 #endif
598     entry(getarg),
599     entry(putargr),     entry(putargi),
600     entry(addr),        entry(addi),
601     entry(addxr),       entry(addxi),
602     entry(addcr),       entry(addci),
603     entry(subr),        entry(subi),
604     entry(subxr),       entry(subxi),
605     entry(subcr),       entry(subci),
606     entry(rsbr),        entry(rsbi),
607     entry(mulr),        entry(muli),
608     entry(qmulr),       entry(qmuli),
609     entry(qmulr_u),     entry(qmuli_u),
610     entry(divr),        entry(divi),
611     entry(divr_u),      entry(divi_u),
612     entry(qdivr),       entry(qdivi),
613     entry(qdivr_u),     entry(qdivi_u),
614     entry(remr),        entry(remi),
615     entry(remr_u),      entry(remi_u),
616     entry(andr),        entry(andi),
617     entry(orr),         entry(ori),
618     entry(xorr),        entry(xori),
619     entry(lshr),        entry(lshi),
620     entry(rshr),        entry(rshi),
621     entry(rshr_u),      entry(rshi_u),
622     entry(negr),        entry(comr),
623     entry(ltr),         entry(lti),
624     entry(ltr_u),       entry(lti_u),
625     entry(ler),         entry(lei),
626     entry(ler_u),       entry(lei_u),
627     entry(eqr),         entry(eqi),
628     entry(ger),         entry(gei),
629     entry(ger_u),       entry(gei_u),
630     entry(gtr),         entry(gti),
631     entry(gtr_u),       entry(gti_u),
632     entry(ner),         entry(nei),
633     entry(movr),        entry(movi),
634     entry(extr_c),      entry(extr_uc),
635     entry(extr_s),      entry(extr_us),
636 #if __WORDSIZE == 64
637     entry(extr_i),      entry(extr_ui),
638 #endif
639     entry(htonr_us),    entry(ntohr_us),
640     entry(htonr_ui),    entry(ntohr_ui),
641 #if __WORDSIZE == 64
642     entry(htonr_ul),    entry(ntohr_ul),
643 #endif
644     entry(htonr),       entry(ntohr),
645     entry(movnr),       entry(movzr),
646     entry(ldr_c),       entry(ldi_c),
647     entry(ldr_uc),      entry(ldi_uc),
648     entry(ldr_s),       entry(ldi_s),
649     entry(ldr_us),      entry(ldi_us),
650     entry(ldr_i),       entry(ldi_i),
651 #if __WORDSIZE == 64
652     entry(ldr_ui),      entry(ldi_ui),
653     entry(ldr_l),       entry(ldi_l),
654 #endif
655     entry(ldr),         entry(ldi),
656     entry(ldxr_c),      entry(ldxi_c),
657     entry(ldxr_uc),     entry(ldxi_uc),
658     entry(ldxr_s),      entry(ldxi_s),
659     entry(ldxr_us),     entry(ldxi_us),
660     entry(ldxr_i),      entry(ldxi_i),
661 #if __WORDSIZE == 64
662     entry(ldxr_ui),     entry(ldxi_ui),
663     entry(ldxr_l),      entry(ldxi_l),
664 #endif
665     entry(ldxr),        entry(ldxi),
666     entry(str_c),       entry(sti_c),
667     entry(str_s),       entry(sti_s),
668     entry(str_i),       entry(sti_i),
669 #if __WORDSIZE == 64
670     entry(str_l),       entry(sti_l),
671 #endif
672     entry(str),         entry(sti),
673     entry(stxr_c),      entry(stxi_c),
674     entry(stxr_s),      entry(stxi_s),
675     entry(stxr_i),      entry(stxi_i),
676 #if __WORDSIZE == 64
677     entry(stxr_l),      entry(stxi_l),
678 #endif
679     entry(stxr),        entry(stxi),
680     entry(bltr),        entry(blti),
681     entry(bltr_u),      entry(blti_u),
682     entry(bler),        entry(blei),
683     entry(bler_u),      entry(blei_u),
684     entry(beqr),        entry(beqi),
685     entry(bger),        entry(bgei),
686     entry(bger_u),      entry(bgei_u),
687     entry(bgtr),        entry(bgti),
688     entry(bgtr_u),      entry(bgti_u),
689     entry(bner),        entry(bnei),
690     entry(bmsr),        entry(bmsi),
691     entry(bmcr),        entry(bmci),
692     entry(boaddr),      entry(boaddi),
693     entry(boaddr_u),    entry(boaddi_u),
694     entry(bxaddr),      entry(bxaddi),
695     entry(bxaddr_u),    entry(bxaddi_u),
696     entry(bosubr),      entry(bosubi),
697     entry(bosubr_u),    entry(bosubi_u),
698     entry(bxsubr),      entry(bxsubi),
699     entry(bxsubr_u),    entry(bxsubi_u),
700     entry(jmpr),        entry(jmpi),
701     entry(callr),       entry(calli),
702     entry(prepare),
703     entry(pushargr),    entry(pushargi),
704     entry(finishr),     entry(finishi),
705     entry(ret),
706     entry(retr),        entry(reti),
707     entry(retval_c),    entry(retval_uc),
708     entry(retval_s),    entry(retval_us),
709     entry(retval_i),
710 #if __WORDSIZE == 64
711     entry(retval_ui),   entry(retval_l),
712 #endif
713     entry(retval),
714     entry(epilog),
715     entry(arg_f),       entry(getarg_f),
716     entry(putargr_f),   entry(putargi_f),
717     entry(addr_f),      entry(addi_f),
718     entry(subr_f),      entry(subi_f),
719     entry(rsbr_f),      entry(rsbi_f),
720     entry(mulr_f),      entry(muli_f),
721     entry(divr_f),      entry(divi_f),
722     entry(negr_f),      entry(absr_f),
723     entry(sqrtr_f),
724     entry(ltr_f),       entry(lti_f),
725     entry(ler_f),       entry(lei_f),
726     entry(eqr_f),       entry(eqi_f),
727     entry(ger_f),       entry(gei_f),
728     entry(gtr_f),       entry(gti_f),
729     entry(ner_f),       entry(nei_f),
730     entry(unltr_f),     entry(unlti_f),
731     entry(unler_f),     entry(unlei_f),
732     entry(uneqr_f),     entry(uneqi_f),
733     entry(unger_f),     entry(ungei_f),
734     entry(ungtr_f),     entry(ungti_f),
735     entry(ltgtr_f),     entry(ltgti_f),
736     entry(ordr_f),      entry(ordi_f),
737     entry(unordr_f),    entry(unordi_f),
738     entry(truncr_f_i),
739 #if __WORDSIZE == 64
740     entry(truncr_f_l),
741 #endif
742     entry(truncr_f),
743     entry(extr_f),      entry(extr_d_f),
744     entry(movr_f),      entry(movi_f),
745     entry(ldr_f),       entry(ldi_f),
746     entry(ldxr_f),      entry(ldxi_f),
747     entry(str_f),       entry(sti_f),
748     entry(stxr_f),      entry(stxi_f),
749     entry(bltr_f),      entry(blti_f),
750     entry(bler_f),      entry(blei_f),
751     entry(beqr_f),      entry(beqi_f),
752     entry(bger_f),      entry(bgei_f),
753     entry(bgtr_f),      entry(bgti_f),
754     entry(bner_f),      entry(bnei_f),
755     entry(bunltr_f),    entry(bunlti_f),
756     entry(bunler_f),    entry(bunlei_f),
757     entry(buneqr_f),    entry(buneqi_f),
758     entry(bunger_f),    entry(bungei_f),
759     entry(bungtr_f),    entry(bungti_f),
760     entry(bltgtr_f),    entry(bltgti_f),
761     entry(bordr_f),     entry(bordi_f),
762     entry(bunordr_f),   entry(bunordi_f),
763     entry(pushargr_f),  entry(pushargi_f),
764     entry(retr_f),      entry(reti_f),
765     entry(retval_f),
766     entry(arg_d),       entry(getarg_d),
767     entry(putargr_d),   entry(putargi_d),
768     entry(addr_d),      entry(addi_d),
769     entry(subr_d),      entry(subi_d),
770     entry(rsbr_d),      entry(rsbi_d),
771     entry(mulr_d),      entry(muli_d),
772     entry(divr_d),      entry(divi_d),
773     entry(negr_d),      entry(absr_d),
774     entry(sqrtr_d),
775     entry(ltr_d),       entry(lti_d),
776     entry(ler_d),       entry(lei_d),
777     entry(eqr_d),       entry(eqi_d),
778     entry(ger_d),       entry(gei_d),
779     entry(gtr_d),       entry(gti_d),
780     entry(ner_d),       entry(nei_d),
781     entry(unltr_d),     entry(unlti_d),
782     entry(unler_d),     entry(unlei_d),
783     entry(uneqr_d),     entry(uneqi_d),
784     entry(unger_d),     entry(ungei_d),
785     entry(ungtr_d),     entry(ungti_d),
786     entry(ltgtr_d),     entry(ltgti_d),
787     entry(ordr_d),      entry(ordi_d),
788     entry(unordr_d),    entry(unordi_d),
789     entry(truncr_d_i),
790 #if __WORDSIZE == 64
791     entry(truncr_d_l),
792 #endif
793     entry(truncr_d),
794     entry(extr_d),      entry(extr_f_d),
795     entry(movr_d),      entry(movi_d),
796     entry(ldr_d),       entry(ldi_d),
797     entry(ldxr_d),      entry(ldxi_d),
798     entry(str_d),       entry(sti_d),
799     entry(stxr_d),      entry(stxi_d),
800     entry(bltr_d),      entry(blti_d),
801     entry(bler_d),      entry(blei_d),
802     entry(beqr_d),      entry(beqi_d),
803     entry(bger_d),      entry(bgei_d),
804     entry(bgtr_d),      entry(bgti_d),
805     entry(bner_d),      entry(bnei_d),
806     entry(bunltr_d),    entry(bunlti_d),
807     entry(bunler_d),    entry(bunlei_d),
808     entry(buneqr_d),    entry(buneqi_d),
809     entry(bunger_d),    entry(bungei_d),
810     entry(bungtr_d),    entry(bungti_d),
811     entry(bltgtr_d),    entry(bltgti_d),
812     entry(bordr_d),     entry(bordi_d),
813     entry(bunordr_d),   entry(bunordi_d),
814     entry(pushargr_d),  entry(pushargi_d),
815     entry(retr_d),      entry(reti_d),
816     entry(retval_d),
817     entry2("va_start", vastart),
818     entry2("va_push", vapush),
819     entry2("va_arg", vaarg),
820     entry2("va_arg_d", vaarg_d),
821     entry2("va_end", vaend),
822 #undef entry
823 };
824
825 /*
826  * Implementation
827  */
828 static jit_gpr_t
829 get_ireg(void)
830 {
831     if (primary(skip_ws) != tok_register)
832         error("bad register");
833     if (parser.regtype != type_l)
834         error("bad int register");
835
836     return ((jit_gpr_t)parser.regval);
837 }
838
839 static jit_fpr_t
840 get_freg(void)
841 {
842     if (primary(skip_ws) != tok_register)
843         error("bad register");
844     if (parser.regtype != type_d)
845         error("bad float register");
846
847     return ((jit_fpr_t)parser.regval);
848 }
849
850 static symbol_t *
851 get_symbol(void)
852 {
853     symbol_t    *symbol;
854     int          ch = skipws();
855
856     if (ch != '$')
857         error("expecting variable");
858     (void)identifier('$');
859     if (parser.string[1] == '\0')
860         error("expecting variable");
861     if ((symbol = get_symbol_by_name(parser.string)) == NULL)
862         symbol = new_symbol(parser.string);
863
864     return (symbol);
865 }
866
867 static void
868 jmp_forward(void *value, label_t *label)
869 {
870     (void)new_patch(patch_kind_jmp, label, value);
871 }
872
873 static void
874 mov_forward(void *value, label_t *label)
875 {
876     (void)new_patch(patch_kind_mov, label, value);
877 }
878
879 static void
880 call_forward(void *value, label_t *label)
881 {
882     (void)new_patch(patch_kind_call, label, value);
883 }
884
885 static void
886 make_arg(void *value)
887 {
888     symbol_t    *symbol = get_symbol();
889
890     symbol->type = type_p;
891     symbol->value.p = value;
892 }
893
894 static jit_pointer_t
895 get_arg(void)
896 {
897     symbol_t    *symbol = get_symbol();
898
899     if (symbol->type != type_p)
900         error("bad argument %s type", symbol->name);
901
902     return symbol->value.p;
903 }
904
905 static jit_word_t
906 get_imm(void)
907 {
908     int          ch;
909     label_t     *label;
910     jit_word_t   value;
911     ch = skipws();
912     switch (ch) {
913         case '+': case '-': case '0' ... '9':
914             ungetch(ch);
915             value = get_int(skip_none);
916             break;
917         case '\'':
918             character();
919             value = parser.value.i;
920             break;
921         case '$':
922             switch (expression()) {
923                 case tok_int:
924                 case tok_pointer:
925                     value = parser.value.i;
926                     break;
927                 default:
928                     error("expecting immediate");
929             }
930             break;
931         case '@':
932             dynamic();
933             value = (jit_word_t)parser.value.p;
934             break;
935         default:
936             ungetch(ch);
937             label = get_label(skip_none);
938             if (label->kind == label_kind_data)
939                 value = (jit_word_t)label->value;
940             else
941                 error("expecting immediate");
942             break;
943     }
944     return (value);
945 }
946
947 #define entry(name)                                                     \
948 static void                                                             \
949 name(void)                                                              \
950 {                                                                       \
951     jit_##name();                                                       \
952 }
953 #define entry_ca(name)                                                  \
954 static void                                                             \
955 name(void)                                                              \
956 {                                                                       \
957     make_arg(jit_##name());                                             \
958 }
959 #define entry_ia(name)                                                  \
960 static void                                                             \
961 name(void)                                                              \
962 {                                                                       \
963     jit_gpr_t           r0 = get_ireg();                                \
964     jit_pointer_t       ac = get_arg();                                 \
965     jit_##name(r0, ac);                                                 \
966 }
967 #define entry_im(name)                                                  \
968 static void                                                             \
969 name(void)                                                              \
970 {                                                                       \
971     jit_word_t   im = get_imm();                                        \
972     jit_##name(im);                                                     \
973 }
974 #define entry_ir(name)                                                  \
975 static void                                                             \
976 name(void)                                                              \
977 {                                                                       \
978     jit_gpr_t    r0 = get_ireg();                                       \
979     jit_##name(r0);                                                     \
980 }
981 #define entry_ima(name)                                                 \
982 static void                                                             \
983 name(void)                                                              \
984 {                                                                       \
985     jit_word_t          im = get_imm();                                 \
986     jit_pointer_t       ac = get_arg();                                 \
987     jit_##name(im, ac);                                                 \
988 }
989 #define entry_ir_ir_ir(name)                                            \
990 static void                                                             \
991 name(void)                                                              \
992 {                                                                       \
993     jit_gpr_t   r0 = get_ireg(), r1 = get_ireg(), r2 = get_ireg();      \
994     jit_##name(r0, r1, r2);                                             \
995 }
996 #define entry_ir_ir_im(name)                                            \
997 static void                                                             \
998 name(void)                                                              \
999 {                                                                       \
1000     jit_gpr_t   r0 = get_ireg(), r1 = get_ireg();                       \
1001     jit_word_t  im = get_imm();                                         \
1002     jit_##name(r0, r1, im);                                             \
1003 }
1004 #define entry_ir_ir_ir_ir(name)                                         \
1005 static void                                                             \
1006 name(void)                                                              \
1007 {                                                                       \
1008     jit_gpr_t   r0 = get_ireg(), r1 = get_ireg(),                       \
1009                 r2 = get_ireg(), r3 = get_ireg();                       \
1010     jit_##name(r0, r1, r2, r3);                                         \
1011 }
1012 #define entry_ir_ir_ir_im(name)                                         \
1013 static void                                                             \
1014 name(void)                                                              \
1015 {                                                                       \
1016     jit_gpr_t   r0 = get_ireg(), r1 = get_ireg(), r2 = get_ireg();      \
1017     jit_word_t  im = get_imm();                                         \
1018     jit_##name(r0, r1, r2, im);                                         \
1019 }
1020 #define entry_ir_ir(name)                                               \
1021 static void                                                             \
1022 name(void)                                                              \
1023 {                                                                       \
1024     jit_gpr_t   r0 = get_ireg(), r1 = get_ireg();                       \
1025     jit_##name(r0, r1);                                                 \
1026 }
1027 #define entry_ir_im(name)                                               \
1028 static void                                                             \
1029 name(void)                                                              \
1030 {                                                                       \
1031     jit_gpr_t   r0 = get_ireg();                                        \
1032     jit_word_t  im = get_imm();                                         \
1033     jit_##name(r0, im);                                                 \
1034 }
1035 #define entry_ir_pm(name)                                               \
1036 static void                                                             \
1037 name(void)                                                              \
1038 {                                                                       \
1039     jit_gpr_t    r0 = get_ireg();                                       \
1040     void        *pm = get_pointer(skip_ws);                             \
1041     jit_##name(r0, pm);                                                 \
1042 }
1043 #define entry_pm_ir(name)                                               \
1044 static void                                                             \
1045 name(void)                                                              \
1046 {                                                                       \
1047     void        *pm = get_pointer(skip_ws);                             \
1048     jit_gpr_t    r0 = get_ireg();                                       \
1049     jit_##name(pm, r0);                                                 \
1050 }
1051 #define entry_im_ir_ir(name)                                            \
1052 static void                                                             \
1053 name(void)                                                              \
1054 {                                                                       \
1055     jit_word_t  im = get_imm();                                         \
1056     jit_gpr_t   r0 = get_ireg(), r1 = get_ireg();                       \
1057     (void)jit_##name(im, r0, r1);                                       \
1058 }
1059 #define entry_lb_ir_ir(name)                                            \
1060 static void                                                             \
1061 name(void)                                                              \
1062 {                                                                       \
1063     jit_node_t  *jmp;                                                   \
1064     label_t     *label = get_label(skip_ws);                            \
1065     jit_gpr_t    r0 = get_ireg(), r1 = get_ireg();                      \
1066     if (label->kind == label_kind_code_forward)                         \
1067         jmp_forward((void *)jit_##name(r0, r1), label);                 \
1068     else {                                                              \
1069         jmp = jit_##name(r0, r1);                                       \
1070         jit_patch_at(jmp, (jit_node_t *)label->value);                  \
1071     }                                                                   \
1072 }
1073 #define entry_lb_ir_im(name)                                            \
1074 static void                                                             \
1075 name(void)                                                              \
1076 {                                                                       \
1077     jit_node_t  *jmp;                                                   \
1078     label_t     *label = get_label(skip_ws);                            \
1079     jit_gpr_t    r0 = get_ireg();                                       \
1080     jit_word_t   im = get_imm();                                        \
1081     if (label->kind == label_kind_code_forward)                         \
1082         jmp_forward((void *)jit_##name(r0, im), label);                 \
1083     else {                                                              \
1084         jmp = jit_##name(r0, im);                                       \
1085         jit_patch_at(jmp, (jit_node_t *)label->value);                  \
1086     }                                                                   \
1087 }
1088 #define entry_lb(name)                                                  \
1089 static void                                                             \
1090 name(void)                                                              \
1091 {                                                                       \
1092     jit_node_t  *jmp;                                                   \
1093     label_t     *label = get_label(skip_ws);                            \
1094     if (label->kind == label_kind_code_forward)                         \
1095         jmp_forward((void *)jit_##name(), label);                       \
1096     else {                                                              \
1097         jmp = jit_##name();                                             \
1098         jit_patch_at(jmp, (jit_node_t *)label->value);                  \
1099     }                                                                   \
1100 }
1101 #define entry_pm(name)                                                  \
1102 static void                                                             \
1103 name(void)                                                              \
1104 {                                                                       \
1105     void        *pm = get_pointer(skip_ws);                             \
1106     jit_##name(pm);                                                     \
1107 }
1108 #define entry_fa(name)                                                  \
1109 static void                                                             \
1110 name(void)                                                              \
1111 {                                                                       \
1112     jit_fpr_t           r0 = get_freg();                                \
1113     jit_pointer_t       ac = get_arg();                                 \
1114     jit_##name(r0, ac);                                                 \
1115 }
1116 #define entry_fma(name)                                                 \
1117 static void                                                             \
1118 name(void)                                                              \
1119 {                                                                       \
1120     jit_float64_t       im = get_float(skip_ws);                        \
1121     jit_pointer_t       ac = get_arg();                                 \
1122     jit_##name(im, ac);                                                 \
1123 }
1124 #define entry_fr_fr_fr(name)                                            \
1125 static void                                                             \
1126 name(void)                                                              \
1127 {                                                                       \
1128     jit_fpr_t   r0 = get_freg(), r1 = get_freg(), r2 = get_freg();      \
1129     jit_##name(r0, r1, r2);                                             \
1130 }
1131 #define entry_fr_fr_fm(name)                                            \
1132 static void                                                             \
1133 name(void)                                                              \
1134 {                                                                       \
1135     jit_fpr_t           r0 = get_freg(), r1 = get_freg();               \
1136     jit_float64_t       im = get_float(skip_ws);                        \
1137     jit_##name(r0, r1, make_float(im));                                 \
1138 }
1139 #define entry_fr_fr_dm(name)                                            \
1140 static void                                                             \
1141 name(void)                                                              \
1142 {                                                                       \
1143     jit_fpr_t           r0 = get_freg(), r1 = get_freg();               \
1144     jit_float64_t       im = get_float(skip_ws);                        \
1145     jit_##name(r0, r1, im);                                             \
1146 }
1147 #define entry_fr_fr(name)                                               \
1148 static void                                                             \
1149 name(void)                                                              \
1150 {                                                                       \
1151     jit_fpr_t   r0 = get_freg(), r1 = get_freg();                       \
1152     jit_##name(r0, r1);                                                 \
1153 }
1154 #define entry_ir_fr_fr(name)                                            \
1155 static void                                                             \
1156 name(void)                                                              \
1157 {                                                                       \
1158     jit_gpr_t   r0 = get_ireg();                                        \
1159     jit_fpr_t   r1 = get_freg(), r2 = get_freg();                       \
1160     jit_##name(r0, r1, r2);                                             \
1161 }
1162 #define entry_ir_fr_fm(name)                                            \
1163 static void                                                             \
1164 name(void)                                                              \
1165 {                                                                       \
1166     jit_gpr_t           r0 = get_ireg();                                \
1167     jit_fpr_t           r1 = get_freg();                                \
1168     jit_float64_t       im = get_float(skip_ws);                        \
1169     jit_##name(r0, r1, make_float(im));                                 \
1170 }
1171 #define entry_ir_fr_dm(name)                                            \
1172 static void                                                             \
1173 name(void)                                                              \
1174 {                                                                       \
1175     jit_gpr_t           r0 = get_ireg();                                \
1176     jit_fpr_t           r1 = get_freg();                                \
1177     jit_float64_t       im = get_float(skip_ws);                        \
1178     jit_##name(r0, r1, im);                                             \
1179 }
1180 #define entry_ir_fr(name)                                               \
1181 static void                                                             \
1182 name(void)                                                              \
1183 {                                                                       \
1184     jit_gpr_t   r0 = get_ireg();                                        \
1185     jit_fpr_t   r1 = get_freg();                                        \
1186     jit_##name(r0, r1);                                                 \
1187 }
1188 #define entry_fr_ir(name)                                               \
1189 static void                                                             \
1190 name(void)                                                              \
1191 {                                                                       \
1192     jit_fpr_t   r0 = get_freg();                                        \
1193     jit_gpr_t   r1 = get_ireg();                                        \
1194     jit_##name(r0, r1);                                                 \
1195 }
1196 #define entry_fr_fm(name)                                               \
1197 static void                                                             \
1198 name(void)                                                              \
1199 {                                                                       \
1200     jit_fpr_t           r0 = get_freg();                                \
1201     jit_float64_t       im = get_float(skip_ws);                        \
1202     jit_##name(r0, make_float(im));                                     \
1203 }
1204 #define entry_fr_dm(name)                                               \
1205 static void                                                             \
1206 name(void)                                                              \
1207 {                                                                       \
1208     jit_fpr_t           r0 = get_freg();                                \
1209     jit_float64_t       im = get_float(skip_ws);                        \
1210     jit_##name(r0, im);                                                 \
1211 }
1212 #define entry_fr_pm(name)                                               \
1213 static void                                                             \
1214 name(void)                                                              \
1215 {                                                                       \
1216     jit_fpr_t    r0 = get_freg();                                       \
1217     void        *pm = get_pointer(skip_ws);                             \
1218     jit_##name(r0, pm);                                                 \
1219 }
1220 #define entry_fr_ir_ir(name)                                            \
1221 static void                                                             \
1222 name(void)                                                              \
1223 {                                                                       \
1224     jit_fpr_t   r0 = get_freg();                                        \
1225     jit_gpr_t   r1 = get_ireg(), r2 = get_ireg();                       \
1226     jit_##name(r0, r1, r2);                                             \
1227 }
1228 #define entry_fr_ir_im(name)                                            \
1229 static void                                                             \
1230 name(void)                                                              \
1231 {                                                                       \
1232     jit_fpr_t   r0 = get_freg();                                        \
1233     jit_gpr_t   r1 = get_ireg();                                        \
1234     jit_word_t  im = get_imm();                                         \
1235     jit_##name(r0, r1, im);                                             \
1236 }
1237 #define entry_pm_fr(name)                                               \
1238 static void                                                             \
1239 name(void)                                                              \
1240 {                                                                       \
1241     void        *pm = get_pointer(skip_ws);                             \
1242     jit_fpr_t    r0 = get_freg();                                       \
1243     jit_##name(pm, r0);                                                 \
1244 }
1245 #define entry_ir_ir_fr(name)                                            \
1246 static void                                                             \
1247 name(void)                                                              \
1248 {                                                                       \
1249     jit_gpr_t   r0 = get_ireg(), r1 = get_ireg();                       \
1250     jit_fpr_t   r2 = get_freg();                                        \
1251     jit_##name(r0, r1, r2);                                             \
1252 }
1253 #define entry_im_ir_fr(name)                                            \
1254 static void                                                             \
1255 name(void)                                                              \
1256 {                                                                       \
1257     jit_word_t  im = get_imm();                                         \
1258     jit_gpr_t   r0 = get_ireg();                                        \
1259     jit_fpr_t   r1 = get_freg();                                        \
1260     jit_##name(im, r0, r1);                                             \
1261 }
1262 #define entry_lb_fr_fr(name)                                            \
1263 static void                                                             \
1264 name(void)                                                              \
1265 {                                                                       \
1266     jit_node_t  *jmp;                                                   \
1267     label_t     *label = get_label(skip_ws);                            \
1268     jit_fpr_t    r0 = get_freg(), r1 = get_freg();                      \
1269     if (label->kind == label_kind_code_forward)                         \
1270         jmp_forward((void *)jit_##name(r0, r1), label);                 \
1271     else {                                                              \
1272         jmp = jit_##name(r0, r1);                                       \
1273         jit_patch_at(jmp, (jit_node_t *)label->value);                  \
1274     }                                                                   \
1275 }
1276 #define entry_lb_fr_fm(name)                                            \
1277 static void                                                             \
1278 name(void)                                                              \
1279 {                                                                       \
1280     jit_node_t          *jmp;                                           \
1281     label_t             *label = get_label(skip_ws);                    \
1282     jit_fpr_t            r0 = get_freg();                               \
1283     jit_float64_t        im = get_float(skip_ws);                       \
1284     if (label->kind == label_kind_code_forward)                         \
1285         jmp_forward((void *)jit_##name(r0, make_float(im)), label);     \
1286     else {                                                              \
1287         jmp = jit_##name(r0, make_float(im));                           \
1288         jit_patch_at(jmp, (jit_node_t *)label->value);                  \
1289     }                                                                   \
1290 }
1291 #define entry_lb_fr_dm(name)                                            \
1292 static void                                                             \
1293 name(void)                                                              \
1294 {                                                                       \
1295     jit_node_t          *jmp;                                           \
1296     label_t             *label = get_label(skip_ws);                    \
1297     jit_fpr_t            r0 = get_freg();                               \
1298     jit_float64_t        im = get_float(skip_ws);                       \
1299     if (label->kind == label_kind_code_forward)                         \
1300         jmp_forward((void *)jit_##name(r0, im), label);                 \
1301     else {                                                              \
1302         jmp = jit_##name(r0, im);                                       \
1303         jit_patch_at(jmp, (jit_node_t *)label->value);                  \
1304     }                                                                   \
1305 }
1306 #define entry_fr(name)                                                  \
1307 static void                                                             \
1308 name(void)                                                              \
1309 {                                                                       \
1310     jit_fpr_t   r0 = get_freg();                                        \
1311     jit_##name(r0);                                                     \
1312 }
1313 #define entry_fm(name)                                                  \
1314 static void                                                             \
1315 name(void)                                                              \
1316 {                                                                       \
1317     jit_float64_t       im = get_float(skip_ws);                        \
1318     jit_##name(make_float(im));                                         \
1319 }
1320 #define entry_dm(name)                                                  \
1321 static void                                                             \
1322 name(void)                                                              \
1323 {                                                                       \
1324     jit_float64_t       im = get_float(skip_ws);                        \
1325     jit_##name(im);                                                     \
1326 }
1327 #define entry_fn(name)                                                  \
1328 static void                                                             \
1329 name(void)                                                              \
1330 {                                                                       \
1331     int          ch;                                                    \
1332     label_t     *label;                                                 \
1333     void        *value;                                                 \
1334     ch = skipws();                                                      \
1335     switch (ch) {                                                       \
1336         case '0' ... '9':                                               \
1337             ungetch(ch);                                                \
1338             value = (void *)(jit_word_t)get_uint(skip_none);            \
1339             break;                                                      \
1340         case '$':                                                       \
1341             switch (expression()) {                                     \
1342                 case tok_int:                                           \
1343                     value = (void *)parser.value.i;                     \
1344                     break;                                              \
1345                 case tok_pointer:                                       \
1346                     value = parser.value.p;                             \
1347                     break;                                              \
1348                 default:                                                \
1349                     error("expecting pointer");                         \
1350             }                                                           \
1351             break;                                                      \
1352         case '@':                                                       \
1353             dynamic();                                                  \
1354             value = parser.value.p;                                     \
1355             break;                                                      \
1356         default:                                                        \
1357             ungetch(ch);                                                \
1358             label = get_label(skip_none);                               \
1359             if (label->kind == label_kind_code_forward)                 \
1360                 call_forward((void *)jit_##name(NULL), label);          \
1361             else                                                        \
1362                 jit_patch_at(jit_##name(NULL), label->value);           \
1363             return;                                                     \
1364     }                                                                   \
1365     jit_##name(value);                                                  \
1366 }
1367 static void
1368 name(void) {
1369     int          ch = skipws();
1370     (void)identifier(ch);
1371     jit_name(parser.string);
1372 }
1373 static void
1374 live(void) {
1375     if (primary(skip_ws) != tok_register)
1376         error("bad register");
1377     jit_live(parser.regval);
1378 }
1379 entry_im(align)
1380 entry(prolog)
1381 entry_im(frame)                 entry_im(tramp)
1382 entry(ellipsis)
1383 void
1384 allocai(void) {
1385     symbol_t    *symbol;
1386     jit_word_t   i, im = get_imm();
1387     i = jit_allocai(im);
1388     symbol = get_symbol();
1389     symbol->type = type_l;
1390     symbol->value.i = i;
1391 }
1392 entry_ir_ir(allocar)
1393 entry_ca(arg)
1394 entry_ia(getarg_c)              entry_ia(getarg_uc)
1395 entry_ia(getarg_s)              entry_ia(getarg_us)
1396 entry_ia(getarg_i)
1397 #if __WORDSIZE == 64
1398 entry_ia(getarg_ui)             entry_ia(getarg_l)
1399 #endif
1400 entry_ia(getarg)
1401 entry_ia(putargr)               entry_ima(putargi)
1402 entry_ir_ir_ir(addr)            entry_ir_ir_im(addi)
1403 entry_ir_ir_ir(addxr)           entry_ir_ir_im(addxi)
1404 entry_ir_ir_ir(addcr)           entry_ir_ir_im(addci)
1405 entry_ir_ir_ir(subr)            entry_ir_ir_im(subi)
1406 entry_ir_ir_ir(subxr)           entry_ir_ir_im(subxi)
1407 entry_ir_ir_ir(subcr)           entry_ir_ir_im(subci)
1408 entry_ir_ir_ir(rsbr)            entry_ir_ir_im(rsbi)
1409 entry_ir_ir_ir(mulr)            entry_ir_ir_im(muli)
1410 entry_ir_ir_ir_ir(qmulr)        entry_ir_ir_ir_im(qmuli)
1411 entry_ir_ir_ir_ir(qmulr_u)      entry_ir_ir_ir_im(qmuli_u)
1412 entry_ir_ir_ir(divr)            entry_ir_ir_im(divi)
1413 entry_ir_ir_ir(divr_u)          entry_ir_ir_im(divi_u)
1414 entry_ir_ir_ir_ir(qdivr)        entry_ir_ir_ir_im(qdivi)
1415 entry_ir_ir_ir_ir(qdivr_u)      entry_ir_ir_ir_im(qdivi_u)
1416 entry_ir_ir_ir(remr)            entry_ir_ir_im(remi)
1417 entry_ir_ir_ir(remr_u)          entry_ir_ir_im(remi_u)
1418 entry_ir_ir_ir(andr)            entry_ir_ir_im(andi)
1419 entry_ir_ir_ir(orr)             entry_ir_ir_im(ori)
1420 entry_ir_ir_ir(xorr)            entry_ir_ir_im(xori)
1421 entry_ir_ir_ir(lshr)            entry_ir_ir_im(lshi)
1422 entry_ir_ir_ir(rshr)            entry_ir_ir_im(rshi)
1423 entry_ir_ir_ir(rshr_u)          entry_ir_ir_im(rshi_u)
1424 entry_ir_ir(negr)               entry_ir_ir(comr)
1425 entry_ir_ir_ir(ltr)             entry_ir_ir_im(lti)
1426 entry_ir_ir_ir(ltr_u)           entry_ir_ir_im(lti_u)
1427 entry_ir_ir_ir(ler)             entry_ir_ir_im(lei)
1428 entry_ir_ir_ir(ler_u)           entry_ir_ir_im(lei_u)
1429 entry_ir_ir_ir(eqr)             entry_ir_ir_im(eqi)
1430 entry_ir_ir_ir(ger)             entry_ir_ir_im(gei)
1431 entry_ir_ir_ir(ger_u)           entry_ir_ir_im(gei_u)
1432 entry_ir_ir_ir(gtr)             entry_ir_ir_im(gti)
1433 entry_ir_ir_ir(gtr_u)           entry_ir_ir_im(gti_u)
1434 entry_ir_ir_ir(ner)             entry_ir_ir_im(nei)
1435 entry_ir_ir(movr)
1436 static void
1437 movi(void)
1438 {
1439     int          ch;
1440     label_t     *label;
1441     void        *value;
1442     jit_gpr_t    r0 = get_ireg();
1443     ch = skipws();
1444     switch (ch) {
1445         case '+': case '-':
1446         case '0' ... '9':
1447             ungetch(ch);
1448             value = (void *)(jit_word_t)get_uint(skip_none);
1449             break;
1450         case '\'':
1451             character();
1452             value = (void *)parser.value.i;
1453             break;
1454         case '$':
1455             switch (expression()) {
1456                 case tok_int:
1457                     value = (void *)parser.value.i;
1458                     break;
1459                 case tok_pointer:
1460                     value = parser.value.p;
1461                     break;
1462                 default:
1463                     error("expecting pointer");
1464             }
1465             break;
1466         case '@':
1467             dynamic();
1468             value = parser.value.p;
1469             break;
1470         default:
1471             ungetch(ch);
1472             label = get_label(skip_none);
1473             if (label->kind == label_kind_code ||
1474                 label->kind == label_kind_code_forward) {
1475                 mov_forward((void *)jit_movi(r0, 0), label);
1476                 return;
1477             }
1478             value = label->value;
1479             break;
1480     }
1481     jit_movi(r0, (jit_word_t)value);
1482 }
1483 entry_ir_ir(extr_c)             entry_ir_ir(extr_uc)
1484 entry_ir_ir(extr_s)             entry_ir_ir(extr_us)
1485 #if __WORDSIZE == 64
1486 entry_ir_ir(extr_i)             entry_ir_ir(extr_ui)
1487 #endif
1488 entry_ir_ir(htonr_us)           entry_ir_ir(ntohr_us)
1489 entry_ir_ir(htonr_ui)           entry_ir_ir(ntohr_ui)
1490 #if __WORDSIZE == 64
1491 entry_ir_ir(htonr_ul)           entry_ir_ir(ntohr_ul)
1492 #endif
1493 entry_ir_ir(htonr)              entry_ir_ir(ntohr)
1494 entry_ir_ir_ir(movnr)           entry_ir_ir_ir(movzr)
1495 entry_ir_ir(ldr_c)              entry_ir_pm(ldi_c)
1496 entry_ir_ir(ldr_uc)             entry_ir_pm(ldi_uc)
1497 entry_ir_ir(ldr_s)              entry_ir_pm(ldi_s)
1498 entry_ir_ir(ldr_us)             entry_ir_pm(ldi_us)
1499 entry_ir_ir(ldr_i)              entry_ir_pm(ldi_i)
1500 #if __WORDSIZE == 64
1501 entry_ir_ir(ldr_ui)             entry_ir_pm(ldi_ui)
1502 entry_ir_ir(ldr_l)              entry_ir_pm(ldi_l)
1503 #endif
1504 entry_ir_ir(ldr)                entry_ir_pm(ldi)
1505 entry_ir_ir_ir(ldxr_c)          entry_ir_ir_im(ldxi_c)
1506 entry_ir_ir_ir(ldxr_uc)         entry_ir_ir_im(ldxi_uc)
1507 entry_ir_ir_ir(ldxr_s)          entry_ir_ir_im(ldxi_s)
1508 entry_ir_ir_ir(ldxr_us)         entry_ir_ir_im(ldxi_us)
1509 entry_ir_ir_ir(ldxr_i)          entry_ir_ir_im(ldxi_i)
1510 #if __WORDSIZE == 64
1511 entry_ir_ir_ir(ldxr_ui)         entry_ir_ir_im(ldxi_ui)
1512 entry_ir_ir_ir(ldxr_l)          entry_ir_ir_im(ldxi_l)
1513 #endif
1514 entry_ir_ir_ir(ldxr)            entry_ir_ir_im(ldxi)
1515 entry_ir_ir(str_c)              entry_pm_ir(sti_c)
1516 entry_ir_ir(str_s)              entry_pm_ir(sti_s)
1517 entry_ir_ir(str_i)              entry_pm_ir(sti_i)
1518 #if __WORDSIZE == 64
1519 entry_ir_ir(str_l)              entry_pm_ir(sti_l)
1520 #endif
1521 entry_ir_ir(str)                entry_pm_ir(sti)
1522 entry_ir_ir_ir(stxr_c)          entry_im_ir_ir(stxi_c)
1523 entry_ir_ir_ir(stxr_s)          entry_im_ir_ir(stxi_s)
1524 entry_ir_ir_ir(stxr_i)          entry_im_ir_ir(stxi_i)
1525 #if __WORDSIZE == 64
1526 entry_ir_ir_ir(stxr_l)          entry_im_ir_ir(stxi_l)
1527 #endif
1528 entry_ir_ir_ir(stxr)            entry_im_ir_ir(stxi)
1529 entry_lb_ir_ir(bltr)            entry_lb_ir_im(blti)
1530 entry_lb_ir_ir(bltr_u)          entry_lb_ir_im(blti_u)
1531 entry_lb_ir_ir(bler)            entry_lb_ir_im(blei)
1532 entry_lb_ir_ir(bler_u)          entry_lb_ir_im(blei_u)
1533 entry_lb_ir_ir(beqr)            entry_lb_ir_im(beqi)
1534 entry_lb_ir_ir(bger)            entry_lb_ir_im(bgei)
1535 entry_lb_ir_ir(bger_u)          entry_lb_ir_im(bgei_u)
1536 entry_lb_ir_ir(bgtr)            entry_lb_ir_im(bgti)
1537 entry_lb_ir_ir(bgtr_u)          entry_lb_ir_im(bgti_u)
1538 entry_lb_ir_ir(bner)            entry_lb_ir_im(bnei)
1539 entry_lb_ir_ir(bmsr)            entry_lb_ir_im(bmsi)
1540 entry_lb_ir_ir(bmcr)            entry_lb_ir_im(bmci)
1541 entry_lb_ir_ir(boaddr)          entry_lb_ir_im(boaddi)
1542 entry_lb_ir_ir(boaddr_u)        entry_lb_ir_im(boaddi_u)
1543 entry_lb_ir_ir(bxaddr)          entry_lb_ir_im(bxaddi)
1544 entry_lb_ir_ir(bxaddr_u)        entry_lb_ir_im(bxaddi_u)
1545 entry_lb_ir_ir(bosubr)          entry_lb_ir_im(bosubi)
1546 entry_lb_ir_ir(bosubr_u)        entry_lb_ir_im(bosubi_u)
1547 entry_lb_ir_ir(bxsubr)          entry_lb_ir_im(bxsubi)
1548 entry_lb_ir_ir(bxsubr_u)        entry_lb_ir_im(bxsubi_u)
1549 entry_ir(jmpr)                  entry_lb(jmpi)
1550 entry_ir(callr)                 entry_fn(calli)
1551 entry(prepare)
1552 entry_ir(pushargr)              entry_im(pushargi)
1553 entry_ir(finishr)               entry_fn(finishi)
1554 entry(ret)
1555 entry_ir(retr)                  entry_im(reti)
1556 entry_ir(retval_c)              entry_ir(retval_uc)
1557 entry_ir(retval_s)              entry_ir(retval_us)
1558 entry_ir(retval_i)
1559 #if __WORDSIZE == 64
1560 entry_ir(retval_ui)             entry_ir(retval_l)
1561 #endif
1562 entry_ir(retval)
1563 entry(epilog)
1564 entry_ca(arg_f)                 entry_fa(getarg_f)
1565 entry_fa(putargr_f)             entry_fma(putargi_f)
1566 entry_fr_fr_fr(addr_f)          entry_fr_fr_fm(addi_f)
1567 entry_fr_fr_fr(subr_f)          entry_fr_fr_fm(subi_f)
1568 entry_fr_fr_fr(rsbr_f)          entry_fr_fr_fm(rsbi_f)
1569 entry_fr_fr_fr(mulr_f)          entry_fr_fr_fm(muli_f)
1570 entry_fr_fr_fr(divr_f)          entry_fr_fr_fm(divi_f)
1571 entry_fr_fr(negr_f)             entry_fr_fr(absr_f)
1572 entry_fr_fr(sqrtr_f)
1573 entry_ir_fr_fr(ltr_f)           entry_ir_fr_fm(lti_f)
1574 entry_ir_fr_fr(ler_f)           entry_ir_fr_fm(lei_f)
1575 entry_ir_fr_fr(eqr_f)           entry_ir_fr_fm(eqi_f)
1576 entry_ir_fr_fr(ger_f)           entry_ir_fr_fm(gei_f)
1577 entry_ir_fr_fr(gtr_f)           entry_ir_fr_fm(gti_f)
1578 entry_ir_fr_fr(ner_f)           entry_ir_fr_fm(nei_f)
1579 entry_ir_fr_fr(unltr_f)         entry_ir_fr_fm(unlti_f)
1580 entry_ir_fr_fr(unler_f)         entry_ir_fr_fm(unlei_f)
1581 entry_ir_fr_fr(uneqr_f)         entry_ir_fr_fm(uneqi_f)
1582 entry_ir_fr_fr(unger_f)         entry_ir_fr_fm(ungei_f)
1583 entry_ir_fr_fr(ungtr_f)         entry_ir_fr_fm(ungti_f)
1584 entry_ir_fr_fr(ltgtr_f)         entry_ir_fr_fm(ltgti_f)
1585 entry_ir_fr_fr(ordr_f)          entry_ir_fr_fm(ordi_f)
1586 entry_ir_fr_fr(unordr_f)        entry_ir_fr_fm(unordi_f)
1587 entry_ir_fr(truncr_f_i)
1588 #if __WORDSIZE == 64
1589 entry_ir_fr(truncr_f_l)
1590 #endif
1591 entry_ir_fr(truncr_f)
1592 entry_fr_ir(extr_f)             entry_fr_fr(extr_d_f)
1593 entry_fr_fr(movr_f)             entry_fr_fm(movi_f)
1594 entry_fr_ir(ldr_f)              entry_fr_pm(ldi_f)
1595 entry_fr_ir_ir(ldxr_f)          entry_fr_ir_im(ldxi_f)
1596 entry_ir_fr(str_f)              entry_pm_fr(sti_f)
1597 entry_ir_ir_fr(stxr_f)          entry_im_ir_fr(stxi_f)
1598 entry_lb_fr_fr(bltr_f)          entry_lb_fr_fm(blti_f)
1599 entry_lb_fr_fr(bler_f)          entry_lb_fr_fm(blei_f)
1600 entry_lb_fr_fr(beqr_f)          entry_lb_fr_fm(beqi_f)
1601 entry_lb_fr_fr(bger_f)          entry_lb_fr_fm(bgei_f)
1602 entry_lb_fr_fr(bgtr_f)          entry_lb_fr_fm(bgti_f)
1603 entry_lb_fr_fr(bner_f)          entry_lb_fr_fm(bnei_f)
1604 entry_lb_fr_fr(bunltr_f)        entry_lb_fr_fm(bunlti_f)
1605 entry_lb_fr_fr(bunler_f)        entry_lb_fr_fm(bunlei_f)
1606 entry_lb_fr_fr(buneqr_f)        entry_lb_fr_fm(buneqi_f)
1607 entry_lb_fr_fr(bunger_f)        entry_lb_fr_fm(bungei_f)
1608 entry_lb_fr_fr(bungtr_f)        entry_lb_fr_fm(bungti_f)
1609 entry_lb_fr_fr(bltgtr_f)        entry_lb_fr_fm(bltgti_f)
1610 entry_lb_fr_fr(bordr_f)         entry_lb_fr_fm(bordi_f)
1611 entry_lb_fr_fr(bunordr_f)       entry_lb_fr_fm(bunordi_f)
1612 entry_fr(pushargr_f)            entry_fm(pushargi_f)
1613 entry_fr(retr_f)                entry_fm(reti_f)
1614 entry_fr(retval_f)
1615 entry_ca(arg_d)                 entry_fa(getarg_d)
1616 entry_fa(putargr_d)             entry_fma(putargi_d)
1617 entry_fr_fr_fr(addr_d)          entry_fr_fr_dm(addi_d)
1618 entry_fr_fr_fr(subr_d)          entry_fr_fr_dm(subi_d)
1619 entry_fr_fr_fr(rsbr_d)          entry_fr_fr_dm(rsbi_d)
1620 entry_fr_fr_fr(mulr_d)          entry_fr_fr_dm(muli_d)
1621 entry_fr_fr_fr(divr_d)          entry_fr_fr_dm(divi_d)
1622 entry_fr_fr(negr_d)             entry_fr_fr(absr_d)
1623 entry_fr_fr(sqrtr_d)
1624 entry_ir_fr_fr(ltr_d)           entry_ir_fr_dm(lti_d)
1625 entry_ir_fr_fr(ler_d)           entry_ir_fr_dm(lei_d)
1626 entry_ir_fr_fr(eqr_d)           entry_ir_fr_dm(eqi_d)
1627 entry_ir_fr_fr(ger_d)           entry_ir_fr_dm(gei_d)
1628 entry_ir_fr_fr(gtr_d)           entry_ir_fr_dm(gti_d)
1629 entry_ir_fr_fr(ner_d)           entry_ir_fr_dm(nei_d)
1630 entry_ir_fr_fr(unltr_d)         entry_ir_fr_dm(unlti_d)
1631 entry_ir_fr_fr(unler_d)         entry_ir_fr_dm(unlei_d)
1632 entry_ir_fr_fr(uneqr_d)         entry_ir_fr_dm(uneqi_d)
1633 entry_ir_fr_fr(unger_d)         entry_ir_fr_dm(ungei_d)
1634 entry_ir_fr_fr(ungtr_d)         entry_ir_fr_dm(ungti_d)
1635 entry_ir_fr_fr(ltgtr_d)         entry_ir_fr_dm(ltgti_d)
1636 entry_ir_fr_fr(ordr_d)          entry_ir_fr_dm(ordi_d)
1637 entry_ir_fr_fr(unordr_d)        entry_ir_fr_dm(unordi_d)
1638 entry_ir_fr(truncr_d_i)
1639 #if __WORDSIZE == 64
1640 entry_ir_fr(truncr_d_l)
1641 #endif
1642 entry_ir_fr(truncr_d)
1643 entry_fr_ir(extr_d)             entry_fr_fr(extr_f_d)
1644 entry_fr_fr(movr_d)             entry_fr_dm(movi_d)
1645 entry_fr_ir(ldr_d)              entry_fr_pm(ldi_d)
1646 entry_fr_ir_ir(ldxr_d)          entry_fr_ir_im(ldxi_d)
1647 entry_ir_fr(str_d)              entry_pm_fr(sti_d)
1648 entry_ir_ir_fr(stxr_d)          entry_im_ir_fr(stxi_d)
1649 entry_lb_fr_fr(bltr_d)          entry_lb_fr_dm(blti_d)
1650 entry_lb_fr_fr(bler_d)          entry_lb_fr_dm(blei_d)
1651 entry_lb_fr_fr(beqr_d)          entry_lb_fr_dm(beqi_d)
1652 entry_lb_fr_fr(bger_d)          entry_lb_fr_dm(bgei_d)
1653 entry_lb_fr_fr(bgtr_d)          entry_lb_fr_dm(bgti_d)
1654 entry_lb_fr_fr(bner_d)          entry_lb_fr_dm(bnei_d)
1655 entry_lb_fr_fr(bunltr_d)        entry_lb_fr_dm(bunlti_d)
1656 entry_lb_fr_fr(bunler_d)        entry_lb_fr_dm(bunlei_d)
1657 entry_lb_fr_fr(buneqr_d)        entry_lb_fr_dm(buneqi_d)
1658 entry_lb_fr_fr(bunger_d)        entry_lb_fr_dm(bungei_d)
1659 entry_lb_fr_fr(bungtr_d)        entry_lb_fr_dm(bungti_d)
1660 entry_lb_fr_fr(bltgtr_d)        entry_lb_fr_dm(bltgti_d)
1661 entry_lb_fr_fr(bordr_d)         entry_lb_fr_dm(bordi_d)
1662 entry_lb_fr_fr(bunordr_d)       entry_lb_fr_dm(bunordi_d)
1663 entry_fr(pushargr_d)            entry_dm(pushargi_d)
1664 entry_fr(retr_d)                entry_dm(reti_d)
1665 entry_fr(retval_d)
1666 static void
1667 vastart(void)
1668 {
1669     jit_gpr_t   r0 = get_ireg();
1670     jit_va_start(r0);
1671 }
1672 static void
1673 vapush(void)
1674 {
1675     jit_gpr_t   r0 = get_ireg();
1676     jit_va_push(r0);
1677 }
1678 static void
1679 vaarg(void)
1680 {
1681     jit_gpr_t   r0 = get_ireg(), r1 = get_ireg();
1682     jit_va_arg(r0, r1);
1683 }
1684 static void
1685 vaarg_d(void)
1686 {
1687     jit_fpr_t   r0 = get_freg();
1688     jit_gpr_t   r1 = get_ireg();
1689     jit_va_arg_d(r0, r1);
1690 }
1691 static void
1692 vaend(void)
1693 {
1694     jit_gpr_t   r0 = get_ireg();
1695     jit_va_end(r0);
1696 }
1697 #undef entry_fn
1698 #undef entry_fm
1699 #undef entry_dm
1700 #undef entry_lb_fr_fm
1701 #undef entry_lb_fr_dm
1702 #undef entry_lb_fr_fr
1703 #undef entry_im_ir_fr
1704 #undef entry_ir_ir_fr
1705 #undef entry_pm_fr
1706 #undef entry_fr_ir_ir
1707 #undef entry_fr_ir_im
1708 #undef entry_fr_pm
1709 #undef entry_fr_fm
1710 #undef entry_fr_dm
1711 #undef entry_fr_ir
1712 #undef entry_ir_fr
1713 #undef entry_ir_fr_fm
1714 #undef entry_ir_fr_dm
1715 #undef entry_ir_fr_fr
1716 #undef entry_fr_fr
1717 #undef entry_fr_fr_fm
1718 #undef entry_fr_fr_dm
1719 #undef entry_fr_fr_fr
1720 #undef entry_fma
1721 #undef entry_fa
1722 #undef entry_pm
1723 #undef entry_lb
1724 #undef entry_lb_ir_im
1725 #undef entry_lb_ir_ir
1726 #undef entry_im_ir_ir
1727 #undef entry_pm_ir
1728 #undef entry_ir_pm
1729 #undef entry_ir_im
1730 #undef entry_ir_ir
1731 #undef entry_ir_ir_im
1732 #undef entry_ir_ir_ir
1733 #undef entry_ima
1734 #undef entry_ir
1735 #undef entry_im
1736 #undef entry_ia
1737 #undef entry_ca
1738 #undef entry
1739
1740 static void
1741 error(const char *format, ...)
1742 {
1743     va_list      ap;
1744     int          length;
1745     char        *string;
1746
1747     va_start(ap, format);
1748     message("error", format, ap);
1749     va_end(ap);
1750     length = parser.data.length - parser.data.offset;
1751     string = (char *)(parser.data.buffer + parser.data.offset - 1);
1752     if (length > 77)
1753         strcpy(string + 74, "...");
1754     else
1755         parser.data.buffer[parser.data.length - 1] = '\0';
1756     fprintf(stderr, "(%s)\n", string);
1757     exit(-1);
1758 }
1759
1760 static void
1761 warn(const char *format, ...)
1762 {
1763     va_list     ap;
1764     va_start(ap, format);
1765     message("warning", format, ap);
1766     va_end(ap);
1767 }
1768
1769 static void
1770 message(const char *kind, const char *format, va_list ap)
1771 {
1772     fprintf(stderr, "%s:%d: %s: ", parser.name,
1773             parser.line - parser.newline, kind);
1774     vfprintf(stderr, format, ap);
1775     fputc('\n', stderr);
1776 }
1777
1778 static int
1779 getch(void)
1780 {
1781     int         ch;
1782
1783     if (parser.data.offset < parser.data.length)
1784         ch = parser.data.buffer[parser.data.offset++];
1785     else {
1786         /* keep first offset for ungetch */
1787         if ((parser.data.length = fread(parser.data.buffer + 1, 1,
1788                                         sizeof(parser.data.buffer) - 1,
1789                                         parser.fp) + 1) <= 1) {
1790             ch = EOF;
1791             parser.data.offset = 1;
1792         }
1793         else {
1794             ch = parser.data.buffer[1];
1795             parser.data.offset = 2;
1796         }
1797     }
1798     if ((parser.newline = ch == '\n'))
1799         ++parser.line;
1800
1801     return (ch);
1802 }
1803
1804 static int
1805 getch_noeof(void)
1806 {
1807     int         ch = getch();
1808
1809     if (ch == EOF)
1810         error("unexpected end of file");
1811
1812     return (ch);
1813 }
1814
1815 static int
1816 ungetch(int ch)
1817 {
1818     if ((parser.newline = ch == '\n'))
1819         --parser.line;
1820
1821     if (parser.data.offset)
1822         parser.data.buffer[--parser.data.offset] = ch;
1823     else
1824         /* overwrite */
1825         parser.data.buffer[0] = ch;
1826
1827     return (ch);
1828 }
1829
1830 static int
1831 skipws(void)
1832 {
1833     int         ch;
1834
1835     for (ch = getch();; ch = getch()) {
1836         switch (ch) {
1837             case '/':
1838                 ch = skipct();
1839                 break;
1840             case '#':
1841                 ch = skipcp();
1842                 break;
1843         }
1844         switch (ch) {
1845             case ' ': case '\f': case '\r': case '\t':
1846                 break;
1847             default:
1848                 return (ch);
1849         }
1850     }
1851 }
1852
1853 static int
1854 skipnl(void)
1855 {
1856     int         ch;
1857
1858     for (ch = getch();; ch = getch()) {
1859         switch (ch) {
1860             case '/':
1861                 ch = skipct();
1862                 break;
1863             case '#':
1864                 ch = skipcp();
1865                 break;
1866         }
1867         switch (ch) {
1868             case ' ': case '\f': case '\n': case '\r': case '\t':
1869                 break;
1870                 /* handle as newline */
1871             case ';':
1872                 break;
1873             default:
1874                 return (ch);
1875         }
1876     }
1877 }
1878
1879 static int
1880 skipct(void)
1881 {
1882     int         ch;
1883
1884     ch = getch();
1885     switch (ch) {
1886         case '/':
1887             for (ch = getch(); ch != '\n' && ch != EOF; ch = getch())
1888                 ;
1889             return (ch);
1890         case '*':
1891             for (; ch != '/';) {
1892                 while (getch_noeof() != '*')
1893                     ;
1894                 while ((ch = getch_noeof()) == '*')
1895                     ;
1896             }
1897             return (getch());
1898         default:
1899             ungetch(ch);
1900             return ('/');
1901     }
1902 }
1903
1904 static int
1905 skipcp(void)
1906 {
1907     int         ch;
1908
1909     for (ch = getch(); ch != '\n' && ch != EOF; ch = getch()) {
1910         switch (ch) {
1911             case '0' ... '9':
1912                 if ((number(ch)) == tok_int)
1913                     parser.line = parser.value.i - 1;
1914                 break;
1915             case '"':
1916                 string();
1917                 if (parser.offset >= (int)sizeof(parser.name)) {
1918                     strncpy(parser.name, parser.string, sizeof(parser.name));
1919                     parser.name[sizeof(parser.name) - 1] = '\0';
1920                 }
1921                 else
1922                     strcpy(parser.name, parser.string);
1923                 break;
1924             default:
1925                 break;
1926         }
1927     }
1928
1929     return (ch);
1930 }
1931
1932 static jit_word_t
1933 get_int(skip_t skip)
1934 {
1935     switch (primary(skip)) {
1936         case tok_int:
1937             break;
1938         case tok_pointer:
1939             parser.type = type_l;
1940             parser.value.i = (jit_word_t)parser.value.p;
1941             break;
1942         default:
1943             error("expecting integer");
1944     }
1945
1946     return (parser.value.i);
1947 }
1948
1949 static jit_uword_t
1950 get_uint(skip_t skip)
1951 {
1952     switch (primary(skip)) {
1953         case tok_char:          case tok_int:
1954             break;
1955         case tok_pointer:
1956             parser.type = type_l;
1957             parser.value.ui = (jit_uword_t)parser.value.p;
1958             break;
1959         default:
1960             error("expecting integer");
1961     }
1962
1963     return (parser.value.ui);
1964 }
1965
1966 static double
1967 get_float(skip_t skip)
1968 {
1969     switch (primary(skip)) {
1970         case tok_char:
1971         case tok_int:
1972             parser.type = type_d;
1973             parser.value.d = parser.value.i;
1974             break;
1975         case tok_float:
1976             break;
1977         default:
1978             error("expecting float");
1979     }
1980
1981     return (parser.value.d);
1982 }
1983
1984 /* Workaround gcc not converting unordered values from double to
1985  * float (as done in other architectures) on s390 */
1986 static float
1987 make_float(double d)
1988 {
1989     /* This is an workaround to a bug in Hercules s390 emulator,
1990      * and at least HP-UX ia64 not have these */
1991 #if defined(HAVE_ISNAN) && defined(HAVE_ISINF)
1992     if (isnan(d))       return ( 0.0f/0.0f);
1993     if (isinf(d)) {
1994         if (d > 0.0)    return ( 1.0f/0.0f);
1995         else            return (-1.0f/0.0f);
1996     }
1997 #endif
1998     return ((float)d);
1999 }
2000
2001 static void *
2002 get_pointer(skip_t skip)
2003 {
2004     label_t     *label;
2005     token_t      token = primary(skip);
2006
2007     switch (token) {
2008         case tok_symbol:
2009             label = get_label_by_name(parser.string);
2010             if (label == NULL)
2011                 error("bad identifier %s", parser.string);
2012             switch (label->kind) {
2013                 case label_kind_data:
2014                 case label_kind_code:
2015                     break;
2016                 case label_kind_code_forward:
2017                     /* as expression arguments */
2018                     error("forward references not implemented");
2019                     break;
2020                 case label_kind_dynamic:
2021                     break;
2022             }
2023             parser.type = type_p;
2024             return (parser.value.p = label->value);
2025         case tok_int:
2026             parser.type = type_p;
2027             return (parser.value.p = (void *)parser.value.ui);
2028         case tok_pointer:
2029             return (parser.value.p);
2030         default:                error("bad pointer");
2031     }
2032 }
2033
2034 static label_t *
2035 get_label(skip_t skip)
2036 {
2037     label_t     *label;
2038     int          ch = skipws();
2039
2040     switch (ch) {
2041         case '@':
2042             (void)dynamic();
2043             break;
2044         case 'a' ... 'z': case 'A' ... 'Z': case '_':
2045             (void)identifier(ch);
2046             break;
2047         default:
2048             error("expecting label/immediate");
2049     }
2050     if ((label = get_label_by_name(parser.string)) == NULL)
2051         label = new_label(label_kind_code_forward,
2052                           parser.string, jit_forward());
2053
2054     return (label);
2055 }
2056
2057 static token_t
2058 regname(void)
2059 {
2060     jit_word_t  num;
2061     int         check = 1, ch = getch();
2062
2063     switch (ch) {
2064         case 'r':
2065             parser.regtype = type_l;
2066             switch (ch = getch()) {
2067                 case '0':       parser.regval = JIT_R0;         break;
2068                 case '1':       parser.regval = JIT_R1;         break;
2069                 case '2':       parser.regval = JIT_R2;         break;
2070                 case '(':
2071                     num = get_int(skip_none);
2072                     if (num < 0 || num >= JIT_R_NUM)            goto fail;
2073                     parser.regval = JIT_R(num);
2074                     if (getch() != ')')                         goto fail;
2075                     check = 0;
2076                     break;
2077                 default:                                        goto fail;
2078             }
2079             break;
2080         case 'v':
2081             parser.regtype = type_l;
2082             switch (ch = getch()) {
2083                 case '0':       parser.regval = JIT_V0;         break;
2084                 case '1':       parser.regval = JIT_V1;         break;
2085                 case '2':       parser.regval = JIT_V2;         break;
2086                 default:                                        goto fail;
2087                 case '(':
2088                     num = get_int(skip_none);
2089                     if (num < 0 || num >= JIT_V_NUM)            goto fail;
2090                     parser.regval = JIT_V(num);
2091                     if (getch() != ')')                         goto fail;
2092                     check = 0;
2093                     break;
2094             }
2095             break;
2096         case 'f':
2097             parser.regtype = type_d;
2098             switch (ch = getch()) {
2099                 case '0':       parser.regval = JIT_F0;         break;
2100                 case '1':       parser.regval = JIT_F1;         break;
2101                 case '2':       parser.regval = JIT_F2;         break;
2102                 case '3':       parser.regval = JIT_F3;         break;
2103                 case '4':       parser.regval = JIT_F4;         break;
2104                 case '5':       parser.regval = JIT_F5;         break;
2105                 case 'p':
2106                     parser.regtype = type_l;    /* oops */
2107                     parser.regval = JIT_FP;                     break;
2108                 case '(':
2109                     num = get_int(skip_none);
2110                     if (num < 0 || num >= JIT_F_NUM)            goto fail;
2111                     parser.regval = JIT_F(num);
2112                     if (getch() != ')')                         goto fail;
2113                     check = 0;
2114                     break;
2115                 default:                                        goto fail;
2116             }
2117             break;
2118         default:
2119         fail:
2120             error("bad register");
2121     }
2122     if (check) {
2123         ch = getch();
2124         if ((ch >= 'a' && ch <= 'z') ||
2125             (ch >= 'A' && ch <= 'Z') ||
2126             (ch >= '0' && ch <= '9') ||
2127             ch == '_')
2128             goto fail;
2129         ungetch(ch);
2130     }
2131
2132     return (tok_register);
2133 }
2134
2135 static token_t
2136 identifier(int ch)
2137 {
2138     parser.string[0] = ch;
2139     for (parser.offset = 1;;) {
2140         switch ((ch = getch())) {
2141             case 'a' ... 'z': case 'A' ... 'Z': case '0' ... '9' :  case '_':
2142                 if (parser.offset + 1 >= MAX_IDENTIFIER) {
2143                     parser.string[parser.offset] = '\0';
2144                     error("bad identifier %s", parser.string);
2145                 }
2146                 parser.string[parser.offset++] = ch;
2147                 break;
2148             default:
2149                 parser.string[parser.offset] = '\0';
2150                 ungetch(ch);
2151                 return (tok_symbol);
2152         }
2153     }
2154 }
2155
2156 static void
2157 get_data(type_t type)
2158 {
2159     int          ch;
2160     token_t      token;
2161     char        *test = data;
2162
2163     for (;;) {
2164         switch (type) {
2165             case type_c:
2166                 switch (token = primary(skip_ws)) {
2167                     case tok_char: case tok_int:
2168                         check_data(sizeof(signed char));
2169                         *(signed char *)(data + data_offset) = parser.value.i;
2170                         data_offset += sizeof(char);
2171                         break;
2172                     case tok_string:
2173                         check_data(parser.offset);
2174                         memcpy(data + data_offset, parser.string,
2175                                parser.offset);
2176                         data_offset += parser.offset;
2177                         break;
2178                     case tok_newline:
2179                     case tok_semicollon:
2180                         if (test == data)       error("syntax error");
2181                         return;
2182                     default:                    error("bad initializer");
2183                 }
2184                 break;
2185             case type_s:
2186                 check_data(sizeof(signed short));
2187                 *(signed short *)(data + data_offset) = get_int(skip_ws);
2188                 data_offset += sizeof(short);
2189                 break;
2190             case type_i:
2191                 check_data(sizeof(signed int));
2192                 *(signed int *)(data + data_offset) = get_int(skip_ws);
2193                 data_offset += sizeof(int);
2194                 break;
2195             case type_l:
2196                 check_data(sizeof(jit_word_t));
2197                 *(jit_word_t *)(data + data_offset) = get_int(skip_ws);
2198                 data_offset += sizeof(jit_word_t);
2199                 break;
2200             case type_f:
2201                 check_data(sizeof(float));
2202                 *(float *)(data + data_offset) = get_float(skip_ws);
2203                 data_offset += sizeof(float);
2204                 break;
2205             case type_d:
2206                 check_data(sizeof(double));
2207                 *(double *)(data + data_offset) = get_float(skip_ws);
2208                 data_offset += sizeof(double);
2209                 break;
2210             case type_p:
2211                 /* FIXME **patch if realloc** */
2212                 check_data(sizeof(void*));
2213                 *(void **)(data + data_offset) = get_pointer(skip_ws);
2214                 data_offset += sizeof(void*);
2215                 break;
2216             default:
2217                 abort();
2218         }
2219         ch = skipws();
2220         if (ch == '\n' || ch == ';' || ch == EOF)
2221             break;
2222         ungetch(ch);
2223     }
2224 }
2225
2226 static void
2227 dot(void)
2228 {
2229     int         ch;
2230     size_t      offset, length;
2231
2232     switch (ch = getch_noeof()) {
2233         case '$':
2234             /* use .$(expression) for non side effects expression */
2235             (void)expression();
2236             return;
2237         case 'a' ... 'z': case 'A' ... 'Z': case '_':
2238             (void)identifier(ch);
2239             break;
2240         default:
2241             ungetch(ch);
2242             if (skipws() != '$')
2243                 error("expecting symbol");
2244             /* allow spaces before an expression */
2245             (void)expression();
2246             return;
2247     }
2248     if (parser.string[1] == '\0') {
2249         switch (parser.string[0]) {
2250             case 'c':   get_data(type_c);       break;
2251             case 's':   get_data(type_s);       break;
2252             case 'i':   get_data(type_i);       break;
2253             case 'l':   get_data(type_l);       break;
2254             case 'f':   get_data(type_f);       break;
2255             case 'd':   get_data(type_d);       break;
2256             case 'p':   get_data(type_p);       break;
2257             default:    error("bad type .%c", parser.string[0]);
2258         }
2259     }
2260     else if (strcmp(parser.string, "data") == 0) {
2261         if (parser.parsing != PARSING_NONE)
2262             error(".data must be specified once and be the first section");
2263         parser.parsing = PARSING_DATA;
2264         data_length = get_int(skip_ws);
2265         data = (char *)xcalloc(1, data_length);
2266     }
2267     else if (strcmp(parser.string, "code") == 0) {
2268         if (parser.parsing != PARSING_NONE &&
2269             parser.parsing != PARSING_DATA)
2270             error(".code must be specified once only");
2271         parser.parsing = PARSING_CODE;
2272     }
2273     else if (strcmp(parser.string, "align") == 0) {
2274         length = get_int(skip_ws);
2275         if (parser.parsing != PARSING_DATA)
2276             error(".align must be in .data");
2277         if (length > 1 && length <= 4096 && !(length & (length - 1))) {
2278             offset = data_offset;
2279             offset += length - ((offset + length) % length);
2280             check_data(offset - data_offset);
2281             data_offset = offset;
2282         }
2283         else
2284             error("bad .align %ld (must be a power of 2, >= 2 && <= 4096)",
2285                   (jit_word_t)length);
2286     }
2287     else if (strcmp(parser.string, "size") == 0) {
2288         length = get_int(skip_ws);
2289         if (parser.parsing != PARSING_DATA)
2290             error(".size must be in .data");
2291         check_data(length);
2292         data_offset += length;
2293     }
2294     else if (strcmp(parser.string, "disasm") == 0)
2295         flag_disasm = 1;
2296     else
2297         error("unknown command .%s", parser.string);
2298 }
2299
2300 static token_t
2301 number(int ch)
2302 {
2303     char        buffer[1024], *endptr;
2304     int         integer = 1, offset = 0, neg = 0, e = 0, d = 0, base = 10;
2305
2306     for (;; ch = getch()) {
2307         switch (ch) {
2308             case '-':
2309                 if (offset == 0) {
2310                     neg = 1;
2311                     continue;
2312                 }
2313                 if (offset && buffer[offset - 1] != 'e') {
2314                     ungetch(ch);
2315                     goto done;
2316                 }
2317                 break;
2318             case '+':
2319                 if (offset == 0)
2320                     continue;
2321                 if (offset && buffer[offset - 1] != 'e') {
2322                     ungetch(ch);
2323                     goto done;
2324                 }
2325                 break;
2326             case '.':
2327                 if (d)
2328                     goto fail;
2329                 d = 1;
2330                 base = 10;
2331                 integer = 0;
2332                 break;
2333             case '0':
2334                 if (offset == 0 && base == 10) {
2335                     base = 8;
2336                     continue;
2337                 }
2338                 break;
2339             case 'b':
2340                 if (offset == 0 && base == 8) {
2341                     base = 2;
2342                     continue;
2343                 }
2344                 if (base != 16)
2345                     goto fail;
2346                 break;
2347             case '1':
2348                 break;
2349             case '2' ... '7':
2350                 if (base < 8)
2351                     goto fail;
2352                 break;
2353             case '8': case '9':
2354                 if (base < 10)
2355                     goto fail;
2356                 break;
2357             case 'x':
2358                 if (offset == 0 && base == 8) {
2359                     base = 16;
2360                     continue;
2361                 }
2362                 goto fail;
2363             case 'a': case 'c': case 'd': case 'f':
2364                 if (base < 16)
2365                     goto fail;
2366                 break;
2367             case 'e':
2368                 if (e)
2369                     goto fail;
2370                 if (base != 16) {
2371                     e = 1;
2372                     base = 10;
2373                     integer = 0;
2374                 }
2375                 break;
2376             case '_': case 'g' ... 'w': case 'y': case 'z': case 'A' ... 'Z':
2377             fail:
2378                 buffer[offset++] = '\0';
2379                 error("bad constant %s", buffer);
2380             default:
2381                 ungetch(ch);
2382                 goto done;
2383         }
2384         if (offset + 1 >= (int)sizeof(buffer))
2385             goto fail;
2386         buffer[offset++] = ch;
2387     }
2388 done:
2389     /* check for literal 0 */
2390     if (offset == 0 && base == 8)       buffer[offset++] = '0';
2391     buffer[offset] = '\0';
2392     if (integer) {
2393 #if _WIN32
2394 #  define STRTOUL       strtoull
2395 #else
2396 #  define STRTOUL       strtoul
2397 #endif
2398         parser.value.ui = STRTOUL(buffer, &endptr, base);
2399         parser.type = type_l;
2400         if (neg)
2401             parser.value.i = -parser.value.i;
2402     }
2403     else {
2404         parser.type = type_d;
2405         parser.value.d = strtod(buffer, &endptr);
2406         if (neg)
2407             parser.value.d = -parser.value.d;
2408     }
2409     if (*endptr)
2410         goto fail;
2411
2412     return (integer ? tok_int : tok_float);
2413 }
2414
2415 static int
2416 escape(int ch)
2417 {
2418     switch (ch) {
2419         case 'a':       ch = '\a';      break;
2420         case 'b':       ch = '\b';      break;
2421         case 'f':       ch = '\f';      break;
2422         case 'n':       ch = '\n';      break;
2423         case 'r':       ch = '\r';      break;
2424         case 't':       ch = '\t';      break;
2425         case 'v':       ch = '\v';      break;
2426         default:                        break;
2427     }
2428
2429     return (ch);
2430 }
2431
2432 static token_t
2433 string(void)
2434 {
2435     int         ch, esc = 0;
2436
2437     for (parser.offset = 0;;) {
2438         switch (ch = getch_noeof()) {
2439             case '\\':
2440                 if (esc)                goto append;
2441                 esc = 1;
2442                 break;
2443             case '"':
2444                 if (!esc) {
2445                     parser.string[parser.offset++] = '\0';
2446                     parser.value.p = parser.string;
2447                     parser.type = type_p;
2448                     return (tok_string);
2449                 }
2450                 /* FALLTHROUGH */
2451             default:
2452             append:
2453                 if (esc) {
2454                     ch = escape(ch);
2455                     esc = 0;
2456                 }
2457                 if (parser.offset + 1 >= parser.length) {
2458                     parser.length += 4096;
2459                     parser.string = (char *)xrealloc(parser.string,
2460                                                      parser.length);
2461                 }
2462                 parser.string[parser.offset++] = ch;
2463                 break;
2464         }
2465     }
2466 }
2467
2468 static token_t
2469 character(void)
2470 {
2471     int         ch, esc = 0;
2472
2473     if ((ch = getch_noeof()) == '\\') {
2474         esc = 1;
2475         ch = getch();
2476     }
2477     if (getch_noeof() != '\'')
2478         error("bad single byte char");
2479     if (esc)
2480         ch = escape(ch);
2481     parser.type = type_l;
2482     parser.value.i = ch & 0xff;
2483
2484     return (tok_char);
2485 }
2486
2487 static token_t
2488 dynamic(void)
2489 {
2490     label_t     *label;
2491     void        *value;
2492     char        *string;
2493     (void)identifier('@');
2494     if ((label = get_label_by_name(parser.string)) == NULL) {
2495 #if __CYGWIN__ ||_WIN32
2496         /* FIXME kludge to pass varargs test case, otherwise,
2497          * will not print/scan float values */
2498         if (strcmp(parser.string + 1, "sprintf") == 0)
2499             value = sprintf;
2500         else if (strcmp(parser.string + 1, "sscanf") == 0)
2501             value = sscanf;
2502         else
2503 #endif
2504         {
2505             value = dlsym(DL_HANDLE, parser.string + 1);
2506             if ((string = dlerror()))
2507                 error("%s", string);
2508         }
2509         label = new_label(label_kind_dynamic, parser.string, value);
2510     }
2511     parser.type = type_p;
2512     parser.value.p = label->value;
2513
2514     return (tok_pointer);
2515 }
2516
2517 static void
2518 expression_prim(void)
2519 {
2520     int          ch;
2521     token_t      token;
2522     label_t     *label;
2523     symbol_t    *symbol;
2524
2525     if (parser.putback) {
2526         parser.expr = parser.putback;
2527         parser.putback = (expr_t)0;
2528         return;
2529     }
2530     switch (ch = skipws()) {
2531         case '!':
2532             if ((ch = getch_noeof()) == '=')    parser.expr = expr_ne;
2533             else {
2534                 ungetch(ch);                    parser.expr = expr_not;
2535             }
2536             break;
2537         case '~':                               parser.expr = expr_com;
2538             break;
2539         case '*':
2540             if ((ch = getch_noeof()) == '=')    parser.expr = expr_mulset;
2541             else {
2542                 ungetch(ch);                    parser.expr = expr_mul;
2543             }
2544             break;
2545         case '/':
2546             if ((ch = getch_noeof()) == '=')    parser.expr = expr_divset;
2547             else {
2548                 ungetch(ch);                    parser.expr = expr_div;
2549             }
2550             break;
2551         case '%':
2552             if ((ch = getch_noeof()) == '=')    parser.expr = expr_remset;
2553             else {
2554                 ungetch(ch);                    parser.expr = expr_rem;
2555             }
2556             break;
2557         case '+':
2558             switch (ch = getch_noeof()) {
2559                 case '+':                       parser.expr = expr_inc;
2560                     break;
2561                 case '=':                       parser.expr = expr_addset;
2562                     break;
2563                 default:        ungetch(ch);    parser.expr = expr_add;
2564                     break;
2565             }
2566             break;
2567         case '-':
2568             switch (ch = getch_noeof()) {
2569                 case '-':                       parser.expr = expr_dec;
2570                     break;
2571                 case '=':                       parser.expr = expr_subset;
2572                     break;
2573                 default:        ungetch(ch);    parser.expr = expr_sub;
2574                     break;
2575             }
2576             break;
2577         case '<':
2578             switch (ch = getch_noeof()) {
2579                 case '=':                       parser.expr = expr_le;
2580                     break;
2581                 case '<':                       ch = getch_noeof();
2582                     if (ch == '=')              parser.expr = expr_lshset;
2583                     else {
2584                         ungetch(ch);            parser.expr = expr_lsh;
2585                     }
2586                     break;
2587                 default:        ungetch(ch);    parser.expr = expr_lt;
2588                     break;
2589             }
2590             break;
2591         case '>':
2592             switch (ch = getch_noeof()) {
2593                 case '=':                       parser.expr = expr_ge;
2594                     break;
2595                 case '>':                       ch = getch_noeof();
2596                     if (ch == '=')              parser.expr = expr_rshset;
2597                     else {
2598                         ungetch(ch);            parser.expr = expr_rsh;
2599                     }
2600                     break;
2601                 default:        ungetch(ch);    parser.expr = expr_gt;
2602                     break;
2603             }
2604             break;
2605         case '&':
2606             switch (ch = getch_noeof()) {
2607                 case '=':                       parser.expr = expr_andset;
2608                     break;
2609                 case '&':                       parser.expr = expr_andand;
2610                     break;
2611                 default:        ungetch(ch);    parser.expr = expr_and;
2612                     break;
2613             }
2614             break;
2615         case '|':
2616             switch (ch = getch_noeof()) {
2617                 case '=':                       parser.expr = expr_orset;
2618                     break;
2619                 case '|':                       parser.expr = expr_oror;
2620                     break;
2621                 default:        ungetch(ch);    parser.expr = expr_or;
2622                     break;
2623             }
2624             break;
2625         case '^':
2626             if ((ch = getch_noeof()) == '=')    parser.expr = expr_xorset;
2627             else {
2628                 ungetch(ch);                    parser.expr = expr_xor;
2629             }
2630             break;
2631         case '=':
2632             if ((ch = getch_noeof()) == '=')    parser.expr = expr_eq;
2633             else {
2634                 ungetch(ch);                    parser.expr = expr_set;
2635             }
2636             break;
2637         case '(':                               parser.expr = expr_lparen;
2638             break;
2639         case ')':                               parser.expr = expr_rparen;
2640             break;
2641         case '0' ... '9':
2642             token = number(ch);
2643             parser.expr = token == tok_int ? expr_int : expr_float;
2644             break;
2645         case '@':
2646             (void)dynamic();
2647             parser.expr = expr_pointer;
2648             break;
2649         case '$':
2650             identifier('$');
2651             /* no support for nested expressions */
2652             if (parser.string[0] == '\0')
2653                 error("syntax error");
2654             parser.expr = expr_symbol;
2655             if ((symbol = get_symbol_by_name(parser.string)) != NULL) {
2656                 parser.type = symbol->type;
2657                 parser.value = symbol->value;
2658             }
2659             else
2660                 /* only create symbol on assignment */
2661                 parser.type = type_none;
2662             break;
2663         case 'a' ... 'z': case 'A' ... 'Z': case '_':
2664             identifier(ch);
2665             if ((label = get_label_by_name(parser.string))) {
2666                 if (label->kind == label_kind_code_forward)
2667                     error("forward value for %s not supported",
2668                           parser.string);
2669                 parser.expr = expr_pointer;
2670                 parser.type = type_p;
2671                 parser.value.p = label->value;
2672             }
2673             else
2674                 error("invalid identifier %s", parser.string);
2675             break;
2676         case '\'':
2677             character();
2678             parser.expr = expr_int;
2679             break;
2680         case '"':
2681             /* not smart enough to put it in data and/or relocate it, etc */
2682             error("must declare strings as data");
2683         default:
2684             error("syntax error");
2685     }
2686 }
2687
2688 static void
2689 expression_inc(int pre)
2690 {
2691     symbol_t    *symbol;
2692
2693     if (pre) {
2694         expression_prim();
2695         if (parser.expr != expr_symbol)
2696             error("syntax error");
2697     }
2698     if ((symbol = get_symbol_by_name(parser.string)) == NULL) {
2699         if (!parser.short_circuit)
2700             error("undefined symbol %s", symbol->name);
2701     }
2702     if (!parser.short_circuit) {
2703         parser.type = symbol->type;
2704         if (!pre)
2705             parser.value = symbol->value;
2706         switch (symbol->type) {
2707             case type_l:
2708                 ++symbol->value.i;
2709                 break;
2710             case type_d:
2711                 /* should really be an error */
2712                 symbol->value.d += 1.0;
2713                 break;
2714             default:
2715                 ++parser.value.cp;
2716                 break;
2717         }
2718         if (pre)
2719             parser.value = symbol->value;
2720     }
2721     expression_prim();
2722 }
2723
2724 static void
2725 expression_dec(int pre)
2726 {
2727     symbol_t    *symbol;
2728
2729     if (pre) {
2730         expression_prim();
2731         if (parser.expr != expr_symbol)
2732             error("syntax error");
2733     }
2734     if ((symbol = get_symbol_by_name(parser.string)) == NULL) {
2735         if (!parser.short_circuit)
2736             error("undefined symbol %s", symbol->name);
2737     }
2738     if (!parser.short_circuit) {
2739         parser.type = symbol->type;
2740         if (!pre)
2741             parser.value = symbol->value;
2742         switch (symbol->type) {
2743             case type_l:
2744                 --symbol->value.i;
2745                 break;
2746             case type_d:
2747                 /* should really be an error */
2748                 symbol->value.d -= 1.0;
2749                 break;
2750             default:
2751                 --parser.value.cp;
2752                 break;
2753         }
2754         if (pre)
2755             parser.value = symbol->value;
2756     }
2757     expression_prim();
2758 }
2759
2760 static void
2761 expression_unary(void)
2762 {
2763     symbol_t    *symbol;
2764     char         buffer[256];
2765
2766     expression_prim();
2767     switch (parser.expr) {
2768         case expr_add:
2769             expression_unary();
2770             switch (parser.type) {
2771                 case type_l:
2772                 case type_d:
2773                     break;
2774                 default:
2775                     error("syntax error");
2776             }
2777             break;
2778         case expr_sub:
2779             expression_unary();
2780             switch (parser.type) {
2781                 case type_l:
2782                     parser.value.i = -parser.value.i;
2783                     break;
2784                 case type_d:
2785                     parser.value.d = -parser.value.d;
2786                     break;
2787                 default:
2788                     error("syntax error");
2789             }
2790             break;
2791         case expr_inc:
2792             expression_inc(1);
2793             break;
2794         case expr_dec:
2795             expression_dec(1);
2796             break;
2797         case expr_not:
2798             expression_unary();
2799             switch (parser.type) {
2800                 case type_l:
2801                     parser.value.i = !parser.value.i;
2802                     break;
2803                 case type_d:
2804                     parser.value.i = parser.value.d != 0;
2805                     break;
2806                 case type_p:
2807                     parser.value.i = parser.value.p != NULL;
2808                     break;
2809                 default:
2810                     error("syntax error");
2811             }
2812             parser.type = type_l;
2813             break;
2814         case expr_com:
2815             expression_unary();
2816             if (parser.type != type_l)
2817                 error("syntax error");
2818             parser.value.i = ~parser.value.i;
2819             break;
2820         case expr_lparen:
2821             expression_cond();
2822             if (parser.expr != expr_rparen)
2823                 error("syntax error");
2824             expression_prim();
2825             break;
2826         case expr_symbol:
2827             strcpy(buffer, parser.string);
2828             expression_prim();
2829             switch (parser.expr) {
2830                 case expr_set:
2831                     if ((symbol = get_symbol_by_name(buffer)) == NULL) {
2832                         if (!parser.short_circuit)
2833                             symbol = new_symbol(buffer);
2834                     }
2835                     expression_cond();
2836                 set:
2837                     if (!parser.short_circuit) {
2838                         if (symbol == NULL)
2839                             error("syntax error");
2840                         symbol->type = parser.type;
2841                         symbol->value = parser.value;
2842                     }
2843                     break;
2844                 case expr_mulset:               parser.putback = expr_mul;
2845                     goto check;
2846                 case expr_divset:               parser.putback = expr_div;
2847                     goto check;
2848                 case expr_remset:               parser.putback = expr_rem;
2849                     goto check;
2850                 case expr_addset:               parser.putback = expr_add;
2851                     goto check;
2852                 case expr_subset:               parser.putback = expr_sub;
2853                     goto check;
2854                 case expr_lshset:               parser.putback = expr_lsh;
2855                     goto check;
2856                 case expr_rshset:               parser.putback = expr_rsh;
2857                     goto check;
2858                 case expr_andset:               parser.putback = expr_and;
2859                     goto check;
2860                 case expr_orset:                parser.putback = expr_or;
2861                     goto check;
2862                 case expr_xorset:               parser.putback = expr_xor;
2863                 check:
2864                     if ((symbol = get_symbol_by_name(buffer)) == NULL) {
2865                         if (!parser.short_circuit)
2866                             error("undefined symbol %s", buffer);
2867                         parser.type = type_l;
2868                         parser.value.i = 1;
2869                     }
2870                     switch (parser.putback) {
2871                         case expr_mul:  case expr_div:  case expr_rem:
2872                             expression_mul();
2873                             break;
2874                         case expr_add:  case expr_sub:
2875                             expression_add();
2876                             break;
2877                         case expr_lsh:  case expr_rsh:
2878                             expression_shift();
2879                             break;
2880                         case expr_and:  case expr_or:  case expr_xor:
2881                             expression_bit();
2882                             break;
2883                         default:
2884                             abort();
2885                     }
2886                     goto set;
2887                 case expr_inc:
2888                     expression_inc(0);
2889                     break;
2890                 case expr_dec:
2891                     expression_dec(0);
2892                     break;
2893                 default:
2894                     break;
2895             }
2896             break;
2897         case expr_int:
2898         case expr_float:
2899         case expr_pointer:
2900             /* make next token available */
2901             expression_prim();
2902         default:
2903             break;
2904     }
2905 }
2906
2907 static void
2908 expression_mul(void)
2909 {
2910     type_t      type;
2911     value_t     value;
2912
2913     expression_unary();
2914     switch (parser.type) {
2915         case type_l:    case type_d:    case type_p:    break;
2916         default:                                        return;
2917     }
2918     for (;;) {
2919         switch (parser.expr) {
2920             case expr_mul:
2921                 type = parser.type, value = parser.value;
2922                 expression_unary();
2923                 switch (parser.type) {
2924                     case type_l:
2925                         if (type == type_l)
2926                             value.i *= parser.value.i;
2927                         else
2928                             value.d *= parser.value.i;
2929                         break;
2930                     case type_d:
2931                         if (type == type_l) {
2932                             type = type_d;
2933                             value.d = value.i;
2934                         }
2935                         value.d *= parser.value.d;
2936                         break;
2937                     default:
2938                         error("invalid operand");
2939                 }
2940                 parser.type = type, parser.value = value;
2941                 break;
2942             case expr_div:
2943                 type = parser.type, value = parser.value;
2944                 expression_unary();
2945                 switch (parser.type) {
2946                     case type_l:
2947                         if (type == type_l) {
2948                             if (parser.value.i == 0)
2949                                 error("divide by zero");
2950                             value.i /= parser.value.i;
2951                         }
2952                         else
2953                             value.d /= parser.value.i;
2954                         break;
2955                     case type_d:
2956                         if (type == type_l) {
2957                             type = type_d;
2958                             value.d = value.i;
2959                         }
2960                         value.d /= parser.value.d;
2961                         break;
2962                     default:
2963                         error("invalid operand");
2964                 }
2965                 parser.type = type, parser.value = value;
2966                 break;
2967             case expr_rem:
2968                 type = parser.type, value = parser.value;
2969                 expression_unary();
2970                 switch (parser.type) {
2971                     case type_l:
2972                         if (type == type_l) {
2973                             if (parser.value.i == 0)
2974                                 error("divide by zero");
2975                             value.i %= parser.value.i;
2976                         }
2977                         else
2978                             error("invalid operand");
2979                         break;
2980                     default:
2981                         error("invalid operand");
2982                 }
2983                 parser.type = type, parser.value = value;
2984                 break;
2985             default:
2986                 return;
2987         }
2988     }
2989 }
2990
2991 static void
2992 expression_add(void)
2993 {
2994     type_t      type;
2995     value_t     value;
2996
2997     expression_mul();
2998     switch (parser.type) {
2999         case type_l:    case type_d:    case type_p:    break;
3000         default:                                        return;
3001     }
3002     for (;;) {
3003         switch (parser.expr) {
3004             case expr_add:
3005                 type = parser.type, value = parser.value;
3006                 expression_mul();
3007                 switch (parser.type) {
3008                     case type_l:
3009                         switch (type) {
3010                             case type_l:
3011                                 value.i += parser.value.i;
3012                                 break;
3013                             case type_d:
3014                                 value.d += parser.value.i;
3015                                 break;
3016                             default:
3017                                 value.cp += parser.value.i;
3018                                 break;
3019                         }
3020                         break;
3021                     case type_d:
3022                         switch (type) {
3023                             case type_l:
3024                                 type = type_d;
3025                                 value.d = value.i;
3026                                 break;
3027                             case type_d:
3028                                 break;
3029                             default:
3030                                 error("invalid operand");
3031                         }
3032                         value.d += parser.value.d;
3033                         break;
3034                     case type_p:
3035                         switch (type) {
3036                             case type_l:
3037                                 type = type_p;
3038                                 value.cp = value.i + parser.value.cp;
3039                                 break;
3040                             default:
3041                                 error("invalid operand");
3042                         }
3043                         break;
3044                     default:
3045                         error("invalid operand");
3046                 }
3047                 parser.type = type, parser.value = value;
3048                 break;
3049             case expr_sub:
3050                 type = parser.type, value = parser.value;
3051                 expression_mul();
3052                 switch (parser.type) {
3053                     case type_l:
3054                         switch (type) {
3055                             case type_l:
3056                                 value.i -= parser.value.i;
3057                                 break;
3058                             case type_d:
3059                                 value.d -= parser.value.i;
3060                                 break;
3061                             default:
3062                                 value.cp -= parser.value.i;
3063                                 break;
3064                         }
3065                         break;
3066                     case type_d:
3067                         switch (type) {
3068                             case type_l:
3069                                 type = type_d;
3070                                 value.d = value.i;
3071                                 break;
3072                             case type_d:
3073                                 break;
3074                             default:
3075                                 error("invalid operand");
3076                         }
3077                         value.d -= parser.value.d;
3078                         break;
3079                     case type_p:
3080                         switch (type) {
3081                             case type_p:
3082                                 type = type_l;
3083                                 value.i = value.cp - parser.value.cp;
3084                                 break;
3085                             default:
3086                                 error("invalid operand");
3087                         }
3088                         break;
3089                     default:
3090                         error("invalid operand");
3091                 }
3092                 parser.type = type, parser.value = value;
3093                 break;
3094             default:
3095                 return;
3096         }
3097     }
3098 }
3099
3100 static void
3101 expression_shift(void)
3102 {
3103     jit_word_t  value;
3104     expression_add();
3105
3106     switch (parser.type) {
3107         case type_l:    case type_d:    case type_p:    break;
3108         default:                                        return;
3109     }
3110     for (;;) {
3111         switch (parser.expr) {
3112             case expr_lsh:
3113                 value = parser.value.i;
3114                 if (parser.type != type_l)
3115                     error("invalid operand");
3116                 expression_add();
3117                 if (parser.type != type_l)
3118                     error("invalid operand");
3119                 value <<= parser.value.i;
3120                 parser.value.i = value;
3121                 break;
3122             case expr_rsh:
3123                 value = parser.value.i;
3124                 if (parser.type != type_l)
3125                     error("invalid operand");
3126                 expression_add();
3127                 if (parser.type != type_l)
3128                     error("invalid operand");
3129                 value >>= parser.value.i;
3130                 parser.value.i = value;
3131                 break;
3132             default:
3133                 return;
3134         }
3135     }
3136 }
3137
3138 static void
3139 expression_bit(void)
3140 {
3141     jit_word_t  i;
3142
3143     expression_shift();
3144     switch (parser.type) {
3145         case type_l:    case type_d:    case type_p:    break;
3146         default:                                        return;
3147     }
3148     for (;;) {
3149         switch (parser.expr) {
3150             case expr_and:
3151                 if (parser.type != type_l)
3152                     error("invalid operand");
3153                 i = parser.value.i;
3154                 expression_shift();
3155                 if (parser.type != type_l)
3156                     error("invalid operand");
3157                 i &= parser.value.i;
3158                 parser.value.i = i;
3159                 break;
3160             case expr_or:
3161                 if (parser.type != type_l)
3162                     error("invalid operand");
3163                 i = parser.value.i;
3164                 expression_shift();
3165                 if (parser.type != type_l)
3166                     error("invalid operand");
3167                 i |= parser.value.i;
3168                 parser.value.i = i;
3169                 break;
3170             case expr_xor:
3171                 if (parser.type != type_l)
3172                     error("invalid operand");
3173                 i = parser.value.i;
3174                 expression_shift();
3175                 if (parser.type != type_l)
3176                     error("invalid operand");
3177                 i ^= parser.value.i;
3178                 parser.value.i = i;
3179                 break;
3180             default:
3181                 return;
3182         }
3183     }
3184 }
3185
3186 static void
3187 expression_rel(void)
3188 {
3189     type_t      type;
3190     value_t     value;
3191
3192     expression_bit();
3193     switch (parser.type) {
3194         case type_l:    case type_d:    case type_p:    break;
3195         default:                                        return;
3196     }
3197     for (;;) {
3198         switch (parser.expr) {
3199             case expr_lt:
3200                 type = parser.type, value = parser.value;
3201                 expression_bit();
3202                 switch (parser.type) {
3203                     case type_l:
3204                         switch (type) {
3205                             case type_l:
3206                                 value.i = value.i < parser.value.i;
3207                                 break;
3208                             case type_d:
3209                                 value.i = value.d < parser.value.i;
3210                                 break;
3211                             default:
3212                                 value.i = (jit_word_t)value.p < parser.value.i;
3213                                 break;
3214                         }
3215                         break;
3216                     case type_d:
3217                         switch (type) {
3218                             case type_l:
3219                                 value.i = value.i < parser.value.d;
3220                                 break;
3221                             case type_d:
3222                                 value.i = value.d < parser.value.d;
3223                                 break;
3224                             default:
3225                                 error("invalid operand");
3226                         }
3227                         break;
3228                     case type_p:
3229                         switch (type) {
3230                             case type_l:
3231                                 value.i = value.i < (jit_word_t)parser.value.p;
3232                                 break;
3233                             case type_d:
3234                                 error("invalid operand");
3235                             default:
3236                                 value.i = (jit_word_t)value.p < (jit_word_t)parser.value.p;
3237                                 break;
3238                         }
3239                         break;
3240                     default:
3241                         error("invalid operand");
3242                 }
3243                 parser.type = type_l, parser.value = value;
3244                 break;
3245             case expr_le:
3246                 type = parser.type, value = parser.value;
3247                 expression_bit();
3248                 switch (parser.type) {
3249                     case type_l:
3250                         switch (type) {
3251                             case type_l:
3252                                 value.i = value.i <= parser.value.i;
3253                                 break;
3254                             case type_d:
3255                                 value.i = value.d <= parser.value.i;
3256                                 break;
3257                             default:
3258                                 value.i = (jit_word_t)value.p <= parser.value.i;
3259                                 break;
3260                         }
3261                         break;
3262                     case type_d:
3263                         switch (type) {
3264                             case type_l:
3265                                 value.i = value.i <= parser.value.d;
3266                                 break;
3267                             case type_d:
3268                                 value.i = value.d <= parser.value.d;
3269                                 break;
3270                             default:
3271                                 value.i = (jit_word_t)value.p <= parser.value.d;
3272                                 break;
3273                         }
3274                         break;
3275                     case type_p:
3276                         switch (type) {
3277                             case type_l:
3278                                 value.i = value.i <= (jit_word_t)parser.value.p;
3279                                 break;
3280                             case type_d:
3281                                 error("invalid operand");
3282                             default:
3283                                 value.i = (jit_word_t)value.p <= (jit_word_t)parser.value.p;
3284                                 break;
3285                         }
3286                         break;
3287                     default:
3288                         error("invalid operand");
3289                 }
3290                 parser.type = type_l, parser.value = value;
3291                 break;
3292             case expr_eq:
3293                 type = parser.type, value = parser.value;
3294                 expression_bit();
3295                 switch (parser.type) {
3296                     case type_l:
3297                         switch (type) {
3298                             case type_l:
3299                                 value.i = value.i == parser.value.i;
3300                                 break;
3301                             case type_d:
3302                                 value.i = value.d == parser.value.i;
3303                                 break;
3304                             default:
3305                                 value.i = (jit_word_t)value.p == parser.value.i;
3306                                 break;
3307                         }
3308                         break;
3309                     case type_d:
3310                         switch (type) {
3311                             case type_l:
3312                                 value.i = value.i == parser.value.d;
3313                                 break;
3314                             case type_d:
3315                                 value.i = value.d == parser.value.d;
3316                                 break;
3317                             default:
3318                                 error("invalid operand");
3319                         }
3320                         break;
3321                     case type_p:
3322                         switch (type) {
3323                             case type_l:
3324                                 value.i = value.i == (jit_word_t)parser.value.p;
3325                                 break;
3326                             case type_d:
3327                                 error("invalid operand");
3328                             default:
3329                                 value.i = value.p == parser.value.p;
3330                                 break;
3331                         }
3332                         break;
3333                     default:
3334                         error("invalid operand");
3335                 }
3336                 parser.type = type_l, parser.value = value;
3337                 break;
3338             case expr_ge:
3339                 type = parser.type, value = parser.value;
3340                 expression_bit();
3341                 switch (parser.type) {
3342                     case type_l:
3343                         switch (type) {
3344                             case type_l:
3345                                 value.i = value.i >= parser.value.i;
3346                                 break;
3347                             case type_d:
3348                                 value.i = value.d >= parser.value.i;
3349                                 break;
3350                             default:
3351                                 value.i = (jit_word_t)value.p >= parser.value.i;
3352                                 break;
3353                         }
3354                         break;
3355                     case type_d:
3356                         switch (type) {
3357                             case type_l:
3358                                 value.i = value.i >= parser.value.d;
3359                                 break;
3360                             case type_d:
3361                                 value.i = value.d >= parser.value.d;
3362                                 break;
3363                             default:
3364                                 error("invalid operand");
3365                         }
3366                         break;
3367                     case type_p:
3368                         switch (type) {
3369                             case type_l:
3370                                 value.i = value.i >= (jit_word_t)parser.value.p;
3371                                 break;
3372                             case type_d:
3373                                 error("invalid operand");
3374                             default:
3375                                 value.i = (jit_word_t)value.p >= (jit_word_t)parser.value.p;
3376                                 break;
3377                         }
3378                         break;
3379                     default:
3380                         error("invalid operand");
3381                 }
3382                 parser.type = type_l, parser.value = value;
3383                 break;
3384             case expr_gt:
3385                 type = parser.type, value = parser.value;
3386                 expression_bit();
3387                 switch (parser.type) {
3388                     case type_l:
3389                         switch (type) {
3390                             case type_l:
3391                                 value.i = value.i > parser.value.i;
3392                                 break;
3393                             case type_d:
3394                                 value.i = value.d > parser.value.i;
3395                                 break;
3396                             default:
3397                                 value.i = (jit_word_t)value.p > parser.value.i;
3398                                 break;
3399                         }
3400                         break;
3401                     case type_d:
3402                         switch (type) {
3403                             case type_l:
3404                                 value.i = value.i > parser.value.d;
3405                                 break;
3406                             case type_d:
3407                                 value.i = value.d > parser.value.d;
3408                                 break;
3409                             default:
3410                                 error("invalid operand");
3411                         }
3412                         break;
3413                     case type_p:
3414                         switch (type) {
3415                             case type_l:
3416                                 value.i = value.i > (jit_word_t)parser.value.p;
3417                                 break;
3418                             case type_d:
3419                                 error("invalid operand");
3420                             default:
3421                                 value.i = (jit_word_t)value.p > (jit_word_t)parser.value.p;
3422                                 break;
3423                         }
3424                         break;
3425                     default:
3426                         error("invalid operand");
3427                 }
3428                 parser.type = type_l, parser.value = value;
3429                 break;
3430             case expr_ne:
3431                 type = parser.type, value = parser.value;
3432                 expression_bit();
3433                 switch (parser.type) {
3434                     case type_l:
3435                         switch (type) {
3436                             case type_l:
3437                                 value.i = value.i != parser.value.i;
3438                                 break;
3439                             case type_d:
3440                                 value.i = value.d != parser.value.i;
3441                                 break;
3442                             default:
3443                                 value.i = (jit_word_t)value.p != parser.value.i;
3444                                 break;
3445                         }
3446                         break;
3447                     case type_d:
3448                         switch (type) {
3449                             case type_l:
3450                                 value.i = value.i != parser.value.d;
3451                                 break;
3452                             case type_d:
3453                                 value.i = value.d != parser.value.d;
3454                                 break;
3455                             default:
3456                                 error("invalid operand");
3457                         }
3458                         break;
3459                     case type_p:
3460                         switch (type) {
3461                             case type_l:
3462                                 value.i = value.i != (jit_word_t)parser.value.p;
3463                                 break;
3464                             case type_d:
3465                                 error("invalid operand");
3466                             default:
3467                                 value.i = value.p != parser.value.p;
3468                                 break;
3469                         }
3470                         break;
3471                     default:
3472                         error("invalid operand");
3473                 }
3474                 parser.type = type_l, parser.value = value;
3475                 break;
3476             default:
3477                 return;
3478         }
3479     }
3480 }
3481
3482 static void
3483 expression_cond(void)
3484 {
3485     type_t      type;
3486     value_t     value;
3487     int         short_circuit;
3488
3489     expression_rel();
3490     switch (parser.type) {
3491         case type_l:    case type_d:    case type_p:    break;
3492         default:                                        return;
3493     }
3494     for (;;) {
3495         switch (parser.expr) {
3496             case expr_andand:
3497                 type = parser.type, value = parser.value;
3498                 switch (type) {
3499                     case type_l:
3500                         short_circuit = value.i == 0;
3501                         break;
3502                     case type_d:
3503                         short_circuit = value.d == 0.0;
3504                         break;
3505                     default:
3506                         short_circuit = value.p == NULL;
3507                         break;
3508                 }
3509                 parser.short_circuit += short_circuit;
3510                 expression_rel();
3511                 parser.short_circuit -= short_circuit;
3512                 switch (parser.type) {
3513                     case type_l:
3514                         switch (type) {
3515                             case type_l:
3516                                 value.i = value.i && parser.value.i;
3517                                 break;
3518                             case type_d:
3519                                 value.i = value.d && parser.value.i;
3520                                 break;
3521                             default:
3522                                 value.i = value.p && parser.value.i;
3523                                 break;
3524                         }
3525                         break;
3526                     case type_d:
3527                         switch (type) {
3528                             case type_l:
3529                                 value.i = value.i && parser.value.d;
3530                                 break;
3531                             case type_d:
3532                                 value.i = value.d && parser.value.d;
3533                                 break;
3534                             default:
3535                                 value.i = value.p && parser.value.d;
3536                                 break;
3537                         }
3538                         break;
3539                     case type_p:
3540                         switch (type) {
3541                             case type_l:
3542                                 value.i = value.i && parser.value.p;
3543                                 break;
3544                             case type_d:
3545                                 value.i = value.d && parser.value.p;
3546                                 break;
3547                             default:
3548                                 value.i = value.p && parser.value.p;
3549                                 break;
3550                         }
3551                         break;
3552                     default:
3553                         error("invalid operand");
3554                 }
3555                 parser.type = type_l, parser.value.i = value.i;
3556                 break;
3557             case expr_oror:
3558                 type = parser.type, value = parser.value;
3559                 switch (type) {
3560                     case type_l:
3561                         short_circuit = value.i != 0;
3562                         break;
3563                     case type_d:
3564                         short_circuit = value.d != 0.0;
3565                         break;
3566                     default:
3567                         short_circuit = value.p != NULL;
3568                         break;
3569                 }
3570                 parser.short_circuit += short_circuit;
3571                 expression_rel();
3572                 parser.short_circuit -= short_circuit;
3573                 switch (parser.type) {
3574                     case type_l:
3575                         switch (type) {
3576                             case type_l:
3577                                 value.i = value.i || parser.value.i;
3578                                 break;
3579                             case type_d:
3580                                 value.i = value.d || parser.value.i;
3581                                 break;
3582                             default:
3583                                 value.i = value.p || parser.value.i;
3584                                 break;
3585                         }
3586                         break;
3587                     case type_d:
3588                         switch (type) {
3589                             case type_l:
3590                                 value.i = value.i || parser.value.d;
3591                                 break;
3592                             case type_d:
3593                                 value.i = value.d || parser.value.d;
3594                                 break;
3595                             default:
3596                                 value.i = value.p || parser.value.d;
3597                                 break;
3598                         }
3599                         break;
3600                     case type_p:
3601                         switch (type) {
3602                             case type_l:
3603                                 value.i = value.i || parser.value.p;
3604                                 break;
3605                             case type_d:
3606                                 value.i = value.d || parser.value.p;
3607                                 break;
3608                             default:
3609                                 value.i = value.p || parser.value.p;
3610                                 break;
3611                         }
3612                         break;
3613                     default:
3614                         error("invalid operand");
3615                 }
3616                 parser.type = type_l, parser.value.i = value.i;
3617                 break;
3618             default:
3619                 return;
3620         }
3621     }
3622 }
3623
3624 static token_t
3625 expression(void)
3626 {
3627     symbol_t    *symbol;
3628
3629     (void)identifier('$');
3630     if (parser.string[1] == '\0') {
3631         if (getch_noeof() != '(')
3632             error("bad symbol or expression");
3633         parser.type = type_none;
3634         expression_cond();
3635         if (parser.expr != expr_rparen)
3636             error("bad expression");
3637         switch (parser.type) {
3638             case type_l:
3639                 return (tok_int);
3640             case type_d:
3641                 return (tok_float);
3642             case type_p:
3643                 return (tok_pointer);
3644             default:
3645                 error("bad expression");
3646         }
3647     }
3648     else if ((symbol = get_symbol_by_name(parser.string))) {
3649         switch (parser.type = symbol->type) {
3650             case type_l:
3651                 parser.value.i = symbol->value.i;
3652                 return (tok_int);
3653             case type_d:
3654                 parser.value.d = symbol->value.d;
3655                 return (tok_float);
3656             default:
3657                 parser.value.p = symbol->value.p;
3658                 return (tok_pointer);
3659         }
3660     }
3661     else
3662         error("undefined symbol %s", parser.string);
3663 }
3664
3665 static token_t
3666 primary(skip_t skip)
3667 {
3668     int         ch;
3669
3670     switch (skip) {
3671         case skip_none: ch = getch();   break;
3672         case skip_ws:   ch = skipws();  break;
3673         case skip_nl:   ch = skipnl();  break;
3674         default:                        abort();
3675     }
3676     switch (ch) {
3677         case '%':
3678             return (regname());
3679         case 'a' ... 'z': case 'A' ... 'Z': case '_':
3680             return (identifier(ch));
3681         case '0' ... '9': case '+': case '-':
3682             return (number(ch));
3683         case '.':
3684             return (tok_dot);
3685         case '"':
3686             return (string());
3687         case '\'':
3688             return (character());
3689         case '@':
3690             return (dynamic());
3691         case '$':
3692             return (expression());
3693         case EOF:
3694             return (tok_eof);
3695         case '\n':
3696             return (tok_newline);
3697         case ';':
3698             return (tok_semicollon);
3699         default:
3700             error("syntax error");
3701     }
3702 }
3703
3704 static void
3705 parse(void)
3706 {
3707     int          ch;
3708     token_t      token;
3709     instr_t     *instr;
3710     label_t     *label;
3711     void        *value;
3712
3713     for (;;) {
3714         switch (token = primary(skip_nl)) {
3715             case tok_symbol:
3716                 ch = getch_noeof();
3717                 if (ch == ':') {
3718                     if ((label = get_label_by_name(parser.string))) {
3719                         if (label->kind == label_kind_code_forward) {
3720                             label->kind = label_kind_code;
3721                             jit_link(label->value);
3722                             jit_note(parser.name, parser.line);
3723                         }
3724                         else
3725                             error("label %s: redefined", parser.string);
3726                     }
3727                     else {
3728                         if (parser.parsing == PARSING_DATA) {
3729                             value = data + data_offset;
3730                             label = new_label(label_kind_data,
3731                                               parser.string, value);
3732                         }
3733                         else if (parser.parsing == PARSING_CODE) {
3734                             value = jit_label();
3735                             jit_note(parser.name, parser.line);
3736                             label = new_label(label_kind_code,
3737                                               parser.string, value);
3738                         }
3739                         else
3740                             error("label not in .code or .data");
3741                     }
3742                     break;
3743                 }
3744                 ungetch(ch);
3745                 if ((instr =
3746                      (instr_t *)get_hash(instrs, parser.string)) == NULL)
3747                     error("unhandled symbol %s", parser.string);
3748                 if (parser.parsing != PARSING_CODE)
3749                     error(".code must be specified before instructions");
3750                 (*instr->function)();
3751                 break;
3752             case tok_dot:
3753                 dot();
3754                 break;
3755             case tok_eof:
3756                 return;
3757             default:
3758                 error("syntax error");
3759         }
3760     }
3761 }
3762
3763 static int
3764 execute(int argc, char *argv[])
3765 {
3766     int          result;
3767     label_t     *label;
3768     function_t   function;
3769     patch_t     *patch, *next;
3770
3771     for (patch = patches; patch; patch = next) {
3772         next = patch->next;
3773         label = patch->label;
3774         if (label->kind == label_kind_code_forward)
3775             error("undefined label %s", label->name);
3776         switch (patch->kind) {
3777             case patch_kind_jmp:
3778             case patch_kind_mov:
3779             case patch_kind_call:
3780                 jit_patch_at(patch->value, label->value);
3781                 break;
3782             default:
3783                 abort();
3784         }
3785         free(patch);
3786         patch = next;
3787     }
3788
3789     if (flag_data == 0) {
3790         jit_realize();
3791         jit_set_data(NULL, 0, JIT_DISABLE_DATA | JIT_DISABLE_NOTE);
3792     }
3793
3794     function = jit_emit();
3795     if (flag_verbose > 1 || flag_disasm) {
3796         jit_print();
3797         fprintf(stderr, "  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n");
3798     }
3799     if (flag_verbose > 0 || flag_disasm) {
3800         jit_disassemble();
3801         fprintf(stderr, "  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n");
3802     }
3803
3804     jit_clear_state();
3805     if (flag_disasm)
3806         result = 0;
3807     else
3808         result = (*function)(argc, argv);
3809     jit_destroy_state();
3810
3811     return (result);
3812 }
3813
3814 static void *
3815 xmalloc(size_t size)
3816 {
3817     void        *pointer = malloc(size);
3818
3819     if (pointer == NULL)
3820         error("out of memory");
3821
3822     return (pointer);
3823 }
3824
3825 static void *
3826 xrealloc(void *pointer, size_t size)
3827 {
3828     pointer = realloc(pointer, size);
3829
3830     if (pointer == NULL)
3831         error("out of memory");
3832
3833     return (pointer);
3834 }
3835
3836 static void *
3837 xcalloc(size_t nmemb, size_t size)
3838 {
3839     void        *pointer = calloc(nmemb, size);
3840
3841     if (pointer == NULL)
3842         error("out of memory");
3843
3844     return (pointer);
3845 }
3846
3847 static label_t *
3848 new_label(label_kind_t kind, char *name, void *value)
3849 {
3850     label_t     *label;
3851
3852     label = (label_t *)xmalloc(sizeof(label_t));
3853     label->kind = kind;
3854     label->name = strdup(name);
3855     label->value = value;
3856     put_hash(labels, (entry_t *)label);
3857     label_offset++;
3858     return (label);
3859 }
3860
3861 static patch_t *
3862 new_patch(patch_kind_t kind, label_t *label, void *value)
3863 {
3864     patch_t     *patch = (patch_t *)xmalloc(sizeof(patch_t));
3865     patch->kind = kind;
3866     patch->label = label;
3867     patch->value = value;
3868     patch->next = patches;
3869     patches = patch;
3870
3871     return (patch);
3872 }
3873
3874 static int
3875 bcmp_symbols(const void *left, const void *right)
3876 {
3877     return (strcmp((char *)left, (*(symbol_t **)right)->name));
3878 }
3879
3880 static int
3881 qcmp_symbols(const void *left, const void *right)
3882 {
3883     return (strcmp((*(symbol_t **)left)->name, (*(symbol_t **)right)->name));
3884 }
3885
3886 static symbol_t *
3887 new_symbol(char *name)
3888 {
3889     symbol_t    *symbol;
3890
3891     if ((symbol_offset & 15) == 0) {
3892         if ((symbol_length += 16) == 16)
3893             symbols = (symbol_t **)xmalloc(sizeof(symbol_t *) *
3894                                            symbol_length);
3895         else
3896             symbols = (symbol_t **)xrealloc(symbols, sizeof(symbol_t *) *
3897                                             symbol_length);
3898     }
3899     symbol = (symbol_t *)xmalloc(sizeof(symbol_t));
3900     symbol->name = strdup(name);
3901     symbols[symbol_offset++] = symbol;
3902     qsort(symbols, symbol_offset, sizeof(symbol_t *), qcmp_symbols);
3903
3904     return (symbol);
3905 }
3906
3907 static symbol_t *
3908 get_symbol_by_name(char *name)
3909 {
3910     symbol_t    **symbol_pointer;
3911
3912     if (symbols == NULL)
3913         return (NULL);
3914     symbol_pointer = (symbol_t **)bsearch(name, symbols, symbol_offset,
3915                                           sizeof(symbol_t *), bcmp_symbols);
3916
3917     return (symbol_pointer ? *symbol_pointer : NULL);
3918 }
3919
3920 static hash_t *
3921 new_hash(void)
3922 {
3923     hash_t      *hash;
3924
3925     hash = (hash_t *)xmalloc(sizeof(hash_t));
3926     hash->count = 0;
3927     hash->entries = (entry_t **)xcalloc(hash->size = 32, sizeof(void *));
3928
3929     return (hash);
3930 }
3931
3932 static int
3933 hash_string(char *name)
3934 {
3935     char        *ptr;
3936     int          key;
3937
3938     for (key = 0, ptr = name; *ptr; ptr++)
3939         key = (key << (key & 1)) ^ *ptr;
3940
3941     return (key);
3942 }
3943
3944 static void
3945 put_hash(hash_t *hash, entry_t *entry)
3946 {
3947     entry_t     *prev, *ptr;
3948     int          key = hash_string(entry->name) & (hash->size - 1);
3949
3950     for (prev = ptr = hash->entries[key]; ptr; prev = ptr, ptr = ptr->next) {
3951         if (strcmp(entry->name, ptr->name) == 0)
3952             error("duplicated entry %s", entry->name);
3953     }
3954     if (prev == NULL)
3955         hash->entries[key] = entry;
3956     else
3957         prev->next = entry;
3958     entry->next = NULL;
3959     ++hash->count;
3960     if (hash->count > hash->size * 0.75)
3961         rehash(hash);
3962 }
3963
3964 static entry_t *
3965 get_hash(hash_t *hash, char *name)
3966 {
3967     entry_t     *entry;
3968     int          key = hash_string(name) & (hash->size - 1);
3969
3970     for (entry = hash->entries[key]; entry; entry = entry->next) {
3971         if (strcmp(entry->name, name) == 0)
3972             return (entry);
3973     }
3974     return (NULL);
3975 }
3976
3977 static void
3978 rehash(hash_t *hash)
3979 {
3980     int          i, size, key;
3981     entry_t     *entry, *next, **entries;
3982
3983     entries = (entry_t **)xcalloc(size = hash->size * 2, sizeof(void *));
3984     for (i = 0; i < hash->size; i++) {
3985         for (entry = hash->entries[i]; entry; entry = next) {
3986             next = entry->next;
3987             key = hash_string(entry->name) & (size - 1);
3988             entry->next = entries[key];
3989             entries[key] = entry;
3990         }
3991     }
3992     free(hash->entries);
3993     hash->entries = entries;
3994     hash->size = size;
3995 }
3996
3997 static void
3998 usage(void)
3999 {
4000 #if HAVE_GETOPT_LONG_ONLY
4001     fprintf(stderr, "\
4002 Usage: %s [jit assembler options] file [jit program options]\n\
4003 Jit assembler options:\n\
4004   -help                    Display this information\n\
4005   -v[0-3]                  Verbose output level\n\
4006   -d                       Do not use a data buffer\n\
4007   -D<macro>[=<val>]        Preprocessor options\n"
4008 #  if defined(__i386__) && __WORDSIZE == 32
4009 "  -mx87=1                  Force using x87 when sse2 available\n"
4010 #  endif
4011 #  if defined(__i386__) || defined(__x86_64__)
4012 "  -msse4_1=0               Do not use sse4_1 instructions when available\n"
4013 #  endif
4014 #  if defined(__arm__)
4015 "  -mcpu=<val>              Force cpu version (4, 5, 6 or 7)\n\
4016   -mthumb[=0|1]            Enable or disable thumb\n\
4017   -mvfp=<val>              Set vpf version (0 to disable)\n\
4018   -mneon[=0|1]             Enable or disable neon\n"
4019 #  endif
4020             , progname);
4021 #else
4022     fprintf(stderr, "\
4023 Usage: %s [jit assembler options] file [jit program options]\n\
4024 Jit assembler options:\n\
4025   -h                       Display this information\n\
4026   -v                       Verbose output level\n\
4027   -D<macro>[=<val>]        Preprocessor options\n", progname);
4028 #endif
4029     finish_jit();
4030     exit(1);
4031 }
4032
4033 int
4034 main(int argc, char *argv[])
4035 {
4036 #if HAVE_GETOPT_LONG_ONLY
4037     static const char   *short_options = "dv::";
4038     static struct option long_options[] = {
4039         { "help",               0, 0, 'h' },
4040         { "data",               2, 0, 'd' },
4041 #  if defined(__i386__) && __WORDSIZE == 32
4042         { "mx87",               2, 0, '7' },
4043 #  endif
4044 #  if defined(__i386__) || defined(__x86_64__)
4045         { "msse4_1",            2, 0, '4' },
4046 #  endif
4047 #  if defined(__arm__)
4048         { "mcpu",               2, 0, 'c' },
4049         { "mthumb",             2, 0, 't' },
4050         { "mvfp",               2, 0, 'f' },
4051         { "mneon",              2, 0, 'n' },
4052 #  endif
4053         { 0,                    0, 0, 0   }
4054     };
4055 #else
4056 #endif  /* HAVE_GETOPT_LONG_ONLY */
4057     int                  offset;
4058     char                *endptr;
4059     int                  opt_index;
4060     int                  opt_short;
4061     char                 cmdline[8192];
4062
4063 #if defined(__CYGWIN__)
4064     /* Cause a compile warning about redefinition without dllimport
4065      * attribute, *but* cause correct linkage if liblightning.a is
4066      * linked to binutils (that happens to have an internal
4067      * getopt* implementation and an apparently conflicting
4068      * optind global variable) */
4069     extern int           optind;
4070     optind = 1;
4071 #endif
4072
4073     progname = argv[0];
4074
4075     init_jit(progname);
4076
4077 #if defined(__sgi)
4078     DL_HANDLE = dlopen(NULL, RTLD_LAZY);
4079 #endif
4080
4081     flag_data = 1;
4082 #if HAVE_GETOPT_LONG_ONLY
4083     for (;;) {
4084         if ((opt_short = getopt_long_only(argc, argv, short_options,
4085                                           long_options, &opt_index)) < 0)
4086             break;
4087         switch (opt_short) {
4088             case 'h':
4089             default:
4090                 usage();
4091                 break;
4092             case 'v':
4093                 if (optarg) {
4094                     flag_verbose = strtol(optarg, &endptr, 10);
4095                     if (*endptr || flag_verbose < 0)
4096                         usage();
4097                 }
4098                 else
4099                     flag_verbose = 1;
4100                 break;
4101             case 'd':
4102                 flag_data = 0;
4103                 break;
4104 #if defined(__i386__) && __WORDSIZE == 32
4105             case '7':
4106                 if (optarg) {
4107                     if (strcmp(optarg, "") == 0 || strcmp(optarg, "1") == 0)
4108                         jit_cpu.sse2 = 0;
4109                     else if (strcmp(optarg, "0"))
4110                         usage();
4111                 }
4112                 else
4113                     jit_cpu.sse2 = 0;
4114                 break;
4115 #endif
4116 #if defined(__i386__) || defined(__x86_64__)
4117             case '4':
4118                 if (optarg) {
4119                     if (strcmp(optarg, "0") == 0)
4120                         jit_cpu.sse4_2 = 0;
4121                     else if (strcmp(optarg, "1"))
4122                         usage();
4123                 }
4124                 break;
4125 #endif
4126 #if defined(__arm__)
4127             case 'c':
4128                 if (optarg) {
4129                     offset = strtol(optarg, &endptr, 10);
4130                     if (*endptr || offset < 0)
4131                         usage();
4132                     if (offset < jit_cpu.version)
4133                         jit_cpu.version = offset;
4134                 }
4135                 break;
4136             case 't':
4137                 if (optarg) {
4138                     if (strcmp(optarg, "0") == 0)
4139                         jit_cpu.thumb = 0;
4140                     else if (strcmp(optarg, "1") && strcmp(optarg, "2"))
4141                         usage();
4142                 }
4143                 break;
4144             case 'f':
4145 #  if !defined(__ARM_PCS_VFP)
4146                 /* Do not allow overrinding hard float abi */
4147                 if (optarg) {
4148                     offset = strtol(optarg, &endptr, 10);
4149                     if (*endptr || offset < 0)
4150                         usage();
4151                     if (offset < jit_cpu.vfp)
4152                         jit_cpu.vfp = offset;
4153                 }
4154 #  endif
4155                 break;
4156             case 'n':
4157                 if (optarg) {
4158                     if (strcmp(optarg, "0") == 0)
4159                         jit_cpu.neon = 0;
4160                     else if (strcmp(optarg, "1"))
4161                         usage();
4162                 }
4163                 break;
4164 #endif
4165         }
4166     }
4167 #else
4168     while ((opt_short = getopt(argc, argv, "hvd")) >= 0) {
4169         if (opt_short == 'v')
4170             ++flag_verbose;
4171         else if (opt_short == 'd')
4172             flag_data = 0;
4173         else
4174             usage();
4175     }
4176 #endif
4177
4178     opt_index = optind;
4179 #if defined(__hpux)
4180     /* Workaround */
4181     if (opt_index < argc && argv[opt_index][0] == '-')
4182         ++opt_index;
4183 #endif
4184     if (opt_index < 0 || opt_index >= argc)
4185         usage();
4186     if (strcmp(argv[opt_index], "-") == 0)
4187         strcpy(parser.name, "<stdin>");
4188     else {
4189         if ((endptr = strrchr(argv[opt_index], '/')) == NULL)
4190             endptr = argv[opt_index];
4191         else
4192             ++endptr;
4193         strncpy(parser.name, endptr, sizeof(parser.name));
4194         parser.name[sizeof(parser.name) - 1] = '\0';
4195     }
4196 #if __clang__
4197 #  define cc "clang"
4198 #else
4199 #  define cc "gcc"
4200 #endif
4201     opt_short = snprintf(cmdline, sizeof(cmdline), cc " -E -x c %s", argv[opt_index]);
4202     for (++opt_index; opt_index < argc; opt_index++) {
4203         if (argv[opt_index][0] == '-')
4204             opt_short += snprintf(cmdline + opt_short,
4205                                   sizeof(cmdline) - opt_short,
4206                                   " %s", argv[opt_index]);
4207         else {
4208             --opt_index;
4209             break;
4210         }
4211     }
4212     opt_short += snprintf(cmdline + opt_short,
4213                           sizeof(cmdline) - opt_short,
4214                           " -D__WORDSIZE=%d", __WORDSIZE);
4215     opt_short += snprintf(cmdline + opt_short,
4216                           sizeof(cmdline) - opt_short,
4217                           " -D__LITTLE_ENDIAN=%d", __LITTLE_ENDIAN);
4218     opt_short += snprintf(cmdline + opt_short,
4219                           sizeof(cmdline) - opt_short,
4220                           " -D__BIG_ENDIAN=%d", __BIG_ENDIAN);
4221     opt_short += snprintf(cmdline + opt_short,
4222                           sizeof(cmdline) - opt_short,
4223                           " -D__BYTE_ORDER=%d", __BYTE_ORDER);
4224 #if defined(__i386__)
4225     opt_short += snprintf(cmdline + opt_short,
4226                           sizeof(cmdline) - opt_short,
4227                           " -D__i386__=1");
4228 #endif
4229 #if defined(__x86_64__)
4230     opt_short += snprintf(cmdline + opt_short,
4231                           sizeof(cmdline) - opt_short,
4232                           " -D__x86_64__=1");
4233 #endif
4234 #if defined(__mips__)
4235     opt_short += snprintf(cmdline + opt_short,
4236                           sizeof(cmdline) - opt_short,
4237                           " -D__mips__=1");
4238 #endif
4239 #if defined(__arm__)
4240     opt_short += snprintf(cmdline + opt_short,
4241                           sizeof(cmdline) - opt_short,
4242                           " -D__arm__=1");
4243 #endif
4244 #if defined(__powerpc__)
4245     opt_short += snprintf(cmdline + opt_short,
4246                           sizeof(cmdline) - opt_short,
4247                           " -D__ppc__=1");
4248 #endif
4249 #if defined(__sparc__)
4250     opt_short += snprintf(cmdline + opt_short,
4251                           sizeof(cmdline) - opt_short,
4252                           " -D__sparc__=1");
4253 #endif
4254 #if defined(__ia64__)
4255     opt_short += snprintf(cmdline + opt_short,
4256                           sizeof(cmdline) - opt_short,
4257                           " -D__ia64__=1");
4258 #endif
4259 #if defined(__hppa__)
4260     opt_short += snprintf(cmdline + opt_short,
4261                           sizeof(cmdline) - opt_short,
4262                           " -D__hppa__=1");
4263 #endif
4264 #if defined(_AIX)
4265     opt_short += snprintf(cmdline + opt_short,
4266                           sizeof(cmdline) - opt_short,
4267                           " -D_AIX=1");
4268 #endif
4269 #if defined(__sgi__)
4270     opt_short += snprintf(cmdline + opt_short,
4271                           sizeof(cmdline) - opt_short,
4272                           " -D__sgi__=1");
4273 #endif
4274 #if defined(__aarch64__)
4275     opt_short += snprintf(cmdline + opt_short,
4276                           sizeof(cmdline) - opt_short,
4277                           " -D__aarch64__=1");
4278 #endif
4279 #if defined(__s390__) || defined(__s390x__)
4280     opt_short += snprintf(cmdline + opt_short,
4281                           sizeof(cmdline) - opt_short,
4282                           " -D__s390__=1");
4283 #endif
4284 #if defined(__alpha__)
4285     opt_short += snprintf(cmdline + opt_short,
4286                           sizeof(cmdline) - opt_short,
4287                           " -D__alpha__=1");
4288 #endif
4289     if ((parser.fp = popen(cmdline, "r")) == NULL)
4290         error("cannot execute %s", cmdline);
4291
4292     parser.line = 1;
4293     parser.string = (char *)xmalloc(parser.length = 4096);
4294
4295 #if defined(__linux__) && (defined(__i386__) || defined(__x86_64__))
4296     /*  double precision                0x200
4297      *  round nearest                   0x000
4298      *  invalid operation mask          0x001
4299      *  denormalized operand mask       0x002
4300      *  zero divide mask                0x004
4301      *  precision (inexact) mask        0x020
4302      */
4303     {
4304         fpu_control_t fpu_control = 0x027f;
4305         _FPU_SETCW(fpu_control);
4306     }
4307 #endif
4308
4309     _jit = jit_new_state();
4310
4311     instrs = new_hash();
4312     for (offset = 0;
4313          offset < (int)(sizeof(instr_vector) / sizeof(instr_vector[0]));
4314          offset++)
4315         put_hash(instrs, (entry_t *)(instr_vector + offset));
4316
4317     labels = new_hash();
4318
4319     parse();
4320     pclose(parser.fp);
4321     parser.fp = NULL;
4322
4323     for (opt_short = 0; opt_index < argc; opt_short++, opt_index++)
4324         argv[opt_short] = argv[opt_index];
4325     argv[opt_short] = NULL;
4326     argc = opt_short;
4327     execute(argc, argv);
4328
4329     finish_jit();
4330
4331     return (0);
4332 }