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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [hal/] [sparclite/] [arch/] [current/] [tests/] [sparc_ex.c] - Blame information for rev 786

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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