1 /* 2 * Toshiba TX79-specific instructions translation routines 3 * 4 * Copyright (c) 2018 Fredrik Noring 5 * Copyright (c) 2021 Philippe Mathieu-Daudé 6 * 7 * SPDX-License-Identifier: GPL-2.0-or-later 8 */ 9 10 #include "qemu/osdep.h" 11 #include "tcg/tcg-op.h" 12 #include "exec/helper-gen.h" 13 #include "translate.h" 14 15 /* Include the auto-generated decoder. */ 16 #include "decode-tx79.c.inc" 17 18 /* 19 * Overview of the TX79-specific instruction set 20 * ============================================= 21 * 22 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits 23 * are only used by the specific quadword (128-bit) LQ/SQ load/store 24 * instructions and certain multimedia instructions (MMIs). These MMIs 25 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit 26 * or sixteen 8-bit paths. 27 * 28 * Reference: 29 * 30 * The Toshiba TX System RISC TX79 Core Architecture manual, 31 * https://wiki.qemu.org/File:C790.pdf 32 */ 33 34 bool decode_ext_tx79(DisasContext *ctx, uint32_t insn) 35 { 36 if (TARGET_LONG_BITS == 64 && decode_tx79(ctx, insn)) { 37 return true; 38 } 39 return false; 40 } 41 42 /* 43 * Three-Operand Multiply and Multiply-Add (4 instructions) 44 * -------------------------------------------------------- 45 * MADD [rd,] rs, rt Multiply/Add 46 * MADDU [rd,] rs, rt Multiply/Add Unsigned 47 * MULT [rd,] rs, rt Multiply (3-operand) 48 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand) 49 */ 50 51 /* 52 * Multiply Instructions for Pipeline 1 (10 instructions) 53 * ------------------------------------------------------ 54 * MULT1 [rd,] rs, rt Multiply Pipeline 1 55 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1 56 * DIV1 rs, rt Divide Pipeline 1 57 * DIVU1 rs, rt Divide Unsigned Pipeline 1 58 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1 59 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1 60 * MFHI1 rd Move From HI1 Register 61 * MFLO1 rd Move From LO1 Register 62 * MTHI1 rs Move To HI1 Register 63 * MTLO1 rs Move To LO1 Register 64 */ 65 66 static bool trans_MFHI1(DisasContext *ctx, arg_rtype *a) 67 { 68 gen_store_gpr(cpu_HI[1], a->rd); 69 70 return true; 71 } 72 73 static bool trans_MFLO1(DisasContext *ctx, arg_rtype *a) 74 { 75 gen_store_gpr(cpu_LO[1], a->rd); 76 77 return true; 78 } 79 80 static bool trans_MTHI1(DisasContext *ctx, arg_rtype *a) 81 { 82 gen_load_gpr(cpu_HI[1], a->rs); 83 84 return true; 85 } 86 87 static bool trans_MTLO1(DisasContext *ctx, arg_rtype *a) 88 { 89 gen_load_gpr(cpu_LO[1], a->rs); 90 91 return true; 92 } 93 94 /* 95 * Arithmetic (19 instructions) 96 * ---------------------------- 97 * PADDB rd, rs, rt Parallel Add Byte 98 * PSUBB rd, rs, rt Parallel Subtract Byte 99 * PADDH rd, rs, rt Parallel Add Halfword 100 * PSUBH rd, rs, rt Parallel Subtract Halfword 101 * PADDW rd, rs, rt Parallel Add Word 102 * PSUBW rd, rs, rt Parallel Subtract Word 103 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword 104 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte 105 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte 106 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword 107 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword 108 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word 109 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word 110 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte 111 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte 112 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword 113 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword 114 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word 115 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word 116 */ 117 118 static bool trans_parallel_arith(DisasContext *ctx, arg_rtype *a, 119 void (*gen_logic_i64)(TCGv_i64, TCGv_i64, TCGv_i64)) 120 { 121 TCGv_i64 ax, bx; 122 123 if (a->rd == 0) { 124 /* nop */ 125 return true; 126 } 127 128 ax = tcg_temp_new_i64(); 129 bx = tcg_temp_new_i64(); 130 131 /* Lower half */ 132 gen_load_gpr(ax, a->rs); 133 gen_load_gpr(bx, a->rt); 134 gen_logic_i64(cpu_gpr[a->rd], ax, bx); 135 136 /* Upper half */ 137 gen_load_gpr_hi(ax, a->rs); 138 gen_load_gpr_hi(bx, a->rt); 139 gen_logic_i64(cpu_gpr_hi[a->rd], ax, bx); 140 141 tcg_temp_free(bx); 142 tcg_temp_free(ax); 143 144 return true; 145 } 146 147 /* 148 * Min/Max (4 instructions) 149 * ------------------------ 150 * PMAXH rd, rs, rt Parallel Maximum Halfword 151 * PMINH rd, rs, rt Parallel Minimum Halfword 152 * PMAXW rd, rs, rt Parallel Maximum Word 153 * PMINW rd, rs, rt Parallel Minimum Word 154 */ 155 156 /* 157 * Absolute (2 instructions) 158 * ------------------------- 159 * PABSH rd, rt Parallel Absolute Halfword 160 * PABSW rd, rt Parallel Absolute Word 161 */ 162 163 /* 164 * Logical (4 instructions) 165 * ------------------------ 166 * PAND rd, rs, rt Parallel AND 167 * POR rd, rs, rt Parallel OR 168 * PXOR rd, rs, rt Parallel XOR 169 * PNOR rd, rs, rt Parallel NOR 170 */ 171 172 /* Parallel And */ 173 static bool trans_PAND(DisasContext *ctx, arg_rtype *a) 174 { 175 return trans_parallel_arith(ctx, a, tcg_gen_and_i64); 176 } 177 178 /* Parallel Or */ 179 static bool trans_POR(DisasContext *ctx, arg_rtype *a) 180 { 181 return trans_parallel_arith(ctx, a, tcg_gen_or_i64); 182 } 183 184 /* Parallel Exclusive Or */ 185 static bool trans_PXOR(DisasContext *ctx, arg_rtype *a) 186 { 187 return trans_parallel_arith(ctx, a, tcg_gen_xor_i64); 188 } 189 190 /* Parallel Not Or */ 191 static bool trans_PNOR(DisasContext *ctx, arg_rtype *a) 192 { 193 return trans_parallel_arith(ctx, a, tcg_gen_nor_i64); 194 } 195 196 /* 197 * Shift (9 instructions) 198 * ---------------------- 199 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword 200 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword 201 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword 202 * PSLLW rd, rt, sa Parallel Shift Left Logical Word 203 * PSRLW rd, rt, sa Parallel Shift Right Logical Word 204 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word 205 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word 206 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word 207 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word 208 */ 209 210 /* 211 * Compare (6 instructions) 212 * ------------------------ 213 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte 214 * PCEQB rd, rs, rt Parallel Compare for Equal Byte 215 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword 216 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword 217 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word 218 * PCEQW rd, rs, rt Parallel Compare for Equal Word 219 */ 220 221 /* 222 * LZC (1 instruction) 223 * ------------------- 224 * PLZCW rd, rs Parallel Leading Zero or One Count Word 225 */ 226 227 /* 228 * Quadword Load and Store (2 instructions) 229 * ---------------------------------------- 230 * LQ rt, offset(base) Load Quadword 231 * SQ rt, offset(base) Store Quadword 232 */ 233 234 /* 235 * Multiply and Divide (19 instructions) 236 * ------------------------------------- 237 * PMULTW rd, rs, rt Parallel Multiply Word 238 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word 239 * PDIVW rs, rt Parallel Divide Word 240 * PDIVUW rs, rt Parallel Divide Unsigned Word 241 * PMADDW rd, rs, rt Parallel Multiply-Add Word 242 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word 243 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word 244 * PMULTH rd, rs, rt Parallel Multiply Halfword 245 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword 246 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword 247 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword 248 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword 249 * PDIVBW rs, rt Parallel Divide Broadcast Word 250 * PMFHI rd Parallel Move From HI Register 251 * PMFLO rd Parallel Move From LO Register 252 * PMTHI rs Parallel Move To HI Register 253 * PMTLO rs Parallel Move To LO Register 254 * PMFHL rd Parallel Move From HI/LO Register 255 * PMTHL rs Parallel Move To HI/LO Register 256 */ 257 258 /* 259 * Pack/Extend (11 instructions) 260 * ----------------------------- 261 * PPAC5 rd, rt Parallel Pack to 5 bits 262 * PPACB rd, rs, rt Parallel Pack to Byte 263 * PPACH rd, rs, rt Parallel Pack to Halfword 264 * PPACW rd, rs, rt Parallel Pack to Word 265 * PEXT5 rd, rt Parallel Extend Upper from 5 bits 266 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte 267 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte 268 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword 269 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword 270 * PEXTUW rd, rs, rt Parallel Extend Upper from Word 271 * PEXTLW rd, rs, rt Parallel Extend Lower from Word 272 */ 273 274 /* 275 * Others (16 instructions) 276 * ------------------------ 277 * PCPYH rd, rt Parallel Copy Halfword 278 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword 279 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword 280 * PREVH rd, rt Parallel Reverse Halfword 281 * PINTH rd, rs, rt Parallel Interleave Halfword 282 * PINTEH rd, rs, rt Parallel Interleave Even Halfword 283 * PEXEH rd, rt Parallel Exchange Even Halfword 284 * PEXCH rd, rt Parallel Exchange Center Halfword 285 * PEXEW rd, rt Parallel Exchange Even Word 286 * PEXCW rd, rt Parallel Exchange Center Word 287 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable 288 * MFSA rd Move from Shift Amount Register 289 * MTSA rs Move to Shift Amount Register 290 * MTSAB rs, immediate Move Byte Count to Shift Amount Register 291 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register 292 * PROT3W rd, rt Parallel Rotate 3 Words 293 */ 294 295 /* Parallel Copy Halfword */ 296 static bool trans_PCPYH(DisasContext *s, arg_rtype *a) 297 { 298 if (a->rd == 0) { 299 /* nop */ 300 return true; 301 } 302 303 if (a->rt == 0) { 304 tcg_gen_movi_i64(cpu_gpr[a->rd], 0); 305 tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0); 306 return true; 307 } 308 309 tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rt], cpu_gpr[a->rt], 16, 16); 310 tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rd], cpu_gpr[a->rd], 32, 32); 311 tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rt], cpu_gpr_hi[a->rt], 16, 16); 312 tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], 32, 32); 313 314 return true; 315 } 316 317 /* Parallel Copy Lower Doubleword */ 318 static bool trans_PCPYLD(DisasContext *s, arg_rtype *a) 319 { 320 if (a->rd == 0) { 321 /* nop */ 322 return true; 323 } 324 325 if (a->rs == 0) { 326 tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0); 327 } else { 328 tcg_gen_mov_i64(cpu_gpr_hi[a->rd], cpu_gpr[a->rs]); 329 } 330 331 if (a->rt == 0) { 332 tcg_gen_movi_i64(cpu_gpr[a->rd], 0); 333 } else if (a->rd != a->rt) { 334 tcg_gen_mov_i64(cpu_gpr[a->rd], cpu_gpr[a->rt]); 335 } 336 337 return true; 338 } 339 340 /* Parallel Copy Upper Doubleword */ 341 static bool trans_PCPYUD(DisasContext *s, arg_rtype *a) 342 { 343 if (a->rd == 0) { 344 /* nop */ 345 return true; 346 } 347 348 gen_load_gpr_hi(cpu_gpr[a->rd], a->rs); 349 350 if (a->rt == 0) { 351 tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0); 352 } else if (a->rd != a->rt) { 353 tcg_gen_mov_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rt]); 354 } 355 356 return true; 357 } 358