3 * mainly to cope with arm hard-wiring register numbers into instructions.
5 * CP15 (system control) is the one that gets used the most in practice.
6 * these routines must be callable from KZERO space or the 0 segment.
9 #include "../port/lib.h"
18 /* alternates: 0xe12fff1e BX (R14); last e is R14 */
19 /* 0xe28ef000 B 0(R14); second e is R14 (ken) */
20 Retinst = 0xe1a0f00e, /* MOV R14, R15 */
26 typedef ulong (*Pufv)(void);
27 typedef void (*Pvfu)(ulong);
30 setupcpop(ulong instr[2], ulong opcode, int cp, int op1, int crn, int crm,
40 instr[0] = opcode | op1 << 21 | crn << 16 | cp << 8 | op2 << 5 | crm;
43 cachedwbse(instr, sizeof instrsz);
48 cprd(int cp, int op1, int crn, int crm, int op2)
51 volatile ulong instr[2];
56 * MRC. return value will be in R0, which is convenient.
59 setupcpop(instr, 0xee100010, cp, op1, crn, crm, op2);
67 cpwr(int cp, int op1, int crn, int crm, int op2, ulong val)
70 volatile ulong instr[2];
74 setupcpop(instr, 0xee000010, cp, op1, crn, crm, op2); /* MCR, Rt is R0 */
82 cprdsc(int op1, int crn, int crm, int op2)
84 return cprd(CpSC, op1, crn, crm, op2);
88 cpwrsc(int op1, int crn, int crm, int op2, ulong val)
90 cpwr(CpSC, op1, crn, crm, op2, val);
95 /* fp coproc control */
97 setupfpctlop(ulong instr[2], int opcode, int fpctlreg)
101 fpctlreg &= Nfpctlregs - 1;
102 instr[0] = opcode | fpctlreg << 16 | 0 << 12 | CpFP << 8;
105 cachedwbse(instr, sizeof instrsz);
113 volatile ulong instr[2];
118 panic("fprd: cpu%d fpu off", m->machno);
122 * VMRS. return value will be in R0, which is convenient.
125 setupfpctlop(instr, 0xeef00010, fpreg);
133 fpwr(int fpreg, ulong val)
136 volatile ulong instr[2];
139 /* fpu might be off and this VMSR might enable it */
141 setupfpctlop(instr, 0xeee00010, fpreg); /* VMSR, Rt is R0 */
148 /* fp register access; don't bother with single precision */
150 setupfpop(ulong instr[2], int opcode, int fpreg)
154 instr[0] = opcode | 0 << 16 | (fpreg & (16 - 1)) << 12;
156 instr[0] |= 1 << 22; /* high bit of dfp reg # */
159 cachedwbse(instr, sizeof instrsz);
164 fpsavereg(int fpreg, uvlong *fpp)
167 volatile ulong instr[2];
168 ulong (*fp)(uvlong *);
171 panic("fpsavereg: cpu%d fpu off", m->machno);
174 * VSTR. pointer will be in R0, which is convenient.
177 setupfpop(instr, 0xed000000 | CpDFP << 8, fpreg);
178 fp = (ulong (*)(uvlong *))instr;
182 return r; /* not too meaningful */
186 fprestreg(int fpreg, uvlong val)
189 volatile ulong instr[2];
190 void (*fp)(uvlong *);
193 panic("fprestreg: cpu%d fpu off", m->machno);
195 setupfpop(instr, 0xed100000 | CpDFP << 8, fpreg); /* VLDR, Rt is R0 */
196 fp = (void (*)(uvlong *))instr;