2 * Copyright (C) 2006-2007 Michael Buesch <mb@bu3sch.de>
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.
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.
26 extern int yyparse(void);
30 const char *infile_name;
31 const char *outfile_name;
41 unsigned int operand; /* For NORMAL */
42 struct label *label; /* For LABELREF */
53 struct out_operand operands[3];
55 /* The absolute address of this instruction.
56 * Only used in resolve_labels(). */
59 const char *labelname; /* only for OUT_LABEL */
60 /* Set to 1, if this is the %start instruction. */
63 struct list_head list;
66 struct assembler_context {
67 /* The architecture version (802.11 core revision) */
70 struct label *start_label;
73 struct statement *cur_stmt;
75 struct list_head output;
79 #define for_each_statement(ctx, s) \
80 list_for_each_entry(s, &infile.sl, list) { \
83 #define for_each_statement_end(ctx, s) \
84 } do { ctx->cur_stmt = NULL; } while (0)
86 #define _msg_helper(type, stmt, msg, x...) do { \
87 fprintf(stderr, "Assembler " type); \
89 fprintf(stderr, " (file \"%s\", line %u)", \
93 fprintf(stderr, ":\n " msg "\n" ,##x); \
96 #define asm_error(ctx, msg, x...) do { \
97 _msg_helper("ERROR", (ctx)->cur_stmt, msg ,##x); \
101 #define asm_warn(ctx, msg, x...) \
102 _msg_helper("warning", (ctx)->cur_stmt, msg ,##x)
104 #define asm_info(ctx, msg, x...) \
105 _msg_helper("info", (ctx)->cur_stmt, msg ,##x)
108 static void eval_directives(struct assembler_context *ctx)
113 int have_start_label = 0;
116 for_each_statement(ctx, s) {
117 if (s->type == STMT_ASMDIR) {
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",
131 if (have_start_label)
132 asm_error(ctx, "Multiple %%start definitions");
133 ctx->start_label = ad->u.start;
134 have_start_label = 1;
137 asm_error(ctx, "Unknown ASM directive");
140 } for_each_statement_end(ctx, s);
143 asm_error(ctx, "No %%arch defined");
144 if (!have_start_label)
145 asm_info(ctx, "Using start address 0");
148 static bool is_possible_imm(unsigned int imm)
152 /* Immediates are only possible up to 16bit (wordsize). */
155 if (imm & (1 << 15)) {
156 if ((imm & mask) != mask &&
160 if ((imm & mask) != 0)
167 static bool is_valid_imm(struct assembler_context *ctx,
171 unsigned int immediate_size;
173 /* This function checks if the immediate value is representable
174 * as a native immediate operand.
176 * For v5 architecture the immediate can be 10bit long.
177 * For v15 architecture the immediate can be 11bit long.
179 * The value is sign-extended, so we allow values
180 * of 0xFFFA, for example.
183 if (!is_possible_imm(imm))
187 if (ctx->arch == 5) {
188 immediate_size = 10; /* 10bit */
189 } else if (ctx->arch == 15) {
190 immediate_size = 11; /* 11bit */
192 asm_error(ctx, "Unknown immediate size for arch %u",
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)
207 /* All bits above the immediate's size must
216 /* This checks if the value is nonzero and a power of two. */
217 static bool is_power_of_two(unsigned int value)
219 return (value && ((value & (value - 1)) == 0));
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)
226 unsigned int low_zeros_mask;
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);
242 return is_contiguous;
245 static unsigned int generate_imm_operand(struct assembler_context *ctx,
246 const struct immediate *imm)
248 unsigned int val, tmp;
251 /* format: 0b11ii iiii iiii */
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?",
274 static unsigned int generate_reg_operand(struct assembler_context *ctx,
275 const struct registr *reg)
277 unsigned int val = 0;
281 /* format: 0b1011 11rr rrrr */
285 if (reg->nr & ~0x3F) //FIXME 128 regs for v15 arch possible?
286 asm_error(ctx, "GPR-nr too big");
290 /* format: 0b100. .... .... */
294 if (reg->nr & ~0x1FF)
295 asm_error(ctx, "SPR-nr too big");
299 /* format: 0b1000 0110 0rrr */
304 asm_error(ctx, "OFFR-nr too big");
308 asm_error(ctx, "generate_reg_operand() regtype");
314 static unsigned int generate_mem_operand(struct assembler_context *ctx,
315 const struct memory *mem)
317 unsigned int val = 0, off, reg;
321 /* format: 0b0mmm mmmm mmmm */
323 if (off & ~0x7FF) { //FIXME 4096 words for v15 arch possible?
324 asm_warn(ctx, "DIRECT memoffset 0x%X too long (> 11 bits)", off);
330 /* format: 0b101r rroo oooo */
334 //FIXME what about v15 arch?
336 asm_warn(ctx, "INDIRECT memoffset 0x%X too long (> 6 bits)", off);
340 asm_error(ctx, "OFFR-nr too big");
345 asm_error(ctx, "generate_mem_operand() memtype");
351 static void generate_operand(struct assembler_context *ctx,
352 const struct operand *oper,
353 struct out_operand *out)
355 out->type = OUTOPER_NORMAL;
357 switch (oper->type) {
359 out->u.operand = generate_imm_operand(ctx, oper->u.imm);
362 out->u.operand = generate_reg_operand(ctx, oper->u.reg);
365 out->u.operand = generate_mem_operand(ctx, oper->u.mem);
368 out->type = OUTOPER_LABELREF;
369 out->u.label = oper->u.label;
372 out->u.operand = oper->u.addr->addr;
375 out->u.operand = oper->u.raw;
378 asm_error(ctx, "generate_operand() operstate");
382 static void do_assemble_insn(struct assembler_context *ctx,
383 struct instruction *insn,
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;
396 out = xmalloc(sizeof(*out));
397 INIT_LIST_HEAD(&out->list);
398 out->opcode = opcode;
401 if (ARRAY_SIZE(out->operands) > ARRAY_SIZE(ol->oper))
402 asm_error(ctx, "Internal operand array confusion");
404 for (i = 0; i < ARRAY_SIZE(out->operands); i++) {
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;
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;
427 generate_operand(ctx, oper, &out->operands[i]);
431 asm_error(ctx, "Internal error: nr_oper at "
432 "lowlevel do_assemble_insn");
434 list_add_tail(&out->list, &ctx->output);
437 static unsigned int merge_ext_into_opcode(struct assembler_context *ctx,
439 struct instruction *insn)
443 unsigned int mask, shift;
447 mask = ol->oper[0]->u.raw;
449 asm_error(ctx, "opcode MASK extension too big (> 0xF)");
450 shift = ol->oper[1]->u.raw;
452 asm_error(ctx, "opcode SHIFT extension too big (> 0xF)");
453 opcode |= (mask << 4);
455 ol->oper[0] = ol->oper[2];
456 ol->oper[1] = ol->oper[3];
457 ol->oper[2] = ol->oper[4];
462 static unsigned int merge_external_jmp_into_opcode(struct assembler_context *ctx,
464 struct instruction *insn)
472 cond = ol->oper[0]->u.raw;
474 asm_error(ctx, "External jump condition value too big (> 0xFF)");
476 ol->oper[0] = ol->oper[1];
477 ol->oper[1] = ol->oper[2];
478 ol->oper[2] = ol->oper[3];
483 static void assemble_instruction(struct assembler_context *ctx,
484 struct instruction *insn);
486 static void emulate_mov_insn(struct assembler_context *ctx,
487 struct instruction *insn)
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;
498 struct operand *in, *out;
501 /* This is a pseudo-OP. We emulate it by OR or ORX */
503 in = insn->operands->oper[0];
504 out = insn->operands->oper[1];
509 em_op_x.type = OPER_IMM;
510 em_op_x.u.imm = &em_imm_x;
511 em_ol.oper[1] = &em_op_x;
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 */
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;
527 em_imm_x.imm = (tmp & 0xFF00) >> 8;
528 em_op_x.type = OPER_IMM;
529 em_op_x.u.imm = &em_imm_x;
531 em_imm_y.imm = (tmp & 0x00FF);
532 em_op_y.type = OPER_IMM;
533 em_op_y.u.imm = &em_imm_y;
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;
543 em_insn.operands = &em_ol;
544 assemble_instruction(ctx, &em_insn); /* recurse */
547 static void emulate_jmp_insn(struct assembler_context *ctx,
548 struct instruction *insn)
550 struct instruction em_insn;
551 struct operlist em_ol;
552 struct operand em_op;
553 struct immediate em_imm;
555 /* This is a pseudo-OP. We emulate it by JE */
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 */
568 static void emulate_jand_insn(struct assembler_context *ctx,
569 struct instruction *insn,
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;
579 struct operand *oper0, *oper1, *oper2;
580 struct operand *imm_oper = NULL;
582 int first_bit, last_bit;
584 oper0 = insn->operands->oper[0];
585 oper1 = insn->operands->oper[1];
586 oper2 = insn->operands->oper[2];
588 if (oper0->type == OPER_IMM)
590 if (oper1->type == OPER_IMM)
592 if (oper0->type == OPER_IMM && oper1->type == OPER_IMM)
596 /* We have a single immediate operand.
597 * Check if it's representable by a normal JAND insn.
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",
607 first_bit = ffs(tmp);
608 last_bit = ffs(~(tmp >> (first_bit - 1))) - 1 + first_bit - 1;
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;
620 em_op_y.type = OPER_IMM;
621 em_op_y.u.imm = &em_imm;
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;
628 em_ol.oper[2] = oper1;
629 em_ol.oper[3] = &em_op_y;
630 em_ol.oper[4] = oper2;
632 em_insn.operands = &em_ol;
634 assemble_instruction(ctx, &em_insn); /* recurse */
639 /* Do a normal JAND/JNAND instruction */
641 do_assemble_insn(ctx, insn, 0x040 | 0x1);
643 do_assemble_insn(ctx, insn, 0x040);
646 static void assemble_instruction(struct assembler_context *ctx,
647 struct instruction *insn)
653 do_assemble_insn(ctx, insn, 0x1C0);
656 do_assemble_insn(ctx, insn, 0x1C2);
659 do_assemble_insn(ctx, insn, 0x1C1);
662 do_assemble_insn(ctx, insn, 0x1C3);
665 do_assemble_insn(ctx, insn, 0x1D0);
668 do_assemble_insn(ctx, insn, 0x1D2);
671 do_assemble_insn(ctx, insn, 0x1D1);
674 do_assemble_insn(ctx, insn, 0x1D3);
677 do_assemble_insn(ctx, insn, 0x130);
680 do_assemble_insn(ctx, insn, 0x160);
683 do_assemble_insn(ctx, insn, 0x140);
686 do_assemble_insn(ctx, insn, 0x170);
689 do_assemble_insn(ctx, insn, 0x120);
692 opcode = merge_ext_into_opcode(ctx, 0x200, insn);
693 do_assemble_insn(ctx, insn, opcode);
696 do_assemble_insn(ctx, insn, 0x110);
699 do_assemble_insn(ctx, insn, 0x1A0);
702 do_assemble_insn(ctx, insn, 0x1B0);
705 do_assemble_insn(ctx, insn, 0x150);
708 opcode = merge_ext_into_opcode(ctx, 0x300, insn);
709 do_assemble_insn(ctx, insn, opcode);
712 emulate_mov_insn(ctx, insn);
715 emulate_jmp_insn(ctx, insn);
718 emulate_jand_insn(ctx, insn, 0);
721 emulate_jand_insn(ctx, insn, 1);
724 do_assemble_insn(ctx, insn, 0x050);
727 do_assemble_insn(ctx, insn, 0x050 | 0x1);
730 do_assemble_insn(ctx, insn, 0x0D0);
733 do_assemble_insn(ctx, insn, 0x0D0 | 0x1);
736 do_assemble_insn(ctx, insn, 0x0D2);
739 do_assemble_insn(ctx, insn, 0x0D2 | 0x1);
742 do_assemble_insn(ctx, insn, 0x0D4);
745 do_assemble_insn(ctx, insn, 0x0D4 | 0x1);
748 do_assemble_insn(ctx, insn, 0x0DA);
751 do_assemble_insn(ctx, insn, 0x0DA | 0x1);
754 do_assemble_insn(ctx, insn, 0x0DC);
757 do_assemble_insn(ctx, insn, 0x0DC | 0x1);
760 opcode = merge_ext_into_opcode(ctx, 0x400, insn);
761 do_assemble_insn(ctx, insn, opcode);
764 opcode = merge_ext_into_opcode(ctx, 0x500, insn);
765 do_assemble_insn(ctx, insn, opcode);
768 opcode = merge_external_jmp_into_opcode(ctx, 0x700, insn);
769 do_assemble_insn(ctx, insn, opcode);
772 opcode = merge_external_jmp_into_opcode(ctx, 0x600, insn);
773 do_assemble_insn(ctx, insn, opcode);
776 do_assemble_insn(ctx, insn, 0x002);
779 do_assemble_insn(ctx, insn, 0x003);
785 do_assemble_insn(ctx, insn, 0x1E0);
788 do_assemble_insn(ctx, insn, 0x001);
791 do_assemble_insn(ctx, insn, insn->opcode);
794 asm_error(ctx, "Unknown op");
798 static void assemble_instructions(struct assembler_context *ctx)
801 struct instruction *insn;
802 struct code_output *out;
804 if (ctx->start_label) {
805 /* Generate a jump instruction at offset 0 to
806 * jump to the code start.
808 struct instruction sjmp;
812 oper.type = OPER_LABEL;
813 oper.u.label = ctx->start_label;
818 assemble_instruction(ctx, &sjmp);
819 out = list_entry(ctx->output.next, struct code_output, list);
820 out->is_start_insn = 1;
823 for_each_statement(ctx, s) {
828 assemble_instruction(ctx, insn);
831 out = xmalloc(sizeof(*out));
832 INIT_LIST_HEAD(&out->list);
833 out->type = OUT_LABEL;
834 out->labelname = s->u.label->name;
836 list_add_tail(&out->list, &ctx->output);
841 } for_each_statement_end(ctx, s);
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)
849 struct code_output *c;
853 switch (labelref->direction) {
854 case LABELREF_ABSOLUTE:
855 list_for_each_entry(c, &ctx->output, list) {
856 if (c->type != OUT_LABEL)
858 if (strcmp(c->labelname, labelref->name) != 0)
861 asm_error(ctx, "Ambiguous label reference \"%s\"",
865 address = c->address;
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)
874 if (strcmp(c->labelname, labelref->name) == 0) {
876 address = c->address;
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)
887 if (strcmp(c->labelname, labelref->name) == 0) {
889 address = c->address;
899 static void resolve_labels(struct assembler_context *ctx)
901 struct code_output *c;
904 unsigned int current_address;
906 /* Calculate the absolute addresses for each instruction. */
907 recalculate_addresses:
909 list_for_each_entry(c, &ctx->output, list) {
912 c->address = current_address;
916 c->address = current_address;
921 /* Resolve the symbolic label references. */
922 list_for_each_entry(c, &ctx->output, list) {
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.
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);
938 list_del(&c->list); /* Kill it */
939 goto recalculate_addresses;
943 for (i = 0; i < ARRAY_SIZE(c->operands); i++) {
944 if (c->operands[i].type != OUTOPER_LABELREF)
946 addr = get_labeladdress(ctx, c, c->operands[i].u.label);
949 c->operands[i].u.operand = addr;
951 /* Is not a jump target.
952 * Make it be an immediate */
954 c->operands[i].u.operand |= 0xC00;
955 else if (ctx->arch == 15)
956 c->operands[i].u.operand |= 0xC00 << 1;
958 asm_error(ctx, "Internal error: label res imm");
969 asm_error(ctx, "Label \"%s\" does not exist",
970 c->operands[i].u.label->name);
973 static void emit_code(struct assembler_context *ctx)
978 struct code_output *c;
980 unsigned char outbuf[8];
981 unsigned int insn_count = 0;
982 struct fw_header hdr;
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+");
989 fprintf(stderr, "Could not open microcode output file \"%s\"\n", fn);
993 if (IS_VERBOSE_DEBUG)
994 fprintf(stderr, "\nCode:\n");
996 list_for_each_entry(c, &ctx->output, list) {
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");
1015 if (insn_count > NUM_INSN_LIMIT)
1016 asm_warn(ctx, "Generating more than %d instructions. This "
1017 "will overflow the device microcode memory.",
1020 list_for_each_entry(c, &ctx->output, list) {
1023 if (IS_VERBOSE_DEBUG) {
1024 fprintf(stderr, "%03X %03X,%03X,%03X\n",
1026 c->operands[0].u.operand,
1027 c->operands[1].u.operand,
1028 c->operands[2].u.operand);
1032 if (ctx->arch == 5) {
1033 /* Instruction binary format is: xxyyyzzz0000oooX
1036 * Xxx is the first operand
1037 * yyy is the second operand
1038 * zzz is the third operand
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);
1054 asm_error(ctx, "No emit format for arch %u",
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;
1066 if (fwrite(&outbuf, ARRAY_SIZE(outbuf), 1, fd) != 1) {
1067 fprintf(stderr, "Could not write microcode outfile\n");
1079 static void assemble(void)
1081 struct assembler_context ctx;
1083 memset(&ctx, 0, sizeof(ctx));
1084 INIT_LIST_HEAD(&ctx.output);
1086 eval_directives(&ctx);
1087 assemble_instructions(&ctx);
1088 resolve_labels(&ctx);
1092 static void initialize(void)
1094 INIT_LIST_HEAD(&infile.sl);
1095 INIT_LIST_HEAD(&infile.ivals);
1097 if (IS_INSANE_DEBUG)
1101 #endif /* YYDEBUG */
1104 int main(int argc, char **argv)
1108 err = parse_args(argc, argv);
1111 err = open_input_file();
1117 assemble_initvals();
1121 /* Lazyman simply leaks all allocated memory. */