1/*
2 * Copyright (c) 2013-2014 ARM Limited
3 * All rights reserved.
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Andrew Bardsley
38 */
39
40#include "cpu/timing_expr.hh"
41
42#include "base/intmath.hh"
43
44TimingExprEvalContext::TimingExprEvalContext(const StaticInstPtr &inst_,
45 ThreadContext *thread_,
46 TimingExprLet *let_) :
47 inst(inst_), thread(thread_), let(let_)
48{
49 /* Reserve space to hold the results of evaluating the
50 * let expressions */
51 if (let) {
52 unsigned int num_defns = let->defns.size();
53
54 results.resize(num_defns, 0);
55 resultAvailable.resize(num_defns, false);
56 }
57}
58
59uint64_t TimingExprSrcReg::eval(TimingExprEvalContext &context)
60{
61 return context.inst->srcRegIdx(index);
61 return context.inst->srcRegIdx(index).regIdx;
62}
63
64uint64_t TimingExprReadIntReg::eval(TimingExprEvalContext &context)
65{
66 return context.thread->readIntReg(reg->eval(context));
67}
68
69uint64_t TimingExprLet::eval(TimingExprEvalContext &context)
70{
71 TimingExprEvalContext new_context(context.inst,
72 context.thread, this);
73
74 return expr->eval(new_context);
75}
76
77uint64_t TimingExprRef::eval(TimingExprEvalContext &context)
78{
79 /* Lookup the result, evaluating if necessary. @todo, this
80 * should have more error checking */
81 if (!context.resultAvailable[index]) {
82 context.results[index] = context.let->defns[index]->eval(context);
83 context.resultAvailable[index] = true;
84 }
85
86 return context.results[index];
87}
88
89uint64_t TimingExprUn::eval(TimingExprEvalContext &context)
90{
91 uint64_t arg_value = arg->eval(context);
92 uint64_t ret = 0;
93
94 switch (op) {
95 case Enums::timingExprSizeInBits:
96 if (arg_value == 0)
97 ret = 0;
98 else
99 ret = ceilLog2(arg_value);
100 break;
101 case Enums::timingExprNot:
102 ret = arg_value != 0;
103 break;
104 case Enums::timingExprInvert:
105 ret = ~arg_value;
106 break;
107 case Enums::timingExprSignExtend32To64:
108 ret = static_cast<int64_t>(
109 static_cast<int32_t>(arg_value));
110 break;
111 case Enums::timingExprAbs:
112 if (static_cast<int64_t>(arg_value) < 0)
113 ret = -arg_value;
114 else
115 ret = arg_value;
116 break;
117 default:
118 break;
119 }
120
121 return ret;
122}
123
124uint64_t TimingExprBin::eval(TimingExprEvalContext &context)
125{
126 uint64_t left_value = left->eval(context);
127 uint64_t right_value = right->eval(context);
128 uint64_t ret = 0;
129
130 switch (op) {
131 case Enums::timingExprAdd:
132 ret = left_value + right_value;
133 break;
134 case Enums::timingExprSub:
135 ret = left_value - right_value;
136 break;
137 case Enums::timingExprUMul:
138 ret = left_value * right_value;
139 break;
140 case Enums::timingExprUDiv:
141 if (right_value != 0) {
142 ret = left_value / right_value;
143 }
144 break;
145 case Enums::timingExprUCeilDiv:
146 if (right_value != 0) {
147 ret = (left_value + (right_value - 1)) / right_value;
148 }
149 break;
150 case Enums::timingExprSMul:
151 ret = static_cast<int64_t>(left_value) *
152 static_cast<int64_t>(right_value);
153 break;
154 case Enums::timingExprSDiv:
155 if (right_value != 0) {
156 ret = static_cast<int64_t>(left_value) /
157 static_cast<int64_t>(right_value);
158 }
159 break;
160 case Enums::timingExprEqual:
161 ret = left_value == right_value;
162 break;
163 case Enums::timingExprNotEqual:
164 ret = left_value != right_value;
165 break;
166 case Enums::timingExprULessThan:
167 ret = left_value < right_value;
168 break;
169 case Enums::timingExprUGreaterThan:
170 ret = left_value > right_value;
171 break;
172 case Enums::timingExprSLessThan:
173 ret = static_cast<int64_t>(left_value) <
174 static_cast<int64_t>(right_value);
175 break;
176 case Enums::timingExprSGreaterThan:
177 ret = static_cast<int64_t>(left_value) >
178 static_cast<int64_t>(right_value);
179 break;
180 case Enums::timingExprAnd:
181 ret = (left_value != 0) && (right_value != 0);
182 break;
183 case Enums::timingExprOr:
184 ret = (left_value != 0) || (right_value != 0);
185 break;
186 default:
187 break;
188 }
189
190 return ret;
191}
192
193uint64_t TimingExprIf::eval(TimingExprEvalContext &context)
194{
195 uint64_t cond_value = cond->eval(context);
196
197 if (cond_value != 0)
198 return trueExpr->eval(context);
199 else
200 return falseExpr->eval(context);
201}
202
203TimingExprLiteral *
204TimingExprLiteralParams::create()
205{
206 return new TimingExprLiteral(this);
207}
208
209TimingExprSrcReg *
210TimingExprSrcRegParams::create()
211{
212 return new TimingExprSrcReg(this);
213}
214
215TimingExprReadIntReg *
216TimingExprReadIntRegParams::create()
217{
218 return new TimingExprReadIntReg(this);
219}
220
221TimingExprLet *
222TimingExprLetParams::create()
223{
224 return new TimingExprLet(this);
225}
226
227TimingExprRef *
228TimingExprRefParams::create()
229{
230 return new TimingExprRef(this);
231}
232
233TimingExprUn *
234TimingExprUnParams::create()
235{
236 return new TimingExprUn(this);
237}
238
239TimingExprBin *
240TimingExprBinParams::create()
241{
242 return new TimingExprBin(this);
243}
244
245TimingExprIf *
246TimingExprIfParams::create()
247{
248 return new TimingExprIf(this);
249}