-
- default:
- as_bad("Unknown opcode: `%s'", str);
- return;
- }
- if ((insn = (struct machine_opcode *) hash_find(op_hash, str)) == NULL) {
- as_bad("Unknown opcode `%s'.", str);
- return;
- }
- argsStart = s;
- opcode = insn->opcode;
- bzero(&the_insn, sizeof(the_insn));
- the_insn.reloc = NO_RELOC;
-
- /*
- * Build the opcode, checking as we go to make
- * sure that the operands match.
- *
- * If an operand matches, we modify the_insn or opcode appropriately,
- * and do a "continue". If an operand fails to match, we "break".
- */
- if (insn->args[0] != '\0')
- s = parse_operand (s, operand); /* Prime the pump */
-
- for (args = insn->args; ; ++args) {
- switch (*args) {
-
- case '\0': /* end of args */
- if (*s == '\0') {
- /* We are truly done. */
- the_insn.opcode = opcode;
- return;
- }
- as_bad("Too many operands: %s", s);
- break;
-
- case ',': /* Must match a comma */
- if (*s++ == ',') {
- s = parse_operand (s, operand); /* Parse next opnd */
- continue;
- }
- break;
-
- case 'v': /* Trap numbers (immediate field) */
- if (operand->X_seg == SEG_ABSOLUTE) {
- if (operand->X_add_number < 256) {
- opcode |= (operand->X_add_number << 16);
- continue;
- } else {
- as_bad("Immediate value of %d is too large",
- operand->X_add_number);
- continue;
- }
- }
- the_insn.reloc = RELOC_8;
- the_insn.reloc_offset = 1; /* BIG-ENDIAN Byte 1 of insn */
- the_insn.exp = *operand;
- continue;
-
- case 'b': /* A general register or 8-bit immediate */
- case 'i':
- /* We treat the two cases identically since we mashed
- them together in the opcode table. */
- if (operand->X_seg == SEG_REGISTER)
- goto general_reg;
-
- opcode |= IMMEDIATE_BIT;
- if (operand->X_seg == SEG_ABSOLUTE) {
- if (operand->X_add_number < 256) {
- opcode |= operand->X_add_number;
- continue;
- } else {
- as_bad("Immediate value of %d is too large",
- operand->X_add_number);
- continue;
- }
- }
- the_insn.reloc = RELOC_8;
- the_insn.reloc_offset = 3; /* BIG-ENDIAN Byte 3 of insn */
- the_insn.exp = *operand;
- continue;
-
- case 'a': /* next operand must be a register */
- case 'c':
- general_reg:
- /* lrNNN or grNNN or %%expr or a user-def register name */
- if (operand->X_seg != SEG_REGISTER)
- break; /* Only registers */
- know (operand->X_add_symbol == 0);
- know (operand->X_subtract_symbol == 0);
- reg = operand->X_add_number;
- if (reg >= SREG)
- break; /* No special registers */
-
- /*
- * Got the register, now figure out where
- * it goes in the opcode.
- */
- switch (*args) {
- case 'a':
- opcode |= reg << 8;
- continue;
-
- case 'b':
- case 'i':
- opcode |= reg;
- continue;
-
- case 'c':
- opcode |= reg << 16;
- continue;
- }
- as_fatal("failed sanity check.");
- break;
-
- case 'x': /* 16 bit constant, zero-extended */
- case 'X': /* 16 bit constant, one-extended */
- if (operand->X_seg == SEG_ABSOLUTE) {
- opcode |= (operand->X_add_number & 0xFF) << 0 |
- ((operand->X_add_number & 0xFF00) << 8);
- continue;
- }
- the_insn.reloc = RELOC_CONST;
- the_insn.exp = *operand;
- continue;
-
- case 'h':
- if (operand->X_seg == SEG_ABSOLUTE) {
- opcode |= (operand->X_add_number & 0x00FF0000) >> 16 |
- (((unsigned long)operand->X_add_number
- /* avoid sign ext */ & 0xFF000000) >> 8);
- continue;
- }
- the_insn.reloc = RELOC_CONSTH;
- the_insn.exp = *operand;
- continue;
-
- case 'P': /* PC-relative jump address */
- case 'A': /* Absolute jump address */
- /* These two are treated together since we folded the
- opcode table entries together. */
- if (operand->X_seg == SEG_ABSOLUTE) {
- opcode |= ABSOLUTE_BIT |
- (operand->X_add_number & 0x0003FC00) << 6 |
- ((operand->X_add_number & 0x000003FC) >> 2);
- continue;
- }
- the_insn.reloc = RELOC_JUMPTARG;
- the_insn.exp = *operand;
- the_insn.pcrel = 1; /* Assume PC-relative jump */
- /* FIXME-SOON, Do we figure out whether abs later, after know sym val? */
- continue;
-
- case 'e': /* Coprocessor enable bit for LOAD/STORE insn */
- if (operand->X_seg == SEG_ABSOLUTE) {
- if (operand->X_add_number == 0)
- continue;
- if (operand->X_add_number == 1) {
- opcode |= CE_BIT;
- continue;
- }
- }
- break;
-
- case 'n': /* Control bits for LOAD/STORE instructions */
- if (operand->X_seg == SEG_ABSOLUTE &&
- operand->X_add_number < 128) {
- opcode |= (operand->X_add_number << 16);
- continue;
- }
- break;
-
- case 's': /* Special register number */
- if (operand->X_seg != SEG_REGISTER)
- break; /* Only registers */
- if (operand->X_add_number < SREG)
- break; /* Not a special register */
- opcode |= (operand->X_add_number & 0xFF) << 8;
- continue;
-
- case 'u': /* UI bit of CONVERT */
- if (operand->X_seg == SEG_ABSOLUTE) {
- if (operand->X_add_number == 0)
- continue;
- if (operand->X_add_number == 1) {
- opcode |= UI_BIT;
- continue;
- }
- }
- break;
-
- case 'r': /* RND bits of CONVERT */
- if (operand->X_seg == SEG_ABSOLUTE &&
- operand->X_add_number < 8) {
- opcode |= operand->X_add_number << 4;
- continue;
- }
- break;
-
- case 'd': /* FD bits of CONVERT */
- if (operand->X_seg == SEG_ABSOLUTE &&
- operand->X_add_number < 4) {
- opcode |= operand->X_add_number << 2;
- continue;
- }
- break;
-
-
- case 'f': /* FS bits of CONVERT */
- if (operand->X_seg == SEG_ABSOLUTE &&
- operand->X_add_number < 4) {
- opcode |= operand->X_add_number << 0;
- continue;
- }
- break;
-
- case 'C':
- if (operand->X_seg == SEG_ABSOLUTE &&
- operand->X_add_number < 4) {
- opcode |= operand->X_add_number << 16;
- continue;
- }
- break;
-
- case 'F':
- if (operand->X_seg == SEG_ABSOLUTE &&
- operand->X_add_number < 16) {
- opcode |= operand->X_add_number << 18;
- continue;
- }
- break;
-
- default:
- BAD_CASE (*args);