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