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 57 to Rev 69
- ↔ Reverse comparison
Rev 57 → Rev 69
/wdt.S
9,7 → 9,7
; as we can to memory before the watchdog kicks in. |
; |
; Creator: Dan Gisselquist, Ph.D. |
; Gisselquist Tecnology, LLC |
; Gisselquist Technology, LLC |
; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; |
/testdiv.S
7,7 → 7,7
; Purpose: Tests the libraries signed division algorithm. |
; |
; Creator: Dan Gisselquist, Ph.D. |
; Gisselquist Tecnology, LLC |
; Gisselquist Technology, LLC |
; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; |
33,6 → 33,7
; R12 Peripheral base |
; R11 Address of our one memory variable |
; |
/* something else */ |
#include "sys.i" |
start: |
LDI 0xc0000000,R12 ; Get the address of our peripheral base |
39,7 → 40,7
MOV $1(PC),R11 ; Get a memory address for a variable |
BRA skip_test_variable |
test_variable: |
.DAT 0 |
WORD 0 |
skip_test_variable: |
LDI $-1,R0 ; Start the watchdog timer |
STO R0,sys.bus.wdt(R12) |
85,7 → 86,6
BUSY |
|
test_div_program: |
SUB 1,SP |
; |
LDI 1,R11 |
LDI 5,R0 |
92,8 → 92,7
LDI 1,R1 |
LDI 5,R2 |
LDI 0,R3 |
MOV __HERE__+3(PC),R4 |
STO R4,1(SP) |
MOV __HERE__+2(PC),R4 |
BRA test_divs |
|
; |
102,8 → 101,7
LDI 2,R1 |
LDI 2,R2 |
LDI 1,R3 |
MOV __HERE__+3(PC),R4 |
STO R4,1(SP) |
MOV __HERE__+2(PC),R4 |
BRA test_divs |
|
; |
112,8 → 110,7
LDI 0x2d,R1 |
LDI 16496,R2 |
LDI 32,R3 |
MOV __HERE__+3(PC),R4 |
STO R4,1(SP) |
MOV __HERE__+2(PC),R4 |
BRA test_divs |
|
; |
122,8 → 119,7
LDI 120193795,R1 |
LDI 16,R2 |
LDI 108789471,R3 |
MOV __HERE__+3(PC),R4 |
STO R4,1(SP) |
MOV __HERE__+2(PC),R4 |
BRA test_divs |
|
; |
132,8 → 128,7
LDI 142580994,R1 |
LDI 0,R2 |
LDI 203553,R3 |
MOV __HERE__+3(PC),R4 |
STO R4,1(SP) |
MOV __HERE__+2(PC),R4 |
BRA test_divs |
|
; |
142,8 → 137,7
LDI 203553,R1 |
LDI 700,R2 |
LDI 93894,R3 |
MOV __HERE__+3(PC),R4 |
STO R4,1(SP) |
MOV __HERE__+2(PC),R4 |
BRA test_divs |
|
; |
152,8 → 146,7
LDI 2499,R1 |
LDI 57055,R2 |
LDI 549,R3 |
MOV __HERE__+3(PC),R4 |
STO R4,1(SP) |
MOV __HERE__+2(PC),R4 |
BRA test_divs |
|
; |
162,8 → 155,7
LDI 2499,R1 |
LDI -57055,R2 |
LDI -549,R3 |
MOV __HERE__+3(PC),R4 |
STO R4,1(SP) |
MOV __HERE__+2(PC),R4 |
BRA test_divs |
|
; |
172,8 → 164,7
LDI -2499,R1 |
LDI -57055,R2 |
LDI 549,R3 |
MOV __HERE__+3(PC),R4 |
STO R4,1(SP) |
MOV __HERE__+2(PC),R4 |
BRA test_divs |
|
; |
182,8 → 173,7
LDI -2499,R1 |
LDI 57055,R2 |
LDI -549,R3 |
MOV __HERE__+3(PC),R4 |
STO R4,1(SP) |
MOV __HERE__+2(PC),R4 |
BRA test_divs |
|
; |
195,19 → 185,17
; R1 = Denominator |
; R2 = Integer result |
; R3 = Remainder |
; R4 = Return address |
; R11= Test failure ID |
SUB 1,SP |
MOV R2,R4 |
MOV R3,R5 |
MOV __HERE__+3(PC),R2 |
STO R2,1(SP) |
BRA divs |
CMP R0,R4 |
MOV R2,R5 |
MOV R3,R6 |
MOV __HERE__+2(PC),R2 |
BRA lib_divs |
CMP R0,R5 |
BNZ test_failure |
CMP R1,R5 |
CMP R1,R6 |
BNZ test_failure |
ADD 1,SP |
RETN |
JMP R4 |
|
test_failure: |
TRAP 0 |
/lodsto.S
10,7 → 10,7
; worked or didn't. |
; |
; Creator: Dan Gisselquist, Ph.D. |
; Gisselquist Tecnology, LLC |
; Gisselquist Technology, LLC |
; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; |
/pcpc.S
9,7 → 9,7
; to observe it in a simulator to know if it worked or not. |
; |
; Creator: Dan Gisselquist, Ph.D. |
; Gisselquist Tecnology, LLC |
; Gisselquist Technology, LLC |
; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; |
/ivec.S
11,7 → 11,7
; On any failure, the processor will execute a BUSY command. |
; |
; Creator: Dan Gisselquist, Ph.D. |
; Gisselquist Tecnology, LLC |
; Gisselquist Technology, LLC |
; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; |
/zipdhry.S
7,8 → 7,20
; Purpose: Zip assembly file for running the Dhrystone benchmark in the |
; Zip CPU. |
; |
; To calculate a DMIPS value, take the value of R0 upon completion. This |
; is the number of clock ticks used from start to finish (i.e., from |
; entrance into user mode to the return to supervisor mode). Let |
; CLKSPD be your clock speed in Hz. Then: |
; |
; DMIPS = (CLKSPD*NRUNS/R0) / 1757; |
; |
; For my tests, CLKSPD = 100e6 Hz (100 MHz), NRUNS = 512. Thus, |
; |
; DMIPS = (100e6 * 512) / R0 / 1757 |
; |
; |
; Creator: Dan Gisselquist, Ph.D. |
; Gisselquist Tecnology, LLC |
; Gisselquist Technology, LLC |
; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; |
31,9 → 43,20
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; |
// Under Verilator: |
// DMIPS: 28.6 100 MHz (sim) 0.29 |
// DMIPS: 30.3 100 MHz (sim) 0.29 // Initial baseline |
// DMIPS: 37.5 100 MHz (sim) 0.38 // 20151017 |
// DMIPS: 38.0 100 MHz (sim) 0.38 // 20151211 (new ISA) |
// DMIPS: 40.5 100 MHz (sim) 0.41 // 20151212 (H/W DIV) |
// DMIPS: 8.2 100 MHz (sim) 0.08 // 20151104--!pipelined |
// DMIPS: 60.1 100 MHz (sim) 0.60 // 20151215 (New PF) |
// DMIPS: 54.8 100 MHz (sim) 0.55 // 20151219 |
// On real hardware: |
// DMIPS: 24.7 100 MHz (basys) 0.25 // Initial baseline |
// DMIPS: 30.6 100 MHz (basys) 0.31 // 20151017 |
// |
// (And, under Verilator, if the cache holds the entire 4kW program: 55.1 DMIPS) |
// |
// |
// with no loop unrolling nor function inlining |
// DMIPS: 24.3 100 MHz (sim) 0.24 |
// with packed strings |
40,7 → 63,7
// DMIPS: 35.6 100 MHz (sim) 0.36 |
// |
// For comparison: |
// uBlaze: 255 177 MHz 1.44 |
// uBlaze: 230 177 MHz 1.3 |
// LEON3 1.4 |
// NiOS II: 218 185 MHz 1.16 |
// OpenRisk 250 250 MHz 1.00 |
52,23 → 75,88
// |
// SKIP_SHORT_CIRCUITS determines whether or not we do internal testing and |
// jump to a BUSY instruction on failure for the debugger to pick up. Skip |
// this for valid testing. |
// this for valid testing. Enable it and see whether or not zipdhry dies mid |
// process--if it down, you got there--so fix it. |
// |
// #define SKIP_SHORT_CIRCUITS |
#define SKIP_SHORT_CIRCUITS |
// |
// |
// |
// NO_INLINE controls whether or not we inline certain functions. If you |
// define this, nothing will be inlined. |
// |
// I recommend not setting this define. |
// |
// #define NO_INLINE |
// |
// |
// |
// NO_LOOP_UNROLLING controls loop unrolling. The default is to unroll loops |
// by a factor of 4x. By defining this, all loop unrolling is removed. |
// by a factor of 4x. By defining this, all loop unrolling is removed. (Well, |
// except the pipelined strcpy and strcmp below--those loops are automatically |
// unrolled as part of being piped. Undefine those as well and all loops will |
// be effectively unrolled. |
// |
// I recommend not setting this define. |
// |
// #define NO_LOOP_UNROLLING |
// |
// Use PSTRS has to deal with whether or not we are processing packed strings |
// or normal strings. Packed strings are really a cheaters exception to the |
// dhrystone measure, although they do get our score up. |
// |
// #define USE_PSTRS |
// |
// After building this whole thing and putting it together, I discovered another |
// means I could use of generating a return statement. In this case, instead |
// of LOD -1(SP),PC, I would load the return PC from the stack as part of the |
// pipelined memory operations, adjust the stack pointer, and jump to the |
// register address. It saves clocks because it uses the pipelined memory |
// operation, but other than that it suffers the same number of stalls. |
// |
// Fast returns used to be controlled by a #define. This has been removed, |
// and all returns are "fast" by default. |
// |
// |
// |
// |
// |
// SKIP_DIVIDE controlls whether or not we want to calculate the speed of |
// our processor assuming we had a divide instruction. If you skip the |
// divide, it will be as though you had such an instruction. Otherwise, |
// leave it in and the test bench will measure how long it takes to run |
// while including the divide emulation. |
// |
// I recommend leaving this undefined, for a more accurate measure. |
// |
// #define SKIP_DIVIDE // 0xace17/0x50f37 vs 0xbd817/0x57d37 |
// |
// Thus a divide instruction might raise our score from 37.5 to 41.1, or |
// from 81 to 87.8--depending on whether or not the cache is loaded or not. |
// |
// |
// |
// |
// HARDWARE_DIVIDE is appropriate when the hardware has a divide instruction, |
// as it will use this divide instruction for the one time a divide is needed. |
// |
// I recommended setting this value ... IF the hardware has the divide |
// instruction built in. |
// |
#define HARDWARE_DIVIDE |
// |
// |
// PIPELINED_STRCPY and PIPELINED_STRCMP both have to do with whether or not |
// the memory accesses of each of these "library" functions are pipelined. |
// As you may recall, the Zip CPU allows you to pipeline memory accesses |
// that are all done with the same condition, and that all reference either |
// the same or increasing addresses. These one-clock memory access instructions |
// are ridiculously fast (when available), and we would be foolish not to use |
// them. These two defines modify the library functions to use this mode |
// and to capitalize upon it as much as possible. |
// |
// I recommend setting these. |
// |
#define PIPELINED_STRCPY |
#define PIPELINED_STRCMP |
// |
// |
sys.ctr.mtask equ 0xc0000008 |
// int main(int argc, char **argv) { |
// dhrystone(); |
82,8 → 170,7
CLR R0 |
STO R0,(R1) |
#ifdef SUPERVISOR_TASK |
MOV __HERE__+3(PC),R0 |
STO R0,1(SP) |
MOV __HERE__+2(PC),R0 |
BRA dhrystone |
#else |
MOV dhrystone(PC),uPC |
98,11 → 185,7
|
// typedef int Arr_1_Dim[50]; |
// typedef int Arr_2_Dim[50][50]; |
#ifdef USE_PSTRS |
#define RECSIZE 12 |
#else |
#define RECSIZE 35 |
#endif |
#define NUMBER_OF_RUNS (512) |
ptr_comp equ 0 |
discr equ 1 |
124,6 → 207,32
word 0 |
gbl_ptr: |
word 0 |
|
some_string: |
word 'D','H','R','Y','S','T','O','N','E',' ' |
word 'P','R','O','G','R','A','M',',',' ' |
word 'S','O','M','E',' ','S','T','R','I','N','G' |
word 0 |
|
first_string: |
word 'D','H','R','Y','S','T','O','N','E',' ' |
word 'P','R','O','G','R','A','M',',' |
word ' ','1','\'','S','T' |
word ' ','S','T','R','I','N','G' |
word 0 |
|
second_string: |
word 'D','H','R','Y','S','T','O','N','E',' ' |
word 'P','R','O','G','R','A','M',',',' ' |
word '2','\'','N','D',' ','S','T','R','I','N','G' |
word 0 |
|
third_string: |
word 'D','H','R','Y','S','T','O','N','E',' ' |
word 'P','R','O','G','R','A','M',',',' ' |
word '3','\'','R','D',' ','S','T','R','I','N','G' |
word 0 |
|
// Arr_1_Dim gbl_arr_1; |
// Arr_2_Dim gbl_arr_2; |
// char gbl_ch, gbl_ch_2; |
140,67 → 249,104
// |
//} |
// |
|
#ifdef PIPELINED_STRCPY |
; On entry, |
; R0 = dst |
; R1 = src |
; R2 = return address |
lcl_strcpy: |
SUB 4,SP |
STO R2,(SP) |
STO R3,1(SP) |
STO R4,2(SP) |
STO R5,3(SP) |
|
copy_next_char: |
; R0 = d |
; R1 = s |
; R3 = ch |
LOD (R1),R2 |
LOD 1(R1),R3 |
LOD 2(R1),R4 |
LOD 3(R1),R5 |
|
CMP 0,R2 |
CMP.NZ 0,R3 |
CMP.NZ 0,R4 |
CMP.NZ 0,R5 |
BZ end_strcpy |
|
STO R2,(R0) |
STO R3,1(R0) |
STO R4,2(R0) |
STO R5,3(R0) |
|
ADD 4,R1 |
ADD 4,R0 |
BRA copy_next_char |
|
end_strcpy: |
CMP 0,R2 |
STO.NZ R2,(R0) |
CMP.NZ 0,R3 |
STO.NZ R3,1(R0) |
CMP.NZ 0,R4 |
STO.NZ R4,1(R0) |
CMP.NZ 0,R5 |
STO.NZ R5,1(R0) |
|
LOD (SP),R2 |
LOD 1(SP),R3 |
LOD 2(SP),R4 |
LOD 3(SP),R5 |
ADD 4,SP |
JMP R2 |
NOP |
|
#else |
lcl_strcpy: |
; R0 = d |
; R1 = s |
; R3 = ch |
copy_next_char: |
SUB 1,SP |
STO R2,(SP) |
#ifdef NO_LOOP_UNROLLING |
LOD (R1),R2 |
STO R2,(R0) |
#ifdef USE_PSTRS |
TST 255,R2 |
#else |
CMP 0,R2 |
#endif |
RETN.Z |
BZ lcl_strcpy_end_of_loop |
ADD 1,R0 |
ADD 1,R1 |
BRA copy_next_char |
|
|
|
#else |
LOD (R1),R2 |
STO R2,(R0) |
#ifdef USE_PSTRS |
TST 255,R2 |
#else |
CMP 0,R2 |
#endif |
; BZ lcl_strcpy_end_of_loop |
RETN.Z |
BZ lcl_strcpy_end_of_loop |
LOD 1(R1),R2 |
STO R2,1(R0) |
#ifdef USE_PSTRS |
TST 255,R2 |
#else |
CMP 0,R2 |
#endif |
; BZ lcl_strcpy_end_of_loop |
RETN.Z |
BZ lcl_strcpy_end_of_loop |
LOD 2(R1),R2 |
STO R2,2(R0) |
#ifdef USE_PSTRS |
TST 255,R2 |
#else |
CMP 0,R2 |
#endif |
; BZ lcl_strcpy_end_of_loop |
RETN.Z |
BZ lcl_strcpy_end_of_loop |
LOD 3(R1),R2 |
STO R2,3(R0) |
; BZ lcl_strcpy_end_of_loop |
#ifdef USE_PSTRS |
TST 255,R2 |
#else |
CMP 0,R2 |
#endif |
RETN.Z |
BZ lcl_strcpy_end_of_loop |
ADD 4,R0 |
ADD 4,R1 |
BRA copy_next_char |
#endif |
lcl_strcpy_end_of_loop: |
LOD (SP),R2 |
ADD 1,SP |
JMP R2 |
#endif |
|
//int lcl_strcmp(char *s1, char *s2) { |
// char a, b; |
211,11 → 357,91
// return a-b; |
//} |
|
#ifdef PIPELINED_STRCMP |
lcl_strcmp: |
SUB 1,SP |
SUB 8,SP |
STO R2,(SP) |
STO R3,1(SP) |
STO R4,2(SP) |
STO R5,3(SP) |
STO R6,4(SP) |
STO R7,5(SP) |
STO R8,6(SP) |
STO R9,7(SP) |
|
strcmp_top_of_loop: |
LOD (R0),R2 |
LOD 1(R0),R3 |
LOD 2(R0),R4 |
LOD 3(R0),R5 |
; |
LOD (R1),R6 |
LOD 1(R1),R7 |
LOD 2(R1),R8 |
LOD 3(R1),R9 |
; |
CMP 0,R2 |
CMP.NZ 0,R3 |
CMP.NZ 0,R4 |
CMP.NZ 0,R5 |
BZ strcmp_end_loop |
|
CMP R2,R6 |
CMP.Z R3,R7 |
CMP.Z R4,R8 |
CMP.Z R5,R9 |
BNZ strcmp_end_loop |
|
ADD 4,R0 |
ADD 4,R1 |
BRA strcmp_top_of_loop |
|
strcmp_end_loop: |
CMP 0,R2 |
BZ final_str_compare |
CMP R2,R6 |
BNZ final_str_compare |
|
MOV R3,R2 |
MOV R7,R6 |
CMP 0,R2 |
BZ final_str_compare |
CMP R2,R6 |
BNZ final_str_compare |
|
MOV R4,R2 |
MOV R8,R6 |
CMP 0,R2 |
BZ final_str_compare |
CMP R2,R6 |
BNZ final_str_compare |
|
MOV R5,R2 |
MOV R9,R6 |
|
final_str_compare: |
SUB R6,R2 |
MOV R2,R0 |
|
LOD (SP),R2 |
LOD 1(SP),R3 |
LOD 2(SP),R4 |
LOD 3(SP),R5 |
LOD 4(SP),R6 |
LOD 5(SP),R7 |
LOD 6(SP),R8 |
LOD 7(SP),R9 |
ADD 8,SP |
JMP R2 |
NOP |
|
#else |
lcl_strcmp: |
SUB 2,SP |
STO R2,(SP) |
STO R3,1(SP) |
|
strcmp_top_of_loop: |
#ifdef NO_LOOP_UNROLLING |
; LOD (R0),R2 |
; LOD (R1),R3 ; Alternate approach: |
230,11 → 456,7
; BRA strcmp_top_of_loop |
LOD (R0),R2 |
LOD (R1),R3 |
#ifdef USE_PSTRS |
TST 255,R2 |
#else |
CMP 0,R2 |
#endif |
BZ strcmp_end_loop |
ADD 1,R0 |
ADD 1,R1 |
243,41 → 465,25
#else |
LOD (R0),R2 |
LOD (R1),R3 |
#ifdef USE_PSTRS |
TST 255,R2 |
#else |
CMP 0,R2 |
#endif |
BZ strcmp_end_loop |
CMP R2,R3 |
BNZ strcmp_end_loop |
LOD 1(R0),R2 |
LOD 1(R1),R3 |
#ifdef USE_PSTRS |
TST 255,R2 |
#else |
CMP 0,R2 |
#endif |
BZ strcmp_end_loop |
CMP R2,R3 |
BNZ strcmp_end_loop |
LOD 2(R0),R2 |
LOD 2(R1),R3 |
#ifdef USE_PSTRS |
TST 255,R2 |
#else |
CMP 0,R2 |
#endif |
BZ strcmp_end_loop |
CMP R2,R3 |
BNZ strcmp_end_loop |
LOD 3(R0),R2 |
LOD 3(R1),R3 |
#ifdef USE_PSTRS |
TST 255,R2 |
#else |
CMP 0,R2 |
#endif |
BZ strcmp_end_loop |
CMP R2,R3 |
BNZ strcmp_end_loop |
290,9 → 496,11
SUB R3,R2 |
MOV R2,R0 |
|
LOD (SP),R2 |
LOD 1(SP),R3 |
ADD 1,SP |
RETN |
ADD 2,SP |
JMP R2 |
#endif |
|
|
//test_enum func_1(char ch_1, char ch_2) { |
315,12 → 523,16
; R2 = available |
; On output, R0 is our return value |
|
SUB 1,SP |
STO R2,(SP) |
MOV R0,R2 |
CMP R2,R1 |
CLR.NZ R0 |
STO.Z R2,gbl_ch(R12) |
LDILO.Z 1,R0 |
RETN |
LOD (SP),R2 |
ADD 1,SP |
JMP R2 |
#endif |
|
//bool func_2(char *str_1, char *str_2) { |
350,11 → 562,12
func_2: |
; |
SUB 6,SP |
STO R3,2(SP) |
STO R4,3(SP) |
STO R5,4(SP) |
STO R6,5(SP) |
STO R7,6(SP) |
STO R2,(SP) |
STO R3,1(SP) |
STO R4,2(SP) |
STO R5,3(SP) |
STO R6,4(SP) |
STO R7,5(SP) |
|
MOV R0,R3 ; R3 = str_1 |
MOV R1,R4 ; R4 = str_2 |
373,8 → 586,7
ADD R5,R6 |
LOD 1(R6),R1 |
|
MOV __HERE__+3(PC),R2 |
STO R2,1(SP) |
MOV __HERE__+2(PC),R2 |
BRA func_1 |
|
CMP 0,R0 |
417,8 → 629,7
// |
MOV R3,R0 |
MOV R4,R1 |
MOV __HERE__+3(PC),R2 |
STO R2,1(SP) |
MOV __HERE__+2(PC),R2 |
BRA lcl_strcmp |
CMP 0,R0 |
BGT func_2_final_then |
432,13 → 643,15
#endif |
func_2_return_and_cleanup: |
|
LOD 2(SP),R3 |
LOD 3(SP),R4 |
LOD 4(SP),R5 |
LOD 5(SP),R6 |
LOD 6(SP),R7 |
LOD (SP),R2 |
LOD 1(SP),R3 |
LOD 2(SP),R4 |
LOD 3(SP),R5 |
LOD 4(SP),R6 |
LOD 5(SP),R7 |
ADD 6,SP |
RETN |
JMP R2 |
NOP |
|
//bool func_3(test_enum a) { |
// test_enum lcl_enum; |
456,9 → 669,9
; R0 = a |
; R1 - available |
CMP 2,R0 |
CLR R0 ; CLR Doesn't set flags |
LDILO.Z 1,R0 |
RETN |
CLR R0 ; CLR Doesn't set flags |
LDILO.Z 1,R0 |
JMP R1 |
#endif |
|
|
488,13 → 701,14
; On entry: |
; R0 = ev |
; R1 = ep |
; R2 - unassigned |
; R2 = link address |
; Since we call func_3, we have to reserve R0 and R1 |
; for other purposes. Thus |
; R2 = ev |
; R3 = ep |
SUB 2,SP |
STO R3,2(SP) |
STO R2,(SP) |
STO R3,1(SP) |
|
MOV R1,R3 |
MOV R0,R2 |
507,25 → 721,23
|
#ifdef NO_INLINE |
; !func_3(ev) |
MOV __HERE__+3(PC),R1 |
STO R1,1(SP) |
MOV __HERE__+2(PC),R1 |
BRA func_3 |
|
TST -1,R0 |
LDI 3,R1 |
#ifndef SKIP_SHORT_CIRCUITS |
BUSY.Z |
#endif |
STO.Z R1,(R3) |
#else |
CMP 2,R0 |
CMP 2,R0 |
LDI 3,R1 |
STO.Z R1,(R3) |
#ifdef SKIP_SHORT_CIRCUITS |
BUSY.NZ |
#endif |
|
TST -1,R0 |
LDI 3,R1 |
#ifndef SKIP_SHORT_CIRCUITS |
BUSY.Z |
STO.NZ R1,(R3) |
#endif |
STO.Z R1,(R3) |
|
#ifndef SKIP_SHORT_CIRCUITS |
CMP 2,R2 |
568,9 → 780,11
// BRA proc_6_end_of_case |
proc_6_case_not_four: |
proc_6_end_of_case: |
LOD 2(SP),R3 |
LOD (SP),R2 |
LOD 1(SP),R3 |
ADD 2,SP |
RETN |
JMP R2 |
NOP |
|
// void proc_7(int a, int b, int *c) { |
// int lcl; |
584,7 → 798,7
ADD 2+R0,R1 |
STO R1,(R2) |
|
RETN |
JMP R3 |
#endif |
|
// int a[50]; |
612,7 → 826,8
; Makes no function/procedure calls, so these can keep |
; R2 = loc = c+5, replaces c |
; R4 = idx |
SUB 2,SP |
SUB 3,SP |
STO R4,(SP) |
STO R5,1(SP) |
STO R6,2(SP) |
|
652,10 → 867,11
LDI 5,R3 |
STO R3,gbl_int(R12) |
|
LOD (SP),R4 |
LOD 1(SP),R5 |
LOD 2(SP),R6 |
ADD 2,SP |
RETN |
ADD 3,SP |
JMP R4 |
|
// void proc_5(void) { |
// gbl_ch = 'A'; |
663,12 → 879,17
//} |
#ifdef NO_INLINE |
proc_5: |
SUB 1,SP |
STO R0,(SP) |
; |
LDI 'A',R0 |
STO R0,gbl_ch(R12) |
CLR R0 |
STO R0,gbl_bool(R12) |
; |
RETN |
LOD (SP),R0 |
ADD 1,SP |
JMP R0 |
#endif |
|
// void proc_4(void) { |
689,10 → 910,15
; CMP 'A',R0 |
; ADD.Z 1,R1 |
; |
SUB 1,SP |
STO R0,(SP) |
; |
LDI 'B',R0 |
STO R0,gbl_ch_2(R12) |
; |
RETN |
LOD (SP),R0 |
ADD 1,SP |
JMP R0 |
#endif |
|
// void proc_3(RECP *a) { |
702,9 → 928,9
//} |
proc_3: |
SUB 3,SP |
STO R1,(SP) |
STO R2,1(SP) |
STO R3,2(SP) |
STO R2,3(SP) |
; Save one for the return address from our JSR "instruction" |
; |
LOD gbl_ptr(R12),R2 |
TST -1,R2 |
717,8 → 943,7
LDI 10,R0 |
LOD gbl_int(R12),R1 |
MOV variant.var_1.int_comp(R2),R2 |
MOV __HERE__+3(PC),R3 |
STO R3,1(SP) |
MOV __HERE__+2(PC),R3 |
BRA proc_7 |
#else |
LOD gbl_int(R12),R1 |
726,12 → 951,13
STO R1,variant.var_1.int_comp(R2) |
#endif |
; |
LOD (SP),R1 |
LOD 1(SP),R2 |
LOD 2(SP),R3 |
LOD 3(SP),R2 |
ADD 3,SP |
RETN |
JMP R1 |
NOP |
|
|
// void proc_2(int *a) { |
// int lcl_int; |
// test_enum lcl_enum; |
746,12 → 972,13
// } while(lcl_enum != Ident_1); |
//} |
proc_2: |
SUB 5,SP |
STO R6,1(SP) |
STO R5,2(SP) |
SUB 6,SP |
STO R1,(SP) |
STO R2,1(SP) |
STO R3,2(SP) |
STO R4,3(SP) |
STO R3,4(SP) |
STO R2,5(SP) |
STO R5,4(SP) |
STO R6,5(SP) |
// R1 doesn't need to be stored, it was used in the subroutine |
// call calculation |
|
782,13 → 1009,15
STO R2,(R0) |
#endif |
; |
LOD 1(SP),R6 |
LOD 2(SP),R5 |
LOD (SP),R1 |
LOD 1(SP),R2 |
LOD 2(SP),R3 |
LOD 3(SP),R4 |
LOD 4(SP),R3 |
LOD 5(SP),R2 |
ADD 5,SP |
RETN |
LOD 4(SP),R5 |
LOD 5(SP),R6 |
ADD 6,SP |
JMP R1 |
NOP |
|
//void proc_1 (RECP a) { |
// RECP nxt = a->ptr_comp; |
810,15 → 1039,20
// *a = *(a->ptr_comp); |
//} |
proc_1: |
SUB 9,SP |
STO R2,2(SP) |
STO R3,3(SP) |
STO R4,4(SP) |
STO R5,5(SP) |
STO R6,6(SP) |
STO R7,7(SP) |
STO R8,8(SP) |
STO R9,9(SP) |
SUB 11,SP |
STO R1,(SP) |
STO R2,1(SP) |
STO R3,2(SP) |
STO R4,3(SP) |
STO R5,4(SP) |
STO R6,5(SP) |
STO R7,6(SP) |
STO R8,7(SP) |
STO R9,8(SP) |
#ifndef NO_LOOP_UNROLLING |
STO R10,9(SP) |
STO R11,10(SP) |
#endif |
|
; R9 = a |
; R4 = nxt |
829,10 → 1063,20
#ifndef SKIP_SHORT_CIRCUITS |
TST -1,R4 |
BUSY.Z |
CMP PC,R9 |
BUSY.LT |
#endif |
LDI 35,R5 |
MOV R9,R6 |
LOD gbl_ptr(R12),R7 |
|
#ifndef SKIP_SHORT_CIRCUITS |
LOD variant.var_1.enum_comp(R7), R0 |
CMP 2,R0 |
BUSY.NZ |
#endif |
|
#ifdef NO_LOOP_UNROLLING |
LDI 35,R5 |
proc_1_assign_loop_1: |
LOD (R6),R8 |
ADD 1,R6 |
840,11 → 1084,41
ADD 1,R7 |
SUB 1,R5 |
BNZ proc_1_assign_loop_1; |
#else |
|
; R2 is available |
; R3 is available |
|
LDI 34,R5 |
proc_1_assign_loop_1: |
LOD (R6),R8 |
LOD 1(R6),R10 |
LOD 2(R6),R11 |
LOD 3(R6),R2 |
LOD 4(R6),R3 |
ADD 5,R6 |
SUB 5,R5 |
STO R8,(R7) |
STO R10,1(R7) |
STO R11,2(R7) |
STO R2,3(R7) |
STO R3,4(R7) |
BLT proc_1_assign_loop_1_end |
ADD 5,R7 |
; BNZ proc_1_assign_loop_1; |
BRA proc_1_assign_loop_1 |
proc_1_assign_loop_1_end: |
; Loop length is fixed, nothing to test here |
#endif |
|
#ifndef SKIP_SHORT_CIRCUITS |
LOD gbl_ptr(R12),R2 |
TST -1,R2 |
BUSY.Z |
; |
LOD variant.var_1.enum_comp(R9), R0 |
CMP 2,R0 |
BUSY.NZ |
#endif |
|
LDI 5,R5 |
851,8 → 1125,7
STO R5,variant.var_1.int_comp(R9) |
STO R5,variant.var_1.int_comp(R4) |
MOV ptr_comp(R4),R0 |
MOV __HERE__+3(PC),R1 |
STO R1,1(SP) |
MOV __HERE__+2(PC),R1 |
BRA proc_3 ; Uses R0 and R1 |
|
LOD discr(R4),R5 |
868,8 → 1141,7
BUSY.NZ |
#endif |
MOV variant.var_1.enum_comp+R4, R1 |
MOV __HERE__+3(PC),R2 |
STO R2,1(SP) |
MOV __HERE__+2(PC),R2 |
BRA proc_6 |
; |
LOD gbl_ptr(R12),R5 |
881,7 → 1153,6
LDI 10,R1 |
MOV variant.var_1.int_comp(R4),R2 |
MOV proc_1_return_closeout(PC),R3 |
STO R3,1(SP) |
BRA proc_7 |
#else |
LOD variant.var_1.int_comp(R4),R0 |
907,16 → 1178,22
// |
proc_1_return_closeout: |
// |
LOD 2(SP),R2 |
LOD 3(SP),R3 |
LOD 4(SP),R4 |
LOD 5(SP),R5 |
LOD 6(SP),R6 |
LOD 7(SP),R7 |
LOD 8(SP),R8 |
LOD 9(SP),R9 |
ADD 9,SP |
RETN |
LOD (SP),R1 |
LOD 1(SP),R2 |
LOD 2(SP),R3 |
LOD 3(SP),R4 |
LOD 4(SP),R5 |
LOD 5(SP),R6 |
LOD 6(SP),R7 |
LOD 7(SP),R8 |
LOD 8(SP),R9 |
#ifndef NO_LOOP_UNROLLING |
LOD 9(SP),R10 |
LOD 10(SP),R11 |
#endif |
ADD 11,SP |
JMP R1 // Jumps to wrong address ?? |
NOP |
|
// void dhrystone(void) { |
// int lcl_int_1, lcl_int_2, lcl_int_3, index, number_of_runs = 500; |
967,67 → 1244,23
// } |
//} |
|
some_string: |
#ifdef USE_PSTRS |
word 'DHRY','STON','E PR','OGRA','M, S','OME ' |
word 'STRI','NG\0\0' |
#else |
word 'D','H','R','Y','S','T','O','N','E',' ' |
word 'P','R','O','G','R','A','M',',',' ' |
word 'S','O','M','E',' ','S','T','R','I','N','G' |
word 0 |
#endif |
|
first_string: |
#ifdef USE_PSTRS |
word 'DHRY','STON','E PR','OGRA' |
word 'M, 1','\'ST ','STRI','NG\0\0' |
#else |
word 'D','H','R','Y','S','T','O','N','E',' ' |
word 'P','R','O','G','R','A','M',',' |
word ' ','1','\'','S','T' |
word ' ','S','T','R','I','N','G' |
word 0 |
#endif |
|
second_string: |
#ifdef USE_PSTRS |
word 'DHRY','STON','E PR','OGRA' |
word 'M, 2','\'ND ','STRI','NG\0\0' |
#else |
word 'D','H','R','Y','S','T','O','N','E',' ' |
word 'P','R','O','G','R','A','M',',',' ' |
word '2','\'','N','D',' ','S','T','R','I','N','G' |
word 0 |
#endif |
|
third_string: |
#ifdef USE_PSTRS |
word 'DHRY','STON','E PR','OGRA' |
word 'M, 3','\'RD ','STRI','NG\0\0' |
#else |
word 'D','H','R','Y','S','T','O','N','E',' ' |
word 'P','R','O','G','R','A','M',',',' ' |
word '3','\'','R','D',' ','S','T','R','I','N','G' |
word 0 |
#endif |
|
dhrystone: |
#ifdef SUPERVISOR_TASK |
SUB 12+RECSIZE+RECSIZE+30+30+3,SP |
; Leave a space on the top of the stack for calling |
; subroutines. |
STO R1,2(SP) |
STO R2,3(SP) |
STO R3,4(SP) |
STO R4,5(SP) |
STO R5,6(SP) |
STO R6,7(SP) |
STO R7,8(SP) |
STO R8,9(SP) |
STO R9,10(SP) |
STO R10,11(SP) |
STO R11,12(SP) |
STO R0,(SP) |
STO R1,1(SP) |
STO R2,2(SP) |
STO R3,3(SP) |
STO R4,4(SP) |
STO R5,5(SP) |
STO R6,6(SP) |
STO R7,7(SP) |
STO R8,8(SP) |
STO R9,9(SP) |
STO R10,10(SP) |
STO R11,11(SP) |
lcl_int_1 equ 12 ; plus SP |
#else |
lcl_int_1 equ 2 ; plus SP |
1065,15 → 1298,13
// lcl_strcpy(gbl_ptr->variant.var_1.str_comp, "DHRYSTONE PROGRAM, SOME STRING"); |
MOV variant.var_1.str_comp(R0),R0 |
MOV some_string(PC),R1 |
MOV __HERE__+3(PC),R2 |
STO R2,1(SP) |
MOV __HERE__+2(PC),R2 |
BRA lcl_strcpy |
|
// lcl_strcpy(lcl_str_1, "DHRYSTONE PROGRAM, 1\'ST STRING"); |
MOV lcl_str_1(SP),R0 |
MOV first_string(PC),R1 |
MOV __HERE__+3(PC),R2 |
STO R2,1(SP) |
MOV __HERE__+2(PC),R2 |
BRA lcl_strcpy |
|
// gbl_arr_2[8][7] = 10; |
1087,8 → 1318,7
;; Start of Dhrystone main loop |
; proc_5(); |
#ifdef NO_INLINE |
MOV __HERE__+3(PC),R0 |
STO R0,1(SP) |
MOV __HERE__+2(PC),R0 |
BRA proc_5 |
#else |
LDI 'A',R0 |
1098,8 → 1328,7
#endif |
; proc_4(); |
#ifdef NO_INLINE |
MOV __HERE__+3(PC),R0 |
STO R0,1(SP) |
MOV __HERE__+2(PC),R0 |
BRA proc_4 |
#else |
LDI 'B',R0 |
1113,8 → 1342,7
// lcl_strcpy(lcl_str_2, "DHRYSTONE PROGRAM, 2\'ND STRING"); |
MOV lcl_str_2(SP),R0 |
MOV second_string(PC),R1 |
MOV __HERE__+3(PC),R2 |
STO R2,1(SP) |
MOV __HERE__+2(PC),R2 |
BRA lcl_strcpy |
// lcl_enum = Ident_2; |
LDI 2,R0 |
1122,8 → 1350,7
// gbl_bool = !func_2(lcl_str_1, lcl_str_2); |
MOV lcl_str_1(SP),R0 |
MOV lcl_str_2(SP),R1 |
MOV __HERE__+3(PC),R2 |
STO R2,1(SP) |
MOV __HERE__+2(PC),R2 |
BRA func_2 |
CLR R1 |
TST -1,R0 |
1143,13 → 1370,16
MPYS 5,R7 |
SUB R6,R7 |
STO R7,lcl_int_3(SP) |
#ifndef SKIP_SHORT_CIRCUITS |
CMP 7,R7 |
BUSY.NZ |
#endif |
// proc_7(lcl_int_1, lcl_int_2, &lcl_int_3); |
#ifdef NO_INLINE |
MOV R5,R0 |
MOV R6,R1 |
MOV lcl_int_3(SP),R2 |
MOV __HERE__+3(PC),R3 |
STO R3,1(SP) |
MOV __HERE__+2(PC),R3 |
BRA proc_7 |
#else |
MOV R6,R1 |
1167,18 → 1397,26
dhrystone_end_while_loop: |
// } |
// |
#ifndef SKIP_SHORT_CIRCUITS |
LOD lcl_int_1(SP),R0 |
CMP 3,R0 |
BUSY.NZ |
CMP 3,R6 |
BUSY.NZ |
LOD lcl_int_3(SP),R0 |
CMP 7,R0 |
BUSY.NZ |
#endif |
// proc_8(gbl_arr_1, gbl_arr_2, lcl_int_1, lcl_int_3); |
MOV gbl_arr_1(PC),R0 |
MOV gbl_arr_2(PC),R1 |
MOV R5,R2 |
MOV R6,R3 |
MOV __HERE__+3(PC),R4 |
STO R4,1(SP) |
MOV __HERE__+2(PC),R4 |
BRA proc_8 |
// proc_1(gbl_ptr); |
LOD gbl_ptr(PC),R0 |
MOV __HERE__+3(PC),R2 |
STO R2,1(SP) |
MOV __HERE__+2(PC),R1 |
BRA proc_1 |
// |
// for(ch_index='A'; ch_index <= gbl_ch_2; ch_index++) { |
1191,8 → 1429,7
#ifdef NO_INLINE |
MOV R7,R0 |
LDI 'C',R1 |
MOV __HERE__+3(PC),R2 |
STO R2,1(SP) |
MOV __HERE__+2(PC),R2 |
BRA func_1 |
#else |
CMP 'C',R7 |
1209,20 → 1446,18
// proc_6(0, &lcl_enum); |
|
#ifndef SKIP_SHORT_CIRCUITS |
BUSY |
BUSY // Shouldn't ever get here |
#endif |
|
CLR R0 |
MOV lcl_enum(SP),R1 |
MOV __HERE__+3(PC),R2 |
STO R2,1(SP) |
MOV __HERE__+2(PC),R2 |
BRA proc_6 |
|
// lcl_strcpy(lcl_str_2, "DHRYSTONE PROGRAM, 3\'RD STRING"); |
MOV lcl_str_2(SP),R0 |
MOV third_string(PC),R1 |
MOV __HERE__+3(PC),R2 |
STO R2,1(SP) |
MOV __HERE__+2(PC),R2 |
BRA lcl_strcpy |
// lcl_int_2 = index; |
MOV R11,R6 |
1236,20 → 1471,35
BGE dhrystone_top_of_for_loop |
dhrystone_end_of_for_loop: |
// } |
#ifndef SKIP_SHORT_CIRCUITS |
LOD lcl_int_1(SP),R0 |
CMP 3,R0 |
BUSY.NZ |
CMP 3,R6 |
BUSY.NZ |
LOD lcl_int_3(SP),R0 |
CMP 7,R0 |
BUSY.NZ |
#endif |
// |
// lcl_int_2 = lcl_int_2 * lcl_int_1; |
LOD lcl_int_1(SP),R5 |
MPYS R5,R6 ; lcl_int_2 = |
// lcl_int_1 = lcl_int_2 / lcl_int_3; |
#ifdef HARDWARE_DIVIDE |
LOD lcl_int_3(SP),R1 |
MOV R6,R0 |
DIVS R1,R0 |
#else |
#ifndef SKIP_DIVIDE |
MOV R6,R0 |
LOD lcl_int_3(SP),R1 |
MOV __HERE__+3(PC),R2 |
STO R2,1(SP) |
BRA divs |
MOV __HERE__+2(PC),R2 |
BRA lib_divs |
#else |
LDI 9,R0 |
#endif |
#endif |
STO R0,lcl_int_1(SP) |
// lcl_int_2 = 7 * ( lcl_int_2 - lcl_int_3) - lcl_int_1; |
LOD lcl_int_3(SP),R2 |
1257,10 → 1507,24
MPYS 7,R6 |
SUB R0,R6 |
// proc_2(&lcl_int_1); |
#ifndef SKIP_SHORT_CIRCUITS |
LOD lcl_int_1(SP),R0 |
CMP 1,R0 |
BUSY.NZ |
CMP 13,R6 |
BUSY.NZ |
LOD lcl_int_3(SP),R0 |
CMP 7,R0 |
BUSY.NZ |
#endif |
MOV lcl_int_1(SP),R0 |
MOV __HERE__+3(PC),R1 |
STO R1,1(SP) |
MOV __HERE__+2(PC),R1 |
BRA proc_2 |
#ifndef SKIP_SHORT_CIRCUITS |
LOD lcl_int_1(SP),R0 |
CMP 5,R0 |
BUSY.NZ |
#endif |
|
;; Bottom of (and return from) Dhrystone main loop |
ADD 1,R11 |
1269,21 → 1533,22
// } |
|
#ifdef SUPERVISOR_TASK |
LOD 2(SP),R1 |
LOD 3(SP),R2 |
LOD 4(SP),R3 |
LOD 5(SP),R4 |
LOD 6(SP),R5 |
LOD 7(SP),R6 |
LOD 8(SP),R7 |
LOD 9(SP),R8 |
LOD 10(SP),R9 |
LOD 11(SP),R10 |
LOD 12(SP),R11 |
LOD (SP),R0 |
LOD 1(SP),R1 |
LOD 2(SP),R2 |
LOD 3(SP),R3 |
LOD 4(SP),R4 |
LOD 5(SP),R5 |
LOD 6(SP),R6 |
LOD 7(SP),R7 |
LOD 8(SP),R8 |
LOD 9(SP),R9 |
LOD 10(SP),R10 |
LOD 11(SP),R11 |
; |
ADD 12+RECSIZE+RECSIZE+30+30+3,SP |
; Return from subroutine |
RETN |
JMP R0 |
#else |
LDI 0,CC |
NOP |
1290,3 → 1555,4
NOP |
BUSY |
#endif |
; |
/helloworld.S
16,7 → 16,7
; bugs were fixed to get this to work. |
; |
; Creator: Dan Gisselquist, Ph.D. |
; Gisselquist Tecnology, LLC |
; Gisselquist Technology, LLC |
; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
; |
/Makefile
8,7 → 8,7
# that exist. |
# |
# Creator: Dan Gisselquist, Ph.D. |
# Gisselquist Tecnology, LLC |
# Gisselquist Technology, LLC |
# |
################################################################################ |
# |
31,10 → 31,11
################################################################################ |
# |
all: zipdhry.z testdiv.z wdt.z halttest.z |
ZASM := ../../sw/zasm/zasm |
ZDMP := ../../sw/zasm/zdump |
ZDIR := ../../sw/zasm/z2 |
ZASM := $(ZDIR)/zasm |
ZDMP := $(ZDIR)/zdump |
LIBS := ../../sw/lib |
INCS := -I../../sw/zasm |
INCS := -I$(ZDIR)/ |
|
dump: zipdhry.txt testdiv.txt |
|
57,4 → 58,4
$(ZDMP) testdiv.z > testdiv.txt |
|
clean: |
rm -rf *.z |
rm -rf *.z zipdhry.txt testdiv.txt |