Add generated files to .gitignore
[b43-tools.git] / assembler / main.c
1 /*
2  *   Copyright (C) 2006-2007  Michael Buesch <mb@bu3sch.de>
3  *
4  *   This program is free software; you can redistribute it and/or modify
5  *   it under the terms of the GNU General Public License version 2
6  *   as published by the Free Software Foundation.
7  *
8  *   This program is distributed in the hope that it will be useful,
9  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
10  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  *   GNU General Public License for more details.
12  */
13
14 #include "main.h"
15 #include "list.h"
16 #include "util.h"
17 #include "parser.h"
18 #include "args.h"
19 #include "initvals.h"
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25
26 extern int yyparse(void);
27 extern int yydebug;
28
29 struct file infile;
30 const char *infile_name;
31 const char *outfile_name;
32
33
34 struct out_operand {
35         enum {
36                 OUTOPER_NORMAL,
37                 OUTOPER_LABELREF,
38         } type;
39
40         union {
41                 unsigned int operand; /* For NORMAL */
42                 struct label *label; /* For LABELREF */
43         } u;
44 };
45
46 struct code_output {
47         enum {
48                 OUT_INSN,
49                 OUT_LABEL,
50         } type;
51
52         /* Set to true, if this is a jump instruction.
53          * This is only used when assembling RET to check
54          * whether the previous instruction was a jump or not. */
55         bool is_jump_insn;
56
57         unsigned int opcode;
58         struct out_operand operands[3];
59
60         /* The absolute address of this instruction.
61          * Only used in resolve_labels(). */
62         unsigned int address;
63
64         const char *labelname; /* only for OUT_LABEL */
65         /* Set to 1, if this is the %start instruction. */
66         int is_start_insn;
67
68         struct list_head list;
69 };
70
71 struct assembler_context {
72         /* The architecture version (802.11 core revision) */
73         unsigned int arch;
74
75         struct label *start_label;
76
77         /* Tracking stuff */
78         struct statement *cur_stmt;
79
80         struct list_head output;
81 };
82
83
84 #define for_each_statement(ctx, s)                      \
85         list_for_each_entry(s, &infile.sl, list) {      \
86                 ctx->cur_stmt = s;
87
88 #define for_each_statement_end(ctx, s)                  \
89         } do { ctx->cur_stmt = NULL; } while (0)
90
91 #define _msg_helper(type, stmt, msg, x...)      do {            \
92         fprintf(stderr, "Assembler " type);                     \
93         if (stmt) {                                             \
94                 fprintf(stderr, " (file \"%s\", line %u)",      \
95                         stmt->info.file,                        \
96                         stmt->info.lineno);                     \
97         }                                                       \
98         fprintf(stderr, ":\n  " msg "\n" ,##x);                 \
99                                                 } while (0)
100
101 #define asm_error(ctx, msg, x...)       do {                    \
102         _msg_helper("ERROR", (ctx)->cur_stmt, msg ,##x);        \
103         exit(1);                                                \
104                                         } while (0)
105
106 #define asm_warn(ctx, msg, x...)        \
107         _msg_helper("warning", (ctx)->cur_stmt, msg ,##x)
108
109 #define asm_info(ctx, msg, x...)        \
110         _msg_helper("info", (ctx)->cur_stmt, msg ,##x)
111
112
113 static void eval_directives(struct assembler_context *ctx)
114 {
115         struct statement *s;
116         struct asmdir *ad;
117         struct label *l;
118         int have_start_label = 0;
119         int have_arch = 0;
120
121         for_each_statement(ctx, s) {
122                 if (s->type == STMT_ASMDIR) {
123                         ad = s->u.asmdir;
124                         switch (ad->type) {
125                         case ADIR_ARCH:
126                                 if (have_arch)
127                                         asm_error(ctx, "Multiple %%arch definitions");
128                                 ctx->arch = ad->u.arch;
129                                 if (ctx->arch != 5 && ctx->arch != 15) {
130                                         asm_error(ctx, "Architecture version %u unsupported",
131                                                   ctx->arch);
132                                 }
133                                 have_arch = 1;
134                                 break;
135                         case ADIR_START:
136                                 if (have_start_label)
137                                         asm_error(ctx, "Multiple %%start definitions");
138                                 ctx->start_label = ad->u.start;
139                                 have_start_label = 1;
140                                 break;
141                         default:
142                                 asm_error(ctx, "Unknown ASM directive");
143                         }
144                 }
145         } for_each_statement_end(ctx, s);
146
147         if (!have_arch)
148                 asm_error(ctx, "No %%arch defined");
149         if (!have_start_label)
150                 asm_info(ctx, "Using start address 0");
151 }
152
153 static bool is_possible_imm(unsigned int imm)
154 {
155         unsigned int mask;
156
157         /* Immediates are only possible up to 16bit (wordsize). */
158         mask = ~0;
159         mask <<= 16;
160         if (imm & (1 << 15)) {
161                 if ((imm & mask) != mask &&
162                     (imm & mask) != 0)
163                         return 0;
164         } else {
165                 if ((imm & mask) != 0)
166                         return 0;
167         }
168
169         return 1;
170 }
171
172 static bool is_valid_imm(struct assembler_context *ctx,
173                          unsigned int imm)
174 {
175         unsigned int mask;
176         unsigned int immediate_size;
177
178         /* This function checks if the immediate value is representable
179          * as a native immediate operand.
180          *
181          * For v5 architecture the immediate can be 10bit long.
182          * For v15 architecture the immediate can be 11bit long.
183          *
184          * The value is sign-extended, so we allow values
185          * of 0xFFFA, for example.
186          */
187
188         if (!is_possible_imm(imm))
189                 return 0;
190         imm &= 0xFFFF;
191
192         if (ctx->arch == 5) {
193                 immediate_size = 10; /* 10bit */
194         } else if (ctx->arch == 15) {
195                 immediate_size = 11; /* 11bit */
196         } else {
197                 asm_error(ctx, "Unknown immediate size for arch %u",
198                           ctx->arch);
199         }
200
201         /* First create a mask with all possible bits for
202          * an immediate value unset. */
203         mask = (~0 << immediate_size) & 0xFFFF;
204         /* Is the sign bit of the immediate set? */
205         if (imm & (1 << (immediate_size - 1))) {
206                 /* Yes, so all bits above that must also
207                  * be set, otherwise we can't represent this
208                  * value in an operand. */
209                 if ((imm & mask) != mask)
210                         return 0;
211         } else {
212                 /* All bits above the immediate's size must
213                  * be unset. */
214                 if (imm & mask)
215                         return 0;
216         }
217
218         return 1;
219 }
220
221 /* This checks if the value is nonzero and a power of two. */
222 static bool is_power_of_two(unsigned int value)
223 {
224         return (value && ((value & (value - 1)) == 0));
225 }
226
227 /* This checks if all bits set in the mask are contiguous.
228  * Zero is also considered a contiguous mask. */
229 static bool is_contiguous_bitmask(unsigned int mask)
230 {
231         unsigned int low_zeros_mask;
232         bool is_contiguous;
233
234         if (mask == 0)
235                 return 1;
236         /* Turn the lowest zeros of the mask into a bitmask.
237          * Example:  0b00011000 -> 0b00000111 */
238         low_zeros_mask = (mask - 1) & ~mask;
239         /* Adding the low_zeros_mask to the original mask
240          * basically is a bitwise OR operation.
241          * If the original mask was contiguous, we end up with a
242          * contiguous bitmask from bit 0 to the highest bit
243          * set in the original mask. Adding 1 will result in a single
244          * bit set, which is a power of two. */
245         is_contiguous = is_power_of_two(mask + low_zeros_mask + 1);
246
247         return is_contiguous;
248 }
249
250 static unsigned int generate_imm_operand(struct assembler_context *ctx,
251                                          const struct immediate *imm)
252 {
253         unsigned int val, tmp;
254         unsigned int mask;
255
256         /* format: 0b11ii iiii iiii */
257
258         val = 0xC00;
259         if (ctx->arch == 15)
260                 val <<= 1;
261         tmp = imm->imm;
262
263         if (!is_valid_imm(ctx, tmp)) {
264                 asm_warn(ctx, "IMMEDIATE 0x%X (%d) too long "
265                               "(> 9 bits + sign). Did you intend to "
266                               "use implicit sign extension?",
267                          tmp, (int)tmp);
268         }
269
270         if (ctx->arch == 15)
271                 tmp &= 0x7FF;
272         else
273                 tmp &= 0x3FF;
274         val |= tmp;
275
276         return val;
277 }
278
279 static unsigned int generate_reg_operand(struct assembler_context *ctx,
280                                          const struct registr *reg)
281 {
282         unsigned int val = 0;
283
284         switch (reg->type) {
285         case GPR:
286                 /* format: 0b1011 11rr rrrr */
287                 val |= 0xBC0;
288                 if (ctx->arch == 15)
289                         val <<= 1;
290                 if (reg->nr & ~0x3F) //FIXME 128 regs for v15 arch possible?
291                         asm_error(ctx, "GPR-nr too big");
292                 val |= reg->nr;
293                 break;
294         case SPR:
295                 /* format: 0b100. .... .... */
296                 val |= 0x800;
297                 if (ctx->arch == 15)
298                         val <<= 1;
299                 if (reg->nr & ~0x1FF)
300                         asm_error(ctx, "SPR-nr too big");
301                 val |= reg->nr;
302                 break;
303         case OFFR:
304                 /* format: 0b1000 0110 0rrr */
305                 val |= 0x860;
306                 if (ctx->arch == 15)
307                         val <<= 1;
308                 if (reg->nr & ~0x7)
309                         asm_error(ctx, "OFFR-nr too big");
310                 val |= reg->nr;
311                 break;
312         default:
313                 asm_error(ctx, "generate_reg_operand() regtype");
314         }
315
316         return val;
317 }
318
319 static unsigned int generate_mem_operand(struct assembler_context *ctx,
320                                          const struct memory *mem)
321 {
322         unsigned int val = 0, off, reg;
323
324         switch (mem->type) {
325         case MEM_DIRECT:
326                 /* format: 0b0mmm mmmm mmmm */
327                 off = mem->offset;
328                 if (off & ~0x7FF) { //FIXME 4096 words for v15 arch possible?
329                         asm_warn(ctx, "DIRECT memoffset 0x%X too long (> 11 bits)", off);
330                         off &= 0x7FF;
331                 }
332                 val |= off;
333                 break;
334         case MEM_INDIRECT:
335                 /* format: 0b101r rroo oooo */
336                 off = mem->offset;
337                 reg = mem->offr_nr;
338                 val |= 0xA00;
339                 //FIXME what about v15 arch?
340                 if (off & ~0x3F) {
341                         asm_warn(ctx, "INDIRECT memoffset 0x%X too long (> 6 bits)", off);
342                         off &= 0x3F;
343                 }
344                 if (reg > 6) {
345                         /* Assembler bug. The parser shouldn't pass this value. */
346                         asm_error(ctx, "OFFR-nr too big");
347                 }
348                 if (reg == 6) {
349                         asm_warn(ctx, "Using offset register 6. This register is broken "
350                                  "on certain devices. Use off0 to off5 only.");
351                 }
352                 val |= off;
353                 val |= (reg << 6);
354                 break;
355         default:
356                 asm_error(ctx, "generate_mem_operand() memtype");
357         }
358
359         return val;
360 }
361
362 static void generate_operand(struct assembler_context *ctx,
363                              const struct operand *oper,
364                              struct out_operand *out)
365 {
366         out->type = OUTOPER_NORMAL;
367
368         switch (oper->type) {
369         case OPER_IMM:
370                 out->u.operand = generate_imm_operand(ctx, oper->u.imm);
371                 break;
372         case OPER_REG:
373                 out->u.operand = generate_reg_operand(ctx, oper->u.reg);
374                 break;
375         case OPER_MEM:
376                 out->u.operand = generate_mem_operand(ctx, oper->u.mem);
377                 break;
378         case OPER_LABEL:
379                 out->type = OUTOPER_LABELREF;
380                 out->u.label = oper->u.label;
381                 break;
382         case OPER_ADDR:
383                 out->u.operand = oper->u.addr->addr;
384                 break;
385         case OPER_RAW:
386                 out->u.operand = oper->u.raw;
387                 break;
388         default:
389                 asm_error(ctx, "generate_operand() operstate");
390         }
391 }
392
393 static struct code_output * do_assemble_insn(struct assembler_context *ctx,
394                                              struct instruction *insn,
395                                              unsigned int opcode)
396 {
397         int i;
398         struct operlist *ol;
399         int nr_oper = 0;
400         uint64_t code = 0;
401         struct code_output *out;
402         struct label *labelref = NULL;
403         struct operand *oper;
404         int have_spr_operand = 0;
405         int have_mem_operand = 0;
406
407         out = xmalloc(sizeof(*out));
408         INIT_LIST_HEAD(&out->list);
409         out->opcode = opcode;
410
411         ol = insn->operands;
412         if (ARRAY_SIZE(out->operands) > ARRAY_SIZE(ol->oper))
413                 asm_error(ctx, "Internal operand array confusion");
414
415         for (i = 0; i < ARRAY_SIZE(out->operands); i++) {
416                 oper = ol->oper[i];
417                 if (!oper)
418                         continue;
419
420                 /* If this is an INPUT operand (first or second), we must
421                  * make sure that not both are accessing SPR or MEMORY.
422                  * The device only supports one SPR or MEMORY operand in
423                  * the input operands. */
424                 if ((i == 0) || (i == 1)) {
425                         if ((oper->type == OPER_REG) &&
426                             (oper->u.reg->type == SPR)) {
427                                 if (have_spr_operand)
428                                         asm_error(ctx, "Multiple SPR input operands in one instruction");
429                                 have_spr_operand = 1;
430                         }
431                         if (oper->type == OPER_MEM) {
432                                 if (have_mem_operand)
433                                         asm_error(ctx, "Multiple MEMORY input operands in on instruction");
434                                 have_mem_operand = 1;
435                         }
436                 }
437
438                 generate_operand(ctx, oper, &out->operands[i]);
439                 nr_oper++;
440         }
441         if (nr_oper != 3)
442                 asm_error(ctx, "Internal error: nr_oper at "
443                                "lowlevel do_assemble_insn");
444
445         list_add_tail(&out->list, &ctx->output);
446
447         return out;
448 }
449
450 static unsigned int merge_ext_into_opcode(struct assembler_context *ctx,
451                                           unsigned int opbase,
452                                           struct instruction *insn)
453 {
454         struct operlist *ol;
455         unsigned int opcode;
456         unsigned int mask, shift;
457
458         ol = insn->operands;
459         opcode = opbase;
460         mask = ol->oper[0]->u.raw;
461         if (mask & ~0xF)
462                 asm_error(ctx, "opcode MASK extension too big (> 0xF)");
463         shift = ol->oper[1]->u.raw;
464         if (shift & ~0xF)
465                 asm_error(ctx, "opcode SHIFT extension too big (> 0xF)");
466         opcode |= (mask << 4);
467         opcode |= shift;
468         ol->oper[0] = ol->oper[2];
469         ol->oper[1] = ol->oper[3];
470         ol->oper[2] = ol->oper[4];
471
472         return opcode;
473 }
474
475 static unsigned int merge_external_jmp_into_opcode(struct assembler_context *ctx,
476                                                    unsigned int opbase,
477                                                    struct instruction *insn)
478 {
479         struct operand *fake;
480         struct registr *fake_reg;
481         struct operand *target;
482         struct operlist *ol;
483         unsigned int cond;
484         unsigned int opcode;
485
486         ol = insn->operands;
487         opcode = opbase;
488         cond = ol->oper[0]->u.imm->imm;
489         if (cond & ~0xFF)
490                 asm_error(ctx, "External jump condition value too big (> 0xFF)");
491         opcode |= cond;
492         target = ol->oper[1];
493         memset(ol->oper, 0, sizeof(ol->oper));
494
495         /* This instruction has two fake r0 operands
496          * at position 0 and 1. */
497         fake = xmalloc(sizeof(*fake));
498         fake_reg = xmalloc(sizeof(*fake_reg));
499         fake->type = OPER_REG;
500         fake->u.reg = fake_reg;
501         fake_reg->type = GPR;
502         fake_reg->nr = 0;
503
504         ol->oper[0] = fake;
505         ol->oper[1] = fake;
506         ol->oper[2] = target;
507
508         return opcode;
509 }
510
511 static void assemble_instruction(struct assembler_context *ctx,
512                                  struct instruction *insn);
513
514 static void emulate_mov_insn(struct assembler_context *ctx,
515                              struct instruction *insn)
516 {
517         struct instruction em_insn;
518         struct operlist em_ol;
519         struct operand em_op_shift;
520         struct operand em_op_mask;
521         struct operand em_op_x;
522         struct operand em_op_y;
523         struct immediate em_imm_x;
524         struct immediate em_imm_y;
525
526         struct operand *in, *out;
527         unsigned int tmp;
528
529         /* This is a pseudo-OP. We emulate it by OR or ORX */
530
531         in = insn->operands->oper[0];
532         out = insn->operands->oper[1];
533
534         em_insn.op = OP_OR;
535         em_ol.oper[0] = in;
536         em_imm_x.imm = 0;
537         em_op_x.type = OPER_IMM;
538         em_op_x.u.imm = &em_imm_x;
539         em_ol.oper[1] = &em_op_x;
540         em_ol.oper[2] = out;
541
542         if (in->type == OPER_IMM) {
543                 tmp = in->u.imm->imm;
544                 if (!is_possible_imm(tmp))
545                         asm_error(ctx, "MOV operand 0x%X > 16bit", tmp);
546                 if (!is_valid_imm(ctx, tmp)) {
547                         /* Immediate too big for plain OR */
548                         em_insn.op = OP_ORX;
549
550                         em_op_mask.type = OPER_RAW;
551                         em_op_mask.u.raw = 0x7;
552                         em_op_shift.type = OPER_RAW;
553                         em_op_shift.u.raw = 0x8;
554
555                         em_imm_x.imm = (tmp & 0xFF00) >> 8;
556                         em_op_x.type = OPER_IMM;
557                         em_op_x.u.imm = &em_imm_x;
558
559                         em_imm_y.imm = (tmp & 0x00FF);
560                         em_op_y.type = OPER_IMM;
561                         em_op_y.u.imm = &em_imm_y;
562
563                         em_ol.oper[0] = &em_op_mask;
564                         em_ol.oper[1] = &em_op_shift;
565                         em_ol.oper[2] = &em_op_x;
566                         em_ol.oper[3] = &em_op_y;
567                         em_ol.oper[4] = out;
568                 }
569         }
570
571         em_insn.operands = &em_ol;
572         assemble_instruction(ctx, &em_insn); /* recurse */
573 }
574
575 static void emulate_jmp_insn(struct assembler_context *ctx,
576                              struct instruction *insn)
577 {
578         struct instruction em_insn;
579         struct operlist em_ol;
580         struct immediate em_condition;
581         struct operand em_cond_op;
582
583         /* This is a pseudo-OP. We emulate it with
584          * JEXT 0x7F, target */
585
586         em_insn.op = OP_JEXT;
587         em_condition.imm = 0x7F; /* Ext cond: Always true */
588         em_cond_op.type = OPER_IMM;
589         em_cond_op.u.imm = &em_condition;
590         em_ol.oper[0] = &em_cond_op;
591         em_ol.oper[1] = insn->operands->oper[0]; /* Target */
592         em_insn.operands = &em_ol;
593
594         assemble_instruction(ctx, &em_insn); /* recurse */
595 }
596
597 static void emulate_jand_insn(struct assembler_context *ctx,
598                               struct instruction *insn,
599                               int inverted)
600 {
601         struct code_output *out;
602         struct instruction em_insn;
603         struct operlist em_ol;
604         struct operand em_op_shift;
605         struct operand em_op_mask;
606         struct operand em_op_y;
607         struct immediate em_imm;
608
609         struct operand *oper0, *oper1, *oper2;
610         struct operand *imm_oper = NULL;
611         unsigned int tmp;
612         int first_bit, last_bit;
613
614         oper0 = insn->operands->oper[0];
615         oper1 = insn->operands->oper[1];
616         oper2 = insn->operands->oper[2];
617
618         if (oper0->type == OPER_IMM)
619                 imm_oper = oper0;
620         if (oper1->type == OPER_IMM)
621                 imm_oper = oper1;
622         if (oper0->type == OPER_IMM && oper1->type == OPER_IMM)
623                 imm_oper = NULL;
624
625         if (imm_oper) {
626                 /* We have a single immediate operand.
627                  * Check if it's representable by a normal JAND insn.
628                  */
629                 tmp = imm_oper->u.imm->imm;
630                 if (!is_valid_imm(ctx, tmp)) {
631                         /* Nope, this must be emulated by JZX/JNZX */
632                         if (!is_contiguous_bitmask(tmp)) {
633                                 asm_error(ctx, "Long bitmask 0x%X is not contiguous",
634                                           tmp);
635                         }
636
637                         first_bit = ffs(tmp);
638                         last_bit = ffs(~(tmp >> (first_bit - 1))) - 1 + first_bit - 1;
639
640                         if (inverted)
641                                 em_insn.op = OP_JZX;
642                         else
643                                 em_insn.op = OP_JNZX;
644                         em_op_shift.type = OPER_RAW;
645                         em_op_shift.u.raw = first_bit - 1;
646                         em_op_mask.type = OPER_RAW;
647                         em_op_mask.u.raw = last_bit - first_bit;
648
649                         em_imm.imm = 0;
650                         em_op_y.type = OPER_IMM;
651                         em_op_y.u.imm = &em_imm;
652
653                         em_ol.oper[0] = &em_op_mask;
654                         em_ol.oper[1] = &em_op_shift;
655                         if (oper0->type != OPER_IMM)
656                                 em_ol.oper[2] = oper0;
657                         else
658                                 em_ol.oper[2] = oper1;
659                         em_ol.oper[3] = &em_op_y;
660                         em_ol.oper[4] = oper2;
661
662                         em_insn.operands = &em_ol;
663
664                         assemble_instruction(ctx, &em_insn); /* recurse */
665                         return;
666                 }
667         }
668
669         /* Do a normal JAND/JNAND instruction */
670         if (inverted)
671                 out = do_assemble_insn(ctx, insn, 0x040 | 0x1);
672         else
673                 out = do_assemble_insn(ctx, insn, 0x040);
674         out->is_jump_insn = 1;
675 }
676
677 static void assemble_instruction(struct assembler_context *ctx,
678                                  struct instruction *insn)
679 {
680         struct code_output *out;
681         unsigned int opcode;
682
683         switch (insn->op) {
684         case OP_ADD:
685                 do_assemble_insn(ctx, insn, 0x1C0);
686                 break;
687         case OP_ADDSC:
688                 do_assemble_insn(ctx, insn, 0x1C2);
689                 break;
690         case OP_ADDC:
691                 do_assemble_insn(ctx, insn, 0x1C1);
692                 break;
693         case OP_ADDSCC:
694                 do_assemble_insn(ctx, insn, 0x1C3);
695                 break;
696         case OP_SUB:
697                 do_assemble_insn(ctx, insn, 0x1D0);
698                 break;
699         case OP_SUBSC:
700                 do_assemble_insn(ctx, insn, 0x1D2);
701                 break;
702         case OP_SUBC:
703                 do_assemble_insn(ctx, insn, 0x1D1);
704                 break;
705         case OP_SUBSCC:
706                 do_assemble_insn(ctx, insn, 0x1D3);
707                 break;
708         case OP_SRA:
709                 do_assemble_insn(ctx, insn, 0x130);
710                 break;
711         case OP_OR:
712                 do_assemble_insn(ctx, insn, 0x160);
713                 break;
714         case OP_AND:
715                 do_assemble_insn(ctx, insn, 0x140);
716                 break;
717         case OP_XOR:
718                 do_assemble_insn(ctx, insn, 0x170);
719                 break;
720         case OP_SR:
721                 do_assemble_insn(ctx, insn, 0x120);
722                 break;
723         case OP_SRX:
724                 opcode = merge_ext_into_opcode(ctx, 0x200, insn);
725                 do_assemble_insn(ctx, insn, opcode);
726                 break;
727         case OP_SL:
728                 do_assemble_insn(ctx, insn, 0x110);
729                 break;
730         case OP_RL:
731                 do_assemble_insn(ctx, insn, 0x1A0);
732                 break;
733         case OP_RR:
734                 do_assemble_insn(ctx, insn, 0x1B0);
735                 break;
736         case OP_NAND:
737                 do_assemble_insn(ctx, insn, 0x150);
738                 break;
739         case OP_ORX:
740                 opcode = merge_ext_into_opcode(ctx, 0x300, insn);
741                 do_assemble_insn(ctx, insn, opcode);
742                 break;
743         case OP_MOV:
744                 emulate_mov_insn(ctx, insn);
745                 return;
746         case OP_JMP:
747                 emulate_jmp_insn(ctx, insn);
748                 return;
749         case OP_JAND:
750                 emulate_jand_insn(ctx, insn, 0);
751                 return;
752         case OP_JNAND:
753                 emulate_jand_insn(ctx, insn, 1);
754                 return;
755         case OP_JS:
756                 out = do_assemble_insn(ctx, insn, 0x050);
757                 out->is_jump_insn = 1;
758                 break;
759         case OP_JNS:
760                 out = do_assemble_insn(ctx, insn, 0x050 | 0x1);
761                 out->is_jump_insn = 1;
762                 break;
763         case OP_JE:
764                 out = do_assemble_insn(ctx, insn, 0x0D0);
765                 out->is_jump_insn = 1;
766                 break;
767         case OP_JNE:
768                 out = do_assemble_insn(ctx, insn, 0x0D0 | 0x1);
769                 out->is_jump_insn = 1;
770                 break;
771         case OP_JLS:
772                 out = do_assemble_insn(ctx, insn, 0x0D2);
773                 out->is_jump_insn = 1;
774                 break;
775         case OP_JGES:
776                 out = do_assemble_insn(ctx, insn, 0x0D2 | 0x1);
777                 out->is_jump_insn = 1;
778                 break;
779         case OP_JGS:
780                 out = do_assemble_insn(ctx, insn, 0x0D4);
781                 out->is_jump_insn = 1;
782                 break;
783         case OP_JLES:
784                 out = do_assemble_insn(ctx, insn, 0x0D4 | 0x1);
785                 out->is_jump_insn = 1;
786                 break;
787         case OP_JL:
788                 out = do_assemble_insn(ctx, insn, 0x0DA);
789                 out->is_jump_insn = 1;
790                 break;
791         case OP_JGE:
792                 out = do_assemble_insn(ctx, insn, 0x0DA | 0x1);
793                 out->is_jump_insn = 1;
794                 break;
795         case OP_JG:
796                 out = do_assemble_insn(ctx, insn, 0x0DC);
797                 break;
798         case OP_JLE:
799                 out = do_assemble_insn(ctx, insn, 0x0DC | 0x1);
800                 out->is_jump_insn = 1;
801                 break;
802         case OP_JZX:
803                 opcode = merge_ext_into_opcode(ctx, 0x400, insn);
804                 out = do_assemble_insn(ctx, insn, opcode);
805                 out->is_jump_insn = 1;
806                 break;
807         case OP_JNZX:
808                 opcode = merge_ext_into_opcode(ctx, 0x500, insn);
809                 out = do_assemble_insn(ctx, insn, opcode);
810                 out->is_jump_insn = 1;
811                 break;
812         case OP_JEXT:
813                 opcode = merge_external_jmp_into_opcode(ctx, 0x700, insn);
814                 out = do_assemble_insn(ctx, insn, opcode);
815                 out->is_jump_insn = 1;
816                 break;
817         case OP_JNEXT:
818                 opcode = merge_external_jmp_into_opcode(ctx, 0x600, insn);
819                 out = do_assemble_insn(ctx, insn, opcode);
820                 out->is_jump_insn = 1;
821                 break;
822         case OP_CALL:
823                 do_assemble_insn(ctx, insn, 0x002);
824                 break;
825         case OP_RET:
826                 /* Get the previous instruction and check whether it
827                  * is a jump instruction. */
828                 list_for_each_entry_reverse(out, &ctx->output, list) {
829                         /* Search the last insn. */
830                         if (out->type == OUT_INSN) {
831                                 if (out->is_jump_insn) {
832                                         asm_warn(ctx, "RET instruction directly after "
833                                                  "jump instruction. The hardware won't like this.");
834                                 }
835                                 break;
836                         }
837                 }
838                 do_assemble_insn(ctx, insn, 0x003);
839                 break;
840         case OP_TKIPH:
841         case OP_TKIPHS:
842         case OP_TKIPL:
843         case OP_TKIPLS:
844                 do_assemble_insn(ctx, insn, 0x1E0);
845                 break;
846         case OP_NAP:
847                 do_assemble_insn(ctx, insn, 0x001);
848                 break;
849         case RAW_CODE:
850                 do_assemble_insn(ctx, insn, insn->opcode);
851                 break;
852         default:
853                 asm_error(ctx, "Unknown op");
854         }
855 }
856
857 static void assemble_instructions(struct assembler_context *ctx)
858 {
859         struct statement *s;
860         struct instruction *insn;
861         struct code_output *out;
862
863         if (ctx->start_label) {
864                 /* Generate a jump instruction at offset 0 to
865                  * jump to the code start.
866                  */
867                 struct instruction sjmp;
868                 struct operlist ol;
869                 struct operand oper;
870
871                 oper.type = OPER_LABEL;
872                 oper.u.label = ctx->start_label;
873                 ol.oper[0] = &oper;
874                 sjmp.op = OP_JMP;
875                 sjmp.operands = &ol;
876
877                 assemble_instruction(ctx, &sjmp);
878                 out = list_entry(ctx->output.next, struct code_output, list);
879                 out->is_start_insn = 1;
880         }
881
882         for_each_statement(ctx, s) {
883                 switch (s->type) {
884                 case STMT_INSN:
885                         ctx->cur_stmt = s;
886                         insn = s->u.insn;
887                         assemble_instruction(ctx, insn);
888                         break;
889                 case STMT_LABEL:
890                         out = xmalloc(sizeof(*out));
891                         INIT_LIST_HEAD(&out->list);
892                         out->type = OUT_LABEL;
893                         out->labelname = s->u.label->name;
894
895                         list_add_tail(&out->list, &ctx->output);
896                         break;
897                 case STMT_ASMDIR:
898                         break;
899                 }
900         } for_each_statement_end(ctx, s);
901 }
902
903 /* Resolve a label reference to the address it points to. */
904 static int get_labeladdress(struct assembler_context *ctx,
905                             struct code_output *this_insn,
906                             struct label *labelref)
907 {
908         struct code_output *c;
909         bool found = 0;
910         int address = -1;
911
912         switch (labelref->direction) {
913         case LABELREF_ABSOLUTE:
914                 list_for_each_entry(c, &ctx->output, list) {
915                         if (c->type != OUT_LABEL)
916                                 continue;
917                         if (strcmp(c->labelname, labelref->name) != 0)
918                                 continue;
919                         if (found) {
920                                 asm_error(ctx, "Ambiguous label reference \"%s\"",
921                                           labelref->name);
922                         }
923                         found = 1;
924                         address = c->address;
925                 }
926                 break;
927         case LABELREF_RELATIVE_BACK:
928                 for (c = list_entry(this_insn->list.prev, typeof(*c), list);
929                      &c->list != &ctx->output;
930                      c = list_entry(c->list.prev, typeof(*c), list)) {
931                         if (c->type != OUT_LABEL)
932                                 continue;
933                         if (strcmp(c->labelname, labelref->name) == 0) {
934                                 /* Found */
935                                 address = c->address;
936                                 break;
937                         }
938                 }
939                 break;
940         case LABELREF_RELATIVE_FORWARD:
941                 for (c = list_entry(this_insn->list.next, typeof(*c), list);
942                      &c->list != &ctx->output;
943                      c = list_entry(c->list.next, typeof(*c), list)) {
944                         if (c->type != OUT_LABEL)
945                                 continue;
946                         if (strcmp(c->labelname, labelref->name) == 0) {
947                                 /* Found */
948                                 address = c->address;
949                                 break;
950                         }
951                 }
952                 break;
953         }
954
955         return address;
956 }
957
958 static void resolve_labels(struct assembler_context *ctx)
959 {
960         struct code_output *c;
961         int addr;
962         int i;
963         unsigned int current_address;
964
965         /* Calculate the absolute addresses for each instruction. */
966 recalculate_addresses:
967         current_address = 0;
968         list_for_each_entry(c, &ctx->output, list) {
969                 switch (c->type) {
970                 case OUT_INSN:
971                         c->address = current_address;
972                         current_address++;
973                         break;
974                 case OUT_LABEL:
975                         c->address = current_address;
976                         break;
977                 }
978         }
979
980         /* Resolve the symbolic label references. */
981         list_for_each_entry(c, &ctx->output, list) {
982                 switch (c->type) {
983                 case OUT_INSN:
984                         if (c->is_start_insn) {
985                                 /* If the first %start-jump jumps to 001, we can
986                                  * optimize it away, as it's unneeded.
987                                  */
988                                 i = 2;
989                                 if (c->operands[i].type != OUTOPER_LABELREF)
990                                         asm_error(ctx, "Internal error, %%start insn oper 2 not labelref");
991                                 if (c->operands[i].u.label->direction != LABELREF_ABSOLUTE)
992                                         asm_error(ctx, "%%start label reference not absolute");
993                                 addr = get_labeladdress(ctx, c, c->operands[i].u.label);
994                                 if (addr < 0)
995                                         goto does_not_exist;
996                                 if (addr == 1) {
997                                         list_del(&c->list); /* Kill it */
998                                         goto recalculate_addresses;
999                                 }
1000                         }
1001
1002                         for (i = 0; i < ARRAY_SIZE(c->operands); i++) {
1003                                 if (c->operands[i].type != OUTOPER_LABELREF)
1004                                         continue;
1005                                 addr = get_labeladdress(ctx, c, c->operands[i].u.label);
1006                                 if (addr < 0)
1007                                         goto does_not_exist;
1008                                 c->operands[i].u.operand = addr;
1009                                 if (i != 2) {
1010                                         /* Is not a jump target.
1011                                          * Make it be an immediate */
1012                                         if (ctx->arch == 5)
1013                                                 c->operands[i].u.operand |= 0xC00;
1014                                         else if (ctx->arch == 15)
1015                                                 c->operands[i].u.operand |= 0xC00 << 1;
1016                                         else
1017                                                 asm_error(ctx, "Internal error: label res imm");
1018                                 }
1019                         }
1020                         break;
1021                 case OUT_LABEL:
1022                         break;
1023                 }
1024         }
1025
1026         return;
1027 does_not_exist:
1028         asm_error(ctx, "Label \"%s\" does not exist",
1029                   c->operands[i].u.label->name);
1030 }
1031
1032 static void emit_code(struct assembler_context *ctx)
1033 {
1034         FILE *fd;
1035         const char *fn;
1036         struct code_output *c;
1037         uint64_t code;
1038         unsigned char outbuf[8];
1039         unsigned int insn_count = 0;
1040         struct fw_header hdr;
1041
1042         fn = outfile_name;
1043         fd = fopen(fn, "w+");
1044         if (!fd) {
1045                 fprintf(stderr, "Could not open microcode output file \"%s\"\n", fn);
1046                 exit(1);
1047         }
1048         if (IS_VERBOSE_DEBUG)
1049                 fprintf(stderr, "\nCode:\n");
1050
1051         list_for_each_entry(c, &ctx->output, list) {
1052                 switch (c->type) {
1053                 case OUT_INSN:
1054                         insn_count++;
1055                         break;
1056                 default:
1057                         break;
1058                 }
1059         }
1060
1061         memset(&hdr, 0, sizeof(hdr));
1062         hdr.type = FW_TYPE_UCODE;
1063         hdr.ver = FW_HDR_VER;
1064         hdr.size = cpu_to_be32(8 * insn_count);
1065         if (fwrite(&hdr, sizeof(hdr), 1, fd) != 1) {
1066                 fprintf(stderr, "Could not write microcode outfile\n");
1067                 exit(1);
1068         }
1069
1070         if (insn_count > NUM_INSN_LIMIT)
1071                 asm_warn(ctx, "Generating more than %d instructions. This "
1072                               "will overflow the device microcode memory.",
1073                          NUM_INSN_LIMIT);
1074
1075         list_for_each_entry(c, &ctx->output, list) {
1076                 switch (c->type) {
1077                 case OUT_INSN:
1078                         if (IS_VERBOSE_DEBUG) {
1079                                 fprintf(stderr, "%03X %03X,%03X,%03X\n",
1080                                         c->opcode,
1081                                         c->operands[0].u.operand,
1082                                         c->operands[1].u.operand,
1083                                         c->operands[2].u.operand);
1084                         }
1085                         code = 0;
1086
1087                         if (ctx->arch == 5) {
1088                                 /* Instruction binary format is: xxyyyzzz0000oooX
1089                                  *                        byte-0-^       byte-7-^
1090                                  * ooo is the opcode
1091                                  * Xxx is the first operand
1092                                  * yyy is the second operand
1093                                  * zzz is the third operand
1094                                  */
1095                                 code |= ((uint64_t)c->operands[2].u.operand);
1096                                 code |= ((uint64_t)c->operands[1].u.operand) << 12;
1097                                 code |= ((uint64_t)c->operands[0].u.operand) << 24;
1098                                 code |= ((uint64_t)c->opcode) << 36;
1099                                 code = ((code & (uint64_t)0xFFFFFFFF00000000ULL) >> 32) |
1100                                        ((code & (uint64_t)0x00000000FFFFFFFFULL) << 32);
1101                         } else if (ctx->arch == 15) {
1102                                 code |= ((uint64_t)c->operands[2].u.operand);
1103                                 code |= ((uint64_t)c->operands[1].u.operand) << 13;
1104                                 code |= ((uint64_t)c->operands[0].u.operand) << 26;
1105                                 code |= ((uint64_t)c->opcode) << 39;
1106                                 code = ((code & (uint64_t)0xFFFFFFFF00000000ULL) >> 32) |
1107                                        ((code & (uint64_t)0x00000000FFFFFFFFULL) << 32);
1108                         } else {
1109                                 asm_error(ctx, "No emit format for arch %u",
1110                                           ctx->arch);
1111                         }
1112                         outbuf[0] = (code & (uint64_t)0xFF00000000000000ULL) >> 56;
1113                         outbuf[1] = (code & (uint64_t)0x00FF000000000000ULL) >> 48;
1114                         outbuf[2] = (code & (uint64_t)0x0000FF0000000000ULL) >> 40;
1115                         outbuf[3] = (code & (uint64_t)0x000000FF00000000ULL) >> 32;
1116                         outbuf[4] = (code & (uint64_t)0x00000000FF000000ULL) >> 24;
1117                         outbuf[5] = (code & (uint64_t)0x0000000000FF0000ULL) >> 16;
1118                         outbuf[6] = (code & (uint64_t)0x000000000000FF00ULL) >> 8;
1119                         outbuf[7] = (code & (uint64_t)0x00000000000000FFULL) >> 0;
1120
1121                         if (fwrite(&outbuf, ARRAY_SIZE(outbuf), 1, fd) != 1) {
1122                                 fprintf(stderr, "Could not write microcode outfile\n");
1123                                 exit(1);
1124                         }
1125                         break;
1126                 case OUT_LABEL:
1127                         break;
1128                 }
1129         }
1130
1131         if (arg_print_sizes) {
1132                 printf("%s:  text = %u instructions (%u bytes)\n",
1133                        fn, insn_count,
1134                        (unsigned int)(insn_count * sizeof(uint64_t)));
1135         }
1136
1137         fclose(fd);
1138 }
1139
1140 static void assemble(void)
1141 {
1142         struct assembler_context ctx;
1143
1144         memset(&ctx, 0, sizeof(ctx));
1145         INIT_LIST_HEAD(&ctx.output);
1146
1147         eval_directives(&ctx);
1148         assemble_instructions(&ctx);
1149         resolve_labels(&ctx);
1150         emit_code(&ctx);
1151 }
1152
1153 static void initialize(void)
1154 {
1155         INIT_LIST_HEAD(&infile.sl);
1156         INIT_LIST_HEAD(&infile.ivals);
1157 #ifdef YYDEBUG
1158         if (IS_INSANE_DEBUG)
1159                 yydebug = 1;
1160         else
1161                 yydebug = 0;
1162 #endif /* YYDEBUG */
1163 }
1164
1165 int main(int argc, char **argv)
1166 {
1167         int err, res = 1;
1168
1169         err = parse_args(argc, argv);
1170         if (err < 0)
1171                 goto out;
1172         if (err > 0) {
1173                 res = 0;
1174                 goto out;
1175         }
1176         err = open_input_file();
1177         if (err)
1178                 goto out;
1179         initialize();
1180         yyparse();
1181         assemble();
1182         assemble_initvals();
1183         close_input_file();
1184         res = 0;
1185 out:
1186         /* Lazyman simply leaks all allocated memory. */
1187         return res;
1188 }