📄 tc-sh.c
字号:
*mode = DSP_REG_N; *reg = A_A1G_NUM; return 3; } } if (l1 == 'x' && src[2] >= '0' && src[2] <= '1' && ! IDENT_CHAR ((unsigned char) src[3])) { *mode = A_REG_N; *reg = 4 + (l1 - '0'); return 3; } if (l1 == 'y' && src[2] >= '0' && src[2] <= '1' && ! IDENT_CHAR ((unsigned char) src[3])) { *mode = A_REG_N; *reg = 6 + (l1 - '0'); return 3; } if (l1 == 's' && src[2] >= '0' && src[2] <= '3' && ! IDENT_CHAR ((unsigned char) src[3])) { int n = l1 - '0'; *mode = A_REG_N; *reg = n | ((~n & 2) << 1); return 3; } } if (l0 == 'i' && l1 && ! IDENT_CHAR ((unsigned char) src[3])) { if (l1 == 's') { *mode = A_REG_N; *reg = 8; return 2; } if (l1 == 'x') { *mode = A_REG_N; *reg = 8; return 2; } if (l1 == 'y') { *mode = A_REG_N; *reg = 9; return 2; } } if (l0 == 'x' && l1 >= '0' && l1 <= '1' && ! IDENT_CHAR ((unsigned char) src[2])) { *mode = DSP_REG_N; *reg = A_X0_NUM + l1 - '0'; return 2; } if (l0 == 'y' && l1 >= '0' && l1 <= '1' && ! IDENT_CHAR ((unsigned char) src[2])) { *mode = DSP_REG_N; *reg = A_Y0_NUM + l1 - '0'; return 2; } if (l0 == 'm' && l1 >= '0' && l1 <= '1' && ! IDENT_CHAR ((unsigned char) src[2])) { *mode = DSP_REG_N; *reg = l1 == '0' ? A_M0_NUM : A_M1_NUM; return 2; } if (l0 == 's' && l1 == 's' && tolower (src[2]) == 'r' && ! IDENT_CHAR ((unsigned char) src[3])) { *mode = A_SSR; return 3; } if (l0 == 's' && l1 == 'p' && tolower (src[2]) == 'c' && ! IDENT_CHAR ((unsigned char) src[3])) { *mode = A_SPC; return 3; } if (l0 == 's' && l1 == 'g' && tolower (src[2]) == 'r' && ! IDENT_CHAR ((unsigned char) src[3])) { *mode = A_SGR; return 3; } if (l0 == 'd' && l1 == 's' && tolower (src[2]) == 'r' && ! IDENT_CHAR ((unsigned char) src[3])) { *mode = A_DSR; return 3; } if (l0 == 'd' && l1 == 'b' && tolower (src[2]) == 'r' && ! IDENT_CHAR ((unsigned char) src[3])) { *mode = A_DBR; return 3; } if (l0 == 's' && l1 == 'r' && ! IDENT_CHAR ((unsigned char) src[2])) { *mode = A_SR; return 2; } if (l0 == 's' && l1 == 'p' && ! IDENT_CHAR ((unsigned char) src[2])) { *mode = A_REG_N; *reg = 15; return 2; } if (l0 == 'p' && l1 == 'r' && ! IDENT_CHAR ((unsigned char) src[2])) { *mode = A_PR; return 2; } if (l0 == 'p' && l1 == 'c' && ! IDENT_CHAR ((unsigned char) src[2])) { /* Don't use A_DISP_PC here - that would accept stuff like 'mova pc,r0' and use an uninitialized immediate. */ *mode = A_PC; return 2; } if (l0 == 'g' && l1 == 'b' && tolower (src[2]) == 'r' && ! IDENT_CHAR ((unsigned char) src[3])) { *mode = A_GBR; return 3; } if (l0 == 'v' && l1 == 'b' && tolower (src[2]) == 'r' && ! IDENT_CHAR ((unsigned char) src[3])) { *mode = A_VBR; return 3; } if (l0 == 'm' && l1 == 'a' && tolower (src[2]) == 'c' && ! IDENT_CHAR ((unsigned char) src[4])) { if (tolower (src[3]) == 'l') { *mode = A_MACL; return 4; } if (tolower (src[3]) == 'h') { *mode = A_MACH; return 4; } } if (l0 == 'm' && l1 == 'o' && tolower (src[2]) == 'd' && ! IDENT_CHAR ((unsigned char) src[4])) { *mode = A_MOD; return 3; } if (l0 == 'f' && l1 == 'r') { if (src[2] == '1') { if (src[3] >= '0' && src[3] <= '5' && ! IDENT_CHAR ((unsigned char) src[4])) { *mode = F_REG_N; *reg = 10 + src[3] - '0'; return 4; } } if (src[2] >= '0' && src[2] <= '9' && ! IDENT_CHAR ((unsigned char) src[3])) { *mode = F_REG_N; *reg = (src[2] - '0'); return 3; } } if (l0 == 'd' && l1 == 'r') { if (src[2] == '1') { if (src[3] >= '0' && src[3] <= '4' && ! ((src[3] - '0') & 1) && ! IDENT_CHAR ((unsigned char) src[4])) { *mode = D_REG_N; *reg = 10 + src[3] - '0'; return 4; } } if (src[2] >= '0' && src[2] <= '8' && ! ((src[2] - '0') & 1) && ! IDENT_CHAR ((unsigned char) src[3])) { *mode = D_REG_N; *reg = (src[2] - '0'); return 3; } } if (l0 == 'x' && l1 == 'd') { if (src[2] == '1') { if (src[3] >= '0' && src[3] <= '4' && ! ((src[3] - '0') & 1) && ! IDENT_CHAR ((unsigned char) src[4])) { *mode = X_REG_N; *reg = 11 + src[3] - '0'; return 4; } } if (src[2] >= '0' && src[2] <= '8' && ! ((src[2] - '0') & 1) && ! IDENT_CHAR ((unsigned char) src[3])) { *mode = X_REG_N; *reg = (src[2] - '0') + 1; return 3; } } if (l0 == 'f' && l1 == 'v') { if (src[2] == '1'&& src[3] == '2' && ! IDENT_CHAR ((unsigned char) src[4])) { *mode = V_REG_N; *reg = 12; return 4; } if ((src[2] == '0' || src[2] == '4' || src[2] == '8') && ! IDENT_CHAR ((unsigned char) src[3])) { *mode = V_REG_N; *reg = (src[2] - '0'); return 3; } } if (l0 == 'f' && l1 == 'p' && tolower (src[2]) == 'u' && tolower (src[3]) == 'l' && ! IDENT_CHAR ((unsigned char) src[4])) { *mode = FPUL_N; return 4; } if (l0 == 'f' && l1 == 'p' && tolower (src[2]) == 's' && tolower (src[3]) == 'c' && tolower (src[4]) == 'r' && ! IDENT_CHAR ((unsigned char) src[5])) { *mode = FPSCR_N; return 5; } if (l0 == 'x' && l1 == 'm' && tolower (src[2]) == 't' && tolower (src[3]) == 'r' && tolower (src[4]) == 'x' && ! IDENT_CHAR ((unsigned char) src[5])) { *mode = XMTRX_M4; return 5; } return 0;}static symbolS *dot (){ const char *fake; /* JF: '.' is pseudo symbol with value of current location in current segment. */ fake = FAKE_LABEL_NAME; return symbol_new (fake, now_seg, (valueT) frag_now_fix (), frag_now);}static char *parse_exp (s, op) char *s; sh_operand_info *op;{ char *save; char *new; save = input_line_pointer; input_line_pointer = s; expression (&op->immediate); if (op->immediate.X_op == O_absent) as_bad (_("missing operand")); new = input_line_pointer; input_line_pointer = save; return new;}/* The many forms of operand: Rn Register direct @Rn Register indirect @Rn+ Autoincrement @-Rn Autodecrement @(disp:4,Rn) @(disp:8,GBR) @(disp:8,PC) @(R0,Rn) @(R0,GBR) disp:8 disp:12 #imm8 pr, gbr, vbr, macl, mach */static char *parse_at (src, op) char *src; sh_operand_info *op;{ int len; int mode; src++; if (src[0] == '-') { /* Must be predecrement. */ src++; len = parse_reg (src, &mode, &(op->reg)); if (mode != A_REG_N) as_bad (_("illegal register after @-")); op->type = A_DEC_N; src += len; } else if (src[0] == '(') { /* Could be @(disp, rn), @(disp, gbr), @(disp, pc), @(r0, gbr) or @(r0, rn) */ src++; len = parse_reg (src, &mode, &(op->reg)); if (len && mode == A_REG_N) { src += len; if (op->reg != 0) { as_bad (_("must be @(r0,...)")); } if (src[0] == ',') src++; /* Now can be rn or gbr */ len = parse_reg (src, &mode, &(op->reg)); if (mode == A_GBR) { op->type = A_R0_GBR; } else if (mode == A_REG_N) { op->type = A_IND_R0_REG_N; } else { as_bad (_("syntax error in @(r0,...)")); } } else { /* Must be an @(disp,.. thing) */ src = parse_exp (src, op); if (src[0] == ',') src++; /* Now can be rn, gbr or pc */ len = parse_reg (src, &mode, &op->reg); if (len) { if (mode == A_REG_N) { op->type = A_DISP_REG_N; } else if (mode == A_GBR) { op->type = A_DISP_GBR; } else if (mode == A_PC) { /* Turn a plain @(4,pc) into @(.+4,pc). */ if (op->immediate.X_op == O_constant) { op->immediate.X_add_symbol = dot(); op->immediate.X_op = O_symbol; } op->type = A_DISP_PC; } else { as_bad (_("syntax error in @(disp,[Rn, gbr, pc])")); } } else { as_bad (_("syntax error in @(disp,[Rn, gbr, pc])")); } } src += len; if (src[0] != ')') as_bad (_("expecting )")); else src++; } else { src += parse_reg (src, &mode, &(op->reg)); if (mode != A_REG_N) { as_bad (_("illegal register after @")); } if (src[0] == '+') { src++; if ((src[0] == 'r' && src[1] == '8') || (src[0] == 'i' && (src[1] == 'x' || src[1] == 's'))) { src += 2; op->type = A_PMOD_N; } if ((src[0] == 'r' && src[1] == '9') || (src[0] == 'i' && src[1] == 'y')) { src += 2; op->type = A_PMODY_N; } else op->type = A_INC_N; } else { op->type = A_IND_N; } } return src;}static voidget_operand (ptr, op) char **ptr; sh_operand_info *op;{ char *src = *ptr; int mode = -1; unsigned int len; if (src[0] == '#') { src++; *ptr = parse_exp (src, op); op->type = A_IMM; return; } else if (src[0] == '@') { *ptr = parse_at (src, op); return; } len = parse_reg (src, &mode, &(op->reg)); if (len) { *ptr = src + len; op->type = mode; return; } else { /* Not a reg, the only thing left is a displacement. */ *ptr = parse_exp (src, op); op->type = A_DISP_PC; return; }}static char *get_operands (info, args, operand) sh_opcode_info *info; char *args; sh_operand_info *operand;{ char *ptr = args; if (info->arg[0]) { /* The pre-processor will eliminate whitespace in front of '@' after the first argument; we may be called multiple times from assemble_ppi, so don't insist on finding whitespace here. */ if (*ptr == ' ') ptr++; get_operand (&ptr, operand + 0); if (info->arg[1]) { if (*ptr == ',') { ptr++; } get_operand (&ptr, operand + 1); /* ??? Hack: psha/pshl have a varying operand number depending on the type of the first operand. We handle this by having the three-operand version first and reducing the number of operands parsed to two if we see that the first operand is an immediate. This works because no insn with three operands has an immediate as first operand. */ if (info->arg[2] && operand[0].type != A_IMM) { if (*ptr == ',') { ptr++; } get_operand (&ptr, operand + 2); } else { operand[2].type = 0; } } else { operand[1].type = 0; operand[2].type = 0; } } else { operand[0].type = 0; operand[1].type = 0; operand[2].type = 0; } return ptr;}/* Passed a pointer to a list of opcodes which use different addressing modes, return the opcode which matches the opcodes
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -