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