1#ifndef _S390_BITOPS_H
2#define _S390_BITOPS_H
3
4
5
6
7
8
9
10
11
12
13
14
15
16#ifdef __KERNEL__
17
18#ifndef _LINUX_BITOPS_H
19#error only <linux/bitops.h> can be included directly
20#endif
21
22#include <linux/compiler.h>
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61extern const char _oi_bitmap[];
62extern const char _ni_bitmap[];
63extern const char _zb_findmap[];
64extern const char _sb_findmap[];
65
66#ifndef __s390x__
67
68#define __BITOPS_ALIGN 3
69#define __BITOPS_WORDSIZE 32
70#define __BITOPS_OR "or"
71#define __BITOPS_AND "nr"
72#define __BITOPS_XOR "xr"
73
74#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
75
76#define __BITOPS_LOOP(__old, __new, __addr, __val, __op_string) \
77 asm volatile( \
78 " l %0,%2\n" \
79 "0: lr %1,%0\n" \
80 __op_string " %1,%3\n" \
81 " cs %0,%1,%2\n" \
82 " jl 0b" \
83 : "=&d" (__old), "=&d" (__new), \
84 "=Q" (*(unsigned long *) __addr) \
85 : "d" (__val), "Q" (*(unsigned long *) __addr) \
86 : "cc");
87
88#else
89
90#define __BITOPS_LOOP(__old, __new, __addr, __val, __op_string) \
91 asm volatile( \
92 " l %0,0(%4)\n" \
93 "0: lr %1,%0\n" \
94 __op_string " %1,%3\n" \
95 " cs %0,%1,0(%4)\n" \
96 " jl 0b" \
97 : "=&d" (__old), "=&d" (__new), \
98 "=m" (*(unsigned long *) __addr) \
99 : "d" (__val), "a" (__addr), \
100 "m" (*(unsigned long *) __addr) : "cc");
101
102#endif
103
104#else
105
106#define __BITOPS_ALIGN 7
107#define __BITOPS_WORDSIZE 64
108#define __BITOPS_OR "ogr"
109#define __BITOPS_AND "ngr"
110#define __BITOPS_XOR "xgr"
111
112#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
113
114#define __BITOPS_LOOP(__old, __new, __addr, __val, __op_string) \
115 asm volatile( \
116 " lg %0,%2\n" \
117 "0: lgr %1,%0\n" \
118 __op_string " %1,%3\n" \
119 " csg %0,%1,%2\n" \
120 " jl 0b" \
121 : "=&d" (__old), "=&d" (__new), \
122 "=Q" (*(unsigned long *) __addr) \
123 : "d" (__val), "Q" (*(unsigned long *) __addr) \
124 : "cc");
125
126#else
127
128#define __BITOPS_LOOP(__old, __new, __addr, __val, __op_string) \
129 asm volatile( \
130 " lg %0,0(%4)\n" \
131 "0: lgr %1,%0\n" \
132 __op_string " %1,%3\n" \
133 " csg %0,%1,0(%4)\n" \
134 " jl 0b" \
135 : "=&d" (__old), "=&d" (__new), \
136 "=m" (*(unsigned long *) __addr) \
137 : "d" (__val), "a" (__addr), \
138 "m" (*(unsigned long *) __addr) : "cc");
139
140
141#endif
142
143#endif
144
145#define __BITOPS_WORDS(bits) (((bits)+__BITOPS_WORDSIZE-1)/__BITOPS_WORDSIZE)
146#define __BITOPS_BARRIER() asm volatile("" : : : "memory")
147
148#ifdef CONFIG_SMP
149
150
151
152static inline void set_bit_cs(unsigned long nr, volatile unsigned long *ptr)
153{
154 unsigned long addr, old, new, mask;
155
156 addr = (unsigned long) ptr;
157
158 addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3;
159
160 mask = 1UL << (nr & (__BITOPS_WORDSIZE - 1));
161
162 __BITOPS_LOOP(old, new, addr, mask, __BITOPS_OR);
163}
164
165
166
167
168static inline void clear_bit_cs(unsigned long nr, volatile unsigned long *ptr)
169{
170 unsigned long addr, old, new, mask;
171
172 addr = (unsigned long) ptr;
173
174 addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3;
175
176 mask = ~(1UL << (nr & (__BITOPS_WORDSIZE - 1)));
177
178 __BITOPS_LOOP(old, new, addr, mask, __BITOPS_AND);
179}
180
181
182
183
184static inline void change_bit_cs(unsigned long nr, volatile unsigned long *ptr)
185{
186 unsigned long addr, old, new, mask;
187
188 addr = (unsigned long) ptr;
189
190 addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3;
191
192 mask = 1UL << (nr & (__BITOPS_WORDSIZE - 1));
193
194 __BITOPS_LOOP(old, new, addr, mask, __BITOPS_XOR);
195}
196
197
198
199
200static inline int
201test_and_set_bit_cs(unsigned long nr, volatile unsigned long *ptr)
202{
203 unsigned long addr, old, new, mask;
204
205 addr = (unsigned long) ptr;
206
207 addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3;
208
209 mask = 1UL << (nr & (__BITOPS_WORDSIZE - 1));
210
211 __BITOPS_LOOP(old, new, addr, mask, __BITOPS_OR);
212 __BITOPS_BARRIER();
213 return (old & mask) != 0;
214}
215
216
217
218
219static inline int
220test_and_clear_bit_cs(unsigned long nr, volatile unsigned long *ptr)
221{
222 unsigned long addr, old, new, mask;
223
224 addr = (unsigned long) ptr;
225
226 addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3;
227
228 mask = ~(1UL << (nr & (__BITOPS_WORDSIZE - 1)));
229
230 __BITOPS_LOOP(old, new, addr, mask, __BITOPS_AND);
231 __BITOPS_BARRIER();
232 return (old ^ new) != 0;
233}
234
235
236
237
238static inline int
239test_and_change_bit_cs(unsigned long nr, volatile unsigned long *ptr)
240{
241 unsigned long addr, old, new, mask;
242
243 addr = (unsigned long) ptr;
244
245 addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3;
246
247 mask = 1UL << (nr & (__BITOPS_WORDSIZE - 1));
248
249 __BITOPS_LOOP(old, new, addr, mask, __BITOPS_XOR);
250 __BITOPS_BARRIER();
251 return (old & mask) != 0;
252}
253#endif
254
255
256
257
258static inline void __set_bit(unsigned long nr, volatile unsigned long *ptr)
259{
260 unsigned long addr;
261
262 addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
263 asm volatile(
264 " oc 0(1,%1),0(%2)"
265 : "=m" (*(char *) addr) : "a" (addr),
266 "a" (_oi_bitmap + (nr & 7)), "m" (*(char *) addr) : "cc" );
267}
268
269static inline void
270__constant_set_bit(const unsigned long nr, volatile unsigned long *ptr)
271{
272 unsigned long addr;
273
274 addr = ((unsigned long) ptr) + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
275 *(unsigned char *) addr |= 1 << (nr & 7);
276}
277
278#define set_bit_simple(nr,addr) \
279(__builtin_constant_p((nr)) ? \
280 __constant_set_bit((nr),(addr)) : \
281 __set_bit((nr),(addr)) )
282
283
284
285
286static inline void
287__clear_bit(unsigned long nr, volatile unsigned long *ptr)
288{
289 unsigned long addr;
290
291 addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
292 asm volatile(
293 " nc 0(1,%1),0(%2)"
294 : "=m" (*(char *) addr) : "a" (addr),
295 "a" (_ni_bitmap + (nr & 7)), "m" (*(char *) addr) : "cc");
296}
297
298static inline void
299__constant_clear_bit(const unsigned long nr, volatile unsigned long *ptr)
300{
301 unsigned long addr;
302
303 addr = ((unsigned long) ptr) + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
304 *(unsigned char *) addr &= ~(1 << (nr & 7));
305}
306
307#define clear_bit_simple(nr,addr) \
308(__builtin_constant_p((nr)) ? \
309 __constant_clear_bit((nr),(addr)) : \
310 __clear_bit((nr),(addr)) )
311
312
313
314
315static inline void __change_bit(unsigned long nr, volatile unsigned long *ptr)
316{
317 unsigned long addr;
318
319 addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
320 asm volatile(
321 " xc 0(1,%1),0(%2)"
322 : "=m" (*(char *) addr) : "a" (addr),
323 "a" (_oi_bitmap + (nr & 7)), "m" (*(char *) addr) : "cc" );
324}
325
326static inline void
327__constant_change_bit(const unsigned long nr, volatile unsigned long *ptr)
328{
329 unsigned long addr;
330
331 addr = ((unsigned long) ptr) + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
332 *(unsigned char *) addr ^= 1 << (nr & 7);
333}
334
335#define change_bit_simple(nr,addr) \
336(__builtin_constant_p((nr)) ? \
337 __constant_change_bit((nr),(addr)) : \
338 __change_bit((nr),(addr)) )
339
340
341
342
343static inline int
344test_and_set_bit_simple(unsigned long nr, volatile unsigned long *ptr)
345{
346 unsigned long addr;
347 unsigned char ch;
348
349 addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
350 ch = *(unsigned char *) addr;
351 asm volatile(
352 " oc 0(1,%1),0(%2)"
353 : "=m" (*(char *) addr)
354 : "a" (addr), "a" (_oi_bitmap + (nr & 7)),
355 "m" (*(char *) addr) : "cc", "memory");
356 return (ch >> (nr & 7)) & 1;
357}
358#define __test_and_set_bit(X,Y) test_and_set_bit_simple(X,Y)
359
360
361
362
363static inline int
364test_and_clear_bit_simple(unsigned long nr, volatile unsigned long *ptr)
365{
366 unsigned long addr;
367 unsigned char ch;
368
369 addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
370 ch = *(unsigned char *) addr;
371 asm volatile(
372 " nc 0(1,%1),0(%2)"
373 : "=m" (*(char *) addr)
374 : "a" (addr), "a" (_ni_bitmap + (nr & 7)),
375 "m" (*(char *) addr) : "cc", "memory");
376 return (ch >> (nr & 7)) & 1;
377}
378#define __test_and_clear_bit(X,Y) test_and_clear_bit_simple(X,Y)
379
380
381
382
383static inline int
384test_and_change_bit_simple(unsigned long nr, volatile unsigned long *ptr)
385{
386 unsigned long addr;
387 unsigned char ch;
388
389 addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
390 ch = *(unsigned char *) addr;
391 asm volatile(
392 " xc 0(1,%1),0(%2)"
393 : "=m" (*(char *) addr)
394 : "a" (addr), "a" (_oi_bitmap + (nr & 7)),
395 "m" (*(char *) addr) : "cc", "memory");
396 return (ch >> (nr & 7)) & 1;
397}
398#define __test_and_change_bit(X,Y) test_and_change_bit_simple(X,Y)
399
400#ifdef CONFIG_SMP
401#define set_bit set_bit_cs
402#define clear_bit clear_bit_cs
403#define change_bit change_bit_cs
404#define test_and_set_bit test_and_set_bit_cs
405#define test_and_clear_bit test_and_clear_bit_cs
406#define test_and_change_bit test_and_change_bit_cs
407#else
408#define set_bit set_bit_simple
409#define clear_bit clear_bit_simple
410#define change_bit change_bit_simple
411#define test_and_set_bit test_and_set_bit_simple
412#define test_and_clear_bit test_and_clear_bit_simple
413#define test_and_change_bit test_and_change_bit_simple
414#endif
415
416
417
418
419
420
421static inline int __test_bit(unsigned long nr, const volatile unsigned long *ptr)
422{
423 unsigned long addr;
424 unsigned char ch;
425
426 addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
427 ch = *(volatile unsigned char *) addr;
428 return (ch >> (nr & 7)) & 1;
429}
430
431static inline int
432__constant_test_bit(unsigned long nr, const volatile unsigned long *addr) {
433 return (((volatile char *) addr)
434 [(nr^(__BITOPS_WORDSIZE-8))>>3] & (1<<(nr&7))) != 0;
435}
436
437#define test_bit(nr,addr) \
438(__builtin_constant_p((nr)) ? \
439 __constant_test_bit((nr),(addr)) : \
440 __test_bit((nr),(addr)) )
441
442
443
444
445
446
447
448
449
450
451static inline unsigned long __ffz_word_loop(const unsigned long *addr,
452 unsigned long size)
453{
454 typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype;
455 unsigned long bytes = 0;
456
457 asm volatile(
458#ifndef __s390x__
459 " ahi %1,-1\n"
460 " sra %1,5\n"
461 " jz 1f\n"
462 "0: c %2,0(%0,%3)\n"
463 " jne 1f\n"
464 " la %0,4(%0)\n"
465 " brct %1,0b\n"
466 "1:\n"
467#else
468 " aghi %1,-1\n"
469 " srag %1,%1,6\n"
470 " jz 1f\n"
471 "0: cg %2,0(%0,%3)\n"
472 " jne 1f\n"
473 " la %0,8(%0)\n"
474 " brct %1,0b\n"
475 "1:\n"
476#endif
477 : "+&a" (bytes), "+&d" (size)
478 : "d" (-1UL), "a" (addr), "m" (*(addrtype *) addr)
479 : "cc" );
480 return bytes;
481}
482
483
484
485
486
487
488static inline unsigned long __ffs_word_loop(const unsigned long *addr,
489 unsigned long size)
490{
491 typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype;
492 unsigned long bytes = 0;
493
494 asm volatile(
495#ifndef __s390x__
496 " ahi %1,-1\n"
497 " sra %1,5\n"
498 " jz 1f\n"
499 "0: c %2,0(%0,%3)\n"
500 " jne 1f\n"
501 " la %0,4(%0)\n"
502 " brct %1,0b\n"
503 "1:\n"
504#else
505 " aghi %1,-1\n"
506 " srag %1,%1,6\n"
507 " jz 1f\n"
508 "0: cg %2,0(%0,%3)\n"
509 " jne 1f\n"
510 " la %0,8(%0)\n"
511 " brct %1,0b\n"
512 "1:\n"
513#endif
514 : "+&a" (bytes), "+&a" (size)
515 : "d" (0UL), "a" (addr), "m" (*(addrtype *) addr)
516 : "cc" );
517 return bytes;
518}
519
520
521
522
523
524
525static inline unsigned long __ffz_word(unsigned long nr, unsigned long word)
526{
527#ifdef __s390x__
528 if (likely((word & 0xffffffff) == 0xffffffff)) {
529 word >>= 32;
530 nr += 32;
531 }
532#endif
533 if (likely((word & 0xffff) == 0xffff)) {
534 word >>= 16;
535 nr += 16;
536 }
537 if (likely((word & 0xff) == 0xff)) {
538 word >>= 8;
539 nr += 8;
540 }
541 return nr + _zb_findmap[(unsigned char) word];
542}
543
544
545
546
547
548
549static inline unsigned long __ffs_word(unsigned long nr, unsigned long word)
550{
551#ifdef __s390x__
552 if (likely((word & 0xffffffff) == 0)) {
553 word >>= 32;
554 nr += 32;
555 }
556#endif
557 if (likely((word & 0xffff) == 0)) {
558 word >>= 16;
559 nr += 16;
560 }
561 if (likely((word & 0xff) == 0)) {
562 word >>= 8;
563 nr += 8;
564 }
565 return nr + _sb_findmap[(unsigned char) word];
566}
567
568
569
570
571
572
573
574static inline unsigned long __load_ulong_be(const unsigned long *p,
575 unsigned long offset)
576{
577 p = (unsigned long *)((unsigned long) p + offset);
578 return *p;
579}
580
581
582
583
584
585
586static inline unsigned long __load_ulong_le(const unsigned long *p,
587 unsigned long offset)
588{
589 unsigned long word;
590
591 p = (unsigned long *)((unsigned long) p + offset);
592#ifndef __s390x__
593 asm volatile(
594 " ic %0,0(%1)\n"
595 " icm %0,2,1(%1)\n"
596 " icm %0,4,2(%1)\n"
597 " icm %0,8,3(%1)"
598 : "=&d" (word) : "a" (p), "m" (*p) : "cc");
599#else
600 asm volatile(
601 " lrvg %0,%1"
602 : "=d" (word) : "m" (*p) );
603#endif
604 return word;
605}
606
607
608
609
610
611
612
613
614
615
616
617static inline unsigned long ffz(unsigned long word)
618{
619 return __ffz_word(0, word);
620}
621
622
623
624
625
626
627
628static inline unsigned long __ffs (unsigned long word)
629{
630 return __ffs_word(0, word);
631}
632
633
634
635
636
637
638
639
640
641static inline int ffs(int x)
642{
643 if (!x)
644 return 0;
645 return __ffs_word(1, x);
646}
647
648
649
650
651
652
653
654
655
656static inline unsigned long find_first_zero_bit(const unsigned long *addr,
657 unsigned long size)
658{
659 unsigned long bytes, bits;
660
661 if (!size)
662 return 0;
663 bytes = __ffz_word_loop(addr, size);
664 bits = __ffz_word(bytes*8, __load_ulong_be(addr, bytes));
665 return (bits < size) ? bits : size;
666}
667
668
669
670
671
672
673
674
675
676static inline unsigned long find_first_bit(const unsigned long * addr,
677 unsigned long size)
678{
679 unsigned long bytes, bits;
680
681 if (!size)
682 return 0;
683 bytes = __ffs_word_loop(addr, size);
684 bits = __ffs_word(bytes*8, __load_ulong_be(addr, bytes));
685 return (bits < size) ? bits : size;
686}
687
688
689
690
691
692
693
694static inline int find_next_zero_bit (const unsigned long * addr,
695 unsigned long size,
696 unsigned long offset)
697{
698 const unsigned long *p;
699 unsigned long bit, set;
700
701 if (offset >= size)
702 return size;
703 bit = offset & (__BITOPS_WORDSIZE - 1);
704 offset -= bit;
705 size -= offset;
706 p = addr + offset / __BITOPS_WORDSIZE;
707 if (bit) {
708
709
710
711
712 set = __ffz_word(bit, *p >> bit);
713 if (set >= size)
714 return size + offset;
715 if (set < __BITOPS_WORDSIZE)
716 return set + offset;
717 offset += __BITOPS_WORDSIZE;
718 size -= __BITOPS_WORDSIZE;
719 p++;
720 }
721 return offset + find_first_zero_bit(p, size);
722}
723
724
725
726
727
728
729
730static inline int find_next_bit (const unsigned long * addr,
731 unsigned long size,
732 unsigned long offset)
733{
734 const unsigned long *p;
735 unsigned long bit, set;
736
737 if (offset >= size)
738 return size;
739 bit = offset & (__BITOPS_WORDSIZE - 1);
740 offset -= bit;
741 size -= offset;
742 p = addr + offset / __BITOPS_WORDSIZE;
743 if (bit) {
744
745
746
747
748 set = __ffs_word(0, *p & (~0UL << bit));
749 if (set >= size)
750 return size + offset;
751 if (set < __BITOPS_WORDSIZE)
752 return set + offset;
753 offset += __BITOPS_WORDSIZE;
754 size -= __BITOPS_WORDSIZE;
755 p++;
756 }
757 return offset + find_first_bit(p, size);
758}
759
760
761
762
763
764
765
766static inline int sched_find_first_bit(unsigned long *b)
767{
768 return find_first_bit(b, 140);
769}
770
771#include <asm-generic/bitops/fls.h>
772#include <asm-generic/bitops/__fls.h>
773#include <asm-generic/bitops/fls64.h>
774
775#include <asm-generic/bitops/hweight.h>
776#include <asm-generic/bitops/lock.h>
777
778
779
780
781
782
783
784
785
786
787
788#define ext2_set_bit(nr, addr) \
789 __test_and_set_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr)
790#define ext2_set_bit_atomic(lock, nr, addr) \
791 test_and_set_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr)
792#define ext2_clear_bit(nr, addr) \
793 __test_and_clear_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr)
794#define ext2_clear_bit_atomic(lock, nr, addr) \
795 test_and_clear_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr)
796#define ext2_test_bit(nr, addr) \
797 test_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr)
798
799static inline int ext2_find_first_zero_bit(void *vaddr, unsigned int size)
800{
801 unsigned long bytes, bits;
802
803 if (!size)
804 return 0;
805 bytes = __ffz_word_loop(vaddr, size);
806 bits = __ffz_word(bytes*8, __load_ulong_le(vaddr, bytes));
807 return (bits < size) ? bits : size;
808}
809
810static inline int ext2_find_next_zero_bit(void *vaddr, unsigned long size,
811 unsigned long offset)
812{
813 unsigned long *addr = vaddr, *p;
814 unsigned long bit, set;
815
816 if (offset >= size)
817 return size;
818 bit = offset & (__BITOPS_WORDSIZE - 1);
819 offset -= bit;
820 size -= offset;
821 p = addr + offset / __BITOPS_WORDSIZE;
822 if (bit) {
823
824
825
826
827 set = __ffz_word(bit, __load_ulong_le(p, 0) >> bit);
828 if (set >= size)
829 return size + offset;
830 if (set < __BITOPS_WORDSIZE)
831 return set + offset;
832 offset += __BITOPS_WORDSIZE;
833 size -= __BITOPS_WORDSIZE;
834 p++;
835 }
836 return offset + ext2_find_first_zero_bit(p, size);
837}
838
839static inline unsigned long ext2_find_first_bit(void *vaddr,
840 unsigned long size)
841{
842 unsigned long bytes, bits;
843
844 if (!size)
845 return 0;
846 bytes = __ffs_word_loop(vaddr, size);
847 bits = __ffs_word(bytes*8, __load_ulong_le(vaddr, bytes));
848 return (bits < size) ? bits : size;
849}
850
851static inline int ext2_find_next_bit(void *vaddr, unsigned long size,
852 unsigned long offset)
853{
854 unsigned long *addr = vaddr, *p;
855 unsigned long bit, set;
856
857 if (offset >= size)
858 return size;
859 bit = offset & (__BITOPS_WORDSIZE - 1);
860 offset -= bit;
861 size -= offset;
862 p = addr + offset / __BITOPS_WORDSIZE;
863 if (bit) {
864
865
866
867
868 set = __ffs_word(0, __load_ulong_le(p, 0) & (~0UL << bit));
869 if (set >= size)
870 return size + offset;
871 if (set < __BITOPS_WORDSIZE)
872 return set + offset;
873 offset += __BITOPS_WORDSIZE;
874 size -= __BITOPS_WORDSIZE;
875 p++;
876 }
877 return offset + ext2_find_first_bit(p, size);
878}
879
880#include <asm-generic/bitops/minix.h>
881
882#endif
883
884#endif
885