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