📄 tc-a29k.c
字号:
and do a "continue". If an operand fails to match, we "break". */ if (insn->args[0] != '\0') { /* Prime the pump. */ s = parse_operand (s, operand, insn->args[0] == 'I'); } for (args = insn->args;; ++args) { switch (*args) { case '\0': /* end of args */ if (*s == '\0') { /* We are truly done. */ the_insn.opcode = opcode; return; } as_bad (_("Too many operands: %s"), s); break; case ',': /* Must match a comma */ if (*s++ == ',') { /* Parse next operand. */ s = parse_operand (s, operand, args[1] == 'I'); continue; } break; case 'v': /* Trap numbers (immediate field) */ if (operand->X_op == O_constant) { if (operand->X_add_number < 256) { opcode |= (operand->X_add_number << 16); continue; } else { as_bad (_("Immediate value of %ld is too large"), (long) operand->X_add_number); continue; } } the_insn.reloc = RELOC_8; the_insn.reloc_offset = 1; /* BIG-ENDIAN Byte 1 of insn */ the_insn.exp = *operand; continue; case 'b': /* A general register or 8-bit immediate */ case 'i': /* We treat the two cases identically since we mashed them together in the opcode table. */ if (operand->X_op == O_register) goto general_reg; /* Make sure the 'i' case really exists. */ if ((insn->opcode | IMMEDIATE_BIT) != (insn + 1)->opcode) break; opcode |= IMMEDIATE_BIT; if (operand->X_op == O_constant) { if (operand->X_add_number < 256) { opcode |= operand->X_add_number; continue; } else { as_bad (_("Immediate value of %ld is too large"), (long) operand->X_add_number); continue; } } the_insn.reloc = RELOC_8; the_insn.reloc_offset = 3; /* BIG-ENDIAN Byte 3 of insn */ the_insn.exp = *operand; continue; case 'a': /* next operand must be a register */ case 'c': general_reg: /* lrNNN or grNNN or %%expr or a user-def register name */ if (operand->X_op != O_register) break; /* Only registers */ know (operand->X_add_symbol == 0); know (operand->X_op_symbol == 0); reg = operand->X_add_number; if (reg >= SREG) break; /* No special registers */ /* Got the register, now figure out where it goes in the opcode. */ switch (*args) { case 'a': opcode |= reg << 8; continue; case 'b': case 'i': opcode |= reg; continue; case 'c': opcode |= reg << 16; continue; } as_fatal (_("failed sanity check.")); break; case 'x': /* 16 bit constant, zero-extended */ case 'X': /* 16 bit constant, one-extended */ if (operand->X_op == O_constant) { opcode |= (operand->X_add_number & 0xFF) << 0 | ((operand->X_add_number & 0xFF00) << 8); continue; } the_insn.reloc = RELOC_CONST; the_insn.exp = *operand; continue; case 'h': if (operand->X_op == O_constant) { opcode |= (operand->X_add_number & 0x00FF0000) >> 16 | (((unsigned long) operand->X_add_number /* avoid sign ext */ & 0xFF000000) >> 8); continue; } the_insn.reloc = RELOC_CONSTH; the_insn.exp = *operand; continue; case 'P': /* PC-relative jump address */ case 'A': /* Absolute jump address */ /* These two are treated together since we folded the opcode table entries together. */ if (operand->X_op == O_constant) { /* Make sure the 'A' case really exists. */ if ((insn->opcode | ABSOLUTE_BIT) != (insn + 1)->opcode) break; { bfd_vma v, mask; mask = 0x1ffff; v = operand->X_add_number & ~ mask; if (v) as_bad ("call/jmp target out of range"); } opcode |= ABSOLUTE_BIT | (operand->X_add_number & 0x0003FC00) << 6 | ((operand->X_add_number & 0x000003FC) >> 2); continue; } the_insn.reloc = RELOC_JUMPTARG; the_insn.exp = *operand; the_insn.pcrel = 1; /* Assume PC-relative jump */ /* FIXME-SOON, Do we figure out whether abs later, after know sym val? */ continue; case 'e': /* Coprocessor enable bit for LOAD/STORE insn */ if (operand->X_op == O_constant) { if (operand->X_add_number == 0) continue; if (operand->X_add_number == 1) { opcode |= CE_BIT; continue; } } break; case 'n': /* Control bits for LOAD/STORE instructions */ if (operand->X_op == O_constant && operand->X_add_number < 128) { opcode |= (operand->X_add_number << 16); continue; } break; case 's': /* Special register number */ if (operand->X_op != O_register) break; /* Only registers */ if (operand->X_add_number < SREG) break; /* Not a special register */ opcode |= (operand->X_add_number & 0xFF) << 8; continue; case 'u': /* UI bit of CONVERT */ if (operand->X_op == O_constant) { if (operand->X_add_number == 0) continue; if (operand->X_add_number == 1) { opcode |= UI_BIT; continue; } } break; case 'r': /* RND bits of CONVERT */ if (operand->X_op == O_constant && operand->X_add_number < 8) { opcode |= operand->X_add_number << 4; continue; } break; case 'I': /* ID bits of INV and IRETINV. */ /* This operand is optional. */ if (operand->X_op == O_absent) continue; else if (operand->X_op == O_constant && operand->X_add_number < 4) { opcode |= operand->X_add_number << 16; continue; } break; case 'd': /* FD bits of CONVERT */ if (operand->X_op == O_constant && operand->X_add_number < 4) { opcode |= operand->X_add_number << 2; continue; } break; case 'f': /* FS bits of CONVERT */ if (operand->X_op == O_constant && operand->X_add_number < 4) { opcode |= operand->X_add_number << 0; continue; } break; case 'C': if (operand->X_op == O_constant && operand->X_add_number < 4) { opcode |= operand->X_add_number << 16; continue; } break; case 'F': if (operand->X_op == O_constant && operand->X_add_number < 16) { opcode |= operand->X_add_number << 18; continue; } break; default: BAD_CASE (*args); } /* Types or values of args don't match. */ as_bad ("Invalid operands"); return; }}/* This is identical to the md_atof in m68k.c. I think this is right, but I'm not sure. Turn a string in input_line_pointer into a floating point constant of type TYPE, and store the appropriate bytes in *LITP. The number of LITTLENUMS emitted is stored in *SIZEP. An error message is returned, or NULL on OK. *//* Equal to MAX_PRECISION in atof-ieee.c */#define MAX_LITTLENUMS 6char *md_atof (type, litP, sizeP) char type; char *litP; int *sizeP;{ int prec; LITTLENUM_TYPE words[MAX_LITTLENUMS]; LITTLENUM_TYPE *wordP; char *t; switch (type) { case 'f': case 'F': case 's': case 'S': prec = 2; break; case 'd': case 'D': case 'r': case 'R': prec = 4; break; case 'x': case 'X': prec = 6; break; case 'p': case 'P': prec = 6; break; default: *sizeP = 0; return "Bad call to MD_ATOF()"; } t = atof_ieee (input_line_pointer, type, words); if (t) input_line_pointer = t; *sizeP = prec * sizeof (LITTLENUM_TYPE); for (wordP = words; prec--;) { md_number_to_chars (litP, (valueT) (*wordP++), sizeof (LITTLENUM_TYPE)); litP += sizeof (LITTLENUM_TYPE); } return 0;}/* * Write out big-endian. */voidmd_number_to_chars (buf, val, n) char *buf; valueT val; int n;{ number_to_chars_bigendian (buf, val, n);}voidmd_apply_fix (fixP, val) fixS *fixP; long val;{ char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; fixP->fx_addnumber = val; /* Remember value for emit_reloc */ know (fixP->fx_size == 4); know (fixP->fx_r_type < NO_RELOC); /* This is a hack. There should be a better way to handle this. */ if (fixP->fx_r_type == RELOC_WDISP30 && fixP->fx_addsy) { val += fixP->fx_where + fixP->fx_frag->fr_address; } switch (fixP->fx_r_type) { case RELOC_32: buf[0] = val >> 24; buf[1] = val >> 16; buf[2] = val >> 8; buf[3] = val; break; case RELOC_8: buf[0] = val; break; case RELOC_WDISP30: val = (val >>= 2) + 1; buf[0] |= (val >> 24) & 0x3f; buf[1] = (val >> 16); buf[2] = val >> 8; buf[3] = val; break; case RELOC_HI22: buf[1] |= (val >> 26) & 0x3f; buf[2] = val >> 18; buf[3] = val >> 10; break; case RELOC_LO10: buf[2] |= (val >> 8) & 0x03; buf[3] = val; break; case RELOC_BASE13: buf[2] |= (val >> 8) & 0x1f; buf[3] = val; break; case RELOC_WDISP22: val = (val >>= 2) + 1; /* FALLTHROUGH */ case RELOC_BASE22: buf[1] |= (val >> 16) & 0x3f; buf[2] = val >> 8; buf[3] = val; break; case RELOC_JUMPTARG: /* 00XX00XX pattern in a word */ if (!fixP->fx_done) { /* The linker tries to support both AMD and old GNU style R_IREL relocs. That means that if the addend is exactly the negative of the address within the section, the linker will not handle it correctly. */ if (fixP->fx_pcrel && val != 0 && val == - (fixP->fx_frag->fr_address + fixP->fx_where)) as_bad_where (fixP->fx_file, fixP->fx_line, "the linker will not handle this relocation correctly");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -