xref: /openbsd/sys/arch/alpha/tc/tc_bus_mem.c (revision d415bd75)
1 /* $OpenBSD: tc_bus_mem.c,v 1.18 2023/03/08 04:43:07 guenther 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 int
239 tc_mem_map(v, memaddr, memsize, flags, memhp)
240 	void *v;
241 	bus_addr_t memaddr;
242 	bus_size_t memsize;
243 	int flags;
244 	bus_space_handle_t *memhp;
245 {
246 	int cacheable = flags & BUS_SPACE_MAP_CACHEABLE;
247 	int linear = flags & BUS_SPACE_MAP_LINEAR;
248 
249 	/* Requests for linear uncacheable space can't be satisfied. */
250 	if (linear && !cacheable)
251 		return (EOPNOTSUPP);
252 
253 	if (memaddr & 0x7)
254 		panic("tc_mem_map needs 8 byte alignment");
255 	if (cacheable)
256 		*memhp = ALPHA_PHYS_TO_K0SEG(memaddr);
257 	else
258 		*memhp = ALPHA_PHYS_TO_K0SEG(TC_DENSE_TO_SPARSE(memaddr));
259 	return (0);
260 }
261 
262 void
263 tc_mem_unmap(v, memh, memsize)
264 	void *v;
265 	bus_space_handle_t memh;
266 	bus_size_t memsize;
267 {
268 
269 	/* XXX XX XXX nothing to do. */
270 }
271 
272 int
273 tc_mem_subregion(v, memh, offset, size, nmemh)
274 	void *v;
275 	bus_space_handle_t memh, *nmemh;
276 	bus_size_t offset, size;
277 {
278 
279 	/* Disallow subregioning that would make the handle unaligned. */
280 	if ((offset & 0x7) != 0)
281 		return (1);
282 
283 	if ((memh & TC_SPACE_SPARSE) != 0)
284 		*nmemh = memh + (offset << 1);
285 	else
286 		*nmemh = memh + offset;
287 
288 	return (0);
289 }
290 
291 int
292 tc_mem_alloc(v, rstart, rend, size, align, boundary, flags, addrp, bshp)
293 	void *v;
294 	bus_addr_t rstart, rend, *addrp;
295 	bus_size_t size, align, boundary;
296 	int flags;
297 	bus_space_handle_t *bshp;
298 {
299 
300 	/* XXX XXX XXX XXX XXX XXX */
301 	panic("tc_mem_alloc unimplemented");
302 }
303 
304 void
305 tc_mem_free(v, bsh, size)
306 	void *v;
307 	bus_space_handle_t bsh;
308 	bus_size_t size;
309 {
310 
311 	/* XXX XXX XXX XXX XXX XXX */
312 	panic("tc_mem_free unimplemented");
313 }
314 
315 void *
316 tc_mem_vaddr(void *v, bus_space_handle_t bsh)
317 {
318 #ifdef DIAGNOSTIC
319 	if ((bsh & TC_SPACE_SPARSE) != 0) {
320 		/*
321 		 * tc_mem_map() catches linear && !cacheable,
322 		 * so we shouldn't come here
323 		 */
324 		panic("tc_mem_vaddr");
325 	}
326 #endif
327 	return ((void *)bsh);
328 }
329 
330 inline void
331 tc_mem_barrier(v, h, o, l, f)
332 	void *v;
333 	bus_space_handle_t h;
334 	bus_size_t o, l;
335 	int f;
336 {
337 
338 	if ((f & BUS_SPACE_BARRIER_READ) != 0)
339 		alpha_mb();
340 	else if ((f & BUS_SPACE_BARRIER_WRITE) != 0)
341 		alpha_wmb();
342 }
343 
344 inline u_int8_t
345 tc_mem_read_1(v, memh, off)
346 	void *v;
347 	bus_space_handle_t memh;
348 	bus_size_t off;
349 {
350 	volatile u_int8_t *p;
351 
352 	alpha_mb();		/* XXX XXX XXX */
353 
354 	if ((memh & TC_SPACE_SPARSE) != 0)
355 		panic("tc_mem_read_1 not implemented for sparse space");
356 
357 	p = (u_int8_t *)(memh + off);
358 	return (*p);
359 }
360 
361 inline u_int16_t
362 tc_mem_read_2(v, memh, off)
363 	void *v;
364 	bus_space_handle_t memh;
365 	bus_size_t off;
366 {
367 	volatile u_int16_t *p;
368 
369 	alpha_mb();		/* XXX XXX XXX */
370 
371 	if ((memh & TC_SPACE_SPARSE) != 0)
372 		panic("tc_mem_read_2 not implemented for sparse space");
373 
374 	p = (u_int16_t *)(memh + off);
375 	return (*p);
376 }
377 
378 inline u_int32_t
379 tc_mem_read_4(v, memh, off)
380 	void *v;
381 	bus_space_handle_t memh;
382 	bus_size_t off;
383 {
384 	volatile u_int32_t *p;
385 
386 	alpha_mb();		/* XXX XXX XXX */
387 
388 	if ((memh & TC_SPACE_SPARSE) != 0)
389 		/* Nothing special to do for 4-byte sparse space accesses */
390 		p = (u_int32_t *)(memh + (off << 1));
391 	else
392 		p = (u_int32_t *)(memh + off);
393 	return (*p);
394 }
395 
396 inline u_int64_t
397 tc_mem_read_8(v, memh, off)
398 	void *v;
399 	bus_space_handle_t memh;
400 	bus_size_t off;
401 {
402 	volatile u_int64_t *p;
403 
404 	alpha_mb();		/* XXX XXX XXX */
405 
406 	if ((memh & TC_SPACE_SPARSE) != 0)
407 		panic("tc_mem_read_8 not implemented for sparse space");
408 
409 	p = (u_int64_t *)(memh + off);
410 	return (*p);
411 }
412 
413 #define	tc_mem_read_multi_N(BYTES,TYPE)					\
414 void									\
415 __C(tc_mem_read_multi_,BYTES)(v, h, o, a, c)				\
416 	void *v;							\
417 	bus_space_handle_t h;						\
418 	bus_size_t o, c;						\
419 	TYPE *a;							\
420 {									\
421 									\
422 	while (c-- > 0) {						\
423 		tc_mem_barrier(v, h, o, sizeof *a, BUS_SPACE_BARRIER_READ); \
424 		*a++ = __C(tc_mem_read_,BYTES)(v, h, o);		\
425 	}								\
426 }
427 tc_mem_read_multi_N(1,u_int8_t)
428 tc_mem_read_multi_N(2,u_int16_t)
429 tc_mem_read_multi_N(4,u_int32_t)
430 tc_mem_read_multi_N(8,u_int64_t)
431 
432 #define	tc_mem_read_region_N(BYTES,TYPE)				\
433 void									\
434 __C(tc_mem_read_region_,BYTES)(v, h, o, a, c)				\
435 	void *v;							\
436 	bus_space_handle_t h;						\
437 	bus_size_t o, c;						\
438 	TYPE *a;							\
439 {									\
440 									\
441 	while (c-- > 0) {						\
442 		*a++ = __C(tc_mem_read_,BYTES)(v, h, o);		\
443 		o += sizeof *a;						\
444 	}								\
445 }
446 tc_mem_read_region_N(1,u_int8_t)
447 tc_mem_read_region_N(2,u_int16_t)
448 tc_mem_read_region_N(4,u_int32_t)
449 tc_mem_read_region_N(8,u_int64_t)
450 
451 inline void
452 tc_mem_write_1(v, memh, off, val)
453 	void *v;
454 	bus_space_handle_t memh;
455 	bus_size_t off;
456 	u_int8_t val;
457 {
458 
459 	if ((memh & TC_SPACE_SPARSE) != 0) {
460 		volatile u_int64_t *p, v;
461 		u_int64_t shift, msk;
462 
463 		shift = off & 0x3;
464 		off &= 0x3;
465 
466 		p = (u_int64_t *)(memh + (off << 1));
467 
468 		msk = ~(0x1 << shift) & 0xf;
469 		v = (msk << 32) | (((u_int64_t)val) << (shift * 8));
470 
471 		*p = val;
472 	} else {
473 		volatile u_int8_t *p;
474 
475 		p = (u_int8_t *)(memh + off);
476 		*p = val;
477 	}
478         alpha_mb();		/* XXX XXX XXX */
479 }
480 
481 inline void
482 tc_mem_write_2(v, memh, off, val)
483 	void *v;
484 	bus_space_handle_t memh;
485 	bus_size_t off;
486 	u_int16_t val;
487 {
488 
489 	if ((memh & TC_SPACE_SPARSE) != 0) {
490 		volatile u_int64_t *p, v;
491 		u_int64_t shift, msk;
492 
493 		shift = off & 0x2;
494 		off &= 0x3;
495 
496 		p = (u_int64_t *)(memh + (off << 1));
497 
498 		msk = ~(0x3 << shift) & 0xf;
499 		v = (msk << 32) | (((u_int64_t)val) << (shift * 8));
500 
501 		*p = val;
502 	} else {
503 		volatile u_int16_t *p;
504 
505 		p = (u_int16_t *)(memh + off);
506 		*p = val;
507 	}
508         alpha_mb();		/* XXX XXX XXX */
509 }
510 
511 inline void
512 tc_mem_write_4(v, memh, off, val)
513 	void *v;
514 	bus_space_handle_t memh;
515 	bus_size_t off;
516 	u_int32_t val;
517 {
518 	volatile u_int32_t *p;
519 
520 	if ((memh & TC_SPACE_SPARSE) != 0)
521 		/* Nothing special to do for 4-byte sparse space accesses */
522 		p = (u_int32_t *)(memh + (off << 1));
523 	else
524 		p = (u_int32_t *)(memh + off);
525 	*p = val;
526         alpha_mb();		/* XXX XXX XXX */
527 }
528 
529 inline void
530 tc_mem_write_8(v, memh, off, val)
531 	void *v;
532 	bus_space_handle_t memh;
533 	bus_size_t off;
534 	u_int64_t val;
535 {
536 	volatile u_int64_t *p;
537 
538 	if ((memh & TC_SPACE_SPARSE) != 0)
539 		panic("tc_mem_read_8 not implemented for sparse space");
540 
541 	p = (u_int64_t *)(memh + off);
542 	*p = val;
543         alpha_mb();		/* XXX XXX XXX */
544 }
545 
546 #define	tc_mem_write_multi_N(BYTES,TYPE)				\
547 void									\
548 __C(tc_mem_write_multi_,BYTES)(v, h, o, a, c)				\
549 	void *v;							\
550 	bus_space_handle_t h;						\
551 	bus_size_t o, c;						\
552 	const TYPE *a;							\
553 {									\
554 									\
555 	while (c-- > 0) {						\
556 		__C(tc_mem_write_,BYTES)(v, h, o, *a++);		\
557 		tc_mem_barrier(v, h, o, sizeof *a, BUS_SPACE_BARRIER_WRITE); \
558 	}								\
559 }
560 tc_mem_write_multi_N(1,u_int8_t)
561 tc_mem_write_multi_N(2,u_int16_t)
562 tc_mem_write_multi_N(4,u_int32_t)
563 tc_mem_write_multi_N(8,u_int64_t)
564 
565 #define	tc_mem_write_region_N(BYTES,TYPE)				\
566 void									\
567 __C(tc_mem_write_region_,BYTES)(v, h, o, a, c)				\
568 	void *v;							\
569 	bus_space_handle_t h;						\
570 	bus_size_t o, c;						\
571 	const TYPE *a;							\
572 {									\
573 									\
574 	while (c-- > 0) {						\
575 		__C(tc_mem_write_,BYTES)(v, h, o, *a++);		\
576 		o += sizeof *a;						\
577 	}								\
578 }
579 tc_mem_write_region_N(1,u_int8_t)
580 tc_mem_write_region_N(2,u_int16_t)
581 tc_mem_write_region_N(4,u_int32_t)
582 tc_mem_write_region_N(8,u_int64_t)
583 
584 #define	tc_mem_set_multi_N(BYTES,TYPE)					\
585 void									\
586 __C(tc_mem_set_multi_,BYTES)(v, h, o, val, c)				\
587 	void *v;							\
588 	bus_space_handle_t h;						\
589 	bus_size_t o, c;						\
590 	TYPE val;							\
591 {									\
592 									\
593 	while (c-- > 0) {						\
594 		__C(tc_mem_write_,BYTES)(v, h, o, val);			\
595 		tc_mem_barrier(v, h, o, sizeof val, BUS_SPACE_BARRIER_WRITE); \
596 	}								\
597 }
598 tc_mem_set_multi_N(1,u_int8_t)
599 tc_mem_set_multi_N(2,u_int16_t)
600 tc_mem_set_multi_N(4,u_int32_t)
601 tc_mem_set_multi_N(8,u_int64_t)
602 
603 #define	tc_mem_set_region_N(BYTES,TYPE)					\
604 void									\
605 __C(tc_mem_set_region_,BYTES)(v, h, o, val, c)				\
606 	void *v;							\
607 	bus_space_handle_t h;						\
608 	bus_size_t o, c;						\
609 	TYPE val;							\
610 {									\
611 									\
612 	while (c-- > 0) {						\
613 		__C(tc_mem_write_,BYTES)(v, h, o, val);			\
614 		o += sizeof val;					\
615 	}								\
616 }
617 tc_mem_set_region_N(1,u_int8_t)
618 tc_mem_set_region_N(2,u_int16_t)
619 tc_mem_set_region_N(4,u_int32_t)
620 tc_mem_set_region_N(8,u_int64_t)
621 
622 #define	tc_mem_copy_N(BYTES)						\
623 void									\
624 __C(tc_mem_copy_,BYTES)(v, h1, o1, h2, o2, c)				\
625 	void *v;							\
626 	bus_space_handle_t h1, h2;					\
627 	bus_size_t o1, o2, c;						\
628 {									\
629 	bus_size_t o;							\
630 									\
631 	if ((h1 & TC_SPACE_SPARSE) != 0 &&				\
632 	    (h2 & TC_SPACE_SPARSE) != 0) {				\
633 		bcopy((void *)(h1 + o1), (void *)(h2 + o2), c * BYTES); \
634 		return;							\
635 	}								\
636 									\
637 	if (h1 + o1 >= h2 + o2)						\
638 		/* src after dest: copy forward */			\
639 		for (o = 0; c > 0; c--, o += BYTES)			\
640 			__C(tc_mem_write_,BYTES)(v, h2, o2 + o,		\
641 			    __C(tc_mem_read_,BYTES)(v, h1, o1 + o));	\
642 	else								\
643 		/* dest after src: copy backwards */			\
644 		for (o = (c - 1) * BYTES; c > 0; c--, o -= BYTES)	\
645 			__C(tc_mem_write_,BYTES)(v, h2, o2 + o,		\
646 			    __C(tc_mem_read_,BYTES)(v, h1, o1 + o));	\
647 }
648 tc_mem_copy_N(1)
649 tc_mem_copy_N(2)
650 tc_mem_copy_N(4)
651 tc_mem_copy_N(8)
652