Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 * arm co-processors
3
 * CP15 (system control) is the one that gets used the most in practice.
4
 */
5
#include "u.h"
6
#include "../port/lib.h"
7
#include "mem.h"
8
#include "dat.h"
9
#include "fns.h"
10
#include "io.h"
11
 
12
#include "arm.h"
13
 
14
#define MAP2PCSPACE(va, pc) ((uintptr)(va) & ~KSEGM | (pc) & KSEGM)
15
 
16
enum {
17
	/* alternates:	0xe12fff1e	BX (R14); last e is R14 */
18
	/*		0xe28ef000	B 0(R14); second e is R14 (ken) */
19
	Retinst	= 0xe1a0f00e,		/* MOVW R14, R15 */
20
 
21
	Fpproc	= 10,			/* for vfp 3+; also 11 for doubles */
22
};
23
 
24
void
25
cpwr(int cp, int op1, int crn, int crm, int op2, ulong val)
26
{
27
	int s;
28
	volatile ulong instr[2];
29
	void *pcaddr;
30
	void (*fp)(ulong);
31
 
32
	s = splhi();
33
	op1 &= 7;
34
	op2 &= 7;
35
	crn &= 017;
36
	crm &= 017;
37
	cp &= 017;
38
	/* MCR.  Rt will be R0. */
39
	instr[0] = 0xee000010 |
40
		op1 << 21 | crn << 16 | cp << 8 | op2 << 5 | crm;
41
	instr[1] = Retinst;
42
	coherence();
43
 
44
	pcaddr = (void *)MAP2PCSPACE(instr, getcallerpc(&cp));
45
	cachedwbse(pcaddr, sizeof instr);
46
	cacheiinv();
47
 
48
	fp = (void (*)(ulong))pcaddr;
49
	(*fp)(val);
50
	coherence();
51
	splx(s);
52
}
53
 
54
void
55
cpwrsc(int op1, int crn, int crm, int op2, ulong val)
56
{
57
	cpwr(CpSC, op1, crn, crm, op2, val);
58
}
59
 
60
ulong
61
cprd(int cp, int op1, int crn, int crm, int op2)
62
{
63
	int s;
64
	ulong res;
65
	volatile ulong instr[2];
66
	void *pcaddr;
67
	ulong (*fp)(void);
68
 
69
	s = splhi();
70
	op1 &= 7;
71
	op2 &= 7;
72
	crn &= 017;
73
	crm &= 017;
74
	/*
75
	 * MRC.  return value will be in R0, which is convenient.
76
	 * Rt will be R0.
77
	 */
78
	instr[0] = 0xee100010 |
79
		op1 << 21 | crn << 16 | cp << 8 | op2 << 5 | crm;
80
	instr[1] = Retinst;
81
	coherence();
82
 
83
	pcaddr = (void *)MAP2PCSPACE(instr, getcallerpc(&cp));
84
	cachedwbse(pcaddr, sizeof instr);
85
	cacheiinv();
86
 
87
	fp = (ulong (*)(void))pcaddr;
88
	res = (*fp)();
89
	splx(s);
90
	return res;
91
}
92
 
93
ulong
94
cprdsc(int op1, int crn, int crm, int op2)
95
{
96
	return cprd(CpSC, op1, crn, crm, op2);
97
}
98
 
99
/* floating point */
100
 
101
ulong
102
fprd(int fpreg)
103
{
104
	int s;
105
	ulong res;
106
	volatile ulong instr[2];
107
	void *pcaddr;
108
	ulong (*fp)(void);
109
 
110
	s = splhi();
111
	fpreg &= 017;
112
	/*
113
	 * VMRS.  return value will be in R0, which is convenient.
114
	 * Rt will be R0.
115
	 */
116
	instr[0] = 0xeef00010 | fpreg << 16 | 0 << 12 | Fpproc << 8;
117
	instr[1] = Retinst;
118
	coherence();
119
 
120
	pcaddr = (void *)MAP2PCSPACE(instr, getcallerpc(&fpreg));
121
	cachedwbse(pcaddr, sizeof instr);
122
	cacheiinv();
123
 
124
	fp = (ulong (*)(void))pcaddr;
125
	res = (*fp)();
126
	splx(s);
127
	return res;
128
}
129
 
130
void
131
fpwr(int fpreg, ulong val)
132
{
133
	int s;
134
	volatile ulong instr[2];
135
	void *pcaddr;
136
	void (*fp)(ulong);
137
 
138
	s = splhi();
139
	fpreg &= 017;
140
	/* VMSR.  Rt will be R0. */
141
	instr[0] = 0xeee00010 | fpreg << 16 | 0 << 12 | Fpproc << 8;
142
	instr[1] = Retinst;
143
	coherence();
144
 
145
	pcaddr = (void *)MAP2PCSPACE(instr, getcallerpc(&fpreg));
146
	cachedwbse(pcaddr, sizeof instr);
147
	cacheiinv();
148
 
149
	fp = (void (*)(ulong))pcaddr;
150
	(*fp)(val);
151
	coherence();
152
	splx(s);
153
}