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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [hal/] [sparclite/] [arch/] [v2_0/] [tests/] [sparc_ex.c] - Blame information for rev 565

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

Line No. Rev Author Line
1 27 unneback
/*=================================================================
2
//
3
//        sparc_ex.c
4
//
5
//        SPARClite HAL exception and register manipulation test
6
//
7
//==========================================================================
8
//####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under
14
// the terms of the GNU General Public License as published by the Free
15
// Software Foundation; either version 2 or (at your option) any later version.
16
//
17
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20
// for more details.
21
//
22
// You should have received a copy of the GNU General Public License along
23
// with eCos; if not, write to the Free Software Foundation, Inc.,
24
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25
//
26
// As a special exception, if other files instantiate templates or use macros
27
// or inline functions from this file, or you compile this file and link it
28
// with other works to produce a work based on this file, this file does not
29
// by itself cause the resulting work to be covered by the GNU General Public
30
// License. However the source code for this file must still be made available
31
// in accordance with section (3) of the GNU General Public License.
32
//
33
// This exception does not invalidate any other reasons why a work based on
34
// this file might be covered by the GNU General Public License.
35
//
36
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37
// at http://sources.redhat.com/ecos/ecos-license/
38
// -------------------------------------------
39
//####ECOSGPLCOPYRIGHTEND####
40
//==========================================================================
41
//#####DESCRIPTIONBEGIN####
42
//
43
// Author(s):     dsm
44
// Contributors:    dsm, nickg
45
// Date:          1998-06-18
46
//####DESCRIPTIONEND####
47
*/
48
 
49
#include <pkgconf/system.h>
50
 
51
#include <pkgconf/hal.h>
52
 
53
#include <cyg/infra/cyg_type.h>
54
 
55
#include <cyg/infra/testcase.h>
56
 
57
#include <cyg/hal/hal_arch.h>
58
#include <cyg/hal/hal_intr.h>
59
 
60
#include <pkgconf/infra.h>
61
 
62
#ifdef CYGDBG_USE_TRACING
63
#define OUTER_REPEATS 1
64
#define SIM_REPEATS  10
65
#define HW_REPEATS 1000 
66
#else
67
#define OUTER_REPEATS 10
68
#define SIM_REPEATS  100
69
#define HW_REPEATS 10000 
70
#endif // using tracing to slow everything down
71
 
72
// -------------------------------------------------------------------------
73
// These routines are used to cause an alignment trap; the compiler is too
74
// darned clever by half, if you try to inline this stuff as macros it uses
75
// different instruction sequences and register pairs.  This makes for a
76
// less thorough test, but there's no option other than writing a LOT of
77
// assembler code.
78
 
79
// Further, with -O3, the compiler inlines these anyway and so makes
80
// non-trapping code.  So they are now at the end, to prevent this.
81
 
82
extern cyg_uint64 get_ll( cyg_uint64 *p );
83
 
84
extern cyg_uint64 get_llplus( cyg_uint64 *p );
85
 
86
extern cyg_uint32 get_i( cyg_uint32 *p );
87
 
88
extern cyg_uint32 get_iplus( cyg_uint32 *p );
89
 
90
extern cyg_uint16 get_s( cyg_uint16 *p );
91
 
92
extern cyg_uint16 get_splus( cyg_uint16 *p );
93
 
94
// -------------------------------------------------------------------------
95
// Some memory to read in more-or-less aligned manners.
96
 
97
#define L1 (0x123456789abcdef0l)
98
#define L2 (0xfedcba9876543210l)
99
static cyg_uint64 a[ 2 ] = {
100
    L1,
101
    L2
102
};
103
 
104
#define M32 (0x00000000ffffffffl)
105
#define M16 (0x000000000000ffffl)
106
#define M8  (0x00000000000000ffl)
107
 
108
volatile cyg_uint32 trap = 0;
109
volatile cyg_uint32 same = 0;
110
volatile cyg_uint32 tcount = 0;
111
 
112
// -------------------------------------------------------------------------
113
// This macro invokes a routine then checks that a suitable trap occurred.
114
// It expects the instruction simply to be skipped, rather than the trap
115
// _handled_ or the unaligned access to be _emulated_ in any way.  This
116
// test is just a proof that we could write such a handler.
117
 
118
#define TRAPPROC( _var_, _type_, _align_, _proc_ )                         \
119
CYG_MACRO_START                                                            \
120
    otrap = trap;                                                          \
121
    otcount = tcount;                                                      \
122
    _var_ = _proc_( (_type_ *)(cp + (_align_)) );                          \
123
    CYG_TEST_CHECK( trap != otrap || same > 0,                             \
124
                    "No trap [" #_type_ ":" #_align_ "," #_proc_ "]" );    \
125
    CYG_TEST_CHECK( same < 20,                                             \
126
        "Undetected trap loop[" #_type_ ":" #_align_ "," #_proc_ "]" );    \
127
    CYG_TEST_CHECK( tcount > otcount,                                      \
128
        "No trap counted [" #_type_ ":" #_align_ "," #_proc_ "]" );        \
129
    CYG_TEST_CHECK( (tcount - 1) <= otcount,                               \
130
        "Tcount overinc [" #_type_ ":" #_align_ "," #_proc_ "]" );         \
131
CYG_MACRO_END
132
 
133
// and this one expects no trap to occur:
134
#define SAFEPROC( _var_, _type_, _align_, _proc_ )                         \
135
CYG_MACRO_START                                                            \
136
    trap = 0;                                                              \
137
    otcount = tcount;                                                      \
138
    _var_ = _proc_( (_type_ *)(cp + (_align_)) );                          \
139
    CYG_TEST_CHECK( 0 == trap,                                             \
140
                        "Trap [" #_type_ ":" #_align_ "," #_proc_ "]" );   \
141
    CYG_TEST_CHECK( tcount == otcount,                                     \
142
            "Trap counted [" #_type_ ":" #_align_ "," #_proc_ "]" );       \
143
CYG_MACRO_END
144
 
145
static void do_test( void )
146
{
147
    cyg_uint32 *ip = (cyg_uint32 *)a;
148
    cyg_uint16 *sp = (cyg_uint16 *)a;
149
    cyg_uint8  *cp = (cyg_uint8  *)a;
150
 
151
    cyg_uint64 l;
152
    cyg_uint32 i;
153
    cyg_uint16 s;
154
    cyg_uint8  c;
155
 
156
    cyg_int32 z, repeats;
157
 
158
    cyg_uint32 otrap;
159
    cyg_uint32 otcount;
160
 
161
    otrap = trap = 0;
162
    otcount = tcount;
163
 
164
    // First test interestingly aligned accesses that are legal.
165
 
166
    l = a[0];  CYG_TEST_CHECK( L1 == l, "a[0] read bad" );
167
    l = a[1];  CYG_TEST_CHECK( L2 == l, "a[1] read bad" );
168
 
169
    i = ip[0];  CYG_TEST_CHECK( ((L1 >> 32) & M32) == i, "ip[0]" );
170
    i = ip[1];  CYG_TEST_CHECK( ((L1      ) & M32) == i, "ip[1]" );
171
    i = ip[2];  CYG_TEST_CHECK( ((L2 >> 32) & M32) == i, "ip[2]" );
172
    i = ip[3];  CYG_TEST_CHECK( ((L2      ) & M32) == i, "ip[3]" );
173
 
174
    s = sp[0];  CYG_TEST_CHECK( ((L1 >> 48) & M16) == s, "sp[0]" );
175
    s = sp[1];  CYG_TEST_CHECK( ((L1 >> 32) & M16) == s, "sp[1]" );
176
    s = sp[2];  CYG_TEST_CHECK( ((L1 >> 16) & M16) == s, "sp[2]" );
177
    s = sp[3];  CYG_TEST_CHECK( ((L1      ) & M16) == s, "sp[3]" );
178
    s = sp[4];  CYG_TEST_CHECK( ((L2 >> 48) & M16) == s, "sp[4]" );
179
    s = sp[5];  CYG_TEST_CHECK( ((L2 >> 32) & M16) == s, "sp[5]" );
180
    s = sp[6];  CYG_TEST_CHECK( ((L2 >> 16) & M16) == s, "sp[6]" );
181
    s = sp[7];  CYG_TEST_CHECK( ((L2      ) & M16) == s, "sp[7]" );
182
 
183
    c = cp[0];  CYG_TEST_CHECK( ((L1 >> 56) & M8) == c, "cp[0]" );
184
    c = cp[1];  CYG_TEST_CHECK( ((L1 >> 48) & M8) == c, "cp[1]" );
185
    c = cp[2];  CYG_TEST_CHECK( ((L1 >> 40) & M8) == c, "cp[2]" );
186
    c = cp[3];  CYG_TEST_CHECK( ((L1 >> 32) & M8) == c, "cp[3]" );
187
    c = cp[4];  CYG_TEST_CHECK( ((L1 >> 24) & M8) == c, "cp[4]" );
188
    c = cp[5];  CYG_TEST_CHECK( ((L1 >> 16) & M8) == c, "cp[5]" );
189
    c = cp[6];  CYG_TEST_CHECK( ((L1 >>  8) & M8) == c, "cp[6]" );
190
    c = cp[7];  CYG_TEST_CHECK( ((L1      ) & M8) == c, "cp[7]" );
191
    c = cp[8];  CYG_TEST_CHECK( ((L2 >> 56) & M8) == c, "cp[8]" );
192
    c = cp[9];  CYG_TEST_CHECK( ((L2 >> 48) & M8) == c, "cp[9]" );
193
    c = cp[10]; CYG_TEST_CHECK( ((L2 >> 40) & M8) == c, "cp[10]" );
194
    c = cp[11]; CYG_TEST_CHECK( ((L2 >> 32) & M8) == c, "cp[11]" );
195
    c = cp[12]; CYG_TEST_CHECK( ((L2 >> 24) & M8) == c, "cp[12]" );
196
    c = cp[13]; CYG_TEST_CHECK( ((L2 >> 16) & M8) == c, "cp[13]" );
197
    c = cp[14]; CYG_TEST_CHECK( ((L2 >>  8) & M8) == c, "cp[14]" );
198
    c = cp[15]; CYG_TEST_CHECK( ((L2      ) & M8) == c, "cp[15]" );
199
 
200
    CYG_TEST_CHECK( 0 == trap, "Traps occurred (legal accesses)" );
201
    CYG_TEST_CHECK( tcount == otcount, "Traps counted (legal accesses)" );
202
 
203
    CYG_TEST_PASS( "Aligned accesses OK" );
204
 
205
    for ( z = OUTER_REPEATS; z > 0; z-- ) {
206
 
207
        for ( repeats = (cyg_test_is_simulator ? SIM_REPEATS : HW_REPEATS) ;
208
              repeats > 0 ; repeats-- ) {
209
 
210
            TRAPPROC( l, cyg_uint64, 4, get_llplus );
211
            TRAPPROC( l, cyg_uint64, 5, get_llplus );
212
            TRAPPROC( l, cyg_uint64, 6, get_llplus );
213
            TRAPPROC( l, cyg_uint64, 7, get_llplus );
214
 
215
            TRAPPROC( l, cyg_uint64, 4, get_ll );
216
            TRAPPROC( l, cyg_uint64, 1, get_ll );
217
            TRAPPROC( l, cyg_uint64, 2, get_ll );
218
            TRAPPROC( l, cyg_uint64, 3, get_ll );
219
 
220
            TRAPPROC( i, cyg_uint32, 1, get_iplus );
221
            TRAPPROC( i, cyg_uint32, 2, get_iplus );
222
            TRAPPROC( i, cyg_uint32, 3, get_iplus );
223
 
224
            TRAPPROC( i, cyg_uint32, 5, get_i );
225
            TRAPPROC( i, cyg_uint32, 6, get_i );
226
            TRAPPROC( i, cyg_uint32, 7, get_i );
227
 
228
            TRAPPROC( s, cyg_uint16, 1, get_splus );
229
            TRAPPROC( s, cyg_uint16, 3, get_splus );
230
 
231
            TRAPPROC( s, cyg_uint16, 5, get_s );
232
            TRAPPROC( s, cyg_uint16, 7, get_s );
233
        }
234
 
235
        CYG_TEST_PASS( "Unaligned accesses OK" );
236
 
237
        // Now test some legal and illegal accesses intermingled.
238
 
239
        for ( repeats = (cyg_test_is_simulator ? SIM_REPEATS : HW_REPEATS) ;
240
              repeats > 0 ; repeats-- ) {
241
 
242
            SAFEPROC( l, cyg_uint64, 0, get_llplus );
243
            TRAPPROC( l, cyg_uint64, 5, get_llplus );
244
            TRAPPROC( l, cyg_uint64, 6, get_llplus );
245
            SAFEPROC( l, cyg_uint64, 8, get_llplus );
246
 
247
            TRAPPROC( i, cyg_uint32, 1, get_iplus );
248
            SAFEPROC( i, cyg_uint32, 4, get_iplus );
249
            TRAPPROC( i, cyg_uint32, 2, get_iplus );
250
            SAFEPROC( i, cyg_uint32, 8, get_iplus );
251
            SAFEPROC( i, cyg_uint32, 12, get_iplus );
252
            SAFEPROC( i, cyg_uint32, 16, get_iplus );
253
            TRAPPROC( i, cyg_uint32, 3, get_iplus );
254
 
255
            TRAPPROC( s, cyg_uint16, 5, get_s );
256
            SAFEPROC( s, cyg_uint16, 6, get_s );
257
            TRAPPROC( s, cyg_uint16, 7, get_s );
258
            SAFEPROC( s, cyg_uint16, 8, get_s );
259
 
260
            TRAPPROC( i, cyg_uint32, 5, get_i );
261
            SAFEPROC( i, cyg_uint32, 4, get_i );
262
            TRAPPROC( i, cyg_uint32, 6, get_i );
263
            TRAPPROC( i, cyg_uint32, 7, get_i );
264
            SAFEPROC( i, cyg_uint32, 0, get_i );
265
 
266
            TRAPPROC( l, cyg_uint64, 4, get_ll );
267
            SAFEPROC( l, cyg_uint64, 0, get_ll );
268
            TRAPPROC( l, cyg_uint64, 1, get_ll );
269
            SAFEPROC( l, cyg_uint64, 8, get_ll );
270
 
271
            TRAPPROC( s, cyg_uint16, 1, get_splus );
272
            SAFEPROC( s, cyg_uint16, 2, get_splus );
273
            TRAPPROC( s, cyg_uint16, 3, get_splus );
274
            SAFEPROC( s, cyg_uint16, 4, get_splus );
275
        }
276
 
277
        CYG_TEST_PASS( "Mixture of accesses OK" );
278
    }
279
}
280
 
281
// -------------------------------------------------------------------------
282
 
283
externC void
284
skip_exception_handler(CYG_ADDRWORD vector, CYG_ADDRWORD data,
285
                                   CYG_ADDRWORD stackpointer);
286
 
287
externC void
288
fail_exception_handler(CYG_ADDRWORD vector, CYG_ADDRWORD data,
289
                                   CYG_ADDRWORD stackpointer);
290
 
291
// -------------------------------------------------------------------------
292
 
293
void sparc_ex_main( void )
294
{
295
    int i;
296
 
297
    CYG_TEST_INIT();
298
 
299
    for ( i = CYGNUM_HAL_EXCEPTION_MIN; i <= CYGNUM_HAL_EXCEPTION_MAX; i++ ){
300
        int j;
301
        HAL_TRANSLATE_VECTOR( i, j );
302
        HAL_INTERRUPT_ATTACH( j, &fail_exception_handler, j, 0 );
303
        // we must also ensure that eCos handles the exception;
304
        // do not drop into CygMon or equivalent.
305
        // Leave USER_TRAP undisturbed so that breakpoints work.
306
        if ( CYGNUM_HAL_VECTOR_USER_TRAP != i ) {
307
            extern void hal_default_exception_vsr( void );
308
            HAL_VSR_SET( i, (CYG_ADDRESS)hal_default_exception_vsr, NULL );
309
        }
310
    }
311
 
312
    HAL_TRANSLATE_VECTOR( CYGNUM_HAL_VECTOR_UNALIGNED, i );
313
    HAL_INTERRUPT_DETACH( i, &fail_exception_handler );
314
    HAL_INTERRUPT_ATTACH( i, &skip_exception_handler, i, 0 );
315
 
316
    CYG_TEST_INFO( "Vectors attached OK; calling do_test" );
317
 
318
    do_test();
319
 
320
    CYG_TEST_EXIT( "Done" );
321
}
322
 
323
// -------------------------------------------------------------------------
324
externC void
325
skip_exception_handler(CYG_ADDRWORD vector, CYG_ADDRWORD data,
326
                                   CYG_ADDRWORD stackpointer)
327
{
328
    HAL_SavedRegisters *save;
329
    HAL_FrameStructure *frame;
330
 
331
    HAL_FLUSH_REGISTERS_TO_STACK();
332
 
333
    save = (HAL_SavedRegisters *) stackpointer;
334
    frame = (HAL_FrameStructure *) (save + 1); // immediately after
335
 
336
    // now, this is the invokation environment when this saved regset
337
    // was created (copied from hal_xvsr.S):
338
    //  ! here,locals have been set up as follows:
339
    //  ! %l0 = psr (with this CWP/window-level in it)
340
    //  ! %l1 = pc
341
    //  ! %l2 = npc
342
    //  ! %l3 = vector number (16-25 for traps)
343
    //  ! and we are in our own register window, though it is likely that
344
    //  ! the next one will need to be saved before we can use it:
345
    //  ! ie. this one is the invalid register window.
346
    // and the intention is that we can mess therewith:
347
 
348
    // Check we're not in a trap loop
349
    if ( trap == save->li.l[1] ) {
350
        same++;
351
        if ( 10 < same )
352
            CYG_TEST_FAIL_EXIT( "Repeated trap" );
353
    }
354
    else // restart the count
355
       same = 0;
356
 
357
    // and record it
358
    trap = save->li.l[1];
359
    tcount++;
360
 
361
    // now step on so that we return to the instruction after:
362
    save->li.l[1] = save->li.l[2]; // PC := NPC
363
    save->li.l[2] += 4;            // NPC += 4
364
 
365
    // that's all.
366
}
367
 
368
externC void
369
fail_exception_handler(CYG_ADDRWORD vector, CYG_ADDRWORD data,
370
                                   CYG_ADDRWORD stackpointer)
371
{
372
    HAL_FLUSH_REGISTERS_TO_STACK();
373
    CYG_TEST_FAIL_EXIT( "Other exception handler called" );
374
}
375
 
376
// -------------------------------------------------------------------------
377
 
378
externC void
379
#ifdef CYGPKG_KERNEL
380
cyg_user_start( void )
381
#else
382
cyg_start( void )
383
#endif
384
{
385
    sparc_ex_main();
386
}
387
 
388
// -------------------------------------------------------------------------
389
 
390
cyg_uint64 get_ll( cyg_uint64 *p )
391
{
392
    return *p;
393
}
394
 
395
cyg_uint64 get_llplus( cyg_uint64 *p )
396
{
397
    cyg_uint64 ll = 0l, v;
398
    ll = (cyg_uint32)p;
399
    ll++;
400
    v = *p;
401
    v^= ll;
402
    return v;
403
}
404
 
405
cyg_uint32 get_i( cyg_uint32 *p )
406
{
407
    return *p;
408
}
409
 
410
cyg_uint32 get_iplus( cyg_uint32 *p )
411
{
412
    cyg_uint32 i = 0, v;
413
    i = (cyg_uint32)p;
414
    i++;
415
    v = *p;
416
    v^= i;
417
    return v;
418
}
419
 
420
cyg_uint16 get_s( cyg_uint16 *p )
421
{
422
    return *p;
423
}
424
 
425
cyg_uint16 get_splus( cyg_uint16 *p )
426
{
427
    cyg_uint16 s = 0, v;
428
    s = (cyg_uint16)(0xffff & (cyg_uint32)p);
429
    s++;
430
    v = *p;
431
    v^= s;
432
    return v;
433
}
434
 
435
// -------------------------------------------------------------------------
436
 
437
/* EOF sparc_ex.c */

powered by: WebSVN 2.1.0

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