1// Copyright 2015 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/interpreter/bytecode-register.h"
6
7namespace v8 {
8namespace internal {
9namespace interpreter {
10
11static const int kFirstParamRegisterIndex =
12    (InterpreterFrameConstants::kRegisterFileFromFp -
13     InterpreterFrameConstants::kFirstParamFromFp) /
14    kSystemPointerSize;
15static const int kFunctionClosureRegisterIndex =
16    (InterpreterFrameConstants::kRegisterFileFromFp -
17     StandardFrameConstants::kFunctionOffset) /
18    kSystemPointerSize;
19static const int kCurrentContextRegisterIndex =
20    (InterpreterFrameConstants::kRegisterFileFromFp -
21     StandardFrameConstants::kContextOffset) /
22    kSystemPointerSize;
23static const int kBytecodeArrayRegisterIndex =
24    (InterpreterFrameConstants::kRegisterFileFromFp -
25     InterpreterFrameConstants::kBytecodeArrayFromFp) /
26    kSystemPointerSize;
27static const int kBytecodeOffsetRegisterIndex =
28    (InterpreterFrameConstants::kRegisterFileFromFp -
29     InterpreterFrameConstants::kBytecodeOffsetFromFp) /
30    kSystemPointerSize;
31static const int kCallerPCOffsetRegisterIndex =
32    (InterpreterFrameConstants::kRegisterFileFromFp -
33     InterpreterFrameConstants::kCallerPCOffset) /
34    kSystemPointerSize;
35static const int kArgumentCountRegisterIndex =
36    (InterpreterFrameConstants::kRegisterFileFromFp -
37     InterpreterFrameConstants::kArgCOffset) /
38    kSystemPointerSize;
39
40Register Register::FromParameterIndex(int index) {
41  DCHECK_GE(index, 0);
42  int register_index = kFirstParamRegisterIndex - index;
43  DCHECK_LT(register_index, 0);
44  return Register(register_index);
45}
46
47int Register::ToParameterIndex() const {
48  DCHECK(is_parameter());
49  return kFirstParamRegisterIndex - index();
50}
51
52Register Register::function_closure() {
53  return Register(kFunctionClosureRegisterIndex);
54}
55
56bool Register::is_function_closure() const {
57  return index() == kFunctionClosureRegisterIndex;
58}
59
60Register Register::current_context() {
61  return Register(kCurrentContextRegisterIndex);
62}
63
64bool Register::is_current_context() const {
65  return index() == kCurrentContextRegisterIndex;
66}
67
68Register Register::bytecode_array() {
69  return Register(kBytecodeArrayRegisterIndex);
70}
71
72bool Register::is_bytecode_array() const {
73  return index() == kBytecodeArrayRegisterIndex;
74}
75
76Register Register::bytecode_offset() {
77  return Register(kBytecodeOffsetRegisterIndex);
78}
79
80bool Register::is_bytecode_offset() const {
81  return index() == kBytecodeOffsetRegisterIndex;
82}
83
84// static
85Register Register::virtual_accumulator() {
86  return Register(kCallerPCOffsetRegisterIndex);
87}
88
89// static
90Register Register::argument_count() {
91  return Register(kArgumentCountRegisterIndex);
92}
93
94OperandSize Register::SizeOfOperand() const {
95  int32_t operand = ToOperand();
96  if (operand >= kMinInt8 && operand <= kMaxInt8) {
97    return OperandSize::kByte;
98  } else if (operand >= kMinInt16 && operand <= kMaxInt16) {
99    return OperandSize::kShort;
100  } else {
101    return OperandSize::kQuad;
102  }
103}
104
105bool Register::AreContiguous(Register reg1, Register reg2, Register reg3,
106                             Register reg4, Register reg5) {
107  if (reg1.index() + 1 != reg2.index()) {
108    return false;
109  }
110  if (reg3.is_valid() && reg2.index() + 1 != reg3.index()) {
111    return false;
112  }
113  if (reg4.is_valid() && reg3.index() + 1 != reg4.index()) {
114    return false;
115  }
116  if (reg5.is_valid() && reg4.index() + 1 != reg5.index()) {
117    return false;
118  }
119  return true;
120}
121
122std::string Register::ToString() const {
123  if (is_current_context()) {
124    return std::string("<context>");
125  } else if (is_function_closure()) {
126    return std::string("<closure>");
127  } else if (*this == virtual_accumulator()) {
128    return std::string("<accumulator>");
129  } else if (is_parameter()) {
130    int parameter_index = ToParameterIndex();
131    if (parameter_index == 0) {
132      return std::string("<this>");
133    } else {
134      std::ostringstream s;
135      s << "a" << parameter_index - 1;
136      return s.str();
137    }
138  } else {
139    std::ostringstream s;
140    s << "r" << index();
141    return s.str();
142  }
143}
144
145}  // namespace interpreter
146}  // namespace internal
147}  // namespace v8
148