;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;
|
;
|
; Filename: zipdhry.S
|
; Filename: zipdhry.S
|
;
|
;
|
; Project: Zip CPU -- a small, lightweight, RISC CPU soft core
|
; Project: Zip CPU -- a small, lightweight, RISC CPU soft core
|
;
|
;
|
; Purpose: Zip assembly file for running the Dhrystone benchmark in the
|
; Purpose: Zip assembly file for running the Dhrystone benchmark in the
|
; Zip CPU.
|
; 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.
|
; Creator: Dan Gisselquist, Ph.D.
|
; Gisselquist Tecnology, LLC
|
; Gisselquist Technology, LLC
|
;
|
;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;
|
;
|
; Copyright (C) 2015, Gisselquist Technology, LLC
|
; Copyright (C) 2015, Gisselquist Technology, LLC
|
;
|
;
|
; This program is free software (firmware): you can redistribute it and/or
|
; 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
|
; 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
|
; by the Free Software Foundation, either version 3 of the License, or (at
|
; your option) any later version.
|
; your option) any later version.
|
;
|
;
|
; This program is distributed in the hope that it will be useful, but WITHOUT
|
; This program is distributed in the hope that it will be useful, but WITHOUT
|
; ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
|
; ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
|
; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
; for more details.
|
; for more details.
|
;
|
;
|
; License: GPL, v3, as defined and found on www.gnu.org,
|
; License: GPL, v3, as defined and found on www.gnu.org,
|
; http://www.gnu.org/licenses/gpl.html
|
; http://www.gnu.org/licenses/gpl.html
|
;
|
;
|
;
|
;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;
|
;
|
// Under Verilator:
|
// 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
|
// with no loop unrolling nor function inlining
|
// DMIPS: 24.3 100 MHz (sim) 0.24
|
// DMIPS: 24.3 100 MHz (sim) 0.24
|
// with packed strings
|
// with packed strings
|
// DMIPS: 35.6 100 MHz (sim) 0.36
|
// DMIPS: 35.6 100 MHz (sim) 0.36
|
//
|
//
|
// For comparison:
|
// For comparison:
|
// uBlaze: 255 177 MHz 1.44
|
// uBlaze: 230 177 MHz 1.3
|
// LEON3 1.4
|
// LEON3 1.4
|
// NiOS II: 218 185 MHz 1.16
|
// NiOS II: 218 185 MHz 1.16
|
// OpenRisk 250 250 MHz 1.00
|
// OpenRisk 250 250 MHz 1.00
|
// LM32 1.14
|
// LM32 1.14
|
// ZPU 2.6 50 MHz 0.05
|
// ZPU 2.6 50 MHz 0.05
|
//
|
//
|
|
|
// Some #def's to control compilation.
|
// Some #def's to control compilation.
|
//
|
//
|
// SKIP_SHORT_CIRCUITS determines whether or not we do internal testing and
|
// 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
|
// 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
|
// NO_INLINE controls whether or not we inline certain functions. If you
|
// define this, nothing will be inlined.
|
// define this, nothing will be inlined.
|
|
//
|
|
// I recommend not setting this define.
|
|
//
|
// #define NO_INLINE
|
// #define NO_INLINE
|
//
|
//
|
|
//
|
|
//
|
// NO_LOOP_UNROLLING controls loop unrolling. The default is to unroll loops
|
// 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
|
// #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
|
sys.ctr.mtask equ 0xc0000008
|
// int main(int argc, char **argv) {
|
// int main(int argc, char **argv) {
|
// dhrystone();
|
// dhrystone();
|
// }
|
// }
|
entry:
|
entry:
|
MOV top_of_stack(PC),uSP
|
MOV top_of_stack(PC),uSP
|
MOV entry(PC),uR12
|
MOV entry(PC),uR12
|
; Store our tick counter in R1
|
; Store our tick counter in R1
|
LDI sys.ctr.mtask,R1
|
LDI sys.ctr.mtask,R1
|
; And start with our counter cleared at zero
|
; And start with our counter cleared at zero
|
CLR R0
|
CLR R0
|
STO R0,(R1)
|
STO R0,(R1)
|
#ifdef SUPERVISOR_TASK
|
#ifdef SUPERVISOR_TASK
|
MOV __HERE__+3(PC),R0
|
MOV __HERE__+2(PC),R0
|
STO R0,1(SP)
|
|
BRA dhrystone
|
BRA dhrystone
|
#else
|
#else
|
MOV dhrystone(PC),uPC
|
MOV dhrystone(PC),uPC
|
RTU
|
RTU
|
#endif
|
#endif
|
; Read the tick counter back out
|
; Read the tick counter back out
|
LOD (R1),R0
|
LOD (R1),R0
|
HALT ; Stop the CPU--We're done!!!!!!!
|
HALT ; Stop the CPU--We're done!!!!!!!
|
|
|
// typedef enum { Ident_1, Ident_2, Ident_3, Ident_4, Ident_5 } test_enum;
|
// typedef enum { Ident_1, Ident_2, Ident_3, Ident_4, Ident_5 } test_enum;
|
// typedef enum { false, true } bool;
|
// typedef enum { false, true } bool;
|
|
|
// typedef int Arr_1_Dim[50];
|
// typedef int Arr_1_Dim[50];
|
// typedef int Arr_2_Dim[50][50];
|
// typedef int Arr_2_Dim[50][50];
|
#ifdef USE_PSTRS
|
|
#define RECSIZE 12
|
|
#else
|
|
#define RECSIZE 35
|
#define RECSIZE 35
|
#endif
|
|
#define NUMBER_OF_RUNS (512)
|
#define NUMBER_OF_RUNS (512)
|
ptr_comp equ 0
|
ptr_comp equ 0
|
discr equ 1
|
discr equ 1
|
variant.var_1.enum_comp equ 2
|
variant.var_1.enum_comp equ 2
|
variant.var_1.int_comp equ 3
|
variant.var_1.int_comp equ 3
|
variant.var_1.str_comp equ 4
|
variant.var_1.str_comp equ 4
|
|
|
gbl_arr_1:
|
gbl_arr_1:
|
fill 50,0
|
fill 50,0
|
gbl_arr_2:
|
gbl_arr_2:
|
fill 2500,0
|
fill 2500,0
|
gbl_ch:
|
gbl_ch:
|
word 0
|
word 0
|
gbl_ch_2:
|
gbl_ch_2:
|
word 0
|
word 0
|
gbl_bool:
|
gbl_bool:
|
word 0
|
word 0
|
gbl_int:
|
gbl_int:
|
word 0
|
word 0
|
gbl_ptr:
|
gbl_ptr:
|
word 0
|
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_1_Dim gbl_arr_1;
|
// Arr_2_Dim gbl_arr_2;
|
// Arr_2_Dim gbl_arr_2;
|
// char gbl_ch, gbl_ch_2;
|
// char gbl_ch, gbl_ch_2;
|
// bool gbl_bool;
|
// bool gbl_bool;
|
// int gbl_int;
|
// int gbl_int;
|
// RECP gbl_ptr;
|
// RECP gbl_ptr;
|
|
|
//char *lcl_strcpy(char *d, char *s) {
|
//char *lcl_strcpy(char *d, char *s) {
|
// char *cpd = d, ch;
|
// char *cpd = d, ch;
|
//
|
//
|
// do{
|
// do{
|
// *cpd++ = ch = *s++;
|
// *cpd++ = ch = *s++;
|
// } while(ch);
|
// } while(ch);
|
//
|
//
|
//}
|
//}
|
//
|
//
|
|
|
|
#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:
|
lcl_strcpy:
|
; R0 = d
|
; R0 = d
|
; R1 = s
|
; R1 = s
|
; R3 = ch
|
; R3 = ch
|
copy_next_char:
|
copy_next_char:
|
|
SUB 1,SP
|
|
STO R2,(SP)
|
#ifdef NO_LOOP_UNROLLING
|
#ifdef NO_LOOP_UNROLLING
|
LOD (R1),R2
|
LOD (R1),R2
|
STO R2,(R0)
|
STO R2,(R0)
|
#ifdef USE_PSTRS
|
|
TST 255,R2
|
|
#else
|
|
CMP 0,R2
|
CMP 0,R2
|
#endif
|
BZ lcl_strcpy_end_of_loop
|
RETN.Z
|
|
ADD 1,R0
|
ADD 1,R0
|
ADD 1,R1
|
ADD 1,R1
|
BRA copy_next_char
|
BRA copy_next_char
|
|
|
|
|
|
|
#else
|
#else
|
LOD (R1),R2
|
LOD (R1),R2
|
STO R2,(R0)
|
STO R2,(R0)
|
#ifdef USE_PSTRS
|
|
TST 255,R2
|
|
#else
|
|
CMP 0,R2
|
CMP 0,R2
|
#endif
|
BZ lcl_strcpy_end_of_loop
|
; BZ lcl_strcpy_end_of_loop
|
|
RETN.Z
|
|
LOD 1(R1),R2
|
LOD 1(R1),R2
|
STO R2,1(R0)
|
STO R2,1(R0)
|
#ifdef USE_PSTRS
|
|
TST 255,R2
|
|
#else
|
|
CMP 0,R2
|
CMP 0,R2
|
#endif
|
BZ lcl_strcpy_end_of_loop
|
; BZ lcl_strcpy_end_of_loop
|
|
RETN.Z
|
|
LOD 2(R1),R2
|
LOD 2(R1),R2
|
STO R2,2(R0)
|
STO R2,2(R0)
|
#ifdef USE_PSTRS
|
|
TST 255,R2
|
|
#else
|
|
CMP 0,R2
|
CMP 0,R2
|
#endif
|
BZ lcl_strcpy_end_of_loop
|
; BZ lcl_strcpy_end_of_loop
|
|
RETN.Z
|
|
LOD 3(R1),R2
|
LOD 3(R1),R2
|
STO R2,3(R0)
|
STO R2,3(R0)
|
; BZ lcl_strcpy_end_of_loop
|
|
#ifdef USE_PSTRS
|
|
TST 255,R2
|
|
#else
|
|
CMP 0,R2
|
CMP 0,R2
|
#endif
|
BZ lcl_strcpy_end_of_loop
|
RETN.Z
|
|
ADD 4,R0
|
ADD 4,R0
|
ADD 4,R1
|
ADD 4,R1
|
BRA copy_next_char
|
BRA copy_next_char
|
#endif
|
#endif
|
|
lcl_strcpy_end_of_loop:
|
|
LOD (SP),R2
|
|
ADD 1,SP
|
|
JMP R2
|
|
#endif
|
|
|
//int lcl_strcmp(char *s1, char *s2) {
|
//int lcl_strcmp(char *s1, char *s2) {
|
// char a, b;
|
// char a, b;
|
// do {
|
// do {
|
// a = *s1++; b = *s2++;
|
// a = *s1++; b = *s2++;
|
// } while((a)&&(a==b));
|
// } while((a)&&(a==b));
|
//
|
//
|
// return a-b;
|
// return a-b;
|
//}
|
//}
|
|
|
|
#ifdef PIPELINED_STRCMP
|
lcl_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)
|
STO R3,1(SP)
|
|
|
strcmp_top_of_loop:
|
strcmp_top_of_loop:
|
#ifdef NO_LOOP_UNROLLING
|
#ifdef NO_LOOP_UNROLLING
|
; LOD (R0),R2
|
; LOD (R0),R2
|
; LOD (R1),R3 ; Alternate approach:
|
; LOD (R1),R3 ; Alternate approach:
|
; CMP R2,R3 ; CMP 0,R2
|
; CMP R2,R3 ; CMP 0,R2
|
; BNZ strcmp_end_loop ; BZ strcmp_end_loop
|
; BNZ strcmp_end_loop ; BZ strcmp_end_loop
|
; CMP 0,R2 ; CMP R2,R3
|
; CMP 0,R2 ; CMP R2,R3
|
; BZ strcmp_end_loop ; BZ strcmp_top_of_loop
|
; BZ strcmp_end_loop ; BZ strcmp_top_of_loop
|
; CMP 0,R3 ;
|
; CMP 0,R3 ;
|
; BZ strcmp_end_loop ;
|
; BZ strcmp_end_loop ;
|
; ADD 1,R0
|
; ADD 1,R0
|
; ADD 1,R1
|
; ADD 1,R1
|
; BRA strcmp_top_of_loop
|
; BRA strcmp_top_of_loop
|
LOD (R0),R2
|
LOD (R0),R2
|
LOD (R1),R3
|
LOD (R1),R3
|
#ifdef USE_PSTRS
|
|
TST 255,R2
|
|
#else
|
|
CMP 0,R2
|
CMP 0,R2
|
#endif
|
|
BZ strcmp_end_loop
|
BZ strcmp_end_loop
|
ADD 1,R0
|
ADD 1,R0
|
ADD 1,R1
|
ADD 1,R1
|
CMP R2,R3
|
CMP R2,R3
|
BZ strcmp_top_of_loop
|
BZ strcmp_top_of_loop
|
#else
|
#else
|
LOD (R0),R2
|
LOD (R0),R2
|
LOD (R1),R3
|
LOD (R1),R3
|
#ifdef USE_PSTRS
|
|
TST 255,R2
|
|
#else
|
|
CMP 0,R2
|
CMP 0,R2
|
#endif
|
|
BZ strcmp_end_loop
|
BZ strcmp_end_loop
|
CMP R2,R3
|
CMP R2,R3
|
BNZ strcmp_end_loop
|
BNZ strcmp_end_loop
|
LOD 1(R0),R2
|
LOD 1(R0),R2
|
LOD 1(R1),R3
|
LOD 1(R1),R3
|
#ifdef USE_PSTRS
|
|
TST 255,R2
|
|
#else
|
|
CMP 0,R2
|
CMP 0,R2
|
#endif
|
|
BZ strcmp_end_loop
|
BZ strcmp_end_loop
|
CMP R2,R3
|
CMP R2,R3
|
BNZ strcmp_end_loop
|
BNZ strcmp_end_loop
|
LOD 2(R0),R2
|
LOD 2(R0),R2
|
LOD 2(R1),R3
|
LOD 2(R1),R3
|
#ifdef USE_PSTRS
|
|
TST 255,R2
|
|
#else
|
|
CMP 0,R2
|
CMP 0,R2
|
#endif
|
|
BZ strcmp_end_loop
|
BZ strcmp_end_loop
|
CMP R2,R3
|
CMP R2,R3
|
BNZ strcmp_end_loop
|
BNZ strcmp_end_loop
|
LOD 3(R0),R2
|
LOD 3(R0),R2
|
LOD 3(R1),R3
|
LOD 3(R1),R3
|
#ifdef USE_PSTRS
|
|
TST 255,R2
|
|
#else
|
|
CMP 0,R2
|
CMP 0,R2
|
#endif
|
|
BZ strcmp_end_loop
|
BZ strcmp_end_loop
|
CMP R2,R3
|
CMP R2,R3
|
BNZ strcmp_end_loop
|
BNZ strcmp_end_loop
|
ADD 4,R0
|
ADD 4,R0
|
ADD 4,R1
|
ADD 4,R1
|
BRA strcmp_top_of_loop
|
BRA strcmp_top_of_loop
|
#endif
|
#endif
|
|
|
strcmp_end_loop:
|
strcmp_end_loop:
|
SUB R3,R2
|
SUB R3,R2
|
MOV R2,R0
|
MOV R2,R0
|
|
|
|
LOD (SP),R2
|
LOD 1(SP),R3
|
LOD 1(SP),R3
|
ADD 1,SP
|
ADD 2,SP
|
RETN
|
JMP R2
|
|
#endif
|
|
|
|
|
//test_enum func_1(char ch_1, char ch_2) {
|
//test_enum func_1(char ch_1, char ch_2) {
|
// char lcl_ch_1, lcl_ch_2;
|
// char lcl_ch_1, lcl_ch_2;
|
//
|
//
|
// lcl_ch_1 = ch_1;
|
// lcl_ch_1 = ch_1;
|
// lcl_ch_2 = lcl_ch_1;
|
// lcl_ch_2 = lcl_ch_1;
|
// if (lcl_ch_2 != ch_2)
|
// if (lcl_ch_2 != ch_2)
|
// return 0;
|
// return 0;
|
// else {
|
// else {
|
// gbl_ch = lcl_ch_1;
|
// gbl_ch = lcl_ch_1;
|
// return 1;
|
// return 1;
|
// }
|
// }
|
|
|
#ifdef NO_INLINE
|
#ifdef NO_INLINE
|
func_1:
|
func_1:
|
; On input,
|
; On input,
|
; R0 = ch_1
|
; R0 = ch_1
|
; R1 = ch_2
|
; R1 = ch_2
|
; R2 = available
|
; R2 = available
|
; On output, R0 is our return value
|
; On output, R0 is our return value
|
|
|
|
SUB 1,SP
|
|
STO R2,(SP)
|
MOV R0,R2
|
MOV R0,R2
|
CMP R2,R1
|
CMP R2,R1
|
CLR.NZ R0
|
CLR.NZ R0
|
STO.Z R2,gbl_ch(R12)
|
STO.Z R2,gbl_ch(R12)
|
LDILO.Z 1,R0
|
LDILO.Z 1,R0
|
RETN
|
LOD (SP),R2
|
|
ADD 1,SP
|
|
JMP R2
|
#endif
|
#endif
|
|
|
//bool func_2(char *str_1, char *str_2) {
|
//bool func_2(char *str_1, char *str_2) {
|
// int lcl_int;
|
// int lcl_int;
|
// char lcl_ch;
|
// char lcl_ch;
|
//
|
//
|
// lcl_int = 2;
|
// lcl_int = 2;
|
// while(lcl_int <= 2) {
|
// while(lcl_int <= 2) {
|
// if (func_1(str_1[lcl_int], str_2[lcl_int+1])==0) {
|
// if (func_1(str_1[lcl_int], str_2[lcl_int+1])==0) {
|
// lcl_ch = 'A';
|
// lcl_ch = 'A';
|
// lcl_int ++;
|
// lcl_int ++;
|
// }
|
// }
|
// }
|
// }
|
//
|
//
|
// if ((lcl_ch >= 'W')&&(lcl_ch < 'Z'))
|
// if ((lcl_ch >= 'W')&&(lcl_ch < 'Z'))
|
// lcl_int = 7;
|
// lcl_int = 7;
|
// if (lcl_ch == 'R')
|
// if (lcl_ch == 'R')
|
// return true;
|
// return true;
|
// else {
|
// else {
|
// if (lcl_strcmp(str_1, str_2)>0) {
|
// if (lcl_strcmp(str_1, str_2)>0) {
|
// lcl_int += 7;
|
// lcl_int += 7;
|
// gbl_int = lcl_int;
|
// gbl_int = lcl_int;
|
// } else
|
// } else
|
// return false;
|
// return false;
|
// }
|
// }
|
//}
|
//}
|
func_2:
|
func_2:
|
;
|
;
|
SUB 6,SP
|
SUB 6,SP
|
STO R3,2(SP)
|
STO R2,(SP)
|
STO R4,3(SP)
|
STO R3,1(SP)
|
STO R5,4(SP)
|
STO R4,2(SP)
|
STO R6,5(SP)
|
STO R5,3(SP)
|
STO R7,6(SP)
|
STO R6,4(SP)
|
|
STO R7,5(SP)
|
|
|
MOV R0,R3 ; R3 = str_1
|
MOV R0,R3 ; R3 = str_1
|
MOV R1,R4 ; R4 = str_2
|
MOV R1,R4 ; R4 = str_2
|
LDI 2,R5 ; R5 = lcl_int
|
LDI 2,R5 ; R5 = lcl_int
|
LDI 'A',R7 ; R7 = lcl_ch
|
LDI 'A',R7 ; R7 = lcl_ch
|
func_2_while_loop:
|
func_2_while_loop:
|
CMP 2,R5
|
CMP 2,R5
|
BGT func_2_end_while_loop
|
BGT func_2_end_while_loop
|
func_2_top_while_loop:
|
func_2_top_while_loop:
|
MOV R3,R6
|
MOV R3,R6
|
ADD R5,R6
|
ADD R5,R6
|
|
|
#ifdef NO_INLINE
|
#ifdef NO_INLINE
|
LOD (R6),R0
|
LOD (R6),R0
|
MOV R4,R6
|
MOV R4,R6
|
ADD R5,R6
|
ADD R5,R6
|
LOD 1(R6),R1
|
LOD 1(R6),R1
|
|
|
MOV __HERE__+3(PC),R2
|
MOV __HERE__+2(PC),R2
|
STO R2,1(SP)
|
|
BRA func_1
|
BRA func_1
|
|
|
CMP 0,R0
|
CMP 0,R0
|
ADD.Z 1,R5
|
ADD.Z 1,R5
|
#ifndef SKIP_SHORT_CIRCUITS
|
#ifndef SKIP_SHORT_CIRCUITS
|
BUSY.NZ
|
BUSY.NZ
|
#endif
|
#endif
|
#else
|
#else
|
LOD (R6),R2
|
LOD (R6),R2
|
MOV R4,R6
|
MOV R4,R6
|
ADD R5,R6
|
ADD R5,R6
|
LOD 1(R6),R1
|
LOD 1(R6),R1
|
|
|
CMP R2,R1
|
CMP R2,R1
|
STO.Z R2,gbl_ch(R12)
|
STO.Z R2,gbl_ch(R12)
|
LDILO.Z 1,R0
|
LDILO.Z 1,R0
|
|
|
ADD.NZ 1,R5
|
ADD.NZ 1,R5
|
#ifndef SKIP_SHORT_CIRCUITS
|
#ifndef SKIP_SHORT_CIRCUITS
|
BUSY.Z
|
BUSY.Z
|
#endif
|
#endif
|
#endif
|
#endif
|
|
|
CMP 3,R5
|
CMP 3,R5
|
#ifndef SKIP_SHORT_CIRCUITS
|
#ifndef SKIP_SHORT_CIRCUITS
|
BUSY.LT
|
BUSY.LT
|
#endif
|
#endif
|
BLT func_2_top_while_loop
|
BLT func_2_top_while_loop
|
|
|
func_2_end_while_loop:
|
func_2_end_while_loop:
|
|
|
// CMP 'W',R7 // BUT! We know lcl_ch='A'
|
// CMP 'W',R7 // BUT! We know lcl_ch='A'
|
// BLT skip_if // So we can skip this
|
// BLT skip_if // So we can skip this
|
// CMP 'Z',R7 // entire section
|
// CMP 'Z',R7 // entire section
|
// LDI.LT 7,R5
|
// LDI.LT 7,R5
|
// CMP 'R',R7
|
// CMP 'R',R7
|
// BNZ alt_if_case
|
// BNZ alt_if_case
|
// LLO.Z 1,R0
|
// LLO.Z 1,R0
|
// BRA func_2_return_and_cleanup
|
// BRA func_2_return_and_cleanup
|
//
|
//
|
MOV R3,R0
|
MOV R3,R0
|
MOV R4,R1
|
MOV R4,R1
|
MOV __HERE__+3(PC),R2
|
MOV __HERE__+2(PC),R2
|
STO R2,1(SP)
|
|
BRA lcl_strcmp
|
BRA lcl_strcmp
|
CMP 0,R0
|
CMP 0,R0
|
BGT func_2_final_then
|
BGT func_2_final_then
|
CLR R0
|
CLR R0
|
BRA func_2_return_and_cleanup
|
BRA func_2_return_and_cleanup
|
func_2_final_then:
|
func_2_final_then:
|
// ADD 7,R5 ; Never read, so useless code
|
// ADD 7,R5 ; Never read, so useless code
|
LDI 1,R0
|
LDI 1,R0
|
#ifndef SKIP_SHORT_CIRCUITS
|
#ifndef SKIP_SHORT_CIRCUITS
|
BUSY
|
BUSY
|
#endif
|
#endif
|
func_2_return_and_cleanup:
|
func_2_return_and_cleanup:
|
|
|
LOD 2(SP),R3
|
LOD (SP),R2
|
LOD 3(SP),R4
|
LOD 1(SP),R3
|
LOD 4(SP),R5
|
LOD 2(SP),R4
|
LOD 5(SP),R6
|
LOD 3(SP),R5
|
LOD 6(SP),R7
|
LOD 4(SP),R6
|
|
LOD 5(SP),R7
|
ADD 6,SP
|
ADD 6,SP
|
RETN
|
JMP R2
|
|
NOP
|
|
|
//bool func_3(test_enum a) {
|
//bool func_3(test_enum a) {
|
// test_enum lcl_enum;
|
// test_enum lcl_enum;
|
//
|
//
|
// lcl_enum = a;
|
// lcl_enum = a;
|
// if (lcl_enum == Ident_3)
|
// if (lcl_enum == Ident_3)
|
// return true;
|
// return true;
|
// else
|
// else
|
// return false;
|
// return false;
|
//}
|
//}
|
|
|
#ifdef NO_INLINE
|
#ifdef NO_INLINE
|
func_3:
|
func_3:
|
; On entry,
|
; On entry,
|
; R0 = a
|
; R0 = a
|
; R1 - available
|
; R1 - available
|
CMP 2,R0
|
CMP 2,R0
|
CLR R0 ; CLR Doesn't set flags
|
CLR R0 ; CLR Doesn't set flags
|
LDILO.Z 1,R0
|
LDILO.Z 1,R0
|
RETN
|
JMP R1
|
#endif
|
#endif
|
|
|
|
|
// void proc_6(test_enum ev, test_enum *ep) {
|
// void proc_6(test_enum ev, test_enum *ep) {
|
// *ep = ev;
|
// *ep = ev;
|
// if (!func_3(ev))
|
// if (!func_3(ev))
|
// *ep = 3;
|
// *ep = 3;
|
// switch(ev) {
|
// switch(ev) {
|
// case 0: *ep = 0; break;
|
// case 0: *ep = 0; break;
|
// case 1:
|
// case 1:
|
// if (gbl_int > 100)
|
// if (gbl_int > 100)
|
// *ep = 0;
|
// *ep = 0;
|
// else
|
// else
|
// *ep = 3;
|
// *ep = 3;
|
// break;
|
// break;
|
// case 2:
|
// case 2:
|
// *ep = 1;
|
// *ep = 1;
|
// break;
|
// break;
|
// case 3:
|
// case 3:
|
// break;
|
// break;
|
// case 4:
|
// case 4:
|
// *ep = 2;
|
// *ep = 2;
|
// }
|
// }
|
//}
|
//}
|
|
|
proc_6:
|
proc_6:
|
; On entry:
|
; On entry:
|
; R0 = ev
|
; R0 = ev
|
; R1 = ep
|
; R1 = ep
|
; R2 - unassigned
|
; R2 = link address
|
; Since we call func_3, we have to reserve R0 and R1
|
; Since we call func_3, we have to reserve R0 and R1
|
; for other purposes. Thus
|
; for other purposes. Thus
|
; R2 = ev
|
; R2 = ev
|
; R3 = ep
|
; R3 = ep
|
SUB 2,SP
|
SUB 2,SP
|
STO R3,2(SP)
|
STO R2,(SP)
|
|
STO R3,1(SP)
|
|
|
MOV R1,R3
|
MOV R1,R3
|
MOV R0,R2
|
MOV R0,R2
|
; *ep = ev
|
; *ep = ev
|
STO R0,(R1)
|
STO R0,(R1)
|
#ifndef SKIP_SHORT_CIRCUITS
|
#ifndef SKIP_SHORT_CIRCUITS
|
CMP 2,R0
|
CMP 2,R0
|
BUSY.NZ
|
BUSY.NZ
|
#endif
|
#endif
|
|
|
#ifdef NO_INLINE
|
#ifdef NO_INLINE
|
; !func_3(ev)
|
; !func_3(ev)
|
MOV __HERE__+3(PC),R1
|
MOV __HERE__+2(PC),R1
|
STO R1,1(SP)
|
|
BRA func_3
|
BRA func_3
|
|
|
TST -1,R0
|
TST -1,R0
|
LDI 3,R1
|
LDI 3,R1
|
|
#ifndef SKIP_SHORT_CIRCUITS
|
|
BUSY.Z
|
|
#endif
|
STO.Z R1,(R3)
|
STO.Z R1,(R3)
|
#else
|
#else
|
CMP 2,R0
|
CMP 2,R0
|
LDI 3,R1
|
LDI 3,R1
|
STO.Z R1,(R3)
|
#ifdef SKIP_SHORT_CIRCUITS
|
|
BUSY.NZ
|
#endif
|
#endif
|
|
STO.NZ R1,(R3)
|
TST -1,R0
|
|
LDI 3,R1
|
|
#ifndef SKIP_SHORT_CIRCUITS
|
|
BUSY.Z
|
|
#endif
|
#endif
|
STO.Z R1,(R3)
|
|
|
|
#ifndef SKIP_SHORT_CIRCUITS
|
#ifndef SKIP_SHORT_CIRCUITS
|
CMP 2,R2
|
CMP 2,R2
|
BUSY.NZ
|
BUSY.NZ
|
#endif
|
#endif
|
CMP 0,R2
|
CMP 0,R2
|
BNZ proc_6_case_not_zero
|
BNZ proc_6_case_not_zero
|
#ifndef SKIP_SHORT_CIRCUITS
|
#ifndef SKIP_SHORT_CIRCUITS
|
BUSY
|
BUSY
|
#endif
|
#endif
|
LDI 0,R1
|
LDI 0,R1
|
STO R1,(R3)
|
STO R1,(R3)
|
BRA proc_6_end_of_case
|
BRA proc_6_end_of_case
|
proc_6_case_not_zero:
|
proc_6_case_not_zero:
|
CMP 1,R2
|
CMP 1,R2
|
BNZ proc_6_case_not_one
|
BNZ proc_6_case_not_one
|
#ifndef SKIP_SHORT_CIRCUITS
|
#ifndef SKIP_SHORT_CIRCUITS
|
BUSY
|
BUSY
|
#endif
|
#endif
|
LDI 3,R0
|
LDI 3,R0
|
LOD gbl_int(R12),R1
|
LOD gbl_int(R12),R1
|
CMP 100,R1
|
CMP 100,R1
|
CLR.GT R0
|
CLR.GT R0
|
STO R0,(R3)
|
STO R0,(R3)
|
BRA proc_6_end_of_case
|
BRA proc_6_end_of_case
|
proc_6_case_not_one:
|
proc_6_case_not_one:
|
CMP 2,R2
|
CMP 2,R2
|
BNZ proc_6_case_not_two
|
BNZ proc_6_case_not_two
|
LDI 1,R1 // Executed, if done properly
|
LDI 1,R1 // Executed, if done properly
|
STO R1,(R3)
|
STO R1,(R3)
|
BRA proc_6_end_of_case
|
BRA proc_6_end_of_case
|
proc_6_case_not_two:
|
proc_6_case_not_two:
|
#ifndef SKIP_SHORT_CIRCUITS
|
#ifndef SKIP_SHORT_CIRCUITS
|
BUSY
|
BUSY
|
#endif
|
#endif
|
CMP 4,R2
|
CMP 4,R2
|
BNZ proc_6_case_not_four
|
BNZ proc_6_case_not_four
|
LDI 2,R1
|
LDI 2,R1
|
STO R1,(R3)
|
STO R1,(R3)
|
// BRA proc_6_end_of_case
|
// BRA proc_6_end_of_case
|
proc_6_case_not_four:
|
proc_6_case_not_four:
|
proc_6_end_of_case:
|
proc_6_end_of_case:
|
LOD 2(SP),R3
|
LOD (SP),R2
|
|
LOD 1(SP),R3
|
ADD 2,SP
|
ADD 2,SP
|
RETN
|
JMP R2
|
|
NOP
|
|
|
// void proc_7(int a, int b, int *c) {
|
// void proc_7(int a, int b, int *c) {
|
// int lcl;
|
// int lcl;
|
//
|
//
|
// lcl = a + 2;
|
// lcl = a + 2;
|
// *c = b + a;
|
// *c = b + a;
|
//}
|
//}
|
|
|
#ifdef NO_INLINE
|
#ifdef NO_INLINE
|
proc_7:
|
proc_7:
|
ADD 2+R0,R1
|
ADD 2+R0,R1
|
STO R1,(R2)
|
STO R1,(R2)
|
|
|
RETN
|
JMP R3
|
#endif
|
#endif
|
|
|
// int a[50];
|
// int a[50];
|
// int b[50][50];
|
// int b[50][50];
|
//
|
//
|
// void proc_8(Arr_1_Dim a, Arr_2_Dim b, int c, int d) {
|
// void proc_8(Arr_1_Dim a, Arr_2_Dim b, int c, int d) {
|
// int idx, loc;
|
// int idx, loc;
|
//
|
//
|
// loc = c+5;
|
// loc = c+5;
|
// a[loc] = d;
|
// a[loc] = d;
|
// a[loc+1] = a[loc];
|
// a[loc+1] = a[loc];
|
// a[loc+30] = loc;
|
// a[loc+30] = loc;
|
// for(idx=loc; idx<= loc+1; idx++)
|
// for(idx=loc; idx<= loc+1; idx++)
|
// b[loc][idx] = loc;
|
// b[loc][idx] = loc;
|
// b[loc][loc-1] += 1;
|
// b[loc][loc-1] += 1;
|
// b[loc+20][loc] = a[loc];
|
// b[loc+20][loc] = a[loc];
|
// gbl_int = 5;
|
// gbl_int = 5;
|
//}
|
//}
|
proc_8:
|
proc_8:
|
; R0 = a
|
; R0 = a
|
; R1 = b
|
; R1 = b
|
; R2 = c
|
; R2 = c
|
; R3 = d
|
; R3 = d
|
; R4 - unassigned
|
; R4 - unassigned
|
; Makes no function/procedure calls, so these can keep
|
; Makes no function/procedure calls, so these can keep
|
; R2 = loc = c+5, replaces c
|
; R2 = loc = c+5, replaces c
|
; R4 = idx
|
; R4 = idx
|
SUB 2,SP
|
SUB 3,SP
|
|
STO R4,(SP)
|
STO R5,1(SP)
|
STO R5,1(SP)
|
STO R6,2(SP)
|
STO R6,2(SP)
|
|
|
ADD 5,R2 ; loc = c+5
|
ADD 5,R2 ; loc = c+5
|
MOV R0,R5
|
MOV R0,R5
|
ADD R2,R5
|
ADD R2,R5
|
STO R3,(R5)
|
STO R3,(R5)
|
STO R3,1(R5)
|
STO R3,1(R5)
|
STO R2,30(R5)
|
STO R2,30(R5)
|
MOV R2,R5
|
MOV R2,R5
|
MPYU 50,R5 ; R5 = 50 * R2 = 50 * loc
|
MPYU 50,R5 ; R5 = 50 * R2 = 50 * loc
|
ADD R1,R5 ; R5 = &b[loc][0]
|
ADD R1,R5 ; R5 = &b[loc][0]
|
MOV R5,R6 ; R6 = &b[loc][0]
|
MOV R5,R6 ; R6 = &b[loc][0]
|
ADD R2,R5 ; R5 = &b[loc][loc]
|
ADD R2,R5 ; R5 = &b[loc][loc]
|
MOV R2,R4 ; R4 = loc = index
|
MOV R2,R4 ; R4 = loc = index
|
proc_8_top_of_loop:
|
proc_8_top_of_loop:
|
CMP 1(R2),R4
|
CMP 1(R2),R4
|
BGT proc_8_end_of_loop
|
BGT proc_8_end_of_loop
|
proc_8_loop_after_condition:
|
proc_8_loop_after_condition:
|
STO R2,(R5)
|
STO R2,(R5)
|
ADD 1,R5
|
ADD 1,R5
|
ADD 1,R4
|
ADD 1,R4
|
CMP 2(R2),R4
|
CMP 2(R2),R4
|
BLT proc_8_loop_after_condition
|
BLT proc_8_loop_after_condition
|
proc_8_end_of_loop:
|
proc_8_end_of_loop:
|
|
|
; b[loc][loc-1] += 1
|
; b[loc][loc-1] += 1
|
ADD R2,R6 ; R6 = &b[loc][loc]
|
ADD R2,R6 ; R6 = &b[loc][loc]
|
LOD -1(R6),R5
|
LOD -1(R6),R5
|
ADD 1,R5
|
ADD 1,R5
|
STO R5,-1(R6)
|
STO R5,-1(R6)
|
; b[loc+20][loc] = a[loc]
|
; b[loc+20][loc] = a[loc]
|
MOV R0,R4
|
MOV R0,R4
|
ADD R2,R4
|
ADD R2,R4
|
LOD (R4),R3
|
LOD (R4),R3
|
STO R3,20*50(R6)
|
STO R3,20*50(R6)
|
LDI 5,R3
|
LDI 5,R3
|
STO R3,gbl_int(R12)
|
STO R3,gbl_int(R12)
|
|
|
|
LOD (SP),R4
|
LOD 1(SP),R5
|
LOD 1(SP),R5
|
LOD 2(SP),R6
|
LOD 2(SP),R6
|
ADD 2,SP
|
ADD 3,SP
|
RETN
|
JMP R4
|
|
|
// void proc_5(void) {
|
// void proc_5(void) {
|
// gbl_ch = 'A';
|
// gbl_ch = 'A';
|
// gbl_bool = false;
|
// gbl_bool = false;
|
//}
|
//}
|
#ifdef NO_INLINE
|
#ifdef NO_INLINE
|
proc_5:
|
proc_5:
|
|
SUB 1,SP
|
|
STO R0,(SP)
|
|
;
|
LDI 'A',R0
|
LDI 'A',R0
|
STO R0,gbl_ch(R12)
|
STO R0,gbl_ch(R12)
|
CLR R0
|
CLR R0
|
STO R0,gbl_bool(R12)
|
STO R0,gbl_bool(R12)
|
;
|
;
|
RETN
|
LOD (SP),R0
|
|
ADD 1,SP
|
|
JMP R0
|
#endif
|
#endif
|
|
|
// void proc_4(void) {
|
// void proc_4(void) {
|
// bool lcl_bool;
|
// bool lcl_bool;
|
// lcl_bool = (gbl_ch == 'A');
|
// lcl_bool = (gbl_ch == 'A');
|
// gbl_ch_2 = 'B';
|
// gbl_ch_2 = 'B';
|
// }
|
// }
|
#ifdef NO_INLINE
|
#ifdef NO_INLINE
|
proc_4:
|
proc_4:
|
//
|
//
|
; LDI GBL,R12 // Already in R12
|
; LDI GBL,R12 // Already in R12
|
; Setting lcl_bool is irrelevant, so the optimizer should remove it.
|
; 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
|
; R0 doesn't need to be saved, since it's already trashed by the
|
; subroutine call.
|
; subroutine call.
|
;
|
;
|
; LOD gbl_ch(R12),R0
|
; LOD gbl_ch(R12),R0
|
; CLR R1
|
; CLR R1
|
; CMP 'A',R0
|
; CMP 'A',R0
|
; ADD.Z 1,R1
|
; ADD.Z 1,R1
|
;
|
;
|
|
SUB 1,SP
|
|
STO R0,(SP)
|
|
;
|
LDI 'B',R0
|
LDI 'B',R0
|
STO R0,gbl_ch_2(R12)
|
STO R0,gbl_ch_2(R12)
|
;
|
;
|
RETN
|
LOD (SP),R0
|
|
ADD 1,SP
|
|
JMP R0
|
#endif
|
#endif
|
|
|
// void proc_3(RECP *a) {
|
// void proc_3(RECP *a) {
|
// if (gbl_ptr != NULL)
|
// if (gbl_ptr != NULL)
|
// *a = gbl_ptr->ptr_comp;
|
// *a = gbl_ptr->ptr_comp;
|
// proc_7(10,gbl_int, &gbl_ptr->variant.var_1.int_comp); // ??
|
// proc_7(10,gbl_int, &gbl_ptr->variant.var_1.int_comp); // ??
|
//}
|
//}
|
proc_3:
|
proc_3:
|
SUB 3,SP
|
SUB 3,SP
|
|
STO R1,(SP)
|
|
STO R2,1(SP)
|
STO R3,2(SP)
|
STO R3,2(SP)
|
STO R2,3(SP)
|
|
; Save one for the return address from our JSR "instruction"
|
|
;
|
;
|
LOD gbl_ptr(R12),R2
|
LOD gbl_ptr(R12),R2
|
TST -1,R2
|
TST -1,R2
|
#ifndef SKIP_SHORT_CIRCUITS
|
#ifndef SKIP_SHORT_CIRCUITS
|
BUSY.Z
|
BUSY.Z
|
#endif
|
#endif
|
LOD.NZ ptr_comp(R2),R3
|
LOD.NZ ptr_comp(R2),R3
|
STO.NZ R3,(R0)
|
STO.NZ R3,(R0)
|
#ifdef NO_INLINE
|
#ifdef NO_INLINE
|
LDI 10,R0
|
LDI 10,R0
|
LOD gbl_int(R12),R1
|
LOD gbl_int(R12),R1
|
MOV variant.var_1.int_comp(R2),R2
|
MOV variant.var_1.int_comp(R2),R2
|
MOV __HERE__+3(PC),R3
|
MOV __HERE__+2(PC),R3
|
STO R3,1(SP)
|
|
BRA proc_7
|
BRA proc_7
|
#else
|
#else
|
LOD gbl_int(R12),R1
|
LOD gbl_int(R12),R1
|
ADD 12,R1
|
ADD 12,R1
|
STO R1,variant.var_1.int_comp(R2)
|
STO R1,variant.var_1.int_comp(R2)
|
#endif
|
#endif
|
;
|
;
|
|
LOD (SP),R1
|
|
LOD 1(SP),R2
|
LOD 2(SP),R3
|
LOD 2(SP),R3
|
LOD 3(SP),R2
|
|
ADD 3,SP
|
ADD 3,SP
|
RETN
|
JMP R1
|
|
NOP
|
|
|
// void proc_2(int *a) {
|
// void proc_2(int *a) {
|
// int lcl_int;
|
// int lcl_int;
|
// test_enum lcl_enum;
|
// test_enum lcl_enum;
|
//
|
//
|
// lcl_int = *a + 10;
|
// lcl_int = *a + 10;
|
// do {
|
// do {
|
// if (gbl_ch == 'A') {
|
// if (gbl_ch == 'A') {
|
// lcl_int -= 1;
|
// lcl_int -= 1;
|
// *a = lcl_int - gbl_int;
|
// *a = lcl_int - gbl_int;
|
// lcl_enum = Ident_1;
|
// lcl_enum = Ident_1;
|
// }
|
// }
|
// } while(lcl_enum != Ident_1);
|
// } while(lcl_enum != Ident_1);
|
//}
|
//}
|
proc_2:
|
proc_2:
|
SUB 5,SP
|
SUB 6,SP
|
STO R6,1(SP)
|
STO R1,(SP)
|
STO R5,2(SP)
|
STO R2,1(SP)
|
|
STO R3,2(SP)
|
STO R4,3(SP)
|
STO R4,3(SP)
|
STO R3,4(SP)
|
STO R5,4(SP)
|
STO R2,5(SP)
|
STO R6,5(SP)
|
// R1 doesn't need to be stored, it was used in the subroutine
|
// R1 doesn't need to be stored, it was used in the subroutine
|
// call calculation
|
// call calculation
|
|
|
LOD (R0),R1
|
LOD (R0),R1
|
MOV 10(R1),R2 ; R2 = lcl_int
|
MOV 10(R1),R2 ; R2 = lcl_int
|
LOD gbl_ch(R12),R4 ; R4 = gbl_ch
|
LOD gbl_ch(R12),R4 ; R4 = gbl_ch
|
#ifdef NO_CHEATING
|
#ifdef NO_CHEATING
|
proc_2_loop:
|
proc_2_loop:
|
CMP 'A',R4
|
CMP 'A',R4
|
SUB.Z 1,R2
|
SUB.Z 1,R2
|
LOD.Z gbl_int(R12),R5 ; R5 = gbl_int
|
LOD.Z gbl_int(R12),R5 ; R5 = gbl_int
|
MOV.Z R2,R6 ; R6 = lcl_int
|
MOV.Z R2,R6 ; R6 = lcl_int
|
SUB.Z R5,R6 ; lcl_int - gbl_int
|
SUB.Z R5,R6 ; lcl_int - gbl_int
|
STO.Z R6,(R0) ; *a = R6
|
STO.Z R6,(R0) ; *a = R6
|
CLR.Z R3 ; lcl_enum = 0
|
CLR.Z R3 ; lcl_enum = 0
|
// #ifndef SKIP_SHORT_CIRCUITS
|
// #ifndef SKIP_SHORT_CIRCUITS
|
// BUSY.NZ
|
// BUSY.NZ
|
// #endif
|
// #endif
|
|
|
TST -1,R3
|
TST -1,R3
|
// #ifndef SKIP_SHORT_CIRCUITS
|
// #ifndef SKIP_SHORT_CIRCUITS
|
// BUSY.NZ
|
// BUSY.NZ
|
// #endif
|
// #endif
|
BNZ proc_2_loop
|
BNZ proc_2_loop
|
#else
|
#else
|
LOD gbl_int(R12),R5
|
LOD gbl_int(R12),R5
|
SUB 1(R5),R2
|
SUB 1(R5),R2
|
STO R2,(R0)
|
STO R2,(R0)
|
#endif
|
#endif
|
;
|
;
|
LOD 1(SP),R6
|
LOD (SP),R1
|
LOD 2(SP),R5
|
LOD 1(SP),R2
|
|
LOD 2(SP),R3
|
LOD 3(SP),R4
|
LOD 3(SP),R4
|
LOD 4(SP),R3
|
LOD 4(SP),R5
|
LOD 5(SP),R2
|
LOD 5(SP),R6
|
ADD 5,SP
|
ADD 6,SP
|
RETN
|
JMP R1
|
|
NOP
|
|
|
//void proc_1 (RECP a) {
|
//void proc_1 (RECP a) {
|
// RECP nxt = a->ptr_comp;
|
// RECP nxt = a->ptr_comp;
|
//
|
//
|
// // structassign(a->ptr_comp, gbl_ptr);
|
// // structassign(a->ptr_comp, gbl_ptr);
|
// *(a->ptr_comp) = *(gbl_ptr);
|
// *(a->ptr_comp) = *(gbl_ptr);
|
//
|
//
|
// a->variant.var_1.int_comp = 5;
|
// a->variant.var_1.int_comp = 5;
|
// nxt->variant.var_1.int_comp = a->variant.var_1.int_comp;
|
// nxt->variant.var_1.int_comp = a->variant.var_1.int_comp;
|
// proc_3(&nxt->ptr_comp);
|
// proc_3(&nxt->ptr_comp);
|
//
|
//
|
// if (nxt->discr == 0) {
|
// if (nxt->discr == 0) {
|
// nxt->variant.var_1.int_comp = 6;
|
// nxt->variant.var_1.int_comp = 6;
|
// proc_6(a->variant.var_1.enum_comp, &nxt->variant.var_1.enum_comp);
|
// proc_6(a->variant.var_1.enum_comp, &nxt->variant.var_1.enum_comp);
|
// nxt->ptr_comp = gbl_ptr->ptr_comp;
|
// nxt->ptr_comp = gbl_ptr->ptr_comp;
|
// proc_7(nxt->variant.var_1.int_comp, 10, &nxt->variant.var_1.int_comp);
|
// proc_7(nxt->variant.var_1.int_comp, 10, &nxt->variant.var_1.int_comp);
|
// } else
|
// } else
|
// // structassign(a, a->ptr_comp);
|
// // structassign(a, a->ptr_comp);
|
// *a = *(a->ptr_comp);
|
// *a = *(a->ptr_comp);
|
//}
|
//}
|
proc_1:
|
proc_1:
|
SUB 9,SP
|
SUB 11,SP
|
STO R2,2(SP)
|
STO R1,(SP)
|
STO R3,3(SP)
|
STO R2,1(SP)
|
STO R4,4(SP)
|
STO R3,2(SP)
|
STO R5,5(SP)
|
STO R4,3(SP)
|
STO R6,6(SP)
|
STO R5,4(SP)
|
STO R7,7(SP)
|
STO R6,5(SP)
|
STO R8,8(SP)
|
STO R7,6(SP)
|
STO R9,9(SP)
|
STO R8,7(SP)
|
|
STO R9,8(SP)
|
|
#ifndef NO_LOOP_UNROLLING
|
|
STO R10,9(SP)
|
|
STO R11,10(SP)
|
|
#endif
|
|
|
; R9 = a
|
; R9 = a
|
; R4 = nxt
|
; R4 = nxt
|
; R12 = GBL
|
; R12 = GBL
|
; R13 = SP
|
; R13 = SP
|
MOV R0,R9
|
MOV R0,R9
|
LOD ptr_comp(R9),R4
|
LOD ptr_comp(R9),R4
|
#ifndef SKIP_SHORT_CIRCUITS
|
#ifndef SKIP_SHORT_CIRCUITS
|
TST -1,R4
|
TST -1,R4
|
BUSY.Z
|
BUSY.Z
|
|
CMP PC,R9
|
|
BUSY.LT
|
#endif
|
#endif
|
LDI 35,R5
|
|
MOV R9,R6
|
MOV R9,R6
|
LOD gbl_ptr(R12),R7
|
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:
|
proc_1_assign_loop_1:
|
LOD (R6),R8
|
LOD (R6),R8
|
ADD 1,R6
|
ADD 1,R6
|
STO R8,(R7)
|
STO R8,(R7)
|
ADD 1,R7
|
ADD 1,R7
|
SUB 1,R5
|
SUB 1,R5
|
BNZ proc_1_assign_loop_1;
|
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
|
#ifndef SKIP_SHORT_CIRCUITS
|
LOD gbl_ptr(R12),R2
|
LOD gbl_ptr(R12),R2
|
TST -1,R2
|
TST -1,R2
|
BUSY.Z
|
BUSY.Z
|
|
;
|
|
LOD variant.var_1.enum_comp(R9), R0
|
|
CMP 2,R0
|
|
BUSY.NZ
|
#endif
|
#endif
|
|
|
LDI 5,R5
|
LDI 5,R5
|
STO R5,variant.var_1.int_comp(R9)
|
STO R5,variant.var_1.int_comp(R9)
|
STO R5,variant.var_1.int_comp(R4)
|
STO R5,variant.var_1.int_comp(R4)
|
MOV ptr_comp(R4),R0
|
MOV ptr_comp(R4),R0
|
MOV __HERE__+3(PC),R1
|
MOV __HERE__+2(PC),R1
|
STO R1,1(SP)
|
|
BRA proc_3 ; Uses R0 and R1
|
BRA proc_3 ; Uses R0 and R1
|
|
|
LOD discr(R4),R5
|
LOD discr(R4),R5
|
CMP 0,R5
|
CMP 0,R5
|
BNZ proc_1_last_struct_assign
|
BNZ proc_1_last_struct_assign
|
; This is the juncture that is "supposed" to be taken
|
; This is the juncture that is "supposed" to be taken
|
LDI 6,R5
|
LDI 6,R5
|
|
|
STO R5,variant.var_1.int_comp(R4)
|
STO R5,variant.var_1.int_comp(R4)
|
LOD variant.var_1.enum_comp(R9), R0
|
LOD variant.var_1.enum_comp(R9), R0
|
#ifndef SKIP_SHORT_CIRCUITS
|
#ifndef SKIP_SHORT_CIRCUITS
|
CMP 2,R0
|
CMP 2,R0
|
BUSY.NZ
|
BUSY.NZ
|
#endif
|
#endif
|
MOV variant.var_1.enum_comp+R4, R1
|
MOV variant.var_1.enum_comp+R4, R1
|
MOV __HERE__+3(PC),R2
|
MOV __HERE__+2(PC),R2
|
STO R2,1(SP)
|
|
BRA proc_6
|
BRA proc_6
|
;
|
;
|
LOD gbl_ptr(R12),R5
|
LOD gbl_ptr(R12),R5
|
LOD ptr_comp(R5),R5
|
LOD ptr_comp(R5),R5
|
STO R5,ptr_comp(R4)
|
STO R5,ptr_comp(R4)
|
;
|
;
|
#ifdef NO_INLINE
|
#ifdef NO_INLINE
|
LOD variant.var_1.int_comp(R4),R0
|
LOD variant.var_1.int_comp(R4),R0
|
LDI 10,R1
|
LDI 10,R1
|
MOV variant.var_1.int_comp(R4),R2
|
MOV variant.var_1.int_comp(R4),R2
|
MOV proc_1_return_closeout(PC),R3
|
MOV proc_1_return_closeout(PC),R3
|
STO R3,1(SP)
|
|
BRA proc_7
|
BRA proc_7
|
#else
|
#else
|
LOD variant.var_1.int_comp(R4),R0
|
LOD variant.var_1.int_comp(R4),R0
|
ADD 12,R0
|
ADD 12,R0
|
STO R0,variant.var_1.int_comp(R4)
|
STO R0,variant.var_1.int_comp(R4)
|
BRA proc_1_return_closeout
|
BRA proc_1_return_closeout
|
#endif
|
#endif
|
;
|
;
|
proc_1_last_struct_assign:
|
proc_1_last_struct_assign:
|
#ifndef SKIP_SHORT_CIRCUITS
|
#ifndef SKIP_SHORT_CIRCUITS
|
BUSY
|
BUSY
|
#endif
|
#endif
|
LDI 35,R4
|
LDI 35,R4
|
MOV R2,R5
|
MOV R2,R5
|
LOD gbl_ptr(R12),R6
|
LOD gbl_ptr(R12),R6
|
proc_1_assign_loop_2:
|
proc_1_assign_loop_2:
|
LOD (R6),R8
|
LOD (R6),R8
|
STO R8,(R7)
|
STO R8,(R7)
|
ADD 1,R6
|
ADD 1,R6
|
ADD 1,R7
|
ADD 1,R7
|
SUB 1,R5
|
SUB 1,R5
|
BNZ proc_1_assign_loop_2
|
BNZ proc_1_assign_loop_2
|
//
|
//
|
proc_1_return_closeout:
|
proc_1_return_closeout:
|
//
|
//
|
LOD 2(SP),R2
|
LOD (SP),R1
|
LOD 3(SP),R3
|
LOD 1(SP),R2
|
LOD 4(SP),R4
|
LOD 2(SP),R3
|
LOD 5(SP),R5
|
LOD 3(SP),R4
|
LOD 6(SP),R6
|
LOD 4(SP),R5
|
LOD 7(SP),R7
|
LOD 5(SP),R6
|
LOD 8(SP),R8
|
LOD 6(SP),R7
|
LOD 9(SP),R9
|
LOD 7(SP),R8
|
ADD 9,SP
|
LOD 8(SP),R9
|
RETN
|
#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) {
|
// void dhrystone(void) {
|
// int lcl_int_1, lcl_int_2, lcl_int_3, index, number_of_runs = 500;
|
// int lcl_int_1, lcl_int_2, lcl_int_3, index, number_of_runs = 500;
|
// test_enum lcl_enum;
|
// test_enum lcl_enum;
|
// char lcl_str_1[30], lcl_str_2[30], ch_index;
|
// char lcl_str_1[30], lcl_str_2[30], ch_index;
|
// REC_T a, b, *nxt = &a;
|
// REC_T a, b, *nxt = &a;
|
//
|
//
|
// gbl_ptr = &b;
|
// gbl_ptr = &b;
|
// gbl_ptr->ptr_comp = nxt;
|
// gbl_ptr->ptr_comp = nxt;
|
// gbl_ptr->variant.var_1.enum_comp = 2;
|
// gbl_ptr->variant.var_1.enum_comp = 2;
|
// gbl_ptr->variant.var_1.int_comp = 40;
|
// gbl_ptr->variant.var_1.int_comp = 40;
|
// lcl_strcpy(gbl_ptr->variant.var_1.str_comp, "DHRYSTONE PROGRAM, SOME STRING");
|
// lcl_strcpy(gbl_ptr->variant.var_1.str_comp, "DHRYSTONE PROGRAM, SOME STRING");
|
// lcl_strcpy(lcl_str_1, "DHRYSTONE PROGRAM, 1\'ST STRING");
|
// lcl_strcpy(lcl_str_1, "DHRYSTONE PROGRAM, 1\'ST STRING");
|
//
|
//
|
// gbl_arr_2[8][7] = 10;
|
// gbl_arr_2[8][7] = 10;
|
//
|
//
|
// for(index=0; index < number_of_runs; index++) {
|
// for(index=0; index < number_of_runs; index++) {
|
// proc_5();
|
// proc_5();
|
// proc_4();
|
// proc_4();
|
// lcl_int_1 = 2;
|
// lcl_int_1 = 2;
|
// lcl_int_2 = 3;
|
// lcl_int_2 = 3;
|
// lcl_strcpy(lcl_str_2, "DHRYSTONE PROGRAM, 2\'ND STRING");
|
// lcl_strcpy(lcl_str_2, "DHRYSTONE PROGRAM, 2\'ND STRING");
|
// lcl_enum = Ident_2;
|
// lcl_enum = Ident_2;
|
// gbl_bool = !func_2(lcl_str_1, lcl_str_2);
|
// gbl_bool = !func_2(lcl_str_1, lcl_str_2);
|
// while(lcl_int_1 < lcl_int_2) {
|
// while(lcl_int_1 < lcl_int_2) {
|
// lcl_int_3 = 5 * 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);
|
// proc_7(lcl_int_1, lcl_int_2, &lcl_int_3);
|
// lcl_int_1 += 1;
|
// lcl_int_1 += 1;
|
// }
|
// }
|
//
|
//
|
// proc_8(gbl_arr_1, gbl_arr_2, lcl_int_1, lcl_int_3);
|
// proc_8(gbl_arr_1, gbl_arr_2, lcl_int_1, lcl_int_3);
|
// proc_1(gbl_ptr);
|
// proc_1(gbl_ptr);
|
//
|
//
|
// for(ch_index='A'; ch_index <= gbl_ch_2; ch_index++) {
|
// for(ch_index='A'; ch_index <= gbl_ch_2; ch_index++) {
|
// if (lcl_enum == func_1(ch_index, 'C')) {
|
// if (lcl_enum == func_1(ch_index, 'C')) {
|
// // Then not executed??
|
// // Then not executed??
|
// proc_6(0, &lcl_enum);
|
// proc_6(0, &lcl_enum);
|
// lcl_strcpy(lcl_str_2, "DHRYSTONE PROGRAM, 3\'RD STRING");
|
// lcl_strcpy(lcl_str_2, "DHRYSTONE PROGRAM, 3\'RD STRING");
|
// lcl_int_2 = index;
|
// lcl_int_2 = index;
|
// gbl_int = index;
|
// gbl_int = index;
|
// }
|
// }
|
// }
|
// }
|
//
|
//
|
// lcl_int_2 = lcl_int_2 * lcl_int_1;
|
// lcl_int_2 = lcl_int_2 * lcl_int_1;
|
// lcl_int_1 = lcl_int_2 / lcl_int_3;
|
// lcl_int_1 = lcl_int_2 / lcl_int_3;
|
// lcl_int_2 = 7 * ( lcl_int_2 - lcl_int_3) - lcl_int_1;
|
// lcl_int_2 = 7 * ( lcl_int_2 - lcl_int_3) - lcl_int_1;
|
// proc_2(&lcl_int_1);
|
// proc_2(&lcl_int_1);
|
// }
|
// }
|
//}
|
//}
|
|
|
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:
|
dhrystone:
|
#ifdef SUPERVISOR_TASK
|
#ifdef SUPERVISOR_TASK
|
SUB 12+RECSIZE+RECSIZE+30+30+3,SP
|
SUB 12+RECSIZE+RECSIZE+30+30+3,SP
|
; Leave a space on the top of the stack for calling
|
; Leave a space on the top of the stack for calling
|
; subroutines.
|
; subroutines.
|
STO R1,2(SP)
|
STO R0,(SP)
|
STO R2,3(SP)
|
STO R1,1(SP)
|
STO R3,4(SP)
|
STO R2,2(SP)
|
STO R4,5(SP)
|
STO R3,3(SP)
|
STO R5,6(SP)
|
STO R4,4(SP)
|
STO R6,7(SP)
|
STO R5,5(SP)
|
STO R7,8(SP)
|
STO R6,6(SP)
|
STO R8,9(SP)
|
STO R7,7(SP)
|
STO R9,10(SP)
|
STO R8,8(SP)
|
STO R10,11(SP)
|
STO R9,9(SP)
|
STO R11,12(SP)
|
STO R10,10(SP)
|
|
STO R11,11(SP)
|
lcl_int_1 equ 12 ; plus SP
|
lcl_int_1 equ 12 ; plus SP
|
#else
|
#else
|
lcl_int_1 equ 2 ; plus SP
|
lcl_int_1 equ 2 ; plus SP
|
SUB 2+RECSIZE+RECSIZE+30+30+3,SP
|
SUB 2+RECSIZE+RECSIZE+30+30+3,SP
|
#endif
|
#endif
|
// 12 is the global variable pointer
|
// 12 is the global variable pointer
|
// 13 is our stack
|
// 13 is our stack
|
// 14 is our condition code register
|
// 14 is our condition code register
|
// 15 is the program counter
|
// 15 is the program counter
|
;
|
;
|
lcl_int_3 equ lcl_int_1+1 ; plus SP
|
lcl_int_3 equ lcl_int_1+1 ; plus SP
|
lcl_enum equ lcl_int_3+1 ; plus SP
|
lcl_enum equ lcl_int_3+1 ; plus SP
|
lcl_str_1 equ lcl_enum+1 ; plus SP
|
lcl_str_1 equ lcl_enum+1 ; plus SP
|
lcl_str_2 equ lcl_str_1+30 ; plus SP
|
lcl_str_2 equ lcl_str_1+30 ; plus SP
|
rec_a equ lcl_str_2+30 ; plus SP
|
rec_a equ lcl_str_2+30 ; plus SP
|
rec_b equ rec_a+RECSIZE ; 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;
|
// int lcl_int_1, lcl_int_2, lcl_int_3, index, number_of_runs = 500;
|
// test_enum lcl_enum;
|
// test_enum lcl_enum;
|
// char lcl_str_1[30], lcl_str_2[30], ch_index;
|
// char lcl_str_1[30], lcl_str_2[30], ch_index;
|
// REC_T a, b, *nxt = &a;
|
// REC_T a, b, *nxt = &a;
|
//
|
//
|
// gbl_ptr = &b;
|
// gbl_ptr = &b;
|
MOV rec_b(SP),R0 ; R0 = &b
|
MOV rec_b(SP),R0 ; R0 = &b
|
STO R0,gbl_ptr(PC)
|
STO R0,gbl_ptr(PC)
|
// gbl_ptr->ptr_comp = nxt;
|
// gbl_ptr->ptr_comp = nxt;
|
MOV rec_a(SP),R1 ; R1 = &a = nxt
|
MOV rec_a(SP),R1 ; R1 = &a = nxt
|
STO R1,ptr_comp(R0) ; gbp_ptr->ptr.comp=b->ptr.comp=R1=nxt
|
STO R1,ptr_comp(R0) ; gbp_ptr->ptr.comp=b->ptr.comp=R1=nxt
|
// gbl_ptr->variant.var_1.enum_comp = 2;
|
// gbl_ptr->variant.var_1.enum_comp = 2;
|
LDI 2,R2
|
LDI 2,R2
|
STO R2,variant.var_1.enum_comp(R0)
|
STO R2,variant.var_1.enum_comp(R0)
|
// gbl_ptr->variant.var_1.int_comp = 40;
|
// gbl_ptr->variant.var_1.int_comp = 40;
|
LDI 40,R2
|
LDI 40,R2
|
STO R2,variant.var_1.int_comp(R0)
|
STO R2,variant.var_1.int_comp(R0)
|
// lcl_strcpy(gbl_ptr->variant.var_1.str_comp, "DHRYSTONE PROGRAM, SOME STRING");
|
// lcl_strcpy(gbl_ptr->variant.var_1.str_comp, "DHRYSTONE PROGRAM, SOME STRING");
|
MOV variant.var_1.str_comp(R0),R0
|
MOV variant.var_1.str_comp(R0),R0
|
MOV some_string(PC),R1
|
MOV some_string(PC),R1
|
MOV __HERE__+3(PC),R2
|
MOV __HERE__+2(PC),R2
|
STO R2,1(SP)
|
|
BRA lcl_strcpy
|
BRA lcl_strcpy
|
|
|
// lcl_strcpy(lcl_str_1, "DHRYSTONE PROGRAM, 1\'ST STRING");
|
// lcl_strcpy(lcl_str_1, "DHRYSTONE PROGRAM, 1\'ST STRING");
|
MOV lcl_str_1(SP),R0
|
MOV lcl_str_1(SP),R0
|
MOV first_string(PC),R1
|
MOV first_string(PC),R1
|
MOV __HERE__+3(PC),R2
|
MOV __HERE__+2(PC),R2
|
STO R2,1(SP)
|
|
BRA lcl_strcpy
|
BRA lcl_strcpy
|
|
|
// gbl_arr_2[8][7] = 10;
|
// gbl_arr_2[8][7] = 10;
|
LDI 10,R0
|
LDI 10,R0
|
STO R0,8*50+7+gbl_arr_2(R12)
|
STO R0,8*50+7+gbl_arr_2(R12)
|
//
|
//
|
// for(index=0; index < number_of_runs; index++) {
|
// for(index=0; index < number_of_runs; index++) {
|
; Let R11 be our index
|
; Let R11 be our index
|
CLR R11
|
CLR R11
|
dhrystone_main_loop:
|
dhrystone_main_loop:
|
;; Start of Dhrystone main loop
|
;; Start of Dhrystone main loop
|
; proc_5();
|
; proc_5();
|
#ifdef NO_INLINE
|
#ifdef NO_INLINE
|
MOV __HERE__+3(PC),R0
|
MOV __HERE__+2(PC),R0
|
STO R0,1(SP)
|
|
BRA proc_5
|
BRA proc_5
|
#else
|
#else
|
LDI 'A',R0
|
LDI 'A',R0
|
STO R0,gbl_ch(R12)
|
STO R0,gbl_ch(R12)
|
CLR R0
|
CLR R0
|
STO R0,gbl_bool(R12)
|
STO R0,gbl_bool(R12)
|
#endif
|
#endif
|
; proc_4();
|
; proc_4();
|
#ifdef NO_INLINE
|
#ifdef NO_INLINE
|
MOV __HERE__+3(PC),R0
|
MOV __HERE__+2(PC),R0
|
STO R0,1(SP)
|
|
BRA proc_4
|
BRA proc_4
|
#else
|
#else
|
LDI 'B',R0
|
LDI 'B',R0
|
STO R0,gbl_ch_2(R12)
|
STO R0,gbl_ch_2(R12)
|
#endif
|
#endif
|
// lcl_int_1 = 2;
|
// lcl_int_1 = 2;
|
LDI 2,R5
|
LDI 2,R5
|
STO R5,lcl_int_1(SP)
|
STO R5,lcl_int_1(SP)
|
// lcl_int_2 = 3;
|
// lcl_int_2 = 3;
|
LDI 3,R6
|
LDI 3,R6
|
// lcl_strcpy(lcl_str_2, "DHRYSTONE PROGRAM, 2\'ND STRING");
|
// lcl_strcpy(lcl_str_2, "DHRYSTONE PROGRAM, 2\'ND STRING");
|
MOV lcl_str_2(SP),R0
|
MOV lcl_str_2(SP),R0
|
MOV second_string(PC),R1
|
MOV second_string(PC),R1
|
MOV __HERE__+3(PC),R2
|
MOV __HERE__+2(PC),R2
|
STO R2,1(SP)
|
|
BRA lcl_strcpy
|
BRA lcl_strcpy
|
// lcl_enum = Ident_2;
|
// lcl_enum = Ident_2;
|
LDI 2,R0
|
LDI 2,R0
|
STO R0,lcl_enum(SP)
|
STO R0,lcl_enum(SP)
|
// gbl_bool = !func_2(lcl_str_1, lcl_str_2);
|
// gbl_bool = !func_2(lcl_str_1, lcl_str_2);
|
MOV lcl_str_1(SP),R0
|
MOV lcl_str_1(SP),R0
|
MOV lcl_str_2(SP),R1
|
MOV lcl_str_2(SP),R1
|
MOV __HERE__+3(PC),R2
|
MOV __HERE__+2(PC),R2
|
STO R2,1(SP)
|
|
BRA func_2
|
BRA func_2
|
CLR R1
|
CLR R1
|
TST -1,R0
|
TST -1,R0
|
LDILO.Z 1,R1
|
LDILO.Z 1,R1
|
STO R1,gbl_bool(PC)
|
STO R1,gbl_bool(PC)
|
|
|
// while(lcl_int_1 < lcl_int_2) {
|
// while(lcl_int_1 < lcl_int_2) {
|
; R5 = lcl_int_1 = 2 on entry
|
; R5 = lcl_int_1 = 2 on entry
|
; R6 = lcl_int_2 = 3 on entry, so no entry test is required
|
; R6 = lcl_int_2 = 3 on entry, so no entry test is required
|
LOD lcl_int_1(SP),R5
|
LOD lcl_int_1(SP),R5
|
// The 'while' comparison
|
// The 'while' comparison
|
CMP R6,R5
|
CMP R6,R5
|
BGE dhrystone_end_while_loop
|
BGE dhrystone_end_while_loop
|
dhrystone_while_loop:
|
dhrystone_while_loop:
|
// lcl_int_3 = 5 * lcl_int_1 - lcl_int_2;
|
// lcl_int_3 = 5 * lcl_int_1 - lcl_int_2;
|
MOV R5,R7
|
MOV R5,R7
|
MPYS 5,R7
|
MPYS 5,R7
|
SUB R6,R7
|
SUB R6,R7
|
STO R7,lcl_int_3(SP)
|
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);
|
// proc_7(lcl_int_1, lcl_int_2, &lcl_int_3);
|
#ifdef NO_INLINE
|
#ifdef NO_INLINE
|
MOV R5,R0
|
MOV R5,R0
|
MOV R6,R1
|
MOV R6,R1
|
MOV lcl_int_3(SP),R2
|
MOV lcl_int_3(SP),R2
|
MOV __HERE__+3(PC),R3
|
MOV __HERE__+2(PC),R3
|
STO R3,1(SP)
|
|
BRA proc_7
|
BRA proc_7
|
#else
|
#else
|
MOV R6,R1
|
MOV R6,R1
|
ADD 2+R5,R1
|
ADD 2+R5,R1
|
STO R1,lcl_int_3(SP)
|
STO R1,lcl_int_3(SP)
|
#endif
|
#endif
|
// lcl_int_1 += 1;
|
// lcl_int_1 += 1;
|
LOD lcl_int_1(SP),R5
|
LOD lcl_int_1(SP),R5
|
ADD 1,R5
|
ADD 1,R5
|
STO R5,lcl_int_1(SP)
|
STO R5,lcl_int_1(SP)
|
;
|
;
|
; BRA dhrystone_while_loop ; We'll unroll the loop, and put an
|
; BRA dhrystone_while_loop ; We'll unroll the loop, and put an
|
CMP R6,R5 ; additional comparison at the bottom
|
CMP R6,R5 ; additional comparison at the bottom
|
BLT dhrystone_while_loop
|
BLT dhrystone_while_loop
|
dhrystone_end_while_loop:
|
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);
|
// proc_8(gbl_arr_1, gbl_arr_2, lcl_int_1, lcl_int_3);
|
MOV gbl_arr_1(PC),R0
|
MOV gbl_arr_1(PC),R0
|
MOV gbl_arr_2(PC),R1
|
MOV gbl_arr_2(PC),R1
|
MOV R5,R2
|
MOV R5,R2
|
MOV R6,R3
|
MOV R6,R3
|
MOV __HERE__+3(PC),R4
|
MOV __HERE__+2(PC),R4
|
STO R4,1(SP)
|
|
BRA proc_8
|
BRA proc_8
|
// proc_1(gbl_ptr);
|
// proc_1(gbl_ptr);
|
LOD gbl_ptr(PC),R0
|
LOD gbl_ptr(PC),R0
|
MOV __HERE__+3(PC),R2
|
MOV __HERE__+2(PC),R1
|
STO R2,1(SP)
|
|
BRA proc_1
|
BRA proc_1
|
//
|
//
|
// for(ch_index='A'; ch_index <= gbl_ch_2; ch_index++) {
|
// for(ch_index='A'; ch_index <= gbl_ch_2; ch_index++) {
|
LDI 'A',R7
|
LDI 'A',R7
|
LOD gbl_ch_2(SP),R8
|
LOD gbl_ch_2(SP),R8
|
CMP R7,R8
|
CMP R7,R8
|
BLT dhrystone_end_of_for_loop
|
BLT dhrystone_end_of_for_loop
|
dhrystone_top_of_for_loop:
|
dhrystone_top_of_for_loop:
|
// if (lcl_enum == func_1(ch_index, 'C')) {
|
// if (lcl_enum == func_1(ch_index, 'C')) {
|
#ifdef NO_INLINE
|
#ifdef NO_INLINE
|
MOV R7,R0
|
MOV R7,R0
|
LDI 'C',R1
|
LDI 'C',R1
|
MOV __HERE__+3(PC),R2
|
MOV __HERE__+2(PC),R2
|
STO R2,1(SP)
|
|
BRA func_1
|
BRA func_1
|
#else
|
#else
|
CMP 'C',R7
|
CMP 'C',R7
|
CLR.NZ R0
|
CLR.NZ R0
|
STO.Z R7,gbl_ch(R12)
|
STO.Z R7,gbl_ch(R12)
|
LDILO.Z 1,R0
|
LDILO.Z 1,R0
|
#endif
|
#endif
|
|
|
; Result is now in R0
|
; Result is now in R0
|
LOD lcl_enum(SP),R1
|
LOD lcl_enum(SP),R1
|
CMP R0,R1
|
CMP R0,R1
|
BNZ dhrystone_skip_then_clause
|
BNZ dhrystone_skip_then_clause
|
// // Then not executed??
|
// // Then not executed??
|
// proc_6(0, &lcl_enum);
|
// proc_6(0, &lcl_enum);
|
|
|
#ifndef SKIP_SHORT_CIRCUITS
|
#ifndef SKIP_SHORT_CIRCUITS
|
BUSY
|
BUSY // Shouldn't ever get here
|
#endif
|
#endif
|
|
|
CLR R0
|
CLR R0
|
MOV lcl_enum(SP),R1
|
MOV lcl_enum(SP),R1
|
MOV __HERE__+3(PC),R2
|
MOV __HERE__+2(PC),R2
|
STO R2,1(SP)
|
|
BRA proc_6
|
BRA proc_6
|
|
|
// lcl_strcpy(lcl_str_2, "DHRYSTONE PROGRAM, 3\'RD STRING");
|
// lcl_strcpy(lcl_str_2, "DHRYSTONE PROGRAM, 3\'RD STRING");
|
MOV lcl_str_2(SP),R0
|
MOV lcl_str_2(SP),R0
|
MOV third_string(PC),R1
|
MOV third_string(PC),R1
|
MOV __HERE__+3(PC),R2
|
MOV __HERE__+2(PC),R2
|
STO R2,1(SP)
|
|
BRA lcl_strcpy
|
BRA lcl_strcpy
|
// lcl_int_2 = index;
|
// lcl_int_2 = index;
|
MOV R11,R6
|
MOV R11,R6
|
// gbl_int = index;
|
// gbl_int = index;
|
STO R11,gbl_int(PC)
|
STO R11,gbl_int(PC)
|
// }
|
// }
|
dhrystone_skip_then_clause:
|
dhrystone_skip_then_clause:
|
ADD 1,R7
|
ADD 1,R7
|
LOD gbl_ch_2(SP),R8
|
LOD gbl_ch_2(SP),R8
|
CMP R8,R7
|
CMP R8,R7
|
BGE dhrystone_top_of_for_loop
|
BGE dhrystone_top_of_for_loop
|
dhrystone_end_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;
|
// lcl_int_2 = lcl_int_2 * lcl_int_1;
|
LOD lcl_int_1(SP),R5
|
LOD lcl_int_1(SP),R5
|
MPYS R5,R6 ; lcl_int_2 =
|
MPYS R5,R6 ; lcl_int_2 =
|
// lcl_int_1 = lcl_int_2 / lcl_int_3;
|
// 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
|
#ifndef SKIP_DIVIDE
|
MOV R6,R0
|
MOV R6,R0
|
LOD lcl_int_3(SP),R1
|
LOD lcl_int_3(SP),R1
|
MOV __HERE__+3(PC),R2
|
MOV __HERE__+2(PC),R2
|
STO R2,1(SP)
|
BRA lib_divs
|
BRA divs
|
|
#else
|
#else
|
LDI 9,R0
|
LDI 9,R0
|
#endif
|
#endif
|
|
#endif
|
STO R0,lcl_int_1(SP)
|
STO R0,lcl_int_1(SP)
|
// lcl_int_2 = 7 * ( lcl_int_2 - lcl_int_3) - lcl_int_1;
|
// lcl_int_2 = 7 * ( lcl_int_2 - lcl_int_3) - lcl_int_1;
|
LOD lcl_int_3(SP),R2
|
LOD lcl_int_3(SP),R2
|
SUB R2,R6
|
SUB R2,R6
|
MPYS 7,R6
|
MPYS 7,R6
|
SUB R0,R6
|
SUB R0,R6
|
// proc_2(&lcl_int_1);
|
// 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 lcl_int_1(SP),R0
|
MOV __HERE__+3(PC),R1
|
MOV __HERE__+2(PC),R1
|
STO R1,1(SP)
|
|
BRA proc_2
|
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
|
;; Bottom of (and return from) Dhrystone main loop
|
ADD 1,R11
|
ADD 1,R11
|
CMP NUMBER_OF_RUNS,R11
|
CMP NUMBER_OF_RUNS,R11
|
BLT dhrystone_main_loop
|
BLT dhrystone_main_loop
|
// }
|
// }
|
|
|
#ifdef SUPERVISOR_TASK
|
#ifdef SUPERVISOR_TASK
|
LOD 2(SP),R1
|
LOD (SP),R0
|
LOD 3(SP),R2
|
LOD 1(SP),R1
|
LOD 4(SP),R3
|
LOD 2(SP),R2
|
LOD 5(SP),R4
|
LOD 3(SP),R3
|
LOD 6(SP),R5
|
LOD 4(SP),R4
|
LOD 7(SP),R6
|
LOD 5(SP),R5
|
LOD 8(SP),R7
|
LOD 6(SP),R6
|
LOD 9(SP),R8
|
LOD 7(SP),R7
|
LOD 10(SP),R9
|
LOD 8(SP),R8
|
LOD 11(SP),R10
|
LOD 9(SP),R9
|
LOD 12(SP),R11
|
LOD 10(SP),R10
|
|
LOD 11(SP),R11
|
;
|
;
|
ADD 12+RECSIZE+RECSIZE+30+30+3,SP
|
ADD 12+RECSIZE+RECSIZE+30+30+3,SP
|
; Return from subroutine
|
; Return from subroutine
|
RETN
|
JMP R0
|
#else
|
#else
|
LDI 0,CC
|
LDI 0,CC
|
NOP
|
NOP
|
NOP
|
NOP
|
BUSY
|
BUSY
|
#endif
|
#endif
|
|
;
|
|
|