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