+ lituse = load_expression (AXP_REG_AT, &tok[1],
+ &basereg, &newtok[1], (const char *) opname);
+ }
+ else
+ {
+ newtok[1] = tok[1];
+ lituse = 0;
+ }
+
+ newtok[0] = tok[0];
+ set_tok_preg (newtok[2], basereg);
+
+ assemble_tokens_to_insn ((const char *) opname, newtok, 3, &insn);
+
+ if (lituse)
+ {
+ gas_assert (insn.nfixups < MAX_INSN_FIXUPS);
+ insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE;
+ insn.fixups[insn.nfixups].exp.X_op = O_absent;
+ insn.nfixups++;
+ insn.sequence = lituse;
+ }
+
+ emit_insn (&insn);
+}
+
+/* Load a half-word or byte as an unsigned value. */
+
+static void
+emit_ldXu (const expressionS *tok,
+ int ntok,
+ const void * vlgsize)
+{
+ if (alpha_target & AXP_OPCODE_BWX)
+ emit_ir_load (tok, ntok, ldXu_op[(long) vlgsize]);
+ else
+ {
+ expressionS newtok[3];
+ struct alpha_insn insn;
+ int basereg;
+ long lituse;
+
+ if (alpha_noat_on)
+ as_bad (_("macro requires $at register while noat in effect"));
+
+ if (ntok == 2)
+ basereg = (tok[1].X_op == O_constant
+ ? AXP_REG_ZERO : alpha_gp_register);
+ else
+ basereg = tok[2].X_add_number;
+
+ /* Emit "lda $at, exp". */
+ lituse = load_expression (AXP_REG_AT, &tok[1], &basereg, NULL, "lda");
+
+ /* Emit "ldq_u targ, 0($at)". */
+ newtok[0] = tok[0];
+ set_tok_const (newtok[1], 0);
+ set_tok_preg (newtok[2], basereg);
+ assemble_tokens_to_insn ("ldq_u", newtok, 3, &insn);
+
+ if (lituse)
+ {
+ gas_assert (insn.nfixups < MAX_INSN_FIXUPS);
+ insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE;
+ insn.fixups[insn.nfixups].exp.X_op = O_absent;
+ insn.nfixups++;
+ insn.sequence = lituse;
+ }
+
+ emit_insn (&insn);
+
+ /* Emit "extXl targ, $at, targ". */
+ set_tok_reg (newtok[1], basereg);
+ newtok[2] = newtok[0];
+ assemble_tokens_to_insn (extXl_op[(long) vlgsize], newtok, 3, &insn);
+
+ if (lituse)
+ {
+ gas_assert (insn.nfixups < MAX_INSN_FIXUPS);
+ insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BYTOFF;
+ insn.fixups[insn.nfixups].exp.X_op = O_absent;
+ insn.nfixups++;
+ insn.sequence = lituse;
+ }
+
+ emit_insn (&insn);
+ }
+}
+
+/* Load a half-word or byte as a signed value. */
+
+static void
+emit_ldX (const expressionS *tok,
+ int ntok,
+ const void * vlgsize)
+{
+ emit_ldXu (tok, ntok, vlgsize);
+ assemble_tokens (sextX_op[(long) vlgsize], tok, 1, 1);
+}
+
+/* Load an integral value from an unaligned address as an unsigned
+ value. */
+
+static void
+emit_uldXu (const expressionS *tok,
+ int ntok,
+ const void * vlgsize)
+{
+ long lgsize = (long) vlgsize;
+ expressionS newtok[3];
+
+ if (alpha_noat_on)
+ as_bad (_("macro requires $at register while noat in effect"));
+
+ /* Emit "lda $at, exp". */
+ memcpy (newtok, tok, sizeof (expressionS) * ntok);
+ newtok[0].X_add_number = AXP_REG_AT;
+ assemble_tokens ("lda", newtok, ntok, 1);
+
+ /* Emit "ldq_u $t9, 0($at)". */
+ set_tok_reg (newtok[0], AXP_REG_T9);
+ set_tok_const (newtok[1], 0);
+ set_tok_preg (newtok[2], AXP_REG_AT);
+ assemble_tokens ("ldq_u", newtok, 3, 1);
+
+ /* Emit "ldq_u $t10, size-1($at)". */
+ set_tok_reg (newtok[0], AXP_REG_T10);
+ set_tok_const (newtok[1], (1 << lgsize) - 1);
+ assemble_tokens ("ldq_u", newtok, 3, 1);
+
+ /* Emit "extXl $t9, $at, $t9". */
+ set_tok_reg (newtok[0], AXP_REG_T9);
+ set_tok_reg (newtok[1], AXP_REG_AT);
+ set_tok_reg (newtok[2], AXP_REG_T9);
+ assemble_tokens (extXl_op[lgsize], newtok, 3, 1);
+
+ /* Emit "extXh $t10, $at, $t10". */
+ set_tok_reg (newtok[0], AXP_REG_T10);
+ set_tok_reg (newtok[2], AXP_REG_T10);
+ assemble_tokens (extXh_op[lgsize], newtok, 3, 1);
+
+ /* Emit "or $t9, $t10, targ". */
+ set_tok_reg (newtok[0], AXP_REG_T9);
+ set_tok_reg (newtok[1], AXP_REG_T10);
+ newtok[2] = tok[0];
+ assemble_tokens ("or", newtok, 3, 1);
+}
+
+/* Load an integral value from an unaligned address as a signed value.
+ Note that quads should get funneled to the unsigned load since we
+ don't have to do the sign extension. */
+
+static void
+emit_uldX (const expressionS *tok,
+ int ntok,
+ const void * vlgsize)
+{
+ emit_uldXu (tok, ntok, vlgsize);
+ assemble_tokens (sextX_op[(long) vlgsize], tok, 1, 1);
+}
+
+/* Implement the ldil macro. */
+
+static void
+emit_ldil (const expressionS *tok,
+ int ntok,
+ const void * unused ATTRIBUTE_UNUSED)
+{
+ expressionS newtok[2];
+
+ memcpy (newtok, tok, sizeof (newtok));
+ newtok[1].X_add_number = sign_extend_32 (tok[1].X_add_number);
+
+ assemble_tokens ("lda", newtok, ntok, 1);
+}
+
+/* Store a half-word or byte. */
+
+static void
+emit_stX (const expressionS *tok,
+ int ntok,
+ const void * vlgsize)
+{
+ int lgsize = (int) (long) vlgsize;
+
+ if (alpha_target & AXP_OPCODE_BWX)
+ emit_loadstore (tok, ntok, stX_op[lgsize]);
+ else
+ {
+ expressionS newtok[3];
+ struct alpha_insn insn;
+ int basereg;
+ long lituse;
+
+ if (alpha_noat_on)
+ as_bad (_("macro requires $at register while noat in effect"));
+
+ if (ntok == 2)
+ basereg = (tok[1].X_op == O_constant
+ ? AXP_REG_ZERO : alpha_gp_register);
+ else
+ basereg = tok[2].X_add_number;
+
+ /* Emit "lda $at, exp". */
+ lituse = load_expression (AXP_REG_AT, &tok[1], &basereg, NULL, "lda");
+
+ /* Emit "ldq_u $t9, 0($at)". */
+ set_tok_reg (newtok[0], AXP_REG_T9);
+ set_tok_const (newtok[1], 0);
+ set_tok_preg (newtok[2], basereg);
+ assemble_tokens_to_insn ("ldq_u", newtok, 3, &insn);
+
+ if (lituse)
+ {
+ gas_assert (insn.nfixups < MAX_INSN_FIXUPS);
+ insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE;
+ insn.fixups[insn.nfixups].exp.X_op = O_absent;
+ insn.nfixups++;
+ insn.sequence = lituse;
+ }
+
+ emit_insn (&insn);
+
+ /* Emit "insXl src, $at, $t10". */
+ newtok[0] = tok[0];
+ set_tok_reg (newtok[1], basereg);
+ set_tok_reg (newtok[2], AXP_REG_T10);
+ assemble_tokens_to_insn (insXl_op[lgsize], newtok, 3, &insn);
+
+ if (lituse)
+ {
+ gas_assert (insn.nfixups < MAX_INSN_FIXUPS);
+ insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BYTOFF;
+ insn.fixups[insn.nfixups].exp.X_op = O_absent;
+ insn.nfixups++;
+ insn.sequence = lituse;
+ }
+
+ emit_insn (&insn);
+
+ /* Emit "mskXl $t9, $at, $t9". */
+ set_tok_reg (newtok[0], AXP_REG_T9);
+ newtok[2] = newtok[0];
+ assemble_tokens_to_insn (mskXl_op[lgsize], newtok, 3, &insn);
+
+ if (lituse)
+ {
+ gas_assert (insn.nfixups < MAX_INSN_FIXUPS);
+ insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BYTOFF;
+ insn.fixups[insn.nfixups].exp.X_op = O_absent;
+ insn.nfixups++;
+ insn.sequence = lituse;
+ }
+
+ emit_insn (&insn);
+
+ /* Emit "or $t9, $t10, $t9". */
+ set_tok_reg (newtok[1], AXP_REG_T10);
+ assemble_tokens ("or", newtok, 3, 1);
+
+ /* Emit "stq_u $t9, 0($at). */
+ set_tok_const(newtok[1], 0);
+ set_tok_preg (newtok[2], AXP_REG_AT);
+ assemble_tokens_to_insn ("stq_u", newtok, 3, &insn);
+
+ if (lituse)
+ {
+ gas_assert (insn.nfixups < MAX_INSN_FIXUPS);
+ insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE;
+ insn.fixups[insn.nfixups].exp.X_op = O_absent;
+ insn.nfixups++;
+ insn.sequence = lituse;
+ }
+
+ emit_insn (&insn);
+ }
+}
+
+/* Store an integer to an unaligned address. */
+
+static void
+emit_ustX (const expressionS *tok,
+ int ntok,
+ const void * vlgsize)
+{
+ int lgsize = (int) (long) vlgsize;
+ expressionS newtok[3];
+
+ /* Emit "lda $at, exp". */
+ memcpy (newtok, tok, sizeof (expressionS) * ntok);
+ newtok[0].X_add_number = AXP_REG_AT;
+ assemble_tokens ("lda", newtok, ntok, 1);
+
+ /* Emit "ldq_u $9, 0($at)". */
+ set_tok_reg (newtok[0], AXP_REG_T9);
+ set_tok_const (newtok[1], 0);
+ set_tok_preg (newtok[2], AXP_REG_AT);
+ assemble_tokens ("ldq_u", newtok, 3, 1);
+
+ /* Emit "ldq_u $10, size-1($at)". */
+ set_tok_reg (newtok[0], AXP_REG_T10);
+ set_tok_const (newtok[1], (1 << lgsize) - 1);
+ assemble_tokens ("ldq_u", newtok, 3, 1);
+
+ /* Emit "insXl src, $at, $t11". */
+ newtok[0] = tok[0];
+ set_tok_reg (newtok[1], AXP_REG_AT);
+ set_tok_reg (newtok[2], AXP_REG_T11);
+ assemble_tokens (insXl_op[lgsize], newtok, 3, 1);
+
+ /* Emit "insXh src, $at, $t12". */
+ set_tok_reg (newtok[2], AXP_REG_T12);
+ assemble_tokens (insXh_op[lgsize], newtok, 3, 1);
+
+ /* Emit "mskXl $t9, $at, $t9". */
+ set_tok_reg (newtok[0], AXP_REG_T9);
+ newtok[2] = newtok[0];
+ assemble_tokens (mskXl_op[lgsize], newtok, 3, 1);
+
+ /* Emit "mskXh $t10, $at, $t10". */
+ set_tok_reg (newtok[0], AXP_REG_T10);
+ newtok[2] = newtok[0];
+ assemble_tokens (mskXh_op[lgsize], newtok, 3, 1);
+
+ /* Emit "or $t9, $t11, $t9". */
+ set_tok_reg (newtok[0], AXP_REG_T9);
+ set_tok_reg (newtok[1], AXP_REG_T11);
+ newtok[2] = newtok[0];
+ assemble_tokens ("or", newtok, 3, 1);
+
+ /* Emit "or $t10, $t12, $t10". */
+ set_tok_reg (newtok[0], AXP_REG_T10);
+ set_tok_reg (newtok[1], AXP_REG_T12);
+ newtok[2] = newtok[0];
+ assemble_tokens ("or", newtok, 3, 1);
+
+ /* Emit "stq_u $t10, size-1($at)". */
+ set_tok_reg (newtok[0], AXP_REG_T10);
+ set_tok_const (newtok[1], (1 << lgsize) - 1);
+ set_tok_preg (newtok[2], AXP_REG_AT);
+ assemble_tokens ("stq_u", newtok, 3, 1);
+
+ /* Emit "stq_u $t9, 0($at)". */
+ set_tok_reg (newtok[0], AXP_REG_T9);
+ set_tok_const (newtok[1], 0);
+ assemble_tokens ("stq_u", newtok, 3, 1);
+}
+
+/* Sign extend a half-word or byte. The 32-bit sign extend is
+ implemented as "addl $31, $r, $t" in the opcode table. */
+
+static void
+emit_sextX (const expressionS *tok,
+ int ntok,
+ const void * vlgsize)
+{
+ long lgsize = (long) vlgsize;
+
+ if (alpha_target & AXP_OPCODE_BWX)
+ assemble_tokens (sextX_op[lgsize], tok, ntok, 0);
+ else
+ {
+ int bitshift = 64 - 8 * (1 << lgsize);
+ expressionS newtok[3];
+
+ /* Emit "sll src,bits,dst". */
+ newtok[0] = tok[0];
+ set_tok_const (newtok[1], bitshift);
+ newtok[2] = tok[ntok - 1];
+ assemble_tokens ("sll", newtok, 3, 1);
+
+ /* Emit "sra dst,bits,dst". */
+ newtok[0] = newtok[2];
+ assemble_tokens ("sra", newtok, 3, 1);
+ }
+}
+
+/* Implement the division and modulus macros. */
+
+#ifdef OBJ_EVAX
+
+/* Make register usage like in normal procedure call.
+ Don't clobber PV and RA. */
+
+static void
+emit_division (const expressionS *tok,
+ int ntok,
+ const void * symname)
+{
+ /* DIVISION and MODULUS. Yech.
+
+ Convert
+ OP x,y,result
+ to
+ mov x,R16 # if x != R16
+ mov y,R17 # if y != R17
+ lda AT,__OP
+ jsr AT,(AT),0
+ mov R0,result
+
+ with appropriate optimizations if R0,R16,R17 are the registers
+ specified by the compiler. */
+
+ int xr, yr, rr;
+ symbolS *sym;
+ expressionS newtok[3];
+
+ xr = regno (tok[0].X_add_number);
+ yr = regno (tok[1].X_add_number);
+
+ if (ntok < 3)
+ rr = xr;
+ else
+ rr = regno (tok[2].X_add_number);
+
+ /* Move the operands into the right place. */
+ if (yr == AXP_REG_R16 && xr == AXP_REG_R17)
+ {
+ /* They are in exactly the wrong order -- swap through AT. */
+ if (alpha_noat_on)
+ as_bad (_("macro requires $at register while noat in effect"));
+
+ set_tok_reg (newtok[0], AXP_REG_R16);
+ set_tok_reg (newtok[1], AXP_REG_AT);
+ assemble_tokens ("mov", newtok, 2, 1);
+
+ set_tok_reg (newtok[0], AXP_REG_R17);
+ set_tok_reg (newtok[1], AXP_REG_R16);
+ assemble_tokens ("mov", newtok, 2, 1);
+
+ set_tok_reg (newtok[0], AXP_REG_AT);
+ set_tok_reg (newtok[1], AXP_REG_R17);
+ assemble_tokens ("mov", newtok, 2, 1);
+ }
+ else
+ {
+ if (yr == AXP_REG_R16)
+ {
+ set_tok_reg (newtok[0], AXP_REG_R16);
+ set_tok_reg (newtok[1], AXP_REG_R17);
+ assemble_tokens ("mov", newtok, 2, 1);
+ }
+
+ if (xr != AXP_REG_R16)
+ {
+ set_tok_reg (newtok[0], xr);
+ set_tok_reg (newtok[1], AXP_REG_R16);
+ assemble_tokens ("mov", newtok, 2, 1);
+ }
+
+ if (yr != AXP_REG_R16 && yr != AXP_REG_R17)
+ {
+ set_tok_reg (newtok[0], yr);
+ set_tok_reg (newtok[1], AXP_REG_R17);
+ assemble_tokens ("mov", newtok, 2, 1);
+ }
+ }
+
+ sym = symbol_find_or_make ((const char *) symname);
+
+ set_tok_reg (newtok[0], AXP_REG_AT);
+ set_tok_sym (newtok[1], sym, 0);
+ assemble_tokens ("lda", newtok, 2, 1);
+
+ /* Call the division routine. */
+ set_tok_reg (newtok[0], AXP_REG_AT);
+ set_tok_cpreg (newtok[1], AXP_REG_AT);
+ set_tok_const (newtok[2], 0);
+ assemble_tokens ("jsr", newtok, 3, 1);
+
+ /* Move the result to the right place. */
+ if (rr != AXP_REG_R0)
+ {
+ set_tok_reg (newtok[0], AXP_REG_R0);
+ set_tok_reg (newtok[1], rr);
+ assemble_tokens ("mov", newtok, 2, 1);
+ }
+}
+
+#else /* !OBJ_EVAX */
+
+static void
+emit_division (const expressionS *tok,
+ int ntok,
+ const void * symname)
+{
+ /* DIVISION and MODULUS. Yech.
+ Convert
+ OP x,y,result
+ to
+ lda pv,__OP
+ mov x,t10
+ mov y,t11
+ jsr t9,(pv),__OP
+ mov t12,result
+
+ with appropriate optimizations if t10,t11,t12 are the registers
+ specified by the compiler. */
+
+ int xr, yr, rr;
+ symbolS *sym;
+ expressionS newtok[3];
+
+ xr = regno (tok[0].X_add_number);
+ yr = regno (tok[1].X_add_number);
+
+ if (ntok < 3)
+ rr = xr;
+ else
+ rr = regno (tok[2].X_add_number);
+
+ sym = symbol_find_or_make ((const char *) symname);
+
+ /* Move the operands into the right place. */
+ if (yr == AXP_REG_T10 && xr == AXP_REG_T11)
+ {
+ /* They are in exactly the wrong order -- swap through AT. */
+ if (alpha_noat_on)
+ as_bad (_("macro requires $at register while noat in effect"));
+
+ set_tok_reg (newtok[0], AXP_REG_T10);
+ set_tok_reg (newtok[1], AXP_REG_AT);
+ assemble_tokens ("mov", newtok, 2, 1);
+
+ set_tok_reg (newtok[0], AXP_REG_T11);
+ set_tok_reg (newtok[1], AXP_REG_T10);
+ assemble_tokens ("mov", newtok, 2, 1);
+
+ set_tok_reg (newtok[0], AXP_REG_AT);
+ set_tok_reg (newtok[1], AXP_REG_T11);
+ assemble_tokens ("mov", newtok, 2, 1);
+ }
+ else
+ {
+ if (yr == AXP_REG_T10)
+ {
+ set_tok_reg (newtok[0], AXP_REG_T10);
+ set_tok_reg (newtok[1], AXP_REG_T11);
+ assemble_tokens ("mov", newtok, 2, 1);
+ }
+
+ if (xr != AXP_REG_T10)
+ {
+ set_tok_reg (newtok[0], xr);
+ set_tok_reg (newtok[1], AXP_REG_T10);
+ assemble_tokens ("mov", newtok, 2, 1);
+ }
+
+ if (yr != AXP_REG_T10 && yr != AXP_REG_T11)
+ {
+ set_tok_reg (newtok[0], yr);
+ set_tok_reg (newtok[1], AXP_REG_T11);
+ assemble_tokens ("mov", newtok, 2, 1);
+ }
+ }
+
+ /* Call the division routine. */
+ set_tok_reg (newtok[0], AXP_REG_T9);
+ set_tok_sym (newtok[1], sym, 0);
+ assemble_tokens ("jsr", newtok, 2, 1);
+
+ /* Reload the GP register. */
+#ifdef OBJ_AOUT
+FIXME
+#endif
+#if defined(OBJ_ECOFF) || defined(OBJ_ELF)
+ set_tok_reg (newtok[0], alpha_gp_register);
+ set_tok_const (newtok[1], 0);
+ set_tok_preg (newtok[2], AXP_REG_T9);
+ assemble_tokens ("ldgp", newtok, 3, 1);
+#endif
+
+ /* Move the result to the right place. */
+ if (rr != AXP_REG_T12)
+ {
+ set_tok_reg (newtok[0], AXP_REG_T12);
+ set_tok_reg (newtok[1], rr);
+ assemble_tokens ("mov", newtok, 2, 1);
+ }
+}
+
+#endif /* !OBJ_EVAX */
+
+/* The jsr and jmp macros differ from their instruction counterparts
+ in that they can load the target address and default most
+ everything. */
+
+static void
+emit_jsrjmp (const expressionS *tok,
+ int ntok,
+ const void * vopname)
+{
+ const char *opname = (const char *) vopname;
+ struct alpha_insn insn;
+ expressionS newtok[3];
+ int r, tokidx = 0;
+ long lituse = 0;
+
+ if (tokidx < ntok && tok[tokidx].X_op == O_register)
+ r = regno (tok[tokidx++].X_add_number);
+ else
+ r = strcmp (opname, "jmp") == 0 ? AXP_REG_ZERO : AXP_REG_RA;
+
+ set_tok_reg (newtok[0], r);
+
+ if (tokidx < ntok &&
+ (tok[tokidx].X_op == O_pregister || tok[tokidx].X_op == O_cpregister))
+ r = regno (tok[tokidx++].X_add_number);
+#ifdef OBJ_EVAX
+ /* Keep register if jsr $n.<sym>. */
+#else
+ else
+ {
+ int basereg = alpha_gp_register;
+ lituse = load_expression (r = AXP_REG_PV, &tok[tokidx],
+ &basereg, NULL, opname);
+ }
+#endif
+
+ set_tok_cpreg (newtok[1], r);
+
+#ifndef OBJ_EVAX
+ if (tokidx < ntok)
+ newtok[2] = tok[tokidx];
+ else
+#endif
+ set_tok_const (newtok[2], 0);
+
+ assemble_tokens_to_insn (opname, newtok, 3, &insn);
+
+ if (lituse)
+ {
+ gas_assert (insn.nfixups < MAX_INSN_FIXUPS);
+ insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_JSR;
+ insn.fixups[insn.nfixups].exp.X_op = O_absent;
+ insn.nfixups++;
+ insn.sequence = lituse;
+ }
+
+#ifdef OBJ_EVAX
+ if (alpha_flag_replace
+ && r == AXP_REG_RA
+ && tok[tokidx].X_add_symbol
+ && alpha_linkage_symbol)
+ {
+ /* Create a BOH reloc for 'jsr $27,NAME'. */
+ const char *symname = S_GET_NAME (tok[tokidx].X_add_symbol);
+ int symlen = strlen (symname);
+ char *ensymname;
+
+ /* Build the entry name as 'NAME..en'. */
+ ensymname = (char *) xmalloc (symlen + 5);
+ memcpy (ensymname, symname, symlen);
+ memcpy (ensymname + symlen, "..en", 5);
+
+ gas_assert (insn.nfixups < MAX_INSN_FIXUPS);
+ if (insn.nfixups > 0)
+ {
+ memmove (&insn.fixups[1], &insn.fixups[0],
+ sizeof(struct alpha_fixup) * insn.nfixups);
+ }
+
+ /* The fixup must be the same as the BFD_RELOC_ALPHA_NOP
+ case in load_expression. See B.4.5.2 of the OpenVMS
+ Linker Utility Manual. */
+ insn.fixups[0].reloc = BFD_RELOC_ALPHA_BOH;
+ insn.fixups[0].exp.X_op = O_symbol;
+ insn.fixups[0].exp.X_add_symbol = symbol_find_or_make (ensymname);
+ insn.fixups[0].exp.X_add_number = 0;
+ insn.fixups[0].xtrasym = alpha_linkage_symbol;
+ insn.fixups[0].procsym = alpha_evax_proc->symbol;
+ insn.nfixups++;
+ alpha_linkage_symbol = 0;
+ free (ensymname);
+ }
+#endif
+
+ emit_insn (&insn);
+}
+
+/* The ret and jcr instructions differ from their instruction
+ counterparts in that everything can be defaulted. */
+
+static void
+emit_retjcr (const expressionS *tok,
+ int ntok,
+ const void * vopname)
+{
+ const char *opname = (const char *) vopname;
+ expressionS newtok[3];
+ int r, tokidx = 0;
+
+ if (tokidx < ntok && tok[tokidx].X_op == O_register)
+ r = regno (tok[tokidx++].X_add_number);
+ else
+ r = AXP_REG_ZERO;