1 /* Copyright (c) 2003-2005 MySQL AB
2    Use is subject to license terms
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; version 2 of the License.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program; if not, write to the Free Software
15    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA */
16 
17 #ifndef NDB_INTERPRETER_HPP
18 #define NDB_INTERPRETER_HPP
19 
20 #include <ndb_types.h>
21 
22 class Interpreter {
23 public:
24 
mod4(Uint32 len)25   inline static Uint32 mod4(Uint32 len){
26     return len + ((4 - (len & 3)) & 3);
27   }
28 
29 
30   /**
31    * General Mnemonic format
32    *
33    * i = Instruction            -  5 Bits ( 0 - 5 ) max 63
34    * x = Register 1             -  3 Bits ( 6 - 8 ) max 7
35    * y = Register 2             -  3 Bits ( 9 -11 ) max 7
36    * b = Branch offset (only branches)
37    *
38    *           1111111111222222222233
39    * 01234567890123456789012345678901
40    * iiiiiixxxyyy    bbbbbbbbbbbbbbbb
41    *
42    *
43    */
44 
45   /**
46    * Instructions
47    */
48   STATIC_CONST( READ_ATTR_INTO_REG    = 1 );
49   STATIC_CONST( WRITE_ATTR_FROM_REG   = 2 );
50   STATIC_CONST( LOAD_CONST_NULL       = 3 );
51   STATIC_CONST( LOAD_CONST16          = 4 );
52   STATIC_CONST( LOAD_CONST32          = 5 );
53   STATIC_CONST( LOAD_CONST64          = 6 );
54   STATIC_CONST( ADD_REG_REG           = 7 );
55   STATIC_CONST( SUB_REG_REG           = 8 );
56   STATIC_CONST( BRANCH                = 9 );
57   STATIC_CONST( BRANCH_REG_EQ_NULL    = 10 );
58   STATIC_CONST( BRANCH_REG_NE_NULL    = 11 );
59   STATIC_CONST( BRANCH_EQ_REG_REG     = 12 );
60   STATIC_CONST( BRANCH_NE_REG_REG     = 13 );
61   STATIC_CONST( BRANCH_LT_REG_REG     = 14 );
62   STATIC_CONST( BRANCH_LE_REG_REG     = 15 );
63   STATIC_CONST( BRANCH_GT_REG_REG     = 16 );
64   STATIC_CONST( BRANCH_GE_REG_REG     = 17 );
65   STATIC_CONST( EXIT_OK               = 18 );
66   STATIC_CONST( EXIT_REFUSE           = 19 );
67   STATIC_CONST( CALL                  = 20 );
68   STATIC_CONST( RETURN                = 21 );
69   STATIC_CONST( EXIT_OK_LAST          = 22 );
70   STATIC_CONST( BRANCH_ATTR_OP_ARG    = 23 );
71   STATIC_CONST( BRANCH_ATTR_EQ_NULL   = 24 );
72   STATIC_CONST( BRANCH_ATTR_NE_NULL   = 25 );
73 
74   /**
75    * Macros for creating code
76    */
77   static Uint32 Read(Uint32 AttrId, Uint32 Register);
78   static Uint32 Write(Uint32 AttrId, Uint32 Register);
79 
80   static Uint32 LoadNull(Uint32 Register);
81   static Uint32 LoadConst16(Uint32 Register, Uint32 Value);
82   static Uint32 LoadConst32(Uint32 Register); // Value in next word
83   static Uint32 LoadConst64(Uint32 Register); // Value in next 2 words
84   static Uint32 Add(Uint32 DstReg, Uint32 SrcReg1, Uint32 SrcReg2);
85   static Uint32 Sub(Uint32 DstReg, Uint32 SrcReg1, Uint32 SrcReg2);
86   static Uint32 Branch(Uint32 Inst, Uint32 Reg1, Uint32 Reg2);
87   static Uint32 ExitOK();
88 
89   /**
90    * Branch string
91    *
92    * i = Instruction            -  5 Bits ( 0 - 5 ) max 63
93    * a = Attribute id
94    * l = Length of string
95    * b = Branch offset
96    * t = branch type
97    * d = Array length diff
98    * v = Varchar flag
99    * p = No-blank-padding flag for char compare
100    *
101    *           1111111111222222222233
102    * 01234567890123456789012345678901
103    * iiiiii   ddvtttpbbbbbbbbbbbbbbbb
104    * aaaaaaaaaaaaaaaallllllllllllllll
105    * -string....                    -
106    */
107   enum UnaryCondition {
108     IS_NULL = 0,
109     IS_NOT_NULL = 1
110   };
111 
112   enum BinaryCondition {
113     EQ = 0,
114     NE = 1,
115     LT = 2,
116     LE = 3,
117     GT = 4,
118     GE = 5,
119     LIKE = 6,
120     NOT_LIKE = 7
121   };
122   static Uint32 BranchCol(BinaryCondition cond,
123 			  Uint32 arrayLengthDiff, Uint32 varchar, bool nopad);
124   static Uint32 BranchCol_2(Uint32 AttrId);
125   static Uint32 BranchCol_2(Uint32 AttrId, Uint32 Len);
126 
127   static Uint32 getBinaryCondition(Uint32 op1);
128   static Uint32 getArrayLengthDiff(Uint32 op1);
129   static Uint32 isVarchar(Uint32 op1);
130   static Uint32 isNopad(Uint32 op1);
131   static Uint32 getBranchCol_AttrId(Uint32 op2);
132   static Uint32 getBranchCol_Len(Uint32 op2);
133 
134   /**
135    * Macros for decoding code
136    */
137   static Uint32 getOpCode(Uint32 op);
138   static Uint32 getReg1(Uint32 op);
139   static Uint32 getReg2(Uint32 op);
140   static Uint32 getReg3(Uint32 op);
141 };
142 
143 inline
144 Uint32
Read(Uint32 AttrId,Uint32 Register)145 Interpreter::Read(Uint32 AttrId, Uint32 Register){
146   return (AttrId << 16) + (Register << 6) + READ_ATTR_INTO_REG;
147 }
148 
149 inline
150 Uint32
Write(Uint32 AttrId,Uint32 Register)151 Interpreter::Write(Uint32 AttrId, Uint32 Register){
152   return (AttrId << 16) + (Register << 6) + WRITE_ATTR_FROM_REG;
153 }
154 
155 inline
156 Uint32
LoadConst16(Uint32 Register,Uint32 Value)157 Interpreter::LoadConst16(Uint32 Register, Uint32 Value){
158   return (Value << 16) + (Register << 6) + LOAD_CONST16;
159 }
160 
161 inline
162 Uint32
LoadConst32(Uint32 Register)163 Interpreter::LoadConst32(Uint32 Register){
164   return (Register << 6) + LOAD_CONST32;
165 }
166 
167 inline
168 Uint32
LoadConst64(Uint32 Register)169 Interpreter::LoadConst64(Uint32 Register){
170   return (Register << 6) + LOAD_CONST64;
171 }
172 
173 inline
174 Uint32
Add(Uint32 Dcoleg,Uint32 SrcReg1,Uint32 SrcReg2)175 Interpreter::Add(Uint32 Dcoleg, Uint32 SrcReg1, Uint32 SrcReg2){
176   return (SrcReg1 << 6) + (SrcReg2 << 9) + (Dcoleg << 16) + ADD_REG_REG;
177 }
178 
179 inline
180 Uint32
Sub(Uint32 Dcoleg,Uint32 SrcReg1,Uint32 SrcReg2)181 Interpreter::Sub(Uint32 Dcoleg, Uint32 SrcReg1, Uint32 SrcReg2){
182   return (SrcReg1 << 6) + (SrcReg2 << 9) + (Dcoleg << 16) + SUB_REG_REG;
183 }
184 
185 inline
186 Uint32
Branch(Uint32 Inst,Uint32 Reg1,Uint32 Reg2)187 Interpreter::Branch(Uint32 Inst, Uint32 Reg1, Uint32 Reg2){
188   return (Reg1 << 9) + (Reg2 << 6) + Inst;
189 }
190 
191 inline
192 Uint32
BranchCol(BinaryCondition cond,Uint32 arrayLengthDiff,Uint32 varchar,bool nopad)193 Interpreter::BranchCol(BinaryCondition cond,
194 		       Uint32 arrayLengthDiff,
195 		       Uint32 varchar, bool nopad){
196   //ndbout_c("BranchCol: cond=%d diff=%u varchar=%u nopad=%d",
197       //cond, arrayLengthDiff, varchar, nopad);
198   return
199     BRANCH_ATTR_OP_ARG +
200     (arrayLengthDiff << 9) +
201     (varchar << 11) +
202     (cond << 12) +
203     (nopad << 15);
204 }
205 
206 inline
207 Uint32
BranchCol_2(Uint32 AttrId,Uint32 Len)208 Interpreter::BranchCol_2(Uint32 AttrId, Uint32 Len){
209   return (AttrId << 16) + Len;
210 }
211 
212 inline
213 Uint32
BranchCol_2(Uint32 AttrId)214 Interpreter::BranchCol_2(Uint32 AttrId){
215   return (AttrId << 16);
216 }
217 
218 inline
219 Uint32
getBinaryCondition(Uint32 op)220 Interpreter::getBinaryCondition(Uint32 op){
221   return (op >> 12) & 0x7;
222 }
223 
224 inline
225 Uint32
getArrayLengthDiff(Uint32 op)226 Interpreter::getArrayLengthDiff(Uint32 op){
227   return (op >> 9) & 0x3;
228 }
229 
230 inline
231 Uint32
isVarchar(Uint32 op)232 Interpreter::isVarchar(Uint32 op){
233   return (op >> 11) & 1;
234 }
235 
236 inline
237 Uint32
isNopad(Uint32 op)238 Interpreter::isNopad(Uint32 op){
239   return (op >> 15) & 1;
240 }
241 
242 inline
243 Uint32
getBranchCol_AttrId(Uint32 op)244 Interpreter::getBranchCol_AttrId(Uint32 op){
245   return (op >> 16) & 0xFFFF;
246 }
247 
248 inline
249 Uint32
getBranchCol_Len(Uint32 op)250 Interpreter::getBranchCol_Len(Uint32 op){
251   return op & 0xFFFF;
252 }
253 
254 inline
255 Uint32
ExitOK()256 Interpreter::ExitOK(){
257   return EXIT_OK;
258 }
259 
260 inline
261 Uint32
getOpCode(Uint32 op)262 Interpreter::getOpCode(Uint32 op){
263   return op & 0x3f;
264 }
265 
266 inline
267 Uint32
getReg1(Uint32 op)268 Interpreter::getReg1(Uint32 op){
269   return (op >> 6) & 0x7;
270 }
271 
272 inline
273 Uint32
getReg2(Uint32 op)274 Interpreter::getReg2(Uint32 op){
275   return (op >> 9) & 0x7;
276 }
277 
278 inline
279 Uint32
getReg3(Uint32 op)280 Interpreter::getReg3(Uint32 op){
281   return (op >> 16) & 0x7;
282 }
283 
284 #endif
285