static_inst.cc revision 6254
1/* Copyright (c) 2007-2008 The Florida State University
2 * 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 are
6 * met: redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer;
8 * redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution;
11 * neither the name of the copyright holders nor the names of its
12 * contributors may be used to endorse or promote products derived from
13 * this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 * Authors: Stephen Hines
28 */
29
30#include "arch/arm/insts/static_inst.hh"
31
32namespace ArmISA
33{
34static int32_t arm_NEG(int32_t val) { return (val >> 31); }
35static int32_t arm_POS(int32_t val) { return ((~val) >> 31); }
36
37// Shift Rm by an immediate value
38int32_t
39ArmStaticInst::shift_rm_imm(uint32_t base, uint32_t shamt,
40                            uint32_t type, uint32_t cfval) const
41{
42    enum ArmShiftType shiftType;
43    shiftType = (enum ArmShiftType) type;
44
45    switch (shiftType)
46    {
47        case LSL:
48            return (base << shamt);
49        case LSR:
50            if (shamt == 0)
51                return (0);
52            else
53                return (base >> shamt);
54        case ASR:
55            if (shamt == 0)
56                return ((uint32_t) ((int32_t) base >> 31L));
57            else
58                return ((uint32_t) (((int32_t) base) >> shamt));
59        case ROR:
60            //shamt = shamt & 0x1f;
61            if (shamt == 0)
62                return (cfval << 31) | (base >> 1); // RRX
63            else
64                return (base << (32 - shamt)) | (base >> shamt);
65        default:
66            fprintf(stderr, "Unhandled shift type\n");
67            exit(1);
68            break;
69    }
70    return 0;
71}
72
73// Shift Rm by Rs
74int32_t
75ArmStaticInst::shift_rm_rs(uint32_t base, uint32_t shamt,
76                           uint32_t type, uint32_t cfval) const
77{
78    enum ArmShiftType shiftType;
79    shiftType = (enum ArmShiftType) type;
80
81    switch (shiftType)
82    {
83        case LSL:
84            if (shamt == 0)
85                return (base);
86            else if (shamt >= 32)
87                return (0);
88            else
89                return (base << shamt);
90        case LSR:
91            if (shamt == 0)
92                return (base);
93            else if (shamt >= 32)
94                return (0);
95            else
96                return (base >> shamt);
97        case ASR:
98            if (shamt == 0)
99                return base;
100            else if (shamt >= 32)
101                return ((uint32_t) ((int32_t) base >> 31L));
102            else
103                return ((uint32_t) (((int32_t) base) >> (int) shamt));
104        case ROR:
105            shamt = shamt & 0x1f;
106            if (shamt == 0)
107                return (base);
108            else
109                return ((base << (32 - shamt)) | (base >> shamt));
110        default:
111            fprintf(stderr, "Unhandled shift type\n");
112            exit(1);
113            break;
114    }
115    return 0;
116}
117
118
119// Generate C for a shift by immediate
120int32_t
121ArmStaticInst::shift_carry_imm(uint32_t base, uint32_t shamt,
122                               uint32_t type, uint32_t cfval) const
123{
124    enum ArmShiftType shiftType;
125    shiftType = (enum ArmShiftType) type;
126
127    switch (shiftType)
128    {
129        case LSL:
130            return (base >> (32 - shamt)) & 1;
131        case LSR:
132            if (shamt == 0)
133                return (base >> 31) & 1;
134            else
135                return (base >> (shamt - 1)) & 1;
136        case ASR:
137            if (shamt == 0)
138                return (base >> 31L);
139            else
140                return ((uint32_t) (((int32_t) base) >> (shamt - 1))) & 1;
141        case ROR:
142            shamt = shamt & 0x1f;
143            if (shamt == 0)
144                return (base & 1); // RRX
145            else
146                return (base >> (shamt - 1)) & 1;
147        default:
148            fprintf(stderr, "Unhandled shift type\n");
149            exit(1);
150            break;
151
152    }
153    return 0;
154}
155
156
157// Generate C for a shift by Rs
158int32_t
159ArmStaticInst::shift_carry_rs(uint32_t base, uint32_t shamt,
160                              uint32_t type, uint32_t cfval) const
161{
162    enum ArmShiftType shiftType;
163    shiftType = (enum ArmShiftType) type;
164
165    switch (shiftType)
166    {
167        case LSL:
168            if (shamt == 0)
169                return (!!cfval);
170            else if (shamt == 32)
171                return (base & 1);
172            else if (shamt > 32)
173                return (0);
174            else
175                return ((base >> (32 - shamt)) & 1);
176        case LSR:
177            if (shamt == 0)
178                return (!!cfval);
179            else if (shamt == 32)
180                return (base >> 31);
181            else if (shamt > 32)
182                return (0);
183            else
184                return ((base >> (shamt - 1)) & 1);
185        case ASR:
186            if (shamt == 0)
187                return (!!cfval);
188            else if (shamt >= 32)
189                return (base >> 31L);
190            else
191                return (((uint32_t) (((int32_t) base) >> (shamt - 1))) & 1);
192        case ROR:
193            if (shamt == 0)
194                return (!!cfval);
195            shamt = shamt & 0x1f;
196            if (shamt == 0)
197                return (base >> 31); // RRX
198            else
199                return ((base >> (shamt - 1)) & 1);
200        default:
201            fprintf(stderr, "Unhandled shift type\n");
202            exit(1);
203            break;
204
205    }
206    return 0;
207}
208
209
210// Generate the appropriate carry bit for an addition operation
211int32_t
212ArmStaticInst::arm_add_carry(int32_t result, int32_t lhs, int32_t rhs) const
213{
214    if ((lhs | rhs) >> 30)
215        return ((arm_NEG(lhs) && arm_NEG(rhs)) ||
216                (arm_NEG(lhs) && arm_POS(result)) ||
217                (arm_NEG(rhs) && arm_POS(result)));
218
219    return 0;
220}
221
222// Generate the appropriate carry bit for a subtraction operation
223int32_t
224ArmStaticInst::arm_sub_carry(int32_t result, int32_t lhs, int32_t rhs) const
225{
226    if ((lhs >= rhs) || ((rhs | lhs) >> 31))
227        return ((arm_NEG(lhs) && arm_POS(rhs)) ||
228                (arm_NEG(lhs) && arm_POS(result)) ||
229                (arm_POS(rhs) && arm_POS(result)));
230
231    return 0;
232}
233
234int32_t
235ArmStaticInst::arm_add_overflow(int32_t result, int32_t lhs, int32_t rhs) const
236{
237    if ((lhs | rhs) >> 30)
238        return ((arm_NEG(lhs) && arm_NEG(rhs) && arm_POS(result)) ||
239                (arm_POS(lhs) && arm_POS(rhs) && arm_NEG(result)));
240
241    return 0;
242}
243
244int32_t
245ArmStaticInst::arm_sub_overflow(int32_t result, int32_t lhs, int32_t rhs) const
246{
247    if ((lhs >= rhs) || ((rhs | lhs) >> 31))
248        return ((arm_NEG(lhs) && arm_POS(rhs) && arm_POS(result)) ||
249                (arm_POS(lhs) && arm_NEG(rhs) && arm_NEG(result)));
250
251    return 0;
252}
253
254void
255ArmStaticInst::printReg(std::ostream &os, int reg) const
256{
257    if (reg < FP_Base_DepTag) {
258        ccprintf(os, "r%d", reg);
259    }
260    else {
261        ccprintf(os, "f%d", reg - FP_Base_DepTag);
262    }
263}
264
265std::string
266ArmStaticInst::generateDisassembly(Addr pc,
267                                   const SymbolTable *symtab) const
268{
269    std::stringstream ss;
270
271    ccprintf(ss, "%-10s ", mnemonic);
272
273    return ss.str();
274}
275}
276