xref: /plan9/sys/src/9/omap/coproc.c (revision ad6b799d56798facc7dde48aa03401b84a87de1e)
17bb09086SDavid du Colombier /*
27bb09086SDavid du Colombier  * arm co-processors
37bb09086SDavid du Colombier  * CP15 (system control) is the one that gets used the most in practice.
47bb09086SDavid du Colombier  */
57bb09086SDavid du Colombier #include "u.h"
67bb09086SDavid du Colombier #include "../port/lib.h"
77bb09086SDavid du Colombier #include "mem.h"
87bb09086SDavid du Colombier #include "dat.h"
97bb09086SDavid du Colombier #include "fns.h"
107bb09086SDavid du Colombier #include "io.h"
117bb09086SDavid du Colombier 
127bb09086SDavid du Colombier #include "arm.h"
137bb09086SDavid du Colombier 
147bb09086SDavid du Colombier #define MAP2PCSPACE(va, pc) ((uintptr)(va) & ~KSEGM | (pc) & KSEGM)
157bb09086SDavid du Colombier 
167bb09086SDavid du Colombier enum {
177bb09086SDavid du Colombier 	/* alternates:	0xe12fff1e	BX (R14); last e is R14 */
187bb09086SDavid du Colombier 	/*		0xe28ef000	B 0(R14); second e is R14 (ken) */
197bb09086SDavid du Colombier 	Retinst	= 0xe1a0f00e,		/* MOV R14, R15 */
207bb09086SDavid du Colombier };
217bb09086SDavid du Colombier 
227bb09086SDavid du Colombier void
cpwr(int cp,int op1,int crn,int crm,int op2,ulong val)237bb09086SDavid du Colombier cpwr(int cp, int op1, int crn, int crm, int op2, ulong val)
247bb09086SDavid du Colombier {
257bb09086SDavid du Colombier 	volatile ulong instr[2];
267bb09086SDavid du Colombier 	void *pcaddr;
277bb09086SDavid du Colombier 	void (*fp)(ulong);
287bb09086SDavid du Colombier 
297bb09086SDavid du Colombier 	op1 &= 7;
307bb09086SDavid du Colombier 	op2 &= 7;
317bb09086SDavid du Colombier 	crn &= 017;
327bb09086SDavid du Colombier 	crm &= 017;
337bb09086SDavid du Colombier 	cp &= 017;
347bb09086SDavid du Colombier 	/* MCR.  Rt will be R0. */
357bb09086SDavid du Colombier 	instr[0] = 0xee000010 |
367bb09086SDavid du Colombier 		op1 << 21 | crn << 16 | cp << 8 | op2 << 5 | crm;
377bb09086SDavid du Colombier 	instr[1] = Retinst;
387bb09086SDavid du Colombier 
397bb09086SDavid du Colombier 	pcaddr = (void *)MAP2PCSPACE(instr, getcallerpc(&cp));
407bb09086SDavid du Colombier 	cachedwbse(pcaddr, sizeof instr);
417bb09086SDavid du Colombier 	cacheiinv();
427bb09086SDavid du Colombier 
437bb09086SDavid du Colombier 	fp = (void (*)(ulong))pcaddr;
447bb09086SDavid du Colombier 	(*fp)(val);
457bb09086SDavid du Colombier 	coherence();
467bb09086SDavid du Colombier }
477bb09086SDavid du Colombier 
487bb09086SDavid du Colombier void
cpwrsc(int op1,int crn,int crm,int op2,ulong val)497bb09086SDavid du Colombier cpwrsc(int op1, int crn, int crm, int op2, ulong val)
507bb09086SDavid du Colombier {
517bb09086SDavid du Colombier 	cpwr(CpSC, op1, crn, crm, op2, val);
527bb09086SDavid du Colombier }
537bb09086SDavid du Colombier 
547bb09086SDavid du Colombier ulong
cprd(int cp,int op1,int crn,int crm,int op2)557bb09086SDavid du Colombier cprd(int cp, int op1, int crn, int crm, int op2)
567bb09086SDavid du Colombier {
577bb09086SDavid du Colombier 	volatile ulong instr[2];
587bb09086SDavid du Colombier 	void *pcaddr;
597bb09086SDavid du Colombier 	ulong (*fp)(void);
607bb09086SDavid du Colombier 
617bb09086SDavid du Colombier 	op1 &= 7;
627bb09086SDavid du Colombier 	op2 &= 7;
637bb09086SDavid du Colombier 	crn &= 017;
647bb09086SDavid du Colombier 	crm &= 017;
657bb09086SDavid du Colombier 	/*
667bb09086SDavid du Colombier 	 * MRC.  return value will be in R0, which is convenient.
677bb09086SDavid du Colombier 	 * Rt will be R0.
687bb09086SDavid du Colombier 	 */
697bb09086SDavid du Colombier 	instr[0] = 0xee100010 |
707bb09086SDavid du Colombier 		op1 << 21 | crn << 16 | cp << 8 | op2 << 5 | crm;
717bb09086SDavid du Colombier 	instr[1] = Retinst;
727bb09086SDavid du Colombier 
737bb09086SDavid du Colombier 	pcaddr = (void *)MAP2PCSPACE(instr, getcallerpc(&cp));
747bb09086SDavid du Colombier 	cachedwbse(pcaddr, sizeof instr);
757bb09086SDavid du Colombier 	cacheiinv();
767bb09086SDavid du Colombier 
777bb09086SDavid du Colombier 	fp = (ulong (*)(void))pcaddr;
78*ad6b799dSDavid du Colombier 	return (*fp)();
797bb09086SDavid du Colombier }
807bb09086SDavid du Colombier 
817bb09086SDavid du Colombier ulong
cprdsc(int op1,int crn,int crm,int op2)827bb09086SDavid du Colombier cprdsc(int op1, int crn, int crm, int op2)
837bb09086SDavid du Colombier {
847bb09086SDavid du Colombier 	return cprd(CpSC, op1, crn, crm, op2);
857bb09086SDavid du Colombier }
867bb09086SDavid du Colombier 
877bb09086SDavid du Colombier /* floating point */
887bb09086SDavid du Colombier 
897bb09086SDavid du Colombier ulong
fprd(int fpreg)907bb09086SDavid du Colombier fprd(int fpreg)
917bb09086SDavid du Colombier {
927bb09086SDavid du Colombier 	volatile ulong instr[2];
937bb09086SDavid du Colombier 	void *pcaddr;
947bb09086SDavid du Colombier 	ulong (*fp)(void);
957bb09086SDavid du Colombier 
967bb09086SDavid du Colombier 	fpreg &= 017;
977bb09086SDavid du Colombier 	/*
987bb09086SDavid du Colombier 	 * VMRS.  return value will be in R0, which is convenient.
997bb09086SDavid du Colombier 	 * Rt will be R0.
1007bb09086SDavid du Colombier 	 */
1017bb09086SDavid du Colombier 	instr[0] = 0xeef00a10 | fpreg << 16 | 0 << 12;
1027bb09086SDavid du Colombier 	instr[1] = Retinst;
1037bb09086SDavid du Colombier 	coherence();
1047bb09086SDavid du Colombier 
1057bb09086SDavid du Colombier 	pcaddr = (void *)MAP2PCSPACE(instr, getcallerpc(&fpreg));
1067bb09086SDavid du Colombier 	cachedwbse(pcaddr, sizeof instr);
1077bb09086SDavid du Colombier 	cacheiinv();
1087bb09086SDavid du Colombier 
1097bb09086SDavid du Colombier 	fp = (ulong (*)(void))pcaddr;
110*ad6b799dSDavid du Colombier 	return (*fp)();
1117bb09086SDavid du Colombier }
1127bb09086SDavid du Colombier 
1137bb09086SDavid du Colombier void
fpwr(int fpreg,ulong val)1147bb09086SDavid du Colombier fpwr(int fpreg, ulong val)
1157bb09086SDavid du Colombier {
1167bb09086SDavid du Colombier 	volatile ulong instr[2];
1177bb09086SDavid du Colombier 	void *pcaddr;
1187bb09086SDavid du Colombier 	void (*fp)(ulong);
1197bb09086SDavid du Colombier 
1207bb09086SDavid du Colombier 	fpreg &= 017;
1217bb09086SDavid du Colombier 	/* VMSR.  Rt will be R0. */
1227bb09086SDavid du Colombier 	instr[0] = 0xeee00a10 | fpreg << 16 | 0 << 12;
1237bb09086SDavid du Colombier 	instr[1] = Retinst;
1247bb09086SDavid du Colombier 	coherence();
1257bb09086SDavid du Colombier 
1267bb09086SDavid du Colombier 	pcaddr = (void *)MAP2PCSPACE(instr, getcallerpc(&fpreg));
1277bb09086SDavid du Colombier 	cachedwbse(pcaddr, sizeof instr);
1287bb09086SDavid du Colombier 	cacheiinv();
1297bb09086SDavid du Colombier 
1307bb09086SDavid du Colombier 	fp = (void (*)(ulong))pcaddr;
1317bb09086SDavid du Colombier 	(*fp)(val);
1327bb09086SDavid du Colombier 	coherence();
1337bb09086SDavid du Colombier }
134