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