source: rtems/c/src/tests/libffi/ffitest/ffitest.c @ 41ab6966

4.104.114.84.95
Last change on this file since 41ab6966 was 41ab6966, checked in by Joel Sherrill <joel.sherrill@…>, on 06/12/00 at 20:06:59

Patch from John Cotton <john.cotton@…>, Charles-Antoine Gauthier
<charles.gauthier@…>, and Darlene A. Stewart
<Darlene.Stewart@…> to add support for a number of very
significant things:

+ BSPs for many variations on the Motorola MBX8xx board series
+ Cache Manager including initial support for m68040

and PowerPC

+ Rework of mpc8xx libcpu code so all mpc8xx CPUs now use

same code base.

+ Rework of eth_comm BSP to utiltize above.

John reports this works on the 821 and 860

  • Property mode set to 100644
File size: 16.9 KB
Line 
1/* -----------------------------------------------------------------------
2   ffitest.c - Copyright (c) 1996, 1997, 1998  Cygnus Solutions
3
4   $Id$
5
6   Permission is hereby granted, free of charge, to any person obtaining
7   a copy of this software and associated documentation files (the
8   ``Software''), to deal in the Software without restriction, including
9   without limitation the rights to use, copy, modify, merge, publish,
10   distribute, sublicense, and/or sell copies of the Software, and to
11   permit persons to whom the Software is furnished to do so, subject to
12   the following conditions:
13
14   The above copyright notice and this permission notice shall be included
15   in all copies or substantial portions of the Software.
16
17   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
18   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23   OTHER DEALINGS IN THE SOFTWARE.
24   ----------------------------------------------------------------------- */
25
26#include <ffi.h>
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <float.h>
31#include <rtems.h>
32#include <rtems/error.h>
33
34/* This is lame. Long double support is barely there under SunOS 4.x  */
35#if defined(SPARC) && (SIZEOF_LONG_DOUBLE != 16)
36#define BROKEN_LONG_DOUBLE
37#endif
38
39#define CHECK(x) !(x) ? fail(__FILE__, __LINE__) : 0
40
41static int fail(char *file, int line)
42{
43  fprintf(stderr, "Test failure: %s line %d\n", file, line);
44  exit(EXIT_FAILURE);
45  /*@notreached@*/
46  return 0;
47}
48
49#define MAX_ARGS 256
50
51static size_t my_strlen(char *s)
52{
53  return (strlen(s));
54}
55
56static int promotion(signed char sc, signed short ss,
57                     unsigned char uc, unsigned short us)
58{
59  int r = (int) sc + (int) ss + (int) uc + (int) us;
60
61  return r;
62}
63
64static signed char return_sc(signed char sc)
65{
66  return sc;
67}
68
69static unsigned char return_uc(unsigned char uc)
70{
71  return uc;
72}
73
74static long long return_ll(long long ll)
75{
76  return ll;
77}
78
79static int floating(int a, float b, double c, long double d, int e)
80{
81  int i;
82
83#if 0
84  /* This is ifdef'd out for now. long double support under SunOS/gcc
85     is pretty much non-existent.  You'll get the odd bus error in library
86     routines like printf().  */
87  printf("%d %f %f %Lf %d\n", a, (double)b, c, d, e);
88#endif
89
90  i = (int) ((float)a/b + ((float)c/(float)d));
91
92  return i;
93}
94
95static float many(float f1,
96                  float f2,
97                  float f3,
98                  float f4,
99                  float f5,
100                  float f6,
101                  float f7,
102                  float f8,
103                  float f9,
104                  float f10,
105                  float f11,
106                  float f12,
107                  float f13)
108{
109#if 0
110  printf("%f %f %f %f %f %f %f %f %f %f %f %f %f\n",
111         (double) f1, (double) f2, (double) f3, (double) f4, (double) f5,
112         (double) f6, (double) f7, (double) f8, (double) f9, (double) f10,
113         (double) f11, (double) f12, (double) f13);
114#endif
115
116  return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
117}
118
119static double dblit(float f)
120{
121  return f/3.0;
122}
123
124static long double ldblit(float f)
125{
126  return (long double) (((long double) f)/ (long double) 3.0);
127}
128
129typedef struct
130{
131  unsigned char uc;
132  double d;
133  unsigned int ui;
134} test_structure_1;
135
136typedef struct
137{
138  double d1;
139  double d2;
140} test_structure_2;
141
142typedef struct
143{
144  int si;
145} test_structure_3;
146
147typedef struct
148{
149  unsigned ui1;
150  unsigned ui2;
151  unsigned ui3;
152} test_structure_4;
153
154typedef struct
155{
156  char c1;
157  char c2;
158} test_structure_5;
159
160static test_structure_1 struct1(test_structure_1 ts)
161{
162  /*@-type@*/
163  ts.uc++;
164  /*@=type@*/
165  ts.d--;
166  ts.ui++;
167
168  return ts;
169}
170
171static test_structure_2 struct2(test_structure_2 ts)
172{
173  ts.d1--;
174  ts.d2--;
175
176  return ts;
177}
178
179static test_structure_3 struct3(test_structure_3 ts)
180{
181  ts.si = -(ts.si*2);
182
183  return ts;
184}
185
186static test_structure_4 struct4(test_structure_4 ts)
187{
188  ts.ui3 = ts.ui1 * ts.ui2 * ts.ui3;
189
190  return ts;
191}
192
193static test_structure_5 struct5(test_structure_5 ts1, test_structure_5 ts2)
194{
195  ts1.c1 += ts2.c1;
196  ts1.c2 -= ts2.c2;
197
198  return ts1;
199}
200
201/* Take an int and a float argument, together with int userdata, and    */
202/* return the sum.                                                      */
203static void closure_test_fn(ffi_cif* cif,void* resp,void** args, void* userdata)
204{
205    *(int*)resp =
206         *(int *)args[0] + (int)(*(float *)args[1]) + (int)(long)userdata;
207}
208
209typedef int (*closure_test_type)(int, float);
210
211int ffi_main( void )
212{
213  ffi_cif cif;
214  ffi_type *args[MAX_ARGS];
215  void *values[MAX_ARGS];
216  char *s;
217  signed char sc;
218  unsigned char uc;
219  signed short ss;
220  unsigned short us;
221  unsigned long ul;
222  long long ll;
223  float f;
224  double d;
225  long double ld;
226  signed int si1;
227  signed int si2;
228
229#if defined(ALPHA) || defined(IA64) || defined(SPARC64) || (defined(MIPS) && (_MIPS_SIM == _ABIN32))
230  long long rint;
231#else
232  int rint;
233#endif
234  long long rlonglong;
235
236  ffi_type ts1_type;
237  ffi_type ts2_type;
238  ffi_type ts3_type;
239  ffi_type ts4_type; 
240  ffi_type ts5_type;
241  ffi_type *ts1_type_elements[4];
242  ffi_type *ts2_type_elements[3];
243  ffi_type *ts3_type_elements[2];
244  ffi_type *ts4_type_elements[4];
245  ffi_type *ts5_type_elements[3];
246
247  ts1_type.size = 0;
248  ts1_type.alignment = 0;
249  ts1_type.type = FFI_TYPE_STRUCT;
250
251  ts2_type.size = 0;
252  ts2_type.alignment = 0;
253  ts2_type.type = FFI_TYPE_STRUCT;
254
255  ts3_type.size = 0;
256  ts3_type.alignment = 0;
257  ts3_type.type = FFI_TYPE_STRUCT;
258
259  ts4_type.size = 0;
260  ts4_type.alignment = 0;
261  ts4_type.type = FFI_TYPE_STRUCT;
262
263  ts5_type.size = 0;
264  ts5_type.alignment = 0;
265  ts5_type.type = FFI_TYPE_STRUCT;
266
267  /*@-immediatetrans@*/
268  ts1_type.elements = ts1_type_elements;
269  ts2_type.elements = ts2_type_elements;
270  ts3_type.elements = ts3_type_elements;
271  ts4_type.elements = ts4_type_elements;
272  ts5_type.elements = ts5_type_elements;
273  /*@=immediatetrans@*/
274 
275  ts1_type_elements[0] = &ffi_type_uchar;
276  ts1_type_elements[1] = &ffi_type_double;
277  ts1_type_elements[2] = &ffi_type_uint;
278  ts1_type_elements[3] = NULL;
279 
280  ts2_type_elements[0] = &ffi_type_double;
281  ts2_type_elements[1] = &ffi_type_double;
282  ts2_type_elements[2] = NULL;
283
284  ts3_type_elements[0] = &ffi_type_sint;
285  ts3_type_elements[1] = NULL;
286
287  ts4_type_elements[0] = &ffi_type_uint;
288  ts4_type_elements[1] = &ffi_type_uint;
289  ts4_type_elements[2] = &ffi_type_uint;
290  ts4_type_elements[3] = NULL;
291
292  ts5_type_elements[0] = &ffi_type_schar;
293  ts5_type_elements[1] = &ffi_type_schar;
294  ts5_type_elements[2] = NULL;
295
296  ul = 0;
297
298  /* return value tests */
299  {
300#if defined(MIPS) /* || defined(ARM) */
301    puts ("long long tests not run. This is a known bug on this architecture.");
302#else
303    args[0] = &ffi_type_sint64;
304    values[0] = &ll;
305   
306    /* Initialize the cif */
307    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
308                       &ffi_type_sint64, args) == FFI_OK);
309
310    for (ll = 0LL; ll < 100LL; ll++)
311      {
312        ul++;
313        ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
314        CHECK(rlonglong == ll);
315      }
316
317    for (ll = 55555555555000LL; ll < 55555555555100LL; ll++)
318      {
319        ul++;
320        ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
321        CHECK(rlonglong == ll);
322      }
323#endif
324
325    args[0] = &ffi_type_schar;
326    values[0] = &sc;
327   
328    /* Initialize the cif */
329    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
330                       &ffi_type_schar, args) == FFI_OK);
331
332    for (sc = (signed char) -127;
333         sc < (signed char) 127; /*@-type@*/ sc++ /*@=type@*/)
334      {
335        ul++;
336        ffi_call(&cif, FFI_FN(return_sc), &rint, values);
337        CHECK(rint == (int) sc);
338      }
339
340    args[0] = &ffi_type_uchar;
341    values[0] = &uc;
342   
343    /* Initialize the cif */
344    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
345                       &ffi_type_uchar, args) == FFI_OK);
346
347    for (uc = (unsigned char) '\x00';
348         uc < (unsigned char) '\xff'; /*@-type@*/ uc++ /*@=type@*/)
349      {
350        ul++;
351        ffi_call(&cif, FFI_FN(return_uc), &rint, values);
352        CHECK(rint == (signed int) uc);
353      }
354
355    printf("%lu return value tests run\n", ul);
356  }
357
358#ifdef BROKEN_LONG_DOUBLE
359  printf ("This architecture has broken `long double' support. No floating point\ntests have been run.\n");
360#else
361  /* float arg tests */
362  {
363    args[0] = &ffi_type_float;
364    values[0] = &f;
365
366    /* Initialize the cif */
367    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
368                       &ffi_type_longdouble, args) == FFI_OK);
369
370    f = 3.14159;
371
372#if 0
373  /* This is ifdef'd out for now. long double support under SunOS/gcc
374     is pretty much non-existent.  You'll get the odd bus error in library
375     routines like printf().  */
376    printf ("%Lf\n", ldblit(f));
377#endif
378    ld = 666;
379    ffi_call(&cif, FFI_FN(ldblit), &ld, values);
380
381#if 0
382  /* This is ifdef'd out for now. long double support under SunOS/gcc
383     is pretty much non-existent.  You'll get the odd bus error in library
384     routines like printf().  */
385    printf ("%Lf, %Lf, %Lf, %Lf\n", ld, ldblit(f), ld - ldblit(f), LDBL_EPSILON);
386#endif
387
388    /* These are not always the same!! Check for a reasonable delta */
389    /*@-realcompare@*/
390    if (ld - ldblit(f) < LDBL_EPSILON)
391    /*@=realcompare@*/
392        puts("long double return value tests ok!");
393    else
394        CHECK(0);
395  }
396
397  /* float arg tests */
398  {
399    args[0] = &ffi_type_sint;
400    values[0] = &si1;
401    args[1] = &ffi_type_float;
402    values[1] = &f;
403    args[2] = &ffi_type_double;
404    values[2] = &d;
405    args[3] = &ffi_type_longdouble;
406    values[3] = &ld;
407    args[4] = &ffi_type_sint;
408    values[4] = &si2;
409   
410    /* Initialize the cif */
411    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 5,
412                       &ffi_type_sint, args) == FFI_OK);
413
414    si1 = 6;
415    f = 3.14159;
416    d = (double)1.0/(double)3.0;
417    ld = 2.71828182846L;
418    si2 = 10;
419
420    floating (si1, f, d, ld, si2);
421
422    ffi_call(&cif, FFI_FN(floating), &rint, values);
423
424    printf ("%d vs %d\n", rint, floating (si1, f, d, ld, si2));
425
426    CHECK(rint == floating(si1, f, d, ld, si2));
427
428    printf("float arg tests ok!\n");
429  }
430#endif
431
432  /* strlen tests */
433  {
434    args[0] = &ffi_type_pointer;
435    values[0] = (void*) &s;
436   
437    /* Initialize the cif */
438    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
439                       &ffi_type_sint, args) == FFI_OK);
440
441    s = "a";
442    ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
443    CHECK(rint == 1);
444
445    s = "1234567";
446    ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
447    CHECK(rint == 7);
448
449    s = "1234567890123456789012345";
450    ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
451    CHECK(rint == 25);
452
453    printf("strlen tests passed\n");
454  }
455
456  /* float arg tests */
457  {
458    args[0] = &ffi_type_float;
459    values[0] = &f;
460   
461    /* Initialize the cif */
462    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
463                       &ffi_type_double, args) == FFI_OK);
464
465    f = 3.14159;
466
467    ffi_call(&cif, FFI_FN(dblit), &d, values);
468
469    /* These are not always the same!! Check for a reasonable delta */
470    /*@-realcompare@*/
471    CHECK(d - dblit(f) < DBL_EPSILON);
472    /*@=realcompare@*/
473
474    printf("double return value tests ok!\n");
475  }
476
477  /* many arg tests */
478  {
479    float ff;
480    float fa[13];
481   
482    for (ul = 0; ul < 13; ul++)
483      {
484        args[ul] = &ffi_type_float;
485        values[ul] = &fa[ul];
486        fa[ul] = (float) ul;
487      }
488
489    /* Initialize the cif */
490    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 13,
491                       &ffi_type_float, args) == FFI_OK);
492
493    /*@-usedef@*/
494    ff =  many(fa[0], fa[1],
495               fa[2], fa[3],
496               fa[4], fa[5],
497               fa[6], fa[7],
498               fa[8], fa[9],
499               fa[10],fa[11],fa[12]);
500    /*@=usedef@*/
501
502    ffi_call(&cif, FFI_FN(many), &f, values);
503
504    /*@-realcompare@*/
505    if (f - ff < FLT_EPSILON)
506    /*@=realcompare@*/
507        printf("many arg tests ok!\n");
508    else
509#ifdef POWERPC
510        printf("many arg tests failed!  This is a gcc bug.\n");
511#else
512        CHECK(0);
513#endif
514  }
515
516  /* promotion tests */
517  {
518    args[0] = &ffi_type_schar;
519    args[1] = &ffi_type_sshort;
520    args[2] = &ffi_type_uchar;
521    args[3] = &ffi_type_ushort;
522    values[0] = &sc;
523    values[1] = &ss;
524    values[2] = &uc;
525    values[3] = &us;
526   
527    /* Initialize the cif */
528    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
529                       &ffi_type_sint, args) == FFI_OK);
530
531    us = 0;
532    ul = 0;
533
534    for (sc = (signed char) -127;
535         sc <= (signed char) 120; /*@-type@*/ sc += 1 /*@=type@*/)
536      for (ss = -30000; ss <= 30000; ss += 10000)
537        for (uc = (unsigned char) 0;
538             uc <= (unsigned char) 200; /*@-type@*/ uc += 20 /*@=type@*/)
539          for (us = 0; us <= 60000; us += 10000)
540            {
541              ul++;
542              ffi_call(&cif, FFI_FN(promotion), &rint, values);
543              CHECK(rint == (int) sc + (int) ss + (int) uc + (int) us);
544            }
545    printf("%lu promotion tests run\n", ul);
546  }
547
548  /* struct tests */
549  {
550    test_structure_1 ts1_arg;
551    /* This is a hack to get a properly aligned result buffer */
552    test_structure_1 *ts1_result =
553      (test_structure_1 *) malloc (sizeof(test_structure_1));
554                if (! ts1_result )
555                        rtems_panic("Could not get memory for struct 1 result.");
556    args[0] = &ts1_type;
557    values[0] = &ts1_arg;
558   
559    /* Initialize the cif */
560    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
561                       &ts1_type, args) == FFI_OK);
562
563    ts1_arg.uc = '\x01';
564    ts1_arg.d = 3.14159;
565    ts1_arg.ui = 555;
566
567    ffi_call(&cif, FFI_FN(struct1), ts1_result, values);
568
569    CHECK(ts1_result->ui == 556);
570    CHECK(ts1_result->d == 3.14159 - 1);
571
572    puts ("structure test 1 ok!\n");
573
574    free (ts1_result);
575  }
576
577  /* struct tests */
578  {
579    test_structure_2 ts2_arg;
580
581    /* This is a hack to get a properly aligned result buffer */
582    test_structure_2 *ts2_result =
583      (test_structure_2 *) malloc (sizeof(test_structure_2));
584
585    args[0] = &ts2_type;
586    values[0] = &ts2_arg;
587   
588    /* Initialize the cif */
589    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
590                       &ts2_type, args) == FFI_OK);
591
592    ts2_arg.d1 = 5.55;
593    ts2_arg.d2 = 6.66;
594
595    printf ("%g\n", ts2_result->d1);
596    printf ("%g\n", ts2_result->d2);
597
598    ffi_call(&cif, FFI_FN(struct2), ts2_result, values);
599
600    printf ("%g\n", ts2_result->d1);
601    printf ("%g\n", ts2_result->d2);
602   
603    CHECK(ts2_result->d1 == 5.55 - 1);
604    CHECK(ts2_result->d2 == 6.66 - 1);
605
606    printf("structure test 2 ok!\n");
607
608    free (ts2_result);
609  }
610
611  /* struct tests */
612  {
613    int compare_value;
614    test_structure_3 ts3_arg;
615    test_structure_3 *ts3_result =
616      (test_structure_3 *) malloc (sizeof(test_structure_3));
617
618    args[0] = &ts3_type;
619    values[0] = &ts3_arg;
620   
621    /* Initialize the cif */
622    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
623                       &ts3_type, args) == FFI_OK);
624
625    ts3_arg.si = -123;
626    compare_value = ts3_arg.si;
627
628    ffi_call(&cif, FFI_FN(struct3), ts3_result, values);
629
630    printf ("%d %d\n", ts3_result->si, -(compare_value*2));
631
632    if (ts3_result->si == -(ts3_arg.si*2))
633        puts ("structure test 3 ok!");
634    else
635      {
636        puts ("Structure test 3 found structure passing bug.");
637        puts ("  Current versions of GCC are not 100% compliant with the");
638        puts ("  n32 ABI.  There is a known problem related to passing");
639        puts ("  small structures.  Send a bug report to the gcc maintainers.");
640      }
641
642    free (ts3_result);
643  }
644
645  /* struct tests */
646  {
647    test_structure_4 ts4_arg;
648
649    /* This is a hack to get a properly aligned result buffer */
650    test_structure_4 *ts4_result =
651      (test_structure_4 *) malloc (sizeof(test_structure_4));
652
653    args[0] = &ts4_type;
654    values[0] = &ts4_arg;
655   
656    /* Initialize the cif */
657    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
658                       &ts4_type, args) == FFI_OK);
659
660    ts4_arg.ui1 = 2;
661    ts4_arg.ui2 = 3;
662    ts4_arg.ui3 = 4;
663
664    ffi_call (&cif, FFI_FN(struct4), ts4_result, values);
665   
666    if (ts4_result->ui3 == 2U * 3U * 4U)
667      puts ("structure test 4 ok!");
668    else
669      puts ("Structure test 4 found GCC's structure passing bug.");
670
671    free (ts4_result);
672  }
673
674  /* struct tests */
675  {
676    test_structure_5 ts5_arg1, ts5_arg2;
677
678    /* This is a hack to get a properly aligned result buffer */
679    test_structure_5 *ts5_result =
680      (test_structure_5 *) malloc (sizeof(test_structure_5));
681
682    args[0] = &ts5_type;
683    args[1] = &ts5_type;
684    values[0] = &ts5_arg1;
685    values[1] = &ts5_arg2;
686   
687    /* Initialize the cif */
688    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
689                       &ts5_type, args) == FFI_OK);
690
691    ts5_arg1.c1 = 2;
692    ts5_arg1.c2 = 6;
693    ts5_arg2.c1 = 5;
694    ts5_arg2.c2 = 3;
695
696    ffi_call (&cif, FFI_FN(struct5), ts5_result, values);
697   
698    if (ts5_result->c1 == 7
699        && ts5_result->c2 == 3)
700      puts ("structure test 5 ok!");
701    else
702      puts ("Structure test 5 found GCC's structure passing bug.");
703
704    free (ts5_result);
705  }
706
707# if FFI_CLOSURES
708  /* A simple closure test */
709    {
710      ffi_closure cl;
711      ffi_type * cl_arg_types[3];
712
713      cl_arg_types[0] = &ffi_type_sint;
714      cl_arg_types[1] = &ffi_type_float;
715      cl_arg_types[2] = NULL;
716     
717      /* Initialize the cif */
718      CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
719                         &ffi_type_sint, cl_arg_types) == FFI_OK);
720
721      CHECK(ffi_prep_closure(&cl, &cif, closure_test_fn,
722                             (void *) 3 /* userdata */)
723            == FFI_OK);
724      CHECK((*((closure_test_type)(&cl)))(1, 2.0) == 6);
725    }
726# endif
727
728  /* If we arrived here, all is good */
729  (void) puts("\nLooks good. No surprises.\n");
730
731  /*@-compdestroy@*/
732
733  return 0;
734}
735
Note: See TracBrowser for help on using the repository browser.