Setting up repository
[linux-libre-firmware.git] / b43-tools / assembler / main.c
1 /*
2  *   Copyright (C) 2006-2010  Michael Buesch <m@bues.ch>
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         unsigned 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 void do_assemble_ret(struct assembler_context *ctx,
486                             struct instruction *insn,
487                             unsigned int opcode)
488 {
489         struct code_output *out;
490
491         /* Get the previous instruction and check whether it
492          * is a jump instruction. */
493         list_for_each_entry_reverse(out, &ctx->output, list) {
494                 /* Search the last insn. */
495                 if (out->type == OUT_INSN) {
496                         if (out->is_jump_insn) {
497                                 asm_warn(ctx, "RET instruction directly after "
498                                          "jump instruction. The hardware won't like this.");
499                         }
500                         break;
501                 }
502         }
503         do_assemble_insn(ctx, insn, opcode);
504 }
505
506 static unsigned int merge_ext_into_opcode(struct assembler_context *ctx,
507                                           unsigned int opbase,
508                                           struct instruction *insn)
509 {
510         struct operlist *ol;
511         unsigned int opcode;
512         unsigned int mask, shift;
513
514         ol = insn->operands;
515         opcode = opbase;
516         mask = ol->oper[0]->u.raw;
517         if (mask & ~0xF)
518                 asm_error(ctx, "opcode MASK extension too big (> 0xF)");
519         shift = ol->oper[1]->u.raw;
520         if (shift & ~0xF)
521                 asm_error(ctx, "opcode SHIFT extension too big (> 0xF)");
522         opcode |= (mask << 4);
523         opcode |= shift;
524         ol->oper[0] = ol->oper[2];
525         ol->oper[1] = ol->oper[3];
526         ol->oper[2] = ol->oper[4];
527
528         return opcode;
529 }
530
531 static unsigned int merge_external_jmp_into_opcode(struct assembler_context *ctx,
532                                                    unsigned int opbase,
533                                                    struct instruction *insn)
534 {
535         struct operand *fake;
536         struct registr *fake_reg;
537         struct operand *target;
538         struct operlist *ol;
539         unsigned int cond;
540         unsigned int opcode;
541
542         ol = insn->operands;
543         opcode = opbase;
544         cond = ol->oper[0]->u.imm->imm;
545         if (cond & ~0xFF)
546                 asm_error(ctx, "External jump condition value too big (> 0xFF)");
547         opcode |= cond;
548         target = ol->oper[1];
549         memset(ol->oper, 0, sizeof(ol->oper));
550
551         /* This instruction has two fake r0 operands
552          * at position 0 and 1. */
553         fake = xmalloc(sizeof(*fake));
554         fake_reg = xmalloc(sizeof(*fake_reg));
555         fake->type = OPER_REG;
556         fake->u.reg = fake_reg;
557         fake_reg->type = GPR;
558         fake_reg->nr = 0;
559
560         ol->oper[0] = fake;
561         ol->oper[1] = fake;
562         ol->oper[2] = target;
563
564         return opcode;
565 }
566
567 static void assemble_instruction(struct assembler_context *ctx,
568                                  struct instruction *insn);
569
570 static void emulate_mov_insn(struct assembler_context *ctx,
571                              struct instruction *insn)
572 {
573         struct instruction em_insn;
574         struct operlist em_ol;
575         struct operand em_op_shift;
576         struct operand em_op_mask;
577         struct operand em_op_x;
578         struct operand em_op_y;
579         struct immediate em_imm_x;
580         struct immediate em_imm_y;
581
582         struct operand *in, *out;
583         unsigned int tmp;
584
585         /* This is a pseudo-OP. We emulate it by OR or ORX */
586
587         in = insn->operands->oper[0];
588         out = insn->operands->oper[1];
589
590         em_insn.op = OP_OR;
591         em_ol.oper[0] = in;
592         em_imm_x.imm = 0;
593         em_op_x.type = OPER_IMM;
594         em_op_x.u.imm = &em_imm_x;
595         em_ol.oper[1] = &em_op_x;
596         em_ol.oper[2] = out;
597
598         if (in->type == OPER_IMM) {
599                 tmp = in->u.imm->imm;
600                 if (!is_possible_imm(tmp))
601                         asm_error(ctx, "MOV operand 0x%X > 16bit", tmp);
602                 if (!is_valid_imm(ctx, tmp)) {
603                         /* Immediate too big for plain OR */
604                         em_insn.op = OP_ORX;
605
606                         em_op_mask.type = OPER_RAW;
607                         em_op_mask.u.raw = 0x7;
608                         em_op_shift.type = OPER_RAW;
609                         em_op_shift.u.raw = 0x8;
610
611                         em_imm_x.imm = (tmp & 0xFF00) >> 8;
612                         em_op_x.type = OPER_IMM;
613                         em_op_x.u.imm = &em_imm_x;
614
615                         em_imm_y.imm = (tmp & 0x00FF);
616                         em_op_y.type = OPER_IMM;
617                         em_op_y.u.imm = &em_imm_y;
618
619                         em_ol.oper[0] = &em_op_mask;
620                         em_ol.oper[1] = &em_op_shift;
621                         em_ol.oper[2] = &em_op_x;
622                         em_ol.oper[3] = &em_op_y;
623                         em_ol.oper[4] = out;
624                 }
625         }
626
627         em_insn.operands = &em_ol;
628         assemble_instruction(ctx, &em_insn); /* recurse */
629 }
630
631 static void emulate_jmp_insn(struct assembler_context *ctx,
632                              struct instruction *insn)
633 {
634         struct instruction em_insn;
635         struct operlist em_ol;
636         struct immediate em_condition;
637         struct operand em_cond_op;
638
639         /* This is a pseudo-OP. We emulate it with
640          * JEXT 0x7F, target */
641
642         em_insn.op = OP_JEXT;
643         em_condition.imm = 0x7F; /* Ext cond: Always true */
644         em_cond_op.type = OPER_IMM;
645         em_cond_op.u.imm = &em_condition;
646         em_ol.oper[0] = &em_cond_op;
647         em_ol.oper[1] = insn->operands->oper[0]; /* Target */
648         em_insn.operands = &em_ol;
649
650         assemble_instruction(ctx, &em_insn); /* recurse */
651 }
652
653 static void emulate_jand_insn(struct assembler_context *ctx,
654                               struct instruction *insn,
655                               int inverted)
656 {
657         struct code_output *out;
658         struct instruction em_insn;
659         struct operlist em_ol;
660         struct operand em_op_shift;
661         struct operand em_op_mask;
662         struct operand em_op_y;
663         struct immediate em_imm;
664
665         struct operand *oper0, *oper1, *oper2;
666         struct operand *imm_oper = NULL;
667         unsigned int tmp;
668         int first_bit, last_bit;
669
670         oper0 = insn->operands->oper[0];
671         oper1 = insn->operands->oper[1];
672         oper2 = insn->operands->oper[2];
673
674         if (oper0->type == OPER_IMM)
675                 imm_oper = oper0;
676         if (oper1->type == OPER_IMM)
677                 imm_oper = oper1;
678         if (oper0->type == OPER_IMM && oper1->type == OPER_IMM)
679                 imm_oper = NULL;
680
681         if (imm_oper) {
682                 /* We have a single immediate operand.
683                  * Check if it's representable by a normal JAND insn.
684                  */
685                 tmp = imm_oper->u.imm->imm;
686                 if (!is_valid_imm(ctx, tmp)) {
687                         /* Nope, this must be emulated by JZX/JNZX */
688                         if (!is_contiguous_bitmask(tmp)) {
689                                 asm_error(ctx, "Long bitmask 0x%X is not contiguous",
690                                           tmp);
691                         }
692
693                         first_bit = ffs(tmp);
694                         last_bit = ffs(~(tmp >> (first_bit - 1))) - 1 + first_bit - 1;
695
696                         if (inverted)
697                                 em_insn.op = OP_JZX;
698                         else
699                                 em_insn.op = OP_JNZX;
700                         em_op_shift.type = OPER_RAW;
701                         em_op_shift.u.raw = first_bit - 1;
702                         em_op_mask.type = OPER_RAW;
703                         em_op_mask.u.raw = last_bit - first_bit;
704
705                         em_imm.imm = 0;
706                         em_op_y.type = OPER_IMM;
707                         em_op_y.u.imm = &em_imm;
708
709                         em_ol.oper[0] = &em_op_mask;
710                         em_ol.oper[1] = &em_op_shift;
711                         if (oper0->type != OPER_IMM)
712                                 em_ol.oper[2] = oper0;
713                         else
714                                 em_ol.oper[2] = oper1;
715                         em_ol.oper[3] = &em_op_y;
716                         em_ol.oper[4] = oper2;
717
718                         em_insn.operands = &em_ol;
719
720                         assemble_instruction(ctx, &em_insn); /* recurse */
721                         return;
722                 }
723         }
724
725         /* Do a normal JAND/JNAND instruction */
726         if (inverted)
727                 out = do_assemble_insn(ctx, insn, 0x040 | 0x1);
728         else
729                 out = do_assemble_insn(ctx, insn, 0x040);
730         out->is_jump_insn = 1;
731 }
732
733 static void assemble_instruction(struct assembler_context *ctx,
734                                  struct instruction *insn)
735 {
736         struct code_output *out;
737         unsigned int opcode;
738
739         switch (insn->op) {
740         case OP_MUL:
741                 do_assemble_insn(ctx, insn, 0x101);
742                 break;
743         case OP_ADD:
744                 do_assemble_insn(ctx, insn, 0x1C0);
745                 break;
746         case OP_ADDSC:
747                 do_assemble_insn(ctx, insn, 0x1C2);
748                 break;
749         case OP_ADDC:
750                 do_assemble_insn(ctx, insn, 0x1C1);
751                 break;
752         case OP_ADDSCC:
753                 do_assemble_insn(ctx, insn, 0x1C3);
754                 break;
755         case OP_SUB:
756                 do_assemble_insn(ctx, insn, 0x1D0);
757                 break;
758         case OP_SUBSC:
759                 do_assemble_insn(ctx, insn, 0x1D2);
760                 break;
761         case OP_SUBC:
762                 do_assemble_insn(ctx, insn, 0x1D1);
763                 break;
764         case OP_SUBSCC:
765                 do_assemble_insn(ctx, insn, 0x1D3);
766                 break;
767         case OP_SRA:
768                 do_assemble_insn(ctx, insn, 0x130);
769                 break;
770         case OP_OR:
771                 do_assemble_insn(ctx, insn, 0x160);
772                 break;
773         case OP_AND:
774                 do_assemble_insn(ctx, insn, 0x140);
775                 break;
776         case OP_XOR:
777                 do_assemble_insn(ctx, insn, 0x170);
778                 break;
779         case OP_SR:
780                 do_assemble_insn(ctx, insn, 0x120);
781                 break;
782         case OP_SRX:
783                 opcode = merge_ext_into_opcode(ctx, 0x200, insn);
784                 do_assemble_insn(ctx, insn, opcode);
785                 break;
786         case OP_SL:
787                 do_assemble_insn(ctx, insn, 0x110);
788                 break;
789         case OP_RL:
790                 do_assemble_insn(ctx, insn, 0x1A0);
791                 break;
792         case OP_RR:
793                 do_assemble_insn(ctx, insn, 0x1B0);
794                 break;
795         case OP_NAND:
796                 do_assemble_insn(ctx, insn, 0x150);
797                 break;
798         case OP_ORX:
799                 opcode = merge_ext_into_opcode(ctx, 0x300, insn);
800                 do_assemble_insn(ctx, insn, opcode);
801                 break;
802         case OP_MOV:
803                 emulate_mov_insn(ctx, insn);
804                 return;
805         case OP_JMP:
806                 emulate_jmp_insn(ctx, insn);
807                 return;
808         case OP_JAND:
809                 emulate_jand_insn(ctx, insn, 0);
810                 return;
811         case OP_JNAND:
812                 emulate_jand_insn(ctx, insn, 1);
813                 return;
814         case OP_JS:
815                 out = do_assemble_insn(ctx, insn, 0x050);
816                 out->is_jump_insn = 1;
817                 break;
818         case OP_JNS:
819                 out = do_assemble_insn(ctx, insn, 0x050 | 0x1);
820                 out->is_jump_insn = 1;
821                 break;
822         case OP_JE:
823                 out = do_assemble_insn(ctx, insn, 0x0D0);
824                 out->is_jump_insn = 1;
825                 break;
826         case OP_JNE:
827                 out = do_assemble_insn(ctx, insn, 0x0D0 | 0x1);
828                 out->is_jump_insn = 1;
829                 break;
830         case OP_JLS:
831                 out = do_assemble_insn(ctx, insn, 0x0D2);
832                 out->is_jump_insn = 1;
833                 break;
834         case OP_JGES:
835                 out = do_assemble_insn(ctx, insn, 0x0D2 | 0x1);
836                 out->is_jump_insn = 1;
837                 break;
838         case OP_JGS:
839                 out = do_assemble_insn(ctx, insn, 0x0D4);
840                 out->is_jump_insn = 1;
841                 break;
842         case OP_JLES:
843                 out = do_assemble_insn(ctx, insn, 0x0D4 | 0x1);
844                 out->is_jump_insn = 1;
845                 break;
846         case OP_JL:
847                 out = do_assemble_insn(ctx, insn, 0x0DA);
848                 out->is_jump_insn = 1;
849                 break;
850         case OP_JGE:
851                 out = do_assemble_insn(ctx, insn, 0x0DA | 0x1);
852                 out->is_jump_insn = 1;
853                 break;
854         case OP_JG:
855                 out = do_assemble_insn(ctx, insn, 0x0DC);
856                 break;
857         case OP_JLE:
858                 out = do_assemble_insn(ctx, insn, 0x0DC | 0x1);
859                 out->is_jump_insn = 1;
860                 break;
861         case OP_JDN:
862                 out = do_assemble_insn(ctx, insn, 0x0D6);
863                 out->is_jump_insn = 1;
864                 break;
865         case OP_JDPZ:
866                 out = do_assemble_insn(ctx, insn, 0x0D6 | 0x1);
867                 out->is_jump_insn = 1;
868                 break;
869         case OP_JDP:
870                 out = do_assemble_insn(ctx, insn, 0x0D8);
871                 out->is_jump_insn = 1;
872                 break;
873         case OP_JDNZ:
874                 out = do_assemble_insn(ctx, insn, 0x0D8 | 0x1);
875                 out->is_jump_insn = 1;
876                 break;
877         case OP_JZX:
878                 opcode = merge_ext_into_opcode(ctx, 0x400, insn);
879                 out = do_assemble_insn(ctx, insn, opcode);
880                 out->is_jump_insn = 1;
881                 break;
882         case OP_JNZX:
883                 opcode = merge_ext_into_opcode(ctx, 0x500, insn);
884                 out = do_assemble_insn(ctx, insn, opcode);
885                 out->is_jump_insn = 1;
886                 break;
887         case OP_JEXT:
888                 opcode = merge_external_jmp_into_opcode(ctx, 0x700, insn);
889                 out = do_assemble_insn(ctx, insn, opcode);
890                 out->is_jump_insn = 1;
891                 break;
892         case OP_JNEXT:
893                 opcode = merge_external_jmp_into_opcode(ctx, 0x600, insn);
894                 out = do_assemble_insn(ctx, insn, opcode);
895                 out->is_jump_insn = 1;
896                 break;
897         case OP_CALL:
898                 if (ctx->arch != 5)
899                         asm_error(ctx, "'call' instruction is only supported on arch 5");
900                 do_assemble_insn(ctx, insn, 0x002);
901                 break;
902         case OP_CALLS:
903                 if (ctx->arch != 15)
904                         asm_error(ctx, "'calls' instruction is only supported on arch 15");
905                 do_assemble_insn(ctx, insn, 0x004);
906                 break;
907         case OP_RET:
908                 if (ctx->arch != 5)
909                         asm_error(ctx, "'ret' instruction is only supported on arch 5");
910                 do_assemble_ret(ctx, insn, 0x003);
911                 break;
912         case OP_RETS:
913                 if (ctx->arch != 15)
914                         asm_error(ctx, "'rets' instruction is only supported on arch 15");
915                 do_assemble_insn(ctx, insn, 0x005);
916                 break;
917         case OP_TKIPH:
918         case OP_TKIPHS:
919         case OP_TKIPL:
920         case OP_TKIPLS:
921                 do_assemble_insn(ctx, insn, 0x1E0);
922                 break;
923         case OP_NAP:
924                 do_assemble_insn(ctx, insn, 0x001);
925                 break;
926         case RAW_CODE:
927                 do_assemble_insn(ctx, insn, insn->opcode);
928                 break;
929         default:
930                 asm_error(ctx, "Unknown op");
931         }
932 }
933
934 static void assemble_instructions(struct assembler_context *ctx)
935 {
936         struct statement *s;
937         struct instruction *insn;
938         struct code_output *out;
939
940         if (ctx->start_label) {
941                 /* Generate a jump instruction at offset 0 to
942                  * jump to the code start.
943                  */
944                 struct instruction sjmp;
945                 struct operlist ol;
946                 struct operand oper;
947
948                 oper.type = OPER_LABEL;
949                 oper.u.label = ctx->start_label;
950                 ol.oper[0] = &oper;
951                 sjmp.op = OP_JMP;
952                 sjmp.operands = &ol;
953
954                 assemble_instruction(ctx, &sjmp);
955                 out = list_entry(ctx->output.next, struct code_output, list);
956                 out->is_start_insn = 1;
957         }
958
959         for_each_statement(ctx, s) {
960                 switch (s->type) {
961                 case STMT_INSN:
962                         ctx->cur_stmt = s;
963                         insn = s->u.insn;
964                         assemble_instruction(ctx, insn);
965                         break;
966                 case STMT_LABEL:
967                         out = xmalloc(sizeof(*out));
968                         INIT_LIST_HEAD(&out->list);
969                         out->type = OUT_LABEL;
970                         out->labelname = s->u.label->name;
971
972                         list_add_tail(&out->list, &ctx->output);
973                         break;
974                 case STMT_ASMDIR:
975                         break;
976                 }
977         } for_each_statement_end(ctx, s);
978 }
979
980 /* Resolve a label reference to the address it points to. */
981 static int get_labeladdress(struct assembler_context *ctx,
982                             struct code_output *this_insn,
983                             struct label *labelref)
984 {
985         struct code_output *c;
986         bool found = 0;
987         int address = -1;
988
989         switch (labelref->direction) {
990         case LABELREF_ABSOLUTE:
991                 list_for_each_entry(c, &ctx->output, list) {
992                         if (c->type != OUT_LABEL)
993                                 continue;
994                         if (strcmp(c->labelname, labelref->name) != 0)
995                                 continue;
996                         if (found) {
997                                 asm_error(ctx, "Ambiguous label reference \"%s\"",
998                                           labelref->name);
999                         }
1000                         found = 1;
1001                         address = c->address;
1002                 }
1003                 break;
1004         case LABELREF_RELATIVE_BACK:
1005                 for (c = list_entry(this_insn->list.prev, typeof(*c), list);
1006                      &c->list != &ctx->output;
1007                      c = list_entry(c->list.prev, typeof(*c), list)) {
1008                         if (c->type != OUT_LABEL)
1009                                 continue;
1010                         if (strcmp(c->labelname, labelref->name) == 0) {
1011                                 /* Found */
1012                                 address = c->address;
1013                                 break;
1014                         }
1015                 }
1016                 break;
1017         case LABELREF_RELATIVE_FORWARD:
1018                 for (c = list_entry(this_insn->list.next, typeof(*c), list);
1019                      &c->list != &ctx->output;
1020                      c = list_entry(c->list.next, typeof(*c), list)) {
1021                         if (c->type != OUT_LABEL)
1022                                 continue;
1023                         if (strcmp(c->labelname, labelref->name) == 0) {
1024                                 /* Found */
1025                                 address = c->address;
1026                                 break;
1027                         }
1028                 }
1029                 break;
1030         }
1031
1032         return address;
1033 }
1034
1035 static void resolve_labels(struct assembler_context *ctx)
1036 {
1037         struct code_output *c;
1038         int addr;
1039         unsigned int i;
1040         unsigned int current_address;
1041
1042         /* Calculate the absolute addresses for each instruction. */
1043 recalculate_addresses:
1044         current_address = 0;
1045         list_for_each_entry(c, &ctx->output, list) {
1046                 switch (c->type) {
1047                 case OUT_INSN:
1048                         c->address = current_address;
1049                         current_address++;
1050                         break;
1051                 case OUT_LABEL:
1052                         c->address = current_address;
1053                         break;
1054                 }
1055         }
1056
1057         /* Resolve the symbolic label references. */
1058         list_for_each_entry(c, &ctx->output, list) {
1059                 switch (c->type) {
1060                 case OUT_INSN:
1061                         if (c->is_start_insn) {
1062                                 /* If the first %start-jump jumps to 001, we can
1063                                  * optimize it away, as it's unneeded.
1064                                  */
1065                                 i = 2;
1066                                 if (c->operands[i].type != OUTOPER_LABELREF)
1067                                         asm_error(ctx, "Internal error, %%start insn oper 2 not labelref");
1068                                 if (c->operands[i].u.label->direction != LABELREF_ABSOLUTE)
1069                                         asm_error(ctx, "%%start label reference not absolute");
1070                                 addr = get_labeladdress(ctx, c, c->operands[i].u.label);
1071                                 if (addr < 0)
1072                                         goto does_not_exist;
1073                                 if (addr == 1) {
1074                                         list_del(&c->list); /* Kill it */
1075                                         goto recalculate_addresses;
1076                                 }
1077                         }
1078
1079                         for (i = 0; i < ARRAY_SIZE(c->operands); i++) {
1080                                 if (c->operands[i].type != OUTOPER_LABELREF)
1081                                         continue;
1082                                 addr = get_labeladdress(ctx, c, c->operands[i].u.label);
1083                                 if (addr < 0)
1084                                         goto does_not_exist;
1085                                 c->operands[i].u.operand = addr;
1086                                 if (i != 2) {
1087                                         /* Is not a jump target.
1088                                          * Make it be an immediate */
1089                                         if (ctx->arch == 5)
1090                                                 c->operands[i].u.operand |= 0xC00;
1091                                         else if (ctx->arch == 15)
1092                                                 c->operands[i].u.operand |= 0xC00 << 1;
1093                                         else
1094                                                 asm_error(ctx, "Internal error: label res imm");
1095                                 }
1096                         }
1097                         break;
1098                 case OUT_LABEL:
1099                         break;
1100                 }
1101         }
1102
1103         return;
1104 does_not_exist:
1105         asm_error(ctx, "Label \"%s\" does not exist",
1106                   c->operands[i].u.label->name);
1107 }
1108
1109 static void emit_code(struct assembler_context *ctx)
1110 {
1111         FILE *fd;
1112         const char *fn;
1113         struct code_output *c;
1114         uint64_t code;
1115         unsigned char outbuf[8];
1116         unsigned int insn_count = 0, insn_count_limit;
1117         struct fw_header hdr;
1118
1119         fn = outfile_name;
1120         fd = fopen(fn, "w+");
1121         if (!fd) {
1122                 fprintf(stderr, "Could not open microcode output file \"%s\"\n", fn);
1123                 exit(1);
1124         }
1125         if (IS_VERBOSE_DEBUG)
1126                 printf("\nCode:\n");
1127
1128         list_for_each_entry(c, &ctx->output, list) {
1129                 switch (c->type) {
1130                 case OUT_INSN:
1131                         insn_count++;
1132                         break;
1133                 default:
1134                         break;
1135                 }
1136         }
1137
1138         switch (cmdargs.outformat) {
1139         case FMT_RAW_LE32:
1140         case FMT_RAW_BE32:
1141                 /* Nothing */
1142                 break;
1143         case FMT_B43:
1144                 memset(&hdr, 0, sizeof(hdr));
1145                 hdr.type = FW_TYPE_UCODE;
1146                 hdr.ver = FW_HDR_VER;
1147                 hdr.size = cpu_to_be32(8 * insn_count);
1148                 if (fwrite(&hdr, sizeof(hdr), 1, fd) != 1) {
1149                         fprintf(stderr, "Could not write microcode outfile\n");
1150                         exit(1);
1151                 }
1152                 break;
1153         }
1154
1155         switch (ctx->arch) {
1156         case 5:
1157                 insn_count_limit = NUM_INSN_LIMIT_R5;
1158                 break;
1159         case 15:
1160                 insn_count_limit = ~0; //FIXME limit currently unknown.
1161                 break;
1162         default:
1163                 asm_error(ctx, "Internal error: emit_code unknown arch\n");
1164         }
1165         if (insn_count > insn_count_limit)
1166                 asm_warn(ctx, "Generating more than %u instructions. This "
1167                               "will overflow the device microcode memory.",
1168                          insn_count_limit);
1169
1170         list_for_each_entry(c, &ctx->output, list) {
1171                 switch (c->type) {
1172                 case OUT_INSN:
1173                         if (IS_VERBOSE_DEBUG) {
1174                                 printf("%03X %04X,%04X,%04X\n",
1175                                         c->opcode,
1176                                         c->operands[0].u.operand,
1177                                         c->operands[1].u.operand,
1178                                         c->operands[2].u.operand);
1179                         }
1180
1181                         switch (ctx->arch) {
1182                         case 5:
1183                                 code = 0;
1184                                 code |= ((uint64_t)c->operands[2].u.operand);
1185                                 code |= ((uint64_t)c->operands[1].u.operand) << 12;
1186                                 code |= ((uint64_t)c->operands[0].u.operand) << 24;
1187                                 code |= ((uint64_t)c->opcode) << 36;
1188                                 break;
1189                         case 15:
1190                                 code = 0;
1191                                 code |= ((uint64_t)c->operands[2].u.operand);
1192                                 code |= ((uint64_t)c->operands[1].u.operand) << 13;
1193                                 code |= ((uint64_t)c->operands[0].u.operand) << 26;
1194                                 code |= ((uint64_t)c->opcode) << 39;
1195                                 break;
1196                         default:
1197                                 asm_error(ctx, "No emit format for arch %u",
1198                                           ctx->arch);
1199                         }
1200
1201                         switch (cmdargs.outformat) {
1202                         case FMT_B43:
1203                         case FMT_RAW_BE32:
1204                                 code = ((code & (uint64_t)0xFFFFFFFF00000000ULL) >> 32) |
1205                                        ((code & (uint64_t)0x00000000FFFFFFFFULL) << 32);
1206                                 outbuf[0] = (code & (uint64_t)0xFF00000000000000ULL) >> 56;
1207                                 outbuf[1] = (code & (uint64_t)0x00FF000000000000ULL) >> 48;
1208                                 outbuf[2] = (code & (uint64_t)0x0000FF0000000000ULL) >> 40;
1209                                 outbuf[3] = (code & (uint64_t)0x000000FF00000000ULL) >> 32;
1210                                 outbuf[4] = (code & (uint64_t)0x00000000FF000000ULL) >> 24;
1211                                 outbuf[5] = (code & (uint64_t)0x0000000000FF0000ULL) >> 16;
1212                                 outbuf[6] = (code & (uint64_t)0x000000000000FF00ULL) >> 8;
1213                                 outbuf[7] = (code & (uint64_t)0x00000000000000FFULL) >> 0;
1214                                 break;
1215                         case FMT_RAW_LE32:
1216                                 outbuf[7] = (code & (uint64_t)0xFF00000000000000ULL) >> 56;
1217                                 outbuf[6] = (code & (uint64_t)0x00FF000000000000ULL) >> 48;
1218                                 outbuf[5] = (code & (uint64_t)0x0000FF0000000000ULL) >> 40;
1219                                 outbuf[4] = (code & (uint64_t)0x000000FF00000000ULL) >> 32;
1220                                 outbuf[3] = (code & (uint64_t)0x00000000FF000000ULL) >> 24;
1221                                 outbuf[2] = (code & (uint64_t)0x0000000000FF0000ULL) >> 16;
1222                                 outbuf[1] = (code & (uint64_t)0x000000000000FF00ULL) >> 8;
1223                                 outbuf[0] = (code & (uint64_t)0x00000000000000FFULL) >> 0;
1224                                 break;
1225                         }
1226
1227                         if (fwrite(&outbuf, ARRAY_SIZE(outbuf), 1, fd) != 1) {
1228                                 fprintf(stderr, "Could not write microcode outfile\n");
1229                                 exit(1);
1230                         }
1231                         break;
1232                 case OUT_LABEL:
1233                         break;
1234                 }
1235         }
1236
1237         if (cmdargs.print_sizes) {
1238                 printf("%s:  text = %u instructions (%u bytes)\n",
1239                        fn, insn_count,
1240                        (unsigned int)(insn_count * sizeof(uint64_t)));
1241         }
1242
1243         fclose(fd);
1244 }
1245
1246 static void assemble(void)
1247 {
1248         struct assembler_context ctx;
1249
1250         memset(&ctx, 0, sizeof(ctx));
1251         INIT_LIST_HEAD(&ctx.output);
1252
1253         eval_directives(&ctx);
1254         assemble_instructions(&ctx);
1255         resolve_labels(&ctx);
1256         emit_code(&ctx);
1257 }
1258
1259 static void initialize(void)
1260 {
1261         INIT_LIST_HEAD(&infile.sl);
1262         INIT_LIST_HEAD(&infile.ivals);
1263 #if YYDEBUG
1264         if (IS_INSANE_DEBUG)
1265                 yydebug = 1;
1266         else
1267                 yydebug = 0;
1268 #endif /* YYDEBUG */
1269 }
1270
1271 int main(int argc, char **argv)
1272 {
1273         int err, res = 1;
1274
1275         err = parse_args(argc, argv);
1276         if (err < 0)
1277                 goto out;
1278         if (err > 0) {
1279                 res = 0;
1280                 goto out;
1281         }
1282         err = open_input_file();
1283         if (err)
1284                 goto out;
1285         initialize();
1286         yyparse();
1287         assemble();
1288         assemble_initvals();
1289         close_input_file();
1290         res = 0;
1291 out:
1292         /* Lazyman simply leaks all allocated memory. */
1293         return res;
1294 }