📄 tc-h8500.c
字号:
/* tc-h8500.c -- Assemble code for the Hitachi H8/500 Copyright 1993, 1994, 1995, 1998, 2000, 2001 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* Written By Steve Chamberlain <sac@cygnus.com>. */#include <stdio.h>#include "as.h"#include "bfd.h"#include "subsegs.h"#define DEFINE_TABLE#define ASSEMBLER_TABLE#include "opcodes/h8500-opc.h"#include <ctype.h>const char comment_chars[] = "!";const char line_separator_chars[] = ";";const char line_comment_chars[] = "!#";/* This table describes all the machine specific pseudo-ops the assembler has to support. The fields are: pseudo-op name without dot function to call to execute this pseudo-op Integer arg to pass to the function */void cons ();const pseudo_typeS md_pseudo_table[] ={ {"int", cons, 2}, {"data.b", cons, 1}, {"data.w", cons, 2}, {"data.l", cons, 4}, {"form", listing_psize, 0}, {"heading", listing_title, 0}, {"import", s_ignore, 0}, {"page", listing_eject, 0}, {"program", s_ignore, 0}, {0, 0, 0}};const int md_reloc_size;const char EXP_CHARS[] = "eE";/* Chars that mean this number is a floating point constant *//* As in 0f12.456 *//* or 0d1.2345e12 */const char FLT_CHARS[] = "rRsSfFdDxXpP";#define C(a,b) ENCODE_RELAX(a,b)#define ENCODE_RELAX(what,length) (((what) << 2) + (length))#define GET_WHAT(x) ((x>>2))#define BYTE_DISP 1#define WORD_DISP 2#define UNDEF_BYTE_DISP 0#define UNDEF_WORD_DISP 3#define BRANCH 1#define SCB_F 2#define SCB_TST 3#define END 4#define BYTE_F 127#define BYTE_B -126#define WORD_F 32767#define WORD_B 32768relax_typeS md_relax_table[C (END, 0)] = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, /* BRANCH */ { 0, 0, 0, 0 }, { BYTE_F, BYTE_B, 2, C (BRANCH, WORD_DISP) }, { WORD_F, WORD_B, 3, 0 }, { 0, 0, 3, 0 }, /* SCB_F */ { 0, 0, 0, 0 }, { BYTE_F, BYTE_B, 3, C (SCB_F, WORD_DISP) }, { WORD_F, WORD_B, 8, 0 }, { 0, 0, 8, 0 }, /* SCB_TST */ { 0, 0, 0, 0 }, { BYTE_F, BYTE_B, 3, C (SCB_TST, WORD_DISP) }, { WORD_F, WORD_B, 10, 0 }, { 0, 0, 10, 0 }};static struct hash_control *opcode_hash_control; /* Opcode mnemonics *//* This function is called once, at assembler startup time. This should set up all the tables, etc. that the MD part of the assembler needs */voidmd_begin (){ h8500_opcode_info *opcode; char prev_buffer[100]; int idx = 0; opcode_hash_control = hash_new (); prev_buffer[0] = 0; /* Insert unique names into hash table */ for (opcode = h8500_table; opcode->name; opcode++) { if (idx != opcode->idx) { hash_insert (opcode_hash_control, opcode->name, (char *) opcode); idx++; } }}static int rn; /* register number used by RN */static int rs; /* register number used by RS */static int rd; /* register number used by RD */static int crb; /* byte size cr */static int crw; /* word sized cr */static int cr; /* unknown size cr */static expressionS displacement;/* displacement expression */static int displacement_size; /* and size if given */static int immediate_inpage;static expressionS immediate; /* immediate expression */static int immediate_size; /* and size if given */static expressionS absolute; /* absolute expression */static int absolute_size; /* and size if given */typedef struct{ int type; int reg; expressionS exp; int page;}h8500_operand_info;/* Try to parse a reg name. Return the number of chars consumed. */static intparse_reg (src, mode, reg) char *src; int *mode; int *reg;{ char *end; int len; /* Cribbed from get_symbol_end(). */ if (!is_name_beginner (*src) || *src == '\001') return 0; end = src + 1; while (is_part_of_name (*end) || *end == '\001') end++; len = end - src; if (len == 2 && src[0] == 'r') { if (src[1] >= '0' && src[1] <= '7') { *mode = RN; *reg = (src[1] - '0'); return len; } } if (len == 2 && src[0] == 's' && src[1] == 'p') { *mode = RN; *reg = 7; return len; } if (len == 3 && src[0] == 'c' && src[1] == 'c' && src[2] == 'r') { *mode = CRB; *reg = 1; return len; } if (len == 2 && src[0] == 's' && src[1] == 'r') { *mode = CRW; *reg = 0; return len; } if (len == 2 && src[0] == 'b' && src[1] == 'r') { *mode = CRB; *reg = 3; return len; } if (len == 2 && src[0] == 'e' && src[1] == 'p') { *mode = CRB; *reg = 4; return len; } if (len == 2 && src[0] == 'd' && src[1] == 'p') { *mode = CRB; *reg = 5; return len; } if (len == 2 && src[0] == 't' && src[1] == 'p') { *mode = CRB; *reg = 7; return len; } if (len == 2 && src[0] == 'f' && src[1] == 'p') { *mode = RN; *reg = 6; return len; } return 0;}static char *parse_exp (s, op, page) char *s; expressionS *op; int *page;{ char *save; char *new; save = input_line_pointer; *page = 0; if (s[0] == '%') { if (s[1] == 'p' && s[2] == 'a' && s[3] == 'g' && s[4] == 'e') { s += 5; *page = 'p'; } if (s[1] == 'h' && s[2] == 'i' && s[3] == '1' && s[4] == '6') { s += 5; *page = 'h'; } else if (s[1] == 'o' && s[2] == 'f' && s[3] == 'f') { s += 4; *page = 'o'; } } input_line_pointer = s; expression (op); if (op->X_op == O_absent) as_bad (_("missing operand")); new = input_line_pointer; input_line_pointer = save; return new;}typedef enum { exp_signed, exp_unsigned, exp_sandu } sign_type;static char *skip_colonthing (sign, ptr, exp, def, size8, size16, size24) sign_type sign; char *ptr; h8500_operand_info *exp; int def; int size8; int size16; int size24;{ ptr = parse_exp (ptr, &exp->exp, &exp->page); if (*ptr == ':') { ptr++; if (*ptr == '8') { ptr++; exp->type = size8; } else if (ptr[0] == '1' & ptr[1] == '6') { ptr += 2; exp->type = size16; } else if (ptr[0] == '2' & ptr[1] == '4') { if (!size24) { as_bad (_(":24 not valid for this opcode")); } ptr += 2; exp->type = size24; } else { as_bad (_("expect :8,:16 or :24")); exp->type = size16; } } else { if (exp->page == 'p') { exp->type = IMM8; } else if (exp->page == 'h') { exp->type = IMM16; } else { /* Let's work out the size from the context */ int n = exp->exp.X_add_number; if (size8 && exp->exp.X_op == O_constant && ((sign == exp_signed && (n >= -128 && n <= 127)) || (sign == exp_unsigned && (n >= 0 && (n <= 255))) || (sign == exp_sandu && (n >= -128 && (n <= 255))))) { exp->type = size8; } else { exp->type = def; } } } return ptr;}static intparse_reglist (src, op) char *src; h8500_operand_info *op;{ int mode; int rn; int mask = 0; int rm; int idx = 1; /* skip ( */ while (src[idx] && src[idx] != ')') { int done = parse_reg (src + idx, &mode, &rn); if (done) { idx += done; mask |= 1 << rn; } else { as_bad (_("syntax error in reg list")); return 0; } if (src[idx] == '-') { idx++; done = parse_reg (src + idx, &mode, &rm); if (done) { idx += done; while (rn <= rm) { mask |= 1 << rn; rn++; } } else { as_bad (_("missing final register in range")); } } if (src[idx] == ',') idx++; } idx++; op->exp.X_add_symbol = 0; op->exp.X_op_symbol = 0; op->exp.X_add_number = mask; op->exp.X_op = O_constant; op->exp.X_unsigned = 1; op->type = IMM8; return idx;}/* The many forms of operand: Rn Register direct @Rn Register indirect @(disp[:size], Rn) Register indirect with displacement @Rn+ @-Rn @aa[:size] absolute #xx[:size] immediate data */static voidget_operand (ptr, op, ispage) char **ptr; h8500_operand_info *op; char ispage;{ char *src = *ptr; int mode; unsigned int num; unsigned int len; op->page = 0; if (src[0] == '(' && src[1] == 'r') { /* This is a register list */ *ptr = src + parse_reglist (src, op); return; } len = parse_reg (src, &op->type, &op->reg); if (len) { *ptr = src + len; return; } if (*src == '@') { src++; if (*src == '-') { src++; len = parse_reg (src, &mode, &num); if (len == 0) { /* Oops, not a reg after all, must be ordinary exp */ src--; /* must be a symbol */ *ptr = skip_colonthing (exp_unsigned, src, op, ABS16, ABS8, ABS16, ABS24); return; } op->type = RNDEC; op->reg = num; *ptr = src + len; return; } if (*src == '(') { /* Disp */ src++; src = skip_colonthing (exp_signed, src, op, RNIND_D16, RNIND_D8, RNIND_D16, 0); if (*src != ',') { as_bad (_("expected @(exp, Rn)")); return; } src++; len = parse_reg (src, &mode, &op->reg); if (len == 0 || mode != RN) { as_bad (_("expected @(exp, Rn)")); return; } src += len; if (*src != ')') { as_bad (_("expected @(exp, Rn)")); return; } *ptr = src + 1; return; } len = parse_reg (src, &mode, &num); if (len) { src += len; if (*src == '+') { src++; if (mode != RN) { as_bad (_("@Rn+ needs word register")); return; } op->type = RNINC; op->reg = num; *ptr = src; return; } if (mode != RN) { as_bad (_("@Rn needs word register")); return; } op->type = RNIND; op->reg = num; *ptr = src;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -