Skip to content

Commit 79e5729

Browse files
jaqchenwkz
authored andcommitted
arch: Add support for mips architecture
There exists mainly two variants of ABIs in the linux kernel for MIPS architecture, o32 and n32/n64. Configure option `CFLAGS=-DUSE_MIPS_N32 can be specified to enable n32/n64 kernel ABI. Note that only support for 32-bit MIPS architecture is added.
1 parent 864fac7 commit 79e5729

File tree

2 files changed

+166
-0
lines changed

2 files changed

+166
-0
lines changed

configure.ac

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ AC_SUBST(arch)
3939

4040
AS_CASE($host_cpu,
4141
arm*, arch=arm,
42+
mips*, arch=mips,
4243
arch=$host_cpu)
4344

4445
AC_OUTPUT

src/libply/arch/mips.c

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
/*
2+
* Copyright Tobias Waldekranz <[email protected]>
3+
* Copyright Ye Jiaqiang <[email protected]>
4+
*
5+
* SPDX-License-Identifier: GPL-2.0
6+
*/
7+
8+
#include <assert.h>
9+
10+
#include <ply/internal.h>
11+
12+
#define arch_typedef(_a, _t) { \
13+
.ttype = T_TYPEDEF, \
14+
.tdef = { .name = #_a, .type = _t }, \
15+
}
16+
17+
struct type t_s8 = arch_typedef(s8, &t_schar);
18+
struct type t_u8 = arch_typedef(u8, &t_uchar);
19+
struct type t_s16 = arch_typedef(s16, &t_sshort);
20+
struct type t_u16 = arch_typedef(u16, &t_ushort);
21+
struct type t_s32 = arch_typedef(s32, &t_sint);
22+
struct type t_u32 = arch_typedef(u32, &t_uint);
23+
struct type t_s64 = arch_typedef(s64, &t_sllong);
24+
struct type t_u64 = arch_typedef(u64, &t_ullong);
25+
26+
static int reg_fprint(struct type *t, FILE *fp, const void *data)
27+
{
28+
return fprintf(fp, "%#lx", *((unsigned long *)data));
29+
}
30+
31+
struct type t_reg_t = {
32+
.ttype = T_TYPEDEF,
33+
.tdef = {
34+
.name = "reg_t",
35+
.type = &t_ulong,
36+
},
37+
38+
.fprint = reg_fprint,
39+
};
40+
41+
struct tfield f_pt_regs_fields[] = {
42+
/*
43+
* Only 32-bit MIPS architecture is supported.
44+
* 8 userspace registers padding, which is mandatory for MIPS32.
45+
* Refer to linux/arch/mips/include/asm/ptrace.h
46+
*/
47+
{ .name = "uarg0", .type = &t_reg_t },
48+
{ .name = "uarg1", .type = &t_reg_t },
49+
{ .name = "uarg2", .type = &t_reg_t },
50+
{ .name = "uarg3", .type = &t_reg_t },
51+
{ .name = "uarg4", .type = &t_reg_t },
52+
{ .name = "uarg5", .type = &t_reg_t },
53+
{ .name = "uarg6", .type = &t_reg_t },
54+
{ .name = "uarg7", .type = &t_reg_t },
55+
56+
{ .name = "zero", .type = &t_reg_t }, /* $0 */
57+
{ .name = "at", .type = &t_reg_t }, /* $1 */
58+
{ .name = "v0", .type = &t_reg_t }, /* $2 */
59+
{ .name = "v1", .type = &t_reg_t }, /* $3 */
60+
{ .name = "a0", .type = &t_reg_t }, /* $4 */
61+
{ .name = "a1", .type = &t_reg_t }, /* $5 */
62+
{ .name = "a2", .type = &t_reg_t }, /* $6 */
63+
{ .name = "a3", .type = &t_reg_t }, /* $7 */
64+
#ifndef USE_MIPS_N32 /* o32 ABI */
65+
{ .name = "t0", .type = &t_reg_t }, /* $8 */
66+
{ .name = "t1", .type = &t_reg_t }, /* $9 */
67+
{ .name = "t2", .type = &t_reg_t }, /* $10 */
68+
{ .name = "t3", .type = &t_reg_t }, /* $11 */
69+
#else /* n32 or native 64-bit ABI */
70+
{ .name = "a4", .type = &t_reg_t }, /* $8 */
71+
{ .name = "a5", .type = &t_reg_t }, /* $9 */
72+
{ .name = "a6", .type = &t_reg_t }, /* $10 */
73+
{ .name = "a7", .type = &t_reg_t }, /* $11 */
74+
#endif
75+
{ .name = "t4", .type = &t_reg_t }, /* $12 */
76+
{ .name = "t5", .type = &t_reg_t }, /* $13 */
77+
{ .name = "t6", .type = &t_reg_t }, /* $14 */
78+
{ .name = "t7", .type = &t_reg_t }, /* $15 */
79+
{ .name = "s0", .type = &t_reg_t }, /* $16 */
80+
{ .name = "s1", .type = &t_reg_t }, /* $17 */
81+
{ .name = "s2", .type = &t_reg_t }, /* $18 */
82+
{ .name = "s3", .type = &t_reg_t }, /* $19 */
83+
{ .name = "s4", .type = &t_reg_t }, /* $20 */
84+
{ .name = "s5", .type = &t_reg_t }, /* $21 */
85+
{ .name = "s6", .type = &t_reg_t }, /* $22 */
86+
{ .name = "s7", .type = &t_reg_t }, /* $23 */
87+
{ .name = "t8", .type = &t_reg_t }, /* $24 */
88+
{ .name = "t9", .type = &t_reg_t }, /* $25 */
89+
{ .name = "k0", .type = &t_reg_t }, /* $26 */
90+
{ .name = "k1", .type = &t_reg_t }, /* $27 */
91+
{ .name = "gp", .type = &t_reg_t }, /* $28 */
92+
{ .name = "sp", .type = &t_reg_t }, /* $29 */
93+
{ .name = "fp", .type = &t_reg_t }, /* $30, or s8 */
94+
{ .name = "ra", .type = &t_reg_t }, /* $31 */
95+
96+
{ .name = "cp0_status", .type = &t_reg_t },
97+
{ .name = "hi", .type = &t_reg_t },
98+
{ .name = "lo", .type = &t_reg_t },
99+
100+
/*
101+
* Uncomment next line for register `acx, which is rarely
102+
* enabled via CONFIG_CPU_HAS_SMARTMIPS kernel option:
103+
*/
104+
/* { .name = "acx", .type = &t_reg_t }, */
105+
{ .name = "cp0_badvaddr", .type = &t_reg_t },
106+
{ .name = "cp0_cause", .type = &t_reg_t },
107+
{ .name = "cp0_epc", .type = &t_reg_t },
108+
109+
{ .name = NULL, .type = NULL }
110+
};
111+
112+
struct type t_pt_regs = {
113+
.ttype = T_STRUCT,
114+
115+
.sou = {
116+
.name = "pt_regs",
117+
.fields = f_pt_regs_fields,
118+
},
119+
};
120+
121+
struct type *arch_types[] = {
122+
&t_s8, &t_u8,
123+
&t_s16, &t_u16,
124+
&t_s32, &t_u32,
125+
&t_s64, &t_u64,
126+
&t_reg_t, &t_pt_regs,
127+
NULL
128+
};
129+
130+
const char *arch_register_argument(int num)
131+
{
132+
switch (num) {
133+
case 0: return "a0";
134+
case 1: return "a1";
135+
case 2: return "a2";
136+
case 3: return "a3";
137+
#ifdef USE_MIPS_N32
138+
case 4: return "a4";
139+
case 5: return "a5";
140+
case 6: return "a6";
141+
case 7: return "a7";
142+
#endif
143+
default:
144+
break;
145+
}
146+
147+
return NULL;
148+
}
149+
150+
const char *arch_register_pc(void)
151+
{
152+
return "cp0_epc";
153+
}
154+
155+
const char *arch_register_return(void)
156+
{
157+
return "v0";
158+
}
159+
160+
__attribute__((constructor))
161+
static void arch_init(void)
162+
{
163+
type_struct_layout(&t_pt_regs);
164+
type_add_list(arch_types);
165+
}

0 commit comments

Comments
 (0)