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 {
68 struct label *start_label;
71 struct statement *cur_stmt;
73 struct list_head output;
77 #define for_each_statement(ctx, s) \
78 list_for_each_entry(s, &infile.sl, list) { \
81 #define for_each_statement_end(ctx, s) \
82 } do { ctx->cur_stmt = NULL; } while (0)
84 #define _msg_helper(type, stmt, msg, x...) do { \
85 fprintf(stderr, "Assembler " type); \
87 fprintf(stderr, " (file \"%s\", line %u)", \
91 fprintf(stderr, ":\n " msg "\n" ,##x); \
94 #define asm_error(ctx, msg, x...) do { \
95 _msg_helper("ERROR", (ctx)->cur_stmt, msg ,##x); \
99 #define asm_warn(ctx, msg, x...) \
100 _msg_helper("warning", (ctx)->cur_stmt, msg ,##x)
102 #define asm_info(ctx, msg, x...) \
103 _msg_helper("info", (ctx)->cur_stmt, msg ,##x)
106 static void eval_directives(struct assembler_context *ctx)
111 int have_start_label = 0;
114 for_each_statement(ctx, s) {
115 if (s->type == STMT_ASMDIR) {
120 asm_error(ctx, "Multiple %%arch definitions");
121 ctx->arch = ad->u.arch;
125 if (have_start_label)
126 asm_error(ctx, "Multiple %%start definitions");
127 ctx->start_label = ad->u.start;
128 have_start_label = 1;
131 asm_error(ctx, "Unknown ASM directive");
134 } for_each_statement_end(ctx, s);
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");
144 static int is_possible_imm(unsigned int imm)
148 /* Immediates are only possible up to 16bit (wordsize). */
151 if (imm & (1 << 15)) {
152 if ((imm & mask) != mask &&
156 if ((imm & mask) != 0)
163 static int is_valid_imm(unsigned int imm)
167 /* This function checks if the immediate value is representable
168 * as a native immediate operand.
170 * The value itself is 10bit long, signed.
171 * We also honor sign-extension, so we allow values
172 * of 0xFFFF, for example.
175 if (!is_possible_imm(imm))
179 /* assert sign extension */
181 if (imm & (1 << 9)) {
183 if ((imm & mask) != mask)
193 static int is_contiguous_bitmask(unsigned int mask)
196 int only_zero_now = 0;
198 /* This checks if the mask is contiguous.
199 * A contiguous mask is:
201 * A non-contiguous mask is:
211 for ( ; bit < 16; bit++) {
212 if (mask & (1 << bit)) {
222 static unsigned int generate_imm_operand(struct assembler_context *ctx,
223 const struct immediate *imm)
225 unsigned int val, tmp;
229 /* format: 0b11ii iiii iiii */
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?",
247 static unsigned int generate_reg_operand(struct assembler_context *ctx,
248 const struct registr *reg)
250 unsigned int val = 0;
254 /* format: 0b1011 11rr rrrr */
257 asm_error(ctx, "GPR-nr too big");
261 /* format: 0b100. .... .... */
263 if (reg->nr & ~0x1FF)
264 asm_error(ctx, "SPR-nr too big");
268 /* format: 0b1000 0110 0rrr */
271 asm_error(ctx, "OFFR-nr too big");
275 asm_error(ctx, "generate_reg_operand() regtype");
281 static unsigned int generate_mem_operand(struct assembler_context *ctx,
282 const struct memory *mem)
284 unsigned int val = 0, off, reg;
288 /* format: 0b0mmm mmmm mmmm */
291 asm_warn(ctx, "DIRECT memoffset 0x%X too long (> 11 bits)", off);
297 /* format: 0b101r rroo oooo */
302 asm_warn(ctx, "INDIRECT memoffset 0x%X too long (> 6 bits)", off);
306 asm_error(ctx, "OFFR-nr too big");
311 asm_error(ctx, "generate_mem_operand() memtype");
317 static void generate_operand(struct assembler_context *ctx,
318 const struct operand *oper,
319 struct out_operand *out)
321 out->type = OUTOPER_NORMAL;
323 switch (oper->type) {
325 out->u.operand = generate_imm_operand(ctx, oper->u.imm);
328 out->u.operand = generate_reg_operand(ctx, oper->u.reg);
331 out->u.operand = generate_mem_operand(ctx, oper->u.mem);
334 out->type = OUTOPER_LABELREF;
335 out->u.label = oper->u.label;
338 out->u.operand = oper->u.addr->addr;
341 out->u.operand = oper->u.raw;
344 asm_error(ctx, "generate_operand() operstate");
348 static void do_assemble_insn(struct assembler_context *ctx,
349 struct instruction *insn,
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;
362 out = xmalloc(sizeof(*out));
363 INIT_LIST_HEAD(&out->list);
364 out->opcode = opcode;
367 if (ARRAY_SIZE(out->operands) > ARRAY_SIZE(ol->oper))
368 asm_error(ctx, "Internal operand array confusion");
370 for (i = 0; i < ARRAY_SIZE(out->operands); i++) {
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;
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;
393 generate_operand(ctx, oper, &out->operands[i]);
397 asm_error(ctx, "Internal error: nr_oper at "
398 "lowlevel do_assemble_insn");
400 list_add_tail(&out->list, &ctx->output);
403 static unsigned int merge_ext_into_opcode(struct assembler_context *ctx,
405 struct instruction *insn)
409 unsigned int mask, shift;
413 mask = ol->oper[0]->u.raw;
415 asm_error(ctx, "opcode MASK extension too big (> 0xF)");
416 shift = ol->oper[1]->u.raw;
418 asm_error(ctx, "opcode SHIFT extension too big (> 0xF)");
419 opcode |= (mask << 4);
421 ol->oper[0] = ol->oper[2];
422 ol->oper[1] = ol->oper[3];
423 ol->oper[2] = ol->oper[4];
428 static unsigned int merge_external_jmp_into_opcode(struct assembler_context *ctx,
430 struct instruction *insn)
438 cond = ol->oper[0]->u.raw;
440 asm_error(ctx, "External jump condition value too big (> 0xFF)");
442 ol->oper[0] = ol->oper[1];
443 ol->oper[1] = ol->oper[2];
444 ol->oper[2] = ol->oper[3];
449 static void assemble_instruction(struct assembler_context *ctx,
450 struct instruction *insn);
452 static void emulate_mov_insn(struct assembler_context *ctx,
453 struct instruction *insn)
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;
464 struct operand *in, *out;
467 /* This is a pseudo-OP. We emulate it by OR or ORX */
469 in = insn->operands->oper[0];
470 out = insn->operands->oper[1];
475 em_op_x.type = OPER_IMM;
476 em_op_x.u.imm = &em_imm_x;
477 em_ol.oper[1] = &em_op_x;
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 */
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;
493 em_imm_x.imm = (tmp & 0xFF00) >> 8;
494 em_op_x.type = OPER_IMM;
495 em_op_x.u.imm = &em_imm_x;
497 em_imm_y.imm = (tmp & 0x00FF);
498 em_op_y.type = OPER_IMM;
499 em_op_y.u.imm = &em_imm_y;
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;
509 em_insn.operands = &em_ol;
510 assemble_instruction(ctx, &em_insn); /* recurse */
513 static void emulate_jmp_insn(struct assembler_context *ctx,
514 struct instruction *insn)
516 struct instruction em_insn;
517 struct operlist em_ol;
518 struct operand em_op;
519 struct immediate em_imm;
521 /* This is a pseudo-OP. We emulate it by JE */
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 */
534 static void emulate_jand_insn(struct assembler_context *ctx,
535 struct instruction *insn,
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;
545 struct operand *oper0, *oper1, *oper2;
546 struct operand *imm_oper = NULL;
548 int first_bit, last_bit;
550 oper0 = insn->operands->oper[0];
551 oper1 = insn->operands->oper[1];
552 oper2 = insn->operands->oper[2];
554 if (oper0->type == OPER_IMM)
556 if (oper1->type == OPER_IMM)
558 if (oper0->type == OPER_IMM && oper1->type == OPER_IMM)
562 /* We have a single immediate operand.
563 * Check if it's representable by a normal JAND insn.
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",
573 first_bit = ffs(tmp);
574 last_bit = ffs(~(tmp >> (first_bit - 1))) - 1 + first_bit - 1;
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;
586 em_op_y.type = OPER_IMM;
587 em_op_y.u.imm = &em_imm;
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;
594 em_ol.oper[2] = oper1;
595 em_ol.oper[3] = &em_op_y;
596 em_ol.oper[4] = oper2;
598 em_insn.operands = &em_ol;
600 assemble_instruction(ctx, &em_insn); /* recurse */
605 /* Do a normal JAND/JNAND instruction */
607 do_assemble_insn(ctx, insn, 0x040 | 0x1);
609 do_assemble_insn(ctx, insn, 0x040);
612 static void assemble_instruction(struct assembler_context *ctx,
613 struct instruction *insn)
619 do_assemble_insn(ctx, insn, 0x1C0);
622 do_assemble_insn(ctx, insn, 0x1C2);
625 do_assemble_insn(ctx, insn, 0x1C1);
628 do_assemble_insn(ctx, insn, 0x1C3);
631 do_assemble_insn(ctx, insn, 0x1D0);
634 do_assemble_insn(ctx, insn, 0x1D2);
637 do_assemble_insn(ctx, insn, 0x1D1);
640 do_assemble_insn(ctx, insn, 0x1D3);
643 do_assemble_insn(ctx, insn, 0x130);
646 do_assemble_insn(ctx, insn, 0x160);
649 do_assemble_insn(ctx, insn, 0x140);
652 do_assemble_insn(ctx, insn, 0x170);
655 do_assemble_insn(ctx, insn, 0x120);
658 opcode = merge_ext_into_opcode(ctx, 0x200, insn);
659 do_assemble_insn(ctx, insn, opcode);
662 do_assemble_insn(ctx, insn, 0x110);
665 do_assemble_insn(ctx, insn, 0x1A0);
668 do_assemble_insn(ctx, insn, 0x1B0);
671 do_assemble_insn(ctx, insn, 0x150);
674 opcode = merge_ext_into_opcode(ctx, 0x300, insn);
675 do_assemble_insn(ctx, insn, opcode);
678 emulate_mov_insn(ctx, insn);
681 emulate_jmp_insn(ctx, insn);
684 emulate_jand_insn(ctx, insn, 0);
687 emulate_jand_insn(ctx, insn, 1);
690 do_assemble_insn(ctx, insn, 0x050);
693 do_assemble_insn(ctx, insn, 0x050 | 0x1);
696 do_assemble_insn(ctx, insn, 0x0D0);
699 do_assemble_insn(ctx, insn, 0x0D0 | 0x1);
702 do_assemble_insn(ctx, insn, 0x0D2);
705 do_assemble_insn(ctx, insn, 0x0D2 | 0x1);
708 do_assemble_insn(ctx, insn, 0x0D4);
711 do_assemble_insn(ctx, insn, 0x0D4 | 0x1);
714 do_assemble_insn(ctx, insn, 0x0DA);
717 do_assemble_insn(ctx, insn, 0x0DA | 0x1);
720 do_assemble_insn(ctx, insn, 0x0DC);
723 do_assemble_insn(ctx, insn, 0x0DC | 0x1);
726 opcode = merge_ext_into_opcode(ctx, 0x400, insn);
727 do_assemble_insn(ctx, insn, opcode);
730 opcode = merge_ext_into_opcode(ctx, 0x500, insn);
731 do_assemble_insn(ctx, insn, opcode);
734 opcode = merge_external_jmp_into_opcode(ctx, 0x700, insn);
735 do_assemble_insn(ctx, insn, opcode);
738 opcode = merge_external_jmp_into_opcode(ctx, 0x600, insn);
739 do_assemble_insn(ctx, insn, opcode);
742 do_assemble_insn(ctx, insn, 0x002);
745 do_assemble_insn(ctx, insn, 0x003);
751 do_assemble_insn(ctx, insn, 0x1E0);
754 do_assemble_insn(ctx, insn, 0x001);
757 do_assemble_insn(ctx, insn, insn->opcode);
760 asm_error(ctx, "Unknown op");
764 static void assemble_instructions(struct assembler_context *ctx)
767 struct instruction *insn;
768 struct code_output *out;
770 if (ctx->start_label) {
771 /* Generate a jump instruction at offset 0 to
772 * jump to the code start.
774 struct instruction sjmp;
778 oper.type = OPER_LABEL;
779 oper.u.label = ctx->start_label;
784 assemble_instruction(ctx, &sjmp);
785 out = list_entry(ctx->output.next, struct code_output, list);
786 out->is_start_insn = 1;
789 for_each_statement(ctx, s) {
794 assemble_instruction(ctx, insn);
797 out = xmalloc(sizeof(*out));
798 INIT_LIST_HEAD(&out->list);
799 out->type = OUT_LABEL;
800 out->labelname = s->u.label->name;
802 list_add_tail(&out->list, &ctx->output);
807 } for_each_statement_end(ctx, s);
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)
815 struct code_output *c;
819 switch (labelref->direction) {
820 case LABELREF_ABSOLUTE:
821 list_for_each_entry(c, &ctx->output, list) {
822 if (c->type != OUT_LABEL)
824 if (strcmp(c->labelname, labelref->name) != 0)
827 asm_error(ctx, "Ambiguous label reference \"%s\"",
831 address = c->address;
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)
840 if (strcmp(c->labelname, labelref->name) == 0) {
842 address = c->address;
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)
853 if (strcmp(c->labelname, labelref->name) == 0) {
855 address = c->address;
865 static void resolve_labels(struct assembler_context *ctx)
867 struct code_output *c;
870 unsigned int current_address;
872 /* Calculate the absolute addresses for each instruction. */
873 recalculate_addresses:
875 list_for_each_entry(c, &ctx->output, list) {
878 c->address = current_address;
882 c->address = current_address;
887 /* Resolve the symbolic label references. */
888 list_for_each_entry(c, &ctx->output, list) {
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.
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);
904 list_del(&c->list); /* Kill it */
905 goto recalculate_addresses;
909 for (i = 0; i < ARRAY_SIZE(c->operands); i++) {
910 if (c->operands[i].type != OUTOPER_LABELREF)
912 addr = get_labeladdress(ctx, c, c->operands[i].u.label);
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 */
927 asm_error(ctx, "Label \"%s\" does not exist",
928 c->operands[i].u.label->name);
931 static void emit_code(struct assembler_context *ctx)
936 struct code_output *c;
938 unsigned char outbuf[8];
939 unsigned int insn_count = 0;
940 struct fw_header hdr;
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+");
947 fprintf(stderr, "Could not open microcode output file \"%s\"\n", fn);
951 if (IS_VERBOSE_DEBUG)
952 fprintf(stderr, "\nCode:\n");
954 list_for_each_entry(c, &ctx->output, list) {
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");
973 if (insn_count > NUM_INSN_LIMIT)
974 asm_warn(ctx, "Generating more than %d instructions. This "
975 "will overflow the device microcode memory.",
978 list_for_each_entry(c, &ctx->output, list) {
981 if (IS_VERBOSE_DEBUG) {
982 fprintf(stderr, "%03X %03X,%03X,%03X\n",
984 c->operands[0].u.operand,
985 c->operands[1].u.operand,
986 c->operands[2].u.operand);
990 /* Instruction binary format is: xxyy yzzz 0000 oooX
991 * Big-Endian, X is the most significant part of Xxx.
993 code |= (c->opcode << 4);
995 code |= (((uint64_t)c->operands[0].u.operand & 0xF00) >> 8);
996 code |= (((uint64_t)c->operands[0].u.operand & 0x0FF) << 56);
998 code |= ((uint64_t)c->operands[1].u.operand << 44);
1000 code |= ((uint64_t)c->operands[2].u.operand << 32);
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;
1011 if (fwrite(&outbuf, ARRAY_SIZE(outbuf), 1, fd) != 1) {
1012 fprintf(stderr, "Could not write microcode outfile\n");
1024 static void assemble(void)
1026 struct assembler_context ctx;
1028 memset(&ctx, 0, sizeof(ctx));
1029 INIT_LIST_HEAD(&ctx.output);
1031 eval_directives(&ctx);
1032 assemble_instructions(&ctx);
1033 resolve_labels(&ctx);
1037 static void initialize(void)
1039 INIT_LIST_HEAD(&infile.sl);
1040 INIT_LIST_HEAD(&infile.ivals);
1042 if (IS_INSANE_DEBUG)
1046 #endif /* YYDEBUG */
1049 int main(int argc, char **argv)
1053 err = parse_args(argc, argv);
1056 err = open_input_file();
1062 assemble_initvals();
1066 /* Lazyman simply leaks all allocated memory. */