📄 vax.c
字号:
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; default: break; } return (fragP->fr_var + fragP->fr_fix - old_fr_fix);} /* md_estimate_size_before_relax() *//* * 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 (fragP) register fragS *fragP;{ register char *addressP; /* -> _var to change. */ register char *opcodeP; /* -> opcode char(s) to change. */ register short int length_code; /* 2=long 1=word 0=byte */ register short int extension; /* Size of relaxed address. */ /* Added to fr_fix: incl. ALL var chars. */ register symbolS *symbolP; register long int where; register long int address_of_var; /* Where, in file space, is _var of *fragP? */ register long int target_address; /* Where, in file space, does addr point? */ know (fragP->fr_type == rs_machine_dependent); length_code = fragP->fr_subtype & 3; /* depends on ENCODE_RELAX() */ know (length_code >= 0 && length_code < 3); where = fragP->fr_fix; addressP = fragP->fr_literal + where; opcodeP = fragP->fr_opcode; symbolP = fragP->fr_symbol; know (symbolP); target_address = symbolP->sy_value + fragP->fr_offset; address_of_var = fragP->fr_address + where; switch (fragP->fr_subtype) { case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE): know (*addressP == 0 || *addressP == 0x10); /* '@' bit. */ addressP[0] |= 0xAF; /* Byte displacement. */ addressP[1] = target_address - (address_of_var + 2); extension = 2; break; case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_WORD): know (*addressP == 0 || *addressP == 0x10); /* '@' bit. */ addressP[0] |= 0xCF; /* Word displacement. */ md_number_to_chars (addressP + 1, target_address - (address_of_var + 3), 2); extension = 3; break; case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_LONG): know (*addressP == 0 || *addressP == 0x10); /* '@' bit. */ addressP[0] |= 0xEF; /* Long word displacement. */ md_number_to_chars (addressP + 1, target_address - (address_of_var + 5), 4); extension = 5; break; case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_BYTE): addressP[0] = target_address - (address_of_var + 1); extension = 1; break; case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_WORD): opcodeP[0] ^= 1; /* Reverse sense of test. */ addressP[0] = 3; addressP[1] = VAX_BRB + VAX_WIDEN_WORD; md_number_to_chars (addressP + 2, target_address - (address_of_var + 4), 2); extension = 4; break; case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_LONG): opcodeP[0] ^= 1; /* Reverse sense of test. */ addressP[0] = 6; addressP[1] = VAX_JMP; addressP[2] = VAX_PC_RELATIVE_MODE; md_number_to_chars (addressP + 3, target_address, 4); extension = 7; break; case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_BYTE): addressP[0] = target_address - (address_of_var + 1); extension = 1; break; case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_WORD): opcodeP[0] += VAX_WIDEN_WORD; /* brb -> brw, bsbb -> bsbw */ md_number_to_chars (addressP, target_address - (address_of_var + 2), 2); extension = 2; break; case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_LONG): opcodeP[0] += VAX_WIDEN_LONG; /* brb -> jmp, bsbb -> jsb */ addressP[0] = VAX_PC_RELATIVE_MODE; md_number_to_chars (addressP + 1, target_address - (address_of_var + 5), 4); extension = 5; break; case ENCODE_RELAX (STATE_COMPLEX_BRANCH, STATE_WORD): md_number_to_chars (addressP, target_address - (address_of_var + 2), 2); extension = 2; break; case ENCODE_RELAX (STATE_COMPLEX_BRANCH, STATE_LONG): addressP[0] = 2; addressP[1] = 0; addressP[2] = VAX_BRB; addressP[3] = 6; addressP[4] = VAX_JMP; addressP[5] = VAX_PC_RELATIVE_MODE; md_number_to_chars (addressP + 6, target_address, 4); extension = 10; break; case ENCODE_RELAX (STATE_COMPLEX_HOP, STATE_BYTE): addressP[0] = target_address - (address_of_var + 1); extension = 1; break; case ENCODE_RELAX (STATE_COMPLEX_HOP, STATE_WORD): addressP[0] = 2; addressP[1] = VAX_BRB; addressP[2] = 3; addressP[3] = VAX_BRW; md_number_to_chars (addressP + 4, target_address - (address_of_var + 6), 2); extension = 6; break; case ENCODE_RELAX (STATE_COMPLEX_HOP, STATE_LONG): addressP[0] = 2; addressP[1] = VAX_BRB; addressP[2] = 6; addressP[3] = VAX_JMP; addressP[4] = VAX_PC_RELATIVE_MODE; md_number_to_chars (addressP + 5, target_address, 4); extension = 9; break; default: BAD_CASE (fragP->fr_subtype); break; } fragP->fr_fix += extension;}/* the bit-field entries in the relocation_info struct plays hell with the byte-order problems of cross-assembly. So as a hack, I added this mach. dependent ri twiddler. Ugly, but it gets you there. -KWK *//* on vax: first 4 bytes are normal unsigned long, next three bytes are symbolnum, least sig. byte first. Last byte is broken up with the upper nibble as nuthin, bit 3 as extern, bits 2 & 1 as length, and bit 0 as pcrel. */void md_ri_to_chars (ri_p, ri) struct relocation_info *ri_p, ri;{ unsigned char the_bytes[8]; /* this is easy */ md_number_to_chars (the_bytes, ri.r_address, sizeof (ri.r_address)); /* now the fun stuff */ the_bytes[6] = (ri.r_symbolnum >> 16) & 0x0ff; the_bytes[5] = (ri.r_symbolnum >> 8) & 0x0ff; the_bytes[4] = ri.r_symbolnum & 0x0ff; the_bytes[7] = (((ri.r_extern << 3) & 0x08) | ((ri.r_length << 1) & 0x06) | ((ri.r_pcrel << 0) & 0x01)) & 0x0F; /* now put it back where you found it */ bcopy (the_bytes, (char *) ri_p, sizeof (struct relocation_info));} /* JF this used to be a separate file *//* vax_ins_parse.c - a part for a VAX assembler *//* Copyright (C) 1987 Free Software Foundtation, Inc *//* * BUGS, GRIPES, APOLOGIA, etc. * * The opcode table 'votstrs' needs to be sorted on opcode frequency. * That is, AFTER we hash it with hash_...(), we want most-used opcodes * to come out of the hash table faster. * * I am sorry to inflict * yet another VAX assembler on the world, but RMS says we must * do everything from scratch, to prevent pin-heads restricting * this software. *//* * This is a vaguely modular set of routines in C to parse VAX * assembly code using DEC mnemonics. It is NOT un*x specific. * * The idea here is that the assembler has taken care of all: * labels * macros * listing * pseudo-ops * line continuation * comments * condensing any whitespace down to exactly one space * and all we have to do is parse 1 line into a vax instruction * partially formed. We will accept a line, and deliver: * an error message (hopefully empty) * a skeleton VAX instruction (tree structure) * textual pointers to all the operand expressions * a warning message that notes a silly operand (hopefully empty) *//* * E D I T H I S T O R Y * * 17may86 Dean Elsner. Bug if line ends immediately after opcode. * 30apr86 Dean Elsner. New vip_op() uses arg block so change call. * 6jan86 Dean Elsner. Crock vip_begin() to call vip_op_defaults(). * 2jan86 Dean Elsner. Invent synthetic opcodes. * Widen vax_opcodeT to 32 bits. Use a bit for VIT_OPCODE_SYNTHETIC, * which means this is not a real opcode, it is like a macro; it will * be relax()ed into 1 or more instructions. * Use another bit for VIT_OPCODE_SPECIAL if the op-code is not optimised * like a regular branch instruction. Option added to vip_begin(): * exclude synthetic opcodes. Invent synthetic_votstrs[]. * 31dec85 Dean Elsner. Invent vit_opcode_nbytes. * Also make vit_opcode into a char[]. We now have n-byte vax opcodes, * so caller's don't have to know the difference between a 1-byte & a * 2-byte op-code. Still need vax_opcodeT concept, so we know how * big an object must be to hold an op.code. * 30dec85 Dean Elsner. Widen typedef vax_opcodeT in "vax-inst.h" * because vax opcodes may be 16 bits. Our crufty C compiler was * happily initialising 8-bit vot_codes with 16-bit numbers! * (Wouldn't the 'phone company like to compress data so easily!) * 29dec85 Dean Elsner. New static table vax_operand_width_size[]. * Invented so we know hw many bytes a "I^#42" needs in its immediate * operand. Revised struct vop in "vax-inst.h": explicitly include * byte length of each operand, and it's letter-code datum type. * 17nov85 Dean Elsner. Name Change. * Due to ar(1) truncating names, we learned the hard way that * "vax-inst-parse.c" -> "vax-inst-parse." dropping the "o" off * the archived object name. SO... we shortened the name of this * source file, and changed the makefile. *//* #include <stdio.h> JF for one big happy file *//* JF #include "vax-inst.h" /* define the tree we parse it into */static char *op_hash = NULL; /* handle of the OPCODE hash table */ /* NULL means any use before vip_begin() */ /* will crash *//* * In: 1 character, from "bdfghloqpw" being the data-type of an operand * of a vax instruction. * * Out: the length of an operand of that type, in bytes. * Special branch operands types "-?!" have length 0. */static const short int vax_operand_width_size[256] ={#define _ 0 _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, 1, _, 8, _, 4, 8, 16, _, _, _, 4, _, _, 16, /* ..b.d.fgh...l..o */ _, 8, _, _, _, _, _, 2, _, _, _, _, _, _, _, _, /* .q.....w........ */ _, _, 1, _, 8, _, 4, 8, 16, _, _, _, 4, _, _, 16, /* ..b.d.fgh...l..o */ _, 8, _, _, _, _, _, 2, _, _, _, _, _, _, _, _, /* .q.....w........ */ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _};#undef _/* * This perversion encodes all the vax opcodes as a bunch of strings. * RMS says we should build our hash-table at run-time. Hmm. * Please would someone arrange these in decreasing frequency of opcode? * Because of the way hash_...() works, the most frequently used opcode * should be textually first and so on. * * Input for this table was 'vax.opcodes', awk(1)ed by 'vax.opcodes.c.awk' . * So change 'vax.opcodes', then re-generate this table. */#include "vax-opcode.h"/* * This is a table of optional op-codes. All of them represent * 'synthetic' instructions that seem popular. * * Here we make some pseudo op-codes. Every code has a bit set to say * it is synthetic. This lets you catch them if you want to * ban these opcodes. They are mnemonics for "elastic" instructions * that are supposed to assemble into the fewest bytes needed to do a * branch, or to do a conditional branch, or whatever. * * The opcode is in the usual place [low-order n*8 bits]. This means * that if you mask off the bucky bits, the usual rules apply about * how long the opcode is. * * All VAX branch displacements come at the end of the instruction. * For simple branches (1-byte opcode + 1-byte displacement) the last * operand is coded 'b?' where the "data type" '?' is a clue that we * may reverse the sense of the branch (complement lowest order bit) * and branch around a jump. This is by far the most common case. * That is why the VIT_OPCODE_SYNTHETIC bit is set: it says this is * a 0-byte op-code followed by 2 or more bytes of operand address. * * If the op-code has VIT_OPCODE_SPECIAL set, then we have a more unusual * case. * * For JBSB & JBR the treatment is the similar, except (1) we have a 'bw' * option before (2) we can directly JSB/JMP because there is no condition. * These operands have 'b-' as their access/data type. * * That leaves a bunch of random opcodes: JACBx, JxOBxxx. In these * cases, we do the same idea. JACBxxx are all marked with a 'b!' * JAOBxxx & JSOBxxx are marked with a 'b:'. * */#if (VIT_OPCODE_SYNTHETIC != 0x80000000)You have just broken the encoding below, which assumes the sign bit means 'I am an imaginary instruction'.#endif#if (VIT_OPCODE_SPECIAL != 0x40000000) You have just broken the encoding below, which assumes the 0x40 M bit means 'I am not to be "optimised" the way normal branches are'.#endifstatic const struct vot synthetic_votstrs[] ={ {"jbsb", {"b-", 0xC0000010}}, /* BSD 4.2 */ /* jsb used already */ {"jbr", {"b-", 0xC0000011}}, /* BSD 4.2 */ {"jr", {"b-", 0xC0000011}}, /* consistent */ {"jneq", {"b?", 0x80000012}}, {"jnequ", {"b?", 0x80000012}}, {"jeql", {"b?", 0x80000013}}, {"jeqlu", {"b?", 0x80000013}}, {"jgtr", {"b?", 0x80000014}}, {"jleq", {"b?", 0x80000015}}, /* un-used opcodes here */ {"jgeq", {"b?", 0x80000018}}, {"jlss", {"b?", 0x80000019}}, {"jgtru", {"b?", 0x8000001a}}, {"jlequ", {"b?", 0x8000001b}}, {"jvc", {"b?", 0x8000001c}}, {"jvs", {"b?", 0x8000001d}}, {"jgequ", {"b?", 0x8000001e}}, {"jcc", {"b?", 0x8000001e}}, {"jlssu", {"b?", 0x8000001f}}, {"jcs", {"b?", 0x8000001f}}, {"jacbw", {"rwrwmwb!", 0xC000003d}}, {"jacbf", {"rfrfmfb!", 0xC000004f}}, {"jacbd", {"rdrdmdb!", 0xC000006f}}, {"jacbb", {"rbrbmbb!", 0xC000009d}}, {"jacbl", {"rlrlmlb!", 0xC00000f1}}, {"jacbg", {"rgrgmgb!", 0xC0004ffd}}, {"jacbh", {"rhrhmhb!", 0xC0006ffd}}, {"jbs", {"rlvbb?", 0x800000e0}}, {"jbc", {"rlvbb?", 0x800000e1}}, {"jbss", {"rlvbb?", 0x800000e2}}, {"jbcs", {"rlvbb?", 0x800000e3}}, {"jbsc", {"rlvbb?", 0x800000e4}}, {"jbcc", {"rlvbb?", 0x800000e5}}, {"jbssi", {"rlvbb?", 0x800000e6}}, {"jbcci", {"rlvbb?", 0x800000e7}}, {"jlbs", {"rlb?", 0x800000e8}}, /* JF changed from rlvbb? */ {"jlbc", {"rlb?", 0x800000e9}}, /* JF changed from rlvbb? */ {"jaoblss", {"rlmlb:", 0xC00000f2}}, {"jaobleq", {"rlmlb:", 0xC00000f3}}, {"jsobgeq", {"mlb:", 0xC00000f4}}, /* JF was rlmlb: */ {"jsobgtr", {"mlb:", 0xC00000f5}}, /* JF was rlmlb: *//* CASEx has no branch addresses in our conception of it. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -