OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [include/] [asm-s390/] [bitops.h] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1276 phoenix
#ifndef _S390_BITOPS_H
2
#define _S390_BITOPS_H
3
 
4
/*
5
 *  include/asm-s390/bitops.h
6
 *
7
 *  S390 version
8
 *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
9
 *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
10
 *
11
 *  Derived from "include/asm-i386/bitops.h"
12
 *    Copyright (C) 1992, Linus Torvalds
13
 *
14
 */
15
#include <linux/config.h>
16
 
17
/*
18
 * bit 0 is the LSB of *addr; bit 31 is the MSB of *addr;
19
 * bit 32 is the LSB of *(addr+4). That combined with the
20
 * big endian byte order on S390 give the following bit
21
 * order in memory:
22
 *    1f 1e 1d 1c 1b 1a 19 18 17 16 15 14 13 12 11 10 \
23
 *    0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00
24
 * after that follows the next long with bit numbers
25
 *    3f 3e 3d 3c 3b 3a 39 38 37 36 35 34 33 32 31 30
26
 *    2f 2e 2d 2c 2b 2a 29 28 27 26 25 24 23 22 21 20
27
 * The reason for this bit ordering is the fact that
28
 * in the architecture independent code bits operations
29
 * of the form "flags |= (1 << bitnr)" are used INTERMIXED
30
 * with operation of the form "set_bit(bitnr, flags)".
31
 */
32
 
33
/* set ALIGN_CS to 1 if the SMP safe bit operations should
34
 * align the address to 4 byte boundary. It seems to work
35
 * without the alignment.
36
 */
37
#ifdef __KERNEL__
38
#define ALIGN_CS 0
39
#else
40
#define ALIGN_CS 1
41
#ifndef CONFIG_SMP
42
#error "bitops won't work without CONFIG_SMP"
43
#endif
44
#endif
45
 
46
/* bitmap tables from arch/S390/kernel/bitmap.S */
47
extern const char _oi_bitmap[];
48
extern const char _ni_bitmap[];
49
extern const char _zb_findmap[];
50
 
51
#ifdef CONFIG_SMP
52
/*
53
 * SMP save set_bit routine based on compare and swap (CS)
54
 */
55
static __inline__ void set_bit_cs(int nr, volatile void * addr)
56
{
57
        unsigned long bits, mask;
58
        __asm__ __volatile__(
59
#if ALIGN_CS == 1
60
             "   lhi   %2,3\n"         /* CS must be aligned on 4 byte b. */
61
             "   nr    %2,%1\n"        /* isolate last 2 bits of address */
62
             "   xr    %1,%2\n"        /* make addr % 4 == 0 */
63
             "   sll   %2,3\n"
64
             "   ar    %0,%2\n"        /* add alignement to bitnr */
65
#endif
66
             "   lhi   %2,31\n"
67
             "   nr    %2,%0\n"        /* make shift value */
68
             "   xr    %0,%2\n"
69
             "   srl   %0,3\n"
70
             "   lhi   %3,1\n"
71
             "   la    %1,0(%0,%1)\n"  /* calc. address for CS */
72
             "   sll   %3,0(%2)\n"       /* make OR mask */
73
             "   l     %0,0(%1)\n"
74
             "0: lr    %2,%0\n"         /* CS loop starts here */
75
             "   or    %2,%3\n"          /* set bit */
76
             "   cs    %0,%2,0(%1)\n"
77
             "   jl    0b"
78
             : "+a" (nr), "+a" (addr), "=&a" (bits), "=&d" (mask) :
79
             : "cc", "memory" );
80
}
81
 
82
/*
83
 * SMP save clear_bit routine based on compare and swap (CS)
84
 */
85
static __inline__ void clear_bit_cs(int nr, volatile void * addr)
86
{
87
        static const int minusone = -1;
88
        unsigned long bits, mask;
89
        __asm__ __volatile__(
90
#if ALIGN_CS == 1
91
             "   lhi   %2,3\n"         /* CS must be aligned on 4 byte b. */
92
             "   nr    %2,%1\n"        /* isolate last 2 bits of address */
93
             "   xr    %1,%2\n"        /* make addr % 4 == 0 */
94
             "   sll   %2,3\n"
95
             "   ar    %0,%2\n"        /* add alignement to bitnr */
96
#endif
97
             "   lhi   %2,31\n"
98
             "   nr    %2,%0\n"        /* make shift value */
99
             "   xr    %0,%2\n"
100
             "   srl   %0,3\n"
101
             "   lhi   %3,1\n"
102
             "   la    %1,0(%0,%1)\n"  /* calc. address for CS */
103
             "   sll   %3,0(%2)\n"
104
             "   x     %3,%4\n"        /* make AND mask */
105
             "   l     %0,0(%1)\n"
106
             "0: lr    %2,%0\n"        /* CS loop starts here */
107
             "   nr    %2,%3\n"        /* clear bit */
108
             "   cs    %0,%2,0(%1)\n"
109
             "   jl    0b"
110
             : "+a" (nr), "+a" (addr), "=&a" (bits), "=&d" (mask)
111
             : "m" (minusone) : "cc", "memory" );
112
}
113
 
114
/*
115
 * SMP save change_bit routine based on compare and swap (CS)
116
 */
117
static __inline__ void change_bit_cs(int nr, volatile void * addr)
118
{
119
        unsigned long bits, mask;
120
        __asm__ __volatile__(
121
#if ALIGN_CS == 1
122
             "   lhi   %2,3\n"         /* CS must be aligned on 4 byte b. */
123
             "   nr    %2,%1\n"        /* isolate last 2 bits of address */
124
             "   xr    %1,%2\n"        /* make addr % 4 == 0 */
125
             "   sll   %2,3\n"
126
             "   ar    %0,%2\n"        /* add alignement to bitnr */
127
#endif
128
             "   lhi   %2,31\n"
129
             "   nr    %2,%0\n"        /* make shift value */
130
             "   xr    %0,%2\n"
131
             "   srl   %0,3\n"
132
             "   lhi   %3,1\n"
133
             "   la    %1,0(%0,%1)\n"  /* calc. address for CS */
134
             "   sll   %3,0(%2)\n"     /* make XR mask */
135
             "   l     %0,0(%1)\n"
136
             "0: lr    %2,%0\n"        /* CS loop starts here */
137
             "   xr    %2,%3\n"        /* change bit */
138
             "   cs    %0,%2,0(%1)\n"
139
             "   jl    0b"
140
             : "+a" (nr), "+a" (addr), "=&a" (bits), "=&d" (mask) :
141
             : "cc", "memory" );
142
}
143
 
144
/*
145
 * SMP save test_and_set_bit routine based on compare and swap (CS)
146
 */
147
static __inline__ int test_and_set_bit_cs(int nr, volatile void * addr)
148
{
149
        unsigned long bits, mask;
150
        __asm__ __volatile__(
151
#if ALIGN_CS == 1
152
             "   lhi   %2,3\n"         /* CS must be aligned on 4 byte b. */
153
             "   nr    %2,%1\n"        /* isolate last 2 bits of address */
154
             "   xr    %1,%2\n"        /* make addr % 4 == 0 */
155
             "   sll   %2,3\n"
156
             "   ar    %0,%2\n"        /* add alignement to bitnr */
157
#endif
158
             "   lhi   %2,31\n"
159
             "   nr    %2,%0\n"        /* make shift value */
160
             "   xr    %0,%2\n"
161
             "   srl   %0,3\n"
162
             "   lhi   %3,1\n"
163
             "   la    %1,0(%0,%1)\n"  /* calc. address for CS */
164
             "   sll   %3,0(%2)\n"     /* make OR mask */
165
             "   l     %0,0(%1)\n"
166
             "0: lr    %2,%0\n"        /* CS loop starts here */
167
             "   or    %2,%3\n"        /* set bit */
168
             "   cs    %0,%2,0(%1)\n"
169
             "   jl    0b\n"
170
             "   nr    %0,%3\n"        /* isolate old bit */
171
             : "+a" (nr), "+a" (addr), "=&a" (bits), "=&d" (mask) :
172
             : "cc", "memory" );
173
        return nr != 0;
174
}
175
 
176
/*
177
 * SMP save test_and_clear_bit routine based on compare and swap (CS)
178
 */
179
static __inline__ int test_and_clear_bit_cs(int nr, volatile void * addr)
180
{
181
        static const int minusone = -1;
182
        unsigned long bits, mask;
183
        __asm__ __volatile__(
184
#if ALIGN_CS == 1
185
             "   lhi   %2,3\n"         /* CS must be aligned on 4 byte b. */
186
             "   nr    %2,%1\n"        /* isolate last 2 bits of address */
187
             "   xr    %1,%2\n"        /* make addr % 4 == 0 */
188
             "   sll   %2,3\n"
189
             "   ar    %0,%2\n"        /* add alignement to bitnr */
190
#endif
191
             "   lhi   %2,31\n"
192
             "   nr    %2,%0\n"        /* make shift value */
193
             "   xr    %0,%2\n"
194
             "   srl   %0,3\n"
195
             "   lhi   %3,1\n"
196
             "   la    %1,0(%0,%1)\n"  /* calc. address for CS */
197
             "   sll   %3,0(%2)\n"
198
             "   l     %0,0(%1)\n"
199
             "   x     %3,%4\n"        /* make AND mask */
200
             "0: lr    %2,%0\n"        /* CS loop starts here */
201
             "   nr    %2,%3\n"        /* clear bit */
202
             "   cs    %0,%2,0(%1)\n"
203
             "   jl    0b\n"
204
             "   x     %3,%4\n"
205
             "   nr    %0,%3\n"         /* isolate old bit */
206
             : "+a" (nr), "+a" (addr), "=&a" (bits), "=&d" (mask)
207
             : "m" (minusone) : "cc", "memory" );
208
        return nr;
209
}
210
 
211
/*
212
 * SMP save test_and_change_bit routine based on compare and swap (CS)
213
 */
214
static __inline__ int test_and_change_bit_cs(int nr, volatile void * addr)
215
{
216
        unsigned long bits, mask;
217
        __asm__ __volatile__(
218
#if ALIGN_CS == 1
219
             "   lhi   %2,3\n"         /* CS must be aligned on 4 byte b. */
220
             "   nr    %2,%1\n"        /* isolate last 2 bits of address */
221
             "   xr    %1,%2\n"        /* make addr % 4 == 0 */
222
             "   sll   %2,3\n"
223
             "   ar    %0,%2\n"        /* add alignement to bitnr */
224
#endif
225
             "   lhi   %2,31\n"
226
             "   nr    %2,%0\n"        /* make shift value */
227
             "   xr    %0,%2\n"
228
             "   srl   %0,3\n"
229
             "   lhi   %3,1\n"
230
             "   la    %1,0(%0,%1)\n"  /* calc. address for CS */
231
             "   sll   %3,0(%2)\n"     /* make OR mask */
232
             "   l     %0,0(%1)\n"
233
             "0: lr    %2,%0\n"        /* CS loop starts here */
234
             "   xr    %2,%3\n"        /* change bit */
235
             "   cs    %0,%2,0(%1)\n"
236
             "   jl    0b\n"
237
             "   nr    %0,%3\n"        /* isolate old bit */
238
             : "+a" (nr), "+a" (addr), "=&a" (bits), "=&d" (mask) :
239
             : "cc", "memory" );
240
        return nr != 0;
241
}
242
#endif /* CONFIG_SMP */
243
 
244
/*
245
 * fast, non-SMP set_bit routine
246
 */
247
static __inline__ void __set_bit(int nr, volatile void * addr)
248
{
249
        unsigned long reg1, reg2;
250
        __asm__ __volatile__(
251
             "   lhi   %1,24\n"
252
             "   lhi   %0,7\n"
253
             "   xr    %1,%2\n"
254
             "   nr    %0,%2\n"
255
             "   srl   %1,3\n"
256
             "   la    %1,0(%1,%3)\n"
257
             "   la    %0,0(%0,%4)\n"
258
             "   oc    0(1,%1),0(%0)"
259
             : "=&a" (reg1), "=&a" (reg2)
260
             : "r" (nr), "a" (addr), "a" (&_oi_bitmap) : "cc", "memory" );
261
}
262
 
263
static __inline__ void
264
__constant_set_bit(const int nr, volatile void * addr)
265
{
266
  switch (nr&7) {
267
  case 0:
268
    __asm__ __volatile__ ("la 1,%0\n\t"
269
                          "oi 0(1),0x01"
270
                          : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
271
                          : : "1", "cc", "memory");
272
    break;
273
  case 1:
274
    __asm__ __volatile__ ("la 1,%0\n\t"
275
                          "oi 0(1),0x02"
276
                          : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
277
                          : : "1", "cc", "memory" );
278
    break;
279
  case 2:
280
    __asm__ __volatile__ ("la 1,%0\n\t"
281
                          "oi 0(1),0x04"
282
                          : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
283
                          : : "1", "cc", "memory" );
284
    break;
285
  case 3:
286
    __asm__ __volatile__ ("la 1,%0\n\t"
287
                          "oi 0(1),0x08"
288
                          : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
289
                          : : "1", "cc", "memory" );
290
    break;
291
  case 4:
292
    __asm__ __volatile__ ("la 1,%0\n\t"
293
                          "oi 0(1),0x10"
294
                          : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
295
                          : : "1", "cc", "memory" );
296
    break;
297
  case 5:
298
    __asm__ __volatile__ ("la 1,%0\n\t"
299
                          "oi 0(1),0x20"
300
                          : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
301
                          : : "1", "cc", "memory" );
302
    break;
303
  case 6:
304
    __asm__ __volatile__ ("la 1,%0\n\t"
305
                          "oi 0(1),0x40"
306
                          : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
307
                          : : "1", "cc", "memory" );
308
    break;
309
  case 7:
310
    __asm__ __volatile__ ("la 1,%0\n\t"
311
                          "oi 0(1),0x80"
312
                          : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
313
                          : : "1", "cc", "memory" );
314
    break;
315
  }
316
}
317
 
318
#define set_bit_simple(nr,addr) \
319
(__builtin_constant_p((nr)) ? \
320
 __constant_set_bit((nr),(addr)) : \
321
 __set_bit((nr),(addr)) )
322
 
323
/*
324
 * fast, non-SMP clear_bit routine
325
 */
326
static __inline__ void
327
__clear_bit(int nr, volatile void * addr)
328
{
329
        unsigned long reg1, reg2;
330
        __asm__ __volatile__(
331
             "   lhi   %1,24\n"
332
             "   lhi   %0,7\n"
333
             "   xr    %1,%2\n"
334
             "   nr    %0,%2\n"
335
             "   srl   %1,3\n"
336
             "   la    %1,0(%1,%3)\n"
337
             "   la    %0,0(%0,%4)\n"
338
             "   nc    0(1,%1),0(%0)"
339
             : "=&a" (reg1), "=&a" (reg2)
340
             : "r" (nr), "a" (addr), "a" (&_ni_bitmap) : "cc", "memory" );
341
}
342
 
343
static __inline__ void
344
__constant_clear_bit(const int nr, volatile void * addr)
345
{
346
  switch (nr&7) {
347
  case 0:
348
    __asm__ __volatile__ ("la 1,%0\n\t"
349
                          "ni 0(1),0xFE"
350
                          : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
351
                          : : "1", "cc", "memory" );
352
    break;
353
  case 1:
354
    __asm__ __volatile__ ("la 1,%0\n\t"
355
                          "ni 0(1),0xFD"
356
                          : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
357
                          : : "1", "cc", "memory" );
358
    break;
359
  case 2:
360
    __asm__ __volatile__ ("la 1,%0\n\t"
361
                          "ni 0(1),0xFB"
362
                          : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
363
                          : : "1", "cc", "memory" );
364
    break;
365
  case 3:
366
    __asm__ __volatile__ ("la 1,%0\n\t"
367
                          "ni 0(1),0xF7"
368
                          : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
369
                          : : "1", "cc", "memory" );
370
    break;
371
  case 4:
372
    __asm__ __volatile__ ("la 1,%0\n\t"
373
                          "ni 0(1),0xEF"
374
                          : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
375
                          : : "cc", "memory" );
376
    break;
377
  case 5:
378
    __asm__ __volatile__ ("la 1,%0\n\t"
379
                          "ni 0(1),0xDF"
380
                          : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
381
                          : : "1", "cc", "memory" );
382
    break;
383
  case 6:
384
    __asm__ __volatile__ ("la 1,%0\n\t"
385
                          "ni 0(1),0xBF"
386
                          : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
387
                          : : "1", "cc", "memory" );
388
    break;
389
  case 7:
390
    __asm__ __volatile__ ("la 1,%0\n\t"
391
                          "ni 0(1),0x7F"
392
                          : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
393
                          : : "1", "cc", "memory" );
394
    break;
395
  }
396
}
397
 
398
#define clear_bit_simple(nr,addr) \
399
(__builtin_constant_p((nr)) ? \
400
 __constant_clear_bit((nr),(addr)) : \
401
 __clear_bit((nr),(addr)) )
402
 
403
/*
404
 * fast, non-SMP change_bit routine
405
 */
406
static __inline__ void __change_bit(int nr, volatile void * addr)
407
{
408
        unsigned long reg1, reg2;
409
        __asm__ __volatile__(
410
             "   lhi   %1,24\n"
411
             "   lhi   %0,7\n"
412
             "   xr    %1,%2\n"
413
             "   nr    %0,%2\n"
414
             "   srl   %1,3\n"
415
             "   la    %1,0(%1,%3)\n"
416
             "   la    %0,0(%0,%4)\n"
417
             "   xc    0(1,%1),0(%0)"
418
             : "=&a" (reg1), "=&a" (reg2)
419
             : "r" (nr), "a" (addr), "a" (&_oi_bitmap) : "cc", "memory" );
420
}
421
 
422
static __inline__ void
423
__constant_change_bit(const int nr, volatile void * addr)
424
{
425
  switch (nr&7) {
426
  case 0:
427
    __asm__ __volatile__ ("la 1,%0\n\t"
428
                          "xi 0(1),0x01"
429
                          : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
430
                          : : "cc", "memory" );
431
    break;
432
  case 1:
433
    __asm__ __volatile__ ("la 1,%0\n\t"
434
                          "xi 0(1),0x02"
435
                          : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
436
                          : : "cc", "memory" );
437
    break;
438
  case 2:
439
    __asm__ __volatile__ ("la 1,%0\n\t"
440
                          "xi 0(1),0x04"
441
                          : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
442
                          : : "cc", "memory" );
443
    break;
444
  case 3:
445
    __asm__ __volatile__ ("la 1,%0\n\t"
446
                          "xi 0(1),0x08"
447
                          : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
448
                          : : "cc", "memory" );
449
    break;
450
  case 4:
451
    __asm__ __volatile__ ("la 1,%0\n\t"
452
                          "xi 0(1),0x10"
453
                          : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
454
                          : : "cc", "memory" );
455
    break;
456
  case 5:
457
    __asm__ __volatile__ ("la 1,%0\n\t"
458
                          "xi 0(1),0x20"
459
                          : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
460
                          : : "1", "cc", "memory" );
461
    break;
462
  case 6:
463
    __asm__ __volatile__ ("la 1,%0\n\t"
464
                          "xi 0(1),0x40"
465
                          : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
466
                          : : "1", "cc", "memory" );
467
    break;
468
  case 7:
469
    __asm__ __volatile__ ("la 1,%0\n\t"
470
                          "xi 0(1),0x80"
471
                          : "=m" (*((volatile char *) addr + ((nr>>3)^3)))
472
                          : : "1", "cc", "memory" );
473
    break;
474
  }
475
}
476
 
477
#define change_bit_simple(nr,addr) \
478
(__builtin_constant_p((nr)) ? \
479
 __constant_change_bit((nr),(addr)) : \
480
 __change_bit((nr),(addr)) )
481
 
482
/*
483
 * fast, non-SMP test_and_set_bit routine
484
 */
485
static __inline__ int test_and_set_bit_simple(int nr, volatile void * addr)
486
{
487
        unsigned long reg1, reg2;
488
        int oldbit;
489
        __asm__ __volatile__(
490
             "   lhi   %1,24\n"
491
             "   lhi   %2,7\n"
492
             "   xr    %1,%3\n"
493
             "   nr    %2,%3\n"
494
             "   srl   %1,3\n"
495
             "   la    %1,0(%1,%4)\n"
496
             "   ic    %0,0(%1)\n"
497
             "   srl   %0,0(%2)\n"
498
             "   la    %2,0(%2,%5)\n"
499
             "   oc    0(1,%1),0(%2)"
500
             : "=d&" (oldbit), "=&a" (reg1), "=&a" (reg2)
501
             : "r" (nr), "a" (addr), "a" (&_oi_bitmap) : "cc", "memory" );
502
        return oldbit & 1;
503
}
504
#define __test_and_set_bit(X,Y)         test_and_set_bit_simple(X,Y)
505
 
506
/*
507
 * fast, non-SMP test_and_clear_bit routine
508
 */
509
static __inline__ int test_and_clear_bit_simple(int nr, volatile void * addr)
510
{
511
        unsigned long reg1, reg2;
512
        int oldbit;
513
 
514
        __asm__ __volatile__(
515
             "   lhi   %1,24\n"
516
             "   lhi   %2,7\n"
517
             "   xr    %1,%3\n"
518
             "   nr    %2,%3\n"
519
             "   srl   %1,3\n"
520
             "   la    %1,0(%1,%4)\n"
521
             "   ic    %0,0(%1)\n"
522
             "   srl   %0,0(%2)\n"
523
             "   la    %2,0(%2,%5)\n"
524
             "   nc    0(1,%1),0(%2)"
525
             : "=d&" (oldbit), "=&a" (reg1), "=&a" (reg2)
526
             : "r" (nr), "a" (addr), "a" (&_ni_bitmap) : "cc", "memory" );
527
        return oldbit & 1;
528
}
529
#define __test_and_clear_bit(X,Y)       test_and_clear_bit_simple(X,Y)
530
 
531
/*
532
 * fast, non-SMP test_and_change_bit routine
533
 */
534
static __inline__ int test_and_change_bit_simple(int nr, volatile void * addr)
535
{
536
        unsigned long reg1, reg2;
537
        int oldbit;
538
 
539
        __asm__ __volatile__(
540
             "   lhi   %1,24\n"
541
             "   lhi   %2,7\n"
542
             "   xr    %1,%3\n"
543
             "   nr    %2,%1\n"
544
             "   srl   %1,3\n"
545
             "   la    %1,0(%1,%4)\n"
546
             "   ic    %0,0(%1)\n"
547
             "   srl   %0,0(%2)\n"
548
             "   la    %2,0(%2,%5)\n"
549
             "   xc    0(1,%1),0(%2)"
550
             : "=d&" (oldbit), "=&a" (reg1), "=&a" (reg2)
551
             : "r" (nr), "a" (addr), "a" (&_oi_bitmap) : "cc", "memory" );
552
        return oldbit & 1;
553
}
554
#define __test_and_change_bit(X,Y)      test_and_change_bit_simple(X,Y)
555
 
556
#ifdef CONFIG_SMP
557
#define set_bit             set_bit_cs
558
#define clear_bit           clear_bit_cs
559
#define change_bit          change_bit_cs
560
#define test_and_set_bit    test_and_set_bit_cs
561
#define test_and_clear_bit  test_and_clear_bit_cs
562
#define test_and_change_bit test_and_change_bit_cs
563
#else
564
#define set_bit             set_bit_simple
565
#define clear_bit           clear_bit_simple
566
#define change_bit          change_bit_simple
567
#define test_and_set_bit    test_and_set_bit_simple
568
#define test_and_clear_bit  test_and_clear_bit_simple
569
#define test_and_change_bit test_and_change_bit_simple
570
#endif
571
 
572
 
573
/*
574
 * This routine doesn't need to be atomic.
575
 */
576
 
577
static __inline__ int __test_bit(int nr, volatile void * addr)
578
{
579
        unsigned long reg1, reg2;
580
        int oldbit;
581
 
582
        __asm__ __volatile__(
583
             "   lhi   %2,24\n"
584
             "   lhi   %1,7\n"
585
             "   xr    %2,%3\n"
586
             "   nr    %1,%3\n"
587
             "   srl   %2,3\n"
588
             "   ic    %0,0(%2,%4)\n"
589
             "   srl   %0,0(%1)"
590
             : "=d&" (oldbit), "=&a" (reg1), "=&a" (reg2)
591
             : "r" (nr), "a" (addr) : "cc" );
592
        return oldbit & 1;
593
}
594
 
595
static __inline__ int __constant_test_bit(int nr, volatile void * addr) {
596
    return (((volatile char *) addr)[(nr>>3)^3] & (1<<(nr&7))) != 0;
597
}
598
 
599
#define test_bit(nr,addr) \
600
(__builtin_constant_p((nr)) ? \
601
 __constant_test_bit((nr),(addr)) : \
602
 __test_bit((nr),(addr)) )
603
 
604
/*
605
 * Find-bit routines..
606
 */
607
static __inline__ int find_first_zero_bit(void * addr, unsigned size)
608
{
609
        unsigned long cmp, count;
610
        int res;
611
 
612
        if (!size)
613
                return 0;
614
        __asm__("   lhi  %1,-1\n"
615
                "   lr   %2,%3\n"
616
                "   slr  %0,%0\n"
617
                "   ahi  %2,31\n"
618
                "   srl  %2,5\n"
619
                "0: c    %1,0(%0,%4)\n"
620
                "   jne  1f\n"
621
                "   ahi  %0,4\n"
622
                "   brct %2,0b\n"
623
                "   lr   %0,%3\n"
624
                "   j    4f\n"
625
                "1: l    %2,0(%0,%4)\n"
626
                "   sll  %0,3\n"
627
                "   lhi  %1,0xff\n"
628
                "   tml  %2,0xffff\n"
629
                "   jno  2f\n"
630
                "   ahi  %0,16\n"
631
                "   srl  %2,16\n"
632
                "2: tml  %2,0x00ff\n"
633
                "   jno  3f\n"
634
                "   ahi  %0,8\n"
635
                "   srl  %2,8\n"
636
                "3: nr   %2,%1\n"
637
                "   ic   %2,0(%2,%5)\n"
638
                "   alr  %0,%2\n"
639
                "4:"
640
                : "=&a" (res), "=&d" (cmp), "=&a" (count)
641
                : "a" (size), "a" (addr), "a" (&_zb_findmap) : "cc" );
642
        return (res < size) ? res : size;
643
}
644
 
645
static __inline__ int find_next_zero_bit (void * addr, int size, int offset)
646
{
647
        unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
648
        unsigned long bitvec, reg;
649
        int set, bit = offset & 31, res;
650
 
651
        if (bit) {
652
                /*
653
                 * Look for zero in first word
654
                 */
655
                bitvec = (*p) >> bit;
656
                __asm__("   slr  %0,%0\n"
657
                        "   lhi  %2,0xff\n"
658
                        "   tml  %1,0xffff\n"
659
                        "   jno  0f\n"
660
                        "   ahi  %0,16\n"
661
                        "   srl  %1,16\n"
662
                        "0: tml  %1,0x00ff\n"
663
                        "   jno  1f\n"
664
                        "   ahi  %0,8\n"
665
                        "   srl  %1,8\n"
666
                        "1: nr   %1,%2\n"
667
                        "   ic   %1,0(%1,%3)\n"
668
                        "   alr  %0,%1"
669
                        : "=&d" (set), "+a" (bitvec), "=&d" (reg)
670
                        : "a" (&_zb_findmap) : "cc" );
671
                if (set < (32 - bit))
672
                        return set + offset;
673
                offset += 32 - bit;
674
                p++;
675
        }
676
        /*
677
         * No zero yet, search remaining full words for a zero
678
         */
679
        res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr));
680
        return (offset + res);
681
}
682
 
683
/*
684
 * ffz = Find First Zero in word. Undefined if no zero exists,
685
 * so code should check against ~0UL first..
686
 */
687
static __inline__ unsigned long ffz(unsigned long word)
688
{
689
        unsigned long reg;
690
        int result;
691
 
692
        __asm__("   slr  %0,%0\n"
693
                "   lhi  %2,0xff\n"
694
                "   tml  %1,0xffff\n"
695
                "   jno  0f\n"
696
                "   ahi  %0,16\n"
697
                "   srl  %1,16\n"
698
                "0: tml  %1,0x00ff\n"
699
                "   jno  1f\n"
700
                "   ahi  %0,8\n"
701
                "   srl  %1,8\n"
702
                "1: nr   %1,%2\n"
703
                "   ic   %1,0(%1,%3)\n"
704
                "   alr  %0,%1"
705
                : "=&d" (result), "+a" (word), "=&d" (reg)
706
                : "a" (&_zb_findmap) : "cc" );
707
        return result;
708
}
709
 
710
/*
711
 * ffs: find first bit set. This is defined the same way as
712
 * the libc and compiler builtin ffs routines, therefore
713
 * differs in spirit from the above ffz (man ffs).
714
 */
715
 
716
extern int __inline__ ffs (int x)
717
{
718
        int r;
719
 
720
        if (x == 0)
721
          return 0;
722
        __asm__("    slr  %0,%0\n"
723
                "    tml  %1,0xffff\n"
724
                "    jnz  0f\n"
725
                "    ahi  %0,16\n"
726
                "    srl  %1,16\n"
727
                "0:  tml  %1,0x00ff\n"
728
                "    jnz  1f\n"
729
                "    ahi  %0,8\n"
730
                "    srl  %1,8\n"
731
                "1:  tml  %1,0x000f\n"
732
                "    jnz  2f\n"
733
                "    ahi  %0,4\n"
734
                "    srl  %1,4\n"
735
                "2:  tml  %1,0x0003\n"
736
                "    jnz  3f\n"
737
                "    ahi  %0,2\n"
738
                "    srl  %1,2\n"
739
                "3:  tml  %1,0x0001\n"
740
                "    jnz  4f\n"
741
                "    ahi  %0,1\n"
742
                "4:"
743
                : "=&d" (r), "+d" (x) : : "cc" );
744
        return r+1;
745
}
746
 
747
/*
748
 * hweightN: returns the hamming weight (i.e. the number
749
 * of bits set) of a N-bit word
750
 */
751
 
752
#define hweight32(x) generic_hweight32(x)
753
#define hweight16(x) generic_hweight16(x)
754
#define hweight8(x) generic_hweight8(x)
755
 
756
 
757
#ifdef __KERNEL__
758
 
759
/*
760
 * ATTENTION: intel byte ordering convention for ext2 and minix !!
761
 * bit 0 is the LSB of addr; bit 31 is the MSB of addr;
762
 * bit 32 is the LSB of (addr+4).
763
 * That combined with the little endian byte order of Intel gives the
764
 * following bit order in memory:
765
 *    07 06 05 04 03 02 01 00 15 14 13 12 11 10 09 08 \
766
 *    23 22 21 20 19 18 17 16 31 30 29 28 27 26 25 24
767
 */
768
 
769
#define ext2_set_bit(nr, addr)       test_and_set_bit((nr)^24, addr)
770
#define ext2_clear_bit(nr, addr)     test_and_clear_bit((nr)^24, addr)
771
#define ext2_test_bit(nr, addr)      test_bit((nr)^24, addr)
772
static __inline__ int ext2_find_first_zero_bit(void *vaddr, unsigned size)
773
{
774
        unsigned long cmp, count;
775
        int res;
776
 
777
        if (!size)
778
                return 0;
779
        __asm__("   lhi  %1,-1\n"
780
                "   lr   %2,%3\n"
781
                "   ahi  %2,31\n"
782
                "   srl  %2,5\n"
783
                "   slr  %0,%0\n"
784
                "0: cl   %1,0(%0,%4)\n"
785
                "   jne  1f\n"
786
                "   ahi  %0,4\n"
787
                "   brct %2,0b\n"
788
                "   lr   %0,%3\n"
789
                "   j    4f\n"
790
                "1: l    %2,0(%0,%4)\n"
791
                "   sll  %0,3\n"
792
                "   ahi  %0,24\n"
793
                "   lhi  %1,0xff\n"
794
                "   tmh  %2,0xffff\n"
795
                "   jo   2f\n"
796
                "   ahi  %0,-16\n"
797
                "   srl  %2,16\n"
798
                "2: tml  %2,0xff00\n"
799
                "   jo   3f\n"
800
                "   ahi  %0,-8\n"
801
                "   srl  %2,8\n"
802
                "3: nr   %2,%1\n"
803
                "   ic   %2,0(%2,%5)\n"
804
                "   alr  %0,%2\n"
805
                "4:"
806
                : "=&a" (res), "=&d" (cmp), "=&a" (count)
807
                : "a" (size), "a" (vaddr), "a" (&_zb_findmap) : "cc" );
808
        return (res < size) ? res : size;
809
}
810
 
811
static __inline__ int
812
ext2_find_next_zero_bit(void *vaddr, unsigned size, unsigned offset)
813
{
814
        unsigned long *addr = vaddr;
815
        unsigned long *p = addr + (offset >> 5);
816
        unsigned long word, reg;
817
        int bit = offset & 31UL, res;
818
 
819
        if (offset >= size)
820
                return size;
821
 
822
        if (bit) {
823
                __asm__("   ic   %0,0(%1)\n"
824
                        "   icm  %0,2,1(%1)\n"
825
                        "   icm  %0,4,2(%1)\n"
826
                        "   icm  %0,8,3(%1)"
827
                        : "=&a" (word) : "a" (p) : "cc" );
828
                word >>= bit;
829
                res = bit;
830
                /* Look for zero in first longword */
831
                __asm__("   lhi  %2,0xff\n"
832
                        "   tml  %1,0xffff\n"
833
                        "   jno  0f\n"
834
                        "   ahi  %0,16\n"
835
                        "   srl  %1,16\n"
836
                        "0: tml  %1,0x00ff\n"
837
                        "   jno  1f\n"
838
                        "   ahi  %0,8\n"
839
                        "   srl  %1,8\n"
840
                        "1: nr   %1,%2\n"
841
                        "   ic   %1,0(%1,%3)\n"
842
                        "   alr  %0,%1"
843
                        : "+&d" (res), "+&a" (word), "=&d" (reg)
844
                        : "a" (&_zb_findmap) : "cc" );
845
                if (res < 32)
846
                        return (p - addr)*32 + res;
847
                p++;
848
        }
849
        /* No zero yet, search remaining full bytes for a zero */
850
        res = ext2_find_first_zero_bit (p, size - 32 * (p - addr));
851
        return (p - addr) * 32 + res;
852
}
853
 
854
/* Bitmap functions for the minix filesystem.  */
855
/* FIXME !!! */
856
#define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr)
857
#define minix_set_bit(nr,addr) set_bit(nr,addr)
858
#define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
859
#define minix_test_bit(nr,addr) test_bit(nr,addr)
860
#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
861
 
862
#endif /* __KERNEL__ */
863
 
864
#endif /* _S390_BITOPS_H */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.