master
c 158 lines 4.5 KB
Raw
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 void elf_core_copy_fpregs(target_elf_fpregset_t *r, const CPUMIPSState *env)
134 {
135 for (int i = 0; i < 32; i++) {
136 r->fpr[i] = tswap64(env->active_fpu.fpr[i].d);
137 }
138 r->fcsr = tswap32(env->active_fpu.fcr31);
139 }
140
141 /* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs. */
142 #ifndef TARGET_MIPS64
143 void elf_core_copy_regs(target_elf_gregset_t *r, const CPUMIPSState *env)
144 {
145 for (int i = 1; i < ARRAY_SIZE(env->active_tc.gpr); i++) {
146 r->pt.regs[i] = tswap32(env->active_tc.gpr[i]);
147 }
148
149 r->pt.regs[26] = 0;
150 r->pt.regs[27] = 0;
151 r->pt.lo = tswap32(env->active_tc.LO[0]);
152 r->pt.hi = tswap32(env->active_tc.HI[0]);
153 r->pt.cp0_epc = tswap32(env->active_tc.PC);
154 r->pt.cp0_badvaddr = tswap32(env->CP0_BadVAddr);
155 r->pt.cp0_status = tswap32(env->CP0_Status);
156 r->pt.cp0_cause = tswap32(env->CP0_Cause);
157 }
158 #endif