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

Subversion Repositories zipcpu

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

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

powered by: WebSVN 2.1.0

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