pred.isa revision 6019:76890d8b28f5
1// -*- mode:c++ -*-
2
3// Copyright (c) 2007-2008 The Florida State University
4// All rights reserved.
5//
6// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are
8// met: redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer;
10// redistributions in binary form must reproduce the above copyright
11// notice, this list of conditions and the following disclaimer in the
12// documentation and/or other materials provided with the distribution;
13// neither the name of the copyright holders nor the names of its
14// contributors may be used to endorse or promote products derived from
15// this software without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28//
29// Authors: Stephen Hines
30
31////////////////////////////////////////////////////////////////////
32//
33// Predicated Instruction Execution
34//
35
36output header {{
37#include <iostream>
38
39    enum ArmPredicateBits {
40        COND_EQ  =   0,
41        COND_NE, //  1
42        COND_CS, //  2
43        COND_CC, //  3
44        COND_MI, //  4
45        COND_PL, //  5
46        COND_VS, //  6
47        COND_VC, //  7
48        COND_HI, //  8
49        COND_LS, //  9
50        COND_GE, // 10
51        COND_LT, // 11
52        COND_GT, // 12
53        COND_LE, // 13
54        COND_AL, // 14
55        COND_NV  // 15
56    };
57
58    inline uint32_t
59    rotate_imm(uint32_t immValue, uint32_t rotateValue)
60    {
61        return ((immValue >> (int)(rotateValue & 31)) |
62                (immValue << (32 - (int)(rotateValue & 31))));
63    }
64
65    inline uint32_t nSet(uint32_t cpsr) { return cpsr & (1<<31); }
66    inline uint32_t zSet(uint32_t cpsr) { return cpsr & (1<<30); }
67    inline uint32_t cSet(uint32_t cpsr) { return cpsr & (1<<29); }
68    inline uint32_t vSet(uint32_t cpsr) { return cpsr & (1<<28); }
69
70    inline bool arm_predicate(uint32_t cpsr, uint32_t predBits)
71    {
72
73        enum ArmPredicateBits armPredBits = (enum ArmPredicateBits) predBits;
74        uint32_t result = 0;
75        switch (armPredBits)
76        {
77            case COND_EQ:
78                result = zSet(cpsr); break;
79            case COND_NE:
80                result = !zSet(cpsr); break;
81            case COND_CS:
82                result = cSet(cpsr); break;
83            case COND_CC:
84                result = !cSet(cpsr); break;
85            case COND_MI:
86                result = nSet(cpsr); break;
87            case COND_PL:
88                result = !nSet(cpsr); break;
89            case COND_VS:
90                result = vSet(cpsr); break;
91            case COND_VC:
92                result = !vSet(cpsr); break;
93            case COND_HI:
94                result = cSet(cpsr) && !zSet(cpsr); break;
95            case COND_LS:
96                result = !cSet(cpsr) || zSet(cpsr); break;
97            case COND_GE:
98                result = (!nSet(cpsr) && !vSet(cpsr)) || (nSet(cpsr) && vSet(cpsr)); break;
99            case COND_LT:
100                result = (nSet(cpsr) && !vSet(cpsr)) || (!nSet(cpsr) && vSet(cpsr)); break;
101            case COND_GT:
102                result = (!nSet(cpsr) && !vSet(cpsr) && !zSet(cpsr)) || (nSet(cpsr) && vSet(cpsr) && !zSet(cpsr)); break;
103            case COND_LE:
104                result = (nSet(cpsr) && !vSet(cpsr)) || (!nSet(cpsr) && vSet(cpsr)) || zSet(cpsr); break;
105            case COND_AL: result = 1; break;
106            case COND_NV: result = 0; break;
107            default:
108                fprintf(stderr, "Unhandled predicate condition: %d\n", armPredBits);
109                exit(1);
110        }
111        if (result)
112            return true;
113        else
114            return false;
115    }
116
117
118    /**
119     * Base class for predicated integer operations.
120     */
121    class PredOp : public ArmStaticInst
122    {
123            protected:
124
125            uint32_t condCode;
126
127            /// Constructor
128            PredOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
129                            ArmStaticInst(mnem, _machInst, __opClass),
130                            condCode(COND_CODE)
131            {
132            }
133
134            std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
135    };
136
137    /**
138     * Base class for predicated immediate operations.
139     */
140    class PredImmOp : public PredOp
141    {
142            protected:
143
144            uint32_t imm;
145            uint32_t rotate;
146            uint32_t rotated_imm;
147            uint32_t rotated_carry;
148
149            /// Constructor
150            PredImmOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
151                            PredOp(mnem, _machInst, __opClass),
152                            imm(IMM), rotate(ROTATE << 1), rotated_imm(0),
153                            rotated_carry(0)
154            {
155                rotated_imm = rotate_imm(imm, rotate);
156                if (rotate != 0)
157                    rotated_carry = (rotated_imm >> 31) & 1;
158            }
159
160            std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
161    };
162
163    /**
164     * Base class for predicated integer operations.
165     */
166    class PredIntOp : public PredOp
167    {
168            protected:
169
170            uint32_t shift_size;
171            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