mem.isa revision 7129:0eb03024678f
1// -*- mode:c++ -*-
2
3// Copyright (c) 2010 ARM Limited
4// All rights reserved
5//
6// The license below extends only to copyright in the software and shall
7// not be construed as granting a license to any other intellectual
8// property including but not limited to intellectual property relating
9// to a hardware implementation of the functionality of the software
10// licensed hereunder.  You may use the software subject to the license
11// terms below provided that you ensure that this notice is replicated
12// unmodified and in its entirety in all distributions of the software,
13// modified or unmodified, in source code or in binary form.
14//
15// Copyright (c) 2007-2008 The Florida State University
16// All rights reserved.
17//
18// Redistribution and use in source and binary forms, with or without
19// modification, are permitted provided that the following conditions are
20// met: redistributions of source code must retain the above copyright
21// notice, this list of conditions and the following disclaimer;
22// redistributions in binary form must reproduce the above copyright
23// notice, this list of conditions and the following disclaimer in the
24// documentation and/or other materials provided with the distribution;
25// neither the name of the copyright holders nor the names of its
26// contributors may be used to endorse or promote products derived from
27// this software without specific prior written permission.
28//
29// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40//
41// Authors: Gabe Black
42//          Stephen Hines
43
44////////////////////////////////////////////////////////////////////
45//
46// Memory-format instructions
47//
48
49def template LoadStoreDeclare {{
50    /**
51     * Static instruction class for "%(mnemonic)s".
52     */
53    class %(class_name)s : public %(base_class)s
54    {
55      public:
56
57        /// Constructor.
58        %(class_name)s(ExtMachInst machInst);
59
60        %(BasicExecDeclare)s
61
62        %(InitiateAccDeclare)s
63
64        %(CompleteAccDeclare)s
65    };
66}};
67
68
69def template InitiateAccDeclare {{
70    Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
71}};
72
73
74def template CompleteAccDeclare {{
75    Fault completeAcc(PacketPtr,  %(CPU_exec_context)s *, Trace::InstRecord *) const;
76}};
77
78
79def template LoadStoreConstructor {{
80    inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
81         : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
82    {
83        %(constructor)s;
84    }
85}};
86
87def format AddrMode2(imm) {{
88    if eval(imm):
89        imm = True
90    else:
91        imm = False
92
93    def buildPUBWLCase(p, u, b, w, l):
94        return (p << 4) + (u << 3) + (b << 2) + (w << 1) + (l << 0)
95
96    header_output = decoder_output = exec_output = ""
97    decode_block = "switch(PUBWL) {\n"
98
99    # Loop over all the values of p, u, b, w and l and build instructions and
100    # a decode block for them.
101    for p in (0, 1):
102        for u in (0, 1):
103            for b in (0, 1):
104                for w in (0, 1):
105                    post = (p == 0)
106                    user = (p == 0 and w == 1)
107                    writeback = (p == 0 or w == 1)
108                    add = (u == 1)
109                    if b == 0:
110                        size = 4
111                    else:
112                        size = 1
113                    if add:
114                        addStr = "true"
115                    else:
116                        addStr = "false"
117                    if imm:
118                        newDecode = "return new %s(machInst, RD, RN," + \
119                                                  "%s, machInst.immed11_0);"
120                        loadClass = loadImmClassName(post, add, writeback,
121                                                     size, False, user)
122                        storeClass = storeImmClassName(post, add, writeback,
123                                                       size, False, user)
124                        loadDecode = newDecode % (loadClass, addStr)
125                        storeDecode = newDecode % (storeClass, addStr)
126                    else:
127                        newDecode = "return new %s(machInst, RD, RN, %s," + \
128                                                  "machInst.shiftSize," + \
129                                                  "machInst.shift, RM);"
130                        loadClass = loadRegClassName(post, add, writeback,
131                                                     size, False, user)
132                        storeClass = storeRegClassName(post, add, writeback,
133                                                       size, False, user)
134                        loadDecode = newDecode % (loadClass, addStr)
135                        storeDecode = newDecode % (storeClass, addStr)
136                    decode = '''
137                        case %#x:
138                          {%s}
139                          break;
140                    '''
141                    decode_block += decode % \
142                        (buildPUBWLCase(p,u,b,w,1), loadDecode)
143                    decode_block += decode % \
144                        (buildPUBWLCase(p,u,b,w,0), storeDecode)
145    decode_block += '''
146        default:
147          return new Unknown(machInst);
148        break;
149    }'''
150}};
151
152def format AddrMode3() {{
153    decode = '''
154    {
155        const uint32_t op1 = bits(machInst, 24, 20);
156        const uint32_t op2 = bits(machInst, 6, 5);
157        const uint32_t puiw = bits(machInst, 24, 21);
158        const uint32_t imm = IMMED_HI_11_8 << 4 | IMMED_LO_3_0;
159        switch (op2) {
160          case 0x1:
161            if (op1 & 0x1) {
162                %(ldrh)s
163            } else {
164                %(strh)s
165            }
166          case 0x2:
167            if (op1 & 0x1) {
168                %(ldrsb)s
169            } else {
170                %(ldrd)s
171            }
172          case 0x3:
173            if (op1 & 0x1) {
174                %(ldrsh)s
175            } else {
176                %(strd)s
177            }
178          default:
179            return new Unknown(machInst);
180        }
181    }
182    '''
183
184    def decodePuiwCase(load, d, p, u, i, w, size=4, sign=False):
185        post = (p == 0)
186        user = (p == 0 and w == 1)
187        writeback = (p == 0 or w == 1)
188        add = (u == 1)
189        caseVal = (p << 3) + (u << 2) + (i << 1) + (w << 0)
190        decode = '''
191          case %#x:
192            return new '''% caseVal
193        if add:
194            addStr = "true"
195        else:
196            addStr = "false"
197        if i:
198            if load:
199                if d:
200                    className = loadDoubleImmClassName(post, add, writeback)
201                else:
202                    className = loadImmClassName(post, add, writeback, \
203                                                 size=size, sign=sign, \
204                                                 user=user)
205            else:
206                if d:
207                    className = storeDoubleImmClassName(post, add, writeback)
208                else:
209                    className = storeImmClassName(post, add, writeback, \
210                                                  size=size, sign=sign, \
211                                                  user=user)
212            decode += ("%s(machInst, RT, RN, %s, imm);\n" % \
213                       (className, addStr))
214        else:
215            if load:
216                if d:
217                    className = loadDoubleRegClassName(post, add, writeback)
218                else:
219                    className = loadRegClassName(post, add, writeback, \
220                                                 size=size, sign=sign, \
221                                                 user=user)
222            else:
223                if d:
224                    className = storeDoubleRegClassName(post, add, writeback)
225                else:
226                    className = storeRegClassName(post, add, writeback, \
227                                                  size=size, sign=sign, \
228                                                  user=user)
229            decode += ("%s(machInst, RT, RN, %s, 0, LSL, RM);\n" % \
230                       (className, addStr))
231        return decode
232
233    def decodePuiw(load, d, size=4, sign=False):
234        global decodePuiwCase
235        decode = "switch (puiw) {\n"
236        for p in (0, 1):
237            for u in (0, 1):
238                for i in (0, 1):
239                    for w in (0, 1):
240                        decode += decodePuiwCase(load, d, p, u, i, w,
241                                                 size, sign)
242        decode += '''
243          default:
244            return new Unknown(machInst);
245        }
246        '''
247        return decode
248
249    subs = {
250        "ldrh" : decodePuiw(True, False, size=2),
251        "strh" : decodePuiw(False, False, size=2),
252        "ldrsb" : decodePuiw(True, False, size=1, sign=True),
253        "ldrd" : decodePuiw(True, True),
254        "ldrsh" : decodePuiw(True, False, size=2, sign=True),
255        "strd" : decodePuiw(False, True)
256    }
257    decode_block = decode % subs
258}};
259
260def format Thumb32LoadWord() {{
261    decode = '''
262    {
263        uint32_t op1 = bits(machInst, 24, 23);
264        if (bits(op1, 1) == 0) {
265            uint32_t op2 = bits(machInst, 11, 6);
266            if (HTRN == 0xF) {
267                if (UP) {
268                    return new %(literal_u)s(machInst, RT, INTREG_PC,
269                                             true, IMMED_11_0);
270                } else {
271                    return new %(literal)s(machInst, RT, INTREG_PC,
272                                           false, IMMED_11_0);
273                }
274            } else if (op1 == 0x1) {
275                return new %(imm_pu)s(machInst, RT, RN, true, IMMED_11_0);
276            } else if (op2 == 0) {
277                return new %(register)s(machInst, RT, RN, UP,
278                                        bits(machInst, 5, 4), LSL, RM);
279            } else if ((op2 & 0x3c) == 0x38) {
280                return new %(ldrt)s(machInst, RT, RN, true, IMMED_7_0);
281            } else if ((op2 & 0x3c) == 0x30 || //P
282                       (op2 & 0x24) == 0x24) { //W
283                uint32_t puw = bits(machInst, 10, 8);
284                uint32_t imm = IMMED_7_0;
285                switch (puw) {
286                  case 0:
287                  case 2:
288                    // If we're here, either P or W must have been set.
289                    panic("Neither P or W set, but that "
290                            "shouldn't be possible.\\n");
291                  case 1:
292                    return new %(imm_w)s(machInst, RT, RN, false, imm);
293                  case 3:
294                    return new %(imm_uw)s(machInst, RT, RN, true, imm);
295                  case 4:
296                    return new %(imm_p)s(machInst, RT, RN, false, imm);
297                  case 5:
298                    return new %(imm_pw)s(machInst, RT, RN, false, imm);
299                  case 6:
300                    return new %(imm_pu)s(machInst, RT, RN, true, imm);
301                  case 7:
302                    return new %(imm_puw)s(machInst, RT, RN, true, imm);
303                }
304            }
305        } else {
306            return new Unknown(machInst);
307        }
308    }
309    '''
310    classNames = {
311        "literal_u" : loadImmClassName(False, True, False),
312        "literal" : loadImmClassName(False, False, False),
313        "register" : loadRegClassName(False, True, False),
314        "ldrt" : loadImmClassName(False, True, False, user=True),
315        "imm_w" : loadImmClassName(True, False, True),
316        "imm_uw" : loadImmClassName(True, True, True),
317        "imm_p" : loadImmClassName(False, False, False),
318        "imm_pw" : loadImmClassName(False, False, True),
319        "imm_pu" : loadImmClassName(False, True, False),
320        "imm_puw" : loadImmClassName(False, True, True)
321    }
322    decode_block = decode % classNames
323}};
324
325def format Thumb32StoreSingle() {{
326    def buildPuwDecode(size):
327        puwDecode = '''
328                {
329                    uint32_t puw = bits(machInst, 10, 8);
330                    uint32_t imm = IMMED_7_0;
331                    switch (puw) {
332                      case 0:
333                      case 2:
334                        // If we're here, either P or W must have been set.
335                        panic("Neither P or W set, but that "
336                                "shouldn't be possible.\\n");
337                      case 1:
338                        return new %(imm_w)s(machInst, RT, RN, false, imm);
339                      case 3:
340                        return new %(imm_uw)s(machInst, RT, RN, true, imm);
341                      case 4:
342                        return new %(imm_p)s(machInst, RT, RN, false, imm);
343                      case 5:
344                        return new %(imm_pw)s(machInst, RT, RN, false, imm);
345                      case 6:
346                        return new %(imm_pu)s(machInst, RT, RN, true, imm);
347                      case 7:
348                        return new %(imm_puw)s(machInst, RT, RN, true, imm);
349                    }
350                }
351        '''
352        return puwDecode % {
353            "imm_w" : storeImmClassName(True, False, True, size=size),
354            "imm_uw" : storeImmClassName(True, True, True, size=size),
355            "imm_p" : storeImmClassName(False, False, False, size=size),
356            "imm_pw" : storeImmClassName(False, False, True, size=size),
357            "imm_pu" : storeImmClassName(False, True, False, size=size),
358            "imm_puw" : storeImmClassName(False, True, True, size=size)
359        }
360    decode = '''
361    {
362        uint32_t op1 = bits(machInst, 23, 21);
363        uint32_t op2 = bits(machInst, 11, 6);
364        bool op2Puw = ((op2 & 0x24) == 0x24 ||
365                       (op2 & 0x3c) == 0x30);
366        if (op1 == 4) {
367            return new %(strb_imm)s(machInst, RT, RN, true, IMMED_11_0);
368        } else if (op1 == 0 && op2Puw) {
369            %(strb_puw)s;
370        } else if (op1 == 0 && ((op2 & 0x3c) == 0x38)) {
371            return new %(strbt)s(machInst, RT, RN, true, IMMED_7_0);
372        } else if (op1 == 0 && op2 == 0) {
373            return new %(strb_reg)s(machInst, RT, RN, true,
374                                    bits(machInst, 5, 4), LSL, RM);
375        } else if (op1 == 5) {
376            return new %(strh_imm)s(machInst, RT, RN, true, IMMED_11_0);
377        } else if (op1 == 1 && op2Puw) {
378            %(strh_puw)s;
379        } else if (op1 == 1 && ((op2 & 0x3c) == 0x38)) {
380            return new %(strht)s(machInst, RT, RN, true, IMMED_7_0);
381        } else if (op1 == 1 && op2 == 0) {
382            return new %(strh_reg)s(machInst, RT, RN, true,
383                                    bits(machInst, 5, 4), LSL, RM);
384        } else if (op1 == 6) {
385            return new %(str_imm)s(machInst, RT, RN, true, IMMED_11_0);
386        } else if (op1 == 2 && op2Puw) {
387            %(str_puw)s;
388        } else if (op1 == 2 && ((op2 & 0x3c) == 0x38)) {
389            return new %(strt)s(machInst, RT, RN, true, IMMED_7_0);
390        } else if (op1 == 2 && op2 == 0) {
391            return new %(str_reg)s(machInst, RT, RN, true,
392                                   bits(machInst, 5, 4), LSL, RM);
393        } else {
394            return new Unknown(machInst);
395        }
396    }
397    '''
398    classNames = {
399        "strb_imm" : storeImmClassName(False, True, False, size=1),
400        "strb_puw" : buildPuwDecode(1),
401        "strbt" : storeImmClassName(False, True, False, user=True, size=1),
402        "strb_reg" : storeRegClassName(False, True, False, size=1),
403        "strh_imm" : storeImmClassName(False, True, False, size=2),
404        "strh_puw" : buildPuwDecode(2),
405        "strht" : storeImmClassName(False, True, False, user=True, size=2),
406        "strh_reg" : storeRegClassName(False, True, False, size=2),
407        "str_imm" : storeImmClassName(False, True, False),
408        "str_puw" : buildPuwDecode(4),
409        "strt" : storeImmClassName(False, True, False, user=True),
410        "str_reg" : storeRegClassName(False, True, False)
411    }
412    decode_block = decode % classNames
413}};
414
415def format Thumb16MemReg() {{
416    decode = '''
417    {
418        const uint32_t opb = bits(machInst, 11, 9);
419        const uint32_t rt = bits(machInst, 2, 0);
420        const uint32_t rn = bits(machInst, 5, 3);
421        const uint32_t rm = bits(machInst, 8, 6);
422        switch (opb) {
423          case 0x0:
424            return new %(str)s(machInst, rt, rn, true, 0, LSL, rm);
425          case 0x1:
426            return new %(strh)s(machInst, rt, rn, true, 0, LSL, rm);
427          case 0x2:
428            return new %(strb)s(machInst, rt, rn, true, 0, LSL, rm);
429          case 0x3:
430            return new %(ldrsb)s(machInst, rt, rn, true, 0, LSL, rm);
431          case 0x4:
432            return new %(ldr)s(machInst, rt, rn, true, 0, LSL, rm);
433          case 0x5:
434            return new %(ldrh)s(machInst, rt, rn, true, 0, LSL, rm);
435          case 0x6:
436            return new %(ldrb)s(machInst, rt, rn, true, 0, LSL, rm);
437          case 0x7:
438            return new %(ldrsh)s(machInst, rt, rn, true, 0, LSL, rm);
439        }
440    }
441    '''
442    classNames = {
443        "str" : storeRegClassName(False, True, False),
444        "strh" : storeRegClassName(False, True, False, size=2),
445        "strb" : storeRegClassName(False, True, False, size=1),
446        "ldrsb" : loadRegClassName(False, True, False, sign=True, size=1),
447        "ldr" : loadRegClassName(False, True, False),
448        "ldrh" : loadRegClassName(False, True, False, size=2),
449        "ldrb" : loadRegClassName(False, True, False, size=1),
450        "ldrsh" : loadRegClassName(False, True, False, sign=True, size=2),
451    }
452    decode_block = decode % classNames
453}};
454
455def format Thumb16MemImm() {{
456    decode = '''
457    {
458        const uint32_t opa = bits(machInst, 15, 12);
459        const uint32_t opb = bits(machInst, 11, 9);
460        const uint32_t lrt = bits(machInst, 2, 0);
461        const uint32_t lrn = bits(machInst, 5, 3);
462        const uint32_t hrt = bits(machInst, 10, 8);
463        const uint32_t imm5 = bits(machInst, 10, 6);
464        const uint32_t imm8 = bits(machInst, 7, 0);
465        const bool load = bits(opb, 2);
466        switch (opa) {
467          case 0x6:
468            if (load) {
469                return new %(ldr)s(machInst, lrt, lrn, true, imm5 << 2);
470            } else {
471                return new %(str)s(machInst, lrt, lrn, true, imm5 << 2);
472            }
473          case 0x7:
474            if (load) {
475                return new %(ldrb)s(machInst, lrt, lrn, true, imm5);
476            } else {
477                return new %(strb)s(machInst, lrt, lrn, true, imm5);
478            }
479          case 0x8:
480            if (load) {
481                return new %(ldrh)s(machInst, lrt, lrn, true, imm5 << 1);
482            } else {
483                return new %(strh)s(machInst, lrt, lrn, true, imm5 << 1);
484            }
485          case 0x9:
486            if (load) {
487                return new %(ldr)s(machInst, hrt, INTREG_SP, true, imm8 << 2);
488            } else {
489                return new %(str)s(machInst, hrt, INTREG_SP, true, imm8 << 2);
490            }
491          default:
492            return new Unknown(machInst);
493        }
494    }
495    '''
496    classNames = {
497        "ldr" : loadImmClassName(False, True, False),
498        "str" : storeImmClassName(False, True, False),
499        "ldrh" : loadImmClassName(False, True, False, size=2),
500        "strh" : storeImmClassName(False, True, False, size=2),
501        "ldrb" : loadImmClassName(False, True, False, size=1),
502        "strb" : storeImmClassName(False, True, False, size=1),
503    }
504    decode_block = decode % classNames
505}};
506
507def format Thumb16MemLit() {{
508    decode_block = '''
509    {
510        const uint32_t rt = bits(machInst, 10, 8);
511        const uint32_t imm8 = bits(machInst, 7, 0);
512        return new %s(machInst, rt, INTREG_PC, true, imm8 << 2);
513    }
514    ''' % loadImmClassName(False, True, False)
515}};
516
517def format ArmLoadMemory(memacc_code, ea_code = {{ EA = Rn + disp; }},
518                     mem_flags = [], inst_flags = []) {{
519    ea_code = ArmGenericCodeSubs(ea_code)
520    memacc_code = ArmGenericCodeSubs(memacc_code)
521    (header_output, decoder_output, decode_block, exec_output) = \
522        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
523                      decode_template = BasicDecode,
524                      exec_template_base = 'Load')
525}};
526
527def format ArmStoreMemory(memacc_code, ea_code = {{ EA = Rn + disp; }},
528                     mem_flags = [], inst_flags = []) {{
529    ea_code = ArmGenericCodeSubs(ea_code)
530    memacc_code = ArmGenericCodeSubs(memacc_code)
531    (header_output, decoder_output, decode_block, exec_output) = \
532        LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
533                      exec_template_base = 'Store')
534}};
535
536