📄 vax.c
字号:
else { /* b<cond> */ *opcode_low_byteP ^= 1; /* To reverse the condition in a VAX branch, complement the lowest order bit. */ p = frag_more (7); p[0] = 6; p[1] = VAX_JMP; p[2] = VAX_ABSOLUTE_MODE; /* @#... */ md_number_to_chars (p + 3, this_add_number, 4); /* * Now (eg) BLEQ 1f * JMP @#foo * 1: */ } } } else { /* to_seg != now_seg && to_seg != SEG_UNKNOWN && to_Seg != SEG_ABSOLUTE */ if (nbytes > 0) { /* Pc-relative. Conventional relocation. */ know (!(opcode_as_number & VIT_OPCODE_SYNTHETIC)); p = frag_more (nbytes); fix_new (frag_now, p - frag_now->fr_literal, nbytes, &abs_symbol, 0, this_add_number, 1); } else { know (opcode_as_number & VIT_OPCODE_SYNTHETIC); if (opcode_as_number & VIT_OPCODE_SPECIAL) { if (operandP->vop_width == VAX_WIDTH_UNCONDITIONAL_JUMP) { /* br or jsb */ know (opcode_as_chars[1] == 0); *opcode_low_byteP = opcode_as_chars[0] + VAX_WIDEN_LONG; p = frag_more (5); p[0] = VAX_PC_RELATIVE_MODE; fix_new (frag_now, p + 1 - frag_now->fr_literal, 4, this_add_symbol, 0, this_add_number, 1); /* Now eg JMP foo or JSB foo. */ } else { if (operandP->vop_width == VAX_WIDTH_WORD_JUMP) { p = frag_more (10); p[0] = 0; p[1] = 2; p[2] = VAX_BRB; p[3] = 6; p[4] = VAX_JMP; p[5] = VAX_PC_RELATIVE_MODE; fix_new (frag_now, p + 6 - frag_now->fr_literal, 4, this_add_symbol, 0, this_add_number, 1); /* * Now (eg) ACBx 1f * BRB 2f * 1: JMP foo * 2: */ } 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, 0, this_add_number, 1); /* * 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, 0, this_add_number, 1); } } } } } 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 < 0 || this_add_number >= 64) { as_warn ("Short literal overflow(%d.), immediate mode assumed.", 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", seg_name[(int) now_seg], seg_name[(int) 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); /* JF is this array stuff really going to work? */ p[0] = 0xF | ((at + "?\12\14?\16"[length]) << 4); fix_new (frag_now, p + 1 - frag_now->fr_literal, length, this_add_symbol, 0, this_add_number, 1); } } 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, 0, this_add_number, 1); } } } } else { /* {@}{q^}foo(Rn) or S^# or I^# or # */ if (operandP->vop_mode < 0xA) { /* # or S^# or I^# */ /* know( (length == 0 && operandP->vop_short == ' ') \ || (length > 0 && operandP->vop_short != ' ')); */ if (length == 0 && to_seg == SEG_ABSOLUTE && operandP->vop_mode == 8 /* No '@'. */ && this_add_number < 64 && this_add_number >= 0) { 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) {/* * 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) { bzero (p + 5, nbytes - 4); } } else { if (to_seg == SEG_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, 0, this_add_number, 0); } } } } else { /* {@}{q^}foo(Rn) */ know ((length == 0 && operandP->vop_short == ' ') \ ||(length > 0 && operandP->vop_short != ' ')); if (length == 0) { if (to_seg == SEG_ABSOLUTE) { register long int 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, 0, this_add_number, 0); } } } } /* if(single-byte-operand) */ } } /* for(operandP) */ } /* if(!need_pass_2&&!goofed) */} /* 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. * Return the initial "guess for fr_var" to caller. * The guess for fr_var is ACTUALLY the growth beyond fr_fix. * Whatever we do to grow fr_fix or fr_var contributes to our returned value. * Although it may not be explicit in the frag, pretend fr_var starts with a * 0 value. */intmd_estimate_size_before_relax (fragP, segment_type) register fragS *fragP; register int segment_type; /* N_DATA or N_TEXT. */{ register char *p; register int old_fr_fix; old_fr_fix = fragP->fr_fix; switch (fragP->fr_subtype) { case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_UNDF): if ((fragP->fr_symbol->sy_type & N_TYPE) == segment_type) { /* A relaxable case. */ fragP->fr_subtype = ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE); } else { p = fragP->fr_literal + old_fr_fix; p[0] |= VAX_PC_RELATIVE_MODE; /* Preserve @ bit. */ fragP->fr_fix += 1 + 4; fix_new (fragP, old_fr_fix + 1, 4, fragP->fr_symbol, 0, fragP->fr_offset, 1); frag_wane (fragP); } break; case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_UNDF): if ((fragP->fr_symbol->sy_type & N_TYPE) == segment_type) { fragP->fr_subtype = ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_BYTE); } else { p = fragP->fr_literal + old_fr_fix; *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, 0, fragP->fr_offset, 1); frag_wane (fragP); } break; case ENCODE_RELAX (STATE_COMPLEX_BRANCH, STATE_UNDF): if ((fragP->fr_symbol->sy_type & N_TYPE) == segment_type) { fragP->fr_subtype = ENCODE_RELAX (STATE_COMPLEX_BRANCH, STATE_WORD); } else { p = fragP->fr_literal + old_fr_fix; 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, 0, fragP->fr_offset, 1); frag_wane (fragP); } break; case ENCODE_RELAX (STATE_COMPLEX_HOP, STATE_UNDF): if ((fragP->fr_symbol->sy_type & N_TYPE) == segment_type) { fragP->fr_subtype = ENCODE_RELAX (STATE_COMPLEX_HOP, STATE_BYTE); } else { p = fragP->fr_literal + old_fr_fix; 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, 0, fragP->fr_offset, 1); frag_wane (fragP); } break; case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_UNDF): if ((fragP->fr_symbol->sy_type & N_TYPE) == segment_type) { fragP->fr_subtype = ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_BYTE); } else { p = fragP->fr_literal + old_fr_fix; *fragP->fr_opcode += VAX_WIDEN_LONG; p[0] = VAX_PC_RELATIVE_MODE; /* ...(PC) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -