📄 tc-vax.c
字号:
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 - (address_of_var + 7), 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 - (address_of_var + 10), 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 - (address_of_var + 9), 4); extension = 9; break; default: BAD_CASE (fragP->fr_subtype); break; } fragP->fr_fix += extension;} /* md_convert_frag() *//* Translate internal format of relocation info into target format. 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. */#ifdef commentvoidmd_ri_to_chars (the_bytes, ri) char *the_bytes; struct reloc_info_generic ri;{ /* 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;}#endif /* comment */voidtc_aout_fix_to_chars (where, fixP, segment_address_in_file) char *where; fixS *fixP; relax_addressT segment_address_in_file;{ /* * In: length of relocation (or of address) in chars: 1, 2 or 4. * Out: GNU LD relocation length code: 0, 1, or 2. */ static const unsigned char nbytes_r_length[] = {42, 0, 1, 42, 2}; long r_symbolnum; know (fixP->fx_addsy != NULL); md_number_to_chars (where, fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file, 4); r_symbolnum = (S_IS_DEFINED (fixP->fx_addsy) ? S_GET_TYPE (fixP->fx_addsy) : fixP->fx_addsy->sy_number); where[6] = (r_symbolnum >> 16) & 0x0ff; where[5] = (r_symbolnum >> 8) & 0x0ff; where[4] = r_symbolnum & 0x0ff; where[7] = ((((!S_IS_DEFINED (fixP->fx_addsy)) << 3) & 0x08) | ((nbytes_r_length[fixP->fx_size] << 1) & 0x06) | (((fixP->fx_pcrel << 0) & 0x01) & 0x0f));}/* * 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. *//* handle of the OPCODE hash table */static struct hash_control *op_hash;/* * 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] ={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 8, 0, 4, 8, 16, 0, 0, 0, 4, 0, 0,16, /* ..b.d.fgh...l..o */ 0, 8, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, /* .q.....w........ */ 0, 0, 1, 0, 8, 0, 4, 8, 16, 0, 0, 0, 4, 0, 0,16, /* ..b.d.fgh...l..o */ 0, 8, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, /* .q.....w........ */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,};/* * 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 "opcode/vax.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}}, {"jlbs", {"rlb?", 0x800000e8}}, {"jlbc", {"rlb?", 0x800000e9}}, {"jaoblss", {"rlmlb:", 0xC00000f2}}, {"jaobleq", {"rlmlb:", 0xC00000f3}}, {"jsobgeq", {"mlb:", 0xC00000f4}}, {"jsobgtr", {"mlb:", 0xC00000f5}},/* CASEx has no branch addresses in our conception of it. *//* You should use ".word ..." statements after the "case ...". */ {"", {"", 0}} /* empty is end sentinel */}; /* synthetic_votstrs *//* * v i p _ b e g i n ( ) * * Call me once before you decode any lines. * I decode votstrs into a hash table at op_hash (which I create). * I return an error text or null. * If you want, I will include the 'synthetic' jXXX instructions in the * instruction table. * You must nominate metacharacters for eg DEC's "#", "@", "^". */static const char *vip_begin (synthetic_too, immediate, indirect, displen) int synthetic_too; /* 1 means include jXXX op-codes. */ const char *immediate, *indirect, *displen;{ const struct vot *vP; /* scan votstrs */ const char *retval = 0; /* error text */ op_hash = hash_new (); for (vP = votstrs; *vP->vot_name && !retval; vP++) retval = hash_insert (op_hash, vP->vot_name, (PTR) &vP->vot_detail); if (synthetic_too) for (vP = synthetic_votstrs; *vP->vot_name && !retval; vP++) retval = hash_insert (op_hash, vP->vot_name, (PTR) &vP->vot_detail);#ifndef CONST_TABLE vip_op_defaults (immediate, indirect, displen);#endif return retval;}/* * v i p ( ) * * This converts a string into a vax instruction. * The string must be a bare single instruction in dec-vax (with BSD4 frobs) * format. * It provides some error messages: at most one fatal error message (which * stops the scan) and at most one warning message for each operand. * The vax instruction is returned in exploded form, since we have no * knowledge of how you parse (or evaluate) your expressions. * We do however strip off and decode addressing modes and operation * mnemonic. * * The exploded instruction is returned to a struct vit of your choice. * #include "vax-inst.h" to know what a struct vit is. * * This function's value is a string. If it is not "" then an internal * logic error was found: read this code to assign meaning to the string. * No argument string should generate such an error string: * it means a bug in our code, not in the user's text. *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -