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