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