b43-asm: Add an option to print the code sizes after assembling.
[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 & ~0x7)
345                         asm_error(ctx, "OFFR-nr too big");
346                 val |= off;
347                 val |= (reg << 6);
348                 break;
349         default:
350                 asm_error(ctx, "generate_mem_operand() memtype");
351         }
352
353         return val;
354 }
355
356 static void generate_operand(struct assembler_context *ctx,
357                              const struct operand *oper,
358                              struct out_operand *out)
359 {
360         out->type = OUTOPER_NORMAL;
361
362         switch (oper->type) {
363         case OPER_IMM:
364                 out->u.operand = generate_imm_operand(ctx, oper->u.imm);
365                 break;
366         case OPER_REG:
367                 out->u.operand = generate_reg_operand(ctx, oper->u.reg);
368                 break;
369         case OPER_MEM:
370                 out->u.operand = generate_mem_operand(ctx, oper->u.mem);
371                 break;
372         case OPER_LABEL:
373                 out->type = OUTOPER_LABELREF;
374                 out->u.label = oper->u.label;
375                 break;
376         case OPER_ADDR:
377                 out->u.operand = oper->u.addr->addr;
378                 break;
379         case OPER_RAW:
380                 out->u.operand = oper->u.raw;
381                 break;
382         default:
383                 asm_error(ctx, "generate_operand() operstate");
384         }
385 }
386
387 static struct code_output * do_assemble_insn(struct assembler_context *ctx,
388                                              struct instruction *insn,
389                                              unsigned int opcode)
390 {
391         int i;
392         struct operlist *ol;
393         int nr_oper = 0;
394         uint64_t code = 0;
395         struct code_output *out;
396         struct label *labelref = NULL;
397         struct operand *oper;
398         int have_spr_operand = 0;
399         int have_mem_operand = 0;
400
401         out = xmalloc(sizeof(*out));
402         INIT_LIST_HEAD(&out->list);
403         out->opcode = opcode;
404
405         ol = insn->operands;
406         if (ARRAY_SIZE(out->operands) > ARRAY_SIZE(ol->oper))
407                 asm_error(ctx, "Internal operand array confusion");
408
409         for (i = 0; i < ARRAY_SIZE(out->operands); i++) {
410                 oper = ol->oper[i];
411                 if (!oper)
412                         continue;
413
414                 /* If this is an INPUT operand (first or second), we must
415                  * make sure that not both are accessing SPR or MEMORY.
416                  * The device only supports one SPR or MEMORY operand in
417                  * the input operands. */
418                 if ((i == 0) || (i == 1)) {
419                         if ((oper->type == OPER_REG) &&
420                             (oper->u.reg->type == SPR)) {
421                                 if (have_spr_operand)
422                                         asm_error(ctx, "Multiple SPR input operands in one instruction");
423                                 have_spr_operand = 1;
424                         }
425                         if (oper->type == OPER_MEM) {
426                                 if (have_mem_operand)
427                                         asm_error(ctx, "Multiple MEMORY input operands in on instruction");
428                                 have_mem_operand = 1;
429                         }
430                 }
431
432                 generate_operand(ctx, oper, &out->operands[i]);
433                 nr_oper++;
434         }
435         if (nr_oper != 3)
436                 asm_error(ctx, "Internal error: nr_oper at "
437                                "lowlevel do_assemble_insn");
438
439         list_add_tail(&out->list, &ctx->output);
440
441         return out;
442 }
443
444 static unsigned int merge_ext_into_opcode(struct assembler_context *ctx,
445                                           unsigned int opbase,
446                                           struct instruction *insn)
447 {
448         struct operlist *ol;
449         unsigned int opcode;
450         unsigned int mask, shift;
451
452         ol = insn->operands;
453         opcode = opbase;
454         mask = ol->oper[0]->u.raw;
455         if (mask & ~0xF)
456                 asm_error(ctx, "opcode MASK extension too big (> 0xF)");
457         shift = ol->oper[1]->u.raw;
458         if (shift & ~0xF)
459                 asm_error(ctx, "opcode SHIFT extension too big (> 0xF)");
460         opcode |= (mask << 4);
461         opcode |= shift;
462         ol->oper[0] = ol->oper[2];
463         ol->oper[1] = ol->oper[3];
464         ol->oper[2] = ol->oper[4];
465
466         return opcode;
467 }
468
469 static unsigned int merge_external_jmp_into_opcode(struct assembler_context *ctx,
470                                                    unsigned int opbase,
471                                                    struct instruction *insn)
472 {
473         struct operand *fake;
474         struct registr *fake_reg;
475         struct operand *target;
476         struct operlist *ol;
477         unsigned int cond;
478         unsigned int opcode;
479
480         ol = insn->operands;
481         opcode = opbase;
482         cond = ol->oper[0]->u.imm->imm;
483         if (cond & ~0xFF)
484                 asm_error(ctx, "External jump condition value too big (> 0xFF)");
485         opcode |= cond;
486         target = ol->oper[1];
487         memset(ol->oper, 0, sizeof(ol->oper));
488
489         /* This instruction has two fake r0 operands
490          * at position 0 and 1. */
491         fake = xmalloc(sizeof(*fake));
492         fake_reg = xmalloc(sizeof(*fake_reg));
493         fake->type = OPER_REG;
494         fake->u.reg = fake_reg;
495         fake_reg->type = GPR;
496         fake_reg->nr = 0;
497
498         ol->oper[0] = fake;
499         ol->oper[1] = fake;
500         ol->oper[2] = target;
501
502         return opcode;
503 }
504
505 static void assemble_instruction(struct assembler_context *ctx,
506                                  struct instruction *insn);
507
508 static void emulate_mov_insn(struct assembler_context *ctx,
509                              struct instruction *insn)
510 {
511         struct instruction em_insn;
512         struct operlist em_ol;
513         struct operand em_op_shift;
514         struct operand em_op_mask;
515         struct operand em_op_x;
516         struct operand em_op_y;
517         struct immediate em_imm_x;
518         struct immediate em_imm_y;
519
520         struct operand *in, *out;
521         unsigned int tmp;
522
523         /* This is a pseudo-OP. We emulate it by OR or ORX */
524
525         in = insn->operands->oper[0];
526         out = insn->operands->oper[1];
527
528         em_insn.op = OP_OR;
529         em_ol.oper[0] = in;
530         em_imm_x.imm = 0;
531         em_op_x.type = OPER_IMM;
532         em_op_x.u.imm = &em_imm_x;
533         em_ol.oper[1] = &em_op_x;
534         em_ol.oper[2] = out;
535
536         if (in->type == OPER_IMM) {
537                 tmp = in->u.imm->imm;
538                 if (!is_possible_imm(tmp))
539                         asm_error(ctx, "MOV operand 0x%X > 16bit", tmp);
540                 if (!is_valid_imm(ctx, tmp)) {
541                         /* Immediate too big for plain OR */
542                         em_insn.op = OP_ORX;
543
544                         em_op_mask.type = OPER_RAW;
545                         em_op_mask.u.raw = 0x7;
546                         em_op_shift.type = OPER_RAW;
547                         em_op_shift.u.raw = 0x8;
548
549                         em_imm_x.imm = (tmp & 0xFF00) >> 8;
550                         em_op_x.type = OPER_IMM;
551                         em_op_x.u.imm = &em_imm_x;
552
553                         em_imm_y.imm = (tmp & 0x00FF);
554                         em_op_y.type = OPER_IMM;
555                         em_op_y.u.imm = &em_imm_y;
556
557                         em_ol.oper[0] = &em_op_mask;
558                         em_ol.oper[1] = &em_op_shift;
559                         em_ol.oper[2] = &em_op_x;
560                         em_ol.oper[3] = &em_op_y;
561                         em_ol.oper[4] = out;
562                 }
563         }
564
565         em_insn.operands = &em_ol;
566         assemble_instruction(ctx, &em_insn); /* recurse */
567 }
568
569 static void emulate_jmp_insn(struct assembler_context *ctx,
570                              struct instruction *insn)
571 {
572         struct instruction em_insn;
573         struct operlist em_ol;
574         struct immediate em_condition;
575         struct operand em_cond_op;
576
577         /* This is a pseudo-OP. We emulate it with
578          * JEXT 0x7F, target */
579
580         em_insn.op = OP_JEXT;
581         em_condition.imm = 0x7F; /* Ext cond: Always true */
582         em_cond_op.type = OPER_IMM;
583         em_cond_op.u.imm = &em_condition;
584         em_ol.oper[0] = &em_cond_op;
585         em_ol.oper[1] = insn->operands->oper[0]; /* Target */
586         em_insn.operands = &em_ol;
587
588         assemble_instruction(ctx, &em_insn); /* recurse */
589 }
590
591 static void emulate_jand_insn(struct assembler_context *ctx,
592                               struct instruction *insn,
593                               int inverted)
594 {
595         struct code_output *out;
596         struct instruction em_insn;
597         struct operlist em_ol;
598         struct operand em_op_shift;
599         struct operand em_op_mask;
600         struct operand em_op_y;
601         struct immediate em_imm;
602
603         struct operand *oper0, *oper1, *oper2;
604         struct operand *imm_oper = NULL;
605         unsigned int tmp;
606         int first_bit, last_bit;
607
608         oper0 = insn->operands->oper[0];
609         oper1 = insn->operands->oper[1];
610         oper2 = insn->operands->oper[2];
611
612         if (oper0->type == OPER_IMM)
613                 imm_oper = oper0;
614         if (oper1->type == OPER_IMM)
615                 imm_oper = oper1;
616         if (oper0->type == OPER_IMM && oper1->type == OPER_IMM)
617                 imm_oper = NULL;
618
619         if (imm_oper) {
620                 /* We have a single immediate operand.
621                  * Check if it's representable by a normal JAND insn.
622                  */
623                 tmp = imm_oper->u.imm->imm;
624                 if (!is_valid_imm(ctx, tmp)) {
625                         /* Nope, this must be emulated by JZX/JNZX */
626                         if (!is_contiguous_bitmask(tmp)) {
627                                 asm_error(ctx, "Long bitmask 0x%X is not contiguous",
628                                           tmp);
629                         }
630
631                         first_bit = ffs(tmp);
632                         last_bit = ffs(~(tmp >> (first_bit - 1))) - 1 + first_bit - 1;
633
634                         if (inverted)
635                                 em_insn.op = OP_JZX;
636                         else
637                                 em_insn.op = OP_JNZX;
638                         em_op_shift.type = OPER_RAW;
639                         em_op_shift.u.raw = first_bit - 1;
640                         em_op_mask.type = OPER_RAW;
641                         em_op_mask.u.raw = last_bit - first_bit;
642
643                         em_imm.imm = 0;
644                         em_op_y.type = OPER_IMM;
645                         em_op_y.u.imm = &em_imm;
646
647                         em_ol.oper[0] = &em_op_mask;
648                         em_ol.oper[1] = &em_op_shift;
649                         if (oper0->type != OPER_IMM)
650                                 em_ol.oper[2] = oper0;
651                         else
652                                 em_ol.oper[2] = oper1;
653                         em_ol.oper[3] = &em_op_y;
654                         em_ol.oper[4] = oper2;
655
656                         em_insn.operands = &em_ol;
657
658                         assemble_instruction(ctx, &em_insn); /* recurse */
659                         return;
660                 }
661         }
662
663         /* Do a normal JAND/JNAND instruction */
664         if (inverted)
665                 out = do_assemble_insn(ctx, insn, 0x040 | 0x1);
666         else
667                 out = do_assemble_insn(ctx, insn, 0x040);
668         out->is_jump_insn = 1;
669 }
670
671 static void assemble_instruction(struct assembler_context *ctx,
672                                  struct instruction *insn)
673 {
674         struct code_output *out;
675         unsigned int opcode;
676
677         switch (insn->op) {
678         case OP_ADD:
679                 do_assemble_insn(ctx, insn, 0x1C0);
680                 break;
681         case OP_ADDSC:
682                 do_assemble_insn(ctx, insn, 0x1C2);
683                 break;
684         case OP_ADDC:
685                 do_assemble_insn(ctx, insn, 0x1C1);
686                 break;
687         case OP_ADDSCC:
688                 do_assemble_insn(ctx, insn, 0x1C3);
689                 break;
690         case OP_SUB:
691                 do_assemble_insn(ctx, insn, 0x1D0);
692                 break;
693         case OP_SUBSC:
694                 do_assemble_insn(ctx, insn, 0x1D2);
695                 break;
696         case OP_SUBC:
697                 do_assemble_insn(ctx, insn, 0x1D1);
698                 break;
699         case OP_SUBSCC:
700                 do_assemble_insn(ctx, insn, 0x1D3);
701                 break;
702         case OP_SRA:
703                 do_assemble_insn(ctx, insn, 0x130);
704                 break;
705         case OP_OR:
706                 do_assemble_insn(ctx, insn, 0x160);
707                 break;
708         case OP_AND:
709                 do_assemble_insn(ctx, insn, 0x140);
710                 break;
711         case OP_XOR:
712                 do_assemble_insn(ctx, insn, 0x170);
713                 break;
714         case OP_SR:
715                 do_assemble_insn(ctx, insn, 0x120);
716                 break;
717         case OP_SRX:
718                 opcode = merge_ext_into_opcode(ctx, 0x200, insn);
719                 do_assemble_insn(ctx, insn, opcode);
720                 break;
721         case OP_SL:
722                 do_assemble_insn(ctx, insn, 0x110);
723                 break;
724         case OP_RL:
725                 do_assemble_insn(ctx, insn, 0x1A0);
726                 break;
727         case OP_RR:
728                 do_assemble_insn(ctx, insn, 0x1B0);
729                 break;
730         case OP_NAND:
731                 do_assemble_insn(ctx, insn, 0x150);
732                 break;
733         case OP_ORX:
734                 opcode = merge_ext_into_opcode(ctx, 0x300, insn);
735                 do_assemble_insn(ctx, insn, opcode);
736                 break;
737         case OP_MOV:
738                 emulate_mov_insn(ctx, insn);
739                 return;
740         case OP_JMP:
741                 emulate_jmp_insn(ctx, insn);
742                 return;
743         case OP_JAND:
744                 emulate_jand_insn(ctx, insn, 0);
745                 return;
746         case OP_JNAND:
747                 emulate_jand_insn(ctx, insn, 1);
748                 return;
749         case OP_JS:
750                 out = do_assemble_insn(ctx, insn, 0x050);
751                 out->is_jump_insn = 1;
752                 break;
753         case OP_JNS:
754                 out = do_assemble_insn(ctx, insn, 0x050 | 0x1);
755                 out->is_jump_insn = 1;
756                 break;
757         case OP_JE:
758                 out = do_assemble_insn(ctx, insn, 0x0D0);
759                 out->is_jump_insn = 1;
760                 break;
761         case OP_JNE:
762                 out = do_assemble_insn(ctx, insn, 0x0D0 | 0x1);
763                 out->is_jump_insn = 1;
764                 break;
765         case OP_JLS:
766                 out = do_assemble_insn(ctx, insn, 0x0D2);
767                 out->is_jump_insn = 1;
768                 break;
769         case OP_JGES:
770                 out = do_assemble_insn(ctx, insn, 0x0D2 | 0x1);
771                 out->is_jump_insn = 1;
772                 break;
773         case OP_JGS:
774                 out = do_assemble_insn(ctx, insn, 0x0D4);
775                 out->is_jump_insn = 1;
776                 break;
777         case OP_JLES:
778                 out = do_assemble_insn(ctx, insn, 0x0D4 | 0x1);
779                 out->is_jump_insn = 1;
780                 break;
781         case OP_JL:
782                 out = do_assemble_insn(ctx, insn, 0x0DA);
783                 out->is_jump_insn = 1;
784                 break;
785         case OP_JGE:
786                 out = do_assemble_insn(ctx, insn, 0x0DA | 0x1);
787                 out->is_jump_insn = 1;
788                 break;
789         case OP_JG:
790                 out = do_assemble_insn(ctx, insn, 0x0DC);
791                 break;
792         case OP_JLE:
793                 out = do_assemble_insn(ctx, insn, 0x0DC | 0x1);
794                 out->is_jump_insn = 1;
795                 break;
796         case OP_JZX:
797                 opcode = merge_ext_into_opcode(ctx, 0x400, insn);
798                 out = do_assemble_insn(ctx, insn, opcode);
799                 out->is_jump_insn = 1;
800                 break;
801         case OP_JNZX:
802                 opcode = merge_ext_into_opcode(ctx, 0x500, insn);
803                 out = do_assemble_insn(ctx, insn, opcode);
804                 out->is_jump_insn = 1;
805                 break;
806         case OP_JEXT:
807                 opcode = merge_external_jmp_into_opcode(ctx, 0x700, insn);
808                 out = do_assemble_insn(ctx, insn, opcode);
809                 out->is_jump_insn = 1;
810                 break;
811         case OP_JNEXT:
812                 opcode = merge_external_jmp_into_opcode(ctx, 0x600, insn);
813                 out = do_assemble_insn(ctx, insn, opcode);
814                 out->is_jump_insn = 1;
815                 break;
816         case OP_CALL:
817                 do_assemble_insn(ctx, insn, 0x002);
818                 break;
819         case OP_RET:
820                 /* Get the previous instruction and check whether it
821                  * is a jump instruction. */
822                 list_for_each_entry_reverse(out, &ctx->output, list) {
823                         /* Search the last insn. */
824                         if (out->type == OUT_INSN) {
825                                 if (out->is_jump_insn) {
826                                         asm_error(ctx, "RET instruction directly after "
827                                                   "jump instruction. The hardware won't like this.");
828                                 }
829                                 break;
830                         }
831                 }
832                 do_assemble_insn(ctx, insn, 0x003);
833                 break;
834         case OP_TKIPH:
835         case OP_TKIPHS:
836         case OP_TKIPL:
837         case OP_TKIPLS:
838                 do_assemble_insn(ctx, insn, 0x1E0);
839                 break;
840         case OP_NAP:
841                 do_assemble_insn(ctx, insn, 0x001);
842                 break;
843         case RAW_CODE:
844                 do_assemble_insn(ctx, insn, insn->opcode);
845                 break;
846         default:
847                 asm_error(ctx, "Unknown op");
848         }
849 }
850
851 static void assemble_instructions(struct assembler_context *ctx)
852 {
853         struct statement *s;
854         struct instruction *insn;
855         struct code_output *out;
856
857         if (ctx->start_label) {
858                 /* Generate a jump instruction at offset 0 to
859                  * jump to the code start.
860                  */
861                 struct instruction sjmp;
862                 struct operlist ol;
863                 struct operand oper;
864
865                 oper.type = OPER_LABEL;
866                 oper.u.label = ctx->start_label;
867                 ol.oper[0] = &oper;
868                 sjmp.op = OP_JMP;
869                 sjmp.operands = &ol;
870
871                 assemble_instruction(ctx, &sjmp);
872                 out = list_entry(ctx->output.next, struct code_output, list);
873                 out->is_start_insn = 1;
874         }
875
876         for_each_statement(ctx, s) {
877                 switch (s->type) {
878                 case STMT_INSN:
879                         ctx->cur_stmt = s;
880                         insn = s->u.insn;
881                         assemble_instruction(ctx, insn);
882                         break;
883                 case STMT_LABEL:
884                         out = xmalloc(sizeof(*out));
885                         INIT_LIST_HEAD(&out->list);
886                         out->type = OUT_LABEL;
887                         out->labelname = s->u.label->name;
888
889                         list_add_tail(&out->list, &ctx->output);
890                         break;
891                 case STMT_ASMDIR:
892                         break;
893                 }
894         } for_each_statement_end(ctx, s);
895 }
896
897 /* Resolve a label reference to the address it points to. */
898 static int get_labeladdress(struct assembler_context *ctx,
899                             struct code_output *this_insn,
900                             struct label *labelref)
901 {
902         struct code_output *c;
903         bool found = 0;
904         int address = -1;
905
906         switch (labelref->direction) {
907         case LABELREF_ABSOLUTE:
908                 list_for_each_entry(c, &ctx->output, list) {
909                         if (c->type != OUT_LABEL)
910                                 continue;
911                         if (strcmp(c->labelname, labelref->name) != 0)
912                                 continue;
913                         if (found) {
914                                 asm_error(ctx, "Ambiguous label reference \"%s\"",
915                                           labelref->name);
916                         }
917                         found = 1;
918                         address = c->address;
919                 }
920                 break;
921         case LABELREF_RELATIVE_BACK:
922                 for (c = list_entry(this_insn->list.prev, typeof(*c), list);
923                      &c->list != &ctx->output;
924                      c = list_entry(c->list.prev, typeof(*c), list)) {
925                         if (c->type != OUT_LABEL)
926                                 continue;
927                         if (strcmp(c->labelname, labelref->name) == 0) {
928                                 /* Found */
929                                 address = c->address;
930                                 break;
931                         }
932                 }
933                 break;
934         case LABELREF_RELATIVE_FORWARD:
935                 for (c = list_entry(this_insn->list.next, typeof(*c), list);
936                      &c->list != &ctx->output;
937                      c = list_entry(c->list.next, typeof(*c), list)) {
938                         if (c->type != OUT_LABEL)
939                                 continue;
940                         if (strcmp(c->labelname, labelref->name) == 0) {
941                                 /* Found */
942                                 address = c->address;
943                                 break;
944                         }
945                 }
946                 break;
947         }
948
949         return address;
950 }
951
952 static void resolve_labels(struct assembler_context *ctx)
953 {
954         struct code_output *c;
955         int addr;
956         int i;
957         unsigned int current_address;
958
959         /* Calculate the absolute addresses for each instruction. */
960 recalculate_addresses:
961         current_address = 0;
962         list_for_each_entry(c, &ctx->output, list) {
963                 switch (c->type) {
964                 case OUT_INSN:
965                         c->address = current_address;
966                         current_address++;
967                         break;
968                 case OUT_LABEL:
969                         c->address = current_address;
970                         break;
971                 }
972         }
973
974         /* Resolve the symbolic label references. */
975         list_for_each_entry(c, &ctx->output, list) {
976                 switch (c->type) {
977                 case OUT_INSN:
978                         if (c->is_start_insn) {
979                                 /* If the first %start-jump jumps to 001, we can
980                                  * optimize it away, as it's unneeded.
981                                  */
982                                 i = 2;
983                                 if (c->operands[i].type != OUTOPER_LABELREF)
984                                         asm_error(ctx, "Internal error, %%start insn oper 2 not labelref");
985                                 if (c->operands[i].u.label->direction != LABELREF_ABSOLUTE)
986                                         asm_error(ctx, "%%start label reference not absolute");
987                                 addr = get_labeladdress(ctx, c, c->operands[i].u.label);
988                                 if (addr < 0)
989                                         goto does_not_exist;
990                                 if (addr == 1) {
991                                         list_del(&c->list); /* Kill it */
992                                         goto recalculate_addresses;
993                                 }
994                         }
995
996                         for (i = 0; i < ARRAY_SIZE(c->operands); i++) {
997                                 if (c->operands[i].type != OUTOPER_LABELREF)
998                                         continue;
999                                 addr = get_labeladdress(ctx, c, c->operands[i].u.label);
1000                                 if (addr < 0)
1001                                         goto does_not_exist;
1002                                 c->operands[i].u.operand = addr;
1003                                 if (i != 2) {
1004                                         /* Is not a jump target.
1005                                          * Make it be an immediate */
1006                                         if (ctx->arch == 5)
1007                                                 c->operands[i].u.operand |= 0xC00;
1008                                         else if (ctx->arch == 15)
1009                                                 c->operands[i].u.operand |= 0xC00 << 1;
1010                                         else
1011                                                 asm_error(ctx, "Internal error: label res imm");
1012                                 }
1013                         }
1014                         break;
1015                 case OUT_LABEL:
1016                         break;
1017                 }
1018         }
1019
1020         return;
1021 does_not_exist:
1022         asm_error(ctx, "Label \"%s\" does not exist",
1023                   c->operands[i].u.label->name);
1024 }
1025
1026 static void emit_code(struct assembler_context *ctx)
1027 {
1028         FILE *fd;
1029         char *fn;
1030         size_t fn_len;
1031         struct code_output *c;
1032         uint64_t code;
1033         unsigned char outbuf[8];
1034         unsigned int insn_count = 0;
1035         struct fw_header hdr;
1036
1037         fn_len = strlen(outfile_name) + 20;
1038         fn = xmalloc(fn_len);
1039         snprintf(fn, fn_len, "%s.ucode", outfile_name);
1040         fd = fopen(fn, "w+");
1041         if (!fd) {
1042                 fprintf(stderr, "Could not open microcode output file \"%s\"\n", fn);
1043                 free(fn);
1044                 exit(1);
1045         }
1046         if (IS_VERBOSE_DEBUG)
1047                 fprintf(stderr, "\nCode:\n");
1048
1049         list_for_each_entry(c, &ctx->output, list) {
1050                 switch (c->type) {
1051                 case OUT_INSN:
1052                         insn_count++;
1053                         break;
1054                 default:
1055                         break;
1056                 }
1057         }
1058
1059         memset(&hdr, 0, sizeof(hdr));
1060         hdr.type = FW_TYPE_UCODE;
1061         hdr.ver = FW_HDR_VER;
1062         hdr.size = cpu_to_be32(8 * insn_count);
1063         if (fwrite(&hdr, sizeof(hdr), 1, fd) != 1) {
1064                 fprintf(stderr, "Could not write microcode outfile\n");
1065                 exit(1);
1066         }
1067
1068         if (insn_count > NUM_INSN_LIMIT)
1069                 asm_warn(ctx, "Generating more than %d instructions. This "
1070                               "will overflow the device microcode memory.",
1071                          NUM_INSN_LIMIT);
1072
1073         list_for_each_entry(c, &ctx->output, list) {
1074                 switch (c->type) {
1075                 case OUT_INSN:
1076                         if (IS_VERBOSE_DEBUG) {
1077                                 fprintf(stderr, "%03X %03X,%03X,%03X\n",
1078                                         c->opcode,
1079                                         c->operands[0].u.operand,
1080                                         c->operands[1].u.operand,
1081                                         c->operands[2].u.operand);
1082                         }
1083                         code = 0;
1084
1085                         if (ctx->arch == 5) {
1086                                 /* Instruction binary format is: xxyyyzzz0000oooX
1087                                  *                        byte-0-^       byte-7-^
1088                                  * ooo is the opcode
1089                                  * Xxx is the first operand
1090                                  * yyy is the second operand
1091                                  * zzz is the third operand
1092                                  */
1093                                 code |= ((uint64_t)c->operands[2].u.operand);
1094                                 code |= ((uint64_t)c->operands[1].u.operand) << 12;
1095                                 code |= ((uint64_t)c->operands[0].u.operand) << 24;
1096                                 code |= ((uint64_t)c->opcode) << 36;
1097                                 code = ((code & (uint64_t)0xFFFFFFFF00000000ULL) >> 32) |
1098                                        ((code & (uint64_t)0x00000000FFFFFFFFULL) << 32);
1099                         } else if (ctx->arch == 15) {
1100                                 code |= ((uint64_t)c->operands[2].u.operand);
1101                                 code |= ((uint64_t)c->operands[1].u.operand) << 13;
1102                                 code |= ((uint64_t)c->operands[0].u.operand) << 26;
1103                                 code |= ((uint64_t)c->opcode) << 39;
1104                                 code = ((code & (uint64_t)0xFFFFFFFF00000000ULL) >> 32) |
1105                                        ((code & (uint64_t)0x00000000FFFFFFFFULL) << 32);
1106                         } else {
1107                                 asm_error(ctx, "No emit format for arch %u",
1108                                           ctx->arch);
1109                         }
1110                         outbuf[0] = (code & (uint64_t)0xFF00000000000000ULL) >> 56;
1111                         outbuf[1] = (code & (uint64_t)0x00FF000000000000ULL) >> 48;
1112                         outbuf[2] = (code & (uint64_t)0x0000FF0000000000ULL) >> 40;
1113                         outbuf[3] = (code & (uint64_t)0x000000FF00000000ULL) >> 32;
1114                         outbuf[4] = (code & (uint64_t)0x00000000FF000000ULL) >> 24;
1115                         outbuf[5] = (code & (uint64_t)0x0000000000FF0000ULL) >> 16;
1116                         outbuf[6] = (code & (uint64_t)0x000000000000FF00ULL) >> 8;
1117                         outbuf[7] = (code & (uint64_t)0x00000000000000FFULL) >> 0;
1118
1119                         if (fwrite(&outbuf, ARRAY_SIZE(outbuf), 1, fd) != 1) {
1120                                 fprintf(stderr, "Could not write microcode outfile\n");
1121                                 exit(1);
1122                         }
1123                         break;
1124                 case OUT_LABEL:
1125                         break;
1126                 }
1127         }
1128
1129         if (arg_print_sizes) {
1130                 printf("%s:  text = %u instructions (%u bytes)\n",
1131                        fn, insn_count, insn_count * sizeof(uint64_t));
1132         }
1133
1134         fclose(fd);
1135         free(fn);
1136 }
1137
1138 static void assemble(void)
1139 {
1140         struct assembler_context ctx;
1141
1142         memset(&ctx, 0, sizeof(ctx));
1143         INIT_LIST_HEAD(&ctx.output);
1144
1145         eval_directives(&ctx);
1146         assemble_instructions(&ctx);
1147         resolve_labels(&ctx);
1148         emit_code(&ctx);
1149 }
1150
1151 static void initialize(void)
1152 {
1153         INIT_LIST_HEAD(&infile.sl);
1154         INIT_LIST_HEAD(&infile.ivals);
1155 #ifdef YYDEBUG
1156         if (IS_INSANE_DEBUG)
1157                 yydebug = 1;
1158         else
1159                 yydebug = 0;
1160 #endif /* YYDEBUG */
1161 }
1162
1163 int main(int argc, char **argv)
1164 {
1165         int err, res = 1;
1166
1167         err = parse_args(argc, argv);
1168         if (err < 0)
1169                 goto out;
1170         if (err > 0) {
1171                 res = 0;
1172                 goto out;
1173         }
1174         err = open_input_file();
1175         if (err)
1176                 goto out;
1177         initialize();
1178         yyparse();
1179         assemble();
1180         assemble_initvals();
1181         close_input_file();
1182         res = 0;
1183 out:
1184         /* Lazyman simply leaks all allocated memory. */
1185         return res;
1186 }