~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/m68k/math-emu/fp_arith.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-or-later
  2 /*
  3 
  4    fp_arith.c: floating-point math routines for the Linux-m68k
  5    floating point emulator.
  6 
  7    Copyright (c) 1998-1999 David Huggins-Daines.
  8 
  9    Somewhat based on the AlphaLinux floating point emulator, by David
 10    Mosberger-Tang.
 11 
 12  */
 13 
 14 #include "fp_emu.h"
 15 #include "multi_arith.h"
 16 #include "fp_arith.h"
 17 
 18 const struct fp_ext fp_QNaN =
 19 {
 20         .exp = 0x7fff,
 21         .mant = { .m64 = ~0 }
 22 };
 23 
 24 const struct fp_ext fp_Inf =
 25 {
 26         .exp = 0x7fff,
 27 };
 28 
 29 /* let's start with the easy ones */
 30 
 31 struct fp_ext *fp_fabs(struct fp_ext *dest, struct fp_ext *src)
 32 {
 33         dprint(PINSTR, "fabs\n");
 34 
 35         fp_monadic_check(dest, src);
 36 
 37         dest->sign = 0;
 38 
 39         return dest;
 40 }
 41 
 42 struct fp_ext *fp_fneg(struct fp_ext *dest, struct fp_ext *src)
 43 {
 44         dprint(PINSTR, "fneg\n");
 45 
 46         fp_monadic_check(dest, src);
 47 
 48         dest->sign = !dest->sign;
 49 
 50         return dest;
 51 }
 52 
 53 /* Now, the slightly harder ones */
 54 
 55 /* fp_fadd: Implements the kernel of the FADD, FSADD, FDADD, FSUB,
 56    FDSUB, and FCMP instructions. */
 57 
 58 struct fp_ext *fp_fadd(struct fp_ext *dest, struct fp_ext *src)
 59 {
 60         int diff;
 61 
 62         dprint(PINSTR, "fadd\n");
 63 
 64         fp_dyadic_check(dest, src);
 65 
 66         if (IS_INF(dest)) {
 67                 /* infinity - infinity == NaN */
 68                 if (IS_INF(src) && (src->sign != dest->sign))
 69                         fp_set_nan(dest);
 70                 return dest;
 71         }
 72         if (IS_INF(src)) {
 73                 fp_copy_ext(dest, src);
 74                 return dest;
 75         }
 76 
 77         if (IS_ZERO(dest)) {
 78                 if (IS_ZERO(src)) {
 79                         if (src->sign != dest->sign) {
 80                                 if (FPDATA->rnd == FPCR_ROUND_RM)
 81                                         dest->sign = 1;
 82                                 else
 83                                         dest->sign = 0;
 84                         }
 85                 } else
 86                         fp_copy_ext(dest, src);
 87                 return dest;
 88         }
 89 
 90         dest->lowmant = src->lowmant = 0;
 91 
 92         if ((diff = dest->exp - src->exp) > 0)
 93                 fp_denormalize(src, diff);
 94         else if ((diff = -diff) > 0)
 95                 fp_denormalize(dest, diff);
 96 
 97         if (dest->sign == src->sign) {
 98                 if (fp_addmant(dest, src))
 99                         if (!fp_addcarry(dest))
100                                 return dest;
101         } else {
102                 if (dest->mant.m64 < src->mant.m64) {
103                         fp_submant(dest, src, dest);
104                         dest->sign = !dest->sign;
105                 } else
106                         fp_submant(dest, dest, src);
107         }
108 
109         return dest;
110 }
111 
112 /* fp_fsub: Implements the kernel of the FSUB, FSSUB, and FDSUB
113    instructions.
114 
115    Remember that the arguments are in assembler-syntax order! */
116 
117 struct fp_ext *fp_fsub(struct fp_ext *dest, struct fp_ext *src)
118 {
119         dprint(PINSTR, "fsub ");
120 
121         src->sign = !src->sign;
122         return fp_fadd(dest, src);
123 }
124 
125 
126 struct fp_ext *fp_fcmp(struct fp_ext *dest, struct fp_ext *src)
127 {
128         dprint(PINSTR, "fcmp ");
129 
130         FPDATA->temp[1] = *dest;
131         src->sign = !src->sign;
132         return fp_fadd(&FPDATA->temp[1], src);
133 }
134 
135 struct fp_ext *fp_ftst(struct fp_ext *dest, struct fp_ext *src)
136 {
137         dprint(PINSTR, "ftst\n");
138 
139         (void)dest;
140 
141         return src;
142 }
143 
144 struct fp_ext *fp_fmul(struct fp_ext *dest, struct fp_ext *src)
145 {
146         union fp_mant128 temp;
147         int exp;
148 
149         dprint(PINSTR, "fmul\n");
150 
151         fp_dyadic_check(dest, src);
152 
153         /* calculate the correct sign now, as it's necessary for infinities */
154         dest->sign = src->sign ^ dest->sign;
155 
156         /* Handle infinities */
157         if (IS_INF(dest)) {
158                 if (IS_ZERO(src))
159                         fp_set_nan(dest);
160                 return dest;
161         }
162         if (IS_INF(src)) {
163                 if (IS_ZERO(dest))
164                         fp_set_nan(dest);
165                 else
166                         fp_copy_ext(dest, src);
167                 return dest;
168         }
169 
170         /* Of course, as we all know, zero * anything = zero.  You may
171            not have known that it might be a positive or negative
172            zero... */
173         if (IS_ZERO(dest) || IS_ZERO(src)) {
174                 dest->exp = 0;
175                 dest->mant.m64 = 0;
176                 dest->lowmant = 0;
177 
178                 return dest;
179         }
180 
181         exp = dest->exp + src->exp - 0x3ffe;
182 
183         /* shift up the mantissa for denormalized numbers,
184            so that the highest bit is set, this makes the
185            shift of the result below easier */
186         if ((long)dest->mant.m32[0] >= 0)
187                 exp -= fp_overnormalize(dest);
188         if ((long)src->mant.m32[0] >= 0)
189                 exp -= fp_overnormalize(src);
190 
191         /* now, do a 64-bit multiply with expansion */
192         fp_multiplymant(&temp, dest, src);
193 
194         /* normalize it back to 64 bits and stuff it back into the
195            destination struct */
196         if ((long)temp.m32[0] > 0) {
197                 exp--;
198                 fp_putmant128(dest, &temp, 1);
199         } else
200                 fp_putmant128(dest, &temp, 0);
201 
202         if (exp >= 0x7fff) {
203                 fp_set_ovrflw(dest);
204                 return dest;
205         }
206         dest->exp = exp;
207         if (exp < 0) {
208                 fp_set_sr(FPSR_EXC_UNFL);
209                 fp_denormalize(dest, -exp);
210         }
211 
212         return dest;
213 }
214 
215 /* fp_fdiv: Implements the "kernel" of the FDIV, FSDIV, FDDIV and
216    FSGLDIV instructions.
217 
218    Note that the order of the operands is counter-intuitive: instead
219    of src / dest, the result is actually dest / src. */
220 
221 struct fp_ext *fp_fdiv(struct fp_ext *dest, struct fp_ext *src)
222 {
223         union fp_mant128 temp;
224         int exp;
225 
226         dprint(PINSTR, "fdiv\n");
227 
228         fp_dyadic_check(dest, src);
229 
230         /* calculate the correct sign now, as it's necessary for infinities */
231         dest->sign = src->sign ^ dest->sign;
232 
233         /* Handle infinities */
234         if (IS_INF(dest)) {
235                 /* infinity / infinity = NaN (quiet, as always) */
236                 if (IS_INF(src))
237                         fp_set_nan(dest);
238                 /* infinity / anything else = infinity (with appropriate sign) */
239                 return dest;
240         }
241         if (IS_INF(src)) {
242                 /* anything / infinity = zero (with appropriate sign) */
243                 dest->exp = 0;
244                 dest->mant.m64 = 0;
245                 dest->lowmant = 0;
246 
247                 return dest;
248         }
249 
250         /* zeroes */
251         if (IS_ZERO(dest)) {
252                 /* zero / zero = NaN */
253                 if (IS_ZERO(src))
254                         fp_set_nan(dest);
255                 /* zero / anything else = zero */
256                 return dest;
257         }
258         if (IS_ZERO(src)) {
259                 /* anything / zero = infinity (with appropriate sign) */
260                 fp_set_sr(FPSR_EXC_DZ);
261                 dest->exp = 0x7fff;
262                 dest->mant.m64 = 0;
263 
264                 return dest;
265         }
266 
267         exp = dest->exp - src->exp + 0x3fff;
268 
269         /* shift up the mantissa for denormalized numbers,
270            so that the highest bit is set, this makes lots
271            of things below easier */
272         if ((long)dest->mant.m32[0] >= 0)
273                 exp -= fp_overnormalize(dest);
274         if ((long)src->mant.m32[0] >= 0)
275                 exp -= fp_overnormalize(src);
276 
277         /* now, do the 64-bit divide */
278         fp_dividemant(&temp, dest, src);
279 
280         /* normalize it back to 64 bits and stuff it back into the
281            destination struct */
282         if (!temp.m32[0]) {
283                 exp--;
284                 fp_putmant128(dest, &temp, 32);
285         } else
286                 fp_putmant128(dest, &temp, 31);
287 
288         if (exp >= 0x7fff) {
289                 fp_set_ovrflw(dest);
290                 return dest;
291         }
292         dest->exp = exp;
293         if (exp < 0) {
294                 fp_set_sr(FPSR_EXC_UNFL);
295                 fp_denormalize(dest, -exp);
296         }
297 
298         return dest;
299 }
300 
301 struct fp_ext *fp_fsglmul(struct fp_ext *dest, struct fp_ext *src)
302 {
303         int exp;
304 
305         dprint(PINSTR, "fsglmul\n");
306 
307         fp_dyadic_check(dest, src);
308 
309         /* calculate the correct sign now, as it's necessary for infinities */
310         dest->sign = src->sign ^ dest->sign;
311 
312         /* Handle infinities */
313         if (IS_INF(dest)) {
314                 if (IS_ZERO(src))
315                         fp_set_nan(dest);
316                 return dest;
317         }
318         if (IS_INF(src)) {
319                 if (IS_ZERO(dest))
320                         fp_set_nan(dest);
321                 else
322                         fp_copy_ext(dest, src);
323                 return dest;
324         }
325 
326         /* Of course, as we all know, zero * anything = zero.  You may
327            not have known that it might be a positive or negative
328            zero... */
329         if (IS_ZERO(dest) || IS_ZERO(src)) {
330                 dest->exp = 0;
331                 dest->mant.m64 = 0;
332                 dest->lowmant = 0;
333 
334                 return dest;
335         }
336 
337         exp = dest->exp + src->exp - 0x3ffe;
338 
339         /* do a 32-bit multiply */
340         fp_mul64(dest->mant.m32[0], dest->mant.m32[1],
341                  dest->mant.m32[0] & 0xffffff00,
342                  src->mant.m32[0] & 0xffffff00);
343 
344         if (exp >= 0x7fff) {
345                 fp_set_ovrflw(dest);
346                 return dest;
347         }
348         dest->exp = exp;
349         if (exp < 0) {
350                 fp_set_sr(FPSR_EXC_UNFL);
351                 fp_denormalize(dest, -exp);
352         }
353 
354         return dest;
355 }
356 
357 struct fp_ext *fp_fsgldiv(struct fp_ext *dest, struct fp_ext *src)
358 {
359         int exp;
360         unsigned long quot, rem;
361 
362         dprint(PINSTR, "fsgldiv\n");
363 
364         fp_dyadic_check(dest, src);
365 
366         /* calculate the correct sign now, as it's necessary for infinities */
367         dest->sign = src->sign ^ dest->sign;
368 
369         /* Handle infinities */
370         if (IS_INF(dest)) {
371                 /* infinity / infinity = NaN (quiet, as always) */
372                 if (IS_INF(src))
373                         fp_set_nan(dest);
374                 /* infinity / anything else = infinity (with approprate sign) */
375                 return dest;
376         }
377         if (IS_INF(src)) {
378                 /* anything / infinity = zero (with appropriate sign) */
379                 dest->exp = 0;
380                 dest->mant.m64 = 0;
381                 dest->lowmant = 0;
382 
383                 return dest;
384         }
385 
386         /* zeroes */
387         if (IS_ZERO(dest)) {
388                 /* zero / zero = NaN */
389                 if (IS_ZERO(src))
390                         fp_set_nan(dest);
391                 /* zero / anything else = zero */
392                 return dest;
393         }
394         if (IS_ZERO(src)) {
395                 /* anything / zero = infinity (with appropriate sign) */
396                 fp_set_sr(FPSR_EXC_DZ);
397                 dest->exp = 0x7fff;
398                 dest->mant.m64 = 0;
399 
400                 return dest;
401         }
402 
403         exp = dest->exp - src->exp + 0x3fff;
404 
405         dest->mant.m32[0] &= 0xffffff00;
406         src->mant.m32[0] &= 0xffffff00;
407 
408         /* do the 32-bit divide */
409         if (dest->mant.m32[0] >= src->mant.m32[0]) {
410                 fp_sub64(dest->mant, src->mant);
411                 fp_div64(quot, rem, dest->mant.m32[0], 0, src->mant.m32[0]);
412                 dest->mant.m32[0] = 0x80000000 | (quot >> 1);
413                 dest->mant.m32[1] = (quot & 1) | rem;   /* only for rounding */
414         } else {
415                 fp_div64(quot, rem, dest->mant.m32[0], 0, src->mant.m32[0]);
416                 dest->mant.m32[0] = quot;
417                 dest->mant.m32[1] = rem;                /* only for rounding */
418                 exp--;
419         }
420 
421         if (exp >= 0x7fff) {
422                 fp_set_ovrflw(dest);
423                 return dest;
424         }
425         dest->exp = exp;
426         if (exp < 0) {
427                 fp_set_sr(FPSR_EXC_UNFL);
428                 fp_denormalize(dest, -exp);
429         }
430 
431         return dest;
432 }
433 
434 /* fp_roundint: Internal rounding function for use by several of these
435    emulated instructions.
436 
437    This one rounds off the fractional part using the rounding mode
438    specified. */
439 
440 static void fp_roundint(struct fp_ext *dest, int mode)
441 {
442         union fp_mant64 oldmant;
443         unsigned long mask;
444 
445         if (!fp_normalize_ext(dest))
446                 return;
447 
448         /* infinities and zeroes */
449         if (IS_INF(dest) || IS_ZERO(dest))
450                 return;
451 
452         /* first truncate the lower bits */
453         oldmant = dest->mant;
454         switch (dest->exp) {
455         case 0 ... 0x3ffe:
456                 dest->mant.m64 = 0;
457                 break;
458         case 0x3fff ... 0x401e:
459                 dest->mant.m32[0] &= 0xffffffffU << (0x401e - dest->exp);
460                 dest->mant.m32[1] = 0;
461                 if (oldmant.m64 == dest->mant.m64)
462                         return;
463                 break;
464         case 0x401f ... 0x403e:
465                 dest->mant.m32[1] &= 0xffffffffU << (0x403e - dest->exp);
466                 if (oldmant.m32[1] == dest->mant.m32[1])
467                         return;
468                 break;
469         default:
470                 return;
471         }
472         fp_set_sr(FPSR_EXC_INEX2);
473 
474         /* We might want to normalize upwards here... however, since
475            we know that this is only called on the output of fp_fdiv,
476            or with the input to fp_fint or fp_fintrz, and the inputs
477            to all these functions are either normal or denormalized
478            (no subnormals allowed!), there's really no need.
479 
480            In the case of fp_fdiv, observe that 0x80000000 / 0xffff =
481            0xffff8000, and the same holds for 128-bit / 64-bit. (i.e. the
482            smallest possible normal dividend and the largest possible normal
483            divisor will still produce a normal quotient, therefore, (normal
484            << 64) / normal is normal in all cases) */
485 
486         switch (mode) {
487         case FPCR_ROUND_RN:
488                 switch (dest->exp) {
489                 case 0 ... 0x3ffd:
490                         return;
491                 case 0x3ffe:
492                         /* As noted above, the input is always normal, so the
493                            guard bit (bit 63) is always set.  therefore, the
494                            only case in which we will NOT round to 1.0 is when
495                            the input is exactly 0.5. */
496                         if (oldmant.m64 == (1ULL << 63))
497                                 return;
498                         break;
499                 case 0x3fff ... 0x401d:
500                         mask = 1 << (0x401d - dest->exp);
501                         if (!(oldmant.m32[0] & mask))
502                                 return;
503                         if (oldmant.m32[0] & (mask << 1))
504                                 break;
505                         if (!(oldmant.m32[0] << (dest->exp - 0x3ffd)) &&
506                                         !oldmant.m32[1])
507                                 return;
508                         break;
509                 case 0x401e:
510                         if (oldmant.m32[1] & 0x80000000)
511                                 return;
512                         if (oldmant.m32[0] & 1)
513                                 break;
514                         if (!(oldmant.m32[1] << 1))
515                                 return;
516                         break;
517                 case 0x401f ... 0x403d:
518                         mask = 1 << (0x403d - dest->exp);
519                         if (!(oldmant.m32[1] & mask))
520                                 return;
521                         if (oldmant.m32[1] & (mask << 1))
522                                 break;
523                         if (!(oldmant.m32[1] << (dest->exp - 0x401d)))
524                                 return;
525                         break;
526                 default:
527                         return;
528                 }
529                 break;
530         case FPCR_ROUND_RZ:
531                 return;
532         default:
533                 if (dest->sign ^ (mode - FPCR_ROUND_RM))
534                         break;
535                 return;
536         }
537 
538         switch (dest->exp) {
539         case 0 ... 0x3ffe:
540                 dest->exp = 0x3fff;
541                 dest->mant.m64 = 1ULL << 63;
542                 break;
543         case 0x3fff ... 0x401e:
544                 mask = 1 << (0x401e - dest->exp);
545                 if (dest->mant.m32[0] += mask)
546                         break;
547                 dest->mant.m32[0] = 0x80000000;
548                 dest->exp++;
549                 break;
550         case 0x401f ... 0x403e:
551                 mask = 1 << (0x403e - dest->exp);
552                 if (dest->mant.m32[1] += mask)
553                         break;
554                 if (dest->mant.m32[0] += 1)
555                         break;
556                 dest->mant.m32[0] = 0x80000000;
557                 dest->exp++;
558                 break;
559         }
560 }
561 
562 /* modrem_kernel: Implementation of the FREM and FMOD instructions
563    (which are exactly the same, except for the rounding used on the
564    intermediate value) */
565 
566 static struct fp_ext *modrem_kernel(struct fp_ext *dest, struct fp_ext *src,
567                                     int mode)
568 {
569         struct fp_ext tmp;
570 
571         fp_dyadic_check(dest, src);
572 
573         /* Infinities and zeros */
574         if (IS_INF(dest) || IS_ZERO(src)) {
575                 fp_set_nan(dest);
576                 return dest;
577         }
578         if (IS_ZERO(dest) || IS_INF(src))
579                 return dest;
580 
581         /* FIXME: there is almost certainly a smarter way to do this */
582         fp_copy_ext(&tmp, dest);
583         fp_fdiv(&tmp, src);             /* NOTE: src might be modified */
584         fp_roundint(&tmp, mode);
585         fp_fmul(&tmp, src);
586         fp_fsub(dest, &tmp);
587 
588         /* set the quotient byte */
589         fp_set_quotient((dest->mant.m64 & 0x7f) | (dest->sign << 7));
590         return dest;
591 }
592 
593 /* fp_fmod: Implements the kernel of the FMOD instruction.
594 
595    Again, the argument order is backwards.  The result, as defined in
596    the Motorola manuals, is:
597 
598    fmod(src,dest) = (dest - (src * floor(dest / src))) */
599 
600 struct fp_ext *fp_fmod(struct fp_ext *dest, struct fp_ext *src)
601 {
602         dprint(PINSTR, "fmod\n");
603         return modrem_kernel(dest, src, FPCR_ROUND_RZ);
604 }
605 
606 /* fp_frem: Implements the kernel of the FREM instruction.
607 
608    frem(src,dest) = (dest - (src * round(dest / src)))
609  */
610 
611 struct fp_ext *fp_frem(struct fp_ext *dest, struct fp_ext *src)
612 {
613         dprint(PINSTR, "frem\n");
614         return modrem_kernel(dest, src, FPCR_ROUND_RN);
615 }
616 
617 struct fp_ext *fp_fint(struct fp_ext *dest, struct fp_ext *src)
618 {
619         dprint(PINSTR, "fint\n");
620 
621         fp_copy_ext(dest, src);
622 
623         fp_roundint(dest, FPDATA->rnd);
624 
625         return dest;
626 }
627 
628 struct fp_ext *fp_fintrz(struct fp_ext *dest, struct fp_ext *src)
629 {
630         dprint(PINSTR, "fintrz\n");
631 
632         fp_copy_ext(dest, src);
633 
634         fp_roundint(dest, FPCR_ROUND_RZ);
635 
636         return dest;
637 }
638 
639 struct fp_ext *fp_fscale(struct fp_ext *dest, struct fp_ext *src)
640 {
641         int scale, oldround;
642 
643         dprint(PINSTR, "fscale\n");
644 
645         fp_dyadic_check(dest, src);
646 
647         /* Infinities */
648         if (IS_INF(src)) {
649                 fp_set_nan(dest);
650                 return dest;
651         }
652         if (IS_INF(dest))
653                 return dest;
654 
655         /* zeroes */
656         if (IS_ZERO(src) || IS_ZERO(dest))
657                 return dest;
658 
659         /* Source exponent out of range */
660         if (src->exp >= 0x400c) {
661                 fp_set_ovrflw(dest);
662                 return dest;
663         }
664 
665         /* src must be rounded with round to zero. */
666         oldround = FPDATA->rnd;
667         FPDATA->rnd = FPCR_ROUND_RZ;
668         scale = fp_conv_ext2long(src);
669         FPDATA->rnd = oldround;
670 
671         /* new exponent */
672         scale += dest->exp;
673 
674         if (scale >= 0x7fff) {
675                 fp_set_ovrflw(dest);
676         } else if (scale <= 0) {
677                 fp_set_sr(FPSR_EXC_UNFL);
678                 fp_denormalize(dest, -scale);
679         } else
680                 dest->exp = scale;
681 
682         return dest;
683 }
684 
685 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php