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

Subversion Repositories zipcpu

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

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 165 dgisselq
        ldi     -1,r0
615
        asr     1,r0
616
        cmp     -1,r0
617
        bnz     test_failure
618 26 dgisselq
 
619 19 dgisselq
// Let's test whether LSL works
620
        ldi     0x035,r2
621
        lsl     8,r2
622
        ldi     0x03500,r1
623
        cmp     r2,r1
624
        trap.ne r11
625
        ldi     0x074,r0
626
        and     0x0ff,r0
627
        or      r0,r2
628
        cmp     0x03574,r2
629
        trap.ne r11
630 26 dgisselq
#endif
631 19 dgisselq
 
632 26 dgisselq
#ifdef  MPY_TEST
633
 
634
// We have two multiply instructions.  Let's see if those work
635
        ldi     $0x0d000,r11    // Mark our test
636
        ldi     23171,r0        // = sqrt(2)/2 * 32768
637
        mpyu    r0,r0           // Should = 2/4 * 2^30 = 2^29 or thereabouts
638
        ldi     536895241,r2
639
        cmp     r0,r2
640
        trap.ne r11
641
        ldi     0x0ffff,r0
642
        mpyu    r0,r0
643
        ldi     0xfffe0001,r1
644
        cmp     r1,r0
645
        trap.ne r11
646
        ldi     0x08001,r0
647
        ldi     0x07fff,r1
648
        mpys    r0,r1           // FAILS: result is 0x008001 ??? (pipeline prob)
649
        ldi     0x3fff0001,r2
650
        neg     r2
651
        cmp     r2,r1           // @0x010011c
652
        trap.ne r11             //TRAP FAILS TO TRIGGER ????? (R2=0x0c000ffff,R1=0x0008001 -- did mpy even happen?)
653
        mpys    r0,r0           // FAILS: result is 0x40010001
654
        ldi     0x3fff0001,r2
655
        cmp     r2,r0
656
        trap.ne r11             // TRAP FAILS TO TRIGGER AGAIN
657
        ldi     0x08000,r0
658
        mpys    r0,r0           // R0 now equals 0x40000000
659
        ldi     0x40000000,r1
660
        cmp     r0,r1
661
        trap.ne r11
662 69 dgisselq
//
663
// And from our eyeball test ...
664
        LDI     0x01ff01ff,R0
665
        MOV     R0,R7
666
        MOV     8(SP),R6
667
        LSR     7,R0
668
        AND     7,R0
669
        LDI     7,R1
670
        SUB     R0,R1
671
        MOV     R1,R0
672
        MPYU    5,R0
673
        CMP     20,R0
674
        TRAP.NE R11
675 26 dgisselq
#endif
676 34 dgisselq
 
677
#ifdef  PUSH_TEST
678
        ldi     $0x0e000,r11    // Mark our test
679
        ldi     0x01248cab,r0
680
        ldi     0xd5312480,r1   // Let's see if we can preserve this as well
681
        mov     r1,r7
682 69 dgisselq
        FJSR(reverse_bit_order,R4);     // *SP = 0x010013d
683 34 dgisselq
        cmp     r0,r1
684
        trap.ne r11
685
        cmp     r0,r7
686
        trap.ne r11
687
#endif
688 39 dgisselq
 
689
#ifdef  PIPELINE_STACK_TEST
690
        ldi     $0x0f000,r11    // Mark our test
691
        LDI     1,R0
692
        MOV     1(R0),R1
693
        MOV     1(R1),R2
694
        MOV     1(R2),R3
695
        MOV     1(R3),R4
696
        MOV     1(R4),R5
697
        MOV     1(R5),R6
698 69 dgisselq
        FJSR(pipeline_stack_test,R7)
699 39 dgisselq
        CMP     1,R0
700
        trap.ne R11
701
        CMP     2,R1
702
        trap.ne R11
703
        CMP     3,R2
704
        trap.ne R11
705
        CMP     4,R3
706
        trap.ne R11
707
        CMP     5,R4
708
        trap.ne R11
709
        CMP     6,R5
710
        trap.ne R11
711
        CMP     7,R6
712
        trap.ne R11
713
#endif
714 46 dgisselq
 
715
#ifdef  MEM_PIPELINE_TEST
716 69 dgisselq
        LDI     0x10000,R11
717
        FJSR(mem_pipeline_test,R0)
718 46 dgisselq
#endif  // MEM_PIPELINE_TEST
719
 
720 60 dgisselq
#ifdef  CONDITIONAL_EXECUTION_TEST
721 69 dgisselq
        LDI     0x11000,R11
722
        FJSR(conditional_execution_test,R0)
723 60 dgisselq
#endif  // CONDITIONAL_EXECUTION_TEST
724
 
725 55 dgisselq
#ifdef  NOWAIT_PIPELINE_TEST
726 69 dgisselq
        LDI     0x12000,R11
727
        FJSR(nowait_pipeline_test,R0)
728 55 dgisselq
#endif  // NOWAIT_PIPELINE_TEST
729
 
730 69 dgisselq
#ifdef  BCMEM_TEST
731
        LDI     0x13000,R11
732
        CLR     R0
733
        LDI     -1,R1
734
        STO     R0,bcmemtestloc(PC)
735
        LOD     bcmemtestloc(PC),R1
736
        CMP     R0,R1
737
        TRAP.NZ R11
738
        CMP     0x13000,R11
739
        BZ      bcmemtest_cmploc_1
740
        STO     R11,bcmemtestloc(PC)
741
bcmemtest_cmploc_1:
742
        LOD     bcmemtestloc(PC),R0
743
        CMP     R0,R11
744
        TRAP.Z  R11
745
        CLR     R0
746
        CMP     R0,R11
747
        BZ      bcmemtest_cmploc_2
748
        STO.NZ  R11,bcmemtestloc(PC)
749
bcmemtest_cmploc_2:
750
        NOOP
751
        LOD     bcmemtestloc(PC),R0
752
        CMP     R0,R11
753
        TRAP.NZ R11
754
        BRA     end_bcmemtest
755
bcmemtestloc:
756
        WORD    0
757
end_bcmemtest:
758
#endif
759 123 dgisselq
 
760
#ifdef  PIPELINE_MEMORY_RACE_CONDITIONS
761
        LDI     0x14000,R11
762
        FJSR(pipeline_memory_race_test,R0)
763
#endif // PIPELINE_MEMORY_RACE_CONDITIONS
764
 
765 2 dgisselq
// Return success / Test the trap interrupt
766
        clr     r11
767 103 dgisselq
        trap    r11     // FAILS HERE FAILS FAILS FAILS !!!!!!!!!!!
768 2 dgisselq
        noop
769
        noop
770
 
771
        busy
772
 
773
// And, in case we miss a halt ...
774
        halt
775 16 dgisselq
 
776
// Now, let's test whether or not we can handle a subroutine
777 19 dgisselq
#ifdef  PUSH_TEST
778 16 dgisselq
reverse_bit_order:
779 69 dgisselq
        SUB     3,SP
780
        STO     R1,(SP)         ; R1 will be our loop counter
781
        STO     R2,1(SP)        ; R2 will be our accumulator and eventual result
782
        STO     R4,2(SP)
783 16 dgisselq
        LDI     32,R1
784
        CLR     R2
785 34 dgisselq
reverse_bit_order_loop:
786 16 dgisselq
        LSL     1,R2
787
        LSR     1,R0
788
        OR.C    1,R2
789
        SUB     1,R1
790
        BNZ     reverse_bit_order_loop
791
        MOV     R2,R0
792 69 dgisselq
        LOD     (SP),R1
793
        LOD     1(SP),R2
794
        LOD     2(SP),R4
795
        ADD     3,SP
796
        JMP     R4
797 19 dgisselq
#endif
798 39 dgisselq
 
799 55 dgisselq
; The pipeline stack test examines whether or not a series of memory commands
800
; can be evaluated right after the other without problems.  This depends upon
801
; the calling routine to properly set up registers to be tested.
802
;
803
; This is also an incomplete test, as nothing is done to test how these
804
; pipeline reads/writes are affected by condition codes.
805
;
806 39 dgisselq
#ifdef  PIPELINE_STACK_TEST
807
pipeline_stack_test:
808
        SUB     13,SP
809 69 dgisselq
        STO     R0,(SP)
810
        STO     R1,1(SP)
811
        STO     R2,2(SP)
812
        STO     R3,3(SP)
813
        STO     R4,4(SP)
814
        STO     R5,5(SP)
815
        STO     R6,6(SP)
816
        STO     R7,7(SP)
817
        STO     R8,8(SP)
818
        STO     R9,9(SP)
819
        STO     R10,10(SP)
820
        STO     R11,11(SP)
821
        STO     R12,12(SP)
822 39 dgisselq
        XOR     -1,R0
823
        XOR     -1,R1
824
        XOR     -1,R2
825
        XOR     -1,R3
826
        XOR     -1,R4
827
        XOR     -1,R5
828
        XOR     -1,R6
829
        XOR     -1,R7
830
        XOR     -1,R8
831
        XOR     -1,R9
832
        XOR     -1,R10
833
        XOR     -1,R11
834
        XOR     -1,R12
835 69 dgisselq
        LOD     (SP),R0
836
        LOD     1(SP),R1
837
        LOD     2(SP),R2
838
        LOD     3(SP),R3
839
        LOD     4(SP),R4
840
        LOD     5(SP),R5
841
        LOD     6(SP),R6
842
        LOD     7(SP),R7
843
        LOD     8(SP),R8
844
        LOD     9(SP),R9
845
        LOD     10(SP),R10
846
        LOD     11(SP),R11
847
        LOD     12(SP),R12
848 39 dgisselq
        ADD     13,SP
849 69 dgisselq
        JMP     R7
850 39 dgisselq
#endif // PIPELINE_STACK_TEST
851
 
852 46 dgisselq
#ifdef  MEM_PIPELINE_TEST
853
mem_pipeline_test:
854
        SUB     4,SP
855 69 dgisselq
        STO     R0,(SP)
856
        STO     R1,1(SP)
857 46 dgisselq
        LDI     0x10000,R11
858
        ;
859
        ; Test #1 ... Let's start by writing a value to memory
860
        LDI     -1,R0
861
        CLR     R1
862 69 dgisselq
        STO     R0,2(SP)
863
        LOD     2(SP),R1
864 46 dgisselq
        CMP     R1,R0
865
        MOV.NZ  R11,CC
866
 
867
        ; Test #2, reading and then writing a value from memory
868
        NOP
869
        NOP
870
        CLR     R0
871
        CLR     R1
872 69 dgisselq
        LOD     2(SP),R0        ; This should load back up our -1 value
873
        STO     R0,3(SP)
874 46 dgisselq
        ; Insist that the pipeline clear
875 69 dgisselq
        LOD     2(SP),R0
876 46 dgisselq
        ; Now let's try loading into R1
877
        NOP
878
        NOP
879
        NOP
880
        NOP
881 69 dgisselq
        LOD     3(SP),R1
882 46 dgisselq
        CMP     R1,R0
883
        MOV.NZ  R11,CC
884
 
885 69 dgisselq
        LOD     (SP),R0
886
        LOD     1(SP),R1
887 46 dgisselq
        ADD     4,SP
888 69 dgisselq
        JMP     R0
889 46 dgisselq
#endif
890
 
891 60 dgisselq
#ifdef  CONDITIONAL_EXECUTION_TEST
892
conditional_execution_test:
893 69 dgisselq
        SUB     1,SP
894
        STO     R0,(SP)
895
        ;
896 60 dgisselq
        CLRF    R0
897
        ADD.Z   1,R0
898
        TRAP.NZ R11
899
        CMP.Z   0,R0
900
        TRAP.Z  R11
901
 
902 69 dgisselq
        LOD     (SP),R0
903
        ADD     1,SP
904
        JMP     R0
905 60 dgisselq
#endif
906
 
907 55 dgisselq
;
908
; Pipeline stalls have been hideous problems for me.  The CPU has been modified
909
; with special logic to keep stages from stalling.  For the most part, this
910
; means that ALU and memory results may be accessed either before or as they
911
; are written to the register file.  This set of code is designed to test
912
; whether this bypass logic works.
913
#ifdef  NOWAIT_PIPELINE_TEST
914
nowait_pipeline_test:
915
        ; Allocate for us some number of registers
916
        ;
917 60 dgisselq
        SUB     6,SP
918
        ; Leave a spot open on the stack for a local variable,
919
        ; kept in memory.
920 69 dgisselq
        STO     R0,(SP)
921
        STO     R1,1(SP)
922
        STO     R2,2(SP)
923
        STO     R3,3(SP)
924
        STO     R4,4(SP)
925 55 dgisselq
        ;
926
        ; Let's start with ALU-ALU testing
927
        ;       AA: result->input A
928 60 dgisselq
        CLR     R0
929
        ADD     1,R0
930
        CMP     1,R0
931
        TRAP.NZ R11
932
 
933 55 dgisselq
        ;       AA: result->input B
934 60 dgisselq
        CLR     R0
935
        CLR     R1
936
        ADD     1,R0
937
        CMP     R0,R1
938
        TRAP.Z  R11
939
 
940 55 dgisselq
        ;       AA: result->input A on condition
941 60 dgisselq
        CLRF    R0
942
        ADD.Z   5,R0
943
        CMP     5,R0
944
        TRAP.NZ R11
945
 
946 55 dgisselq
        ;       AA: result->input B on condition
947 60 dgisselq
        CLR     R0
948
        CLRF    R1
949
        ADD.Z   5,R0
950
        CMP     R0,R1
951
        TRAP.Z  R11
952
 
953 55 dgisselq
        ;       AA: result->input B plus offset
954 60 dgisselq
        CLR     R0
955
        CLRF    R1
956
        ADD     5,R0
957
        CMP     -5(R0),R1
958
        TRAP.NZ R11
959
 
960 55 dgisselq
        ;       AA: result->input B plus offset on condition
961 60 dgisselq
        CLR     R0
962
        CLRF    R1
963
        ADD.Z   5,R0
964
        CMP     -5(R0),R1
965
        TRAP.NZ R11
966
 
967 55 dgisselq
        ;
968
        ; Then we need to do ALU-Mem input testing
969 60 dgisselq
        ;
970
        CLR     R0
971 69 dgisselq
        STO     R0,5(SP)
972 60 dgisselq
        LDI     8352,R0
973 69 dgisselq
        LOD     5(SP),R0
974 60 dgisselq
        TST     -1,R0
975
        TRAP.NZ R11
976
 
977
        LDI     937,R0          ; Let's try again, this time something that's
978 69 dgisselq
        STO     R0,5(SP)        ; not zero
979 60 dgisselq
        NOOP
980 69 dgisselq
        LOD     5(SP),R0
981 60 dgisselq
        CMP     938,R0          ; Let's not compare with self, let's that
982
        TRAP.GE R11             ; masks a problem--compare with a different
983
        CMP     936,R0          ; number instead.
984
        TRAP.LT R11
985
 
986 55 dgisselq
        ; Mem output->ALU input testing
987 60 dgisselq
        ;       We just did that as partof our last test
988 55 dgisselq
        ; Mem output->MEM input testing
989
        ;
990 60 dgisselq
        LDI     5328,R2
991 69 dgisselq
        LOD     5(SP),R2
992
        STO     R2,5(SP)
993
        LOD     5(SP),R1
994 60 dgisselq
        CMP     937,R1
995
        TRAP.NZ R11
996
        ;
997 69 dgisselq
        LOD     (SP),R0
998
        LOD     1(SP),R1
999
        LOD     2(SP),R2
1000
        LOD     3(SP),R3
1001
        LOD     4(SP),R4
1002 60 dgisselq
        ADD     6,SP
1003 69 dgisselq
        JMP     R0
1004 55 dgisselq
#endif  // NOWAIT_PIPELINE_TEST
1005
 
1006 123 dgisselq
#ifdef  PIPELINE_MEMORY_RACE_CONDITIONS
1007
pipeline_memory_race_test:
1008
        SUB     3,SP
1009
        STO     R0,(SP)
1010
        STO     R1,1(SP)
1011
        STO     R2,2(SP)
1012 69 dgisselq
 
1013 123 dgisselq
        MOV     pipeline_memory_test_data(PC),R0
1014
        LOD     (R0),R0
1015
        LOD     (R0),R0
1016
        CMP     275,R0
1017
        MOV.NZ  R11,CC
1018
 
1019
        MOV     pipeline_memory_test_data(PC),R0
1020
        ; Here's the test sequence
1021
        LOD     (R0),R1
1022
        LOD     1(R0),R2
1023
        STO     R2,1(R1)
1024
        ; Make sure we clear the load pipeline
1025
        LOD     (R0),R1
1026
        ; Load our written value
1027
        LOD     2(R0),R2
1028
        CMP     275,R2
1029
        MOV.NZ  R11,CC
1030
 
1031
        ;
1032
        ; Next failing sequence:
1033
        ;       LOD -x(R12),R0
1034
        ;       LOD y(R0),R0
1035
        MOV     pipeline_memory_test_data(PC),R0
1036
        MOV     1(R0),R1
1037
        STO     R1,1(R0)
1038
        LDI     3588,R2         ; Just some random value
1039
        STO     R2,2(R0)
1040
        MOV     R0,R1
1041
        ; Here's the test sequence
1042
        LOD     (R0),R1
1043
        LOD     1(R1),R1
1044
        CMP     R2,R1
1045
        MOV.NZ  R11,CC
1046
 
1047
        LOD     (SP),R0
1048
        LOD     1(SP),R1
1049
        LOD     2(SP),R2
1050
        ADD     3,SP
1051
        JMP     R0
1052
pipeline_memory_test_data:
1053
        .dat    __here__+0x0100000+1
1054
        .dat    275
1055
        .dat    0
1056
#endif
1057
 
1058
 
1059 16 dgisselq
        fill    512,0
1060 34 dgisselq
stack:  // Must point to a valid word initially
1061 16 dgisselq
        word    0

powered by: WebSVN 2.1.0

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