xref: /plan9/sys/src/9/teg2/arm.s (revision 53ff6c4dddeb19bd84c918cdd2542d7c51263329)
1/*
2 * nvidia tegra 2 machine assist, definitions
3 * dual-core cortex-a9 processor
4 *
5 * R9 and R10 are used for `extern register' variables.
6 * R11 is used by the loader as a temporary, so avoid it.
7 */
8
9#include "mem.h"
10#include "arm.h"
11
12#undef B					/* B is for 'botch' */
13
14#define KADDR(pa)	(KZERO    | ((pa) & ~KSEGM))
15#define PADDR(va)	(PHYSDRAM | ((va) & ~KSEGM))
16
17#define L1X(va)		(((((va))>>20) & 0x0fff)<<2)
18
19#define MACHADDR	(L1-MACHSIZE)		/* only room for cpu0's */
20
21/* L1 pte values */
22#define PTEDRAM	(Dom0|L1AP(Krw)|Section|L1ptedramattrs)
23#define PTEIO	(Dom0|L1AP(Krw)|Section)
24
25#define DOUBLEMAPMBS	 512	/* megabytes of low dram to double-map */
26
27/* steps on R0 */
28#define DELAY(label, mloops) \
29	MOVW	$((mloops)*1000000), R0; \
30label: \
31	SUB.S	$1, R0; \
32	BNE	label
33
34/* print a byte on the serial console; clobbers R0 & R6; needs R12 (SB) set */
35#define PUTC(c) \
36	BARRIERS; \
37	MOVW	$(c), R0; \
38	MOVW	$PHYSCONS, R6; \
39	MOVW	R0, (R6); \
40	BARRIERS
41
42/*
43 * new instructions
44 */
45
46#define SMC	WORD	$0xe1600070	/* low 4-bits are call # (trustzone) */
47/* flush branch-target cache */
48#define FLBTC  MTCP CpSC, 0, PC, C(CpCACHE), C(CpCACHEinvi), CpCACHEflushbtc
49/* flush one entry of the branch-target cache, va in R0 (cortex) */
50#define FLBTSE MTCP CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEflushbtse
51
52/* arm v7 arch defines these */
53#define DSB	WORD	$0xf57ff04f	/* data synch. barrier; last f = SY */
54#define DMB	WORD	$0xf57ff05f	/* data mem. barrier; last f = SY */
55#define ISB	WORD	$0xf57ff06f	/* instr. sync. barrier; last f = SY */
56
57#define WFI	WORD	$0xe320f003	/* wait for interrupt */
58#define NOOP	WORD	$0xe320f000
59
60#define CLZ(s, d) WORD	$(0xe16f0f10 | (d) << 12 | (s))	/* count leading 0s */
61
62#define SETEND(o) WORD	$(0xf1010000 | (o) << 9)  /* o==0, little-endian */
63
64#define CPSIE	WORD	$0xf1080080	/* intr enable: zeroes I bit */
65#define CPSID	WORD	$0xf10c00c0	/* intr disable: sets I,F bits */
66#define CPSAE	WORD	$0xf1080100	/* async abt enable: zeroes A bit */
67#define CPSMODE(m) WORD $(0xf1020000 | (m)) /* switch to mode m (PsrM*) */
68
69#define	CLREX	WORD	$0xf57ff01f
70
71/* floating point */
72#define VMRS(fp, cpu) WORD $(0xeef00a10 | (fp)<<16 | (cpu)<<12) /* FP → arm */
73#define VMSR(cpu, fp) WORD $(0xeee00a10 | (fp)<<16 | (cpu)<<12) /* arm → FP */
74
75/*
76 * a popular code sequence used to write a pte for va is:
77 *
78 *	MOVW	R(n), TTB[LnX(va)]
79 *	// clean the cache line
80 *	DSB
81 *	// invalidate tlb entry for va
82 *	FLBTC
83 *	DSB
84 * 	PFF (now ISB)
85 */
86#define	BARRIERS	FLBTC; DSB; ISB
87
88/*
89 * invoked with PTE bits in R2, pa in R3, PTE pointed to by R4.
90 * fill PTE pointed to by R4 and increment R4 past it.
91 * increment R3 by a MB.  clobbers R1.
92 */
93#define FILLPTE() \
94	ORR	R3, R2, R1;			/* pte bits in R2, pa in R3 */ \
95	MOVW	R1, (R4); \
96	ADD	$4, R4;				/* bump PTE address */ \
97	ADD	$MiB, R3;			/* bump pa */ \
98
99/* zero PTE pointed to by R4 and increment R4 past it. assumes R0 is 0. */
100#define ZEROPTE() \
101	MOVW	R0, (R4); \
102	ADD	$4, R4;				/* bump PTE address */
103
104/*
105 * set kernel SB for zero segment (instead of usual KZERO segment).
106 * NB: the next line puts rubbish in R12:
107 *	MOVW	$setR12-KZERO(SB), R12
108 */
109#define SETZSB \
110	MOVW	$setR12(SB), R12;		/* load kernel's SB */ \
111	SUB	$KZERO, R12; \
112	ADD	$PHYSDRAM, R12
113
114/*
115 * note that 5a's RFE is not the v6/7 arch. instruction (0xf8900a00),
116 * which loads CPSR from the word after the PC at (R13), but rather
117 * the pre-v6 simulation `MOVM.IA.S.W (R13), [R15]' (0xe8fd8000 since
118 * MOVM is LDM in this case), which loads CPSR not from memory but
119 * from SPSR due to `.S'.
120 */
121#define RFEV7(r)    WORD $(0xf8900a00 | (r) << 16)
122#define RFEV7W(r)   WORD $(0xf8900a00 | (r) << 16 | 0x00200000)	/* RFE.W */
123#define RFEV7DB(r)  WORD $(0xf9100a00 | (r) << 16)		/* RFE.DB */
124#define RFEV7DBW(r) WORD $(0xf9100a00 | (r) << 16 | 0x00200000)	/* RFE.DB.W */
125
126#define CKPSR(psr, tmp, bad)
127#define CKCPSR(psrtmp, tmp, bad)
128
129/* return with cpu id in r and condition codes set from "r == 0" */
130#define CPUID(r) \
131	MFCP	CpSC, 0, r, C(CpID), C(CpIDidct), CpIDmpid; \
132	AND.S	$(MAXMACH-1), r			/* mask out non-cpu-id bits */
133