📄 tc-m68hc11.c
字号:
{ return strcmp (op1->name, op2->name);}/* Initialize the assembler. Create the opcode hash table (sorted on the names) with the M6811 opcode table (from opcode library). */voidmd_begin (){ char *prev_name = ""; struct m68hc11_opcode *opcodes; struct m68hc11_opcode_def *opc = 0; int i, j; get_default_target (); m68hc11_hash = hash_new (); /* Get a writable copy of the opcode table and sort it on the names. */ opcodes = (struct m68hc11_opcode *) xmalloc (m68hc11_num_opcodes * sizeof (struct m68hc11_opcode)); m68hc11_sorted_opcodes = opcodes; num_opcodes = 0; for (i = 0; i < m68hc11_num_opcodes; i++) { if (m68hc11_opcodes[i].arch & current_architecture) { opcodes[num_opcodes] = m68hc11_opcodes[i]; if (opcodes[num_opcodes].name[0] == 'b' && opcodes[num_opcodes].format & M6811_OP_JUMP_REL && !(opcodes[num_opcodes].format & M6811_OP_BITMASK)) { num_opcodes++; opcodes[num_opcodes] = m68hc11_opcodes[i]; } num_opcodes++; for (j = 0; alias_opcodes[j].name != 0; j++) if (strcmp (m68hc11_opcodes[i].name, alias_opcodes[j].name) == 0) { opcodes[num_opcodes] = m68hc11_opcodes[i]; opcodes[num_opcodes].name = alias_opcodes[j].alias; num_opcodes++; break; } } } qsort (opcodes, num_opcodes, sizeof (struct m68hc11_opcode), cmp_opcode); opc = (struct m68hc11_opcode_def *) xmalloc (num_opcodes * sizeof (struct m68hc11_opcode_def)); m68hc11_opcode_defs = opc--; /* Insert unique names into hash table. The M6811 instruction set has several identical opcode names that have different opcodes based on the operands. This hash table then provides a quick index to the first opcode with a particular name in the opcode table. */ for (i = 0; i < num_opcodes; i++, opcodes++) { int expect; if (strcmp (prev_name, opcodes->name)) { prev_name = (char *) opcodes->name; opc++; opc->format = 0; opc->min_operands = 100; opc->max_operands = 0; opc->nb_modes = 0; opc->opcode = opcodes; opc->used = 0; hash_insert (m68hc11_hash, opcodes->name, (char *) opc); } opc->nb_modes++; opc->format |= opcodes->format; /* See how many operands this opcode needs. */ expect = 0; if (opcodes->format & M6811_OP_MASK) expect++; if (opcodes->format & M6811_OP_BITMASK) expect++; if (opcodes->format & (M6811_OP_JUMP_REL | M6812_OP_JUMP_REL16)) expect++; if (opcodes->format & (M6812_OP_IND16_P2 | M6812_OP_IDX_P2)) expect++; if (expect < opc->min_operands) opc->min_operands = expect; if (expect > opc->max_operands) opc->max_operands = expect; } opc++; m68hc11_nb_opcode_defs = opc - m68hc11_opcode_defs; if (flag_print_opcodes) { print_opcode_list (); exit (EXIT_SUCCESS); }}voidm68hc11_init_after_args (){}/* Builtin help. *//* Return a string that represents the operand format for the instruction. When example is true, this generates an example of operand. This is used to give an example and also to generate a test. */static char *print_opcode_format (opcode, example) struct m68hc11_opcode *opcode; int example;{ static char buf[128]; int format = opcode->format; char *p; p = buf; buf[0] = 0; if (format & M6811_OP_IMM8) { if (example) sprintf (p, "#%d", rand () & 0x0FF); else strcpy (p, _("#<imm8>")); p = &p[strlen (p)]; } if (format & M6811_OP_IMM16) { if (example) sprintf (p, "#%d", rand () & 0x0FFFF); else strcpy (p, _("#<imm16>")); p = &p[strlen (p)]; } if (format & M6811_OP_IX) { if (example) sprintf (p, "%d,X", rand () & 0x0FF); else strcpy (p, _("<imm8>,X")); p = &p[strlen (p)]; } if (format & M6811_OP_IY) { if (example) sprintf (p, "%d,X", rand () & 0x0FF); else strcpy (p, _("<imm8>,X")); p = &p[strlen (p)]; } if (format & M6812_OP_IDX) { if (example) sprintf (p, "%d,X", rand () & 0x0FF); else strcpy (p, "n,r"); p = &p[strlen (p)]; } if (format & M6811_OP_DIRECT) { if (example) sprintf (p, "*Z%d", rand () & 0x0FF); else strcpy (p, _("*<abs8>")); p = &p[strlen (p)]; } if (format & M6811_OP_BITMASK) { if (buf[0]) *p++ = ' '; if (example) sprintf (p, "#$%02x", rand () & 0x0FF); else strcpy (p, _("#<mask>")); p = &p[strlen (p)]; if (format & M6811_OP_JUMP_REL) *p++ = ' '; } if (format & M6811_OP_IND16) { if (example) sprintf (p, _("symbol%d"), rand () & 0x0FF); else strcpy (p, _("<abs>")); p = &p[strlen (p)]; } if (format & (M6811_OP_JUMP_REL | M6812_OP_JUMP_REL16)) { if (example) { if (format & M6811_OP_BITMASK) { sprintf (p, ".+%d", rand () & 0x7F); } else { sprintf (p, "L%d", rand () & 0x0FF); } } else strcpy (p, _("<label>")); } return buf;}/* Prints the list of instructions with the possible operands. */static voidprint_opcode_list (){ int i; char *prev_name = ""; struct m68hc11_opcode *opcodes; int example = flag_print_opcodes == 2; if (example) printf (_("# Example of `%s' instructions\n\t.sect .text\n_start:\n"), default_cpu); opcodes = m68hc11_sorted_opcodes; /* Walk the list sorted on names (by md_begin). We only report one instruction per line, and we collect the different operand formats. */ for (i = 0; i < num_opcodes; i++, opcodes++) { char *fmt = print_opcode_format (opcodes, example); if (example) { printf ("L%d:\t", i); printf ("%s %s\n", opcodes->name, fmt); } else { if (strcmp (prev_name, opcodes->name)) { if (i > 0) printf ("\n"); printf ("%-5.5s ", opcodes->name); prev_name = (char *) opcodes->name; } if (fmt[0]) printf (" [%s]", fmt); } } printf ("\n");}/* Print the instruction format. This operation is called when some instruction is not correct. Instruction format is printed as an error message. */static voidprint_insn_format (name) char *name;{ struct m68hc11_opcode_def *opc; struct m68hc11_opcode *opcode; char buf[128]; opc = (struct m68hc11_opcode_def *) hash_find (m68hc11_hash, name); if (opc == NULL) { as_bad (_("Instruction `%s' is not recognized."), name); return; } opcode = opc->opcode; as_bad (_("Instruction formats for `%s':"), name); do { char *fmt; fmt = print_opcode_format (opcode, 0, 0); sprintf (buf, "\t%-5.5s %s", opcode->name, fmt); as_bad ("%s", buf); opcode++; } while (strcmp (opcode->name, name) == 0);}/* Analysis of 68HC11 and 68HC12 operands. *//* reg_name_search() finds the register number given its name. Returns the register number or REG_NONE on failure. */static register_idreg_name_search (name) char *name;{ if (strcasecmp (name, "x") == 0 || strcasecmp (name, "ix") == 0) return REG_X; if (strcasecmp (name, "y") == 0 || strcasecmp (name, "iy") == 0) return REG_Y; if (strcasecmp (name, "a") == 0) return REG_A; if (strcasecmp (name, "b") == 0) return REG_B; if (strcasecmp (name, "d") == 0) return REG_D; if (strcasecmp (name, "sp") == 0) return REG_SP; if (strcasecmp (name, "pc") == 0) return REG_PC; if (strcasecmp (name, "ccr") == 0) return REG_CCR; return REG_NONE;}static char *skip_whites (p) char *p;{ while (*p == ' ' || *p == '\t') p++; return p;}/* Check the string at input_line_pointer to see if it is a valid register name. */static register_idregister_name (){ register_id reg_number; char c, *p = input_line_pointer; if (!is_name_beginner (*p++)) return REG_NONE; while (is_part_of_name (*p++)) continue; c = *--p; if (c) *p++ = 0; /* Look to see if it's in the register table. */ reg_number = reg_name_search (input_line_pointer); if (reg_number != REG_NONE) { if (c) *--p = c; input_line_pointer = p; return reg_number; } if (c) *--p = c; return reg_number;}/* Parse a string of operands and return an array of expressions. Operand mode[0] mode[1] exp[0] exp[1] #n M6811_OP_IMM16 - O_* *<exp> M6811_OP_DIRECT - O_* .{+-}<exp> M6811_OP_JUMP_REL - O_* <exp> M6811_OP_IND16 - O_* ,r N,r M6812_OP_IDX M6812_OP_REG O_constant O_register n,-r M6812_PRE_DEC M6812_OP_REG O_constant O_register n,+r M6812_PRE_INC " " n,r- M6812_POST_DEC " " n,r+ M6812_POST_INC " " A,r B,r D,r M6811_OP_REG M6812_OP_REG O_register O_register [D,r] M6811_OP_IDX_2 M6812_OP_REG O_register O_register [n,r] M6811_OP_IDX_1 M6812_OP_REG O_constant O_register */static intget_operand (oper, which, opmode) operand *oper; int which; long opmode;{ char *p = input_line_pointer; int mode; register_id reg; oper->exp.X_op = O_absent; oper->reg1 = REG_NONE; oper->reg2 = REG_NONE; mode = M6811_OP_NONE; p = skip_whites (p); if (*p == 0 || *p == '\n' || *p == '\r') { input_line_pointer = p; return 0; } if (*p == '*' && (opmode & (M6811_OP_DIRECT | M6811_OP_IND16))) { mode = M6811_OP_DIRECT; p++; } else if (*p == '#') { if (!(opmode & (M6811_OP_IMM8 | M6811_OP_IMM16 | M6811_OP_BITMASK))) { as_bad (_("Immediate operand is not allowed for operand %d."), which); return -1; } mode = M6811_OP_IMM16; p++; if (strncmp (p, "%hi", 3) == 0) { p += 3; mode |= M6811_OP_HIGH_ADDR; } else if (strncmp (p, "%lo", 3) == 0) { p += 3; mode |= M6811_OP_LOW_ADDR; } } else if (*p == '.' && (p[1] == '+' || p[1] == '-')) { p++; mode = M6811_OP_JUMP_REL; } else if (*p == '[') { if (current_architecture & cpu6811) as_bad (_("Indirect indexed addressing is not valid for 68HC11.")); p++; mode = M6812_OP_IDX_2; p = skip_whites (p); } else if (*p == ',') /* Special handling of ,x and ,y. */ { p++; input_line_pointer = p; reg = register_name (); if (reg != REG_NONE) { oper->reg1 = reg; oper->exp.X_op = O_constant; oper->exp.X_add_number = 0; oper->mode = M6812_OP_IDX; return 1; } as_bad (_("Spurious `,' or bad indirect register addressing mode.")); return -1; } input_line_pointer = p; if (mode == M6811_OP_NONE || mode == M6812_OP_IDX_2) reg = register_name (); else reg = REG_NONE; if (reg != REG_NONE) { p = skip_whites (input_line_pointer); if (*p == ']' && mode == M6812_OP_IDX_2) { as_bad (_("Missing second register or offset for indexed-indirect mode.")); return -1; } oper->reg1 = reg; oper->mode = mode | M6812_OP_REG; if (*p != ',') { if (mode == M6812_OP_IDX_2) { as_bad (_("Missing second register for indexed-indirect mode.")); return -1; } return 1; } p++; input_line_pointer = p; reg = register_name (); if (reg != REG_NONE) { p = skip_whites (input_line_pointer); if (mode == M6812_OP_IDX_2) { if (*p != ']') { as_bad (_("Missing `]' to close indexed-indirect mode.")); return -1; } p++; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -