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).index();
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}
250