summaryrefslogtreecommitdiffstats
path: root/src/dex_instruction.h
blob: f1bb7bf1cd69e6ef04e97296bc002a9a2cfd548c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// Copyright 2011 Google Inc. All Rights Reserved.

#ifndef ART_SRC_DEX_INSTRUCTION_H_
#define ART_SRC_DEX_INSTRUCTION_H_

#include "src/globals.h"
#include "src/logging.h"
#include "src/macros.h"

namespace art {

class Instruction {
 public:
  // NOP-encoded switch-statement signatures.
  enum {
    kPackedSwitchSignature = 0x0100,
    kSparseSwitchSignature = 0x0200,
    kArrayDataSignature = 0x0300
  };

  enum Code {
#define INSTRUCTION_ENUM(opcode, cname, p, f, r, i, a) cname = opcode,
#include "src/dex_instruction_list.h"
    DEX_INSTRUCTION_LIST(INSTRUCTION_ENUM)
#undef DEX_INSTRUCTION_LIST
#undef INSTRUCTION_ENUM
  };

  enum InstructionFormat {
    k10x,  // op
    k12x,  // op vA, vB
    k11n,  // op vA, #+B
    k11x,  // op vAA
    k10t,  // op +AA
    k20t,  // op +AAAA
    k22x,  // op vAA, vBBBB
    k21t,  // op vAA, +BBBB
    k21s,  // op vAA, #+BBBB
    k21h,  // op vAA, #+BBBB00000[00000000]
    k21c,  // op vAA, thing@BBBB
    k23x,  // op vAA, vBB, vCC
    k22b,  // op vAA, vBB, #+CC
    k22t,  // op vA, vB, +CCCC
    k22s,  // op vA, vB, #+CCCC
    k22c,  // op vA, vB, thing@CCCC
    k32x,  // op vAAAA, vBBBB
    k30t,  // op +AAAAAAAA
    k31t,  // op vAA, +BBBBBBBB
    k31i,  // op vAA, #+BBBBBBBB
    k31c,  // op vAA, thing@BBBBBBBB
    k35c,  // op {vC, vD, vE, vF, vG}, thing@BBBB (B: count, A: vG)
    k3rc,  // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB
    k51l,  // op vAA, #+BBBBBBBBBBBBBBBB
  };

  enum Flags {
    kBranch   = 0x01,  // conditional or unconditional branch
    kContinue = 0x02,  // flow can continue to next statement
    kSwitch   = 0x04,  // switch statement
    kThrow    = 0x08,  // could cause an exception to be thrown
    kReturn   = 0x10,  // returns, no additional statements
    kInvoke   = 0x20,  // a flavor of invoke
    // TODO: kUnconditional
  };

  // Returns the size in bytes of this instruction.
  size_t Size() const;

  // Returns a pointer to the next instruction in the stream.
  const Instruction* Next() const;

  // Name of the instruction.
  const char* Name() const {
    return kInstructionNames[Opcode()];
  }

  // Returns the opcode field of the instruction.
  Code Opcode() const;

  // Reads an instruction out of the stream at the specified address.
  static Instruction* At(byte* code) {
    CHECK(code != NULL);
    return reinterpret_cast<Instruction*>(code);
  }

  // Returns the format of the current instruction.
  InstructionFormat Format() const {
    return kInstructionFormats[Opcode()];
  }

  // Returns true if this instruction is a branch.
  bool IsBranch() const {
    return (kInstructionFlags[Opcode()] & kBranch) != 0;
  }

  // Determine if the instruction is any of 'return' instructions.
  bool IsReturn() const {
    return (kInstructionFlags[Opcode()] & kReturn) != 0;
  }

  // Determine if this instruction ends execution of its basic block.
  bool IsBasicBlockEnd() const {
    return IsBranch() || IsReturn() || Opcode() == THROW;
  }

  // Determine if this instruction is an invoke.
  bool IsInvoke() const {
    return (kInstructionFlags[Opcode()] & kInvoke) != 0;
  }

 private:
  static const char* const kInstructionNames[];
  static InstructionFormat const kInstructionFormats[];
  static int const kInstructionFlags[];
  DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction);
};

}  // namespace art

#endif  // ART_SRC_DEX_INSTRUCTION_H_