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