-/* Assemble a single instruction. Its label has already been handled
- by the generic front end. We just parse opcode and operands, and
- produce the bytes of data and relocation. */
-
-void
-md_assemble (str)
- char *str;
-{
- char *toP;
- fixS *fixP;
- bit_fixS *bitP;
-
- know (str);
- machine_ip (str);
- toP = frag_more (4);
- /* Put out the opcode. */
- md_number_to_chars (toP, the_insn.opcode, 4);
-
- /* Put out the symbol-dependent stuff. */
- if (the_insn.reloc != NO_RELOC)
- {
- fixP = fix_new_exp (frag_now,
- (toP - frag_now->fr_literal + the_insn.reloc_offset),
- the_insn.size, & the_insn.exp, the_insn.pcrel,
- the_insn.reloc);
-
- /* Turn off complaints that the addend is
- too large for things like foo+100000@ha. */
- switch (the_insn.reloc)
- {
- case RELOC_DLX_HI16:
- case RELOC_DLX_LO16:
- fixP->fx_no_overflow = 1;
- break;
- default:
- break;
- }
-
- switch (fixP->fx_r_type)
- {
- case RELOC_DLX_REL26:
- bitP = malloc (sizeof (bit_fixS));
- bitP->fx_bit_size = 26;
- bitP->fx_bit_offset = 25;
- bitP->fx_bit_base = the_insn.opcode & 0xFC000000;
- bitP->fx_bit_base_adj = 0;
- bitP->fx_bit_max = 0;
- bitP->fx_bit_min = 0;
- bitP->fx_bit_add = 0x03FFFFFF;
- fixP->fx_bit_fixP = bitP;
- break;
- case RELOC_DLX_LO16:
- case RELOC_DLX_REL16:
- bitP = malloc (sizeof (bit_fixS));
- bitP->fx_bit_size = 16;
- bitP->fx_bit_offset = 15;
- bitP->fx_bit_base = the_insn.opcode & 0xFFFF0000;
- bitP->fx_bit_base_adj = 0;
- bitP->fx_bit_max = 0;
- bitP->fx_bit_min = 0;
- bitP->fx_bit_add = 0x0000FFFF;
- fixP->fx_bit_fixP = bitP;
- break;
- case RELOC_DLX_HI16:
- bitP = malloc (sizeof (bit_fixS));
- bitP->fx_bit_size = 16;
- bitP->fx_bit_offset = 15;
- bitP->fx_bit_base = the_insn.opcode & 0xFFFF0000;
- bitP->fx_bit_base_adj = 0;
- bitP->fx_bit_max = 0;
- bitP->fx_bit_min = 0;
- bitP->fx_bit_add = 0x0000FFFF;
- fixP->fx_bit_fixP = bitP;
- break;
- default:
- fixP->fx_bit_fixP = (bit_fixS *)NULL;
- break;
- }
- }
-}
-
-static int
-hilo_modifier_ok (s)
- char *s;
-{
- char *ptr = s;
- int idx, count = 1;
-
- if (*ptr != '(')
- return 1;
-
- for (idx = 1; ptr[idx] != '\0' && ptr[idx] != '[' && idx < 73; idx += 1)
- {
- if (count == 0)
- return count;
-
- if (ptr[idx] == '(')
- count += 1;
-
- if (ptr[idx] == ')')
- count -= 1;
- }
-
- return (count == 0) ? 1:0;
-}
-
-char *
-parse_operand (s, operandp)
- char *s;
- expressionS *operandp;
-{
- char *save = input_line_pointer;
- char *new;
-
- the_insn.HI = the_insn.LO = 0;
-
- /* Search for %hi and %lo, make a mark and skip it. */
- if (strncmp (s, "%hi", 3) == 0)
- {
- s += 3;
- the_insn.HI = 1;
- }
- else
- {
- if (strncmp (s, "%lo", 3) == 0)
- {
- s += 3;
- the_insn.LO = 1;
- }
- else
- the_insn.LO = 0;
- }
-
- if (the_insn.HI || the_insn.LO)
- {
- if (!hilo_modifier_ok (s))
- as_bad (_("Expression Error for operand modifier %%hi/%%lo\n"));
- }
-
- /* Check for the % and $ register representation */
- if ((s[0] == '%' || s[0] == '$' || s[0] == 'r' || s[0] == 'R')
- && ISDIGIT ((unsigned char) s[1]))
- {
- /* We have a numeric register expression. No biggy. */
- s += 1;
- input_line_pointer = s;
- (void) expression (operandp);
- if (operandp->X_op != O_constant
- || operandp->X_add_number > 31)
- as_bad (_("Invalid expression after %%%%\n"));
- operandp->X_op = O_register;
- }
- else
- {
- /* Normal operand parsing. */
- input_line_pointer = s;
- (void) expression (operandp);
- }
-
- new = input_line_pointer;
- input_line_pointer = save;
- return new;
-}
-