assembler: Put commandline args into structure
[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 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_ADD:
741                 do_assemble_insn(ctx, insn, 0x1C0);
742                 break;
743         case OP_ADDSC:
744                 do_assemble_insn(ctx, insn, 0x1C2);
745                 break;
746         case OP_ADDC:
747                 do_assemble_insn(ctx, insn, 0x1C1);
748                 break;
749         case OP_ADDSCC:
750                 do_assemble_insn(ctx, insn, 0x1C3);
751                 break;
752         case OP_SUB:
753                 do_assemble_insn(ctx, insn, 0x1D0);
754                 break;
755         case OP_SUBSC:
756                 do_assemble_insn(ctx, insn, 0x1D2);
757                 break;
758         case OP_SUBC:
759                 do_assemble_insn(ctx, insn, 0x1D1);
760                 break;
761         case OP_SUBSCC:
762                 do_assemble_insn(ctx, insn, 0x1D3);
763                 break;
764         case OP_SRA:
765                 do_assemble_insn(ctx, insn, 0x130);
766                 break;
767         case OP_OR:
768                 do_assemble_insn(ctx, insn, 0x160);
769                 break;
770         case OP_AND:
771                 do_assemble_insn(ctx, insn, 0x140);
772                 break;
773         case OP_XOR:
774                 do_assemble_insn(ctx, insn, 0x170);
775                 break;
776         case OP_SR:
777                 do_assemble_insn(ctx, insn, 0x120);
778                 break;
779         case OP_SRX:
780                 opcode = merge_ext_into_opcode(ctx, 0x200, insn);
781                 do_assemble_insn(ctx, insn, opcode);
782                 break;
783         case OP_SL:
784                 do_assemble_insn(ctx, insn, 0x110);
785                 break;
786         case OP_RL:
787                 do_assemble_insn(ctx, insn, 0x1A0);
788                 break;
789         case OP_RR:
790                 do_assemble_insn(ctx, insn, 0x1B0);
791                 break;
792         case OP_NAND:
793                 do_assemble_insn(ctx, insn, 0x150);
794                 break;
795         case OP_ORX:
796                 opcode = merge_ext_into_opcode(ctx, 0x300, insn);
797                 do_assemble_insn(ctx, insn, opcode);
798                 break;
799         case OP_MOV:
800                 emulate_mov_insn(ctx, insn);
801                 return;
802         case OP_JMP:
803                 emulate_jmp_insn(ctx, insn);
804                 return;
805         case OP_JAND:
806                 emulate_jand_insn(ctx, insn, 0);
807                 return;
808         case OP_JNAND:
809                 emulate_jand_insn(ctx, insn, 1);
810                 return;
811         case OP_JS:
812                 out = do_assemble_insn(ctx, insn, 0x050);
813                 out->is_jump_insn = 1;
814                 break;
815         case OP_JNS:
816                 out = do_assemble_insn(ctx, insn, 0x050 | 0x1);
817                 out->is_jump_insn = 1;
818                 break;
819         case OP_JE:
820                 out = do_assemble_insn(ctx, insn, 0x0D0);
821                 out->is_jump_insn = 1;
822                 break;
823         case OP_JNE:
824                 out = do_assemble_insn(ctx, insn, 0x0D0 | 0x1);
825                 out->is_jump_insn = 1;
826                 break;
827         case OP_JLS:
828                 out = do_assemble_insn(ctx, insn, 0x0D2);
829                 out->is_jump_insn = 1;
830                 break;
831         case OP_JGES:
832                 out = do_assemble_insn(ctx, insn, 0x0D2 | 0x1);
833                 out->is_jump_insn = 1;
834                 break;
835         case OP_JGS:
836                 out = do_assemble_insn(ctx, insn, 0x0D4);
837                 out->is_jump_insn = 1;
838                 break;
839         case OP_JLES:
840                 out = do_assemble_insn(ctx, insn, 0x0D4 | 0x1);
841                 out->is_jump_insn = 1;
842                 break;
843         case OP_JL:
844                 out = do_assemble_insn(ctx, insn, 0x0DA);
845                 out->is_jump_insn = 1;
846                 break;
847         case OP_JGE:
848                 out = do_assemble_insn(ctx, insn, 0x0DA | 0x1);
849                 out->is_jump_insn = 1;
850                 break;
851         case OP_JG:
852                 out = do_assemble_insn(ctx, insn, 0x0DC);
853                 break;
854         case OP_JLE:
855                 out = do_assemble_insn(ctx, insn, 0x0DC | 0x1);
856                 out->is_jump_insn = 1;
857                 break;
858         case OP_JZX:
859                 opcode = merge_ext_into_opcode(ctx, 0x400, insn);
860                 out = do_assemble_insn(ctx, insn, opcode);
861                 out->is_jump_insn = 1;
862                 break;
863         case OP_JNZX:
864                 opcode = merge_ext_into_opcode(ctx, 0x500, insn);
865                 out = do_assemble_insn(ctx, insn, opcode);
866                 out->is_jump_insn = 1;
867                 break;
868         case OP_JEXT:
869                 opcode = merge_external_jmp_into_opcode(ctx, 0x700, insn);
870                 out = do_assemble_insn(ctx, insn, opcode);
871                 out->is_jump_insn = 1;
872                 break;
873         case OP_JNEXT:
874                 opcode = merge_external_jmp_into_opcode(ctx, 0x600, insn);
875                 out = do_assemble_insn(ctx, insn, opcode);
876                 out->is_jump_insn = 1;
877                 break;
878         case OP_CALL:
879                 if (ctx->arch != 5)
880                         asm_error(ctx, "'call' instruction is only supported on arch 5");
881                 do_assemble_insn(ctx, insn, 0x002);
882                 break;
883         case OP_CALLS:
884                 if (ctx->arch != 15)
885                         asm_error(ctx, "'calls' instruction is only supported on arch 15");
886                 do_assemble_insn(ctx, insn, 0x004);
887                 break;
888         case OP_RET:
889                 if (ctx->arch != 5)
890                         asm_error(ctx, "'ret' instruction is only supported on arch 5");
891                 do_assemble_ret(ctx, insn, 0x003);
892                 break;
893         case OP_RETS:
894                 if (ctx->arch != 15)
895                         asm_error(ctx, "'rets' instruction is only supported on arch 15");
896                 do_assemble_insn(ctx, insn, 0x005);
897                 break;
898         case OP_TKIPH:
899         case OP_TKIPHS:
900         case OP_TKIPL:
901         case OP_TKIPLS:
902                 do_assemble_insn(ctx, insn, 0x1E0);
903                 break;
904         case OP_NAP:
905                 do_assemble_insn(ctx, insn, 0x001);
906                 break;
907         case RAW_CODE:
908                 do_assemble_insn(ctx, insn, insn->opcode);
909                 break;
910         default:
911                 asm_error(ctx, "Unknown op");
912         }
913 }
914
915 static void assemble_instructions(struct assembler_context *ctx)
916 {
917         struct statement *s;
918         struct instruction *insn;
919         struct code_output *out;
920
921         if (ctx->start_label) {
922                 /* Generate a jump instruction at offset 0 to
923                  * jump to the code start.
924                  */
925                 struct instruction sjmp;
926                 struct operlist ol;
927                 struct operand oper;
928
929                 oper.type = OPER_LABEL;
930                 oper.u.label = ctx->start_label;
931                 ol.oper[0] = &oper;
932                 sjmp.op = OP_JMP;
933                 sjmp.operands = &ol;
934
935                 assemble_instruction(ctx, &sjmp);
936                 out = list_entry(ctx->output.next, struct code_output, list);
937                 out->is_start_insn = 1;
938         }
939
940         for_each_statement(ctx, s) {
941                 switch (s->type) {
942                 case STMT_INSN:
943                         ctx->cur_stmt = s;
944                         insn = s->u.insn;
945                         assemble_instruction(ctx, insn);
946                         break;
947                 case STMT_LABEL:
948                         out = xmalloc(sizeof(*out));
949                         INIT_LIST_HEAD(&out->list);
950                         out->type = OUT_LABEL;
951                         out->labelname = s->u.label->name;
952
953                         list_add_tail(&out->list, &ctx->output);
954                         break;
955                 case STMT_ASMDIR:
956                         break;
957                 }
958         } for_each_statement_end(ctx, s);
959 }
960
961 /* Resolve a label reference to the address it points to. */
962 static int get_labeladdress(struct assembler_context *ctx,
963                             struct code_output *this_insn,
964                             struct label *labelref)
965 {
966         struct code_output *c;
967         bool found = 0;
968         int address = -1;
969
970         switch (labelref->direction) {
971         case LABELREF_ABSOLUTE:
972                 list_for_each_entry(c, &ctx->output, list) {
973                         if (c->type != OUT_LABEL)
974                                 continue;
975                         if (strcmp(c->labelname, labelref->name) != 0)
976                                 continue;
977                         if (found) {
978                                 asm_error(ctx, "Ambiguous label reference \"%s\"",
979                                           labelref->name);
980                         }
981                         found = 1;
982                         address = c->address;
983                 }
984                 break;
985         case LABELREF_RELATIVE_BACK:
986                 for (c = list_entry(this_insn->list.prev, typeof(*c), list);
987                      &c->list != &ctx->output;
988                      c = list_entry(c->list.prev, typeof(*c), list)) {
989                         if (c->type != OUT_LABEL)
990                                 continue;
991                         if (strcmp(c->labelname, labelref->name) == 0) {
992                                 /* Found */
993                                 address = c->address;
994                                 break;
995                         }
996                 }
997                 break;
998         case LABELREF_RELATIVE_FORWARD:
999                 for (c = list_entry(this_insn->list.next, typeof(*c), list);
1000                      &c->list != &ctx->output;
1001                      c = list_entry(c->list.next, typeof(*c), list)) {
1002                         if (c->type != OUT_LABEL)
1003                                 continue;
1004                         if (strcmp(c->labelname, labelref->name) == 0) {
1005                                 /* Found */
1006                                 address = c->address;
1007                                 break;
1008                         }
1009                 }
1010                 break;
1011         }
1012
1013         return address;
1014 }
1015
1016 static void resolve_labels(struct assembler_context *ctx)
1017 {
1018         struct code_output *c;
1019         int addr;
1020         int i;
1021         unsigned int current_address;
1022
1023         /* Calculate the absolute addresses for each instruction. */
1024 recalculate_addresses:
1025         current_address = 0;
1026         list_for_each_entry(c, &ctx->output, list) {
1027                 switch (c->type) {
1028                 case OUT_INSN:
1029                         c->address = current_address;
1030                         current_address++;
1031                         break;
1032                 case OUT_LABEL:
1033                         c->address = current_address;
1034                         break;
1035                 }
1036         }
1037
1038         /* Resolve the symbolic label references. */
1039         list_for_each_entry(c, &ctx->output, list) {
1040                 switch (c->type) {
1041                 case OUT_INSN:
1042                         if (c->is_start_insn) {
1043                                 /* If the first %start-jump jumps to 001, we can
1044                                  * optimize it away, as it's unneeded.
1045                                  */
1046                                 i = 2;
1047                                 if (c->operands[i].type != OUTOPER_LABELREF)
1048                                         asm_error(ctx, "Internal error, %%start insn oper 2 not labelref");
1049                                 if (c->operands[i].u.label->direction != LABELREF_ABSOLUTE)
1050                                         asm_error(ctx, "%%start label reference not absolute");
1051                                 addr = get_labeladdress(ctx, c, c->operands[i].u.label);
1052                                 if (addr < 0)
1053                                         goto does_not_exist;
1054                                 if (addr == 1) {
1055                                         list_del(&c->list); /* Kill it */
1056                                         goto recalculate_addresses;
1057                                 }
1058                         }
1059
1060                         for (i = 0; i < ARRAY_SIZE(c->operands); i++) {
1061                                 if (c->operands[i].type != OUTOPER_LABELREF)
1062                                         continue;
1063                                 addr = get_labeladdress(ctx, c, c->operands[i].u.label);
1064                                 if (addr < 0)
1065                                         goto does_not_exist;
1066                                 c->operands[i].u.operand = addr;
1067                                 if (i != 2) {
1068                                         /* Is not a jump target.
1069                                          * Make it be an immediate */
1070                                         if (ctx->arch == 5)
1071                                                 c->operands[i].u.operand |= 0xC00;
1072                                         else if (ctx->arch == 15)
1073                                                 c->operands[i].u.operand |= 0xC00 << 1;
1074                                         else
1075                                                 asm_error(ctx, "Internal error: label res imm");
1076                                 }
1077                         }
1078                         break;
1079                 case OUT_LABEL:
1080                         break;
1081                 }
1082         }
1083
1084         return;
1085 does_not_exist:
1086         asm_error(ctx, "Label \"%s\" does not exist",
1087                   c->operands[i].u.label->name);
1088 }
1089
1090 static void emit_code(struct assembler_context *ctx)
1091 {
1092         FILE *fd;
1093         const char *fn;
1094         struct code_output *c;
1095         uint64_t code;
1096         unsigned char outbuf[8];
1097         unsigned int insn_count = 0, insn_count_limit;
1098         struct fw_header hdr;
1099
1100         fn = outfile_name;
1101         fd = fopen(fn, "w+");
1102         if (!fd) {
1103                 fprintf(stderr, "Could not open microcode output file \"%s\"\n", fn);
1104                 exit(1);
1105         }
1106         if (IS_VERBOSE_DEBUG)
1107                 fprintf(stderr, "\nCode:\n");
1108
1109         list_for_each_entry(c, &ctx->output, list) {
1110                 switch (c->type) {
1111                 case OUT_INSN:
1112                         insn_count++;
1113                         break;
1114                 default:
1115                         break;
1116                 }
1117         }
1118
1119         switch (cmdargs.outformat) {
1120         case FMT_RAW_LE32:
1121         case FMT_RAW_BE32:
1122                 /* Nothing */
1123                 break;
1124         case FMT_B43:
1125                 memset(&hdr, 0, sizeof(hdr));
1126                 hdr.type = FW_TYPE_UCODE;
1127                 hdr.ver = FW_HDR_VER;
1128                 hdr.size = cpu_to_be32(8 * insn_count);
1129                 if (fwrite(&hdr, sizeof(hdr), 1, fd) != 1) {
1130                         fprintf(stderr, "Could not write microcode outfile\n");
1131                         exit(1);
1132                 }
1133                 break;
1134         }
1135
1136         switch (ctx->arch) {
1137         case 5:
1138                 insn_count_limit = NUM_INSN_LIMIT_R5;
1139                 break;
1140         case 15:
1141                 insn_count_limit = ~0; //FIXME limit currently unknown.
1142                 break;
1143         default:
1144                 asm_error(ctx, "Internal error: emit_code unknown arch\n");
1145         }
1146         if (insn_count > insn_count_limit)
1147                 asm_warn(ctx, "Generating more than %u instructions. This "
1148                               "will overflow the device microcode memory.",
1149                          insn_count_limit);
1150
1151         list_for_each_entry(c, &ctx->output, list) {
1152                 switch (c->type) {
1153                 case OUT_INSN:
1154                         if (IS_VERBOSE_DEBUG) {
1155                                 fprintf(stderr, "%03X %03X,%03X,%03X\n",
1156                                         c->opcode,
1157                                         c->operands[0].u.operand,
1158                                         c->operands[1].u.operand,
1159                                         c->operands[2].u.operand);
1160                         }
1161
1162                         switch (ctx->arch) {
1163                         case 5:
1164                                 code = 0;
1165                                 code |= ((uint64_t)c->operands[2].u.operand);
1166                                 code |= ((uint64_t)c->operands[1].u.operand) << 12;
1167                                 code |= ((uint64_t)c->operands[0].u.operand) << 24;
1168                                 code |= ((uint64_t)c->opcode) << 36;
1169                                 break;
1170                         case 15:
1171                                 code = 0;
1172                                 code |= ((uint64_t)c->operands[2].u.operand);
1173                                 code |= ((uint64_t)c->operands[1].u.operand) << 13;
1174                                 code |= ((uint64_t)c->operands[0].u.operand) << 26;
1175                                 code |= ((uint64_t)c->opcode) << 39;
1176                                 break;
1177                         default:
1178                                 asm_error(ctx, "No emit format for arch %u",
1179                                           ctx->arch);
1180                         }
1181
1182                         switch (cmdargs.outformat) {
1183                         case FMT_B43:
1184                         case FMT_RAW_BE32:
1185                                 code = ((code & (uint64_t)0xFFFFFFFF00000000ULL) >> 32) |
1186                                        ((code & (uint64_t)0x00000000FFFFFFFFULL) << 32);
1187                                 outbuf[0] = (code & (uint64_t)0xFF00000000000000ULL) >> 56;
1188                                 outbuf[1] = (code & (uint64_t)0x00FF000000000000ULL) >> 48;
1189                                 outbuf[2] = (code & (uint64_t)0x0000FF0000000000ULL) >> 40;
1190                                 outbuf[3] = (code & (uint64_t)0x000000FF00000000ULL) >> 32;
1191                                 outbuf[4] = (code & (uint64_t)0x00000000FF000000ULL) >> 24;
1192                                 outbuf[5] = (code & (uint64_t)0x0000000000FF0000ULL) >> 16;
1193                                 outbuf[6] = (code & (uint64_t)0x000000000000FF00ULL) >> 8;
1194                                 outbuf[7] = (code & (uint64_t)0x00000000000000FFULL) >> 0;
1195                                 break;
1196                         case FMT_RAW_LE32:
1197                                 outbuf[7] = (code & (uint64_t)0xFF00000000000000ULL) >> 56;
1198                                 outbuf[6] = (code & (uint64_t)0x00FF000000000000ULL) >> 48;
1199                                 outbuf[5] = (code & (uint64_t)0x0000FF0000000000ULL) >> 40;
1200                                 outbuf[4] = (code & (uint64_t)0x000000FF00000000ULL) >> 32;
1201                                 outbuf[3] = (code & (uint64_t)0x00000000FF000000ULL) >> 24;
1202                                 outbuf[2] = (code & (uint64_t)0x0000000000FF0000ULL) >> 16;
1203                                 outbuf[1] = (code & (uint64_t)0x000000000000FF00ULL) >> 8;
1204                                 outbuf[0] = (code & (uint64_t)0x00000000000000FFULL) >> 0;
1205                                 break;
1206                         }
1207
1208                         if (fwrite(&outbuf, ARRAY_SIZE(outbuf), 1, fd) != 1) {
1209                                 fprintf(stderr, "Could not write microcode outfile\n");
1210                                 exit(1);
1211                         }
1212                         break;
1213                 case OUT_LABEL:
1214                         break;
1215                 }
1216         }
1217
1218         if (cmdargs.print_sizes) {
1219                 printf("%s:  text = %u instructions (%u bytes)\n",
1220                        fn, insn_count,
1221                        (unsigned int)(insn_count * sizeof(uint64_t)));
1222         }
1223
1224         fclose(fd);
1225 }
1226
1227 static void assemble(void)
1228 {
1229         struct assembler_context ctx;
1230
1231         memset(&ctx, 0, sizeof(ctx));
1232         INIT_LIST_HEAD(&ctx.output);
1233
1234         eval_directives(&ctx);
1235         assemble_instructions(&ctx);
1236         resolve_labels(&ctx);
1237         emit_code(&ctx);
1238 }
1239
1240 static void initialize(void)
1241 {
1242         INIT_LIST_HEAD(&infile.sl);
1243         INIT_LIST_HEAD(&infile.ivals);
1244 #ifdef YYDEBUG
1245         if (IS_INSANE_DEBUG)
1246                 yydebug = 1;
1247         else
1248                 yydebug = 0;
1249 #endif /* YYDEBUG */
1250 }
1251
1252 int main(int argc, char **argv)
1253 {
1254         int err, res = 1;
1255
1256         err = parse_args(argc, argv);
1257         if (err < 0)
1258                 goto out;
1259         if (err > 0) {
1260                 res = 0;
1261                 goto out;
1262         }
1263         err = open_input_file();
1264         if (err)
1265                 goto out;
1266         initialize();
1267         yyparse();
1268         assemble();
1269         assemble_initvals();
1270         close_input_file();
1271         res = 0;
1272 out:
1273         /* Lazyman simply leaks all allocated memory. */
1274         return res;
1275 }