📄 tc-vax.c
字号:
* modified frag type and then coding up a frag for this * case will be easy. SEG_OP was invented for the * .words after a CASE opcode, and was never intended for * instruction operands. */ need_pass_2 = 1; as_warn (_("Can't relocate expression")); break; case O_big: /* Preserve the bits. */ if (expP->X_add_number > 0) { bignum_copy (generic_bignum, expP->X_add_number, floatP->low, SIZE_OF_LARGE_NUMBER); } else { know (expP->X_add_number < 0); flonum_copy (&generic_floating_point_number, floatP); if (strchr ("s i", operandP->vop_short)) { /* Could possibly become S^# */ flonum_gen2vax (-expP->X_add_number, floatP, literal_float); switch (-expP->X_add_number) { case 'f': can_be_short = (literal_float[0] & 0xFC0F) == 0x4000 && literal_float[1] == 0; break; case 'd': can_be_short = (literal_float[0] & 0xFC0F) == 0x4000 && literal_float[1] == 0 && literal_float[2] == 0 && literal_float[3] == 0; break; case 'g': can_be_short = (literal_float[0] & 0xFF81) == 0x4000 && literal_float[1] == 0 && literal_float[2] == 0 && literal_float[3] == 0; break; case 'h': can_be_short = ((literal_float[0] & 0xFFF8) == 0x4000 && (literal_float[1] & 0xE000) == 0 && literal_float[2] == 0 && literal_float[3] == 0 && literal_float[4] == 0 && literal_float[5] == 0 && literal_float[6] == 0 && literal_float[7] == 0); break; default: BAD_CASE (-expP->X_add_number); break; } /* switch (float type) */ } /* if (could want to become S^#...) */ } /* bignum or flonum ? */ if (operandP->vop_short == 's' || operandP->vop_short == 'i' || (operandP->vop_short == ' ' && operandP->vop_reg == 0xF && (operandP->vop_mode & 0xE) == 0x8)) { /* Saw a '#'. */ if (operandP->vop_short == ' ') { /* We must chose S^ or I^. */ if (expP->X_add_number > 0) { /* Bignum: Short literal impossible. */ operandP->vop_short = 'i'; operandP->vop_mode = 8; operandP->vop_reg = 0xF; /* VAX PC. */ } else { /* Flonum: Try to do it. */ if (can_be_short) { operandP->vop_short = 's'; operandP->vop_mode = 0; operandP->vop_ndx = -1; operandP->vop_reg = -1; expP->X_op = O_constant; } else { operandP->vop_short = 'i'; operandP->vop_mode = 8; operandP->vop_reg = 0xF; /* VAX PC */ } } /* bignum or flonum ? */ } /* if #, but no S^ or I^ seen. */ /* No more ' ' case: either 's' or 'i'. */ if (operandP->vop_short == 's') { /* Wants to be a short literal. */ if (expP->X_add_number > 0) { as_warn (_("Bignum not permitted in short literal. Immediate mode assumed.")); operandP->vop_short = 'i'; operandP->vop_mode = 8; operandP->vop_reg = 0xF; /* VAX PC. */ } else { if (!can_be_short) { as_warn (_("Can't do flonum short literal: immediate mode used.")); operandP->vop_short = 'i'; operandP->vop_mode = 8; operandP->vop_reg = 0xF; /* VAX PC. */ } else { /* Encode short literal now. */ int temp = 0; switch (-expP->X_add_number) { case 'f': case 'd': temp = literal_float[0] >> 4; break; case 'g': temp = literal_float[0] >> 1; break; case 'h': temp = ((literal_float[0] << 3) & 070) | ((literal_float[1] >> 13) & 07); break; default: BAD_CASE (-expP->X_add_number); break; } floatP->low[0] = temp & 077; floatP->low[1] = 0; } /* if can be short literal float */ } /* flonum or bignum ? */ } else { /* I^# seen: set it up if float. */ if (expP->X_add_number < 0) { memcpy (floatP->low, literal_float, sizeof (literal_float)); } } /* if S^# seen. */ } else { as_warn (_("A bignum/flonum may not be a displacement: 0x%lx used"), (expP->X_add_number = 0x80000000L)); /* Chosen so luser gets the most offset bits to patch later. */ } expP->X_add_number = floatP->low[0] | ((LITTLENUM_MASK & (floatP->low[1])) << LITTLENUM_NUMBER_OF_BITS); /* * For the O_big case we have: * If vop_short == 's' then a short floating literal is in the * lowest 6 bits of floatP -> low [0], which is * big_operand_bits [---] [0]. * If vop_short == 'i' then the appropriate number of elements * of big_operand_bits [---] [...] are set up with the correct * bits. * Also, just in case width is byte word or long, we copy the lowest * 32 bits of the number to X_add_number. */ break; } if (input_line_pointer != operandP->vop_expr_end + 1) { as_warn ("Junk at end of expression \"%s\"", input_line_pointer); goofed = 1; } operandP->vop_expr_end[1] = c_save; } } /* for(each operand) */ input_line_pointer = save_input_line_pointer; if (need_pass_2 || goofed) { return; } /* Emit op-code. */ /* Remember where it is, in case we want to modify the op-code later. */ opcode_low_byteP = frag_more (v.vit_opcode_nbytes); memcpy (opcode_low_byteP, v.vit_opcode, v.vit_opcode_nbytes); opcode_as_number = md_chars_to_number (opcode_as_chars = v.vit_opcode, 4); for (operandP = v.vit_operand, expP = exp_of_operand, segP = seg_of_operand, floatP = float_operand, end_operandP = v.vit_operand + v.vit_operands; operandP < end_operandP; operandP++, floatP++, segP++, expP++) { if (operandP->vop_ndx >= 0) { /* indexed addressing byte */ /* Legality of indexed mode already checked: it is OK */ FRAG_APPEND_1_CHAR (0x40 + operandP->vop_ndx); } /* if(vop_ndx>=0) */ /* Here to make main operand frag(s). */ this_add_number = expP->X_add_number; this_add_symbol = expP->X_add_symbol; to_seg = *segP; is_undefined = (to_seg == SEG_UNKNOWN); at = operandP->vop_mode & 1; length = (operandP->vop_short == 'b' ? 1 : (operandP->vop_short == 'w' ? 2 : (operandP->vop_short == 'l' ? 4 : 0))); nbytes = operandP->vop_nbytes; if (operandP->vop_access == 'b') { if (to_seg == now_seg || is_undefined) { /* If is_undefined, then it might BECOME now_seg. */ if (nbytes) { p = frag_more (nbytes); fix_new (frag_now, p - frag_now->fr_literal, nbytes, this_add_symbol, this_add_number, 1, NO_RELOC); } else { /* to_seg==now_seg || to_seg == SEG_UNKNOWN */ /* nbytes==0 */ length_code = is_undefined ? STATE_UNDF : STATE_BYTE; if (opcode_as_number & VIT_OPCODE_SPECIAL) { if (operandP->vop_width == VAX_WIDTH_UNCONDITIONAL_JUMP) { /* br or jsb */ frag_var (rs_machine_dependent, 5, 1, ENCODE_RELAX (STATE_ALWAYS_BRANCH, length_code), this_add_symbol, this_add_number, opcode_low_byteP); } else { if (operandP->vop_width == VAX_WIDTH_WORD_JUMP) { length_code = STATE_WORD; /* JF: There is no state_byte for this one! */ frag_var (rs_machine_dependent, 10, 2, ENCODE_RELAX (STATE_COMPLEX_BRANCH, length_code), this_add_symbol, this_add_number, opcode_low_byteP); } else { know (operandP->vop_width == VAX_WIDTH_BYTE_JUMP); frag_var (rs_machine_dependent, 9, 1, ENCODE_RELAX (STATE_COMPLEX_HOP, length_code), this_add_symbol, this_add_number, opcode_low_byteP); } } } else { know (operandP->vop_width == VAX_WIDTH_CONDITIONAL_JUMP); frag_var (rs_machine_dependent, 7, 1, ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, length_code), this_add_symbol, this_add_number, opcode_low_byteP); } } } else { /* to_seg != now_seg && to_seg != SEG_UNKNOWN */ /* * --- SEG FLOAT MAY APPEAR HERE ---- */ if (to_seg == SEG_ABSOLUTE) { if (nbytes) { know (!(opcode_as_number & VIT_OPCODE_SYNTHETIC)); p = frag_more (nbytes); /* Conventional relocation. */ fix_new (frag_now, p - frag_now->fr_literal, nbytes, &abs_symbol, this_add_number, 1, NO_RELOC); } 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 */ *opcode_low_byteP = opcode_as_chars[0] + VAX_WIDEN_LONG; know (opcode_as_chars[1] == 0); p = frag_more (5); p[0] = VAX_ABSOLUTE_MODE; /* @#... */ md_number_to_chars (p + 1, this_add_number, 4); /* Now (eg) JMP @#foo or JSB @#foo. */ } else { if (operandP->vop_width == VAX_WIDTH_WORD_JUMP) { p = frag_more (10); p[0] = 2; p[1] = 0; p[2] = VAX_BRB; p[3] = 6; p[4] = VAX_JMP; p[5] = VAX_ABSOLUTE_MODE; /* @#... */ md_number_to_chars (p + 6, this_add_number, 4); /* * Now (eg) ACBx 1f * BRB 2f * 1: JMP @#foo * 2: */ } else { know (operandP->vop_width == VAX_WIDTH_BYTE_JUMP); p = frag_more (9); p[0] = 2; p[1] = VAX_BRB; p[2] = 6; p[3] = VAX_JMP; p[4] = VAX_ABSOLUTE_MODE; /* @#... */ md_number_to_chars (p + 5, this_add_number, 4); /* * Now (eg) xOBxxx 1f * BRB 2f * 1: JMP @#foo * 2: */ } } } 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, this_add_number, 1, NO_RELOC); } 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, this_add_number, 1, NO_RELOC); /* 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, this_add_number, 1, NO_RELOC); /* * Now (eg) ACBx 1f * BRB 2f * 1: JMP foo * 2: */ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -