pred.isa revision 6019
15425Sgblack@eecs.umich.edu// -*- mode:c++ -*-
25425Sgblack@eecs.umich.edu
35425Sgblack@eecs.umich.edu// Copyright (c) 2007-2008 The Florida State University
47087Snate@binkert.org// All rights reserved.
57087Snate@binkert.org//
67087Snate@binkert.org// Redistribution and use in source and binary forms, with or without
77087Snate@binkert.org// modification, are permitted provided that the following conditions are
87087Snate@binkert.org// met: redistributions of source code must retain the above copyright
97087Snate@binkert.org// notice, this list of conditions and the following disclaimer;
107087Snate@binkert.org// redistributions in binary form must reproduce the above copyright
117087Snate@binkert.org// notice, this list of conditions and the following disclaimer in the
125425Sgblack@eecs.umich.edu// documentation and/or other materials provided with the distribution;
137087Snate@binkert.org// neither the name of the copyright holders nor the names of its
147087Snate@binkert.org// contributors may be used to endorse or promote products derived from
157087Snate@binkert.org// this software without specific prior written permission.
167087Snate@binkert.org//
177087Snate@binkert.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
187087Snate@binkert.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
197087Snate@binkert.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
207087Snate@binkert.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
215425Sgblack@eecs.umich.edu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
227087Snate@binkert.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
235425Sgblack@eecs.umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
245425Sgblack@eecs.umich.edu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
255425Sgblack@eecs.umich.edu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
265425Sgblack@eecs.umich.edu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
275425Sgblack@eecs.umich.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
285425Sgblack@eecs.umich.edu//
295425Sgblack@eecs.umich.edu// Authors: Stephen Hines
305425Sgblack@eecs.umich.edu
315425Sgblack@eecs.umich.edu////////////////////////////////////////////////////////////////////
325425Sgblack@eecs.umich.edu//
335425Sgblack@eecs.umich.edu// Predicated Instruction Execution
345425Sgblack@eecs.umich.edu//
355425Sgblack@eecs.umich.edu
365425Sgblack@eecs.umich.eduoutput header {{
375425Sgblack@eecs.umich.edu#include <iostream>
385425Sgblack@eecs.umich.edu
395425Sgblack@eecs.umich.edu    enum ArmPredicateBits {
405425Sgblack@eecs.umich.edu        COND_EQ  =   0,
415425Sgblack@eecs.umich.edu        COND_NE, //  1
425425Sgblack@eecs.umich.edu        COND_CS, //  2
435425Sgblack@eecs.umich.edu        COND_CC, //  3
445425Sgblack@eecs.umich.edu        COND_MI, //  4
455425Sgblack@eecs.umich.edu        COND_PL, //  5
465425Sgblack@eecs.umich.edu        COND_VS, //  6
475425Sgblack@eecs.umich.edu        COND_VC, //  7
487965Sgblack@eecs.umich.edu        COND_HI, //  8
497965Sgblack@eecs.umich.edu        COND_LS, //  9
505425Sgblack@eecs.umich.edu        COND_GE, // 10
515425Sgblack@eecs.umich.edu        COND_LT, // 11
525425Sgblack@eecs.umich.edu        COND_GT, // 12
535425Sgblack@eecs.umich.edu        COND_LE, // 13
547965Sgblack@eecs.umich.edu        COND_AL, // 14
557620Sgblack@eecs.umich.edu        COND_NV  // 15
567965Sgblack@eecs.umich.edu    };
577965Sgblack@eecs.umich.edu
587965Sgblack@eecs.umich.edu    inline uint32_t
597965Sgblack@eecs.umich.edu    rotate_imm(uint32_t immValue, uint32_t rotateValue)
605425Sgblack@eecs.umich.edu    {
617965Sgblack@eecs.umich.edu        return ((immValue >> (int)(rotateValue & 31)) |
627965Sgblack@eecs.umich.edu                (immValue << (32 - (int)(rotateValue & 31))));
637965Sgblack@eecs.umich.edu    }
647965Sgblack@eecs.umich.edu
657965Sgblack@eecs.umich.edu    inline uint32_t nSet(uint32_t cpsr) { return cpsr & (1<<31); }
667965Sgblack@eecs.umich.edu    inline uint32_t zSet(uint32_t cpsr) { return cpsr & (1<<30); }
677965Sgblack@eecs.umich.edu    inline uint32_t cSet(uint32_t cpsr) { return cpsr & (1<<29); }
687965Sgblack@eecs.umich.edu    inline uint32_t vSet(uint32_t cpsr) { return cpsr & (1<<28); }
697965Sgblack@eecs.umich.edu
707965Sgblack@eecs.umich.edu    inline bool arm_predicate(uint32_t cpsr, uint32_t predBits)
715425Sgblack@eecs.umich.edu    {
725425Sgblack@eecs.umich.edu
735425Sgblack@eecs.umich.edu        enum ArmPredicateBits armPredBits = (enum ArmPredicateBits) predBits;
745425Sgblack@eecs.umich.edu        uint32_t result = 0;
755425Sgblack@eecs.umich.edu        switch (armPredBits)
765425Sgblack@eecs.umich.edu        {
775425Sgblack@eecs.umich.edu            case COND_EQ:
785425Sgblack@eecs.umich.edu                result = zSet(cpsr); break;
797620Sgblack@eecs.umich.edu            case COND_NE:
805425Sgblack@eecs.umich.edu                result = !zSet(cpsr); break;
8112236Sgabeblack@google.com            case COND_CS:
825425Sgblack@eecs.umich.edu                result = cSet(cpsr); break;
835425Sgblack@eecs.umich.edu            case COND_CC:
845425Sgblack@eecs.umich.edu                result = !cSet(cpsr); break;
855425Sgblack@eecs.umich.edu            case COND_MI:
867965Sgblack@eecs.umich.edu                result = nSet(cpsr); break;
8712234Sgabeblack@google.com            case COND_PL:
885425Sgblack@eecs.umich.edu                result = !nSet(cpsr); break;
895425Sgblack@eecs.umich.edu            case COND_VS:
905425Sgblack@eecs.umich.edu                result = vSet(cpsr); break;
915425Sgblack@eecs.umich.edu            case COND_VC:
925425Sgblack@eecs.umich.edu                result = !vSet(cpsr); break;
9310474Sandreas.hansson@arm.com            case COND_HI:
9410474Sandreas.hansson@arm.com                result = cSet(cpsr) && !zSet(cpsr); break;
957965Sgblack@eecs.umich.edu            case COND_LS:
967965Sgblack@eecs.umich.edu                result = !cSet(cpsr) || zSet(cpsr); break;
975425Sgblack@eecs.umich.edu            case COND_GE:
985425Sgblack@eecs.umich.edu                result = (!nSet(cpsr) && !vSet(cpsr)) || (nSet(cpsr) && vSet(cpsr)); break;
995425Sgblack@eecs.umich.edu            case COND_LT:
1005425Sgblack@eecs.umich.edu                result = (nSet(cpsr) && !vSet(cpsr)) || (!nSet(cpsr) && vSet(cpsr)); break;
1015425Sgblack@eecs.umich.edu            case COND_GT:
1027975Sgblack@eecs.umich.edu                result = (!nSet(cpsr) && !vSet(cpsr) && !zSet(cpsr)) || (nSet(cpsr) && vSet(cpsr) && !zSet(cpsr)); break;
1037620Sgblack@eecs.umich.edu            case COND_LE:
1045425Sgblack@eecs.umich.edu                result = (nSet(cpsr) && !vSet(cpsr)) || (!nSet(cpsr) && vSet(cpsr)) || zSet(cpsr); break;
1055425Sgblack@eecs.umich.edu            case COND_AL: result = 1; break;
1067965Sgblack@eecs.umich.edu            case COND_NV: result = 0; break;
1075425Sgblack@eecs.umich.edu            default:
1087626Sgblack@eecs.umich.edu                fprintf(stderr, "Unhandled predicate condition: %d\n", armPredBits);
1095425Sgblack@eecs.umich.edu                exit(1);
1105425Sgblack@eecs.umich.edu        }
1115425Sgblack@eecs.umich.edu        if (result)
1125425Sgblack@eecs.umich.edu            return true;
1135425Sgblack@eecs.umich.edu        else
1145425Sgblack@eecs.umich.edu            return false;
1155425Sgblack@eecs.umich.edu    }
1165425Sgblack@eecs.umich.edu
1175425Sgblack@eecs.umich.edu
1185425Sgblack@eecs.umich.edu    /**
1195425Sgblack@eecs.umich.edu     * Base class for predicated integer operations.
1205425Sgblack@eecs.umich.edu     */
1215425Sgblack@eecs.umich.edu    class PredOp : public ArmStaticInst
1225425Sgblack@eecs.umich.edu    {
1235425Sgblack@eecs.umich.edu            protected:
1247620Sgblack@eecs.umich.edu
1257620Sgblack@eecs.umich.edu            uint32_t condCode;
1265425Sgblack@eecs.umich.edu
1275425Sgblack@eecs.umich.edu            /// Constructor
1285425Sgblack@eecs.umich.edu            PredOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
1295425Sgblack@eecs.umich.edu                            ArmStaticInst(mnem, _machInst, __opClass),
1305425Sgblack@eecs.umich.edu                            condCode(COND_CODE)
1315425Sgblack@eecs.umich.edu            {
1325425Sgblack@eecs.umich.edu            }
1335425Sgblack@eecs.umich.edu
1345425Sgblack@eecs.umich.edu            std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
1355425Sgblack@eecs.umich.edu    };
1365425Sgblack@eecs.umich.edu
1377965Sgblack@eecs.umich.edu    /**
1385425Sgblack@eecs.umich.edu     * Base class for predicated immediate operations.
1395425Sgblack@eecs.umich.edu     */
1405425Sgblack@eecs.umich.edu    class PredImmOp : public PredOp
1415425Sgblack@eecs.umich.edu    {
1425425Sgblack@eecs.umich.edu            protected:
1435425Sgblack@eecs.umich.edu
1447965Sgblack@eecs.umich.edu            uint32_t imm;
1459010Snilay@cs.wisc.edu            uint32_t rotate;
1469211Snilay@cs.wisc.edu            uint32_t rotated_imm;
1475425Sgblack@eecs.umich.edu            uint32_t rotated_carry;
1485425Sgblack@eecs.umich.edu
1495425Sgblack@eecs.umich.edu            /// Constructor
1505425Sgblack@eecs.umich.edu            PredImmOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
1515425Sgblack@eecs.umich.edu                            PredOp(mnem, _machInst, __opClass),
1525425Sgblack@eecs.umich.edu                            imm(IMM), rotate(ROTATE << 1), rotated_imm(0),
1535425Sgblack@eecs.umich.edu                            rotated_carry(0)
1545425Sgblack@eecs.umich.edu            {
1557965Sgblack@eecs.umich.edu                rotated_imm = rotate_imm(imm, rotate);
1565425Sgblack@eecs.umich.edu                if (rotate != 0)
1575425Sgblack@eecs.umich.edu                    rotated_carry = (rotated_imm >> 31) & 1;
1585425Sgblack@eecs.umich.edu            }
1595425Sgblack@eecs.umich.edu
1605425Sgblack@eecs.umich.edu            std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
1615425Sgblack@eecs.umich.edu    };
1625425Sgblack@eecs.umich.edu
1635425Sgblack@eecs.umich.edu    /**
1645425Sgblack@eecs.umich.edu     * Base class for predicated integer operations.
1655425Sgblack@eecs.umich.edu     */
1665425Sgblack@eecs.umich.edu    class PredIntOp : public PredOp
1677965Sgblack@eecs.umich.edu    {
1687965Sgblack@eecs.umich.edu            protected:
1697965Sgblack@eecs.umich.edu
1707965Sgblack@eecs.umich.edu            uint32_t shift_size;
1715425Sgblack@eecs.umich.edu            uint32_t shift;
172
173            /// Constructor
174            PredIntOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
175                            PredOp(mnem, _machInst, __opClass),
176                            shift_size(SHIFT_SIZE), shift(SHIFT)
177            {
178            }
179
180            std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
181    };
182
183    /**
184     * Base class for predicated macro-operations.
185     */
186    class PredMacroOp : public PredOp
187    {
188            protected:
189
190            uint32_t numMicroops;
191            StaticInstPtr * microOps;
192
193            /// Constructor
194            PredMacroOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
195                            PredOp(mnem, _machInst, __opClass),
196                            numMicroops(0)
197            {
198                // We rely on the subclasses of this object to handle the
199                // initialization of the micro-operations, since they are
200                // all of variable length
201                flags[IsMacroop] = true;
202            }
203
204            ~PredMacroOp()
205            {
206                if (numMicroops)
207                    delete [] microOps;
208            }
209
210            StaticInstPtr fetchMicroop(MicroPC microPC)
211            {
212                assert(microPC < numMicroops);
213                return microOps[microPC];
214            }
215
216            %(BasicExecPanic)s
217
218            std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
219    };
220
221    /**
222     * Base class for predicated micro-operations.
223     */
224    class PredMicroop : public PredOp
225    {
226            /// Constructor
227            PredMicroop(const char *mnem, MachInst _machInst, OpClass __opClass) :
228                            PredOp(mnem, _machInst, __opClass)
229            {
230                flags[IsMicroop] = true;
231            }
232    };
233
234}};
235
236def template PredOpExecute {{
237    Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
238    {
239        Fault fault = NoFault;
240
241        %(fp_enable_check)s;
242        %(op_decl)s;
243        %(op_rd)s;
244        %(code)s;
245
246        if (arm_predicate(xc->readMiscReg(ArmISA::CPSR), condCode))
247        {
248            if (fault == NoFault)
249            {
250                %(op_wb)s;
251            }
252        }
253        else
254            return NoFault;
255            // Predicated false instructions should not return faults
256
257        return fault;
258    }
259}};
260
261//Outputs to decoder.cc
262output decoder {{
263    std::string PredOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
264    {
265        std::stringstream ss;
266
267        ccprintf(ss, "%-10s ", mnemonic);
268
269        if (_numDestRegs > 0) {
270            printReg(ss, _destRegIdx[0]);
271        }
272
273        ss << ", ";
274
275        if (_numSrcRegs > 0) {
276            printReg(ss, _srcRegIdx[0]);
277            ss << ", ";
278        }
279
280        return ss.str();
281    }
282
283    std::string PredImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
284    {
285        std::stringstream ss;
286
287        ccprintf(ss, "%-10s ", mnemonic);
288
289        if (_numDestRegs > 0) {
290            printReg(ss, _destRegIdx[0]);
291        }
292
293        ss << ", ";
294
295        if (_numSrcRegs > 0) {
296            printReg(ss, _srcRegIdx[0]);
297            ss << ", ";
298        }
299
300        return ss.str();
301    }
302
303    std::string PredIntOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
304    {
305        std::stringstream ss;
306
307        ccprintf(ss, "%-10s ", mnemonic);
308
309        if (_numDestRegs > 0) {
310            printReg(ss, _destRegIdx[0]);
311        }
312
313        ss << ", ";
314
315        if (_numSrcRegs > 0) {
316            printReg(ss, _srcRegIdx[0]);
317            ss << ", ";
318        }
319
320        return ss.str();
321    }
322
323    std::string PredMacroOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
324    {
325        std::stringstream ss;
326
327        ccprintf(ss, "%-10s ", mnemonic);
328
329        return ss.str();
330    }
331
332}};
333
334let {{
335
336    calcCcCode = '''
337        uint16_t _ic, _iv, _iz, _in;
338
339        _in = (resTemp >> 31) & 1;
340        _iz = (resTemp == 0);
341        _iv = %(ivValue)s & 1;
342        _ic = %(icValue)s & 1;
343
344        Cpsr =  _in << 31 | _iz << 30 | _ic << 29 | _iv << 28 |
345            (Cpsr & 0x0FFFFFFF);
346
347        DPRINTF(Arm, "in = %%d\\n", _in);
348        DPRINTF(Arm, "iz = %%d\\n", _iz);
349        DPRINTF(Arm, "ic = %%d\\n", _ic);
350        DPRINTF(Arm, "iv = %%d\\n", _iv);
351        '''
352
353}};
354
355def format PredOp(code, *opt_flags) {{
356    iop = InstObjParams(name, Name, 'PredOp', code, opt_flags)
357    header_output = BasicDeclare.subst(iop)
358    decoder_output = BasicConstructor.subst(iop)
359    decode_block = BasicDecode.subst(iop)
360    exec_output = PredOpExecute.subst(iop)
361}};
362
363def format PredImmOp(code, *opt_flags) {{
364    iop = InstObjParams(name, Name, 'PredImmOp', code, opt_flags)
365    header_output = BasicDeclare.subst(iop)
366    decoder_output = BasicConstructor.subst(iop)
367    decode_block = BasicDecode.subst(iop)
368    exec_output = PredOpExecute.subst(iop)
369}};
370
371def format PredImmOpCc(code, icValue, ivValue, *opt_flags) {{
372    ccCode = calcCcCode % vars()
373    code += ccCode;
374    iop = InstObjParams(name, Name, 'PredImmOp',
375        {"code": code, "cc_code": ccCode}, opt_flags)
376    header_output = BasicDeclare.subst(iop)
377    decoder_output = BasicConstructor.subst(iop)
378    decode_block = BasicDecode.subst(iop)
379    exec_output = PredOpExecute.subst(iop)
380}};
381
382def format PredIntOp(code, *opt_flags) {{
383    new_code = ArmGenericCodeSubs(code)
384    iop = InstObjParams(name, Name, 'PredIntOp', new_code, opt_flags)
385    header_output = BasicDeclare.subst(iop)
386    decoder_output = BasicConstructor.subst(iop)
387    decode_block = BasicDecode.subst(iop)
388    exec_output = PredOpExecute.subst(iop)
389}};
390
391def format PredIntOpCc(code, icValue, ivValue, *opt_flags) {{
392    ccCode = calcCcCode % vars()
393    code += ccCode;
394    new_code = ArmGenericCodeSubs(code)
395    iop = InstObjParams(name, Name, 'PredIntOp',
396        {"code": new_code, "cc_code": ccCode }, opt_flags)
397    header_output = BasicDeclare.subst(iop)
398    decoder_output = BasicConstructor.subst(iop)
399    decode_block = BasicDecode.subst(iop)
400    exec_output = PredOpExecute.subst(iop)
401}};
402
403