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