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