assembler: Some r15 fixes
[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                 switch (ctx->arch) {
329                 case 5:
330                         if (off & ~0x7FF) {
331                                 asm_warn(ctx, "DIRECT memoffset 0x%X too long (> 11 bits)", off);
332                                 off &= 0x7FF;
333                         }
334                         break;
335                 case 15:
336                         if (off & ~0xFFF) {
337                                 asm_warn(ctx, "DIRECT memoffset 0x%X too long (> 12 bits)", off);
338                                 off &= 0xFFF;
339                         }
340                         break;
341                 default:
342                         asm_error(ctx, "Internal error: generate_mem_operand invalid arch");
343                 }
344                 val |= off;
345                 break;
346         case MEM_INDIRECT:
347                 /* format: 0b101r rroo oooo */
348                 off = mem->offset;
349                 reg = mem->offr_nr;
350                 val |= 0xA00;
351                 //FIXME what about v15 arch?
352                 if (off & ~0x3F) {
353                         asm_warn(ctx, "INDIRECT memoffset 0x%X too long (> 6 bits)", off);
354                         off &= 0x3F;
355                 }
356                 if (reg > 6) {
357                         /* Assembler bug. The parser shouldn't pass this value. */
358                         asm_error(ctx, "OFFR-nr too big");
359                 }
360                 if (reg == 6 && ctx->arch == 5) {
361                         asm_warn(ctx, "Using offset register 6. This register is broken "
362                                  "on architecture 5 devices. Use off0 to off5 only.");
363                 }
364                 val |= off;
365                 val |= (reg << 6);
366                 break;
367         default:
368                 asm_error(ctx, "generate_mem_operand() memtype");
369         }
370
371         return val;
372 }
373
374 static void generate_operand(struct assembler_context *ctx,
375                              const struct operand *oper,
376                              struct out_operand *out)
377 {
378         out->type = OUTOPER_NORMAL;
379
380         switch (oper->type) {
381         case OPER_IMM:
382                 out->u.operand = generate_imm_operand(ctx, oper->u.imm);
383                 break;
384         case OPER_REG:
385                 out->u.operand = generate_reg_operand(ctx, oper->u.reg);
386                 break;
387         case OPER_MEM:
388                 out->u.operand = generate_mem_operand(ctx, oper->u.mem);
389                 break;
390         case OPER_LABEL:
391                 out->type = OUTOPER_LABELREF;
392                 out->u.label = oper->u.label;
393                 break;
394         case OPER_ADDR:
395                 out->u.operand = oper->u.addr->addr;
396                 break;
397         case OPER_RAW:
398                 out->u.operand = oper->u.raw;
399                 break;
400         default:
401                 asm_error(ctx, "generate_operand() operstate");
402         }
403 }
404
405 static struct code_output * do_assemble_insn(struct assembler_context *ctx,
406                                              struct instruction *insn,
407                                              unsigned int opcode)
408 {
409         int i;
410         struct operlist *ol;
411         int nr_oper = 0;
412         uint64_t code = 0;
413         struct code_output *out;
414         struct label *labelref = NULL;
415         struct operand *oper;
416         int have_spr_operand = 0;
417         int have_mem_operand = 0;
418
419         out = xmalloc(sizeof(*out));
420         INIT_LIST_HEAD(&out->list);
421         out->opcode = opcode;
422
423         ol = insn->operands;
424         if (ARRAY_SIZE(out->operands) > ARRAY_SIZE(ol->oper))
425                 asm_error(ctx, "Internal operand array confusion");
426
427         for (i = 0; i < ARRAY_SIZE(out->operands); i++) {
428                 oper = ol->oper[i];
429                 if (!oper)
430                         continue;
431
432                 /* If this is an INPUT operand (first or second), we must
433                  * make sure that not both are accessing SPR or MEMORY.
434                  * The device only supports one SPR or MEMORY operand in
435                  * the input operands. */
436                 if ((i == 0) || (i == 1)) {
437                         if ((oper->type == OPER_REG) &&
438                             (oper->u.reg->type == SPR)) {
439                                 if (have_spr_operand)
440                                         asm_error(ctx, "Multiple SPR input operands in one instruction");
441                                 have_spr_operand = 1;
442                         }
443                         if (oper->type == OPER_MEM) {
444                                 if (have_mem_operand)
445                                         asm_error(ctx, "Multiple MEMORY input operands in on instruction");
446                                 have_mem_operand = 1;
447                         }
448                 }
449
450                 generate_operand(ctx, oper, &out->operands[i]);
451                 nr_oper++;
452         }
453         if (nr_oper != 3)
454                 asm_error(ctx, "Internal error: nr_oper at "
455                                "lowlevel do_assemble_insn");
456
457         list_add_tail(&out->list, &ctx->output);
458
459         return out;
460 }
461
462 static unsigned int merge_ext_into_opcode(struct assembler_context *ctx,
463                                           unsigned int opbase,
464                                           struct instruction *insn)
465 {
466         struct operlist *ol;
467         unsigned int opcode;
468         unsigned int mask, shift;
469
470         ol = insn->operands;
471         opcode = opbase;
472         mask = ol->oper[0]->u.raw;
473         if (mask & ~0xF)
474                 asm_error(ctx, "opcode MASK extension too big (> 0xF)");
475         shift = ol->oper[1]->u.raw;
476         if (shift & ~0xF)
477                 asm_error(ctx, "opcode SHIFT extension too big (> 0xF)");
478         opcode |= (mask << 4);
479         opcode |= shift;
480         ol->oper[0] = ol->oper[2];
481         ol->oper[1] = ol->oper[3];
482         ol->oper[2] = ol->oper[4];
483
484         return opcode;
485 }
486
487 static unsigned int merge_external_jmp_into_opcode(struct assembler_context *ctx,
488                                                    unsigned int opbase,
489                                                    struct instruction *insn)
490 {
491         struct operand *fake;
492         struct registr *fake_reg;
493         struct operand *target;
494         struct operlist *ol;
495         unsigned int cond;
496         unsigned int opcode;
497
498         ol = insn->operands;
499         opcode = opbase;
500         cond = ol->oper[0]->u.imm->imm;
501         if (cond & ~0xFF)
502                 asm_error(ctx, "External jump condition value too big (> 0xFF)");
503         opcode |= cond;
504         target = ol->oper[1];
505         memset(ol->oper, 0, sizeof(ol->oper));
506
507         /* This instruction has two fake r0 operands
508          * at position 0 and 1. */
509         fake = xmalloc(sizeof(*fake));
510         fake_reg = xmalloc(sizeof(*fake_reg));
511         fake->type = OPER_REG;
512         fake->u.reg = fake_reg;
513         fake_reg->type = GPR;
514         fake_reg->nr = 0;
515
516         ol->oper[0] = fake;
517         ol->oper[1] = fake;
518         ol->oper[2] = target;
519
520         return opcode;
521 }
522
523 static void assemble_instruction(struct assembler_context *ctx,
524                                  struct instruction *insn);
525
526 static void emulate_mov_insn(struct assembler_context *ctx,
527                              struct instruction *insn)
528 {
529         struct instruction em_insn;
530         struct operlist em_ol;
531         struct operand em_op_shift;
532         struct operand em_op_mask;
533         struct operand em_op_x;
534         struct operand em_op_y;
535         struct immediate em_imm_x;
536         struct immediate em_imm_y;
537
538         struct operand *in, *out;
539         unsigned int tmp;
540
541         /* This is a pseudo-OP. We emulate it by OR or ORX */
542
543         in = insn->operands->oper[0];
544         out = insn->operands->oper[1];
545
546         em_insn.op = OP_OR;
547         em_ol.oper[0] = in;
548         em_imm_x.imm = 0;
549         em_op_x.type = OPER_IMM;
550         em_op_x.u.imm = &em_imm_x;
551         em_ol.oper[1] = &em_op_x;
552         em_ol.oper[2] = out;
553
554         if (in->type == OPER_IMM) {
555                 tmp = in->u.imm->imm;
556                 if (!is_possible_imm(tmp))
557                         asm_error(ctx, "MOV operand 0x%X > 16bit", tmp);
558                 if (!is_valid_imm(ctx, tmp)) {
559                         /* Immediate too big for plain OR */
560                         em_insn.op = OP_ORX;
561
562                         em_op_mask.type = OPER_RAW;
563                         em_op_mask.u.raw = 0x7;
564                         em_op_shift.type = OPER_RAW;
565                         em_op_shift.u.raw = 0x8;
566
567                         em_imm_x.imm = (tmp & 0xFF00) >> 8;
568                         em_op_x.type = OPER_IMM;
569                         em_op_x.u.imm = &em_imm_x;
570
571                         em_imm_y.imm = (tmp & 0x00FF);
572                         em_op_y.type = OPER_IMM;
573                         em_op_y.u.imm = &em_imm_y;
574
575                         em_ol.oper[0] = &em_op_mask;
576                         em_ol.oper[1] = &em_op_shift;
577                         em_ol.oper[2] = &em_op_x;
578                         em_ol.oper[3] = &em_op_y;
579                         em_ol.oper[4] = out;
580                 }
581         }
582
583         em_insn.operands = &em_ol;
584         assemble_instruction(ctx, &em_insn); /* recurse */
585 }
586
587 static void emulate_jmp_insn(struct assembler_context *ctx,
588                              struct instruction *insn)
589 {
590         struct instruction em_insn;
591         struct operlist em_ol;
592         struct immediate em_condition;
593         struct operand em_cond_op;
594
595         /* This is a pseudo-OP. We emulate it with
596          * JEXT 0x7F, target */
597
598         em_insn.op = OP_JEXT;
599         em_condition.imm = 0x7F; /* Ext cond: Always true */
600         em_cond_op.type = OPER_IMM;
601         em_cond_op.u.imm = &em_condition;
602         em_ol.oper[0] = &em_cond_op;
603         em_ol.oper[1] = insn->operands->oper[0]; /* Target */
604         em_insn.operands = &em_ol;
605
606         assemble_instruction(ctx, &em_insn); /* recurse */
607 }
608
609 static void emulate_jand_insn(struct assembler_context *ctx,
610                               struct instruction *insn,
611                               int inverted)
612 {
613         struct code_output *out;
614         struct instruction em_insn;
615         struct operlist em_ol;
616         struct operand em_op_shift;
617         struct operand em_op_mask;
618         struct operand em_op_y;
619         struct immediate em_imm;
620
621         struct operand *oper0, *oper1, *oper2;
622         struct operand *imm_oper = NULL;
623         unsigned int tmp;
624         int first_bit, last_bit;
625
626         oper0 = insn->operands->oper[0];
627         oper1 = insn->operands->oper[1];
628         oper2 = insn->operands->oper[2];
629
630         if (oper0->type == OPER_IMM)
631                 imm_oper = oper0;
632         if (oper1->type == OPER_IMM)
633                 imm_oper = oper1;
634         if (oper0->type == OPER_IMM && oper1->type == OPER_IMM)
635                 imm_oper = NULL;
636
637         if (imm_oper) {
638                 /* We have a single immediate operand.
639                  * Check if it's representable by a normal JAND insn.
640                  */
641                 tmp = imm_oper->u.imm->imm;
642                 if (!is_valid_imm(ctx, tmp)) {
643                         /* Nope, this must be emulated by JZX/JNZX */
644                         if (!is_contiguous_bitmask(tmp)) {
645                                 asm_error(ctx, "Long bitmask 0x%X is not contiguous",
646                                           tmp);
647                         }
648
649                         first_bit = ffs(tmp);
650                         last_bit = ffs(~(tmp >> (first_bit - 1))) - 1 + first_bit - 1;
651
652                         if (inverted)
653                                 em_insn.op = OP_JZX;
654                         else
655                                 em_insn.op = OP_JNZX;
656                         em_op_shift.type = OPER_RAW;
657                         em_op_shift.u.raw = first_bit - 1;
658                         em_op_mask.type = OPER_RAW;
659                         em_op_mask.u.raw = last_bit - first_bit;
660
661                         em_imm.imm = 0;
662                         em_op_y.type = OPER_IMM;
663                         em_op_y.u.imm = &em_imm;
664
665                         em_ol.oper[0] = &em_op_mask;
666                         em_ol.oper[1] = &em_op_shift;
667                         if (oper0->type != OPER_IMM)
668                                 em_ol.oper[2] = oper0;
669                         else
670                                 em_ol.oper[2] = oper1;
671                         em_ol.oper[3] = &em_op_y;
672                         em_ol.oper[4] = oper2;
673
674                         em_insn.operands = &em_ol;
675
676                         assemble_instruction(ctx, &em_insn); /* recurse */
677                         return;
678                 }
679         }
680
681         /* Do a normal JAND/JNAND instruction */
682         if (inverted)
683                 out = do_assemble_insn(ctx, insn, 0x040 | 0x1);
684         else
685                 out = do_assemble_insn(ctx, insn, 0x040);
686         out->is_jump_insn = 1;
687 }
688
689 static void assemble_instruction(struct assembler_context *ctx,
690                                  struct instruction *insn)
691 {
692         struct code_output *out;
693         unsigned int opcode;
694
695         switch (insn->op) {
696         case OP_ADD:
697                 do_assemble_insn(ctx, insn, 0x1C0);
698                 break;
699         case OP_ADDSC:
700                 do_assemble_insn(ctx, insn, 0x1C2);
701                 break;
702         case OP_ADDC:
703                 do_assemble_insn(ctx, insn, 0x1C1);
704                 break;
705         case OP_ADDSCC:
706                 do_assemble_insn(ctx, insn, 0x1C3);
707                 break;
708         case OP_SUB:
709                 do_assemble_insn(ctx, insn, 0x1D0);
710                 break;
711         case OP_SUBSC:
712                 do_assemble_insn(ctx, insn, 0x1D2);
713                 break;
714         case OP_SUBC:
715                 do_assemble_insn(ctx, insn, 0x1D1);
716                 break;
717         case OP_SUBSCC:
718                 do_assemble_insn(ctx, insn, 0x1D3);
719                 break;
720         case OP_SRA:
721                 do_assemble_insn(ctx, insn, 0x130);
722                 break;
723         case OP_OR:
724                 do_assemble_insn(ctx, insn, 0x160);
725                 break;
726         case OP_AND:
727                 do_assemble_insn(ctx, insn, 0x140);
728                 break;
729         case OP_XOR:
730                 do_assemble_insn(ctx, insn, 0x170);
731                 break;
732         case OP_SR:
733                 do_assemble_insn(ctx, insn, 0x120);
734                 break;
735         case OP_SRX:
736                 opcode = merge_ext_into_opcode(ctx, 0x200, insn);
737                 do_assemble_insn(ctx, insn, opcode);
738                 break;
739         case OP_SL:
740                 do_assemble_insn(ctx, insn, 0x110);
741                 break;
742         case OP_RL:
743                 do_assemble_insn(ctx, insn, 0x1A0);
744                 break;
745         case OP_RR:
746                 do_assemble_insn(ctx, insn, 0x1B0);
747                 break;
748         case OP_NAND:
749                 do_assemble_insn(ctx, insn, 0x150);
750                 break;
751         case OP_ORX:
752                 opcode = merge_ext_into_opcode(ctx, 0x300, insn);
753                 do_assemble_insn(ctx, insn, opcode);
754                 break;
755         case OP_MOV:
756                 emulate_mov_insn(ctx, insn);
757                 return;
758         case OP_JMP:
759                 emulate_jmp_insn(ctx, insn);
760                 return;
761         case OP_JAND:
762                 emulate_jand_insn(ctx, insn, 0);
763                 return;
764         case OP_JNAND:
765                 emulate_jand_insn(ctx, insn, 1);
766                 return;
767         case OP_JS:
768                 out = do_assemble_insn(ctx, insn, 0x050);
769                 out->is_jump_insn = 1;
770                 break;
771         case OP_JNS:
772                 out = do_assemble_insn(ctx, insn, 0x050 | 0x1);
773                 out->is_jump_insn = 1;
774                 break;
775         case OP_JE:
776                 out = do_assemble_insn(ctx, insn, 0x0D0);
777                 out->is_jump_insn = 1;
778                 break;
779         case OP_JNE:
780                 out = do_assemble_insn(ctx, insn, 0x0D0 | 0x1);
781                 out->is_jump_insn = 1;
782                 break;
783         case OP_JLS:
784                 out = do_assemble_insn(ctx, insn, 0x0D2);
785                 out->is_jump_insn = 1;
786                 break;
787         case OP_JGES:
788                 out = do_assemble_insn(ctx, insn, 0x0D2 | 0x1);
789                 out->is_jump_insn = 1;
790                 break;
791         case OP_JGS:
792                 out = do_assemble_insn(ctx, insn, 0x0D4);
793                 out->is_jump_insn = 1;
794                 break;
795         case OP_JLES:
796                 out = do_assemble_insn(ctx, insn, 0x0D4 | 0x1);
797                 out->is_jump_insn = 1;
798                 break;
799         case OP_JL:
800                 out = do_assemble_insn(ctx, insn, 0x0DA);
801                 out->is_jump_insn = 1;
802                 break;
803         case OP_JGE:
804                 out = do_assemble_insn(ctx, insn, 0x0DA | 0x1);
805                 out->is_jump_insn = 1;
806                 break;
807         case OP_JG:
808                 out = do_assemble_insn(ctx, insn, 0x0DC);
809                 break;
810         case OP_JLE:
811                 out = do_assemble_insn(ctx, insn, 0x0DC | 0x1);
812                 out->is_jump_insn = 1;
813                 break;
814         case OP_JZX:
815                 opcode = merge_ext_into_opcode(ctx, 0x400, insn);
816                 out = do_assemble_insn(ctx, insn, opcode);
817                 out->is_jump_insn = 1;
818                 break;
819         case OP_JNZX:
820                 opcode = merge_ext_into_opcode(ctx, 0x500, insn);
821                 out = do_assemble_insn(ctx, insn, opcode);
822                 out->is_jump_insn = 1;
823                 break;
824         case OP_JEXT:
825                 opcode = merge_external_jmp_into_opcode(ctx, 0x700, insn);
826                 out = do_assemble_insn(ctx, insn, opcode);
827                 out->is_jump_insn = 1;
828                 break;
829         case OP_JNEXT:
830                 opcode = merge_external_jmp_into_opcode(ctx, 0x600, insn);
831                 out = do_assemble_insn(ctx, insn, opcode);
832                 out->is_jump_insn = 1;
833                 break;
834         case OP_CALL:
835                 do_assemble_insn(ctx, insn, 0x002);
836                 break;
837         case OP_RET:
838                 /* Get the previous instruction and check whether it
839                  * is a jump instruction. */
840                 list_for_each_entry_reverse(out, &ctx->output, list) {
841                         /* Search the last insn. */
842                         if (out->type == OUT_INSN) {
843                                 if (out->is_jump_insn) {
844                                         asm_warn(ctx, "RET instruction directly after "
845                                                  "jump instruction. The hardware won't like this.");
846                                 }
847                                 break;
848                         }
849                 }
850                 do_assemble_insn(ctx, insn, 0x003);
851                 break;
852         case OP_TKIPH:
853         case OP_TKIPHS:
854         case OP_TKIPL:
855         case OP_TKIPLS:
856                 do_assemble_insn(ctx, insn, 0x1E0);
857                 break;
858         case OP_NAP:
859                 do_assemble_insn(ctx, insn, 0x001);
860                 break;
861         case RAW_CODE:
862                 do_assemble_insn(ctx, insn, insn->opcode);
863                 break;
864         default:
865                 asm_error(ctx, "Unknown op");
866         }
867 }
868
869 static void assemble_instructions(struct assembler_context *ctx)
870 {
871         struct statement *s;
872         struct instruction *insn;
873         struct code_output *out;
874
875         if (ctx->start_label) {
876                 /* Generate a jump instruction at offset 0 to
877                  * jump to the code start.
878                  */
879                 struct instruction sjmp;
880                 struct operlist ol;
881                 struct operand oper;
882
883                 oper.type = OPER_LABEL;
884                 oper.u.label = ctx->start_label;
885                 ol.oper[0] = &oper;
886                 sjmp.op = OP_JMP;
887                 sjmp.operands = &ol;
888
889                 assemble_instruction(ctx, &sjmp);
890                 out = list_entry(ctx->output.next, struct code_output, list);
891                 out->is_start_insn = 1;
892         }
893
894         for_each_statement(ctx, s) {
895                 switch (s->type) {
896                 case STMT_INSN:
897                         ctx->cur_stmt = s;
898                         insn = s->u.insn;
899                         assemble_instruction(ctx, insn);
900                         break;
901                 case STMT_LABEL:
902                         out = xmalloc(sizeof(*out));
903                         INIT_LIST_HEAD(&out->list);
904                         out->type = OUT_LABEL;
905                         out->labelname = s->u.label->name;
906
907                         list_add_tail(&out->list, &ctx->output);
908                         break;
909                 case STMT_ASMDIR:
910                         break;
911                 }
912         } for_each_statement_end(ctx, s);
913 }
914
915 /* Resolve a label reference to the address it points to. */
916 static int get_labeladdress(struct assembler_context *ctx,
917                             struct code_output *this_insn,
918                             struct label *labelref)
919 {
920         struct code_output *c;
921         bool found = 0;
922         int address = -1;
923
924         switch (labelref->direction) {
925         case LABELREF_ABSOLUTE:
926                 list_for_each_entry(c, &ctx->output, list) {
927                         if (c->type != OUT_LABEL)
928                                 continue;
929                         if (strcmp(c->labelname, labelref->name) != 0)
930                                 continue;
931                         if (found) {
932                                 asm_error(ctx, "Ambiguous label reference \"%s\"",
933                                           labelref->name);
934                         }
935                         found = 1;
936                         address = c->address;
937                 }
938                 break;
939         case LABELREF_RELATIVE_BACK:
940                 for (c = list_entry(this_insn->list.prev, typeof(*c), list);
941                      &c->list != &ctx->output;
942                      c = list_entry(c->list.prev, typeof(*c), list)) {
943                         if (c->type != OUT_LABEL)
944                                 continue;
945                         if (strcmp(c->labelname, labelref->name) == 0) {
946                                 /* Found */
947                                 address = c->address;
948                                 break;
949                         }
950                 }
951                 break;
952         case LABELREF_RELATIVE_FORWARD:
953                 for (c = list_entry(this_insn->list.next, typeof(*c), list);
954                      &c->list != &ctx->output;
955                      c = list_entry(c->list.next, typeof(*c), list)) {
956                         if (c->type != OUT_LABEL)
957                                 continue;
958                         if (strcmp(c->labelname, labelref->name) == 0) {
959                                 /* Found */
960                                 address = c->address;
961                                 break;
962                         }
963                 }
964                 break;
965         }
966
967         return address;
968 }
969
970 static void resolve_labels(struct assembler_context *ctx)
971 {
972         struct code_output *c;
973         int addr;
974         int i;
975         unsigned int current_address;
976
977         /* Calculate the absolute addresses for each instruction. */
978 recalculate_addresses:
979         current_address = 0;
980         list_for_each_entry(c, &ctx->output, list) {
981                 switch (c->type) {
982                 case OUT_INSN:
983                         c->address = current_address;
984                         current_address++;
985                         break;
986                 case OUT_LABEL:
987                         c->address = current_address;
988                         break;
989                 }
990         }
991
992         /* Resolve the symbolic label references. */
993         list_for_each_entry(c, &ctx->output, list) {
994                 switch (c->type) {
995                 case OUT_INSN:
996                         if (c->is_start_insn) {
997                                 /* If the first %start-jump jumps to 001, we can
998                                  * optimize it away, as it's unneeded.
999                                  */
1000                                 i = 2;
1001                                 if (c->operands[i].type != OUTOPER_LABELREF)
1002                                         asm_error(ctx, "Internal error, %%start insn oper 2 not labelref");
1003                                 if (c->operands[i].u.label->direction != LABELREF_ABSOLUTE)
1004                                         asm_error(ctx, "%%start label reference not absolute");
1005                                 addr = get_labeladdress(ctx, c, c->operands[i].u.label);
1006                                 if (addr < 0)
1007                                         goto does_not_exist;
1008                                 if (addr == 1) {
1009                                         list_del(&c->list); /* Kill it */
1010                                         goto recalculate_addresses;
1011                                 }
1012                         }
1013
1014                         for (i = 0; i < ARRAY_SIZE(c->operands); i++) {
1015                                 if (c->operands[i].type != OUTOPER_LABELREF)
1016                                         continue;
1017                                 addr = get_labeladdress(ctx, c, c->operands[i].u.label);
1018                                 if (addr < 0)
1019                                         goto does_not_exist;
1020                                 c->operands[i].u.operand = addr;
1021                                 if (i != 2) {
1022                                         /* Is not a jump target.
1023                                          * Make it be an immediate */
1024                                         if (ctx->arch == 5)
1025                                                 c->operands[i].u.operand |= 0xC00;
1026                                         else if (ctx->arch == 15)
1027                                                 c->operands[i].u.operand |= 0xC00 << 1;
1028                                         else
1029                                                 asm_error(ctx, "Internal error: label res imm");
1030                                 }
1031                         }
1032                         break;
1033                 case OUT_LABEL:
1034                         break;
1035                 }
1036         }
1037
1038         return;
1039 does_not_exist:
1040         asm_error(ctx, "Label \"%s\" does not exist",
1041                   c->operands[i].u.label->name);
1042 }
1043
1044 static void emit_code(struct assembler_context *ctx)
1045 {
1046         FILE *fd;
1047         const char *fn;
1048         struct code_output *c;
1049         uint64_t code;
1050         unsigned char outbuf[8];
1051         unsigned int insn_count = 0;
1052         struct fw_header hdr;
1053
1054         fn = outfile_name;
1055         fd = fopen(fn, "w+");
1056         if (!fd) {
1057                 fprintf(stderr, "Could not open microcode output file \"%s\"\n", fn);
1058                 exit(1);
1059         }
1060         if (IS_VERBOSE_DEBUG)
1061                 fprintf(stderr, "\nCode:\n");
1062
1063         list_for_each_entry(c, &ctx->output, list) {
1064                 switch (c->type) {
1065                 case OUT_INSN:
1066                         insn_count++;
1067                         break;
1068                 default:
1069                         break;
1070                 }
1071         }
1072
1073         memset(&hdr, 0, sizeof(hdr));
1074         hdr.type = FW_TYPE_UCODE;
1075         hdr.ver = FW_HDR_VER;
1076         hdr.size = cpu_to_be32(8 * insn_count);
1077         if (fwrite(&hdr, sizeof(hdr), 1, fd) != 1) {
1078                 fprintf(stderr, "Could not write microcode outfile\n");
1079                 exit(1);
1080         }
1081
1082         if (insn_count > NUM_INSN_LIMIT)
1083                 asm_warn(ctx, "Generating more than %d instructions. This "
1084                               "will overflow the device microcode memory.",
1085                          NUM_INSN_LIMIT);
1086
1087         list_for_each_entry(c, &ctx->output, list) {
1088                 switch (c->type) {
1089                 case OUT_INSN:
1090                         if (IS_VERBOSE_DEBUG) {
1091                                 fprintf(stderr, "%03X %03X,%03X,%03X\n",
1092                                         c->opcode,
1093                                         c->operands[0].u.operand,
1094                                         c->operands[1].u.operand,
1095                                         c->operands[2].u.operand);
1096                         }
1097                         code = 0;
1098
1099                         if (ctx->arch == 5) {
1100                                 /* Instruction binary format is: xxyyyzzz0000oooX
1101                                  *                        byte-0-^       byte-7-^
1102                                  * ooo is the opcode
1103                                  * Xxx is the first operand
1104                                  * yyy is the second operand
1105                                  * zzz is the third operand
1106                                  */
1107                                 code |= ((uint64_t)c->operands[2].u.operand);
1108                                 code |= ((uint64_t)c->operands[1].u.operand) << 12;
1109                                 code |= ((uint64_t)c->operands[0].u.operand) << 24;
1110                                 code |= ((uint64_t)c->opcode) << 36;
1111                                 code = ((code & (uint64_t)0xFFFFFFFF00000000ULL) >> 32) |
1112                                        ((code & (uint64_t)0x00000000FFFFFFFFULL) << 32);
1113                         } else if (ctx->arch == 15) {
1114                                 code |= ((uint64_t)c->operands[2].u.operand);
1115                                 code |= ((uint64_t)c->operands[1].u.operand) << 13;
1116                                 code |= ((uint64_t)c->operands[0].u.operand) << 26;
1117                                 code |= ((uint64_t)c->opcode) << 39;
1118                                 code = ((code & (uint64_t)0xFFFFFFFF00000000ULL) >> 32) |
1119                                        ((code & (uint64_t)0x00000000FFFFFFFFULL) << 32);
1120                         } else {
1121                                 asm_error(ctx, "No emit format for arch %u",
1122                                           ctx->arch);
1123                         }
1124                         outbuf[0] = (code & (uint64_t)0xFF00000000000000ULL) >> 56;
1125                         outbuf[1] = (code & (uint64_t)0x00FF000000000000ULL) >> 48;
1126                         outbuf[2] = (code & (uint64_t)0x0000FF0000000000ULL) >> 40;
1127                         outbuf[3] = (code & (uint64_t)0x000000FF00000000ULL) >> 32;
1128                         outbuf[4] = (code & (uint64_t)0x00000000FF000000ULL) >> 24;
1129                         outbuf[5] = (code & (uint64_t)0x0000000000FF0000ULL) >> 16;
1130                         outbuf[6] = (code & (uint64_t)0x000000000000FF00ULL) >> 8;
1131                         outbuf[7] = (code & (uint64_t)0x00000000000000FFULL) >> 0;
1132
1133                         if (fwrite(&outbuf, ARRAY_SIZE(outbuf), 1, fd) != 1) {
1134                                 fprintf(stderr, "Could not write microcode outfile\n");
1135                                 exit(1);
1136                         }
1137                         break;
1138                 case OUT_LABEL:
1139                         break;
1140                 }
1141         }
1142
1143         if (arg_print_sizes) {
1144                 printf("%s:  text = %u instructions (%u bytes)\n",
1145                        fn, insn_count,
1146                        (unsigned int)(insn_count * sizeof(uint64_t)));
1147         }
1148
1149         fclose(fd);
1150 }
1151
1152 static void assemble(void)
1153 {
1154         struct assembler_context ctx;
1155
1156         memset(&ctx, 0, sizeof(ctx));
1157         INIT_LIST_HEAD(&ctx.output);
1158
1159         eval_directives(&ctx);
1160         assemble_instructions(&ctx);
1161         resolve_labels(&ctx);
1162         emit_code(&ctx);
1163 }
1164
1165 static void initialize(void)
1166 {
1167         INIT_LIST_HEAD(&infile.sl);
1168         INIT_LIST_HEAD(&infile.ivals);
1169 #ifdef YYDEBUG
1170         if (IS_INSANE_DEBUG)
1171                 yydebug = 1;
1172         else
1173                 yydebug = 0;
1174 #endif /* YYDEBUG */
1175 }
1176
1177 int main(int argc, char **argv)
1178 {
1179         int err, res = 1;
1180
1181         err = parse_args(argc, argv);
1182         if (err < 0)
1183                 goto out;
1184         if (err > 0) {
1185                 res = 0;
1186                 goto out;
1187         }
1188         err = open_input_file();
1189         if (err)
1190                 goto out;
1191         initialize();
1192         yyparse();
1193         assemble();
1194         assemble_initvals();
1195         close_input_file();
1196         res = 0;
1197 out:
1198         /* Lazyman simply leaks all allocated memory. */
1199         return res;
1200 }