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

Subversion Repositories zipcpu

[/] [zipcpu/] [trunk/] [sw/] [zasm/] [test.S] - Blame information for rev 143

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

Line No. Rev Author Line
1 2 dgisselq
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;
3
; Filename:     test.S
4
;
5
; Project:      Zip CPU -- a small, lightweight, RISC CPU soft core
6
;
7
; Purpose:      A disorganized test, just showing some initial operation of
8
;               the CPU.  As a disorganized test, it doesn't prove anything
9
;               beyond the generic operation of the CPU.
10
;
11 13 dgisselq
; Status:       As of August, 2015, this file assembles, builds, and passes
12
;               all of its tests in the Verilator simulator.
13 2 dgisselq
;
14 19 dgisselq
;       Okay, as of 15 August, there are now some tests that don't pass.
15
;       In particular, the #include test used to pass but didn't pass today.
16
;       Likewise the PUSH() macro test hasn't passed yet.  Finally, be aware
17
;       that this implementation is specific to where it loads on a board.
18
;       I tried loading it on my Basys development board, where I had placed
19
;       RAM in a different location and ... things didn't work out so well.
20
;       So grep the __here__ line and adjust it for where you intend to load
21
;       this file.
22
;
23
;       In general, as I'm building the CPU, I'm modifying this file to place
24
;       more and more capability tests within the file.  If the Lord is
25
;       willing, this will become the proof that the CPU completely works.
26
;
27
;
28 2 dgisselq
; Creator:      Dan Gisselquist, Ph.D.
29 69 dgisselq
;               Gisselquist Technology, LLC
30 2 dgisselq
;
31
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
32
;
33
; Copyright (C) 2015, Gisselquist Technology, LLC
34
;
35
; This program is free software (firmware): you can redistribute it and/or
36
; modify it under the terms of  the GNU General Public License as published
37
; by the Free Software Foundation, either version 3 of the License, or (at
38
; your option) any later version.
39
;
40
; This program is distributed in the hope that it will be useful, but WITHOUT
41
; ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
42
; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
43
; for more details.
44
;
45
; License:      GPL, v3, as defined and found on www.gnu.org,
46
;               http://www.gnu.org/licenses/gpl.html
47
;
48
;
49
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
50
;
51 26 dgisselq
#include "sys.i"
52 13 dgisselq
        sys.bus         equ     0xc0000000
53
        sys.breaken     equ     0x080
54
        sys.step        equ     0x040
55
        sys.gie         equ     0x020
56
        sys.sleep       equ     0x010
57
        sys.ccv         equ     0x008
58
        sys.ccn         equ     0x004
59
        sys.ccc         equ     0x002
60
        sys.ccz         equ     0x001
61 26 dgisselq
        sys.cctrap      equ     0x200
62 13 dgisselq
        sys.bu.pic      equ     0x000
63
        sys.bus.wdt     equ     0x001
64
        sys.bus.cache   equ     0x002
65
        sys.bus.ctrpic  equ     0x003
66
        sys.bus.tma     equ     0x004
67
        sys.bus.tmb     equ     0x005
68
        sys.bus.tmc     equ     0x006
69
        sys.bus.jiffies equ     0x007
70
        sys.bus.mtask   equ     0x008
71
        sys.bus.mpstl   equ     0x009
72
        sys.bus.mastl   equ     0x00a
73
        sys.bus.mstl    equ     0x00b
74
        sys.bus.utask   equ     0x00c
75
        sys.bus.upstl   equ     0x00d
76
        sys.bus.uastl   equ     0x00e
77
        sys.bus.ustl    equ     0x00f
78
#define DO_TEST_ASSEMBLER
79 103 dgisselq
#define LJMP_TEST
80 105 dgisselq
#define EARLY_BRANCH_TEST
81 26 dgisselq
#define BREAK_TEST
82
#define OVERFLOW_TEST
83
#define CARRY_TEST
84
#define LOOP_TEST
85
#define SHIFT_TEST
86
#define TRAP_TEST
87 143 dgisselq
;
88
; Since updating our multiplies, the old MPY_TEST doesn't work anymore.  It
89
; really needs to be rebuilt.  For now, we just disable it.  I know, this is the
90
; wrong approach.  Test first and don't get surprised later.  Yes.  I need to
91
; come back to this--hopefully before getting surprised.
92
;
93
; #define       MPY_TEST
94 34 dgisselq
#define PUSH_TEST
95 46 dgisselq
#define PIPELINE_STACK_TEST
96
#define MEM_PIPELINE_TEST
97 60 dgisselq
#define CONDITIONAL_EXECUTION_TEST
98 55 dgisselq
#define NOWAIT_PIPELINE_TEST    // Were wait states btwn regs removed properly?
99 69 dgisselq
#define BCMEM_TEST      // Do memory and conditions work well together?
100 123 dgisselq
#define PIPELINE_MEMORY_RACE_CONDITIONS
101 2 dgisselq
test:
102 13 dgisselq
#ifdef  DO_TEST_ASSEMBLER
103
; We start out by testing our assembler.  We give it some instructions, which
104
; are then manually checked  by disassembling/dumping the result and making
105
; certain they match.  This is not an automated test, but it is an important
106
; one.
107
        noop
108
        bra     continue_test_with_testable_instructions
109
        break
110
        wait
111 26 dgisselq
        break
112 13 dgisselq
        busy
113
        rtu
114
continue_test_with_testable_instructions:
115
        ; Now, let's place the assembler into a known state
116 2 dgisselq
        clr     r0
117 13 dgisselq
        clr     r1
118
        clr     r2
119
        clr     r3
120
        clr     r4
121
        clr     r5
122
        clr     r6
123
        clr     r7
124 36 dgisselq
        clr     r8
125 13 dgisselq
        clr     r9
126
        clr     r10
127
        clr     r11
128
        clr     r12
129
        clr     r13
130
        ; Don't clear the CC register
131
        ; Don't clear the SP register
132
        ; And repeat for the user registers
133
        mov     R0,uR0
134
        mov     R0,uR1
135
        mov     R0,uR2
136
        mov     R0,uR3
137
        mov     R0,uR4
138
        mov     R0,uR5
139
        mov     R0,uR6
140
        mov     R0,uR7
141
        mov     R0,uR8
142
        mov     R0,uR9
143
        mov     R0,uR10
144
        mov     R0,uR11
145
        mov     R0,uR12
146
        mov     R0,uR13
147
        mov     R0,uCC
148
        ; Don't clear the user PC register
149
        ; Now, let's try loading some constants into registers
150 19 dgisselq
        ; Specifically, we're testing the LDI, LDIHI, and LDILO instructions
151 13 dgisselq
dead_beef       equ     0xdeadbeef
152
        ldi     0x0dead,r5
153
        ldi     0x0beef,r6
154
        ldi     0xdeadbeef,r7
155 143 dgisselq
        brev    0xb57b, r8
156 13 dgisselq
        ldilo   0xbeef, r8
157
        ldi     dead_beef,r9
158
        cmp     r5,r6
159
        bz      test_failure
160
        cmp     r7,r8
161
        bnz     test_failure
162
        ldi     $deadbeefh,r7   ; Try loading with the $[HEX]h mneumonic
163
        cmp     r7,r8
164
        bnz     test_failure
165
        cmp     r7,r9
166
        bnz     test_failure
167
        bra     skip_dead_beef
168
dead_beef.base:
169
        word    0
170
        fill    5,dead_beef
171
        word    0
172
dead_beef.zero          equ     0
173
dead_beef.values        equ     1
174
skip_dead_beef:
175
        lod     dead_beef.base(pc),r10  ; Should load a zero here
176
        cmp     r10,r11                 ; r11 should still be zero from init abv
177
        bnz     test_failure
178
        mov     dead_beef.base(pc),r10  ; Now, let's get the address
179
        lod     dead_beef.values(r10),r10       ; r10 now equals 0xdeadbeef
180
        cmp     r10,r9
181
        bnz     test_failure
182 34 dgisselq
 
183
; Test whether or not our operator precedence rules work
184
        ldi     5+3*8,r0
185
        ldi     3*8+5,r1
186
        cmp     r0,r1
187
        bnz     test_failure
188
        ldi     (5+3)*8,r0
189
        ldi     8*(3+5),r1
190
        cmp     r0,r1
191
        bnz     test_failure
192
 
193 13 dgisselq
; Test whether or not we can properly decode OCTAL values
194
        clr     r0      ; Re-clear our register set first
195
        clr     r1
196
        clr     r2
197
        clr     r3
198
        clr     r4
199
        clr     r5
200
        clr     r6
201
        clr     r7
202 36 dgisselq
        clr     r8
203 13 dgisselq
        clr     r9
204
        clr     r10
205
        clr     r11
206
        clr     r12
207
        clr     r13
208
        ;
209
        ldi     $024o,r0
210
        ldi     $20,r1
211
        cmp     r0,r1
212
        bnz     test_failure
213
        ldi     $024,r0
214
        cmp     r0,r1
215
        bnz     test_failure
216
        clr     r0
217
        clr     r1
218 2 dgisselq
        mov     $1+r0,r2
219
        mov     $2+r0,r3
220
        mov     $22h+r0,r4
221
        mov     $377h+r0,ur5
222
        noop
223
        nop
224
        add     r2,r0
225
        add     $32,r0
226
        add     $-33,r0
227 13 dgisselq
        bnz     test_failure
228 36 dgisselq
        not     r0
229 13 dgisselq
        bge     test_failure
230
junk_address:
231 2 dgisselq
        clrf    r0
232 13 dgisselq
        bnz     test_failure
233 2 dgisselq
        ldi     $5,r1
234
        cmp     $0+r0,r1
235
        not.lt  r0
236
        not.ge  r1
237 13 dgisselq
        mov     junk_address(pc),r2     ; Test pc-relative addressing
238
        mov     junk_address(pc),r3
239
        cmp     r2,r3
240
        bnz     test_failure
241
        lod     junk_address(pc),r5     ; Test loads with pc-relative addressing
242
        lod     junk_address(pc),r6
243
        cmp     r5,r6
244
        bnz     test_failure
245 26 dgisselq
#endif
246
 
247
#ifdef  NOONE // Testing comments after ifdef
248
#else   ; After else
249
#endif /* and after endif */
250
 
251 103 dgisselq
#ifdef  LJMP_TEST
252 105 dgisselq
        // A long jump is a 32-bit instruction followed by a 32-bit address.
253
        // The CPU is supposed to jump to this address.  At issue in this test,
254
        // which can only really be verified by watching it in person currently,
255
        // is how fast this branch can take place.  Currently, it takes four
256
        // clocks--not that bad.
257
        //
258
        // Although really long jumps, we also test some of our early branching
259
        // forms here as well:
260
        //      1. Add to PC
261
        //      2. LOD (PC),PC (the long jump itself)
262
        //      3. LDI x,PC     // An early branch target not tested elsewhere
263
        //
264 103 dgisselq
        CLR     R0
265
        CLR     R1
266
        LJMP
267
        .dat    __here__+0x0100000+4
268
        ADD     1,R0
269
        ADD     1,R0
270
        ADD     1,R0
271
        ADD     1,R0
272
        ADD     1,R0
273
        ADD     1,R0
274
        CMP     3,R0
275
        BNZ     test_failure
276
        LOD.Z   __here__+2(PC),PC
277
        BRA     test_failure
278
        .dat    __here__+0x0100000+2
279
        ADD     1,R0
280
        ADD     1,R0
281
        ADD     1,R0
282
        CMP     5,R0
283
        BNZ     test_failure
284
// And our last early branching test
285
        LDI     0x0100000+__here__+4,PC
286
        ADD     1,R0
287
        ADD     1,R0
288
        ADD     1,R0
289
        SUB     1,R0
290
        CMP     4,R0
291
        BNZ     test_failure
292
#endif
293 105 dgisselq
#ifdef  EARLY_BRANCH_TEST
294
        // Unlike the previous test, this test is going to see whether or not
295
        // early branching messes with the pipeline.
296
        BRA     eb_a
297
        BUSY
298
eb_a:
299
        BRA     eb_b
300
        NOP
301
        BUSY
302
eb_b:
303
        BRA     eb_c
304
        NOP
305
        NOP
306
        BUSY
307
eb_c:
308
        BRA     eb_d
309
        NOP
310
        NOP
311
        NOP
312
        BUSY
313
eb_d:
314
        BRA     eb_e
315
        NOP
316
        NOP
317
        NOP
318
        NOP
319
        BUSY
320
eb_e:
321
        NOOP
322
        // Only problem is, I don't expect it to mess with the pipeline unless
323
        // the pipeline is full.  Therefore we are interested in something which
324
        // is not an early branch, conflicting with early branches.  So let's
325
        // try loading our pipeline in all kinds of different configurations,
326
        // just to see which if the conditional branch always annihilates the
327
        // early branch as desired.
328
        //
329
        CLR     R0
330
        BZ      ebz_a
331
        BUSY
332
ebz_a:
333
        BZ      ebz_b
334
        NOP
335
        BUSY
336
ebz_b:
337
        BZ      ebz_c
338
        NOP
339
        NOP
340
        BUSY
341
        // Let's repeat that last test, just in case the cache reloaded itself
342
        // in the middle and we didn't get our proper test.
343
ebz_c:
344
        BZ      ebz_d
345
        NOP
346
        NOP
347
        BUSY
348
ebz_d:
349
        BZ      ebz_e
350
        NOP
351
        NOP
352
        NOP
353
        BUSY
354
ebz_e:
355
        BZ      ebz_f
356
        NOP
357
        NOP
358
        NOP
359
        NOP
360
        BUSY
361
ebz_f:
362
        NOOP
363
#endif
364 103 dgisselq
 
365 26 dgisselq
#ifdef  BREAK_TEST
366
breaktest:
367
        bra     breaksupervisor
368
breakuser:
369
        clr     r0
370
        mov     1+r0,r1
371
        mov     1+r1,r2
372
        mov     1+r2,r3
373
        break           ; At address 0x0100097
374
        mov     1+r4,r5
375
        mov     1+r5,r6
376
        clr     cc
377
        busy
378
breaksupervisor:
379 13 dgisselq
        ldi     -1,r0
380 26 dgisselq
        mov     breakuser(pc),upc
381
        rtu     ; Should just keep returning immediately
382
        mov     upc,r0
383
        rtu
384
        rtu
385
        mov     upc,r1
386
        cmp     r0,r1
387 13 dgisselq
        bnz     test_failure
388 26 dgisselq
#endif
389
 
390
#ifdef  TRAP_TEST
391
traptest:
392
        bra     traptest_supervisor
393
        busy
394
traptest_user:
395
        trap    0
396
        busy
397
traptest_supervisor:
398
        mov     traptest_user(pc),upc
399
        rtu
400 69 dgisselq
        mov     ucc,r0
401 26 dgisselq
        tst     sys.cctrap,r0
402 69 dgisselq
        tst.nz  sys.gie,r0
403 13 dgisselq
        bz      test_failure
404
#endif
405 2 dgisselq
 
406
testbench:
407
        // Let's build a software test bench.
408 13 dgisselq
        ldi     $c0000000h,r12  ; Set R12 to point to our peripheral address
409 2 dgisselq
        mov     r12,ur12
410 13 dgisselq
        mov     test_start(pc),upc
411 34 dgisselq
        mov     stack(pc),usp
412 13 dgisselq
        ldi     0x8000ffff,r0   ; Clear interrupts, turn all vectors off
413
        sto     r0,(r12)
414 2 dgisselq
        rtu
415 13 dgisselq
        mov     ucc,r0
416 123 dgisselq
        and     0x0ffff,r0
417 69 dgisselq
        CMP     sys.cctrap+sys.gie,r0
418 13 dgisselq
        bnz     test_failure
419 2 dgisselq
        halt
420 13 dgisselq
// Go into an infinite loop if the trap fails
421
// Permanent loop instruction -- a busy halt if you will
422
test_failure:
423 2 dgisselq
        busy
424
 
425
; Now for a series of tests.  If the test fails, call the trap
426
; interrupt with the test number that failed.  Upon completion,
427
; call the trap with #0.
428
 
429
; Test LDI to PC
430
; Some data registers
431 13 dgisselq
test_data:
432
        .dat    __here__+0x0100000+5
433 2 dgisselq
test_start:
434 26 dgisselq
        ldi     $0x01000,r11
435 36 dgisselq
        ldi     -1,r10
436 13 dgisselq
        lod     test_data+pc,pc
437 36 dgisselq
        clr     r10
438 2 dgisselq
        noop
439 36 dgisselq
        cmp     $0,r10
440 13 dgisselq
        trap.z  r11
441 2 dgisselq
        add     $1,r0
442
        add     $1,r0
443
 
444 26 dgisselq
#ifdef  OVERFLOW_TEST
445 2 dgisselq
// Let's test whether overflow works
446 26 dgisselq
        ldi     $0x02000,r11
447 2 dgisselq
        ldi     $-1,r0
448
        lsr     $1,r0
449
        add     $1,r0
450 13 dgisselq
        bv      first_overflow_passes
451
        trap    r11
452
first_overflow_passes:
453 2 dgisselq
// Overflow set from subtraction
454 26 dgisselq
        ldi     $0x03000,r11
455 2 dgisselq
        ldi     $1,r0
456 13 dgisselq
        rol     $31,r0                  ; rol $31,r0
457 2 dgisselq
        sub     $1,r0
458 13 dgisselq
        bv      subtraction_overflow_passes
459
        trap    r11
460
subtraction_overflow_passes:
461 2 dgisselq
// Overflow set from LSR
462 26 dgisselq
        ldi     $0x04000,r11
463 2 dgisselq
        ldi     $1,r0
464 13 dgisselq
        rol     $31,r0                  ; rol $31,r0
465 2 dgisselq
        lsr     $1,r0
466 13 dgisselq
        bv      lsr_overflow_passes
467
        trap    r11
468
lsr_overflow_passes:
469 2 dgisselq
// Overflow set from LSL
470 26 dgisselq
        ldi     $0x05000,r11
471 2 dgisselq
        ldi     $1,r0
472 13 dgisselq
        rol     $30,r0
473 2 dgisselq
        lsl     $1,r0
474 13 dgisselq
        bv      lsl_overflow_passes
475
        trap    r11
476
lsl_overflow_passes:
477 2 dgisselq
// Overflow set from LSL, negative to positive
478 26 dgisselq
        ldi     $0x06000,r11
479 2 dgisselq
        ldi     $1,r0
480 13 dgisselq
        rol     $31,r0
481 2 dgisselq
        lsl     $1,r0
482 13 dgisselq
        bv      second_lsl_overflow_passes
483
        trap    r11
484 26 dgisselq
#endif // OVERFLOW_TEST
485
#ifdef  CARRY_TEST
486 13 dgisselq
second_lsl_overflow_passes:
487 2 dgisselq
// Test carry
488 26 dgisselq
        ldi     $0x07000,r11
489 2 dgisselq
        ldi     $-1,r0
490
        add     $1,r0
491 55 dgisselq
        tst     sys.ccc,cc
492 13 dgisselq
        trap.z  r11
493 2 dgisselq
// and carry from subtraction
494 26 dgisselq
        ldi     $0x08000,r11
495
        clr     r0
496 2 dgisselq
        sub     $1,r0
497 55 dgisselq
        tst     sys.ccc,cc
498 13 dgisselq
        trap.z  r11
499 55 dgisselq
// Carry from right shift
500
        clr     r0              ; r0 = 0
501
        lsr     1,r0            ; r0 = 0, c = 0
502
        add.c   1,r0            ; r0 = 0
503
        cmp     1,r0            ; r0 ?= 1
504
        trap.z  r11
505
        LDI     1,r0            ; r0 = 1
506
        lsr     1,r0            ; r0 = 0, c = 1
507
        add.c   1,r0            ; r0 = 1
508
        cmp     1,r0
509
        trap.nz r11
510
 
511
        ldi     0x070eca6,r0
512
        ldi     0x0408b85,r1
513
        ldi     0x0387653,r2
514
        lsr     1,r0
515
        xor.c   r1,r0
516
        cmp     r2,r0
517
        trap.nz r11
518 26 dgisselq
#endif
519 2 dgisselq
 
520 26 dgisselq
#ifdef  LOOP_TEST
521
 
522 2 dgisselq
// Let's try a loop: for i=0; i<5; i++)
523
//      We'll use R0=i, Immediates for 5
524 26 dgisselq
        ldi     $0x09000,r11
525 13 dgisselq
        clr     r0
526 2 dgisselq
for_loop:
527
        noop
528
        add     $1,r0
529
        cmp     $5,r0
530
        blt     for_loop
531
//
532
// Let's try a reverse loop.  Such loops are usually cheaper to
533
// implement, and this one is no different: 2 loop instructions
534
// (minus setup instructions) vs 3 from before.
535
// R0 = 5; (from before)
536
// do {
537
// } while (R0 > 0);
538 26 dgisselq
        ldi     $0x0a000,r11
539 2 dgisselq
bgt_loop:
540
        noop
541
        sub     $1,r0
542
        bgt     bgt_loop
543
 
544
// How about the same thing with a >= comparison?
545
// R1 = 5; // Need to do this explicitly
546
// do {
547
// } while(R1 >= 0);
548 13 dgisselq
        ldi     $20,r0
549 2 dgisselq
        ldi     $5,r1
550
bge_loop:
551
        noop
552
        sub     $1,r1
553
        bge     bge_loop
554
 
555
// Let's try the reverse loop again, only this time we'll store our
556
// loop variable in memory.
557
// R0 = 5; (from before)
558
// do {
559
// } while (R0 > 0);
560 26 dgisselq
        ldi     $0x0b000,r11
561 13 dgisselq
        bra     mem_loop_test
562 2 dgisselq
loop_var:
563
        .dat    0
564 13 dgisselq
mem_loop_test:
565
        mov     loop_var(pc),r1
566
        ldi     $5,r0
567
        clr     r2
568
        sto     r0,(r1)
569 2 dgisselq
mem_loop:
570
        add     $1,r2
571
        add     $14,r0
572
        lod     (r1),r0
573
        sub     $1,r0
574 13 dgisselq
        sto     r0,(r1)
575
        bgt     mem_loop
576 2 dgisselq
        cmp     $5,r2
577 13 dgisselq
        trap.ne r11
578 26 dgisselq
#endif
579 2 dgisselq
 
580 26 dgisselq
#ifdef  SHIFT_TEST
581
; Now, let's test whether or not our LSR and carry flags work
582
        ldi     $0x0c000,r11
583
        ldi     -1,r0   ; First test: shifting all the way should yield zero
584
        lsr     32,r0
585
        cmp     0,r0
586
        bnz     test_failure
587
        ldi     -1,r0   ; Second test: anything greater than zero should set
588
        lsr     0,r0    ; the carry flag
589
        bc      test_failure
590
        lsr     1,r0
591 103 dgisselq
        tst     sys.ccc,cc
592 26 dgisselq
        bz      test_failure
593
        lsr     31,r0
594
        tst     sys.ccc,cc
595
        bz      test_failure
596
        lsr     1,r0
597
        bc      test_failure
598
; Now repeat the above tests, looking to see whether or not ASR works
599
        ldi     -1,r0
600
        asr     32,r0
601
        cmp     -1,r0
602
        bnz     test_failure
603
        ldi     -1,r0
604
        asr     0,r0
605
        bc      test_failure
606
        cmp     -1,r0
607
        bnz     test_failure
608
        asr     1,r0
609
        tst     sys.ccc,r14
610
        bz      test_failure
611
        asr     30,r0
612
        tst     sys.ccc,r14
613
        bz      test_failure
614
 
615 19 dgisselq
// Let's test whether LSL works
616
        ldi     0x035,r2
617
        lsl     8,r2
618
        ldi     0x03500,r1
619
        cmp     r2,r1
620
        trap.ne r11
621
        ldi     0x074,r0
622
        and     0x0ff,r0
623
        or      r0,r2
624
        cmp     0x03574,r2
625
        trap.ne r11
626 26 dgisselq
#endif
627 19 dgisselq
 
628 26 dgisselq
#ifdef  MPY_TEST
629
 
630
// We have two multiply instructions.  Let's see if those work
631
        ldi     $0x0d000,r11    // Mark our test
632
        ldi     23171,r0        // = sqrt(2)/2 * 32768
633
        mpyu    r0,r0           // Should = 2/4 * 2^30 = 2^29 or thereabouts
634
        ldi     536895241,r2
635
        cmp     r0,r2
636
        trap.ne r11
637
        ldi     0x0ffff,r0
638
        mpyu    r0,r0
639
        ldi     0xfffe0001,r1
640
        cmp     r1,r0
641
        trap.ne r11
642
        ldi     0x08001,r0
643
        ldi     0x07fff,r1
644
        mpys    r0,r1           // FAILS: result is 0x008001 ??? (pipeline prob)
645
        ldi     0x3fff0001,r2
646
        neg     r2
647
        cmp     r2,r1           // @0x010011c
648
        trap.ne r11             //TRAP FAILS TO TRIGGER ????? (R2=0x0c000ffff,R1=0x0008001 -- did mpy even happen?)
649
        mpys    r0,r0           // FAILS: result is 0x40010001
650
        ldi     0x3fff0001,r2
651
        cmp     r2,r0
652
        trap.ne r11             // TRAP FAILS TO TRIGGER AGAIN
653
        ldi     0x08000,r0
654
        mpys    r0,r0           // R0 now equals 0x40000000
655
        ldi     0x40000000,r1
656
        cmp     r0,r1
657
        trap.ne r11
658 69 dgisselq
//
659
// And from our eyeball test ...
660
        LDI     0x01ff01ff,R0
661
        MOV     R0,R7
662
        MOV     8(SP),R6
663
        LSR     7,R0
664
        AND     7,R0
665
        LDI     7,R1
666
        SUB     R0,R1
667
        MOV     R1,R0
668
        MPYU    5,R0
669
        CMP     20,R0
670
        TRAP.NE R11
671 26 dgisselq
#endif
672 34 dgisselq
 
673
#ifdef  PUSH_TEST
674
        ldi     $0x0e000,r11    // Mark our test
675
        ldi     0x01248cab,r0
676
        ldi     0xd5312480,r1   // Let's see if we can preserve this as well
677
        mov     r1,r7
678 69 dgisselq
        FJSR(reverse_bit_order,R4);     // *SP = 0x010013d
679 34 dgisselq
        cmp     r0,r1
680
        trap.ne r11
681
        cmp     r0,r7
682
        trap.ne r11
683
#endif
684 39 dgisselq
 
685
#ifdef  PIPELINE_STACK_TEST
686
        ldi     $0x0f000,r11    // Mark our test
687
        LDI     1,R0
688
        MOV     1(R0),R1
689
        MOV     1(R1),R2
690
        MOV     1(R2),R3
691
        MOV     1(R3),R4
692
        MOV     1(R4),R5
693
        MOV     1(R5),R6
694 69 dgisselq
        FJSR(pipeline_stack_test,R7)
695 39 dgisselq
        CMP     1,R0
696
        trap.ne R11
697
        CMP     2,R1
698
        trap.ne R11
699
        CMP     3,R2
700
        trap.ne R11
701
        CMP     4,R3
702
        trap.ne R11
703
        CMP     5,R4
704
        trap.ne R11
705
        CMP     6,R5
706
        trap.ne R11
707
        CMP     7,R6
708
        trap.ne R11
709
#endif
710 46 dgisselq
 
711
#ifdef  MEM_PIPELINE_TEST
712 69 dgisselq
        LDI     0x10000,R11
713
        FJSR(mem_pipeline_test,R0)
714 46 dgisselq
#endif  // MEM_PIPELINE_TEST
715
 
716 60 dgisselq
#ifdef  CONDITIONAL_EXECUTION_TEST
717 69 dgisselq
        LDI     0x11000,R11
718
        FJSR(conditional_execution_test,R0)
719 60 dgisselq
#endif  // CONDITIONAL_EXECUTION_TEST
720
 
721 55 dgisselq
#ifdef  NOWAIT_PIPELINE_TEST
722 69 dgisselq
        LDI     0x12000,R11
723
        FJSR(nowait_pipeline_test,R0)
724 55 dgisselq
#endif  // NOWAIT_PIPELINE_TEST
725
 
726 69 dgisselq
#ifdef  BCMEM_TEST
727
        LDI     0x13000,R11
728
        CLR     R0
729
        LDI     -1,R1
730
        STO     R0,bcmemtestloc(PC)
731
        LOD     bcmemtestloc(PC),R1
732
        CMP     R0,R1
733
        TRAP.NZ R11
734
        CMP     0x13000,R11
735
        BZ      bcmemtest_cmploc_1
736
        STO     R11,bcmemtestloc(PC)
737
bcmemtest_cmploc_1:
738
        LOD     bcmemtestloc(PC),R0
739
        CMP     R0,R11
740
        TRAP.Z  R11
741
        CLR     R0
742
        CMP     R0,R11
743
        BZ      bcmemtest_cmploc_2
744
        STO.NZ  R11,bcmemtestloc(PC)
745
bcmemtest_cmploc_2:
746
        NOOP
747
        LOD     bcmemtestloc(PC),R0
748
        CMP     R0,R11
749
        TRAP.NZ R11
750
        BRA     end_bcmemtest
751
bcmemtestloc:
752
        WORD    0
753
end_bcmemtest:
754
#endif
755 123 dgisselq
 
756
#ifdef  PIPELINE_MEMORY_RACE_CONDITIONS
757
        LDI     0x14000,R11
758
        FJSR(pipeline_memory_race_test,R0)
759
#endif // PIPELINE_MEMORY_RACE_CONDITIONS
760
 
761 2 dgisselq
// Return success / Test the trap interrupt
762
        clr     r11
763 103 dgisselq
        trap    r11     // FAILS HERE FAILS FAILS FAILS !!!!!!!!!!!
764 2 dgisselq
        noop
765
        noop
766
 
767
        busy
768
 
769
// And, in case we miss a halt ...
770
        halt
771 16 dgisselq
 
772
// Now, let's test whether or not we can handle a subroutine
773 19 dgisselq
#ifdef  PUSH_TEST
774 16 dgisselq
reverse_bit_order:
775 69 dgisselq
        SUB     3,SP
776
        STO     R1,(SP)         ; R1 will be our loop counter
777
        STO     R2,1(SP)        ; R2 will be our accumulator and eventual result
778
        STO     R4,2(SP)
779 16 dgisselq
        LDI     32,R1
780
        CLR     R2
781 34 dgisselq
reverse_bit_order_loop:
782 16 dgisselq
        LSL     1,R2
783
        LSR     1,R0
784
        OR.C    1,R2
785
        SUB     1,R1
786
        BNZ     reverse_bit_order_loop
787
        MOV     R2,R0
788 69 dgisselq
        LOD     (SP),R1
789
        LOD     1(SP),R2
790
        LOD     2(SP),R4
791
        ADD     3,SP
792
        JMP     R4
793 19 dgisselq
#endif
794 39 dgisselq
 
795 55 dgisselq
; The pipeline stack test examines whether or not a series of memory commands
796
; can be evaluated right after the other without problems.  This depends upon
797
; the calling routine to properly set up registers to be tested.
798
;
799
; This is also an incomplete test, as nothing is done to test how these
800
; pipeline reads/writes are affected by condition codes.
801
;
802 39 dgisselq
#ifdef  PIPELINE_STACK_TEST
803
pipeline_stack_test:
804
        SUB     13,SP
805 69 dgisselq
        STO     R0,(SP)
806
        STO     R1,1(SP)
807
        STO     R2,2(SP)
808
        STO     R3,3(SP)
809
        STO     R4,4(SP)
810
        STO     R5,5(SP)
811
        STO     R6,6(SP)
812
        STO     R7,7(SP)
813
        STO     R8,8(SP)
814
        STO     R9,9(SP)
815
        STO     R10,10(SP)
816
        STO     R11,11(SP)
817
        STO     R12,12(SP)
818 39 dgisselq
        XOR     -1,R0
819
        XOR     -1,R1
820
        XOR     -1,R2
821
        XOR     -1,R3
822
        XOR     -1,R4
823
        XOR     -1,R5
824
        XOR     -1,R6
825
        XOR     -1,R7
826
        XOR     -1,R8
827
        XOR     -1,R9
828
        XOR     -1,R10
829
        XOR     -1,R11
830
        XOR     -1,R12
831 69 dgisselq
        LOD     (SP),R0
832
        LOD     1(SP),R1
833
        LOD     2(SP),R2
834
        LOD     3(SP),R3
835
        LOD     4(SP),R4
836
        LOD     5(SP),R5
837
        LOD     6(SP),R6
838
        LOD     7(SP),R7
839
        LOD     8(SP),R8
840
        LOD     9(SP),R9
841
        LOD     10(SP),R10
842
        LOD     11(SP),R11
843
        LOD     12(SP),R12
844 39 dgisselq
        ADD     13,SP
845 69 dgisselq
        JMP     R7
846 39 dgisselq
#endif // PIPELINE_STACK_TEST
847
 
848 46 dgisselq
#ifdef  MEM_PIPELINE_TEST
849
mem_pipeline_test:
850
        SUB     4,SP
851 69 dgisselq
        STO     R0,(SP)
852
        STO     R1,1(SP)
853 46 dgisselq
        LDI     0x10000,R11
854
        ;
855
        ; Test #1 ... Let's start by writing a value to memory
856
        LDI     -1,R0
857
        CLR     R1
858 69 dgisselq
        STO     R0,2(SP)
859
        LOD     2(SP),R1
860 46 dgisselq
        CMP     R1,R0
861
        MOV.NZ  R11,CC
862
 
863
        ; Test #2, reading and then writing a value from memory
864
        NOP
865
        NOP
866
        CLR     R0
867
        CLR     R1
868 69 dgisselq
        LOD     2(SP),R0        ; This should load back up our -1 value
869
        STO     R0,3(SP)
870 46 dgisselq
        ; Insist that the pipeline clear
871 69 dgisselq
        LOD     2(SP),R0
872 46 dgisselq
        ; Now let's try loading into R1
873
        NOP
874
        NOP
875
        NOP
876
        NOP
877 69 dgisselq
        LOD     3(SP),R1
878 46 dgisselq
        CMP     R1,R0
879
        MOV.NZ  R11,CC
880
 
881 69 dgisselq
        LOD     (SP),R0
882
        LOD     1(SP),R1
883 46 dgisselq
        ADD     4,SP
884 69 dgisselq
        JMP     R0
885 46 dgisselq
#endif
886
 
887 60 dgisselq
#ifdef  CONDITIONAL_EXECUTION_TEST
888
conditional_execution_test:
889 69 dgisselq
        SUB     1,SP
890
        STO     R0,(SP)
891
        ;
892 60 dgisselq
        CLRF    R0
893
        ADD.Z   1,R0
894
        TRAP.NZ R11
895
        CMP.Z   0,R0
896
        TRAP.Z  R11
897
 
898 69 dgisselq
        LOD     (SP),R0
899
        ADD     1,SP
900
        JMP     R0
901 60 dgisselq
#endif
902
 
903 55 dgisselq
;
904
; Pipeline stalls have been hideous problems for me.  The CPU has been modified
905
; with special logic to keep stages from stalling.  For the most part, this
906
; means that ALU and memory results may be accessed either before or as they
907
; are written to the register file.  This set of code is designed to test
908
; whether this bypass logic works.
909
#ifdef  NOWAIT_PIPELINE_TEST
910
nowait_pipeline_test:
911
        ; Allocate for us some number of registers
912
        ;
913 60 dgisselq
        SUB     6,SP
914
        ; Leave a spot open on the stack for a local variable,
915
        ; kept in memory.
916 69 dgisselq
        STO     R0,(SP)
917
        STO     R1,1(SP)
918
        STO     R2,2(SP)
919
        STO     R3,3(SP)
920
        STO     R4,4(SP)
921 55 dgisselq
        ;
922
        ; Let's start with ALU-ALU testing
923
        ;       AA: result->input A
924 60 dgisselq
        CLR     R0
925
        ADD     1,R0
926
        CMP     1,R0
927
        TRAP.NZ R11
928
 
929 55 dgisselq
        ;       AA: result->input B
930 60 dgisselq
        CLR     R0
931
        CLR     R1
932
        ADD     1,R0
933
        CMP     R0,R1
934
        TRAP.Z  R11
935
 
936 55 dgisselq
        ;       AA: result->input A on condition
937 60 dgisselq
        CLRF    R0
938
        ADD.Z   5,R0
939
        CMP     5,R0
940
        TRAP.NZ R11
941
 
942 55 dgisselq
        ;       AA: result->input B on condition
943 60 dgisselq
        CLR     R0
944
        CLRF    R1
945
        ADD.Z   5,R0
946
        CMP     R0,R1
947
        TRAP.Z  R11
948
 
949 55 dgisselq
        ;       AA: result->input B plus offset
950 60 dgisselq
        CLR     R0
951
        CLRF    R1
952
        ADD     5,R0
953
        CMP     -5(R0),R1
954
        TRAP.NZ R11
955
 
956 55 dgisselq
        ;       AA: result->input B plus offset on condition
957 60 dgisselq
        CLR     R0
958
        CLRF    R1
959
        ADD.Z   5,R0
960
        CMP     -5(R0),R1
961
        TRAP.NZ R11
962
 
963 55 dgisselq
        ;
964
        ; Then we need to do ALU-Mem input testing
965 60 dgisselq
        ;
966
        CLR     R0
967 69 dgisselq
        STO     R0,5(SP)
968 60 dgisselq
        LDI     8352,R0
969 69 dgisselq
        LOD     5(SP),R0
970 60 dgisselq
        TST     -1,R0
971
        TRAP.NZ R11
972
 
973
        LDI     937,R0          ; Let's try again, this time something that's
974 69 dgisselq
        STO     R0,5(SP)        ; not zero
975 60 dgisselq
        NOOP
976 69 dgisselq
        LOD     5(SP),R0
977 60 dgisselq
        CMP     938,R0          ; Let's not compare with self, let's that
978
        TRAP.GE R11             ; masks a problem--compare with a different
979
        CMP     936,R0          ; number instead.
980
        TRAP.LT R11
981
 
982 55 dgisselq
        ; Mem output->ALU input testing
983 60 dgisselq
        ;       We just did that as partof our last test
984 55 dgisselq
        ; Mem output->MEM input testing
985
        ;
986 60 dgisselq
        LDI     5328,R2
987 69 dgisselq
        LOD     5(SP),R2
988
        STO     R2,5(SP)
989
        LOD     5(SP),R1
990 60 dgisselq
        CMP     937,R1
991
        TRAP.NZ R11
992
        ;
993 69 dgisselq
        LOD     (SP),R0
994
        LOD     1(SP),R1
995
        LOD     2(SP),R2
996
        LOD     3(SP),R3
997
        LOD     4(SP),R4
998 60 dgisselq
        ADD     6,SP
999 69 dgisselq
        JMP     R0
1000 55 dgisselq
#endif  // NOWAIT_PIPELINE_TEST
1001
 
1002 123 dgisselq
#ifdef  PIPELINE_MEMORY_RACE_CONDITIONS
1003
pipeline_memory_race_test:
1004
        SUB     3,SP
1005
        STO     R0,(SP)
1006
        STO     R1,1(SP)
1007
        STO     R2,2(SP)
1008 69 dgisselq
 
1009 123 dgisselq
        MOV     pipeline_memory_test_data(PC),R0
1010
        LOD     (R0),R0
1011
        LOD     (R0),R0
1012
        CMP     275,R0
1013
        MOV.NZ  R11,CC
1014
 
1015
        MOV     pipeline_memory_test_data(PC),R0
1016
        ; Here's the test sequence
1017
        LOD     (R0),R1
1018
        LOD     1(R0),R2
1019
        STO     R2,1(R1)
1020
        ; Make sure we clear the load pipeline
1021
        LOD     (R0),R1
1022
        ; Load our written value
1023
        LOD     2(R0),R2
1024
        CMP     275,R2
1025
        MOV.NZ  R11,CC
1026
 
1027
        ;
1028
        ; Next failing sequence:
1029
        ;       LOD -x(R12),R0
1030
        ;       LOD y(R0),R0
1031
        MOV     pipeline_memory_test_data(PC),R0
1032
        MOV     1(R0),R1
1033
        STO     R1,1(R0)
1034
        LDI     3588,R2         ; Just some random value
1035
        STO     R2,2(R0)
1036
        MOV     R0,R1
1037
        ; Here's the test sequence
1038
        LOD     (R0),R1
1039
        LOD     1(R1),R1
1040
        CMP     R2,R1
1041
        MOV.NZ  R11,CC
1042
 
1043
        LOD     (SP),R0
1044
        LOD     1(SP),R1
1045
        LOD     2(SP),R2
1046
        ADD     3,SP
1047
        JMP     R0
1048
pipeline_memory_test_data:
1049
        .dat    __here__+0x0100000+1
1050
        .dat    275
1051
        .dat    0
1052
#endif
1053
 
1054
 
1055 16 dgisselq
        fill    512,0
1056 34 dgisselq
stack:  // Must point to a valid word initially
1057 16 dgisselq
        word    0

powered by: WebSVN 2.1.0

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