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