Line 31... |
Line 31... |
//
|
//
|
//
|
//
|
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
//
|
//
|
|
#include "artyboard.h"
|
#include "zipcpu.h"
|
#include "zipcpu.h"
|
#include "zipsys.h"
|
#include "zipsys.h"
|
#include "artyboard.h"
|
|
|
|
#ifndef NULL
|
#ifndef NULL
|
#define NULL (void *)0
|
#define NULL (void *)0
|
#endif
|
#endif
|
|
|
static volatile int *const UARTTX = &((IOSPACE *)0x0100)->io_uart_tx,
|
#define UARTTX _uart->u_tx
|
*const UART_CTRL = &((IOSPACE *)0x0100)->io_auxsetup;
|
#define UART_CTRL _uart->u_setup
|
static volatile int * const PIC = (volatile int *)0xff000000;
|
#define PIC SYSPIC
|
static const int INT_UARTTX = SYSINT_UARTTX; // 0x2000;
|
#define TIMER SYSTIMER
|
static volatile int *const COUNTER = &((ZIPSYS *)ZIPSYS_ADDR)->z_m.ac_ck;
|
#define COUNTER zip->z_m.ac_ck
|
|
|
#define HAVE_COUNTER
|
// #define HAVE_COUNTER
|
#define HAVE_SCOPE
|
#define HAVE_SCOPE
|
#define SCOPEc sys->io_scope[0].s_ctrl
|
#define SCOPEc _sys->io_scope[0].s_ctrl
|
#define SCOPE_DELAY 4
|
#define SCOPE_DELAY 4
|
#define TRIGGER_SCOPE_NOW (SCOPE_TRIGGER|SCOPE_DELAY)
|
#define TRIGGER_SCOPE_NOW (WBSCOPE_TRIGGER|SCOPE_DELAY)
|
#define PREPARE_SCOPE SCOPE_DELAY
|
#define PREPARE_SCOPE SCOPE_DELAY
|
|
|
unsigned zip_ucc(void);
|
unsigned zip_ucc(void);
|
unsigned zip_cc(void);
|
unsigned zip_cc(void);
|
void zip_save_context(int *);
|
void zip_save_context(int *);
|
Line 89... |
Line 89... |
"\tBRA\tentry\n"
|
"\tBRA\tentry\n"
|
"busy_failure:\n"
|
"busy_failure:\n"
|
"\tBUSY\n"
|
"\tBUSY\n"
|
"\t.section\t.text");
|
"\t.section\t.text");
|
|
|
#ifdef HAVE_COUNTER
|
#ifdef COUNTER
|
#define MARKSTART start_time = *COUNTER
|
#define MARKSTART start_time = COUNTER
|
#define MARKSTOP stop_time = *COUNTER
|
#define MARKSTOP stop_time = COUNTER
|
#else
|
#else
|
#ifdef HAVE_TIMER
|
#ifdef TIMER
|
#define MARKSTART start_time = *TIMER
|
#define MARKSTART start_time = TIMER
|
#define MARKSTOP stop_time = *TIMER
|
#define MARKSTOP stop_time = TIMER
|
#else
|
#else
|
#define MARKSTART
|
#define MARKSTART
|
#define MARKSTOP
|
#define MARKSTOP
|
#endif
|
#endif
|
#endif
|
#endif
|
Line 337... |
Line 337... |
"\tCMP\t5,R3\n"
|
"\tCMP\t5,R3\n"
|
"\tOR.NZ\t1,R1\n"
|
"\tOR.NZ\t1,R1\n"
|
// How about a reverse do{} while loop? These are usually cheaper than for()
|
// How about a reverse do{} while loop? These are usually cheaper than for()
|
// loops.
|
// loops.
|
"\tLDI\t0,R2\n"
|
"\tLDI\t0,R2\n"
|
"\tLDI\t5,R3\n"
|
|
"bgt_loop_test:\n"
|
|
"\tADD\t1,R2\n"
|
|
"\tSUB\t1,R3\n"
|
|
"\tBGT\tbgt_loop_test\n"
|
|
"\tCMP\t5,R2\n"
|
|
"\tOR.NZ\t2,R1\n"
|
|
// What if we use >=?
|
// What if we use >=?
|
"\tLDI\t0,R2\n"
|
|
"\tLDI\t5,R3\n"
|
"\tLDI\t5,R3\n"
|
"bge_loop_test:\n"
|
"bge_loop_test:\n"
|
"\tADD\t1,R2\n"
|
"\tADD\t1,R2\n"
|
"\tSUB\t1,R3\n"
|
"\tSUB\t1,R3\n"
|
"\tBGE\tbge_loop_test\n"
|
"\tBGE\tbge_loop_test\n"
|
"\tCMP\t6,R2\n"
|
"\tCMP\t6,R2\n"
|
"\tOR.NZ\t4,R1\n"
|
"\tOR.NZ\t4,R1\n"
|
// Once more with the reverse loop, this time storing the loop variable in
|
// Once more with the reverse loop, this time storing the loop variable in
|
// memory
|
// memory
|
"\tSUB\t1,SP\n"
|
"\tSUB\t4,SP\n"
|
"\tLDI\t0,R2\n"
|
"\tLDI\t0,R2\n"
|
"\tLDI\t5,R3\n"
|
"\tLDI\t4,R3\n"
|
"\tSTO\tR3,(SP)\n"
|
"\tSW\tR3,(SP)\n"
|
"mem_loop_test:\n"
|
"mem_loop_test:\n"
|
"\tADD\t1,R2\n"
|
"\tADD\t1,R2\n" // Keep track of the number of times loop is executed
|
"\tADD\t14,R3\n"
|
"\tADD\t14,R3\n"
|
"\tLOD\t(SP),R3\n"
|
"\tLW\t(SP),R3\n"
|
"\tSUB\t1,R3\n"
|
"\tSUB\t1,R3\n"
|
"\tSTO\tR3,(SP)\n"
|
"\tSW\tR3,(SP)\n"
|
"\tBGT\tmem_loop_test\n"
|
"\tBGE\tmem_loop_test\n"
|
"\tCMP\t5,R2\n"
|
"\tCMP\t5,R2\n"
|
"\tOR.NZ\t8,R1\n"
|
"\tOR.NZ\t8,R1\n"
|
"\tADD\t1,SP\n"
|
"\tADD\t4,SP\n"
|
//
|
//
|
"\tJMP\tR0\n");
|
"\tJMP\tR0\n");
|
|
|
// Test whether or not LSL, LSR, and ASR instructions work, together with their
|
// Test whether or not LSL, LSR, and ASR instructions work, together with their
|
// carry flags
|
// carry flags
|
void shift_test(void);
|
void shift_test(void);
|
asm("\t.text\n\t.global\tshift_test\n"
|
asm("\t.text\n\t.global\tshift_test\n"
|
"\t.type\tshift_test,@function\n"
|
"\t.type\tshift_test,@function\n"
|
"shift_test:\n"
|
"shift_test:\n"
|
"\tLDI\t0,R1\n"
|
"\tLDI\t0,R1\n" // Bit-field of tests that have failed
|
"\tLDI\t0,R3\n"
|
"\tLDI\t0,R3\n" // Bit-field of tests that have worked
|
"\tLDI\t0,R4\n"
|
"\tLDI\t0,R4\n" // Upper 16-bits of the same bit field
|
|
"\tLDI\t0,R5\n" // Upper 16-bits of tests that have failed
|
// Does shifting right by 32 result in a zero?
|
// Does shifting right by 32 result in a zero?
|
"\tLDI\t-1,R2\n"
|
"\tLDI\t-1,R2\n"
|
"\tLSR\t32,R2\n"
|
"\tLSR\t32,R2\n"
|
"\tOR.Z\t1,R3\n"
|
"\tOR.Z\t1,R3\n"
|
"\tOR.C\t2,R3\n"
|
"\tOR.C\t2,R3\n"
|
Line 425... |
Line 418... |
"\tOR\t32768,R3\n"
|
"\tOR\t32768,R3\n"
|
"\tCMP\t-1,R2\n"
|
"\tCMP\t-1,R2\n"
|
"\tOR.Z\t1,R4\n"
|
"\tOR.Z\t1,R4\n"
|
//
|
//
|
"\tLSR\t0,R2\n"
|
"\tLSR\t0,R2\n"
|
"\tOR.C\t131072,R1\n"
|
"\tLDI\t131072,R5\n"
|
|
"\tOR.C\tR5,R1\n"
|
"\tCMP\t-1,R2\n"
|
"\tCMP\t-1,R2\n"
|
"\tOR.Z\t2,R4\n"
|
"\tOR.Z\t2,R4\n"
|
//
|
//
|
"\tLSL\t0,R2\n"
|
"\tLSL\t0,R2\n"
|
"\tOR.C\t524288,R1\n"
|
"\tLDI\t524288,R5\n"
|
|
"\tOR.C\tR5,R1\n"
|
"\tCMP\t-1,R2\n"
|
"\tCMP\t-1,R2\n"
|
"\tOR.Z\t4,R4\n"
|
"\tOR.Z\t4,R4\n"
|
// Tally up our results and return
|
// Tally up our results and return
|
"\tXOR\t7,R4\n"
|
"\tXOR\t7,R4\n"
|
"\tXOR\t65535,R3\n"
|
"\tXOR\t65535,R3\n"
|
Line 445... |
Line 440... |
|
|
int sw_brev(int v);
|
int sw_brev(int v);
|
asm("\t.text\n\t.global\tsw_brev\n"
|
asm("\t.text\n\t.global\tsw_brev\n"
|
"\t.type\tsw_brev,@function\n"
|
"\t.type\tsw_brev,@function\n"
|
"sw_brev:\n"
|
"sw_brev:\n"
|
"\tSUB\t2,SP\n"
|
"\tSUB\t8,SP\n"
|
"\tSTO\tR2,(SP)\n"
|
"\tSW\tR2,(SP)\n"
|
"\tSTO\tR3,1(SP)\n"
|
"\tSW\tR3,4(SP)\n"
|
"\tLDI\t-1,R2\n"
|
"\tLDI\t-1,R2\n"
|
"\tCLR\tR3\n"
|
"\tCLR\tR3\n"
|
"sw_brev_loop:\n"
|
"sw_brev_loop:\n"
|
"\tLSL\t1,R3\n"
|
"\tLSL\t1,R3\n"
|
"\tLSR\t1,R1\n"
|
"\tLSR\t1,R1\n"
|
Line 459... |
Line 454... |
"\tLSR\t1,R2\n"
|
"\tLSR\t1,R2\n"
|
"\tBZ\tsw_brev_endloop\n"
|
"\tBZ\tsw_brev_endloop\n"
|
"\tBRA\tsw_brev_loop\n"
|
"\tBRA\tsw_brev_loop\n"
|
"sw_brev_endloop:\n"
|
"sw_brev_endloop:\n"
|
"\tMOV\tR3,R1\n"
|
"\tMOV\tR3,R1\n"
|
"\tLOD\t(SP),R2\n"
|
"\tLW\t(SP),R2\n"
|
"\tLOD\t1(SP),R3\n"
|
"\tLW\t4(SP),R3\n"
|
"\tADD\t2,SP\n"
|
"\tADD\t8,SP\n"
|
"\tJMP\tR0");
|
"\tJMP\tR0");
|
|
|
void pipeline_stack_test(void);
|
void pipeline_stack_test(void);
|
asm("\t.text\n\t.global\tpipeline_stack_test\n"
|
asm("\t.text\n\t.global\tpipeline_stack_test\n"
|
"\t.type\tpipeline_stack_test,@function\n"
|
"\t.type\tpipeline_stack_test,@function\n"
|
"pipeline_stack_test:\n"
|
"pipeline_stack_test:\n"
|
"\tSUB\t1,SP\n"
|
"\tSUB\t4,SP\n"
|
"\tSTO\tR0,(SP)\n"
|
"\tSW\tR0,(SP)\n"
|
"\tLDI\t0,R0\n"
|
"\tLDI\t0,R0\n"
|
"\tMOV\t1(R0),R1\n"
|
"\tMOV\t1(R0),R1\n"
|
"\tMOV\t1(R1),R2\n"
|
"\tMOV\t1(R1),R2\n"
|
"\tMOV\t1(R2),R3\n"
|
"\tMOV\t1(R2),R3\n"
|
"\tMOV\t1(R3),R4\n"
|
"\tMOV\t1(R3),R4\n"
|
Line 501... |
Line 496... |
"\tCMP.Z\t9,R9\n"
|
"\tCMP.Z\t9,R9\n"
|
"\tCMP.Z\t10,R10\n"
|
"\tCMP.Z\t10,R10\n"
|
"\tCMP.Z\t11,R11\n"
|
"\tCMP.Z\t11,R11\n"
|
"\tCMP.Z\t12,R12\n"
|
"\tCMP.Z\t12,R12\n"
|
"\tBREV.NZ\t-1,R1\n"
|
"\tBREV.NZ\t-1,R1\n"
|
"\tLOD\t(SP),R0\n"
|
"\tLW\t(SP),R0\n"
|
"\tADD\t1,SP\n"
|
"\tADD\t4,SP\n"
|
"\tJMP\tR0\n"
|
"\tJMP\tR0\n"
|
);
|
);
|
|
|
void pipeline_stack_test_component(void);
|
void pipeline_stack_test_component(void);
|
asm("\t.text\n\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"
|
"\t.type\tpipeline_stack_test_component,@function\n"
|
"pipeline_stack_test_component:\n"
|
"pipeline_stack_test_component:\n"
|
"\tSUB\t13,SP\n"
|
"\tSUB\t52,SP\n"
|
"\tSTO\tR0,(SP)\n"
|
"\tSW\tR0,(SP)\n"
|
"\tSTO\tR1,1(SP)\n"
|
"\tSW\tR1,4(SP)\n"
|
"\tSTO\tR2,2(SP)\n"
|
"\tSW\tR2,8(SP)\n"
|
"\tSTO\tR3,3(SP)\n"
|
"\tSW\tR3,12(SP)\n"
|
"\tSTO\tR4,4(SP)\n"
|
"\tSW\tR4,16(SP)\n"
|
"\tSTO\tR5,5(SP)\n"
|
"\tSW\tR5,20(SP)\n"
|
"\tSTO\tR6,6(SP)\n"
|
"\tSW\tR6,24(SP)\n"
|
"\tSTO\tR7,7(SP)\n"
|
"\tSW\tR7,28(SP)\n"
|
"\tSTO\tR8,8(SP)\n"
|
"\tSW\tR8,32(SP)\n"
|
"\tSTO\tR9,9(SP)\n"
|
"\tSW\tR9,36(SP)\n"
|
"\tSTO\tR10,10(SP)\n"
|
"\tSW\tR10,40(SP)\n"
|
"\tSTO\tR11,11(SP)\n"
|
"\tSW\tR11,44(SP)\n"
|
"\tSTO\tR12,12(SP)\n"
|
"\tSW\tR12,48(SP)\n"
|
"\tXOR\t-1,R0\n"
|
"\tXOR\t-1,R0\n"
|
"\tXOR\t-1,R1\n"
|
"\tXOR\t-1,R1\n"
|
"\tXOR\t-1,R2\n"
|
"\tXOR\t-1,R2\n"
|
"\tXOR\t-1,R3\n"
|
"\tXOR\t-1,R3\n"
|
"\tXOR\t-1,R4\n"
|
"\tXOR\t-1,R4\n"
|
Line 537... |
Line 532... |
"\tXOR\t-1,R8\n"
|
"\tXOR\t-1,R8\n"
|
"\tXOR\t-1,R9\n"
|
"\tXOR\t-1,R9\n"
|
"\tXOR\t-1,R10\n"
|
"\tXOR\t-1,R10\n"
|
"\tXOR\t-1,R11\n"
|
"\tXOR\t-1,R11\n"
|
"\tXOR\t-1,R12\n"
|
"\tXOR\t-1,R12\n"
|
"\tLOD\t(SP),R0\n"
|
"\tLW\t(SP),R0\n"
|
"\tLOD\t1(SP),R1\n"
|
"\tLW\t4(SP),R1\n"
|
"\tLOD\t2(SP),R2\n"
|
"\tLW\t8(SP),R2\n"
|
"\tLOD\t3(SP),R3\n"
|
"\tLW\t12(SP),R3\n"
|
"\tLOD\t4(SP),R4\n"
|
"\tLW\t16(SP),R4\n"
|
"\tLOD\t5(SP),R5\n"
|
"\tLW\t20(SP),R5\n"
|
"\tLOD\t6(SP),R6\n"
|
"\tLW\t24(SP),R6\n"
|
"\tLOD\t7(SP),R7\n"
|
"\tLW\t28(SP),R7\n"
|
"\tLOD\t8(SP),R8\n"
|
"\tLW\t32(SP),R8\n"
|
"\tLOD\t9(SP),R9\n"
|
"\tLW\t36(SP),R9\n"
|
"\tLOD\t10(SP),R10\n"
|
"\tLW\t40(SP),R10\n"
|
"\tLOD\t11(SP),R11\n"
|
"\tLW\t44(SP),R11\n"
|
"\tLOD\t12(SP),R12\n"
|
"\tLW\t48(SP),R12\n"
|
"\tADD\t13,SP\n"
|
"\tADD\t52,SP\n"
|
"\tJMP\tR0\n");
|
"\tJMP\tR0\n");
|
|
|
//mpy_test
|
//mpy_test
|
void mpy_test(void);
|
void mpy_test(void);
|
asm("\t.text\n\t.global\tmpy_test\n"
|
asm("\t.text\n\t.global\tmpy_test\n"
|
Line 594... |
Line 589... |
|
|
unsigned hard_mpyuhi(unsigned, unsigned);
|
unsigned hard_mpyuhi(unsigned, unsigned);
|
asm("\t.text\n\t.global\thard_mpyuhi\n"
|
asm("\t.text\n\t.global\thard_mpyuhi\n"
|
"\t.type\thard_mpyuhi,@function\n"
|
"\t.type\thard_mpyuhi,@function\n"
|
"hard_mpyuhi:\n"
|
"hard_mpyuhi:\n"
|
"\tNOOP\n"
|
|
"\tNOOP\n"
|
|
"\tMPYUHI\tR2,R1\n"
|
"\tMPYUHI\tR2,R1\n"
|
"\tRETN\n");
|
"\tRETN\n");
|
|
|
int hard_mpyshi(int, int);
|
int hard_mpyshi(int, int);
|
asm("\t.text\n\t.global\thard_mpyshi\n"
|
asm("\t.text\n\t.global\thard_mpyshi\n"
|
Line 653... |
Line 646... |
|
|
return 0;
|
return 0;
|
}
|
}
|
|
|
unsigned soft_mpyuhi(unsigned a, unsigned b) {
|
unsigned soft_mpyuhi(unsigned a, unsigned b) {
|
unsigned alo, ahi, blo, bhi;
|
unsigned alo, ahi;
|
unsigned rhi, rlhi, rllo;
|
unsigned rhi, rlhi, rllo;
|
|
|
alo = (a & 0x0ffff);
|
alo = (a & 0x0ffff);
|
ahi = (a>>16)& 0x0ffff;
|
ahi = (a>>16)& 0x0ffff;
|
blo = (b & 0x0ffff);
|
|
bhi = (b>>16)& 0x0ffff;
|
|
|
|
rhi = 0;
|
rhi = 0;
|
rlhi = 0;
|
rlhi = 0;
|
rllo = 0;
|
rllo = 0;
|
|
|
Line 730... |
Line 721... |
if ((sgn)&&(p==0))
|
if ((sgn)&&(p==0))
|
r += 1;
|
r += 1;
|
return r;
|
return r;
|
}
|
}
|
|
|
|
int div_test(void);
|
|
asm("\t.text\n\t.global\tdiv_test\n"
|
|
"\t.type\tdiv_test,@function\n"
|
|
"div_test:\n"
|
|
"\tLDI\t0x4881a7,R4\n"
|
|
"\tLDI\t0x2d5108b,R2\n"
|
|
"\tLDI\t10,R3\n"
|
|
"\tDIVU\tR3,R2\n"
|
|
"\tCMP\tR4,R2\n"
|
|
"\tLDILO.NZ\t1,R1\n"
|
|
"\tRETN.NZ\n"
|
|
"\tLDI\t0x2d5108b,R2\n"
|
|
"\tDIVU\t10,R2\n"
|
|
"\tCMP\tR4,R2\n"
|
|
"\tLDILO.NZ\t1,R1\n"
|
|
"\tRETN\n");
|
|
|
//brev_test
|
//brev_test
|
//pipeline_test -- used to be called pipeline memory race conditions
|
//pipeline_test -- used to be called pipeline memory race conditions
|
void pipeline_test(void);
|
void pipeline_test(void);
|
asm("\t.text\n\t.global\tpipeline_test\n"
|
asm("\t.text\n\t.global\tpipeline_test\n"
|
"\t.type\tpipeline_test,@function\n"
|
"\t.type\tpipeline_test,@function\n"
|
"pipeline_test:\n"
|
"pipeline_test:\n"
|
"\tSUB\t2,SP\n"
|
"\tSUB\t12,SP\n"
|
// Test setup
|
// Test setup
|
"\tLDI\t275,R2\n"
|
"\tLDI\t275,R2\n"
|
"\tSTO\tR2,1(SP)\n"
|
"\tSW\tR2,4(SP)\n"
|
"\tMOV\t1(SP),R2\n"
|
"\tMOV\t4(SP),R2\n"
|
"\tSTO\tR2,(SP)\n"
|
"\tSW\tR2,(SP)\n"
|
"\tCLR\tR2\n"
|
"\tCLR\tR2\n"
|
//
|
//
|
"\tMOV\tSP,R2\n"
|
"\tMOV\tSP,R2\n"
|
"\tLOD\t(R2),R2\n"
|
"\tLW\t(R2),R2\n"
|
"\tLOD\t(R2),R2\n"
|
"\tLW\t(R2),R2\n"
|
"\tCMP\t275,R2\n"
|
"\tCMP\t275,R2\n"
|
"\tOR.NZ\t1,R1\n"
|
"\tOR.NZ\t1,R1\n"
|
//
|
//
|
"\tMOV\tSP,R2\n"
|
"\tMOV\tSP,R2\n"
|
// Here's the test sequence
|
// Here's the test sequence
|
"\tLOD\t(R2),R3\n"
|
"\tLW\t(R2),R3\n"
|
"\tLOD\t1(R2),R4\n"
|
"\tLW\t4(R2),R4\n"
|
"\tSTO\tR4,1(R3)\n"
|
"\tSW\tR4,4(R3)\n"
|
// Make sure we clear the load pipeline
|
// Make sure we clear the load pipeline
|
"\tLOD\t(R2),R3\n"
|
"\tLW\t(R2),R3\n"
|
// Load our written value
|
// Load our written value
|
"\tLOD\t2(R2),R4\n"
|
"\tLW\t8(R2),R4\n"
|
"\tCMP\t275,R4\n"
|
"\tCMP\t275,R4\n"
|
"\tOR.NZ\t2,R1\n"
|
"\tOR.NZ\t2,R1\n"
|
//
|
//
|
//
|
//
|
// Next (once upon a time) failing sequence:
|
// Next (once upon a time) failing sequence:
|
// LOD -x(R12),R0
|
// LOD -x(R12),R0
|
// LOD y(R0),R0
|
// LOD y(R0),R0
|
"\tMOV\tSP,R2\n"
|
"\tMOV\tSP,R2\n"
|
"\tMOV\t1(R2),R3\n"
|
"\tMOV\t4(R2),R3\n"
|
"\tSTO\tR3,1(R2)\n"
|
"\tSW\tR3,4(R2)\n"
|
"\tLDI\t3588,R4\n" // Just some random value
|
"\tLDI\t3588,R4\n" // Just some random value
|
"\tSTO\tR4,2(R2)\n"
|
"\tSW\tR4,8(R2)\n"
|
"\tMOV\tR2,R3\n"
|
"\tMOV\tR2,R3\n"
|
// Here's the test sequence
|
// Here's the test sequence
|
"\tLOD\t(R2),R3\n"
|
"\tLW\t(R2),R3\n"
|
"\tLOD\t1(R3),R3\n"
|
"\tLW\t4(R3),R3\n"
|
"\tCMP\tR4,R3\n"
|
"\tCMP\tR4,R3\n"
|
"\tOR.NZ\t4,R1\n"
|
"\tOR.NZ\t4,R1\n"
|
//
|
//
|
"\tADD\t2,SP\n"
|
"\tADD\t12,SP\n"
|
"\tJMP\tR0\n");
|
"\tJMP\tR0\n");
|
|
|
//mempipe_test
|
//mempipe_test
|
void mempipe_test(void);
|
void mempipe_test(void);
|
asm("\t.text\n\t.global\tmempipe_test\n"
|
asm("\t.text\n\t.global\tmempipe_test\n"
|
"\t.type\tmempipe_test,@function\n"
|
"\t.type\tmempipe_test,@function\n"
|
"mempipe_test:\n"
|
"mempipe_test:\n"
|
"\tSUB\t4,SP\n"
|
"\tSUB\t16,SP\n"
|
"\tSTO\tR0,(SP)\n"
|
"\tSW\tR0,(SP)\n"
|
"\tLDI\t0x1000,R11\n"
|
"\tLDI\t0x1000,R11\n"
|
// Test #1 ... Let's start by writing a value to memory
|
// Test #1 ... Let's start by writing a value to memory
|
"\tLDI\t-1,R2\n"
|
"\tLDI\t-1,R2\n"
|
"\tCLR\tR3\n"
|
"\tCLR\tR3\n"
|
"\tSTO\tR2,2(SP)\n"
|
"\tSW\tR2,8(SP)\n"
|
"\tLOD\t2(SP),R3\n"
|
"\tLW\t8(SP),R3\n"
|
"\tCMP\tR3,R2\n"
|
"\tCMP\tR3,R2\n"
|
"\tOR.NZ\t1,R1\n"
|
"\tOR.NZ\t1,R1\n"
|
// Test #2, reading and then writing a value from memory
|
// Test #2, reading and then writing a value from memory
|
"\tNOOP\n"
|
"\tNOOP\n"
|
"\tNOOP\n"
|
"\tNOOP\n"
|
"\tCLR\tR2\n"
|
"\tCLR\tR2\n"
|
"\tCLR\tR3\n"
|
"\tCLR\tR3\n"
|
"\tLOD\t2(SP),R2\n" // This should load back up our -1 value
|
"\tLW\t8(SP),R2\n" // This should load back up our -1 value
|
"\tSTO\tR2,3(SP)\n"
|
"\tSW\tR2,12(SP)\n"
|
// Insist that the pipeline clear
|
// Insist that the pipeline clear
|
"\tLOD\t2(SP),R2\n"
|
"\tLW\t8(SP),R2\n"
|
// Now let's try loading into R3
|
// Now let's try loading into R3
|
"\tNOOP\n"
|
"\tNOOP\n"
|
"\tNOOP\n"
|
"\tNOOP\n"
|
"\tNOOP\n"
|
"\tNOOP\n"
|
"\tNOOP\n"
|
"\tNOOP\n"
|
"\tLOD\t3(SP),R3\n"
|
"\tLW\t12(SP),R3\n"
|
"\tCMP\tR3,R2\n"
|
"\tCMP\tR3,R2\n"
|
"\tOR.NZ\t2,R1\n"
|
"\tOR.NZ\t2,R1\n"
|
//
|
//
|
"\tLOD\t(SP),R0\n"
|
"\tLW\t(SP),R0\n"
|
"\tADD\t4,SP\n"
|
"\tADD\t16,SP\n"
|
"\tJMP\tR0\n");
|
"\tJMP\tR0\n");
|
|
|
//cexec_test
|
//cexec_test
|
void cexec_test(void);
|
void cexec_test(void);
|
asm("\t.text\n\t.global\tcexec_test\n"
|
asm("\t.text\n\t.global\tcexec_test\n"
|
"\t.type\tcexec_test,@function\n"
|
"\t.type\tcexec_test,@function\n"
|
"cexec_test:\n"
|
"cexec_test:\n"
|
"\tSUB\t1,SP\n"
|
"\tSUB\t4,SP\n"
|
"\tSTO\tR0,(SP)\n"
|
"\tSW\tR0,(SP)\n"
|
//
|
//
|
"\tXOR\tR2,R2\n"
|
"\tXOR\tR2,R2\n"
|
"\tADD.Z\t1,R2\n"
|
"\tADD.Z\t1,R2\n"
|
"\tADD.NZ\t1,R1\n"
|
"\tADD.NZ\t1,R1\n"
|
"\tCMP.Z\t0,R2\n"
|
"\tCMP.Z\t0,R2\n"
|
"\tOR.Z\t2,R1\n"
|
"\tOR.Z\t2,R1\n"
|
//
|
//
|
"\tLOD\t(SP),R0\n"
|
"\tLW\t(SP),R0\n"
|
"\tADD\t1,SP\n"
|
"\tADD\t4,SP\n"
|
"\tJMP\tR0\n");
|
"\tJMP\tR0\n");
|
|
|
// Pipeline stalls have been hideous problems for me. The CPU has been modified
|
// Pipeline stalls have been hideous problems for me. The CPU has been modified
|
// with special logic to keep stages from stalling. For the most part, this
|
// with special logic to keep stages from stalling. For the most part, this
|
// means that ALU and memory results may be accessed either before or as they
|
// means that ALU and memory results may be accessed either before or as they
|
Line 847... |
Line 855... |
//nowaitpipe_test
|
//nowaitpipe_test
|
void nowaitpipe_test(void);
|
void nowaitpipe_test(void);
|
asm("\t.text\n\t.global\tnowaitpipe_test\n"
|
asm("\t.text\n\t.global\tnowaitpipe_test\n"
|
"\t.type\tnowaitpipe_test,@function\n"
|
"\t.type\tnowaitpipe_test,@function\n"
|
"nowaitpipe_test:\n"
|
"nowaitpipe_test:\n"
|
"\tSUB\t2,SP\n"
|
"\tSUB\t8,SP\n"
|
//
|
//
|
// Let's start with ALU-ALU testing
|
// Let's start with ALU-ALU testing
|
// AA: result->input A
|
// AA: result->input A
|
"\tLDI\t-1,R2\n"
|
"\tLDI\t-1,R2\n"
|
"\tCLR\tR2\n"
|
"\tCLR\tR2\n"
|
Line 890... |
Line 898... |
"\tOR.NZ\t32,R1\n"
|
"\tOR.NZ\t32,R1\n"
|
//
|
//
|
// Then we need to do the ALU-MEM input testing
|
// Then we need to do the ALU-MEM input testing
|
//
|
//
|
"\tCLR\tR2\n"
|
"\tCLR\tR2\n"
|
"\tSTO\tR2,1(SP)\n"
|
"\tSW\tR2,4(SP)\n"
|
"\tLDI\t8352,R2\n"
|
"\tLDI\t8352,R2\n"
|
"\tLOD\t1(SP),R2\n"
|
"\tLW\t4(SP),R2\n"
|
"\tTST\t-1,R2\n"
|
"\tTST\t-1,R2\n"
|
"\tOR.NZ\t64,R1\n"
|
"\tOR.NZ\t64,R1\n"
|
// Let's try again, this time with something that's not zero
|
// Let's try again, this time with something that's not zero
|
"\tLDI\t937,R2\n"
|
"\tLDI\t937,R2\n"
|
"\tSTO\tR2,1(SP)\n"
|
"\tSW\tR2,4(SP)\n"
|
"\tNOOP\n"
|
"\tNOOP\n"
|
"\tLOD\t1(SP),R2\n"
|
"\tLW\t4(SP),R2\n"
|
"\tCMP\t938,R2\n"
|
"\tCMP\t938,R2\n"
|
"\tOR.GE\t128,R1\n"
|
"\tOR.GE\t128,R1\n"
|
"\tCMP\t936,R2\n"
|
"\tCMP\t936,R2\n"
|
"\tOR.LT\t256,R1\n"
|
"\tOR.LT\t256,R1\n"
|
// Mem output->ALU input testing
|
// Mem output->ALU input testing
|
// Okay, we just did that as part of our last test
|
// Okay, we just did that as part of our last test
|
// Mem output->mem input testing
|
// Mem output->mem input testing
|
"\tLDI\t5328,R2\n"
|
"\tLDI\t5328,R2\n"
|
"\tLOD\t1(SP),R2\n"
|
"\tLW\t4(SP),R2\n"
|
"\tSTO\tR2,1(SP)\n"
|
"\tSW\tR2,4(SP)\n"
|
"\tLOD\t1(SP),R3\n"
|
"\tLW\t4(SP),R3\n"
|
"\tCMP\t937,R3\n"
|
"\tCMP\t937,R3\n"
|
"\tOR.NZ\t512,R1\n"
|
"\tOR.NZ\t512,R1\n"
|
//
|
//
|
"\tADD\t2,SP\n"
|
"\tADD\t8,SP\n"
|
"\tJMP\tR0\n");
|
"\tJMP\tR0\n");
|
|
|
//bcmem_test
|
//bcmem_test
|
void bcmem_test(void);
|
void bcmem_test(void);
|
asm("\t.text\n.global\tbcmem_test\n"
|
asm("\t.text\n.global\tbcmem_test\n"
|
"\t.type\tbcmem_test,@function\n"
|
"\t.type\tbcmem_test,@function\n"
|
"bcmem_test:\n"
|
"bcmem_test:\n"
|
"\tSUB\t1,SP\n"
|
"\tSUB\t4,SP\n"
|
"\tCLR\tR1\n"
|
"\tCLR\tR1\n"
|
"\tCLR\tR2\n"
|
"\tCLR\tR2\n"
|
"\tLDI\t-1,R3\n"
|
"\tLDI\t-1,R3\n"
|
"\tLDI\t0x13000,R4\n"
|
"\tLDI\t0x13000,R4\n"
|
"\tSTO\tR2,(SP)\n"
|
"\tSW\tR2,(SP)\n"
|
"\tLOD\t(SP),R3\n"
|
"\tLW\t(SP),R3\n"
|
"\tCMP\tR2,R3\n"
|
"\tCMP\tR2,R3\n"
|
"\tOR.NZ\t1,R1\n"
|
"\tOR.NZ\t1,R1\n"
|
"\tCMP\t0x13000,R4\n"
|
"\tCMP\t0x13000,R4\n"
|
"\tBZ\tbcmem_test_cmploc_1\n"
|
"\tBZ\tbcmem_test_cmploc_1\n"
|
"\tSTO\tR4,(SP)\n"
|
"\tSW\tR4,(SP)\n"
|
"bcmem_test_cmploc_1:\n"
|
"bcmem_test_cmploc_1:\n"
|
"\tLOD\t(SP),R2\n"
|
"\tLW\t(SP),R2\n"
|
"\tCMP\tR2,R4\n"
|
"\tCMP\tR2,R4\n"
|
"\tOR.Z\t2,R1\n"
|
"\tOR.Z\t2,R1\n"
|
"\tCLR\tR2\n"
|
"\tCLR\tR2\n"
|
"\tCMP\tR2,R4\n"
|
"\tCMP\tR2,R4\n"
|
"\tBZ\tbcmem_test_cmploc_2\n"
|
"\tBZ\tbcmem_test_cmploc_2\n"
|
"\tSTO.NZ\tR4,(SP)\n"
|
"\tSW.NZ\tR4,(SP)\n"
|
"bcmem_test_cmploc_2:\n"
|
"bcmem_test_cmploc_2:\n"
|
"\tLOD\t(SP),R2\n"
|
"\tLW\t(SP),R2\n"
|
"\tCMP\tR2,R4\n"
|
"\tCMP\tR2,R4\n"
|
"\tOR.NZ\t4,R1\n"
|
"\tOR.NZ\t4,R1\n"
|
//
|
//
|
"\tADD\t1,SP\n"
|
"\tADD\t4,SP\n"
|
"\tJMP\tR0\n");
|
"\tJMP\tR0\n");
|
|
|
// The illegal instruction test. Specifically, illegal instructions cannot be
|
// The illegal instruction test. Specifically, illegal instructions cannot be
|
// allowed to execute. The PC must, upon completion, point to the illegal
|
// allowed to execute. The PC must, upon completion, point to the illegal
|
// instruction that caused the exception.
|
// instruction that caused the exception.
|
Line 960... |
Line 968... |
// operations without arguments are NOOP, BREAK, LOCK, and so we envision a
|
// operations without arguments are NOOP, BREAK, LOCK, and so we envision a
|
// fourth instruction to create.
|
// fourth instruction to create.
|
void ill_test(void);
|
void ill_test(void);
|
asm("\t.text\n.global\till_test\n"
|
asm("\t.text\n.global\till_test\n"
|
"\t.type\till_test,@function\n"
|
"\t.type\till_test,@function\n"
|
"ill_test:\n"
|
"ill_test:\n" // 0.111_1.110_11......
|
"\t.word\t0x7ff00000\n"
|
"\t.int\t0x7ec00000\n"
|
|
"\tJMP\tR0\n");
|
|
|
|
// Are sim instructions considered valid? Just hit the illegal instruction
|
|
// so we can report the result
|
|
void sim_test(void);
|
|
asm("\t.text\n.global\tsim_test\n"
|
|
"\t.type\tsim_test,@function\n"
|
|
"sim_test:\n" // 0.111_1.111_10......
|
|
"\t.int\t0x7f800000\n"
|
|
"\tJMP\tR0\n");
|
|
|
|
// Are CIS instructions considered valid? Try two compare instructions to
|
|
// see if they are built into our CPU.
|
|
void cis_test(void);
|
|
asm("\t.text\n.global\tcis_test\n"
|
|
"\t.type\tcis_test,@function\n"
|
|
"cis_test:\n" // 1.000_0.011._1.101_0.000 ... 1.000_1.011._1.110_0.000
|
|
"\t.int\t0x83d08be0\n"
|
"\tJMP\tR0\n");
|
"\tJMP\tR0\n");
|
|
|
|
void cmpeq_test(void);
|
|
asm("\t.text\n.global\tcmpeq_test\n"
|
|
"\t.type\tcmpeq_test,@function\n"
|
|
"cmpeq_test:\n"
|
|
"\tCMP\tR1,R2\n"
|
|
"\tCMP.Z\tR3,R4\n"
|
|
"\tLDILO.NZ\t1,R1\n"
|
|
"\tJMP\tR0\n");
|
|
|
|
void cmpneq_test(void);
|
|
asm("\t.text\n.global\tcmpneq_test\n"
|
|
"\t.type\tcmpneq_test,@function\n"
|
|
"cmpneq_test:\n"
|
|
"\tLDI\t1,R4\n"
|
|
"\tCMP\tR1,R2\n"
|
|
"\tCMP.Z\tR3,R4\n"
|
|
"\tLDILO.Z\t1,R0\n"
|
|
"\tJMP\tR0\n");
|
//
|
//
|
// The CC register has some ... unique requirements associated with it.
|
// The CC register has some ... unique requirements associated with it.
|
// Particularly, flags are unavailable until after an ALU operation completes,
|
// Particularly, flags are unavailable until after an ALU operation completes,
|
// and they can't really be bypassed for the CC register. After writeback,
|
// and they can't really be bypassed for the CC register. After writeback,
|
// the "new" CC register isn't really available for another clock. Trying to
|
// the "new" CC register isn't really available for another clock. Trying to
|
Line 1031... |
Line 1075... |
return multiarg_subroutine(0,1,2,3,4,5,6);
|
return multiarg_subroutine(0,1,2,3,4,5,6);
|
}
|
}
|
|
|
__attribute__((noinline))
|
__attribute__((noinline))
|
void wait(unsigned int msk) {
|
void wait(unsigned int msk) {
|
*PIC = 0x7fff0000|msk;
|
PIC = 0x7fff0000|msk;
|
asm("MOV\tidle_task(PC),uPC\n");
|
asm("MOV\tidle_task(PC),uPC\n");
|
*PIC = 0x80000000|(msk<<16);
|
PIC = 0x80000000|(msk<<16);
|
asm("WAIT\n");
|
asm("WAIT\n");
|
*PIC = 0; // Turn interrupts back off, lest they confuse the test
|
PIC = 0; // Turn interrupts back off, lest they confuse the test
|
}
|
}
|
|
|
asm("\n\t.text\nidle_task:\n\tWAIT\n\tBRA\tidle_task\n");
|
asm("\n\t.text\nidle_task:\n\tWAIT\n\tBRA\tidle_task\n");
|
|
|
__attribute__((noinline))
|
__attribute__((noinline))
|
void txchr(char v) {
|
void txchr(char v) {
|
if (zip_cc() & CC_GIE) {
|
#ifdef _ZIP_HAS_WBUART
|
while(*UARTTX & 0x100)
|
while(_uart->u_fifo & 0x010000)
|
;
|
;
|
} else
|
uint8_t c = v;
|
wait(INT_UARTTX);
|
_uart->u_tx = (unsigned)c;
|
*UARTTX = v;
|
#endif
|
|
/*
|
|
if (zip_cc() & CC_GIE) {
|
|
while(*UARTTX & 0x100)
|
|
;
|
|
} else
|
|
wait(INT_UARTTX);
|
|
*UARTTX = v;
|
|
*/
|
|
}
|
|
|
|
void wait_for_uart_idle(void) {
|
|
#ifdef _ZIP_HAS_WBUART
|
|
while(_uart->u_fifo & 0x100) // While the FIFO is non-empty
|
|
;
|
|
#else
|
|
#error "No uart defined"
|
|
#endif
|
}
|
}
|
|
|
__attribute__((noinline))
|
__attribute__((noinline))
|
void txstr(const char *str) {
|
void txstr(const char *str) {
|
const char *ptr = str;
|
const char *ptr = str;
|
Line 1146... |
Line 1207... |
txreg("uSP : ", context[13]);
|
txreg("uSP : ", context[13]);
|
txreg("uCC : ", context[14]);
|
txreg("uCC : ", context[14]);
|
txreg("uPC : ", context[15]);
|
txreg("uPC : ", context[15]);
|
txstr("\r\n\r\n");
|
txstr("\r\n\r\n");
|
|
|
|
wait_for_uart_idle();
|
|
asm("NEXIT -1");
|
// While previous versions of cputest.c called zip_busy(), here we
|
// While previous versions of cputest.c called zip_busy(), here we
|
// reject that notion for the simple reason that zip_busy may not
|
// reject that notion for the simple reason that zip_busy may not
|
// necessarily halt any Verilator simulation. Instead, we try to
|
// necessarily halt any Verilator simulation. Instead, we try to
|
// halt the CPU.
|
// halt the CPU.
|
while(1)
|
while(1)
|
Line 1172... |
Line 1235... |
|
|
void entry(void) {
|
void entry(void) {
|
int context[16];
|
int context[16];
|
int user_stack[256], *user_stack_ptr = &user_stack[256];
|
int user_stack[256], *user_stack_ptr = &user_stack[256];
|
int start_time, i;
|
int start_time, i;
|
|
int cc_fail, cis_insns = 0;
|
|
|
|
|
for(i=0; i<32; i++)
|
for(i=0; i<32; i++)
|
testlist[i] = -1;
|
testlist[i] = -1;
|
|
|
#ifdef HAVE_TIMER
|
#ifdef TIMER
|
*TIMER = 0x7fffffff;
|
TIMER = 0x7fffffff;
|
#endif
|
#endif
|
#ifdef HAVE_COUNTER
|
#ifdef COUNTER
|
*COUNTER = 0;
|
COUNTER = 0;
|
#endif
|
#endif
|
#ifdef HAVE_SCOPE
|
#ifdef HAVE_SCOPE
|
SCOPEc = PREPARE_SCOPE;
|
SCOPEc = PREPARE_SCOPE;
|
#endif
|
#endif
|
|
|
|
// UART_CTRL = 82; // 1MBaud, given n 82.5MHz clock
|
|
UART_CTRL = 705; // 115200 Baud, given n 81.25MHz clock
|
// *UART_CTRL = 8333; // 9600 Baud, 8-bit chars, no parity, one stop bit
|
// *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
|
// *UART_CTRL = 25; // 9600 Baud, 8-bit chars, no parity, one stop bit
|
//
|
//
|
|
|
txstr("\r\n");
|
txstr("\r\n");
|
txstr("Running CPU self-test\r\n");
|
txstr("Running CPU self-test\r\n");
|
txstr("-----------------------------------\r\n");
|
txstr("-----------------------------------\r\n");
|
|
|
int tnum = 0;
|
int tnum = 0;
|
|
|
|
// Check whether or not this CPU correctly identifies SIM instructions
|
|
// as illegal instructions
|
|
testid("SIM Instructions"); MARKSTART;
|
|
cc_fail = CC_MMUERR|CC_FPUERR|CC_DIVERR|CC_BUSERR|CC_TRAP|CC_STEP|CC_SLEEP;
|
|
if ((run_test(sim_test, user_stack_ptr))||(zip_ucc()&cc_fail))
|
|
test_fails(start_time, &testlist[tnum]);
|
|
else if (zip_ucc() & CC_ILL) {
|
|
txstr("Pass\r\n"); testlist[tnum++]; // 0
|
|
} else
|
|
txstr("Is this a simulator?\r\n");
|
|
|
|
testid("CIS Instructions"); MARKSTART;
|
|
cc_fail = CC_MMUERR|CC_FPUERR|CC_DIVERR|CC_BUSERR|CC_STEP|CC_SLEEP;
|
|
if ((run_test(cis_test, user_stack_ptr))||(zip_ucc()&cc_fail))
|
|
test_fails(start_time, &testlist[tnum]);
|
|
else if (zip_ucc() & CC_ILL)
|
|
txstr("Not supported\r\n");
|
|
else {
|
|
txstr("Supported\r\n");
|
|
cis_insns = 1;
|
|
}
|
|
|
// Test break instruction in user mode
|
// Test break instruction in user mode
|
// Make sure the break works as designed
|
// Make sure the break works as designed
|
testid("Break test #1"); MARKSTART;
|
testid("Break test #1"); MARKSTART;
|
|
|
if ((run_test(break_one, user_stack_ptr))||(zip_ucc()&0x1f50))
|
cc_fail = CC_MMUERR|CC_FPUERR|CC_DIVERR|CC_BUSERR|CC_TRAP|CC_ILL|CC_STEP|CC_SLEEP;
|
|
if ((run_test(break_one, user_stack_ptr))||(zip_ucc()&cc_fail))
|
test_fails(start_time, &testlist[tnum]);
|
test_fails(start_time, &testlist[tnum]);
|
|
|
save_context(context);
|
save_context(context);
|
if ((context[15] != (int)break_one+1)||(0==(zip_ucc()&0x80)))
|
if ((context[15] != (int)break_one+4)||(0==(zip_ucc()&CC_BREAK)))
|
test_fails(start_time, &testlist[tnum]);
|
test_fails(start_time, &testlist[tnum]);
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // 0
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #1
|
|
|
|
|
// Test break instruction in user mode
|
// Test break instruction in user mode
|
// Make sure that a decision on the clock prior won't still cause a
|
// Make sure that a decision on the clock prior won't still cause a
|
// break condition
|
// break condition
|
|
cc_fail = CC_MMUERR|CC_FPUERR|CC_DIVERR|CC_BUSERR|CC_ILL|CC_BREAK|CC_STEP|CC_SLEEP;
|
testid("Break test #2"); MARKSTART;
|
testid("Break test #2"); MARKSTART;
|
if ((run_test(break_two, user_stack_ptr))||(zip_ucc()&0x1d90))
|
if ((run_test(break_two, user_stack_ptr))||(zip_ucc()&cc_fail))
|
test_fails(start_time, &testlist[tnum]);
|
test_fails(start_time, &testlist[tnum]);
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #1
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #2
|
|
|
// Test break instruction in user mode
|
// Test break instruction in user mode
|
// Make sure that a decision on the clock prior won't still cause a
|
// Make sure that a decision on the clock prior won't still cause a
|
// break condition
|
// break condition
|
|
cc_fail = (CC_FAULT)|CC_MMUERR|CC_TRAP|CC_STEP|CC_SLEEP;
|
testid("Break test #3"); MARKSTART;
|
testid("Break test #3"); MARKSTART;
|
run_test(break_three, user_stack_ptr);
|
run_test(break_three, user_stack_ptr);
|
|
save_context(context);
|
if ((context[15] != (int)break_three) // Insist we stop at the break
|
if ((context[15] != (int)break_three) // Insist we stop at the break
|
||(0==(zip_ucc()&0x80)) // insn, that the break flag is
|
||(0==(zip_ucc()&CC_BREAK))//insn,that the break flag is
|
||(zip_ucc()&0x01d10)) // set, and no other excpt flags
|
||(zip_ucc()&cc_fail)) // set, and no other excpt flags
|
test_fails(start_time, &testlist[tnum]);
|
test_fails(start_time, &testlist[tnum]);
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // 0
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #3
|
|
|
// LJMP test ... not (yet) written
|
// LJMP test ... not (yet) written
|
|
|
// Test the early branching capability
|
// Test the early branching capability
|
// Does it successfully clear whatever else is in the pipeline?
|
// Does it successfully clear whatever else is in the pipeline?
|
testid("Early Branch test"); MARKSTART;
|
testid("Early Branch test"); MARKSTART;
|
if ((run_test(early_branch_test, user_stack_ptr))||(zip_ucc()&0x01d90))
|
if ((run_test(early_branch_test, user_stack_ptr))||(zip_ucc()&CC_EXCEPTION))
|
test_fails(start_time, &testlist[tnum]);
|
test_fails(start_time, &testlist[tnum]);
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #2
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #4
|
|
|
// TRAP test
|
// TRAP test
|
testid("Trap test/AND"); MARKSTART;
|
testid("Trap test/AND"); MARKSTART;
|
if ((run_test(trap_test_and, user_stack_ptr))||(zip_ucc()&0x01d90))
|
if ((run_test(trap_test_and, user_stack_ptr))||(zip_ucc()&CC_EXCEPTION))
|
test_fails(start_time, &testlist[tnum]);
|
test_fails(start_time, &testlist[tnum]);
|
if ((zip_ucc() & 0x0200)==0)
|
if ((zip_ucc() & 0x0200)==0)
|
test_fails(start_time, &testlist[tnum]);
|
test_fails(start_time, &testlist[tnum]);
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #3
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #5
|
|
|
testid("Trap test/CLR"); MARKSTART;
|
testid("Trap test/CLR"); MARKSTART;
|
if ((run_test(trap_test_clr, user_stack_ptr))||(zip_ucc()&0x01d90))
|
if ((run_test(trap_test_clr, user_stack_ptr))||(zip_ucc()&CC_EXCEPTION))
|
test_fails(start_time, &testlist[tnum]);
|
test_fails(start_time, &testlist[tnum]);
|
if ((zip_ucc() & 0x0200)==0)
|
if ((zip_ucc() & 0x0200)==0)
|
test_fails(start_time, &testlist[tnum]);
|
test_fails(start_time, &testlist[tnum]);
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #4
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #6
|
|
|
// Overflow test
|
// Overflow test
|
testid("Overflow test"); MARKSTART;
|
testid("Overflow test"); MARKSTART;
|
if ((run_test(overflow_test, user_stack_ptr))||(zip_ucc()&0x01d90))
|
if ((run_test(overflow_test, user_stack_ptr))||(zip_ucc()&CC_EXCEPTION))
|
test_fails(start_time, &testlist[tnum]);
|
test_fails(start_time, &testlist[tnum]);
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #5
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #7
|
|
|
// Carry test
|
// Carry test
|
testid("Carry test"); MARKSTART;
|
testid("Carry test"); MARKSTART;
|
if ((run_test(carry_test, user_stack_ptr))||(zip_ucc()&0x01d90))
|
if ((run_test(carry_test, user_stack_ptr))||(zip_ucc()&CC_EXCEPTION))
|
test_fails(start_time, &testlist[tnum]);
|
test_fails(start_time, &testlist[tnum]);
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #6
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #8
|
|
|
// LOOP_TEST
|
// LOOP_TEST
|
testid("Loop test"); MARKSTART;
|
testid("Loop test"); MARKSTART;
|
if ((run_test(loop_test, user_stack_ptr))||(zip_ucc()&0x01d90))
|
if ((run_test(loop_test, user_stack_ptr))||(zip_ucc()&CC_EXCEPTION))
|
test_fails(start_time, &testlist[tnum]);
|
test_fails(start_time, &testlist[tnum]);
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #7 -- FAILS
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #9
|
|
|
// SHIFT_TEST
|
// SHIFT_TEST
|
testid("Shift test"); MARKSTART;
|
testid("Shift test"); MARKSTART;
|
if ((run_test(shift_test, user_stack_ptr))||(zip_ucc()&0x01d90))
|
if ((run_test(shift_test, user_stack_ptr))||(zip_ucc()&CC_EXCEPTION))
|
test_fails(start_time, &testlist[tnum]);
|
test_fails(start_time, &testlist[tnum]);
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #8
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #10
|
|
|
// BREV_TEST
|
// BREV_TEST
|
//testid("BREV/stack test"); MARKSTART;
|
//testid("BREV/stack test"); MARKSTART;
|
//if ((run_test(brev_test, user_stack_ptr))||(zip_ucc()&0x01d90))
|
//if ((run_test(brev_test, user_stack_ptr))||(zip_ucc()&0x01d90))
|
//test_fails(start_time);
|
//test_fails(start_time); // #10
|
//txstr("Pass\r\n");
|
//txstr("Pass\r\n");
|
|
|
// PIPELINE_TEST
|
// PIPELINE_TEST
|
testid("Pipeline test"); MARKSTART;
|
testid("Pipeline test"); MARKSTART;
|
if ((run_test(pipeline_test, user_stack_ptr))||(zip_ucc()&0x01d90))
|
if ((run_test(pipeline_test, user_stack_ptr))||(zip_ucc()&CC_EXCEPTION))
|
test_fails(start_time, &testlist[tnum]);
|
test_fails(start_time, &testlist[tnum]);
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #10
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #11
|
|
|
// MEM_PIPELINE_STACK_TEST
|
// MEM_PIPELINE_STACK_TEST
|
testid("Mem-Pipeline test"); MARKSTART;
|
testid("Mem-Pipeline test"); MARKSTART;
|
if ((run_test(mempipe_test, user_stack_ptr))||(zip_ucc()&0x01d90))
|
if ((run_test(mempipe_test, user_stack_ptr))||(zip_ucc()&CC_EXCEPTION))
|
test_fails(start_time, &testlist[tnum]);
|
test_fails(start_time, &testlist[tnum]);
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #11
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #12
|
|
|
// CONDITIONAL EXECUTION test
|
// CONDITIONAL EXECUTION test
|
testid("Conditional Execution test"); MARKSTART;
|
testid("Conditional Execution test"); MARKSTART;
|
if ((run_test(cexec_test, user_stack_ptr))||(zip_ucc()&0x01d90))
|
if ((run_test(cexec_test, user_stack_ptr))||(zip_ucc()&CC_EXCEPTION))
|
test_fails(start_time, &testlist[tnum]);
|
test_fails(start_time, &testlist[tnum]);
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #12 -- FAILS
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #13
|
|
|
// NOWAIT pipeline test
|
// NOWAIT pipeline test
|
testid("No-waiting pipeline test"); MARKSTART;
|
testid("No-waiting pipeline test"); MARKSTART;
|
if ((run_test(nowaitpipe_test, user_stack_ptr))||(zip_ucc()&0x01d90))
|
if ((run_test(nowaitpipe_test, user_stack_ptr))||(zip_ucc()&CC_EXCEPTION))
|
test_fails(start_time, &testlist[tnum]);
|
test_fails(start_time, &testlist[tnum]);
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #13
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #14
|
|
|
// BCMEM test
|
// BCMEM test
|
testid("Conditional Branching test"); MARKSTART;
|
testid("Conditional Branching test"); MARKSTART;
|
if ((run_test(bcmem_test, user_stack_ptr))||(zip_ucc()&0x01d90))
|
if ((run_test(bcmem_test, user_stack_ptr))||(zip_ucc()&CC_EXCEPTION))
|
test_fails(start_time, &testlist[tnum]);
|
test_fails(start_time, &testlist[tnum]);
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #14
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #15
|
|
|
// Illegal Instruction test
|
// Illegal Instruction test
|
testid("Ill Instruction test, NULL PC"); MARKSTART;
|
testid("Ill Instruction test, NULL PC"); MARKSTART;
|
if ((run_test(NULL, user_stack_ptr))||((zip_ucc()^0x100)&0x01d90))
|
if ((run_test(NULL, user_stack_ptr))||((zip_ucc()^CC_ILL)&CC_EXCEPTION))
|
test_fails(start_time, &testlist[tnum]);
|
test_fails(start_time, &testlist[tnum]);
|
txstr("Pass\r\n"); testlist[tnum++] = 0;
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #16
|
|
|
// Illegal Instruction test
|
// Illegal Instruction test
|
|
cc_fail = CC_BUSERR|CC_DIVERR|CC_FPUERR|CC_BREAK|CC_MMUERR;
|
testid("Ill Instruction test, two"); MARKSTART;
|
testid("Ill Instruction test, two"); MARKSTART;
|
if ((run_test(ill_test, user_stack_ptr))||((zip_ucc()^0x100)&0x01d90))
|
if ((run_test(ill_test, user_stack_ptr))||(zip_ucc()&cc_fail))
|
test_fails(start_time, &testlist[tnum]);
|
test_fails(start_time, &testlist[tnum]);
|
save_context(context);
|
save_context(context);
|
if (context[15] != (int)&ill_test)
|
if (context[15] != (int)&ill_test)
|
test_fails(start_time, &testlist[tnum]);
|
test_fails(start_time, &testlist[tnum]);
|
txstr("Pass\r\n"); testlist[tnum++] = 0;
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #17
|
|
|
|
// Compare EQuals test
|
|
cc_fail = CC_BUSERR|CC_DIVERR|CC_FPUERR|CC_BREAK|CC_MMUERR|CC_ILL;
|
|
testid("Comparison test, =="); MARKSTART;
|
|
if ((run_test(cmpeq_test, user_stack_ptr))||(zip_ucc()&CC_EXCEPTION))
|
|
test_fails(start_time, &testlist[tnum]);
|
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #18
|
|
|
|
// Compare !EQuals test
|
|
cc_fail = CC_BUSERR|CC_DIVERR|CC_FPUERR|CC_BREAK|CC_MMUERR|CC_ILL;
|
|
testid("Comparison test, !="); MARKSTART;
|
|
if ((run_test(cmpneq_test, user_stack_ptr))||(zip_ucc()&CC_EXCEPTION))
|
|
test_fails(start_time, &testlist[tnum]);
|
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #19
|
|
|
// Pipeline memory race condition test
|
// Pipeline memory race condition test
|
// DIVIDE test
|
// DIVIDE test
|
|
|
// CC Register test
|
// CC Register test
|
testid("CC Register test"); MARKSTART;
|
testid("CC Register test"); MARKSTART;
|
if ((run_test(ccreg_test, user_stack_ptr))||(zip_ucc()&0x01d90))
|
if ((run_test(ccreg_test, user_stack_ptr))||(zip_ucc()&CC_EXCEPTION))
|
test_fails(start_time, &testlist[tnum]);
|
test_fails(start_time, &testlist[tnum]);
|
txstr("Pass\r\n"); testlist[tnum++] = 0;
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #20
|
|
|
// Multiple argument test
|
// Multiple argument test
|
testid("Multi-Arg test"); MARKSTART;
|
testid("Multi-Arg test"); MARKSTART;
|
if ((run_test(multiarg_test, user_stack_ptr))||(zip_ucc()&0x01d90))
|
if ((run_test(multiarg_test, user_stack_ptr))||(zip_ucc()&CC_EXCEPTION))
|
test_fails(start_time, &testlist[tnum]);
|
test_fails(start_time, &testlist[tnum]);
|
txstr("Pass\r\n"); testlist[tnum++] = 0;
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #21
|
|
|
// MPY_TEST
|
// MPY_TEST
|
testid("Multiply test"); MARKSTART;
|
testid("Multiply test"); MARKSTART;
|
if ((run_test(mpy_test, user_stack_ptr))||(zip_ucc()&0x01d90))
|
if ((run_test(mpy_test, user_stack_ptr))||(zip_ucc()&CC_EXCEPTION))
|
test_fails(start_time, &testlist[tnum]);
|
test_fails(start_time, &testlist[tnum]);
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #9
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #22
|
|
|
// MPYxHI_TEST
|
// MPYxHI_TEST
|
testid("Multiply HI-word test"); MARKSTART;
|
testid("Multiply HI-word test"); MARKSTART;
|
if ((run_test(mpyhi_test, user_stack_ptr))||(zip_ucc()&0x01d90))
|
if ((run_test(mpyhi_test, user_stack_ptr))||(zip_ucc()&CC_EXCEPTION))
|
test_fails(start_time, &testlist[tnum]);
|
test_fails(start_time, &testlist[tnum]);
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #9
|
txstr("Pass\r\n"); testlist[tnum++] = 0; // #23
|
|
|
|
// DIV_TEST
|
|
testid("Divide test");
|
|
if ((zip_cc() & 0x20000000)==0) {
|
|
txstr("No divide unit installed\r\n");
|
|
} else { MARKSTART;
|
|
if ((run_test(div_test, user_stack_ptr))||(zip_ucc()&CC_EXCEPTION))
|
|
test_fails(start_time, &testlist[tnum]);
|
|
} txstr("Pass\r\n"); testlist[tnum++] = 0; // #24
|
|
|
|
|
txstr("\r\n");
|
txstr("\r\n");
|
txstr("-----------------------------------\r\n");
|
txstr("-----------------------------------\r\n");
|
txstr("All tests passed. Halting CPU.\r\n");
|
txstr("All tests passed. Halting CPU.\r\n");
|
|
wait_for_uart_idle();
|
|
for(int k=0; k<50000; k++)
|
|
asm("NOOP");
|
|
asm("NEXIT 0");
|
zip_halt();
|
zip_halt();
|
}
|
}
|
|
|
// To build this:
|
// To build this:
|
// zip-gcc -O3 -Wall -Wextra -nostdlib -fno-builtin -T xula.ld -Wl,-Map,cputest.map cputest.cpp -o cputest
|
// zip-gcc -O3 -Wall -Wextra -nostdlib -fno-builtin -T xula.ld -Wl,-Map,cputest.map cputest.cpp -o cputest
|