1/*
2 * Copyright (C) 2018 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#include "Opcode.h"
29#include "OpcodeSize.h"
30
31namespace JSC {
32
33struct Instruction {
34
35 struct Metadata { };
36
37protected:
38 Instruction()
39 { }
40
41private:
42 template<OpcodeSize Width>
43 class Impl {
44 public:
45 OpcodeID opcodeID() const { return static_cast<OpcodeID>(m_opcode); }
46
47 private:
48 typename TypeBySize<Width>::unsignedType m_opcode;
49 };
50
51public:
52 OpcodeID opcodeID() const
53 {
54 if (isWide32())
55 return wide32()->opcodeID();
56 if (isWide16())
57 return wide16()->opcodeID();
58 return narrow()->opcodeID();
59 }
60
61 const char* name() const
62 {
63 return opcodeNames[opcodeID()];
64 }
65
66 bool isWide16() const
67 {
68 return narrow()->opcodeID() == op_wide16;
69 }
70
71 bool isWide32() const
72 {
73 return narrow()->opcodeID() == op_wide32;
74 }
75
76 bool hasMetadata() const
77 {
78 return opcodeID() < NUMBER_OF_BYTECODE_WITH_METADATA;
79 }
80
81 int sizeShiftAmount() const
82 {
83 if (isWide32())
84 return 2;
85 if (isWide16())
86 return 1;
87 return 0;
88 }
89
90 size_t size() const
91 {
92 auto sizeShiftAmount = this->sizeShiftAmount();
93 auto padding = sizeShiftAmount ? 1 : 0;
94 auto size = 1 << sizeShiftAmount;
95 return opcodeLengths[opcodeID()] * size + padding;
96 }
97
98 template<class T>
99 bool is() const
100 {
101 return opcodeID() == T::opcodeID;
102 }
103
104 template<class T>
105 T as() const
106 {
107 ASSERT(is<T>());
108 return T::decode(reinterpret_cast<const uint8_t*>(this));
109 }
110
111 template<class T>
112 T* cast()
113 {
114 ASSERT(is<T>());
115 return bitwise_cast<T*>(this);
116 }
117
118 template<class T>
119 const T* cast() const
120 {
121 ASSERT(is<T>());
122 return reinterpret_cast<const T*>(this);
123 }
124
125 const Impl<OpcodeSize::Narrow>* narrow() const
126 {
127 return reinterpret_cast<const Impl<OpcodeSize::Narrow>*>(this);
128 }
129
130 const Impl<OpcodeSize::Wide16>* wide16() const
131 {
132
133 ASSERT(isWide16());
134 return reinterpret_cast<const Impl<OpcodeSize::Wide16>*>(bitwise_cast<uintptr_t>(this) + 1);
135 }
136
137 const Impl<OpcodeSize::Wide32>* wide32() const
138 {
139
140 ASSERT(isWide32());
141 return reinterpret_cast<const Impl<OpcodeSize::Wide32>*>(bitwise_cast<uintptr_t>(this) + 1);
142 }
143};
144
145} // namespace JSC
146