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