;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;
|
;
|
; Filename: test.S
|
; Filename: test.S
|
;
|
;
|
; Project: Zip CPU -- a small, lightweight, RISC CPU soft core
|
; Project: Zip CPU -- a small, lightweight, RISC CPU soft core
|
;
|
;
|
; Purpose: A disorganized test, just showing some initial operation of
|
; Purpose: A disorganized test, just showing some initial operation of
|
; the CPU. As a disorganized test, it doesn't prove anything
|
; the CPU. As a disorganized test, it doesn't prove anything
|
; beyond the generic operation of the CPU.
|
; beyond the generic operation of the CPU.
|
;
|
;
|
; Status: As of August, 2015, this file assembles, builds, and passes
|
; Status: As of August, 2015, this file assembles, builds, and passes
|
; all of its tests in the Verilator simulator.
|
; all of its tests in the Verilator simulator.
|
;
|
;
|
|
; Okay, as of 15 August, there are now some tests that don't pass.
|
|
; In particular, the #include test used to pass but didn't pass today.
|
|
; Likewise the PUSH() macro test hasn't passed yet. Finally, be aware
|
|
; that this implementation is specific to where it loads on a board.
|
|
; I tried loading it on my Basys development board, where I had placed
|
|
; RAM in a different location and ... things didn't work out so well.
|
|
; So grep the __here__ line and adjust it for where you intend to load
|
|
; this file.
|
|
;
|
|
; In general, as I'm building the CPU, I'm modifying this file to place
|
|
; more and more capability tests within the file. If the Lord is
|
|
; willing, this will become the proof that the CPU completely works.
|
|
;
|
|
;
|
; Creator: Dan Gisselquist, Ph.D.
|
; Creator: Dan Gisselquist, Ph.D.
|
; Gisselquist Tecnology, LLC
|
; Gisselquist Tecnology, LLC
|
;
|
;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;
|
;
|
; Copyright (C) 2015, Gisselquist Technology, LLC
|
; Copyright (C) 2015, Gisselquist Technology, LLC
|
;
|
;
|
; This program is free software (firmware): you can redistribute it and/or
|
; This program is free software (firmware): you can redistribute it and/or
|
; modify it under the terms of the GNU General Public License as published
|
; modify it under the terms of the GNU General Public License as published
|
; by the Free Software Foundation, either version 3 of the License, or (at
|
; by the Free Software Foundation, either version 3 of the License, or (at
|
; your option) any later version.
|
; your option) any later version.
|
;
|
;
|
; This program is distributed in the hope that it will be useful, but WITHOUT
|
; This program is distributed in the hope that it will be useful, but WITHOUT
|
; ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
|
; ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
|
; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
; for more details.
|
; for more details.
|
;
|
;
|
; License: GPL, v3, as defined and found on www.gnu.org,
|
; License: GPL, v3, as defined and found on www.gnu.org,
|
; http://www.gnu.org/licenses/gpl.html
|
; http://www.gnu.org/licenses/gpl.html
|
;
|
;
|
;
|
;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;
|
;
|
#include "sys.i"
|
// #include "sys.i"
|
sys.bus equ 0xc0000000
|
sys.bus equ 0xc0000000
|
sys.breaken equ 0x080
|
sys.breaken equ 0x080
|
sys.step equ 0x040
|
sys.step equ 0x040
|
sys.gie equ 0x020
|
sys.gie equ 0x020
|
sys.sleep equ 0x010
|
sys.sleep equ 0x010
|
sys.ccv equ 0x008
|
sys.ccv equ 0x008
|
sys.ccn equ 0x004
|
sys.ccn equ 0x004
|
sys.ccc equ 0x002
|
sys.ccc equ 0x002
|
sys.ccz equ 0x001
|
sys.ccz equ 0x001
|
sys.bu.pic equ 0x000
|
sys.bu.pic equ 0x000
|
sys.bus.wdt equ 0x001
|
sys.bus.wdt equ 0x001
|
sys.bus.cache equ 0x002
|
sys.bus.cache equ 0x002
|
sys.bus.ctrpic equ 0x003
|
sys.bus.ctrpic equ 0x003
|
sys.bus.tma equ 0x004
|
sys.bus.tma equ 0x004
|
sys.bus.tmb equ 0x005
|
sys.bus.tmb equ 0x005
|
sys.bus.tmc equ 0x006
|
sys.bus.tmc equ 0x006
|
sys.bus.jiffies equ 0x007
|
sys.bus.jiffies equ 0x007
|
sys.bus.mtask equ 0x008
|
sys.bus.mtask equ 0x008
|
sys.bus.mpstl equ 0x009
|
sys.bus.mpstl equ 0x009
|
sys.bus.mastl equ 0x00a
|
sys.bus.mastl equ 0x00a
|
sys.bus.mstl equ 0x00b
|
sys.bus.mstl equ 0x00b
|
sys.bus.utask equ 0x00c
|
sys.bus.utask equ 0x00c
|
sys.bus.upstl equ 0x00d
|
sys.bus.upstl equ 0x00d
|
sys.bus.uastl equ 0x00e
|
sys.bus.uastl equ 0x00e
|
sys.bus.ustl equ 0x00f
|
sys.bus.ustl equ 0x00f
|
#define DO_TEST_ASSEMBLER
|
#define DO_TEST_ASSEMBLER
|
test:
|
test:
|
#ifdef DO_TEST_ASSEMBLER
|
#ifdef DO_TEST_ASSEMBLER
|
; We start out by testing our assembler. We give it some instructions, which
|
; We start out by testing our assembler. We give it some instructions, which
|
; are then manually checked by disassembling/dumping the result and making
|
; are then manually checked by disassembling/dumping the result and making
|
; certain they match. This is not an automated test, but it is an important
|
; certain they match. This is not an automated test, but it is an important
|
; one.
|
; one.
|
noop
|
noop
|
bra continue_test_with_testable_instructions
|
bra continue_test_with_testable_instructions
|
break
|
break
|
wait
|
wait
|
busy
|
busy
|
rtu
|
rtu
|
continue_test_with_testable_instructions:
|
continue_test_with_testable_instructions:
|
; Now, let's place the assembler into a known state
|
; Now, let's place the assembler into a known state
|
clr r0
|
clr r0
|
clr r1
|
clr r1
|
clr r2
|
clr r2
|
clr r3
|
clr r3
|
clr r4
|
clr r4
|
clr r5
|
clr r5
|
clr r6
|
clr r6
|
clr r7
|
clr r7
|
clr r9
|
clr r9
|
clr r10
|
clr r10
|
clr r11
|
clr r11
|
clr r12
|
clr r12
|
clr r13
|
clr r13
|
; Don't clear the CC register
|
; Don't clear the CC register
|
; Don't clear the SP register
|
; Don't clear the SP register
|
; And repeat for the user registers
|
; And repeat for the user registers
|
mov R0,uR0
|
mov R0,uR0
|
mov R0,uR1
|
mov R0,uR1
|
mov R0,uR2
|
mov R0,uR2
|
mov R0,uR3
|
mov R0,uR3
|
mov R0,uR4
|
mov R0,uR4
|
mov R0,uR5
|
mov R0,uR5
|
mov R0,uR6
|
mov R0,uR6
|
mov R0,uR7
|
mov R0,uR7
|
mov R0,uR8
|
mov R0,uR8
|
mov R0,uR9
|
mov R0,uR9
|
mov R0,uR10
|
mov R0,uR10
|
mov R0,uR11
|
mov R0,uR11
|
mov R0,uR12
|
mov R0,uR12
|
mov R0,uR13
|
mov R0,uR13
|
mov R0,uCC
|
mov R0,uCC
|
; Don't clear the user PC register
|
; Don't clear the user PC register
|
; Now, let's try loading some constants into registers
|
; Now, let's try loading some constants into registers
|
|
; Specifically, we're testing the LDI, LDIHI, and LDILO instructions
|
dead_beef equ 0xdeadbeef
|
dead_beef equ 0xdeadbeef
|
ldi 0x0dead,r5
|
ldi 0x0dead,r5
|
ldi 0x0beef,r6
|
ldi 0x0beef,r6
|
ldi 0xdeadbeef,r7
|
ldi 0xdeadbeef,r7
|
ldihi 0xdead, r8
|
ldihi 0xdead, r8
|
ldilo 0xbeef, r8
|
ldilo 0xbeef, r8
|
ldi dead_beef,r9
|
ldi dead_beef,r9
|
cmp r5,r6
|
cmp r5,r6
|
bz test_failure
|
bz test_failure
|
cmp r7,r8
|
cmp r7,r8
|
bnz test_failure
|
bnz test_failure
|
ldi $deadbeefh,r7 ; Try loading with the $[HEX]h mneumonic
|
ldi $deadbeefh,r7 ; Try loading with the $[HEX]h mneumonic
|
cmp r7,r8
|
cmp r7,r8
|
bnz test_failure
|
bnz test_failure
|
cmp r7,r9
|
cmp r7,r9
|
bnz test_failure
|
bnz test_failure
|
bra skip_dead_beef
|
bra skip_dead_beef
|
dead_beef.base:
|
dead_beef.base:
|
word 0
|
word 0
|
fill 5,dead_beef
|
fill 5,dead_beef
|
word 0
|
word 0
|
dead_beef.zero equ 0
|
dead_beef.zero equ 0
|
dead_beef.values equ 1
|
dead_beef.values equ 1
|
skip_dead_beef:
|
skip_dead_beef:
|
lod dead_beef.base(pc),r10 ; Should load a zero here
|
lod dead_beef.base(pc),r10 ; Should load a zero here
|
cmp r10,r11 ; r11 should still be zero from init abv
|
cmp r10,r11 ; r11 should still be zero from init abv
|
bnz test_failure
|
bnz test_failure
|
mov dead_beef.base(pc),r10 ; Now, let's get the address
|
mov dead_beef.base(pc),r10 ; Now, let's get the address
|
lod dead_beef.values(r10),r10 ; r10 now equals 0xdeadbeef
|
lod dead_beef.values(r10),r10 ; r10 now equals 0xdeadbeef
|
cmp r10,r9
|
cmp r10,r9
|
bnz test_failure
|
bnz test_failure
|
|
|
; Test whether or not we can properly decode OCTAL values
|
; Test whether or not we can properly decode OCTAL values
|
clr r0 ; Re-clear our register set first
|
clr r0 ; Re-clear our register set first
|
clr r1
|
clr r1
|
clr r2
|
clr r2
|
clr r3
|
clr r3
|
clr r4
|
clr r4
|
clr r5
|
clr r5
|
clr r6
|
clr r6
|
clr r7
|
clr r7
|
clr r9
|
clr r9
|
clr r10
|
clr r10
|
clr r11
|
clr r11
|
clr r12
|
clr r12
|
clr r13
|
clr r13
|
;
|
;
|
ldi $024o,r0
|
ldi $024o,r0
|
ldi $20,r1
|
ldi $20,r1
|
cmp r0,r1
|
cmp r0,r1
|
bnz test_failure
|
bnz test_failure
|
ldi $024,r0
|
ldi $024,r0
|
cmp r0,r1
|
cmp r0,r1
|
bnz test_failure
|
bnz test_failure
|
clr r0
|
clr r0
|
clr r1
|
clr r1
|
mov $1+r0,r2
|
mov $1+r0,r2
|
mov $2+r0,r3
|
mov $2+r0,r3
|
mov $22h+r0,r4
|
mov $22h+r0,r4
|
mov $377h+r0,ur5
|
mov $377h+r0,ur5
|
noop
|
noop
|
nop
|
nop
|
add r2,r0
|
add r2,r0
|
add $32,r0
|
add $32,r0
|
add $-33,r0
|
add $-33,r0
|
bnz test_failure
|
bnz test_failure
|
not.z r0
|
not.z r0
|
bge test_failure
|
bge test_failure
|
junk_address:
|
junk_address:
|
clrf r0
|
clrf r0
|
bnz test_failure
|
bnz test_failure
|
ldi $5,r1
|
ldi $5,r1
|
cmp $0+r0,r1
|
cmp $0+r0,r1
|
not.lt r0
|
not.lt r0
|
not.ge r1
|
not.ge r1
|
mov junk_address(pc),r2 ; Test pc-relative addressing
|
mov junk_address(pc),r2 ; Test pc-relative addressing
|
mov junk_address(pc),r3
|
mov junk_address(pc),r3
|
cmp r2,r3
|
cmp r2,r3
|
bnz test_failure
|
bnz test_failure
|
lod junk_address(pc),r5 ; Test loads with pc-relative addressing
|
lod junk_address(pc),r5 ; Test loads with pc-relative addressing
|
lod junk_address(pc),r6
|
lod junk_address(pc),r6
|
cmp r5,r6
|
cmp r5,r6
|
bnz test_failure
|
bnz test_failure
|
; Now, let's test whether or not our LSR and carry flags work
|
; Now, let's test whether or not our LSR and carry flags work
|
ldi -1,r0 ; First test: shifting all the way should yield zero
|
ldi -1,r0 ; First test: shifting all the way should yield zero
|
lsr 32,r0
|
lsr 32,r0
|
cmp 0,r0
|
cmp 0,r0
|
bnz test_failure
|
bnz test_failure
|
ldi -1,r0 ; Second test: anything greater than zero should set
|
ldi -1,r0 ; Second test: anything greater than zero should set
|
lsr 0,r0 ; the carry flag
|
lsr 0,r0 ; the carry flag
|
bc test_failure
|
bc test_failure
|
lsr 1,r0
|
lsr 1,r0
|
tst sys.ccc,cc
|
tst sys.ccc,cc
|
bz test_failure
|
bz test_failure
|
lsr 31,r0
|
lsr 31,r0
|
tst sys.ccc,cc
|
tst sys.ccc,cc
|
bz test_failure
|
bz test_failure
|
lsr 1,r0
|
lsr 1,r0
|
bc test_failure
|
bc test_failure
|
; Now repeat the above tests, looking to see whether or not ASR works
|
; Now repeat the above tests, looking to see whether or not ASR works
|
ldi -1,r0
|
ldi -1,r0
|
asr 32,r0
|
asr 32,r0
|
cmp -1,r0
|
cmp -1,r0
|
bnz test_failure
|
bnz test_failure
|
ldi -1,r0
|
ldi -1,r0
|
asr 0,r0
|
asr 0,r0
|
bc test_failure
|
bc test_failure
|
cmp -1,r0
|
cmp -1,r0
|
bnz test_failure
|
bnz test_failure
|
asr 1,r0
|
asr 1,r0
|
tst sys.ccc,r14
|
tst sys.ccc,r14
|
bz test_failure
|
bz test_failure
|
asr 30,r0
|
asr 30,r0
|
tst sys.ccc,r14
|
tst sys.ccc,r14
|
bz test_failure
|
bz test_failure
|
#endif
|
#endif
|
|
|
#ifdef NOONE // Testing comments after ifdef
|
#ifdef NOONE // Testing comments after ifdef
|
#else ; After else
|
#else ; After else
|
#endif /* and after endif */
|
#endif /* and after endif */
|
testbench:
|
testbench:
|
// Let's build a software test bench.
|
// Let's build a software test bench.
|
ldi $c0000000h,r12 ; Set R12 to point to our peripheral address
|
ldi $c0000000h,r12 ; Set R12 to point to our peripheral address
|
mov r12,ur12
|
mov r12,ur12
|
mov test_start(pc),upc
|
mov test_start(pc),upc
|
ldi 0x8000ffff,r0 ; Clear interrupts, turn all vectors off
|
ldi 0x8000ffff,r0 ; Clear interrupts, turn all vectors off
|
sto r0,(r12)
|
sto r0,(r12)
|
rtu
|
rtu
|
mov ucc,r0
|
mov ucc,r0
|
tst -256,r0
|
tst -256,r0
|
bnz test_failure
|
bnz test_failure
|
halt
|
halt
|
// Go into an infinite loop if the trap fails
|
// Go into an infinite loop if the trap fails
|
// Permanent loop instruction -- a busy halt if you will
|
// Permanent loop instruction -- a busy halt if you will
|
test_failure:
|
test_failure:
|
busy
|
busy
|
|
|
; Now for a series of tests. If the test fails, call the trap
|
; Now for a series of tests. If the test fails, call the trap
|
; interrupt with the test number that failed. Upon completion,
|
; interrupt with the test number that failed. Upon completion,
|
; call the trap with #0.
|
; call the trap with #0.
|
|
|
; Test LDI to PC
|
; Test LDI to PC
|
; Some data registers
|
; Some data registers
|
test_data:
|
test_data:
|
.dat __here__+0x0100000+5
|
.dat __here__+0x0100000+5
|
test_start:
|
test_start:
|
ldi $0x0100,r11
|
ldi $0x0100,r11
|
lod test_data+pc,pc
|
lod test_data+pc,pc
|
clr r11
|
clr r11
|
noop
|
noop
|
cmp $0,r11
|
cmp $0,r11
|
trap.z r11
|
trap.z r11
|
add $1,r0
|
add $1,r0
|
add $1,r0
|
add $1,r0
|
|
|
// Let's test whether overflow works
|
// Let's test whether overflow works
|
ldi $0x0200,r11
|
ldi $0x0200,r11
|
ldi $-1,r0
|
ldi $-1,r0
|
lsr $1,r0
|
lsr $1,r0
|
add $1,r0
|
add $1,r0
|
bv first_overflow_passes
|
bv first_overflow_passes
|
trap r11
|
trap r11
|
first_overflow_passes:
|
first_overflow_passes:
|
// Overflow set from subtraction
|
// Overflow set from subtraction
|
ldi $0x0300,r11
|
ldi $0x0300,r11
|
ldi $1,r0
|
ldi $1,r0
|
rol $31,r0 ; rol $31,r0
|
rol $31,r0 ; rol $31,r0
|
sub $1,r0
|
sub $1,r0
|
bv subtraction_overflow_passes
|
bv subtraction_overflow_passes
|
trap r11
|
trap r11
|
subtraction_overflow_passes:
|
subtraction_overflow_passes:
|
// Overflow set from LSR
|
// Overflow set from LSR
|
ldi $0x0400,r11
|
ldi $0x0400,r11
|
ldi $1,r0
|
ldi $1,r0
|
rol $31,r0 ; rol $31,r0
|
rol $31,r0 ; rol $31,r0
|
lsr $1,r0
|
lsr $1,r0
|
bv lsr_overflow_passes
|
bv lsr_overflow_passes
|
trap r11
|
trap r11
|
lsr_overflow_passes:
|
lsr_overflow_passes:
|
// Overflow set from LSL
|
// Overflow set from LSL
|
ldi $0x0500,r11
|
ldi $0x0500,r11
|
ldi $1,r0
|
ldi $1,r0
|
rol $30,r0
|
rol $30,r0
|
lsl $1,r0
|
lsl $1,r0
|
bv lsl_overflow_passes
|
bv lsl_overflow_passes
|
trap r11
|
trap r11
|
lsl_overflow_passes:
|
lsl_overflow_passes:
|
// Overflow set from LSL, negative to positive
|
// Overflow set from LSL, negative to positive
|
ldi $0x0600,r11
|
ldi $0x0600,r11
|
ldi $1,r0
|
ldi $1,r0
|
rol $31,r0
|
rol $31,r0
|
lsl $1,r0
|
lsl $1,r0
|
bv second_lsl_overflow_passes
|
bv second_lsl_overflow_passes
|
trap r11
|
trap r11
|
second_lsl_overflow_passes:
|
second_lsl_overflow_passes:
|
// Test carry
|
// Test carry
|
ldi $0x0700,r11
|
ldi $0x0700,r11
|
ldi $-1,r0
|
ldi $-1,r0
|
add $1,r0
|
add $1,r0
|
tst $2,cc
|
tst $2,cc
|
trap.z r11
|
trap.z r11
|
// and carry from subtraction
|
// and carry from subtraction
|
ldi $0x0800,r11
|
ldi $0x0800,r11
|
sub $1,r0
|
sub $1,r0
|
tst $2,cc
|
tst $2,cc
|
trap.z r11
|
trap.z r11
|
|
|
// Let's try a loop: for i=0; i<5; i++)
|
// Let's try a loop: for i=0; i<5; i++)
|
// We'll use R0=i, Immediates for 5
|
// We'll use R0=i, Immediates for 5
|
ldi $0x0800,r11
|
ldi $0x0800,r11
|
clr r0
|
clr r0
|
for_loop:
|
for_loop:
|
noop
|
noop
|
add $1,r0
|
add $1,r0
|
cmp $5,r0
|
cmp $5,r0
|
blt for_loop
|
blt for_loop
|
//
|
//
|
// Let's try a reverse loop. Such loops are usually cheaper to
|
// Let's try a reverse loop. Such loops are usually cheaper to
|
// implement, and this one is no different: 2 loop instructions
|
// implement, and this one is no different: 2 loop instructions
|
// (minus setup instructions) vs 3 from before.
|
// (minus setup instructions) vs 3 from before.
|
// R0 = 5; (from before)
|
// R0 = 5; (from before)
|
// do {
|
// do {
|
// } while (R0 > 0);
|
// } while (R0 > 0);
|
ldi $0x0900,r11
|
ldi $0x0900,r11
|
bgt_loop:
|
bgt_loop:
|
noop
|
noop
|
sub $1,r0
|
sub $1,r0
|
bgt bgt_loop
|
bgt bgt_loop
|
|
|
// How about the same thing with a >= comparison?
|
// How about the same thing with a >= comparison?
|
// R1 = 5; // Need to do this explicitly
|
// R1 = 5; // Need to do this explicitly
|
// do {
|
// do {
|
// } while(R1 >= 0);
|
// } while(R1 >= 0);
|
ldi $20,r0
|
ldi $20,r0
|
ldi $5,r1
|
ldi $5,r1
|
bge_loop:
|
bge_loop:
|
noop
|
noop
|
sub $1,r1
|
sub $1,r1
|
bge bge_loop
|
bge bge_loop
|
|
|
// Let's try the reverse loop again, only this time we'll store our
|
// Let's try the reverse loop again, only this time we'll store our
|
// loop variable in memory.
|
// loop variable in memory.
|
// R0 = 5; (from before)
|
// R0 = 5; (from before)
|
// do {
|
// do {
|
// } while (R0 > 0);
|
// } while (R0 > 0);
|
ldi $0x0a00,r11
|
ldi $0x0a00,r11
|
bra mem_loop_test
|
bra mem_loop_test
|
loop_var:
|
loop_var:
|
.dat 0
|
.dat 0
|
mem_loop_test:
|
mem_loop_test:
|
mov loop_var(pc),r1
|
mov loop_var(pc),r1
|
ldi $5,r0
|
ldi $5,r0
|
clr r2
|
clr r2
|
sto r0,(r1)
|
sto r0,(r1)
|
mem_loop:
|
mem_loop:
|
add $1,r2
|
add $1,r2
|
add $14,r0
|
add $14,r0
|
lod (r1),r0
|
lod (r1),r0
|
sub $1,r0
|
sub $1,r0
|
sto r0,(r1)
|
sto r0,(r1)
|
bgt mem_loop
|
bgt mem_loop
|
cmp $5,r2
|
cmp $5,r2
|
trap.ne r11
|
trap.ne r11
|
|
|
|
// Let's test whether LSL works
|
|
ldi $0x0b00,r11
|
|
ldi 0x035,r2
|
|
lsl 8,r2
|
|
ldi 0x03500,r1
|
|
cmp r2,r1
|
|
trap.ne r11
|
|
ldi 0x074,r0
|
|
and 0x0ff,r0
|
|
or r0,r2
|
|
cmp 0x03574,r2
|
|
trap.ne r11
|
|
|
// Return success / Test the trap interrupt
|
// Return success / Test the trap interrupt
|
clr r11
|
clr r11
|
trap r11
|
trap r11
|
noop
|
noop
|
noop
|
noop
|
|
|
busy
|
busy
|
|
|
// And, in case we miss a halt ...
|
// And, in case we miss a halt ...
|
halt
|
halt
|
|
|
// Now, let's test whether or not we can handle a subroutine
|
// Now, let's test whether or not we can handle a subroutine
|
|
#ifdef PUSH_TEST
|
reverse_bit_order:
|
reverse_bit_order:
|
PUSH(R1,SP)
|
PUSH(R1,SP)
|
PUSH(R2,SP)
|
PUSH(R2,SP)
|
LDI 32,R1
|
LDI 32,R1
|
CLR R2
|
CLR R2
|
LSL 1,R2
|
LSL 1,R2
|
LSR 1,R0
|
LSR 1,R0
|
OR.C 1,R2
|
OR.C 1,R2
|
SUB 1,R1
|
SUB 1,R1
|
BNZ reverse_bit_order_loop
|
BNZ reverse_bit_order_loop
|
MOV R2,R0
|
MOV R2,R0
|
POP(R2,SP)
|
POP(R2,SP)
|
POP(R1,SP)
|
POP(R1,SP)
|
RET
|
RET
|
|
#endif
|
fill 512,0
|
fill 512,0
|
stack:
|
stack:
|
word 0
|
word 0
|
|
|