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// Redistribution and use in source and binary forms, with or without
16// modification, are permitted provided that the following conditions are
17// met: redistributions of source code must retain the above copyright
18// notice, this list of conditions and the following disclaimer;
19// redistributions in binary form must reproduce the above copyright
20// notice, this list of conditions and the following disclaimer in the
21// documentation and/or other materials provided with the distribution;
22// neither the name of the copyright holders nor the names of its
23// contributors may be used to endorse or promote products derived from
24// this software without specific prior written permission.
25//
26// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37//
38// Authors: Gabe Black
39
40let {{
41
42    header_output = ""
43    decoder_output = ""
44    exec_output = ""
45
46    calcQCode = '''
47        CpsrQ = (resTemp & 1) << 27;
48    '''
49
50    calcCcCode = '''
51        uint16_t _iz, _in;
52        _in = (resTemp >> %(negBit)d) & 1;
53        _iz = ((%(zType)s)resTemp == 0);
54
55        CondCodesNZ = (_in << 1) | _iz;
56
57        DPRINTF(Arm, "(in, iz) = (%%d, %%d)\\n", _in, _iz);
58       '''
59
60    def buildMultInst(mnem, doCc, unCc, regs, code, flagType):
61        global header_output, decoder_output, exec_output
62        cCode = carryCode[flagType]
63        vCode = overflowCode[flagType]
64        zType = "uint32_t"
65        negBit = 31
66        if flagType == "llbit":
67            zType = "uint64_t"
68            negBit = 63
69        if flagType == "overflow":
70            ccCode = calcQCode
71        else:
72            ccCode = calcCcCode % {
73                "negBit": negBit,
74                "zType": zType
75            }
76
77        if not regs in (3, 4):
78            raise Exception, "Multiplication instructions with %d " + \
79                             "registers are not implemented"
80
81        if regs == 3:
82            base = 'Mult3'
83        else:
84            base = 'Mult4'
85
86        Name = mnem.capitalize()
87
88        if unCc:
89            iop = InstObjParams(mnem, Name, base,
90                            {"code" : code,
91                             "predicate_test": pickPredicate(code),
92                             "op_class": "IntMultOp" })
93        if doCc:
94            iopCc = InstObjParams(mnem + "s", Name + "Cc", base,
95                              {"code" : code + ccCode,
96                               "predicate_test": pickPredicate(code + ccCode),
97                               "op_class": "IntMultOp" })
98
99        if regs == 3:
100            declare = Mult3Declare
101            constructor = Mult3Constructor
102        else:
103            declare = Mult4Declare
104            constructor = Mult4Constructor
105
106        if unCc:
107            header_output += declare.subst(iop)
108            decoder_output += constructor.subst(iop)
109            exec_output += PredOpExecute.subst(iop)
110        if doCc:
111            header_output += declare.subst(iopCc)
112            decoder_output += constructor.subst(iopCc)
113            exec_output += PredOpExecute.subst(iopCc)
114
115    def buildMult3Inst(mnem, code, flagType = "logic"):
116        buildMultInst(mnem, True, True, 3, code, flagType)
117
118    def buildMult3InstCc(mnem, code, flagType = "logic"):
119        buildMultInst(mnem, True, False, 3, code, flagType)
120
121    def buildMult3InstUnCc(mnem, code, flagType = "logic"):
122        buildMultInst(mnem, False, True, 3, code, flagType)
123
124    def buildMult4Inst(mnem, code, flagType = "logic"):
125        buildMultInst(mnem, True, True, 4, code, flagType)
126
127    def buildMult4InstCc(mnem, code, flagType = "logic"):
128        buildMultInst(mnem, True, False, 4, code, flagType)
129
130    def buildMult4InstUnCc(mnem, code, flagType = "logic"):
131        buildMultInst(mnem, False, True, 4, code, flagType)
132
133    buildMult4Inst    ("mla", "Reg0 = resTemp = Reg1 * Reg2 + Reg3;")
134    buildMult4InstUnCc("mls", "Reg0 = resTemp = Reg3 - Reg1 * Reg2;")
135    buildMult3Inst    ("mul", "Reg0 = resTemp = Reg1 * Reg2;")
136    buildMult4InstCc  ("smlabb", '''Reg0 = resTemp =
137                                        sext<16>(bits(Reg1, 15, 0)) *
138                                        sext<16>(bits(Reg2_sw, 15, 0)) +
139                                        Reg3_sw;
140                                 resTemp = bits(resTemp, 32) !=
141                                           bits(resTemp, 31);
142                                 ''', "overflow")
143    buildMult4InstCc  ("smlabt", '''Reg0 = resTemp =
144                                        sext<16>(bits(Reg1, 15, 0)) *
145                                        sext<16>(bits(Reg2_sw, 31, 16)) +
146                                        Reg3_sw;
147                                 resTemp = bits(resTemp, 32) !=
148                                           bits(resTemp, 31);
149                                 ''', "overflow")
150    buildMult4InstCc  ("smlatb", '''Reg0 = resTemp =
151                                        sext<16>(bits(Reg1, 31, 16)) *
152                                        sext<16>(bits(Reg2_sw, 15, 0)) +
153                                        Reg3_sw;
154                                 resTemp = bits(resTemp, 32) !=
155                                           bits(resTemp, 31);
156                                 ''', "overflow")
157    buildMult4InstCc  ("smlatt", '''Reg0 = resTemp =
158                                        sext<16>(bits(Reg1, 31, 16)) *
159                                        sext<16>(bits(Reg2_sw, 31, 16)) +
160                                        Reg3_sw;
161                                 resTemp = bits(resTemp, 32) !=
162                                           bits(resTemp, 31);
163                                 ''', "overflow")
164    buildMult4InstCc  ("smlad", '''Reg0 = resTemp =
165                                        sext<16>(bits(Reg1, 31, 16)) *
166                                        sext<16>(bits(Reg2, 31, 16)) +
167                                        sext<16>(bits(Reg1, 15, 0)) *
168                                        sext<16>(bits(Reg2, 15, 0)) +
169                                        Reg3_sw;
170                                    resTemp = bits(resTemp, 32) !=
171                                              bits(resTemp, 31);
172                                ''', "overflow")
173    buildMult4InstCc  ("smladx", '''Reg0 = resTemp =
174                                         sext<16>(bits(Reg1, 31, 16)) *
175                                         sext<16>(bits(Reg2, 15, 0)) +
176                                         sext<16>(bits(Reg1, 15, 0)) *
177                                         sext<16>(bits(Reg2, 31, 16)) +
178                                         Reg3_sw;
179                                    resTemp = bits(resTemp, 32) !=
180                                              bits(resTemp, 31);
181                                 ''', "overflow")
182    buildMult4Inst    ("smlal", '''resTemp = sext<32>(Reg2) * sext<32>(Reg3) +
183                                       (int64_t)((Reg1_ud << 32) | Reg0_ud);
184                                   Reg0_ud = (uint32_t)resTemp;
185                                   Reg1_ud = (uint32_t)(resTemp >> 32);
186                                ''', "llbit")
187    buildMult4InstUnCc("smlalbb", '''resTemp = sext<16>(bits(Reg2, 15, 0)) *
188                                               sext<16>(bits(Reg3, 15, 0)) +
189                                               (int64_t)((Reg1_ud << 32) |
190                                                         Reg0_ud);
191                                     Reg0_ud = (uint32_t)resTemp;
192                                     Reg1_ud = (uint32_t)(resTemp >> 32);
193                                  ''')
194    buildMult4InstUnCc("smlalbt", '''resTemp = sext<16>(bits(Reg2, 15, 0)) *
195                                               sext<16>(bits(Reg3, 31, 16)) +
196                                               (int64_t)((Reg1_ud << 32) |
197                                                         Reg0_ud);
198                                     Reg0_ud = (uint32_t)resTemp;
199                                     Reg1_ud = (uint32_t)(resTemp >> 32);
200                                  ''')
201    buildMult4InstUnCc("smlaltb", '''resTemp = sext<16>(bits(Reg2, 31, 16)) *
202                                               sext<16>(bits(Reg3, 15, 0)) +
203                                               (int64_t)((Reg1_ud << 32) |
204                                                         Reg0_ud);
205                                     Reg0_ud = (uint32_t)resTemp;
206                                     Reg1_ud = (uint32_t)(resTemp >> 32);
207                                  ''')
208    buildMult4InstUnCc("smlaltt", '''resTemp = sext<16>(bits(Reg2, 31, 16)) *
209                                               sext<16>(bits(Reg3, 31, 16)) +
210                                               (int64_t)((Reg1_ud << 32) |
211                                                         Reg0_ud);
212                                     Reg0_ud = (uint32_t)resTemp;
213                                     Reg1_ud = (uint32_t)(resTemp >> 32);
214                                  ''')
215    buildMult4InstUnCc("smlald", '''resTemp =
216                                        sext<16>(bits(Reg2, 31, 16)) *
217                                        sext<16>(bits(Reg3, 31, 16)) +
218                                        sext<16>(bits(Reg2, 15, 0)) *
219                                        sext<16>(bits(Reg3, 15, 0)) +
220                                        (int64_t)((Reg1_ud << 32) |
221                                                  Reg0_ud);
222                                    Reg0_ud = (uint32_t)resTemp;
223                                    Reg1_ud = (uint32_t)(resTemp >> 32);
224                                 ''')
225    buildMult4InstUnCc("smlaldx", '''resTemp =
226                                         sext<16>(bits(Reg2, 31, 16)) *
227                                         sext<16>(bits(Reg3, 15, 0)) +
228                                         sext<16>(bits(Reg2, 15, 0)) *
229                                         sext<16>(bits(Reg3, 31, 16)) +
230                                         (int64_t)((Reg1_ud << 32) |
231                                                   Reg0_ud);
232                                     Reg0_ud = (uint32_t)resTemp;
233                                     Reg1_ud = (uint32_t)(resTemp >> 32);
234                                  ''')
235    buildMult4InstCc  ("smlawb", '''Reg0 = resTemp =
236                                        (Reg1_sw *
237                                         sext<16>(bits(Reg2, 15, 0)) +
238                                         ((int64_t)Reg3_sw << 16)) >> 16;
239                                    resTemp = bits(resTemp, 32) !=
240                                              bits(resTemp, 31);
241                                 ''', "overflow")
242    buildMult4InstCc  ("smlawt", '''Reg0 = resTemp =
243                                        (Reg1_sw *
244                                         sext<16>(bits(Reg2, 31, 16)) +
245                                         ((int64_t)Reg3_sw << 16)) >> 16;
246                                    resTemp = bits(resTemp, 32) !=
247                                              bits(resTemp, 31);
248                                 ''', "overflow")
249    buildMult4InstCc  ("smlsd", '''Reg0 = resTemp =
250                                       sext<16>(bits(Reg1, 15, 0)) *
251                                       sext<16>(bits(Reg2, 15, 0)) -
252                                       sext<16>(bits(Reg1, 31, 16)) *
253                                       sext<16>(bits(Reg2, 31, 16)) +
254                                       Reg3_sw;
255                                    resTemp = bits(resTemp, 32) !=
256                                              bits(resTemp, 31);
257                                ''', "overflow")
258    buildMult4InstCc  ("smlsdx", '''Reg0 = resTemp =
259                                        sext<16>(bits(Reg1, 15, 0)) *
260                                        sext<16>(bits(Reg2, 31, 16)) -
261                                        sext<16>(bits(Reg1, 31, 16)) *
262                                        sext<16>(bits(Reg2, 15, 0)) +
263                                        Reg3_sw;
264                                    resTemp = bits(resTemp, 32) !=
265                                              bits(resTemp, 31);
266                                 ''', "overflow")
267    buildMult4InstUnCc("smlsld", '''resTemp =
268                                        sext<16>(bits(Reg2, 15, 0)) *
269                                        sext<16>(bits(Reg3, 15, 0)) -
270                                        sext<16>(bits(Reg2, 31, 16)) *
271                                        sext<16>(bits(Reg3, 31, 16)) +
272                                        (int64_t)((Reg1_ud << 32) |
273                                                  Reg0_ud);
274                                    Reg0_ud = (uint32_t)resTemp;
275                                    Reg1_ud = (uint32_t)(resTemp >> 32);
276                                 ''')
277    buildMult4InstUnCc("smlsldx", '''resTemp =
278                                         sext<16>(bits(Reg2, 15, 0)) *
279                                         sext<16>(bits(Reg3, 31, 16)) -
280                                         sext<16>(bits(Reg2, 31, 16)) *
281                                         sext<16>(bits(Reg3, 15, 0)) +
282                                         (int64_t)((Reg1_ud << 32) |
283                                                   Reg0_ud);
284                                     Reg0_ud = (uint32_t)resTemp;
285                                     Reg1_ud = (uint32_t)(resTemp >> 32);
286                                  ''')
287    buildMult4InstUnCc("smmla", '''Reg0 = resTemp =
288                                       ((int64_t)(Reg3_ud << 32) +
289                                        (int64_t)Reg1_sw *
290                                        (int64_t)Reg2_sw) >> 32;
291                                ''')
292    buildMult4InstUnCc("smmlar", '''Reg0 = resTemp =
293                                        ((int64_t)(Reg3_ud << 32) +
294                                         (int64_t)Reg1_sw *
295                                         (int64_t)Reg2_sw +
296                                         ULL(0x80000000)) >> 32;
297                                 ''')
298    buildMult4InstUnCc("smmls", '''Reg0 = resTemp =
299                                       ((int64_t)(Reg3_ud << 32) -
300                                        (int64_t)Reg1_sw *
301                                        (int64_t)Reg2_sw) >> 32;
302                                ''')
303    buildMult4InstUnCc("smmlsr", '''Reg0 = resTemp =
304                                        ((int64_t)(Reg3_ud << 32) -
305                                         (int64_t)Reg1_sw *
306                                         (int64_t)Reg2_sw +
307                                         ULL(0x80000000)) >> 32;
308                                 ''')
309    buildMult3InstUnCc("smmul", '''Reg0 = resTemp =
310                                       ((int64_t)Reg1_sw *
311                                        (int64_t)Reg2_sw) >> 32;
312                                ''')
313    buildMult3InstUnCc("smmulr", '''Reg0 = resTemp =
314                                        ((int64_t)Reg1_sw *
315                                         (int64_t)Reg2_sw +
316                                         ULL(0x80000000)) >> 32;
317                                 ''')
318    buildMult3InstCc  ("smuad", '''Reg0 = resTemp =
319                                        sext<16>(bits(Reg1, 15, 0)) *
320                                        sext<16>(bits(Reg2, 15, 0)) +
321                                        sext<16>(bits(Reg1, 31, 16)) *
322                                        sext<16>(bits(Reg2, 31, 16));
323                                    resTemp = bits(resTemp, 32) !=
324                                              bits(resTemp, 31);
325                                ''', "overflow")
326    buildMult3InstCc  ("smuadx", '''Reg0 = resTemp =
327                                        sext<16>(bits(Reg1, 15, 0)) *
328                                        sext<16>(bits(Reg2, 31, 16)) +
329                                        sext<16>(bits(Reg1, 31, 16)) *
330                                        sext<16>(bits(Reg2, 15, 0));
331                                    resTemp = bits(resTemp, 32) !=
332                                              bits(resTemp, 31);
333                                 ''', "overflow")
334    buildMult3InstUnCc("smulbb", '''Reg0 = resTemp =
335                                         sext<16>(bits(Reg1, 15, 0)) *
336                                         sext<16>(bits(Reg2, 15, 0));
337                                 ''')
338    buildMult3InstUnCc("smulbt", '''Reg0 = resTemp =
339                                         sext<16>(bits(Reg1, 15, 0)) *
340                                         sext<16>(bits(Reg2, 31, 16));
341                                 ''')
342    buildMult3InstUnCc("smultb", '''Reg0 = resTemp =
343                                         sext<16>(bits(Reg1, 31, 16)) *
344                                         sext<16>(bits(Reg2, 15, 0));
345                                 ''')
346    buildMult3InstUnCc("smultt", '''Reg0 = resTemp =
347                                         sext<16>(bits(Reg1, 31, 16)) *
348                                         sext<16>(bits(Reg2, 31, 16));
349                                 ''')
350    buildMult4Inst    ("smull", '''resTemp = (int64_t)Reg2_sw *
351                                             (int64_t)Reg3_sw;
352                                   Reg1 = (int32_t)(resTemp >> 32);
353                                   Reg0 = (int32_t)resTemp;
354                                ''', "llbit")
355    buildMult3InstUnCc("smulwb", '''Reg0 = resTemp =
356                                        (Reg1_sw *
357                                         sext<16>(bits(Reg2, 15, 0))) >> 16;
358                                 ''')
359    buildMult3InstUnCc("smulwt", '''Reg0 = resTemp =
360                                        (Reg1_sw *
361                                         sext<16>(bits(Reg2, 31, 16))) >> 16;
362                                 ''')
363    buildMult3InstUnCc("smusd", '''Reg0 = resTemp =
364                                        sext<16>(bits(Reg1, 15, 0)) *
365                                        sext<16>(bits(Reg2, 15, 0)) -
366                                        sext<16>(bits(Reg1, 31, 16)) *
367                                        sext<16>(bits(Reg2, 31, 16));
368                                ''')
369    buildMult3InstUnCc("smusdx", '''Reg0 = resTemp =
370                                        sext<16>(bits(Reg1, 15, 0)) *
371                                        sext<16>(bits(Reg2, 31, 16)) -
372                                        sext<16>(bits(Reg1, 31, 16)) *
373                                        sext<16>(bits(Reg2, 15, 0));
374                                 ''')
375    buildMult4InstUnCc("umaal", '''resTemp = Reg2_ud * Reg3_ud +
376                                             Reg0_ud + Reg1_ud;
377                                   Reg1_ud = (uint32_t)(resTemp >> 32);
378                                   Reg0_ud = (uint32_t)resTemp;
379                                ''')
380    buildMult4Inst    ("umlal", '''resTemp = Reg2_ud * Reg3_ud + Reg0_ud +
381                                             (Reg1_ud << 32);
382                                   Reg1_ud = (uint32_t)(resTemp >> 32);
383                                   Reg0_ud = (uint32_t)resTemp;
384                                ''', "llbit")
385    buildMult4Inst    ("umull", '''resTemp = Reg2_ud * Reg3_ud;
386                                   Reg1 = (uint32_t)(resTemp >> 32);
387                                   Reg0 = (uint32_t)resTemp;
388                                ''', "llbit")
389}};
390