+
+ return ptr;
+}
+
+/* MOVA has special requirements. Rather than adding twice the amount of
+ addressing modes, we simply special case it a bit. */
+static void
+get_mova_operands (char *op_end, struct h8_op *operand)
+{
+ char *ptr = op_end;
+
+ if (ptr[1] != '@' || ptr[2] != '(')
+ goto error;
+ ptr += 3;
+ operand[0].mode = 0;
+ ptr = parse_exp (ptr, &operand[0]);
+
+ if (*ptr !=',')
+ goto error;
+ ptr++;
+ get_operand (&ptr, operand + 1, DST);
+
+ if (*ptr =='.')
+ {
+ ptr++;
+ switch (*ptr++)
+ {
+ case 'b': case 'B':
+ operand[0].mode = (operand[0].mode & ~MODE) | INDEXB;
+ break;
+ case 'w': case 'W':
+ operand[0].mode = (operand[0].mode & ~MODE) | INDEXW;
+ break;
+ case 'l': case 'L':
+ operand[0].mode = (operand[0].mode & ~MODE) | INDEXL;
+ break;
+ default:
+ goto error;
+ }
+ }
+ else if ((operand[1].mode & MODE) == LOWREG)
+ {
+ switch (operand[1].mode & SIZE)
+ {
+ case L_8:
+ operand[0].mode = (operand[0].mode & ~MODE) | INDEXB;
+ break;
+ case L_16:
+ operand[0].mode = (operand[0].mode & ~MODE) | INDEXW;
+ break;
+ case L_32:
+ operand[0].mode = (operand[0].mode & ~MODE) | INDEXL;
+ break;
+ default:
+ goto error;
+ }
+ }
+ else
+ goto error;
+
+ if (*ptr++ != ')' || *ptr++ != ',')
+ goto error;
+ get_operand (&ptr, operand + 2, OP3);
+ /* See if we can use the short form of MOVA. */
+ if (((operand[1].mode & MODE) == REG || (operand[1].mode & MODE) == LOWREG)
+ && (operand[2].mode & MODE) == REG
+ && (operand[1].reg & 7) == (operand[2].reg & 7))
+ {
+ operand[1].mode = operand[2].mode = 0;
+ operand[0].reg = operand[2].reg & 7;
+ }
+ return;
+
+ error:
+ as_bad (_("expected valid addressing mode for mova: \"@(disp, ea.sz),ERn\""));
+}
+
+static void
+get_rtsl_operands (char *ptr, struct h8_op *operand)
+{
+ int mode, len, type = 0;
+ unsigned int num, num2;
+
+ ptr++;
+ if (*ptr == '(')
+ {
+ ptr++;
+ type = 1;
+ }
+ len = parse_reg (ptr, &mode, &num, SRC);
+ if (len == 0 || (mode & MODE) != REG)
+ {
+ as_bad (_("expected register"));
+ return;
+ }
+ ptr += len;
+ if (*ptr == '-')
+ {
+ len = parse_reg (++ptr, &mode, &num2, SRC);
+ if (len == 0 || (mode & MODE) != REG)
+ {
+ as_bad (_("expected register"));
+ return;
+ }
+ ptr += len;
+ /* CONST_xxx are used as placeholders in the opcode table. */
+ num = num2 - num;
+ if (num > 3)
+ {
+ as_bad (_("invalid register list"));
+ return;
+ }
+ }
+ else
+ num2 = num, num = 0;
+ if (type == 1 && *ptr++ != ')')
+ {
+ as_bad (_("expected closing paren"));
+ return;
+ }
+ operand[0].mode = RS32;
+ operand[1].mode = RD32;
+ operand[0].reg = num;
+ operand[1].reg = num2;