xref: /plan9/sys/src/9/omap/coproc.c (revision ad6b799d56798facc7dde48aa03401b84a87de1e)
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
cpwr(int cp,int op1,int crn,int crm,int op2,ulong val)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
cpwrsc(int op1,int crn,int crm,int op2,ulong val)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
cprd(int cp,int op1,int crn,int crm,int op2)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
cprdsc(int op1,int crn,int crm,int op2)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
fprd(int fpreg)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
fpwr(int fpreg,ulong val)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 }
134