URL
https://opencores.org/ocsvn/zipcpu/zipcpu/trunk
Subversion Repositories zipcpu
Compare Revisions
- This comparison shows the changes necessary to convert path
/zipcpu/trunk/bench/asm
- from Rev 172 to Rev 202
- ↔ Reverse comparison
Rev 172 → Rev 202
/Makefile
4,15 → 4,42
# |
# Project: Zip CPU -- a small, lightweight, RISC CPU soft core |
# |
# Purpose: This makefile builds the various assembler level test benches |
# that exist. |
# Purpose: To direct and simplify the build of a variety of simple assembly |
# language test programs which will use one (or both) of the |
# ZipCPU simulators. |
# |
# Targets include: |
# |
# hellosim |
# Using the SIM instruction, prints Hello World to the screen. |
# |
# simuart |
# Same as hellosim, but without using the SIM instruction. This |
# *should* be able to run successfully on a verilated or |
# synthesized hardware, although I hvae yet to test it there. |
# |
# simtest |
# A set of simple tests designed to demonstrate if the simulator |
# works or not. |
# |
# clean |
# Removes the object file directory and any executables that have |
# been created. |
# |
# None of the files/targets below have any dependencies, or if they did, |
# GCC can't determine them, so thus there is no make depends step. |
# |
# To actually run one of these programs, list the program on the command |
# line with the ZipCPU simulator, zsim. |
# |
# |
# |
# Creator: Dan Gisselquist, Ph.D. |
# Gisselquist Technology, LLC |
# |
################################################################################ |
# |
# Copyright (C) 2015, Gisselquist Technology, LLC |
# Copyright (C) 2017, Gisselquist Technology, LLC |
# |
# 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 |
24,6 → 51,11
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
# for more details. |
# |
# You should have received a copy of the GNU General Public License along |
# with this program. (It's in the $(ROOT)/doc directory. Run make with no |
# target there if the PDF file isn't present.) If not, see |
# <http://www.gnu.org/licenses/> for a copy. |
# |
# License: GPL, v3, as defined and found on www.gnu.org, |
# http://www.gnu.org/licenses/gpl.html |
# |
30,42 → 62,72
# |
################################################################################ |
# |
all: zipdhry.z testdiv.z wdt.z halttest.z zipdhry.txt nullpc.txt poptest.txt |
ZDIR := ../../sw/zasm |
ZASM := $(ZDIR)/zasm |
ZDMP := $(ZDIR)/zdump |
LIBS := ../../sw/lib |
INCS := -I$(ZDIR)/ |
.PHONY: all |
all: $(OBJDIR)/ hellosim simtest simuart cmptest |
|
dump: zipdhry.txt testdiv.txt |
CC := zip-gcc |
CPP := zip-cpp |
AS := zip-as |
LD := zip-ld |
OBJDUMP := zip-objdump |
OBJDIR := obj-zip |
CFLAGS := -O3 |
LIBD := ../../sw/install/cross-tools/zip/lib |
LIBS := -L$(LIBD) -lzipbasic |
LDSCRIPT:= ../zipsim.ld |
|
halttest.z: halttest.S |
$(ZASM) $(INCS) $^ -o $@ |
zipdhry.z: zipdhry.S $(LIBS)/divs.S $(LIBS)/divu.S stack.S |
$(ZASM) $(INCS) $^ -o $@ |
zipdhry.txt: zipdhry.z |
$(ZDMP) zipdhry.z > zipdhry.txt |
$(OBJDIR)/%.o: %.c $(OBJDIR)/ |
$(CC) $(CFLAGS) -c $< -o $@ |
|
nullpc.z: nullpc.s |
$(ZASM) $(INCS) $^ -o $@ |
nullpc.txt: nullpc.z |
$(ZDMP) nullpc.z > nullpc.txt |
$(OBJDIR)/%.o: %.s $(OBJDIR)/ |
$(AS) $< -o $@ |
|
poptest.z: poptest.s |
$(ZASM) $(INCS) $^ -o $@ |
poptest.txt: poptest.z |
$(ZDMP) poptest.z > poptest.txt |
%.txt: % |
$(OBJDUMP) -dr $< > $@ |
|
wdt.z: wdt.S |
$(ZASM) $(INCS) $^ -o $@ |
# |
# hellosim |
# |
# This is an assembly version of Hello World that uses the new SIM instructions. |
# It should fail with an illegal instruction error if it is ever tried on an |
# RTL-synthesized implementation |
# |
hellosim: $(OBJDIR)/hellosim.o |
$(LD) -T $(LDSCRIPT) $< -o $@ |
|
.PHONY: testdiv |
testdiv: testdiv.z |
testdiv.z: testdiv.S $(LIBS)/divs.S $(LIBS)/divu.S stack.S |
$(ZASM) $(INCS) $^ -o $@ |
# |
# simuart |
# |
# This is an assembly version of Hello World that uses the UART in the |
# process. It doesn't use newlib or any other support tools, just binutils. |
# |
simuart: $(OBJDIR)/simuart.o |
$(LD) -T $(LDSCRIPT) $< -o $@ |
|
testdiv.txt: testdiv.z |
$(ZDMP) testdiv.z > testdiv.txt |
# |
# simtest |
# |
# This is just a simple series of instruction tests that should be able to be |
# used to determine whether the simulator has a basic amount of functionality. |
# Because the test includes #define, #ifdef, and #endif statements, though, it |
# needs to be run through the C pre-processor before it can go through the |
# assembler. Hence the build is a tocuh trickier, but still simple enough. |
# |
$(OBJDIR)/simtest.o: simtest.s $(OBJDIR)/ |
$(CPP) $< > $(OBJDIR)/simtest.s |
$(AS) $(OBJDIR)/simtest.s -o $@ |
|
simtest: $(OBJDIR)/simtest.o |
$(LD) -T $(LDSCRIPT) $< -o $@ |
|
cmptest: $(OBJDIR)/cmptest.o |
$(LD) -T $(LDSCRIPT) -Map=map.txt $< -o $@ |
|
|
$(OBJDIR)/: |
@bash -c "if [[ ! -e $(OBJDIR) ]]; then mkdir -p $(OBJDIR)/; fi" |
|
.PHONY: clean |
clean: |
rm -rf *.z zipdhry.txt testdiv.txt |
rm -rf $(OBJDIR)/ |
rm -rf hellosim simuart simtest |
/cputest.c
33,7 → 33,10
/////////////////////////////////////////////////////////////////////////////// |
// |
// |
#ifndef NULL |
#define NULL (void *)0 |
#endif |
|
volatile int *const UARTTX = (volatile int *)0x010b, |
* const UART_CTRL = (int *)0x0107; |
// #define ZIPSYS |
60,6 → 63,13
void zip_save_context(int *); |
void zip_halt(void); |
|
|
void txchr(char v); |
void txstr(const char *str); |
void txhex(int num); |
void tx4hex(int num); |
|
|
asm("\t.section\t.start\n" |
"\t.global\t_start\n" |
"\t.type\t_start,@function\n" |
110,7 → 120,7
|
|
extern int run_test(void *pc, void *stack); |
asm("\t.global\trun_test\n" |
asm("\t.text\n\t.global\trun_test\n" |
"\t.type\trun_test,@function\n" |
"run_test:\n" |
"\tCLR\tR3\n" |
125,11 → 135,11
"\tMOV\tR3,uR8\n" |
"\tMOV\tR3,uR9\n" |
"\tMOV\tR3,uR10\n" |
"\tMOV\tR1,uR11\n" |
"\tMOV\tR1,uR12\n" |
"\tMOV\tR2,uSP\n" |
"\tMOV\t0x20+R3,uCC\n" |
"\tMOV\tR1,uPC\n" |
"\tMOV\tR3,uR11\n" |
"\tMOV\tR3,uR12\n" |
"\tMOV\tR2,uSP\n" // uSP = stack |
"\tMOV\t0x20+R3,uCC\n" // Clear uCC of all but the GIE bit |
"\tMOV\tR1,uPC\n" // uPC = pc |
"\tRTU\n" |
"test_return:\n" |
"\tMOV\tuR1,R1\n" |
137,8 → 147,39
// Works with 5 NOOPS, works with 3 NOOPS, works with 1 NOOP |
"\tJMP\tR0\n"); |
|
extern int idle_test(void); |
asm("\t.text\n\t.global\tidle_test\n" |
"\t.type\tidle_test,@function\n" |
"idle_test:\n" |
"\tCLR\tR1\n" |
"\tMOV\tidle_loop(PC),uR0\n" |
"\tMOV\tR1,uR1\n" |
"\tMOV\tR1,uR2\n" |
"\tMOV\tR1,uR3\n" |
"\tMOV\tR1,uR4\n" |
"\tMOV\tR1,uR5\n" |
"\tMOV\tR1,uR6\n" |
"\tMOV\tR1,uR7\n" |
"\tMOV\tR1,uR8\n" |
"\tMOV\tR1,uR9\n" |
"\tMOV\tR1,uR10\n" |
"\tMOV\tR1,uR11\n" |
"\tMOV\tR1,uR12\n" |
"\tMOV\tR1,uSP\n" |
"\tMOV\t0x20+R1,uCC\n" |
"\tMOV\tidle_loop(PC),uPC\n" |
"\tWAIT\n" |
"\tMOV uPC,R1\n" |
"\tCMP idle_loop(PC),R1\n" |
"\tLDI 0,R1\n" |
"\tLDI.NZ 1,R1\n" |
"\nRETN\n" |
"idle_loop:\n" |
"\tWAIT\n" |
"\tBRA idle_loop\n"); |
|
void break_one(void); |
asm("\t.global\tbreak_one\n" |
asm("\t.text\n\t.global\tbreak_one\n" |
"\t.type\tbreak_one,@function\n" |
"break_one:\n" |
"\tLDI\t0,R1\n" |
148,7 → 189,7
|
void break_two(void); |
// Can we stop a break before we hit it? |
asm("\t.global\tbreak_two\n" |
asm("\t.text\n\t.global\tbreak_two\n" |
"\t.type\tbreak_two,@function\n" |
"break_two:\n" |
"\tLDI\t0,R1\n" |
156,7 → 197,7
"\tBREAK\n"); |
|
void early_branch_test(void); |
asm("\t.global\tearly_branch_test\n" |
asm("\t.text\n\t.global\tearly_branch_test\n" |
"\t.type\tearly_branch_test,@function\n" |
"early_branch_test:\n" |
"\tLDI\t1,R1\n" |
202,7 → 243,7
"\tJMP\tR0"); |
|
void trap_test_and(void); |
asm("\t.global\ttrap_test_and\n" |
asm("\t.text\n\t.global\ttrap_test_and\n" |
"\t.type\ttrap_test_and,@function\n" |
"trap_test_and:\n" |
"\tLDI\t0,R1\n" |
211,7 → 252,7
"\tJMP\tR0"); |
|
void trap_test_clr(void); |
asm("\t.global\ttrap_test_clr\n" |
asm("\t.text\n\t.global\ttrap_test_clr\n" |
"\t.type\ttrap_test_clr,@function\n" |
"trap_test_clr:\n" |
"\tLDI\t0,R1\n" |
220,7 → 261,7
"\tJMP\tR0"); |
|
void overflow_test(void); |
asm("\t.global\toverflow_test\n" |
asm("\t.text\n\t.global\toverflow_test\n" |
"\t.type\toverflow_test,@function\n" |
"overflow_test:\n" |
"\tLDI\t0,R1\n" |
254,7 → 295,7
|
|
void carry_test(void); |
asm("\t.global\tcarry_test\n" |
asm("\t.text\n\t.global\tcarry_test\n" |
"\t.type\tcarry_test,@function\n" |
"carry_test:\n" |
"\tLDI\t0,R1\n" |
283,7 → 324,7
"\tJMP\tR0"); |
|
void loop_test(void); |
asm("\t.global\tloop_test\n" |
asm("\t.text\n\t.global\tloop_test\n" |
"\t.type\tloop_test,@function\n" |
"loop_test:\n" |
"\tLDI\t0,R1\n" |
341,7 → 382,7
// Test whether or not LSL, LSR, and ASR instructions work, together with their |
// carry flags |
void shift_test(void); |
asm("\t.global\tshift_test\n" |
asm("\t.text\n\t.global\tshift_test\n" |
"\t.type\tshift_test,@function\n" |
"shift_test:\n" |
"\tLDI\t0,R1\n" |
408,7 → 449,7
"\tJMP\tR0"); |
|
int sw_brev(int v); |
asm("\t.global\tsw_brev\n" |
asm("\t.text\n\t.global\tsw_brev\n" |
"\t.type\tsw_brev,@function\n" |
"sw_brev:\n" |
"\tSUB\t2,SP\n" |
431,7 → 472,7
"\tJMP\tR0"); |
|
void pipeline_stack_test(void); |
asm("\t.global\tpipeline_stack_test\n" |
asm("\t.text\n\t.global\tpipeline_stack_test\n" |
"\t.type\tpipeline_stack_test,@function\n" |
"pipeline_stack_test:\n" |
"\tSUB\t1,SP\n" |
473,7 → 514,7
); |
|
void pipeline_stack_test_component(void); |
asm("\t.global\tpipeline_stack_test_component\n" |
asm("\t.text\n\t.global\tpipeline_stack_test_component\n" |
"\t.type\tpipeline_stack_test_component,@function\n" |
"pipeline_stack_test_component:\n" |
"\tSUB\t13,SP\n" |
521,7 → 562,7
|
//mpy_test |
void mpy_test(void); |
asm("\t.global\tmpy_test\n" |
asm("\t.text\n\t.global\tmpy_test\n" |
"\t.type\tmpy_test,@function\n" |
"mpy_test:\n" |
"\tCLR\tR1\n" |
553,10 → 594,153
// Second test ... whatever that might be |
"\tJMP\tR0\n"); |
|
unsigned soft_mpyuhi(unsigned, unsigned); |
int soft_mpyshi(int,int); |
|
unsigned hard_mpyuhi(unsigned, unsigned); |
asm("\t.text\n\t.global\thard_mpyuhi\n" |
"\t.type\thard_mpyuhi,@function\n" |
"hard_mpyuhi:\n" |
"\tNOOP\n" |
"\tNOOP\n" |
"\tMPYUHI\tR2,R1\n" |
"\tRETN\n"); |
|
int hard_mpyshi(int, int); |
asm("\t.text\n\t.global\thard_mpyshi\n" |
"\t.type\thard_mpyshi,@function\n" |
"hard_mpyshi:\n" |
"\tMPYSHI\tR2,R1\n" |
"\tRETN\n"); |
|
void debugmpy(char *str, int a, int b, int s, int r) { |
#ifdef HAVE_SCOPE |
// Trigger the scope, if it hasn't been triggered yet |
// but ... dont reset it if it has been. |
*SCOPE = TRIGGER_SCOPE_NOW; |
#endif |
txstr("\r\n"); txstr(str); txhex(a); |
txstr(" x "); txhex(b); |
txstr(" = "); txhex(s); |
txstr("(Soft) = "); txhex(r); |
txstr("(Hard)\r\n"); |
} |
|
int mpyhi_test(void) { |
int a = 0xf97e27ab, b = 0; |
|
while(b<0x6fffffff) { |
int r, sr; |
|
sr = soft_mpyuhi(a, b); |
r = hard_mpyuhi(a,b); |
if (r != sr) { |
debugmpy("MPYUHI: ", a,b,sr,r); |
return 1; |
} |
|
sr = soft_mpyshi(a, b); |
r = hard_mpyshi(a,b); |
if (r != sr) { |
debugmpy("MPYSHI: ", a,b,sr,r); |
return 2; |
} |
|
sr = soft_mpyshi(-a, b); |
r = hard_mpyshi(-a,b); |
if (r != sr) { |
debugmpy("MPYSHI-NEG: ", -a,b,sr,r); |
return 3; |
} |
|
b += 0x197e2*7; |
} |
|
return 0; |
} |
|
unsigned soft_mpyuhi(unsigned a, unsigned b) { |
unsigned alo, ahi, blo, bhi; |
unsigned rhi, rlhi, rllo; |
|
alo = (a & 0x0ffff); |
ahi = (a>>16)& 0x0ffff; |
blo = (b & 0x0ffff); |
bhi = (b>>16)& 0x0ffff; |
|
rhi = 0; |
rlhi = 0; |
rllo = 0; |
|
for(int i=0; i<16; i++) { |
if (b&(1<<i)) { |
unsigned slo, shi, sup; |
slo = (alo << i); |
shi = (ahi << i); |
shi |= (slo>>16) & 0x0ffff; |
slo &= 0x0ffff; |
sup = (shi>>16)&0x0ffff; |
shi &= 0x0ffff; |
|
rhi += sup; |
rlhi += shi; |
rllo += slo; |
|
rlhi += (rllo >> 16)&0x0ffff; |
rllo &= 0x0ffff; |
|
rhi += (rlhi >> 16)&0x0ffff; |
rlhi &= 0x0ffff; |
} |
} |
|
for(int i=16; i<32; i++) { |
if (b&(1<<i)) { |
unsigned slo, shi, sup; |
slo = (alo << (i-16)); |
shi = (ahi << (i-16)); |
shi |= (slo>>16) & 0x0ffff; |
slo &= 0x0ffff; |
sup = (shi>>16)&0x0ffff; |
shi &= 0x0ffff; |
|
rhi += sup << 16; |
rhi += shi; |
rlhi += slo; |
|
rhi += (rlhi >> 16)&0x0ffff; |
rlhi &= 0x0ffff; |
} |
} |
|
return rhi; |
} |
|
int soft_mpyshi(int a, int b) { |
unsigned sgn, r, p; |
|
sgn = ((a^b)>>31)&0x01; |
|
if (a<0) a = -a; |
if (b<0) b = -b; |
|
p = a * b; |
|
// This will only fail if the lower 32-bits of of a*b are 0, |
// at which point our following negation won't capture the carry it |
// needs. |
r = soft_mpyuhi(a, b); |
|
r = (sgn)?(r^-1):r; |
if ((sgn)&&(p==0)) |
r += 1; |
return r; |
} |
|
//brev_test |
//pipeline_test -- used to be called pipeline memory race conditions |
void pipeline_test(void); |
asm("\t.global\tpipeline_test\n" |
asm("\t.text\n\t.global\tpipeline_test\n" |
"\t.type\tpipeline_test,@function\n" |
"pipeline_test:\n" |
"\tSUB\t2,SP\n" |
606,7 → 790,7
|
//mempipe_test |
void mempipe_test(void); |
asm("\t.global\tmempipe_test\n" |
asm("\t.text\n\t.global\tmempipe_test\n" |
"\t.type\tmempipe_test,@function\n" |
"mempipe_test:\n" |
"\tSUB\t4,SP\n" |
643,7 → 827,7
|
//cexec_test |
void cexec_test(void); |
asm("\t.global\tcexec_test\n" |
asm("\t.text\n\t.global\tcexec_test\n" |
"\t.type\tcexec_test,@function\n" |
"cexec_test:\n" |
"\tSUB\t1,SP\n" |
667,7 → 851,7
// |
//nowaitpipe_test |
void nowaitpipe_test(void); |
asm("\t.global\tnowaitpipe_test\n" |
asm("\t.text\n\t.global\tnowaitpipe_test\n" |
"\t.type\tnowaitpipe_test,@function\n" |
"nowaitpipe_test:\n" |
"\tSUB\t2,SP\n" |
742,7 → 926,7
|
//bcmem_test |
void bcmem_test(void); |
asm("\t.global\tbcmem_test\n" |
asm("\t.text\n.global\tbcmem_test\n" |
"\t.type\tbcmem_test,@function\n" |
"bcmem_test:\n" |
"\tSUB\t1,SP\n" |
773,7 → 957,21
"\tADD\t1,SP\n" |
"\tJMP\tR0\n"); |
|
// The illegal instruction test. Specifically, illegal instructions cannot be |
// allowed to execute. The PC must, upon completion, point to the illegal |
// instruction that caused the exception. |
// |
// To create our illegal instruction, we assume that the only the three |
// operations without arguments are NOOP, BREAK, LOCK, and so we envision a |
// fourth instruction to create. |
void ill_test(void); |
asm("\t.text\n.global\till_test\n" |
"\t.type\till_test,@function\n" |
"ill_test:\n" |
"\t.word\t0x7ff00000\n" |
"\tJMP\tR0\n"); |
|
// |
// The CC register has some ... unique requirements associated with it. |
// Particularly, flags are unavailable until after an ALU operation completes, |
// and they can't really be bypassed for the CC register. After writeback, |
787,7 → 985,7
// issues. |
// |
void ccreg_test(void); |
asm("\t.global\tccreg_test\n" |
asm("\t.text\n.global\tccreg_test\n" |
"\t.type\tccreg_test,@function\n" |
"ccreg_test:\n" |
// First test: If we try to change the fixed bits, will they change |
847,11 → 1045,15
*PIC = 0; // Turn interrupts back off, lest they confuse the test |
} |
|
asm("\nidle_task:\n\tWAIT\n\tBRA\tidle_task\n"); |
asm("\n\t.text\nidle_task:\n\tWAIT\n\tBRA\tidle_task\n"); |
|
__attribute__((noinline)) |
void txchr(char v) { |
wait(INT_UARTTX); |
if (zip_cc() & CC_GIE) { |
while(*UARTTX & 0x100) |
; |
} else |
wait(INT_UARTTX); |
*UARTTX = v; |
} |
|
876,6 → 1078,22
} |
|
__attribute__((noinline)) |
void tx4hex(int num) { |
if (num & 0xffff0000){ |
txhex(num); |
return; |
} for(int ds=12; ds>=0; ds-=4) { |
int ch; |
ch = (num >> ds)&0x0f; |
if (ch >= 10) |
ch = 'A'+ch-10; |
else |
ch += '0'; |
txchr(ch); |
} |
} |
|
__attribute__((noinline)) |
void txreg(const char *name, int val) { |
txstr(name); // 4 characters |
txstr("0x"); // 2 characters |
895,7 → 1113,7
// Trigger the scope, if it hasn't already triggered. Otherwise, |
// if it has triggered, don't clear it. |
#ifdef HAVE_SCOPE |
*SCOPE = 0x8f000004; |
*SCOPE = TRIGGER_SCOPE_NOW; |
#endif |
|
MARKSTOP; |
935,7 → 1153,12
txreg("uPC : ", context[15]); |
txstr("\r\n\r\n"); |
|
asm("\tBUSY"); |
// While previous versions of cputest.c called zip_busy(), here we |
// reject that notion for the simple reason that zip_busy may not |
// necessarily halt any Verilator simulation. Instead, we try to |
// halt the CPU. |
while(1) |
zip_halt(); |
} |
|
void testid(const char *str) { |
966,31 → 1189,26
#ifdef HAVE_COUNTER |
*COUNTER = 0; |
#endif |
#ifdef HAVE_SCOPE |
*SCOPE = PREPARE_SCOPE; |
#endif |
|
// #define STACKTEST asm("CMP\t16108,SP\n\tHALT.NZ\n") |
#define STACKTEST |
STACKTEST; |
|
// *UART_CTRL = 8333; // 9600 Baud, 8-bit chars, no parity, one stop bit |
*UART_CTRL = 25; // 9600 Baud, 8-bit chars, no parity, one stop bit |
// |
STACKTEST; |
|
txstr("\r\n"); |
txstr("Running CPU self-test\n"); |
txstr("Running CPU self-test\r\n"); |
txstr("-----------------------------------\r\n"); |
|
int tnum = 0; |
STACKTEST; |
|
// Test break instruction in user mode |
// Make sure the break works as designed |
testid("Break test #1"); MARKSTART; |
STACKTEST; |
|
if ((run_test(break_one, user_stack_ptr))||(zip_ucc()&0x1f50)) |
test_fails(start_time, &testlist[tnum]); |
STACKTEST; |
|
save_context(context); |
if ((context[15] != (int)break_one+1)||(0==(zip_ucc()&0x80))) |
997,8 → 1215,6
test_fails(start_time, &testlist[tnum]); |
txstr("Pass\r\n"); testlist[tnum++] = 0; // 0 |
|
STACKTEST; |
|
// Test break instruction in user mode |
// Make sure that a decision on the clock prior won't still cause a |
// break condition |
1055,12 → 1271,6
test_fails(start_time, &testlist[tnum]); |
txstr("Pass\r\n"); testlist[tnum++] = 0; // #8 |
|
// MPY_TEST |
testid("Multiply test"); MARKSTART; |
if ((run_test(mpy_test, user_stack_ptr))||(zip_ucc()&0x01d90)) |
test_fails(start_time, &testlist[tnum]); |
txstr("Pass\r\n"); testlist[tnum++] = 0; // #9 |
|
// BREV_TEST |
//testid("BREV/stack test"); MARKSTART; |
//if ((run_test(brev_test, user_stack_ptr))||(zip_ucc()&0x01d90)) |
1098,11 → 1308,20
txstr("Pass\r\n"); testlist[tnum++] = 0; // #14 |
|
// Illegal Instruction test |
testid("Illegal Instruction test"); MARKSTART; |
testid("Ill Instruction test, NULL PC"); MARKSTART; |
if ((run_test(NULL, user_stack_ptr))||((zip_ucc()^0x100)&0x01d90)) |
test_fails(start_time, &testlist[tnum]); |
txstr("Pass\r\n"); testlist[tnum++] = 0; |
|
// Illegal Instruction test |
testid("Ill Instruction test, two"); MARKSTART; |
if ((run_test(ill_test, user_stack_ptr))||((zip_ucc()^0x100)&0x01d90)) |
test_fails(start_time, &testlist[tnum]); |
save_context(context); |
if (context[15] != (int)&ill_test) |
test_fails(start_time, &testlist[tnum]); |
txstr("Pass\r\n"); testlist[tnum++] = 0; |
|
// Pipeline memory race condition test |
// DIVIDE test |
|
1118,9 → 1337,20
test_fails(start_time, &testlist[tnum]); |
txstr("Pass\r\n"); testlist[tnum++] = 0; |
|
// MPY_TEST |
testid("Multiply test"); MARKSTART; |
if ((run_test(mpy_test, user_stack_ptr))||(zip_ucc()&0x01d90)) |
test_fails(start_time, &testlist[tnum]); |
txstr("Pass\r\n"); testlist[tnum++] = 0; // #9 |
|
// MPYxHI_TEST |
testid("Multiply HI-word test"); MARKSTART; |
if ((run_test(mpyhi_test, user_stack_ptr))||(zip_ucc()&0x01d90)) |
test_fails(start_time, &testlist[tnum]); |
txstr("Pass\r\n"); testlist[tnum++] = 0; // #9 |
txstr("\r\n"); |
txstr("-----------------------------------\r\n"); |
txstr("All tests passed. Halting CPU.\n"); |
txstr("All tests passed. Halting CPU.\r\n"); |
zip_halt(); |
} |
|
/zipdhry.S
252,13 → 252,12
BRA copy_next_char |
|
end_strcpy: |
STO R2,(R0) |
CMP 0,R2 |
STO.NZ R2,(R0) |
STO.NZ R3,1(R0) |
CMP.NZ 0,R3 |
STO.NZ R3,1(R0) |
STO.NZ R4,2(R0) |
CMP.NZ 0,R4 |
STO.NZ R4,2(R0) |
CMP.NZ 0,R5 |
STO.NZ R5,3(R0) |
|
LOD (SP),R2 |