📄 tc-vax.c
字号:
else { know (operandP->vop_width == VAX_WIDTH_BYTE_JUMP); p = frag_more (10); p[0] = 2; p[1] = VAX_BRB; p[2] = 6; p[3] = VAX_JMP; p[4] = VAX_PC_RELATIVE_MODE; fix_new (frag_now, p + 5 - frag_now->fr_literal, 4, this_add_symbol, this_add_number, 1, NO_RELOC); /* * Now (eg) xOBxxx 1f * BRB 2f * 1: JMP foo * 2: */ } } } else { know (operandP->vop_width == VAX_WIDTH_CONDITIONAL_JUMP); *opcode_low_byteP ^= 1; /* Reverse branch condition. */ p = frag_more (7); p[0] = 6; p[1] = VAX_JMP; p[2] = VAX_PC_RELATIVE_MODE; fix_new (frag_now, p + 3 - frag_now->fr_literal, 4, this_add_symbol, this_add_number, 1, NO_RELOC); } } } } } else { know (operandP->vop_access != 'b'); /* So it is ordinary operand. */ know (operandP->vop_access != ' '); /* ' ' target-independent: elsewhere. */ know (operandP->vop_access == 'a' || operandP->vop_access == 'm' || operandP->vop_access == 'r' || operandP->vop_access == 'v' || operandP->vop_access == 'w'); if (operandP->vop_short == 's') { if (to_seg == SEG_ABSOLUTE) { if (this_add_number >= 64) { as_warn (_("Short literal overflow(%ld.), immediate mode assumed."), (long) this_add_number); operandP->vop_short = 'i'; operandP->vop_mode = 8; operandP->vop_reg = 0xF; } } else { as_warn (_("Forced short literal to immediate mode. now_seg=%s to_seg=%s"), segment_name (now_seg), segment_name (to_seg)); operandP->vop_short = 'i'; operandP->vop_mode = 8; operandP->vop_reg = 0xF; } } if (operandP->vop_reg >= 0 && (operandP->vop_mode < 8 || (operandP->vop_reg != 0xF && operandP->vop_mode < 10))) { /* One byte operand. */ know (operandP->vop_mode > 3); FRAG_APPEND_1_CHAR (operandP->vop_mode << 4 | operandP->vop_reg); /* All 1-bytes except S^# happen here. */ } else { /* {@}{q^}foo{(Rn)} or S^#foo */ if (operandP->vop_reg == -1 && operandP->vop_short != 's') { /* "{@}{q^}foo" */ if (to_seg == now_seg) { if (length == 0) { know (operandP->vop_short == ' '); p = frag_var (rs_machine_dependent, 10, 2, ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE), this_add_symbol, this_add_number, opcode_low_byteP); know (operandP->vop_mode == 10 + at); *p = at << 4; /* At is the only context we need to carry to other side of relax() process. Must be in the correct bit position of VAX operand spec. byte. */ } else { know (length); know (operandP->vop_short != ' '); p = frag_more (length + 1); p[0] = 0xF | ((at + "?\12\14?\16"[length]) << 4); fix_new (frag_now, p + 1 - frag_now->fr_literal, length, this_add_symbol, this_add_number, 1, NO_RELOC); } } else { /* to_seg != now_seg */ if (this_add_symbol == NULL) { know (to_seg == SEG_ABSOLUTE); /* Do @#foo: simpler relocation than foo-.(pc) anyway. */ p = frag_more (5); p[0] = VAX_ABSOLUTE_MODE; /* @#... */ md_number_to_chars (p + 1, this_add_number, 4); if (length && length != 4) { as_warn (_("Length specification ignored. Address mode 9F used")); } } else { /* {@}{q^}other_seg */ know ((length == 0 && operandP->vop_short == ' ') || (length > 0 && operandP->vop_short != ' ')); if (is_undefined) { /* * We have a SEG_UNKNOWN symbol. It might * turn out to be in the same segment as * the instruction, permitting relaxation. */ p = frag_var (rs_machine_dependent, 5, 2, ENCODE_RELAX (STATE_PC_RELATIVE, STATE_UNDF), this_add_symbol, this_add_number, 0); p[0] = at << 4; } else { if (length == 0) { know (operandP->vop_short == ' '); length = 4; /* Longest possible. */ } p = frag_more (length + 1); p[0] = 0xF | ((at + "?\12\14?\16"[length]) << 4); md_number_to_chars (p + 1, this_add_number, length); fix_new (frag_now, p + 1 - frag_now->fr_literal, length, this_add_symbol, this_add_number, 1, NO_RELOC); } } } } else { /* {@}{q^}foo(Rn) or S^# or I^# or # */ if (operandP->vop_mode < 0xA) { /* # or S^# or I^# */ if (operandP->vop_access == 'v' || operandP->vop_access == 'a') { if (operandP->vop_access == 'v') as_warn (_("Invalid operand: immediate value used as base address.")); else as_warn (_("Invalid operand: immediate value used as address.")); /* gcc 2.6.3 is known to generate these in at least one case. */ } if (length == 0 && to_seg == SEG_ABSOLUTE && (expP->X_op != O_big) && operandP->vop_mode == 8 /* No '@'. */ && this_add_number < 64) { operandP->vop_short = 's'; } if (operandP->vop_short == 's') { FRAG_APPEND_1_CHAR (this_add_number); } else { /* I^#... */ know (nbytes); p = frag_more (nbytes + 1); know (operandP->vop_reg == 0xF); p[0] = (operandP->vop_mode << 4) | 0xF; if ((to_seg == SEG_ABSOLUTE) && (expP->X_op != O_big)) { /* * If nbytes > 4, then we are scrod. We * don't know if the high order bytes * are to be 0xFF or 0x00. BSD4.2 & RMS * say use 0x00. OK --- but this * assembler needs ANOTHER rewrite to * cope properly with this bug. */ md_number_to_chars (p + 1, this_add_number, min (4, nbytes)); if (nbytes > 4) { memset (p + 5, '\0', nbytes - 4); } } else { if (expP->X_op == O_big) { /* * Problem here is to get the bytes * in the right order. We stored * our constant as LITTLENUMs, not * bytes. */ LITTLENUM_TYPE *lP; lP = floatP->low; if (nbytes & 1) { know (nbytes == 1); p[1] = *lP; } else { for (p++; nbytes; nbytes -= 2, p += 2, lP++) { md_number_to_chars (p, *lP, 2); } } } else { fix_new (frag_now, p + 1 - frag_now->fr_literal, nbytes, this_add_symbol, this_add_number, 0, NO_RELOC); } } } } else { /* {@}{q^}foo(Rn) */ know ((length == 0 && operandP->vop_short == ' ') || (length > 0 && operandP->vop_short != ' ')); if (length == 0) { if (to_seg == SEG_ABSOLUTE) { long test; test = this_add_number; if (test < 0) test = ~test; length = test & 0xffff8000 ? 4 : test & 0xffffff80 ? 2 : 1; } else { length = 4; } } p = frag_more (1 + length); know (operandP->vop_reg >= 0); p[0] = operandP->vop_reg | ((at | "?\12\14?\16"[length]) << 4); if (to_seg == SEG_ABSOLUTE) { md_number_to_chars (p + 1, this_add_number, length); } else { fix_new (frag_now, p + 1 - frag_now->fr_literal, length, this_add_symbol, this_add_number, 0, NO_RELOC); } } } } /* if(single-byte-operand) */ } } /* for(operandP) */} /* vax_assemble() *//* md_estimate_size_before_relax(), called just before relax(). Any symbol that is now undefined will not become defined. Return the correct fr_subtype in the frag and the growth beyond fr_fix. */intmd_estimate_size_before_relax (fragP, segment) fragS *fragP; segT segment;{ if (RELAX_LENGTH (fragP->fr_subtype) == STATE_UNDF) { if (S_GET_SEGMENT (fragP->fr_symbol) != segment) { /* Non-relaxable cases. */ char *p; int old_fr_fix; old_fr_fix = fragP->fr_fix; p = fragP->fr_literal + old_fr_fix; switch (RELAX_STATE (fragP->fr_subtype)) { case STATE_PC_RELATIVE: p[0] |= VAX_PC_RELATIVE_MODE; /* Preserve @ bit. */ fragP->fr_fix += 1 + 4; fix_new (fragP, old_fr_fix + 1, 4, fragP->fr_symbol, fragP->fr_offset, 1, NO_RELOC); break; case STATE_CONDITIONAL_BRANCH: *fragP->fr_opcode ^= 1; /* Reverse sense of branch. */ p[0] = 6; p[1] = VAX_JMP; p[2] = VAX_PC_RELATIVE_MODE; /* ...(PC) */ fragP->fr_fix += 1 + 1 + 1 + 4; fix_new (fragP, old_fr_fix + 3, 4, fragP->fr_symbol, fragP->fr_offset, 1, NO_RELOC); break; case STATE_COMPLEX_BRANCH: p[0] = 2; p[1] = 0; p[2] = VAX_BRB; p[3] = 6; p[4] = VAX_JMP; p[5] = VAX_PC_RELATIVE_MODE; /* ...(pc) */ fragP->fr_fix += 2 + 2 + 1 + 1 + 4; fix_new (fragP, old_fr_fix + 6, 4, fragP->fr_symbol, fragP->fr_offset, 1, NO_RELOC); break; case STATE_COMPLEX_HOP: p[0] = 2; p[1] = VAX_BRB; p[2] = 6; p[3] = VAX_JMP; p[4] = VAX_PC_RELATIVE_MODE; /* ...(pc) */ fragP->fr_fix += 1 + 2 + 1 + 1 + 4; fix_new (fragP, old_fr_fix + 5, 4, fragP->fr_symbol, fragP->fr_offset, 1, NO_RELOC); break; case STATE_ALWAYS_BRANCH: *fragP->fr_opcode += VAX_WIDEN_LONG; p[0] = VAX_PC_RELATIVE_MODE; /* ...(PC) */ fragP->fr_fix += 1 + 4; fix_new (fragP, old_fr_fix + 1, 4, fragP->fr_symbol, fragP->fr_offset, 1, NO_RELOC); break; default: abort (); } frag_wane (fragP); /* Return the growth in the fixed part of the frag. */ return fragP->fr_fix - old_fr_fix; } /* Relaxable cases. Set up the initial guess for the variable part of the frag. */ switch (RELAX_STATE (fragP->fr_subtype)) { case STATE_PC_RELATIVE: fragP->fr_subtype = ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE); break; case STATE_CONDITIONAL_BRANCH: fragP->fr_subtype = ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_BYTE); break; case STATE_COMPLEX_BRANCH: fragP->fr_subtype = ENCODE_RELAX (STATE_COMPLEX_BRANCH, STATE_WORD); break; case STATE_COMPLEX_HOP: fragP->fr_subtype = ENCODE_RELAX (STATE_COMPLEX_HOP, STATE_BYTE); break; case STATE_ALWAYS_BRANCH: fragP->fr_subtype = ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_BYTE); break; } } if (fragP->fr_subtype >= sizeof (md_relax_table) / sizeof (md_relax_table[0])) abort (); /* Return the size of the variable part of the frag. */ return md_relax_table[fragP->fr_subtype].rlx_length;}/* * md_convert_frag(); * * Called after relax() is finished. * In: Address of frag. * fr_type == rs_machine_dependent. * fr_subtype is what the address relaxed to. * * Out: Any fixSs and constants are set up. * Caller will turn frag into a ".space 0". */voidmd_convert_frag (headers, seg, fragP) object_headers *headers; segT seg; fragS *fragP;{ char *addressP; /* -> _var to change. */ char *opcodeP; /* -> opcode char(s) to change. */ short int extension = 0; /* Size of relaxed address. */ /* Added to fr_fix: incl. ALL var chars. */ symbolS *symbolP; long where; long address_of_var; /* Where, in file space, is _var of *fragP? */ long target_address = 0; /* Where, in file space, does addr point? */ know (fragP->fr_type == rs_machine_dependent); where = fragP->fr_fix; addressP = fragP->fr_literal + where; opcodeP = fragP->fr_opcode; symbolP = fragP->fr_symbol; know (symbolP); target_address = S_GET_VALUE (symbolP) + fragP->fr_offset; address_of_var = fragP->fr_address + where;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -