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

Subversion Repositories openarty

[/] [openarty/] [trunk/] [sw/] [board/] [cputest.c] - Blame information for rev 41

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

Line No. Rev Author Line
1 41 dgisselq
///////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    cputest.c
4
//
5
// Project:     Zip CPU -- a small, lightweight, RISC CPU soft core
6
//
7
// Purpose:     To test the CPU, it's instructions, cache, and pipeline, to make
8
//              certain that it works.  This includes testing that each of the
9
//      instructions works, as well as any strange instruction combinations.
10
//
11
//
12
// Creator:     Dan Gisselquist, Ph.D.
13
//              Gisselquist Technology, LLC
14
//
15
///////////////////////////////////////////////////////////////////////////////
16
//
17
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
18
//
19
// This program is free software (firmware): you can redistribute it and/or
20
// modify it under the terms of  the GNU General Public License as published
21
// by the Free Software Foundation, either version 3 of the License, or (at
22
// your option) any later version.
23
//
24
// This program is distributed in the hope that it will be useful, but WITHOUT
25
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
26
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
27
// for more details.
28
//
29
// License:     GPL, v3, as defined and found on www.gnu.org,
30
//              http://www.gnu.org/licenses/gpl.html
31
//
32
//
33
///////////////////////////////////////////////////////////////////////////////
34
//
35
//
36
#include "zipsys.h"
37
#include "artyboard.h"
38
 
39
#ifndef NULL
40
#define NULL    (void *)0
41
#endif
42
 
43
static volatile int     *const UARTTX = &((IOSPACE *)0x0100)->io_uart_tx,
44
                        *const UART_CTRL = &((IOSPACE *)0x0100)->io_auxsetup;
45
static volatile int * const PIC = (volatile int *)0xc0000000;
46
static const int        INT_UARTTX = SYSINT_UARTTX; // 0x2000;
47
static volatile int     *const COUNTER = &((ZIPSYS *)ZIPSYS_ADDR)->m.ck;
48
 
49
#define HAVE_COUNTER
50
#define HAVE_SCOPE
51
#define SCOPEc  sys->io_scope[0].s_ctrl
52
#define SCOPE_DELAY             4
53
#define TRIGGER_SCOPE_NOW       (SCOPE_TRIGGER|SCOPE_DELAY)
54
#define PREPARE_SCOPE           SCOPE_DELAY
55
 
56
unsigned        zip_ucc(void);
57
void            zip_save_context(int *);
58
void            zip_halt(void);
59
 
60
 
61
void    txchr(char v);
62
void    txstr(const char *str);
63
void    txhex(int num);
64
void    tx4hex(int num);
65
 
66
 
67
asm("\t.section\t.start\n"
68
        "\t.global\t_start\n"
69
        "\t.type\t_start,@function\n"
70
"_start:\n"
71
        "\tCLR\tR0\n"
72
        "\tCLR\tR1\n"
73
        "\tCLR\tR2\n"
74
        "\tCLR\tR3\n"
75
        "\tCLR\tR4\n"
76
        "\tCLR\tR5\n"
77
        "\tCLR\tR6\n"
78
        "\tCLR\tR7\n"
79
        "\tCLR\tR8\n"
80
        "\tCLR\tR9\n"
81
        "\tCLR\tR10\n"
82
        "\tCLR\tR11\n"
83
        "\tCLR\tR12\n"
84
        "\tLDI\t_top_of_stack,SP\n"
85
        "\tCLR\tCC\n"
86
        "\tMOV\tbusy_failure(PC),R0\n"
87
        "\tBRA\tentry\n"
88
"busy_failure:\n"
89
        "\tBUSY\n"
90
        "\t.section\t.text");
91
 
92
#ifdef  HAVE_COUNTER
93
#define MARKSTART       start_time = *COUNTER
94
#define MARKSTOP        stop_time  = *COUNTER
95
#else
96
#ifdef  HAVE_TIMER
97
#define MARKSTART       start_time = *TIMER
98
#define MARKSTOP        stop_time  = *TIMER
99
#else
100
#define MARKSTART
101
#define MARKSTOP
102
#endif
103
#endif
104
 
105
 
106
extern  int     run_test(void *pc, void *stack);
107
asm("\t.text\n\t.global\trun_test\n"
108
        "\t.type\trun_test,@function\n"
109
"run_test:\n"
110
        "\tCLR\tR3\n"
111
        "\tMOV\ttest_return(PC),uR0\n"
112
        "\tMOV\tR3,uR1\n"
113
        "\tMOV\tR3,uR2\n"
114
        "\tMOV\tR3,uR3\n"
115
        "\tMOV\tR3,uR4\n"
116
        "\tMOV\tR3,uR5\n"
117
        "\tMOV\tR3,uR6\n"
118
        "\tMOV\tR3,uR7\n"
119
        "\tMOV\tR3,uR8\n"
120
        "\tMOV\tR3,uR9\n"
121
        "\tMOV\tR3,uR10\n"
122
        "\tMOV\tR3,uR11\n"      // uR11 = pc
123
        "\tMOV\tR3,uR12\n"      // uR12 = pc
124
        "\tMOV\tR2,uSP\n"       // uSP = stack
125
        "\tMOV\t0x20+R3,uCC\n"  // Clear uCC of all but the GIE bit
126
        "\tMOV\tR1,uPC\n"       // uPC = pc
127
        "\tRTU\n"
128
"test_return:\n"
129
        "\tMOV\tuR1,R1\n"
130
        "\tAND\t0xffffffdf,CC\n"
131
        // Works with 5 NOOPS, works with 3 NOOPS, works with 1 NOOP
132
        "\tJMP\tR0\n");
133
 
134
extern  int     idle_test(void);
135
asm("\t.text\n\t.global\tidle_test\n"
136
        "\t.type\tidle_test,@function\n"
137
"idle_test:\n"
138
        "\tCLR\tR1\n"
139
        "\tMOV\tidle_loop(PC),uR0\n"
140
        "\tMOV\tR1,uR1\n"
141
        "\tMOV\tR1,uR2\n"
142
        "\tMOV\tR1,uR3\n"
143
        "\tMOV\tR1,uR4\n"
144
        "\tMOV\tR1,uR5\n"
145
        "\tMOV\tR1,uR6\n"
146
        "\tMOV\tR1,uR7\n"
147
        "\tMOV\tR1,uR8\n"
148
        "\tMOV\tR1,uR9\n"
149
        "\tMOV\tR1,uR10\n"
150
        "\tMOV\tR1,uR11\n"
151
        "\tMOV\tR1,uR12\n"
152
        "\tMOV\tR1,uSP\n"
153
        "\tMOV\t0x20+R1,uCC\n"
154
        "\tMOV\tidle_loop(PC),uPC\n"
155
        "\tWAIT\n"
156
        "\tMOV uPC,R1\n"
157
        "\tCMP idle_loop(PC),R1\n"
158
        "\tLDI   0,R1\n"
159
        "\tLDI.NZ 1,R1\n"
160
        "\nRETN\n"
161
"idle_loop:\n"
162
        "\tWAIT\n"
163
        "\tBRA idle_loop\n");
164
 
165
void    break_one(void);
166
asm("\t.text\n\t.global\tbreak_one\n"
167
        "\t.type\tbreak_one,@function\n"
168
"break_one:\n"
169
        "\tLDI\t0,R1\n"
170
        "\tBREAK\n"
171
        "\tLDI\t1,R1\n" // Test fails
172
        "\tJMP\tR0");
173
 
174
void    break_two(void);
175
        // Can we stop a break before we hit it?
176
asm("\t.text\n\t.global\tbreak_two\n"
177
        "\t.type\tbreak_two,@function\n"
178
"break_two:\n"
179
        "\tLDI\t0,R1\n"
180
        "\tJMP\tR0\n"
181
        "\tBREAK\n");
182
 
183
void    early_branch_test(void);
184
asm("\t.text\n\t.global\tearly_branch_test\n"
185
        "\t.type\tearly_branch_test,@function\n"
186
"early_branch_test:\n"
187
        "\tLDI\t1,R1\n"
188
        "\tBRA\t_eb_a\n"
189
        "\tBREAK\n"
190
"_eb_a:\n"
191
        "\tLDI\t2,R1\n"
192
        "\tBRA\t_eb_b\n"
193
        "\tNOP\n"
194
        "\tBREAK\n"
195
"_eb_b:\n"
196
        "\tLDI\t3,R1\n"
197
        "\tBRA\t_eb_c\n"
198
        "\tNOP\n"
199
        "\tNOP\n"
200
        "\tBREAK\n"
201
"_eb_c:\n"
202
        "\tLDI\t4,R1\n"
203
        "\tBRA\t_eb_d\n"
204
        "\tNOP\n"
205
        "\tNOP\n"
206
        "\tNOP\n"
207
        "\tBREAK\n"
208
"_eb_d:\n"
209
        "\tLDI\t5,R1\n"
210
        "\tBRA\t_eb_e\n"
211
        "\tNOP\n"
212
        "\tNOP\n"
213
        "\tNOP\n"
214
        "\tNOP\n"
215
        "\tBREAK\n"
216
"_eb_e:\n"
217
        "\tLDI\t6,R1\n"
218
        "\tBRA\t_eb_f\n"
219
        "\tNOP\n"
220
        "\tNOP\n"
221
        "\tNOP\n"
222
        "\tNOP\n"
223
        "\tNOP\n"
224
        "\tBREAK\n"
225
"_eb_f:\n"
226
        "\tLDI\t0,R1\n"
227
        "\tJMP\tR0");
228
 
229
void    trap_test_and(void);
230
asm("\t.text\n\t.global\ttrap_test_and\n"
231
        "\t.type\ttrap_test_and,@function\n"
232
"trap_test_and:\n"
233
        "\tLDI\t0,R1\n"
234
        "\tAND\t0xffffffdf,CC\n"
235
        "\tLDI\t1,R1\n" // Test fails
236
        "\tJMP\tR0");
237
 
238
void    trap_test_clr(void);
239
asm("\t.text\n\t.global\ttrap_test_clr\n"
240
        "\t.type\ttrap_test_clr,@function\n"
241
"trap_test_clr:\n"
242
        "\tLDI\t0,R1\n"
243
        "\tCLR\tCC\n"
244
        "\tLDI\t1,R1\n" // Test fails
245
        "\tJMP\tR0");
246
 
247
void    overflow_test(void);
248
asm("\t.text\n\t.global\toverflow_test\n"
249
        "\t.type\toverflow_test,@function\n"
250
"overflow_test:\n"
251
        "\tLDI\t0,R1\n"
252
        "\tLDI\t0,R3\n"         // Clear our scorecard
253
// First test: does adding one to the maximum integer cause an overflow?
254
        "\tLDI\t-1,R2\n"
255
        "\tLSR\t1,R2\n"
256
        "\tADD\t1,R2\n"
257
        "\tOR.V\t1,R3\n"
258
// Second test: does subtracting one to the minimum integer cause an overflow?
259
        "\tLDI\t0x80000000,R2\n"
260
        "\tSUB\t1,R2\n"
261
        "\tOR.V\t2,R3\n"
262
// Third test, overflow from LSR
263
        "\tLDI\t0x80000000,R2\n"
264
        "\tLSR\t1,R2\n"         // Overflows 'cause the sign changes
265
        "\tOR.V\t4,R3\n"
266
// Fourth test, overflow from LSL
267
        "\tLDI\t0x40000000,R2\n"
268
        "\tLSL\t1,R2\n"
269
        "\tOR.V\t8,R3\n"
270
// Fifth test, overflow from LSL, negative to positive
271
        "\tLDI\t0x80000000,R2\n"
272
        "\tLSL\t1,R2\n"
273
        "\tOR.V\t16,R3\n"
274
// Record our scores
275
        "\tXOR\t31,R3\n"
276
        "\tOR\tR3,R1\n"
277
// And return the results
278
        "\tJMP\tR0");
279
 
280
 
281
void    carry_test(void);
282
asm("\t.text\n\t.global\tcarry_test\n"
283
        "\t.type\tcarry_test,@function\n"
284
"carry_test:\n"
285
        "\tLDI\t0,R1\n"
286
        "\tLDI\t0,R3\n"
287
// First, in adding
288
        "\tLDI\t-1,R2\n"
289
        "\tADD\t1,R2\n"
290
        "\tOR.C\t1,R3\n"
291
// Then, in subtraction
292
        "\tSUB\t1,R2\n"
293
        "\tOR.C\t2,R3\n"
294
// From a right shift
295
        "\tLDI\t1,R2\n"
296
        "\tLSR\t1,R2\n"
297
        "\tOR.C\t4,R3\n"
298
        "\tLDI\t1,R2\n"
299
        "\tASR\t1,R2\n"
300
        "\tOR.C\t8,R3\n"
301
// Or from a compare
302
        "\tLDI\t0,R2\n"
303
        "\tCMP\t1,R2\n"
304
        "\tOR.C\t16,R3\n"
305
// Set our return and clean up
306
        "\tXOR\t31,R3\n"
307
        "\tOR\tR3,R1\n"
308
        "\tJMP\tR0");
309
 
310
void    loop_test(void);
311
asm("\t.text\n\t.global\tloop_test\n"
312
        "\t.type\tloop_test,@function\n"
313
"loop_test:\n"
314
        "\tLDI\t0,R1\n"
315
// Let's try a loop: for(i=0; i<5; i++)
316
        "\tLDI\t0,R2\n"
317
        "\tLDI\t0,R3\n"
318
        "\tCMP\t5,R2\n"
319
        "\tBGE\tend_for_loop_test\n"
320
"for_loop_test:"
321
        "\tADD\t1,R2\n"
322
        "\tADD\t1,R3\n"
323
        "\tCMP\t5,R2\n"
324
        "\tBLT\tfor_loop_test\n"
325
"end_for_loop_test:"
326
        "\tCMP\t5,R3\n"
327
        "\tOR.NZ\t1,R1\n"
328
// How about a reverse do{} while loop?  These are usually cheaper than for()
329
// loops.
330
        "\tLDI\t0,R2\n"
331
        "\tLDI\t5,R3\n"
332
"bgt_loop_test:\n"
333
        "\tADD\t1,R2\n"
334
        "\tSUB\t1,R3\n"
335
        "\tBGT\tbgt_loop_test\n"
336
        "\tCMP\t5,R2\n"
337
        "\tOR.NZ\t2,R1\n"
338
// What if we use >=?
339
        "\tLDI\t0,R2\n"
340
        "\tLDI\t5,R3\n"
341
"bge_loop_test:\n"
342
        "\tADD\t1,R2\n"
343
        "\tSUB\t1,R3\n"
344
        "\tBGE\tbge_loop_test\n"
345
        "\tCMP\t6,R2\n"
346
        "\tOR.NZ\t4,R1\n"
347
// Once more with the reverse loop, this time storing the loop variable in
348
// memory
349
        "\tSUB\t1,SP\n"
350
        "\tLDI\t0,R2\n"
351
        "\tLDI\t5,R3\n"
352
        "\tSTO\tR3,(SP)\n"
353
"mem_loop_test:\n"
354
        "\tADD\t1,R2\n"
355
        "\tADD\t14,R3\n"
356
        "\tLOD\t(SP),R3\n"
357
        "\tSUB\t1,R3\n"
358
        "\tSTO\tR3,(SP)\n"
359
        "\tBGT\tmem_loop_test\n"
360
        "\tCMP\t5,R2\n"
361
        "\tOR.NZ\t8,R1\n"
362
        "\tADD\t1,SP\n"
363
//
364
        "\tJMP\tR0\n");
365
 
366
// Test whether or not LSL, LSR, and ASR instructions work, together with their
367
// carry flags
368
void    shift_test(void);
369
asm("\t.text\n\t.global\tshift_test\n"
370
        "\t.type\tshift_test,@function\n"
371
"shift_test:\n"
372
        "\tLDI\t0,R1\n"
373
        "\tLDI\t0,R3\n"
374
        "\tLDI\t0,R4\n"
375
// Does shifting right by 32 result in a zero?
376
        "\tLDI\t-1,R2\n"
377
        "\tLSR\t32,R2\n"
378
        "\tOR.Z\t1,R3\n"
379
        "\tOR.C\t2,R3\n"
380
        "\tCMP\t0,R2\n"
381
        "\tOR.Z\t4,R3\n"
382
// Does shifting a -1 right arithmetically by 32 result in a -1?
383
        "\tLDI\t-1,R2\n"
384
        "\tASR\t32,R2\n"
385
        "\tOR.LT\t8,R3\n"
386
        "\tOR.C\t16,R3\n"
387
        "\tCMP\t-1,R2\n"
388
        "\tOR.Z\t32,R3\n"
389
// Does shifting a -4 right arithmetically by 2 result in a -1?
390
        "\tLDI\t-4,R2\n"
391
        "\tASR\t2,R2\n"
392
        "\tOR.LT\t64,R3\n"
393
        "\tOR.C\t128,R1\n"
394
        "\tOR\t128,R3\n" // Artificially declare passing, so as not to fail it
395
        "\tCMP\t-1,R2\n"
396
        "\tOR.Z\t256,R3\n"
397
// Does one more set the carry flag as desired?
398
        "\tASR\t1,R2\n"
399
        "\tOR.LT\t512,R3\n"
400
        "\tOR.C\t1024,R3\n"
401
        "\tCMP\t-1,R2\n"
402
        "\tOR.Z\t2048,R3\n"
403
// Does shifting -1 left by 32 result in a zero?
404
        "\tLDI\t-1,R2\n"
405
        "\tLSL\t32,R2\n"
406
        "\tOR.Z\t4096,R3\n"
407
        "\tOR.C\t8192,R3\n"
408
        "\tCMP\t0,R2\n"
409
        "\tOR.Z\t16384,R3\n"
410
// How about shifting by zero?
411
        "\tLDI\t-1,R2\n"
412
        "\tASR\t0,R2\n"
413
        "\tOR.C\t32768,R1\n"
414
        "\tOR\t32768,R3\n"
415
        "\tCMP\t-1,R2\n"
416
        "\tOR.Z\t1,R4\n"
417
// 
418
        "\tLSR\t0,R2\n"
419
        "\tOR.C\t131072,R1\n"
420
        "\tCMP\t-1,R2\n"
421
        "\tOR.Z\t2,R4\n"
422
//
423
        "\tLSL\t0,R2\n"
424
        "\tOR.C\t524288,R1\n"
425
        "\tCMP\t-1,R2\n"
426
        "\tOR.Z\t4,R4\n"
427
// Tally up our results and return
428
        "\tXOR\t7,R4\n"
429
        "\tXOR\t65535,R3\n"
430
        "\tLSL\t16,R4\n"
431
        "\tOR\tR4,R3\n"
432
        "\tOR\tR3,R1\n"
433
        "\tJMP\tR0");
434
 
435
int     sw_brev(int v);
436
asm("\t.text\n\t.global\tsw_brev\n"
437
        "\t.type\tsw_brev,@function\n"
438
"sw_brev:\n"
439
        "\tSUB\t2,SP\n"
440
        "\tSTO\tR2,(SP)\n"
441
        "\tSTO\tR3,1(SP)\n"
442
        "\tLDI\t-1,R2\n"
443
        "\tCLR\tR3\n"
444
"sw_brev_loop:\n"
445
        "\tLSL\t1,R3\n"
446
        "\tLSR\t1,R1\n"
447
        "\tOR.C\t1,R3\n"
448
        "\tLSR\t1,R2\n"
449
        "\tBZ\tsw_brev_endloop\n"
450
        "\tBRA\tsw_brev_loop\n"
451
"sw_brev_endloop:\n"
452
        "\tMOV\tR3,R1\n"
453
        "\tLOD\t(SP),R2\n"
454
        "\tLOD\t1(SP),R3\n"
455
        "\tADD\t2,SP\n"
456
        "\tJMP\tR0");
457
 
458
void    pipeline_stack_test(void);
459
asm("\t.text\n\t.global\tpipeline_stack_test\n"
460
        "\t.type\tpipeline_stack_test,@function\n"
461
"pipeline_stack_test:\n"
462
        "\tSUB\t1,SP\n"
463
        "\tSTO\tR0,(SP)\n"
464
        "\tLDI\t0,R0\n"
465
        "\tMOV\t1(R0),R1\n"
466
        "\tMOV\t1(R1),R2\n"
467
        "\tMOV\t1(R2),R3\n"
468
        "\tMOV\t1(R3),R4\n"
469
        "\tMOV\t1(R4),R5\n"
470
        "\tMOV\t1(R5),R6\n"
471
        "\tMOV\t1(R6),R7\n"
472
        "\tMOV\t1(R7),R8\n"
473
        "\tMOV\t1(R8),R9\n"
474
        "\tMOV\t1(R9),R10\n"
475
        "\tMOV\t1(R10),R11\n"
476
        "\tMOV\t1(R11),R12\n"
477
        "\tMOV\tpipeline_stack_test_component_return(PC),R0\n"
478
        // "\tLJMP\tpipeline_stack_test_component\n"
479
        "\tBRA\tpipeline_stack_test_component\n"
480
"pipeline_stack_test_component_return:\n"
481
        "\tCMP\t1,R1\n"
482
        "\tLDI.Z\t0,R1\n"
483
        "\tCMP\t2,R2\n"
484
        "\tCMP.Z\t3,R3\n"
485
        "\tCMP.Z\t4,R4\n"
486
        "\tCMP.Z\t5,R5\n"
487
        "\tCMP.Z\t6,R6\n"
488
        "\tCMP.Z\t7,R7\n"
489
        "\tCMP.Z\t8,R8\n"
490
        "\tCMP.Z\t9,R9\n"
491
        "\tCMP.Z\t10,R10\n"
492
        "\tCMP.Z\t11,R11\n"
493
        "\tCMP.Z\t12,R12\n"
494
        "\tBREV.NZ\t-1,R1\n"
495
        "\tLOD\t(SP),R0\n"
496
        "\tADD\t1,SP\n"
497
        "\tJMP\tR0\n"
498
        );
499
 
500
void    pipeline_stack_test_component(void);
501
asm("\t.text\n\t.global\tpipeline_stack_test_component\n"
502
        "\t.type\tpipeline_stack_test_component,@function\n"
503
"pipeline_stack_test_component:\n"
504
        "\tSUB\t13,SP\n"
505
        "\tSTO\tR0,(SP)\n"
506
        "\tSTO\tR1,1(SP)\n"
507
        "\tSTO\tR2,2(SP)\n"
508
        "\tSTO\tR3,3(SP)\n"
509
        "\tSTO\tR4,4(SP)\n"
510
        "\tSTO\tR5,5(SP)\n"
511
        "\tSTO\tR6,6(SP)\n"
512
        "\tSTO\tR7,7(SP)\n"
513
        "\tSTO\tR8,8(SP)\n"
514
        "\tSTO\tR9,9(SP)\n"
515
        "\tSTO\tR10,10(SP)\n"
516
        "\tSTO\tR11,11(SP)\n"
517
        "\tSTO\tR12,12(SP)\n"
518
        "\tXOR\t-1,R0\n"
519
        "\tXOR\t-1,R1\n"
520
        "\tXOR\t-1,R2\n"
521
        "\tXOR\t-1,R3\n"
522
        "\tXOR\t-1,R4\n"
523
        "\tXOR\t-1,R5\n"
524
        "\tXOR\t-1,R6\n"
525
        "\tXOR\t-1,R7\n"
526
        "\tXOR\t-1,R8\n"
527
        "\tXOR\t-1,R9\n"
528
        "\tXOR\t-1,R10\n"
529
        "\tXOR\t-1,R11\n"
530
        "\tXOR\t-1,R12\n"
531
        "\tLOD\t(SP),R0\n"
532
        "\tLOD\t1(SP),R1\n"
533
        "\tLOD\t2(SP),R2\n"
534
        "\tLOD\t3(SP),R3\n"
535
        "\tLOD\t4(SP),R4\n"
536
        "\tLOD\t5(SP),R5\n"
537
        "\tLOD\t6(SP),R6\n"
538
        "\tLOD\t7(SP),R7\n"
539
        "\tLOD\t8(SP),R8\n"
540
        "\tLOD\t9(SP),R9\n"
541
        "\tLOD\t10(SP),R10\n"
542
        "\tLOD\t11(SP),R11\n"
543
        "\tLOD\t12(SP),R12\n"
544
        "\tADD\t13,SP\n"
545
        "\tJMP\tR0\n");
546
 
547
//mpy_test
548
void    mpy_test(void);
549
asm("\t.text\n\t.global\tmpy_test\n"
550
        "\t.type\tmpy_test,@function\n"
551
"mpy_test:\n"
552
        "\tCLR\tR1\n"
553
        // First test: let's count multiples of 137
554
        "\tLDI\t137,R2\n"       // What we're doing multiples of
555
        "\tCLR\tR3\n"           // Our accumulator via addition
556
        "\tCLR\tR4\n"           // Our index for multiplication
557
        "mpy_137_test_loop:\n"
558
        "\tMOV\tR2,R5\n"
559
        "\tMPY\tR4,R5\n"
560
        "\tCMP\tR3,R5\n"
561
        "\tBNZ\tend_mpy_137_test_loop_failed\n"
562
        // Let's try negative while we are at it
563
        "\tMOV\tR2,R6\n"
564
        "\tNEG\tR6\n"
565
        "\tMPY\tR4,R6\n"
566
        "\tNEG\tR6\n"
567
        "\tCMP\tR3,R6\n"
568
        "\tBNZ\tend_mpy_137_test_loop_failed\n"
569
        "\tCLR\tR6\n"
570
        "\tTEST\t0xffff0000,R3\n"
571
        "\tBNZ\tend_mpy_137_test_loop\n"
572
        "\tADD\tR2,R3\n"
573
        "\tADD\t1,R4\n"
574
        "\tBRA\tmpy_137_test_loop\n"
575
"end_mpy_137_test_loop_failed:\n"
576
        "\tOR\t1,R1\n"
577
"end_mpy_137_test_loop:\n"
578
        // Second test ... whatever that might be
579
        "\tJMP\tR0\n");
580
 
581
unsigned        soft_mpyuhi(unsigned, unsigned);
582
int             soft_mpyshi(int,int);
583
 
584
unsigned        hard_mpyuhi(unsigned, unsigned);
585
asm("\t.text\n\t.global\thard_mpyuhi\n"
586
        "\t.type\thard_mpyuhi,@function\n"
587
"hard_mpyuhi:\n"
588
        "\tNOOP\n"
589
        "\tNOOP\n"
590
        "\tMPYUHI\tR2,R1\n"
591
        "\tRETN\n");
592
 
593
int     hard_mpyshi(int, int);
594
asm("\t.text\n\t.global\thard_mpyshi\n"
595
        "\t.type\thard_mpyshi,@function\n"
596
"hard_mpyshi:\n"
597
        "\tMPYSHI\tR2,R1\n"
598
        "\tRETN\n");
599
 
600
void    debugmpy(char *str, int a, int b, int s, int r) {
601
#ifdef  HAVE_SCOPE
602
        // Trigger the scope, if it hasn't been triggered yet
603
        // but ... dont reset it if it has been.
604
        SCOPEc = TRIGGER_SCOPE_NOW;
605
#endif
606
        txstr("\r\n"); txstr(str); txhex(a);
607
        txstr(" x "); txhex(b);
608
        txstr(" = "); txhex(s);
609
        txstr("(Soft) = "); txhex(r);
610
        txstr("(Hard)\r\n");
611
}
612
 
613
int     mpyhi_test(void) {
614
        int     a = 0xf97e27ab, b = 0;
615
 
616
        while(b<0x6fffffff) {
617
                int     r, sr;
618
 
619
                sr = soft_mpyuhi(a, b);
620
                r = hard_mpyuhi(a,b);
621
                if (r != sr) {
622
                        debugmpy("MPYUHI: ", a,b,sr,r);
623
                        return 1;
624
                }
625
 
626
                sr = soft_mpyshi(a, b);
627
                r = hard_mpyshi(a,b);
628
                if (r != sr) {
629
                        debugmpy("MPYSHI: ", a,b,sr,r);
630
                        return 2;
631
                }
632
 
633
                sr = soft_mpyshi(-a, b);
634
                r = hard_mpyshi(-a,b);
635
                if (r != sr) {
636
                        debugmpy("MPYSHI-NEG: ", -a,b,sr,r);
637
                        return 3;
638
                }
639
 
640
                b += 0x197e2*7;
641
        }
642
 
643
        return 0;
644
}
645
 
646
unsigned        soft_mpyuhi(unsigned a, unsigned b) {
647
        unsigned        alo, ahi, blo, bhi;
648
        unsigned        rhi, rlhi, rllo;
649
 
650
        alo = (a     & 0x0ffff);
651
        ahi = (a>>16)& 0x0ffff;
652
        blo = (b     & 0x0ffff);
653
        bhi = (b>>16)& 0x0ffff;
654
 
655
        rhi = 0;
656
        rlhi = 0;
657
        rllo = 0;
658
 
659
        for(int i=0; i<16; i++) {
660
                if (b&(1<<i)) {
661
                        unsigned slo, shi, sup;
662
                        slo = (alo << i);
663
                        shi = (ahi << i);
664
                        shi |= (slo>>16) & 0x0ffff;
665
                        slo &= 0x0ffff;
666
                        sup = (shi>>16)&0x0ffff;
667
                        shi &= 0x0ffff;
668
 
669
                        rhi  += sup;
670
                        rlhi += shi;
671
                        rllo += slo;
672
 
673
                        rlhi += (rllo >> 16)&0x0ffff;
674
                        rllo &= 0x0ffff;
675
 
676
                        rhi  += (rlhi >> 16)&0x0ffff;
677
                        rlhi &= 0x0ffff;
678
                }
679
        }
680
 
681
        for(int i=16; i<32; i++) {
682
                if (b&(1<<i)) {
683
                        unsigned slo, shi, sup;
684
                        slo = (alo << (i-16));
685
                        shi = (ahi << (i-16));
686
                        shi |= (slo>>16) & 0x0ffff;
687
                        slo &= 0x0ffff;
688
                        sup = (shi>>16)&0x0ffff;
689
                        shi &= 0x0ffff;
690
 
691
                        rhi  += sup << 16;
692
                        rhi  += shi;
693
                        rlhi += slo;
694
 
695
                        rhi  += (rlhi >> 16)&0x0ffff;
696
                        rlhi &= 0x0ffff;
697
                }
698
        }
699
 
700
        return rhi;
701
}
702
 
703
int     soft_mpyshi(int a, int b) {
704
        unsigned        sgn, r, p;
705
 
706
        sgn = ((a^b)>>31)&0x01;
707
 
708
        if (a<0) a = -a;
709
        if (b<0) b = -b;
710
 
711
        p = a * b;
712
 
713
        // This will only fail if the lower 32-bits of of a*b are 0,
714
        // at which point our following negation won't capture the carry it
715
        // needs.
716
        r = soft_mpyuhi(a, b);
717
 
718
        r = (sgn)?(r^-1):r;
719
        if ((sgn)&&(p==0))
720
                r += 1;
721
        return r;
722
}
723
 
724
//brev_test
725
//pipeline_test -- used to be called pipeline memory race conditions
726
void    pipeline_test(void);
727
asm("\t.text\n\t.global\tpipeline_test\n"
728
        "\t.type\tpipeline_test,@function\n"
729
"pipeline_test:\n"
730
        "\tSUB\t2,SP\n"
731
        // Test setup
732
        "\tLDI\t275,R2\n"
733
        "\tSTO\tR2,1(SP)\n"
734
        "\tMOV\t1(SP),R2\n"
735
        "\tSTO\tR2,(SP)\n"
736
        "\tCLR\tR2\n"
737
        //
738
        "\tMOV\tSP,R2\n"
739
        "\tLOD\t(R2),R2\n"
740
        "\tLOD\t(R2),R2\n"
741
        "\tCMP\t275,R2\n"
742
        "\tOR.NZ\t1,R1\n"
743
        //
744
        "\tMOV\tSP,R2\n"
745
        // Here's the test sequence
746
        "\tLOD\t(R2),R3\n"
747
        "\tLOD\t1(R2),R4\n"
748
        "\tSTO\tR4,1(R3)\n"
749
        // Make sure we clear the load pipeline
750
        "\tLOD\t(R2),R3\n"
751
        // Load our written value
752
        "\tLOD\t2(R2),R4\n"
753
        "\tCMP\t275,R4\n"
754
        "\tOR.NZ\t2,R1\n"
755
        //
756
        //
757
        // Next (once upon a time) failing sequence:
758
        //      LOD -x(R12),R0
759
        //      LOD y(R0),R0
760
        "\tMOV\tSP,R2\n"
761
        "\tMOV\t1(R2),R3\n"
762
        "\tSTO\tR3,1(R2)\n"
763
        "\tLDI\t3588,R4\n"      // Just some random value
764
        "\tSTO\tR4,2(R2)\n"
765
        "\tMOV\tR2,R3\n"
766
        // Here's the test sequence
767
        "\tLOD\t(R2),R3\n"
768
        "\tLOD\t1(R3),R3\n"
769
        "\tCMP\tR4,R3\n"
770
        "\tOR.NZ\t4,R1\n"
771
        //
772
        "\tADD\t2,SP\n"
773
        "\tJMP\tR0\n");
774
 
775
//mempipe_test
776
void    mempipe_test(void);
777
asm("\t.text\n\t.global\tmempipe_test\n"
778
        "\t.type\tmempipe_test,@function\n"
779
"mempipe_test:\n"
780
        "\tSUB\t4,SP\n"
781
        "\tSTO\tR0,(SP)\n"
782
        "\tLDI\t0x1000,R11\n"
783
        // Test #1 ... Let's start by writing a value to memory
784
        "\tLDI\t-1,R2\n"
785
        "\tCLR\tR3\n"
786
        "\tSTO\tR2,2(SP)\n"
787
        "\tLOD\t2(SP),R3\n"
788
        "\tCMP\tR3,R2\n"
789
        "\tOR.NZ\t1,R1\n"
790
        // Test #2, reading and then writing a value from memory
791
        "\tNOOP\n"
792
        "\tNOOP\n"
793
        "\tCLR\tR2\n"
794
        "\tCLR\tR3\n"
795
        "\tLOD\t2(SP),R2\n"     // This should load back up our -1 value
796
        "\tSTO\tR2,3(SP)\n"
797
        // Insist that the pipeline clear
798
        "\tLOD\t2(SP),R2\n"
799
        // Now let's try loading into R3
800
        "\tNOOP\n"
801
        "\tNOOP\n"
802
        "\tNOOP\n"
803
        "\tNOOP\n"
804
        "\tLOD\t3(SP),R3\n"
805
        "\tCMP\tR3,R2\n"
806
        "\tOR.NZ\t2,R1\n"
807
        //
808
        "\tLOD\t(SP),R0\n"
809
        "\tADD\t4,SP\n"
810
        "\tJMP\tR0\n");
811
 
812
//cexec_test
813
void    cexec_test(void);
814
asm("\t.text\n\t.global\tcexec_test\n"
815
        "\t.type\tcexec_test,@function\n"
816
"cexec_test:\n"
817
        "\tSUB\t1,SP\n"
818
        "\tSTO\tR0,(SP)\n"
819
        //
820
        "\tXOR\tR2,R2\n"
821
        "\tADD.Z\t1,R2\n"
822
        "\tADD.NZ\t1,R1\n"
823
        "\tCMP.Z\t0,R2\n"
824
        "\tOR.Z\t2,R1\n"
825
        //
826
        "\tLOD\t(SP),R0\n"
827
        "\tADD\t1,SP\n"
828
        "\tJMP\tR0\n");
829
 
830
// Pipeline stalls have been hideous problems for me.  The CPU has been modified
831
// with special logic to keep stages from stalling.  For the most part, this
832
// means that ALU and memory results may be accessed either before or as they
833
// are written to the register file.  This set of code is designed to test
834
// whether this bypass logic works.
835
//
836
//nowaitpipe_test
837
void    nowaitpipe_test(void);
838
asm("\t.text\n\t.global\tnowaitpipe_test\n"
839
        "\t.type\tnowaitpipe_test,@function\n"
840
"nowaitpipe_test:\n"
841
        "\tSUB\t2,SP\n"
842
        //
843
        // Let's start with ALU-ALU testing
844
        //      AA: result->input A
845
        "\tLDI\t-1,R2\n"
846
        "\tCLR\tR2\n"
847
        "\tADD\t1,R2\n"
848
        "\tCMP\t1,R2\n"
849
        "\tOR.NZ\t1,R1\n"
850
        //
851
        //      AA: result -> input B
852
        "\tCLR\tR2\n"
853
        "\tCLR\tR3\n"
854
        "\tADD\t1,R2\n"
855
        "\tCMP\tR2,R3\n"
856
        "\tOR.Z\t2,R1\n"
857
        //      AA: result -> input A on condition
858
        "\tXOR\tR2,R2\n"
859
        "\tADD.Z\t5,R2\n"
860
        "\tCMP\t5,R2\n"
861
        "\tOR.NZ\t4,R1\n"
862
        //      AA: result -> input B on condition
863
        "\tCLR\tR2\n"
864
        "\tXOR\tR3,R3\n"
865
        "\tADD.Z\t5,R2\n"
866
        "\tCMP\tR2,R3\n"
867
        "\tOR.Z\t8,R1\n"
868
        //      AA: result->input B plus offset
869
        "\tCLR\tR2\n"
870
        "\tXOR\tR3,R3\n"
871
        "\tADD\t5,R2\n"
872
        "\tCMP\t-5(R2),R3\n"
873
        "\tOR.NZ\t16,R1\n"
874
        //      AA: result->input B plus offset on condition
875
        "\tCLR\tR2\n"
876
        "\tXOR\tR3,R3\n"
877
        "\tADD.Z\t5,R2\n"
878
        "\tCMP\t-5(R2),R3\n"
879
        "\tOR.NZ\t32,R1\n"
880
        //
881
        // Then we need to do the ALU-MEM input testing
882
        //
883
        "\tCLR\tR2\n"
884
        "\tSTO\tR2,1(SP)\n"
885
        "\tLDI\t8352,R2\n"
886
        "\tLOD\t1(SP),R2\n"
887
        "\tTST\t-1,R2\n"
888
        "\tOR.NZ\t64,R1\n"
889
        // Let's try again, this time with something that's not zero
890
        "\tLDI\t937,R2\n"
891
        "\tSTO\tR2,1(SP)\n"
892
        "\tNOOP\n"
893
        "\tLOD\t1(SP),R2\n"
894
        "\tCMP\t938,R2\n"
895
        "\tOR.GE\t128,R1\n"
896
        "\tCMP\t936,R2\n"
897
        "\tOR.LT\t256,R1\n"
898
        // Mem output->ALU input testing
899
        //      Okay, we just did that as part of our last test
900
        // Mem output->mem input testing
901
        "\tLDI\t5328,R2\n"
902
        "\tLOD\t1(SP),R2\n"
903
        "\tSTO\tR2,1(SP)\n"
904
        "\tLOD\t1(SP),R3\n"
905
        "\tCMP\t937,R3\n"
906
        "\tOR.NZ\t512,R1\n"
907
        //
908
        "\tADD\t2,SP\n"
909
        "\tJMP\tR0\n");
910
 
911
//bcmem_test
912
void    bcmem_test(void);
913
asm("\t.text\n.global\tbcmem_test\n"
914
        "\t.type\tbcmem_test,@function\n"
915
"bcmem_test:\n"
916
        "\tSUB\t1,SP\n"
917
        "\tCLR\tR1\n"
918
        "\tCLR\tR2\n"
919
        "\tLDI\t-1,R3\n"
920
        "\tLDI\t0x13000,R4\n"
921
        "\tSTO\tR2,(SP)\n"
922
        "\tLOD\t(SP),R3\n"
923
        "\tCMP\tR2,R3\n"
924
        "\tOR.NZ\t1,R1\n"
925
        "\tCMP\t0x13000,R4\n"
926
        "\tBZ\tbcmem_test_cmploc_1\n"
927
        "\tSTO\tR4,(SP)\n"
928
"bcmem_test_cmploc_1:\n"
929
        "\tLOD\t(SP),R2\n"
930
        "\tCMP\tR2,R4\n"
931
        "\tOR.Z\t2,R1\n"
932
        "\tCLR\tR2\n"
933
        "\tCMP\tR2,R4\n"
934
        "\tBZ\tbcmem_test_cmploc_2\n"
935
        "\tSTO.NZ\tR4,(SP)\n"
936
"bcmem_test_cmploc_2:\n"
937
        "\tLOD\t(SP),R2\n"
938
        "\tCMP\tR2,R4\n"
939
        "\tOR.NZ\t4,R1\n"
940
//
941
        "\tADD\t1,SP\n"
942
        "\tJMP\tR0\n");
943
 
944
// The illegal instruction test.  Specifically, illegal instructions cannot be
945
// allowed to execute.  The PC must, upon completion, point to the illegal
946
// instruction that caused the exception.
947
//
948
// To create our illegal instruction, we assume that the only the three
949
// operations without arguments are NOOP, BREAK, LOCK, and so we envision a
950
// fourth instruction to create.
951
void    ill_test(void);
952
asm("\t.text\n.global\till_test\n"
953
        "\t.type\till_test,@function\n"
954
"ill_test:\n"
955
        "\t.word\t0x7ff00000\n"
956
        "\tJMP\tR0\n");
957
 
958
//
959
// The CC register has some ... unique requirements associated with it.
960
// Particularly, flags are unavailable until after an ALU operation completes,
961
// and they can't really be bypassed for the CC register.  After writeback,
962
// the "new" CC register isn't really available for another clock.  Trying to
963
// bypass this extra clock can have problems, since ... some bits are fixed,
964
// some bits can only be changed by the supervisor, and others can/will change
965
// and even have effects--like sending the CPU to supervisor mode or
966
// alternatively to sleep.
967
//
968
// Here, let's see if our pipeline can successfully navigate any of these
969
// issues.
970
//
971
void    ccreg_test(void);
972
asm("\t.text\n.global\tccreg_test\n"
973
        "\t.type\tccreg_test,@function\n"
974
"ccreg_test:\n"
975
        // First test: If we try to change the fixed bits, will they change
976
        // because the pipeline tries to bypass the write-back stage
977
        "\tCLR\tR1\n"   // We'll start with an "answer" of success
978
        "\tMOV\tCC,R2\n"
979
        "\tMOV\tR2,R4\n"        // Keep a copy
980
        "\tBREV\t0x0ff,R3\n"    // Attempt to change the top fixed bits
981
        "\tXOR\tR3,R2\n"        // Arrange for the changes
982
        "\tMOV\tR2,CC\n"        // Set the changes (they won't take)
983
        "\tMOV\tCC,R5\n"        // See if the pipeline makes them take
984
        "\tXOR\tR4,R5\n"        // Let's look for anything that has changed
985
        "\tOR.NZ\t1,R1\n"       // If anything has changed, then we fail the tst
986
        // 
987
        // Test #2: Can we set the flags?
988
        "\tMOV\tCC,R6\n"
989
        "\tOR\t15,R6\n"
990
        "\tMOV\tR6,CC\n"
991
        "\tMOV\tCC,R7\n"
992
        "\tAND\t15,R7\n"
993
        "\tCMP\t15,R7\n"
994
        "\tOR.NZ\t2,R1\n"
995
        //
996
        // Test #3: How about setting specific flags, and immediately acting
997
        // on them?
998
        "\tXOR\t1+R8,R8\n"      // Turn off the Z bit
999
        "\tOR\t1,CC\n"          // Turn on the Z bit
1000
        "\tOR.NZ\t4,R1\n"
1001
        //
1002
        // Test #4: Can we load the CC plus a value into a register?
1003
        //      I don't think so ...
1004
        "\tJMP\tR0\n");
1005
 
1006
// Multiple argument test
1007
__attribute__((noinline))
1008
int     multiarg_subroutine(int a, int b, int c, int d, int e, int f, int g) {
1009
        if (a!=0)        return 1;
1010
        if (b!=1)       return 2;
1011
        if (c!=2)       return 4;
1012
        if (d!=3)       return 8;
1013
        if (e!=4)       return 16;
1014
        if (f!=5)       return 32;
1015
        if (g!=6)       return 64;
1016
        return 0;
1017
}
1018
 
1019
int     multiarg_test(void) {
1020
        return multiarg_subroutine(0,1,2,3,4,5,6);
1021
}
1022
 
1023
__attribute__((noinline))
1024
void    wait(unsigned int msk) {
1025
        *PIC = 0x7fff0000|msk;
1026
        asm("MOV\tidle_task(PC),uPC\n");
1027
        *PIC = 0x80000000|(msk<<16);
1028
        asm("WAIT\n");
1029
        *PIC = 0; // Turn interrupts back off, lest they confuse the test
1030
}
1031
 
1032
asm("\n\t.text\nidle_task:\n\tWAIT\n\tBRA\tidle_task\n");
1033
 
1034
__attribute__((noinline))
1035
void    txchr(char v) {
1036
        if (zip_cc() & CC_GIE) {
1037
                while(*UARTTX & 0x100)
1038
                        ;
1039
        } else
1040
                wait(INT_UARTTX);
1041
        *UARTTX = v;
1042
}
1043
 
1044
__attribute__((noinline))
1045
void    txstr(const char *str) {
1046
        const char *ptr = str;
1047
        while(*ptr)
1048
                txchr(*ptr++);
1049
}
1050
 
1051
__attribute__((noinline))
1052
void    txhex(int num) {
1053
        for(int ds=28; ds>=0; ds-=4) {
1054
                int     ch;
1055
                ch = (num >> ds)&0x0f;
1056
                if (ch >= 10)
1057
                        ch = 'A'+ch-10;
1058
                else
1059
                        ch += '0';
1060
                txchr(ch);
1061
        }
1062
}
1063
 
1064
__attribute__((noinline))
1065
void    tx4hex(int num) {
1066
        if (num & 0xffff0000){
1067
                txhex(num);
1068
                return;
1069
        } for(int ds=12; ds>=0; ds-=4) {
1070
                int     ch;
1071
                ch = (num >> ds)&0x0f;
1072
                if (ch >= 10)
1073
                        ch = 'A'+ch-10;
1074
                else
1075
                        ch += '0';
1076
                txchr(ch);
1077
        }
1078
}
1079
 
1080
__attribute__((noinline))
1081
void    txreg(const char *name, int val) {
1082
        txstr(name);    // 4 characters
1083
        txstr("0x");    // 2 characters
1084
        txhex(val);     // 8 characters
1085
        txstr("    ");  // 4 characters
1086
}
1087
 
1088
__attribute__((noinline))
1089
void    save_context(int *context) {
1090
        zip_save_context(context);
1091
}
1092
 
1093
__attribute__((noinline))
1094
void    test_fails(int start_time, int *listno) {
1095
        int     context[16], stop_time;
1096
 
1097
        // Trigger the scope, if it hasn't already triggered.  Otherwise,
1098
        // if it has triggered, don't clear it.
1099
#ifdef  HAVE_SCOPE
1100
        SCOPEc = TRIGGER_SCOPE_NOW;
1101
#endif
1102
 
1103
        MARKSTOP;
1104
        save_context(context);
1105
        *listno++ = context[1];
1106
        *listno++ = context[14];
1107
        *listno++ = context[15];
1108
#ifdef  HAVE_COUNTER
1109
        *listno   = stop_time;
1110
#endif
1111
 
1112
        txstr("FAIL!\r\n\r\n");
1113
        txstr("Between 0x"); txhex(start_time);
1114
                txstr(" and 0x"); txhex(stop_time); txstr("\r\n\r\n");
1115
        txstr("Core-dump:\r\n");
1116
        txreg("uR0 : ", context[0]);
1117
        txreg("uR1 : ", context[1]);
1118
        txreg("uR2 : ", context[2]);
1119
        txreg("uR3 : ", context[3]);
1120
        txstr("\r\n");
1121
 
1122
        txreg("uR4 : ", context[4]);
1123
        txreg("uR5 : ", context[5]);
1124
        txreg("uR6 : ", context[6]);
1125
        txreg("uR7 : ", context[7]);
1126
        txstr("\r\n");
1127
 
1128
        txreg("uR8 : ", context[8]);
1129
        txreg("uR9 : ", context[9]);
1130
        txreg("uR10: ", context[10]);
1131
        txreg("uR11: ", context[11]);
1132
        txstr("\r\n");
1133
 
1134
        txreg("uR12: ", context[12]);
1135
        txreg("uSP : ", context[13]);
1136
        txreg("uCC : ", context[14]);
1137
        txreg("uPC : ", context[15]);
1138
        txstr("\r\n\r\n");
1139
 
1140
        while(1)
1141
                zip_halt();
1142
}
1143
 
1144
void    testid(const char *str) {
1145
        const int       WIDTH=32;
1146
        txstr(str);
1147
        const char *ptr = str;
1148
        int     i = 0;
1149
        while(0 != *ptr++)
1150
                i++;
1151
        i = WIDTH-i;
1152
        while(i-- > 0)
1153
                txchr(' ');
1154
}
1155
 
1156
int     testlist[32];
1157
 
1158
void entry(void) {
1159
        int     context[16];
1160
        int     user_stack[256], *user_stack_ptr = &user_stack[256];
1161
        int     start_time, i;
1162
 
1163
        for(i=0; i<32; i++)
1164
                testlist[i] = -1;
1165
 
1166
#ifdef  HAVE_TIMER
1167
        *TIMER = 0x7fffffff;
1168
#endif
1169
#ifdef  HAVE_COUNTER
1170
        *COUNTER = 0;
1171
#endif
1172
#ifdef  HAVE_SCOPE
1173
        SCOPEc = PREPARE_SCOPE;
1174
#endif
1175
 
1176
        // *UART_CTRL = 8333; // 9600 Baud, 8-bit chars, no parity, one stop bit
1177
        // *UART_CTRL = 25; // 9600 Baud, 8-bit chars, no parity, one stop bit
1178
        //
1179
 
1180
        txstr("\r\n");
1181
        txstr("Running CPU self-test\r\n");
1182
        txstr("-----------------------------------\r\n");
1183
 
1184
        int     tnum = 0;
1185
 
1186
        // Test break instruction in user mode
1187
        // Make sure the break works as designed
1188
        testid("Break test #1"); MARKSTART;
1189
 
1190
        if ((run_test(break_one, user_stack_ptr))||(zip_ucc()&0x1f50))
1191
                test_fails(start_time, &testlist[tnum]);
1192
 
1193
        save_context(context);
1194
        if ((context[15] != (int)break_one+1)||(0==(zip_ucc()&0x80)))
1195
                test_fails(start_time, &testlist[tnum]);
1196
        txstr("Pass\r\n"); testlist[tnum++] = 0; // 0
1197
 
1198
        // Test break instruction in user mode
1199
        // Make sure that a decision on the clock prior won't still cause a 
1200
        // break condition
1201
        testid("Break test #2"); MARKSTART;
1202
        if ((run_test(break_two, user_stack_ptr))||(zip_ucc()&0x1d90))
1203
                test_fails(start_time, &testlist[tnum]);
1204
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #1
1205
 
1206
        // LJMP test ... not (yet) written
1207
 
1208
        // Test the early branching capability
1209
        //      Does it successfully clear whatever else is in the pipeline?
1210
        testid("Early Branch test"); MARKSTART;
1211
        if ((run_test(early_branch_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1212
                test_fails(start_time, &testlist[tnum]);
1213
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #2
1214
 
1215
        // TRAP test
1216
        testid("Trap test/AND"); MARKSTART;
1217
        if ((run_test(trap_test_and, user_stack_ptr))||(zip_ucc()&0x01d90))
1218
                test_fails(start_time, &testlist[tnum]);
1219
        if ((zip_ucc() & 0x0200)==0)
1220
                test_fails(start_time, &testlist[tnum]);
1221
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #3
1222
 
1223
        testid("Trap test/CLR"); MARKSTART;
1224
        if ((run_test(trap_test_clr, user_stack_ptr))||(zip_ucc()&0x01d90))
1225
                test_fails(start_time, &testlist[tnum]);
1226
        if ((zip_ucc() & 0x0200)==0)
1227
                test_fails(start_time, &testlist[tnum]);
1228
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #4
1229
 
1230
        // Overflow test
1231
        testid("Overflow test"); MARKSTART;
1232
        if ((run_test(overflow_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1233
                test_fails(start_time, &testlist[tnum]);
1234
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #5
1235
 
1236
        // Carry test
1237
        testid("Carry test"); MARKSTART;
1238
        if ((run_test(carry_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1239
                test_fails(start_time, &testlist[tnum]);
1240
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #6
1241
 
1242
        // LOOP_TEST
1243
        testid("Loop test"); MARKSTART;
1244
        if ((run_test(loop_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1245
                test_fails(start_time, &testlist[tnum]);
1246
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #7 -- FAILS
1247
 
1248
        // SHIFT_TEST
1249
        testid("Shift test"); MARKSTART;
1250
        if ((run_test(shift_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1251
                test_fails(start_time, &testlist[tnum]);
1252
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #8
1253
 
1254
        // BREV_TEST
1255
        //testid("BREV/stack test"); MARKSTART;
1256
        //if ((run_test(brev_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1257
                //test_fails(start_time);
1258
        //txstr("Pass\r\n");
1259
 
1260
        // PIPELINE_TEST
1261
        testid("Pipeline test"); MARKSTART;
1262
        if ((run_test(pipeline_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1263
                test_fails(start_time, &testlist[tnum]);
1264
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #10
1265
 
1266
        // MEM_PIPELINE_STACK_TEST
1267
        testid("Mem-Pipeline test"); MARKSTART;
1268
        if ((run_test(mempipe_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1269
                test_fails(start_time, &testlist[tnum]);
1270
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #11
1271
 
1272
        // CONDITIONAL EXECUTION test
1273
        testid("Conditional Execution test"); MARKSTART;
1274
        if ((run_test(cexec_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1275
                test_fails(start_time, &testlist[tnum]);
1276
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #12 -- FAILS
1277
 
1278
        // NOWAIT pipeline test
1279
        testid("No-waiting pipeline test"); MARKSTART;
1280
        if ((run_test(nowaitpipe_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1281
                test_fails(start_time, &testlist[tnum]);
1282
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #13
1283
 
1284
        // BCMEM test
1285
        testid("Conditional Branching test"); MARKSTART;
1286
        if ((run_test(bcmem_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1287
                test_fails(start_time, &testlist[tnum]);
1288
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #14
1289
 
1290
        // Illegal Instruction test
1291
        testid("Ill Instruction test, NULL PC"); MARKSTART;
1292
        if ((run_test(NULL, user_stack_ptr))||((zip_ucc()^0x100)&0x01d90))
1293
                test_fails(start_time, &testlist[tnum]);
1294
        txstr("Pass\r\n"); testlist[tnum++] = 0;
1295
 
1296
        // Illegal Instruction test
1297
        testid("Ill Instruction test, two"); MARKSTART;
1298
        if ((run_test(ill_test, user_stack_ptr))||((zip_ucc()^0x100)&0x01d90))
1299
                test_fails(start_time, &testlist[tnum]);
1300
        save_context(context);
1301
        if (context[15] != (int)&ill_test)
1302
                test_fails(start_time, &testlist[tnum]);
1303
        txstr("Pass\r\n"); testlist[tnum++] = 0;
1304
 
1305
        // Pipeline memory race condition test
1306
        // DIVIDE test
1307
 
1308
        // CC Register test
1309
        testid("CC Register test"); MARKSTART;
1310
        if ((run_test(ccreg_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1311
                test_fails(start_time, &testlist[tnum]);
1312
        txstr("Pass\r\n"); testlist[tnum++] = 0;
1313
 
1314
        // Multiple argument test
1315
        testid("Multi-Arg test"); MARKSTART;
1316
        if ((run_test(multiarg_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1317
                test_fails(start_time, &testlist[tnum]);
1318
        txstr("Pass\r\n"); testlist[tnum++] = 0;
1319
 
1320
        // MPY_TEST
1321
        testid("Multiply test"); MARKSTART;
1322
        if ((run_test(mpy_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1323
                test_fails(start_time, &testlist[tnum]);
1324
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #9
1325
 
1326
        // MPYxHI_TEST
1327
        testid("Multiply HI-word test"); MARKSTART;
1328
        if ((run_test(mpyhi_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1329
                test_fails(start_time, &testlist[tnum]);
1330
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #9
1331
 
1332
        txstr("\r\n");
1333
        txstr("-----------------------------------\r\n");
1334
        txstr("All tests passed.  Halting CPU.\r\n");
1335
        zip_halt();
1336
}
1337
 
1338
// To build this:
1339
//      zip-gcc -O3 -Wall -Wextra -nostdlib -fno-builtin -T xula.ld -Wl,-Map,cputest.map cputest.cpp -o cputest
1340
//      zip-objdump -D cputest > cputest.txt
1341
//

powered by: WebSVN 2.1.0

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