+ 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)
+ {
+ const char *symname = S_GET_NAME (tok[tokidx].X_add_symbol);
+ int symlen = strlen (symname);
+ char *ensymname;
+
+ 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;
+ }
+#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;
+
+ 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);
+ else
+ r = AXP_REG_RA;
+
+ set_tok_cpreg (newtok[1], r);
+
+ if (tokidx < ntok)
+ newtok[2] = tok[tokidx];
+ else
+ set_tok_const (newtok[2], strcmp (opname, "ret") == 0);
+
+ assemble_tokens (opname, newtok, 3, 0);
+}
+
+/* Implement the ldgp macro. */
+
+static void
+emit_ldgp (const expressionS *tok,
+ int ntok ATTRIBUTE_UNUSED,
+ const void * unused ATTRIBUTE_UNUSED)
+{
+#ifdef OBJ_AOUT
+FIXME
+#endif
+#if defined(OBJ_ECOFF) || defined(OBJ_ELF)
+ /* from "ldgp r1,n(r2)", generate "ldah r1,X(R2); lda r1,Y(r1)"
+ with appropriate constants and relocations. */
+ struct alpha_insn insn;
+ expressionS newtok[3];
+ expressionS addend;
+
+#ifdef OBJ_ECOFF
+ if (regno (tok[2].X_add_number) == AXP_REG_PV)
+ ecoff_set_gp_prolog_size (0);
+#endif
+
+ newtok[0] = tok[0];
+ set_tok_const (newtok[1], 0);
+ newtok[2] = tok[2];
+
+ assemble_tokens_to_insn ("ldah", newtok, 3, &insn);
+
+ addend = tok[1];
+
+#ifdef OBJ_ECOFF
+ if (addend.X_op != O_constant)
+ as_bad (_("can not resolve expression"));
+ addend.X_op = O_symbol;
+ addend.X_add_symbol = alpha_gp_symbol;
+#endif
+
+ insn.nfixups = 1;
+ insn.fixups[0].exp = addend;
+ insn.fixups[0].reloc = BFD_RELOC_ALPHA_GPDISP_HI16;
+ insn.sequence = next_sequence_num;
+
+ emit_insn (&insn);
+
+ set_tok_preg (newtok[2], tok[0].X_add_number);
+
+ assemble_tokens_to_insn ("lda", newtok, 3, &insn);
+
+#ifdef OBJ_ECOFF
+ addend.X_add_number += 4;
+#endif
+
+ insn.nfixups = 1;
+ insn.fixups[0].exp = addend;
+ insn.fixups[0].reloc = BFD_RELOC_ALPHA_GPDISP_LO16;
+ insn.sequence = next_sequence_num--;
+
+ emit_insn (&insn);
+#else /* OBJ_ECOFF || OBJ_ELF */
+ /* Avoid warning. */
+ tok = NULL;
+#endif
+}
+
+/* The macro table. */
+
+static const struct alpha_macro alpha_macros[] =
+{
+/* Load/Store macros. */
+ { "lda", emit_lda, NULL,
+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+ { "ldah", emit_ldah, NULL,
+ { MACRO_IR, MACRO_EXP, MACRO_EOA } },
+
+ { "ldl", emit_ir_load, "ldl",
+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+ { "ldl_l", emit_ir_load, "ldl_l",
+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+ { "ldq", emit_ir_load, "ldq",
+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+ { "ldq_l", emit_ir_load, "ldq_l",
+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+ { "ldq_u", emit_ir_load, "ldq_u",
+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+ { "ldf", emit_loadstore, "ldf",
+ { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+ { "ldg", emit_loadstore, "ldg",
+ { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+ { "lds", emit_loadstore, "lds",
+ { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+ { "ldt", emit_loadstore, "ldt",
+ { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+
+ { "ldb", emit_ldX, (void *) 0,
+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+ { "ldbu", emit_ldXu, (void *) 0,
+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+ { "ldw", emit_ldX, (void *) 1,
+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+ { "ldwu", emit_ldXu, (void *) 1,
+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+
+ { "uldw", emit_uldX, (void *) 1,
+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+ { "uldwu", emit_uldXu, (void *) 1,
+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+ { "uldl", emit_uldX, (void *) 2,
+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+ { "uldlu", emit_uldXu, (void *) 2,
+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+ { "uldq", emit_uldXu, (void *) 3,
+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+
+ { "ldgp", emit_ldgp, NULL,
+ { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA } },
+
+ { "ldi", emit_lda, NULL,
+ { MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "ldil", emit_ldil, NULL,
+ { MACRO_IR, MACRO_EXP, MACRO_EOA } },
+ { "ldiq", emit_lda, NULL,
+ { MACRO_IR, MACRO_EXP, MACRO_EOA } },
+
+ { "stl", emit_loadstore, "stl",
+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+ { "stl_c", emit_loadstore, "stl_c",
+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+ { "stq", emit_loadstore, "stq",
+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+ { "stq_c", emit_loadstore, "stq_c",
+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+ { "stq_u", emit_loadstore, "stq_u",
+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+ { "stf", emit_loadstore, "stf",
+ { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+ { "stg", emit_loadstore, "stg",
+ { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+ { "sts", emit_loadstore, "sts",
+ { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+ { "stt", emit_loadstore, "stt",
+ { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+
+ { "stb", emit_stX, (void *) 0,
+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+ { "stw", emit_stX, (void *) 1,
+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+ { "ustw", emit_ustX, (void *) 1,
+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+ { "ustl", emit_ustX, (void *) 2,
+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+ { "ustq", emit_ustX, (void *) 3,
+ { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
+
+/* Arithmetic macros. */
+
+ { "sextb", emit_sextX, (void *) 0,
+ { MACRO_IR, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_EOA,
+ /* MACRO_EXP, MACRO_IR, MACRO_EOA */ } },
+ { "sextw", emit_sextX, (void *) 1,
+ { MACRO_IR, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_EOA,
+ /* MACRO_EXP, MACRO_IR, MACRO_EOA */ } },
+
+ { "divl", emit_division, "__divl",
+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_IR, MACRO_EOA,
+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
+ { "divlu", emit_division, "__divlu",
+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_IR, MACRO_EOA,
+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
+ { "divq", emit_division, "__divq",
+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_IR, MACRO_EOA,
+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
+ { "divqu", emit_division, "__divqu",
+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_IR, MACRO_EOA,
+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
+ { "reml", emit_division, "__reml",
+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_IR, MACRO_EOA,
+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
+ { "remlu", emit_division, "__remlu",
+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_IR, MACRO_EOA,
+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
+ { "remq", emit_division, "__remq",
+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_IR, MACRO_EOA,
+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
+ { "remqu", emit_division, "__remqu",
+ { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_IR, MACRO_EOA,
+ /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
+
+ { "jsr", emit_jsrjmp, "jsr",
+ { MACRO_PIR, MACRO_EXP, MACRO_EOA,
+ MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA,
+ MACRO_EXP, MACRO_EOA } },
+ { "jmp", emit_jsrjmp, "jmp",
+ { MACRO_PIR, MACRO_EXP, MACRO_EOA,
+ MACRO_PIR, MACRO_EOA,
+ MACRO_IR, MACRO_EXP, MACRO_EOA,
+ MACRO_EXP, MACRO_EOA } },
+ { "ret", emit_retjcr, "ret",
+ { MACRO_IR, MACRO_EXP, MACRO_EOA,
+ MACRO_IR, MACRO_EOA,
+ MACRO_PIR, MACRO_EXP, MACRO_EOA,
+ MACRO_PIR, MACRO_EOA,
+ MACRO_EXP, MACRO_EOA,
+ MACRO_EOA } },
+ { "jcr", emit_retjcr, "jcr",
+ { MACRO_IR, MACRO_EXP, MACRO_EOA,
+ MACRO_IR, MACRO_EOA,
+ MACRO_PIR, MACRO_EXP, MACRO_EOA,
+ MACRO_PIR, MACRO_EOA,
+ MACRO_EXP, MACRO_EOA,
+ MACRO_EOA } },
+ { "jsr_coroutine", emit_retjcr, "jcr",
+ { MACRO_IR, MACRO_EXP, MACRO_EOA,
+ MACRO_IR, MACRO_EOA,
+ MACRO_PIR, MACRO_EXP, MACRO_EOA,
+ MACRO_PIR, MACRO_EOA,
+ MACRO_EXP, MACRO_EOA,
+ MACRO_EOA } },
+};
+
+static const unsigned int alpha_num_macros
+ = sizeof (alpha_macros) / sizeof (*alpha_macros);