udis86sx/udis86/libudis86/decode.c
author Jan Vrany <jan.vrany@fit.cvut.cz>
Tue, 14 Jun 2016 22:40:22 +0100
changeset 21 7d99b51b4784
parent 0 e4a716697bef
permissions -rw-r--r--
Build files for udis86 regenerated using newer autotools ...in order to support building under MSYS2 environment.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
     1
/* udis86 - libudis86/decode.c
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
     2
 * 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
     3
 * Copyright (c) 2002-2009 Vivek Thampi
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
     4
 * All rights reserved.
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
     5
 * 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
     6
 * Redistribution and use in source and binary forms, with or without modification, 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
     7
 * are permitted provided that the following conditions are met:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
     8
 * 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
     9
 *     * Redistributions of source code must retain the above copyright notice, 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    10
 *       this list of conditions and the following disclaimer.
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    11
 *     * Redistributions in binary form must reproduce the above copyright notice, 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    12
 *       this list of conditions and the following disclaimer in the documentation 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    13
 *       and/or other materials provided with the distribution.
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    14
 * 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    15
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    16
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    17
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    18
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    19
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    20
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    21
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    22
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    23
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    24
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    25
 */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    26
#include "udint.h"
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    27
#include "types.h"
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    28
#include "decode.h"
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    29
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    30
#ifndef __UD_STANDALONE__
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    31
# include <string.h>
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    32
#endif /* __UD_STANDALONE__ */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    33
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    34
/* The max number of prefixes to an instruction */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    35
#define MAX_PREFIXES    15
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    36
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    37
/* rex prefix bits */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    38
#define REX_W(r)        ( ( 0xF & ( r ) )  >> 3 )
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    39
#define REX_R(r)        ( ( 0x7 & ( r ) )  >> 2 )
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    40
#define REX_X(r)        ( ( 0x3 & ( r ) )  >> 1 )
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    41
#define REX_B(r)        ( ( 0x1 & ( r ) )  >> 0 )
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    42
#define REX_PFX_MASK(n) ( ( P_REXW(n) << 3 ) | \
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    43
                          ( P_REXR(n) << 2 ) | \
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    44
                          ( P_REXX(n) << 1 ) | \
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    45
                          ( P_REXB(n) << 0 ) )
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    46
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    47
/* scable-index-base bits */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    48
#define SIB_S(b)        ( ( b ) >> 6 )
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    49
#define SIB_I(b)        ( ( ( b ) >> 3 ) & 7 )
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    50
#define SIB_B(b)        ( ( b ) & 7 )
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    51
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    52
/* modrm bits */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    53
#define MODRM_REG(b)    ( ( ( b ) >> 3 ) & 7 )
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    54
#define MODRM_NNN(b)    ( ( ( b ) >> 3 ) & 7 )
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    55
#define MODRM_MOD(b)    ( ( ( b ) >> 6 ) & 3 )
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    56
#define MODRM_RM(b)     ( ( b ) & 7 )
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    57
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    58
static int decode_ext(struct ud *u, uint16_t ptr);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    59
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    60
enum reg_class { /* register classes */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    61
  REGCLASS_GPR,
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    62
  REGCLASS_MMX,
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    63
  REGCLASS_CR,
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    64
  REGCLASS_DB,
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    65
  REGCLASS_SEG,
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    66
  REGCLASS_XMM
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    67
};
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    68
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    69
 /* 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    70
 * inp_start
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    71
 *    Should be called before each de-code operation.
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    72
 */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    73
static void
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    74
inp_start(struct ud *u)
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    75
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    76
  u->inp_ctr = 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    77
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    78
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    79
   
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    80
static uint8_t
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    81
inp_next(struct ud *u)
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    82
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    83
  if (u->inp_end == 0) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    84
    if (u->inp_buf != NULL) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    85
      if (u->inp_buf_index < u->inp_buf_size) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    86
        u->inp_ctr++;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    87
        return (u->inp_curr = u->inp_buf[u->inp_buf_index++]);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    88
      }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    89
    } else {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    90
      int c;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    91
      if ((c = u->inp_hook(u)) != UD_EOI) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    92
        u->inp_curr = c;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    93
        u->inp_sess[u->inp_ctr++] = u->inp_curr;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    94
        return u->inp_curr;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    95
      }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    96
    }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    97
  }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    98
  u->inp_end = 1;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
    99
  UDERR(u, "byte expected, eoi received\n");
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   100
  return 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   101
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   102
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   103
static uint8_t
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   104
inp_curr(struct ud *u)
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   105
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   106
  return u->inp_curr;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   107
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   108
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   109
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   110
/*
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   111
 * inp_uint8
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   112
 * int_uint16
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   113
 * int_uint32
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   114
 * int_uint64
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   115
 *    Load little-endian values from input
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   116
 */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   117
static uint8_t 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   118
inp_uint8(struct ud* u)
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   119
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   120
  return inp_next(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   121
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   122
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   123
static uint16_t 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   124
inp_uint16(struct ud* u)
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   125
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   126
  uint16_t r, ret;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   127
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   128
  ret = inp_next(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   129
  r = inp_next(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   130
  return ret | (r << 8);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   131
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   132
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   133
static uint32_t 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   134
inp_uint32(struct ud* u)
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   135
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   136
  uint32_t r, ret;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   137
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   138
  ret = inp_next(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   139
  r = inp_next(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   140
  ret = ret | (r << 8);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   141
  r = inp_next(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   142
  ret = ret | (r << 16);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   143
  r = inp_next(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   144
  return ret | (r << 24);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   145
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   146
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   147
static uint64_t 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   148
inp_uint64(struct ud* u)
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   149
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   150
  uint64_t r, ret;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   151
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   152
  ret = inp_next(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   153
  r = inp_next(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   154
  ret = ret | (r << 8);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   155
  r = inp_next(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   156
  ret = ret | (r << 16);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   157
  r = inp_next(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   158
  ret = ret | (r << 24);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   159
  r = inp_next(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   160
  ret = ret | (r << 32);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   161
  r = inp_next(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   162
  ret = ret | (r << 40);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   163
  r = inp_next(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   164
  ret = ret | (r << 48);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   165
  r = inp_next(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   166
  return ret | (r << 56);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   167
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   168
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   169
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   170
static inline int
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   171
eff_opr_mode(int dis_mode, int rex_w, int pfx_opr)
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   172
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   173
  if (dis_mode == 64) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   174
    return rex_w ? 64 : (pfx_opr ? 16 : 32);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   175
  } else if (dis_mode == 32) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   176
    return pfx_opr ? 16 : 32;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   177
  } else {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   178
    UD_ASSERT(dis_mode == 16);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   179
    return pfx_opr ? 32 : 16;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   180
  }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   181
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   182
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   183
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   184
static inline int
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   185
eff_adr_mode(int dis_mode, int pfx_adr)
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   186
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   187
  if (dis_mode == 64) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   188
    return pfx_adr ? 32 : 64;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   189
  } else if (dis_mode == 32) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   190
    return pfx_adr ? 16 : 32;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   191
  } else {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   192
    UD_ASSERT(dis_mode == 16);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   193
    return pfx_adr ? 32 : 16;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   194
  }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   195
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   196
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   197
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   198
/* 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   199
 * decode_prefixes
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   200
 *
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   201
 *  Extracts instruction prefixes.
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   202
 */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   203
static int 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   204
decode_prefixes(struct ud *u)
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   205
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   206
  int done = 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   207
  uint8_t curr, last = 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   208
  UD_RETURN_ON_ERROR(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   209
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   210
  do {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   211
    last = curr;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   212
    curr = inp_next(u); 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   213
    UD_RETURN_ON_ERROR(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   214
    if (u->inp_ctr == MAX_INSN_LENGTH) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   215
      UD_RETURN_WITH_ERROR(u, "max instruction length");
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   216
    }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   217
   
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   218
    switch (curr)  
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   219
    {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   220
    case 0x2E: 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   221
      u->pfx_seg = UD_R_CS; 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   222
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   223
    case 0x36:     
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   224
      u->pfx_seg = UD_R_SS; 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   225
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   226
    case 0x3E: 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   227
      u->pfx_seg = UD_R_DS; 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   228
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   229
    case 0x26: 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   230
      u->pfx_seg = UD_R_ES; 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   231
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   232
    case 0x64: 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   233
      u->pfx_seg = UD_R_FS; 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   234
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   235
    case 0x65: 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   236
      u->pfx_seg = UD_R_GS; 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   237
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   238
    case 0x67: /* adress-size override prefix */ 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   239
      u->pfx_adr = 0x67;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   240
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   241
    case 0xF0: 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   242
      u->pfx_lock = 0xF0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   243
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   244
    case 0x66: 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   245
      u->pfx_opr = 0x66;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   246
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   247
    case 0xF2:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   248
      u->pfx_str = 0xf2;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   249
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   250
    case 0xF3:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   251
      u->pfx_str = 0xf3;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   252
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   253
    default:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   254
      /* consume if rex */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   255
      done = (u->dis_mode == 64 && (curr & 0xF0) == 0x40) ? 0 : 1;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   256
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   257
    }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   258
  } while (!done);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   259
  /* rex prefixes in 64bit mode, must be the last prefix */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   260
  if (u->dis_mode == 64 && (last & 0xF0) == 0x40) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   261
    u->pfx_rex = last;  
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   262
  }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   263
  return 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   264
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   265
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   266
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   267
static inline unsigned int modrm( struct ud * u )
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   268
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   269
    if ( !u->have_modrm ) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   270
        u->modrm = inp_next( u );
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   271
        u->have_modrm = 1;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   272
    }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   273
    return u->modrm;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   274
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   275
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   276
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   277
static unsigned int
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   278
resolve_operand_size( const struct ud * u, unsigned int s )
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   279
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   280
    switch ( s ) 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   281
    {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   282
    case SZ_V:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   283
        return ( u->opr_mode );
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   284
    case SZ_Z:  
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   285
        return ( u->opr_mode == 16 ) ? 16 : 32;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   286
    case SZ_Y:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   287
        return ( u->opr_mode == 16 ) ? 32 : u->opr_mode;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   288
    case SZ_RDQ:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   289
        return ( u->dis_mode == 64 ) ? 64 : 32;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   290
    default:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   291
        return s;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   292
    }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   293
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   294
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   295
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   296
static int resolve_mnemonic( struct ud* u )
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   297
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   298
  /* resolve 3dnow weirdness. */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   299
  if ( u->mnemonic == UD_I3dnow ) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   300
    u->mnemonic = ud_itab[ u->le->table[ inp_curr( u )  ] ].mnemonic;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   301
  }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   302
  /* SWAPGS is only valid in 64bits mode */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   303
  if ( u->mnemonic == UD_Iswapgs && u->dis_mode != 64 ) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   304
    UDERR(u, "swapgs invalid in 64bits mode\n");
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   305
    return -1;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   306
  }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   307
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   308
  if (u->mnemonic == UD_Ixchg) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   309
    if ((u->operand[0].type == UD_OP_REG && u->operand[0].base == UD_R_AX  &&
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   310
         u->operand[1].type == UD_OP_REG && u->operand[1].base == UD_R_AX) ||
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   311
        (u->operand[0].type == UD_OP_REG && u->operand[0].base == UD_R_EAX &&
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   312
         u->operand[1].type == UD_OP_REG && u->operand[1].base == UD_R_EAX)) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   313
      u->operand[0].type = UD_NONE;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   314
      u->operand[1].type = UD_NONE;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   315
      u->mnemonic = UD_Inop;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   316
    }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   317
  }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   318
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   319
  if (u->mnemonic == UD_Inop && u->pfx_repe) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   320
    u->pfx_repe = 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   321
    u->mnemonic = UD_Ipause;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   322
  }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   323
  return 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   324
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   325
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   326
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   327
/* -----------------------------------------------------------------------------
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   328
 * decode_a()- Decodes operands of the type seg:offset
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   329
 * -----------------------------------------------------------------------------
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   330
 */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   331
static void 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   332
decode_a(struct ud* u, struct ud_operand *op)
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   333
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   334
  if (u->opr_mode == 16) {  
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   335
    /* seg16:off16 */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   336
    op->type = UD_OP_PTR;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   337
    op->size = 32;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   338
    op->lval.ptr.off = inp_uint16(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   339
    op->lval.ptr.seg = inp_uint16(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   340
  } else {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   341
    /* seg16:off32 */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   342
    op->type = UD_OP_PTR;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   343
    op->size = 48;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   344
    op->lval.ptr.off = inp_uint32(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   345
    op->lval.ptr.seg = inp_uint16(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   346
  }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   347
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   348
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   349
/* -----------------------------------------------------------------------------
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   350
 * decode_gpr() - Returns decoded General Purpose Register 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   351
 * -----------------------------------------------------------------------------
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   352
 */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   353
static enum ud_type 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   354
decode_gpr(register struct ud* u, unsigned int s, unsigned char rm)
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   355
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   356
  switch (s) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   357
    case 64:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   358
        return UD_R_RAX + rm;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   359
    case 32:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   360
        return UD_R_EAX + rm;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   361
    case 16:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   362
        return UD_R_AX  + rm;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   363
    case  8:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   364
        if (u->dis_mode == 64 && u->pfx_rex) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   365
            if (rm >= 4)
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   366
                return UD_R_SPL + (rm-4);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   367
            return UD_R_AL + rm;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   368
        } else return UD_R_AL + rm;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   369
    case 0:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   370
        /* invalid size in case of a decode error */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   371
        UD_ASSERT(u->error);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   372
        return UD_NONE;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   373
    default:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   374
        UD_ASSERT(!"invalid operand size");
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   375
        return UD_NONE;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   376
  }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   377
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   378
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   379
static void
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   380
decode_reg(struct ud *u, 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   381
           struct ud_operand *opr,
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   382
           int type,
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   383
           int num,
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   384
           int size)
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   385
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   386
  int reg;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   387
  size = resolve_operand_size(u, size);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   388
  switch (type) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   389
    case REGCLASS_GPR : reg = decode_gpr(u, size, num); break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   390
    case REGCLASS_MMX : reg = UD_R_MM0  + (num & 7); break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   391
    case REGCLASS_XMM : reg = UD_R_XMM0 + num; break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   392
    case REGCLASS_CR : reg = UD_R_CR0  + num; break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   393
    case REGCLASS_DB : reg = UD_R_DR0  + num; break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   394
    case REGCLASS_SEG : {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   395
      /*
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   396
       * Only 6 segment registers, anything else is an error.
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   397
       */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   398
      if ((num & 7) > 5) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   399
        UDERR(u, "invalid segment register value\n");
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   400
        return;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   401
      } else {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   402
        reg = UD_R_ES + (num & 7);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   403
      }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   404
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   405
    }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   406
    default:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   407
      UD_ASSERT(!"invalid register type");
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   408
      return;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   409
  }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   410
  opr->type = UD_OP_REG;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   411
  opr->base = reg;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   412
  opr->size = size;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   413
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   414
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   415
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   416
/*
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   417
 * decode_imm 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   418
 *
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   419
 *    Decode Immediate values.
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   420
 */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   421
static void 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   422
decode_imm(struct ud* u, unsigned int size, struct ud_operand *op)
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   423
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   424
  op->size = resolve_operand_size(u, size);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   425
  op->type = UD_OP_IMM;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   426
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   427
  switch (op->size) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   428
  case  8: op->lval.sbyte = inp_uint8(u);   break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   429
  case 16: op->lval.uword = inp_uint16(u);  break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   430
  case 32: op->lval.udword = inp_uint32(u); break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   431
  case 64: op->lval.uqword = inp_uint64(u); break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   432
  default: return;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   433
  }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   434
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   435
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   436
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   437
/* 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   438
 * decode_mem_disp
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   439
 *
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   440
 *    Decode mem address displacement.
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   441
 */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   442
static void 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   443
decode_mem_disp(struct ud* u, unsigned int size, struct ud_operand *op)
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   444
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   445
  switch (size) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   446
  case 8:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   447
    op->offset = 8; 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   448
    op->lval.ubyte  = inp_uint8(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   449
    break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   450
  case 16:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   451
    op->offset = 16; 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   452
    op->lval.uword  = inp_uint16(u); 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   453
    break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   454
  case 32:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   455
    op->offset = 32; 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   456
    op->lval.udword = inp_uint32(u); 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   457
    break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   458
  case 64:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   459
    op->offset = 64; 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   460
    op->lval.uqword = inp_uint64(u); 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   461
    break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   462
  default:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   463
      return;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   464
  }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   465
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   466
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   467
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   468
/*
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   469
 * decode_modrm_reg
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   470
 *
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   471
 *    Decodes reg field of mod/rm byte
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   472
 * 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   473
 */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   474
static inline void
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   475
decode_modrm_reg(struct ud         *u, 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   476
                 struct ud_operand *operand,
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   477
                 unsigned int       type,
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   478
                 unsigned int       size)
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   479
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   480
  uint8_t reg = (REX_R(u->pfx_rex) << 3) | MODRM_REG(modrm(u));
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   481
  decode_reg(u, operand, type, reg, size);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   482
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   483
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   484
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   485
/*
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   486
 * decode_modrm_rm
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   487
 *
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   488
 *    Decodes rm field of mod/rm byte
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   489
 * 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   490
 */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   491
static void 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   492
decode_modrm_rm(struct ud         *u, 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   493
                struct ud_operand *op,
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   494
                unsigned char      type,    /* register type */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   495
                unsigned int       size)    /* operand size */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   496
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   497
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   498
  size_t offset = 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   499
  unsigned char mod, rm;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   500
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   501
  /* get mod, r/m and reg fields */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   502
  mod = MODRM_MOD(modrm(u));
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   503
  rm  = (REX_B(u->pfx_rex) << 3) | MODRM_RM(modrm(u));
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   504
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   505
  /* 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   506
   * If mod is 11b, then the modrm.rm specifies a register.
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   507
   *
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   508
   */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   509
  if (mod == 3) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   510
    decode_reg(u, op, type, rm, size);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   511
    return;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   512
  }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   513
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   514
  /* 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   515
   * !11b => Memory Address
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   516
   */  
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   517
  op->type = UD_OP_MEM;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   518
  op->size = resolve_operand_size(u, size);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   519
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   520
  if (u->adr_mode == 64) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   521
    op->base = UD_R_RAX + rm;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   522
    if (mod == 1) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   523
      offset = 8;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   524
    } else if (mod == 2) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   525
      offset = 32;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   526
    } else if (mod == 0 && (rm & 7) == 5) {           
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   527
      op->base = UD_R_RIP;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   528
      offset = 32;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   529
    } else {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   530
      offset = 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   531
    }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   532
    /* 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   533
     * Scale-Index-Base (SIB) 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   534
     */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   535
    if ((rm & 7) == 4) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   536
      inp_next(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   537
      
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   538
      op->scale = (1 << SIB_S(inp_curr(u))) & ~1;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   539
      op->index = UD_R_RAX + (SIB_I(inp_curr(u)) | (REX_X(u->pfx_rex) << 3));
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   540
      op->base  = UD_R_RAX + (SIB_B(inp_curr(u)) | (REX_B(u->pfx_rex) << 3));
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   541
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   542
      /* special conditions for base reference */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   543
      if (op->index == UD_R_RSP) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   544
        op->index = UD_NONE;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   545
        op->scale = UD_NONE;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   546
      }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   547
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   548
      if (op->base == UD_R_RBP || op->base == UD_R_R13) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   549
        if (mod == 0) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   550
          op->base = UD_NONE;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   551
        } 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   552
        if (mod == 1) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   553
          offset = 8;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   554
        } else {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   555
          offset = 32;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   556
        }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   557
      }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   558
    }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   559
  } else if (u->adr_mode == 32) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   560
    op->base = UD_R_EAX + rm;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   561
    if (mod == 1) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   562
      offset = 8;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   563
    } else if (mod == 2) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   564
      offset = 32;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   565
    } else if (mod == 0 && rm == 5) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   566
      op->base = UD_NONE;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   567
      offset = 32;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   568
    } else {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   569
      offset = 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   570
    }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   571
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   572
    /* Scale-Index-Base (SIB) */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   573
    if ((rm & 7) == 4) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   574
      inp_next(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   575
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   576
      op->scale = (1 << SIB_S(inp_curr(u))) & ~1;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   577
      op->index = UD_R_EAX + (SIB_I(inp_curr(u)) | (REX_X(u->pfx_rex) << 3));
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   578
      op->base  = UD_R_EAX + (SIB_B(inp_curr(u)) | (REX_B(u->pfx_rex) << 3));
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   579
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   580
      if (op->index == UD_R_ESP) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   581
        op->index = UD_NONE;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   582
        op->scale = UD_NONE;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   583
      }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   584
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   585
      /* special condition for base reference */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   586
      if (op->base == UD_R_EBP) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   587
        if (mod == 0) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   588
          op->base = UD_NONE;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   589
        } 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   590
        if (mod == 1) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   591
          offset = 8;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   592
        } else {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   593
          offset = 32;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   594
        }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   595
      }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   596
    }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   597
  } else {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   598
    const unsigned int bases[]   = { UD_R_BX, UD_R_BX, UD_R_BP, UD_R_BP,
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   599
                                     UD_R_SI, UD_R_DI, UD_R_BP, UD_R_BX };
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   600
    const unsigned int indices[] = { UD_R_SI, UD_R_DI, UD_R_SI, UD_R_DI,
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   601
                                     UD_NONE, UD_NONE, UD_NONE, UD_NONE };
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   602
    op->base  = bases[rm & 7];
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   603
    op->index = indices[rm & 7];
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   604
    if (mod == 0 && rm == 6) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   605
      offset = 16;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   606
      op->base = UD_NONE;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   607
    } else if (mod == 1) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   608
      offset = 8;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   609
    } else if (mod == 2) { 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   610
      offset = 16;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   611
    }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   612
  }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   613
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   614
  if (offset) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   615
    decode_mem_disp(u, offset, op);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   616
  }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   617
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   618
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   619
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   620
/* 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   621
 * decode_moffset
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   622
 *    Decode offset-only memory operand
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   623
 */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   624
static void
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   625
decode_moffset(struct ud *u, unsigned int size, struct ud_operand *opr)
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   626
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   627
  opr->type = UD_OP_MEM;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   628
  opr->size = resolve_operand_size(u, size);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   629
  decode_mem_disp(u, u->adr_mode, opr);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   630
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   631
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   632
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   633
/* -----------------------------------------------------------------------------
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   634
 * decode_operands() - Disassembles Operands.
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   635
 * -----------------------------------------------------------------------------
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   636
 */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   637
static int
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   638
decode_operand(struct ud           *u, 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   639
               struct ud_operand   *operand,
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   640
               enum ud_operand_code type,
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   641
               unsigned int         size)
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   642
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   643
  operand->_oprcode = type;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   644
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   645
  switch (type) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   646
    case OP_A :
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   647
      decode_a(u, operand);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   648
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   649
    case OP_MR:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   650
      decode_modrm_rm(u, operand, REGCLASS_GPR, 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   651
                      MODRM_MOD(modrm(u)) == 3 ? 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   652
                        Mx_reg_size(size) : Mx_mem_size(size));
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   653
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   654
    case OP_F:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   655
      u->br_far  = 1;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   656
      /* intended fall through */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   657
    case OP_M:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   658
      if (MODRM_MOD(modrm(u)) == 3) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   659
        UDERR(u, "expected modrm.mod != 3\n");
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   660
      }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   661
      /* intended fall through */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   662
    case OP_E:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   663
      decode_modrm_rm(u, operand, REGCLASS_GPR, size);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   664
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   665
    case OP_G:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   666
      decode_modrm_reg(u, operand, REGCLASS_GPR, size);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   667
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   668
    case OP_sI:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   669
    case OP_I:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   670
      decode_imm(u, size, operand);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   671
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   672
    case OP_I1:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   673
      operand->type = UD_OP_CONST;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   674
      operand->lval.udword = 1;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   675
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   676
    case OP_N:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   677
      if (MODRM_MOD(modrm(u)) != 3) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   678
        UDERR(u, "expected modrm.mod == 3\n");
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   679
      }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   680
      /* intended fall through */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   681
    case OP_Q:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   682
      decode_modrm_rm(u, operand, REGCLASS_MMX, size);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   683
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   684
    case OP_P:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   685
      decode_modrm_reg(u, operand, REGCLASS_MMX, size);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   686
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   687
    case OP_U:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   688
      if (MODRM_MOD(modrm(u)) != 3) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   689
        UDERR(u, "expected modrm.mod == 3\n");
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   690
      }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   691
      /* intended fall through */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   692
    case OP_W:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   693
      decode_modrm_rm(u, operand, REGCLASS_XMM, size);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   694
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   695
    case OP_V:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   696
      decode_modrm_reg(u, operand, REGCLASS_XMM, size);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   697
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   698
    case OP_MU:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   699
      decode_modrm_rm(u, operand, REGCLASS_XMM, 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   700
                      MODRM_MOD(modrm(u)) == 3 ? 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   701
                        Mx_reg_size(size) : Mx_mem_size(size));
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   702
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   703
    case OP_S:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   704
      decode_modrm_reg(u, operand, REGCLASS_SEG, size);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   705
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   706
    case OP_O:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   707
      decode_moffset(u, size, operand);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   708
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   709
    case OP_R0: 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   710
    case OP_R1: 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   711
    case OP_R2: 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   712
    case OP_R3: 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   713
    case OP_R4: 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   714
    case OP_R5: 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   715
    case OP_R6: 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   716
    case OP_R7:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   717
      decode_reg(u, operand, REGCLASS_GPR, 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   718
                 (REX_B(u->pfx_rex) << 3) | (type - OP_R0), size);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   719
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   720
    case OP_AL:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   721
    case OP_AX:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   722
    case OP_eAX:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   723
    case OP_rAX:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   724
      decode_reg(u, operand, REGCLASS_GPR, 0, size);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   725
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   726
    case OP_CL:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   727
    case OP_CX:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   728
    case OP_eCX:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   729
      decode_reg(u, operand, REGCLASS_GPR, 1, size);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   730
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   731
    case OP_DL:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   732
    case OP_DX:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   733
    case OP_eDX:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   734
      decode_reg(u, operand, REGCLASS_GPR, 2, size);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   735
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   736
    case OP_ES: 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   737
    case OP_CS: 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   738
    case OP_DS:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   739
    case OP_SS: 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   740
    case OP_FS: 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   741
    case OP_GS:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   742
      /* in 64bits mode, only fs and gs are allowed */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   743
      if (u->dis_mode == 64) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   744
        if (type != OP_FS && type != OP_GS) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   745
          UDERR(u, "invalid segment register in 64bits\n");
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   746
        }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   747
      }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   748
      operand->type = UD_OP_REG;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   749
      operand->base = (type - OP_ES) + UD_R_ES;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   750
      operand->size = 16;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   751
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   752
    case OP_J :
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   753
      decode_imm(u, size, operand);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   754
      operand->type = UD_OP_JIMM;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   755
      break ;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   756
    case OP_R :
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   757
      if (MODRM_MOD(modrm(u)) != 3) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   758
        UDERR(u, "expected modrm.mod == 3\n");
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   759
      }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   760
      decode_modrm_rm(u, operand, REGCLASS_GPR, size);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   761
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   762
    case OP_C:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   763
      decode_modrm_reg(u, operand, REGCLASS_CR, size);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   764
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   765
    case OP_D:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   766
      decode_modrm_reg(u, operand, REGCLASS_DB, size);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   767
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   768
    case OP_I3 :
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   769
      operand->type = UD_OP_CONST;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   770
      operand->lval.sbyte = 3;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   771
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   772
    case OP_ST0: 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   773
    case OP_ST1: 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   774
    case OP_ST2: 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   775
    case OP_ST3:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   776
    case OP_ST4:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   777
    case OP_ST5: 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   778
    case OP_ST6: 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   779
    case OP_ST7:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   780
      operand->type = UD_OP_REG;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   781
      operand->base = (type - OP_ST0) + UD_R_ST0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   782
      operand->size = 80;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   783
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   784
    default :
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   785
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   786
  }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   787
  return 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   788
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   789
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   790
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   791
/* 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   792
 * decode_operands
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   793
 *
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   794
 *    Disassemble upto 3 operands of the current instruction being
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   795
 *    disassembled. By the end of the function, the operand fields
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   796
 *    of the ud structure will have been filled.
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   797
 */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   798
static int
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   799
decode_operands(struct ud* u)
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   800
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   801
  decode_operand(u, &u->operand[0],
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   802
                    u->itab_entry->operand1.type,
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   803
                    u->itab_entry->operand1.size);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   804
  decode_operand(u, &u->operand[1],
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   805
                    u->itab_entry->operand2.type,
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   806
                    u->itab_entry->operand2.size);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   807
  decode_operand(u, &u->operand[2],
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   808
                    u->itab_entry->operand3.type,
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   809
                    u->itab_entry->operand3.size);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   810
  return 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   811
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   812
    
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   813
/* -----------------------------------------------------------------------------
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   814
 * clear_insn() - clear instruction structure
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   815
 * -----------------------------------------------------------------------------
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   816
 */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   817
static void
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   818
clear_insn(register struct ud* u)
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   819
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   820
  u->error     = 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   821
  u->pfx_seg   = 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   822
  u->pfx_opr   = 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   823
  u->pfx_adr   = 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   824
  u->pfx_lock  = 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   825
  u->pfx_repne = 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   826
  u->pfx_rep   = 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   827
  u->pfx_repe  = 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   828
  u->pfx_rex   = 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   829
  u->pfx_str   = 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   830
  u->mnemonic  = UD_Inone;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   831
  u->itab_entry = NULL;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   832
  u->have_modrm = 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   833
  u->br_far    = 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   834
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   835
  memset( &u->operand[ 0 ], 0, sizeof( struct ud_operand ) );
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   836
  memset( &u->operand[ 1 ], 0, sizeof( struct ud_operand ) );
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   837
  memset( &u->operand[ 2 ], 0, sizeof( struct ud_operand ) );
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   838
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   839
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   840
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   841
static inline int
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   842
resolve_pfx_str(struct ud* u)
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   843
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   844
  if (u->pfx_str == 0xf3) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   845
    if (P_STR(u->itab_entry->prefix)) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   846
        u->pfx_rep  = 0xf3;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   847
    } else {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   848
        u->pfx_repe = 0xf3;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   849
    }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   850
  } else if (u->pfx_str == 0xf2) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   851
    u->pfx_repne = 0xf3;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   852
  }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   853
  return 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   854
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   855
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   856
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   857
static int
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   858
resolve_mode( struct ud* u )
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   859
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   860
  int default64;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   861
  /* if in error state, bail out */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   862
  if ( u->error ) return -1; 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   863
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   864
  /* propagate prefix effects */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   865
  if ( u->dis_mode == 64 ) {  /* set 64bit-mode flags */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   866
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   867
    /* Check validity of  instruction m64 */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   868
    if ( P_INV64( u->itab_entry->prefix ) ) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   869
      UDERR(u, "instruction invalid in 64bits\n");
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   870
      return -1;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   871
    }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   872
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   873
    /* effective rex prefix is the  effective mask for the 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   874
     * instruction hard-coded in the opcode map.
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   875
     */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   876
    u->pfx_rex = ( u->pfx_rex & 0x40 ) | 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   877
                 ( u->pfx_rex & REX_PFX_MASK( u->itab_entry->prefix ) ); 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   878
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   879
    /* whether this instruction has a default operand size of 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   880
     * 64bit, also hardcoded into the opcode map.
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   881
     */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   882
    default64 = P_DEF64( u->itab_entry->prefix ); 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   883
    /* calculate effective operand size */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   884
    if ( REX_W( u->pfx_rex ) ) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   885
        u->opr_mode = 64;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   886
    } else if ( u->pfx_opr ) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   887
        u->opr_mode = 16;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   888
    } else {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   889
        /* unless the default opr size of instruction is 64,
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   890
         * the effective operand size in the absence of rex.w
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   891
         * prefix is 32.
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   892
         */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   893
        u->opr_mode = default64 ? 64 : 32;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   894
    }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   895
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   896
    /* calculate effective address size */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   897
    u->adr_mode = (u->pfx_adr) ? 32 : 64;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   898
  } else if ( u->dis_mode == 32 ) { /* set 32bit-mode flags */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   899
    u->opr_mode = ( u->pfx_opr ) ? 16 : 32;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   900
    u->adr_mode = ( u->pfx_adr ) ? 16 : 32;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   901
  } else if ( u->dis_mode == 16 ) { /* set 16bit-mode flags */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   902
    u->opr_mode = ( u->pfx_opr ) ? 32 : 16;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   903
    u->adr_mode = ( u->pfx_adr ) ? 32 : 16;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   904
  }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   905
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   906
  return 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   907
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   908
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   909
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   910
static inline int
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   911
decode_insn(struct ud *u, uint16_t ptr)
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   912
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   913
  UD_ASSERT((ptr & 0x8000) == 0);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   914
  u->itab_entry = &ud_itab[ ptr ];
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   915
  u->mnemonic = u->itab_entry->mnemonic;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   916
  return (resolve_pfx_str(u)  == 0 &&
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   917
          resolve_mode(u)     == 0 &&
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   918
          decode_operands(u)  == 0 &&
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   919
          resolve_mnemonic(u) == 0) ? 0 : -1;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   920
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   921
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   922
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   923
/*
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   924
 * decode_3dnow()
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   925
 *
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   926
 *    Decoding 3dnow is a little tricky because of its strange opcode
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   927
 *    structure. The final opcode disambiguation depends on the last
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   928
 *    byte that comes after the operands have been decoded. Fortunately,
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   929
 *    all 3dnow instructions have the same set of operand types. So we
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   930
 *    go ahead and decode the instruction by picking an arbitrarily chosen
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   931
 *    valid entry in the table, decode the operands, and read the final
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   932
 *    byte to resolve the menmonic.
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   933
 */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   934
static inline int
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   935
decode_3dnow(struct ud* u)
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   936
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   937
  uint16_t ptr;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   938
  UD_ASSERT(u->le->type == UD_TAB__OPC_3DNOW);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   939
  UD_ASSERT(u->le->table[0xc] != 0);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   940
  decode_insn(u, u->le->table[0xc]);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   941
  inp_next(u); 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   942
  if (u->error) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   943
    return -1;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   944
  }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   945
  ptr = u->le->table[inp_curr(u)]; 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   946
  UD_ASSERT((ptr & 0x8000) == 0);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   947
  u->mnemonic = ud_itab[ptr].mnemonic;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   948
  return 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   949
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   950
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   951
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   952
static int
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   953
decode_ssepfx(struct ud *u)
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   954
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   955
  uint8_t idx;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   956
  uint8_t pfx;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   957
 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   958
  /*
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   959
   * String prefixes (f2, f3) take precedence over operand
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   960
   * size prefix (66).
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   961
   */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   962
  pfx = u->pfx_str;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   963
  if (pfx == 0) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   964
    pfx = u->pfx_opr;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   965
  }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   966
  idx = ((pfx & 0xf) + 1) / 2;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   967
  if (u->le->table[idx] == 0) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   968
    idx = 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   969
  }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   970
  if (idx && u->le->table[idx] != 0) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   971
    /*
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   972
     * "Consume" the prefix as a part of the opcode, so it is no
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   973
     * longer exported as an instruction prefix.
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   974
     */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   975
    u->pfx_str = 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   976
    if (pfx == 0x66) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   977
        /* 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   978
         * consume "66" only if it was used for decoding, leaving
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   979
         * it to be used as an operands size override for some
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   980
         * simd instructions.
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   981
         */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   982
        u->pfx_opr = 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   983
    }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   984
  }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   985
  return decode_ext(u, u->le->table[idx]);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   986
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   987
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   988
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   989
/*
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   990
 * decode_ext()
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   991
 *
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   992
 *    Decode opcode extensions (if any)
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   993
 */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   994
static int
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   995
decode_ext(struct ud *u, uint16_t ptr)
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   996
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   997
  uint8_t idx = 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   998
  if ((ptr & 0x8000) == 0) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
   999
    return decode_insn(u, ptr); 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1000
  }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1001
  u->le = &ud_lookup_table_list[(~0x8000 & ptr)];
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1002
  if (u->le->type == UD_TAB__OPC_3DNOW) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1003
    return decode_3dnow(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1004
  }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1005
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1006
  switch (u->le->type) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1007
    case UD_TAB__OPC_MOD:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1008
      /* !11 = 0, 11 = 1 */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1009
      idx = (MODRM_MOD(modrm(u)) + 1) / 4;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1010
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1011
      /* disassembly mode/operand size/address size based tables.
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1012
       * 16 = 0,, 32 = 1, 64 = 2
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1013
       */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1014
    case UD_TAB__OPC_MODE:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1015
      idx = u->dis_mode != 64 ? 0 : 1;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1016
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1017
    case UD_TAB__OPC_OSIZE:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1018
      idx = eff_opr_mode(u->dis_mode, REX_W(u->pfx_rex), u->pfx_opr) / 32;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1019
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1020
    case UD_TAB__OPC_ASIZE:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1021
      idx = eff_adr_mode(u->dis_mode, u->pfx_adr) / 32;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1022
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1023
    case UD_TAB__OPC_X87:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1024
      idx = modrm(u) - 0xC0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1025
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1026
    case UD_TAB__OPC_VENDOR:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1027
      if (u->vendor == UD_VENDOR_ANY) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1028
        /* choose a valid entry */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1029
        idx = (u->le->table[idx] != 0) ? 0 : 1;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1030
      } else if (u->vendor == UD_VENDOR_AMD) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1031
        idx = 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1032
      } else {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1033
        idx = 1;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1034
      }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1035
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1036
    case UD_TAB__OPC_RM:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1037
      idx = MODRM_RM(modrm(u));
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1038
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1039
    case UD_TAB__OPC_REG:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1040
      idx = MODRM_REG(modrm(u));
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1041
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1042
    case UD_TAB__OPC_SSE:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1043
      return decode_ssepfx(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1044
    default:
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1045
      UD_ASSERT(!"not reached");
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1046
      break;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1047
  }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1048
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1049
  return decode_ext(u, u->le->table[idx]);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1050
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1051
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1052
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1053
static int
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1054
decode_opcode(struct ud *u)
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1055
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1056
  uint16_t ptr;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1057
  UD_ASSERT(u->le->type == UD_TAB__OPC_TABLE);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1058
  UD_RETURN_ON_ERROR(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1059
  u->primary_opcode = inp_curr(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1060
  ptr = u->le->table[inp_curr(u)];
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1061
  if (ptr & 0x8000) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1062
    u->le = &ud_lookup_table_list[ptr & ~0x8000];
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1063
    if (u->le->type == UD_TAB__OPC_TABLE) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1064
      inp_next(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1065
      return decode_opcode(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1066
    }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1067
  }
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1068
  return decode_ext(u, ptr);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1069
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1070
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1071
 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1072
/* =============================================================================
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1073
 * ud_decode() - Instruction decoder. Returns the number of bytes decoded.
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1074
 * =============================================================================
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1075
 */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1076
unsigned int
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1077
ud_decode(struct ud *u)
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1078
{
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1079
  inp_start(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1080
  clear_insn(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1081
  u->le = &ud_lookup_table_list[0];
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1082
  u->error = decode_prefixes(u) == -1 || 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1083
             decode_opcode(u)   == -1 ||
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1084
             u->error;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1085
  /* Handle decode error. */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1086
  if (u->error) {
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1087
    /* clear out the decode data. */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1088
    clear_insn(u);
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1089
    /* mark the sequence of bytes as invalid. */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1090
    u->itab_entry = &ud_itab[0]; /* entry 0 is invalid */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1091
    u->mnemonic = u->itab_entry->mnemonic;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1092
  } 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1093
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1094
    /* maybe this stray segment override byte
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1095
     * should be spewed out?
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1096
     */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1097
    if ( !P_SEG( u->itab_entry->prefix ) && 
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1098
            u->operand[0].type != UD_OP_MEM &&
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1099
            u->operand[1].type != UD_OP_MEM )
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1100
        u->pfx_seg = 0;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1101
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1102
  u->insn_offset = u->pc; /* set offset of instruction */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1103
  u->asm_buf_fill = 0;   /* set translation buffer index to 0 */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1104
  u->pc += u->inp_ctr;    /* move program counter by bytes decoded */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1105
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1106
  /* return number of bytes disassembled. */
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1107
  return u->inp_ctr;
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1108
}
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1109
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1110
/*
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1111
vim: set ts=2 sw=2 expandtab
e4a716697bef Added sources of udis86 1.7.2
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
diff changeset
  1112
*/