Don't crash when board size is changed.
[AROS-Contrib.git] / vpdf / system / altivec.c
blob6f82a00114444011912961343e751a80b9bf56a7
2 #include <proto/exec.h>
3 #include <proto/utility.h>
4 #include <exec/resident.h>
5 #include <exec/system.h>
7 int hasAltivec = 0;
9 #include "altivec.h"
11 void setupAVExceptions(void)
13 ULONG a[ 4 ] __attribute((aligned( 16 )));
14 vector unsigned short b;
15 b = vec_mfvscr();
16 vec_st(b, 0, (unsigned short *) a);
17 a[ 3 ] |= 1 << 16;
18 b = vec_ld(0, (unsigned short *)a);
19 vec_mtvscr(b);
23 void AltivecInit( void )
25 struct Resident *MyResident;
27 MyResident = FindResident("MorphOS");
29 /* Altivec/VMX detection */
31 if (MyResident && (MyResident->rt_Version > 1 || ((MyResident->rt_Flags & RTF_EXTENDED) && MyResident->rt_Version == 1 && MyResident->rt_Revision >= 5)))
33 struct TagItem MyTag = {TAG_DONE, 0};
34 NewGetSystemAttrsA(&hasAltivec, sizeof(hasAltivec), SYSTEMINFOTYPE_PPC_ALTIVEC, &MyTag);
37 if (hasAltivec)
39 setupAVExceptions();
43 /// Altivec cache prewarming stuff
46 * blockcount: number of blocks (from 0 to 255, 0 = 256 blocks)
47 * blocksize: number of 16-byte chunks (from 0 to 31, 0 = 32 * 16-byte chunks)
48 * blockstride: 16-bit value from -32768 to 32767 (0 = 32768), denotes the address
49 * increment from the beginning of one block to the beginning of the next.
52 static void cpu_vec_dst(CONST_APTR ptr, ULONG opts, ULONG channel)
54 switch (channel)
56 case 0:
57 vec_dst((VECTOR_UBYTE *)ptr, opts, 0);
58 break;
60 case 1:
61 vec_dst((VECTOR_UBYTE *)ptr, opts, 1);
62 break;
64 case 2:
65 vec_dst((VECTOR_UBYTE *)ptr, opts, 2);
66 break;
68 case 3:
69 vec_dst((VECTOR_UBYTE *)ptr, opts, 3);
70 break;
74 static void cpu_vec_dstt(CONST_APTR ptr, ULONG opts, ULONG channel)
76 switch (channel)
78 case 0:
79 vec_dstt((VECTOR_UBYTE *)ptr, opts, 0);
80 break;
82 case 1:
83 vec_dstt((VECTOR_UBYTE *)ptr, opts, 1);
84 break;
86 case 2:
87 vec_dstt((VECTOR_UBYTE *)ptr, opts, 2);
88 break;
90 case 3:
91 vec_dstt((VECTOR_UBYTE *)ptr, opts, 3);
92 break;
97 static void cpu_vec_dstst(CONST_APTR ptr, ULONG opts, ULONG channel)
99 switch (channel)
101 case 0:
102 vec_dstst((VECTOR_UBYTE *)ptr, opts, 0);
103 break;
105 case 1:
106 vec_dstst((VECTOR_UBYTE *)ptr, opts, 1);
107 break;
109 case 2:
110 vec_dstst((VECTOR_UBYTE *)ptr, opts, 2);
111 break;
113 case 3:
114 vec_dstst((VECTOR_UBYTE *)ptr, opts, 3);
115 break;
120 static void cpu_vec_dststt(CONST_APTR ptr, ULONG opts, ULONG channel)
122 switch (channel)
124 case 0:
125 vec_dststt((VECTOR_UBYTE *)ptr, opts, 0);
126 break;
128 case 1:
129 vec_dststt((VECTOR_UBYTE *)ptr, opts, 1);
130 break;
132 case 2:
133 vec_dststt((VECTOR_UBYTE *)ptr, opts, 2);
134 break;
136 case 3:
137 vec_dststt((VECTOR_UBYTE *)ptr, opts, 3);
138 break;
143 static void cpu_vec_dss(ULONG channel)
145 switch (channel)
147 case 0:
148 vec_dss(0);
149 break;
151 case 1:
152 vec_dss(1);
153 break;
155 case 2:
156 vec_dss(2);
157 break;
159 case 3:
160 vec_dss(3);
161 break;
165 void cpu_cache_stream_start(CONST_APTR ptr, ULONG blockcount, ULONG blocksize, LONG stride, ULONG flags)
167 if (hasAltivec)
169 ULONG opts;
170 ULONG channel = 0;
172 opts = (blocksize << 24) | (blockcount << 16) | stride;
174 if (flags & CCSSF_CHANNEL1)
176 channel = 1;
178 else if (flags & CCSSF_CHANNEL2)
180 channel = 2;
182 else if (flags & CCSSF_CHANNEL3)
184 channel = 3;
187 if (flags & CCSSF_WRITES)
189 if (flags & CCSSF_TRANSCIENT)
191 cpu_vec_dststt(ptr, opts, channel);
193 else
195 cpu_vec_dstst(ptr, opts, channel);
198 else
200 if (flags & CCSSF_TRANSCIENT)
202 cpu_vec_dstt(ptr, opts, channel);
204 else
206 cpu_vec_dst(ptr, opts, channel);
210 else
212 //kprintf("[Altivec]: Not available\n");
214 /* XXX: fallback to dtst etc.. ? */
218 void cpu_cache_stream_stop(ULONG channel)
220 if (hasAltivec)
222 cpu_vec_dss(channel);
227 * Function using simple heuristics to determine caching.
230 void cpu_cache_image_start(void *ptr, int rowbytes, int width, int lines)
232 /* blocksize 0...31, 0 == 32 */
233 int blocksize;
234 int blocks = 256;
236 if (!hasAltivec)
237 return;
239 if (lines == 1)
241 blocksize = width / (blocks * 16); /* size of block in 16byte units */
242 if (blocksize == 0)
243 blocksize = 1;
244 if (blocksize > 31)
245 blocksize = 0;
247 else
249 blocksize = (rowbytes * lines) / (blocks * 16);
250 if (blocksize == 0)
251 blocksize = 1;
252 if (blocksize > 31)
253 blocksize = 0;
256 if (blocks > 255)
257 blocks = 0;
259 cpu_cache_stream_start((void*)((unsigned int)ptr & ~0xf), blocks, blocksize, blocksize * 16, CCSSF_CHANNEL1);
262 void cpu_cache_image_stop(void)
264 cpu_cache_stream_stop(1);
267 ////