URL
https://opencores.org/ocsvn/zipcpu/zipcpu/trunk
Subversion Repositories zipcpu
Compare Revisions
- This comparison shows the changes necessary to convert path
/zipcpu
- from Rev 40 to Rev 41
- ↔ Reverse comparison
Rev 40 → Rev 41
/trunk/bench/asm/lfsrleds.S
File deleted
/trunk/bench/asm/testdiv.S
0,0 → 1,142
entry: |
; Set up a test program |
MOV test_div_program(PC),uPC |
MOV top_of_stack(PC),uSP |
; Run it in user space |
RTU |
; Check for how the result came back: R0 = 0 means success |
MOV uR11,R11 |
TST -1,R11 |
HALT.Z |
BUSY |
|
test_div_program: |
SUB 1,SP |
; |
LDI 1,R11 |
LDI 5,R0 |
LDI 1,R1 |
LDI 5,R2 |
LDI 0,R3 |
MOV __HERE__+3(PC),R4 |
STO R4,1(SP) |
BRA test_divs |
|
; |
LDI 2,R11 |
LDI 5,R0 |
LDI 2,R1 |
LDI 2,R2 |
LDI 1,R3 |
MOV __HERE__+3(PC),R4 |
STO R4,1(SP) |
BRA test_divs |
|
; |
LDI 3,R11 |
LDI 0xb53d0,R0 |
LDI 0x2d,R1 |
LDI 16496,R2 |
LDI 32,R3 |
MOV __HERE__+3(PC),R4 |
STO R4,1(SP) |
BRA test_divs |
|
; |
LDI 4,R11 |
LDI 2031890191,R0 |
LDI 120193795,R1 |
LDI 16,R2 |
LDI 108789471,R3 |
MOV __HERE__+3(PC),R4 |
STO R4,1(SP) |
BRA test_divs |
|
; |
LDI 5,R11 |
LDI 203553,R0 |
LDI 142580994,R1 |
LDI 0,R2 |
LDI 203553,R3 |
MOV __HERE__+3(PC),R4 |
STO R4,1(SP) |
BRA test_divs |
|
; |
LDI 6,R11 |
LDI 142580994,R0 |
LDI 203553,R1 |
LDI 700,R2 |
LDI 93894,R3 |
MOV __HERE__+3(PC),R4 |
STO R4,1(SP) |
BRA test_divs |
|
; |
LDI 7,R11 |
LDI 142580994,R0 |
LDI 2499,R1 |
LDI 57055,R2 |
LDI 549,R3 |
MOV __HERE__+3(PC),R4 |
STO R4,1(SP) |
BRA test_divs |
|
; |
LDI 8,R11 |
LDI -142580994,R0 |
LDI 2499,R1 |
LDI -57055,R2 |
LDI -549,R3 |
MOV __HERE__+3(PC),R4 |
STO R4,1(SP) |
BRA test_divs |
|
; |
LDI 9,R11 |
LDI 142580994,R0 |
LDI -2499,R1 |
LDI -57055,R2 |
LDI 549,R3 |
MOV __HERE__+3(PC),R4 |
STO R4,1(SP) |
BRA test_divs |
|
; |
LDI 10,R11 |
LDI -142580994,R0 |
LDI -2499,R1 |
LDI 57055,R2 |
LDI -549,R3 |
MOV __HERE__+3(PC),R4 |
STO R4,1(SP) |
BRA test_divs |
|
; |
CLR R11 |
TRAP 0 |
|
test_divs: |
; R0 = Numerator |
; R1 = Denominator |
; R2 = Integer result |
; R3 = Remainder |
; 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 |
BNZ test_failure |
CMP R1,R5 |
BNZ test_failure |
ADD 1,SP |
RETN |
|
test_failure: |
TRAP 0 |
NOOP |
BUSY |
|
/trunk/bench/asm/zipdhry.S
0,0 → 1,1164
// Under Verilator: |
// DMIPS: 25.57 100 MHz 0.26 |
// For comparison: |
// uBlaze: 255 177 MHz 1.44 |
// LEON3 1.4 |
// NiOS II: 218 185 MHz 1.16 |
// OpenRisk 250 250 MHz 1.00 |
// LM32 1.14 |
// ZPU 2.6 50 MHz 0.05 |
// |
|
// #define NO_LOOP_UNROLLING |
#define SKIP_SHORT_CIRCUITS |
sys.ctr.mtask equ 0xc0000008 |
// int main(int argc, char **argv) { |
// dhrystone(); |
// } |
entry: |
MOV top_of_stack(PC),uSP |
MOV entry(PC),uR12 |
; Store our tick counter in R1 |
LDI sys.ctr.mtask,R1 |
; And start with our counter cleared at zero |
CLR R0 |
STO R0,(R1) |
#ifdef SUPERVISOR_TASK |
MOV __HERE__+3(PC),R0 |
STO R0,1(SP) |
BRA dhrystone |
#else |
MOV dhrystone(PC),uPC |
RTU |
#endif |
; Read the tick counter back out |
LOD (R1),R0 |
HALT ; Stop the CPU--We're done!!!!!!! |
|
// typedef enum { Ident_1, Ident_2, Ident_3, Ident_4, Ident_5 } test_enum; |
// typedef enum { false, true } bool; |
|
// typedef int Arr_1_Dim[50]; |
// typedef int Arr_2_Dim[50][50]; |
#define RECSIZE 35 |
#define NUMBER_OF_RUNS (512) |
ptr_comp equ 0 |
discr equ 1 |
variant.var_1.enum_comp equ 2 |
variant.var_1.int_comp equ 3 |
variant.var_1.str_comp equ 4 |
|
gbl_arr_1: |
fill 50,0 |
gbl_arr_2: |
fill 2500,0 |
gbl_ch: |
word 0 |
gbl_ch_2: |
word 0 |
gbl_bool: |
word 0 |
gbl_int: |
word 0 |
gbl_ptr: |
word 0 |
// Arr_1_Dim gbl_arr_1; |
// Arr_2_Dim gbl_arr_2; |
// char gbl_ch, gbl_ch_2; |
// bool gbl_bool; |
// int gbl_int; |
// RECP gbl_ptr; |
|
//char *lcl_strcpy(char *d, char *s) { |
// char *cpd = d, ch; |
// |
// do{ |
// *cpd++ = ch = *s++; |
// } while(ch); |
// |
//} |
// |
lcl_strcpy: |
; R0 = d |
; R1 = s |
; R3 = ch |
#ifdef NO_LOOP_UNROLLING |
copy_next_char: |
LOD (R1),R2 |
STO R2,(R0) |
ADD 1,R0 |
ADD 1,R1 |
CMP 0,R2 |
BNZ copy_next_char |
#else |
copy_next_char: |
LOD (R1),R2 |
CMP 0,R2 |
STO R2,(R0) |
BZ lcl_strcpy_end_of_loop |
LOD 1(R1),R2 |
CMP 0,R2 |
STO R2,1(R0) |
BZ lcl_strcpy_end_of_loop |
LOD 2(R1),R2 |
CMP 0,R2 |
STO R2,2(R0) |
BZ lcl_strcpy_end_of_loop |
LOD 3(R1),R2 |
CMP 0,R2 |
STO R2,3(R0) |
BZ lcl_strcpy_end_of_loop |
ADD 4,R0 |
ADD 4,R1 |
CMP 0,R2 |
BNZ copy_next_char |
lcl_strcpy_end_of_loop: |
#endif |
RETN |
|
//int lcl_strcmp(char *s1, char *s2) { |
// char a, b; |
// do { |
// a = *s1++; b = *s2++; |
// } while((a)&&(a==b)); |
// |
// return a-b; |
//} |
|
lcl_strcmp: |
SUB 1,SP |
STO R3,1(SP) |
|
strcmp_top_of_loop: |
#ifdef NO_LOOP_UNROLLING |
LOD (R0),R2 |
LOD (R1),R3 ; Alternate approach: |
; CMP R2,R3 ; CMP 0,R2 |
; BNZ strcmp_end_loop ; BZ strcmp_end_loop |
; CMP 0,R2 ; CMP R2,R3 |
; BZ strcmp_end_loop ; BZ strcmp_top_of_loop |
; CMP 0,R3 ; |
; BZ strcmp_end_loop ; |
; ADD 1,R0 |
; ADD 1,R1 |
; BRA strcmp_top_of_loop |
LOD (R0),R2 |
LOD (R1),R3 |
CMP 0,R2 |
BZ strcmp_end_loop |
CMP R2,R3 |
BZ strcmp_top_of_loop |
#else |
LOD (R0),R2 |
LOD (R1),R3 |
CMP 0,R2 |
BZ strcmp_end_loop |
CMP R2,R3 |
BNZ strcmp_end_loop |
LOD 1(R0),R2 |
LOD 1(R1),R3 |
CMP 0,R2 |
BZ strcmp_end_loop |
CMP R2,R3 |
BNZ strcmp_end_loop |
LOD 2(R0),R2 |
LOD 2(R1),R3 |
CMP 0,R2 |
BZ strcmp_end_loop |
CMP R2,R3 |
BNZ strcmp_end_loop |
LOD 3(R0),R2 |
LOD 3(R1),R3 |
CMP 0,R2 |
BZ strcmp_end_loop |
CMP R2,R3 |
BNZ strcmp_end_loop |
ADD 4,R0 |
ADD 4,R1 |
BRA strcmp_top_of_loop |
#endif |
|
strcmp_end_loop: |
SUB R3,R2 |
MOV R2,R0 |
|
LOD 1(SP),R3 |
ADD 1,SP |
RETN |
|
|
//test_enum func_1(char ch_1, char ch_2) { |
// char lcl_ch_1, lcl_ch_2; |
// |
// lcl_ch_1 = ch_1; |
// lcl_ch_2 = lcl_ch_1; |
// if (lcl_ch_2 != ch_2) |
// return 0; |
// else { |
// gbl_ch = lcl_ch_1; |
// return 1; |
// } |
|
#ifdef NO_INLINE |
func_1: |
; On input, |
; R0 = ch_1 |
; R1 = ch_2 |
; R2 = available |
; On output, R0 is our return value |
|
MOV R0,R2 |
CMP R2,R1 |
CLR.NZ R0 |
STO.Z R2,gbl_ch(R12) |
LDILO.Z 1,R0 |
RETN |
#endif |
|
//bool func_2(char *str_1, char *str_2) { |
// int lcl_int; |
// char lcl_ch; |
// |
// lcl_int = 2; |
// while(lcl_int <= 2) { |
// if (func_1(str_1[lcl_int], str_2[lcl_int+1])==0) { |
// lcl_ch = 'A'; |
// lcl_int ++; |
// } |
// } |
// |
// if ((lcl_ch >= 'W')&&(lcl_ch < 'Z')) |
// lcl_int = 7; |
// if (lcl_ch == 'R') |
// return true; |
// else { |
// if (lcl_strcmp(str_1, str_2)>0) { |
// lcl_int += 7; |
// gbl_int = lcl_int; |
// } else |
// return false; |
// } |
//} |
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) |
|
MOV R0,R3 ; R3 = str_1 |
MOV R1,R4 ; R4 = str_2 |
LDI 2,R5 ; R5 = lcl_int |
LDI 'A',R7 ; R7 = lcl_ch |
func_2_while_loop: |
CMP 2,R5 |
BGT func_2_end_while_loop |
func_2_top_while_loop: |
MOV R3,R6 |
ADD R5,R6 |
|
#ifdef NO_INLINE |
LOD (R6),R0 |
MOV R4,R6 |
ADD R5,R6 |
LOD 1(R6),R1 |
|
MOV __HERE__+3(PC),R2 |
STO R2,1(SP) |
BRA func_1 |
|
CMP 0,R0 |
ADD.Z 1,R5 |
#else |
LOD (R6),R2 |
MOV R4,R6 |
ADD R5,R6 |
LOD 1(R6),R1 |
|
CMP R2,R1 |
STO.Z R2,gbl_ch(R12) |
LDILO.Z 1,R0 |
|
ADD.NZ 1,R5 |
#endif |
|
#ifndef SKIP_SHORT_CIRCUITS |
BUSY.NZ |
#endif |
CMP 3,R5 |
#ifndef SKIP_SHORT_CIRCUITS |
BUSY.LT |
#endif |
BLT func_2_top_while_loop |
|
func_2_end_while_loop: |
|
// CMP 'W',R7 // BUT! We know lcl_ch='A' |
// BLT skip_if // So we can skip this |
// CMP 'Z',R7 // entire section |
// LDI.LT 7,R5 |
// CMP 'R',R7 |
// BNZ alt_if_case |
// LLO.Z 1,R0 |
// BRA func_2_return_and_cleanup |
// |
MOV R3,R0 |
MOV R4,R1 |
MOV __HERE__+3(PC),R2 |
STO R2,1(SP) |
BRA lcl_strcmp |
CMP 0,R0 |
BGT func_2_final_then |
#ifndef SKIP_SHORT_CIRCUITS |
BUSY |
#endif |
CLR R0 |
BRA func_2_return_and_cleanup |
func_2_final_then: |
// ADD 7,R5 ; Never read, so useless code |
LDI 1,R0 |
#ifndef SKIP_SHORT_CIRCUITS |
BUSY |
#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 |
ADD 6,SP |
RETN |
|
//bool func_3(test_enum a) { |
// test_enum lcl_enum; |
// |
// lcl_enum = a; |
// if (lcl_enum == Ident_3) |
// return true; |
// else |
// return false; |
//} |
|
#ifdef NO_INLINE |
func_3: |
; On entry, |
; R0 = a |
; R1 - available |
CMP 2,R0 |
CLR R0 ; CLR Doesn't set flags |
LDILO.Z 1,R0 |
RETN |
#endif |
|
|
// void proc_6(test_enum ev, test_enum *ep) { |
// *ep = ev; |
// if (!func_3(ev)) |
// *ep = 3; |
// switch(ev) { |
// case 0: *ep = 0; break; |
// case 1: |
// if (gbl_int > 100) |
// *ep = 0; |
// else |
// *ep = 3; |
// break; |
// case 2: |
// *ep = 1; |
// break; |
// case 3: |
// break; |
// case 4: |
// *ep = 2; |
// } |
//} |
|
proc_6: |
; On entry: |
; R0 = ev |
; R1 = ep |
; R2 - unassigned |
; 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) |
|
MOV R1,R3 |
MOV R0,R2 |
; *ep = ev |
STO R0,(R1) |
#ifndef SKIP_SHORT_CIRCUITS |
CMP 2,R0 |
BUSY.NZ |
#endif |
|
#ifdef NO_INLINE |
; !func_3(ev) |
MOV __HERE__+3(PC),R1 |
STO R1,1(SP) |
BRA func_3 |
|
TST -1,R0 |
LDI 3,R1 |
STO.Z R1,(R3) |
#else |
CMP 2,R0 |
LDI 3,R1 |
STO.Z R1,(R3) |
#endif |
|
TST -1,R0 |
LDI 3,R1 |
#ifndef SKIP_SHORT_CIRCUITS |
BUSY.Z |
#endif |
STO.Z R1,(R3) |
|
#ifndef SKIP_SHORT_CIRCUITS |
CMP 2,R2 |
BUSY.NZ |
#endif |
CMP 0,R2 |
BNZ proc_6_case_not_zero |
#ifndef SKIP_SHORT_CIRCUITS |
BUSY |
#endif |
LDI 0,R1 |
STO R1,(R3) |
BRA proc_6_end_of_case |
proc_6_case_not_zero: |
CMP 1,R2 |
BNZ proc_6_case_not_one |
#ifndef SKIP_SHORT_CIRCUITS |
BUSY |
#endif |
LDI 3,R0 |
LOD gbl_int(R12),R1 |
CMP 100,R1 |
CLR.GT R0 |
STO R0,(R3) |
BRA proc_6_end_of_case |
proc_6_case_not_one: |
CMP 2,R2 |
BNZ proc_6_case_not_two |
LDI 1,R1 // Executed, if done properly |
STO R1,(R3) |
BRA proc_6_end_of_case |
proc_6_case_not_two: |
#ifndef SKIP_SHORT_CIRCUITS |
BUSY |
#endif |
CMP 4,R2 |
BNZ proc_6_case_not_four |
LDI 2,R1 |
STO R1,(R3) |
// BRA proc_6_end_of_case |
proc_6_case_not_four: |
proc_6_end_of_case: |
LOD 2(SP),R3 |
ADD 2,SP |
RETN |
|
// void proc_7(int a, int b, int *c) { |
// int lcl; |
// |
// lcl = a + 2; |
// *c = b + a; |
//} |
|
#ifdef NO_INLINE |
proc_7: |
ADD 2+R0,R1 |
STO R1,(R2) |
|
RETN |
#endif |
|
// int a[50]; |
// int b[50][50]; |
// |
// void proc_8(Arr_1_Dim a, Arr_2_Dim b, int c, int d) { |
// int idx, loc; |
// |
// loc = c+5; |
// a[loc] = d; |
// a[loc+1] = a[loc]; |
// a[loc+30] = loc; |
// for(idx=loc; idx<= loc+1; idx++) |
// b[loc][idx] = loc; |
// b[loc][loc-1] += 1; |
// b[loc+20][loc] = a[loc]; |
// gbl_int = 5; |
//} |
proc_8: |
; R0 = a |
; R1 = b |
; R2 = c |
; R3 = d |
; R4 - unassigned |
; Makes no function/procedure calls, so these can keep |
; R2 = loc = c+5, replaces c |
; R4 = idx |
SUB 2,SP |
STO R5,1(SP) |
STO R6,2(SP) |
|
ADD 5,R2 ; loc = c+5 |
MOV R0,R5 |
ADD R2,R5 |
STO R3,(R5) |
STO R3,1(R5) |
STO R2,30(R5) |
MOV R2,R5 |
MPYU 50,R5 ; R5 = 50 * R2 = 50 * loc |
ADD R1,R5 ; R5 = &b[loc][0] |
MOV R5,R6 ; R6 = &b[loc][0] |
ADD R2,R5 ; R5 = &b[loc][loc] |
MOV R2,R4 ; R4 = loc = index |
proc_8_top_of_loop: |
CMP 1(R2),R4 |
BGT proc_8_end_of_loop |
proc_8_loop_after_condition: |
STO R2,(R5) |
ADD 1,R5 |
ADD 1,R4 |
CMP 2(R2),R4 |
BLT proc_8_loop_after_condition |
proc_8_end_of_loop: |
|
; b[loc][loc-1] += 1 |
ADD R2,R6 ; R6 = &b[loc][loc] |
LOD -1(R6),R5 |
ADD 1,R5 |
STO R5,-1(R6) |
; b[loc+20][loc] = a[loc] |
MOV R0,R4 |
ADD R2,R4 |
LOD (R4),R3 |
STO R3,20*50(R6) |
LDI 5,R3 |
STO R3,gbl_int(R12) |
|
LOD 1(SP),R5 |
LOD 2(SP),R6 |
ADD 2,SP |
RETN |
|
// void proc_5(void) { |
// gbl_ch = 'A'; |
// gbl_bool = false; |
//} |
#ifdef NO_INLINE |
proc_5: |
LDI 'A',R0 |
STO R0,gbl_ch(R12) |
CLR R0 |
STO R0,gbl_bool(R12) |
; |
RETN |
#endif |
|
// void proc_4(void) { |
// bool lcl_bool; |
// lcl_bool = (gbl_ch == 'A'); |
// gbl_ch_2 = 'B'; |
// } |
#ifdef NO_INLINE |
proc_4: |
// |
; LDI GBL,R12 // Already in R12 |
; Setting lcl_bool is irrelevant, so the optimizer should remove it. |
; R0 doesn't need to be saved, since it's already trashed by the |
; subroutine call. |
; |
; LOD gbl_ch(R12),R0 |
; CLR R1 |
; CMP 'A',R0 |
; ADD.Z 1,R1 |
; |
LDI 'B',R0 |
STO R0,gbl_ch_2(R12) |
; |
RETN |
#endif |
|
// void proc_3(RECP *a) { |
// if (gbl_ptr != NULL) |
// *a = gbl_ptr->ptr_comp; |
// proc_7(10,gbl_int, &gbl_ptr->variant.var_1.int_comp); // ?? |
//} |
proc_3: |
SUB 3,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 |
#ifndef SKIP_SHORT_CIRCUITS |
BUSY.Z |
#endif |
LOD.NZ ptr_comp(R2),R3 |
STO.NZ R3,(R0) |
#ifdef NO_INLINE |
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) |
BRA proc_7 |
#else |
LOD gbl_int(R12),R1 |
ADD 12,R1 |
STO R1,variant.var_1.int_comp(R2) |
#endif |
; |
LOD 2(SP),R3 |
LOD 3(SP),R2 |
ADD 3,SP |
RETN |
|
|
// void proc_2(int *a) { |
// int lcl_int; |
// test_enum lcl_enum; |
// |
// lcl_int = *a + 10; |
// do { |
// if (gbl_ch == 'A') { |
// lcl_int -= 1; |
// *a = lcl_int - gbl_int; |
// lcl_enum = Ident_1; |
// } |
// } while(lcl_enum != Ident_1); |
//} |
proc_2: |
SUB 5,SP |
STO R6,1(SP) |
STO R5,2(SP) |
STO R4,3(SP) |
STO R3,4(SP) |
STO R2,5(SP) |
// R1 doesn't need to be stored, it was used in the subroutine |
// call calculation |
|
LOD (R0),R1 |
MOV 10(R1),R2 ; R2 = lcl_int |
LOD gbl_ch(R12),R4 ; R4 = gbl_ch |
#ifdef NO_CHEATING |
proc_2_loop: |
CMP 'A',R4 |
SUB.Z 1,R2 |
LOD.Z gbl_int(R12),R5 ; R5 = gbl_int |
MOV.Z R2,R6 ; R6 = lcl_int |
SUB.Z R5,R6 ; lcl_int - gbl_int |
STO.Z R6,(R0) ; *a = R6 |
CLR.Z R3 ; lcl_enum = 0 |
// #ifndef SKIP_SHORT_CIRCUITS |
// BUSY.NZ |
// #endif |
|
TST -1,R3 |
// #ifndef SKIP_SHORT_CIRCUITS |
// BUSY.NZ |
// #endif |
BNZ proc_2_loop |
#else |
LOD gbl_int(R12),R5 |
SUB 1(R5),R2 |
STO R2,(R0) |
#endif |
; |
LOD 1(SP),R6 |
LOD 2(SP),R5 |
LOD 3(SP),R4 |
LOD 4(SP),R3 |
LOD 5(SP),R2 |
ADD 5,SP |
RETN |
|
//void proc_1 (RECP a) { |
// RECP nxt = a->ptr_comp; |
// |
// // structassign(a->ptr_comp, gbl_ptr); |
// *(a->ptr_comp) = *(gbl_ptr); |
// |
// a->variant.var_1.int_comp = 5; |
// nxt->variant.var_1.int_comp = a->variant.var_1.int_comp; |
// proc_3(&nxt->ptr_comp); |
// |
// if (nxt->discr == 0) { |
// nxt->variant.var_1.int_comp = 6; |
// proc_6(a->variant.var_1.enum_comp, &nxt->variant.var_1.enum_comp); |
// nxt->ptr_comp = gbl_ptr->ptr_comp; |
// proc_7(nxt->variant.var_1.int_comp, 10, &nxt->variant.var_1.int_comp); |
// } else |
// // structassign(a, a->ptr_comp); |
// *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) |
|
; R9 = a |
; R4 = nxt |
; R12 = GBL |
; R13 = SP |
MOV R0,R9 |
LOD ptr_comp(R9),R4 |
#ifndef SKIP_SHORT_CIRCUITS |
TST -1,R4 |
BUSY.Z |
#endif |
LDI 35,R5 |
MOV R9,R6 |
LOD gbl_ptr(R12),R7 |
proc_1_assign_loop_1: |
LOD (R6),R8 |
ADD 1,R6 |
STO R8,(R7) |
ADD 1,R7 |
SUB 1,R5 |
BNZ proc_1_assign_loop_1; |
|
#ifndef SKIP_SHORT_CIRCUITS |
LOD gbl_ptr(R12),R2 |
TST -1,R2 |
BUSY.Z |
#endif |
|
LDI 5,R5 |
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) |
BRA proc_3 ; Uses R0 and R1 |
|
LOD discr(R4),R5 |
CMP 0,R5 |
BNZ proc_1_last_struct_assign |
; This is the juncture that is "supposed" to be taken |
LDI 6,R5 |
|
STO R5,variant.var_1.int_comp(R4) |
LOD variant.var_1.enum_comp(R9), R0 |
#ifndef SKIP_SHORT_CIRCUITS |
CMP 2,R0 |
BUSY.NZ |
#endif |
MOV variant.var_1.enum_comp+R4, R1 |
MOV __HERE__+3(PC),R2 |
STO R2,1(SP) |
BRA proc_6 |
; |
LOD gbl_ptr(R12),R5 |
LOD ptr_comp(R5),R5 |
STO R5,ptr_comp(R4) |
; |
#ifdef NO_INLINE |
LOD variant.var_1.int_comp(R4),R0 |
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 |
ADD 12,R0 |
STO R0,variant.var_1.int_comp(R4) |
BRA proc_1_return_closeout |
#endif |
; |
proc_1_last_struct_assign: |
#ifndef SKIP_SHORT_CIRCUITS |
BUSY |
#endif |
LDI 35,R4 |
MOV R2,R5 |
LOD gbl_ptr(R12),R6 |
proc_1_assign_loop_2: |
LOD (R6),R8 |
STO R8,(R7) |
ADD 1,R6 |
ADD 1,R7 |
SUB 1,R5 |
BNZ proc_1_assign_loop_2 |
// |
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 |
|
// void dhrystone(void) { |
// int lcl_int_1, lcl_int_2, lcl_int_3, index, number_of_runs = 500; |
// test_enum lcl_enum; |
// char lcl_str_1[30], lcl_str_2[30], ch_index; |
// REC_T a, b, *nxt = &a; |
// |
// gbl_ptr = &b; |
// gbl_ptr->ptr_comp = nxt; |
// gbl_ptr->variant.var_1.enum_comp = 2; |
// gbl_ptr->variant.var_1.int_comp = 40; |
// lcl_strcpy(gbl_ptr->variant.var_1.str_comp, "DHRYSTONE PROGRAM, SOME STRING"); |
// lcl_strcpy(lcl_str_1, "DHRYSTONE PROGRAM, 1\'ST STRING"); |
// |
// gbl_arr_2[8][7] = 10; |
// |
// for(index=0; index < number_of_runs; index++) { |
// proc_5(); |
// proc_4(); |
// lcl_int_1 = 2; |
// lcl_int_2 = 3; |
// lcl_strcpy(lcl_str_2, "DHRYSTONE PROGRAM, 2\'ND STRING"); |
// lcl_enum = Ident_2; |
// gbl_bool = !func_2(lcl_str_1, lcl_str_2); |
// while(lcl_int_1 < lcl_int_2) { |
// lcl_int_3 = 5 * lcl_int_1 - lcl_int_2; |
// proc_7(lcl_int_1, lcl_int_2, &lcl_int_3); |
// lcl_int_1 += 1; |
// } |
// |
// proc_8(gbl_arr_1, gbl_arr_2, lcl_int_1, lcl_int_3); |
// proc_1(gbl_ptr); |
// |
// for(ch_index='A'; ch_index <= gbl_ch_2; ch_index++) { |
// if (lcl_enum == func_1(ch_index, 'C')) { |
// // Then not executed?? |
// proc_6(0, &lcl_enum); |
// lcl_strcpy(lcl_str_2, "DHRYSTONE PROGRAM, 3\'RD STRING"); |
// lcl_int_2 = index; |
// gbl_int = index; |
// } |
// } |
// |
// lcl_int_2 = lcl_int_2 * lcl_int_1; |
// lcl_int_1 = lcl_int_2 / lcl_int_3; |
// lcl_int_2 = 7 * ( lcl_int_2 - lcl_int_3) - lcl_int_1; |
// proc_2(&lcl_int_1); |
// } |
//} |
|
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 |
|
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) |
lcl_int_1 equ 12 ; plus SP |
#else |
lcl_int_1 equ 2 ; plus SP |
SUB 2+RECSIZE+RECSIZE+30+30+3,SP |
#endif |
// 12 is the global variable pointer |
// 13 is our stack |
// 14 is our condition code register |
// 15 is the program counter |
; |
lcl_int_3 equ lcl_int_1+1 ; plus SP |
lcl_enum equ lcl_int_3+1 ; plus SP |
lcl_str_1 equ lcl_enum+1 ; plus SP |
lcl_str_2 equ lcl_str_1+30 ; plus SP |
rec_a equ lcl_str_2+30 ; plus SP |
rec_b equ rec_a+RECSIZE ; plus SP |
|
// int lcl_int_1, lcl_int_2, lcl_int_3, index, number_of_runs = 500; |
// test_enum lcl_enum; |
// char lcl_str_1[30], lcl_str_2[30], ch_index; |
// REC_T a, b, *nxt = &a; |
// |
// gbl_ptr = &b; |
MOV rec_b(SP),R0 ; R0 = &b |
STO R0,gbl_ptr(PC) |
// gbl_ptr->ptr_comp = nxt; |
MOV rec_a(SP),R1 ; R1 = &a = nxt |
STO R1,ptr_comp(R0) ; gbp_ptr->ptr.comp=b->ptr.comp=R1=nxt |
// gbl_ptr->variant.var_1.enum_comp = 2; |
LDI 2,R2 |
STO R2,variant.var_1.enum_comp(R0) |
// gbl_ptr->variant.var_1.int_comp = 40; |
LDI 40,R2 |
STO R2,variant.var_1.int_comp(R0) |
// 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) |
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) |
BRA lcl_strcpy |
|
// gbl_arr_2[8][7] = 10; |
LDI 10,R0 |
STO R0,8*50+7+gbl_arr_2(R12) |
// |
// for(index=0; index < number_of_runs; index++) { |
; Let R11 be our index |
CLR R11 |
dhrystone_main_loop: |
;; Start of Dhrystone main loop |
; proc_5(); |
#ifdef NO_INLINE |
MOV __HERE__+3(PC),R0 |
STO R0,1(SP) |
BRA proc_5 |
#else |
LDI 'A',R0 |
STO R0,gbl_ch(R12) |
CLR R0 |
STO R0,gbl_bool(R12) |
#endif |
; proc_4(); |
#ifdef NO_INLINE |
MOV __HERE__+3(PC),R0 |
STO R0,1(SP) |
BRA proc_4 |
#else |
LDI 'B',R0 |
STO R0,gbl_ch_2(R12) |
#endif |
// lcl_int_1 = 2; |
LDI 2,R5 |
STO R5,lcl_int_1(SP) |
// lcl_int_2 = 3; |
LDI 3,R6 |
// 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) |
BRA lcl_strcpy |
// lcl_enum = Ident_2; |
LDI 2,R0 |
STO R0,lcl_enum(SP) |
// 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) |
BRA func_2 |
CLR R1 |
TST -1,R0 |
LDILO.Z 1,R1 |
STO R1,gbl_bool(PC) |
|
// while(lcl_int_1 < lcl_int_2) { |
; R5 = lcl_int_1 = 2 on entry |
; R6 = lcl_int_2 = 3 on entry, so no entry test is required |
LOD lcl_int_1(SP),R5 |
// The 'while' comparison |
CMP R6,R5 |
BGE dhrystone_end_while_loop |
dhrystone_while_loop: |
// lcl_int_3 = 5 * lcl_int_1 - lcl_int_2; |
MOV R5,R7 |
MPYS 5,R7 |
SUB R6,R7 |
STO R7,lcl_int_3(SP) |
// 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) |
BRA proc_7 |
#else |
MOV R6,R1 |
ADD 2+R5,R1 |
STO R1,lcl_int_3(SP) |
#endif |
// lcl_int_1 += 1; |
LOD lcl_int_1(SP),R5 |
ADD 1,R5 |
STO R5,lcl_int_1(SP) |
; |
; BRA dhrystone_while_loop ; We'll unroll the loop, and put an |
CMP R6,R5 ; additional comparison at the bottom |
BLT dhrystone_while_loop |
dhrystone_end_while_loop: |
// } |
// |
// 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) |
BRA proc_8 |
// proc_1(gbl_ptr); |
LOD gbl_ptr(PC),R0 |
MOV __HERE__+3(PC),R2 |
STO R2,1(SP) |
BRA proc_1 |
// |
// for(ch_index='A'; ch_index <= gbl_ch_2; ch_index++) { |
LDI 'A',R7 |
LOD gbl_ch_2(SP),R8 |
CMP R7,R8 |
BLT dhrystone_end_of_for_loop |
dhrystone_top_of_for_loop: |
// if (lcl_enum == func_1(ch_index, 'C')) { |
#ifdef NO_INLINE |
MOV R7,R0 |
LDI 'C',R1 |
MOV __HERE__+3(PC),R2 |
STO R2,1(SP) |
BRA func_1 |
#else |
CMP 'C',R7 |
CLR.NZ R0 |
STO.Z R7,gbl_ch(R12) |
LDILO.Z 1,R0 |
#endif |
|
; Result is now in R0 |
LOD lcl_enum(SP),R1 |
CMP R0,R1 |
BNZ dhrystone_skip_then_clause |
// // Then not executed?? |
// proc_6(0, &lcl_enum); |
|
#ifndef SKIP_SHORT_CIRCUITS |
BUSY |
#endif |
|
CLR R0 |
MOV lcl_enum(SP),R1 |
MOV __HERE__+3(PC),R2 |
STO R2,1(SP) |
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) |
BRA lcl_strcpy |
// lcl_int_2 = index; |
MOV R11,R6 |
// gbl_int = index; |
STO R11,gbl_int(PC) |
// } |
dhrystone_skip_then_clause: |
ADD 1,R7 |
LOD gbl_ch_2(SP),R8 |
CMP R8,R7 |
BGE dhrystone_top_of_for_loop |
dhrystone_end_of_for_loop: |
// } |
// |
// 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; |
#ifndef SKIP_DIVIDE |
MOV R6,R0 |
LOD lcl_int_3(SP),R1 |
MOV __HERE__+3(PC),R2 |
STO R2,1(SP) |
BRA divs |
#else |
LDI 9,R0 |
#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 |
SUB R2,R6 |
MPYS 7,R6 |
SUB R0,R6 |
// proc_2(&lcl_int_1); |
MOV lcl_int_1(SP),R0 |
MOV __HERE__+3(PC),R1 |
STO R1,1(SP) |
BRA proc_2 |
|
;; Bottom of (and return from) Dhrystone main loop |
ADD 1,R11 |
CMP NUMBER_OF_RUNS,R11 |
BLT dhrystone_main_loop |
// } |
|
#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 |
; |
ADD 12+RECSIZE+RECSIZE+30+30+3,SP |
; Return from subroutine |
RETN |
#else |
LDI 0,CC |
NOP |
NOP |
BUSY |
#endif |
/trunk/bench/asm/Makefile
0,0 → 1,26
all: zipdhry.z testdiv.z wdt.z |
ZASM := ../../sw/zasm/zasm |
ZDMP := ../../sw/zasm/zdump |
LIBS := ../../sw/lib |
INCS := -I../../sw/zasm |
|
dump: zipdhry.txt testdiv.txt |
|
zipdhry.z: zipdhry.S $(LIBS)/divs.S $(LIBS)/divu.S stack.S |
$(ZASM) $(INCS) $^ -o $@ |
zipdhry.txt: zipdhry.z |
$(ZDMP) zipdhry.z > zipdhry.txt |
|
wdt.z: wdt.S |
$(ZASM) $(INCS) $^ -o $@ |
|
.PHONY: testdiv |
testdiv: testdiv.z |
testdiv.z: testdiv.S $(LIBS)/divs.S $(LIBS)/divu.S stack.S |
$(ZASM) $(INCS) $^ -o $@ |
|
testdiv.txt: testdiv.z |
$(ZDMP) testdiv.z > testdiv.txt |
|
clean: |
rm -rf *.z |