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

Subversion Repositories zipcpu

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

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
;               Gisselquist Tecnology, LLC
30
;
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 26 dgisselq
#define BREAK_TEST
80
#define OVERFLOW_TEST
81
#define CARRY_TEST
82
#define LOOP_TEST
83
#define SHIFT_TEST
84
#define TRAP_TEST
85
#define MPY_TEST
86 34 dgisselq
#define PUSH_TEST
87 2 dgisselq
test:
88 13 dgisselq
#ifdef  DO_TEST_ASSEMBLER
89
; We start out by testing our assembler.  We give it some instructions, which
90
; are then manually checked  by disassembling/dumping the result and making
91
; certain they match.  This is not an automated test, but it is an important
92
; one.
93
        noop
94
        bra     continue_test_with_testable_instructions
95
        break
96
        wait
97 26 dgisselq
        break
98 13 dgisselq
        busy
99
        rtu
100
continue_test_with_testable_instructions:
101
        ; Now, let's place the assembler into a known state
102 2 dgisselq
        clr     r0
103 13 dgisselq
        clr     r1
104
        clr     r2
105
        clr     r3
106
        clr     r4
107
        clr     r5
108
        clr     r6
109
        clr     r7
110 36 dgisselq
        clr     r8
111 13 dgisselq
        clr     r9
112
        clr     r10
113
        clr     r11
114
        clr     r12
115
        clr     r13
116
        ; Don't clear the CC register
117
        ; Don't clear the SP register
118
        ; And repeat for the user registers
119
        mov     R0,uR0
120
        mov     R0,uR1
121
        mov     R0,uR2
122
        mov     R0,uR3
123
        mov     R0,uR4
124
        mov     R0,uR5
125
        mov     R0,uR6
126
        mov     R0,uR7
127
        mov     R0,uR8
128
        mov     R0,uR9
129
        mov     R0,uR10
130
        mov     R0,uR11
131
        mov     R0,uR12
132
        mov     R0,uR13
133
        mov     R0,uCC
134
        ; Don't clear the user PC register
135
        ; Now, let's try loading some constants into registers
136 19 dgisselq
        ; Specifically, we're testing the LDI, LDIHI, and LDILO instructions
137 13 dgisselq
dead_beef       equ     0xdeadbeef
138
        ldi     0x0dead,r5
139
        ldi     0x0beef,r6
140
        ldi     0xdeadbeef,r7
141
        ldihi   0xdead, r8
142
        ldilo   0xbeef, r8
143
        ldi     dead_beef,r9
144
        cmp     r5,r6
145
        bz      test_failure
146
        cmp     r7,r8
147
        bnz     test_failure
148
        ldi     $deadbeefh,r7   ; Try loading with the $[HEX]h mneumonic
149
        cmp     r7,r8
150
        bnz     test_failure
151
        cmp     r7,r9
152
        bnz     test_failure
153
        bra     skip_dead_beef
154
dead_beef.base:
155
        word    0
156
        fill    5,dead_beef
157
        word    0
158
dead_beef.zero          equ     0
159
dead_beef.values        equ     1
160
skip_dead_beef:
161
        lod     dead_beef.base(pc),r10  ; Should load a zero here
162
        cmp     r10,r11                 ; r11 should still be zero from init abv
163
        bnz     test_failure
164
        mov     dead_beef.base(pc),r10  ; Now, let's get the address
165
        lod     dead_beef.values(r10),r10       ; r10 now equals 0xdeadbeef
166
        cmp     r10,r9
167
        bnz     test_failure
168 34 dgisselq
 
169
; Test whether or not our operator precedence rules work
170
        ldi     5+3*8,r0
171
        ldi     3*8+5,r1
172
        cmp     r0,r1
173
        bnz     test_failure
174
        ldi     (5+3)*8,r0
175
        ldi     8*(3+5),r1
176
        cmp     r0,r1
177
        bnz     test_failure
178
 
179 13 dgisselq
; Test whether or not we can properly decode OCTAL values
180
        clr     r0      ; Re-clear our register set first
181
        clr     r1
182
        clr     r2
183
        clr     r3
184
        clr     r4
185
        clr     r5
186
        clr     r6
187
        clr     r7
188 36 dgisselq
        clr     r8
189 13 dgisselq
        clr     r9
190
        clr     r10
191
        clr     r11
192
        clr     r12
193
        clr     r13
194
        ;
195
        ldi     $024o,r0
196
        ldi     $20,r1
197
        cmp     r0,r1
198
        bnz     test_failure
199
        ldi     $024,r0
200
        cmp     r0,r1
201
        bnz     test_failure
202
        clr     r0
203
        clr     r1
204 2 dgisselq
        mov     $1+r0,r2
205
        mov     $2+r0,r3
206
        mov     $22h+r0,r4
207
        mov     $377h+r0,ur5
208
        noop
209
        nop
210
        add     r2,r0
211
        add     $32,r0
212
        add     $-33,r0
213 13 dgisselq
        bnz     test_failure
214 36 dgisselq
        not     r0
215 13 dgisselq
        bge     test_failure
216
junk_address:
217 2 dgisselq
        clrf    r0
218 13 dgisselq
        bnz     test_failure
219 2 dgisselq
        ldi     $5,r1
220
        cmp     $0+r0,r1
221
        not.lt  r0
222
        not.ge  r1
223 13 dgisselq
        mov     junk_address(pc),r2     ; Test pc-relative addressing
224
        mov     junk_address(pc),r3
225
        cmp     r2,r3
226
        bnz     test_failure
227
        lod     junk_address(pc),r5     ; Test loads with pc-relative addressing
228
        lod     junk_address(pc),r6
229
        cmp     r5,r6
230
        bnz     test_failure
231 26 dgisselq
#endif
232
 
233
#ifdef  NOONE // Testing comments after ifdef
234
#else   ; After else
235
#endif /* and after endif */
236
 
237
#ifdef  BREAK_TEST
238
breaktest:
239
        bra     breaksupervisor
240
breakuser:
241
        clr     r0
242
        mov     1+r0,r1
243
        mov     1+r1,r2
244
        mov     1+r2,r3
245
        break           ; At address 0x0100097
246
        mov     1+r4,r5
247
        mov     1+r5,r6
248
        clr     cc
249
        busy
250
breaksupervisor:
251 13 dgisselq
        ldi     -1,r0
252 26 dgisselq
        mov     breakuser(pc),upc
253
        rtu     ; Should just keep returning immediately
254
        mov     upc,r0
255
        rtu
256
        rtu
257
        mov     upc,r1
258
        cmp     r0,r1
259 13 dgisselq
        bnz     test_failure
260 26 dgisselq
#endif
261
 
262
#ifdef  TRAP_TEST
263
traptest:
264
        bra     traptest_supervisor
265
        busy
266
traptest_user:
267
        trap    0
268
        busy
269
traptest_supervisor:
270
        mov     traptest_user(pc),upc
271
        rtu
272
        mov     cc,r0
273
        tst     sys.cctrap,r0
274 13 dgisselq
        bz      test_failure
275
#endif
276 2 dgisselq
 
277
testbench:
278
        // Let's build a software test bench.
279 13 dgisselq
        ldi     $c0000000h,r12  ; Set R12 to point to our peripheral address
280 2 dgisselq
        mov     r12,ur12
281 13 dgisselq
        mov     test_start(pc),upc
282 34 dgisselq
        mov     stack(pc),usp
283 13 dgisselq
        ldi     0x8000ffff,r0   ; Clear interrupts, turn all vectors off
284
        sto     r0,(r12)
285 2 dgisselq
        rtu
286 13 dgisselq
        mov     ucc,r0
287 26 dgisselq
        cmp     sys.cctrap,r0
288 13 dgisselq
        bnz     test_failure
289 2 dgisselq
        halt
290 13 dgisselq
// Go into an infinite loop if the trap fails
291
// Permanent loop instruction -- a busy halt if you will
292
test_failure:
293 2 dgisselq
        busy
294
 
295
; Now for a series of tests.  If the test fails, call the trap
296
; interrupt with the test number that failed.  Upon completion,
297
; call the trap with #0.
298
 
299
; Test LDI to PC
300
; Some data registers
301 13 dgisselq
test_data:
302
        .dat    __here__+0x0100000+5
303 2 dgisselq
test_start:
304 26 dgisselq
        ldi     $0x01000,r11
305 36 dgisselq
        ldi     -1,r10
306 13 dgisselq
        lod     test_data+pc,pc
307 36 dgisselq
        clr     r10
308 2 dgisselq
        noop
309 36 dgisselq
        cmp     $0,r10
310 13 dgisselq
        trap.z  r11
311 2 dgisselq
        add     $1,r0
312
        add     $1,r0
313
 
314 26 dgisselq
#ifdef  OVERFLOW_TEST
315 2 dgisselq
// Let's test whether overflow works
316 26 dgisselq
        ldi     $0x02000,r11
317 2 dgisselq
        ldi     $-1,r0
318
        lsr     $1,r0
319
        add     $1,r0
320 13 dgisselq
        bv      first_overflow_passes
321
        trap    r11
322
first_overflow_passes:
323 2 dgisselq
// Overflow set from subtraction
324 26 dgisselq
        ldi     $0x03000,r11
325 2 dgisselq
        ldi     $1,r0
326 13 dgisselq
        rol     $31,r0                  ; rol $31,r0
327 2 dgisselq
        sub     $1,r0
328 13 dgisselq
        bv      subtraction_overflow_passes
329
        trap    r11
330
subtraction_overflow_passes:
331 2 dgisselq
// Overflow set from LSR
332 26 dgisselq
        ldi     $0x04000,r11
333 2 dgisselq
        ldi     $1,r0
334 13 dgisselq
        rol     $31,r0                  ; rol $31,r0
335 2 dgisselq
        lsr     $1,r0
336 13 dgisselq
        bv      lsr_overflow_passes
337
        trap    r11
338
lsr_overflow_passes:
339 2 dgisselq
// Overflow set from LSL
340 26 dgisselq
        ldi     $0x05000,r11
341 2 dgisselq
        ldi     $1,r0
342 13 dgisselq
        rol     $30,r0
343 2 dgisselq
        lsl     $1,r0
344 13 dgisselq
        bv      lsl_overflow_passes
345
        trap    r11
346
lsl_overflow_passes:
347 2 dgisselq
// Overflow set from LSL, negative to positive
348 26 dgisselq
        ldi     $0x06000,r11
349 2 dgisselq
        ldi     $1,r0
350 13 dgisselq
        rol     $31,r0
351 2 dgisselq
        lsl     $1,r0
352 13 dgisselq
        bv      second_lsl_overflow_passes
353
        trap    r11
354 26 dgisselq
#endif // OVERFLOW_TEST
355
#ifdef  CARRY_TEST
356 13 dgisselq
second_lsl_overflow_passes:
357 2 dgisselq
// Test carry
358 26 dgisselq
        ldi     $0x07000,r11
359 2 dgisselq
        ldi     $-1,r0
360
        add     $1,r0
361
        tst     $2,cc
362 13 dgisselq
        trap.z  r11
363 2 dgisselq
// and carry from subtraction
364 26 dgisselq
        ldi     $0x08000,r11
365
        clr     r0
366 2 dgisselq
        sub     $1,r0
367
        tst     $2,cc
368 13 dgisselq
        trap.z  r11
369 26 dgisselq
#endif
370 2 dgisselq
 
371 26 dgisselq
#ifdef  LOOP_TEST
372
 
373 2 dgisselq
// Let's try a loop: for i=0; i<5; i++)
374
//      We'll use R0=i, Immediates for 5
375 26 dgisselq
        ldi     $0x09000,r11
376 13 dgisselq
        clr     r0
377 2 dgisselq
for_loop:
378
        noop
379
        add     $1,r0
380
        cmp     $5,r0
381
        blt     for_loop
382
//
383
// Let's try a reverse loop.  Such loops are usually cheaper to
384
// implement, and this one is no different: 2 loop instructions
385
// (minus setup instructions) vs 3 from before.
386
// R0 = 5; (from before)
387
// do {
388
// } while (R0 > 0);
389 26 dgisselq
        ldi     $0x0a000,r11
390 2 dgisselq
bgt_loop:
391
        noop
392
        sub     $1,r0
393
        bgt     bgt_loop
394
 
395
// How about the same thing with a >= comparison?
396
// R1 = 5; // Need to do this explicitly
397
// do {
398
// } while(R1 >= 0);
399 13 dgisselq
        ldi     $20,r0
400 2 dgisselq
        ldi     $5,r1
401
bge_loop:
402
        noop
403
        sub     $1,r1
404
        bge     bge_loop
405
 
406
// Let's try the reverse loop again, only this time we'll store our
407
// loop variable in memory.
408
// R0 = 5; (from before)
409
// do {
410
// } while (R0 > 0);
411 26 dgisselq
        ldi     $0x0b000,r11
412 13 dgisselq
        bra     mem_loop_test
413 2 dgisselq
loop_var:
414
        .dat    0
415 13 dgisselq
mem_loop_test:
416
        mov     loop_var(pc),r1
417
        ldi     $5,r0
418
        clr     r2
419
        sto     r0,(r1)
420 2 dgisselq
mem_loop:
421
        add     $1,r2
422
        add     $14,r0
423
        lod     (r1),r0
424
        sub     $1,r0
425 13 dgisselq
        sto     r0,(r1)
426
        bgt     mem_loop
427 2 dgisselq
        cmp     $5,r2
428 13 dgisselq
        trap.ne r11
429 26 dgisselq
#endif
430 2 dgisselq
 
431 26 dgisselq
#ifdef  SHIFT_TEST
432
; Now, let's test whether or not our LSR and carry flags work
433
        ldi     $0x0c000,r11
434
        ldi     -1,r0   ; First test: shifting all the way should yield zero
435
        lsr     32,r0
436
        cmp     0,r0
437
        bnz     test_failure
438
        ldi     -1,r0   ; Second test: anything greater than zero should set
439
        lsr     0,r0    ; the carry flag
440
        bc      test_failure
441
        lsr     1,r0
442
        tst     sys.ccc,cc      ; FAILS HERE!!!  @0x010007c
443
        bz      test_failure
444
        lsr     31,r0
445
        tst     sys.ccc,cc
446
        bz      test_failure
447
        lsr     1,r0
448
        bc      test_failure
449
; Now repeat the above tests, looking to see whether or not ASR works
450
        ldi     -1,r0
451
        asr     32,r0
452
        cmp     -1,r0
453
        bnz     test_failure
454
        ldi     -1,r0
455
        asr     0,r0
456
        bc      test_failure
457
        cmp     -1,r0
458
        bnz     test_failure
459
        asr     1,r0
460
        tst     sys.ccc,r14
461
        bz      test_failure
462
        asr     30,r0
463
        tst     sys.ccc,r14
464
        bz      test_failure
465
 
466 19 dgisselq
// Let's test whether LSL works
467
        ldi     0x035,r2
468
        lsl     8,r2
469
        ldi     0x03500,r1
470
        cmp     r2,r1
471
        trap.ne r11
472
        ldi     0x074,r0
473
        and     0x0ff,r0
474
        or      r0,r2
475
        cmp     0x03574,r2
476
        trap.ne r11
477 26 dgisselq
#endif
478 19 dgisselq
 
479 26 dgisselq
#ifdef  MPY_TEST
480
 
481
// We have two multiply instructions.  Let's see if those work
482
        ldi     $0x0d000,r11    // Mark our test
483
        ldi     23171,r0        // = sqrt(2)/2 * 32768
484
        mpyu    r0,r0           // Should = 2/4 * 2^30 = 2^29 or thereabouts
485
        ldi     536895241,r2
486
        cmp     r0,r2
487
        trap.ne r11
488
        ldi     0x0ffff,r0
489
        mpyu    r0,r0
490
        ldi     0xfffe0001,r1
491
        cmp     r1,r0
492
        trap.ne r11
493
        ldi     0x08001,r0
494
        ldi     0x07fff,r1
495
        mpys    r0,r1           // FAILS: result is 0x008001 ??? (pipeline prob)
496
        ldi     0x3fff0001,r2
497
        neg     r2
498
        cmp     r2,r1           // @0x010011c
499
        trap.ne r11             //TRAP FAILS TO TRIGGER ????? (R2=0x0c000ffff,R1=0x0008001 -- did mpy even happen?)
500
        mpys    r0,r0           // FAILS: result is 0x40010001
501
        ldi     0x3fff0001,r2
502
        cmp     r2,r0
503
        trap.ne r11             // TRAP FAILS TO TRIGGER AGAIN
504
        ldi     0x08000,r0
505
        mpys    r0,r0           // R0 now equals 0x40000000
506
        ldi     0x40000000,r1
507
        cmp     r0,r1
508
        trap.ne r11
509
#endif
510 34 dgisselq
 
511
#ifdef  PUSH_TEST
512
        ldi     $0x0e000,r11    // Mark our test
513
        ldi     0x01248cab,r0
514
        ldi     0xd5312480,r1   // Let's see if we can preserve this as well
515
        mov     r1,r7
516
        JSR(reverse_bit_order,R4);      // *SP = 0x010013d
517
        cmp     r0,r1
518
        trap.ne r11
519
        cmp     r0,r7
520
        trap.ne r11
521
#endif
522 2 dgisselq
// Return success / Test the trap interrupt
523
        clr     r11
524 13 dgisselq
        trap    r11
525 2 dgisselq
        noop
526
        noop
527
 
528
        busy
529
 
530
// And, in case we miss a halt ...
531
        halt
532 16 dgisselq
 
533
// Now, let's test whether or not we can handle a subroutine
534 19 dgisselq
#ifdef  PUSH_TEST
535 16 dgisselq
reverse_bit_order:
536 36 dgisselq
        PUSH(R1,SP)     ; R1 will be our loop counter
537
        PUSH(R2,SP)     ; R2 will be our accumulator and eventual result
538 16 dgisselq
        LDI     32,R1
539
        CLR     R2
540 34 dgisselq
reverse_bit_order_loop:
541 16 dgisselq
        LSL     1,R2
542
        LSR     1,R0
543
        OR.C    1,R2
544
        SUB     1,R1
545
        BNZ     reverse_bit_order_loop
546
        MOV     R2,R0
547
        POP(R2,SP)
548
        POP(R1,SP)
549
        RET
550 19 dgisselq
#endif
551 16 dgisselq
        fill    512,0
552 34 dgisselq
stack:  // Must point to a valid word initially
553 16 dgisselq
        word    0

powered by: WebSVN 2.1.0

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