📄 tc-arm.c
字号:
switch (temp) { case 16: case 32: opcode_select (temp); break; default: as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp); }}static voidend_of_line (str) char * str;{ skip_whitespace (str); if (* str != '\0') inst.error = _("Garbage following instruction");}static intskip_past_comma (str) char ** str;{ char * p = * str, c; int comma = 0; while ((c = *p) == ' ' || c == ',') { p++; if (c == ',' && comma++) return FAIL; } if (c == '\0') return FAIL; *str = p; return comma ? SUCCESS : FAIL;}/* A standard register must be given at this point. SHIFT is the place to put it in inst.instruction. Restores input start point on error. Returns the reg#, or FAIL. */static intreg_required_here (str, shift) char ** str; int shift;{ static char buff [128]; /* XXX */ int reg; char * start = * str; if ((reg = arm_reg_parse (str)) != FAIL && int_register (reg)) { if (shift >= 0) inst.instruction |= reg << shift; return reg; } /* Restore the start point, we may have got a reg of the wrong class. */ *str = start; /* In the few cases where we might be able to accept something else this error can be overridden. */ sprintf (buff, _("Register expected, not '%.100s'"), start); inst.error = buff; return FAIL;}static CONST struct asm_psr *arm_psr_parse (ccp) register char ** ccp;{ char * start = * ccp; char c; char * p; CONST struct asm_psr * psr; p = start; /* Skip to the end of the next word in the input stream. */ do { c = *p++; } while (isalpha (c) || c == '_'); /* Terminate the word. */ *--p = 0; /* CPSR's and SPSR's can now be lowercase. This is just a convenience feature for ease of use and backwards compatibility. */ if (!strncmp (start, "cpsr", 4)) strncpy (start, "CPSR", 4); else if (!strncmp (start, "spsr", 4)) strncpy (start, "SPSR", 4); /* Now locate the word in the psr hash table. */ psr = (CONST struct asm_psr *) hash_find (arm_psr_hsh, start); /* Restore the input stream. */ *p = c; /* If we found a valid match, advance the stream pointer past the end of the word. */ *ccp = p; return psr;}/* Parse the input looking for a PSR flag. */static intpsr_required_here (str) char ** str;{ char * start = * str; CONST struct asm_psr * psr; psr = arm_psr_parse (str); if (psr) { /* If this is the SPSR that is being modified, set the R bit. */ if (! psr->cpsr) inst.instruction |= SPSR_BIT; /* Set the psr flags in the MSR instruction. */ inst.instruction |= psr->field << PSR_SHIFT; return SUCCESS; } /* In the few cases where we might be able to accept something else this error can be overridden. */ inst.error = _("flag for {c}psr instruction expected"); /* Restore the start point. */ *str = start; return FAIL;}static intco_proc_number (str) char ** str;{ int processor, pchar; skip_whitespace (* str); /* The data sheet seems to imply that just a number on its own is valid here, but the RISC iX assembler seems to accept a prefix 'p'. We will accept either. */ if (**str == 'p' || **str == 'P') (*str)++; pchar = *(*str)++; if (pchar >= '0' && pchar <= '9') { processor = pchar - '0'; if (**str >= '0' && **str <= '9') { processor = processor * 10 + *(*str)++ - '0'; if (processor > 15) { inst.error = _("Illegal co-processor number"); return FAIL; } } } else { inst.error = _("Bad or missing co-processor number"); return FAIL; } inst.instruction |= processor << 8; return SUCCESS;}static intcp_opc_expr (str, where, length) char ** str; int where; int length;{ expressionS expr; skip_whitespace (* str); memset (&expr, '\0', sizeof (expr)); if (my_get_expression (&expr, str)) return FAIL; if (expr.X_op != O_constant) { inst.error = _("bad or missing expression"); return FAIL; } if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number) { inst.error = _("immediate co-processor expression too large"); return FAIL; } inst.instruction |= expr.X_add_number << where; return SUCCESS;}static intcp_reg_required_here (str, where) char ** str; int where;{ int reg; char * start = *str; if ((reg = arm_reg_parse (str)) != FAIL && cp_register (reg)) { reg &= 15; inst.instruction |= reg << where; return reg; } /* In the few cases where we might be able to accept something else this error can be overridden. */ inst.error = _("Co-processor register expected"); /* Restore the start point. */ *str = start; return FAIL;}static intfp_reg_required_here (str, where) char ** str; int where;{ int reg; char * start = * str; if ((reg = arm_reg_parse (str)) != FAIL && fp_register (reg)) { reg &= 7; inst.instruction |= reg << where; return reg; } /* In the few cases where we might be able to accept something else this error can be overridden. */ inst.error = _("Floating point register expected"); /* Restore the start point. */ *str = start; return FAIL;}static intcp_address_offset (str) char ** str;{ int offset; skip_whitespace (* str); if (! is_immediate_prefix (**str)) { inst.error = _("immediate expression expected"); return FAIL; } (*str)++; if (my_get_expression (& inst.reloc.exp, str)) return FAIL; if (inst.reloc.exp.X_op == O_constant) { offset = inst.reloc.exp.X_add_number; if (offset & 3) { inst.error = _("co-processor address must be word aligned"); return FAIL; } if (offset > 1023 || offset < -1023) { inst.error = _("offset too large"); return FAIL; } if (offset >= 0) inst.instruction |= INDEX_UP; else offset = -offset; inst.instruction |= offset >> 2; } else inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM; return SUCCESS;}static intcp_address_required_here (str) char ** str;{ char * p = * str; int pre_inc = 0; int write_back = 0; if (*p == '[') { int reg; p++; skip_whitespace (p); if ((reg = reg_required_here (& p, 16)) == FAIL) return FAIL; skip_whitespace (p); if (*p == ']') { p++; if (skip_past_comma (& p) == SUCCESS) { /* [Rn], #expr */ write_back = WRITE_BACK; if (reg == REG_PC) { inst.error = _("pc may not be used in post-increment"); return FAIL; } if (cp_address_offset (& p) == FAIL) return FAIL; } else pre_inc = PRE_INDEX | INDEX_UP; } else { /* '['Rn, #expr']'[!] */ if (skip_past_comma (& p) == FAIL) { inst.error = _("pre-indexed expression expected"); return FAIL; } pre_inc = PRE_INDEX; if (cp_address_offset (& p) == FAIL) return FAIL; skip_whitespace (p); if (*p++ != ']') { inst.error = _("missing ]"); return FAIL; } skip_whitespace (p); if (*p == '!') { if (reg == REG_PC) { inst.error = _("pc may not be used with write-back"); return FAIL; } p++; write_back = WRITE_BACK; } } } else { if (my_get_expression (&inst.reloc.exp, &p)) return FAIL; inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM; inst.reloc.exp.X_add_number -= 8; /* PC rel adjust. */ inst.reloc.pc_rel = 1; inst.instruction |= (REG_PC << 16); pre_inc = PRE_INDEX; } inst.instruction |= write_back | pre_inc; *str = p; return SUCCESS;}static voiddo_nop (str, flags) char * str; unsigned long flags;{ /* Do nothing really. */ inst.instruction |= flags; /* This is pointless. */ end_of_line (str); return;}static voiddo_mrs (str, flags) char *str; unsigned long flags;{ int skip = 0; /* Only one syntax. */ skip_whitespace (str); if (reg_required_here (&str, 12) == FAIL) { inst.error = BAD_ARGS; return; } if (skip_past_comma (&str) == FAIL) { inst.error = _("comma expected after register name"); return; } skip_whitespace (str); if ( strcmp (s
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -