pred_inst.hh revision 7853:69aae4379062
18999Suri.wiener@arm.com/*
28999Suri.wiener@arm.com * Copyright (c) 2010 ARM Limited
38999Suri.wiener@arm.com * All rights reserved
48999Suri.wiener@arm.com *
58999Suri.wiener@arm.com * The license below extends only to copyright in the software and shall
68999Suri.wiener@arm.com * not be construed as granting a license to any other intellectual
78999Suri.wiener@arm.com * property including but not limited to intellectual property relating
88999Suri.wiener@arm.com * to a hardware implementation of the functionality of the software
98999Suri.wiener@arm.com * licensed hereunder.  You may use the software subject to the license
108999Suri.wiener@arm.com * terms below provided that you ensure that this notice is replicated
118999Suri.wiener@arm.com * unmodified and in its entirety in all distributions of the software,
128999Suri.wiener@arm.com * modified or unmodified, in source code or in binary form.
138999Suri.wiener@arm.com *
148999Suri.wiener@arm.com * Copyright (c) 2007-2008 The Florida State University
158999Suri.wiener@arm.com * All rights reserved.
168999Suri.wiener@arm.com *
178999Suri.wiener@arm.com * Redistribution and use in source and binary forms, with or without
188999Suri.wiener@arm.com * modification, are permitted provided that the following conditions are
198999Suri.wiener@arm.com * met: redistributions of source code must retain the above copyright
208999Suri.wiener@arm.com * notice, this list of conditions and the following disclaimer;
218999Suri.wiener@arm.com * redistributions in binary form must reproduce the above copyright
228999Suri.wiener@arm.com * notice, this list of conditions and the following disclaimer in the
238999Suri.wiener@arm.com * documentation and/or other materials provided with the distribution;
248999Suri.wiener@arm.com * neither the name of the copyright holders nor the names of its
258999Suri.wiener@arm.com * contributors may be used to endorse or promote products derived from
268999Suri.wiener@arm.com * this software without specific prior written permission.
278999Suri.wiener@arm.com *
288999Suri.wiener@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
298999Suri.wiener@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
308999Suri.wiener@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
318999Suri.wiener@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
328999Suri.wiener@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
338999Suri.wiener@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
348999Suri.wiener@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
358999Suri.wiener@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
368999Suri.wiener@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
378999Suri.wiener@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
388999Suri.wiener@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
398999Suri.wiener@arm.com *
408999Suri.wiener@arm.com * Authors: Stephen Hines
418999Suri.wiener@arm.com */
428999Suri.wiener@arm.com#ifndef __ARCH_ARM_INSTS_PREDINST_HH__
438999Suri.wiener@arm.com#define __ARCH_ARM_INSTS_PREDINST_HH__
448999Suri.wiener@arm.com
458999Suri.wiener@arm.com#include "arch/arm/insts/static_inst.hh"
468999Suri.wiener@arm.com#include "base/trace.hh"
478999Suri.wiener@arm.com
488999Suri.wiener@arm.comnamespace ArmISA
498999Suri.wiener@arm.com{
508999Suri.wiener@arm.comstatic inline uint32_t
518999Suri.wiener@arm.comrotate_imm(uint32_t immValue, int rotateValue)
528999Suri.wiener@arm.com{
538999Suri.wiener@arm.com    return ((immValue >> (rotateValue & 31)) |
548999Suri.wiener@arm.com            (immValue << (32 - (rotateValue & 31))));
558999Suri.wiener@arm.com}
568999Suri.wiener@arm.com
578999Suri.wiener@arm.comstatic inline uint32_t
588999Suri.wiener@arm.commodified_imm(uint8_t ctrlImm, uint8_t dataImm)
598999Suri.wiener@arm.com{
609528Ssascha.bischoff@arm.com    uint32_t bigData = dataImm;
618999Suri.wiener@arm.com    uint32_t bigCtrl = ctrlImm;
628999Suri.wiener@arm.com    if (bigCtrl < 4) {
638999Suri.wiener@arm.com        switch (bigCtrl) {
648999Suri.wiener@arm.com          case 0:
658999Suri.wiener@arm.com            return bigData;
668999Suri.wiener@arm.com          case 1:
678999Suri.wiener@arm.com            return bigData | (bigData << 16);
688999Suri.wiener@arm.com          case 2:
698999Suri.wiener@arm.com            return (bigData << 8) | (bigData << 24);
708999Suri.wiener@arm.com          case 3:
718999Suri.wiener@arm.com            return (bigData << 0) | (bigData << 8) |
728999Suri.wiener@arm.com                   (bigData << 16) | (bigData << 24);
738999Suri.wiener@arm.com        }
748999Suri.wiener@arm.com    }
758999Suri.wiener@arm.com    bigCtrl = (bigCtrl << 1) | ((bigData >> 7) & 0x1);
768999Suri.wiener@arm.com    bigData |= (1 << 7);
778999Suri.wiener@arm.com    return bigData << (32 - bigCtrl);
788999Suri.wiener@arm.com}
798999Suri.wiener@arm.com
808999Suri.wiener@arm.comstatic inline uint64_t
818999Suri.wiener@arm.comsimd_modified_imm(bool op, uint8_t cmode, uint8_t data, bool &immValid)
828999Suri.wiener@arm.com{
838999Suri.wiener@arm.com    uint64_t bigData = data;
848999Suri.wiener@arm.com    immValid = true;
858999Suri.wiener@arm.com    switch (cmode) {
868999Suri.wiener@arm.com      case 0x0:
878999Suri.wiener@arm.com      case 0x1:
888999Suri.wiener@arm.com        bigData = (bigData << 0) | (bigData << 32);
898999Suri.wiener@arm.com        break;
908999Suri.wiener@arm.com      case 0x2:
918999Suri.wiener@arm.com      case 0x3:
928999Suri.wiener@arm.com        bigData = (bigData << 8) | (bigData << 40);
938999Suri.wiener@arm.com        break;
948999Suri.wiener@arm.com      case 0x4:
958999Suri.wiener@arm.com      case 0x5:
968999Suri.wiener@arm.com        bigData = (bigData << 16) | (bigData << 48);
978999Suri.wiener@arm.com        break;
988999Suri.wiener@arm.com      case 0x6:
998999Suri.wiener@arm.com      case 0x7:
1008999Suri.wiener@arm.com        bigData = (bigData << 24) | (bigData << 56);
1018999Suri.wiener@arm.com        break;
1028999Suri.wiener@arm.com      case 0x8:
1038999Suri.wiener@arm.com      case 0x9:
1048999Suri.wiener@arm.com        bigData = (bigData << 0) | (bigData << 16) |
1058999Suri.wiener@arm.com                  (bigData << 32) | (bigData << 48);
1068999Suri.wiener@arm.com        break;
1078999Suri.wiener@arm.com      case 0xa:
1088999Suri.wiener@arm.com      case 0xb:
1098999Suri.wiener@arm.com        bigData = (bigData << 8) | (bigData << 24) |
1108999Suri.wiener@arm.com                  (bigData << 40) | (bigData << 56);
1118999Suri.wiener@arm.com        break;
1128999Suri.wiener@arm.com      case 0xc:
1138999Suri.wiener@arm.com        bigData = (0xffULL << 0) | (bigData << 8) |
1148999Suri.wiener@arm.com                  (0xffULL << 32) | (bigData << 40);
1158999Suri.wiener@arm.com        break;
1168999Suri.wiener@arm.com      case 0xd:
1178999Suri.wiener@arm.com        bigData = (0xffffULL << 0) | (bigData << 16) |
1188999Suri.wiener@arm.com                  (0xffffULL << 32) | (bigData << 48);
1198999Suri.wiener@arm.com        break;
1208999Suri.wiener@arm.com      case 0xe:
1218999Suri.wiener@arm.com        if (op) {
1228999Suri.wiener@arm.com            bigData = 0;
1238999Suri.wiener@arm.com            for (int i = 7; i >= 0; i--) {
1248999Suri.wiener@arm.com                if (bits(data, i)) {
1258999Suri.wiener@arm.com                    bigData |= (ULL(0xFF) << (i * 8));
1268999Suri.wiener@arm.com                }
1278999Suri.wiener@arm.com            }
1288999Suri.wiener@arm.com        } else {
1298999Suri.wiener@arm.com            bigData = (bigData << 0)  | (bigData << 8)  |
1308999Suri.wiener@arm.com                      (bigData << 16) | (bigData << 24) |
1318999Suri.wiener@arm.com                      (bigData << 32) | (bigData << 40) |
1328999Suri.wiener@arm.com                      (bigData << 48) | (bigData << 56);
1338999Suri.wiener@arm.com        }
1348999Suri.wiener@arm.com        break;
1358999Suri.wiener@arm.com      case 0xf:
1368999Suri.wiener@arm.com        if (!op) {
1378999Suri.wiener@arm.com            uint64_t bVal = bits(bigData, 6) ? (0x1F) : (0x20);
1388999Suri.wiener@arm.com            bigData = (bits(bigData, 5, 0) << 19) |
1398999Suri.wiener@arm.com                      (bVal << 25) | (bits(bigData, 7) << 31);
1408999Suri.wiener@arm.com            bigData |= (bigData << 32);
1418999Suri.wiener@arm.com            break;
1428999Suri.wiener@arm.com        }
1438999Suri.wiener@arm.com        // Fall through, immediate encoding is invalid.
1448999Suri.wiener@arm.com      default:
1458999Suri.wiener@arm.com        immValid = false;
1468999Suri.wiener@arm.com        break;
1478999Suri.wiener@arm.com    }
1488999Suri.wiener@arm.com    return bigData;
1498999Suri.wiener@arm.com}
1508999Suri.wiener@arm.com
1518999Suri.wiener@arm.comstatic inline uint64_t
1528999Suri.wiener@arm.comvfp_modified_imm(uint8_t data, bool wide)
1538999Suri.wiener@arm.com{
1548999Suri.wiener@arm.com    uint64_t bigData = data;
1558999Suri.wiener@arm.com    uint64_t repData;
1568999Suri.wiener@arm.com    if (wide) {
1578999Suri.wiener@arm.com        repData = bits(data, 6) ? 0xFF : 0;
1588999Suri.wiener@arm.com        bigData = (bits(bigData, 5, 0) << 48) |
1598999Suri.wiener@arm.com                  (repData << 54) | (bits(~bigData, 6) << 62) |
1608999Suri.wiener@arm.com                  (bits(bigData, 7) << 63);
1618999Suri.wiener@arm.com    } else {
1628999Suri.wiener@arm.com        repData = bits(data, 6) ? 0x1F : 0;
1638999Suri.wiener@arm.com        bigData = (bits(bigData, 5, 0) << 19) |
1648999Suri.wiener@arm.com                  (repData << 25) | (bits(~bigData, 6) << 30) |
1658999Suri.wiener@arm.com                  (bits(bigData, 7) << 31);
1668999Suri.wiener@arm.com    }
1678999Suri.wiener@arm.com    return bigData;
1688999Suri.wiener@arm.com}
1698999Suri.wiener@arm.com
1708999Suri.wiener@arm.com
1718999Suri.wiener@arm.com/**
1728999Suri.wiener@arm.com * Base class for predicated integer operations.
1738999Suri.wiener@arm.com */
1748999Suri.wiener@arm.comclass PredOp : public ArmStaticInst
1758999Suri.wiener@arm.com{
1768999Suri.wiener@arm.com  protected:
1778999Suri.wiener@arm.com
1788999Suri.wiener@arm.com    ConditionCode condCode;
1798999Suri.wiener@arm.com
1809528Ssascha.bischoff@arm.com    /// Constructor
181    PredOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
182           ArmStaticInst(mnem, _machInst, __opClass),
183           condCode(machInst.itstateMask ?
184                   (ConditionCode)(uint8_t)machInst.itstateCond :
185                   (ConditionCode)(unsigned)machInst.condCode)
186    {
187    }
188};
189
190/**
191 * Base class for predicated immediate operations.
192 */
193class PredImmOp : public PredOp
194{
195    protected:
196
197    uint32_t imm;
198    uint32_t rotated_imm;
199    uint32_t rotated_carry;
200    uint32_t rotate;
201
202    /// Constructor
203    PredImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
204              PredOp(mnem, _machInst, __opClass),
205              imm(machInst.imm), rotated_imm(0), rotated_carry(0),
206              rotate(machInst.rotate << 1)
207    {
208        rotated_imm = rotate_imm(imm, rotate);
209        if (rotate != 0)
210            rotated_carry = bits(rotated_imm, 31);
211    }
212
213    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
214};
215
216/**
217 * Base class for predicated integer operations.
218 */
219class PredIntOp : public PredOp
220{
221    protected:
222
223    uint32_t shift_size;
224    uint32_t shift;
225
226    /// Constructor
227    PredIntOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
228              PredOp(mnem, _machInst, __opClass),
229              shift_size(machInst.shiftSize), shift(machInst.shift)
230    {
231    }
232
233    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
234};
235
236class DataImmOp : public PredOp
237{
238  protected:
239    IntRegIndex dest, op1;
240    uint32_t imm;
241    // Whether the carry flag should be modified if that's an option for
242    // this instruction.
243    bool rotC;
244
245    DataImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
246              IntRegIndex _dest, IntRegIndex _op1, uint32_t _imm, bool _rotC) :
247        PredOp(mnem, _machInst, __opClass),
248        dest(_dest), op1(_op1), imm(_imm), rotC(_rotC)
249    {}
250
251    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
252};
253
254class DataRegOp : public PredOp
255{
256  protected:
257    IntRegIndex dest, op1, op2;
258    int32_t shiftAmt;
259    ArmShiftType shiftType;
260
261    DataRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
262              IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2,
263              int32_t _shiftAmt, ArmShiftType _shiftType) :
264        PredOp(mnem, _machInst, __opClass),
265        dest(_dest), op1(_op1), op2(_op2),
266        shiftAmt(_shiftAmt), shiftType(_shiftType)
267    {}
268
269    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
270};
271
272class DataRegRegOp : public PredOp
273{
274  protected:
275    IntRegIndex dest, op1, op2, shift;
276    ArmShiftType shiftType;
277
278    DataRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
279                 IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2,
280                 IntRegIndex _shift, ArmShiftType _shiftType) :
281        PredOp(mnem, _machInst, __opClass),
282        dest(_dest), op1(_op1), op2(_op2), shift(_shift),
283        shiftType(_shiftType)
284    {}
285
286    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
287};
288
289/**
290 * Base class for predicated macro-operations.
291 */
292class PredMacroOp : public PredOp
293{
294    protected:
295
296    uint32_t numMicroops;
297    StaticInstPtr * microOps;
298
299    /// Constructor
300    PredMacroOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
301                PredOp(mnem, _machInst, __opClass),
302                numMicroops(0)
303    {
304        // We rely on the subclasses of this object to handle the
305        // initialization of the micro-operations, since they are
306        // all of variable length
307        flags[IsMacroop] = true;
308    }
309
310    ~PredMacroOp()
311    {
312        if (numMicroops)
313            delete [] microOps;
314    }
315
316    StaticInstPtr
317    fetchMicroop(MicroPC microPC) const
318    {
319        assert(microPC < numMicroops);
320        return microOps[microPC];
321    }
322
323    std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
324};
325
326/**
327 * Base class for predicated micro-operations.
328 */
329class PredMicroop : public PredOp
330{
331    /// Constructor
332    PredMicroop(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
333                PredOp(mnem, _machInst, __opClass)
334    {
335        flags[IsMicroop] = true;
336    }
337
338    void
339    advancePC(PCState &pcState) const
340    {
341        if (flags[IsLastMicroop])
342            pcState.uEnd();
343        else
344            pcState.uAdvance();
345    }
346};
347}
348
349#endif //__ARCH_ARM_INSTS_PREDINST_HH__
350