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,		/* MOV R14, R15 */
20
};
21
 
22
void
23
cpwr(int cp, int op1, int crn, int crm, int op2, ulong val)
24
{
25
	volatile ulong instr[2];
26
	void *pcaddr;
27
	void (*fp)(ulong);
28
 
29
	op1 &= 7;
30
	op2 &= 7;
31
	crn &= 017;
32
	crm &= 017;
33
	cp &= 017;
34
	/* MCR.  Rt will be R0. */
35
	instr[0] = 0xee000010 |
36
		op1 << 21 | crn << 16 | cp << 8 | op2 << 5 | crm;
37
	instr[1] = Retinst;
38
 
39
	pcaddr = (void *)MAP2PCSPACE(instr, getcallerpc(&cp));
40
	cachedwbse(pcaddr, sizeof instr);
41
	cacheiinv();
42
 
43
	fp = (void (*)(ulong))pcaddr;
44
	(*fp)(val);
45
	coherence();
46
}
47
 
48
void
49
cpwrsc(int op1, int crn, int crm, int op2, ulong val)
50
{
51
	cpwr(CpSC, op1, crn, crm, op2, val);
52
}
53
 
54
ulong
55
cprd(int cp, int op1, int crn, int crm, int op2)
56
{
57
	volatile ulong instr[2];
58
	void *pcaddr;
59
	ulong (*fp)(void);
60
 
61
	op1 &= 7;
62
	op2 &= 7;
63
	crn &= 017;
64
	crm &= 017;
65
	/*
66
	 * MRC.  return value will be in R0, which is convenient.
67
	 * Rt will be R0.
68
	 */
69
	instr[0] = 0xee100010 |
70
		op1 << 21 | crn << 16 | cp << 8 | op2 << 5 | crm;
71
	instr[1] = Retinst;
72
 
73
	pcaddr = (void *)MAP2PCSPACE(instr, getcallerpc(&cp));
74
	cachedwbse(pcaddr, sizeof instr);
75
	cacheiinv();
76
 
77
	fp = (ulong (*)(void))pcaddr;
78
	return (*fp)();
79
}
80
 
81
ulong
82
cprdsc(int op1, int crn, int crm, int op2)
83
{
84
	return cprd(CpSC, op1, crn, crm, op2);
85
}
86
 
87
/* floating point */
88
 
89
ulong
90
fprd(int fpreg)
91
{
92
	volatile ulong instr[2];
93
	void *pcaddr;
94
	ulong (*fp)(void);
95
 
96
	fpreg &= 017;
97
	/*
98
	 * VMRS.  return value will be in R0, which is convenient.
99
	 * Rt will be R0.
100
	 */
101
	instr[0] = 0xeef00a10 | fpreg << 16 | 0 << 12;
102
	instr[1] = Retinst;
103
	coherence();
104
 
105
	pcaddr = (void *)MAP2PCSPACE(instr, getcallerpc(&fpreg));
106
	cachedwbse(pcaddr, sizeof instr);
107
	cacheiinv();
108
 
109
	fp = (ulong (*)(void))pcaddr;
110
	return (*fp)();
111
}
112
 
113
void
114
fpwr(int fpreg, ulong val)
115
{
116
	volatile ulong instr[2];
117
	void *pcaddr;
118
	void (*fp)(ulong);
119
 
120
	fpreg &= 017;
121
	/* VMSR.  Rt will be R0. */
122
	instr[0] = 0xeee00a10 | fpreg << 16 | 0 << 12;
123
	instr[1] = Retinst;
124
	coherence();
125
 
126
	pcaddr = (void *)MAP2PCSPACE(instr, getcallerpc(&fpreg));
127
	cachedwbse(pcaddr, sizeof instr);
128
	cacheiinv();
129
 
130
	fp = (void (*)(ulong))pcaddr;
131
	(*fp)(val);
132
	coherence();
133
}