qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

Merge remote-tracking branch 'remotes/amarkovic/tags/mips-queue-aug-2018' into staging

MIPS queue August 2018 v6

# gpg: Signature made Fri 24 Aug 2018 16:52:27 BST
# gpg: using RSA key D4972A8967F75A65
# gpg: Good signature from "Aleksandar Markovic <amarkovic@wavecomp.com>"
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg: There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 8526 FBF1 5DA3 811F 4A01 DD75 D497 2A89 67F7 5A65

* remotes/amarkovic/tags/mips-queue-aug-2018: (45 commits)
target/mips: Add definition of nanoMIPS I7200 CPU
mips_malta: Fix semihosting argument passing for nanoMIPS bare metal
mips_malta: Add setting up GT64120 BARs to the nanoMIPS bootloader
mips_malta: Add basic nanoMIPS boot code for Malta board
elf: Don't check FCR31_NAN2008 bit for nanoMIPS
elf: On elf loading, treat both EM_MIPS and EM_NANOMIPS as legal for MIPS
elf: Relax MIPS' elf_check_arch() to accept EM_NANOMIPS too
elf: Add EM_NANOMIPS value as a valid one for e_machine field
target/mips: Fix ERET/ERETNC behavior related to ADEL exception
target/mips: Add updating BadInstr and BadInstrX for nanoMIPS
target/mips: Add availability control via bit NMS
target/mips: Add emulation of DSP ASE for nanoMIPS - part 6
target/mips: Add emulation of DSP ASE for nanoMIPS - part 5
target/mips: Add emulation of DSP ASE for nanoMIPS - part 4
target/mips: Add emulation of DSP ASE for nanoMIPS - part 3
target/mips: Add emulation of DSP ASE for nanoMIPS - part 2
target/mips: Add emulation of DSP ASE for nanoMIPS - part 1
target/mips: Implement MT ASE support for nanoMIPS
target/mips: Fix pre-nanoMIPS MT ASE instructions availability control
target/mips: Add emulation of nanoMIPS 32-bit branch instructions
...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

+5275 -37
+209 -3
hw/mips/mips_malta.c
··· 599 599 } 600 600 } 601 601 602 + static void write_bootloader_nanomips(uint8_t *base, int64_t run_addr, 603 + int64_t kernel_entry) 604 + { 605 + uint16_t *p; 606 + 607 + /* Small bootloader */ 608 + p = (uint16_t *)base; 609 + 610 + #define NM_HI1(VAL) (((VAL) >> 16) & 0x1f) 611 + #define NM_HI2(VAL) \ 612 + (((VAL) & 0xf000) | (((VAL) >> 19) & 0xffc) | (((VAL) >> 31) & 0x1)) 613 + #define NM_LO(VAL) ((VAL) & 0xfff) 614 + 615 + stw_p(p++, 0x2800); stw_p(p++, 0x001c); 616 + /* bc to_here */ 617 + stw_p(p++, 0x8000); stw_p(p++, 0xc000); 618 + /* nop */ 619 + stw_p(p++, 0x8000); stw_p(p++, 0xc000); 620 + /* nop */ 621 + stw_p(p++, 0x8000); stw_p(p++, 0xc000); 622 + /* nop */ 623 + stw_p(p++, 0x8000); stw_p(p++, 0xc000); 624 + /* nop */ 625 + stw_p(p++, 0x8000); stw_p(p++, 0xc000); 626 + /* nop */ 627 + stw_p(p++, 0x8000); stw_p(p++, 0xc000); 628 + /* nop */ 629 + stw_p(p++, 0x8000); stw_p(p++, 0xc000); 630 + /* nop */ 631 + 632 + /* to_here: */ 633 + if (semihosting_get_argc()) { 634 + /* Preserve a0 content as arguments have been passed */ 635 + stw_p(p++, 0x8000); stw_p(p++, 0xc000); 636 + /* nop */ 637 + } else { 638 + stw_p(p++, 0x0080); stw_p(p++, 0x0002); 639 + /* li a0,2 */ 640 + } 641 + 642 + stw_p(p++, 0xe3a0 | NM_HI1(ENVP_ADDR - 64)); 643 + 644 + stw_p(p++, NM_HI2(ENVP_ADDR - 64)); 645 + /* lui sp,%hi(ENVP_ADDR - 64) */ 646 + 647 + stw_p(p++, 0x83bd); stw_p(p++, NM_LO(ENVP_ADDR - 64)); 648 + /* ori sp,sp,%lo(ENVP_ADDR - 64) */ 649 + 650 + stw_p(p++, 0xe0a0 | NM_HI1(ENVP_ADDR)); 651 + 652 + stw_p(p++, NM_HI2(ENVP_ADDR)); 653 + /* lui a1,%hi(ENVP_ADDR) */ 654 + 655 + stw_p(p++, 0x80a5); stw_p(p++, NM_LO(ENVP_ADDR)); 656 + /* ori a1,a1,%lo(ENVP_ADDR) */ 657 + 658 + stw_p(p++, 0xe0c0 | NM_HI1(ENVP_ADDR + 8)); 659 + 660 + stw_p(p++, NM_HI2(ENVP_ADDR + 8)); 661 + /* lui a2,%hi(ENVP_ADDR + 8) */ 662 + 663 + stw_p(p++, 0x80c6); stw_p(p++, NM_LO(ENVP_ADDR + 8)); 664 + /* ori a2,a2,%lo(ENVP_ADDR + 8) */ 665 + 666 + stw_p(p++, 0xe0e0 | NM_HI1(loaderparams.ram_low_size)); 667 + 668 + stw_p(p++, NM_HI2(loaderparams.ram_low_size)); 669 + /* lui a3,%hi(loaderparams.ram_low_size) */ 670 + 671 + stw_p(p++, 0x80e7); stw_p(p++, NM_LO(loaderparams.ram_low_size)); 672 + /* ori a3,a3,%lo(loaderparams.ram_low_size) */ 673 + 674 + /* 675 + * Load BAR registers as done by YAMON: 676 + * 677 + * - set up PCI0 I/O BARs from 0x18000000 to 0x181fffff 678 + * - set up PCI0 MEM0 at 0x10000000, size 0x8000000 679 + * - set up PCI0 MEM1 at 0x18200000, size 0xbe00000 680 + * 681 + */ 682 + stw_p(p++, 0xe040); stw_p(p++, 0x0681); 683 + /* lui t1, %hi(0xb4000000) */ 684 + 685 + #ifdef TARGET_WORDS_BIGENDIAN 686 + 687 + stw_p(p++, 0xe020); stw_p(p++, 0x0be1); 688 + /* lui t0, %hi(0xdf000000) */ 689 + 690 + /* 0x68 corresponds to GT_ISD (from hw/mips/gt64xxx_pci.c) */ 691 + stw_p(p++, 0x8422); stw_p(p++, 0x9068); 692 + /* sw t0, 0x68(t1) */ 693 + 694 + stw_p(p++, 0xe040); stw_p(p++, 0x077d); 695 + /* lui t1, %hi(0xbbe00000) */ 696 + 697 + stw_p(p++, 0xe020); stw_p(p++, 0x0801); 698 + /* lui t0, %hi(0xc0000000) */ 699 + 700 + /* 0x48 corresponds to GT_PCI0IOLD */ 701 + stw_p(p++, 0x8422); stw_p(p++, 0x9048); 702 + /* sw t0, 0x48(t1) */ 703 + 704 + stw_p(p++, 0xe020); stw_p(p++, 0x0800); 705 + /* lui t0, %hi(0x40000000) */ 706 + 707 + /* 0x50 corresponds to GT_PCI0IOHD */ 708 + stw_p(p++, 0x8422); stw_p(p++, 0x9050); 709 + /* sw t0, 0x50(t1) */ 710 + 711 + stw_p(p++, 0xe020); stw_p(p++, 0x0001); 712 + /* lui t0, %hi(0x80000000) */ 713 + 714 + /* 0x58 corresponds to GT_PCI0M0LD */ 715 + stw_p(p++, 0x8422); stw_p(p++, 0x9058); 716 + /* sw t0, 0x58(t1) */ 717 + 718 + stw_p(p++, 0xe020); stw_p(p++, 0x07e0); 719 + /* lui t0, %hi(0x3f000000) */ 720 + 721 + /* 0x60 corresponds to GT_PCI0M0HD */ 722 + stw_p(p++, 0x8422); stw_p(p++, 0x9060); 723 + /* sw t0, 0x60(t1) */ 724 + 725 + stw_p(p++, 0xe020); stw_p(p++, 0x0821); 726 + /* lui t0, %hi(0xc1000000) */ 727 + 728 + /* 0x80 corresponds to GT_PCI0M1LD */ 729 + stw_p(p++, 0x8422); stw_p(p++, 0x9080); 730 + /* sw t0, 0x80(t1) */ 731 + 732 + stw_p(p++, 0xe020); stw_p(p++, 0x0bc0); 733 + /* lui t0, %hi(0x5e000000) */ 734 + 735 + #else 736 + 737 + stw_p(p++, 0x0020); stw_p(p++, 0x00df); 738 + /* addiu[32] t0, $0, 0xdf */ 739 + 740 + /* 0x68 corresponds to GT_ISD */ 741 + stw_p(p++, 0x8422); stw_p(p++, 0x9068); 742 + /* sw t0, 0x68(t1) */ 743 + 744 + /* Use kseg2 remapped address 0x1be00000 */ 745 + stw_p(p++, 0xe040); stw_p(p++, 0x077d); 746 + /* lui t1, %hi(0xbbe00000) */ 747 + 748 + stw_p(p++, 0x0020); stw_p(p++, 0x00c0); 749 + /* addiu[32] t0, $0, 0xc0 */ 750 + 751 + /* 0x48 corresponds to GT_PCI0IOLD */ 752 + stw_p(p++, 0x8422); stw_p(p++, 0x9048); 753 + /* sw t0, 0x48(t1) */ 754 + 755 + stw_p(p++, 0x0020); stw_p(p++, 0x0040); 756 + /* addiu[32] t0, $0, 0x40 */ 757 + 758 + /* 0x50 corresponds to GT_PCI0IOHD */ 759 + stw_p(p++, 0x8422); stw_p(p++, 0x9050); 760 + /* sw t0, 0x50(t1) */ 761 + 762 + stw_p(p++, 0x0020); stw_p(p++, 0x0080); 763 + /* addiu[32] t0, $0, 0x80 */ 764 + 765 + /* 0x58 corresponds to GT_PCI0M0LD */ 766 + stw_p(p++, 0x8422); stw_p(p++, 0x9058); 767 + /* sw t0, 0x58(t1) */ 768 + 769 + stw_p(p++, 0x0020); stw_p(p++, 0x003f); 770 + /* addiu[32] t0, $0, 0x3f */ 771 + 772 + /* 0x60 corresponds to GT_PCI0M0HD */ 773 + stw_p(p++, 0x8422); stw_p(p++, 0x9060); 774 + /* sw t0, 0x60(t1) */ 775 + 776 + stw_p(p++, 0x0020); stw_p(p++, 0x00c1); 777 + /* addiu[32] t0, $0, 0xc1 */ 778 + 779 + /* 0x80 corresponds to GT_PCI0M1LD */ 780 + stw_p(p++, 0x8422); stw_p(p++, 0x9080); 781 + /* sw t0, 0x80(t1) */ 782 + 783 + stw_p(p++, 0x0020); stw_p(p++, 0x005e); 784 + /* addiu[32] t0, $0, 0x5e */ 785 + 786 + #endif 787 + 788 + /* 0x88 corresponds to GT_PCI0M1HD */ 789 + stw_p(p++, 0x8422); stw_p(p++, 0x9088); 790 + /* sw t0, 0x88(t1) */ 791 + 792 + stw_p(p++, 0xe320 | NM_HI1(kernel_entry)); 793 + 794 + stw_p(p++, NM_HI2(kernel_entry)); 795 + /* lui t9,%hi(kernel_entry) */ 796 + 797 + stw_p(p++, 0x8339); stw_p(p++, NM_LO(kernel_entry)); 798 + /* ori t9,t9,%lo(kernel_entry) */ 799 + 800 + stw_p(p++, 0x4bf9); stw_p(p++, 0x0000); 801 + /* jalrc t8 */ 802 + } 803 + 602 804 /* ROM and pseudo bootloader 603 805 604 806 The following code implements a very very simple bootloader. It first ··· 620 822 a2 - 32-bit address of the environment variables table 621 823 a3 - RAM size in bytes 622 824 */ 623 - 624 825 static void write_bootloader(uint8_t *base, int64_t run_addr, 625 826 int64_t kernel_entry) 626 827 { ··· 1096 1297 loaderparams.initrd_filename = initrd_filename; 1097 1298 kernel_entry = load_kernel(); 1098 1299 1099 - write_bootloader(memory_region_get_ram_ptr(bios), 1100 - bootloader_run_addr, kernel_entry); 1300 + if (!cpu_supports_isa(machine->cpu_type, ISA_NANOMIPS32)) { 1301 + write_bootloader(memory_region_get_ram_ptr(bios), 1302 + bootloader_run_addr, kernel_entry); 1303 + } else { 1304 + write_bootloader_nanomips(memory_region_get_ram_ptr(bios), 1305 + bootloader_run_addr, kernel_entry); 1306 + } 1101 1307 if (kvm_enabled()) { 1102 1308 /* Write the bootloader code @ the end of RAM, 1MB reserved */ 1103 1309 write_bootloader(memory_region_get_ram_ptr(ram_low_preio) +
+2
include/elf.h
··· 143 143 144 144 #define EM_RISCV 243 /* RISC-V */ 145 145 146 + #define EM_NANOMIPS 249 /* Wave Computing nanoMIPS */ 147 + 146 148 /* 147 149 * This is an interim value that we will use until the committee comes 148 150 * up with a final number.
+8
include/hw/elf_ops.h
··· 327 327 } 328 328 } 329 329 break; 330 + case EM_MIPS: 331 + case EM_NANOMIPS: 332 + if ((ehdr.e_machine != EM_MIPS) && 333 + (ehdr.e_machine != EM_NANOMIPS)) { 334 + ret = ELF_LOAD_WRONG_ARCH; 335 + goto fail; 336 + } 337 + break; 330 338 default: 331 339 if (elf_machine != ehdr.e_machine) { 332 340 ret = ELF_LOAD_WRONG_ARCH;
+2
linux-user/elfload.c
··· 853 853 #endif 854 854 #define ELF_ARCH EM_MIPS 855 855 856 + #define elf_check_arch(x) ((x) == EM_MIPS || (x) == EM_NANOMIPS) 857 + 856 858 static inline void init_thread(struct target_pt_regs *regs, 857 859 struct image_info *infop) 858 860 {
+23 -5
linux-user/mips/cpu_loop.c
··· 397 397 target_ulong addr; 398 398 target_ulong page_addr; 399 399 target_ulong val; 400 + uint32_t val_wp = 0; 401 + uint32_t llnewval_wp = 0; 400 402 int flags; 401 403 int segv = 0; 402 404 int reg; 403 405 int d; 406 + int wp; 404 407 405 408 addr = env->lladdr; 406 409 page_addr = addr & TARGET_PAGE_MASK; ··· 412 415 } else { 413 416 reg = env->llreg & 0x1f; 414 417 d = (env->llreg & 0x20) != 0; 415 - if (d) { 416 - segv = get_user_s64(val, addr); 418 + wp = (env->llreg & 0x40) != 0; 419 + if (!wp) { 420 + if (d) { 421 + segv = get_user_s64(val, addr); 422 + } else { 423 + segv = get_user_s32(val, addr); 424 + } 417 425 } else { 418 426 segv = get_user_s32(val, addr); 427 + segv |= get_user_s32(val_wp, addr); 428 + llnewval_wp = env->llnewval_wp; 419 429 } 420 430 if (!segv) { 421 - if (val != env->llval) { 431 + if (val != env->llval && val_wp == llnewval_wp) { 422 432 env->active_tc.gpr[reg] = 0; 423 433 } else { 424 - if (d) { 425 - segv = put_user_u64(env->llnewval, addr); 434 + if (!wp) { 435 + if (d) { 436 + segv = put_user_u64(env->llnewval, addr); 437 + } else { 438 + segv = put_user_u32(env->llnewval, addr); 439 + } 426 440 } else { 427 441 segv = put_user_u32(env->llnewval, addr); 442 + segv |= put_user_u32(env->llnewval_wp, addr + 4); 428 443 } 429 444 if (!segv) { 430 445 env->active_tc.gpr[reg] = 1; ··· 731 746 env->active_tc.PC = regs->cp0_epc & ~(target_ulong)1; 732 747 if (regs->cp0_epc & 1) { 733 748 env->hflags |= MIPS_HFLAG_M16; 749 + } 750 + if (env->insn_flags & ISA_NANOMIPS32) { 751 + return; 734 752 } 735 753 if (((info->elf_flags & EF_MIPS_NAN2008) != 0) != 736 754 ((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) != 0)) {
+2
target/mips/cpu.h
··· 506 506 uint64_t lladdr; 507 507 target_ulong llval; 508 508 target_ulong llnewval; 509 + uint64_t llval_wp; 510 + uint32_t llnewval_wp; 509 511 target_ulong llreg; 510 512 uint64_t CP0_LLAddr_rw_bitmask; 511 513 int CP0_LLAddr_shift;
+16
target/mips/helper.c
··· 682 682 683 683 static inline void set_badinstr_registers(CPUMIPSState *env) 684 684 { 685 + if (env->insn_flags & ISA_NANOMIPS32) { 686 + if (env->CP0_Config3 & (1 << CP0C3_BI)) { 687 + uint32_t instr = (cpu_lduw_code(env, env->active_tc.PC)) << 16; 688 + if ((instr & 0x10000000) == 0) { 689 + instr |= cpu_lduw_code(env, env->active_tc.PC + 2); 690 + } 691 + env->CP0_BadInstr = instr; 692 + 693 + if ((instr & 0xFC000000) == 0x60000000) { 694 + instr = cpu_lduw_code(env, env->active_tc.PC + 4) << 16; 695 + env->CP0_BadInstrX = instr; 696 + } 697 + } 698 + return; 699 + } 700 + 685 701 if (env->hflags & MIPS_HFLAG_M16) { 686 702 /* TODO: add BadInstr support for microMIPS */ 687 703 return;
+2
target/mips/helper.h
··· 40 40 DEF_HELPER_FLAGS_1(dbitswap, TCG_CALL_NO_RWG_SE, tl, tl) 41 41 #endif 42 42 43 + DEF_HELPER_FLAGS_4(rotx, TCG_CALL_NO_RWG_SE, tl, tl, i32, i32, i32) 44 + 43 45 #ifndef CONFIG_USER_ONLY 44 46 /* CP0 helpers */ 45 47 DEF_HELPER_1(mfc0_mvpcontrol, tl, env)
+4
target/mips/mips-defs.h
··· 39 39 #define ISA_MIPS64R5 0x00001000 40 40 #define ISA_MIPS32R6 0x00002000 41 41 #define ISA_MIPS64R6 0x00004000 42 + #define ISA_NANOMIPS32 0x00008000 42 43 43 44 /* MIPS ASEs. */ 44 45 #define ASE_MIPS16 0x00010000 ··· 86 87 /* MIPS Technologies "Release 6" */ 87 88 #define CPU_MIPS32R6 (CPU_MIPS32R5 | ISA_MIPS32R6) 88 89 #define CPU_MIPS64R6 (CPU_MIPS64R5 | CPU_MIPS32R6 | ISA_MIPS64R6) 90 + 91 + /* Wave Computing: "nanoMIPS" */ 92 + #define CPU_NANOMIPS32 (CPU_MIPS32R6 | ISA_NANOMIPS32) 89 93 90 94 /* Strictly follow the architecture standard: 91 95 - Disallow "special" instruction handling for PMON/SPIM.
+97 -1
target/mips/op_helper.c
··· 249 249 return (int32_t)bitswap(rt); 250 250 } 251 251 252 + target_ulong helper_rotx(target_ulong rs, uint32_t shift, uint32_t shiftx, 253 + uint32_t stripe) 254 + { 255 + int i; 256 + uint64_t tmp0 = ((uint64_t)rs) << 32 | ((uint64_t)rs & 0xffffffff); 257 + uint64_t tmp1 = tmp0; 258 + for (i = 0; i <= 46; i++) { 259 + int s; 260 + if (i & 0x8) { 261 + s = shift; 262 + } else { 263 + s = shiftx; 264 + } 265 + 266 + if (stripe != 0 && !(i & 0x4)) { 267 + s = ~s; 268 + } 269 + if (s & 0x10) { 270 + if (tmp0 & (1LL << (i + 16))) { 271 + tmp1 |= 1LL << i; 272 + } else { 273 + tmp1 &= ~(1LL << i); 274 + } 275 + } 276 + } 277 + 278 + uint64_t tmp2 = tmp1; 279 + for (i = 0; i <= 38; i++) { 280 + int s; 281 + if (i & 0x4) { 282 + s = shift; 283 + } else { 284 + s = shiftx; 285 + } 286 + 287 + if (s & 0x8) { 288 + if (tmp1 & (1LL << (i + 8))) { 289 + tmp2 |= 1LL << i; 290 + } else { 291 + tmp2 &= ~(1LL << i); 292 + } 293 + } 294 + } 295 + 296 + uint64_t tmp3 = tmp2; 297 + for (i = 0; i <= 34; i++) { 298 + int s; 299 + if (i & 0x2) { 300 + s = shift; 301 + } else { 302 + s = shiftx; 303 + } 304 + if (s & 0x4) { 305 + if (tmp2 & (1LL << (i + 4))) { 306 + tmp3 |= 1LL << i; 307 + } else { 308 + tmp3 &= ~(1LL << i); 309 + } 310 + } 311 + } 312 + 313 + uint64_t tmp4 = tmp3; 314 + for (i = 0; i <= 32; i++) { 315 + int s; 316 + if (i & 0x1) { 317 + s = shift; 318 + } else { 319 + s = shiftx; 320 + } 321 + if (s & 0x2) { 322 + if (tmp3 & (1LL << (i + 2))) { 323 + tmp4 |= 1LL << i; 324 + } else { 325 + tmp4 &= ~(1LL << i); 326 + } 327 + } 328 + } 329 + 330 + uint64_t tmp5 = tmp4; 331 + for (i = 0; i <= 31; i++) { 332 + int s; 333 + s = shift; 334 + if (s & 0x1) { 335 + if (tmp4 & (1LL << (i + 1))) { 336 + tmp5 |= 1LL << i; 337 + } else { 338 + tmp5 &= ~(1LL << i); 339 + } 340 + } 341 + } 342 + 343 + return (int64_t)(int32_t)(uint32_t)tmp5; 344 + } 345 + 252 346 #ifndef CONFIG_USER_ONLY 253 347 254 348 static inline hwaddr do_translate_address(CPUMIPSState *env, ··· 2333 2427 void helper_deret(CPUMIPSState *env) 2334 2428 { 2335 2429 debug_pre_eret(env); 2336 - set_pc(env, env->CP0_DEPC); 2337 2430 2338 2431 env->hflags &= ~MIPS_HFLAG_DM; 2339 2432 compute_hflags(env); 2433 + 2434 + set_pc(env, env->CP0_DEPC); 2435 + 2340 2436 debug_post_eret(env); 2341 2437 } 2342 2438 #endif /* !CONFIG_USER_ONLY */
+4871 -28
target/mips/translate.c
··· 1449 1449 uint32_t opcode; 1450 1450 int insn_flags; 1451 1451 int32_t CP0_Config1; 1452 + int32_t CP0_Config3; 1453 + int32_t CP0_Config5; 1452 1454 /* Routine used to access memory */ 1453 1455 int mem_idx; 1454 1456 TCGMemOp default_tcg_memop_mask; ··· 1746 1748 #endif 1747 1749 } 1748 1750 1751 + static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base, 1752 + target_long ofs) 1753 + { 1754 + tcg_gen_addi_tl(ret, base, ofs); 1755 + 1756 + #if defined(TARGET_MIPS64) 1757 + if (ctx->hflags & MIPS_HFLAG_AWRAP) { 1758 + tcg_gen_ext32s_i64(ret, ret); 1759 + } 1760 + #endif 1761 + } 1762 + 1749 1763 /* Addresses computation (translation time) */ 1750 1764 static target_long addr_add(DisasContext *ctx, target_long base, 1751 1765 target_long offset) ··· 1902 1916 } 1903 1917 #endif 1904 1918 1919 + /* 1920 + * This code generates a "reserved instruction" exception if the 1921 + * Config5 XNP bit is set. 1922 + */ 1923 + static inline void check_xnp(DisasContext *ctx) 1924 + { 1925 + if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) { 1926 + generate_exception_end(ctx, EXCP_RI); 1927 + } 1928 + } 1929 + 1930 + /* 1931 + * This code generates a "reserved instruction" exception if the 1932 + * Config3 MT bit is NOT set. 1933 + */ 1934 + static inline void check_mt(DisasContext *ctx) 1935 + { 1936 + if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) { 1937 + generate_exception_end(ctx, EXCP_RI); 1938 + } 1939 + } 1940 + 1941 + #ifndef CONFIG_USER_ONLY 1942 + /* 1943 + * This code generates a "coprocessor unusable" exception if CP0 is not 1944 + * available, and, if that is not the case, generates a "reserved instruction" 1945 + * exception if the Config5 MT bit is NOT set. This is needed for availability 1946 + * control of some of MT ASE instructions. 1947 + */ 1948 + static inline void check_cp0_mt(DisasContext *ctx) 1949 + { 1950 + if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) { 1951 + generate_exception_err(ctx, EXCP_CpU, 0); 1952 + } else { 1953 + if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) { 1954 + generate_exception_err(ctx, EXCP_RI, 0); 1955 + } 1956 + } 1957 + } 1958 + #endif 1959 + 1960 + /* 1961 + * This code generates a "reserved instruction" exception if the 1962 + * Config5 NMS bit is set. 1963 + */ 1964 + static inline void check_nms(DisasContext *ctx) 1965 + { 1966 + if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) { 1967 + generate_exception_end(ctx, EXCP_RI); 1968 + } 1969 + } 1970 + 1971 + 1905 1972 /* Define small wrappers for gen_load_fpr* so that we have a uniform 1906 1973 calling interface for 32 and 64-bit FPRs. No sense in changing 1907 1974 all callers for gen_load_fpr32 when we need the CTX parameter for ··· 2348 2415 tcg_temp_free(t0); 2349 2416 } 2350 2417 2418 + static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset, 2419 + uint32_t reg1, uint32_t reg2) 2420 + { 2421 + TCGv taddr = tcg_temp_new(); 2422 + TCGv_i64 tval = tcg_temp_new_i64(); 2423 + TCGv tmp1 = tcg_temp_new(); 2424 + TCGv tmp2 = tcg_temp_new(); 2425 + 2426 + gen_base_offset_addr(ctx, taddr, base, offset); 2427 + tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx); 2428 + #ifdef TARGET_WORDS_BIGENDIAN 2429 + tcg_gen_extr_i64_tl(tmp2, tmp1, tval); 2430 + #else 2431 + tcg_gen_extr_i64_tl(tmp1, tmp2, tval); 2432 + #endif 2433 + gen_store_gpr(tmp1, reg1); 2434 + tcg_temp_free(tmp1); 2435 + gen_store_gpr(tmp2, reg2); 2436 + tcg_temp_free(tmp2); 2437 + tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp)); 2438 + tcg_temp_free_i64(tval); 2439 + tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr)); 2440 + tcg_temp_free(taddr); 2441 + } 2442 + 2351 2443 /* Store */ 2352 2444 static void gen_st (DisasContext *ctx, uint32_t opc, int rt, 2353 2445 int base, int offset) ··· 2442 2534 } 2443 2535 tcg_temp_free(t1); 2444 2536 tcg_temp_free(t0); 2537 + } 2538 + 2539 + static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset, 2540 + uint32_t reg1, uint32_t reg2) 2541 + { 2542 + TCGv taddr = tcg_temp_local_new(); 2543 + TCGv lladdr = tcg_temp_local_new(); 2544 + TCGv_i64 tval = tcg_temp_new_i64(); 2545 + TCGv_i64 llval = tcg_temp_new_i64(); 2546 + TCGv_i64 val = tcg_temp_new_i64(); 2547 + TCGv tmp1 = tcg_temp_new(); 2548 + TCGv tmp2 = tcg_temp_new(); 2549 + TCGLabel *lab_fail = gen_new_label(); 2550 + TCGLabel *lab_done = gen_new_label(); 2551 + 2552 + gen_base_offset_addr(ctx, taddr, base, offset); 2553 + 2554 + tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr)); 2555 + tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail); 2556 + 2557 + gen_load_gpr(tmp1, reg1); 2558 + gen_load_gpr(tmp2, reg2); 2559 + 2560 + #ifdef TARGET_WORDS_BIGENDIAN 2561 + tcg_gen_concat_tl_i64(tval, tmp2, tmp1); 2562 + #else 2563 + tcg_gen_concat_tl_i64(tval, tmp1, tmp2); 2564 + #endif 2565 + 2566 + tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp)); 2567 + tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval, 2568 + ctx->mem_idx, MO_64); 2569 + if (reg1 != 0) { 2570 + tcg_gen_movi_tl(cpu_gpr[reg1], 1); 2571 + } 2572 + tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done); 2573 + 2574 + gen_set_label(lab_fail); 2575 + 2576 + if (reg1 != 0) { 2577 + tcg_gen_movi_tl(cpu_gpr[reg1], 0); 2578 + } 2579 + gen_set_label(lab_done); 2580 + tcg_gen_movi_tl(lladdr, -1); 2581 + tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr)); 2445 2582 } 2446 2583 2447 2584 /* Load and store */ ··· 4564 4701 tcg_temp_free(t1); 4565 4702 } 4566 4703 4704 + 4705 + /* nanoMIPS Branches */ 4706 + static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc, 4707 + int insn_bytes, 4708 + int rs, int rt, int32_t offset) 4709 + { 4710 + target_ulong btgt = -1; 4711 + int bcond_compute = 0; 4712 + TCGv t0 = tcg_temp_new(); 4713 + TCGv t1 = tcg_temp_new(); 4714 + 4715 + /* Load needed operands */ 4716 + switch (opc) { 4717 + case OPC_BEQ: 4718 + case OPC_BNE: 4719 + /* Compare two registers */ 4720 + if (rs != rt) { 4721 + gen_load_gpr(t0, rs); 4722 + gen_load_gpr(t1, rt); 4723 + bcond_compute = 1; 4724 + } 4725 + btgt = ctx->base.pc_next + insn_bytes + offset; 4726 + break; 4727 + case OPC_BGEZAL: 4728 + /* Compare to zero */ 4729 + if (rs != 0) { 4730 + gen_load_gpr(t0, rs); 4731 + bcond_compute = 1; 4732 + } 4733 + btgt = ctx->base.pc_next + insn_bytes + offset; 4734 + break; 4735 + case OPC_BPOSGE32: 4736 + tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F); 4737 + bcond_compute = 1; 4738 + btgt = ctx->base.pc_next + insn_bytes + offset; 4739 + break; 4740 + case OPC_JR: 4741 + case OPC_JALR: 4742 + /* Jump to register */ 4743 + if (offset != 0 && offset != 16) { 4744 + /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the 4745 + others are reserved. */ 4746 + MIPS_INVAL("jump hint"); 4747 + generate_exception_end(ctx, EXCP_RI); 4748 + goto out; 4749 + } 4750 + gen_load_gpr(btarget, rs); 4751 + break; 4752 + default: 4753 + MIPS_INVAL("branch/jump"); 4754 + generate_exception_end(ctx, EXCP_RI); 4755 + goto out; 4756 + } 4757 + if (bcond_compute == 0) { 4758 + /* No condition to be computed */ 4759 + switch (opc) { 4760 + case OPC_BEQ: /* rx == rx */ 4761 + /* Always take */ 4762 + ctx->hflags |= MIPS_HFLAG_B; 4763 + break; 4764 + case OPC_BGEZAL: /* 0 >= 0 */ 4765 + /* Always take and link */ 4766 + tcg_gen_movi_tl(cpu_gpr[31], 4767 + ctx->base.pc_next + insn_bytes); 4768 + ctx->hflags |= MIPS_HFLAG_B; 4769 + break; 4770 + case OPC_BNE: /* rx != rx */ 4771 + tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8); 4772 + /* Skip the instruction in the delay slot */ 4773 + ctx->base.pc_next += 4; 4774 + goto out; 4775 + case OPC_JR: 4776 + ctx->hflags |= MIPS_HFLAG_BR; 4777 + break; 4778 + case OPC_JALR: 4779 + if (rt > 0) { 4780 + tcg_gen_movi_tl(cpu_gpr[rt], 4781 + ctx->base.pc_next + insn_bytes); 4782 + } 4783 + ctx->hflags |= MIPS_HFLAG_BR; 4784 + break; 4785 + default: 4786 + MIPS_INVAL("branch/jump"); 4787 + generate_exception_end(ctx, EXCP_RI); 4788 + goto out; 4789 + } 4790 + } else { 4791 + switch (opc) { 4792 + case OPC_BEQ: 4793 + tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1); 4794 + goto not_likely; 4795 + case OPC_BNE: 4796 + tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1); 4797 + goto not_likely; 4798 + case OPC_BGEZAL: 4799 + tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0); 4800 + tcg_gen_movi_tl(cpu_gpr[31], 4801 + ctx->base.pc_next + insn_bytes); 4802 + goto not_likely; 4803 + case OPC_BPOSGE32: 4804 + tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32); 4805 + not_likely: 4806 + ctx->hflags |= MIPS_HFLAG_BC; 4807 + break; 4808 + default: 4809 + MIPS_INVAL("conditional branch/jump"); 4810 + generate_exception_end(ctx, EXCP_RI); 4811 + goto out; 4812 + } 4813 + } 4814 + 4815 + ctx->btarget = btgt; 4816 + 4817 + out: 4818 + if (insn_bytes == 2) { 4819 + ctx->hflags |= MIPS_HFLAG_B16; 4820 + } 4821 + tcg_temp_free(t0); 4822 + tcg_temp_free(t1); 4823 + } 4824 + 4825 + 4567 4826 /* special3 bitfield operations */ 4568 4827 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt, 4569 4828 int rs, int lsb, int msb) ··· 4736 4995 return; 4737 4996 } 4738 4997 4739 - static void gen_align(DisasContext *ctx, int opc, int rd, int rs, int rt, 4740 - int bp) 4998 + static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs, 4999 + int rt, int bits) 4741 5000 { 4742 5001 TCGv t0; 4743 5002 if (rd == 0) { ··· 4745 5004 return; 4746 5005 } 4747 5006 t0 = tcg_temp_new(); 4748 - gen_load_gpr(t0, rt); 4749 - if (bp == 0) { 4750 - switch (opc) { 4751 - case OPC_ALIGN: 5007 + if (bits == 0 || bits == wordsz) { 5008 + if (bits == 0) { 5009 + gen_load_gpr(t0, rt); 5010 + } else { 5011 + gen_load_gpr(t0, rs); 5012 + } 5013 + switch (wordsz) { 5014 + case 32: 4752 5015 tcg_gen_ext32s_tl(cpu_gpr[rd], t0); 4753 5016 break; 4754 5017 #if defined(TARGET_MIPS64) 4755 - case OPC_DALIGN: 5018 + case 64: 4756 5019 tcg_gen_mov_tl(cpu_gpr[rd], t0); 4757 5020 break; 4758 5021 #endif 4759 5022 } 4760 5023 } else { 4761 5024 TCGv t1 = tcg_temp_new(); 5025 + gen_load_gpr(t0, rt); 4762 5026 gen_load_gpr(t1, rs); 4763 - switch (opc) { 4764 - case OPC_ALIGN: 5027 + switch (wordsz) { 5028 + case 32: 4765 5029 { 4766 5030 TCGv_i64 t2 = tcg_temp_new_i64(); 4767 5031 tcg_gen_concat_tl_i64(t2, t1, t0); 4768 - tcg_gen_shri_i64(t2, t2, 8 * (4 - bp)); 5032 + tcg_gen_shri_i64(t2, t2, 32 - bits); 4769 5033 gen_move_low32(cpu_gpr[rd], t2); 4770 5034 tcg_temp_free_i64(t2); 4771 5035 } 4772 5036 break; 4773 5037 #if defined(TARGET_MIPS64) 4774 - case OPC_DALIGN: 4775 - tcg_gen_shli_tl(t0, t0, 8 * bp); 4776 - tcg_gen_shri_tl(t1, t1, 8 * (8 - bp)); 5038 + case 64: 5039 + tcg_gen_shli_tl(t0, t0, bits); 5040 + tcg_gen_shri_tl(t1, t1, 64 - bits); 4777 5041 tcg_gen_or_tl(cpu_gpr[rd], t1, t0); 4778 5042 break; 4779 5043 #endif ··· 4782 5046 } 4783 5047 4784 5048 tcg_temp_free(t0); 5049 + } 5050 + 5051 + static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt, 5052 + int bp) 5053 + { 5054 + gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8); 5055 + } 5056 + 5057 + static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt, 5058 + int shift) 5059 + { 5060 + gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift); 4785 5061 } 4786 5062 4787 5063 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt) ··· 8360 8636 opn = "mthc0"; 8361 8637 break; 8362 8638 case OPC_MFTR: 8363 - check_insn(ctx, ASE_MT); 8639 + check_cp0_enabled(ctx); 8364 8640 if (rd == 0) { 8365 8641 /* Treat as NOP. */ 8366 8642 return; ··· 8370 8646 opn = "mftr"; 8371 8647 break; 8372 8648 case OPC_MTTR: 8373 - check_insn(ctx, ASE_MT); 8649 + check_cp0_enabled(ctx); 8374 8650 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1, 8375 8651 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1); 8376 8652 opn = "mttr"; ··· 14276 14552 break; 14277 14553 case ALIGN: 14278 14554 check_insn(ctx, ISA_MIPS32R6); 14279 - gen_align(ctx, OPC_ALIGN, rd, rs, rt, 14280 - extract32(ctx->opcode, 9, 2)); 14555 + gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2)); 14281 14556 break; 14282 14557 case EXT: 14283 14558 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd); ··· 15701 15976 return 2; 15702 15977 } 15703 15978 15979 + /* 15980 + * 15981 + * nanoMIPS opcodes 15982 + * 15983 + */ 15984 + 15985 + /* MAJOR, P16, and P32 pools opcodes */ 15986 + enum { 15987 + NM_P_ADDIU = 0x00, 15988 + NM_ADDIUPC = 0x01, 15989 + NM_MOVE_BALC = 0x02, 15990 + NM_P16_MV = 0x04, 15991 + NM_LW16 = 0x05, 15992 + NM_BC16 = 0x06, 15993 + NM_P16_SR = 0x07, 15994 + 15995 + NM_POOL32A = 0x08, 15996 + NM_P_BAL = 0x0a, 15997 + NM_P16_SHIFT = 0x0c, 15998 + NM_LWSP16 = 0x0d, 15999 + NM_BALC16 = 0x0e, 16000 + NM_P16_4X4 = 0x0f, 16001 + 16002 + NM_P_GP_W = 0x10, 16003 + NM_P_GP_BH = 0x11, 16004 + NM_P_J = 0x12, 16005 + NM_P16C = 0x14, 16006 + NM_LWGP16 = 0x15, 16007 + NM_P16_LB = 0x17, 16008 + 16009 + NM_P48I = 0x18, 16010 + NM_P16_A1 = 0x1c, 16011 + NM_LW4X4 = 0x1d, 16012 + NM_P16_LH = 0x1f, 16013 + 16014 + NM_P_U12 = 0x20, 16015 + NM_P_LS_U12 = 0x21, 16016 + NM_P_BR1 = 0x22, 16017 + NM_P16_A2 = 0x24, 16018 + NM_SW16 = 0x25, 16019 + NM_BEQZC16 = 0x26, 16020 + 16021 + NM_POOL32F = 0x28, 16022 + NM_P_LS_S9 = 0x29, 16023 + NM_P_BR2 = 0x2a, 16024 + 16025 + NM_P16_ADDU = 0x2c, 16026 + NM_SWSP16 = 0x2d, 16027 + NM_BNEZC16 = 0x2e, 16028 + NM_MOVEP = 0x2f, 16029 + 16030 + NM_POOL32S = 0x30, 16031 + NM_P_BRI = 0x32, 16032 + NM_LI16 = 0x34, 16033 + NM_SWGP16 = 0x35, 16034 + NM_P16_BR = 0x36, 16035 + 16036 + NM_P_LUI = 0x38, 16037 + NM_ANDI16 = 0x3c, 16038 + NM_SW4X4 = 0x3d, 16039 + NM_MOVEPREV = 0x3f, 16040 + }; 16041 + 16042 + /* POOL32A instruction pool */ 16043 + enum { 16044 + NM_POOL32A0 = 0x00, 16045 + NM_SPECIAL2 = 0x01, 16046 + NM_COP2_1 = 0x02, 16047 + NM_UDI = 0x03, 16048 + NM_POOL32A5 = 0x05, 16049 + NM_POOL32A7 = 0x07, 16050 + }; 16051 + 16052 + /* P.GP.W instruction pool */ 16053 + enum { 16054 + NM_ADDIUGP_W = 0x00, 16055 + NM_LWGP = 0x02, 16056 + NM_SWGP = 0x03, 16057 + }; 16058 + 16059 + /* P48I instruction pool */ 16060 + enum { 16061 + NM_LI48 = 0x00, 16062 + NM_ADDIU48 = 0x01, 16063 + NM_ADDIUGP48 = 0x02, 16064 + NM_ADDIUPC48 = 0x03, 16065 + NM_LWPC48 = 0x0b, 16066 + NM_SWPC48 = 0x0f, 16067 + }; 16068 + 16069 + /* P.U12 instruction pool */ 16070 + enum { 16071 + NM_ORI = 0x00, 16072 + NM_XORI = 0x01, 16073 + NM_ANDI = 0x02, 16074 + NM_P_SR = 0x03, 16075 + NM_SLTI = 0x04, 16076 + NM_SLTIU = 0x05, 16077 + NM_SEQI = 0x06, 16078 + NM_ADDIUNEG = 0x08, 16079 + NM_P_SHIFT = 0x0c, 16080 + NM_P_ROTX = 0x0d, 16081 + NM_P_INS = 0x0e, 16082 + NM_P_EXT = 0x0f, 16083 + }; 16084 + 16085 + /* POOL32F instruction pool */ 16086 + enum { 16087 + NM_POOL32F_0 = 0x00, 16088 + NM_POOL32F_3 = 0x03, 16089 + NM_POOL32F_5 = 0x05, 16090 + }; 16091 + 16092 + /* POOL32S instruction pool */ 16093 + enum { 16094 + NM_POOL32S_0 = 0x00, 16095 + NM_POOL32S_4 = 0x04, 16096 + }; 16097 + 16098 + /* P.LUI instruction pool */ 16099 + enum { 16100 + NM_LUI = 0x00, 16101 + NM_ALUIPC = 0x01, 16102 + }; 16103 + 16104 + /* P.GP.BH instruction pool */ 16105 + enum { 16106 + NM_LBGP = 0x00, 16107 + NM_SBGP = 0x01, 16108 + NM_LBUGP = 0x02, 16109 + NM_ADDIUGP_B = 0x03, 16110 + NM_P_GP_LH = 0x04, 16111 + NM_P_GP_SH = 0x05, 16112 + NM_P_GP_CP1 = 0x06, 16113 + }; 16114 + 16115 + /* P.LS.U12 instruction pool */ 16116 + enum { 16117 + NM_LB = 0x00, 16118 + NM_SB = 0x01, 16119 + NM_LBU = 0x02, 16120 + NM_P_PREFU12 = 0x03, 16121 + NM_LH = 0x04, 16122 + NM_SH = 0x05, 16123 + NM_LHU = 0x06, 16124 + NM_LWU = 0x07, 16125 + NM_LW = 0x08, 16126 + NM_SW = 0x09, 16127 + NM_LWC1 = 0x0a, 16128 + NM_SWC1 = 0x0b, 16129 + NM_LDC1 = 0x0e, 16130 + NM_SDC1 = 0x0f, 16131 + }; 16132 + 16133 + /* P.LS.S9 instruction pool */ 16134 + enum { 16135 + NM_P_LS_S0 = 0x00, 16136 + NM_P_LS_S1 = 0x01, 16137 + NM_P_LS_E0 = 0x02, 16138 + NM_P_LS_WM = 0x04, 16139 + NM_P_LS_UAWM = 0x05, 16140 + }; 16141 + 16142 + /* P.BAL instruction pool */ 16143 + enum { 16144 + NM_BC = 0x00, 16145 + NM_BALC = 0x01, 16146 + }; 16147 + 16148 + /* P.J instruction pool */ 16149 + enum { 16150 + NM_JALRC = 0x00, 16151 + NM_JALRC_HB = 0x01, 16152 + NM_P_BALRSC = 0x08, 16153 + }; 16154 + 16155 + /* P.BR1 instruction pool */ 16156 + enum { 16157 + NM_BEQC = 0x00, 16158 + NM_P_BR3A = 0x01, 16159 + NM_BGEC = 0x02, 16160 + NM_BGEUC = 0x03, 16161 + }; 16162 + 16163 + /* P.BR2 instruction pool */ 16164 + enum { 16165 + NM_BNEC = 0x00, 16166 + NM_BLTC = 0x02, 16167 + NM_BLTUC = 0x03, 16168 + }; 16169 + 16170 + /* P.BRI instruction pool */ 16171 + enum { 16172 + NM_BEQIC = 0x00, 16173 + NM_BBEQZC = 0x01, 16174 + NM_BGEIC = 0x02, 16175 + NM_BGEIUC = 0x03, 16176 + NM_BNEIC = 0x04, 16177 + NM_BBNEZC = 0x05, 16178 + NM_BLTIC = 0x06, 16179 + NM_BLTIUC = 0x07, 16180 + }; 16181 + 16182 + /* P16.SHIFT instruction pool */ 16183 + enum { 16184 + NM_SLL16 = 0x00, 16185 + NM_SRL16 = 0x01, 16186 + }; 16187 + 16188 + /* POOL16C instruction pool */ 16189 + enum { 16190 + NM_POOL16C_0 = 0x00, 16191 + NM_LWXS16 = 0x01, 16192 + }; 16193 + 16194 + /* P16.A1 instruction pool */ 16195 + enum { 16196 + NM_ADDIUR1SP = 0x01, 16197 + }; 16198 + 16199 + /* P16.A2 instruction pool */ 16200 + enum { 16201 + NM_ADDIUR2 = 0x00, 16202 + NM_P_ADDIURS5 = 0x01, 16203 + }; 16204 + 16205 + /* P16.ADDU instruction pool */ 16206 + enum { 16207 + NM_ADDU16 = 0x00, 16208 + NM_SUBU16 = 0x01, 16209 + }; 16210 + 16211 + /* P16.SR instruction pool */ 16212 + enum { 16213 + NM_SAVE16 = 0x00, 16214 + NM_RESTORE_JRC16 = 0x01, 16215 + }; 16216 + 16217 + /* P16.4X4 instruction pool */ 16218 + enum { 16219 + NM_ADDU4X4 = 0x00, 16220 + NM_MUL4X4 = 0x01, 16221 + }; 16222 + 16223 + /* P16.LB instruction pool */ 16224 + enum { 16225 + NM_LB16 = 0x00, 16226 + NM_SB16 = 0x01, 16227 + NM_LBU16 = 0x02, 16228 + }; 16229 + 16230 + /* P16.LH instruction pool */ 16231 + enum { 16232 + NM_LH16 = 0x00, 16233 + NM_SH16 = 0x01, 16234 + NM_LHU16 = 0x02, 16235 + }; 16236 + 16237 + /* P.RI instruction pool */ 16238 + enum { 16239 + NM_SIGRIE = 0x00, 16240 + NM_P_SYSCALL = 0x01, 16241 + NM_BREAK = 0x02, 16242 + NM_SDBBP = 0x03, 16243 + }; 16244 + 16245 + /* POOL32A0 instruction pool */ 16246 + enum { 16247 + NM_P_TRAP = 0x00, 16248 + NM_SEB = 0x01, 16249 + NM_SLLV = 0x02, 16250 + NM_MUL = 0x03, 16251 + NM_MFC0 = 0x06, 16252 + NM_MFHC0 = 0x07, 16253 + NM_SEH = 0x09, 16254 + NM_SRLV = 0x0a, 16255 + NM_MUH = 0x0b, 16256 + NM_MTC0 = 0x0e, 16257 + NM_MTHC0 = 0x0f, 16258 + NM_SRAV = 0x12, 16259 + NM_MULU = 0x13, 16260 + NM_ROTRV = 0x1a, 16261 + NM_MUHU = 0x1b, 16262 + NM_ADD = 0x22, 16263 + NM_DIV = 0x23, 16264 + NM_ADDU = 0x2a, 16265 + NM_MOD = 0x2b, 16266 + NM_SUB = 0x32, 16267 + NM_DIVU = 0x33, 16268 + NM_RDHWR = 0x38, 16269 + NM_SUBU = 0x3a, 16270 + NM_MODU = 0x3b, 16271 + NM_P_CMOVE = 0x42, 16272 + NM_FORK = 0x45, 16273 + NM_MFTR = 0x46, 16274 + NM_MFHTR = 0x47, 16275 + NM_AND = 0x4a, 16276 + NM_YIELD = 0x4d, 16277 + NM_MTTR = 0x4e, 16278 + NM_MTHTR = 0x4f, 16279 + NM_OR = 0x52, 16280 + NM_D_E_MT_VPE = 0x56, 16281 + NM_NOR = 0x5a, 16282 + NM_XOR = 0x62, 16283 + NM_SLT = 0x6a, 16284 + NM_P_SLTU = 0x72, 16285 + NM_SOV = 0x7a, 16286 + }; 16287 + 16288 + /* POOL32A5 instruction pool */ 16289 + enum { 16290 + NM_CMP_EQ_PH = 0x00, 16291 + NM_CMP_LT_PH = 0x08, 16292 + NM_CMP_LE_PH = 0x10, 16293 + NM_CMPGU_EQ_QB = 0x18, 16294 + NM_CMPGU_LT_QB = 0x20, 16295 + NM_CMPGU_LE_QB = 0x28, 16296 + NM_CMPGDU_EQ_QB = 0x30, 16297 + NM_CMPGDU_LT_QB = 0x38, 16298 + NM_CMPGDU_LE_QB = 0x40, 16299 + NM_CMPU_EQ_QB = 0x48, 16300 + NM_CMPU_LT_QB = 0x50, 16301 + NM_CMPU_LE_QB = 0x58, 16302 + NM_ADDQ_S_W = 0x60, 16303 + NM_SUBQ_S_W = 0x68, 16304 + NM_ADDSC = 0x70, 16305 + NM_ADDWC = 0x78, 16306 + 16307 + NM_ADDQ_S_PH = 0x01, 16308 + NM_ADDQH_R_PH = 0x09, 16309 + NM_ADDQH_R_W = 0x11, 16310 + NM_ADDU_S_QB = 0x19, 16311 + NM_ADDU_S_PH = 0x21, 16312 + NM_ADDUH_R_QB = 0x29, 16313 + NM_SHRAV_R_PH = 0x31, 16314 + NM_SHRAV_R_QB = 0x39, 16315 + NM_SUBQ_S_PH = 0x41, 16316 + NM_SUBQH_R_PH = 0x49, 16317 + NM_SUBQH_R_W = 0x51, 16318 + NM_SUBU_S_QB = 0x59, 16319 + NM_SUBU_S_PH = 0x61, 16320 + NM_SUBUH_R_QB = 0x69, 16321 + NM_SHLLV_S_PH = 0x71, 16322 + NM_PRECR_SRA_R_PH_W = 0x79, 16323 + 16324 + NM_MULEU_S_PH_QBL = 0x12, 16325 + NM_MULEU_S_PH_QBR = 0x1a, 16326 + NM_MULQ_RS_PH = 0x22, 16327 + NM_MULQ_S_PH = 0x2a, 16328 + NM_MULQ_RS_W = 0x32, 16329 + NM_MULQ_S_W = 0x3a, 16330 + NM_APPEND = 0x42, 16331 + NM_MODSUB = 0x52, 16332 + NM_SHRAV_R_W = 0x5a, 16333 + NM_SHRLV_PH = 0x62, 16334 + NM_SHRLV_QB = 0x6a, 16335 + NM_SHLLV_QB = 0x72, 16336 + NM_SHLLV_S_W = 0x7a, 16337 + 16338 + NM_SHILO = 0x03, 16339 + 16340 + NM_MULEQ_S_W_PHL = 0x04, 16341 + NM_MULEQ_S_W_PHR = 0x0c, 16342 + 16343 + NM_MUL_S_PH = 0x05, 16344 + NM_PRECR_QB_PH = 0x0d, 16345 + NM_PRECRQ_QB_PH = 0x15, 16346 + NM_PRECRQ_PH_W = 0x1d, 16347 + NM_PRECRQ_RS_PH_W = 0x25, 16348 + NM_PRECRQU_S_QB_PH = 0x2d, 16349 + NM_PACKRL_PH = 0x35, 16350 + NM_PICK_QB = 0x3d, 16351 + NM_PICK_PH = 0x45, 16352 + 16353 + NM_SHRA_R_W = 0x5e, 16354 + NM_SHRA_R_PH = 0x66, 16355 + NM_SHLL_S_PH = 0x76, 16356 + NM_SHLL_S_W = 0x7e, 16357 + 16358 + NM_REPL_PH = 0x07 16359 + }; 16360 + 16361 + /* POOL32A7 instruction pool */ 16362 + enum { 16363 + NM_P_LSX = 0x00, 16364 + NM_LSA = 0x01, 16365 + NM_EXTW = 0x03, 16366 + NM_POOL32AXF = 0x07, 16367 + }; 16368 + 16369 + /* P.SR instruction pool */ 16370 + enum { 16371 + NM_PP_SR = 0x00, 16372 + NM_P_SR_F = 0x01, 16373 + }; 16374 + 16375 + /* P.SHIFT instruction pool */ 16376 + enum { 16377 + NM_P_SLL = 0x00, 16378 + NM_SRL = 0x02, 16379 + NM_SRA = 0x04, 16380 + NM_ROTR = 0x06, 16381 + }; 16382 + 16383 + /* P.ROTX instruction pool */ 16384 + enum { 16385 + NM_ROTX = 0x00, 16386 + }; 16387 + 16388 + /* P.INS instruction pool */ 16389 + enum { 16390 + NM_INS = 0x00, 16391 + }; 16392 + 16393 + /* P.EXT instruction pool */ 16394 + enum { 16395 + NM_EXT = 0x00, 16396 + }; 16397 + 16398 + /* POOL32F_0 (fmt) instruction pool */ 16399 + enum { 16400 + NM_RINT_S = 0x04, 16401 + NM_RINT_D = 0x44, 16402 + NM_ADD_S = 0x06, 16403 + NM_SELEQZ_S = 0x07, 16404 + NM_SELEQZ_D = 0x47, 16405 + NM_CLASS_S = 0x0c, 16406 + NM_CLASS_D = 0x4c, 16407 + NM_SUB_S = 0x0e, 16408 + NM_SELNEZ_S = 0x0f, 16409 + NM_SELNEZ_D = 0x4f, 16410 + NM_MUL_S = 0x16, 16411 + NM_SEL_S = 0x17, 16412 + NM_SEL_D = 0x57, 16413 + NM_DIV_S = 0x1e, 16414 + NM_ADD_D = 0x26, 16415 + NM_SUB_D = 0x2e, 16416 + NM_MUL_D = 0x36, 16417 + NM_MADDF_S = 0x37, 16418 + NM_MADDF_D = 0x77, 16419 + NM_DIV_D = 0x3e, 16420 + NM_MSUBF_S = 0x3f, 16421 + NM_MSUBF_D = 0x7f, 16422 + }; 16423 + 16424 + /* POOL32F_3 instruction pool */ 16425 + enum { 16426 + NM_MIN_FMT = 0x00, 16427 + NM_MAX_FMT = 0x01, 16428 + NM_MINA_FMT = 0x04, 16429 + NM_MAXA_FMT = 0x05, 16430 + NM_POOL32FXF = 0x07, 16431 + }; 16432 + 16433 + /* POOL32F_5 instruction pool */ 16434 + enum { 16435 + NM_CMP_CONDN_S = 0x00, 16436 + NM_CMP_CONDN_D = 0x02, 16437 + }; 16438 + 16439 + /* P.GP.LH instruction pool */ 16440 + enum { 16441 + NM_LHGP = 0x00, 16442 + NM_LHUGP = 0x01, 16443 + }; 16444 + 16445 + /* P.GP.SH instruction pool */ 16446 + enum { 16447 + NM_SHGP = 0x00, 16448 + }; 16449 + 16450 + /* P.GP.CP1 instruction pool */ 16451 + enum { 16452 + NM_LWC1GP = 0x00, 16453 + NM_SWC1GP = 0x01, 16454 + NM_LDC1GP = 0x02, 16455 + NM_SDC1GP = 0x03, 16456 + }; 16457 + 16458 + /* P.LS.S0 instruction pool */ 16459 + enum { 16460 + NM_LBS9 = 0x00, 16461 + NM_LHS9 = 0x04, 16462 + NM_LWS9 = 0x08, 16463 + NM_LDS9 = 0x0c, 16464 + 16465 + NM_SBS9 = 0x01, 16466 + NM_SHS9 = 0x05, 16467 + NM_SWS9 = 0x09, 16468 + NM_SDS9 = 0x0d, 16469 + 16470 + NM_LBUS9 = 0x02, 16471 + NM_LHUS9 = 0x06, 16472 + NM_LWC1S9 = 0x0a, 16473 + NM_LDC1S9 = 0x0e, 16474 + 16475 + NM_P_PREFS9 = 0x03, 16476 + NM_LWUS9 = 0x07, 16477 + NM_SWC1S9 = 0x0b, 16478 + NM_SDC1S9 = 0x0f, 16479 + }; 16480 + 16481 + /* P.LS.S1 instruction pool */ 16482 + enum { 16483 + NM_ASET_ACLR = 0x02, 16484 + NM_UALH = 0x04, 16485 + NM_UASH = 0x05, 16486 + NM_CACHE = 0x07, 16487 + NM_P_LL = 0x0a, 16488 + NM_P_SC = 0x0b, 16489 + }; 16490 + 16491 + /* P.LS.WM instruction pool */ 16492 + enum { 16493 + NM_LWM = 0x00, 16494 + NM_SWM = 0x01, 16495 + }; 16496 + 16497 + /* P.LS.UAWM instruction pool */ 16498 + enum { 16499 + NM_UALWM = 0x00, 16500 + NM_UASWM = 0x01, 16501 + }; 16502 + 16503 + /* P.BR3A instruction pool */ 16504 + enum { 16505 + NM_BC1EQZC = 0x00, 16506 + NM_BC1NEZC = 0x01, 16507 + NM_BC2EQZC = 0x02, 16508 + NM_BC2NEZC = 0x03, 16509 + NM_BPOSGE32C = 0x04, 16510 + }; 16511 + 16512 + /* P16.RI instruction pool */ 16513 + enum { 16514 + NM_P16_SYSCALL = 0x01, 16515 + NM_BREAK16 = 0x02, 16516 + NM_SDBBP16 = 0x03, 16517 + }; 16518 + 16519 + /* POOL16C_0 instruction pool */ 16520 + enum { 16521 + NM_POOL16C_00 = 0x00, 16522 + }; 16523 + 16524 + /* P16.JRC instruction pool */ 16525 + enum { 16526 + NM_JRC = 0x00, 16527 + NM_JALRC16 = 0x01, 16528 + }; 16529 + 16530 + /* P.SYSCALL instruction pool */ 16531 + enum { 16532 + NM_SYSCALL = 0x00, 16533 + NM_HYPCALL = 0x01, 16534 + }; 16535 + 16536 + /* P.TRAP instruction pool */ 16537 + enum { 16538 + NM_TEQ = 0x00, 16539 + NM_TNE = 0x01, 16540 + }; 16541 + 16542 + /* P.CMOVE instruction pool */ 16543 + enum { 16544 + NM_MOVZ = 0x00, 16545 + NM_MOVN = 0x01, 16546 + }; 16547 + 16548 + /* POOL32Axf instruction pool */ 16549 + enum { 16550 + NM_POOL32AXF_1 = 0x01, 16551 + NM_POOL32AXF_2 = 0x02, 16552 + NM_POOL32AXF_4 = 0x04, 16553 + NM_POOL32AXF_5 = 0x05, 16554 + NM_POOL32AXF_7 = 0x07, 16555 + }; 16556 + 16557 + /* POOL32Axf_1 instruction pool */ 16558 + enum { 16559 + NM_POOL32AXF_1_0 = 0x00, 16560 + NM_POOL32AXF_1_1 = 0x01, 16561 + NM_POOL32AXF_1_3 = 0x03, 16562 + NM_POOL32AXF_1_4 = 0x04, 16563 + NM_POOL32AXF_1_5 = 0x05, 16564 + NM_POOL32AXF_1_7 = 0x07, 16565 + }; 16566 + 16567 + /* POOL32Axf_2 instruction pool */ 16568 + enum { 16569 + NM_POOL32AXF_2_0_7 = 0x00, 16570 + NM_POOL32AXF_2_8_15 = 0x01, 16571 + NM_POOL32AXF_2_16_23 = 0x02, 16572 + NM_POOL32AXF_2_24_31 = 0x03, 16573 + }; 16574 + 16575 + /* POOL32Axf_7 instruction pool */ 16576 + enum { 16577 + NM_SHRA_R_QB = 0x0, 16578 + NM_SHRL_PH = 0x1, 16579 + NM_REPL_QB = 0x2, 16580 + }; 16581 + 16582 + /* POOL32Axf_1_0 instruction pool */ 16583 + enum { 16584 + NM_MFHI = 0x0, 16585 + NM_MFLO = 0x1, 16586 + NM_MTHI = 0x2, 16587 + NM_MTLO = 0x3, 16588 + }; 16589 + 16590 + /* POOL32Axf_1_1 instruction pool */ 16591 + enum { 16592 + NM_MTHLIP = 0x0, 16593 + NM_SHILOV = 0x1, 16594 + }; 16595 + 16596 + /* POOL32Axf_1_3 instruction pool */ 16597 + enum { 16598 + NM_RDDSP = 0x0, 16599 + NM_WRDSP = 0x1, 16600 + NM_EXTP = 0x2, 16601 + NM_EXTPDP = 0x3, 16602 + }; 16603 + 16604 + /* POOL32Axf_1_4 instruction pool */ 16605 + enum { 16606 + NM_SHLL_QB = 0x0, 16607 + NM_SHRL_QB = 0x1, 16608 + }; 16609 + 16610 + /* POOL32Axf_1_5 instruction pool */ 16611 + enum { 16612 + NM_MAQ_S_W_PHR = 0x0, 16613 + NM_MAQ_S_W_PHL = 0x1, 16614 + NM_MAQ_SA_W_PHR = 0x2, 16615 + NM_MAQ_SA_W_PHL = 0x3, 16616 + }; 16617 + 16618 + /* POOL32Axf_1_7 instruction pool */ 16619 + enum { 16620 + NM_EXTR_W = 0x0, 16621 + NM_EXTR_R_W = 0x1, 16622 + NM_EXTR_RS_W = 0x2, 16623 + NM_EXTR_S_H = 0x3, 16624 + }; 16625 + 16626 + /* POOL32Axf_2_0_7 instruction pool */ 16627 + enum { 16628 + NM_DPA_W_PH = 0x0, 16629 + NM_DPAQ_S_W_PH = 0x1, 16630 + NM_DPS_W_PH = 0x2, 16631 + NM_DPSQ_S_W_PH = 0x3, 16632 + NM_BALIGN = 0x4, 16633 + NM_MADD = 0x5, 16634 + NM_MULT = 0x6, 16635 + NM_EXTRV_W = 0x7, 16636 + }; 16637 + 16638 + /* POOL32Axf_2_8_15 instruction pool */ 16639 + enum { 16640 + NM_DPAX_W_PH = 0x0, 16641 + NM_DPAQ_SA_L_W = 0x1, 16642 + NM_DPSX_W_PH = 0x2, 16643 + NM_DPSQ_SA_L_W = 0x3, 16644 + NM_MADDU = 0x5, 16645 + NM_MULTU = 0x6, 16646 + NM_EXTRV_R_W = 0x7, 16647 + }; 16648 + 16649 + /* POOL32Axf_2_16_23 instruction pool */ 16650 + enum { 16651 + NM_DPAU_H_QBL = 0x0, 16652 + NM_DPAQX_S_W_PH = 0x1, 16653 + NM_DPSU_H_QBL = 0x2, 16654 + NM_DPSQX_S_W_PH = 0x3, 16655 + NM_EXTPV = 0x4, 16656 + NM_MSUB = 0x5, 16657 + NM_MULSA_W_PH = 0x6, 16658 + NM_EXTRV_RS_W = 0x7, 16659 + }; 16660 + 16661 + /* POOL32Axf_2_24_31 instruction pool */ 16662 + enum { 16663 + NM_DPAU_H_QBR = 0x0, 16664 + NM_DPAQX_SA_W_PH = 0x1, 16665 + NM_DPSU_H_QBR = 0x2, 16666 + NM_DPSQX_SA_W_PH = 0x3, 16667 + NM_EXTPDPV = 0x4, 16668 + NM_MSUBU = 0x5, 16669 + NM_MULSAQ_S_W_PH = 0x6, 16670 + NM_EXTRV_S_H = 0x7, 16671 + }; 16672 + 16673 + /* POOL32Axf_{4, 5} instruction pool */ 16674 + enum { 16675 + NM_CLO = 0x25, 16676 + NM_CLZ = 0x2d, 16677 + 16678 + NM_TLBP = 0x01, 16679 + NM_TLBR = 0x09, 16680 + NM_TLBWI = 0x11, 16681 + NM_TLBWR = 0x19, 16682 + NM_TLBINV = 0x03, 16683 + NM_TLBINVF = 0x0b, 16684 + NM_DI = 0x23, 16685 + NM_EI = 0x2b, 16686 + NM_RDPGPR = 0x70, 16687 + NM_WRPGPR = 0x78, 16688 + NM_WAIT = 0x61, 16689 + NM_DERET = 0x71, 16690 + NM_ERETX = 0x79, 16691 + 16692 + /* nanoMIPS DSP instructions */ 16693 + NM_ABSQ_S_QB = 0x00, 16694 + NM_ABSQ_S_PH = 0x08, 16695 + NM_ABSQ_S_W = 0x10, 16696 + NM_PRECEQ_W_PHL = 0x28, 16697 + NM_PRECEQ_W_PHR = 0x30, 16698 + NM_PRECEQU_PH_QBL = 0x38, 16699 + NM_PRECEQU_PH_QBR = 0x48, 16700 + NM_PRECEU_PH_QBL = 0x58, 16701 + NM_PRECEU_PH_QBR = 0x68, 16702 + NM_PRECEQU_PH_QBLA = 0x39, 16703 + NM_PRECEQU_PH_QBRA = 0x49, 16704 + NM_PRECEU_PH_QBLA = 0x59, 16705 + NM_PRECEU_PH_QBRA = 0x69, 16706 + NM_REPLV_PH = 0x01, 16707 + NM_REPLV_QB = 0x09, 16708 + NM_BITREV = 0x18, 16709 + NM_INSV = 0x20, 16710 + NM_RADDU_W_QB = 0x78, 16711 + 16712 + NM_BITSWAP = 0x05, 16713 + NM_WSBH = 0x3d, 16714 + }; 16715 + 16716 + /* PP.SR instruction pool */ 16717 + enum { 16718 + NM_SAVE = 0x00, 16719 + NM_RESTORE = 0x02, 16720 + NM_RESTORE_JRC = 0x03, 16721 + }; 16722 + 16723 + /* P.SR.F instruction pool */ 16724 + enum { 16725 + NM_SAVEF = 0x00, 16726 + NM_RESTOREF = 0x01, 16727 + }; 16728 + 16729 + /* P16.SYSCALL instruction pool */ 16730 + enum { 16731 + NM_SYSCALL16 = 0x00, 16732 + NM_HYPCALL16 = 0x01, 16733 + }; 16734 + 16735 + /* POOL16C_00 instruction pool */ 16736 + enum { 16737 + NM_NOT16 = 0x00, 16738 + NM_XOR16 = 0x01, 16739 + NM_AND16 = 0x02, 16740 + NM_OR16 = 0x03, 16741 + }; 16742 + 16743 + /* PP.LSX and PP.LSXS instruction pool */ 16744 + enum { 16745 + NM_LBX = 0x00, 16746 + NM_LHX = 0x04, 16747 + NM_LWX = 0x08, 16748 + NM_LDX = 0x0c, 16749 + 16750 + NM_SBX = 0x01, 16751 + NM_SHX = 0x05, 16752 + NM_SWX = 0x09, 16753 + NM_SDX = 0x0d, 16754 + 16755 + NM_LBUX = 0x02, 16756 + NM_LHUX = 0x06, 16757 + NM_LWC1X = 0x0a, 16758 + NM_LDC1X = 0x0e, 16759 + 16760 + NM_LWUX = 0x07, 16761 + NM_SWC1X = 0x0b, 16762 + NM_SDC1X = 0x0f, 16763 + 16764 + NM_LHXS = 0x04, 16765 + NM_LWXS = 0x08, 16766 + NM_LDXS = 0x0c, 16767 + 16768 + NM_SHXS = 0x05, 16769 + NM_SWXS = 0x09, 16770 + NM_SDXS = 0x0d, 16771 + 16772 + NM_LHUXS = 0x06, 16773 + NM_LWC1XS = 0x0a, 16774 + NM_LDC1XS = 0x0e, 16775 + 16776 + NM_LWUXS = 0x07, 16777 + NM_SWC1XS = 0x0b, 16778 + NM_SDC1XS = 0x0f, 16779 + }; 16780 + 16781 + /* ERETx instruction pool */ 16782 + enum { 16783 + NM_ERET = 0x00, 16784 + NM_ERETNC = 0x01, 16785 + }; 16786 + 16787 + /* POOL32FxF_{0, 1} insturction pool */ 16788 + enum { 16789 + NM_CFC1 = 0x40, 16790 + NM_CTC1 = 0x60, 16791 + NM_MFC1 = 0x80, 16792 + NM_MTC1 = 0xa0, 16793 + NM_MFHC1 = 0xc0, 16794 + NM_MTHC1 = 0xe0, 16795 + 16796 + NM_CVT_S_PL = 0x84, 16797 + NM_CVT_S_PU = 0xa4, 16798 + 16799 + NM_CVT_L_S = 0x004, 16800 + NM_CVT_L_D = 0x104, 16801 + NM_CVT_W_S = 0x024, 16802 + NM_CVT_W_D = 0x124, 16803 + 16804 + NM_RSQRT_S = 0x008, 16805 + NM_RSQRT_D = 0x108, 16806 + 16807 + NM_SQRT_S = 0x028, 16808 + NM_SQRT_D = 0x128, 16809 + 16810 + NM_RECIP_S = 0x048, 16811 + NM_RECIP_D = 0x148, 16812 + 16813 + NM_FLOOR_L_S = 0x00c, 16814 + NM_FLOOR_L_D = 0x10c, 16815 + 16816 + NM_FLOOR_W_S = 0x02c, 16817 + NM_FLOOR_W_D = 0x12c, 16818 + 16819 + NM_CEIL_L_S = 0x04c, 16820 + NM_CEIL_L_D = 0x14c, 16821 + NM_CEIL_W_S = 0x06c, 16822 + NM_CEIL_W_D = 0x16c, 16823 + NM_TRUNC_L_S = 0x08c, 16824 + NM_TRUNC_L_D = 0x18c, 16825 + NM_TRUNC_W_S = 0x0ac, 16826 + NM_TRUNC_W_D = 0x1ac, 16827 + NM_ROUND_L_S = 0x0cc, 16828 + NM_ROUND_L_D = 0x1cc, 16829 + NM_ROUND_W_S = 0x0ec, 16830 + NM_ROUND_W_D = 0x1ec, 16831 + 16832 + NM_MOV_S = 0x01, 16833 + NM_MOV_D = 0x81, 16834 + NM_ABS_S = 0x0d, 16835 + NM_ABS_D = 0x8d, 16836 + NM_NEG_S = 0x2d, 16837 + NM_NEG_D = 0xad, 16838 + NM_CVT_D_S = 0x04d, 16839 + NM_CVT_D_W = 0x0cd, 16840 + NM_CVT_D_L = 0x14d, 16841 + NM_CVT_S_D = 0x06d, 16842 + NM_CVT_S_W = 0x0ed, 16843 + NM_CVT_S_L = 0x16d, 16844 + }; 16845 + 16846 + /* P.LL instruction pool */ 16847 + enum { 16848 + NM_LL = 0x00, 16849 + NM_LLWP = 0x01, 16850 + }; 16851 + 16852 + /* P.SC instruction pool */ 16853 + enum { 16854 + NM_SC = 0x00, 16855 + NM_SCWP = 0x01, 16856 + }; 16857 + 16858 + /* P.DVP instruction pool */ 16859 + enum { 16860 + NM_DVP = 0x00, 16861 + NM_EVP = 0x01, 16862 + }; 16863 + 16864 + 16865 + /* 16866 + * 16867 + * nanoMIPS decoding engine 16868 + * 16869 + */ 16870 + 16871 + 16872 + /* extraction utilities */ 16873 + 16874 + #define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7) 16875 + #define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7) 16876 + #define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op) 16877 + #define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7) 16878 + #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f) 16879 + #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f) 16880 + 16881 + /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */ 16882 + static inline int decode_gpr_gpr3(int r) 16883 + { 16884 + static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 }; 16885 + 16886 + return map[r & 0x7]; 16887 + } 16888 + 16889 + /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */ 16890 + static inline int decode_gpr_gpr3_src_store(int r) 16891 + { 16892 + static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 }; 16893 + 16894 + return map[r & 0x7]; 16895 + } 16896 + 16897 + /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */ 16898 + static inline int decode_gpr_gpr4(int r) 16899 + { 16900 + static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7, 16901 + 16, 17, 18, 19, 20, 21, 22, 23 }; 16902 + 16903 + return map[r & 0xf]; 16904 + } 16905 + 16906 + /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */ 16907 + static inline int decode_gpr_gpr4_zero(int r) 16908 + { 16909 + static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7, 16910 + 16, 17, 18, 19, 20, 21, 22, 23 }; 16911 + 16912 + return map[r & 0xf]; 16913 + } 16914 + 16915 + 16916 + /* extraction utilities */ 16917 + 16918 + #define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7) 16919 + #define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7) 16920 + #define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op) 16921 + #define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7) 16922 + #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f) 16923 + #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f) 16924 + 16925 + 16926 + static void gen_adjust_sp(DisasContext *ctx, int u) 16927 + { 16928 + gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u); 16929 + } 16930 + 16931 + static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count, 16932 + uint8_t gp, uint16_t u) 16933 + { 16934 + int counter = 0; 16935 + TCGv va = tcg_temp_new(); 16936 + TCGv t0 = tcg_temp_new(); 16937 + 16938 + while (counter != count) { 16939 + bool use_gp = gp && (counter == count - 1); 16940 + int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f); 16941 + int this_offset = -((counter + 1) << 2); 16942 + gen_base_offset_addr(ctx, va, 29, this_offset); 16943 + gen_load_gpr(t0, this_rt); 16944 + tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx, 16945 + (MO_TEUL | ctx->default_tcg_memop_mask)); 16946 + counter++; 16947 + } 16948 + 16949 + /* adjust stack pointer */ 16950 + gen_adjust_sp(ctx, -u); 16951 + 16952 + tcg_temp_free(t0); 16953 + tcg_temp_free(va); 16954 + } 16955 + 16956 + static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count, 16957 + uint8_t gp, uint16_t u) 16958 + { 16959 + int counter = 0; 16960 + TCGv va = tcg_temp_new(); 16961 + TCGv t0 = tcg_temp_new(); 16962 + 16963 + while (counter != count) { 16964 + bool use_gp = gp && (counter == count - 1); 16965 + int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f); 16966 + int this_offset = u - ((counter + 1) << 2); 16967 + gen_base_offset_addr(ctx, va, 29, this_offset); 16968 + tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL | 16969 + ctx->default_tcg_memop_mask); 16970 + tcg_gen_ext32s_tl(t0, t0); 16971 + gen_store_gpr(t0, this_rt); 16972 + counter++; 16973 + } 16974 + 16975 + /* adjust stack pointer */ 16976 + gen_adjust_sp(ctx, u); 16977 + 16978 + tcg_temp_free(t0); 16979 + tcg_temp_free(va); 16980 + } 16981 + 16982 + static void gen_pool16c_nanomips_insn(DisasContext *ctx) 16983 + { 16984 + int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode)); 16985 + int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode)); 16986 + 16987 + switch (extract32(ctx->opcode, 2, 2)) { 16988 + case NM_NOT16: 16989 + gen_logic(ctx, OPC_NOR, rt, rs, 0); 16990 + break; 16991 + case NM_AND16: 16992 + gen_logic(ctx, OPC_AND, rt, rt, rs); 16993 + break; 16994 + case NM_XOR16: 16995 + gen_logic(ctx, OPC_XOR, rt, rt, rs); 16996 + break; 16997 + case NM_OR16: 16998 + gen_logic(ctx, OPC_OR, rt, rt, rs); 16999 + break; 17000 + } 17001 + } 17002 + 17003 + static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx) 17004 + { 17005 + int rt = extract32(ctx->opcode, 21, 5); 17006 + int rs = extract32(ctx->opcode, 16, 5); 17007 + int rd = extract32(ctx->opcode, 11, 5); 17008 + 17009 + switch (extract32(ctx->opcode, 3, 7)) { 17010 + case NM_P_TRAP: 17011 + switch (extract32(ctx->opcode, 10, 1)) { 17012 + case NM_TEQ: 17013 + check_nms(ctx); 17014 + gen_trap(ctx, OPC_TEQ, rs, rt, -1); 17015 + break; 17016 + case NM_TNE: 17017 + check_nms(ctx); 17018 + gen_trap(ctx, OPC_TNE, rs, rt, -1); 17019 + break; 17020 + } 17021 + break; 17022 + case NM_RDHWR: 17023 + check_nms(ctx); 17024 + gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3)); 17025 + break; 17026 + case NM_SEB: 17027 + check_nms(ctx); 17028 + gen_bshfl(ctx, OPC_SEB, rs, rt); 17029 + break; 17030 + case NM_SEH: 17031 + gen_bshfl(ctx, OPC_SEH, rs, rt); 17032 + break; 17033 + case NM_SLLV: 17034 + gen_shift(ctx, OPC_SLLV, rd, rt, rs); 17035 + break; 17036 + case NM_SRLV: 17037 + gen_shift(ctx, OPC_SRLV, rd, rt, rs); 17038 + break; 17039 + case NM_SRAV: 17040 + gen_shift(ctx, OPC_SRAV, rd, rt, rs); 17041 + break; 17042 + case NM_ROTRV: 17043 + gen_shift(ctx, OPC_ROTRV, rd, rt, rs); 17044 + break; 17045 + case NM_ADD: 17046 + gen_arith(ctx, OPC_ADD, rd, rs, rt); 17047 + break; 17048 + case NM_ADDU: 17049 + gen_arith(ctx, OPC_ADDU, rd, rs, rt); 17050 + break; 17051 + case NM_SUB: 17052 + check_nms(ctx); 17053 + gen_arith(ctx, OPC_SUB, rd, rs, rt); 17054 + break; 17055 + case NM_SUBU: 17056 + gen_arith(ctx, OPC_SUBU, rd, rs, rt); 17057 + break; 17058 + case NM_P_CMOVE: 17059 + switch (extract32(ctx->opcode, 10, 1)) { 17060 + case NM_MOVZ: 17061 + gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt); 17062 + break; 17063 + case NM_MOVN: 17064 + gen_cond_move(ctx, OPC_MOVN, rd, rs, rt); 17065 + break; 17066 + } 17067 + break; 17068 + case NM_AND: 17069 + gen_logic(ctx, OPC_AND, rd, rs, rt); 17070 + break; 17071 + case NM_OR: 17072 + gen_logic(ctx, OPC_OR, rd, rs, rt); 17073 + break; 17074 + case NM_NOR: 17075 + gen_logic(ctx, OPC_NOR, rd, rs, rt); 17076 + break; 17077 + case NM_XOR: 17078 + gen_logic(ctx, OPC_XOR, rd, rs, rt); 17079 + break; 17080 + case NM_SLT: 17081 + gen_slt(ctx, OPC_SLT, rd, rs, rt); 17082 + break; 17083 + case NM_P_SLTU: 17084 + if (rd == 0) { 17085 + /* P_DVP */ 17086 + #ifndef CONFIG_USER_ONLY 17087 + TCGv t0 = tcg_temp_new(); 17088 + switch (extract32(ctx->opcode, 10, 1)) { 17089 + case NM_DVP: 17090 + if (ctx->vp) { 17091 + check_cp0_enabled(ctx); 17092 + gen_helper_dvp(t0, cpu_env); 17093 + gen_store_gpr(t0, rt); 17094 + } 17095 + break; 17096 + case NM_EVP: 17097 + if (ctx->vp) { 17098 + check_cp0_enabled(ctx); 17099 + gen_helper_evp(t0, cpu_env); 17100 + gen_store_gpr(t0, rt); 17101 + } 17102 + break; 17103 + } 17104 + tcg_temp_free(t0); 17105 + #endif 17106 + } else { 17107 + gen_slt(ctx, OPC_SLTU, rd, rs, rt); 17108 + } 17109 + break; 17110 + case NM_SOV: 17111 + { 17112 + TCGv t0 = tcg_temp_new(); 17113 + TCGv t1 = tcg_temp_new(); 17114 + TCGv t2 = tcg_temp_new(); 17115 + 17116 + gen_load_gpr(t1, rs); 17117 + gen_load_gpr(t2, rt); 17118 + tcg_gen_add_tl(t0, t1, t2); 17119 + tcg_gen_ext32s_tl(t0, t0); 17120 + tcg_gen_xor_tl(t1, t1, t2); 17121 + tcg_gen_xor_tl(t2, t0, t2); 17122 + tcg_gen_andc_tl(t1, t2, t1); 17123 + 17124 + /* operands of same sign, result different sign */ 17125 + tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0); 17126 + gen_store_gpr(t0, rd); 17127 + 17128 + tcg_temp_free(t0); 17129 + tcg_temp_free(t1); 17130 + tcg_temp_free(t2); 17131 + } 17132 + break; 17133 + case NM_MUL: 17134 + gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt); 17135 + break; 17136 + case NM_MUH: 17137 + gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt); 17138 + break; 17139 + case NM_MULU: 17140 + gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt); 17141 + break; 17142 + case NM_MUHU: 17143 + gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt); 17144 + break; 17145 + case NM_DIV: 17146 + gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt); 17147 + break; 17148 + case NM_MOD: 17149 + gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt); 17150 + break; 17151 + case NM_DIVU: 17152 + gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt); 17153 + break; 17154 + case NM_MODU: 17155 + gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt); 17156 + break; 17157 + #ifndef CONFIG_USER_ONLY 17158 + case NM_MFC0: 17159 + check_cp0_enabled(ctx); 17160 + if (rt == 0) { 17161 + /* Treat as NOP. */ 17162 + break; 17163 + } 17164 + gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3)); 17165 + break; 17166 + case NM_MTC0: 17167 + check_cp0_enabled(ctx); 17168 + { 17169 + TCGv t0 = tcg_temp_new(); 17170 + 17171 + gen_load_gpr(t0, rt); 17172 + gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3)); 17173 + tcg_temp_free(t0); 17174 + } 17175 + break; 17176 + case NM_D_E_MT_VPE: 17177 + { 17178 + uint8_t sc = extract32(ctx->opcode, 10, 1); 17179 + TCGv t0 = tcg_temp_new(); 17180 + 17181 + switch (sc) { 17182 + case 0: 17183 + if (rs == 1) { 17184 + /* DMT */ 17185 + check_cp0_mt(ctx); 17186 + gen_helper_dmt(t0); 17187 + gen_store_gpr(t0, rt); 17188 + } else if (rs == 0) { 17189 + /* DVPE */ 17190 + check_cp0_mt(ctx); 17191 + gen_helper_dvpe(t0, cpu_env); 17192 + gen_store_gpr(t0, rt); 17193 + } else { 17194 + generate_exception_end(ctx, EXCP_RI); 17195 + } 17196 + break; 17197 + case 1: 17198 + if (rs == 1) { 17199 + /* EMT */ 17200 + check_cp0_mt(ctx); 17201 + gen_helper_emt(t0); 17202 + gen_store_gpr(t0, rt); 17203 + } else if (rs == 0) { 17204 + /* EVPE */ 17205 + check_cp0_mt(ctx); 17206 + gen_helper_evpe(t0, cpu_env); 17207 + gen_store_gpr(t0, rt); 17208 + } else { 17209 + generate_exception_end(ctx, EXCP_RI); 17210 + } 17211 + break; 17212 + } 17213 + 17214 + tcg_temp_free(t0); 17215 + } 17216 + break; 17217 + case NM_FORK: 17218 + check_mt(ctx); 17219 + { 17220 + TCGv t0 = tcg_temp_new(); 17221 + TCGv t1 = tcg_temp_new(); 17222 + 17223 + gen_load_gpr(t0, rt); 17224 + gen_load_gpr(t1, rs); 17225 + gen_helper_fork(t0, t1); 17226 + tcg_temp_free(t0); 17227 + tcg_temp_free(t1); 17228 + } 17229 + break; 17230 + case NM_MFTR: 17231 + case NM_MFHTR: 17232 + check_cp0_enabled(ctx); 17233 + if (rd == 0) { 17234 + /* Treat as NOP. */ 17235 + return; 17236 + } 17237 + gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1), 17238 + extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1)); 17239 + break; 17240 + case NM_MTTR: 17241 + case NM_MTHTR: 17242 + check_cp0_enabled(ctx); 17243 + gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1), 17244 + extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1)); 17245 + break; 17246 + case NM_YIELD: 17247 + check_mt(ctx); 17248 + { 17249 + TCGv t0 = tcg_temp_new(); 17250 + 17251 + gen_load_gpr(t0, rs); 17252 + gen_helper_yield(t0, cpu_env, t0); 17253 + gen_store_gpr(t0, rt); 17254 + tcg_temp_free(t0); 17255 + } 17256 + break; 17257 + #endif 17258 + default: 17259 + generate_exception_end(ctx, EXCP_RI); 17260 + break; 17261 + } 17262 + } 17263 + 17264 + /* dsp */ 17265 + static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc, 17266 + int ret, int v1, int v2) 17267 + { 17268 + TCGv_i32 t0; 17269 + TCGv v0_t; 17270 + TCGv v1_t; 17271 + 17272 + t0 = tcg_temp_new_i32(); 17273 + 17274 + v0_t = tcg_temp_new(); 17275 + v1_t = tcg_temp_new(); 17276 + 17277 + tcg_gen_movi_i32(t0, v2 >> 3); 17278 + 17279 + gen_load_gpr(v0_t, ret); 17280 + gen_load_gpr(v1_t, v1); 17281 + 17282 + switch (opc) { 17283 + case NM_MAQ_S_W_PHR: 17284 + check_dsp(ctx); 17285 + gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env); 17286 + break; 17287 + case NM_MAQ_S_W_PHL: 17288 + check_dsp(ctx); 17289 + gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env); 17290 + break; 17291 + case NM_MAQ_SA_W_PHR: 17292 + check_dsp(ctx); 17293 + gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env); 17294 + break; 17295 + case NM_MAQ_SA_W_PHL: 17296 + check_dsp(ctx); 17297 + gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env); 17298 + break; 17299 + default: 17300 + generate_exception_end(ctx, EXCP_RI); 17301 + break; 17302 + } 17303 + 17304 + tcg_temp_free_i32(t0); 17305 + 17306 + tcg_temp_free(v0_t); 17307 + tcg_temp_free(v1_t); 17308 + } 17309 + 17310 + 17311 + static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc, 17312 + int ret, int v1, int v2) 17313 + { 17314 + int16_t imm; 17315 + TCGv t0 = tcg_temp_new(); 17316 + TCGv t1 = tcg_temp_new(); 17317 + TCGv v0_t = tcg_temp_new(); 17318 + 17319 + gen_load_gpr(v0_t, v1); 17320 + 17321 + switch (opc) { 17322 + case NM_POOL32AXF_1_0: 17323 + check_dsp(ctx); 17324 + switch (extract32(ctx->opcode, 12, 2)) { 17325 + case NM_MFHI: 17326 + gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret); 17327 + break; 17328 + case NM_MFLO: 17329 + gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret); 17330 + break; 17331 + case NM_MTHI: 17332 + gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1); 17333 + break; 17334 + case NM_MTLO: 17335 + gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1); 17336 + break; 17337 + } 17338 + break; 17339 + case NM_POOL32AXF_1_1: 17340 + check_dsp(ctx); 17341 + switch (extract32(ctx->opcode, 12, 2)) { 17342 + case NM_MTHLIP: 17343 + tcg_gen_movi_tl(t0, v2); 17344 + gen_helper_mthlip(t0, v0_t, cpu_env); 17345 + break; 17346 + case NM_SHILOV: 17347 + tcg_gen_movi_tl(t0, v2 >> 3); 17348 + gen_helper_shilo(t0, v0_t, cpu_env); 17349 + break; 17350 + default: 17351 + generate_exception_end(ctx, EXCP_RI); 17352 + break; 17353 + } 17354 + break; 17355 + case NM_POOL32AXF_1_3: 17356 + check_dsp(ctx); 17357 + imm = extract32(ctx->opcode, 14, 7); 17358 + switch (extract32(ctx->opcode, 12, 2)) { 17359 + case NM_RDDSP: 17360 + tcg_gen_movi_tl(t0, imm); 17361 + gen_helper_rddsp(t0, t0, cpu_env); 17362 + gen_store_gpr(t0, ret); 17363 + break; 17364 + case NM_WRDSP: 17365 + gen_load_gpr(t0, ret); 17366 + tcg_gen_movi_tl(t1, imm); 17367 + gen_helper_wrdsp(t0, t1, cpu_env); 17368 + break; 17369 + case NM_EXTP: 17370 + tcg_gen_movi_tl(t0, v2 >> 3); 17371 + tcg_gen_movi_tl(t1, v1); 17372 + gen_helper_extp(t0, t0, t1, cpu_env); 17373 + gen_store_gpr(t0, ret); 17374 + break; 17375 + case NM_EXTPDP: 17376 + tcg_gen_movi_tl(t0, v2 >> 3); 17377 + tcg_gen_movi_tl(t1, v1); 17378 + gen_helper_extpdp(t0, t0, t1, cpu_env); 17379 + gen_store_gpr(t0, ret); 17380 + break; 17381 + } 17382 + break; 17383 + case NM_POOL32AXF_1_4: 17384 + check_dsp(ctx); 17385 + tcg_gen_movi_tl(t0, v2 >> 2); 17386 + switch (extract32(ctx->opcode, 12, 1)) { 17387 + case NM_SHLL_QB: 17388 + gen_helper_shll_qb(t0, t0, v0_t, cpu_env); 17389 + gen_store_gpr(t0, ret); 17390 + break; 17391 + case NM_SHRL_QB: 17392 + gen_helper_shrl_qb(t0, t0, v0_t); 17393 + gen_store_gpr(t0, ret); 17394 + break; 17395 + } 17396 + break; 17397 + case NM_POOL32AXF_1_5: 17398 + opc = extract32(ctx->opcode, 12, 2); 17399 + gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2); 17400 + break; 17401 + case NM_POOL32AXF_1_7: 17402 + check_dsp(ctx); 17403 + tcg_gen_movi_tl(t0, v2 >> 3); 17404 + tcg_gen_movi_tl(t1, v1); 17405 + switch (extract32(ctx->opcode, 12, 2)) { 17406 + case NM_EXTR_W: 17407 + gen_helper_extr_w(t0, t0, t1, cpu_env); 17408 + gen_store_gpr(t0, ret); 17409 + break; 17410 + case NM_EXTR_R_W: 17411 + gen_helper_extr_r_w(t0, t0, t1, cpu_env); 17412 + gen_store_gpr(t0, ret); 17413 + break; 17414 + case NM_EXTR_RS_W: 17415 + gen_helper_extr_rs_w(t0, t0, t1, cpu_env); 17416 + gen_store_gpr(t0, ret); 17417 + break; 17418 + case NM_EXTR_S_H: 17419 + gen_helper_extr_s_h(t0, t0, t1, cpu_env); 17420 + gen_store_gpr(t0, ret); 17421 + break; 17422 + } 17423 + break; 17424 + default: 17425 + generate_exception_end(ctx, EXCP_RI); 17426 + break; 17427 + } 17428 + 17429 + tcg_temp_free(t0); 17430 + tcg_temp_free(t1); 17431 + tcg_temp_free(v0_t); 17432 + } 17433 + 17434 + static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc, 17435 + TCGv v0, TCGv v1, int rd) 17436 + { 17437 + TCGv_i32 t0; 17438 + 17439 + t0 = tcg_temp_new_i32(); 17440 + 17441 + tcg_gen_movi_i32(t0, rd >> 3); 17442 + 17443 + switch (opc) { 17444 + case NM_POOL32AXF_2_0_7: 17445 + switch (extract32(ctx->opcode, 9, 3)) { 17446 + case NM_DPA_W_PH: 17447 + check_dspr2(ctx); 17448 + gen_helper_dpa_w_ph(t0, v1, v0, cpu_env); 17449 + break; 17450 + case NM_DPAQ_S_W_PH: 17451 + check_dsp(ctx); 17452 + gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env); 17453 + break; 17454 + case NM_DPS_W_PH: 17455 + check_dspr2(ctx); 17456 + gen_helper_dps_w_ph(t0, v1, v0, cpu_env); 17457 + break; 17458 + case NM_DPSQ_S_W_PH: 17459 + check_dsp(ctx); 17460 + gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env); 17461 + break; 17462 + default: 17463 + generate_exception_end(ctx, EXCP_RI); 17464 + break; 17465 + } 17466 + break; 17467 + case NM_POOL32AXF_2_8_15: 17468 + switch (extract32(ctx->opcode, 9, 3)) { 17469 + case NM_DPAX_W_PH: 17470 + check_dspr2(ctx); 17471 + gen_helper_dpax_w_ph(t0, v0, v1, cpu_env); 17472 + break; 17473 + case NM_DPAQ_SA_L_W: 17474 + check_dsp(ctx); 17475 + gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env); 17476 + break; 17477 + case NM_DPSX_W_PH: 17478 + check_dspr2(ctx); 17479 + gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env); 17480 + break; 17481 + case NM_DPSQ_SA_L_W: 17482 + check_dsp(ctx); 17483 + gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env); 17484 + break; 17485 + default: 17486 + generate_exception_end(ctx, EXCP_RI); 17487 + break; 17488 + } 17489 + break; 17490 + case NM_POOL32AXF_2_16_23: 17491 + switch (extract32(ctx->opcode, 9, 3)) { 17492 + case NM_DPAU_H_QBL: 17493 + check_dsp(ctx); 17494 + gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env); 17495 + break; 17496 + case NM_DPAQX_S_W_PH: 17497 + check_dspr2(ctx); 17498 + gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env); 17499 + break; 17500 + case NM_DPSU_H_QBL: 17501 + check_dsp(ctx); 17502 + gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env); 17503 + break; 17504 + case NM_DPSQX_S_W_PH: 17505 + check_dspr2(ctx); 17506 + gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env); 17507 + break; 17508 + case NM_MULSA_W_PH: 17509 + check_dspr2(ctx); 17510 + gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env); 17511 + break; 17512 + default: 17513 + generate_exception_end(ctx, EXCP_RI); 17514 + break; 17515 + } 17516 + break; 17517 + case NM_POOL32AXF_2_24_31: 17518 + switch (extract32(ctx->opcode, 9, 3)) { 17519 + case NM_DPAU_H_QBR: 17520 + check_dsp(ctx); 17521 + gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env); 17522 + break; 17523 + case NM_DPAQX_SA_W_PH: 17524 + check_dspr2(ctx); 17525 + gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env); 17526 + break; 17527 + case NM_DPSU_H_QBR: 17528 + check_dsp(ctx); 17529 + gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env); 17530 + break; 17531 + case NM_DPSQX_SA_W_PH: 17532 + check_dspr2(ctx); 17533 + gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env); 17534 + break; 17535 + case NM_MULSAQ_S_W_PH: 17536 + check_dsp(ctx); 17537 + gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env); 17538 + break; 17539 + default: 17540 + generate_exception_end(ctx, EXCP_RI); 17541 + break; 17542 + } 17543 + break; 17544 + default: 17545 + generate_exception_end(ctx, EXCP_RI); 17546 + break; 17547 + } 17548 + 17549 + tcg_temp_free_i32(t0); 17550 + } 17551 + 17552 + static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc, 17553 + int rt, int rs, int rd) 17554 + { 17555 + int ret = rt; 17556 + TCGv t0 = tcg_temp_new(); 17557 + TCGv t1 = tcg_temp_new(); 17558 + TCGv v0_t = tcg_temp_new(); 17559 + TCGv v1_t = tcg_temp_new(); 17560 + 17561 + gen_load_gpr(v0_t, rt); 17562 + gen_load_gpr(v1_t, rs); 17563 + 17564 + switch (opc) { 17565 + case NM_POOL32AXF_2_0_7: 17566 + switch (extract32(ctx->opcode, 9, 3)) { 17567 + case NM_DPA_W_PH: 17568 + case NM_DPAQ_S_W_PH: 17569 + case NM_DPS_W_PH: 17570 + case NM_DPSQ_S_W_PH: 17571 + gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd); 17572 + break; 17573 + case NM_BALIGN: 17574 + check_dspr2(ctx); 17575 + if (rt != 0) { 17576 + gen_load_gpr(t0, rs); 17577 + rd &= 3; 17578 + if (rd != 0 && rd != 2) { 17579 + tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd); 17580 + tcg_gen_ext32u_tl(t0, t0); 17581 + tcg_gen_shri_tl(t0, t0, 8 * (4 - rd)); 17582 + tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0); 17583 + } 17584 + tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]); 17585 + } 17586 + break; 17587 + case NM_MADD: 17588 + check_dsp(ctx); 17589 + { 17590 + int acc = extract32(ctx->opcode, 14, 2); 17591 + TCGv_i64 t2 = tcg_temp_new_i64(); 17592 + TCGv_i64 t3 = tcg_temp_new_i64(); 17593 + 17594 + gen_load_gpr(t0, rt); 17595 + gen_load_gpr(t1, rs); 17596 + tcg_gen_ext_tl_i64(t2, t0); 17597 + tcg_gen_ext_tl_i64(t3, t1); 17598 + tcg_gen_mul_i64(t2, t2, t3); 17599 + tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); 17600 + tcg_gen_add_i64(t2, t2, t3); 17601 + tcg_temp_free_i64(t3); 17602 + gen_move_low32(cpu_LO[acc], t2); 17603 + gen_move_high32(cpu_HI[acc], t2); 17604 + tcg_temp_free_i64(t2); 17605 + } 17606 + break; 17607 + case NM_MULT: 17608 + check_dsp(ctx); 17609 + { 17610 + int acc = extract32(ctx->opcode, 14, 2); 17611 + TCGv_i32 t2 = tcg_temp_new_i32(); 17612 + TCGv_i32 t3 = tcg_temp_new_i32(); 17613 + 17614 + gen_load_gpr(t0, rs); 17615 + gen_load_gpr(t1, rt); 17616 + tcg_gen_trunc_tl_i32(t2, t0); 17617 + tcg_gen_trunc_tl_i32(t3, t1); 17618 + tcg_gen_muls2_i32(t2, t3, t2, t3); 17619 + tcg_gen_ext_i32_tl(cpu_LO[acc], t2); 17620 + tcg_gen_ext_i32_tl(cpu_HI[acc], t3); 17621 + tcg_temp_free_i32(t2); 17622 + tcg_temp_free_i32(t3); 17623 + } 17624 + break; 17625 + case NM_EXTRV_W: 17626 + check_dsp(ctx); 17627 + gen_load_gpr(v1_t, rs); 17628 + tcg_gen_movi_tl(t0, rd >> 3); 17629 + gen_helper_extr_w(t0, t0, v1_t, cpu_env); 17630 + gen_store_gpr(t0, ret); 17631 + break; 17632 + } 17633 + break; 17634 + case NM_POOL32AXF_2_8_15: 17635 + switch (extract32(ctx->opcode, 9, 3)) { 17636 + case NM_DPAX_W_PH: 17637 + case NM_DPAQ_SA_L_W: 17638 + case NM_DPSX_W_PH: 17639 + case NM_DPSQ_SA_L_W: 17640 + gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd); 17641 + break; 17642 + case NM_MADDU: 17643 + check_dsp(ctx); 17644 + { 17645 + int acc = extract32(ctx->opcode, 14, 2); 17646 + TCGv_i64 t2 = tcg_temp_new_i64(); 17647 + TCGv_i64 t3 = tcg_temp_new_i64(); 17648 + 17649 + gen_load_gpr(t0, rs); 17650 + gen_load_gpr(t1, rt); 17651 + tcg_gen_ext32u_tl(t0, t0); 17652 + tcg_gen_ext32u_tl(t1, t1); 17653 + tcg_gen_extu_tl_i64(t2, t0); 17654 + tcg_gen_extu_tl_i64(t3, t1); 17655 + tcg_gen_mul_i64(t2, t2, t3); 17656 + tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); 17657 + tcg_gen_add_i64(t2, t2, t3); 17658 + tcg_temp_free_i64(t3); 17659 + gen_move_low32(cpu_LO[acc], t2); 17660 + gen_move_high32(cpu_HI[acc], t2); 17661 + tcg_temp_free_i64(t2); 17662 + } 17663 + break; 17664 + case NM_MULTU: 17665 + check_dsp(ctx); 17666 + { 17667 + int acc = extract32(ctx->opcode, 14, 2); 17668 + TCGv_i32 t2 = tcg_temp_new_i32(); 17669 + TCGv_i32 t3 = tcg_temp_new_i32(); 17670 + 17671 + gen_load_gpr(t0, rs); 17672 + gen_load_gpr(t1, rt); 17673 + tcg_gen_trunc_tl_i32(t2, t0); 17674 + tcg_gen_trunc_tl_i32(t3, t1); 17675 + tcg_gen_mulu2_i32(t2, t3, t2, t3); 17676 + tcg_gen_ext_i32_tl(cpu_LO[acc], t2); 17677 + tcg_gen_ext_i32_tl(cpu_HI[acc], t3); 17678 + tcg_temp_free_i32(t2); 17679 + tcg_temp_free_i32(t3); 17680 + } 17681 + break; 17682 + case NM_EXTRV_R_W: 17683 + check_dsp(ctx); 17684 + tcg_gen_movi_tl(t0, rd >> 3); 17685 + gen_helper_extr_r_w(t0, t0, v1_t, cpu_env); 17686 + gen_store_gpr(t0, ret); 17687 + break; 17688 + default: 17689 + generate_exception_end(ctx, EXCP_RI); 17690 + break; 17691 + } 17692 + break; 17693 + case NM_POOL32AXF_2_16_23: 17694 + switch (extract32(ctx->opcode, 9, 3)) { 17695 + case NM_DPAU_H_QBL: 17696 + case NM_DPAQX_S_W_PH: 17697 + case NM_DPSU_H_QBL: 17698 + case NM_DPSQX_S_W_PH: 17699 + case NM_MULSA_W_PH: 17700 + gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd); 17701 + break; 17702 + case NM_EXTPV: 17703 + check_dsp(ctx); 17704 + tcg_gen_movi_tl(t0, rd >> 3); 17705 + gen_helper_extp(t0, t0, v1_t, cpu_env); 17706 + gen_store_gpr(t0, ret); 17707 + break; 17708 + case NM_MSUB: 17709 + check_dsp(ctx); 17710 + { 17711 + int acc = extract32(ctx->opcode, 14, 2); 17712 + TCGv_i64 t2 = tcg_temp_new_i64(); 17713 + TCGv_i64 t3 = tcg_temp_new_i64(); 17714 + 17715 + gen_load_gpr(t0, rs); 17716 + gen_load_gpr(t1, rt); 17717 + tcg_gen_ext_tl_i64(t2, t0); 17718 + tcg_gen_ext_tl_i64(t3, t1); 17719 + tcg_gen_mul_i64(t2, t2, t3); 17720 + tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); 17721 + tcg_gen_sub_i64(t2, t3, t2); 17722 + tcg_temp_free_i64(t3); 17723 + gen_move_low32(cpu_LO[acc], t2); 17724 + gen_move_high32(cpu_HI[acc], t2); 17725 + tcg_temp_free_i64(t2); 17726 + } 17727 + break; 17728 + case NM_EXTRV_RS_W: 17729 + check_dsp(ctx); 17730 + tcg_gen_movi_tl(t0, rd >> 3); 17731 + gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env); 17732 + gen_store_gpr(t0, ret); 17733 + break; 17734 + } 17735 + break; 17736 + case NM_POOL32AXF_2_24_31: 17737 + switch (extract32(ctx->opcode, 9, 3)) { 17738 + case NM_DPAU_H_QBR: 17739 + case NM_DPAQX_SA_W_PH: 17740 + case NM_DPSU_H_QBR: 17741 + case NM_DPSQX_SA_W_PH: 17742 + case NM_MULSAQ_S_W_PH: 17743 + gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd); 17744 + break; 17745 + case NM_EXTPDPV: 17746 + check_dsp(ctx); 17747 + tcg_gen_movi_tl(t0, rd >> 3); 17748 + gen_helper_extpdp(t0, t0, v1_t, cpu_env); 17749 + gen_store_gpr(t0, ret); 17750 + break; 17751 + case NM_MSUBU: 17752 + check_dsp(ctx); 17753 + { 17754 + int acc = extract32(ctx->opcode, 14, 2); 17755 + TCGv_i64 t2 = tcg_temp_new_i64(); 17756 + TCGv_i64 t3 = tcg_temp_new_i64(); 17757 + 17758 + gen_load_gpr(t0, rs); 17759 + gen_load_gpr(t1, rt); 17760 + tcg_gen_ext32u_tl(t0, t0); 17761 + tcg_gen_ext32u_tl(t1, t1); 17762 + tcg_gen_extu_tl_i64(t2, t0); 17763 + tcg_gen_extu_tl_i64(t3, t1); 17764 + tcg_gen_mul_i64(t2, t2, t3); 17765 + tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]); 17766 + tcg_gen_sub_i64(t2, t3, t2); 17767 + tcg_temp_free_i64(t3); 17768 + gen_move_low32(cpu_LO[acc], t2); 17769 + gen_move_high32(cpu_HI[acc], t2); 17770 + tcg_temp_free_i64(t2); 17771 + } 17772 + break; 17773 + case NM_EXTRV_S_H: 17774 + check_dsp(ctx); 17775 + tcg_gen_movi_tl(t0, rd >> 3); 17776 + gen_helper_extr_s_h(t0, t0, v0_t, cpu_env); 17777 + gen_store_gpr(t0, ret); 17778 + break; 17779 + } 17780 + break; 17781 + default: 17782 + generate_exception_end(ctx, EXCP_RI); 17783 + break; 17784 + } 17785 + 17786 + tcg_temp_free(t0); 17787 + tcg_temp_free(t1); 17788 + 17789 + tcg_temp_free(v0_t); 17790 + tcg_temp_free(v1_t); 17791 + } 17792 + 17793 + static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc, 17794 + int rt, int rs) 17795 + { 17796 + int ret = rt; 17797 + TCGv t0 = tcg_temp_new(); 17798 + TCGv v0_t = tcg_temp_new(); 17799 + 17800 + gen_load_gpr(v0_t, rs); 17801 + 17802 + switch (opc) { 17803 + case NM_ABSQ_S_QB: 17804 + check_dspr2(ctx); 17805 + gen_helper_absq_s_qb(v0_t, v0_t, cpu_env); 17806 + gen_store_gpr(v0_t, ret); 17807 + break; 17808 + case NM_ABSQ_S_PH: 17809 + check_dsp(ctx); 17810 + gen_helper_absq_s_ph(v0_t, v0_t, cpu_env); 17811 + gen_store_gpr(v0_t, ret); 17812 + break; 17813 + case NM_ABSQ_S_W: 17814 + check_dsp(ctx); 17815 + gen_helper_absq_s_w(v0_t, v0_t, cpu_env); 17816 + gen_store_gpr(v0_t, ret); 17817 + break; 17818 + case NM_PRECEQ_W_PHL: 17819 + check_dsp(ctx); 17820 + tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000); 17821 + tcg_gen_ext32s_tl(v0_t, v0_t); 17822 + gen_store_gpr(v0_t, ret); 17823 + break; 17824 + case NM_PRECEQ_W_PHR: 17825 + check_dsp(ctx); 17826 + tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF); 17827 + tcg_gen_shli_tl(v0_t, v0_t, 16); 17828 + tcg_gen_ext32s_tl(v0_t, v0_t); 17829 + gen_store_gpr(v0_t, ret); 17830 + break; 17831 + case NM_PRECEQU_PH_QBL: 17832 + check_dsp(ctx); 17833 + gen_helper_precequ_ph_qbl(v0_t, v0_t); 17834 + gen_store_gpr(v0_t, ret); 17835 + break; 17836 + case NM_PRECEQU_PH_QBR: 17837 + check_dsp(ctx); 17838 + gen_helper_precequ_ph_qbr(v0_t, v0_t); 17839 + gen_store_gpr(v0_t, ret); 17840 + break; 17841 + case NM_PRECEQU_PH_QBLA: 17842 + check_dsp(ctx); 17843 + gen_helper_precequ_ph_qbla(v0_t, v0_t); 17844 + gen_store_gpr(v0_t, ret); 17845 + break; 17846 + case NM_PRECEQU_PH_QBRA: 17847 + check_dsp(ctx); 17848 + gen_helper_precequ_ph_qbra(v0_t, v0_t); 17849 + gen_store_gpr(v0_t, ret); 17850 + break; 17851 + case NM_PRECEU_PH_QBL: 17852 + check_dsp(ctx); 17853 + gen_helper_preceu_ph_qbl(v0_t, v0_t); 17854 + gen_store_gpr(v0_t, ret); 17855 + break; 17856 + case NM_PRECEU_PH_QBR: 17857 + check_dsp(ctx); 17858 + gen_helper_preceu_ph_qbr(v0_t, v0_t); 17859 + gen_store_gpr(v0_t, ret); 17860 + break; 17861 + case NM_PRECEU_PH_QBLA: 17862 + check_dsp(ctx); 17863 + gen_helper_preceu_ph_qbla(v0_t, v0_t); 17864 + gen_store_gpr(v0_t, ret); 17865 + break; 17866 + case NM_PRECEU_PH_QBRA: 17867 + check_dsp(ctx); 17868 + gen_helper_preceu_ph_qbra(v0_t, v0_t); 17869 + gen_store_gpr(v0_t, ret); 17870 + break; 17871 + case NM_REPLV_PH: 17872 + check_dsp(ctx); 17873 + tcg_gen_ext16u_tl(v0_t, v0_t); 17874 + tcg_gen_shli_tl(t0, v0_t, 16); 17875 + tcg_gen_or_tl(v0_t, v0_t, t0); 17876 + tcg_gen_ext32s_tl(v0_t, v0_t); 17877 + gen_store_gpr(v0_t, ret); 17878 + break; 17879 + case NM_REPLV_QB: 17880 + check_dsp(ctx); 17881 + tcg_gen_ext8u_tl(v0_t, v0_t); 17882 + tcg_gen_shli_tl(t0, v0_t, 8); 17883 + tcg_gen_or_tl(v0_t, v0_t, t0); 17884 + tcg_gen_shli_tl(t0, v0_t, 16); 17885 + tcg_gen_or_tl(v0_t, v0_t, t0); 17886 + tcg_gen_ext32s_tl(v0_t, v0_t); 17887 + gen_store_gpr(v0_t, ret); 17888 + break; 17889 + case NM_BITREV: 17890 + check_dsp(ctx); 17891 + gen_helper_bitrev(v0_t, v0_t); 17892 + gen_store_gpr(v0_t, ret); 17893 + break; 17894 + case NM_INSV: 17895 + check_dsp(ctx); 17896 + { 17897 + TCGv tv0 = tcg_temp_new(); 17898 + 17899 + gen_load_gpr(tv0, rt); 17900 + gen_helper_insv(v0_t, cpu_env, v0_t, tv0); 17901 + gen_store_gpr(v0_t, ret); 17902 + tcg_temp_free(tv0); 17903 + } 17904 + break; 17905 + case NM_RADDU_W_QB: 17906 + check_dsp(ctx); 17907 + gen_helper_raddu_w_qb(v0_t, v0_t); 17908 + gen_store_gpr(v0_t, ret); 17909 + break; 17910 + case NM_BITSWAP: 17911 + gen_bitswap(ctx, OPC_BITSWAP, ret, rs); 17912 + break; 17913 + case NM_CLO: 17914 + check_nms(ctx); 17915 + gen_cl(ctx, OPC_CLO, ret, rs); 17916 + break; 17917 + case NM_CLZ: 17918 + check_nms(ctx); 17919 + gen_cl(ctx, OPC_CLZ, ret, rs); 17920 + break; 17921 + case NM_WSBH: 17922 + gen_bshfl(ctx, OPC_WSBH, ret, rs); 17923 + break; 17924 + default: 17925 + generate_exception_end(ctx, EXCP_RI); 17926 + break; 17927 + } 17928 + 17929 + tcg_temp_free(v0_t); 17930 + tcg_temp_free(t0); 17931 + } 17932 + 17933 + static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc, 17934 + int rt, int rs, int rd) 17935 + { 17936 + TCGv t0 = tcg_temp_new(); 17937 + TCGv rs_t = tcg_temp_new(); 17938 + 17939 + gen_load_gpr(rs_t, rs); 17940 + 17941 + switch (opc) { 17942 + case NM_SHRA_R_QB: 17943 + check_dspr2(ctx); 17944 + tcg_gen_movi_tl(t0, rd >> 2); 17945 + switch (extract32(ctx->opcode, 12, 1)) { 17946 + case 0: 17947 + /* NM_SHRA_QB */ 17948 + gen_helper_shra_qb(t0, t0, rs_t); 17949 + gen_store_gpr(t0, rt); 17950 + break; 17951 + case 1: 17952 + /* NM_SHRA_R_QB */ 17953 + gen_helper_shra_r_qb(t0, t0, rs_t); 17954 + gen_store_gpr(t0, rt); 17955 + break; 17956 + } 17957 + break; 17958 + case NM_SHRL_PH: 17959 + check_dspr2(ctx); 17960 + tcg_gen_movi_tl(t0, rd >> 1); 17961 + gen_helper_shrl_ph(t0, t0, rs_t); 17962 + gen_store_gpr(t0, rt); 17963 + break; 17964 + case NM_REPL_QB: 17965 + check_dsp(ctx); 17966 + { 17967 + int16_t imm; 17968 + target_long result; 17969 + imm = extract32(ctx->opcode, 13, 8); 17970 + result = (uint32_t)imm << 24 | 17971 + (uint32_t)imm << 16 | 17972 + (uint32_t)imm << 8 | 17973 + (uint32_t)imm; 17974 + result = (int32_t)result; 17975 + tcg_gen_movi_tl(t0, result); 17976 + gen_store_gpr(t0, rt); 17977 + } 17978 + break; 17979 + default: 17980 + generate_exception_end(ctx, EXCP_RI); 17981 + break; 17982 + } 17983 + tcg_temp_free(t0); 17984 + tcg_temp_free(rs_t); 17985 + } 17986 + 17987 + 17988 + static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx) 17989 + { 17990 + int rt = extract32(ctx->opcode, 21, 5); 17991 + int rs = extract32(ctx->opcode, 16, 5); 17992 + int rd = extract32(ctx->opcode, 11, 5); 17993 + 17994 + switch (extract32(ctx->opcode, 6, 3)) { 17995 + case NM_POOL32AXF_1: 17996 + { 17997 + int32_t op1 = extract32(ctx->opcode, 9, 3); 17998 + gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd); 17999 + } 18000 + break; 18001 + case NM_POOL32AXF_2: 18002 + { 18003 + int32_t op1 = extract32(ctx->opcode, 12, 2); 18004 + gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd); 18005 + } 18006 + break; 18007 + case NM_POOL32AXF_4: 18008 + { 18009 + int32_t op1 = extract32(ctx->opcode, 9, 7); 18010 + gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs); 18011 + } 18012 + break; 18013 + case NM_POOL32AXF_5: 18014 + switch (extract32(ctx->opcode, 9, 7)) { 18015 + #ifndef CONFIG_USER_ONLY 18016 + case NM_TLBP: 18017 + gen_cp0(env, ctx, OPC_TLBP, 0, 0); 18018 + break; 18019 + case NM_TLBR: 18020 + gen_cp0(env, ctx, OPC_TLBR, 0, 0); 18021 + break; 18022 + case NM_TLBWI: 18023 + gen_cp0(env, ctx, OPC_TLBWI, 0, 0); 18024 + break; 18025 + case NM_TLBWR: 18026 + gen_cp0(env, ctx, OPC_TLBWR, 0, 0); 18027 + break; 18028 + case NM_TLBINV: 18029 + gen_cp0(env, ctx, OPC_TLBINV, 0, 0); 18030 + break; 18031 + case NM_TLBINVF: 18032 + gen_cp0(env, ctx, OPC_TLBINVF, 0, 0); 18033 + break; 18034 + case NM_DI: 18035 + check_cp0_enabled(ctx); 18036 + { 18037 + TCGv t0 = tcg_temp_new(); 18038 + 18039 + save_cpu_state(ctx, 1); 18040 + gen_helper_di(t0, cpu_env); 18041 + gen_store_gpr(t0, rt); 18042 + /* Stop translation as we may have switched the execution mode */ 18043 + ctx->base.is_jmp = DISAS_STOP; 18044 + tcg_temp_free(t0); 18045 + } 18046 + break; 18047 + case NM_EI: 18048 + check_cp0_enabled(ctx); 18049 + { 18050 + TCGv t0 = tcg_temp_new(); 18051 + 18052 + save_cpu_state(ctx, 1); 18053 + gen_helper_ei(t0, cpu_env); 18054 + gen_store_gpr(t0, rt); 18055 + /* Stop translation as we may have switched the execution mode */ 18056 + ctx->base.is_jmp = DISAS_STOP; 18057 + tcg_temp_free(t0); 18058 + } 18059 + break; 18060 + case NM_RDPGPR: 18061 + gen_load_srsgpr(rs, rt); 18062 + break; 18063 + case NM_WRPGPR: 18064 + gen_store_srsgpr(rs, rt); 18065 + break; 18066 + case NM_WAIT: 18067 + gen_cp0(env, ctx, OPC_WAIT, 0, 0); 18068 + break; 18069 + case NM_DERET: 18070 + gen_cp0(env, ctx, OPC_DERET, 0, 0); 18071 + break; 18072 + case NM_ERETX: 18073 + gen_cp0(env, ctx, OPC_ERET, 0, 0); 18074 + break; 18075 + #endif 18076 + default: 18077 + generate_exception_end(ctx, EXCP_RI); 18078 + break; 18079 + } 18080 + break; 18081 + case NM_POOL32AXF_7: 18082 + { 18083 + int32_t op1 = extract32(ctx->opcode, 9, 3); 18084 + gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd); 18085 + } 18086 + break; 18087 + default: 18088 + generate_exception_end(ctx, EXCP_RI); 18089 + break; 18090 + } 18091 + } 18092 + 18093 + /* Immediate Value Compact Branches */ 18094 + static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc, 18095 + int rt, int32_t imm, int32_t offset) 18096 + { 18097 + TCGCond cond; 18098 + int bcond_compute = 0; 18099 + TCGv t0 = tcg_temp_new(); 18100 + TCGv t1 = tcg_temp_new(); 18101 + 18102 + gen_load_gpr(t0, rt); 18103 + tcg_gen_movi_tl(t1, imm); 18104 + ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset); 18105 + 18106 + /* Load needed operands and calculate btarget */ 18107 + switch (opc) { 18108 + case NM_BEQIC: 18109 + if (rt == 0 && imm == 0) { 18110 + /* Unconditional branch */ 18111 + } else if (rt == 0 && imm != 0) { 18112 + /* Treat as NOP */ 18113 + goto out; 18114 + } else { 18115 + bcond_compute = 1; 18116 + cond = TCG_COND_EQ; 18117 + } 18118 + break; 18119 + case NM_BBEQZC: 18120 + case NM_BBNEZC: 18121 + check_nms(ctx); 18122 + if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) { 18123 + generate_exception_end(ctx, EXCP_RI); 18124 + goto out; 18125 + } else if (rt == 0 && opc == NM_BBEQZC) { 18126 + /* Unconditional branch */ 18127 + } else if (rt == 0 && opc == NM_BBNEZC) { 18128 + /* Treat as NOP */ 18129 + goto out; 18130 + } else { 18131 + tcg_gen_shri_tl(t0, t0, imm); 18132 + tcg_gen_andi_tl(t0, t0, 1); 18133 + tcg_gen_movi_tl(t1, 0); 18134 + bcond_compute = 1; 18135 + if (opc == NM_BBEQZC) { 18136 + cond = TCG_COND_EQ; 18137 + } else { 18138 + cond = TCG_COND_NE; 18139 + } 18140 + } 18141 + break; 18142 + case NM_BNEIC: 18143 + if (rt == 0 && imm == 0) { 18144 + /* Treat as NOP */ 18145 + goto out; 18146 + } else if (rt == 0 && imm != 0) { 18147 + /* Unconditional branch */ 18148 + } else { 18149 + bcond_compute = 1; 18150 + cond = TCG_COND_NE; 18151 + } 18152 + break; 18153 + case NM_BGEIC: 18154 + if (rt == 0 && imm == 0) { 18155 + /* Unconditional branch */ 18156 + } else { 18157 + bcond_compute = 1; 18158 + cond = TCG_COND_GE; 18159 + } 18160 + break; 18161 + case NM_BLTIC: 18162 + bcond_compute = 1; 18163 + cond = TCG_COND_LT; 18164 + break; 18165 + case NM_BGEIUC: 18166 + if (rt == 0 && imm == 0) { 18167 + /* Unconditional branch */ 18168 + } else { 18169 + bcond_compute = 1; 18170 + cond = TCG_COND_GEU; 18171 + } 18172 + break; 18173 + case NM_BLTIUC: 18174 + bcond_compute = 1; 18175 + cond = TCG_COND_LTU; 18176 + break; 18177 + default: 18178 + MIPS_INVAL("Immediate Value Compact branch"); 18179 + generate_exception_end(ctx, EXCP_RI); 18180 + goto out; 18181 + } 18182 + 18183 + if (bcond_compute == 0) { 18184 + /* Uncoditional compact branch */ 18185 + gen_goto_tb(ctx, 0, ctx->btarget); 18186 + } else { 18187 + /* Conditional compact branch */ 18188 + TCGLabel *fs = gen_new_label(); 18189 + 18190 + tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs); 18191 + 18192 + gen_goto_tb(ctx, 1, ctx->btarget); 18193 + gen_set_label(fs); 18194 + 18195 + gen_goto_tb(ctx, 0, ctx->base.pc_next + 4); 18196 + } 18197 + 18198 + out: 18199 + tcg_temp_free(t0); 18200 + tcg_temp_free(t1); 18201 + } 18202 + 18203 + /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */ 18204 + static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs, 18205 + int rt) 18206 + { 18207 + TCGv t0 = tcg_temp_new(); 18208 + TCGv t1 = tcg_temp_new(); 18209 + 18210 + /* load rs */ 18211 + gen_load_gpr(t0, rs); 18212 + 18213 + /* link */ 18214 + if (rt != 0) { 18215 + tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4); 18216 + } 18217 + 18218 + /* calculate btarget */ 18219 + tcg_gen_shli_tl(t0, t0, 1); 18220 + tcg_gen_movi_tl(t1, ctx->base.pc_next + 4); 18221 + gen_op_addr_add(ctx, btarget, t1, t0); 18222 + 18223 + /* unconditional branch to register */ 18224 + tcg_gen_mov_tl(cpu_PC, btarget); 18225 + tcg_gen_lookup_and_goto_ptr(); 18226 + 18227 + tcg_temp_free(t0); 18228 + tcg_temp_free(t1); 18229 + } 18230 + 18231 + /* nanoMIPS Branches */ 18232 + static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc, 18233 + int rs, int rt, int32_t offset) 18234 + { 18235 + int bcond_compute = 0; 18236 + TCGv t0 = tcg_temp_new(); 18237 + TCGv t1 = tcg_temp_new(); 18238 + 18239 + /* Load needed operands and calculate btarget */ 18240 + switch (opc) { 18241 + /* compact branch */ 18242 + case OPC_BGEC: 18243 + case OPC_BLTC: 18244 + gen_load_gpr(t0, rs); 18245 + gen_load_gpr(t1, rt); 18246 + bcond_compute = 1; 18247 + ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset); 18248 + break; 18249 + case OPC_BGEUC: 18250 + case OPC_BLTUC: 18251 + if (rs == 0 || rs == rt) { 18252 + /* OPC_BLEZALC, OPC_BGEZALC */ 18253 + /* OPC_BGTZALC, OPC_BLTZALC */ 18254 + tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4); 18255 + } 18256 + gen_load_gpr(t0, rs); 18257 + gen_load_gpr(t1, rt); 18258 + bcond_compute = 1; 18259 + ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset); 18260 + break; 18261 + case OPC_BC: 18262 + ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset); 18263 + break; 18264 + case OPC_BEQZC: 18265 + if (rs != 0) { 18266 + /* OPC_BEQZC, OPC_BNEZC */ 18267 + gen_load_gpr(t0, rs); 18268 + bcond_compute = 1; 18269 + ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset); 18270 + } else { 18271 + /* OPC_JIC, OPC_JIALC */ 18272 + TCGv tbase = tcg_temp_new(); 18273 + TCGv toffset = tcg_temp_new(); 18274 + 18275 + gen_load_gpr(tbase, rt); 18276 + tcg_gen_movi_tl(toffset, offset); 18277 + gen_op_addr_add(ctx, btarget, tbase, toffset); 18278 + tcg_temp_free(tbase); 18279 + tcg_temp_free(toffset); 18280 + } 18281 + break; 18282 + default: 18283 + MIPS_INVAL("Compact branch/jump"); 18284 + generate_exception_end(ctx, EXCP_RI); 18285 + goto out; 18286 + } 18287 + 18288 + if (bcond_compute == 0) { 18289 + /* Uncoditional compact branch */ 18290 + switch (opc) { 18291 + case OPC_BC: 18292 + gen_goto_tb(ctx, 0, ctx->btarget); 18293 + break; 18294 + default: 18295 + MIPS_INVAL("Compact branch/jump"); 18296 + generate_exception_end(ctx, EXCP_RI); 18297 + goto out; 18298 + } 18299 + } else { 18300 + /* Conditional compact branch */ 18301 + TCGLabel *fs = gen_new_label(); 18302 + 18303 + switch (opc) { 18304 + case OPC_BGEUC: 18305 + if (rs == 0 && rt != 0) { 18306 + /* OPC_BLEZALC */ 18307 + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs); 18308 + } else if (rs != 0 && rt != 0 && rs == rt) { 18309 + /* OPC_BGEZALC */ 18310 + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs); 18311 + } else { 18312 + /* OPC_BGEUC */ 18313 + tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs); 18314 + } 18315 + break; 18316 + case OPC_BLTUC: 18317 + if (rs == 0 && rt != 0) { 18318 + /* OPC_BGTZALC */ 18319 + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs); 18320 + } else if (rs != 0 && rt != 0 && rs == rt) { 18321 + /* OPC_BLTZALC */ 18322 + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs); 18323 + } else { 18324 + /* OPC_BLTUC */ 18325 + tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs); 18326 + } 18327 + break; 18328 + case OPC_BGEC: 18329 + if (rs == 0 && rt != 0) { 18330 + /* OPC_BLEZC */ 18331 + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs); 18332 + } else if (rs != 0 && rt != 0 && rs == rt) { 18333 + /* OPC_BGEZC */ 18334 + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs); 18335 + } else { 18336 + /* OPC_BGEC */ 18337 + tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs); 18338 + } 18339 + break; 18340 + case OPC_BLTC: 18341 + if (rs == 0 && rt != 0) { 18342 + /* OPC_BGTZC */ 18343 + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs); 18344 + } else if (rs != 0 && rt != 0 && rs == rt) { 18345 + /* OPC_BLTZC */ 18346 + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs); 18347 + } else { 18348 + /* OPC_BLTC */ 18349 + tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs); 18350 + } 18351 + break; 18352 + case OPC_BEQZC: 18353 + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs); 18354 + break; 18355 + default: 18356 + MIPS_INVAL("Compact conditional branch/jump"); 18357 + generate_exception_end(ctx, EXCP_RI); 18358 + goto out; 18359 + } 18360 + 18361 + /* Generating branch here as compact branches don't have delay slot */ 18362 + gen_goto_tb(ctx, 1, ctx->btarget); 18363 + gen_set_label(fs); 18364 + 18365 + gen_goto_tb(ctx, 0, ctx->base.pc_next + 4); 18366 + } 18367 + 18368 + out: 18369 + tcg_temp_free(t0); 18370 + tcg_temp_free(t1); 18371 + } 18372 + 18373 + 18374 + /* nanoMIPS CP1 Branches */ 18375 + static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op, 18376 + int32_t ft, int32_t offset) 18377 + { 18378 + target_ulong btarget; 18379 + TCGv_i64 t0 = tcg_temp_new_i64(); 18380 + 18381 + gen_load_fpr64(ctx, t0, ft); 18382 + tcg_gen_andi_i64(t0, t0, 1); 18383 + 18384 + btarget = addr_add(ctx, ctx->base.pc_next + 4, offset); 18385 + 18386 + switch (op) { 18387 + case NM_BC1EQZC: 18388 + tcg_gen_xori_i64(t0, t0, 1); 18389 + ctx->hflags |= MIPS_HFLAG_BC; 18390 + break; 18391 + case NM_BC1NEZC: 18392 + /* t0 already set */ 18393 + ctx->hflags |= MIPS_HFLAG_BC; 18394 + break; 18395 + default: 18396 + MIPS_INVAL("cp1 cond branch"); 18397 + generate_exception_end(ctx, EXCP_RI); 18398 + goto out; 18399 + } 18400 + 18401 + tcg_gen_trunc_i64_tl(bcond, t0); 18402 + 18403 + ctx->btarget = btarget; 18404 + 18405 + out: 18406 + tcg_temp_free_i64(t0); 18407 + } 18408 + 18409 + 18410 + static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt) 18411 + { 18412 + TCGv t0, t1; 18413 + t0 = tcg_temp_new(); 18414 + t1 = tcg_temp_new(); 18415 + 18416 + gen_load_gpr(t0, rs); 18417 + gen_load_gpr(t1, rt); 18418 + 18419 + if ((extract32(ctx->opcode, 6, 1)) == 1) { 18420 + /* PP.LSXS instructions require shifting */ 18421 + switch (extract32(ctx->opcode, 7, 4)) { 18422 + case NM_SHXS: 18423 + check_nms(ctx); 18424 + case NM_LHXS: 18425 + case NM_LHUXS: 18426 + tcg_gen_shli_tl(t0, t0, 1); 18427 + break; 18428 + case NM_SWXS: 18429 + check_nms(ctx); 18430 + case NM_LWXS: 18431 + case NM_LWC1XS: 18432 + case NM_SWC1XS: 18433 + tcg_gen_shli_tl(t0, t0, 2); 18434 + break; 18435 + case NM_LDC1XS: 18436 + case NM_SDC1XS: 18437 + tcg_gen_shli_tl(t0, t0, 3); 18438 + break; 18439 + } 18440 + } 18441 + gen_op_addr_add(ctx, t0, t0, t1); 18442 + 18443 + switch (extract32(ctx->opcode, 7, 4)) { 18444 + case NM_LBX: 18445 + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, 18446 + MO_SB); 18447 + gen_store_gpr(t0, rd); 18448 + break; 18449 + case NM_LHX: 18450 + /*case NM_LHXS:*/ 18451 + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, 18452 + MO_TESW); 18453 + gen_store_gpr(t0, rd); 18454 + break; 18455 + case NM_LWX: 18456 + /*case NM_LWXS:*/ 18457 + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, 18458 + MO_TESL); 18459 + gen_store_gpr(t0, rd); 18460 + break; 18461 + case NM_LBUX: 18462 + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, 18463 + MO_UB); 18464 + gen_store_gpr(t0, rd); 18465 + break; 18466 + case NM_LHUX: 18467 + /*case NM_LHUXS:*/ 18468 + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, 18469 + MO_TEUW); 18470 + gen_store_gpr(t0, rd); 18471 + break; 18472 + case NM_SBX: 18473 + check_nms(ctx); 18474 + gen_load_gpr(t1, rd); 18475 + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, 18476 + MO_8); 18477 + break; 18478 + case NM_SHX: 18479 + /*case NM_SHXS:*/ 18480 + check_nms(ctx); 18481 + gen_load_gpr(t1, rd); 18482 + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, 18483 + MO_TEUW); 18484 + break; 18485 + case NM_SWX: 18486 + /*case NM_SWXS:*/ 18487 + check_nms(ctx); 18488 + gen_load_gpr(t1, rd); 18489 + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, 18490 + MO_TEUL); 18491 + break; 18492 + case NM_LWC1X: 18493 + /*case NM_LWC1XS:*/ 18494 + case NM_LDC1X: 18495 + /*case NM_LDC1XS:*/ 18496 + case NM_SWC1X: 18497 + /*case NM_SWC1XS:*/ 18498 + case NM_SDC1X: 18499 + /*case NM_SDC1XS:*/ 18500 + if (ctx->CP0_Config1 & (1 << CP0C1_FP)) { 18501 + check_cp1_enabled(ctx); 18502 + switch (extract32(ctx->opcode, 7, 4)) { 18503 + case NM_LWC1X: 18504 + /*case NM_LWC1XS:*/ 18505 + gen_flt_ldst(ctx, OPC_LWC1, rd, t0); 18506 + break; 18507 + case NM_LDC1X: 18508 + /*case NM_LDC1XS:*/ 18509 + gen_flt_ldst(ctx, OPC_LDC1, rd, t0); 18510 + break; 18511 + case NM_SWC1X: 18512 + /*case NM_SWC1XS:*/ 18513 + gen_flt_ldst(ctx, OPC_SWC1, rd, t0); 18514 + break; 18515 + case NM_SDC1X: 18516 + /*case NM_SDC1XS:*/ 18517 + gen_flt_ldst(ctx, OPC_SDC1, rd, t0); 18518 + break; 18519 + } 18520 + } else { 18521 + generate_exception_err(ctx, EXCP_CpU, 1); 18522 + } 18523 + break; 18524 + default: 18525 + generate_exception_end(ctx, EXCP_RI); 18526 + break; 18527 + } 18528 + 18529 + tcg_temp_free(t0); 18530 + tcg_temp_free(t1); 18531 + } 18532 + 18533 + static void gen_pool32f_nanomips_insn(DisasContext *ctx) 18534 + { 18535 + int rt, rs, rd; 18536 + 18537 + rt = extract32(ctx->opcode, 21, 5); 18538 + rs = extract32(ctx->opcode, 16, 5); 18539 + rd = extract32(ctx->opcode, 11, 5); 18540 + 18541 + if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) { 18542 + generate_exception_end(ctx, EXCP_RI); 18543 + return; 18544 + } 18545 + check_cp1_enabled(ctx); 18546 + switch (extract32(ctx->opcode, 0, 3)) { 18547 + case NM_POOL32F_0: 18548 + switch (extract32(ctx->opcode, 3, 7)) { 18549 + case NM_RINT_S: 18550 + gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0); 18551 + break; 18552 + case NM_RINT_D: 18553 + gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0); 18554 + break; 18555 + case NM_CLASS_S: 18556 + gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0); 18557 + break; 18558 + case NM_CLASS_D: 18559 + gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0); 18560 + break; 18561 + case NM_ADD_S: 18562 + gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0); 18563 + break; 18564 + case NM_ADD_D: 18565 + gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0); 18566 + break; 18567 + case NM_SUB_S: 18568 + gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0); 18569 + break; 18570 + case NM_SUB_D: 18571 + gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0); 18572 + break; 18573 + case NM_MUL_S: 18574 + gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0); 18575 + break; 18576 + case NM_MUL_D: 18577 + gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0); 18578 + break; 18579 + case NM_DIV_S: 18580 + gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0); 18581 + break; 18582 + case NM_DIV_D: 18583 + gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0); 18584 + break; 18585 + case NM_SELEQZ_S: 18586 + gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs); 18587 + break; 18588 + case NM_SELEQZ_D: 18589 + gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs); 18590 + break; 18591 + case NM_SELNEZ_S: 18592 + gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs); 18593 + break; 18594 + case NM_SELNEZ_D: 18595 + gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs); 18596 + break; 18597 + case NM_SEL_S: 18598 + gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs); 18599 + break; 18600 + case NM_SEL_D: 18601 + gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs); 18602 + break; 18603 + case NM_MADDF_S: 18604 + gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0); 18605 + break; 18606 + case NM_MADDF_D: 18607 + gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0); 18608 + break; 18609 + case NM_MSUBF_S: 18610 + gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0); 18611 + break; 18612 + case NM_MSUBF_D: 18613 + gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0); 18614 + break; 18615 + default: 18616 + generate_exception_end(ctx, EXCP_RI); 18617 + break; 18618 + } 18619 + break; 18620 + case NM_POOL32F_3: 18621 + switch (extract32(ctx->opcode, 3, 3)) { 18622 + case NM_MIN_FMT: 18623 + switch (extract32(ctx->opcode, 9, 1)) { 18624 + case FMT_SDPS_S: 18625 + gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0); 18626 + break; 18627 + case FMT_SDPS_D: 18628 + gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0); 18629 + break; 18630 + } 18631 + break; 18632 + case NM_MAX_FMT: 18633 + switch (extract32(ctx->opcode, 9, 1)) { 18634 + case FMT_SDPS_S: 18635 + gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0); 18636 + break; 18637 + case FMT_SDPS_D: 18638 + gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0); 18639 + break; 18640 + } 18641 + break; 18642 + case NM_MINA_FMT: 18643 + switch (extract32(ctx->opcode, 9, 1)) { 18644 + case FMT_SDPS_S: 18645 + gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0); 18646 + break; 18647 + case FMT_SDPS_D: 18648 + gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0); 18649 + break; 18650 + } 18651 + break; 18652 + case NM_MAXA_FMT: 18653 + switch (extract32(ctx->opcode, 9, 1)) { 18654 + case FMT_SDPS_S: 18655 + gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0); 18656 + break; 18657 + case FMT_SDPS_D: 18658 + gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0); 18659 + break; 18660 + } 18661 + break; 18662 + case NM_POOL32FXF: 18663 + switch (extract32(ctx->opcode, 6, 8)) { 18664 + case NM_CFC1: 18665 + gen_cp1(ctx, OPC_CFC1, rt, rs); 18666 + break; 18667 + case NM_CTC1: 18668 + gen_cp1(ctx, OPC_CTC1, rt, rs); 18669 + break; 18670 + case NM_MFC1: 18671 + gen_cp1(ctx, OPC_MFC1, rt, rs); 18672 + break; 18673 + case NM_MTC1: 18674 + gen_cp1(ctx, OPC_MTC1, rt, rs); 18675 + break; 18676 + case NM_MFHC1: 18677 + gen_cp1(ctx, OPC_MFHC1, rt, rs); 18678 + break; 18679 + case NM_MTHC1: 18680 + gen_cp1(ctx, OPC_MTHC1, rt, rs); 18681 + break; 18682 + case NM_CVT_S_PL: 18683 + gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0); 18684 + break; 18685 + case NM_CVT_S_PU: 18686 + gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0); 18687 + break; 18688 + default: 18689 + switch (extract32(ctx->opcode, 6, 9)) { 18690 + case NM_CVT_L_S: 18691 + gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0); 18692 + break; 18693 + case NM_CVT_L_D: 18694 + gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0); 18695 + break; 18696 + case NM_CVT_W_S: 18697 + gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0); 18698 + break; 18699 + case NM_CVT_W_D: 18700 + gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0); 18701 + break; 18702 + case NM_RSQRT_S: 18703 + gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0); 18704 + break; 18705 + case NM_RSQRT_D: 18706 + gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0); 18707 + break; 18708 + case NM_SQRT_S: 18709 + gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0); 18710 + break; 18711 + case NM_SQRT_D: 18712 + gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0); 18713 + break; 18714 + case NM_RECIP_S: 18715 + gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0); 18716 + break; 18717 + case NM_RECIP_D: 18718 + gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0); 18719 + break; 18720 + case NM_FLOOR_L_S: 18721 + gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0); 18722 + break; 18723 + case NM_FLOOR_L_D: 18724 + gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0); 18725 + break; 18726 + case NM_FLOOR_W_S: 18727 + gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0); 18728 + break; 18729 + case NM_FLOOR_W_D: 18730 + gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0); 18731 + break; 18732 + case NM_CEIL_L_S: 18733 + gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0); 18734 + break; 18735 + case NM_CEIL_L_D: 18736 + gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0); 18737 + break; 18738 + case NM_CEIL_W_S: 18739 + gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0); 18740 + break; 18741 + case NM_CEIL_W_D: 18742 + gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0); 18743 + break; 18744 + case NM_TRUNC_L_S: 18745 + gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0); 18746 + break; 18747 + case NM_TRUNC_L_D: 18748 + gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0); 18749 + break; 18750 + case NM_TRUNC_W_S: 18751 + gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0); 18752 + break; 18753 + case NM_TRUNC_W_D: 18754 + gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0); 18755 + break; 18756 + case NM_ROUND_L_S: 18757 + gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0); 18758 + break; 18759 + case NM_ROUND_L_D: 18760 + gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0); 18761 + break; 18762 + case NM_ROUND_W_S: 18763 + gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0); 18764 + break; 18765 + case NM_ROUND_W_D: 18766 + gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0); 18767 + break; 18768 + case NM_MOV_S: 18769 + gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0); 18770 + break; 18771 + case NM_MOV_D: 18772 + gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0); 18773 + break; 18774 + case NM_ABS_S: 18775 + gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0); 18776 + break; 18777 + case NM_ABS_D: 18778 + gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0); 18779 + break; 18780 + case NM_NEG_S: 18781 + gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0); 18782 + break; 18783 + case NM_NEG_D: 18784 + gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0); 18785 + break; 18786 + case NM_CVT_D_S: 18787 + gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0); 18788 + break; 18789 + case NM_CVT_D_W: 18790 + gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0); 18791 + break; 18792 + case NM_CVT_D_L: 18793 + gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0); 18794 + break; 18795 + case NM_CVT_S_D: 18796 + gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0); 18797 + break; 18798 + case NM_CVT_S_W: 18799 + gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0); 18800 + break; 18801 + case NM_CVT_S_L: 18802 + gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0); 18803 + break; 18804 + default: 18805 + generate_exception_end(ctx, EXCP_RI); 18806 + break; 18807 + } 18808 + break; 18809 + } 18810 + break; 18811 + } 18812 + break; 18813 + case NM_POOL32F_5: 18814 + switch (extract32(ctx->opcode, 3, 3)) { 18815 + case NM_CMP_CONDN_S: 18816 + gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd); 18817 + break; 18818 + case NM_CMP_CONDN_D: 18819 + gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd); 18820 + break; 18821 + default: 18822 + generate_exception_end(ctx, EXCP_RI); 18823 + break; 18824 + } 18825 + break; 18826 + default: 18827 + generate_exception_end(ctx, EXCP_RI); 18828 + break; 18829 + } 18830 + } 18831 + 18832 + static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc, 18833 + int rd, int rs, int rt) 18834 + { 18835 + int ret = rd; 18836 + TCGv t0 = tcg_temp_new(); 18837 + TCGv v1_t = tcg_temp_new(); 18838 + TCGv v2_t = tcg_temp_new(); 18839 + 18840 + gen_load_gpr(v1_t, rs); 18841 + gen_load_gpr(v2_t, rt); 18842 + 18843 + switch (opc) { 18844 + case NM_CMP_EQ_PH: 18845 + check_dsp(ctx); 18846 + gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env); 18847 + break; 18848 + case NM_CMP_LT_PH: 18849 + check_dsp(ctx); 18850 + gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env); 18851 + break; 18852 + case NM_CMP_LE_PH: 18853 + check_dsp(ctx); 18854 + gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env); 18855 + break; 18856 + case NM_CMPU_EQ_QB: 18857 + check_dsp(ctx); 18858 + gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env); 18859 + break; 18860 + case NM_CMPU_LT_QB: 18861 + check_dsp(ctx); 18862 + gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env); 18863 + break; 18864 + case NM_CMPU_LE_QB: 18865 + check_dsp(ctx); 18866 + gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env); 18867 + break; 18868 + case NM_CMPGU_EQ_QB: 18869 + check_dsp(ctx); 18870 + gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t); 18871 + gen_store_gpr(v1_t, ret); 18872 + break; 18873 + case NM_CMPGU_LT_QB: 18874 + check_dsp(ctx); 18875 + gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t); 18876 + gen_store_gpr(v1_t, ret); 18877 + break; 18878 + case NM_CMPGU_LE_QB: 18879 + check_dsp(ctx); 18880 + gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t); 18881 + gen_store_gpr(v1_t, ret); 18882 + break; 18883 + case NM_CMPGDU_EQ_QB: 18884 + check_dspr2(ctx); 18885 + gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t); 18886 + tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4); 18887 + gen_store_gpr(v1_t, ret); 18888 + break; 18889 + case NM_CMPGDU_LT_QB: 18890 + check_dspr2(ctx); 18891 + gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t); 18892 + tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4); 18893 + gen_store_gpr(v1_t, ret); 18894 + break; 18895 + case NM_CMPGDU_LE_QB: 18896 + check_dspr2(ctx); 18897 + gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t); 18898 + tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4); 18899 + gen_store_gpr(v1_t, ret); 18900 + break; 18901 + case NM_PACKRL_PH: 18902 + check_dsp(ctx); 18903 + gen_helper_packrl_ph(v1_t, v1_t, v2_t); 18904 + gen_store_gpr(v1_t, ret); 18905 + break; 18906 + case NM_PICK_QB: 18907 + check_dsp(ctx); 18908 + gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env); 18909 + gen_store_gpr(v1_t, ret); 18910 + break; 18911 + case NM_PICK_PH: 18912 + check_dsp(ctx); 18913 + gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env); 18914 + gen_store_gpr(v1_t, ret); 18915 + break; 18916 + case NM_ADDQ_S_W: 18917 + check_dsp(ctx); 18918 + gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env); 18919 + gen_store_gpr(v1_t, ret); 18920 + break; 18921 + case NM_SUBQ_S_W: 18922 + check_dsp(ctx); 18923 + gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env); 18924 + gen_store_gpr(v1_t, ret); 18925 + break; 18926 + case NM_ADDSC: 18927 + check_dsp(ctx); 18928 + gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env); 18929 + gen_store_gpr(v1_t, ret); 18930 + break; 18931 + case NM_ADDWC: 18932 + check_dsp(ctx); 18933 + gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env); 18934 + gen_store_gpr(v1_t, ret); 18935 + break; 18936 + case NM_ADDQ_S_PH: 18937 + check_dsp(ctx); 18938 + switch (extract32(ctx->opcode, 10, 1)) { 18939 + case 0: 18940 + /* ADDQ_PH */ 18941 + gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env); 18942 + gen_store_gpr(v1_t, ret); 18943 + break; 18944 + case 1: 18945 + /* ADDQ_S_PH */ 18946 + gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env); 18947 + gen_store_gpr(v1_t, ret); 18948 + break; 18949 + } 18950 + break; 18951 + case NM_ADDQH_R_PH: 18952 + check_dspr2(ctx); 18953 + switch (extract32(ctx->opcode, 10, 1)) { 18954 + case 0: 18955 + /* ADDQH_PH */ 18956 + gen_helper_addqh_ph(v1_t, v1_t, v2_t); 18957 + gen_store_gpr(v1_t, ret); 18958 + break; 18959 + case 1: 18960 + /* ADDQH_R_PH */ 18961 + gen_helper_addqh_r_ph(v1_t, v1_t, v2_t); 18962 + gen_store_gpr(v1_t, ret); 18963 + break; 18964 + } 18965 + break; 18966 + case NM_ADDQH_R_W: 18967 + check_dspr2(ctx); 18968 + switch (extract32(ctx->opcode, 10, 1)) { 18969 + case 0: 18970 + /* ADDQH_W */ 18971 + gen_helper_addqh_w(v1_t, v1_t, v2_t); 18972 + gen_store_gpr(v1_t, ret); 18973 + break; 18974 + case 1: 18975 + /* ADDQH_R_W */ 18976 + gen_helper_addqh_r_w(v1_t, v1_t, v2_t); 18977 + gen_store_gpr(v1_t, ret); 18978 + break; 18979 + } 18980 + break; 18981 + case NM_ADDU_S_QB: 18982 + check_dsp(ctx); 18983 + switch (extract32(ctx->opcode, 10, 1)) { 18984 + case 0: 18985 + /* ADDU_QB */ 18986 + gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env); 18987 + gen_store_gpr(v1_t, ret); 18988 + break; 18989 + case 1: 18990 + /* ADDU_S_QB */ 18991 + gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env); 18992 + gen_store_gpr(v1_t, ret); 18993 + break; 18994 + } 18995 + break; 18996 + case NM_ADDU_S_PH: 18997 + check_dspr2(ctx); 18998 + switch (extract32(ctx->opcode, 10, 1)) { 18999 + case 0: 19000 + /* ADDU_PH */ 19001 + gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env); 19002 + gen_store_gpr(v1_t, ret); 19003 + break; 19004 + case 1: 19005 + /* ADDU_S_PH */ 19006 + gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env); 19007 + gen_store_gpr(v1_t, ret); 19008 + break; 19009 + } 19010 + break; 19011 + case NM_ADDUH_R_QB: 19012 + check_dspr2(ctx); 19013 + switch (extract32(ctx->opcode, 10, 1)) { 19014 + case 0: 19015 + /* ADDUH_QB */ 19016 + gen_helper_adduh_qb(v1_t, v1_t, v2_t); 19017 + gen_store_gpr(v1_t, ret); 19018 + break; 19019 + case 1: 19020 + /* ADDUH_R_QB */ 19021 + gen_helper_adduh_r_qb(v1_t, v1_t, v2_t); 19022 + gen_store_gpr(v1_t, ret); 19023 + break; 19024 + } 19025 + break; 19026 + case NM_SHRAV_R_PH: 19027 + check_dsp(ctx); 19028 + switch (extract32(ctx->opcode, 10, 1)) { 19029 + case 0: 19030 + /* SHRAV_PH */ 19031 + gen_helper_shra_ph(v1_t, v1_t, v2_t); 19032 + gen_store_gpr(v1_t, ret); 19033 + break; 19034 + case 1: 19035 + /* SHRAV_R_PH */ 19036 + gen_helper_shra_r_ph(v1_t, v1_t, v2_t); 19037 + gen_store_gpr(v1_t, ret); 19038 + break; 19039 + } 19040 + break; 19041 + case NM_SHRAV_R_QB: 19042 + check_dspr2(ctx); 19043 + switch (extract32(ctx->opcode, 10, 1)) { 19044 + case 0: 19045 + /* SHRAV_QB */ 19046 + gen_helper_shra_qb(v1_t, v1_t, v2_t); 19047 + gen_store_gpr(v1_t, ret); 19048 + break; 19049 + case 1: 19050 + /* SHRAV_R_QB */ 19051 + gen_helper_shra_r_qb(v1_t, v1_t, v2_t); 19052 + gen_store_gpr(v1_t, ret); 19053 + break; 19054 + } 19055 + break; 19056 + case NM_SUBQ_S_PH: 19057 + check_dsp(ctx); 19058 + switch (extract32(ctx->opcode, 10, 1)) { 19059 + case 0: 19060 + /* SUBQ_PH */ 19061 + gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env); 19062 + gen_store_gpr(v1_t, ret); 19063 + break; 19064 + case 1: 19065 + /* SUBQ_S_PH */ 19066 + gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env); 19067 + gen_store_gpr(v1_t, ret); 19068 + break; 19069 + } 19070 + break; 19071 + case NM_SUBQH_R_PH: 19072 + check_dspr2(ctx); 19073 + switch (extract32(ctx->opcode, 10, 1)) { 19074 + case 0: 19075 + /* SUBQH_PH */ 19076 + gen_helper_subqh_ph(v1_t, v1_t, v2_t); 19077 + gen_store_gpr(v1_t, ret); 19078 + break; 19079 + case 1: 19080 + /* SUBQH_R_PH */ 19081 + gen_helper_subqh_r_ph(v1_t, v1_t, v2_t); 19082 + gen_store_gpr(v1_t, ret); 19083 + break; 19084 + } 19085 + break; 19086 + case NM_SUBQH_R_W: 19087 + check_dspr2(ctx); 19088 + switch (extract32(ctx->opcode, 10, 1)) { 19089 + case 0: 19090 + /* SUBQH_W */ 19091 + gen_helper_subqh_w(v1_t, v1_t, v2_t); 19092 + gen_store_gpr(v1_t, ret); 19093 + break; 19094 + case 1: 19095 + /* SUBQH_R_W */ 19096 + gen_helper_subqh_r_w(v1_t, v1_t, v2_t); 19097 + gen_store_gpr(v1_t, ret); 19098 + break; 19099 + } 19100 + break; 19101 + case NM_SUBU_S_QB: 19102 + check_dsp(ctx); 19103 + switch (extract32(ctx->opcode, 10, 1)) { 19104 + case 0: 19105 + /* SUBU_QB */ 19106 + gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env); 19107 + gen_store_gpr(v1_t, ret); 19108 + break; 19109 + case 1: 19110 + /* SUBU_S_QB */ 19111 + gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env); 19112 + gen_store_gpr(v1_t, ret); 19113 + break; 19114 + } 19115 + break; 19116 + case NM_SUBU_S_PH: 19117 + check_dspr2(ctx); 19118 + switch (extract32(ctx->opcode, 10, 1)) { 19119 + case 0: 19120 + /* SUBU_PH */ 19121 + gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env); 19122 + gen_store_gpr(v1_t, ret); 19123 + break; 19124 + case 1: 19125 + /* SUBU_S_PH */ 19126 + gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env); 19127 + gen_store_gpr(v1_t, ret); 19128 + break; 19129 + } 19130 + break; 19131 + case NM_SUBUH_R_QB: 19132 + check_dspr2(ctx); 19133 + switch (extract32(ctx->opcode, 10, 1)) { 19134 + case 0: 19135 + /* SUBUH_QB */ 19136 + gen_helper_subuh_qb(v1_t, v1_t, v2_t); 19137 + gen_store_gpr(v1_t, ret); 19138 + break; 19139 + case 1: 19140 + /* SUBUH_R_QB */ 19141 + gen_helper_subuh_r_qb(v1_t, v1_t, v2_t); 19142 + gen_store_gpr(v1_t, ret); 19143 + break; 19144 + } 19145 + break; 19146 + case NM_SHLLV_S_PH: 19147 + check_dsp(ctx); 19148 + switch (extract32(ctx->opcode, 10, 1)) { 19149 + case 0: 19150 + /* SHLLV_PH */ 19151 + gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env); 19152 + gen_store_gpr(v1_t, ret); 19153 + break; 19154 + case 1: 19155 + /* SHLLV_S_PH */ 19156 + gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env); 19157 + gen_store_gpr(v1_t, ret); 19158 + break; 19159 + } 19160 + break; 19161 + case NM_PRECR_SRA_R_PH_W: 19162 + check_dspr2(ctx); 19163 + switch (extract32(ctx->opcode, 10, 1)) { 19164 + case 0: 19165 + /* PRECR_SRA_PH_W */ 19166 + { 19167 + TCGv_i32 sa_t = tcg_const_i32(rd); 19168 + gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t, 19169 + cpu_gpr[rt]); 19170 + gen_store_gpr(v1_t, rt); 19171 + tcg_temp_free_i32(sa_t); 19172 + } 19173 + break; 19174 + case 1: 19175 + /* PRECR_SRA_R_PH_W */ 19176 + { 19177 + TCGv_i32 sa_t = tcg_const_i32(rd); 19178 + gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t, 19179 + cpu_gpr[rt]); 19180 + gen_store_gpr(v1_t, rt); 19181 + tcg_temp_free_i32(sa_t); 19182 + } 19183 + break; 19184 + } 19185 + break; 19186 + case NM_MULEU_S_PH_QBL: 19187 + check_dsp(ctx); 19188 + gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env); 19189 + gen_store_gpr(v1_t, ret); 19190 + break; 19191 + case NM_MULEU_S_PH_QBR: 19192 + check_dsp(ctx); 19193 + gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env); 19194 + gen_store_gpr(v1_t, ret); 19195 + break; 19196 + case NM_MULQ_RS_PH: 19197 + check_dsp(ctx); 19198 + gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env); 19199 + gen_store_gpr(v1_t, ret); 19200 + break; 19201 + case NM_MULQ_S_PH: 19202 + check_dspr2(ctx); 19203 + gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env); 19204 + gen_store_gpr(v1_t, ret); 19205 + break; 19206 + case NM_MULQ_RS_W: 19207 + check_dspr2(ctx); 19208 + gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env); 19209 + gen_store_gpr(v1_t, ret); 19210 + break; 19211 + case NM_MULQ_S_W: 19212 + check_dspr2(ctx); 19213 + gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env); 19214 + gen_store_gpr(v1_t, ret); 19215 + break; 19216 + case NM_APPEND: 19217 + check_dspr2(ctx); 19218 + gen_load_gpr(t0, rs); 19219 + if (rd != 0) { 19220 + tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd); 19221 + } 19222 + tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]); 19223 + break; 19224 + case NM_MODSUB: 19225 + check_dsp(ctx); 19226 + gen_helper_modsub(v1_t, v1_t, v2_t); 19227 + gen_store_gpr(v1_t, ret); 19228 + break; 19229 + case NM_SHRAV_R_W: 19230 + check_dsp(ctx); 19231 + gen_helper_shra_r_w(v1_t, v1_t, v2_t); 19232 + gen_store_gpr(v1_t, ret); 19233 + break; 19234 + case NM_SHRLV_PH: 19235 + check_dspr2(ctx); 19236 + gen_helper_shrl_ph(v1_t, v1_t, v2_t); 19237 + gen_store_gpr(v1_t, ret); 19238 + break; 19239 + case NM_SHRLV_QB: 19240 + check_dsp(ctx); 19241 + gen_helper_shrl_qb(v1_t, v1_t, v2_t); 19242 + gen_store_gpr(v1_t, ret); 19243 + break; 19244 + case NM_SHLLV_QB: 19245 + check_dsp(ctx); 19246 + gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env); 19247 + gen_store_gpr(v1_t, ret); 19248 + break; 19249 + case NM_SHLLV_S_W: 19250 + check_dsp(ctx); 19251 + gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env); 19252 + gen_store_gpr(v1_t, ret); 19253 + break; 19254 + case NM_SHILO: 19255 + check_dsp(ctx); 19256 + { 19257 + TCGv tv0 = tcg_temp_new(); 19258 + TCGv tv1 = tcg_temp_new(); 19259 + int16_t imm = extract32(ctx->opcode, 16, 7); 19260 + 19261 + tcg_gen_movi_tl(tv0, rd >> 3); 19262 + tcg_gen_movi_tl(tv1, imm); 19263 + gen_helper_shilo(tv0, tv1, cpu_env); 19264 + } 19265 + break; 19266 + case NM_MULEQ_S_W_PHL: 19267 + check_dsp(ctx); 19268 + gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env); 19269 + gen_store_gpr(v1_t, ret); 19270 + break; 19271 + case NM_MULEQ_S_W_PHR: 19272 + check_dsp(ctx); 19273 + gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env); 19274 + gen_store_gpr(v1_t, ret); 19275 + break; 19276 + case NM_MUL_S_PH: 19277 + check_dspr2(ctx); 19278 + switch (extract32(ctx->opcode, 10, 1)) { 19279 + case 0: 19280 + /* MUL_PH */ 19281 + gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env); 19282 + gen_store_gpr(v1_t, ret); 19283 + break; 19284 + case 1: 19285 + /* MUL_S_PH */ 19286 + gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env); 19287 + gen_store_gpr(v1_t, ret); 19288 + break; 19289 + } 19290 + break; 19291 + case NM_PRECR_QB_PH: 19292 + check_dspr2(ctx); 19293 + gen_helper_precr_qb_ph(v1_t, v1_t, v2_t); 19294 + gen_store_gpr(v1_t, ret); 19295 + break; 19296 + case NM_PRECRQ_QB_PH: 19297 + check_dsp(ctx); 19298 + gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t); 19299 + gen_store_gpr(v1_t, ret); 19300 + break; 19301 + case NM_PRECRQ_PH_W: 19302 + check_dsp(ctx); 19303 + gen_helper_precrq_ph_w(v1_t, v1_t, v2_t); 19304 + gen_store_gpr(v1_t, ret); 19305 + break; 19306 + case NM_PRECRQ_RS_PH_W: 19307 + check_dsp(ctx); 19308 + gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env); 19309 + gen_store_gpr(v1_t, ret); 19310 + break; 19311 + case NM_PRECRQU_S_QB_PH: 19312 + check_dsp(ctx); 19313 + gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env); 19314 + gen_store_gpr(v1_t, ret); 19315 + break; 19316 + case NM_SHRA_R_W: 19317 + check_dsp(ctx); 19318 + tcg_gen_movi_tl(t0, rd); 19319 + gen_helper_shra_r_w(v1_t, t0, v1_t); 19320 + gen_store_gpr(v1_t, rt); 19321 + break; 19322 + case NM_SHRA_R_PH: 19323 + check_dsp(ctx); 19324 + tcg_gen_movi_tl(t0, rd >> 1); 19325 + switch (extract32(ctx->opcode, 10, 1)) { 19326 + case 0: 19327 + /* SHRA_PH */ 19328 + gen_helper_shra_ph(v1_t, t0, v1_t); 19329 + break; 19330 + gen_store_gpr(v1_t, rt); 19331 + case 1: 19332 + /* SHRA_R_PH */ 19333 + gen_helper_shra_r_ph(v1_t, t0, v1_t); 19334 + gen_store_gpr(v1_t, rt); 19335 + break; 19336 + } 19337 + break; 19338 + case NM_SHLL_S_PH: 19339 + check_dsp(ctx); 19340 + tcg_gen_movi_tl(t0, rd >> 1); 19341 + switch (extract32(ctx->opcode, 10, 2)) { 19342 + case 0: 19343 + /* SHLL_PH */ 19344 + gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env); 19345 + gen_store_gpr(v1_t, rt); 19346 + break; 19347 + case 2: 19348 + /* SHLL_S_PH */ 19349 + gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env); 19350 + gen_store_gpr(v1_t, rt); 19351 + break; 19352 + default: 19353 + generate_exception_end(ctx, EXCP_RI); 19354 + break; 19355 + } 19356 + break; 19357 + case NM_SHLL_S_W: 19358 + check_dsp(ctx); 19359 + tcg_gen_movi_tl(t0, rd); 19360 + gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env); 19361 + gen_store_gpr(v1_t, rt); 19362 + break; 19363 + case NM_REPL_PH: 19364 + check_dsp(ctx); 19365 + { 19366 + int16_t imm; 19367 + imm = sextract32(ctx->opcode, 11, 11); 19368 + imm = (int16_t)(imm << 6) >> 6; 19369 + if (rt != 0) { 19370 + tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm)); 19371 + } 19372 + } 19373 + break; 19374 + default: 19375 + generate_exception_end(ctx, EXCP_RI); 19376 + break; 19377 + } 19378 + } 19379 + 19380 + static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx) 19381 + { 19382 + uint16_t insn; 19383 + uint32_t op; 19384 + int rt, rs, rd; 19385 + int offset; 19386 + int imm; 19387 + 19388 + insn = cpu_lduw_code(env, ctx->base.pc_next + 2); 19389 + ctx->opcode = (ctx->opcode << 16) | insn; 19390 + 19391 + rt = extract32(ctx->opcode, 21, 5); 19392 + rs = extract32(ctx->opcode, 16, 5); 19393 + rd = extract32(ctx->opcode, 11, 5); 19394 + 19395 + op = extract32(ctx->opcode, 26, 6); 19396 + switch (op) { 19397 + case NM_P_ADDIU: 19398 + if (rt == 0) { 19399 + /* P.RI */ 19400 + switch (extract32(ctx->opcode, 19, 2)) { 19401 + case NM_SIGRIE: 19402 + default: 19403 + generate_exception_end(ctx, EXCP_RI); 19404 + break; 19405 + case NM_P_SYSCALL: 19406 + if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) { 19407 + generate_exception_end(ctx, EXCP_SYSCALL); 19408 + } else { 19409 + generate_exception_end(ctx, EXCP_RI); 19410 + } 19411 + break; 19412 + case NM_BREAK: 19413 + generate_exception_end(ctx, EXCP_BREAK); 19414 + break; 19415 + case NM_SDBBP: 19416 + if (is_uhi(extract32(ctx->opcode, 0, 19))) { 19417 + gen_helper_do_semihosting(cpu_env); 19418 + } else { 19419 + if (ctx->hflags & MIPS_HFLAG_SBRI) { 19420 + generate_exception_end(ctx, EXCP_RI); 19421 + } else { 19422 + generate_exception_end(ctx, EXCP_DBp); 19423 + } 19424 + } 19425 + break; 19426 + } 19427 + } else { 19428 + /* NM_ADDIU */ 19429 + imm = extract32(ctx->opcode, 0, 16); 19430 + if (rs != 0) { 19431 + tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm); 19432 + } else { 19433 + tcg_gen_movi_tl(cpu_gpr[rt], imm); 19434 + } 19435 + tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]); 19436 + } 19437 + break; 19438 + case NM_ADDIUPC: 19439 + if (rt != 0) { 19440 + offset = sextract32(ctx->opcode, 0, 1) << 21 | 19441 + extract32(ctx->opcode, 1, 20) << 1; 19442 + target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset); 19443 + tcg_gen_movi_tl(cpu_gpr[rt], addr); 19444 + } 19445 + break; 19446 + case NM_POOL32A: 19447 + switch (ctx->opcode & 0x07) { 19448 + case NM_POOL32A0: 19449 + gen_pool32a0_nanomips_insn(env, ctx); 19450 + break; 19451 + case NM_POOL32A5: 19452 + { 19453 + int32_t op1 = extract32(ctx->opcode, 3, 7); 19454 + gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt); 19455 + } 19456 + break; 19457 + case NM_POOL32A7: 19458 + switch (extract32(ctx->opcode, 3, 3)) { 19459 + case NM_P_LSX: 19460 + gen_p_lsx(ctx, rd, rs, rt); 19461 + break; 19462 + case NM_LSA: 19463 + /* In nanoMIPS, the shift field directly encodes the shift 19464 + * amount, meaning that the supported shift values are in 19465 + * the range 0 to 3 (instead of 1 to 4 in MIPSR6). */ 19466 + gen_lsa(ctx, OPC_LSA, rd, rs, rt, 19467 + extract32(ctx->opcode, 9, 2) - 1); 19468 + break; 19469 + case NM_EXTW: 19470 + gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5)); 19471 + break; 19472 + case NM_POOL32AXF: 19473 + gen_pool32axf_nanomips_insn(env, ctx); 19474 + break; 19475 + default: 19476 + generate_exception_end(ctx, EXCP_RI); 19477 + break; 19478 + } 19479 + break; 19480 + default: 19481 + generate_exception_end(ctx, EXCP_RI); 19482 + break; 19483 + } 19484 + break; 19485 + case NM_P_GP_W: 19486 + switch (ctx->opcode & 0x03) { 19487 + case NM_ADDIUGP_W: 19488 + if (rt != 0) { 19489 + offset = extract32(ctx->opcode, 0, 21); 19490 + gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset); 19491 + } 19492 + break; 19493 + case NM_LWGP: 19494 + gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2); 19495 + break; 19496 + case NM_SWGP: 19497 + gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2); 19498 + break; 19499 + default: 19500 + generate_exception_end(ctx, EXCP_RI); 19501 + break; 19502 + } 19503 + break; 19504 + case NM_P48I: 19505 + { 19506 + insn = cpu_lduw_code(env, ctx->base.pc_next + 4); 19507 + target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16; 19508 + switch (extract32(ctx->opcode, 16, 5)) { 19509 + case NM_LI48: 19510 + check_nms(ctx); 19511 + if (rt != 0) { 19512 + tcg_gen_movi_tl(cpu_gpr[rt], addr_off); 19513 + } 19514 + break; 19515 + case NM_ADDIU48: 19516 + check_nms(ctx); 19517 + if (rt != 0) { 19518 + tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off); 19519 + tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]); 19520 + } 19521 + break; 19522 + case NM_ADDIUGP48: 19523 + check_nms(ctx); 19524 + if (rt != 0) { 19525 + gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off); 19526 + } 19527 + break; 19528 + case NM_ADDIUPC48: 19529 + check_nms(ctx); 19530 + if (rt != 0) { 19531 + target_long addr = addr_add(ctx, ctx->base.pc_next + 6, 19532 + addr_off); 19533 + 19534 + tcg_gen_movi_tl(cpu_gpr[rt], addr); 19535 + } 19536 + break; 19537 + case NM_LWPC48: 19538 + check_nms(ctx); 19539 + if (rt != 0) { 19540 + TCGv t0; 19541 + t0 = tcg_temp_new(); 19542 + 19543 + target_long addr = addr_add(ctx, ctx->base.pc_next + 6, 19544 + addr_off); 19545 + 19546 + tcg_gen_movi_tl(t0, addr); 19547 + tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL); 19548 + tcg_temp_free(t0); 19549 + } 19550 + break; 19551 + case NM_SWPC48: 19552 + check_nms(ctx); 19553 + { 19554 + TCGv t0, t1; 19555 + t0 = tcg_temp_new(); 19556 + t1 = tcg_temp_new(); 19557 + 19558 + target_long addr = addr_add(ctx, ctx->base.pc_next + 6, 19559 + addr_off); 19560 + 19561 + tcg_gen_movi_tl(t0, addr); 19562 + gen_load_gpr(t1, rt); 19563 + 19564 + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); 19565 + 19566 + tcg_temp_free(t0); 19567 + tcg_temp_free(t1); 19568 + } 19569 + break; 19570 + default: 19571 + generate_exception_end(ctx, EXCP_RI); 19572 + break; 19573 + } 19574 + return 6; 19575 + } 19576 + case NM_P_U12: 19577 + switch (extract32(ctx->opcode, 12, 4)) { 19578 + case NM_ORI: 19579 + gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12)); 19580 + break; 19581 + case NM_XORI: 19582 + gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12)); 19583 + break; 19584 + case NM_ANDI: 19585 + gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12)); 19586 + break; 19587 + case NM_P_SR: 19588 + switch (extract32(ctx->opcode, 20, 1)) { 19589 + case NM_PP_SR: 19590 + switch (ctx->opcode & 3) { 19591 + case NM_SAVE: 19592 + gen_save(ctx, rt, extract32(ctx->opcode, 16, 4), 19593 + extract32(ctx->opcode, 2, 1), 19594 + extract32(ctx->opcode, 3, 9) << 3); 19595 + break; 19596 + case NM_RESTORE: 19597 + case NM_RESTORE_JRC: 19598 + gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4), 19599 + extract32(ctx->opcode, 2, 1), 19600 + extract32(ctx->opcode, 3, 9) << 3); 19601 + if ((ctx->opcode & 3) == NM_RESTORE_JRC) { 19602 + gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0); 19603 + } 19604 + break; 19605 + default: 19606 + generate_exception_end(ctx, EXCP_RI); 19607 + break; 19608 + } 19609 + break; 19610 + case NM_P_SR_F: 19611 + generate_exception_end(ctx, EXCP_RI); 19612 + break; 19613 + } 19614 + break; 19615 + case NM_SLTI: 19616 + gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12)); 19617 + break; 19618 + case NM_SLTIU: 19619 + gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12)); 19620 + break; 19621 + case NM_SEQI: 19622 + { 19623 + TCGv t0 = tcg_temp_new(); 19624 + 19625 + imm = extract32(ctx->opcode, 0, 12); 19626 + gen_load_gpr(t0, rs); 19627 + tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm); 19628 + gen_store_gpr(t0, rt); 19629 + 19630 + tcg_temp_free(t0); 19631 + } 19632 + break; 19633 + case NM_ADDIUNEG: 19634 + imm = (int16_t) extract32(ctx->opcode, 0, 12); 19635 + gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm); 19636 + break; 19637 + case NM_P_SHIFT: 19638 + { 19639 + int shift = extract32(ctx->opcode, 0, 5); 19640 + switch (extract32(ctx->opcode, 5, 4)) { 19641 + case NM_P_SLL: 19642 + if (rt == 0 && shift == 0) { 19643 + /* NOP */ 19644 + } else if (rt == 0 && shift == 3) { 19645 + /* EHB - treat as NOP */ 19646 + } else if (rt == 0 && shift == 5) { 19647 + /* PAUSE - treat as NOP */ 19648 + } else if (rt == 0 && shift == 6) { 19649 + /* SYNC */ 19650 + gen_sync(extract32(ctx->opcode, 16, 5)); 19651 + } else { 19652 + /* SLL */ 19653 + gen_shift_imm(ctx, OPC_SLL, rt, rs, 19654 + extract32(ctx->opcode, 0, 5)); 19655 + } 19656 + break; 19657 + case NM_SRL: 19658 + gen_shift_imm(ctx, OPC_SRL, rt, rs, 19659 + extract32(ctx->opcode, 0, 5)); 19660 + break; 19661 + case NM_SRA: 19662 + gen_shift_imm(ctx, OPC_SRA, rt, rs, 19663 + extract32(ctx->opcode, 0, 5)); 19664 + break; 19665 + case NM_ROTR: 19666 + gen_shift_imm(ctx, OPC_ROTR, rt, rs, 19667 + extract32(ctx->opcode, 0, 5)); 19668 + break; 19669 + } 19670 + } 19671 + break; 19672 + case NM_P_ROTX: 19673 + check_nms(ctx); 19674 + if (rt != 0) { 19675 + TCGv t0 = tcg_temp_new(); 19676 + TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5)); 19677 + TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4) 19678 + << 1); 19679 + TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1)); 19680 + 19681 + gen_load_gpr(t0, rs); 19682 + gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe); 19683 + tcg_temp_free(t0); 19684 + 19685 + tcg_temp_free_i32(shift); 19686 + tcg_temp_free_i32(shiftx); 19687 + tcg_temp_free_i32(stripe); 19688 + } 19689 + break; 19690 + case NM_P_INS: 19691 + switch (((ctx->opcode >> 10) & 2) | 19692 + (extract32(ctx->opcode, 5, 1))) { 19693 + case NM_INS: 19694 + check_nms(ctx); 19695 + gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5), 19696 + extract32(ctx->opcode, 6, 5)); 19697 + break; 19698 + default: 19699 + generate_exception_end(ctx, EXCP_RI); 19700 + break; 19701 + } 19702 + break; 19703 + case NM_P_EXT: 19704 + switch (((ctx->opcode >> 10) & 2) | 19705 + (extract32(ctx->opcode, 5, 1))) { 19706 + case NM_EXT: 19707 + check_nms(ctx); 19708 + gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5), 19709 + extract32(ctx->opcode, 6, 5)); 19710 + break; 19711 + default: 19712 + generate_exception_end(ctx, EXCP_RI); 19713 + break; 19714 + } 19715 + break; 19716 + default: 19717 + generate_exception_end(ctx, EXCP_RI); 19718 + break; 19719 + } 19720 + break; 19721 + case NM_POOL32F: 19722 + gen_pool32f_nanomips_insn(ctx); 19723 + break; 19724 + case NM_POOL32S: 19725 + break; 19726 + case NM_P_LUI: 19727 + switch (extract32(ctx->opcode, 1, 1)) { 19728 + case NM_LUI: 19729 + if (rt != 0) { 19730 + tcg_gen_movi_tl(cpu_gpr[rt], 19731 + sextract32(ctx->opcode, 0, 1) << 31 | 19732 + extract32(ctx->opcode, 2, 10) << 21 | 19733 + extract32(ctx->opcode, 12, 9) << 12); 19734 + } 19735 + break; 19736 + case NM_ALUIPC: 19737 + if (rt != 0) { 19738 + offset = sextract32(ctx->opcode, 0, 1) << 31 | 19739 + extract32(ctx->opcode, 2, 10) << 21 | 19740 + extract32(ctx->opcode, 12, 9) << 12; 19741 + target_long addr; 19742 + addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset); 19743 + tcg_gen_movi_tl(cpu_gpr[rt], addr); 19744 + } 19745 + break; 19746 + } 19747 + break; 19748 + case NM_P_GP_BH: 19749 + { 19750 + uint32_t u = extract32(ctx->opcode, 0, 18); 19751 + 19752 + switch (extract32(ctx->opcode, 18, 3)) { 19753 + case NM_LBGP: 19754 + gen_ld(ctx, OPC_LB, rt, 28, u); 19755 + break; 19756 + case NM_SBGP: 19757 + gen_st(ctx, OPC_SB, rt, 28, u); 19758 + break; 19759 + case NM_LBUGP: 19760 + gen_ld(ctx, OPC_LBU, rt, 28, u); 19761 + break; 19762 + case NM_ADDIUGP_B: 19763 + if (rt != 0) { 19764 + gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u); 19765 + } 19766 + break; 19767 + case NM_P_GP_LH: 19768 + u &= ~1; 19769 + switch (ctx->opcode & 1) { 19770 + case NM_LHGP: 19771 + gen_ld(ctx, OPC_LH, rt, 28, u); 19772 + break; 19773 + case NM_LHUGP: 19774 + gen_ld(ctx, OPC_LHU, rt, 28, u); 19775 + break; 19776 + } 19777 + break; 19778 + case NM_P_GP_SH: 19779 + u &= ~1; 19780 + switch (ctx->opcode & 1) { 19781 + case NM_SHGP: 19782 + gen_st(ctx, OPC_SH, rt, 28, u); 19783 + break; 19784 + default: 19785 + generate_exception_end(ctx, EXCP_RI); 19786 + break; 19787 + } 19788 + break; 19789 + case NM_P_GP_CP1: 19790 + u &= ~0x3; 19791 + switch (ctx->opcode & 0x3) { 19792 + case NM_LWC1GP: 19793 + gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u); 19794 + break; 19795 + case NM_LDC1GP: 19796 + gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u); 19797 + break; 19798 + case NM_SWC1GP: 19799 + gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u); 19800 + break; 19801 + case NM_SDC1GP: 19802 + gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u); 19803 + break; 19804 + } 19805 + break; 19806 + default: 19807 + generate_exception_end(ctx, EXCP_RI); 19808 + break; 19809 + } 19810 + } 19811 + break; 19812 + case NM_P_LS_U12: 19813 + { 19814 + uint32_t u = extract32(ctx->opcode, 0, 12); 19815 + 19816 + switch (extract32(ctx->opcode, 12, 4)) { 19817 + case NM_P_PREFU12: 19818 + if (rt == 31) { 19819 + /* SYNCI */ 19820 + /* Break the TB to be able to sync copied instructions 19821 + immediately */ 19822 + ctx->base.is_jmp = DISAS_STOP; 19823 + } else { 19824 + /* PREF */ 19825 + /* Treat as NOP. */ 19826 + } 19827 + break; 19828 + case NM_LB: 19829 + gen_ld(ctx, OPC_LB, rt, rs, u); 19830 + break; 19831 + case NM_LH: 19832 + gen_ld(ctx, OPC_LH, rt, rs, u); 19833 + break; 19834 + case NM_LW: 19835 + gen_ld(ctx, OPC_LW, rt, rs, u); 19836 + break; 19837 + case NM_LBU: 19838 + gen_ld(ctx, OPC_LBU, rt, rs, u); 19839 + break; 19840 + case NM_LHU: 19841 + gen_ld(ctx, OPC_LHU, rt, rs, u); 19842 + break; 19843 + case NM_SB: 19844 + gen_st(ctx, OPC_SB, rt, rs, u); 19845 + break; 19846 + case NM_SH: 19847 + gen_st(ctx, OPC_SH, rt, rs, u); 19848 + break; 19849 + case NM_SW: 19850 + gen_st(ctx, OPC_SW, rt, rs, u); 19851 + break; 19852 + case NM_LWC1: 19853 + gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u); 19854 + break; 19855 + case NM_LDC1: 19856 + gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u); 19857 + break; 19858 + case NM_SWC1: 19859 + gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u); 19860 + break; 19861 + case NM_SDC1: 19862 + gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u); 19863 + break; 19864 + default: 19865 + generate_exception_end(ctx, EXCP_RI); 19866 + break; 19867 + } 19868 + } 19869 + break; 19870 + case NM_P_LS_S9: 19871 + { 19872 + int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) | 19873 + extract32(ctx->opcode, 0, 8); 19874 + 19875 + switch (extract32(ctx->opcode, 8, 3)) { 19876 + case NM_P_LS_S0: 19877 + switch (extract32(ctx->opcode, 11, 4)) { 19878 + case NM_LBS9: 19879 + gen_ld(ctx, OPC_LB, rt, rs, s); 19880 + break; 19881 + case NM_LHS9: 19882 + gen_ld(ctx, OPC_LH, rt, rs, s); 19883 + break; 19884 + case NM_LWS9: 19885 + gen_ld(ctx, OPC_LW, rt, rs, s); 19886 + break; 19887 + case NM_LBUS9: 19888 + gen_ld(ctx, OPC_LBU, rt, rs, s); 19889 + break; 19890 + case NM_LHUS9: 19891 + gen_ld(ctx, OPC_LHU, rt, rs, s); 19892 + break; 19893 + case NM_SBS9: 19894 + gen_st(ctx, OPC_SB, rt, rs, s); 19895 + break; 19896 + case NM_SHS9: 19897 + gen_st(ctx, OPC_SH, rt, rs, s); 19898 + break; 19899 + case NM_SWS9: 19900 + gen_st(ctx, OPC_SW, rt, rs, s); 19901 + break; 19902 + case NM_LWC1S9: 19903 + gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s); 19904 + break; 19905 + case NM_LDC1S9: 19906 + gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s); 19907 + break; 19908 + case NM_SWC1S9: 19909 + gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s); 19910 + break; 19911 + case NM_SDC1S9: 19912 + gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s); 19913 + break; 19914 + case NM_P_PREFS9: 19915 + if (rt == 31) { 19916 + /* SYNCI */ 19917 + /* Break the TB to be able to sync copied instructions 19918 + immediately */ 19919 + ctx->base.is_jmp = DISAS_STOP; 19920 + } else { 19921 + /* PREF */ 19922 + /* Treat as NOP. */ 19923 + } 19924 + break; 19925 + default: 19926 + generate_exception_end(ctx, EXCP_RI); 19927 + break; 19928 + } 19929 + break; 19930 + case NM_P_LS_S1: 19931 + switch (extract32(ctx->opcode, 11, 4)) { 19932 + case NM_UALH: 19933 + case NM_UASH: 19934 + check_nms(ctx); 19935 + { 19936 + TCGv t0 = tcg_temp_new(); 19937 + TCGv t1 = tcg_temp_new(); 19938 + 19939 + gen_base_offset_addr(ctx, t0, rs, s); 19940 + 19941 + switch (extract32(ctx->opcode, 11, 4)) { 19942 + case NM_UALH: 19943 + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW | 19944 + MO_UNALN); 19945 + gen_store_gpr(t0, rt); 19946 + break; 19947 + case NM_UASH: 19948 + gen_load_gpr(t1, rt); 19949 + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW | 19950 + MO_UNALN); 19951 + break; 19952 + } 19953 + tcg_temp_free(t0); 19954 + tcg_temp_free(t1); 19955 + } 19956 + break; 19957 + case NM_P_LL: 19958 + switch (ctx->opcode & 0x03) { 19959 + case NM_LL: 19960 + gen_ld(ctx, OPC_LL, rt, rs, s); 19961 + break; 19962 + case NM_LLWP: 19963 + check_xnp(ctx); 19964 + gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5)); 19965 + break; 19966 + } 19967 + break; 19968 + case NM_P_SC: 19969 + switch (ctx->opcode & 0x03) { 19970 + case NM_SC: 19971 + gen_st_cond(ctx, OPC_SC, rt, rs, s); 19972 + break; 19973 + case NM_SCWP: 19974 + check_xnp(ctx); 19975 + gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5)); 19976 + break; 19977 + } 19978 + break; 19979 + case NM_CACHE: 19980 + check_cp0_enabled(ctx); 19981 + if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) { 19982 + gen_cache_operation(ctx, rt, rs, s); 19983 + } 19984 + break; 19985 + } 19986 + break; 19987 + case NM_P_LS_WM: 19988 + case NM_P_LS_UAWM: 19989 + check_nms(ctx); 19990 + { 19991 + int count = extract32(ctx->opcode, 12, 3); 19992 + int counter = 0; 19993 + 19994 + offset = sextract32(ctx->opcode, 15, 1) << 8 | 19995 + extract32(ctx->opcode, 0, 8); 19996 + TCGv va = tcg_temp_new(); 19997 + TCGv t1 = tcg_temp_new(); 19998 + TCGMemOp memop = (extract32(ctx->opcode, 8, 3)) == 19999 + NM_P_LS_UAWM ? MO_UNALN : 0; 20000 + 20001 + count = (count == 0) ? 8 : count; 20002 + while (counter != count) { 20003 + int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10); 20004 + int this_offset = offset + (counter << 2); 20005 + 20006 + gen_base_offset_addr(ctx, va, rs, this_offset); 20007 + 20008 + switch (extract32(ctx->opcode, 11, 1)) { 20009 + case NM_LWM: 20010 + tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx, 20011 + memop | MO_TESL); 20012 + gen_store_gpr(t1, this_rt); 20013 + if ((this_rt == rs) && 20014 + (counter != (count - 1))) { 20015 + /* UNPREDICTABLE */ 20016 + } 20017 + break; 20018 + case NM_SWM: 20019 + this_rt = (rt == 0) ? 0 : this_rt; 20020 + gen_load_gpr(t1, this_rt); 20021 + tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx, 20022 + memop | MO_TEUL); 20023 + break; 20024 + } 20025 + counter++; 20026 + } 20027 + tcg_temp_free(va); 20028 + tcg_temp_free(t1); 20029 + } 20030 + break; 20031 + default: 20032 + generate_exception_end(ctx, EXCP_RI); 20033 + break; 20034 + } 20035 + } 20036 + break; 20037 + case NM_MOVE_BALC: 20038 + check_nms(ctx); 20039 + { 20040 + TCGv t0 = tcg_temp_new(); 20041 + int32_t s = sextract32(ctx->opcode, 0, 1) << 21 | 20042 + extract32(ctx->opcode, 1, 20) << 1; 20043 + rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5; 20044 + rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 | 20045 + extract32(ctx->opcode, 21, 3)); 20046 + gen_load_gpr(t0, rt); 20047 + tcg_gen_mov_tl(cpu_gpr[rd], t0); 20048 + gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s); 20049 + tcg_temp_free(t0); 20050 + } 20051 + break; 20052 + case NM_P_BAL: 20053 + { 20054 + int32_t s = sextract32(ctx->opcode, 0, 1) << 25 | 20055 + extract32(ctx->opcode, 1, 24) << 1; 20056 + 20057 + if ((extract32(ctx->opcode, 25, 1)) == 0) { 20058 + /* BC */ 20059 + gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s); 20060 + } else { 20061 + /* BALC */ 20062 + gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s); 20063 + } 20064 + } 20065 + break; 20066 + case NM_P_J: 20067 + switch (extract32(ctx->opcode, 12, 4)) { 20068 + case NM_JALRC: 20069 + case NM_JALRC_HB: 20070 + gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0); 20071 + break; 20072 + case NM_P_BALRSC: 20073 + gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt); 20074 + break; 20075 + default: 20076 + generate_exception_end(ctx, EXCP_RI); 20077 + break; 20078 + } 20079 + break; 20080 + case NM_P_BR1: 20081 + { 20082 + int32_t s = sextract32(ctx->opcode, 0, 1) << 14 | 20083 + extract32(ctx->opcode, 1, 13) << 1; 20084 + switch (extract32(ctx->opcode, 14, 2)) { 20085 + case NM_BEQC: 20086 + check_nms(ctx); 20087 + gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s); 20088 + break; 20089 + case NM_P_BR3A: 20090 + s = sextract32(ctx->opcode, 0, 1) << 14 | 20091 + extract32(ctx->opcode, 1, 13) << 1; 20092 + check_cp1_enabled(ctx); 20093 + switch (extract32(ctx->opcode, 16, 5)) { 20094 + case NM_BC1EQZC: 20095 + gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s); 20096 + break; 20097 + case NM_BC1NEZC: 20098 + gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s); 20099 + break; 20100 + case NM_BPOSGE32C: 20101 + check_dspr2(ctx); 20102 + { 20103 + int32_t imm = extract32(ctx->opcode, 1, 13) | 20104 + extract32(ctx->opcode, 0, 1) << 13; 20105 + 20106 + gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2, 20107 + imm); 20108 + } 20109 + break; 20110 + default: 20111 + generate_exception_end(ctx, EXCP_RI); 20112 + break; 20113 + } 20114 + break; 20115 + case NM_BGEC: 20116 + if (rs == rt) { 20117 + gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s); 20118 + } else { 20119 + gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s); 20120 + } 20121 + break; 20122 + case NM_BGEUC: 20123 + if (rs == rt || rt == 0) { 20124 + gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s); 20125 + } else if (rs == 0) { 20126 + gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s); 20127 + } else { 20128 + gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s); 20129 + } 20130 + break; 20131 + } 20132 + } 20133 + break; 20134 + case NM_P_BR2: 20135 + { 20136 + int32_t s = sextract32(ctx->opcode, 0, 1) << 14 | 20137 + extract32(ctx->opcode, 1, 13) << 1; 20138 + switch (extract32(ctx->opcode, 14, 2)) { 20139 + case NM_BNEC: 20140 + check_nms(ctx); 20141 + gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s); 20142 + break; 20143 + case NM_BLTC: 20144 + if (rs != 0 && rt != 0 && rs == rt) { 20145 + /* NOP */ 20146 + ctx->hflags |= MIPS_HFLAG_FBNSLOT; 20147 + } else { 20148 + gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s); 20149 + } 20150 + break; 20151 + case NM_BLTUC: 20152 + if (rs == 0 || rs == rt) { 20153 + /* NOP */ 20154 + ctx->hflags |= MIPS_HFLAG_FBNSLOT; 20155 + } else { 20156 + gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s); 20157 + } 20158 + break; 20159 + default: 20160 + generate_exception_end(ctx, EXCP_RI); 20161 + break; 20162 + } 20163 + } 20164 + break; 20165 + case NM_P_BRI: 20166 + { 20167 + int32_t s = sextract32(ctx->opcode, 0, 1) << 11 | 20168 + extract32(ctx->opcode, 1, 10) << 1; 20169 + uint32_t u = extract32(ctx->opcode, 11, 7); 20170 + 20171 + gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3), 20172 + rt, u, s); 20173 + } 20174 + break; 20175 + default: 20176 + generate_exception_end(ctx, EXCP_RI); 20177 + break; 20178 + } 20179 + return 4; 20180 + } 20181 + 20182 + static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx) 20183 + { 20184 + uint32_t op; 20185 + int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode)); 20186 + int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode)); 20187 + int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS1(ctx->opcode)); 20188 + int offset; 20189 + int imm; 20190 + 20191 + /* make sure instructions are on a halfword boundary */ 20192 + if (ctx->base.pc_next & 0x1) { 20193 + TCGv tmp = tcg_const_tl(ctx->base.pc_next); 20194 + tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); 20195 + tcg_temp_free(tmp); 20196 + generate_exception_end(ctx, EXCP_AdEL); 20197 + return 2; 20198 + } 20199 + 20200 + op = extract32(ctx->opcode, 10, 6); 20201 + switch (op) { 20202 + case NM_P16_MV: 20203 + rt = NANOMIPS_EXTRACT_RD5(ctx->opcode); 20204 + if (rt != 0) { 20205 + /* MOVE */ 20206 + rs = NANOMIPS_EXTRACT_RS5(ctx->opcode); 20207 + gen_arith(ctx, OPC_ADDU, rt, rs, 0); 20208 + } else { 20209 + /* P16.RI */ 20210 + switch (extract32(ctx->opcode, 3, 2)) { 20211 + case NM_P16_SYSCALL: 20212 + if (extract32(ctx->opcode, 2, 1) == 0) { 20213 + generate_exception_end(ctx, EXCP_SYSCALL); 20214 + } else { 20215 + generate_exception_end(ctx, EXCP_RI); 20216 + } 20217 + break; 20218 + case NM_BREAK16: 20219 + generate_exception_end(ctx, EXCP_BREAK); 20220 + break; 20221 + case NM_SDBBP16: 20222 + if (is_uhi(extract32(ctx->opcode, 0, 3))) { 20223 + gen_helper_do_semihosting(cpu_env); 20224 + } else { 20225 + if (ctx->hflags & MIPS_HFLAG_SBRI) { 20226 + generate_exception_end(ctx, EXCP_RI); 20227 + } else { 20228 + generate_exception_end(ctx, EXCP_DBp); 20229 + } 20230 + } 20231 + break; 20232 + default: 20233 + generate_exception_end(ctx, EXCP_RI); 20234 + break; 20235 + } 20236 + } 20237 + break; 20238 + case NM_P16_SHIFT: 20239 + { 20240 + int shift = extract32(ctx->opcode, 0, 3); 20241 + uint32_t opc = 0; 20242 + shift = (shift == 0) ? 8 : shift; 20243 + 20244 + switch (extract32(ctx->opcode, 3, 1)) { 20245 + case NM_SLL16: 20246 + opc = OPC_SLL; 20247 + break; 20248 + case NM_SRL16: 20249 + opc = OPC_SRL; 20250 + break; 20251 + } 20252 + gen_shift_imm(ctx, opc, rt, rs, shift); 20253 + } 20254 + break; 20255 + case NM_P16C: 20256 + switch (ctx->opcode & 1) { 20257 + case NM_POOL16C_0: 20258 + gen_pool16c_nanomips_insn(ctx); 20259 + break; 20260 + case NM_LWXS16: 20261 + gen_ldxs(ctx, rt, rs, rd); 20262 + break; 20263 + } 20264 + break; 20265 + case NM_P16_A1: 20266 + switch (extract32(ctx->opcode, 6, 1)) { 20267 + case NM_ADDIUR1SP: 20268 + imm = extract32(ctx->opcode, 0, 6) << 2; 20269 + gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm); 20270 + break; 20271 + default: 20272 + generate_exception_end(ctx, EXCP_RI); 20273 + break; 20274 + } 20275 + break; 20276 + case NM_P16_A2: 20277 + switch (extract32(ctx->opcode, 3, 1)) { 20278 + case NM_ADDIUR2: 20279 + imm = extract32(ctx->opcode, 0, 3) << 2; 20280 + gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm); 20281 + break; 20282 + case NM_P_ADDIURS5: 20283 + rt = extract32(ctx->opcode, 5, 5); 20284 + if (rt != 0) { 20285 + /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */ 20286 + imm = (sextract32(ctx->opcode, 4, 1) << 3) | 20287 + (extract32(ctx->opcode, 0, 3)); 20288 + gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm); 20289 + } 20290 + break; 20291 + } 20292 + break; 20293 + case NM_P16_ADDU: 20294 + switch (ctx->opcode & 0x1) { 20295 + case NM_ADDU16: 20296 + gen_arith(ctx, OPC_ADDU, rd, rs, rt); 20297 + break; 20298 + case NM_SUBU16: 20299 + gen_arith(ctx, OPC_SUBU, rd, rs, rt); 20300 + break; 20301 + } 20302 + break; 20303 + case NM_P16_4X4: 20304 + rt = (extract32(ctx->opcode, 9, 1) << 3) | 20305 + extract32(ctx->opcode, 5, 3); 20306 + rs = (extract32(ctx->opcode, 4, 1) << 3) | 20307 + extract32(ctx->opcode, 0, 3); 20308 + rt = decode_gpr_gpr4(rt); 20309 + rs = decode_gpr_gpr4(rs); 20310 + switch ((extract32(ctx->opcode, 7, 2) & 0x2) | 20311 + (extract32(ctx->opcode, 3, 1))) { 20312 + case NM_ADDU4X4: 20313 + check_nms(ctx); 20314 + gen_arith(ctx, OPC_ADDU, rt, rs, rt); 20315 + break; 20316 + case NM_MUL4X4: 20317 + check_nms(ctx); 20318 + gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt); 20319 + break; 20320 + default: 20321 + generate_exception_end(ctx, EXCP_RI); 20322 + break; 20323 + } 20324 + break; 20325 + case NM_LI16: 20326 + { 20327 + int imm = extract32(ctx->opcode, 0, 7); 20328 + imm = (imm == 0x7f ? -1 : imm); 20329 + if (rt != 0) { 20330 + tcg_gen_movi_tl(cpu_gpr[rt], imm); 20331 + } 20332 + } 20333 + break; 20334 + case NM_ANDI16: 20335 + { 20336 + uint32_t u = extract32(ctx->opcode, 0, 4); 20337 + u = (u == 12) ? 0xff : 20338 + (u == 13) ? 0xffff : u; 20339 + gen_logic_imm(ctx, OPC_ANDI, rt, rs, u); 20340 + } 20341 + break; 20342 + case NM_P16_LB: 20343 + offset = extract32(ctx->opcode, 0, 2); 20344 + switch (extract32(ctx->opcode, 2, 2)) { 20345 + case NM_LB16: 20346 + gen_ld(ctx, OPC_LB, rt, rs, offset); 20347 + break; 20348 + case NM_SB16: 20349 + rt = decode_gpr_gpr3_src_store( 20350 + NANOMIPS_EXTRACT_RD(ctx->opcode)); 20351 + gen_st(ctx, OPC_SB, rt, rs, offset); 20352 + break; 20353 + case NM_LBU16: 20354 + gen_ld(ctx, OPC_LBU, rt, rs, offset); 20355 + break; 20356 + default: 20357 + generate_exception_end(ctx, EXCP_RI); 20358 + break; 20359 + } 20360 + break; 20361 + case NM_P16_LH: 20362 + offset = extract32(ctx->opcode, 1, 2) << 1; 20363 + switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) { 20364 + case NM_LH16: 20365 + gen_ld(ctx, OPC_LH, rt, rs, offset); 20366 + break; 20367 + case NM_SH16: 20368 + rt = decode_gpr_gpr3_src_store( 20369 + NANOMIPS_EXTRACT_RD(ctx->opcode)); 20370 + gen_st(ctx, OPC_SH, rt, rs, offset); 20371 + break; 20372 + case NM_LHU16: 20373 + gen_ld(ctx, OPC_LHU, rt, rs, offset); 20374 + break; 20375 + default: 20376 + generate_exception_end(ctx, EXCP_RI); 20377 + break; 20378 + } 20379 + break; 20380 + case NM_LW16: 20381 + offset = extract32(ctx->opcode, 0, 4) << 2; 20382 + gen_ld(ctx, OPC_LW, rt, rs, offset); 20383 + break; 20384 + case NM_LWSP16: 20385 + rt = NANOMIPS_EXTRACT_RD5(ctx->opcode); 20386 + offset = extract32(ctx->opcode, 0, 5) << 2; 20387 + gen_ld(ctx, OPC_LW, rt, 29, offset); 20388 + break; 20389 + case NM_LW4X4: 20390 + check_nms(ctx); 20391 + rt = (extract32(ctx->opcode, 9, 1) << 3) | 20392 + extract32(ctx->opcode, 5, 3); 20393 + rs = (extract32(ctx->opcode, 4, 1) << 3) | 20394 + extract32(ctx->opcode, 0, 3); 20395 + offset = (extract32(ctx->opcode, 3, 1) << 3) | 20396 + (extract32(ctx->opcode, 8, 1) << 2); 20397 + rt = decode_gpr_gpr4(rt); 20398 + rs = decode_gpr_gpr4(rs); 20399 + gen_ld(ctx, OPC_LW, rt, rs, offset); 20400 + break; 20401 + case NM_SW4X4: 20402 + check_nms(ctx); 20403 + rt = (extract32(ctx->opcode, 9, 1) << 3) | 20404 + extract32(ctx->opcode, 5, 3); 20405 + rs = (extract32(ctx->opcode, 4, 1) << 3) | 20406 + extract32(ctx->opcode, 0, 3); 20407 + offset = (extract32(ctx->opcode, 3, 1) << 3) | 20408 + (extract32(ctx->opcode, 8, 1) << 2); 20409 + rt = decode_gpr_gpr4_zero(rt); 20410 + rs = decode_gpr_gpr4(rs); 20411 + gen_st(ctx, OPC_SW, rt, rs, offset); 20412 + break; 20413 + case NM_LWGP16: 20414 + offset = extract32(ctx->opcode, 0, 7) << 2; 20415 + gen_ld(ctx, OPC_LW, rt, 28, offset); 20416 + break; 20417 + case NM_SWSP16: 20418 + rt = NANOMIPS_EXTRACT_RD5(ctx->opcode); 20419 + offset = extract32(ctx->opcode, 0, 5) << 2; 20420 + gen_st(ctx, OPC_SW, rt, 29, offset); 20421 + break; 20422 + case NM_SW16: 20423 + rt = decode_gpr_gpr3_src_store( 20424 + NANOMIPS_EXTRACT_RD(ctx->opcode)); 20425 + rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode)); 20426 + offset = extract32(ctx->opcode, 0, 4) << 2; 20427 + gen_st(ctx, OPC_SW, rt, rs, offset); 20428 + break; 20429 + case NM_SWGP16: 20430 + rt = decode_gpr_gpr3_src_store( 20431 + NANOMIPS_EXTRACT_RD(ctx->opcode)); 20432 + offset = extract32(ctx->opcode, 0, 7) << 2; 20433 + gen_st(ctx, OPC_SW, rt, 28, offset); 20434 + break; 20435 + case NM_BC16: 20436 + gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0, 20437 + (sextract32(ctx->opcode, 0, 1) << 10) | 20438 + (extract32(ctx->opcode, 1, 9) << 1)); 20439 + break; 20440 + case NM_BALC16: 20441 + gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0, 20442 + (sextract32(ctx->opcode, 0, 1) << 10) | 20443 + (extract32(ctx->opcode, 1, 9) << 1)); 20444 + break; 20445 + case NM_BEQZC16: 20446 + gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0, 20447 + (sextract32(ctx->opcode, 0, 1) << 7) | 20448 + (extract32(ctx->opcode, 1, 6) << 1)); 20449 + break; 20450 + case NM_BNEZC16: 20451 + gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0, 20452 + (sextract32(ctx->opcode, 0, 1) << 7) | 20453 + (extract32(ctx->opcode, 1, 6) << 1)); 20454 + break; 20455 + case NM_P16_BR: 20456 + switch (ctx->opcode & 0xf) { 20457 + case 0: 20458 + /* P16.JRC */ 20459 + switch (extract32(ctx->opcode, 4, 1)) { 20460 + case NM_JRC: 20461 + gen_compute_branch_nm(ctx, OPC_JR, 2, 20462 + extract32(ctx->opcode, 5, 5), 0, 0); 20463 + break; 20464 + case NM_JALRC16: 20465 + gen_compute_branch_nm(ctx, OPC_JALR, 2, 20466 + extract32(ctx->opcode, 5, 5), 31, 0); 20467 + break; 20468 + } 20469 + break; 20470 + default: 20471 + { 20472 + /* P16.BRI */ 20473 + uint32_t opc = extract32(ctx->opcode, 4, 3) < 20474 + extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE; 20475 + gen_compute_branch_nm(ctx, opc, 2, rs, rt, 20476 + extract32(ctx->opcode, 0, 4) << 1); 20477 + } 20478 + break; 20479 + } 20480 + break; 20481 + case NM_P16_SR: 20482 + { 20483 + int count = extract32(ctx->opcode, 0, 4); 20484 + int u = extract32(ctx->opcode, 4, 4) << 4; 20485 + 20486 + rt = 30 + extract32(ctx->opcode, 9, 1); 20487 + switch (extract32(ctx->opcode, 8, 1)) { 20488 + case NM_SAVE16: 20489 + gen_save(ctx, rt, count, 0, u); 20490 + break; 20491 + case NM_RESTORE_JRC16: 20492 + gen_restore(ctx, rt, count, 0, u); 20493 + gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0); 20494 + break; 20495 + } 20496 + } 20497 + break; 20498 + case NM_MOVEP: 20499 + case NM_MOVEPREV: 20500 + check_nms(ctx); 20501 + { 20502 + static const int gpr2reg1[] = {4, 5, 6, 7}; 20503 + static const int gpr2reg2[] = {5, 6, 7, 8}; 20504 + int re; 20505 + int rd2 = extract32(ctx->opcode, 3, 1) << 1 | 20506 + extract32(ctx->opcode, 8, 1); 20507 + int r1 = gpr2reg1[rd2]; 20508 + int r2 = gpr2reg2[rd2]; 20509 + int r3 = extract32(ctx->opcode, 4, 1) << 3 | 20510 + extract32(ctx->opcode, 0, 3); 20511 + int r4 = extract32(ctx->opcode, 9, 1) << 3 | 20512 + extract32(ctx->opcode, 5, 3); 20513 + TCGv t0 = tcg_temp_new(); 20514 + TCGv t1 = tcg_temp_new(); 20515 + if (op == NM_MOVEP) { 20516 + rd = r1; 20517 + re = r2; 20518 + rs = decode_gpr_gpr4_zero(r3); 20519 + rt = decode_gpr_gpr4_zero(r4); 20520 + } else { 20521 + rd = decode_gpr_gpr4(r3); 20522 + re = decode_gpr_gpr4(r4); 20523 + rs = r1; 20524 + rt = r2; 20525 + } 20526 + gen_load_gpr(t0, rs); 20527 + gen_load_gpr(t1, rt); 20528 + tcg_gen_mov_tl(cpu_gpr[rd], t0); 20529 + tcg_gen_mov_tl(cpu_gpr[re], t1); 20530 + tcg_temp_free(t0); 20531 + tcg_temp_free(t1); 20532 + } 20533 + break; 20534 + default: 20535 + return decode_nanomips_32_48_opc(env, ctx); 20536 + } 20537 + 20538 + return 2; 20539 + } 20540 + 20541 + 15704 20542 /* SmartMIPS extension to MIPS32 */ 15705 20543 15706 20544 #if defined(TARGET_MIPS64) ··· 17901 22739 switch (op2) { 17902 22740 case OPC_ALIGN: 17903 22741 case OPC_ALIGN_END: 17904 - gen_align(ctx, OPC_ALIGN, rd, rs, rt, sa & 3); 22742 + gen_align(ctx, 32, rd, rs, rt, sa & 3); 17905 22743 break; 17906 22744 case OPC_BITSWAP: 17907 22745 gen_bitswap(ctx, op2, rd, rt); ··· 17927 22765 switch (op2) { 17928 22766 case OPC_DALIGN: 17929 22767 case OPC_DALIGN_END: 17930 - gen_align(ctx, OPC_DALIGN, rd, rs, rt, sa & 7); 22768 + gen_align(ctx, 64, rd, rs, rt, sa & 7); 17931 22769 break; 17932 22770 case OPC_DBITSWAP: 17933 22771 gen_bitswap(ctx, op2, rd, rt); ··· 18586 23424 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3)); 18587 23425 break; 18588 23426 case OPC_FORK: 18589 - check_insn(ctx, ASE_MT); 23427 + check_mt(ctx); 18590 23428 { 18591 23429 TCGv t0 = tcg_temp_new(); 18592 23430 TCGv t1 = tcg_temp_new(); ··· 18599 23437 } 18600 23438 break; 18601 23439 case OPC_YIELD: 18602 - check_insn(ctx, ASE_MT); 23440 + check_mt(ctx); 18603 23441 { 18604 23442 TCGv t0 = tcg_temp_new(); 18605 23443 ··· 19896 24734 op2 = MASK_MFMC0(ctx->opcode); 19897 24735 switch (op2) { 19898 24736 case OPC_DMT: 19899 - check_insn(ctx, ASE_MT); 24737 + check_cp0_mt(ctx); 19900 24738 gen_helper_dmt(t0); 19901 24739 gen_store_gpr(t0, rt); 19902 24740 break; 19903 24741 case OPC_EMT: 19904 - check_insn(ctx, ASE_MT); 24742 + check_cp0_mt(ctx); 19905 24743 gen_helper_emt(t0); 19906 24744 gen_store_gpr(t0, rt); 19907 24745 break; 19908 24746 case OPC_DVPE: 19909 - check_insn(ctx, ASE_MT); 24747 + check_cp0_mt(ctx); 19910 24748 gen_helper_dvpe(t0, cpu_env); 19911 24749 gen_store_gpr(t0, rt); 19912 24750 break; 19913 24751 case OPC_EVPE: 19914 - check_insn(ctx, ASE_MT); 24752 + check_cp0_mt(ctx); 19915 24753 gen_helper_evpe(t0, cpu_env); 19916 24754 gen_store_gpr(t0, rt); 19917 24755 break; ··· 20447 25285 ctx->saved_pc = -1; 20448 25286 ctx->insn_flags = env->insn_flags; 20449 25287 ctx->CP0_Config1 = env->CP0_Config1; 25288 + ctx->CP0_Config3 = env->CP0_Config3; 25289 + ctx->CP0_Config5 = env->CP0_Config5; 20450 25290 ctx->btarget = 0; 20451 25291 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff; 20452 25292 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1; ··· 20517 25357 int is_slot; 20518 25358 20519 25359 is_slot = ctx->hflags & MIPS_HFLAG_BMASK; 20520 - if (!(ctx->hflags & MIPS_HFLAG_M16)) { 25360 + if (ctx->insn_flags & ISA_NANOMIPS32) { 25361 + ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next); 25362 + insn_bytes = decode_nanomips_opc(env, ctx); 25363 + } else if (!(ctx->hflags & MIPS_HFLAG_M16)) { 20521 25364 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next); 20522 25365 insn_bytes = 4; 20523 25366 decode_opc(env, ctx); ··· 20956 25799 env->CP0_Status |= (1 << CP0St_FR); 20957 25800 } 20958 25801 20959 - if (env->CP0_Config3 & (1 << CP0C3_ISA)) { 20960 - /* microMIPS on reset when Config3.ISA == {1, 3} */ 25802 + if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) { 25803 + /* microMIPS on reset when Config3.ISA is 3 */ 20961 25804 env->hflags |= MIPS_HFLAG_M16; 20962 25805 } 20963 25806
+39
target/mips/translate_init.inc.c
··· 449 449 .insn_flags = CPU_MIPS32R6 | ASE_MICROMIPS, 450 450 .mmu_type = MMU_TYPE_R4000, 451 451 }, 452 + { 453 + .name = "I7200", 454 + .CP0_PRid = 0x00010000, 455 + .CP0_Config0 = MIPS_CONFIG0 | (1 << CP0C0_MM) | (0x2 << CP0C0_AR) | 456 + (MMU_TYPE_R4000 << CP0C0_MT), 457 + .CP0_Config1 = (1U << CP0C1_M) | (15 << CP0C1_MMU) | (2 << CP0C1_IS) | 458 + (4 << CP0C1_IL) | (3 << CP0C1_IA) | (2 << CP0C1_DS) | 459 + (4 << CP0C1_DL) | (3 << CP0C1_DA) | (1 << CP0C1_PC) | 460 + (1 << CP0C1_EP), 461 + .CP0_Config2 = MIPS_CONFIG2, 462 + .CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | (1 << CP0C3_CMGCR) | 463 + (1 << CP0C3_BI) | (1 << CP0C3_SC) | (3 << CP0C3_MMAR) | 464 + (1 << CP0C3_ISA_ON_EXC) | (1 << CP0C3_ISA) | 465 + (1 << CP0C3_ULRI) | (1 << CP0C3_RXI) | 466 + (1 << CP0C3_DSP2P) | (1 << CP0C3_DSPP) | 467 + (1 << CP0C3_CTXTC) | (1 << CP0C3_VInt) | 468 + (1 << CP0C3_CDMM) | (1 << CP0C3_MT) | (1 << CP0C3_TL), 469 + .CP0_Config4 = MIPS_CONFIG4 | (0xfc << CP0C4_KScrExist) | 470 + (2 << CP0C4_IE) | (1U << CP0C4_M), 471 + .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_MVH) | (1 << CP0C5_LLB), 472 + .CP0_Config5_rw_bitmask = (1 << CP0C5_SBRI) | (1 << CP0C5_FRE) | 473 + (1 << CP0C5_UFE), 474 + .CP0_LLAddr_rw_bitmask = 0, 475 + .CP0_LLAddr_shift = 0, 476 + .SYNCI_Step = 32, 477 + .CCRes = 2, 478 + .CP0_Status_rw_bitmask = 0x3158FF1F, 479 + .CP0_PageGrain = (1 << CP0PG_IEC) | (1 << CP0PG_XIE) | 480 + (1U << CP0PG_RIE), 481 + .CP0_PageGrain_rw_bitmask = 0, 482 + .CP1_fcr0 = (1 << FCR0_FREP) | (1 << FCR0_HAS2008) | (1 << FCR0_F64) | 483 + (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) | 484 + (1 << FCR0_S) | (0x02 << FCR0_PRID) | (0x0 << FCR0_REV), 485 + .CP1_fcr31 = (1 << FCR31_ABS2008) | (1 << FCR31_NAN2008), 486 + .SEGBITS = 32, 487 + .PABITS = 32, 488 + .insn_flags = CPU_NANOMIPS32 | ASE_DSP | ASE_DSPR2 | ASE_MT, 489 + .mmu_type = MMU_TYPE_R4000, 490 + }, 452 491 #if defined(TARGET_MIPS64) 453 492 { 454 493 .name = "R4000",