+/*******************************************************************/
+
+static const char *pch;
+static jmp_buf expr_env;
+
+typedef struct MonitorDef {
+ const char *name;
+ int offset;
+ int (*get_value)(struct MonitorDef *md);
+} MonitorDef;
+
+static MonitorDef monitor_defs[] = {
+#ifdef TARGET_I386
+ { "eax", offsetof(CPUState, regs[0]) },
+ { "ecx", offsetof(CPUState, regs[1]) },
+ { "edx", offsetof(CPUState, regs[2]) },
+ { "ebx", offsetof(CPUState, regs[3]) },
+ { "esp|sp", offsetof(CPUState, regs[4]) },
+ { "ebp|fp", offsetof(CPUState, regs[5]) },
+ { "esi", offsetof(CPUState, regs[6]) },
+ { "esi", offsetof(CPUState, regs[7]) },
+ { "eflags", offsetof(CPUState, eflags) },
+ { "eip|pc", offsetof(CPUState, eip) },
+#endif
+ { NULL },
+};
+
+static void expr_error(const char *fmt)
+{
+ term_printf(fmt);
+ term_printf("\n");
+ longjmp(expr_env, 1);
+}
+
+static int get_monitor_def(int *pval, const char *name)
+{
+ MonitorDef *md;
+ for(md = monitor_defs; md->name != NULL; md++) {
+ if (compare_cmd(name, md->name)) {
+ if (md->get_value) {
+ *pval = md->get_value(md);
+ } else {
+ *pval = *(uint32_t *)((uint8_t *)cpu_single_env + md->offset);
+ }
+ return 0;
+ }
+ }
+ return -1;
+}
+
+static void next(void)
+{
+ if (pch != '\0') {
+ pch++;
+ while (isspace(*pch))
+ pch++;
+ }
+}
+
+static int expr_sum(void);
+
+static int expr_unary(void)
+{
+ int n;
+ char *p;
+
+ switch(*pch) {
+ case '+':
+ next();
+ n = expr_unary();
+ break;
+ case '-':
+ next();
+ n = -expr_unary();
+ break;
+ case '~':
+ next();
+ n = ~expr_unary();
+ break;
+ case '(':
+ next();
+ n = expr_sum();
+ if (*pch != ')') {
+ expr_error("')' expected");
+ }
+ next();
+ break;
+ case '$':
+ {
+ char buf[128], *q;
+
+ pch++;
+ q = buf;
+ while ((*pch >= 'a' && *pch <= 'z') ||
+ (*pch >= 'A' && *pch <= 'Z') ||
+ (*pch >= '0' && *pch <= '9') ||
+ *pch == '_') {
+ if ((q - buf) < sizeof(buf) - 1)
+ *q++ = *pch;
+ pch++;
+ }
+ while (isspace(*pch))
+ pch++;
+ *q = 0;
+ if (get_monitor_def(&n, buf))
+ expr_error("unknown register");
+ }
+ break;
+ case '\0':
+ expr_error("unexpected end of expression");
+ n = 0;
+ break;
+ default:
+ n = strtoul(pch, &p, 0);
+ if (pch == p) {
+ expr_error("invalid char in expression");
+ }
+ pch = p;
+ while (isspace(*pch))
+ pch++;
+ break;
+ }
+ return n;
+}
+
+
+static int expr_prod(void)
+{
+ int val, val2, op;
+
+ val = expr_unary();
+ for(;;) {
+ op = *pch;
+ if (op != '*' && op != '/' && op != '%')
+ break;
+ next();
+ val2 = expr_unary();
+ switch(op) {
+ default:
+ case '*':
+ val *= val2;
+ break;
+ case '/':
+ case '%':
+ if (val2 == 0)
+ expr_error("divison by zero");
+ if (op == '/')
+ val /= val2;
+ else
+ val %= val2;
+ break;
+ }
+ }
+ return val;
+}
+
+static int expr_logic(void)
+{
+ int val, val2, op;
+
+ val = expr_prod();
+ for(;;) {
+ op = *pch;
+ if (op != '&' && op != '|' && op != '^')
+ break;
+ next();
+ val2 = expr_prod();
+ switch(op) {
+ default:
+ case '&':
+ val &= val2;
+ break;
+ case '|':
+ val |= val2;
+ break;
+ case '^':
+ val ^= val2;
+ break;
+ }
+ }
+ return val;
+}
+
+static int expr_sum(void)