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