1 /*
2  * %CopyrightBegin%
3  *
4  * Copyright Ericsson AB 2021. All Rights Reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * %CopyrightEnd%
19  */
20 
21 #include <string>
22 #include <vector>
23 #include <unordered_map>
24 #include <map>
25 
26 extern "C"
27 {
28 #ifdef HAVE_CONFIG_H
29 #    include "config.h"
30 #endif
31 
32 #include "sys.h"
33 #include "erl_vm.h"
34 #include "global.h"
35 
36 #include "beam_jit_common.h"
37 }
38 
39 class ArgVal {
40     BeamOpArg gen_op;
41 
42 public:
43     enum TYPE {
44         u = TAG_u,
45         i = TAG_i,
46         x = TAG_x,
47         y = TAG_y,
48         f = TAG_f,
49         q = TAG_q,
50         e = TAG_r,
51         l = TAG_l /* float register */
52     };
53 
ArgVal(const BeamOpArg & arg)54     ArgVal(const BeamOpArg &arg) {
55         gen_op = arg;
56     }
57 
ArgVal(enum TYPE t,BeamInstr val)58     ArgVal(enum TYPE t, BeamInstr val) {
59         gen_op.type = t;
60         gen_op.val = val;
61     }
62 
ArgVal(unsigned t,BeamInstr val)63     ArgVal(unsigned t, BeamInstr val) {
64 #ifdef DEBUG
65         switch (t) {
66         case TAG_u:
67             break;
68         case TAG_i:
69             break;
70         case TAG_x:
71             break;
72         case TAG_y:
73             break;
74         case TAG_f:
75             break;
76         case TAG_q:
77             break;
78         case TAG_r:
79             break;
80         case TAG_l:
81             break;
82         default:
83             ASSERT(0);
84         }
85 #endif
86 
87         gen_op.type = t;
88         gen_op.val = val;
89     }
90 
getType() const91     constexpr enum TYPE getType() const {
92         return (enum TYPE)gen_op.type;
93     }
94 
getValue() const95     constexpr uint64_t getValue() const {
96         return gen_op.val;
97     }
98 
isMem() const99     constexpr bool isMem() const {
100         return gen_op.type == x || gen_op.type == y;
101     }
102 
isLiteral() const103     constexpr bool isLiteral() const {
104         return gen_op.type == q;
105     }
106 
isImmed() const107     constexpr bool isImmed() const {
108         return gen_op.type == i;
109     }
110 
111     template<typename T>
operator +(T val) const112     ArgVal operator+(T val) const {
113         return ArgVal(gen_op.type, val + gen_op.val);
114     }
115 
116     template<typename T>
operator *(T val) const117     ArgVal operator*(T val) const {
118         return ArgVal(gen_op.type, val * gen_op.val);
119     }
120 
121     enum Relation { none, consecutive, reverse_consecutive };
122 
register_relation(const ArgVal & arg1,const ArgVal & arg2)123     static Relation register_relation(const ArgVal &arg1, const ArgVal &arg2) {
124         TYPE type = arg1.getType();
125         bool same_reg_types =
126                 type == arg2.getType() && (type == TYPE::x || type == TYPE::y);
127         if (!same_reg_types) {
128             return none;
129         } else if (arg1.getValue() + 1 == arg2.getValue()) {
130             return consecutive;
131         } else if (arg1.getValue() == arg2.getValue() + 1) {
132             return reverse_consecutive;
133         } else {
134             return none;
135         }
136     };
137 };
138