URL
https://opencores.org/ocsvn/zipcpu/zipcpu/trunk
Subversion Repositories zipcpu
[/] [zipcpu/] [trunk/] [bench/] [asm/] [zipdhry.S] - Rev 57
Go to most recent revision | Compare with Previous | Blame | View Log
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Filename: zipdhry.S;; Project: Zip CPU -- a small, lightweight, RISC CPU soft core;; Purpose: Zip assembly file for running the Dhrystone benchmark in the; Zip CPU.;; Creator: Dan Gisselquist, Ph.D.; Gisselquist Tecnology, LLC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Copyright (C) 2015, Gisselquist Technology, LLC;; This program is free software (firmware): you can redistribute it and/or; modify it under the terms of the GNU General Public License as published; by the Free Software Foundation, either version 3 of the License, or (at; your option) any later version.;; This program is distributed in the hope that it will be useful, but WITHOUT; ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License; for more details.;; License: GPL, v3, as defined and found on www.gnu.org,; http://www.gnu.org/licenses/gpl.html;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;// Under Verilator:// DMIPS: 28.6 100 MHz (sim) 0.29////// with no loop unrolling nor function inlining// DMIPS: 24.3 100 MHz (sim) 0.24// with packed strings// DMIPS: 35.6 100 MHz (sim) 0.36//// 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//// Some #def's to control compilation.//// 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.//// #define SKIP_SHORT_CIRCUITS//// NO_INLINE controls whether or not we inline certain functions. If you// define this, nothing will be inlined.// #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.// #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_PSTRSsys.ctr.mtask equ 0xc0000008// int main(int argc, char **argv) {// dhrystone();// }entry:MOV top_of_stack(PC),uSPMOV entry(PC),uR12; Store our tick counter in R1LDI sys.ctr.mtask,R1; And start with our counter cleared at zeroCLR R0STO R0,(R1)#ifdef SUPERVISOR_TASKMOV __HERE__+3(PC),R0STO R0,1(SP)BRA dhrystone#elseMOV dhrystone(PC),uPCRTU#endif; Read the tick counter back outLOD (R1),R0HALT ; 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];#ifdef USE_PSTRS#define RECSIZE 12#else#define RECSIZE 35#endif#define NUMBER_OF_RUNS (512)ptr_comp equ 0discr equ 1variant.var_1.enum_comp equ 2variant.var_1.int_comp equ 3variant.var_1.str_comp equ 4gbl_arr_1:fill 50,0gbl_arr_2:fill 2500,0gbl_ch:word 0gbl_ch_2:word 0gbl_bool:word 0gbl_int:word 0gbl_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 = chcopy_next_char:#ifdef NO_LOOP_UNROLLINGLOD (R1),R2STO R2,(R0)#ifdef USE_PSTRSTST 255,R2#elseCMP 0,R2#endifRETN.ZADD 1,R0ADD 1,R1BRA copy_next_char#elseLOD (R1),R2STO R2,(R0)#ifdef USE_PSTRSTST 255,R2#elseCMP 0,R2#endif; BZ lcl_strcpy_end_of_loopRETN.ZLOD 1(R1),R2STO R2,1(R0)#ifdef USE_PSTRSTST 255,R2#elseCMP 0,R2#endif; BZ lcl_strcpy_end_of_loopRETN.ZLOD 2(R1),R2STO R2,2(R0)#ifdef USE_PSTRSTST 255,R2#elseCMP 0,R2#endif; BZ lcl_strcpy_end_of_loopRETN.ZLOD 3(R1),R2STO R2,3(R0); BZ lcl_strcpy_end_of_loop#ifdef USE_PSTRSTST 255,R2#elseCMP 0,R2#endifRETN.ZADD 4,R0ADD 4,R1BRA copy_next_char#endif//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,SPSTO 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_loopLOD (R0),R2LOD (R1),R3#ifdef USE_PSTRSTST 255,R2#elseCMP 0,R2#endifBZ strcmp_end_loopADD 1,R0ADD 1,R1CMP R2,R3BZ strcmp_top_of_loop#elseLOD (R0),R2LOD (R1),R3#ifdef USE_PSTRSTST 255,R2#elseCMP 0,R2#endifBZ strcmp_end_loopCMP R2,R3BNZ strcmp_end_loopLOD 1(R0),R2LOD 1(R1),R3#ifdef USE_PSTRSTST 255,R2#elseCMP 0,R2#endifBZ strcmp_end_loopCMP R2,R3BNZ strcmp_end_loopLOD 2(R0),R2LOD 2(R1),R3#ifdef USE_PSTRSTST 255,R2#elseCMP 0,R2#endifBZ strcmp_end_loopCMP R2,R3BNZ strcmp_end_loopLOD 3(R0),R2LOD 3(R1),R3#ifdef USE_PSTRSTST 255,R2#elseCMP 0,R2#endifBZ strcmp_end_loopCMP R2,R3BNZ strcmp_end_loopADD 4,R0ADD 4,R1BRA strcmp_top_of_loop#endifstrcmp_end_loop:SUB R3,R2MOV R2,R0LOD 1(SP),R3ADD 1,SPRETN//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_INLINEfunc_1:; On input,; R0 = ch_1; R1 = ch_2; R2 = available; On output, R0 is our return valueMOV R0,R2CMP R2,R1CLR.NZ R0STO.Z R2,gbl_ch(R12)LDILO.Z 1,R0RETN#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,SPSTO R3,2(SP)STO R4,3(SP)STO R5,4(SP)STO R6,5(SP)STO R7,6(SP)MOV R0,R3 ; R3 = str_1MOV R1,R4 ; R4 = str_2LDI 2,R5 ; R5 = lcl_intLDI 'A',R7 ; R7 = lcl_chfunc_2_while_loop:CMP 2,R5BGT func_2_end_while_loopfunc_2_top_while_loop:MOV R3,R6ADD R5,R6#ifdef NO_INLINELOD (R6),R0MOV R4,R6ADD R5,R6LOD 1(R6),R1MOV __HERE__+3(PC),R2STO R2,1(SP)BRA func_1CMP 0,R0ADD.Z 1,R5#ifndef SKIP_SHORT_CIRCUITSBUSY.NZ#endif#elseLOD (R6),R2MOV R4,R6ADD R5,R6LOD 1(R6),R1CMP R2,R1STO.Z R2,gbl_ch(R12)LDILO.Z 1,R0ADD.NZ 1,R5#ifndef SKIP_SHORT_CIRCUITSBUSY.Z#endif#endifCMP 3,R5#ifndef SKIP_SHORT_CIRCUITSBUSY.LT#endifBLT func_2_top_while_loopfunc_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,R0MOV R4,R1MOV __HERE__+3(PC),R2STO R2,1(SP)BRA lcl_strcmpCMP 0,R0BGT func_2_final_thenCLR R0BRA func_2_return_and_cleanupfunc_2_final_then:// ADD 7,R5 ; Never read, so useless codeLDI 1,R0#ifndef SKIP_SHORT_CIRCUITSBUSY#endiffunc_2_return_and_cleanup:LOD 2(SP),R3LOD 3(SP),R4LOD 4(SP),R5LOD 5(SP),R6LOD 6(SP),R7ADD 6,SPRETN//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_INLINEfunc_3:; On entry,; R0 = a; R1 - availableCMP 2,R0CLR R0 ; CLR Doesn't set flagsLDILO.Z 1,R0RETN#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 = epSUB 2,SPSTO R3,2(SP)MOV R1,R3MOV R0,R2; *ep = evSTO R0,(R1)#ifndef SKIP_SHORT_CIRCUITSCMP 2,R0BUSY.NZ#endif#ifdef NO_INLINE; !func_3(ev)MOV __HERE__+3(PC),R1STO R1,1(SP)BRA func_3TST -1,R0LDI 3,R1STO.Z R1,(R3)#elseCMP 2,R0LDI 3,R1STO.Z R1,(R3)#endifTST -1,R0LDI 3,R1#ifndef SKIP_SHORT_CIRCUITSBUSY.Z#endifSTO.Z R1,(R3)#ifndef SKIP_SHORT_CIRCUITSCMP 2,R2BUSY.NZ#endifCMP 0,R2BNZ proc_6_case_not_zero#ifndef SKIP_SHORT_CIRCUITSBUSY#endifLDI 0,R1STO R1,(R3)BRA proc_6_end_of_caseproc_6_case_not_zero:CMP 1,R2BNZ proc_6_case_not_one#ifndef SKIP_SHORT_CIRCUITSBUSY#endifLDI 3,R0LOD gbl_int(R12),R1CMP 100,R1CLR.GT R0STO R0,(R3)BRA proc_6_end_of_caseproc_6_case_not_one:CMP 2,R2BNZ proc_6_case_not_twoLDI 1,R1 // Executed, if done properlySTO R1,(R3)BRA proc_6_end_of_caseproc_6_case_not_two:#ifndef SKIP_SHORT_CIRCUITSBUSY#endifCMP 4,R2BNZ proc_6_case_not_fourLDI 2,R1STO R1,(R3)// BRA proc_6_end_of_caseproc_6_case_not_four:proc_6_end_of_case:LOD 2(SP),R3ADD 2,SPRETN// void proc_7(int a, int b, int *c) {// int lcl;//// lcl = a + 2;// *c = b + a;//}#ifdef NO_INLINEproc_7:ADD 2+R0,R1STO 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 = idxSUB 2,SPSTO R5,1(SP)STO R6,2(SP)ADD 5,R2 ; loc = c+5MOV R0,R5ADD R2,R5STO R3,(R5)STO R3,1(R5)STO R2,30(R5)MOV R2,R5MPYU 50,R5 ; R5 = 50 * R2 = 50 * locADD 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 = indexproc_8_top_of_loop:CMP 1(R2),R4BGT proc_8_end_of_loopproc_8_loop_after_condition:STO R2,(R5)ADD 1,R5ADD 1,R4CMP 2(R2),R4BLT proc_8_loop_after_conditionproc_8_end_of_loop:; b[loc][loc-1] += 1ADD R2,R6 ; R6 = &b[loc][loc]LOD -1(R6),R5ADD 1,R5STO R5,-1(R6); b[loc+20][loc] = a[loc]MOV R0,R4ADD R2,R4LOD (R4),R3STO R3,20*50(R6)LDI 5,R3STO R3,gbl_int(R12)LOD 1(SP),R5LOD 2(SP),R6ADD 2,SPRETN// void proc_5(void) {// gbl_ch = 'A';// gbl_bool = false;//}#ifdef NO_INLINEproc_5:LDI 'A',R0STO R0,gbl_ch(R12)CLR R0STO R0,gbl_bool(R12);RETN#endif// void proc_4(void) {// bool lcl_bool;// lcl_bool = (gbl_ch == 'A');// gbl_ch_2 = 'B';// }#ifdef NO_INLINEproc_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',R0STO 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,SPSTO R3,2(SP)STO R2,3(SP); Save one for the return address from our JSR "instruction";LOD gbl_ptr(R12),R2TST -1,R2#ifndef SKIP_SHORT_CIRCUITSBUSY.Z#endifLOD.NZ ptr_comp(R2),R3STO.NZ R3,(R0)#ifdef NO_INLINELDI 10,R0LOD gbl_int(R12),R1MOV variant.var_1.int_comp(R2),R2MOV __HERE__+3(PC),R3STO R3,1(SP)BRA proc_7#elseLOD gbl_int(R12),R1ADD 12,R1STO R1,variant.var_1.int_comp(R2)#endif;LOD 2(SP),R3LOD 3(SP),R2ADD 3,SPRETN// 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,SPSTO 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 calculationLOD (R0),R1MOV 10(R1),R2 ; R2 = lcl_intLOD gbl_ch(R12),R4 ; R4 = gbl_ch#ifdef NO_CHEATINGproc_2_loop:CMP 'A',R4SUB.Z 1,R2LOD.Z gbl_int(R12),R5 ; R5 = gbl_intMOV.Z R2,R6 ; R6 = lcl_intSUB.Z R5,R6 ; lcl_int - gbl_intSTO.Z R6,(R0) ; *a = R6CLR.Z R3 ; lcl_enum = 0// #ifndef SKIP_SHORT_CIRCUITS// BUSY.NZ// #endifTST -1,R3// #ifndef SKIP_SHORT_CIRCUITS// BUSY.NZ// #endifBNZ proc_2_loop#elseLOD gbl_int(R12),R5SUB 1(R5),R2STO R2,(R0)#endif;LOD 1(SP),R6LOD 2(SP),R5LOD 3(SP),R4LOD 4(SP),R3LOD 5(SP),R2ADD 5,SPRETN//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,SPSTO 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 = SPMOV R0,R9LOD ptr_comp(R9),R4#ifndef SKIP_SHORT_CIRCUITSTST -1,R4BUSY.Z#endifLDI 35,R5MOV R9,R6LOD gbl_ptr(R12),R7proc_1_assign_loop_1:LOD (R6),R8ADD 1,R6STO R8,(R7)ADD 1,R7SUB 1,R5BNZ proc_1_assign_loop_1;#ifndef SKIP_SHORT_CIRCUITSLOD gbl_ptr(R12),R2TST -1,R2BUSY.Z#endifLDI 5,R5STO R5,variant.var_1.int_comp(R9)STO R5,variant.var_1.int_comp(R4)MOV ptr_comp(R4),R0MOV __HERE__+3(PC),R1STO R1,1(SP)BRA proc_3 ; Uses R0 and R1LOD discr(R4),R5CMP 0,R5BNZ proc_1_last_struct_assign; This is the juncture that is "supposed" to be takenLDI 6,R5STO R5,variant.var_1.int_comp(R4)LOD variant.var_1.enum_comp(R9), R0#ifndef SKIP_SHORT_CIRCUITSCMP 2,R0BUSY.NZ#endifMOV variant.var_1.enum_comp+R4, R1MOV __HERE__+3(PC),R2STO R2,1(SP)BRA proc_6;LOD gbl_ptr(R12),R5LOD ptr_comp(R5),R5STO R5,ptr_comp(R4);#ifdef NO_INLINELOD variant.var_1.int_comp(R4),R0LDI 10,R1MOV variant.var_1.int_comp(R4),R2MOV proc_1_return_closeout(PC),R3STO R3,1(SP)BRA proc_7#elseLOD variant.var_1.int_comp(R4),R0ADD 12,R0STO R0,variant.var_1.int_comp(R4)BRA proc_1_return_closeout#endif;proc_1_last_struct_assign:#ifndef SKIP_SHORT_CIRCUITSBUSY#endifLDI 35,R4MOV R2,R5LOD gbl_ptr(R12),R6proc_1_assign_loop_2:LOD (R6),R8STO R8,(R7)ADD 1,R6ADD 1,R7SUB 1,R5BNZ proc_1_assign_loop_2//proc_1_return_closeout://LOD 2(SP),R2LOD 3(SP),R3LOD 4(SP),R4LOD 5(SP),R5LOD 6(SP),R6LOD 7(SP),R7LOD 8(SP),R8LOD 9(SP),R9ADD 9,SPRETN// 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:#ifdef USE_PSTRSword 'DHRY','STON','E PR','OGRA','M, S','OME 'word 'STRI','NG\0\0'#elseword '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#endiffirst_string:#ifdef USE_PSTRSword 'DHRY','STON','E PR','OGRA'word 'M, 1','\'ST ','STRI','NG\0\0'#elseword '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#endifsecond_string:#ifdef USE_PSTRSword 'DHRY','STON','E PR','OGRA'word 'M, 2','\'ND ','STRI','NG\0\0'#elseword '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#endifthird_string:#ifdef USE_PSTRSword 'DHRY','STON','E PR','OGRA'word 'M, 3','\'RD ','STRI','NG\0\0'#elseword '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#endifdhrystone:#ifdef SUPERVISOR_TASKSUB 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#elselcl_int_1 equ 2 ; plus SPSUB 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 SPlcl_enum equ lcl_int_3+1 ; plus SPlcl_str_1 equ lcl_enum+1 ; plus SPlcl_str_2 equ lcl_str_1+30 ; plus SPrec_a equ lcl_str_2+30 ; plus SPrec_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 = &bSTO R0,gbl_ptr(PC)// gbl_ptr->ptr_comp = nxt;MOV rec_a(SP),R1 ; R1 = &a = nxtSTO R1,ptr_comp(R0) ; gbp_ptr->ptr.comp=b->ptr.comp=R1=nxt// gbl_ptr->variant.var_1.enum_comp = 2;LDI 2,R2STO R2,variant.var_1.enum_comp(R0)// gbl_ptr->variant.var_1.int_comp = 40;LDI 40,R2STO 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),R0MOV some_string(PC),R1MOV __HERE__+3(PC),R2STO R2,1(SP)BRA lcl_strcpy// lcl_strcpy(lcl_str_1, "DHRYSTONE PROGRAM, 1\'ST STRING");MOV lcl_str_1(SP),R0MOV first_string(PC),R1MOV __HERE__+3(PC),R2STO R2,1(SP)BRA lcl_strcpy// gbl_arr_2[8][7] = 10;LDI 10,R0STO R0,8*50+7+gbl_arr_2(R12)//// for(index=0; index < number_of_runs; index++) {; Let R11 be our indexCLR R11dhrystone_main_loop:;; Start of Dhrystone main loop; proc_5();#ifdef NO_INLINEMOV __HERE__+3(PC),R0STO R0,1(SP)BRA proc_5#elseLDI 'A',R0STO R0,gbl_ch(R12)CLR R0STO R0,gbl_bool(R12)#endif; proc_4();#ifdef NO_INLINEMOV __HERE__+3(PC),R0STO R0,1(SP)BRA proc_4#elseLDI 'B',R0STO R0,gbl_ch_2(R12)#endif// lcl_int_1 = 2;LDI 2,R5STO 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),R0MOV second_string(PC),R1MOV __HERE__+3(PC),R2STO R2,1(SP)BRA lcl_strcpy// lcl_enum = Ident_2;LDI 2,R0STO R0,lcl_enum(SP)// gbl_bool = !func_2(lcl_str_1, lcl_str_2);MOV lcl_str_1(SP),R0MOV lcl_str_2(SP),R1MOV __HERE__+3(PC),R2STO R2,1(SP)BRA func_2CLR R1TST -1,R0LDILO.Z 1,R1STO 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 requiredLOD lcl_int_1(SP),R5// The 'while' comparisonCMP R6,R5BGE dhrystone_end_while_loopdhrystone_while_loop:// lcl_int_3 = 5 * lcl_int_1 - lcl_int_2;MOV R5,R7MPYS 5,R7SUB R6,R7STO R7,lcl_int_3(SP)// proc_7(lcl_int_1, lcl_int_2, &lcl_int_3);#ifdef NO_INLINEMOV R5,R0MOV R6,R1MOV lcl_int_3(SP),R2MOV __HERE__+3(PC),R3STO R3,1(SP)BRA proc_7#elseMOV R6,R1ADD 2+R5,R1STO R1,lcl_int_3(SP)#endif// lcl_int_1 += 1;LOD lcl_int_1(SP),R5ADD 1,R5STO R5,lcl_int_1(SP);; BRA dhrystone_while_loop ; We'll unroll the loop, and put anCMP R6,R5 ; additional comparison at the bottomBLT dhrystone_while_loopdhrystone_end_while_loop:// }//// proc_8(gbl_arr_1, gbl_arr_2, lcl_int_1, lcl_int_3);MOV gbl_arr_1(PC),R0MOV gbl_arr_2(PC),R1MOV R5,R2MOV R6,R3MOV __HERE__+3(PC),R4STO R4,1(SP)BRA proc_8// proc_1(gbl_ptr);LOD gbl_ptr(PC),R0MOV __HERE__+3(PC),R2STO R2,1(SP)BRA proc_1//// for(ch_index='A'; ch_index <= gbl_ch_2; ch_index++) {LDI 'A',R7LOD gbl_ch_2(SP),R8CMP R7,R8BLT dhrystone_end_of_for_loopdhrystone_top_of_for_loop:// if (lcl_enum == func_1(ch_index, 'C')) {#ifdef NO_INLINEMOV R7,R0LDI 'C',R1MOV __HERE__+3(PC),R2STO R2,1(SP)BRA func_1#elseCMP 'C',R7CLR.NZ R0STO.Z R7,gbl_ch(R12)LDILO.Z 1,R0#endif; Result is now in R0LOD lcl_enum(SP),R1CMP R0,R1BNZ dhrystone_skip_then_clause// // Then not executed??// proc_6(0, &lcl_enum);#ifndef SKIP_SHORT_CIRCUITSBUSY#endifCLR R0MOV lcl_enum(SP),R1MOV __HERE__+3(PC),R2STO R2,1(SP)BRA proc_6// lcl_strcpy(lcl_str_2, "DHRYSTONE PROGRAM, 3\'RD STRING");MOV lcl_str_2(SP),R0MOV third_string(PC),R1MOV __HERE__+3(PC),R2STO 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,R7LOD gbl_ch_2(SP),R8CMP R8,R7BGE dhrystone_top_of_for_loopdhrystone_end_of_for_loop:// }//// lcl_int_2 = lcl_int_2 * lcl_int_1;LOD lcl_int_1(SP),R5MPYS R5,R6 ; lcl_int_2 =// lcl_int_1 = lcl_int_2 / lcl_int_3;#ifndef SKIP_DIVIDEMOV R6,R0LOD lcl_int_3(SP),R1MOV __HERE__+3(PC),R2STO R2,1(SP)BRA divs#elseLDI 9,R0#endifSTO R0,lcl_int_1(SP)// lcl_int_2 = 7 * ( lcl_int_2 - lcl_int_3) - lcl_int_1;LOD lcl_int_3(SP),R2SUB R2,R6MPYS 7,R6SUB R0,R6// proc_2(&lcl_int_1);MOV lcl_int_1(SP),R0MOV __HERE__+3(PC),R1STO R1,1(SP)BRA proc_2;; Bottom of (and return from) Dhrystone main loopADD 1,R11CMP NUMBER_OF_RUNS,R11BLT dhrystone_main_loop// }#ifdef SUPERVISOR_TASKLOD 2(SP),R1LOD 3(SP),R2LOD 4(SP),R3LOD 5(SP),R4LOD 6(SP),R5LOD 7(SP),R6LOD 8(SP),R7LOD 9(SP),R8LOD 10(SP),R9LOD 11(SP),R10LOD 12(SP),R11;ADD 12+RECSIZE+RECSIZE+30+30+3,SP; Return from subroutineRETN#elseLDI 0,CCNOPNOPBUSY#endif
Go to most recent revision | Compare with Previous | Blame | View Log
