📄 tc-cris.c
字号:
*size_bitsp = 0; break; case 'W': case 'w': *size_bitsp = 1; break; case 'D': case 'd': *size_bitsp = 2; break; default: return 0; } /* Consume the size letter. */ (*cPP)++; return 1; }}/* Get a B or W size modifier from the string pointed out by *cPP, which must point to a '.' in front of the modifier. On successful return, *cPP is advanced to the character following the size modifier, and is undefined otherwise. cPP Pointer to pointer to string starting with the size modifier. size_bitsp Pointer to variable to contain the size bits on successful return. Return 1 iff a correct size modifier is found, else 0. */static intget_bw_size_modifier (cPP, size_bitsp) char **cPP; int *size_bitsp;{ if (**cPP != '.') return 0; else { /* Consume the '.'. */ (*cPP)++; switch (**cPP) { case 'B': case 'b': *size_bitsp = 0; break; case 'W': case 'w': *size_bitsp = 1; break; default: return 0; } /* Consume the size letter. */ (*cPP)++; return 1; }}/* Get a general register from the string pointed out by *cPP. The variable *cPP is advanced to the character following the general register name on a successful return, and has its initial position otherwise. cPP Pointer to pointer to string, beginning with a general register name. regnop Pointer to int containing the register number. Return 1 iff a correct general register designator is found, else 0. */static intget_gen_reg (cPP, regnop) char **cPP; int *regnop;{ char *oldp; oldp = *cPP; /* Handle a sometimes-mandatory dollar sign as register prefix. */ if (**cPP == REGISTER_PREFIX_CHAR) (*cPP)++; else if (demand_register_prefix) return 0; switch (**cPP) { case 'P': case 'p': /* "P" as in "PC"? Consume the "P". */ (*cPP)++; if ((**cPP == 'C' || **cPP == 'c') && ! isalnum ((*cPP)[1])) { /* It's "PC": consume the "c" and we're done. */ (*cPP)++; *regnop = REG_PC; return 1; } break; case 'R': case 'r': /* Hopefully r[0-9] or r1[0-5]. Consume 'R' or 'r'. */ (*cPP)++; if (isdigit (**cPP)) { /* It's r[0-9]. Consume and check the next digit. */ *regnop = **cPP - '0'; (*cPP)++; if (! isalnum (**cPP)) { /* No more digits, we're done. */ return 1; } else { /* One more digit. Consume and add. */ *regnop = *regnop * 10 + (**cPP - '0'); /* We need to check for a valid register number; Rn, 0 <= n <= MAX_REG. */ if (*regnop <= MAX_REG) { /* Consume second digit. */ (*cPP)++; return 1; } } } break; case 'S': case 's': /* "S" as in "SP"? Consume the "S". */ (*cPP)++; if (**cPP == 'P' || **cPP == 'p') { /* It's "SP": consume the "p" and we're done. */ (*cPP)++; *regnop = REG_SP; return 1; } break; default: /* Just here to silence compilation warnings. */ ; } /* We get here if we fail. Restore the pointer. */ *cPP = oldp; return 0;}/* Get a special register from the string pointed out by *cPP. The variable *cPP is advanced to the character following the special register name if one is found, and retains its original position otherwise. cPP Pointer to pointer to string starting with a special register name. sregpp Pointer to Pointer to struct spec_reg, where a pointer to the register description will be stored. Return 1 iff a correct special register name is found. */static intget_spec_reg (cPP, sregpp) char **cPP; const struct cris_spec_reg **sregpp;{ char *s1; const char *s2; char *name_begin = *cPP; const struct cris_spec_reg *sregp; /* Handle a sometimes-mandatory dollar sign as register prefix. */ if (*name_begin == REGISTER_PREFIX_CHAR) name_begin++; else if (demand_register_prefix) return 0; /* Loop over all special registers. */ for (sregp = cris_spec_regs; sregp->name != NULL; sregp++) { /* Start over from beginning of the supposed name. */ s1 = name_begin; s2 = sregp->name; while (*s2 != '\0' && (isupper (*s1) ? tolower (*s1) == *s2 : *s1 == *s2)) { s1++; s2++; } /* For a match, we must have consumed the name in the table, and we must be outside what could be part of a name. Assume here that a test for alphanumerics is sufficient for a name test. */ if (*s2 == 0 && ! isalnum (*s1)) { /* We have a match. Update the pointer and be done. */ *cPP = s1; *sregpp = sregp; return 1; } } /* If we got here, we did not find any name. */ return 0;}/* Get an unprefixed or side-effect-prefix operand from the string pointed out by *cPP. The pointer *cPP is advanced to the character following the indirect operand if we have success, else it contains an undefined value. cPP Pointer to pointer to string beginning with the first character of the supposed operand. prefixp Pointer to structure containing an optional instruction prefix. is_autoincp Pointer to int indicating the indirect or autoincrement bits. src_regnop Pointer to int containing the source register number in the instruction. imm_foundp Pointer to an int indicating if an immediate expression is found. imm_exprP Pointer to a structure containing an immediate expression, if success and if *imm_foundp is nonzero. Return 1 iff a correct indirect operand is found. */static intget_autoinc_prefix_or_indir_op (cPP, prefixp, is_autoincp, src_regnop, imm_foundp, imm_exprP) char **cPP; struct cris_prefix *prefixp; int *is_autoincp; int *src_regnop; int *imm_foundp; expressionS *imm_exprP;{ /* Assume there was no immediate mode expression. */ *imm_foundp = 0; if (**cPP == '[') { /* So this operand is one of: Indirect: [rN] Autoincrement: [rN+] Indexed with assign: [rN=rM+rO.S] Offset with assign: [rN=rM+I], [rN=rM+[rO].s], [rN=rM+[rO+].s] Either way, consume the '['. */ (*cPP)++; /* Get the rN register. */ if (! get_gen_reg (cPP, src_regnop)) /* If there was no register, then this cannot match. */ return 0; else { /* We got the register, now check the next character. */ switch (**cPP) { case ']': /* Indirect mode. We're done here. */ prefixp->kind = PREFIX_NONE; *is_autoincp = 0; break; case '+': /* This must be an auto-increment mode, if there's a match. */ prefixp->kind = PREFIX_NONE; *is_autoincp = 1; /* We consume this character and break out to check the closing ']'. */ (*cPP)++; break; case '=': /* This must be indexed with assign, or offset with assign to match. */ (*cPP)++; /* Either way, the next thing must be a register. */ if (! get_gen_reg (cPP, &prefixp->base_reg_number)) /* No register, no match. */ return 0; else { /* We've consumed "[rN=rM", so we must be looking at "+rO.s]" or "+I]", or "-I]", or "+[rO].s]" or "+[rO+].s]". */ if (**cPP == '+') { int index_reg_number; (*cPP)++; if (**cPP == '[') { int size_bits; /* This must be [rx=ry+[rz].s] or [rx=ry+[rz+].s] or no match. We must be looking at rz after consuming the '['. */ (*cPP)++; if (!get_gen_reg (cPP, &index_reg_number)) return 0; prefixp->kind = PREFIX_BDAP; prefixp->opcode = (BDAP_INDIR_OPCODE + (prefixp->base_reg_number << 12) + index_reg_number); if (**cPP == '+') { /* We've seen "[rx=ry+[rz+" here, so now we know that there must be "].s]" left to check. */ (*cPP)++; prefixp->opcode |= AUTOINCR_BIT << 8; } /* If it wasn't autoincrement, we don't need to add anything. */ /* Check the next-to-last ']'. */ if (**cPP != ']') return 0; (*cPP)++; /* Check the ".s" modifier. */ if (! get_bwd_size_modifier (cPP, &size_bits)) return 0; prefixp->opcode |= size_bits << 4; /* Now we got [rx=ry+[rz+].s or [rx=ry+[rz].s. We break out to check the final ']'. */ break; } /* It wasn't an indirection. Check if it's a register. */ else if (get_gen_reg (cPP, &index_reg_number)) { int size_bits; /* Indexed with assign mode: "[rN+rM.S]". */ prefixp->kind = PREFIX_BIAP; prefixp->opcode = (BIAP_OPCODE + (index_reg_number << 12) + prefixp->base_reg_number /* << 0 */); if (! get_bwd_size_modifier (cPP, &size_bits)) /* Size missing, this isn't a match. */ return 0; else { /* Size found, break out to check the final ']'. */ prefixp->opcode |= size_bits << 4; break; } } /* Not a register. Then this must be "[rN+I]". */ else if (cris_get_expression (cPP, &prefixp->expr)) { /* We've got offset with assign mode. Fill in the blanks and break out to match the final ']'. */ prefixp->kind = PREFIX_BDAP_IMM; break; } else /* Neither register nor expression found, so this can't be a match. */ return 0; } /* Not "[rN+" but perhaps "[rN-"? */ else if (**cPP == '-') { /* We must have an offset with assign mode. */ if (! cris_get_expression (cPP, &prefixp->expr)) /* No expression, no match. */ return 0; else { /* We've got offset with assign mode. Fill in the blanks and break out to match the final ']'. */ prefixp->kind = PREFIX_BDAP_IMM; break; } } else /* Neither '+' nor '-' after "[rN=rM". Lose. */ return 0; } default: /* Neither ']' nor '+' nor '=' after "[rN". Lose. */ return 0; } } /* When we get here, we have a match and will just check the closing ']'. We can still fail though. */ if (**cPP != ']') return 0; else { /* Don't forget to consume the final ']'. Then return in glory. */ (*cPP)++; return 1; } } /* No indirection. Perhaps a constant? */ else if (cris_get_expression (cPP, imm_exprP)) { /* Expression found, this is immediate mode. */ prefixp->kind = PREFIX_NONE; *is_autoincp = 1; *src_regnop = REG_PC; *imm_foundp = 1; return 1; } /* No luck today. */ return 0;}/* This function gets an indirect operand in a three-address operand combination from the string pointed out by *cPP. The pointer *cPP is advanced to the character following the indirect operand on success, or has an unspecified value on failure. cPP Pointer to pointer to string begining with the operand prefixp Pointer to structure containing an instruction prefix Returns 1 iff a correct indirect operand is found. */static intget_3op_or_dip_prefix_op (cPP, prefixp) char **cPP; struct cris_prefix *prefixp;{ int reg_number; if (**cPP != '[')
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -