pike.git / src / code / amd64.c

version» Context lines:

pike.git/src/code/amd64.c:4960:    { NULL, 0, }, { NULL, 0, }, { NULL, 0, }, { NULL, 0, },       /* 0xf0 */    { NULL, 0, }, { NULL, 0, }, { NULL, 0, }, { NULL, 0, },    { NULL, 0, }, { NULL, 0, }, { NULL, 0, }, { NULL, 0, },    { NULL, 0, }, { NULL, 0, }, { NULL, 0, }, { NULL, 0, },    { NULL, 0, }, { NULL, 0, }, { NULL, 0, }, { NULL, 0, },   },   };    - const char *amd64_registers[16] = { + const char *amd64_registers[5][16] = { +  { /* 8-bit registers with no REX. */ +  "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh", +  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +  }, +  { /* 8-bit registers with REX. */ +  "%al", "%cl", "%dl", "%bl", "%spl", "%bpl", "%sil", "%dil", +  "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b", +  }, +  { /* 16-bit registers (0x66 prefix). */ +  "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di", +  "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w", +  }, +  { /* 32-bit registers. */ +  "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi", +  "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d", +  }, +  { /* 64-bit registers (REX.W prefix). */    "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",    "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", -  +  },   };    - const char *amd64_describe_reg(int rex, int reg) + const char *amd64_describe_reg(int byte_mode, const int *legacy_prefix, +  int rex, int reg_high, int reg)   { -  if (rex) reg += 8; -  return amd64_registers[reg]; +  int reg_bank = 3; +  if (byte_mode) { +  reg_bank = 0; +  if (rex) reg_bank = 1; +  } else if (rex & 0x04) { +  reg_bank = 4; +  } else if (legacy_prefix[2] == 0x66) { +  reg_bank = 2;    } -  +  if (reg_high) reg += 8; +  return amd64_registers[reg_bank][reg]; + }      size_t amd64_readint32(PIKE_OPCODE_T *pc, char *buf)   {    unsigned INT32 val = ((unsigned INT32 *)pc)[0];    buf += strlen(buf);    sprintf(buf, "0x%08x", val);    return 4;   }      size_t amd64_disassemble_sib(PIKE_OPCODE_T *pc,    char *buf, -  const int *UNUSED(legacy_prefix), +  int byte_mode, +  const int *legacy_prefix,    int modrm,    int rex)   {    int sib = pc[0];    int bytes = 1;    buf[0] = 0;    if (((sib & 0x07) == 0x05) && !(rex & 1)) {    switch (modrm & 0xc0) {    case 0x00: /* Disp32 */    {
pike.git/src/code/amd64.c:5025:    bytes += 4;    if (val < 0) {    sprintf(buf, "-0x%x(%%rbp)", -val);    } else {    sprintf(buf, "0x%x(%%rbp)", val);    }    }    break;    }    } else { -  sprintf(buf, "%s", amd64_describe_reg(rex & 1, sib & 0x07)); +  sprintf(buf, "%s", amd64_describe_reg(byte_mode, legacy_prefix, rex, +  rex & 1, sib & 0x07));    }    if ((sib & 0x38) != 0x20) {    if (sib & 0xc0) {    /* Scale factor active */    sprintf(buf + strlen(buf), "(%s*%d)", -  amd64_describe_reg(rex & 2, (sib>>3) & 0x07), +  amd64_describe_reg(byte_mode, legacy_prefix, rex, +  rex & 2, (sib>>3) & 0x07),    1<<((sib>>6) & 3));    } else {    sprintf(buf + strlen(buf), "(%s)", -  amd64_describe_reg(rex & 2, (sib>>3) & 0x07)); +  amd64_describe_reg(byte_mode, legacy_prefix, rex, +  rex & 2, (sib>>3) & 0x07));    }    }    return bytes;   }      size_t amd64_disassemble_modrm(PIKE_OPCODE_T *pc,    char *buf, -  +  int byte_mode,    const int *legacy_prefix,    int modrm,    int rex)   {    size_t bytes = 0;    int mod;    char reg_buf[256];       if (legacy_prefix[3]) {    /* Size prefix override. ==> 16 bits */
pike.git/src/code/amd64.c:5070:    /* RIP + disp32 */    INT32 val = ((INT32 *)pc)[0];    if (val < 0) {    sprintf(buf, "-0x%x(%%rip)", -val);    } else {    sprintf(buf, "0x%x(%%rip)", val);    }    return 4;    }    if ((modrm & 0x07) == 0x04) { -  bytes += amd64_disassemble_sib(pc + bytes, reg_buf, legacy_prefix, -  modrm, rex); +  bytes += amd64_disassemble_sib(pc + bytes, reg_buf, byte_mode, +  legacy_prefix, modrm, rex);    } else { -  sprintf(reg_buf, "%s", amd64_describe_reg(rex & 1, modrm & 7)); +  sprintf(reg_buf, "%s", amd64_describe_reg(byte_mode, legacy_prefix, rex, +  rex & 1, modrm & 7));    }    switch(modrm & 0xc0) {    case 0x00:    sprintf(buf, "(%s)", reg_buf);    break;    case 0x40:    sprintf(buf, "%d(%s)", ((signed char *)pc)[bytes], reg_buf);    bytes++;    break;    case 0x80:    bytes += amd64_readint32(pc + bytes, buf);    sprintf(buf + strlen(buf), "(%s)", reg_buf);    break;    }    break;    case 0xc0: -  sprintf(buf, "%s", amd64_describe_reg(rex & 1, modrm & 7)); +  sprintf(buf, "%s", amd64_describe_reg(byte_mode, legacy_prefix, rex, +  rex & 1, modrm & 7));    break;    }    return bytes;   }      void amd64_disassemble_code(PIKE_OPCODE_T *pc, size_t len)   {    struct string_builder buf;    size_t pos;       init_string_builder(&buf, 0);    for (pos = 0; pos < len;) {    size_t op_start = pos;    size_t i;    const char *opcode = NULL;    const char *params[4] = { NULL, NULL, NULL, NULL, };    int legacy_prefix[4] = { 0, 0, 0, 0 };    int byte;    int rex = 0;    int modrm = 0; -  +  int byte_mode = 0;    struct amd64_opcode *table = amd64_opcodes[0];    struct amd64_opcode *op;    char buffers[4][256];       // Handle prefixes.    while(1) {    byte = pc[pos++];    op = table + byte;    if (op->flags & OP_PREFIX) {    legacy_prefix[op->flags & 3] = byte;
pike.git/src/code/amd64.c:5140:    op = table + byte;    }       while (op->flags & OP_MULTIBYTE) {    table = amd64_opcodes[1 + (op->flags & 0xff)];    byte = pc[pos++];    op = table + byte;    }       opcode = op->name; +  byte_mode = op->flags & (OP_8|OP_S8);       if (op->flags & OP_RM) {    modrm = pc[pos++]; -  params[0] = amd64_describe_reg(rex & 4, (modrm>>3) & 0x07); +  params[0] = amd64_describe_reg(byte_mode, legacy_prefix, rex, +  rex & 4, (modrm>>3) & 0x07);    params[1] = buffers[1]; -  pos += amd64_disassemble_modrm(pc + pos, buffers[1], +  pos += amd64_disassemble_modrm(pc + pos, buffers[1], byte_mode,    legacy_prefix, modrm, rex);    if (op->flags & OP_OPS) {    params[0] = NULL;    opcode = modrm_ops[op->flags & 0x0f][(modrm >> 3) & 0x07];    }    }       if (op->flags & OP_REG) {    int reg = byte & 0x07; -  params[1] = amd64_describe_reg(rex & 1, byte & 0x07); +  params[1] = amd64_describe_reg(byte_mode, legacy_prefix, rex, +  rex & 1, byte & 0x07);    }       if (op->flags & OP_IMM) {    if (!params[0]) {    params[0] = buffers[0];    buffers[0][0] = 0;    }    if (op->flags & (OP_8|OP_S8)) {    sprintf(buffers[0] + strlen(buffers[0]), "$%d", ((signed char *)pc)[pos++]);    } else {