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

Subversion Repositories zipcpu

[/] [zipcpu/] [trunk/] [bench/] [asm/] [cputest.c] - Blame information for rev 202

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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