- /* start-sanitize-r5900 */
- case '0': /* 5 bit signed immediate at 6 */
- my_getExpression (&imm_expr, s);
- check_absolute_expr (ip, &imm_expr);
- if ((c == '\0' && imm_expr.X_op != O_constant)
- || ((imm_expr.X_add_number < -16
- || imm_expr.X_add_number >= 16)
- && imm_expr.X_op == O_constant))
- {
- if (imm_expr.X_op != O_constant
- && imm_expr.X_op != O_big)
- insn_error = "absolute expression required";
- else
- as_bad (_("5 bit expression not in range -16..15"));
- }
- ip->insn_opcode |= (imm_expr.X_add_number) << 6;
- imm_expr.X_op = O_absent;
- s = expr_end;
- continue;
-
- case '9': /* vi27 for vcallmsr */
- if (strncmp (s, "vi27", 4) == 0)
- s += 4;
- else
- as_bad (_("expected vi27"));
- continue;
-
- case '#': /* escape character */
- /* '#' specifies that we've got an optional suffix to this
- operand that must match exactly (if it exists). */
- if (*s != '\0' && *s != ','
- && *s != ' ' && *s != '\t' && *s != '\n')
- {
- if (*s == *(args + 1))
- {
- s++;
- args++;
- continue;
- }
- break;
- }
- args++;
- continue;
-
- case 'K': /* DEST operand completer (optional), must
- match previous dest if specified. */
- case '&': /* DEST instruction completer */
- case ';': /* DEST instruction completer, must be xyz */
- {
- int w,x,y,z;
- static int last_h;
-
- w = x = y = z = 0;
-
- /* Parse the completer. */
- s_reset = s;
- while ((!full_opcode_match || *args == 'K')
- && *s != '\0' && *s != ' ' && *s != ',')
- {
- if (*s == 'w')
- w++;
- else if (*s == 'x')
- x++;
- else if (*s == 'y')
- y++;
- else if (*s == 'z')
- z++;
- else
- {
- insn_error = "Invalid dest specification";
- break;
- }
- s++;
- }
-
- if (insn_error)
- continue;
-
- /* Each completer can only appear once. */
- if (w > 1 || x > 1 || y > 1 || z > 1)
- {
- insn_error = "Invalid dest specification";
- continue;
- }
-
- /* If this is the opcode completer, then we must insert
- the appropriate value into the insn. */
- if (*args == '&')
- {
- /* Not strictly in the specs, but requested by users. */
- if (w == 0 && x == 0 && y == 0 && z == 0)
- w = x = y = z = 1;
-
- ip->insn_opcode |= ((w << 21) | (x << 24)
- | (y << 23) | (z << 22));
- last_h = (w << 3) | (x << 0) | (y << 1) | (z << 2);
- }
- else if (*args == ';')
- {
- /* This implicitly has the .xyz completer. */
- if (w == 0 && x == 0 && y == 0 && z == 0)
- x = y = z = 1;
-
- if (w != 0 || x != 1 || y != 1 || z != 1)
- {
- insn_error = "Invalid dest specification";
- continue;
- }
-
- last_h = (w << 3) | (x << 0) | (y << 1) | (z << 2);
- }
- else
- {
- int temp;
-
- /* This is the operand completer, make sure it matches
- the previous opcode completer. */
- temp = (w << 3) | (x << 0) | (y << 1) | (z << 2);
- if (temp && temp != last_h)
- {
- insn_error = "DEST field in operand does not match DEST field in instruction";
- continue;
- }
-
- }
-
- continue;
- }
-
- case 'J': /* vu0 I register */
- if (s[0] == 'I')
- s += 1;
- else
- insn_error = "operand `I' expected";
- continue;
-
- case 'Q': /* vu0 Q register */
- if (s[0] == 'Q')
- s += 1;
- else
- insn_error = "operand `Q' expected";
- continue;
-
- case 'X': /* vu0 R register */
- if (s[0] == 'R')
- s += 1;
- else
- insn_error = "operand `R' expected";
- continue;
-
- case 'U': /* vu0 ACC register */
- if (s[0] == 'A' && s[1] == 'C' && s[2] == 'C')
- s += 3;
- else
- insn_error = "operand `ACC' expected";
- continue;
-
- case 'O':
- my_getSmallExpression (&imm_expr, s);
- imm_reloc = BFD_RELOC_MIPS15_S3;
- s = expr_end;
- continue;
- /* end-sanitize-r5900 */