xref: /openbsd/sys/arch/alpha/tc/tc_bus_mem.c (revision 09467b48)
1 /* $OpenBSD: tc_bus_mem.c,v 1.17 2010/04/04 12:49:27 miod Exp $ */
2 /* $NetBSD: tc_bus_mem.c,v 1.25 2001/09/04 05:31:28 thorpej Exp $ */
3 
4 /*
5  * Copyright (c) 1996 Carnegie-Mellon University.
6  * All rights reserved.
7  *
8  * Author: Chris G. Demetriou
9  *
10  * Permission to use, copy, modify and distribute this software and
11  * its documentation is hereby granted, provided that both the copyright
12  * notice and this permission notice appear in all copies of the
13  * software, derivative works or modified versions, and any portions
14  * thereof, and that both notices appear in supporting documentation.
15  *
16  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
17  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
18  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
19  *
20  * Carnegie Mellon requests users of this software to return to
21  *
22  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
23  *  School of Computer Science
24  *  Carnegie Mellon University
25  *  Pittsburgh PA 15213-3890
26  *
27  * any improvements or extensions that they make and grant Carnegie the
28  * rights to redistribute these changes.
29  */
30 
31 /*
32  * Common TurboChannel Chipset "bus memory" functions.
33  */
34 
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/malloc.h>
38 #include <sys/syslog.h>
39 #include <sys/device.h>
40 
41 #include <uvm/uvm_extern.h>
42 
43 #include <machine/bus.h>
44 #include <dev/tc/tcvar.h>
45 
46 #define	__C(A,B)	__CONCAT(A,B)
47 
48 /* mapping/unmapping */
49 int		tc_mem_map(void *, bus_addr_t, bus_size_t, int,
50 		    bus_space_handle_t *);
51 void		tc_mem_unmap(void *, bus_space_handle_t, bus_size_t);
52 int		tc_mem_subregion(void *, bus_space_handle_t, bus_size_t,
53 		    bus_size_t, bus_space_handle_t *);
54 
55 /* allocation/deallocation */
56 int		tc_mem_alloc(void *, bus_addr_t, bus_addr_t, bus_size_t,
57 		    bus_size_t, bus_addr_t, int, bus_addr_t *,
58 		    bus_space_handle_t *);
59 void		tc_mem_free(void *, bus_space_handle_t, bus_size_t);
60 
61 /* get kernel virtual address */
62 void *		tc_mem_vaddr(void *, bus_space_handle_t);
63 
64 /* barrier */
65 inline void	tc_mem_barrier(void *, bus_space_handle_t,
66 		    bus_size_t, bus_size_t, int);
67 
68 /* read (single) */
69 inline u_int8_t	tc_mem_read_1(void *, bus_space_handle_t, bus_size_t);
70 inline u_int16_t tc_mem_read_2(void *, bus_space_handle_t, bus_size_t);
71 inline u_int32_t tc_mem_read_4(void *, bus_space_handle_t, bus_size_t);
72 inline u_int64_t tc_mem_read_8(void *, bus_space_handle_t, bus_size_t);
73 
74 /* read multiple */
75 void		tc_mem_read_multi_1(void *, bus_space_handle_t,
76 		    bus_size_t, u_int8_t *, bus_size_t);
77 void		tc_mem_read_multi_2(void *, bus_space_handle_t,
78 		    bus_size_t, u_int16_t *, bus_size_t);
79 void		tc_mem_read_multi_4(void *, bus_space_handle_t,
80 		    bus_size_t, u_int32_t *, bus_size_t);
81 void		tc_mem_read_multi_8(void *, bus_space_handle_t,
82 		    bus_size_t, u_int64_t *, bus_size_t);
83 
84 /* read region */
85 void		tc_mem_read_region_1(void *, bus_space_handle_t,
86 		    bus_size_t, u_int8_t *, bus_size_t);
87 void		tc_mem_read_region_2(void *, bus_space_handle_t,
88 		    bus_size_t, u_int16_t *, bus_size_t);
89 void		tc_mem_read_region_4(void *, bus_space_handle_t,
90 		    bus_size_t, u_int32_t *, bus_size_t);
91 void		tc_mem_read_region_8(void *, bus_space_handle_t,
92 		    bus_size_t, u_int64_t *, bus_size_t);
93 
94 /* write (single) */
95 inline void	tc_mem_write_1(void *, bus_space_handle_t, bus_size_t,
96 		    u_int8_t);
97 inline void	tc_mem_write_2(void *, bus_space_handle_t, bus_size_t,
98 		    u_int16_t);
99 inline void	tc_mem_write_4(void *, bus_space_handle_t, bus_size_t,
100 		    u_int32_t);
101 inline void	tc_mem_write_8(void *, bus_space_handle_t, bus_size_t,
102 		    u_int64_t);
103 
104 /* write multiple */
105 void		tc_mem_write_multi_1(void *, bus_space_handle_t,
106 		    bus_size_t, const u_int8_t *, bus_size_t);
107 void		tc_mem_write_multi_2(void *, bus_space_handle_t,
108 		    bus_size_t, const u_int16_t *, bus_size_t);
109 void		tc_mem_write_multi_4(void *, bus_space_handle_t,
110 		    bus_size_t, const u_int32_t *, bus_size_t);
111 void		tc_mem_write_multi_8(void *, bus_space_handle_t,
112 		    bus_size_t, const u_int64_t *, bus_size_t);
113 
114 /* write region */
115 void		tc_mem_write_region_1(void *, bus_space_handle_t,
116 		    bus_size_t, const u_int8_t *, bus_size_t);
117 void		tc_mem_write_region_2(void *, bus_space_handle_t,
118 		    bus_size_t, const u_int16_t *, bus_size_t);
119 void		tc_mem_write_region_4(void *, bus_space_handle_t,
120 		    bus_size_t, const u_int32_t *, bus_size_t);
121 void		tc_mem_write_region_8(void *, bus_space_handle_t,
122 		    bus_size_t, const u_int64_t *, bus_size_t);
123 
124 /* set multiple */
125 void		tc_mem_set_multi_1(void *, bus_space_handle_t,
126 		    bus_size_t, u_int8_t, bus_size_t);
127 void		tc_mem_set_multi_2(void *, bus_space_handle_t,
128 		    bus_size_t, u_int16_t, bus_size_t);
129 void		tc_mem_set_multi_4(void *, bus_space_handle_t,
130 		    bus_size_t, u_int32_t, bus_size_t);
131 void		tc_mem_set_multi_8(void *, bus_space_handle_t,
132 		    bus_size_t, u_int64_t, bus_size_t);
133 
134 /* set region */
135 void		tc_mem_set_region_1(void *, bus_space_handle_t,
136 		    bus_size_t, u_int8_t, bus_size_t);
137 void		tc_mem_set_region_2(void *, bus_space_handle_t,
138 		    bus_size_t, u_int16_t, bus_size_t);
139 void		tc_mem_set_region_4(void *, bus_space_handle_t,
140 		    bus_size_t, u_int32_t, bus_size_t);
141 void		tc_mem_set_region_8(void *, bus_space_handle_t,
142 		    bus_size_t, u_int64_t, bus_size_t);
143 
144 /* copy */
145 void		tc_mem_copy_1(void *, bus_space_handle_t,
146 		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t);
147 void		tc_mem_copy_2(void *, bus_space_handle_t,
148 		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t);
149 void		tc_mem_copy_4(void *, bus_space_handle_t,
150 		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t);
151 void		tc_mem_copy_8(void *, bus_space_handle_t,
152 		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t);
153 
154 struct alpha_bus_space tc_mem_space = {
155 	/* cookie */
156 	NULL,
157 
158 	/* mapping/unmapping */
159 	tc_mem_map,
160 	tc_mem_unmap,
161 	tc_mem_subregion,
162 
163 	/* allocation/deallocation */
164 	tc_mem_alloc,
165 	tc_mem_free,
166 
167 	/* get kernel virtual address */
168 	tc_mem_vaddr,
169 
170 	/* barrier */
171 	tc_mem_barrier,
172 
173 	/* read (single) */
174 	tc_mem_read_1,
175 	tc_mem_read_2,
176 	tc_mem_read_4,
177 	tc_mem_read_8,
178 
179 	/* read multiple */
180 	tc_mem_read_multi_1,
181 	tc_mem_read_multi_2,
182 	tc_mem_read_multi_4,
183 	tc_mem_read_multi_8,
184 
185 	/* read region */
186 	tc_mem_read_region_1,
187 	tc_mem_read_region_2,
188 	tc_mem_read_region_4,
189 	tc_mem_read_region_8,
190 
191 	/* write (single) */
192 	tc_mem_write_1,
193 	tc_mem_write_2,
194 	tc_mem_write_4,
195 	tc_mem_write_8,
196 
197 	/* write multiple */
198 	tc_mem_write_multi_1,
199 	tc_mem_write_multi_2,
200 	tc_mem_write_multi_4,
201 	tc_mem_write_multi_8,
202 
203 	/* write region */
204 	tc_mem_write_region_1,
205 	tc_mem_write_region_2,
206 	tc_mem_write_region_4,
207 	tc_mem_write_region_8,
208 
209 	/* set multiple */
210 	tc_mem_set_multi_1,
211 	tc_mem_set_multi_2,
212 	tc_mem_set_multi_4,
213 	tc_mem_set_multi_8,
214 
215 	/* set region */
216 	tc_mem_set_region_1,
217 	tc_mem_set_region_2,
218 	tc_mem_set_region_4,
219 	tc_mem_set_region_8,
220 
221 	/* copy */
222 	tc_mem_copy_1,
223 	tc_mem_copy_2,
224 	tc_mem_copy_4,
225 	tc_mem_copy_8,
226 };
227 
228 bus_space_tag_t
229 tc_bus_mem_init(memv)
230 	void *memv;
231 {
232 	bus_space_tag_t h = &tc_mem_space;
233 
234 	h->abs_cookie = memv;
235 	return (h);
236 }
237 
238 /* ARGSUSED */
239 int
240 tc_mem_map(v, memaddr, memsize, flags, memhp)
241 	void *v;
242 	bus_addr_t memaddr;
243 	bus_size_t memsize;
244 	int flags;
245 	bus_space_handle_t *memhp;
246 {
247 	int cacheable = flags & BUS_SPACE_MAP_CACHEABLE;
248 	int linear = flags & BUS_SPACE_MAP_LINEAR;
249 
250 	/* Requests for linear uncacheable space can't be satisfied. */
251 	if (linear && !cacheable)
252 		return (EOPNOTSUPP);
253 
254 	if (memaddr & 0x7)
255 		panic("tc_mem_map needs 8 byte alignment");
256 	if (cacheable)
257 		*memhp = ALPHA_PHYS_TO_K0SEG(memaddr);
258 	else
259 		*memhp = ALPHA_PHYS_TO_K0SEG(TC_DENSE_TO_SPARSE(memaddr));
260 	return (0);
261 }
262 
263 /* ARGSUSED */
264 void
265 tc_mem_unmap(v, memh, memsize)
266 	void *v;
267 	bus_space_handle_t memh;
268 	bus_size_t memsize;
269 {
270 
271 	/* XXX XX XXX nothing to do. */
272 }
273 
274 int
275 tc_mem_subregion(v, memh, offset, size, nmemh)
276 	void *v;
277 	bus_space_handle_t memh, *nmemh;
278 	bus_size_t offset, size;
279 {
280 
281 	/* Disallow subregioning that would make the handle unaligned. */
282 	if ((offset & 0x7) != 0)
283 		return (1);
284 
285 	if ((memh & TC_SPACE_SPARSE) != 0)
286 		*nmemh = memh + (offset << 1);
287 	else
288 		*nmemh = memh + offset;
289 
290 	return (0);
291 }
292 
293 int
294 tc_mem_alloc(v, rstart, rend, size, align, boundary, flags, addrp, bshp)
295 	void *v;
296 	bus_addr_t rstart, rend, *addrp;
297 	bus_size_t size, align, boundary;
298 	int flags;
299 	bus_space_handle_t *bshp;
300 {
301 
302 	/* XXX XXX XXX XXX XXX XXX */
303 	panic("tc_mem_alloc unimplemented");
304 }
305 
306 void
307 tc_mem_free(v, bsh, size)
308 	void *v;
309 	bus_space_handle_t bsh;
310 	bus_size_t size;
311 {
312 
313 	/* XXX XXX XXX XXX XXX XXX */
314 	panic("tc_mem_free unimplemented");
315 }
316 
317 void *
318 tc_mem_vaddr(void *v, bus_space_handle_t bsh)
319 {
320 #ifdef DIAGNOSTIC
321 	if ((bsh & TC_SPACE_SPARSE) != 0) {
322 		/*
323 		 * tc_mem_map() catches linear && !cacheable,
324 		 * so we shouldn't come here
325 		 */
326 		panic("tc_mem_vaddr");
327 	}
328 #endif
329 	return ((void *)bsh);
330 }
331 
332 inline void
333 tc_mem_barrier(v, h, o, l, f)
334 	void *v;
335 	bus_space_handle_t h;
336 	bus_size_t o, l;
337 	int f;
338 {
339 
340 	if ((f & BUS_SPACE_BARRIER_READ) != 0)
341 		alpha_mb();
342 	else if ((f & BUS_SPACE_BARRIER_WRITE) != 0)
343 		alpha_wmb();
344 }
345 
346 inline u_int8_t
347 tc_mem_read_1(v, memh, off)
348 	void *v;
349 	bus_space_handle_t memh;
350 	bus_size_t off;
351 {
352 	volatile u_int8_t *p;
353 
354 	alpha_mb();		/* XXX XXX XXX */
355 
356 	if ((memh & TC_SPACE_SPARSE) != 0)
357 		panic("tc_mem_read_1 not implemented for sparse space");
358 
359 	p = (u_int8_t *)(memh + off);
360 	return (*p);
361 }
362 
363 inline u_int16_t
364 tc_mem_read_2(v, memh, off)
365 	void *v;
366 	bus_space_handle_t memh;
367 	bus_size_t off;
368 {
369 	volatile u_int16_t *p;
370 
371 	alpha_mb();		/* XXX XXX XXX */
372 
373 	if ((memh & TC_SPACE_SPARSE) != 0)
374 		panic("tc_mem_read_2 not implemented for sparse space");
375 
376 	p = (u_int16_t *)(memh + off);
377 	return (*p);
378 }
379 
380 inline u_int32_t
381 tc_mem_read_4(v, memh, off)
382 	void *v;
383 	bus_space_handle_t memh;
384 	bus_size_t off;
385 {
386 	volatile u_int32_t *p;
387 
388 	alpha_mb();		/* XXX XXX XXX */
389 
390 	if ((memh & TC_SPACE_SPARSE) != 0)
391 		/* Nothing special to do for 4-byte sparse space accesses */
392 		p = (u_int32_t *)(memh + (off << 1));
393 	else
394 		p = (u_int32_t *)(memh + off);
395 	return (*p);
396 }
397 
398 inline u_int64_t
399 tc_mem_read_8(v, memh, off)
400 	void *v;
401 	bus_space_handle_t memh;
402 	bus_size_t off;
403 {
404 	volatile u_int64_t *p;
405 
406 	alpha_mb();		/* XXX XXX XXX */
407 
408 	if ((memh & TC_SPACE_SPARSE) != 0)
409 		panic("tc_mem_read_8 not implemented for sparse space");
410 
411 	p = (u_int64_t *)(memh + off);
412 	return (*p);
413 }
414 
415 #define	tc_mem_read_multi_N(BYTES,TYPE)					\
416 void									\
417 __C(tc_mem_read_multi_,BYTES)(v, h, o, a, c)				\
418 	void *v;							\
419 	bus_space_handle_t h;						\
420 	bus_size_t o, c;						\
421 	TYPE *a;							\
422 {									\
423 									\
424 	while (c-- > 0) {						\
425 		tc_mem_barrier(v, h, o, sizeof *a, BUS_SPACE_BARRIER_READ); \
426 		*a++ = __C(tc_mem_read_,BYTES)(v, h, o);		\
427 	}								\
428 }
429 tc_mem_read_multi_N(1,u_int8_t)
430 tc_mem_read_multi_N(2,u_int16_t)
431 tc_mem_read_multi_N(4,u_int32_t)
432 tc_mem_read_multi_N(8,u_int64_t)
433 
434 #define	tc_mem_read_region_N(BYTES,TYPE)				\
435 void									\
436 __C(tc_mem_read_region_,BYTES)(v, h, o, a, c)				\
437 	void *v;							\
438 	bus_space_handle_t h;						\
439 	bus_size_t o, c;						\
440 	TYPE *a;							\
441 {									\
442 									\
443 	while (c-- > 0) {						\
444 		*a++ = __C(tc_mem_read_,BYTES)(v, h, o);		\
445 		o += sizeof *a;						\
446 	}								\
447 }
448 tc_mem_read_region_N(1,u_int8_t)
449 tc_mem_read_region_N(2,u_int16_t)
450 tc_mem_read_region_N(4,u_int32_t)
451 tc_mem_read_region_N(8,u_int64_t)
452 
453 inline void
454 tc_mem_write_1(v, memh, off, val)
455 	void *v;
456 	bus_space_handle_t memh;
457 	bus_size_t off;
458 	u_int8_t val;
459 {
460 
461 	if ((memh & TC_SPACE_SPARSE) != 0) {
462 		volatile u_int64_t *p, v;
463 		u_int64_t shift, msk;
464 
465 		shift = off & 0x3;
466 		off &= 0x3;
467 
468 		p = (u_int64_t *)(memh + (off << 1));
469 
470 		msk = ~(0x1 << shift) & 0xf;
471 		v = (msk << 32) | (((u_int64_t)val) << (shift * 8));
472 
473 		*p = val;
474 	} else {
475 		volatile u_int8_t *p;
476 
477 		p = (u_int8_t *)(memh + off);
478 		*p = val;
479 	}
480         alpha_mb();		/* XXX XXX XXX */
481 }
482 
483 inline void
484 tc_mem_write_2(v, memh, off, val)
485 	void *v;
486 	bus_space_handle_t memh;
487 	bus_size_t off;
488 	u_int16_t val;
489 {
490 
491 	if ((memh & TC_SPACE_SPARSE) != 0) {
492 		volatile u_int64_t *p, v;
493 		u_int64_t shift, msk;
494 
495 		shift = off & 0x2;
496 		off &= 0x3;
497 
498 		p = (u_int64_t *)(memh + (off << 1));
499 
500 		msk = ~(0x3 << shift) & 0xf;
501 		v = (msk << 32) | (((u_int64_t)val) << (shift * 8));
502 
503 		*p = val;
504 	} else {
505 		volatile u_int16_t *p;
506 
507 		p = (u_int16_t *)(memh + off);
508 		*p = val;
509 	}
510         alpha_mb();		/* XXX XXX XXX */
511 }
512 
513 inline void
514 tc_mem_write_4(v, memh, off, val)
515 	void *v;
516 	bus_space_handle_t memh;
517 	bus_size_t off;
518 	u_int32_t val;
519 {
520 	volatile u_int32_t *p;
521 
522 	if ((memh & TC_SPACE_SPARSE) != 0)
523 		/* Nothing special to do for 4-byte sparse space accesses */
524 		p = (u_int32_t *)(memh + (off << 1));
525 	else
526 		p = (u_int32_t *)(memh + off);
527 	*p = val;
528         alpha_mb();		/* XXX XXX XXX */
529 }
530 
531 inline void
532 tc_mem_write_8(v, memh, off, val)
533 	void *v;
534 	bus_space_handle_t memh;
535 	bus_size_t off;
536 	u_int64_t val;
537 {
538 	volatile u_int64_t *p;
539 
540 	if ((memh & TC_SPACE_SPARSE) != 0)
541 		panic("tc_mem_read_8 not implemented for sparse space");
542 
543 	p = (u_int64_t *)(memh + off);
544 	*p = val;
545         alpha_mb();		/* XXX XXX XXX */
546 }
547 
548 #define	tc_mem_write_multi_N(BYTES,TYPE)				\
549 void									\
550 __C(tc_mem_write_multi_,BYTES)(v, h, o, a, c)				\
551 	void *v;							\
552 	bus_space_handle_t h;						\
553 	bus_size_t o, c;						\
554 	const TYPE *a;							\
555 {									\
556 									\
557 	while (c-- > 0) {						\
558 		__C(tc_mem_write_,BYTES)(v, h, o, *a++);		\
559 		tc_mem_barrier(v, h, o, sizeof *a, BUS_SPACE_BARRIER_WRITE); \
560 	}								\
561 }
562 tc_mem_write_multi_N(1,u_int8_t)
563 tc_mem_write_multi_N(2,u_int16_t)
564 tc_mem_write_multi_N(4,u_int32_t)
565 tc_mem_write_multi_N(8,u_int64_t)
566 
567 #define	tc_mem_write_region_N(BYTES,TYPE)				\
568 void									\
569 __C(tc_mem_write_region_,BYTES)(v, h, o, a, c)				\
570 	void *v;							\
571 	bus_space_handle_t h;						\
572 	bus_size_t o, c;						\
573 	const TYPE *a;							\
574 {									\
575 									\
576 	while (c-- > 0) {						\
577 		__C(tc_mem_write_,BYTES)(v, h, o, *a++);		\
578 		o += sizeof *a;						\
579 	}								\
580 }
581 tc_mem_write_region_N(1,u_int8_t)
582 tc_mem_write_region_N(2,u_int16_t)
583 tc_mem_write_region_N(4,u_int32_t)
584 tc_mem_write_region_N(8,u_int64_t)
585 
586 #define	tc_mem_set_multi_N(BYTES,TYPE)					\
587 void									\
588 __C(tc_mem_set_multi_,BYTES)(v, h, o, val, c)				\
589 	void *v;							\
590 	bus_space_handle_t h;						\
591 	bus_size_t o, c;						\
592 	TYPE val;							\
593 {									\
594 									\
595 	while (c-- > 0) {						\
596 		__C(tc_mem_write_,BYTES)(v, h, o, val);			\
597 		tc_mem_barrier(v, h, o, sizeof val, BUS_SPACE_BARRIER_WRITE); \
598 	}								\
599 }
600 tc_mem_set_multi_N(1,u_int8_t)
601 tc_mem_set_multi_N(2,u_int16_t)
602 tc_mem_set_multi_N(4,u_int32_t)
603 tc_mem_set_multi_N(8,u_int64_t)
604 
605 #define	tc_mem_set_region_N(BYTES,TYPE)					\
606 void									\
607 __C(tc_mem_set_region_,BYTES)(v, h, o, val, c)				\
608 	void *v;							\
609 	bus_space_handle_t h;						\
610 	bus_size_t o, c;						\
611 	TYPE val;							\
612 {									\
613 									\
614 	while (c-- > 0) {						\
615 		__C(tc_mem_write_,BYTES)(v, h, o, val);			\
616 		o += sizeof val;					\
617 	}								\
618 }
619 tc_mem_set_region_N(1,u_int8_t)
620 tc_mem_set_region_N(2,u_int16_t)
621 tc_mem_set_region_N(4,u_int32_t)
622 tc_mem_set_region_N(8,u_int64_t)
623 
624 #define	tc_mem_copy_N(BYTES)						\
625 void									\
626 __C(tc_mem_copy_,BYTES)(v, h1, o1, h2, o2, c)				\
627 	void *v;							\
628 	bus_space_handle_t h1, h2;					\
629 	bus_size_t o1, o2, c;						\
630 {									\
631 	bus_size_t o;							\
632 									\
633 	if ((h1 & TC_SPACE_SPARSE) != 0 &&				\
634 	    (h2 & TC_SPACE_SPARSE) != 0) {				\
635 		bcopy((void *)(h1 + o1), (void *)(h2 + o2), c * BYTES); \
636 		return;							\
637 	}								\
638 									\
639 	if (h1 + o1 >= h2 + o2)						\
640 		/* src after dest: copy forward */			\
641 		for (o = 0; c > 0; c--, o += BYTES)			\
642 			__C(tc_mem_write_,BYTES)(v, h2, o2 + o,		\
643 			    __C(tc_mem_read_,BYTES)(v, h1, o1 + o));	\
644 	else								\
645 		/* dest after src: copy backwards */			\
646 		for (o = (c - 1) * BYTES; c > 0; c--, o -= BYTES)	\
647 			__C(tc_mem_write_,BYTES)(v, h2, o2 + o,		\
648 			    __C(tc_mem_read_,BYTES)(v, h1, o1 + o));	\
649 }
650 tc_mem_copy_N(1)
651 tc_mem_copy_N(2)
652 tc_mem_copy_N(4)
653 tc_mem_copy_N(8)
654