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