xref: /qemu/target/mips/tcg/mxu_translate.c (revision 3cc72cdb)
1 /*
2  *  Ingenic XBurst Media eXtension Unit (MXU) translation routines.
3  *
4  *  Copyright (c) 2004-2005 Jocelyn Mayer
5  *  Copyright (c) 2006 Marius Groeger (FPU operations)
6  *  Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7  *  Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
8  *  Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
9  *
10  * SPDX-License-Identifier: LGPL-2.1-or-later
11  *
12  * Datasheet:
13  *
14  *   "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
15  *   Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2, 2017
16  */
17 
18 #include "qemu/osdep.h"
19 #include "translate.h"
20 
21 /*
22  *
23  *       AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
24  *       ============================================
25  *
26  *
27  * MXU (full name: MIPS eXtension/enhanced Unit) is a SIMD extension of MIPS32
28  * instructions set. It is designed to fit the needs of signal, graphical and
29  * video processing applications. MXU instruction set is used in Xburst family
30  * of microprocessors by Ingenic.
31  *
32  * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
33  * the control register.
34  *
35  *
36  *     The notation used in MXU assembler mnemonics
37  *     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
38  *
39  *  Register operands:
40  *
41  *   XRa, XRb, XRc, XRd - MXU registers
42  *   Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
43  *
44  *  Non-register operands:
45  *
46  *   aptn1 - 1-bit accumulate add/subtract pattern
47  *   aptn2 - 2-bit accumulate add/subtract pattern
48  *   eptn2 - 2-bit execute add/subtract pattern
49  *   optn2 - 2-bit operand pattern
50  *   optn3 - 3-bit operand pattern
51  *   sft4  - 4-bit shift amount
52  *   strd2 - 2-bit stride amount
53  *
54  *  Prefixes:
55  *
56  *   Level of parallelism:                Operand size:
57  *    S - single operation at a time       32 - word
58  *    D - two operations in parallel       16 - half word
59  *    Q - four operations in parallel       8 - byte
60  *
61  *  Operations:
62  *
63  *   ADD   - Add or subtract
64  *   ADDC  - Add with carry-in
65  *   ACC   - Accumulate
66  *   ASUM  - Sum together then accumulate (add or subtract)
67  *   ASUMC - Sum together then accumulate (add or subtract) with carry-in
68  *   AVG   - Average between 2 operands
69  *   ABD   - Absolute difference
70  *   ALN   - Align data
71  *   AND   - Logical bitwise 'and' operation
72  *   CPS   - Copy sign
73  *   EXTR  - Extract bits
74  *   I2M   - Move from GPR register to MXU register
75  *   LDD   - Load data from memory to XRF
76  *   LDI   - Load data from memory to XRF (and increase the address base)
77  *   LUI   - Load unsigned immediate
78  *   MUL   - Multiply
79  *   MULU  - Unsigned multiply
80  *   MADD  - 64-bit operand add 32x32 product
81  *   MSUB  - 64-bit operand subtract 32x32 product
82  *   MAC   - Multiply and accumulate (add or subtract)
83  *   MAD   - Multiply and add or subtract
84  *   MAX   - Maximum between 2 operands
85  *   MIN   - Minimum between 2 operands
86  *   M2I   - Move from MXU register to GPR register
87  *   MOVZ  - Move if zero
88  *   MOVN  - Move if non-zero
89  *   NOR   - Logical bitwise 'nor' operation
90  *   OR    - Logical bitwise 'or' operation
91  *   STD   - Store data from XRF to memory
92  *   SDI   - Store data from XRF to memory (and increase the address base)
93  *   SLT   - Set of less than comparison
94  *   SAD   - Sum of absolute differences
95  *   SLL   - Logical shift left
96  *   SLR   - Logical shift right
97  *   SAR   - Arithmetic shift right
98  *   SAT   - Saturation
99  *   SFL   - Shuffle
100  *   SCOP  - Calculate x’s scope (-1, means x<0; 0, means x==0; 1, means x>0)
101  *   XOR   - Logical bitwise 'exclusive or' operation
102  *
103  *  Suffixes:
104  *
105  *   E - Expand results
106  *   F - Fixed point multiplication
107  *   L - Low part result
108  *   R - Doing rounding
109  *   V - Variable instead of immediate
110  *   W - Combine above L and V
111  *
112  *
113  *     The list of MXU instructions grouped by functionality
114  *     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
115  *
116  * Load/Store instructions           Multiplication instructions
117  * -----------------------           ---------------------------
118  *
119  *  S32LDD XRa, Rb, s12               S32MADD XRa, XRd, Rs, Rt
120  *  S32STD XRa, Rb, s12               S32MADDU XRa, XRd, Rs, Rt
121  *  S32LDDV XRa, Rb, rc, strd2        S32MSUB XRa, XRd, Rs, Rt
122  *  S32STDV XRa, Rb, rc, strd2        S32MSUBU XRa, XRd, Rs, Rt
123  *  S32LDI XRa, Rb, s12               S32MUL XRa, XRd, Rs, Rt
124  *  S32SDI XRa, Rb, s12               S32MULU XRa, XRd, Rs, Rt
125  *  S32LDIV XRa, Rb, rc, strd2        D16MUL XRa, XRb, XRc, XRd, optn2
126  *  S32SDIV XRa, Rb, rc, strd2        D16MULE XRa, XRb, XRc, optn2
127  *  S32LDDR XRa, Rb, s12              D16MULF XRa, XRb, XRc, optn2
128  *  S32STDR XRa, Rb, s12              D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
129  *  S32LDDVR XRa, Rb, rc, strd2       D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
130  *  S32STDVR XRa, Rb, rc, strd2       D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
131  *  S32LDIR XRa, Rb, s12              D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
132  *  S32SDIR XRa, Rb, s12              S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
133  *  S32LDIVR XRa, Rb, rc, strd2       Q8MUL XRa, XRb, XRc, XRd
134  *  S32SDIVR XRa, Rb, rc, strd2       Q8MULSU XRa, XRb, XRc, XRd
135  *  S16LDD XRa, Rb, s10, eptn2        Q8MAC XRa, XRb, XRc, XRd, aptn2
136  *  S16STD XRa, Rb, s10, eptn2        Q8MACSU XRa, XRb, XRc, XRd, aptn2
137  *  S16LDI XRa, Rb, s10, eptn2        Q8MADL XRa, XRb, XRc, XRd, aptn2
138  *  S16SDI XRa, Rb, s10, eptn2
139  *  S8LDD XRa, Rb, s8, eptn3
140  *  S8STD XRa, Rb, s8, eptn3         Addition and subtraction instructions
141  *  S8LDI XRa, Rb, s8, eptn3         -------------------------------------
142  *  S8SDI XRa, Rb, s8, eptn3
143  *  LXW Rd, Rs, Rt, strd2             D32ADD XRa, XRb, XRc, XRd, eptn2
144  *  LXH Rd, Rs, Rt, strd2             D32ADDC XRa, XRb, XRc, XRd
145  *  LXHU Rd, Rs, Rt, strd2            D32ACC XRa, XRb, XRc, XRd, eptn2
146  *  LXB Rd, Rs, Rt, strd2             D32ACCM XRa, XRb, XRc, XRd, eptn2
147  *  LXBU Rd, Rs, Rt, strd2            D32ASUM XRa, XRb, XRc, XRd, eptn2
148  *                                    S32CPS XRa, XRb, XRc
149  *                                    Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
150  * Comparison instructions            Q16ACC XRa, XRb, XRc, XRd, eptn2
151  * -----------------------            Q16ACCM XRa, XRb, XRc, XRd, eptn2
152  *                                    D16ASUM XRa, XRb, XRc, XRd, eptn2
153  *  S32MAX XRa, XRb, XRc              D16CPS XRa, XRb,
154  *  S32MIN XRa, XRb, XRc              D16AVG XRa, XRb, XRc
155  *  S32SLT XRa, XRb, XRc              D16AVGR XRa, XRb, XRc
156  *  S32MOVZ XRa, XRb, XRc             Q8ADD XRa, XRb, XRc, eptn2
157  *  S32MOVN XRa, XRb, XRc             Q8ADDE XRa, XRb, XRc, XRd, eptn2
158  *  D16MAX XRa, XRb, XRc              Q8ACCE XRa, XRb, XRc, XRd, eptn2
159  *  D16MIN XRa, XRb, XRc              Q8ABD XRa, XRb, XRc
160  *  D16SLT XRa, XRb, XRc              Q8SAD XRa, XRb, XRc, XRd
161  *  D16MOVZ XRa, XRb, XRc             Q8AVG XRa, XRb, XRc
162  *  D16MOVN XRa, XRb, XRc             Q8AVGR XRa, XRb, XRc
163  *  Q8MAX XRa, XRb, XRc               D8SUM XRa, XRb, XRc, XRd
164  *  Q8MIN XRa, XRb, XRc               D8SUMC XRa, XRb, XRc, XRd
165  *  Q8SLT XRa, XRb, XRc
166  *  Q8SLTU XRa, XRb, XRc
167  *  Q8MOVZ XRa, XRb, XRc             Shift instructions
168  *  Q8MOVN XRa, XRb, XRc             ------------------
169  *
170  *                                    D32SLL XRa, XRb, XRc, XRd, sft4
171  * Bitwise instructions               D32SLR XRa, XRb, XRc, XRd, sft4
172  * --------------------               D32SAR XRa, XRb, XRc, XRd, sft4
173  *                                    D32SARL XRa, XRb, XRc, sft4
174  *  S32NOR XRa, XRb, XRc              D32SLLV XRa, XRb, Rb
175  *  S32AND XRa, XRb, XRc              D32SLRV XRa, XRb, Rb
176  *  S32XOR XRa, XRb, XRc              D32SARV XRa, XRb, Rb
177  *  S32OR XRa, XRb, XRc               D32SARW XRa, XRb, XRc, Rb
178  *                                    Q16SLL XRa, XRb, XRc, XRd, sft4
179  *                                    Q16SLR XRa, XRb, XRc, XRd, sft4
180  * Miscellaneous instructions         Q16SAR XRa, XRb, XRc, XRd, sft4
181  * -------------------------          Q16SLLV XRa, XRb, Rb
182  *                                    Q16SLRV XRa, XRb, Rb
183  *  S32SFL XRa, XRb, XRc, XRd, optn2  Q16SARV XRa, XRb, Rb
184  *  S32ALN XRa, XRb, XRc, Rb
185  *  S32ALNI XRa, XRb, XRc, s3
186  *  S32LUI XRa, s8, optn3            Move instructions
187  *  S32EXTR XRa, XRb, Rb, bits5      -----------------
188  *  S32EXTRV XRa, XRb, Rs, Rt
189  *  Q16SCOP XRa, XRb, XRc, XRd        S32M2I XRa, Rb
190  *  Q16SAT XRa, XRb, XRc              S32I2M XRa, Rb
191  *
192  *
193  *     The opcode organization of MXU instructions
194  *     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
195  *
196  * The bits 31..26 of all MXU instructions are equal to 0x1C (also referred
197  * as opcode SPECIAL2 in the base MIPS ISA). The organization and meaning of
198  * other bits up to the instruction level is as follows:
199  *
200  *              bits
201  *             05..00
202  *
203  *          ┌─ 000000 ─ OPC_MXU_S32MADD
204  *          ├─ 000001 ─ OPC_MXU_S32MADDU
205  *          ├─ 000010 ─ <not assigned>   (non-MXU OPC_MUL)
206  *          │
207  *          │                               20..18
208  *          ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
209  *          │                            ├─ 001 ─ OPC_MXU_S32MIN
210  *          │                            ├─ 010 ─ OPC_MXU_D16MAX
211  *          │                            ├─ 011 ─ OPC_MXU_D16MIN
212  *          │                            ├─ 100 ─ OPC_MXU_Q8MAX
213  *          │                            ├─ 101 ─ OPC_MXU_Q8MIN
214  *          │                            ├─ 110 ─ OPC_MXU_Q8SLT
215  *          │                            └─ 111 ─ OPC_MXU_Q8SLTU
216  *          ├─ 000100 ─ OPC_MXU_S32MSUB
217  *          ├─ 000101 ─ OPC_MXU_S32MSUBU    20..18
218  *          ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
219  *          │                            ├─ 001 ─ OPC_MXU_D16SLT
220  *          │                            ├─ 010 ─ OPC_MXU_D16AVG
221  *          │                            ├─ 011 ─ OPC_MXU_D16AVGR
222  *          │                            ├─ 100 ─ OPC_MXU_Q8AVG
223  *          │                            ├─ 101 ─ OPC_MXU_Q8AVGR
224  *          │                            └─ 111 ─ OPC_MXU_Q8ADD
225  *          │
226  *          │                               20..18
227  *          ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
228  *          │                            ├─ 010 ─ OPC_MXU_D16CPS
229  *          │                            ├─ 100 ─ OPC_MXU_Q8ABD
230  *          │                            └─ 110 ─ OPC_MXU_Q16SAT
231  *          ├─ 001000 ─ OPC_MXU_D16MUL
232  *          │                               25..24
233  *          ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
234  *          │                            └─ 01 ─ OPC_MXU_D16MULE
235  *          ├─ 001010 ─ OPC_MXU_D16MAC
236  *          ├─ 001011 ─ OPC_MXU_D16MACF
237  *          ├─ 001100 ─ OPC_MXU_D16MADL
238  *          ├─ 001101 ─ OPC_MXU_S16MAD
239  *          ├─ 001110 ─ OPC_MXU_Q16ADD
240  *          ├─ 001111 ─ OPC_MXU_D16MACE     20 (13..10 don't care)
241  *          │                            ┌─ 0 ─ OPC_MXU_S32LDD
242  *          ├─ 010000 ─ OPC_MXU__POOL04 ─┴─ 1 ─ OPC_MXU_S32LDDR
243  *          │
244  *          │                               20 (13..10 don't care)
245  *          ├─ 010001 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32STD
246  *          │                            └─ 1 ─ OPC_MXU_S32STDR
247  *          │
248  *          │                               13..10
249  *          ├─ 010010 ─ OPC_MXU__POOL06 ─┬─ 0000 ─ OPC_MXU_S32LDDV
250  *          │                            └─ 0001 ─ OPC_MXU_S32LDDVR
251  *          │
252  *          │                               13..10
253  *          ├─ 010011 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32STDV
254  *          │                            └─ 0001 ─ OPC_MXU_S32STDVR
255  *          │
256  *          │                               20 (13..10 don't care)
257  *          ├─ 010100 ─ OPC_MXU__POOL08 ─┬─ 0 ─ OPC_MXU_S32LDI
258  *          │                            └─ 1 ─ OPC_MXU_S32LDIR
259  *          │
260  *          │                               20 (13..10 don't care)
261  *          ├─ 010101 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32SDI
262  *          │                            └─ 1 ─ OPC_MXU_S32SDIR
263  *          │
264  *          │                               13..10
265  *          ├─ 010110 ─ OPC_MXU__POOL10 ─┬─ 0000 ─ OPC_MXU_S32LDIV
266  *          │                            └─ 0001 ─ OPC_MXU_S32LDIVR
267  *          │
268  *          │                               13..10
269  *          ├─ 010111 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32SDIV
270  *          │                            └─ 0001 ─ OPC_MXU_S32SDIVR
271  *          ├─ 011000 ─ OPC_MXU_D32ADD  (catches D32ADDC too)
272  *          │                               23..22
273  *   MXU    ├─ 011001 ─ OPC_MXU__POOL12 ─┬─ 00 ─ OPC_MXU_D32ACC
274  * opcodes ─┤                            ├─ 01 ─ OPC_MXU_D32ACCM
275  *          │                            └─ 10 ─ OPC_MXU_D32ASUM
276  *          ├─ 011010 ─ <not assigned>
277  *          │                               23..22
278  *          ├─ 011011 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_Q16ACC
279  *          │                            ├─ 01 ─ OPC_MXU_Q16ACCM
280  *          │                            └─ 10 ─ OPC_MXU_D16ASUM
281  *          │
282  *          │                               23..22
283  *          ├─ 011100 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q8ADDE
284  *          │                            ├─ 01 ─ OPC_MXU_D8SUM
285  *          ├─ 011101 ─ OPC_MXU_Q8ACCE   └─ 10 ─ OPC_MXU_D8SUMC
286  *          ├─ 011110 ─ <not assigned>
287  *          ├─ 011111 ─ <not assigned>
288  *          ├─ 100000 ─ <not assigned>   (overlaps with CLZ)
289  *          ├─ 100001 ─ <not assigned>   (overlaps with CLO)
290  *          ├─ 100010 ─ OPC_MXU_S8LDD
291  *          ├─ 100011 ─ OPC_MXU_S8STD       15..14
292  *          ├─ 100100 ─ OPC_MXU_S8LDI    ┌─ 00 ─ OPC_MXU_S32MUL
293  *          ├─ 100101 ─ OPC_MXU_S8SDI    ├─ 01 ─ OPC_MXU_S32MULU
294  *          │                            ├─ 10 ─ OPC_MXU_S32EXTR
295  *          ├─ 100110 ─ OPC_MXU__POOL15 ─┴─ 11 ─ OPC_MXU_S32EXTRV
296  *          │
297  *          │                               20..18
298  *          ├─ 100111 ─ OPC_MXU__POOL16 ─┬─ 000 ─ OPC_MXU_D32SARW
299  *          │                            ├─ 001 ─ OPC_MXU_S32ALN
300  *          │                            ├─ 010 ─ OPC_MXU_S32ALNI
301  *          │                            ├─ 011 ─ OPC_MXU_S32LUI
302  *          │                            ├─ 100 ─ OPC_MXU_S32NOR
303  *          │                            ├─ 101 ─ OPC_MXU_S32AND
304  *          │                            ├─ 110 ─ OPC_MXU_S32OR
305  *          │                            └─ 111 ─ OPC_MXU_S32XOR
306  *          │
307  *          │                               8..6
308  *          ├─ 101000 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_LXB
309  *          │                            ├─ 001 ─ OPC_MXU_LXH
310  *          ├─ 101001 ─ <not assigned>   ├─ 011 ─ OPC_MXU_LXW
311  *          ├─ 101010 ─ OPC_MXU_S16LDD   ├─ 100 ─ OPC_MXU_LXBU
312  *          ├─ 101011 ─ OPC_MXU_S16STD   └─ 101 ─ OPC_MXU_LXHU
313  *          ├─ 101100 ─ OPC_MXU_S16LDI
314  *          ├─ 101101 ─ OPC_MXU_S16SDI
315  *          ├─ 101110 ─ OPC_MXU_S32M2I
316  *          ├─ 101111 ─ OPC_MXU_S32I2M
317  *          ├─ 110000 ─ OPC_MXU_D32SLL
318  *          ├─ 110001 ─ OPC_MXU_D32SLR      20..18
319  *          ├─ 110010 ─ OPC_MXU_D32SARL  ┌─ 000 ─ OPC_MXU_D32SLLV
320  *          ├─ 110011 ─ OPC_MXU_D32SAR   ├─ 001 ─ OPC_MXU_D32SLRV
321  *          ├─ 110100 ─ OPC_MXU_Q16SLL   ├─ 011 ─ OPC_MXU_D32SARV
322  *          ├─ 110101 ─ OPC_MXU_Q16SLR   ├─ 100 ─ OPC_MXU_Q16SLLV
323  *          │                            ├─ 101 ─ OPC_MXU_Q16SLRV
324  *          ├─ 110110 ─ OPC_MXU__POOL18 ─┴─ 111 ─ OPC_MXU_Q16SARV
325  *          │
326  *          ├─ 110111 ─ OPC_MXU_Q16SAR
327  *          │                               23..22
328  *          ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
329  *          │                            └─ 10 ─ OPC_MXU_Q8MULSU
330  *          │
331  *          │                               20..18
332  *          ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
333  *          │                            ├─ 001 ─ OPC_MXU_Q8MOVN
334  *          │                            ├─ 010 ─ OPC_MXU_D16MOVZ
335  *          │                            ├─ 011 ─ OPC_MXU_D16MOVN
336  *          │                            ├─ 100 ─ OPC_MXU_S32MOVZ
337  *          │                            └─ 101 ─ OPC_MXU_S32MOVN
338  *          │
339  *          │                               23..22
340  *          ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
341  *          │                            └─ 10 ─ OPC_MXU_Q8MACSU
342  *          ├─ 111011 ─ OPC_MXU_Q16SCOP
343  *          ├─ 111100 ─ OPC_MXU_Q8MADL
344  *          ├─ 111101 ─ OPC_MXU_S32SFL
345  *          ├─ 111110 ─ OPC_MXU_Q8SAD
346  *          └─ 111111 ─ <not assigned>   (overlaps with SDBBP)
347  *
348  *
349  * Compiled after:
350  *
351  *   "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
352  *   Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2, 2017
353  */
354 
355 enum {
356     OPC_MXU_S32MADD  = 0x00,
357     OPC_MXU_S32MADDU = 0x01,
358     OPC_MXU__POOL00  = 0x03,
359     OPC_MXU_S32MSUB  = 0x04,
360     OPC_MXU_S32MSUBU = 0x05,
361     OPC_MXU__POOL01  = 0x06,
362     OPC_MXU__POOL02  = 0x07,
363     OPC_MXU_D16MUL   = 0x08,
364     OPC_MXU__POOL03  = 0x09,
365     OPC_MXU_D16MAC   = 0x0A,
366     OPC_MXU_D16MACF  = 0x0B,
367     OPC_MXU_D16MADL  = 0x0C,
368     OPC_MXU_S16MAD   = 0x0D,
369     OPC_MXU_Q16ADD   = 0x0E,
370     OPC_MXU_D16MACE  = 0x0F,
371     OPC_MXU__POOL04  = 0x10,
372     OPC_MXU__POOL05  = 0x11,
373     OPC_MXU__POOL06  = 0x12,
374     OPC_MXU__POOL07  = 0x13,
375     OPC_MXU__POOL08  = 0x14,
376     OPC_MXU__POOL09  = 0x15,
377     OPC_MXU__POOL10  = 0x16,
378     OPC_MXU__POOL11  = 0x17,
379     OPC_MXU_D32ADD   = 0x18,
380     OPC_MXU__POOL12  = 0x19,
381     OPC_MXU__POOL13  = 0x1B,
382     OPC_MXU__POOL14  = 0x1C,
383     OPC_MXU_Q8ACCE   = 0x1D,
384     OPC_MXU_S8LDD    = 0x22,
385     OPC_MXU_S8STD    = 0x23,
386     OPC_MXU_S8LDI    = 0x24,
387     OPC_MXU_S8SDI    = 0x25,
388     OPC_MXU__POOL15  = 0x26,
389     OPC_MXU__POOL16  = 0x27,
390     OPC_MXU__POOL17  = 0x28,
391     OPC_MXU_S16LDD   = 0x2A,
392     OPC_MXU_S16STD   = 0x2B,
393     OPC_MXU_S16LDI   = 0x2C,
394     OPC_MXU_S16SDI   = 0x2D,
395     OPC_MXU_S32M2I   = 0x2E,
396     OPC_MXU_S32I2M   = 0x2F,
397     OPC_MXU_D32SLL   = 0x30,
398     OPC_MXU_D32SLR   = 0x31,
399     OPC_MXU_D32SARL  = 0x32,
400     OPC_MXU_D32SAR   = 0x33,
401     OPC_MXU_Q16SLL   = 0x34,
402     OPC_MXU_Q16SLR   = 0x35,
403     OPC_MXU__POOL18  = 0x36,
404     OPC_MXU_Q16SAR   = 0x37,
405     OPC_MXU__POOL19  = 0x38,
406     OPC_MXU__POOL20  = 0x39,
407     OPC_MXU__POOL21  = 0x3A,
408     OPC_MXU_Q16SCOP  = 0x3B,
409     OPC_MXU_Q8MADL   = 0x3C,
410     OPC_MXU_S32SFL   = 0x3D,
411     OPC_MXU_Q8SAD    = 0x3E,
412 };
413 
414 
415 /*
416  * MXU pool 00
417  */
418 enum {
419     OPC_MXU_S32MAX   = 0x00,
420     OPC_MXU_S32MIN   = 0x01,
421     OPC_MXU_D16MAX   = 0x02,
422     OPC_MXU_D16MIN   = 0x03,
423     OPC_MXU_Q8MAX    = 0x04,
424     OPC_MXU_Q8MIN    = 0x05,
425     OPC_MXU_Q8SLT    = 0x06,
426     OPC_MXU_Q8SLTU   = 0x07,
427 };
428 
429 /*
430  * MXU pool 01
431  */
432 enum {
433     OPC_MXU_S32SLT   = 0x00,
434     OPC_MXU_D16SLT   = 0x01,
435     OPC_MXU_D16AVG   = 0x02,
436     OPC_MXU_D16AVGR  = 0x03,
437     OPC_MXU_Q8AVG    = 0x04,
438     OPC_MXU_Q8AVGR   = 0x05,
439     OPC_MXU_Q8ADD    = 0x07,
440 };
441 
442 /*
443  * MXU pool 02
444  */
445 enum {
446     OPC_MXU_S32CPS   = 0x00,
447     OPC_MXU_D16CPS   = 0x02,
448     OPC_MXU_Q8ABD    = 0x04,
449     OPC_MXU_Q16SAT   = 0x06,
450 };
451 
452 /*
453  * MXU pool 03
454  */
455 enum {
456     OPC_MXU_D16MULF  = 0x00,
457     OPC_MXU_D16MULE  = 0x01,
458 };
459 
460 /*
461  * MXU pool 04 05 06 07 08 09 10 11
462  */
463 enum {
464     OPC_MXU_S32LDST  = 0x00,
465     OPC_MXU_S32LDSTR = 0x01,
466 };
467 
468 /*
469  * MXU pool 12
470  */
471 enum {
472     OPC_MXU_D32ACC    = 0x00,
473     OPC_MXU_D32ACCM   = 0x01,
474     OPC_MXU_D32ASUM   = 0x02,
475 };
476 
477 /*
478  * MXU pool 13
479  */
480 enum {
481     OPC_MXU_Q16ACC    = 0x00,
482     OPC_MXU_Q16ACCM   = 0x01,
483     OPC_MXU_D16ASUM   = 0x02,
484 };
485 
486 /*
487  * MXU pool 14
488  */
489 enum {
490     OPC_MXU_Q8ADDE    = 0x00,
491     OPC_MXU_D8SUM     = 0x01,
492     OPC_MXU_D8SUMC    = 0x02,
493 };
494 
495 /*
496  * MXU pool 15
497  */
498 enum {
499     OPC_MXU_S32MUL    = 0x00,
500     OPC_MXU_S32MULU   = 0x01,
501     OPC_MXU_S32EXTR   = 0x02,
502     OPC_MXU_S32EXTRV  = 0x03,
503 };
504 
505 /*
506  * MXU pool 16
507  */
508 enum {
509     OPC_MXU_D32SARW  = 0x00,
510     OPC_MXU_S32ALN   = 0x01,
511     OPC_MXU_S32ALNI  = 0x02,
512     OPC_MXU_S32LUI   = 0x03,
513     OPC_MXU_S32NOR   = 0x04,
514     OPC_MXU_S32AND   = 0x05,
515     OPC_MXU_S32OR    = 0x06,
516     OPC_MXU_S32XOR   = 0x07,
517 };
518 
519 /*
520  * MXU pool 17
521  */
522 enum {
523     OPC_MXU_LXB      = 0x00,
524     OPC_MXU_LXH      = 0x01,
525     OPC_MXU_LXW      = 0x03,
526     OPC_MXU_LXBU     = 0x04,
527     OPC_MXU_LXHU     = 0x05,
528 };
529 
530 /*
531  * MXU pool 18
532  */
533 enum {
534     OPC_MXU_D32SLLV  = 0x00,
535     OPC_MXU_D32SLRV  = 0x01,
536     OPC_MXU_D32SARV  = 0x03,
537     OPC_MXU_Q16SLLV  = 0x04,
538     OPC_MXU_Q16SLRV  = 0x05,
539     OPC_MXU_Q16SARV  = 0x07,
540 };
541 
542 /*
543  * MXU pool 19
544  */
545 enum {
546     OPC_MXU_Q8MUL    = 0x00,
547     OPC_MXU_Q8MULSU  = 0x02,
548 };
549 
550 /*
551  * MXU pool 20
552  */
553 enum {
554     OPC_MXU_Q8MOVZ   = 0x00,
555     OPC_MXU_Q8MOVN   = 0x01,
556     OPC_MXU_D16MOVZ  = 0x02,
557     OPC_MXU_D16MOVN  = 0x03,
558     OPC_MXU_S32MOVZ  = 0x04,
559     OPC_MXU_S32MOVN  = 0x05,
560 };
561 
562 /*
563  * MXU pool 21
564  */
565 enum {
566     OPC_MXU_Q8MAC    = 0x00,
567     OPC_MXU_Q8MACSU  = 0x02,
568 };
569 
570 
571 /* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
572 #define MXU_APTN1_A    0
573 #define MXU_APTN1_S    1
574 
575 /* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
576 #define MXU_APTN2_AA    0
577 #define MXU_APTN2_AS    1
578 #define MXU_APTN2_SA    2
579 #define MXU_APTN2_SS    3
580 
581 /* MXU execute add/subtract 2-bit pattern 'eptn2' */
582 #define MXU_EPTN2_AA    0
583 #define MXU_EPTN2_AS    1
584 #define MXU_EPTN2_SA    2
585 #define MXU_EPTN2_SS    3
586 
587 /* MXU operand getting pattern 'optn2' */
588 #define MXU_OPTN2_PTN0  0
589 #define MXU_OPTN2_PTN1  1
590 #define MXU_OPTN2_PTN2  2
591 #define MXU_OPTN2_PTN3  3
592 /* alternative naming scheme for 'optn2' */
593 #define MXU_OPTN2_WW    0
594 #define MXU_OPTN2_LW    1
595 #define MXU_OPTN2_HW    2
596 #define MXU_OPTN2_XW    3
597 
598 /* MXU operand getting pattern 'optn3' */
599 #define MXU_OPTN3_PTN0  0
600 #define MXU_OPTN3_PTN1  1
601 #define MXU_OPTN3_PTN2  2
602 #define MXU_OPTN3_PTN3  3
603 #define MXU_OPTN3_PTN4  4
604 #define MXU_OPTN3_PTN5  5
605 #define MXU_OPTN3_PTN6  6
606 #define MXU_OPTN3_PTN7  7
607 
608 /* MXU registers */
609 static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1];
610 static TCGv mxu_CR;
611 
612 static const char mxuregnames[NUMBER_OF_MXU_REGISTERS][4] = {
613     "XR1",  "XR2",  "XR3",  "XR4",  "XR5",  "XR6",  "XR7",  "XR8",
614     "XR9",  "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "XCR",
615 };
616 
617 void mxu_translate_init(void)
618 {
619     for (unsigned i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
620         mxu_gpr[i] = tcg_global_mem_new(tcg_env,
621                                         offsetof(CPUMIPSState, active_tc.mxu_gpr[i]),
622                                         mxuregnames[i]);
623     }
624 
625     mxu_CR = tcg_global_mem_new(tcg_env,
626                                 offsetof(CPUMIPSState, active_tc.mxu_cr),
627                                 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
628 }
629 
630 /* MXU General purpose registers moves. */
631 static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg)
632 {
633     if (reg == 0) {
634         tcg_gen_movi_tl(t, 0);
635     } else if (reg <= 15) {
636         tcg_gen_mov_tl(t, mxu_gpr[reg - 1]);
637     }
638 }
639 
640 static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg)
641 {
642     if (reg > 0 && reg <= 15) {
643         tcg_gen_mov_tl(mxu_gpr[reg - 1], t);
644     }
645 }
646 
647 static inline void gen_extract_mxu_gpr(TCGv t, unsigned int reg,
648                                        unsigned int ofs, unsigned int len)
649 {
650     if (reg == 0) {
651         tcg_gen_movi_tl(t, 0);
652     } else if (reg <= 15) {
653         tcg_gen_extract_tl(t, mxu_gpr[reg - 1], ofs, len);
654     }
655 }
656 
657 /* MXU control register moves. */
658 static inline void gen_load_mxu_cr(TCGv t)
659 {
660     tcg_gen_mov_tl(t, mxu_CR);
661 }
662 
663 static inline void gen_store_mxu_cr(TCGv t)
664 {
665     /* TODO: Add handling of RW rules for MXU_CR. */
666     tcg_gen_mov_tl(mxu_CR, t);
667 }
668 
669 /*
670  * S32I2M XRa, rb - Register move from GRF to XRF
671  */
672 static void gen_mxu_s32i2m(DisasContext *ctx)
673 {
674     TCGv t0;
675     uint32_t XRa, Rb;
676 
677     t0 = tcg_temp_new();
678 
679     XRa = extract32(ctx->opcode, 6, 5);
680     Rb = extract32(ctx->opcode, 16, 5);
681 
682     gen_load_gpr(t0, Rb);
683     if (XRa <= 15) {
684         gen_store_mxu_gpr(t0, XRa);
685     } else if (XRa == 16) {
686         gen_store_mxu_cr(t0);
687     }
688 }
689 
690 /*
691  * S32M2I XRa, rb - Register move from XRF to GRF
692  */
693 static void gen_mxu_s32m2i(DisasContext *ctx)
694 {
695     TCGv t0;
696     uint32_t XRa, Rb;
697 
698     t0 = tcg_temp_new();
699 
700     XRa = extract32(ctx->opcode, 6, 5);
701     Rb = extract32(ctx->opcode, 16, 5);
702 
703     if (XRa <= 15) {
704         gen_load_mxu_gpr(t0, XRa);
705     } else if (XRa == 16) {
706         gen_load_mxu_cr(t0);
707     }
708 
709     gen_store_gpr(t0, Rb);
710 }
711 
712 /*
713  * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
714  *
715  * S8LDI XRa, Rb, s8, optn3 - Load a byte from memory to XRF,
716  * post modify address register
717  */
718 static void gen_mxu_s8ldd(DisasContext *ctx, bool postmodify)
719 {
720     TCGv t0, t1;
721     uint32_t XRa, Rb, s8, optn3;
722 
723     t0 = tcg_temp_new();
724     t1 = tcg_temp_new();
725 
726     XRa = extract32(ctx->opcode, 6, 4);
727     s8 = extract32(ctx->opcode, 10, 8);
728     optn3 = extract32(ctx->opcode, 18, 3);
729     Rb = extract32(ctx->opcode, 21, 5);
730 
731     gen_load_gpr(t0, Rb);
732     tcg_gen_addi_tl(t0, t0, (int8_t)s8);
733     if (postmodify) {
734         gen_store_gpr(t0, Rb);
735     }
736 
737     switch (optn3) {
738     /* XRa[7:0] = tmp8 */
739     case MXU_OPTN3_PTN0:
740         tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
741         gen_load_mxu_gpr(t0, XRa);
742         tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
743         break;
744     /* XRa[15:8] = tmp8 */
745     case MXU_OPTN3_PTN1:
746         tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
747         gen_load_mxu_gpr(t0, XRa);
748         tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
749         break;
750     /* XRa[23:16] = tmp8 */
751     case MXU_OPTN3_PTN2:
752         tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
753         gen_load_mxu_gpr(t0, XRa);
754         tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
755         break;
756     /* XRa[31:24] = tmp8 */
757     case MXU_OPTN3_PTN3:
758         tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
759         gen_load_mxu_gpr(t0, XRa);
760         tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
761         break;
762     /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
763     case MXU_OPTN3_PTN4:
764         tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
765         tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
766         break;
767     /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
768     case MXU_OPTN3_PTN5:
769         tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
770         tcg_gen_shli_tl(t1, t1, 8);
771         tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
772         break;
773     /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
774     case MXU_OPTN3_PTN6:
775         tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
776         tcg_gen_mov_tl(t0, t1);
777         tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
778         tcg_gen_shli_tl(t1, t1, 16);
779         tcg_gen_or_tl(t0, t0, t1);
780         break;
781     /* XRa = {tmp8, tmp8, tmp8, tmp8} */
782     case MXU_OPTN3_PTN7:
783         tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
784         tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
785         tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
786         break;
787     }
788 
789     gen_store_mxu_gpr(t0, XRa);
790 }
791 
792 /*
793  * S8STD XRa, Rb, s8, optn3 - Store a byte from XRF to memory
794  *
795  * S8SDI XRa, Rb, s8, optn3 - Store a byte from XRF to memory,
796  * post modify address register
797  */
798 static void gen_mxu_s8std(DisasContext *ctx, bool postmodify)
799 {
800     TCGv t0, t1;
801     uint32_t XRa, Rb, s8, optn3;
802 
803     t0 = tcg_temp_new();
804     t1 = tcg_temp_new();
805 
806     XRa = extract32(ctx->opcode, 6, 4);
807     s8 = extract32(ctx->opcode, 10, 8);
808     optn3 = extract32(ctx->opcode, 18, 3);
809     Rb = extract32(ctx->opcode, 21, 5);
810 
811     if (optn3 > 3) {
812         /* reserved, do nothing */
813         return;
814     }
815 
816     gen_load_gpr(t0, Rb);
817     tcg_gen_addi_tl(t0, t0, (int8_t)s8);
818     if (postmodify) {
819         gen_store_gpr(t0, Rb);
820     }
821     gen_load_mxu_gpr(t1, XRa);
822 
823     switch (optn3) {
824     /* XRa[7:0] => tmp8 */
825     case MXU_OPTN3_PTN0:
826         tcg_gen_extract_tl(t1, t1, 0, 8);
827         break;
828     /* XRa[15:8] => tmp8 */
829     case MXU_OPTN3_PTN1:
830         tcg_gen_extract_tl(t1, t1, 8, 8);
831         break;
832     /* XRa[23:16] => tmp8 */
833     case MXU_OPTN3_PTN2:
834         tcg_gen_extract_tl(t1, t1, 16, 8);
835         break;
836     /* XRa[31:24] => tmp8 */
837     case MXU_OPTN3_PTN3:
838         tcg_gen_extract_tl(t1, t1, 24, 8);
839         break;
840     }
841 
842     tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_UB);
843 }
844 
845 /*
846  * S16LDD XRa, Rb, s10, optn2 - Load a halfword from memory to XRF
847  *
848  * S16LDI XRa, Rb, s10, optn2 - Load a halfword from memory to XRF,
849  * post modify address register
850  */
851 static void gen_mxu_s16ldd(DisasContext *ctx, bool postmodify)
852 {
853     TCGv t0, t1;
854     uint32_t XRa, Rb, optn2;
855     int32_t s10;
856 
857     t0 = tcg_temp_new();
858     t1 = tcg_temp_new();
859 
860     XRa   = extract32(ctx->opcode,   6, 4);
861     s10   = sextract32(ctx->opcode, 10, 9) * 2;
862     optn2 = extract32(ctx->opcode,  19, 2);
863     Rb    = extract32(ctx->opcode,  21, 5);
864 
865     gen_load_gpr(t0, Rb);
866     tcg_gen_addi_tl(t0, t0, s10);
867     if (postmodify) {
868         gen_store_gpr(t0, Rb);
869     }
870 
871     switch (optn2) {
872     /* XRa[15:0] = tmp16 */
873     case MXU_OPTN2_PTN0:
874         tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UW);
875         gen_load_mxu_gpr(t0, XRa);
876         tcg_gen_deposit_tl(t0, t0, t1, 0, 16);
877         break;
878     /* XRa[31:16] = tmp16 */
879     case MXU_OPTN2_PTN1:
880         tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UW);
881         gen_load_mxu_gpr(t0, XRa);
882         tcg_gen_deposit_tl(t0, t0, t1, 16, 16);
883         break;
884     /* XRa = sign_extend(tmp16) */
885     case MXU_OPTN2_PTN2:
886         tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SW);
887         break;
888     /* XRa = {tmp16, tmp16} */
889     case MXU_OPTN2_PTN3:
890         tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UW);
891         tcg_gen_deposit_tl(t0, t1, t1,  0, 16);
892         tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
893         break;
894     }
895 
896     gen_store_mxu_gpr(t0, XRa);
897 }
898 
899 /*
900  * S16STD XRa, Rb, s8, optn2 - Store a byte from XRF to memory
901  *
902  * S16SDI XRa, Rb, s8, optn2 - Store a byte from XRF to memory,
903  * post modify address register
904  */
905 static void gen_mxu_s16std(DisasContext *ctx, bool postmodify)
906 {
907     TCGv t0, t1;
908     uint32_t XRa, Rb, optn2;
909     int32_t s10;
910 
911     t0 = tcg_temp_new();
912     t1 = tcg_temp_new();
913 
914     XRa = extract32(ctx->opcode, 6, 4);
915     s10 = sextract32(ctx->opcode, 10, 9) * 2;
916     optn2 = extract32(ctx->opcode, 19, 2);
917     Rb = extract32(ctx->opcode, 21, 5);
918 
919     if (optn2 > 1) {
920         /* reserved, do nothing */
921         return;
922     }
923 
924     gen_load_gpr(t0, Rb);
925     tcg_gen_addi_tl(t0, t0, s10);
926     if (postmodify) {
927         gen_store_gpr(t0, Rb);
928     }
929     gen_load_mxu_gpr(t1, XRa);
930 
931     switch (optn2) {
932     /* XRa[15:0] => tmp16 */
933     case MXU_OPTN2_PTN0:
934         tcg_gen_extract_tl(t1, t1, 0, 16);
935         break;
936     /* XRa[31:16] => tmp16 */
937     case MXU_OPTN2_PTN1:
938         tcg_gen_extract_tl(t1, t1, 16, 16);
939         break;
940     }
941 
942     tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_UW);
943 }
944 
945 /*
946  * S32MUL  XRa, XRd, rs, rt - Signed 32x32=>64 bit multiplication
947  * of GPR's and stores result into pair of MXU registers.
948  * It strains HI and LO registers.
949  *
950  * S32MULU XRa, XRd, rs, rt - Unsigned 32x32=>64 bit multiplication
951  * of GPR's and stores result into pair of MXU registers.
952  * It strains HI and LO registers.
953  */
954 static void gen_mxu_s32mul(DisasContext *ctx, bool mulu)
955 {
956     TCGv t0, t1;
957     uint32_t XRa, XRd, rs, rt;
958 
959     t0 = tcg_temp_new();
960     t1 = tcg_temp_new();
961 
962     XRa = extract32(ctx->opcode,  6, 4);
963     XRd = extract32(ctx->opcode, 10, 4);
964     rs  = extract32(ctx->opcode, 16, 5);
965     rt  = extract32(ctx->opcode, 21, 5);
966 
967     if (unlikely(rs == 0 || rt == 0)) {
968         tcg_gen_movi_tl(t0, 0);
969         tcg_gen_movi_tl(t1, 0);
970     } else {
971         gen_load_gpr(t0, rs);
972         gen_load_gpr(t1, rt);
973 
974         if (mulu) {
975             tcg_gen_mulu2_tl(t0, t1, t0, t1);
976         } else {
977             tcg_gen_muls2_tl(t0, t1, t0, t1);
978         }
979     }
980     tcg_gen_mov_tl(cpu_HI[0], t1);
981     tcg_gen_mov_tl(cpu_LO[0], t0);
982     gen_store_mxu_gpr(t1, XRa);
983     gen_store_mxu_gpr(t0, XRd);
984 }
985 
986 /*
987  * D16MUL  XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
988  * D16MULF XRa, XRb, XRc, optn2 - Signed Q15 fraction pattern multiplication
989  *   with rounding and packing result
990  * D16MULE XRa, XRb, XRc, XRd, optn2 - Signed Q15 fraction pattern
991  *   multiplication with rounding
992  */
993 static void gen_mxu_d16mul(DisasContext *ctx, bool fractional,
994                            bool packed_result)
995 {
996     TCGv t0, t1, t2, t3;
997     uint32_t XRa, XRb, XRc, XRd, optn2;
998 
999     t0 = tcg_temp_new();
1000     t1 = tcg_temp_new();
1001     t2 = tcg_temp_new();
1002     t3 = tcg_temp_new();
1003 
1004     XRa = extract32(ctx->opcode, 6, 4);
1005     XRb = extract32(ctx->opcode, 10, 4);
1006     XRc = extract32(ctx->opcode, 14, 4);
1007     XRd = extract32(ctx->opcode, 18, 4);
1008     optn2 = extract32(ctx->opcode, 22, 2);
1009 
1010     /*
1011      * TODO: XRd field isn't used for D16MULF
1012      * There's no knowledge how this field affect
1013      * instruction decoding/behavior
1014      */
1015 
1016     gen_load_mxu_gpr(t1, XRb);
1017     tcg_gen_sextract_tl(t0, t1, 0, 16);
1018     tcg_gen_sextract_tl(t1, t1, 16, 16);
1019     gen_load_mxu_gpr(t3, XRc);
1020     tcg_gen_sextract_tl(t2, t3, 0, 16);
1021     tcg_gen_sextract_tl(t3, t3, 16, 16);
1022 
1023     switch (optn2) {
1024     case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
1025         tcg_gen_mul_tl(t3, t1, t3);
1026         tcg_gen_mul_tl(t2, t0, t2);
1027         break;
1028     case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
1029         tcg_gen_mul_tl(t3, t0, t3);
1030         tcg_gen_mul_tl(t2, t0, t2);
1031         break;
1032     case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
1033         tcg_gen_mul_tl(t3, t1, t3);
1034         tcg_gen_mul_tl(t2, t1, t2);
1035         break;
1036     case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
1037         tcg_gen_mul_tl(t3, t0, t3);
1038         tcg_gen_mul_tl(t2, t1, t2);
1039         break;
1040     }
1041     if (fractional) {
1042         TCGLabel *l_done = gen_new_label();
1043         TCGv rounding = tcg_temp_new();
1044 
1045         tcg_gen_shli_tl(t3, t3, 1);
1046         tcg_gen_shli_tl(t2, t2, 1);
1047         tcg_gen_andi_tl(rounding, mxu_CR, 0x2);
1048         tcg_gen_brcondi_tl(TCG_COND_EQ, rounding, 0, l_done);
1049         if (packed_result) {
1050             TCGLabel *l_apply_bias_l = gen_new_label();
1051             TCGLabel *l_apply_bias_r = gen_new_label();
1052             TCGLabel *l_half_done = gen_new_label();
1053             TCGv bias = tcg_temp_new();
1054 
1055             /*
1056              * D16MULF supports unbiased rounding aka "bankers rounding",
1057              * "round to even", "convergent rounding"
1058              */
1059             tcg_gen_andi_tl(bias, mxu_CR, 0x4);
1060             tcg_gen_brcondi_tl(TCG_COND_NE, bias, 0, l_apply_bias_l);
1061             tcg_gen_andi_tl(t0, t3, 0x1ffff);
1062             tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0x8000, l_half_done);
1063             gen_set_label(l_apply_bias_l);
1064             tcg_gen_addi_tl(t3, t3, 0x8000);
1065             gen_set_label(l_half_done);
1066             tcg_gen_brcondi_tl(TCG_COND_NE, bias, 0, l_apply_bias_r);
1067             tcg_gen_andi_tl(t0, t2, 0x1ffff);
1068             tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0x8000, l_done);
1069             gen_set_label(l_apply_bias_r);
1070             tcg_gen_addi_tl(t2, t2, 0x8000);
1071         } else {
1072             /* D16MULE doesn't support unbiased rounding */
1073             tcg_gen_addi_tl(t3, t3, 0x8000);
1074             tcg_gen_addi_tl(t2, t2, 0x8000);
1075         }
1076         gen_set_label(l_done);
1077     }
1078     if (!packed_result) {
1079         gen_store_mxu_gpr(t3, XRa);
1080         gen_store_mxu_gpr(t2, XRd);
1081     } else {
1082         tcg_gen_andi_tl(t3, t3, 0xffff0000);
1083         tcg_gen_shri_tl(t2, t2, 16);
1084         tcg_gen_or_tl(t3, t3, t2);
1085         gen_store_mxu_gpr(t3, XRa);
1086     }
1087 }
1088 
1089 /*
1090  * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1091  *   Signed 16 bit pattern multiply and accumulate
1092  * D16MACF XRa, XRb, XRc, aptn2, optn2
1093  *   Signed Q15 fraction pattern multiply accumulate and pack
1094  * D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1095  *   Signed Q15 fraction pattern multiply and accumulate
1096  */
1097 static void gen_mxu_d16mac(DisasContext *ctx, bool fractional,
1098                            bool packed_result)
1099 {
1100     TCGv t0, t1, t2, t3;
1101     uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
1102 
1103     t0 = tcg_temp_new();
1104     t1 = tcg_temp_new();
1105     t2 = tcg_temp_new();
1106     t3 = tcg_temp_new();
1107 
1108     XRa = extract32(ctx->opcode, 6, 4);
1109     XRb = extract32(ctx->opcode, 10, 4);
1110     XRc = extract32(ctx->opcode, 14, 4);
1111     XRd = extract32(ctx->opcode, 18, 4);
1112     optn2 = extract32(ctx->opcode, 22, 2);
1113     aptn2 = extract32(ctx->opcode, 24, 2);
1114 
1115     gen_load_mxu_gpr(t1, XRb);
1116     tcg_gen_sextract_tl(t0, t1, 0, 16);
1117     tcg_gen_sextract_tl(t1, t1, 16, 16);
1118 
1119     gen_load_mxu_gpr(t3, XRc);
1120     tcg_gen_sextract_tl(t2, t3, 0, 16);
1121     tcg_gen_sextract_tl(t3, t3, 16, 16);
1122 
1123     switch (optn2) {
1124     case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
1125         tcg_gen_mul_tl(t3, t1, t3);
1126         tcg_gen_mul_tl(t2, t0, t2);
1127         break;
1128     case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
1129         tcg_gen_mul_tl(t3, t0, t3);
1130         tcg_gen_mul_tl(t2, t0, t2);
1131         break;
1132     case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
1133         tcg_gen_mul_tl(t3, t1, t3);
1134         tcg_gen_mul_tl(t2, t1, t2);
1135         break;
1136     case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
1137         tcg_gen_mul_tl(t3, t0, t3);
1138         tcg_gen_mul_tl(t2, t1, t2);
1139         break;
1140     }
1141 
1142     if (fractional) {
1143         tcg_gen_shli_tl(t3, t3, 1);
1144         tcg_gen_shli_tl(t2, t2, 1);
1145     }
1146     gen_load_mxu_gpr(t0, XRa);
1147     gen_load_mxu_gpr(t1, XRd);
1148 
1149     switch (aptn2) {
1150     case MXU_APTN2_AA:
1151         tcg_gen_add_tl(t3, t0, t3);
1152         tcg_gen_add_tl(t2, t1, t2);
1153         break;
1154     case MXU_APTN2_AS:
1155         tcg_gen_add_tl(t3, t0, t3);
1156         tcg_gen_sub_tl(t2, t1, t2);
1157         break;
1158     case MXU_APTN2_SA:
1159         tcg_gen_sub_tl(t3, t0, t3);
1160         tcg_gen_add_tl(t2, t1, t2);
1161         break;
1162     case MXU_APTN2_SS:
1163         tcg_gen_sub_tl(t3, t0, t3);
1164         tcg_gen_sub_tl(t2, t1, t2);
1165         break;
1166     }
1167 
1168     if (fractional) {
1169         TCGLabel *l_done = gen_new_label();
1170         TCGv rounding = tcg_temp_new();
1171 
1172         tcg_gen_andi_tl(rounding, mxu_CR, 0x2);
1173         tcg_gen_brcondi_tl(TCG_COND_EQ, rounding, 0, l_done);
1174         if (packed_result) {
1175             TCGLabel *l_apply_bias_l = gen_new_label();
1176             TCGLabel *l_apply_bias_r = gen_new_label();
1177             TCGLabel *l_half_done = gen_new_label();
1178             TCGv bias = tcg_temp_new();
1179 
1180             /*
1181              * D16MACF supports unbiased rounding aka "bankers rounding",
1182              * "round to even", "convergent rounding"
1183              */
1184             tcg_gen_andi_tl(bias, mxu_CR, 0x4);
1185             tcg_gen_brcondi_tl(TCG_COND_NE, bias, 0, l_apply_bias_l);
1186             tcg_gen_andi_tl(t0, t3, 0x1ffff);
1187             tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0x8000, l_half_done);
1188             gen_set_label(l_apply_bias_l);
1189             tcg_gen_addi_tl(t3, t3, 0x8000);
1190             gen_set_label(l_half_done);
1191             tcg_gen_brcondi_tl(TCG_COND_NE, bias, 0, l_apply_bias_r);
1192             tcg_gen_andi_tl(t0, t2, 0x1ffff);
1193             tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0x8000, l_done);
1194             gen_set_label(l_apply_bias_r);
1195             tcg_gen_addi_tl(t2, t2, 0x8000);
1196         } else {
1197             /* D16MACE doesn't support unbiased rounding */
1198             tcg_gen_addi_tl(t3, t3, 0x8000);
1199             tcg_gen_addi_tl(t2, t2, 0x8000);
1200         }
1201         gen_set_label(l_done);
1202     }
1203 
1204     if (!packed_result) {
1205         gen_store_mxu_gpr(t3, XRa);
1206         gen_store_mxu_gpr(t2, XRd);
1207     } else {
1208         tcg_gen_andi_tl(t3, t3, 0xffff0000);
1209         tcg_gen_shri_tl(t2, t2, 16);
1210         tcg_gen_or_tl(t3, t3, t2);
1211         gen_store_mxu_gpr(t3, XRa);
1212     }
1213 }
1214 
1215 /*
1216  * D16MADL XRa, XRb, XRc, XRd, aptn2, optn2 - Double packed
1217  * unsigned 16 bit pattern multiply and add/subtract.
1218  */
1219 static void gen_mxu_d16madl(DisasContext *ctx)
1220 {
1221     TCGv t0, t1, t2, t3;
1222     uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
1223 
1224     t0 = tcg_temp_new();
1225     t1 = tcg_temp_new();
1226     t2 = tcg_temp_new();
1227     t3 = tcg_temp_new();
1228 
1229     XRa = extract32(ctx->opcode, 6, 4);
1230     XRb = extract32(ctx->opcode, 10, 4);
1231     XRc = extract32(ctx->opcode, 14, 4);
1232     XRd = extract32(ctx->opcode, 18, 4);
1233     optn2 = extract32(ctx->opcode, 22, 2);
1234     aptn2 = extract32(ctx->opcode, 24, 2);
1235 
1236     gen_load_mxu_gpr(t1, XRb);
1237     tcg_gen_sextract_tl(t0, t1,  0, 16);
1238     tcg_gen_sextract_tl(t1, t1, 16, 16);
1239 
1240     gen_load_mxu_gpr(t3, XRc);
1241     tcg_gen_sextract_tl(t2, t3,  0, 16);
1242     tcg_gen_sextract_tl(t3, t3, 16, 16);
1243 
1244     switch (optn2) {
1245     case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
1246         tcg_gen_mul_tl(t3, t1, t3);
1247         tcg_gen_mul_tl(t2, t0, t2);
1248         break;
1249     case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
1250         tcg_gen_mul_tl(t3, t0, t3);
1251         tcg_gen_mul_tl(t2, t0, t2);
1252         break;
1253     case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
1254         tcg_gen_mul_tl(t3, t1, t3);
1255         tcg_gen_mul_tl(t2, t1, t2);
1256         break;
1257     case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
1258         tcg_gen_mul_tl(t3, t0, t3);
1259         tcg_gen_mul_tl(t2, t1, t2);
1260         break;
1261     }
1262     tcg_gen_extract_tl(t2, t2, 0, 16);
1263     tcg_gen_extract_tl(t3, t3, 0, 16);
1264 
1265     gen_load_mxu_gpr(t1, XRa);
1266     tcg_gen_extract_tl(t0, t1,  0, 16);
1267     tcg_gen_extract_tl(t1, t1, 16, 16);
1268 
1269     switch (aptn2) {
1270     case MXU_APTN2_AA:
1271         tcg_gen_add_tl(t3, t1, t3);
1272         tcg_gen_add_tl(t2, t0, t2);
1273         break;
1274     case MXU_APTN2_AS:
1275         tcg_gen_add_tl(t3, t1, t3);
1276         tcg_gen_sub_tl(t2, t0, t2);
1277         break;
1278     case MXU_APTN2_SA:
1279         tcg_gen_sub_tl(t3, t1, t3);
1280         tcg_gen_add_tl(t2, t0, t2);
1281         break;
1282     case MXU_APTN2_SS:
1283         tcg_gen_sub_tl(t3, t1, t3);
1284         tcg_gen_sub_tl(t2, t0, t2);
1285         break;
1286     }
1287 
1288     tcg_gen_andi_tl(t2, t2, 0xffff);
1289     tcg_gen_shli_tl(t3, t3, 16);
1290     tcg_gen_or_tl(mxu_gpr[XRd - 1], t3, t2);
1291 }
1292 
1293 /*
1294  * S16MAD XRa, XRb, XRc, XRd, aptn2, optn2 - Single packed
1295  * signed 16 bit pattern multiply and 32-bit add/subtract.
1296  */
1297 static void gen_mxu_s16mad(DisasContext *ctx)
1298 {
1299     TCGv t0, t1;
1300     uint32_t XRa, XRb, XRc, XRd, optn2, aptn1, pad;
1301 
1302     t0 = tcg_temp_new();
1303     t1 = tcg_temp_new();
1304 
1305     XRa = extract32(ctx->opcode, 6, 4);
1306     XRb = extract32(ctx->opcode, 10, 4);
1307     XRc = extract32(ctx->opcode, 14, 4);
1308     XRd = extract32(ctx->opcode, 18, 4);
1309     optn2 = extract32(ctx->opcode, 22, 2);
1310     aptn1 = extract32(ctx->opcode, 24, 1);
1311     pad = extract32(ctx->opcode, 25, 1);
1312 
1313     if (pad) {
1314         /* FIXME check if it influence the result */
1315     }
1316 
1317     gen_load_mxu_gpr(t0, XRb);
1318     gen_load_mxu_gpr(t1, XRc);
1319 
1320     switch (optn2) {
1321     case MXU_OPTN2_WW: /* XRB.H*XRC.H */
1322         tcg_gen_sextract_tl(t0, t0, 16, 16);
1323         tcg_gen_sextract_tl(t1, t1, 16, 16);
1324         break;
1325     case MXU_OPTN2_LW: /* XRB.L*XRC.L */
1326         tcg_gen_sextract_tl(t0, t0,  0, 16);
1327         tcg_gen_sextract_tl(t1, t1,  0, 16);
1328         break;
1329     case MXU_OPTN2_HW: /* XRB.H*XRC.L */
1330         tcg_gen_sextract_tl(t0, t0, 16, 16);
1331         tcg_gen_sextract_tl(t1, t1,  0, 16);
1332         break;
1333     case MXU_OPTN2_XW: /* XRB.L*XRC.H */
1334         tcg_gen_sextract_tl(t0, t0,  0, 16);
1335         tcg_gen_sextract_tl(t1, t1, 16, 16);
1336         break;
1337     }
1338     tcg_gen_mul_tl(t0, t0, t1);
1339 
1340     gen_load_mxu_gpr(t1, XRa);
1341 
1342     switch (aptn1) {
1343     case MXU_APTN1_A:
1344         tcg_gen_add_tl(t1, t1, t0);
1345         break;
1346     case MXU_APTN1_S:
1347         tcg_gen_sub_tl(t1, t1, t0);
1348         break;
1349     }
1350 
1351     gen_store_mxu_gpr(t1, XRd);
1352 }
1353 
1354 /*
1355  * Q8MUL   XRa, XRb, XRc, XRd - Parallel quad unsigned 8 bit multiply
1356  * Q8MULSU XRa, XRb, XRc, XRd - Parallel quad signed 8 bit multiply
1357  * Q8MAC   XRa, XRb, XRc, XRd - Parallel quad unsigned 8 bit multiply
1358  *   and accumulate
1359  * Q8MACSU XRa, XRb, XRc, XRd - Parallel quad signed 8 bit multiply
1360  *   and accumulate
1361  */
1362 static void gen_mxu_q8mul_mac(DisasContext *ctx, bool su, bool mac)
1363 {
1364     TCGv t0, t1, t2, t3, t4, t5, t6, t7;
1365     uint32_t XRa, XRb, XRc, XRd, aptn2;
1366 
1367     t0 = tcg_temp_new();
1368     t1 = tcg_temp_new();
1369     t2 = tcg_temp_new();
1370     t3 = tcg_temp_new();
1371     t4 = tcg_temp_new();
1372     t5 = tcg_temp_new();
1373     t6 = tcg_temp_new();
1374     t7 = tcg_temp_new();
1375 
1376     XRa = extract32(ctx->opcode, 6, 4);
1377     XRb = extract32(ctx->opcode, 10, 4);
1378     XRc = extract32(ctx->opcode, 14, 4);
1379     XRd = extract32(ctx->opcode, 18, 4);
1380     aptn2 = extract32(ctx->opcode, 24, 2);
1381 
1382     gen_load_mxu_gpr(t3, XRb);
1383     gen_load_mxu_gpr(t7, XRc);
1384 
1385     if (su) {
1386         /* Q8MULSU / Q8MACSU */
1387         tcg_gen_sextract_tl(t0, t3,  0, 8);
1388         tcg_gen_sextract_tl(t1, t3,  8, 8);
1389         tcg_gen_sextract_tl(t2, t3, 16, 8);
1390         tcg_gen_sextract_tl(t3, t3, 24, 8);
1391     } else {
1392         /* Q8MUL / Q8MAC */
1393         tcg_gen_extract_tl(t0, t3,  0, 8);
1394         tcg_gen_extract_tl(t1, t3,  8, 8);
1395         tcg_gen_extract_tl(t2, t3, 16, 8);
1396         tcg_gen_extract_tl(t3, t3, 24, 8);
1397     }
1398 
1399     tcg_gen_extract_tl(t4, t7,  0, 8);
1400     tcg_gen_extract_tl(t5, t7,  8, 8);
1401     tcg_gen_extract_tl(t6, t7, 16, 8);
1402     tcg_gen_extract_tl(t7, t7, 24, 8);
1403 
1404     tcg_gen_mul_tl(t0, t0, t4);
1405     tcg_gen_mul_tl(t1, t1, t5);
1406     tcg_gen_mul_tl(t2, t2, t6);
1407     tcg_gen_mul_tl(t3, t3, t7);
1408 
1409     if (mac) {
1410         gen_load_mxu_gpr(t4, XRd);
1411         gen_load_mxu_gpr(t5, XRa);
1412         tcg_gen_extract_tl(t6, t4,  0, 16);
1413         tcg_gen_extract_tl(t7, t4, 16, 16);
1414         if (aptn2 & 1) {
1415             tcg_gen_sub_tl(t0, t6, t0);
1416             tcg_gen_sub_tl(t1, t7, t1);
1417         } else {
1418             tcg_gen_add_tl(t0, t6, t0);
1419             tcg_gen_add_tl(t1, t7, t1);
1420         }
1421         tcg_gen_extract_tl(t6, t5,  0, 16);
1422         tcg_gen_extract_tl(t7, t5, 16, 16);
1423         if (aptn2 & 2) {
1424             tcg_gen_sub_tl(t2, t6, t2);
1425             tcg_gen_sub_tl(t3, t7, t3);
1426         } else {
1427             tcg_gen_add_tl(t2, t6, t2);
1428             tcg_gen_add_tl(t3, t7, t3);
1429         }
1430     }
1431 
1432     tcg_gen_deposit_tl(t0, t0, t1, 16, 16);
1433     tcg_gen_deposit_tl(t1, t2, t3, 16, 16);
1434 
1435     gen_store_mxu_gpr(t0, XRd);
1436     gen_store_mxu_gpr(t1, XRa);
1437 }
1438 
1439 /*
1440  * Q8MADL  XRd, XRa, XRb, XRc
1441  *   Parallel quad unsigned 8 bit multiply and accumulate.
1442  *   e.g. XRd[0..3] = XRa[0..3] + XRb[0..3] * XRc[0..3]
1443  */
1444 static void gen_mxu_q8madl(DisasContext *ctx)
1445 {
1446     TCGv t0, t1, t2, t3, t4, t5, t6, t7;
1447     uint32_t XRa, XRb, XRc, XRd, aptn2;
1448 
1449     t0 = tcg_temp_new();
1450     t1 = tcg_temp_new();
1451     t2 = tcg_temp_new();
1452     t3 = tcg_temp_new();
1453     t4 = tcg_temp_new();
1454     t5 = tcg_temp_new();
1455     t6 = tcg_temp_new();
1456     t7 = tcg_temp_new();
1457 
1458     XRa = extract32(ctx->opcode, 6, 4);
1459     XRb = extract32(ctx->opcode, 10, 4);
1460     XRc = extract32(ctx->opcode, 14, 4);
1461     XRd = extract32(ctx->opcode, 18, 4);
1462     aptn2 = extract32(ctx->opcode, 24, 2);
1463 
1464     gen_load_mxu_gpr(t3, XRb);
1465     gen_load_mxu_gpr(t7, XRc);
1466 
1467     tcg_gen_extract_tl(t0, t3,  0, 8);
1468     tcg_gen_extract_tl(t1, t3,  8, 8);
1469     tcg_gen_extract_tl(t2, t3, 16, 8);
1470     tcg_gen_extract_tl(t3, t3, 24, 8);
1471 
1472     tcg_gen_extract_tl(t4, t7,  0, 8);
1473     tcg_gen_extract_tl(t5, t7,  8, 8);
1474     tcg_gen_extract_tl(t6, t7, 16, 8);
1475     tcg_gen_extract_tl(t7, t7, 24, 8);
1476 
1477     tcg_gen_mul_tl(t0, t0, t4);
1478     tcg_gen_mul_tl(t1, t1, t5);
1479     tcg_gen_mul_tl(t2, t2, t6);
1480     tcg_gen_mul_tl(t3, t3, t7);
1481 
1482     gen_load_mxu_gpr(t4, XRa);
1483     tcg_gen_extract_tl(t6, t4, 0, 8);
1484     tcg_gen_extract_tl(t7, t4, 8, 8);
1485     if (aptn2 & 1) {
1486         tcg_gen_sub_tl(t0, t6, t0);
1487         tcg_gen_sub_tl(t1, t7, t1);
1488     } else {
1489         tcg_gen_add_tl(t0, t6, t0);
1490         tcg_gen_add_tl(t1, t7, t1);
1491     }
1492     tcg_gen_extract_tl(t6, t4, 16, 8);
1493     tcg_gen_extract_tl(t7, t4, 24, 8);
1494     if (aptn2 & 2) {
1495         tcg_gen_sub_tl(t2, t6, t2);
1496         tcg_gen_sub_tl(t3, t7, t3);
1497     } else {
1498         tcg_gen_add_tl(t2, t6, t2);
1499         tcg_gen_add_tl(t3, t7, t3);
1500     }
1501 
1502     tcg_gen_andi_tl(t5, t0, 0xff);
1503     tcg_gen_deposit_tl(t5, t5, t1,  8, 8);
1504     tcg_gen_deposit_tl(t5, t5, t2, 16, 8);
1505     tcg_gen_deposit_tl(t5, t5, t3, 24, 8);
1506 
1507     gen_store_mxu_gpr(t5, XRd);
1508 }
1509 
1510 /*
1511  * S32LDD  XRa, Rb, S12 - Load a word from memory to XRF
1512  * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF
1513  *   in reversed byte seq.
1514  * S32LDI  XRa, Rb, S12 - Load a word from memory to XRF,
1515  *   post modify base address GPR.
1516  * S32LDIR XRa, Rb, S12 - Load a word from memory to XRF,
1517  *   post modify base address GPR and load in reversed byte seq.
1518  */
1519 static void gen_mxu_s32ldxx(DisasContext *ctx, bool reversed, bool postinc)
1520 {
1521     TCGv t0, t1;
1522     uint32_t XRa, Rb, s12;
1523 
1524     t0 = tcg_temp_new();
1525     t1 = tcg_temp_new();
1526 
1527     XRa = extract32(ctx->opcode, 6, 4);
1528     s12 = sextract32(ctx->opcode, 10, 10);
1529     Rb = extract32(ctx->opcode, 21, 5);
1530 
1531     gen_load_gpr(t0, Rb);
1532     tcg_gen_movi_tl(t1, s12 * 4);
1533     tcg_gen_add_tl(t0, t0, t1);
1534 
1535     tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx,
1536                        (MO_TESL ^ (reversed ? MO_BSWAP : 0)) |
1537                         ctx->default_tcg_memop_mask);
1538     gen_store_mxu_gpr(t1, XRa);
1539 
1540     if (postinc) {
1541         gen_store_gpr(t0, Rb);
1542     }
1543 }
1544 
1545 /*
1546  * S32STD  XRa, Rb, S12 - Store a word from XRF to memory
1547  * S32STDR XRa, Rb, S12 - Store a word from XRF to memory
1548  *   in reversed byte seq.
1549  * S32SDI  XRa, Rb, S12 - Store a word from XRF to memory,
1550  *   post modify base address GPR.
1551  * S32SDIR XRa, Rb, S12 - Store a word from XRF to memory,
1552  *   post modify base address GPR and store in reversed byte seq.
1553  */
1554 static void gen_mxu_s32stxx(DisasContext *ctx, bool reversed, bool postinc)
1555 {
1556     TCGv t0, t1;
1557     uint32_t XRa, Rb, s12;
1558 
1559     t0 = tcg_temp_new();
1560     t1 = tcg_temp_new();
1561 
1562     XRa = extract32(ctx->opcode, 6, 4);
1563     s12 = sextract32(ctx->opcode, 10, 10);
1564     Rb = extract32(ctx->opcode, 21, 5);
1565 
1566     gen_load_gpr(t0, Rb);
1567     tcg_gen_movi_tl(t1, s12 * 4);
1568     tcg_gen_add_tl(t0, t0, t1);
1569 
1570     gen_load_mxu_gpr(t1, XRa);
1571     tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
1572                        (MO_TESL ^ (reversed ? MO_BSWAP : 0)) |
1573                         ctx->default_tcg_memop_mask);
1574 
1575     if (postinc) {
1576         gen_store_gpr(t0, Rb);
1577     }
1578 }
1579 
1580 /*
1581  * S32LDDV  XRa, Rb, Rc, STRD2 - Load a word from memory to XRF
1582  * S32LDDVR XRa, Rb, Rc, STRD2 - Load a word from memory to XRF
1583  *   in reversed byte seq.
1584  * S32LDIV  XRa, Rb, Rc, STRD2 - Load a word from memory to XRF,
1585  *   post modify base address GPR.
1586  * S32LDIVR XRa, Rb, Rc, STRD2 - Load a word from memory to XRF,
1587  *   post modify base address GPR and load in reversed byte seq.
1588  */
1589 static void gen_mxu_s32ldxvx(DisasContext *ctx, bool reversed,
1590                              bool postinc, uint32_t strd2)
1591 {
1592     TCGv t0, t1;
1593     uint32_t XRa, Rb, Rc;
1594 
1595     t0 = tcg_temp_new();
1596     t1 = tcg_temp_new();
1597 
1598     XRa = extract32(ctx->opcode, 6, 4);
1599     Rc = extract32(ctx->opcode, 16, 5);
1600     Rb = extract32(ctx->opcode, 21, 5);
1601 
1602     gen_load_gpr(t0, Rb);
1603     gen_load_gpr(t1, Rc);
1604     tcg_gen_shli_tl(t1, t1, strd2);
1605     tcg_gen_add_tl(t0, t0, t1);
1606 
1607     tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx,
1608                        (MO_TESL ^ (reversed ? MO_BSWAP : 0)) |
1609                         ctx->default_tcg_memop_mask);
1610     gen_store_mxu_gpr(t1, XRa);
1611 
1612     if (postinc) {
1613         gen_store_gpr(t0, Rb);
1614     }
1615 }
1616 
1617 /*
1618  * LXW  Ra, Rb, Rc, STRD2 - Load a word from memory to GPR
1619  * LXB  Ra, Rb, Rc, STRD2 - Load a byte from memory to GPR,
1620  *   sign extending to GPR size.
1621  * LXH  Ra, Rb, Rc, STRD2 - Load a byte from memory to GPR,
1622  *   sign extending to GPR size.
1623  * LXBU Ra, Rb, Rc, STRD2 - Load a halfword from memory to GPR,
1624  *   zero extending to GPR size.
1625  * LXHU Ra, Rb, Rc, STRD2 - Load a halfword from memory to GPR,
1626  *   zero extending to GPR size.
1627  */
1628 static void gen_mxu_lxx(DisasContext *ctx, uint32_t strd2, MemOp mop)
1629 {
1630     TCGv t0, t1;
1631     uint32_t Ra, Rb, Rc;
1632 
1633     t0 = tcg_temp_new();
1634     t1 = tcg_temp_new();
1635 
1636     Ra = extract32(ctx->opcode, 11, 5);
1637     Rc = extract32(ctx->opcode, 16, 5);
1638     Rb = extract32(ctx->opcode, 21, 5);
1639 
1640     gen_load_gpr(t0, Rb);
1641     gen_load_gpr(t1, Rc);
1642     tcg_gen_shli_tl(t1, t1, strd2);
1643     tcg_gen_add_tl(t0, t0, t1);
1644 
1645     tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, mop | ctx->default_tcg_memop_mask);
1646     gen_store_gpr(t1, Ra);
1647 }
1648 
1649 /*
1650  * S32STDV  XRa, Rb, Rc, STRD2 - Load a word from memory to XRF
1651  * S32STDVR XRa, Rb, Rc, STRD2 - Load a word from memory to XRF
1652  *   in reversed byte seq.
1653  * S32SDIV  XRa, Rb, Rc, STRD2 - Load a word from memory to XRF,
1654  *   post modify base address GPR.
1655  * S32SDIVR XRa, Rb, Rc, STRD2 - Load a word from memory to XRF,
1656  *   post modify base address GPR and store in reversed byte seq.
1657  */
1658 static void gen_mxu_s32stxvx(DisasContext *ctx, bool reversed,
1659                              bool postinc, uint32_t strd2)
1660 {
1661     TCGv t0, t1;
1662     uint32_t XRa, Rb, Rc;
1663 
1664     t0 = tcg_temp_new();
1665     t1 = tcg_temp_new();
1666 
1667     XRa = extract32(ctx->opcode, 6, 4);
1668     Rc = extract32(ctx->opcode, 16, 5);
1669     Rb = extract32(ctx->opcode, 21, 5);
1670 
1671     gen_load_gpr(t0, Rb);
1672     gen_load_gpr(t1, Rc);
1673     tcg_gen_shli_tl(t1, t1, strd2);
1674     tcg_gen_add_tl(t0, t0, t1);
1675 
1676     gen_load_mxu_gpr(t1, XRa);
1677     tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
1678                        (MO_TESL ^ (reversed ? MO_BSWAP : 0)) |
1679                         ctx->default_tcg_memop_mask);
1680 
1681     if (postinc) {
1682         gen_store_gpr(t0, Rb);
1683     }
1684 }
1685 
1686 /*
1687  *                 MXU instruction category: logic
1688  *                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1689  *
1690  *               S32NOR    S32AND    S32OR    S32XOR
1691  */
1692 
1693 /*
1694  *  S32NOR XRa, XRb, XRc
1695  *    Update XRa with the result of logical bitwise 'nor' operation
1696  *    applied to the content of XRb and XRc.
1697  */
1698 static void gen_mxu_S32NOR(DisasContext *ctx)
1699 {
1700     uint32_t pad, XRc, XRb, XRa;
1701 
1702     pad = extract32(ctx->opcode, 21, 5);
1703     XRc = extract32(ctx->opcode, 14, 4);
1704     XRb = extract32(ctx->opcode, 10, 4);
1705     XRa = extract32(ctx->opcode,  6, 4);
1706 
1707     if (unlikely(pad != 0)) {
1708         /* opcode padding incorrect -> do nothing */
1709     } else if (unlikely(XRa == 0)) {
1710         /* destination is zero register -> do nothing */
1711     } else if (unlikely((XRb == 0) && (XRc == 0))) {
1712         /* both operands zero registers -> just set destination to all 1s */
1713         tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF);
1714     } else if (unlikely(XRb == 0)) {
1715         /* XRb zero register -> just set destination to the negation of XRc */
1716         tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
1717     } else if (unlikely(XRc == 0)) {
1718         /* XRa zero register -> just set destination to the negation of XRb */
1719         tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
1720     } else if (unlikely(XRb == XRc)) {
1721         /* both operands same -> just set destination to the negation of XRb */
1722         tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
1723     } else {
1724         /* the most general case */
1725         tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
1726     }
1727 }
1728 
1729 /*
1730  *  S32AND XRa, XRb, XRc
1731  *    Update XRa with the result of logical bitwise 'and' operation
1732  *    applied to the content of XRb and XRc.
1733  */
1734 static void gen_mxu_S32AND(DisasContext *ctx)
1735 {
1736     uint32_t pad, XRc, XRb, XRa;
1737 
1738     pad = extract32(ctx->opcode, 21, 5);
1739     XRc = extract32(ctx->opcode, 14, 4);
1740     XRb = extract32(ctx->opcode, 10, 4);
1741     XRa = extract32(ctx->opcode,  6, 4);
1742 
1743     if (unlikely(pad != 0)) {
1744         /* opcode padding incorrect -> do nothing */
1745     } else if (unlikely(XRa == 0)) {
1746         /* destination is zero register -> do nothing */
1747     } else if (unlikely((XRb == 0) || (XRc == 0))) {
1748         /* one of operands zero register -> just set destination to all 0s */
1749         tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
1750     } else if (unlikely(XRb == XRc)) {
1751         /* both operands same -> just set destination to one of them */
1752         tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
1753     } else {
1754         /* the most general case */
1755         tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
1756     }
1757 }
1758 
1759 /*
1760  *  S32OR XRa, XRb, XRc
1761  *    Update XRa with the result of logical bitwise 'or' operation
1762  *    applied to the content of XRb and XRc.
1763  */
1764 static void gen_mxu_S32OR(DisasContext *ctx)
1765 {
1766     uint32_t pad, XRc, XRb, XRa;
1767 
1768     pad = extract32(ctx->opcode, 21, 5);
1769     XRc = extract32(ctx->opcode, 14, 4);
1770     XRb = extract32(ctx->opcode, 10, 4);
1771     XRa = extract32(ctx->opcode,  6, 4);
1772 
1773     if (unlikely(pad != 0)) {
1774         /* opcode padding incorrect -> do nothing */
1775     } else if (unlikely(XRa == 0)) {
1776         /* destination is zero register -> do nothing */
1777     } else if (unlikely((XRb == 0) && (XRc == 0))) {
1778         /* both operands zero registers -> just set destination to all 0s */
1779         tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
1780     } else if (unlikely(XRb == 0)) {
1781         /* XRb zero register -> just set destination to the content of XRc */
1782         tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
1783     } else if (unlikely(XRc == 0)) {
1784         /* XRc zero register -> just set destination to the content of XRb */
1785         tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
1786     } else if (unlikely(XRb == XRc)) {
1787         /* both operands same -> just set destination to one of them */
1788         tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
1789     } else {
1790         /* the most general case */
1791         tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
1792     }
1793 }
1794 
1795 /*
1796  *  S32XOR XRa, XRb, XRc
1797  *    Update XRa with the result of logical bitwise 'xor' operation
1798  *    applied to the content of XRb and XRc.
1799  */
1800 static void gen_mxu_S32XOR(DisasContext *ctx)
1801 {
1802     uint32_t pad, XRc, XRb, XRa;
1803 
1804     pad = extract32(ctx->opcode, 21, 5);
1805     XRc = extract32(ctx->opcode, 14, 4);
1806     XRb = extract32(ctx->opcode, 10, 4);
1807     XRa = extract32(ctx->opcode,  6, 4);
1808 
1809     if (unlikely(pad != 0)) {
1810         /* opcode padding incorrect -> do nothing */
1811     } else if (unlikely(XRa == 0)) {
1812         /* destination is zero register -> do nothing */
1813     } else if (unlikely((XRb == 0) && (XRc == 0))) {
1814         /* both operands zero registers -> just set destination to all 0s */
1815         tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
1816     } else if (unlikely(XRb == 0)) {
1817         /* XRb zero register -> just set destination to the content of XRc */
1818         tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
1819     } else if (unlikely(XRc == 0)) {
1820         /* XRc zero register -> just set destination to the content of XRb */
1821         tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
1822     } else if (unlikely(XRb == XRc)) {
1823         /* both operands same -> just set destination to all 0s */
1824         tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
1825     } else {
1826         /* the most general case */
1827         tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
1828     }
1829 }
1830 
1831 /*
1832  *                 MXU instruction category: shift
1833  *                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1834  *
1835  *               D32SLL    D32SLR    D32SAR    D32SARL
1836  *               D32SLLV   D32SLRV   D32SARV   D32SARW
1837  *               Q16SLL    Q16SLR    Q16SAR
1838  *               Q16SLLV   Q16SLRV   Q16SARV
1839  */
1840 
1841 /*
1842  *  D32SLL XRa, XRd, XRb, XRc, SFT4
1843  *    Dual 32-bit shift left from XRb and XRc to SFT4
1844  *    bits (0..15). Store to XRa and XRd respectively.
1845  *  D32SLR XRa, XRd, XRb, XRc, SFT4
1846  *    Dual 32-bit shift logic right from XRb and XRc
1847  *    to SFT4 bits (0..15). Store to XRa and XRd respectively.
1848  *  D32SAR XRa, XRd, XRb, XRc, SFT4
1849  *    Dual 32-bit shift arithmetic right from XRb and XRc
1850  *    to SFT4 bits (0..15). Store to XRa and XRd respectively.
1851  */
1852 static void gen_mxu_d32sxx(DisasContext *ctx, bool right, bool arithmetic)
1853 {
1854     uint32_t XRa, XRb, XRc, XRd, sft4;
1855 
1856     XRa  = extract32(ctx->opcode,  6, 4);
1857     XRb  = extract32(ctx->opcode, 10, 4);
1858     XRc  = extract32(ctx->opcode, 14, 4);
1859     XRd  = extract32(ctx->opcode, 18, 4);
1860     sft4 = extract32(ctx->opcode, 22, 4);
1861 
1862     TCGv t0 = tcg_temp_new();
1863     TCGv t1 = tcg_temp_new();
1864 
1865     gen_load_mxu_gpr(t0, XRb);
1866     gen_load_mxu_gpr(t1, XRc);
1867 
1868     if (right) {
1869         if (arithmetic) {
1870             tcg_gen_sari_tl(t0, t0, sft4);
1871             tcg_gen_sari_tl(t1, t1, sft4);
1872         } else {
1873             tcg_gen_shri_tl(t0, t0, sft4);
1874             tcg_gen_shri_tl(t1, t1, sft4);
1875         }
1876     } else {
1877         tcg_gen_shli_tl(t0, t0, sft4);
1878         tcg_gen_shli_tl(t1, t1, sft4);
1879     }
1880     gen_store_mxu_gpr(t0, XRa);
1881     gen_store_mxu_gpr(t1, XRd);
1882 }
1883 
1884 /*
1885  *  D32SLLV XRa, XRd, rs
1886  *    Dual 32-bit shift left from XRa and XRd to rs[3:0]
1887  *    bits. Store back to XRa and XRd respectively.
1888  *  D32SLRV XRa, XRd, rs
1889  *    Dual 32-bit shift logic right from XRa and XRd to rs[3:0]
1890  *    bits. Store back to XRa and XRd respectively.
1891  *  D32SARV XRa, XRd, rs
1892  *    Dual 32-bit shift arithmetic right from XRa and XRd to rs[3:0]
1893  *    bits. Store back to XRa and XRd respectively.
1894  */
1895 static void gen_mxu_d32sxxv(DisasContext *ctx, bool right, bool arithmetic)
1896 {
1897     uint32_t XRa, XRd, rs;
1898 
1899     XRa = extract32(ctx->opcode, 10, 4);
1900     XRd = extract32(ctx->opcode, 14, 4);
1901     rs  = extract32(ctx->opcode, 21, 5);
1902 
1903     TCGv t0 = tcg_temp_new();
1904     TCGv t1 = tcg_temp_new();
1905     TCGv t2 = tcg_temp_new();
1906 
1907     gen_load_mxu_gpr(t0, XRa);
1908     gen_load_mxu_gpr(t1, XRd);
1909     gen_load_gpr(t2, rs);
1910     tcg_gen_andi_tl(t2, t2, 0x0f);
1911 
1912     if (right) {
1913         if (arithmetic) {
1914             tcg_gen_sar_tl(t0, t0, t2);
1915             tcg_gen_sar_tl(t1, t1, t2);
1916         } else {
1917             tcg_gen_shr_tl(t0, t0, t2);
1918             tcg_gen_shr_tl(t1, t1, t2);
1919         }
1920     } else {
1921         tcg_gen_shl_tl(t0, t0, t2);
1922         tcg_gen_shl_tl(t1, t1, t2);
1923     }
1924     gen_store_mxu_gpr(t0, XRa);
1925     gen_store_mxu_gpr(t1, XRd);
1926 }
1927 
1928 /*
1929  *  D32SARL XRa, XRb, XRc, SFT4
1930  *    Dual shift arithmetic right 32-bit integers in XRb and XRc
1931  *    to SFT4 bits (0..15). Pack 16 LSBs of each into XRa.
1932  *
1933  *  D32SARW XRa, XRb, XRc, rb
1934  *    Dual shift arithmetic right 32-bit integers in XRb and XRc
1935  *    to rb[3:0] bits. Pack 16 LSBs of each into XRa.
1936  */
1937 static void gen_mxu_d32sarl(DisasContext *ctx, bool sarw)
1938 {
1939     uint32_t XRa, XRb, XRc, rb;
1940 
1941     XRa = extract32(ctx->opcode,  6, 4);
1942     XRb = extract32(ctx->opcode, 10, 4);
1943     XRc = extract32(ctx->opcode, 14, 4);
1944     rb  = extract32(ctx->opcode, 21, 5);
1945 
1946     if (unlikely(XRa == 0)) {
1947         /* destination is zero register -> do nothing */
1948     } else {
1949         TCGv t0 = tcg_temp_new();
1950         TCGv t1 = tcg_temp_new();
1951         TCGv t2 = tcg_temp_new();
1952 
1953         if (!sarw) {
1954             /* Make SFT4 from rb field */
1955             tcg_gen_movi_tl(t2, rb >> 1);
1956         } else {
1957             gen_load_gpr(t2, rb);
1958             tcg_gen_andi_tl(t2, t2, 0x0f);
1959         }
1960         gen_load_mxu_gpr(t0, XRb);
1961         gen_load_mxu_gpr(t1, XRc);
1962         tcg_gen_sar_tl(t0, t0, t2);
1963         tcg_gen_sar_tl(t1, t1, t2);
1964         tcg_gen_extract_tl(t2, t1, 0, 16);
1965         tcg_gen_deposit_tl(t2, t2, t0, 16, 16);
1966         gen_store_mxu_gpr(t2, XRa);
1967     }
1968 }
1969 
1970 /*
1971  *  Q16SLL XRa, XRd, XRb, XRc, SFT4
1972  *    Quad 16-bit shift left from XRb and XRc to SFT4
1973  *    bits (0..15). Store to XRa and XRd respectively.
1974  *  Q16SLR XRa, XRd, XRb, XRc, SFT4
1975  *    Quad 16-bit shift logic right from XRb and XRc
1976  *    to SFT4 bits (0..15). Store to XRa and XRd respectively.
1977  *  Q16SAR XRa, XRd, XRb, XRc, SFT4
1978  *    Quad 16-bit shift arithmetic right from XRb and XRc
1979  *    to SFT4 bits (0..15). Store to XRa and XRd respectively.
1980  */
1981 static void gen_mxu_q16sxx(DisasContext *ctx, bool right, bool arithmetic)
1982 {
1983     uint32_t XRa, XRb, XRc, XRd, sft4;
1984 
1985     XRa  = extract32(ctx->opcode,  6, 4);
1986     XRb  = extract32(ctx->opcode, 10, 4);
1987     XRc  = extract32(ctx->opcode, 14, 4);
1988     XRd  = extract32(ctx->opcode, 18, 4);
1989     sft4 = extract32(ctx->opcode, 22, 4);
1990 
1991     TCGv t0 = tcg_temp_new();
1992     TCGv t1 = tcg_temp_new();
1993     TCGv t2 = tcg_temp_new();
1994     TCGv t3 = tcg_temp_new();
1995 
1996     gen_load_mxu_gpr(t0, XRb);
1997     gen_load_mxu_gpr(t2, XRc);
1998 
1999     if (arithmetic) {
2000         tcg_gen_sextract_tl(t1, t0, 16, 16);
2001         tcg_gen_sextract_tl(t0, t0,  0, 16);
2002         tcg_gen_sextract_tl(t3, t2, 16, 16);
2003         tcg_gen_sextract_tl(t2, t2,  0, 16);
2004     } else {
2005         tcg_gen_extract_tl(t1, t0, 16, 16);
2006         tcg_gen_extract_tl(t0, t0,  0, 16);
2007         tcg_gen_extract_tl(t3, t2, 16, 16);
2008         tcg_gen_extract_tl(t2, t2,  0, 16);
2009     }
2010 
2011     if (right) {
2012         if (arithmetic) {
2013             tcg_gen_sari_tl(t0, t0, sft4);
2014             tcg_gen_sari_tl(t1, t1, sft4);
2015             tcg_gen_sari_tl(t2, t2, sft4);
2016             tcg_gen_sari_tl(t3, t3, sft4);
2017         } else {
2018             tcg_gen_shri_tl(t0, t0, sft4);
2019             tcg_gen_shri_tl(t1, t1, sft4);
2020             tcg_gen_shri_tl(t2, t2, sft4);
2021             tcg_gen_shri_tl(t3, t3, sft4);
2022         }
2023     } else {
2024         tcg_gen_shli_tl(t0, t0, sft4);
2025         tcg_gen_shli_tl(t1, t1, sft4);
2026         tcg_gen_shli_tl(t2, t2, sft4);
2027         tcg_gen_shli_tl(t3, t3, sft4);
2028     }
2029     tcg_gen_deposit_tl(t0, t0, t1, 16, 16);
2030     tcg_gen_deposit_tl(t2, t2, t3, 16, 16);
2031 
2032     gen_store_mxu_gpr(t0, XRa);
2033     gen_store_mxu_gpr(t2, XRd);
2034 }
2035 
2036 /*
2037  *  Q16SLLV XRa, XRd, rs
2038  *    Quad 16-bit shift left from XRa and XRd to rs[3:0]
2039  *    bits. Store to XRa and XRd respectively.
2040  *  Q16SLRV XRa, XRd, rs
2041  *    Quad 16-bit shift logic right from XRa and XRd to rs[3:0]
2042  *    bits. Store to XRa and XRd respectively.
2043  *  Q16SARV XRa, XRd, rs
2044  *    Quad 16-bit shift arithmetic right from XRa and XRd to rs[3:0]
2045  *    bits. Store to XRa and XRd respectively.
2046  */
2047 static void gen_mxu_q16sxxv(DisasContext *ctx, bool right, bool arithmetic)
2048 {
2049     uint32_t XRa, XRd, rs;
2050 
2051     XRa = extract32(ctx->opcode, 10, 4);
2052     XRd = extract32(ctx->opcode, 14, 4);
2053     rs  = extract32(ctx->opcode, 21, 5);
2054 
2055     TCGv t0 = tcg_temp_new();
2056     TCGv t1 = tcg_temp_new();
2057     TCGv t2 = tcg_temp_new();
2058     TCGv t3 = tcg_temp_new();
2059     TCGv t5 = tcg_temp_new();
2060 
2061     gen_load_mxu_gpr(t0, XRa);
2062     gen_load_mxu_gpr(t2, XRd);
2063     gen_load_gpr(t5, rs);
2064     tcg_gen_andi_tl(t5, t5, 0x0f);
2065 
2066 
2067     if (arithmetic) {
2068         tcg_gen_sextract_tl(t1, t0, 16, 16);
2069         tcg_gen_sextract_tl(t0, t0,  0, 16);
2070         tcg_gen_sextract_tl(t3, t2, 16, 16);
2071         tcg_gen_sextract_tl(t2, t2,  0, 16);
2072     } else {
2073         tcg_gen_extract_tl(t1, t0, 16, 16);
2074         tcg_gen_extract_tl(t0, t0,  0, 16);
2075         tcg_gen_extract_tl(t3, t2, 16, 16);
2076         tcg_gen_extract_tl(t2, t2,  0, 16);
2077     }
2078 
2079     if (right) {
2080         if (arithmetic) {
2081             tcg_gen_sar_tl(t0, t0, t5);
2082             tcg_gen_sar_tl(t1, t1, t5);
2083             tcg_gen_sar_tl(t2, t2, t5);
2084             tcg_gen_sar_tl(t3, t3, t5);
2085         } else {
2086             tcg_gen_shr_tl(t0, t0, t5);
2087             tcg_gen_shr_tl(t1, t1, t5);
2088             tcg_gen_shr_tl(t2, t2, t5);
2089             tcg_gen_shr_tl(t3, t3, t5);
2090         }
2091     } else {
2092         tcg_gen_shl_tl(t0, t0, t5);
2093         tcg_gen_shl_tl(t1, t1, t5);
2094         tcg_gen_shl_tl(t2, t2, t5);
2095         tcg_gen_shl_tl(t3, t3, t5);
2096     }
2097     tcg_gen_deposit_tl(t0, t0, t1, 16, 16);
2098     tcg_gen_deposit_tl(t2, t2, t3, 16, 16);
2099 
2100     gen_store_mxu_gpr(t0, XRa);
2101     gen_store_mxu_gpr(t2, XRd);
2102 }
2103 
2104 /*
2105  *                   MXU instruction category max/min/avg
2106  *                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2107  *
2108  *                     S32MAX     D16MAX     Q8MAX
2109  *                     S32MIN     D16MIN     Q8MIN
2110  *                     S32SLT     D16SLT     Q8SLT
2111  *                                           Q8SLTU
2112  *                                D16AVG     Q8AVG
2113  *                                D16AVGR    Q8AVGR
2114  *                     S32MOVZ    D16MOVZ    Q8MOVZ
2115  *                     S32MOVN    D16MOVN    Q8MOVN
2116  */
2117 
2118 /*
2119  *  S32MAX XRa, XRb, XRc
2120  *    Update XRa with the maximum of signed 32-bit integers contained
2121  *    in XRb and XRc.
2122  *
2123  *  S32MIN XRa, XRb, XRc
2124  *    Update XRa with the minimum of signed 32-bit integers contained
2125  *    in XRb and XRc.
2126  */
2127 static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx)
2128 {
2129     uint32_t pad, opc, XRc, XRb, XRa;
2130 
2131     pad = extract32(ctx->opcode, 21, 5);
2132     opc = extract32(ctx->opcode, 18, 3);
2133     XRc = extract32(ctx->opcode, 14, 4);
2134     XRb = extract32(ctx->opcode, 10, 4);
2135     XRa = extract32(ctx->opcode,  6, 4);
2136 
2137     if (unlikely(pad != 0)) {
2138         /* opcode padding incorrect -> do nothing */
2139     } else if (unlikely(XRa == 0)) {
2140         /* destination is zero register -> do nothing */
2141     } else if (unlikely((XRb == 0) && (XRc == 0))) {
2142         /* both operands zero registers -> just set destination to zero */
2143         tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
2144     } else if (unlikely((XRb == 0) || (XRc == 0))) {
2145         /* exactly one operand is zero register - find which one is not...*/
2146         uint32_t XRx = XRb ? XRb : XRc;
2147         /* ...and do max/min operation with one operand 0 */
2148         if (opc == OPC_MXU_S32MAX) {
2149             tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
2150         } else {
2151             tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
2152         }
2153     } else if (unlikely(XRb == XRc)) {
2154         /* both operands same -> just set destination to one of them */
2155         tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
2156     } else {
2157         /* the most general case */
2158         if (opc == OPC_MXU_S32MAX) {
2159             tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
2160                                                mxu_gpr[XRc - 1]);
2161         } else {
2162             tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
2163                                                mxu_gpr[XRc - 1]);
2164         }
2165     }
2166 }
2167 
2168 /*
2169  *  D16MAX
2170  *    Update XRa with the 16-bit-wise maximums of signed integers
2171  *    contained in XRb and XRc.
2172  *
2173  *  D16MIN
2174  *    Update XRa with the 16-bit-wise minimums of signed integers
2175  *    contained in XRb and XRc.
2176  */
2177 static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx)
2178 {
2179     uint32_t pad, opc, XRc, XRb, XRa;
2180 
2181     pad = extract32(ctx->opcode, 21, 5);
2182     opc = extract32(ctx->opcode, 18, 3);
2183     XRc = extract32(ctx->opcode, 14, 4);
2184     XRb = extract32(ctx->opcode, 10, 4);
2185     XRa = extract32(ctx->opcode,  6, 4);
2186 
2187     if (unlikely(pad != 0)) {
2188         /* opcode padding incorrect -> do nothing */
2189     } else if (unlikely(XRa == 0)) {
2190         /* destination is zero register -> do nothing */
2191     } else if (unlikely((XRb == 0) && (XRc == 0))) {
2192         /* both operands zero registers -> just set destination to zero */
2193         tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
2194     } else if (unlikely((XRb == 0) || (XRc == 0))) {
2195         /* exactly one operand is zero register - find which one is not...*/
2196         uint32_t XRx = XRb ? XRb : XRc;
2197         /* ...and do half-word-wise max/min with one operand 0 */
2198         TCGv_i32 t0 = tcg_temp_new();
2199         TCGv_i32 t1 = tcg_constant_i32(0);
2200         TCGv_i32 t2 = tcg_temp_new();
2201 
2202         /* the left half-word first */
2203         tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000);
2204         if (opc == OPC_MXU_D16MAX) {
2205             tcg_gen_smax_i32(t2, t0, t1);
2206         } else {
2207             tcg_gen_smin_i32(t2, t0, t1);
2208         }
2209 
2210         /* the right half-word */
2211         tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF);
2212         /* move half-words to the leftmost position */
2213         tcg_gen_shli_i32(t0, t0, 16);
2214         /* t0 will be max/min of t0 and t1 */
2215         if (opc == OPC_MXU_D16MAX) {
2216             tcg_gen_smax_i32(t0, t0, t1);
2217         } else {
2218             tcg_gen_smin_i32(t0, t0, t1);
2219         }
2220         /* return resulting half-words to its original position */
2221         tcg_gen_shri_i32(t0, t0, 16);
2222         /* finally update the destination */
2223         tcg_gen_or_i32(mxu_gpr[XRa - 1], t2, t0);
2224     } else if (unlikely(XRb == XRc)) {
2225         /* both operands same -> just set destination to one of them */
2226         tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
2227     } else {
2228         /* the most general case */
2229         TCGv_i32 t0 = tcg_temp_new();
2230         TCGv_i32 t1 = tcg_temp_new();
2231         TCGv_i32 t2 = tcg_temp_new();
2232 
2233         /* the left half-word first */
2234         tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000);
2235         tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
2236         if (opc == OPC_MXU_D16MAX) {
2237             tcg_gen_smax_i32(t2, t0, t1);
2238         } else {
2239             tcg_gen_smin_i32(t2, t0, t1);
2240         }
2241 
2242         /* the right half-word */
2243         tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
2244         tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF);
2245         /* move half-words to the leftmost position */
2246         tcg_gen_shli_i32(t0, t0, 16);
2247         tcg_gen_shli_i32(t1, t1, 16);
2248         /* t0 will be max/min of t0 and t1 */
2249         if (opc == OPC_MXU_D16MAX) {
2250             tcg_gen_smax_i32(t0, t0, t1);
2251         } else {
2252             tcg_gen_smin_i32(t0, t0, t1);
2253         }
2254         /* return resulting half-words to its original position */
2255         tcg_gen_shri_i32(t0, t0, 16);
2256         /* finally update the destination */
2257         tcg_gen_or_i32(mxu_gpr[XRa - 1], t2, t0);
2258     }
2259 }
2260 
2261 /*
2262  *  Q8MAX
2263  *    Update XRa with the 8-bit-wise maximums of signed integers
2264  *    contained in XRb and XRc.
2265  *
2266  *  Q8MIN
2267  *    Update XRa with the 8-bit-wise minimums of signed integers
2268  *    contained in XRb and XRc.
2269  */
2270 static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx)
2271 {
2272     uint32_t pad, opc, XRc, XRb, XRa;
2273 
2274     pad = extract32(ctx->opcode, 21, 5);
2275     opc = extract32(ctx->opcode, 18, 3);
2276     XRc = extract32(ctx->opcode, 14, 4);
2277     XRb = extract32(ctx->opcode, 10, 4);
2278     XRa = extract32(ctx->opcode,  6, 4);
2279 
2280     if (unlikely(pad != 0)) {
2281         /* opcode padding incorrect -> do nothing */
2282     } else if (unlikely(XRa == 0)) {
2283         /* destination is zero register -> do nothing */
2284     } else if (unlikely((XRb == 0) && (XRc == 0))) {
2285         /* both operands zero registers -> just set destination to zero */
2286         tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
2287     } else if (unlikely((XRb == 0) || (XRc == 0))) {
2288         /* exactly one operand is zero register - make it be the first...*/
2289         uint32_t XRx = XRb ? XRb : XRc;
2290         /* ...and do byte-wise max/min with one operand 0 */
2291         TCGv_i32 t0 = tcg_temp_new();
2292         TCGv_i32 t1 = tcg_constant_i32(0);
2293         TCGv_i32 t2 = tcg_temp_new();
2294         int32_t i;
2295 
2296         /* the leftmost byte (byte 3) first */
2297         tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000);
2298         if (opc == OPC_MXU_Q8MAX) {
2299             tcg_gen_smax_i32(t2, t0, t1);
2300         } else {
2301             tcg_gen_smin_i32(t2, t0, t1);
2302         }
2303 
2304         /* bytes 2, 1, 0 */
2305         for (i = 2; i >= 0; i--) {
2306             /* extract the byte */
2307             tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i));
2308             /* move the byte to the leftmost position */
2309             tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
2310             /* t0 will be max/min of t0 and t1 */
2311             if (opc == OPC_MXU_Q8MAX) {
2312                 tcg_gen_smax_i32(t0, t0, t1);
2313             } else {
2314                 tcg_gen_smin_i32(t0, t0, t1);
2315             }
2316             /* return resulting byte to its original position */
2317             tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
2318             /* finally update the destination */
2319             tcg_gen_or_i32(t2, t2, t0);
2320         }
2321         gen_store_mxu_gpr(t2, XRa);
2322     } else if (unlikely(XRb == XRc)) {
2323         /* both operands same -> just set destination to one of them */
2324         tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
2325     } else {
2326         /* the most general case */
2327         TCGv_i32 t0 = tcg_temp_new();
2328         TCGv_i32 t1 = tcg_temp_new();
2329         TCGv_i32 t2 = tcg_temp_new();
2330         int32_t i;
2331 
2332         /* the leftmost bytes (bytes 3) first */
2333         tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000);
2334         tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
2335         if (opc == OPC_MXU_Q8MAX) {
2336             tcg_gen_smax_i32(t2, t0, t1);
2337         } else {
2338             tcg_gen_smin_i32(t2, t0, t1);
2339         }
2340 
2341         /* bytes 2, 1, 0 */
2342         for (i = 2; i >= 0; i--) {
2343             /* extract corresponding bytes */
2344             tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i));
2345             tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i));
2346             /* move the bytes to the leftmost position */
2347             tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
2348             tcg_gen_shli_i32(t1, t1, 8 * (3 - i));
2349             /* t0 will be max/min of t0 and t1 */
2350             if (opc == OPC_MXU_Q8MAX) {
2351                 tcg_gen_smax_i32(t0, t0, t1);
2352             } else {
2353                 tcg_gen_smin_i32(t0, t0, t1);
2354             }
2355             /* return resulting byte to its original position */
2356             tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
2357             /* finally update the destination */
2358             tcg_gen_or_i32(t2, t2, t0);
2359         }
2360         gen_store_mxu_gpr(t2, XRa);
2361     }
2362 }
2363 
2364 /*
2365  *  Q8SLT
2366  *    Update XRa with the signed "set less than" comparison of XRb and XRc
2367  *    on per-byte basis.
2368  *    a.k.a. XRa[0..3] = XRb[0..3] < XRc[0..3] ? 1 : 0;
2369  *
2370  *  Q8SLTU
2371  *    Update XRa with the unsigned "set less than" comparison of XRb and XRc
2372  *    on per-byte basis.
2373  *    a.k.a. XRa[0..3] = XRb[0..3] < XRc[0..3] ? 1 : 0;
2374  */
2375 static void gen_mxu_q8slt(DisasContext *ctx, bool sltu)
2376 {
2377     uint32_t pad, XRc, XRb, XRa;
2378 
2379     pad = extract32(ctx->opcode, 21, 5);
2380     XRc = extract32(ctx->opcode, 14, 4);
2381     XRb = extract32(ctx->opcode, 10, 4);
2382     XRa = extract32(ctx->opcode,  6, 4);
2383 
2384     if (unlikely(pad != 0)) {
2385         /* opcode padding incorrect -> do nothing */
2386     } else if (unlikely(XRa == 0)) {
2387         /* destination is zero register -> do nothing */
2388     } else if (unlikely((XRb == 0) && (XRc == 0))) {
2389         /* both operands zero registers -> just set destination to zero */
2390         tcg_gen_movi_tl(mxu_gpr[XRa - 1], 0);
2391     } else if (unlikely(XRb == XRc)) {
2392         /* both operands same registers -> just set destination to zero */
2393         tcg_gen_movi_tl(mxu_gpr[XRa - 1], 0);
2394     } else {
2395         /* the most general case */
2396         TCGv t0 = tcg_temp_new();
2397         TCGv t1 = tcg_temp_new();
2398         TCGv t2 = tcg_temp_new();
2399         TCGv t3 = tcg_temp_new();
2400         TCGv t4 = tcg_temp_new();
2401 
2402         gen_load_mxu_gpr(t3, XRb);
2403         gen_load_mxu_gpr(t4, XRc);
2404         tcg_gen_movi_tl(t2, 0);
2405 
2406         for (int i = 0; i < 4; i++) {
2407             if (sltu) {
2408                 tcg_gen_extract_tl(t0, t3, 8 * i, 8);
2409                 tcg_gen_extract_tl(t1, t4, 8 * i, 8);
2410             } else {
2411                 tcg_gen_sextract_tl(t0, t3, 8 * i, 8);
2412                 tcg_gen_sextract_tl(t1, t4, 8 * i, 8);
2413             }
2414             tcg_gen_setcond_tl(TCG_COND_LT, t0, t0, t1);
2415             tcg_gen_deposit_tl(t2, t2, t0, 8 * i, 8);
2416         }
2417         gen_store_mxu_gpr(t2, XRa);
2418     }
2419 }
2420 
2421 /*
2422  *  S32SLT
2423  *    Update XRa with the signed "set less than" comparison of XRb and XRc.
2424  *    a.k.a. XRa = XRb < XRc ? 1 : 0;
2425  */
2426 static void gen_mxu_S32SLT(DisasContext *ctx)
2427 {
2428     uint32_t pad, XRc, XRb, XRa;
2429 
2430     pad = extract32(ctx->opcode, 21, 5);
2431     XRc = extract32(ctx->opcode, 14, 4);
2432     XRb = extract32(ctx->opcode, 10, 4);
2433     XRa = extract32(ctx->opcode,  6, 4);
2434 
2435     if (unlikely(pad != 0)) {
2436         /* opcode padding incorrect -> do nothing */
2437     } else if (unlikely(XRa == 0)) {
2438         /* destination is zero register -> do nothing */
2439     } else if (unlikely((XRb == 0) && (XRc == 0))) {
2440         /* both operands zero registers -> just set destination to zero */
2441         tcg_gen_movi_tl(mxu_gpr[XRa - 1], 0);
2442     } else if (unlikely(XRb == XRc)) {
2443         /* both operands same registers -> just set destination to zero */
2444         tcg_gen_movi_tl(mxu_gpr[XRa - 1], 0);
2445     } else {
2446         /* the most general case */
2447         TCGv t0 = tcg_temp_new();
2448         TCGv t1 = tcg_temp_new();
2449 
2450         gen_load_mxu_gpr(t0, XRb);
2451         gen_load_mxu_gpr(t1, XRc);
2452         tcg_gen_setcond_tl(TCG_COND_LT, mxu_gpr[XRa - 1], t0, t1);
2453     }
2454 }
2455 
2456 /*
2457  *  D16SLT
2458  *    Update XRa with the signed "set less than" comparison of XRb and XRc
2459  *    on per-word basis.
2460  *    a.k.a. XRa[0..1] = XRb[0..1] < XRc[0..1] ? 1 : 0;
2461  */
2462 static void gen_mxu_D16SLT(DisasContext *ctx)
2463 {
2464     uint32_t pad, XRc, XRb, XRa;
2465 
2466     pad = extract32(ctx->opcode, 21, 5);
2467     XRc = extract32(ctx->opcode, 14, 4);
2468     XRb = extract32(ctx->opcode, 10, 4);
2469     XRa = extract32(ctx->opcode,  6, 4);
2470 
2471     if (unlikely(pad != 0)) {
2472         /* opcode padding incorrect -> do nothing */
2473     } else if (unlikely(XRa == 0)) {
2474         /* destination is zero register -> do nothing */
2475     } else if (unlikely((XRb == 0) && (XRc == 0))) {
2476         /* both operands zero registers -> just set destination to zero */
2477         tcg_gen_movi_tl(mxu_gpr[XRa - 1], 0);
2478     } else if (unlikely(XRb == XRc)) {
2479         /* both operands same registers -> just set destination to zero */
2480         tcg_gen_movi_tl(mxu_gpr[XRa - 1], 0);
2481     } else {
2482         /* the most general case */
2483         TCGv t0 = tcg_temp_new();
2484         TCGv t1 = tcg_temp_new();
2485         TCGv t2 = tcg_temp_new();
2486         TCGv t3 = tcg_temp_new();
2487         TCGv t4 = tcg_temp_new();
2488 
2489         gen_load_mxu_gpr(t3, XRb);
2490         gen_load_mxu_gpr(t4, XRc);
2491         tcg_gen_sextract_tl(t0, t3, 16, 16);
2492         tcg_gen_sextract_tl(t1, t4, 16, 16);
2493         tcg_gen_setcond_tl(TCG_COND_LT, t0, t0, t1);
2494         tcg_gen_shli_tl(t2, t0, 16);
2495         tcg_gen_sextract_tl(t0, t3,  0, 16);
2496         tcg_gen_sextract_tl(t1, t4,  0, 16);
2497         tcg_gen_setcond_tl(TCG_COND_LT, t0, t0, t1);
2498         tcg_gen_or_tl(mxu_gpr[XRa - 1], t2, t0);
2499     }
2500 }
2501 
2502 /*
2503  *  D16AVG
2504  *    Update XRa with the signed average of XRb and XRc
2505  *    on per-word basis, rounding down.
2506  *    a.k.a. XRa[0..1] = (XRb[0..1] + XRc[0..1]) >> 1;
2507  *
2508  *  D16AVGR
2509  *    Update XRa with the signed average of XRb and XRc
2510  *    on per-word basis, math rounding 4/5.
2511  *    a.k.a. XRa[0..1] = (XRb[0..1] + XRc[0..1] + 1) >> 1;
2512  */
2513 static void gen_mxu_d16avg(DisasContext *ctx, bool round45)
2514 {
2515     uint32_t pad, XRc, XRb, XRa;
2516 
2517     pad = extract32(ctx->opcode, 21, 5);
2518     XRc = extract32(ctx->opcode, 14, 4);
2519     XRb = extract32(ctx->opcode, 10, 4);
2520     XRa = extract32(ctx->opcode,  6, 4);
2521 
2522     if (unlikely(pad != 0)) {
2523         /* opcode padding incorrect -> do nothing */
2524     } else if (unlikely(XRa == 0)) {
2525         /* destination is zero register -> do nothing */
2526     } else if (unlikely((XRb == 0) && (XRc == 0))) {
2527         /* both operands zero registers -> just set destination to zero */
2528         tcg_gen_movi_tl(mxu_gpr[XRa - 1], 0);
2529     } else if (unlikely(XRb == XRc)) {
2530         /* both operands same registers -> just set destination to same */
2531         tcg_gen_mov_tl(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
2532     } else {
2533         /* the most general case */
2534         TCGv t0 = tcg_temp_new();
2535         TCGv t1 = tcg_temp_new();
2536         TCGv t2 = tcg_temp_new();
2537         TCGv t3 = tcg_temp_new();
2538         TCGv t4 = tcg_temp_new();
2539 
2540         gen_load_mxu_gpr(t3, XRb);
2541         gen_load_mxu_gpr(t4, XRc);
2542         tcg_gen_sextract_tl(t0, t3, 16, 16);
2543         tcg_gen_sextract_tl(t1, t4, 16, 16);
2544         tcg_gen_add_tl(t0, t0, t1);
2545         if (round45) {
2546             tcg_gen_addi_tl(t0, t0, 1);
2547         }
2548         tcg_gen_shli_tl(t2, t0, 15);
2549         tcg_gen_andi_tl(t2, t2, 0xffff0000);
2550         tcg_gen_sextract_tl(t0, t3,  0, 16);
2551         tcg_gen_sextract_tl(t1, t4,  0, 16);
2552         tcg_gen_add_tl(t0, t0, t1);
2553         if (round45) {
2554             tcg_gen_addi_tl(t0, t0, 1);
2555         }
2556         tcg_gen_shri_tl(t0, t0, 1);
2557         tcg_gen_deposit_tl(t2, t2, t0, 0, 16);
2558         gen_store_mxu_gpr(t2, XRa);
2559     }
2560 }
2561 
2562 /*
2563  *  Q8AVG
2564  *    Update XRa with the signed average of XRb and XRc
2565  *    on per-byte basis, rounding down.
2566  *    a.k.a. XRa[0..3] = (XRb[0..3] + XRc[0..3]) >> 1;
2567  *
2568  *  Q8AVGR
2569  *    Update XRa with the signed average of XRb and XRc
2570  *    on per-word basis, math rounding 4/5.
2571  *    a.k.a. XRa[0..3] = (XRb[0..3] + XRc[0..3] + 1) >> 1;
2572  */
2573 static void gen_mxu_q8avg(DisasContext *ctx, bool round45)
2574 {
2575     uint32_t pad, XRc, XRb, XRa;
2576 
2577     pad = extract32(ctx->opcode, 21, 5);
2578     XRc = extract32(ctx->opcode, 14, 4);
2579     XRb = extract32(ctx->opcode, 10, 4);
2580     XRa = extract32(ctx->opcode,  6, 4);
2581 
2582     if (unlikely(pad != 0)) {
2583         /* opcode padding incorrect -> do nothing */
2584     } else if (unlikely(XRa == 0)) {
2585         /* destination is zero register -> do nothing */
2586     } else if (unlikely((XRb == 0) && (XRc == 0))) {
2587         /* both operands zero registers -> just set destination to zero */
2588         tcg_gen_movi_tl(mxu_gpr[XRa - 1], 0);
2589     } else if (unlikely(XRb == XRc)) {
2590         /* both operands same registers -> just set destination to same */
2591         tcg_gen_mov_tl(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
2592     } else {
2593         /* the most general case */
2594         TCGv t0 = tcg_temp_new();
2595         TCGv t1 = tcg_temp_new();
2596         TCGv t2 = tcg_temp_new();
2597         TCGv t3 = tcg_temp_new();
2598         TCGv t4 = tcg_temp_new();
2599 
2600         gen_load_mxu_gpr(t3, XRb);
2601         gen_load_mxu_gpr(t4, XRc);
2602         tcg_gen_movi_tl(t2, 0);
2603 
2604         for (int i = 0; i < 4; i++) {
2605             tcg_gen_extract_tl(t0, t3, 8 * i, 8);
2606             tcg_gen_extract_tl(t1, t4, 8 * i, 8);
2607             tcg_gen_add_tl(t0, t0, t1);
2608             if (round45) {
2609                 tcg_gen_addi_tl(t0, t0, 1);
2610             }
2611             tcg_gen_shri_tl(t0, t0, 1);
2612             tcg_gen_deposit_tl(t2, t2, t0, 8 * i, 8);
2613         }
2614         gen_store_mxu_gpr(t2, XRa);
2615     }
2616 }
2617 
2618 /*
2619  *  Q8MOVZ
2620  *    Quadruple 8-bit packed conditional move where
2621  *    XRb contains conditions, XRc what to move and
2622  *    XRa is the destination.
2623  *    a.k.a. if (XRb[0..3] == 0) { XRa[0..3] = XRc[0..3] }
2624  *
2625  *  Q8MOVN
2626  *    Quadruple 8-bit packed conditional move where
2627  *    XRb contains conditions, XRc what to move and
2628  *    XRa is the destination.
2629  *    a.k.a. if (XRb[0..3] != 0) { XRa[0..3] = XRc[0..3] }
2630  */
2631 static void gen_mxu_q8movzn(DisasContext *ctx, TCGCond cond)
2632 {
2633     uint32_t XRc, XRb, XRa;
2634 
2635     XRa = extract32(ctx->opcode,  6, 4);
2636     XRb = extract32(ctx->opcode, 10, 4);
2637     XRc = extract32(ctx->opcode, 14, 4);
2638 
2639     TCGv t0 = tcg_temp_new();
2640     TCGv t1 = tcg_temp_new();
2641     TCGv t2 = tcg_temp_new();
2642     TCGv t3 = tcg_temp_new();
2643     TCGLabel *l_quarterdone = gen_new_label();
2644     TCGLabel *l_halfdone = gen_new_label();
2645     TCGLabel *l_quarterrest = gen_new_label();
2646     TCGLabel *l_done = gen_new_label();
2647 
2648     gen_load_mxu_gpr(t0, XRc);
2649     gen_load_mxu_gpr(t1, XRb);
2650     gen_load_mxu_gpr(t2, XRa);
2651 
2652     tcg_gen_extract_tl(t3, t1, 24, 8);
2653     tcg_gen_brcondi_tl(cond, t3, 0, l_quarterdone);
2654     tcg_gen_extract_tl(t3, t0, 24, 8);
2655     tcg_gen_deposit_tl(t2, t2, t3, 24, 8);
2656 
2657     gen_set_label(l_quarterdone);
2658     tcg_gen_extract_tl(t3, t1, 16, 8);
2659     tcg_gen_brcondi_tl(cond, t3, 0, l_halfdone);
2660     tcg_gen_extract_tl(t3, t0, 16, 8);
2661     tcg_gen_deposit_tl(t2, t2, t3, 16, 8);
2662 
2663     gen_set_label(l_halfdone);
2664     tcg_gen_extract_tl(t3, t1, 8, 8);
2665     tcg_gen_brcondi_tl(cond, t3, 0, l_quarterrest);
2666     tcg_gen_extract_tl(t3, t0, 8, 8);
2667     tcg_gen_deposit_tl(t2, t2, t3, 8, 8);
2668 
2669     gen_set_label(l_quarterrest);
2670     tcg_gen_extract_tl(t3, t1, 0, 8);
2671     tcg_gen_brcondi_tl(cond, t3, 0, l_done);
2672     tcg_gen_extract_tl(t3, t0, 0, 8);
2673     tcg_gen_deposit_tl(t2, t2, t3, 0, 8);
2674 
2675     gen_set_label(l_done);
2676     gen_store_mxu_gpr(t2, XRa);
2677 }
2678 
2679 /*
2680  *  D16MOVZ
2681  *    Double 16-bit packed conditional move where
2682  *    XRb contains conditions, XRc what to move and
2683  *    XRa is the destination.
2684  *    a.k.a. if (XRb[0..1] == 0) { XRa[0..1] = XRc[0..1] }
2685  *
2686  *  D16MOVN
2687  *    Double 16-bit packed conditional move where
2688  *    XRb contains conditions, XRc what to move and
2689  *    XRa is the destination.
2690  *    a.k.a. if (XRb[0..3] != 0) { XRa[0..1] = XRc[0..1] }
2691  */
2692 static void gen_mxu_d16movzn(DisasContext *ctx, TCGCond cond)
2693 {
2694     uint32_t XRc, XRb, XRa;
2695 
2696     XRa = extract32(ctx->opcode,  6, 4);
2697     XRb = extract32(ctx->opcode, 10, 4);
2698     XRc = extract32(ctx->opcode, 14, 4);
2699 
2700     TCGv t0 = tcg_temp_new();
2701     TCGv t1 = tcg_temp_new();
2702     TCGv t2 = tcg_temp_new();
2703     TCGv t3 = tcg_temp_new();
2704     TCGLabel *l_halfdone = gen_new_label();
2705     TCGLabel *l_done = gen_new_label();
2706 
2707     gen_load_mxu_gpr(t0, XRc);
2708     gen_load_mxu_gpr(t1, XRb);
2709     gen_load_mxu_gpr(t2, XRa);
2710 
2711     tcg_gen_extract_tl(t3, t1, 16, 16);
2712     tcg_gen_brcondi_tl(cond, t3, 0, l_halfdone);
2713     tcg_gen_extract_tl(t3, t0, 16, 16);
2714     tcg_gen_deposit_tl(t2, t2, t3, 16, 16);
2715 
2716     gen_set_label(l_halfdone);
2717     tcg_gen_extract_tl(t3, t1, 0, 16);
2718     tcg_gen_brcondi_tl(cond, t3, 0, l_done);
2719     tcg_gen_extract_tl(t3, t0, 0, 16);
2720     tcg_gen_deposit_tl(t2, t2, t3, 0, 16);
2721 
2722     gen_set_label(l_done);
2723     gen_store_mxu_gpr(t2, XRa);
2724 }
2725 
2726 /*
2727  *  S32MOVZ
2728  *    Quadruple 32-bit conditional move where
2729  *    XRb contains conditions, XRc what to move and
2730  *    XRa is the destination.
2731  *    a.k.a. if (XRb == 0) { XRa = XRc }
2732  *
2733  *  S32MOVN
2734  *    Single 32-bit conditional move where
2735  *    XRb contains conditions, XRc what to move and
2736  *    XRa is the destination.
2737  *    a.k.a. if (XRb != 0) { XRa = XRc }
2738  */
2739 static void gen_mxu_s32movzn(DisasContext *ctx, TCGCond cond)
2740 {
2741     uint32_t XRc, XRb, XRa;
2742 
2743     XRa = extract32(ctx->opcode,  6, 4);
2744     XRb = extract32(ctx->opcode, 10, 4);
2745     XRc = extract32(ctx->opcode, 14, 4);
2746 
2747     TCGv t0 = tcg_temp_new();
2748     TCGv t1 = tcg_temp_new();
2749     TCGLabel *l_done = gen_new_label();
2750 
2751     gen_load_mxu_gpr(t0, XRc);
2752     gen_load_mxu_gpr(t1, XRb);
2753 
2754     tcg_gen_brcondi_tl(cond, t1, 0, l_done);
2755     gen_store_mxu_gpr(t0, XRa);
2756     gen_set_label(l_done);
2757 }
2758 
2759 /*
2760  *      MXU instruction category: Addition and subtraction
2761  *      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2762  *
2763  *              S32CPS      D16CPS
2764  *                                       Q8ADD
2765  */
2766 
2767 /*
2768  *  S32CPS
2769  *    Update XRa if XRc < 0 by value of 0 - XRb
2770  *    else XRa = XRb
2771  */
2772 static void gen_mxu_S32CPS(DisasContext *ctx)
2773 {
2774     uint32_t pad, XRc, XRb, XRa;
2775 
2776     pad = extract32(ctx->opcode, 21, 5);
2777     XRc = extract32(ctx->opcode, 14, 4);
2778     XRb = extract32(ctx->opcode, 10, 4);
2779     XRa = extract32(ctx->opcode,  6, 4);
2780 
2781     if (unlikely(pad != 0)) {
2782         /* opcode padding incorrect -> do nothing */
2783     } else if (unlikely(XRa == 0)) {
2784         /* destination is zero register -> do nothing */
2785     } else if (unlikely(XRb == 0)) {
2786         /* XRc make no sense 0 - 0 = 0 -> just set destination to zero */
2787         tcg_gen_movi_tl(mxu_gpr[XRa - 1], 0);
2788     } else if (unlikely(XRc == 0)) {
2789         /* condition always false -> just move XRb to XRa */
2790         tcg_gen_mov_tl(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
2791     } else {
2792         /* the most general case */
2793         TCGv t0 = tcg_temp_new();
2794         TCGLabel *l_not_less = gen_new_label();
2795         TCGLabel *l_done = gen_new_label();
2796 
2797         tcg_gen_brcondi_tl(TCG_COND_GE, mxu_gpr[XRc - 1], 0, l_not_less);
2798         tcg_gen_neg_tl(t0, mxu_gpr[XRb - 1]);
2799         tcg_gen_br(l_done);
2800         gen_set_label(l_not_less);
2801         gen_load_mxu_gpr(t0, XRb);
2802         gen_set_label(l_done);
2803         gen_store_mxu_gpr(t0, XRa);
2804     }
2805 }
2806 
2807 /*
2808  *  D16CPS
2809  *    Update XRa[0..1] if XRc[0..1] < 0 by value of 0 - XRb[0..1]
2810  *    else XRa[0..1] = XRb[0..1]
2811  */
2812 static void gen_mxu_D16CPS(DisasContext *ctx)
2813 {
2814     uint32_t pad, XRc, XRb, XRa;
2815 
2816     pad = extract32(ctx->opcode, 21, 5);
2817     XRc = extract32(ctx->opcode, 14, 4);
2818     XRb = extract32(ctx->opcode, 10, 4);
2819     XRa = extract32(ctx->opcode,  6, 4);
2820 
2821     if (unlikely(pad != 0)) {
2822         /* opcode padding incorrect -> do nothing */
2823     } else if (unlikely(XRa == 0)) {
2824         /* destination is zero register -> do nothing */
2825     } else if (unlikely(XRb == 0)) {
2826         /* XRc make no sense 0 - 0 = 0 -> just set destination to zero */
2827         tcg_gen_movi_tl(mxu_gpr[XRa - 1], 0);
2828     } else if (unlikely(XRc == 0)) {
2829         /* condition always false -> just move XRb to XRa */
2830         tcg_gen_mov_tl(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
2831     } else {
2832         /* the most general case */
2833         TCGv t0 = tcg_temp_new();
2834         TCGv t1 = tcg_temp_new();
2835         TCGLabel *l_done_hi = gen_new_label();
2836         TCGLabel *l_not_less_lo = gen_new_label();
2837         TCGLabel *l_done_lo = gen_new_label();
2838 
2839         tcg_gen_sextract_tl(t0, mxu_gpr[XRc - 1], 16, 16);
2840         tcg_gen_sextract_tl(t1, mxu_gpr[XRb - 1], 16, 16);
2841         tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l_done_hi);
2842         tcg_gen_subfi_tl(t1, 0, t1);
2843 
2844         gen_set_label(l_done_hi);
2845         tcg_gen_shli_i32(t1, t1, 16);
2846 
2847         tcg_gen_sextract_tl(t0, mxu_gpr[XRc - 1],  0, 16);
2848         tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l_not_less_lo);
2849         tcg_gen_sextract_tl(t0, mxu_gpr[XRb - 1],  0, 16);
2850         tcg_gen_subfi_tl(t0, 0, t0);
2851         tcg_gen_br(l_done_lo);
2852 
2853         gen_set_label(l_not_less_lo);
2854         tcg_gen_extract_tl(t0, mxu_gpr[XRb - 1],  0, 16);
2855 
2856         gen_set_label(l_done_lo);
2857         tcg_gen_deposit_tl(mxu_gpr[XRa - 1], t1, t0, 0, 16);
2858     }
2859 }
2860 
2861 /*
2862  *  Q8ABD XRa, XRb, XRc
2863  *  Gets absolute difference for quadruple of 8-bit
2864  *  packed in XRb to another one in XRc,
2865  *  put the result in XRa.
2866  *  a.k.a. XRa[0..3] = abs(XRb[0..3] - XRc[0..3]);
2867  */
2868 static void gen_mxu_Q8ABD(DisasContext *ctx)
2869 {
2870     uint32_t pad, XRc, XRb, XRa;
2871 
2872     pad = extract32(ctx->opcode, 21, 3);
2873     XRc = extract32(ctx->opcode, 14, 4);
2874     XRb = extract32(ctx->opcode, 10, 4);
2875     XRa = extract32(ctx->opcode,  6, 4);
2876 
2877     if (unlikely(pad != 0)) {
2878         /* opcode padding incorrect -> do nothing */
2879     } else if (unlikely(XRa == 0)) {
2880         /* destination is zero register -> do nothing */
2881     } else if (unlikely((XRb == 0) && (XRc == 0))) {
2882         /* both operands zero registers -> just set destination to zero */
2883         tcg_gen_movi_tl(mxu_gpr[XRa - 1], 0);
2884     } else {
2885         /* the most general case */
2886         TCGv t0 = tcg_temp_new();
2887         TCGv t1 = tcg_temp_new();
2888         TCGv t2 = tcg_temp_new();
2889         TCGv t3 = tcg_temp_new();
2890         TCGv t4 = tcg_temp_new();
2891 
2892         gen_load_mxu_gpr(t3, XRb);
2893         gen_load_mxu_gpr(t4, XRc);
2894         tcg_gen_movi_tl(t2, 0);
2895 
2896         for (int i = 0; i < 4; i++) {
2897             tcg_gen_extract_tl(t0, t3, 8 * i, 8);
2898             tcg_gen_extract_tl(t1, t4, 8 * i, 8);
2899 
2900             tcg_gen_sub_tl(t0, t0, t1);
2901             tcg_gen_abs_tl(t0, t0);
2902 
2903             tcg_gen_deposit_tl(t2, t2, t0, 8 * i, 8);
2904         }
2905         gen_store_mxu_gpr(t2, XRa);
2906     }
2907 }
2908 
2909 /*
2910  *  Q8ADD XRa, XRb, XRc, ptn2
2911  *  Add/subtract quadruple of 8-bit packed in XRb
2912  *  to another one in XRc, put the result in XRa.
2913  */
2914 static void gen_mxu_Q8ADD(DisasContext *ctx)
2915 {
2916     uint32_t aptn2, pad, XRc, XRb, XRa;
2917 
2918     aptn2 = extract32(ctx->opcode, 24, 2);
2919     pad   = extract32(ctx->opcode, 21, 3);
2920     XRc   = extract32(ctx->opcode, 14, 4);
2921     XRb   = extract32(ctx->opcode, 10, 4);
2922     XRa   = extract32(ctx->opcode,  6, 4);
2923 
2924     if (unlikely(pad != 0)) {
2925         /* opcode padding incorrect -> do nothing */
2926     } else if (unlikely(XRa == 0)) {
2927         /* destination is zero register -> do nothing */
2928     } else if (unlikely((XRb == 0) && (XRc == 0))) {
2929         /* both operands zero registers -> just set destination to zero */
2930         tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
2931     } else {
2932         /* the most general case */
2933         TCGv t0 = tcg_temp_new();
2934         TCGv t1 = tcg_temp_new();
2935         TCGv t2 = tcg_temp_new();
2936         TCGv t3 = tcg_temp_new();
2937         TCGv t4 = tcg_temp_new();
2938 
2939         gen_load_mxu_gpr(t3, XRb);
2940         gen_load_mxu_gpr(t4, XRc);
2941 
2942         for (int i = 0; i < 4; i++) {
2943             tcg_gen_andi_tl(t0, t3, 0xff);
2944             tcg_gen_andi_tl(t1, t4, 0xff);
2945 
2946             if (i < 2) {
2947                 if (aptn2 & 0x01) {
2948                     tcg_gen_sub_tl(t0, t0, t1);
2949                 } else {
2950                     tcg_gen_add_tl(t0, t0, t1);
2951                 }
2952             } else {
2953                 if (aptn2 & 0x02) {
2954                     tcg_gen_sub_tl(t0, t0, t1);
2955                 } else {
2956                     tcg_gen_add_tl(t0, t0, t1);
2957                 }
2958             }
2959             if (i < 3) {
2960                 tcg_gen_shri_tl(t3, t3, 8);
2961                 tcg_gen_shri_tl(t4, t4, 8);
2962             }
2963             if (i > 0) {
2964                 tcg_gen_deposit_tl(t2, t2, t0, 8 * i, 8);
2965             } else {
2966                 tcg_gen_andi_tl(t0, t0, 0xff);
2967                 tcg_gen_mov_tl(t2, t0);
2968             }
2969         }
2970         gen_store_mxu_gpr(t2, XRa);
2971     }
2972 }
2973 
2974 /*
2975  *  Q8ADDE XRa, XRb, XRc, XRd, aptn2
2976  *    Add/subtract quadruple of 8-bit packed in XRb
2977  *    to another one in XRc, with zero extending
2978  *    to 16-bit and put results as packed 16-bit data
2979  *    into XRa and XRd.
2980  *    aptn2 manages action add or subtract of pairs of data.
2981  *
2982  *  Q8ACCE XRa, XRb, XRc, XRd, aptn2
2983  *    Add/subtract quadruple of 8-bit packed in XRb
2984  *    to another one in XRc, with zero extending
2985  *    to 16-bit and accumulate results as packed 16-bit data
2986  *    into XRa and XRd.
2987  *    aptn2 manages action add or subtract of pairs of data.
2988  */
2989 static void gen_mxu_q8adde(DisasContext *ctx, bool accumulate)
2990 {
2991     uint32_t aptn2, XRd, XRc, XRb, XRa;
2992 
2993     aptn2 = extract32(ctx->opcode, 24, 2);
2994     XRd   = extract32(ctx->opcode, 18, 4);
2995     XRc   = extract32(ctx->opcode, 14, 4);
2996     XRb   = extract32(ctx->opcode, 10, 4);
2997     XRa   = extract32(ctx->opcode,  6, 4);
2998 
2999     if (unlikely((XRb == 0) && (XRc == 0))) {
3000         /* both operands zero registers -> just set destination to zero */
3001         if (XRa != 0) {
3002             tcg_gen_movi_tl(mxu_gpr[XRa - 1], 0);
3003         }
3004         if (XRd != 0) {
3005             tcg_gen_movi_tl(mxu_gpr[XRd - 1], 0);
3006         }
3007     } else {
3008         /* the most general case */
3009         TCGv t0 = tcg_temp_new();
3010         TCGv t1 = tcg_temp_new();
3011         TCGv t2 = tcg_temp_new();
3012         TCGv t3 = tcg_temp_new();
3013         TCGv t4 = tcg_temp_new();
3014         TCGv t5 = tcg_temp_new();
3015 
3016         if (XRa != 0) {
3017             gen_extract_mxu_gpr(t0, XRb, 16, 8);
3018             gen_extract_mxu_gpr(t1, XRc, 16, 8);
3019             gen_extract_mxu_gpr(t2, XRb, 24, 8);
3020             gen_extract_mxu_gpr(t3, XRc, 24, 8);
3021             if (aptn2 & 2) {
3022                 tcg_gen_sub_tl(t0, t0, t1);
3023                 tcg_gen_sub_tl(t2, t2, t3);
3024             } else {
3025                 tcg_gen_add_tl(t0, t0, t1);
3026                 tcg_gen_add_tl(t2, t2, t3);
3027             }
3028             if (accumulate) {
3029                 gen_load_mxu_gpr(t5, XRa);
3030                 tcg_gen_extract_tl(t1, t5,  0, 16);
3031                 tcg_gen_extract_tl(t3, t5, 16, 16);
3032                 tcg_gen_add_tl(t0, t0, t1);
3033                 tcg_gen_add_tl(t2, t2, t3);
3034             }
3035             tcg_gen_shli_tl(t2, t2, 16);
3036             tcg_gen_extract_tl(t0, t0, 0, 16);
3037             tcg_gen_or_tl(t4, t2, t0);
3038         }
3039         if (XRd != 0) {
3040             gen_extract_mxu_gpr(t0, XRb, 0, 8);
3041             gen_extract_mxu_gpr(t1, XRc, 0, 8);
3042             gen_extract_mxu_gpr(t2, XRb, 8, 8);
3043             gen_extract_mxu_gpr(t3, XRc, 8, 8);
3044             if (aptn2 & 1) {
3045                 tcg_gen_sub_tl(t0, t0, t1);
3046                 tcg_gen_sub_tl(t2, t2, t3);
3047             } else {
3048                 tcg_gen_add_tl(t0, t0, t1);
3049                 tcg_gen_add_tl(t2, t2, t3);
3050             }
3051             if (accumulate) {
3052                 gen_load_mxu_gpr(t5, XRd);
3053                 tcg_gen_extract_tl(t1, t5,  0, 16);
3054                 tcg_gen_extract_tl(t3, t5, 16, 16);
3055                 tcg_gen_add_tl(t0, t0, t1);
3056                 tcg_gen_add_tl(t2, t2, t3);
3057             }
3058             tcg_gen_shli_tl(t2, t2, 16);
3059             tcg_gen_extract_tl(t0, t0, 0, 16);
3060             tcg_gen_or_tl(t5, t2, t0);
3061         }
3062 
3063         gen_store_mxu_gpr(t4, XRa);
3064         gen_store_mxu_gpr(t5, XRd);
3065     }
3066 }
3067 
3068 /*
3069  *  D8SUM XRa, XRb, XRc
3070  *    Double parallel add of quadruple unsigned 8-bit together
3071  *    with zero extending to 16-bit data.
3072  *  D8SUMC XRa, XRb, XRc
3073  *    Double parallel add of quadruple unsigned 8-bit together
3074  *    with zero extending to 16-bit data and adding 2 to each
3075  *    parallel result.
3076  */
3077 static void gen_mxu_d8sum(DisasContext *ctx, bool sumc)
3078 {
3079     uint32_t pad, pad2, XRc, XRb, XRa;
3080 
3081     pad  = extract32(ctx->opcode, 24, 2);
3082     pad2 = extract32(ctx->opcode, 18, 4);
3083     XRc  = extract32(ctx->opcode, 14, 4);
3084     XRb  = extract32(ctx->opcode, 10, 4);
3085     XRa  = extract32(ctx->opcode,  6, 4);
3086 
3087     if (unlikely(pad != 0 || pad2 != 0)) {
3088         /* opcode padding incorrect -> do nothing */
3089     } else if (unlikely(XRa == 0)) {
3090         /* destination is zero register -> do nothing */
3091     } else if (unlikely((XRb == 0) && (XRc == 0))) {
3092         /* both operands zero registers -> just set destination to zero */
3093         tcg_gen_movi_tl(mxu_gpr[XRa - 1], 0);
3094     } else {
3095         /* the most general case */
3096         TCGv t0 = tcg_temp_new();
3097         TCGv t1 = tcg_temp_new();
3098         TCGv t2 = tcg_temp_new();
3099         TCGv t3 = tcg_temp_new();
3100         TCGv t4 = tcg_temp_new();
3101         TCGv t5 = tcg_temp_new();
3102 
3103         if (XRb != 0) {
3104             tcg_gen_extract_tl(t0, mxu_gpr[XRb - 1],  0, 8);
3105             tcg_gen_extract_tl(t1, mxu_gpr[XRb - 1],  8, 8);
3106             tcg_gen_extract_tl(t2, mxu_gpr[XRb - 1], 16, 8);
3107             tcg_gen_extract_tl(t3, mxu_gpr[XRb - 1], 24, 8);
3108             tcg_gen_add_tl(t4, t0, t1);
3109             tcg_gen_add_tl(t4, t4, t2);
3110             tcg_gen_add_tl(t4, t4, t3);
3111         } else {
3112             tcg_gen_mov_tl(t4, 0);
3113         }
3114         if (XRc != 0) {
3115             tcg_gen_extract_tl(t0, mxu_gpr[XRc - 1],  0, 8);
3116             tcg_gen_extract_tl(t1, mxu_gpr[XRc - 1],  8, 8);
3117             tcg_gen_extract_tl(t2, mxu_gpr[XRc - 1], 16, 8);
3118             tcg_gen_extract_tl(t3, mxu_gpr[XRc - 1], 24, 8);
3119             tcg_gen_add_tl(t5, t0, t1);
3120             tcg_gen_add_tl(t5, t5, t2);
3121             tcg_gen_add_tl(t5, t5, t3);
3122         } else {
3123             tcg_gen_mov_tl(t5, 0);
3124         }
3125 
3126         if (sumc) {
3127             tcg_gen_addi_tl(t4, t4, 2);
3128             tcg_gen_addi_tl(t5, t5, 2);
3129         }
3130         tcg_gen_shli_tl(t4, t4, 16);
3131 
3132         tcg_gen_or_tl(mxu_gpr[XRa - 1], t4, t5);
3133     }
3134 }
3135 
3136 /*
3137  * Q16ADD XRa, XRb, XRc, XRd, aptn2, optn2 - Quad packed
3138  * 16-bit pattern addition.
3139  */
3140 static void gen_mxu_q16add(DisasContext *ctx)
3141 {
3142     uint32_t aptn2, optn2, XRc, XRb, XRa, XRd;
3143 
3144     aptn2 = extract32(ctx->opcode, 24, 2);
3145     optn2 = extract32(ctx->opcode, 22, 2);
3146     XRd   = extract32(ctx->opcode, 18, 4);
3147     XRc   = extract32(ctx->opcode, 14, 4);
3148     XRb   = extract32(ctx->opcode, 10, 4);
3149     XRa   = extract32(ctx->opcode,  6, 4);
3150 
3151     TCGv t0 = tcg_temp_new();
3152     TCGv t1 = tcg_temp_new();
3153     TCGv t2 = tcg_temp_new();
3154     TCGv t3 = tcg_temp_new();
3155     TCGv t4 = tcg_temp_new();
3156     TCGv t5 = tcg_temp_new();
3157 
3158     gen_load_mxu_gpr(t1, XRb);
3159     tcg_gen_extract_tl(t0, t1,  0, 16);
3160     tcg_gen_extract_tl(t1, t1, 16, 16);
3161 
3162     gen_load_mxu_gpr(t3, XRc);
3163     tcg_gen_extract_tl(t2, t3,  0, 16);
3164     tcg_gen_extract_tl(t3, t3, 16, 16);
3165 
3166     switch (optn2) {
3167     case MXU_OPTN2_WW: /* XRB.H+XRC.H == lop, XRB.L+XRC.L == rop */
3168         tcg_gen_mov_tl(t4, t1);
3169         tcg_gen_mov_tl(t5, t0);
3170         break;
3171     case MXU_OPTN2_LW: /* XRB.L+XRC.H == lop, XRB.L+XRC.L == rop */
3172         tcg_gen_mov_tl(t4, t0);
3173         tcg_gen_mov_tl(t5, t0);
3174         break;
3175     case MXU_OPTN2_HW: /* XRB.H+XRC.H == lop, XRB.H+XRC.L == rop */
3176         tcg_gen_mov_tl(t4, t1);
3177         tcg_gen_mov_tl(t5, t1);
3178         break;
3179     case MXU_OPTN2_XW: /* XRB.L+XRC.H == lop, XRB.H+XRC.L == rop */
3180         tcg_gen_mov_tl(t4, t0);
3181         tcg_gen_mov_tl(t5, t1);
3182         break;
3183     }
3184 
3185     switch (aptn2) {
3186     case MXU_APTN2_AA: /* lop +, rop + */
3187         tcg_gen_add_tl(t0, t4, t3);
3188         tcg_gen_add_tl(t1, t5, t2);
3189         tcg_gen_add_tl(t4, t4, t3);
3190         tcg_gen_add_tl(t5, t5, t2);
3191         break;
3192     case MXU_APTN2_AS: /* lop +, rop + */
3193         tcg_gen_sub_tl(t0, t4, t3);
3194         tcg_gen_sub_tl(t1, t5, t2);
3195         tcg_gen_add_tl(t4, t4, t3);
3196         tcg_gen_add_tl(t5, t5, t2);
3197         break;
3198     case MXU_APTN2_SA: /* lop +, rop + */
3199         tcg_gen_add_tl(t0, t4, t3);
3200         tcg_gen_add_tl(t1, t5, t2);
3201         tcg_gen_sub_tl(t4, t4, t3);
3202         tcg_gen_sub_tl(t5, t5, t2);
3203         break;
3204     case MXU_APTN2_SS: /* lop +, rop + */
3205         tcg_gen_sub_tl(t0, t4, t3);
3206         tcg_gen_sub_tl(t1, t5, t2);
3207         tcg_gen_sub_tl(t4, t4, t3);
3208         tcg_gen_sub_tl(t5, t5, t2);
3209         break;
3210     }
3211 
3212     tcg_gen_shli_tl(t0, t0, 16);
3213     tcg_gen_extract_tl(t1, t1, 0, 16);
3214     tcg_gen_shli_tl(t4, t4, 16);
3215     tcg_gen_extract_tl(t5, t5, 0, 16);
3216 
3217     tcg_gen_or_tl(mxu_gpr[XRa - 1], t4, t5);
3218     tcg_gen_or_tl(mxu_gpr[XRd - 1], t0, t1);
3219 }
3220 
3221 /*
3222  * Q16ACC XRa, XRb, XRc, XRd, aptn2 - Quad packed
3223  * 16-bit addition/subtraction with accumulate.
3224  */
3225 static void gen_mxu_q16acc(DisasContext *ctx)
3226 {
3227     uint32_t aptn2, XRc, XRb, XRa, XRd;
3228 
3229     aptn2 = extract32(ctx->opcode, 24, 2);
3230     XRd   = extract32(ctx->opcode, 18, 4);
3231     XRc   = extract32(ctx->opcode, 14, 4);
3232     XRb   = extract32(ctx->opcode, 10, 4);
3233     XRa   = extract32(ctx->opcode,  6, 4);
3234 
3235     TCGv t0 = tcg_temp_new();
3236     TCGv t1 = tcg_temp_new();
3237     TCGv t2 = tcg_temp_new();
3238     TCGv t3 = tcg_temp_new();
3239     TCGv s3 = tcg_temp_new();
3240     TCGv s2 = tcg_temp_new();
3241     TCGv s1 = tcg_temp_new();
3242     TCGv s0 = tcg_temp_new();
3243 
3244     gen_load_mxu_gpr(t1, XRb);
3245     tcg_gen_extract_tl(t0, t1,  0, 16);
3246     tcg_gen_extract_tl(t1, t1, 16, 16);
3247 
3248     gen_load_mxu_gpr(t3, XRc);
3249     tcg_gen_extract_tl(t2, t3,  0, 16);
3250     tcg_gen_extract_tl(t3, t3, 16, 16);
3251 
3252     switch (aptn2) {
3253     case MXU_APTN2_AA: /* lop +, rop + */
3254         tcg_gen_add_tl(s3, t1, t3);
3255         tcg_gen_add_tl(s2, t0, t2);
3256         tcg_gen_add_tl(s1, t1, t3);
3257         tcg_gen_add_tl(s0, t0, t2);
3258         break;
3259     case MXU_APTN2_AS: /* lop +, rop - */
3260         tcg_gen_sub_tl(s3, t1, t3);
3261         tcg_gen_sub_tl(s2, t0, t2);
3262         tcg_gen_add_tl(s1, t1, t3);
3263         tcg_gen_add_tl(s0, t0, t2);
3264         break;
3265     case MXU_APTN2_SA: /* lop -, rop + */
3266         tcg_gen_add_tl(s3, t1, t3);
3267         tcg_gen_add_tl(s2, t0, t2);
3268         tcg_gen_sub_tl(s1, t1, t3);
3269         tcg_gen_sub_tl(s0, t0, t2);
3270         break;
3271     case MXU_APTN2_SS: /* lop -, rop - */
3272         tcg_gen_sub_tl(s3, t1, t3);
3273         tcg_gen_sub_tl(s2, t0, t2);
3274         tcg_gen_sub_tl(s1, t1, t3);
3275         tcg_gen_sub_tl(s0, t0, t2);
3276         break;
3277     }
3278 
3279     if (XRa != 0) {
3280         tcg_gen_add_tl(t0, mxu_gpr[XRa - 1], s0);
3281         tcg_gen_extract_tl(t0, t0, 0, 16);
3282         tcg_gen_extract_tl(t1, mxu_gpr[XRa - 1], 16, 16);
3283         tcg_gen_add_tl(t1, t1, s1);
3284         tcg_gen_shli_tl(t1, t1, 16);
3285         tcg_gen_or_tl(mxu_gpr[XRa - 1], t1, t0);
3286     }
3287 
3288     if (XRd != 0) {
3289         tcg_gen_add_tl(t0, mxu_gpr[XRd - 1], s2);
3290         tcg_gen_extract_tl(t0, t0, 0, 16);
3291         tcg_gen_extract_tl(t1, mxu_gpr[XRd - 1], 16, 16);
3292         tcg_gen_add_tl(t1, t1, s3);
3293         tcg_gen_shli_tl(t1, t1, 16);
3294         tcg_gen_or_tl(mxu_gpr[XRd - 1], t1, t0);
3295     }
3296 }
3297 
3298 /*
3299  * Q16ACCM XRa, XRb, XRc, XRd, aptn2 - Quad packed
3300  * 16-bit accumulate.
3301  */
3302 static void gen_mxu_q16accm(DisasContext *ctx)
3303 {
3304     uint32_t aptn2, XRc, XRb, XRa, XRd;
3305 
3306     aptn2 = extract32(ctx->opcode, 24, 2);
3307     XRd   = extract32(ctx->opcode, 18, 4);
3308     XRc   = extract32(ctx->opcode, 14, 4);
3309     XRb   = extract32(ctx->opcode, 10, 4);
3310     XRa   = extract32(ctx->opcode,  6, 4);
3311 
3312     TCGv t0 = tcg_temp_new();
3313     TCGv t1 = tcg_temp_new();
3314     TCGv t2 = tcg_temp_new();
3315     TCGv t3 = tcg_temp_new();
3316 
3317     gen_load_mxu_gpr(t2, XRb);
3318     gen_load_mxu_gpr(t3, XRc);
3319 
3320     if (XRa != 0) {
3321         TCGv a0 = tcg_temp_new();
3322         TCGv a1 = tcg_temp_new();
3323 
3324         tcg_gen_extract_tl(t0, t2,  0, 16);
3325         tcg_gen_extract_tl(t1, t2, 16, 16);
3326 
3327         gen_load_mxu_gpr(a1, XRa);
3328         tcg_gen_extract_tl(a0, a1,  0, 16);
3329         tcg_gen_extract_tl(a1, a1, 16, 16);
3330 
3331         if (aptn2 & 2) {
3332             tcg_gen_sub_tl(a0, a0, t0);
3333             tcg_gen_sub_tl(a1, a1, t1);
3334         } else {
3335             tcg_gen_add_tl(a0, a0, t0);
3336             tcg_gen_add_tl(a1, a1, t1);
3337         }
3338         tcg_gen_extract_tl(a0, a0, 0, 16);
3339         tcg_gen_shli_tl(a1, a1, 16);
3340         tcg_gen_or_tl(mxu_gpr[XRa - 1], a1, a0);
3341     }
3342 
3343     if (XRd != 0) {
3344         TCGv a0 = tcg_temp_new();
3345         TCGv a1 = tcg_temp_new();
3346 
3347         tcg_gen_extract_tl(t0, t3,  0, 16);
3348         tcg_gen_extract_tl(t1, t3, 16, 16);
3349 
3350         gen_load_mxu_gpr(a1, XRd);
3351         tcg_gen_extract_tl(a0, a1,  0, 16);
3352         tcg_gen_extract_tl(a1, a1, 16, 16);
3353 
3354         if (aptn2 & 1) {
3355             tcg_gen_sub_tl(a0, a0, t0);
3356             tcg_gen_sub_tl(a1, a1, t1);
3357         } else {
3358             tcg_gen_add_tl(a0, a0, t0);
3359             tcg_gen_add_tl(a1, a1, t1);
3360         }
3361         tcg_gen_extract_tl(a0, a0, 0, 16);
3362         tcg_gen_shli_tl(a1, a1, 16);
3363         tcg_gen_or_tl(mxu_gpr[XRd - 1], a1, a0);
3364     }
3365 }
3366 
3367 
3368 /*
3369  * D16ASUM XRa, XRb, XRc, XRd, aptn2 - Double packed
3370  * 16-bit sign extended addition and accumulate.
3371  */
3372 static void gen_mxu_d16asum(DisasContext *ctx)
3373 {
3374     uint32_t aptn2, XRc, XRb, XRa, XRd;
3375 
3376     aptn2 = extract32(ctx->opcode, 24, 2);
3377     XRd   = extract32(ctx->opcode, 18, 4);
3378     XRc   = extract32(ctx->opcode, 14, 4);
3379     XRb   = extract32(ctx->opcode, 10, 4);
3380     XRa   = extract32(ctx->opcode,  6, 4);
3381 
3382     TCGv t0 = tcg_temp_new();
3383     TCGv t1 = tcg_temp_new();
3384     TCGv t2 = tcg_temp_new();
3385     TCGv t3 = tcg_temp_new();
3386 
3387     gen_load_mxu_gpr(t2, XRb);
3388     gen_load_mxu_gpr(t3, XRc);
3389 
3390     if (XRa != 0) {
3391         tcg_gen_sextract_tl(t0, t2,  0, 16);
3392         tcg_gen_sextract_tl(t1, t2, 16, 16);
3393         tcg_gen_add_tl(t0, t0, t1);
3394         if (aptn2 & 2) {
3395             tcg_gen_sub_tl(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
3396         } else {
3397             tcg_gen_add_tl(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
3398         }
3399     }
3400 
3401     if (XRd != 0) {
3402         tcg_gen_sextract_tl(t0, t3,  0, 16);
3403         tcg_gen_sextract_tl(t1, t3, 16, 16);
3404         tcg_gen_add_tl(t0, t0, t1);
3405         if (aptn2 & 1) {
3406             tcg_gen_sub_tl(mxu_gpr[XRd - 1], mxu_gpr[XRd - 1], t0);
3407         } else {
3408             tcg_gen_add_tl(mxu_gpr[XRd - 1], mxu_gpr[XRd - 1], t0);
3409         }
3410     }
3411 }
3412 
3413 /*
3414  * D32ADD XRa, XRb, XRc, XRd, aptn2 - Double
3415  * 32 bit pattern addition/subtraction, set carry.
3416  *
3417  * D32ADDC XRa, XRb, XRc, XRd, aptn2 - Double
3418  * 32 bit pattern addition/subtraction with carry.
3419  */
3420 static void gen_mxu_d32add(DisasContext *ctx)
3421 {
3422     uint32_t aptn2, addc, XRc, XRb, XRa, XRd;
3423 
3424     aptn2 = extract32(ctx->opcode, 24, 2);
3425     addc  = extract32(ctx->opcode, 22, 2);
3426     XRd   = extract32(ctx->opcode, 18, 4);
3427     XRc   = extract32(ctx->opcode, 14, 4);
3428     XRb   = extract32(ctx->opcode, 10, 4);
3429     XRa   = extract32(ctx->opcode,  6, 4);
3430 
3431     TCGv t0 = tcg_temp_new();
3432     TCGv t1 = tcg_temp_new();
3433     TCGv t2 = tcg_temp_new();
3434     TCGv cr = tcg_temp_new();
3435 
3436     if (unlikely(addc > 1)) {
3437         /* opcode incorrect -> do nothing */
3438     } else if (addc == 1) {
3439         if (unlikely(XRa == 0 && XRd == 0)) {
3440             /* destinations are zero register -> do nothing */
3441         } else {
3442             /* FIXME ??? What if XRa == XRd ??? */
3443             /* aptn2 is unused here */
3444             gen_load_mxu_gpr(t0, XRb);
3445             gen_load_mxu_gpr(t1, XRc);
3446             gen_load_mxu_cr(cr);
3447             if (XRa != 0) {
3448                 tcg_gen_extract_tl(t2, cr, 31, 1);
3449                 tcg_gen_add_tl(t0, t0, t2);
3450                 tcg_gen_add_tl(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
3451             }
3452             if (XRd != 0) {
3453                 tcg_gen_extract_tl(t2, cr, 30, 1);
3454                 tcg_gen_add_tl(t1, t1, t2);
3455                 tcg_gen_add_tl(mxu_gpr[XRd - 1], mxu_gpr[XRd - 1], t1);
3456             }
3457         }
3458     } else if (unlikely(XRa == 0 && XRd == 0)) {
3459         /* destinations are zero register -> do nothing */
3460     } else {
3461         /* common case */
3462         /* FIXME ??? What if XRa == XRd ??? */
3463         TCGv carry = tcg_temp_new();
3464 
3465         gen_load_mxu_gpr(t0, XRb);
3466         gen_load_mxu_gpr(t1, XRc);
3467         gen_load_mxu_cr(cr);
3468         if (XRa != 0) {
3469             if (aptn2 & 2) {
3470                 tcg_gen_sub_i32(t2, t0, t1);
3471                 tcg_gen_setcond_tl(TCG_COND_GTU, carry, t0, t1);
3472             } else {
3473                 tcg_gen_add_i32(t2, t0, t1);
3474                 tcg_gen_setcond_tl(TCG_COND_GTU, carry, t0, t2);
3475             }
3476             tcg_gen_andi_tl(cr, cr, 0x7fffffff);
3477             tcg_gen_shli_tl(carry, carry, 31);
3478             tcg_gen_or_tl(cr, cr, carry);
3479             gen_store_mxu_gpr(t2, XRa);
3480         }
3481         if (XRd != 0) {
3482             if (aptn2 & 1) {
3483                 tcg_gen_sub_i32(t2, t0, t1);
3484                 tcg_gen_setcond_tl(TCG_COND_GTU, carry, t0, t1);
3485             } else {
3486                 tcg_gen_add_i32(t2, t0, t1);
3487                 tcg_gen_setcond_tl(TCG_COND_GTU, carry, t0, t2);
3488             }
3489             tcg_gen_andi_tl(cr, cr, 0xbfffffff);
3490             tcg_gen_shli_tl(carry, carry, 30);
3491             tcg_gen_or_tl(cr, cr, carry);
3492             gen_store_mxu_gpr(t2, XRd);
3493         }
3494         gen_store_mxu_cr(cr);
3495     }
3496 }
3497 
3498 /*
3499  * D32ACC XRa, XRb, XRc, XRd, aptn2 - Double
3500  * 32 bit pattern addition/subtraction and accumulate.
3501  */
3502 static void gen_mxu_d32acc(DisasContext *ctx)
3503 {
3504     uint32_t aptn2, XRc, XRb, XRa, XRd;
3505 
3506     aptn2 = extract32(ctx->opcode, 24, 2);
3507     XRd   = extract32(ctx->opcode, 18, 4);
3508     XRc   = extract32(ctx->opcode, 14, 4);
3509     XRb   = extract32(ctx->opcode, 10, 4);
3510     XRa   = extract32(ctx->opcode,  6, 4);
3511 
3512     TCGv t0 = tcg_temp_new();
3513     TCGv t1 = tcg_temp_new();
3514     TCGv t2 = tcg_temp_new();
3515 
3516     if (unlikely(XRa == 0 && XRd == 0)) {
3517         /* destinations are zero register -> do nothing */
3518     } else {
3519         /* common case */
3520         gen_load_mxu_gpr(t0, XRb);
3521         gen_load_mxu_gpr(t1, XRc);
3522         if (XRa != 0) {
3523             if (aptn2 & 2) {
3524                 tcg_gen_sub_tl(t2, t0, t1);
3525             } else {
3526                 tcg_gen_add_tl(t2, t0, t1);
3527             }
3528             tcg_gen_add_tl(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t2);
3529         }
3530         if (XRd != 0) {
3531             if (aptn2 & 1) {
3532                 tcg_gen_sub_tl(t2, t0, t1);
3533             } else {
3534                 tcg_gen_add_tl(t2, t0, t1);
3535             }
3536             tcg_gen_add_tl(mxu_gpr[XRd - 1], mxu_gpr[XRd - 1], t2);
3537         }
3538     }
3539 }
3540 
3541 /*
3542  * D32ACCM XRa, XRb, XRc, XRd, aptn2 - Double
3543  * 32 bit pattern addition/subtraction and accumulate.
3544  */
3545 static void gen_mxu_d32accm(DisasContext *ctx)
3546 {
3547     uint32_t aptn2, XRc, XRb, XRa, XRd;
3548 
3549     aptn2 = extract32(ctx->opcode, 24, 2);
3550     XRd   = extract32(ctx->opcode, 18, 4);
3551     XRc   = extract32(ctx->opcode, 14, 4);
3552     XRb   = extract32(ctx->opcode, 10, 4);
3553     XRa   = extract32(ctx->opcode,  6, 4);
3554 
3555     TCGv t0 = tcg_temp_new();
3556     TCGv t1 = tcg_temp_new();
3557     TCGv t2 = tcg_temp_new();
3558 
3559     if (unlikely(XRa == 0 && XRd == 0)) {
3560         /* destinations are zero register -> do nothing */
3561     } else {
3562         /* common case */
3563         gen_load_mxu_gpr(t0, XRb);
3564         gen_load_mxu_gpr(t1, XRc);
3565         if (XRa != 0) {
3566             tcg_gen_add_tl(t2, t0, t1);
3567             if (aptn2 & 2) {
3568                 tcg_gen_sub_tl(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t2);
3569             } else {
3570                 tcg_gen_add_tl(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t2);
3571             }
3572         }
3573         if (XRd != 0) {
3574             tcg_gen_sub_tl(t2, t0, t1);
3575             if (aptn2 & 1) {
3576                 tcg_gen_sub_tl(mxu_gpr[XRd - 1], mxu_gpr[XRd - 1], t2);
3577             } else {
3578                 tcg_gen_add_tl(mxu_gpr[XRd - 1], mxu_gpr[XRd - 1], t2);
3579             }
3580         }
3581     }
3582 }
3583 
3584 /*
3585  * D32ASUM XRa, XRb, XRc, XRd, aptn2 - Double
3586  * 32 bit pattern addition/subtraction.
3587  */
3588 static void gen_mxu_d32asum(DisasContext *ctx)
3589 {
3590     uint32_t aptn2, XRc, XRb, XRa, XRd;
3591 
3592     aptn2 = extract32(ctx->opcode, 24, 2);
3593     XRd   = extract32(ctx->opcode, 18, 4);
3594     XRc   = extract32(ctx->opcode, 14, 4);
3595     XRb   = extract32(ctx->opcode, 10, 4);
3596     XRa   = extract32(ctx->opcode,  6, 4);
3597 
3598     TCGv t0 = tcg_temp_new();
3599     TCGv t1 = tcg_temp_new();
3600 
3601     if (unlikely(XRa == 0 && XRd == 0)) {
3602         /* destinations are zero register -> do nothing */
3603     } else {
3604         /* common case */
3605         gen_load_mxu_gpr(t0, XRb);
3606         gen_load_mxu_gpr(t1, XRc);
3607         if (XRa != 0) {
3608             if (aptn2 & 2) {
3609                 tcg_gen_sub_tl(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
3610             } else {
3611                 tcg_gen_add_tl(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
3612             }
3613         }
3614         if (XRd != 0) {
3615             if (aptn2 & 1) {
3616                 tcg_gen_sub_tl(mxu_gpr[XRd - 1], mxu_gpr[XRd - 1], t1);
3617             } else {
3618                 tcg_gen_add_tl(mxu_gpr[XRd - 1], mxu_gpr[XRd - 1], t1);
3619             }
3620         }
3621     }
3622 }
3623 
3624 /*
3625  *                 MXU instruction category: Miscellaneous
3626  *                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3627  *
3628  *               S32EXTR      S32LUI
3629  *               S32EXTRV
3630  *                            Q16SAT
3631  *                            Q16SCOP
3632  */
3633 
3634 /*
3635  *  S32EXTR XRa, XRd, rs, bits5
3636  *    Extract bits5 bits from 64-bit pair {XRa:XRd}
3637  *    starting from rs[4:0] offset and put to the XRa.
3638  */
3639 static void gen_mxu_s32extr(DisasContext *ctx)
3640 {
3641     TCGv t0, t1, t2, t3;
3642     uint32_t XRa, XRd, rs, bits5;
3643 
3644     t0 = tcg_temp_new();
3645     t1 = tcg_temp_new();
3646     t2 = tcg_temp_new();
3647     t3 = tcg_temp_new();
3648 
3649     XRa   = extract32(ctx->opcode,  6, 4);
3650     XRd   = extract32(ctx->opcode, 10, 4);
3651     bits5 = extract32(ctx->opcode, 16, 5);
3652     rs    = extract32(ctx->opcode, 21, 5);
3653 
3654     /* {tmp} = {XRa:XRd} >> (64 - rt - bits5); */
3655     /* {XRa} = extract({tmp}, 0, bits5); */
3656     if (bits5 > 0) {
3657         TCGLabel *l_xra_only = gen_new_label();
3658         TCGLabel *l_done = gen_new_label();
3659 
3660         gen_load_mxu_gpr(t0, XRd);
3661         gen_load_mxu_gpr(t1, XRa);
3662         gen_load_gpr(t2, rs);
3663         tcg_gen_andi_tl(t2, t2, 0x1f);
3664         tcg_gen_subfi_tl(t2, 32, t2);
3665         tcg_gen_brcondi_tl(TCG_COND_GE, t2, bits5, l_xra_only);
3666         tcg_gen_subfi_tl(t2, bits5, t2);
3667         tcg_gen_subfi_tl(t3, 32, t2);
3668         tcg_gen_shr_tl(t0, t0, t3);
3669         tcg_gen_shl_tl(t1, t1, t2);
3670         tcg_gen_or_tl(t0, t0, t1);
3671         tcg_gen_br(l_done);
3672         gen_set_label(l_xra_only);
3673         tcg_gen_subi_tl(t2, t2, bits5);
3674         tcg_gen_shr_tl(t0, t1, t2);
3675         gen_set_label(l_done);
3676         tcg_gen_extract_tl(t0, t0, 0, bits5);
3677     } else {
3678         /* unspecified behavior but matches tests on real hardware*/
3679         tcg_gen_movi_tl(t0, 0);
3680     }
3681     gen_store_mxu_gpr(t0, XRa);
3682 }
3683 
3684 /*
3685  *  S32EXTRV XRa, XRd, rs, rt
3686  *    Extract rt[4:0] bits from 64-bit pair {XRa:XRd}
3687  *    starting from rs[4:0] offset and put to the XRa.
3688  */
3689 static void gen_mxu_s32extrv(DisasContext *ctx)
3690 {
3691     TCGv t0, t1, t2, t3, t4;
3692     uint32_t XRa, XRd, rs, rt;
3693 
3694     t0 = tcg_temp_new();
3695     t1 = tcg_temp_new();
3696     t2 = tcg_temp_new();
3697     t3 = tcg_temp_new();
3698     t4 = tcg_temp_new();
3699     TCGLabel *l_xra_only = gen_new_label();
3700     TCGLabel *l_done = gen_new_label();
3701     TCGLabel *l_zero = gen_new_label();
3702     TCGLabel *l_extract = gen_new_label();
3703 
3704     XRa = extract32(ctx->opcode,  6, 4);
3705     XRd = extract32(ctx->opcode, 10, 4);
3706     rt  = extract32(ctx->opcode, 16, 5);
3707     rs  = extract32(ctx->opcode, 21, 5);
3708 
3709     /* {tmp} = {XRa:XRd} >> (64 - rs - rt) */
3710     gen_load_mxu_gpr(t0, XRd);
3711     gen_load_mxu_gpr(t1, XRa);
3712     gen_load_gpr(t2, rs);
3713     gen_load_gpr(t4, rt);
3714     tcg_gen_brcondi_tl(TCG_COND_EQ, t4, 0, l_zero);
3715     tcg_gen_andi_tl(t2, t2, 0x1f);
3716     tcg_gen_subfi_tl(t2, 32, t2);
3717     tcg_gen_brcond_tl(TCG_COND_GE, t2, t4, l_xra_only);
3718     tcg_gen_sub_tl(t2, t4, t2);
3719     tcg_gen_subfi_tl(t3, 32, t2);
3720     tcg_gen_shr_tl(t0, t0, t3);
3721     tcg_gen_shl_tl(t1, t1, t2);
3722     tcg_gen_or_tl(t0, t0, t1);
3723     tcg_gen_br(l_extract);
3724 
3725     gen_set_label(l_xra_only);
3726     tcg_gen_sub_tl(t2, t2, t4);
3727     tcg_gen_shr_tl(t0, t1, t2);
3728     tcg_gen_br(l_extract);
3729 
3730     /* unspecified behavior but matches tests on real hardware*/
3731     gen_set_label(l_zero);
3732     tcg_gen_movi_tl(t0, 0);
3733     tcg_gen_br(l_done);
3734 
3735     /* {XRa} = extract({tmp}, 0, rt) */
3736     gen_set_label(l_extract);
3737     tcg_gen_subfi_tl(t4, 32, t4);
3738     tcg_gen_shl_tl(t0, t0, t4);
3739     tcg_gen_shr_tl(t0, t0, t4);
3740 
3741     gen_set_label(l_done);
3742     gen_store_mxu_gpr(t0, XRa);
3743 }
3744 
3745 /*
3746  *  S32LUI XRa, S8, optn3
3747  *    Permutate the immediate S8 value to form a word
3748  *    to update XRa.
3749  */
3750 static void gen_mxu_s32lui(DisasContext *ctx)
3751 {
3752     uint32_t XRa, s8, optn3, pad;
3753 
3754     XRa   = extract32(ctx->opcode,  6, 4);
3755     s8    = extract32(ctx->opcode, 10, 8);
3756     pad   = extract32(ctx->opcode, 21, 2);
3757     optn3 = extract32(ctx->opcode, 23, 3);
3758 
3759     if (unlikely(pad != 0)) {
3760         /* opcode padding incorrect -> do nothing */
3761     } else if (unlikely(XRa == 0)) {
3762         /* destination is zero register -> do nothing */
3763     } else {
3764         uint32_t s16;
3765         TCGv t0 = tcg_temp_new();
3766 
3767         switch (optn3) {
3768         case 0:
3769             tcg_gen_movi_tl(t0, s8);
3770             break;
3771         case 1:
3772             tcg_gen_movi_tl(t0, s8 << 8);
3773             break;
3774         case 2:
3775             tcg_gen_movi_tl(t0, s8 << 16);
3776             break;
3777         case 3:
3778             tcg_gen_movi_tl(t0, s8 << 24);
3779             break;
3780         case 4:
3781             tcg_gen_movi_tl(t0, (s8 << 16) | s8);
3782             break;
3783         case 5:
3784             tcg_gen_movi_tl(t0, (s8 << 24) | (s8 << 8));
3785             break;
3786         case 6:
3787             s16 = (uint16_t)(int16_t)(int8_t)s8;
3788             tcg_gen_movi_tl(t0, (s16 << 16) | s16);
3789             break;
3790         case 7:
3791             tcg_gen_movi_tl(t0, (s8 << 24) | (s8 << 16) | (s8 << 8) | s8);
3792             break;
3793         }
3794         gen_store_mxu_gpr(t0, XRa);
3795     }
3796 }
3797 
3798 /*
3799  *  Q16SAT XRa, XRb, XRc
3800  *  Packs four 16-bit signed integers in XRb and XRc to
3801  *  four saturated unsigned 8-bit into XRa.
3802  *
3803  */
3804 static void gen_mxu_Q16SAT(DisasContext *ctx)
3805 {
3806     uint32_t pad, XRc, XRb, XRa;
3807 
3808     pad = extract32(ctx->opcode, 21, 3);
3809     XRc = extract32(ctx->opcode, 14, 4);
3810     XRb = extract32(ctx->opcode, 10, 4);
3811     XRa = extract32(ctx->opcode,  6, 4);
3812 
3813     if (unlikely(pad != 0)) {
3814         /* opcode padding incorrect -> do nothing */
3815     } else if (unlikely(XRa == 0)) {
3816         /* destination is zero register -> do nothing */
3817     } else {
3818         /* the most general case */
3819         TCGv t0 = tcg_temp_new();
3820         TCGv t1 = tcg_temp_new();
3821         TCGv t2 = tcg_temp_new();
3822 
3823         tcg_gen_movi_tl(t2, 0);
3824         if (XRb != 0) {
3825             TCGLabel *l_less_hi = gen_new_label();
3826             TCGLabel *l_less_lo = gen_new_label();
3827             TCGLabel *l_lo = gen_new_label();
3828             TCGLabel *l_greater_hi = gen_new_label();
3829             TCGLabel *l_greater_lo = gen_new_label();
3830             TCGLabel *l_done = gen_new_label();
3831 
3832             tcg_gen_sari_tl(t0, mxu_gpr[XRb - 1], 16);
3833             tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0, l_less_hi);
3834             tcg_gen_brcondi_tl(TCG_COND_GT, t0, 255, l_greater_hi);
3835             tcg_gen_br(l_lo);
3836             gen_set_label(l_less_hi);
3837             tcg_gen_movi_tl(t0, 0);
3838             tcg_gen_br(l_lo);
3839             gen_set_label(l_greater_hi);
3840             tcg_gen_movi_tl(t0, 255);
3841 
3842             gen_set_label(l_lo);
3843             tcg_gen_shli_tl(t1, mxu_gpr[XRb - 1], 16);
3844             tcg_gen_sari_tl(t1, t1, 16);
3845             tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l_less_lo);
3846             tcg_gen_brcondi_tl(TCG_COND_GT, t1, 255, l_greater_lo);
3847             tcg_gen_br(l_done);
3848             gen_set_label(l_less_lo);
3849             tcg_gen_movi_tl(t1, 0);
3850             tcg_gen_br(l_done);
3851             gen_set_label(l_greater_lo);
3852             tcg_gen_movi_tl(t1, 255);
3853 
3854             gen_set_label(l_done);
3855             tcg_gen_shli_tl(t2, t0, 24);
3856             tcg_gen_shli_tl(t1, t1, 16);
3857             tcg_gen_or_tl(t2, t2, t1);
3858         }
3859 
3860         if (XRc != 0) {
3861             TCGLabel *l_less_hi = gen_new_label();
3862             TCGLabel *l_less_lo = gen_new_label();
3863             TCGLabel *l_lo = gen_new_label();
3864             TCGLabel *l_greater_hi = gen_new_label();
3865             TCGLabel *l_greater_lo = gen_new_label();
3866             TCGLabel *l_done = gen_new_label();
3867 
3868             tcg_gen_sari_tl(t0, mxu_gpr[XRc - 1], 16);
3869             tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0, l_less_hi);
3870             tcg_gen_brcondi_tl(TCG_COND_GT, t0, 255, l_greater_hi);
3871             tcg_gen_br(l_lo);
3872             gen_set_label(l_less_hi);
3873             tcg_gen_movi_tl(t0, 0);
3874             tcg_gen_br(l_lo);
3875             gen_set_label(l_greater_hi);
3876             tcg_gen_movi_tl(t0, 255);
3877 
3878             gen_set_label(l_lo);
3879             tcg_gen_shli_tl(t1, mxu_gpr[XRc - 1], 16);
3880             tcg_gen_sari_tl(t1, t1, 16);
3881             tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l_less_lo);
3882             tcg_gen_brcondi_tl(TCG_COND_GT, t1, 255, l_greater_lo);
3883             tcg_gen_br(l_done);
3884             gen_set_label(l_less_lo);
3885             tcg_gen_movi_tl(t1, 0);
3886             tcg_gen_br(l_done);
3887             gen_set_label(l_greater_lo);
3888             tcg_gen_movi_tl(t1, 255);
3889 
3890             gen_set_label(l_done);
3891             tcg_gen_shli_tl(t0, t0, 8);
3892             tcg_gen_or_tl(t2, t2, t0);
3893             tcg_gen_or_tl(t2, t2, t1);
3894         }
3895         gen_store_mxu_gpr(t2, XRa);
3896     }
3897 }
3898 
3899 /*
3900  *  Q16SCOP XRa, XRd, XRb, XRc
3901  *    Determine sign of quad packed 16-bit signed values
3902  *    in XRb and XRc put result in XRa and XRd respectively.
3903  */
3904 static void gen_mxu_q16scop(DisasContext *ctx)
3905 {
3906     uint32_t XRd, XRc, XRb, XRa;
3907 
3908     XRd  = extract32(ctx->opcode, 18, 4);
3909     XRc  = extract32(ctx->opcode, 14, 4);
3910     XRb  = extract32(ctx->opcode, 10, 4);
3911     XRa  = extract32(ctx->opcode,  6, 4);
3912 
3913     TCGv t0 = tcg_temp_new();
3914     TCGv t1 = tcg_temp_new();
3915     TCGv t2 = tcg_temp_new();
3916     TCGv t3 = tcg_temp_new();
3917     TCGv t4 = tcg_temp_new();
3918 
3919     TCGLabel *l_b_hi_lt = gen_new_label();
3920     TCGLabel *l_b_hi_gt = gen_new_label();
3921     TCGLabel *l_b_lo = gen_new_label();
3922     TCGLabel *l_b_lo_lt = gen_new_label();
3923     TCGLabel *l_c_hi = gen_new_label();
3924     TCGLabel *l_c_hi_lt = gen_new_label();
3925     TCGLabel *l_c_hi_gt = gen_new_label();
3926     TCGLabel *l_c_lo = gen_new_label();
3927     TCGLabel *l_c_lo_lt = gen_new_label();
3928     TCGLabel *l_done = gen_new_label();
3929 
3930     gen_load_mxu_gpr(t0, XRb);
3931     gen_load_mxu_gpr(t1, XRc);
3932 
3933     tcg_gen_sextract_tl(t2, t0, 16, 16);
3934     tcg_gen_brcondi_tl(TCG_COND_LT, t2, 0, l_b_hi_lt);
3935     tcg_gen_brcondi_tl(TCG_COND_GT, t2, 0, l_b_hi_gt);
3936     tcg_gen_movi_tl(t3, 0);
3937     tcg_gen_br(l_b_lo);
3938     gen_set_label(l_b_hi_lt);
3939     tcg_gen_movi_tl(t3, 0xffff0000);
3940     tcg_gen_br(l_b_lo);
3941     gen_set_label(l_b_hi_gt);
3942     tcg_gen_movi_tl(t3, 0x00010000);
3943 
3944     gen_set_label(l_b_lo);
3945     tcg_gen_sextract_tl(t2, t0, 0, 16);
3946     tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l_c_hi);
3947     tcg_gen_brcondi_tl(TCG_COND_LT, t2, 0, l_b_lo_lt);
3948     tcg_gen_ori_tl(t3, t3, 0x00000001);
3949     tcg_gen_br(l_c_hi);
3950     gen_set_label(l_b_lo_lt);
3951     tcg_gen_ori_tl(t3, t3, 0x0000ffff);
3952     tcg_gen_br(l_c_hi);
3953 
3954     gen_set_label(l_c_hi);
3955     tcg_gen_sextract_tl(t2, t1, 16, 16);
3956     tcg_gen_brcondi_tl(TCG_COND_LT, t2, 0, l_c_hi_lt);
3957     tcg_gen_brcondi_tl(TCG_COND_GT, t2, 0, l_c_hi_gt);
3958     tcg_gen_movi_tl(t4, 0);
3959     tcg_gen_br(l_c_lo);
3960     gen_set_label(l_c_hi_lt);
3961     tcg_gen_movi_tl(t4, 0xffff0000);
3962     tcg_gen_br(l_c_lo);
3963     gen_set_label(l_c_hi_gt);
3964     tcg_gen_movi_tl(t4, 0x00010000);
3965 
3966     gen_set_label(l_c_lo);
3967     tcg_gen_sextract_tl(t2, t1, 0, 16);
3968     tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l_done);
3969     tcg_gen_brcondi_tl(TCG_COND_LT, t2, 0, l_c_lo_lt);
3970     tcg_gen_ori_tl(t4, t4, 0x00000001);
3971     tcg_gen_br(l_done);
3972     gen_set_label(l_c_lo_lt);
3973     tcg_gen_ori_tl(t4, t4, 0x0000ffff);
3974 
3975     gen_set_label(l_done);
3976     gen_store_mxu_gpr(t3, XRa);
3977     gen_store_mxu_gpr(t4, XRd);
3978 }
3979 
3980 /*
3981  *  S32SFL XRa, XRd, XRb, XRc
3982  *    Shuffle bytes according to one of four patterns.
3983  */
3984 static void gen_mxu_s32sfl(DisasContext *ctx)
3985 {
3986     uint32_t XRd, XRc, XRb, XRa, ptn2;
3987 
3988     XRd  = extract32(ctx->opcode, 18, 4);
3989     XRc  = extract32(ctx->opcode, 14, 4);
3990     XRb  = extract32(ctx->opcode, 10, 4);
3991     XRa  = extract32(ctx->opcode,  6, 4);
3992     ptn2 = extract32(ctx->opcode, 24, 2);
3993 
3994     TCGv t0 = tcg_temp_new();
3995     TCGv t1 = tcg_temp_new();
3996     TCGv t2 = tcg_temp_new();
3997     TCGv t3 = tcg_temp_new();
3998 
3999     gen_load_mxu_gpr(t0, XRb);
4000     gen_load_mxu_gpr(t1, XRc);
4001 
4002     switch (ptn2) {
4003     case 0:
4004         tcg_gen_andi_tl(t2, t0, 0xff000000);
4005         tcg_gen_andi_tl(t3, t1, 0x000000ff);
4006         tcg_gen_deposit_tl(t3, t3, t0,  8, 8);
4007         tcg_gen_shri_tl(t0, t0,  8);
4008         tcg_gen_shri_tl(t1, t1,  8);
4009         tcg_gen_deposit_tl(t3, t3, t0, 24, 8);
4010         tcg_gen_deposit_tl(t3, t3, t1, 16, 8);
4011         tcg_gen_shri_tl(t0, t0,  8);
4012         tcg_gen_shri_tl(t1, t1,  8);
4013         tcg_gen_deposit_tl(t2, t2, t0,  8, 8);
4014         tcg_gen_deposit_tl(t2, t2, t1,  0, 8);
4015         tcg_gen_shri_tl(t1, t1,  8);
4016         tcg_gen_deposit_tl(t2, t2, t1, 16, 8);
4017         break;
4018     case 1:
4019         tcg_gen_andi_tl(t2, t0, 0xff000000);
4020         tcg_gen_andi_tl(t3, t1, 0x000000ff);
4021         tcg_gen_deposit_tl(t3, t3, t0, 16, 8);
4022         tcg_gen_shri_tl(t0, t0,  8);
4023         tcg_gen_shri_tl(t1, t1,  8);
4024         tcg_gen_deposit_tl(t2, t2, t0, 16, 8);
4025         tcg_gen_deposit_tl(t2, t2, t1,  0, 8);
4026         tcg_gen_shri_tl(t0, t0,  8);
4027         tcg_gen_shri_tl(t1, t1,  8);
4028         tcg_gen_deposit_tl(t3, t3, t0, 24, 8);
4029         tcg_gen_deposit_tl(t3, t3, t1,  8, 8);
4030         tcg_gen_shri_tl(t1, t1,  8);
4031         tcg_gen_deposit_tl(t2, t2, t1,  8, 8);
4032         break;
4033     case 2:
4034         tcg_gen_andi_tl(t2, t0, 0xff00ff00);
4035         tcg_gen_andi_tl(t3, t1, 0x00ff00ff);
4036         tcg_gen_deposit_tl(t3, t3, t0,  8, 8);
4037         tcg_gen_shri_tl(t0, t0, 16);
4038         tcg_gen_shri_tl(t1, t1,  8);
4039         tcg_gen_deposit_tl(t2, t2, t1,  0, 8);
4040         tcg_gen_deposit_tl(t3, t3, t0, 24, 8);
4041         tcg_gen_shri_tl(t1, t1, 16);
4042         tcg_gen_deposit_tl(t2, t2, t1, 16, 8);
4043         break;
4044     case 3:
4045         tcg_gen_andi_tl(t2, t0, 0xffff0000);
4046         tcg_gen_andi_tl(t3, t1, 0x0000ffff);
4047         tcg_gen_shri_tl(t1, t1, 16);
4048         tcg_gen_deposit_tl(t2, t2, t1,  0, 16);
4049         tcg_gen_deposit_tl(t3, t3, t0, 16, 16);
4050         break;
4051     }
4052 
4053     gen_store_mxu_gpr(t2, XRa);
4054     gen_store_mxu_gpr(t3, XRd);
4055 }
4056 
4057 /*
4058  *  Q8SAD XRa, XRd, XRb, XRc
4059  *    Typical SAD operation for motion estimation.
4060  */
4061 static void gen_mxu_q8sad(DisasContext *ctx)
4062 {
4063     uint32_t XRd, XRc, XRb, XRa;
4064 
4065     XRd = extract32(ctx->opcode, 18, 4);
4066     XRc = extract32(ctx->opcode, 14, 4);
4067     XRb = extract32(ctx->opcode, 10, 4);
4068     XRa = extract32(ctx->opcode,  6, 4);
4069 
4070     TCGv t0 = tcg_temp_new();
4071     TCGv t1 = tcg_temp_new();
4072     TCGv t2 = tcg_temp_new();
4073     TCGv t3 = tcg_temp_new();
4074     TCGv t4 = tcg_temp_new();
4075     TCGv t5 = tcg_temp_new();
4076 
4077     gen_load_mxu_gpr(t2, XRb);
4078     gen_load_mxu_gpr(t3, XRc);
4079     gen_load_mxu_gpr(t5, XRd);
4080     tcg_gen_movi_tl(t4, 0);
4081 
4082     for (int i = 0; i < 4; i++) {
4083         tcg_gen_andi_tl(t0, t2, 0xff);
4084         tcg_gen_andi_tl(t1, t3, 0xff);
4085         tcg_gen_sub_tl(t0, t0, t1);
4086         tcg_gen_abs_tl(t0, t0);
4087         tcg_gen_add_tl(t4, t4, t0);
4088         if (i < 3) {
4089             tcg_gen_shri_tl(t2, t2, 8);
4090             tcg_gen_shri_tl(t3, t3, 8);
4091         }
4092     }
4093     tcg_gen_add_tl(t5, t5, t4);
4094     gen_store_mxu_gpr(t4, XRa);
4095     gen_store_mxu_gpr(t5, XRd);
4096 }
4097 
4098 /*
4099  *                 MXU instruction category: align
4100  *                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4101  *
4102  *                       S32ALN     S32ALNI
4103  */
4104 
4105 /*
4106  *  S32ALNI XRc, XRb, XRa, optn3
4107  *    Arrange bytes from XRb and XRc according to one of five sets of
4108  *    rules determined by optn3, and place the result in XRa.
4109  */
4110 static void gen_mxu_S32ALNI(DisasContext *ctx)
4111 {
4112     uint32_t optn3, pad, XRc, XRb, XRa;
4113 
4114     optn3 = extract32(ctx->opcode,  23, 3);
4115     pad   = extract32(ctx->opcode,  21, 2);
4116     XRc   = extract32(ctx->opcode, 14, 4);
4117     XRb   = extract32(ctx->opcode, 10, 4);
4118     XRa   = extract32(ctx->opcode,  6, 4);
4119 
4120     if (unlikely(pad != 0)) {
4121         /* opcode padding incorrect -> do nothing */
4122     } else if (unlikely(XRa == 0)) {
4123         /* destination is zero register -> do nothing */
4124     } else if (unlikely((XRb == 0) && (XRc == 0))) {
4125         /* both operands zero registers -> just set destination to all 0s */
4126         tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
4127     } else if (unlikely(XRb == 0)) {
4128         /* XRb zero register -> just appropriatelly shift XRc into XRa */
4129         switch (optn3) {
4130         case MXU_OPTN3_PTN0:
4131             tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
4132             break;
4133         case MXU_OPTN3_PTN1:
4134         case MXU_OPTN3_PTN2:
4135         case MXU_OPTN3_PTN3:
4136             tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1],
4137                              8 * (4 - optn3));
4138             break;
4139         case MXU_OPTN3_PTN4:
4140             tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
4141             break;
4142         }
4143     } else if (unlikely(XRc == 0)) {
4144         /* XRc zero register -> just appropriatelly shift XRb into XRa */
4145         switch (optn3) {
4146         case MXU_OPTN3_PTN0:
4147             tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
4148             break;
4149         case MXU_OPTN3_PTN1:
4150         case MXU_OPTN3_PTN2:
4151         case MXU_OPTN3_PTN3:
4152             tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
4153             break;
4154         case MXU_OPTN3_PTN4:
4155             tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
4156             break;
4157         }
4158     } else if (unlikely(XRb == XRc)) {
4159         /* both operands same -> just rotation or moving from any of them */
4160         switch (optn3) {
4161         case MXU_OPTN3_PTN0:
4162         case MXU_OPTN3_PTN4:
4163             tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
4164             break;
4165         case MXU_OPTN3_PTN1:
4166         case MXU_OPTN3_PTN2:
4167         case MXU_OPTN3_PTN3:
4168             tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
4169             break;
4170         }
4171     } else {
4172         /* the most general case */
4173         switch (optn3) {
4174         case MXU_OPTN3_PTN0:
4175             {
4176                 /*                                         */
4177                 /*         XRb                XRc          */
4178                 /*  +---------------+                      */
4179                 /*  | A   B   C   D |    E   F   G   H     */
4180                 /*  +-------+-------+                      */
4181                 /*          |                              */
4182                 /*         XRa                             */
4183                 /*                                         */
4184 
4185                 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
4186             }
4187             break;
4188         case MXU_OPTN3_PTN1:
4189             {
4190                 /*                                         */
4191                 /*         XRb                 XRc         */
4192                 /*      +-------------------+              */
4193                 /*    A | B   C   D       E | F   G   H    */
4194                 /*      +---------+---------+              */
4195                 /*                |                        */
4196                 /*               XRa                       */
4197                 /*                                         */
4198 
4199                 TCGv_i32 t0 = tcg_temp_new();
4200                 TCGv_i32 t1 = tcg_temp_new();
4201 
4202                 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF);
4203                 tcg_gen_shli_i32(t0, t0, 8);
4204 
4205                 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
4206                 tcg_gen_shri_i32(t1, t1, 24);
4207 
4208                 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
4209             }
4210             break;
4211         case MXU_OPTN3_PTN2:
4212             {
4213                 /*                                         */
4214                 /*         XRb                 XRc         */
4215                 /*          +-------------------+          */
4216                 /*    A   B | C   D       E   F | G   H    */
4217                 /*          +---------+---------+          */
4218                 /*                    |                    */
4219                 /*                   XRa                   */
4220                 /*                                         */
4221 
4222                 TCGv_i32 t0 = tcg_temp_new();
4223                 TCGv_i32 t1 = tcg_temp_new();
4224 
4225                 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
4226                 tcg_gen_shli_i32(t0, t0, 16);
4227 
4228                 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
4229                 tcg_gen_shri_i32(t1, t1, 16);
4230 
4231                 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
4232             }
4233             break;
4234         case MXU_OPTN3_PTN3:
4235             {
4236                 /*                                         */
4237                 /*         XRb                 XRc         */
4238                 /*              +-------------------+      */
4239                 /*    A   B   C | D       E   F   G | H    */
4240                 /*              +---------+---------+      */
4241                 /*                        |                */
4242                 /*                       XRa               */
4243                 /*                                         */
4244 
4245                 TCGv_i32 t0 = tcg_temp_new();
4246                 TCGv_i32 t1 = tcg_temp_new();
4247 
4248                 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF);
4249                 tcg_gen_shli_i32(t0, t0, 24);
4250 
4251                 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00);
4252                 tcg_gen_shri_i32(t1, t1, 8);
4253 
4254                 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
4255             }
4256             break;
4257         case MXU_OPTN3_PTN4:
4258             {
4259                 /*                                         */
4260                 /*         XRb                 XRc         */
4261                 /*                     +---------------+   */
4262                 /*    A   B   C   D    | E   F   G   H |   */
4263                 /*                     +-------+-------+   */
4264                 /*                             |           */
4265                 /*                            XRa          */
4266                 /*                                         */
4267 
4268                 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
4269             }
4270             break;
4271         }
4272     }
4273 }
4274 
4275 /*
4276  *  S32ALN XRc, XRb, XRa, rs
4277  *    Arrange bytes from XRb and XRc according to one of five sets of
4278  *    rules determined by rs[2:0], and place the result in XRa.
4279  */
4280 static void gen_mxu_S32ALN(DisasContext *ctx)
4281 {
4282     uint32_t rs, XRc, XRb, XRa;
4283 
4284     rs  = extract32(ctx->opcode, 21, 5);
4285     XRc = extract32(ctx->opcode, 14, 4);
4286     XRb = extract32(ctx->opcode, 10, 4);
4287     XRa = extract32(ctx->opcode,  6, 4);
4288 
4289     if (unlikely(XRa == 0)) {
4290         /* destination is zero register -> do nothing */
4291     } else if (unlikely((XRb == 0) && (XRc == 0))) {
4292         /* both operands zero registers -> just set destination to all 0s */
4293         tcg_gen_movi_tl(mxu_gpr[XRa - 1], 0);
4294     } else {
4295         /* the most general case */
4296         TCGv t0 = tcg_temp_new();
4297         TCGv t1 = tcg_temp_new();
4298         TCGv t2 = tcg_temp_new();
4299         TCGv t3 = tcg_temp_new();
4300         TCGLabel *l_exit = gen_new_label();
4301         TCGLabel *l_b_only = gen_new_label();
4302         TCGLabel *l_c_only = gen_new_label();
4303 
4304         gen_load_mxu_gpr(t0, XRb);
4305         gen_load_mxu_gpr(t1, XRc);
4306         gen_load_gpr(t2, rs);
4307         tcg_gen_andi_tl(t2, t2, 0x07);
4308 
4309         /* do nothing for undefined cases */
4310         tcg_gen_brcondi_tl(TCG_COND_GE, t2, 5, l_exit);
4311 
4312         tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l_b_only);
4313         tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 4, l_c_only);
4314 
4315         tcg_gen_shli_tl(t2, t2, 3);
4316         tcg_gen_subfi_tl(t3, 32, t2);
4317 
4318         tcg_gen_shl_tl(t0, t0, t2);
4319         tcg_gen_shr_tl(t1, t1, t3);
4320         tcg_gen_or_tl(mxu_gpr[XRa - 1], t0, t1);
4321         tcg_gen_br(l_exit);
4322 
4323         gen_set_label(l_b_only);
4324         gen_store_mxu_gpr(t0, XRa);
4325         tcg_gen_br(l_exit);
4326 
4327         gen_set_label(l_c_only);
4328         gen_store_mxu_gpr(t1, XRa);
4329 
4330         gen_set_label(l_exit);
4331     }
4332 }
4333 
4334 /*
4335  *  S32MADD XRa, XRd, rb, rc
4336  *    32 to 64 bit signed multiply with subsequent add
4337  *    result stored in {XRa, XRd} pair, stain HI/LO.
4338  *  S32MADDU XRa, XRd, rb, rc
4339  *    32 to 64 bit unsigned multiply with subsequent add
4340  *    result stored in {XRa, XRd} pair, stain HI/LO.
4341  *  S32MSUB XRa, XRd, rb, rc
4342  *    32 to 64 bit signed multiply with subsequent subtract
4343  *    result stored in {XRa, XRd} pair, stain HI/LO.
4344  *  S32MSUBU XRa, XRd, rb, rc
4345  *    32 to 64 bit unsigned multiply with subsequent subtract
4346  *    result stored in {XRa, XRd} pair, stain HI/LO.
4347  */
4348 static void gen_mxu_s32madd_sub(DisasContext *ctx, bool sub, bool uns)
4349 {
4350     uint32_t XRa, XRd, Rb, Rc;
4351 
4352     XRa  = extract32(ctx->opcode,  6, 4);
4353     XRd  = extract32(ctx->opcode, 10, 4);
4354     Rb   = extract32(ctx->opcode, 16, 5);
4355     Rc   = extract32(ctx->opcode, 21, 5);
4356 
4357     if (unlikely(Rb == 0 || Rc == 0)) {
4358         /* do nothing because x + 0 * y => x */
4359     } else if (unlikely(XRa == 0 && XRd == 0)) {
4360         /* do nothing because result just dropped */
4361     } else {
4362         TCGv t0 = tcg_temp_new();
4363         TCGv t1 = tcg_temp_new();
4364         TCGv_i64 t2 = tcg_temp_new_i64();
4365         TCGv_i64 t3 = tcg_temp_new_i64();
4366 
4367         gen_load_gpr(t0, Rb);
4368         gen_load_gpr(t1, Rc);
4369 
4370         if (uns) {
4371             tcg_gen_extu_tl_i64(t2, t0);
4372             tcg_gen_extu_tl_i64(t3, t1);
4373         } else {
4374             tcg_gen_ext_tl_i64(t2, t0);
4375             tcg_gen_ext_tl_i64(t3, t1);
4376         }
4377         tcg_gen_mul_i64(t2, t2, t3);
4378 
4379         gen_load_mxu_gpr(t0, XRa);
4380         gen_load_mxu_gpr(t1, XRd);
4381 
4382         tcg_gen_concat_tl_i64(t3, t1, t0);
4383         if (sub) {
4384             tcg_gen_sub_i64(t3, t3, t2);
4385         } else {
4386             tcg_gen_add_i64(t3, t3, t2);
4387         }
4388         gen_move_low32(t1, t3);
4389         gen_move_high32(t0, t3);
4390 
4391         tcg_gen_mov_tl(cpu_HI[0], t0);
4392         tcg_gen_mov_tl(cpu_LO[0], t1);
4393 
4394         gen_store_mxu_gpr(t1, XRd);
4395         gen_store_mxu_gpr(t0, XRa);
4396     }
4397 }
4398 
4399 /*
4400  * Decoding engine for MXU
4401  * =======================
4402  */
4403 
4404 static void decode_opc_mxu__pool00(DisasContext *ctx)
4405 {
4406     uint32_t opcode = extract32(ctx->opcode, 18, 3);
4407 
4408     switch (opcode) {
4409     case OPC_MXU_S32MAX:
4410     case OPC_MXU_S32MIN:
4411         gen_mxu_S32MAX_S32MIN(ctx);
4412         break;
4413     case OPC_MXU_D16MAX:
4414     case OPC_MXU_D16MIN:
4415         gen_mxu_D16MAX_D16MIN(ctx);
4416         break;
4417     case OPC_MXU_Q8MAX:
4418     case OPC_MXU_Q8MIN:
4419         gen_mxu_Q8MAX_Q8MIN(ctx);
4420         break;
4421     case OPC_MXU_Q8SLT:
4422         gen_mxu_q8slt(ctx, false);
4423         break;
4424     case OPC_MXU_Q8SLTU:
4425         gen_mxu_q8slt(ctx, true);
4426         break;
4427     default:
4428         MIPS_INVAL("decode_opc_mxu");
4429         gen_reserved_instruction(ctx);
4430         break;
4431     }
4432 }
4433 
4434 static bool decode_opc_mxu_s32madd_sub(DisasContext *ctx)
4435 {
4436     uint32_t opcode = extract32(ctx->opcode, 0, 6);
4437     uint32_t pad  = extract32(ctx->opcode, 14, 2);
4438 
4439     if (pad != 2) {
4440         /* MIPS32R1 MADD/MADDU/MSUB/MSUBU are on pad == 0 */
4441         return false;
4442     }
4443 
4444     switch (opcode) {
4445     case OPC_MXU_S32MADD:
4446         gen_mxu_s32madd_sub(ctx, false, false);
4447         break;
4448     case OPC_MXU_S32MADDU:
4449         gen_mxu_s32madd_sub(ctx, false, true);
4450         break;
4451     case OPC_MXU_S32MSUB:
4452         gen_mxu_s32madd_sub(ctx, true, false);
4453         break;
4454     case OPC_MXU_S32MSUBU:
4455         gen_mxu_s32madd_sub(ctx, true, true);
4456         break;
4457     default:
4458         return false;
4459     }
4460     return true;
4461 }
4462 
4463 static void decode_opc_mxu__pool01(DisasContext *ctx)
4464 {
4465     uint32_t opcode = extract32(ctx->opcode, 18, 3);
4466 
4467     switch (opcode) {
4468     case OPC_MXU_S32SLT:
4469         gen_mxu_S32SLT(ctx);
4470         break;
4471     case OPC_MXU_D16SLT:
4472         gen_mxu_D16SLT(ctx);
4473         break;
4474     case OPC_MXU_D16AVG:
4475         gen_mxu_d16avg(ctx, false);
4476         break;
4477     case OPC_MXU_D16AVGR:
4478         gen_mxu_d16avg(ctx, true);
4479         break;
4480     case OPC_MXU_Q8AVG:
4481         gen_mxu_q8avg(ctx, false);
4482         break;
4483     case OPC_MXU_Q8AVGR:
4484         gen_mxu_q8avg(ctx, true);
4485         break;
4486     case OPC_MXU_Q8ADD:
4487         gen_mxu_Q8ADD(ctx);
4488         break;
4489     default:
4490         MIPS_INVAL("decode_opc_mxu");
4491         gen_reserved_instruction(ctx);
4492         break;
4493     }
4494 }
4495 
4496 static void decode_opc_mxu__pool02(DisasContext *ctx)
4497 {
4498     uint32_t opcode = extract32(ctx->opcode, 18, 3);
4499 
4500     switch (opcode) {
4501     case OPC_MXU_S32CPS:
4502         gen_mxu_S32CPS(ctx);
4503         break;
4504     case OPC_MXU_D16CPS:
4505         gen_mxu_D16CPS(ctx);
4506         break;
4507     case OPC_MXU_Q8ABD:
4508         gen_mxu_Q8ABD(ctx);
4509         break;
4510     case OPC_MXU_Q16SAT:
4511         gen_mxu_Q16SAT(ctx);
4512         break;
4513     default:
4514         MIPS_INVAL("decode_opc_mxu");
4515         gen_reserved_instruction(ctx);
4516         break;
4517     }
4518 }
4519 
4520 static void decode_opc_mxu__pool03(DisasContext *ctx)
4521 {
4522     uint32_t opcode = extract32(ctx->opcode, 24, 2);
4523 
4524     switch (opcode) {
4525     case OPC_MXU_D16MULF:
4526         gen_mxu_d16mul(ctx, true, true);
4527         break;
4528     case OPC_MXU_D16MULE:
4529         gen_mxu_d16mul(ctx, true, false);
4530         break;
4531     default:
4532         MIPS_INVAL("decode_opc_mxu");
4533         gen_reserved_instruction(ctx);
4534         break;
4535     }
4536 }
4537 
4538 static void decode_opc_mxu__pool04(DisasContext *ctx)
4539 {
4540     uint32_t reversed = extract32(ctx->opcode, 20, 1);
4541     uint32_t opcode = extract32(ctx->opcode, 10, 4);
4542 
4543     /* Don't care about opcode bits as their meaning is unknown yet */
4544     switch (opcode) {
4545     default:
4546         gen_mxu_s32ldxx(ctx, reversed, false);
4547         break;
4548     }
4549 }
4550 
4551 static void decode_opc_mxu__pool05(DisasContext *ctx)
4552 {
4553     uint32_t reversed = extract32(ctx->opcode, 20, 1);
4554     uint32_t opcode = extract32(ctx->opcode, 10, 4);
4555 
4556     /* Don't care about opcode bits as their meaning is unknown yet */
4557     switch (opcode) {
4558     default:
4559         gen_mxu_s32stxx(ctx, reversed, false);
4560         break;
4561     }
4562 }
4563 
4564 static void decode_opc_mxu__pool06(DisasContext *ctx)
4565 {
4566     uint32_t opcode = extract32(ctx->opcode, 10, 4);
4567     uint32_t strd2  = extract32(ctx->opcode, 14, 2);
4568 
4569     switch (opcode) {
4570     case OPC_MXU_S32LDST:
4571     case OPC_MXU_S32LDSTR:
4572         if (strd2 <= 2) {
4573             gen_mxu_s32ldxvx(ctx, opcode, false, strd2);
4574             break;
4575         }
4576         /* fallthrough */
4577     default:
4578         MIPS_INVAL("decode_opc_mxu");
4579         gen_reserved_instruction(ctx);
4580         break;
4581     }
4582 }
4583 
4584 static void decode_opc_mxu__pool07(DisasContext *ctx)
4585 {
4586     uint32_t opcode = extract32(ctx->opcode, 10, 4);
4587     uint32_t strd2  = extract32(ctx->opcode, 14, 2);
4588 
4589     switch (opcode) {
4590     case OPC_MXU_S32LDST:
4591     case OPC_MXU_S32LDSTR:
4592         if (strd2 <= 2) {
4593             gen_mxu_s32stxvx(ctx, opcode, false, strd2);
4594             break;
4595         }
4596         /* fallthrough */
4597     default:
4598         MIPS_INVAL("decode_opc_mxu");
4599         gen_reserved_instruction(ctx);
4600         break;
4601     }
4602 }
4603 
4604 static void decode_opc_mxu__pool08(DisasContext *ctx)
4605 {
4606     uint32_t reversed = extract32(ctx->opcode, 20, 1);
4607     uint32_t opcode = extract32(ctx->opcode, 10, 4);
4608 
4609     /* Don't care about opcode bits as their meaning is unknown yet */
4610     switch (opcode) {
4611     default:
4612         gen_mxu_s32ldxx(ctx, reversed, true);
4613         break;
4614     }
4615 }
4616 
4617 static void decode_opc_mxu__pool09(DisasContext *ctx)
4618 {
4619     uint32_t reversed = extract32(ctx->opcode, 20, 1);
4620     uint32_t opcode = extract32(ctx->opcode, 10, 4);
4621 
4622     /* Don't care about opcode bits as their meaning is unknown yet */
4623     switch (opcode) {
4624     default:
4625         gen_mxu_s32stxx(ctx, reversed, true);
4626         break;
4627     }
4628 }
4629 
4630 static void decode_opc_mxu__pool10(DisasContext *ctx)
4631 {
4632     uint32_t opcode = extract32(ctx->opcode, 10, 4);
4633     uint32_t strd2  = extract32(ctx->opcode, 14, 2);
4634 
4635     switch (opcode) {
4636     case OPC_MXU_S32LDST:
4637     case OPC_MXU_S32LDSTR:
4638         if (strd2 <= 2) {
4639             gen_mxu_s32ldxvx(ctx, opcode, true, strd2);
4640             break;
4641         }
4642         /* fallthrough */
4643     default:
4644         MIPS_INVAL("decode_opc_mxu");
4645         gen_reserved_instruction(ctx);
4646         break;
4647     }
4648 }
4649 
4650 static void decode_opc_mxu__pool11(DisasContext *ctx)
4651 {
4652     uint32_t opcode = extract32(ctx->opcode, 10, 4);
4653     uint32_t strd2  = extract32(ctx->opcode, 14, 2);
4654 
4655     switch (opcode) {
4656     case OPC_MXU_S32LDST:
4657     case OPC_MXU_S32LDSTR:
4658         if (strd2 <= 2) {
4659             gen_mxu_s32stxvx(ctx, opcode, true, strd2);
4660             break;
4661         }
4662         /* fallthrough */
4663     default:
4664         MIPS_INVAL("decode_opc_mxu");
4665         gen_reserved_instruction(ctx);
4666         break;
4667     }
4668 }
4669 
4670 static void decode_opc_mxu__pool12(DisasContext *ctx)
4671 {
4672     uint32_t opcode = extract32(ctx->opcode, 22, 2);
4673 
4674     switch (opcode) {
4675     case OPC_MXU_D32ACC:
4676         gen_mxu_d32acc(ctx);
4677         break;
4678     case OPC_MXU_D32ACCM:
4679         gen_mxu_d32accm(ctx);
4680         break;
4681     case OPC_MXU_D32ASUM:
4682         gen_mxu_d32asum(ctx);
4683         break;
4684     default:
4685         MIPS_INVAL("decode_opc_mxu");
4686         gen_reserved_instruction(ctx);
4687         break;
4688     }
4689 }
4690 
4691 static void decode_opc_mxu__pool13(DisasContext *ctx)
4692 {
4693     uint32_t opcode = extract32(ctx->opcode, 22, 2);
4694 
4695     switch (opcode) {
4696     case OPC_MXU_Q16ACC:
4697         gen_mxu_q16acc(ctx);
4698         break;
4699     case OPC_MXU_Q16ACCM:
4700         gen_mxu_q16accm(ctx);
4701         break;
4702     case OPC_MXU_D16ASUM:
4703         gen_mxu_d16asum(ctx);
4704         break;
4705     default:
4706         MIPS_INVAL("decode_opc_mxu");
4707         gen_reserved_instruction(ctx);
4708         break;
4709     }
4710 }
4711 
4712 static void decode_opc_mxu__pool14(DisasContext *ctx)
4713 {
4714     uint32_t opcode = extract32(ctx->opcode, 22, 2);
4715 
4716     switch (opcode) {
4717     case OPC_MXU_Q8ADDE:
4718         gen_mxu_q8adde(ctx, false);
4719         break;
4720     case OPC_MXU_D8SUM:
4721         gen_mxu_d8sum(ctx, false);
4722         break;
4723     case OPC_MXU_D8SUMC:
4724         gen_mxu_d8sum(ctx, true);
4725         break;
4726     default:
4727         MIPS_INVAL("decode_opc_mxu");
4728         gen_reserved_instruction(ctx);
4729         break;
4730     }
4731 }
4732 
4733 static void decode_opc_mxu__pool15(DisasContext *ctx)
4734 {
4735     uint32_t opcode = extract32(ctx->opcode, 14, 2);
4736 
4737     switch (opcode) {
4738     case OPC_MXU_S32MUL:
4739         gen_mxu_s32mul(ctx, false);
4740         break;
4741     case OPC_MXU_S32MULU:
4742         gen_mxu_s32mul(ctx, true);
4743         break;
4744     case OPC_MXU_S32EXTR:
4745         gen_mxu_s32extr(ctx);
4746         break;
4747     case OPC_MXU_S32EXTRV:
4748         gen_mxu_s32extrv(ctx);
4749         break;
4750     default:
4751         MIPS_INVAL("decode_opc_mxu");
4752         gen_reserved_instruction(ctx);
4753         break;
4754     }
4755 }
4756 
4757 static void decode_opc_mxu__pool16(DisasContext *ctx)
4758 {
4759     uint32_t opcode = extract32(ctx->opcode, 18, 3);
4760 
4761     switch (opcode) {
4762     case OPC_MXU_D32SARW:
4763         gen_mxu_d32sarl(ctx, true);
4764         break;
4765     case OPC_MXU_S32ALN:
4766         gen_mxu_S32ALN(ctx);
4767         break;
4768     case OPC_MXU_S32ALNI:
4769         gen_mxu_S32ALNI(ctx);
4770         break;
4771     case OPC_MXU_S32LUI:
4772         gen_mxu_s32lui(ctx);
4773         break;
4774     case OPC_MXU_S32NOR:
4775         gen_mxu_S32NOR(ctx);
4776         break;
4777     case OPC_MXU_S32AND:
4778         gen_mxu_S32AND(ctx);
4779         break;
4780     case OPC_MXU_S32OR:
4781         gen_mxu_S32OR(ctx);
4782         break;
4783     case OPC_MXU_S32XOR:
4784         gen_mxu_S32XOR(ctx);
4785         break;
4786     default:
4787         MIPS_INVAL("decode_opc_mxu");
4788         gen_reserved_instruction(ctx);
4789         break;
4790     }
4791 }
4792 
4793 static void decode_opc_mxu__pool17(DisasContext *ctx)
4794 {
4795     uint32_t opcode = extract32(ctx->opcode, 6, 3);
4796     uint32_t strd2  = extract32(ctx->opcode, 9, 2);
4797 
4798     if (strd2 > 2) {
4799         MIPS_INVAL("decode_opc_mxu");
4800         gen_reserved_instruction(ctx);
4801         return;
4802     }
4803 
4804     switch (opcode) {
4805     case OPC_MXU_LXW:
4806           gen_mxu_lxx(ctx, strd2, MO_TE | MO_UL);
4807           break;
4808     case OPC_MXU_LXB:
4809           gen_mxu_lxx(ctx, strd2, MO_TE | MO_SB);
4810           break;
4811     case OPC_MXU_LXH:
4812           gen_mxu_lxx(ctx, strd2, MO_TE | MO_SW);
4813           break;
4814     case OPC_MXU_LXBU:
4815           gen_mxu_lxx(ctx, strd2, MO_TE | MO_UB);
4816           break;
4817     case OPC_MXU_LXHU:
4818           gen_mxu_lxx(ctx, strd2, MO_TE | MO_UW);
4819           break;
4820     default:
4821         MIPS_INVAL("decode_opc_mxu");
4822         gen_reserved_instruction(ctx);
4823         break;
4824     }
4825 }
4826 
4827 static void decode_opc_mxu__pool18(DisasContext *ctx)
4828 {
4829     uint32_t opcode = extract32(ctx->opcode, 18, 3);
4830 
4831     switch (opcode) {
4832     case OPC_MXU_D32SLLV:
4833         gen_mxu_d32sxxv(ctx, false, false);
4834         break;
4835     case OPC_MXU_D32SLRV:
4836         gen_mxu_d32sxxv(ctx, true, false);
4837         break;
4838     case OPC_MXU_D32SARV:
4839         gen_mxu_d32sxxv(ctx, true, true);
4840         break;
4841     case OPC_MXU_Q16SLLV:
4842         gen_mxu_q16sxxv(ctx, false, false);
4843         break;
4844     case OPC_MXU_Q16SLRV:
4845         gen_mxu_q16sxxv(ctx, true, false);
4846         break;
4847     case OPC_MXU_Q16SARV:
4848         gen_mxu_q16sxxv(ctx, true, true);
4849         break;
4850     default:
4851         MIPS_INVAL("decode_opc_mxu");
4852         gen_reserved_instruction(ctx);
4853         break;
4854     }
4855 }
4856 
4857 static void decode_opc_mxu__pool19(DisasContext *ctx)
4858 {
4859     uint32_t opcode = extract32(ctx->opcode, 22, 4);
4860 
4861     switch (opcode) {
4862     case OPC_MXU_Q8MUL:
4863         gen_mxu_q8mul_mac(ctx, false, false);
4864         break;
4865     case OPC_MXU_Q8MULSU:
4866         gen_mxu_q8mul_mac(ctx, true, false);
4867         break;
4868     default:
4869         MIPS_INVAL("decode_opc_mxu");
4870         gen_reserved_instruction(ctx);
4871         break;
4872     }
4873 }
4874 
4875 static void decode_opc_mxu__pool20(DisasContext *ctx)
4876 {
4877     uint32_t opcode = extract32(ctx->opcode, 18, 3);
4878 
4879     switch (opcode) {
4880     case OPC_MXU_Q8MOVZ:
4881         gen_mxu_q8movzn(ctx, TCG_COND_NE);
4882         break;
4883     case OPC_MXU_Q8MOVN:
4884         gen_mxu_q8movzn(ctx, TCG_COND_EQ);
4885         break;
4886     case OPC_MXU_D16MOVZ:
4887         gen_mxu_d16movzn(ctx, TCG_COND_NE);
4888         break;
4889     case OPC_MXU_D16MOVN:
4890         gen_mxu_d16movzn(ctx, TCG_COND_EQ);
4891         break;
4892     case OPC_MXU_S32MOVZ:
4893         gen_mxu_s32movzn(ctx, TCG_COND_NE);
4894         break;
4895     case OPC_MXU_S32MOVN:
4896         gen_mxu_s32movzn(ctx, TCG_COND_EQ);
4897         break;
4898     default:
4899         MIPS_INVAL("decode_opc_mxu");
4900         gen_reserved_instruction(ctx);
4901         break;
4902     }
4903 }
4904 
4905 static void decode_opc_mxu__pool21(DisasContext *ctx)
4906 {
4907     uint32_t opcode = extract32(ctx->opcode, 22, 2);
4908 
4909     switch (opcode) {
4910     case OPC_MXU_Q8MAC:
4911         gen_mxu_q8mul_mac(ctx, false, true);
4912         break;
4913     case OPC_MXU_Q8MACSU:
4914         gen_mxu_q8mul_mac(ctx, true, true);
4915         break;
4916     default:
4917         MIPS_INVAL("decode_opc_mxu");
4918         gen_reserved_instruction(ctx);
4919         break;
4920     }
4921 }
4922 
4923 
4924 bool decode_ase_mxu(DisasContext *ctx, uint32_t insn)
4925 {
4926     uint32_t opcode = extract32(insn, 0, 6);
4927 
4928     if (opcode == OPC_MXU_S32M2I) {
4929         gen_mxu_s32m2i(ctx);
4930         return true;
4931     }
4932 
4933     if (opcode == OPC_MXU_S32I2M) {
4934         gen_mxu_s32i2m(ctx);
4935         return true;
4936     }
4937 
4938     {
4939         TCGv t_mxu_cr = tcg_temp_new();
4940         TCGLabel *l_exit = gen_new_label();
4941 
4942         gen_load_mxu_cr(t_mxu_cr);
4943         tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN);
4944         tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit);
4945 
4946         switch (opcode) {
4947         case OPC_MXU_S32MADD:
4948         case OPC_MXU_S32MADDU:
4949         case OPC_MXU_S32MSUB:
4950         case OPC_MXU_S32MSUBU:
4951             return decode_opc_mxu_s32madd_sub(ctx);
4952         case OPC_MXU__POOL00:
4953             decode_opc_mxu__pool00(ctx);
4954             break;
4955         case OPC_MXU_D16MUL:
4956             gen_mxu_d16mul(ctx, false, false);
4957             break;
4958         case OPC_MXU_D16MAC:
4959             gen_mxu_d16mac(ctx, false, false);
4960             break;
4961         case OPC_MXU_D16MACF:
4962             gen_mxu_d16mac(ctx, true, true);
4963             break;
4964         case OPC_MXU_D16MADL:
4965             gen_mxu_d16madl(ctx);
4966             break;
4967         case OPC_MXU_S16MAD:
4968             gen_mxu_s16mad(ctx);
4969             break;
4970         case OPC_MXU_Q16ADD:
4971             gen_mxu_q16add(ctx);
4972             break;
4973         case OPC_MXU_D16MACE:
4974             gen_mxu_d16mac(ctx, true, false);
4975             break;
4976         case OPC_MXU__POOL01:
4977             decode_opc_mxu__pool01(ctx);
4978             break;
4979         case OPC_MXU__POOL02:
4980             decode_opc_mxu__pool02(ctx);
4981             break;
4982         case OPC_MXU__POOL03:
4983             decode_opc_mxu__pool03(ctx);
4984             break;
4985         case OPC_MXU__POOL04:
4986             decode_opc_mxu__pool04(ctx);
4987             break;
4988         case OPC_MXU__POOL05:
4989             decode_opc_mxu__pool05(ctx);
4990             break;
4991         case OPC_MXU__POOL06:
4992             decode_opc_mxu__pool06(ctx);
4993             break;
4994         case OPC_MXU__POOL07:
4995             decode_opc_mxu__pool07(ctx);
4996             break;
4997         case OPC_MXU__POOL08:
4998             decode_opc_mxu__pool08(ctx);
4999             break;
5000         case OPC_MXU__POOL09:
5001             decode_opc_mxu__pool09(ctx);
5002             break;
5003         case OPC_MXU__POOL10:
5004             decode_opc_mxu__pool10(ctx);
5005             break;
5006         case OPC_MXU__POOL11:
5007             decode_opc_mxu__pool11(ctx);
5008             break;
5009         case OPC_MXU_D32ADD:
5010             gen_mxu_d32add(ctx);
5011             break;
5012         case OPC_MXU__POOL12:
5013             decode_opc_mxu__pool12(ctx);
5014             break;
5015         case OPC_MXU__POOL13:
5016             decode_opc_mxu__pool13(ctx);
5017             break;
5018         case OPC_MXU__POOL14:
5019             decode_opc_mxu__pool14(ctx);
5020             break;
5021         case OPC_MXU_Q8ACCE:
5022             gen_mxu_q8adde(ctx, true);
5023             break;
5024         case OPC_MXU_S8LDD:
5025             gen_mxu_s8ldd(ctx, false);
5026             break;
5027         case OPC_MXU_S8STD:
5028             gen_mxu_s8std(ctx, false);
5029             break;
5030         case OPC_MXU_S8LDI:
5031             gen_mxu_s8ldd(ctx, true);
5032             break;
5033         case OPC_MXU_S8SDI:
5034             gen_mxu_s8std(ctx, true);
5035             break;
5036         case OPC_MXU__POOL15:
5037             decode_opc_mxu__pool15(ctx);
5038             break;
5039         case OPC_MXU__POOL16:
5040             decode_opc_mxu__pool16(ctx);
5041             break;
5042         case OPC_MXU__POOL17:
5043             decode_opc_mxu__pool17(ctx);
5044             break;
5045         case OPC_MXU_S16LDD:
5046             gen_mxu_s16ldd(ctx, false);
5047             break;
5048         case OPC_MXU_S16STD:
5049             gen_mxu_s16std(ctx, false);
5050             break;
5051         case OPC_MXU_S16LDI:
5052             gen_mxu_s16ldd(ctx, true);
5053             break;
5054         case OPC_MXU_S16SDI:
5055             gen_mxu_s16std(ctx, true);
5056             break;
5057         case OPC_MXU_D32SLL:
5058             gen_mxu_d32sxx(ctx, false, false);
5059             break;
5060         case OPC_MXU_D32SLR:
5061             gen_mxu_d32sxx(ctx, true, false);
5062             break;
5063         case OPC_MXU_D32SARL:
5064             gen_mxu_d32sarl(ctx, false);
5065             break;
5066         case OPC_MXU_D32SAR:
5067             gen_mxu_d32sxx(ctx, true, true);
5068             break;
5069         case OPC_MXU_Q16SLL:
5070             gen_mxu_q16sxx(ctx, false, false);
5071             break;
5072         case OPC_MXU__POOL18:
5073             decode_opc_mxu__pool18(ctx);
5074             break;
5075         case OPC_MXU_Q16SLR:
5076             gen_mxu_q16sxx(ctx, true, false);
5077             break;
5078         case OPC_MXU_Q16SAR:
5079             gen_mxu_q16sxx(ctx, true, true);
5080             break;
5081         case OPC_MXU__POOL19:
5082             decode_opc_mxu__pool19(ctx);
5083             break;
5084         case OPC_MXU__POOL20:
5085             decode_opc_mxu__pool20(ctx);
5086             break;
5087         case OPC_MXU__POOL21:
5088             decode_opc_mxu__pool21(ctx);
5089             break;
5090         case OPC_MXU_Q16SCOP:
5091             gen_mxu_q16scop(ctx);
5092             break;
5093         case OPC_MXU_Q8MADL:
5094             gen_mxu_q8madl(ctx);
5095             break;
5096         case OPC_MXU_S32SFL:
5097             gen_mxu_s32sfl(ctx);
5098             break;
5099         case OPC_MXU_Q8SAD:
5100             gen_mxu_q8sad(ctx);
5101             break;
5102         default:
5103             return false;
5104         }
5105 
5106         gen_set_label(l_exit);
5107     }
5108 
5109     return true;
5110 }
5111