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