- /* Here to make main operand frag(s). */
- this_add_number = expP->X_add_number;
- this_add_symbol = expP->X_add_symbol;
- to_seg = *segP;
-#ifdef BFD_ASSEMBLER
- is_undefined = (to_seg == undefined_section);
- is_absolute = (to_seg == absolute_section);
-#else
- is_undefined = (to_seg == SEG_UNKNOWN);
- is_absolute = (to_seg == SEG_ABSOLUTE);
-#endif
- 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 (is_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,
-#ifdef BFD_ASSEMBLER
- section_symbol (absolute_section),
-#else
- &abs_symbol,
-#endif
- 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 && !is_undefinfed && !is_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,
-#ifdef BFD_ASSEMBLER
- section_symbol (absolute_section),
-#else
- &abs_symbol,
-#endif
- 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:
- */
- }
- 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 (is_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 == ' ');
- length_code = STATE_BYTE;
-#ifdef OBJ_ELF
- if (S_IS_EXTERNAL (this_add_symbol)
- || S_IS_WEAK (this_add_symbol))
- length_code = STATE_UNDF;
-#endif
- p = frag_var (rs_machine_dependent, 10, 2,
- ENCODE_RELAX (STATE_PC_RELATIVE, length_code),
- 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 (is_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
-#ifdef OBJ_ELF
- || S_IS_WEAK(this_add_symbol)
- || S_IS_EXTERNAL(this_add_symbol)
+ case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_WORD):
+ opcodeP[0] += VAX_WIDEN_WORD; /* brb -> brw, bsbb -> bsbw */
+ fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, fragP->fr_offset,
+ 1, NO_RELOC);
+ 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;
+ fix_new (fragP, fragP->fr_fix + 1, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
+ extension = 5;
+ break;
+
+ case ENCODE_RELAX (STATE_COMPLEX_BRANCH, STATE_WORD):
+ fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
+ 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;
+ fix_new (fragP, fragP->fr_fix + 6, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
+ extension = 10;
+ break;
+
+ case ENCODE_RELAX (STATE_COMPLEX_HOP, STATE_BYTE):
+ fix_new (fragP, fragP->fr_fix, 1, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
+ 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;
+ fix_new (fragP, fragP->fr_fix + 4, 2, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
+ 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;
+ fix_new (fragP, fragP->fr_fix + 5, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, NO_RELOC);
+ extension = 9;
+ break;
+
+ default:
+ BAD_CASE (fragP->fr_subtype);
+ break;
+ }
+ fragP->fr_fix += extension;
+}
+
+/* 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 comment
+void
+md_ri_to_chars (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 */
+
+/* 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,
+};
+\f
+/* 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"
+\f
+/* 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)
+#error "You have just broken the encoding below, which assumes the sign bit means 'I am an imaginary instruction'."