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

Subversion Repositories openarty

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

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

powered by: WebSVN 2.1.0

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