1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 3 #include "qemu/osdep.h" 4 #include "qemu.h" 5 #include "loader.h" 6 #include "elf.h" 7 #include "target_elf.h" 8 9 10 const char *get_elf_cpu_model(uint32_t eflags) 11 { 12 #ifdef TARGET_MIPS64 13 switch (eflags & EF_MIPS_MACH) { 14 case EF_MIPS_MACH_OCTEON: 15 case EF_MIPS_MACH_OCTEON2: 16 case EF_MIPS_MACH_OCTEON3: 17 return "Octeon68XX"; 18 case EF_MIPS_MACH_LS2E: 19 return "Loongson-2E"; 20 case EF_MIPS_MACH_LS2F: 21 return "Loongson-2F"; 22 case EF_MIPS_MACH_LS3A: 23 return "Loongson-3A1000"; 24 default: 25 break; 26 } 27 switch (eflags & EF_MIPS_ARCH) { 28 case EF_MIPS_ARCH_64R6: 29 return "I6400"; 30 case EF_MIPS_ARCH_64R2: 31 return "MIPS64R2-generic"; 32 default: 33 break; 34 } 35 return "5KEf"; 36 #else 37 if ((eflags & EF_MIPS_ARCH) == EF_MIPS_ARCH_32R6) { 38 return "mips32r6-generic"; 39 } 40 if ((eflags & EF_MIPS_ARCH_ASE) == EF_MIPS_ARCH_ASE_MICROMIPS) { 41 return "M14Kc"; 42 } 43 if ((eflags & EF_MIPS_ARCH_ASE) == EF_MIPS_ARCH_ASE_M16) { 44 return "74Kf"; 45 } 46 if (eflags & EF_MIPS_NAN2008) { 47 return "P5600"; 48 } 49 return "24Kf"; 50 #endif 51 } 52 53 /* See arch/mips/include/uapi/asm/hwcap.h. */ 54 enum { 55 HWCAP_MIPS_R6 = (1 << 0), 56 HWCAP_MIPS_MSA = (1 << 1), 57 HWCAP_MIPS_CRC32 = (1 << 2), 58 HWCAP_MIPS_MIPS16 = (1 << 3), 59 HWCAP_MIPS_MDMX = (1 << 4), 60 HWCAP_MIPS_MIPS3D = (1 << 5), 61 HWCAP_MIPS_SMARTMIPS = (1 << 6), 62 HWCAP_MIPS_DSP = (1 << 7), 63 HWCAP_MIPS_DSP2 = (1 << 8), 64 HWCAP_MIPS_DSP3 = (1 << 9), 65 HWCAP_MIPS_MIPS16E2 = (1 << 10), 66 HWCAP_LOONGSON_MMI = (1 << 11), 67 HWCAP_LOONGSON_EXT = (1 << 12), 68 HWCAP_LOONGSON_EXT2 = (1 << 13), 69 HWCAP_LOONGSON_CPUCFG = (1 << 14), 70 }; 71 72 #define GET_FEATURE_INSN(_flag, _hwcap) \ 73 do { if (cpu->env.insn_flags & (_flag)) { hwcaps |= _hwcap; } } while (0) 74 75 #define GET_FEATURE_REG_SET(_reg, _mask, _hwcap) \ 76 do { if (cpu->env._reg & (_mask)) { hwcaps |= _hwcap; } } while (0) 77 78 #define GET_FEATURE_REG_EQU(_reg, _start, _length, _val, _hwcap) \ 79 do { \ 80 if (extract32(cpu->env._reg, (_start), (_length)) == (_val)) { \ 81 hwcaps |= _hwcap; \ 82 } \ 83 } while (0) 84 85 abi_ulong get_elf_hwcap(CPUState *cs) 86 { 87 MIPSCPU *cpu = MIPS_CPU(cs); 88 abi_ulong hwcaps = 0; 89 90 GET_FEATURE_REG_EQU(CP0_Config0, CP0C0_AR, CP0C0_AR_LENGTH, 91 2, HWCAP_MIPS_R6); 92 GET_FEATURE_REG_SET(CP0_Config3, 1 << CP0C3_MSAP, HWCAP_MIPS_MSA); 93 GET_FEATURE_INSN(ASE_LMMI, HWCAP_LOONGSON_MMI); 94 GET_FEATURE_INSN(ASE_LEXT, HWCAP_LOONGSON_EXT); 95 96 return hwcaps; 97 } 98 99 #undef GET_FEATURE_REG_EQU 100 #undef GET_FEATURE_REG_SET 101 #undef GET_FEATURE_INSN 102 103 #define MATCH_PLATFORM_INSN(_flags, _base_platform) \ 104 do { if ((cpu->env.insn_flags & (_flags)) == _flags) \ 105 { return _base_platform; } } while (0) 106 107 const char *get_elf_base_platform(CPUState *cs) 108 { 109 MIPSCPU *cpu = MIPS_CPU(cs); 110 111 /* 64 bit ISAs goes first */ 112 MATCH_PLATFORM_INSN(CPU_MIPS64R6, "mips64r6"); 113 MATCH_PLATFORM_INSN(CPU_MIPS64R5, "mips64r5"); 114 MATCH_PLATFORM_INSN(CPU_MIPS64R2, "mips64r2"); 115 MATCH_PLATFORM_INSN(CPU_MIPS64R1, "mips64"); 116 MATCH_PLATFORM_INSN(CPU_MIPS5, "mips5"); 117 MATCH_PLATFORM_INSN(CPU_MIPS4, "mips4"); 118 MATCH_PLATFORM_INSN(CPU_MIPS3, "mips3"); 119 120 /* 32 bit ISAs */ 121 MATCH_PLATFORM_INSN(CPU_MIPS32R6, "mips32r6"); 122 MATCH_PLATFORM_INSN(CPU_MIPS32R5, "mips32r5"); 123 MATCH_PLATFORM_INSN(CPU_MIPS32R2, "mips32r2"); 124 MATCH_PLATFORM_INSN(CPU_MIPS32R1, "mips32"); 125 MATCH_PLATFORM_INSN(CPU_MIPS2, "mips2"); 126 127 /* Fallback */ 128 return "mips"; 129 } 130 131 #undef MATCH_PLATFORM_INSN 132 133 /* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs. */ 134 void elf_core_copy_regs(target_elf_gregset_t *r, const CPUMIPSState *env) 135 { 136 for (int i = 1; i < ARRAY_SIZE(env->active_tc.gpr); i++) { 137 r->pt.regs[i] = tswapl(env->active_tc.gpr[i]); 138 } 139 140 r->pt.regs[26] = 0; 141 r->pt.regs[27] = 0; 142 r->pt.lo = tswapl(env->active_tc.LO[0]); 143 r->pt.hi = tswapl(env->active_tc.HI[0]); 144 r->pt.cp0_epc = tswapl(env->active_tc.PC); 145 r->pt.cp0_badvaddr = tswapl(env->CP0_BadVAddr); 146 r->pt.cp0_status = tswapl(env->CP0_Status); 147 r->pt.cp0_cause = tswapl(env->CP0_Cause); 148 } 149