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

Subversion Repositories s6soc

[/] [s6soc/] [trunk/] [sw/] [dev/] [cputest.c] - Blame information for rev 53

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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