1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <libmcpu.h>
static int failures = 0;
#define CHECK(cond,msg) \
do { \
if( !(cond) ) \
{ \
fprintf( stderr, "FAIL: %s\n", (msg) ); \
++failures; \
} \
} while( 0 )
int
main( void )
{
__mpu_uint32_t psw;
__cpu_init();
CHECK( __cpu_pc == 0, "PC after __cpu_init()" );
CHECK( __cpu_sp == 0, "SP after __cpu_init()" );
CHECK( __cpu_fp == 0, "FP after __cpu_init()" );
CHECK( __cpu_get_psw() == 0, "PSW after __cpu_init()" );
/* Verify access to the complete 512 KiB register file. */
__cpu_registers[0] = 0x5a;
__cpu_registers[CPU_REGISTERS_MEM_SIZE_IN_UNITS - 1] = 0xa5;
CHECK( __cpu_registers[0] == 0x5a, "register file first byte" );
CHECK( __cpu_registers[CPU_REGISTERS_MEM_SIZE_IN_UNITS - 1] == 0xa5,
"register file last byte" );
/* Low PSW bits are maintained by LibMPU. */
__mpu_stc();
__mpu_stz();
__mpu_stinx();
psw = __cpu_get_psw();
CHECK( (psw & PSW_CF_MASK) != 0, "PSW reads LibMPU CF" );
CHECK( (psw & PSW_ZF_MASK) != 0, "PSW reads LibMPU ZF" );
CHECK( (psw & PSW_INXF_MASK) != 0, "PSW reads LibMPU INXF" );
/* High PSW bits belong to LibCPU. */
__cpu_sth();
__cpu_stt();
__cpu_sti();
CHECK( __cpu_stmode( 2 ) == 0, "set CPU MODE" );
psw = __cpu_get_psw();
CHECK( (psw & PSW_HF_MASK) != 0, "PSW HF" );
CHECK( (psw & PSW_TF_MASK) != 0, "PSW TF" );
CHECK( (psw & PSW_IF_MASK) != 0, "PSW IF" );
CHECK( __cpu_gtmode() == 2, "PSW MODE" );
/* CPU flag operations do not alter the LibMPU half of PSW. */
__cpu_clh();
__cpu_cmt();
__cpu_cmi();
psw = __cpu_get_psw();
CHECK( (psw & PSW_HF_MASK) == 0, "clear HF" );
CHECK( (psw & PSW_TF_MASK) == 0, "complement TF" );
CHECK( (psw & PSW_IF_MASK) == 0, "complement IF" );
CHECK( (psw & PSW_CF_MASK) != 0, "CF preserved by CPU flags" );
CHECK( (psw & PSW_ZF_MASK) != 0, "ZF preserved by CPU flags" );
CHECK( (psw & PSW_INXF_MASK) != 0, "INXF preserved by CPU flags" );
/* Store/restore the complete logical PSW. */
__cpu_set_psw( PSW_AF_MASK | PSW_OF_MASK | PSW_DOMF_MASK |
PSW_HF_MASK | PSW_IF_MASK |
((__mpu_uint32_t)3 << PSW_MODE_SHIFT) );
psw = __cpu_get_psw();
CHECK( psw == (PSW_AF_MASK | PSW_OF_MASK | PSW_DOMF_MASK |
PSW_HF_MASK | PSW_IF_MASK |
((__mpu_uint32_t)3 << PSW_MODE_SHIFT)),
"complete PSW store/restore" );
CHECK( __mpu_gta() == 1, "LibMPU AF after __cpu_set_psw()" );
CHECK( __mpu_gto() == 1, "LibMPU OF after __cpu_set_psw()" );
CHECK( __mpu_gtdom() == 1, "LibMPU DOMF after __cpu_set_psw()" );
CHECK( __mpu_gtc() == 0, "LibMPU CF cleared by __cpu_set_psw()" );
CHECK( __cpu_gth() == 1, "LibCPU HF after __cpu_set_psw()" );
CHECK( __cpu_gti() == 1, "LibCPU IF after __cpu_set_psw()" );
CHECK( __cpu_gtmode() == 3, "LibCPU MODE after __cpu_set_psw()" );
__cpu_clear_psw();
CHECK( __cpu_get_psw() == 0, "clear complete PSW" );
__cpu_pc = 0x123456789abcdef0ULL;
__cpu_sp = 0x0fedcba987654321ULL;
__cpu_fp = 0x0123456789abcdefULL;
CHECK( __cpu_pc == 0x123456789abcdef0ULL, "PC access" );
CHECK( __cpu_sp == 0x0fedcba987654321ULL, "SP access" );
CHECK( __cpu_fp == 0x0123456789abcdefULL, "FP access" );
__cpu_free_context();
CHECK( __cpu_pc == 0, "PC after __cpu_free_context()" );
CHECK( __cpu_sp == 0, "SP after __cpu_free_context()" );
CHECK( __cpu_fp == 0, "FP after __cpu_free_context()" );
CHECK( __cpu_get_psw() == 0, "PSW after __cpu_free_context()" );
if( failures != 0 )
{
fprintf( stderr, "libcpu context regression: %d failure(s)\n", failures );
return( 1 );
}
printf( "libcpu context/PSW regression: PASS\n" );
printf( "register file: %u bytes\n", CPU_REGISTERS_MEM_SIZE_IN_UNITS );
printf( "PSW: LibMPU bits 0..15, LibCPU bits 16..20\n" );
return( 0 );
}
|