OpenCores
URL https://opencores.org/ocsvn/zipcpu/zipcpu/trunk

Subversion Repositories zipcpu

[/] [zipcpu/] [trunk/] [bench/] [asm/] [zipdhry.S] - Blame information for rev 152

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 50 dgisselq
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;
3
; Filename:     zipdhry.S
4
;
5
; Project:      Zip CPU -- a small, lightweight, RISC CPU soft core
6
;
7
; Purpose:      Zip assembly file for running the Dhrystone benchmark in the
8
;               Zip CPU.
9
;
10 69 dgisselq
;       To calculate a DMIPS value, take the value of R0 upon completion.  This
11
;       is the number of clock ticks used from start to finish (i.e., from
12
;       entrance into user mode to the return to supervisor mode).  Let
13
;       CLKSPD be your clock speed in Hz.  Then:
14
;
15
;       DMIPS = (CLKSPD*NRUNS/R0) / 1757;
16
;
17
;       For my tests, CLKSPD = 100e6 Hz (100 MHz), NRUNS = 512.  Thus,
18
;
19
;       DMIPS = (100e6 * 512) / R0 / 1757
20
;
21
;
22 50 dgisselq
; Creator:      Dan Gisselquist, Ph.D.
23 69 dgisselq
;               Gisselquist Technology, LLC
24 50 dgisselq
;
25
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
26
;
27
; Copyright (C) 2015, Gisselquist Technology, LLC
28
;
29
; This program is free software (firmware): you can redistribute it and/or
30
; modify it under the terms of  the GNU General Public License as published
31
; by the Free Software Foundation, either version 3 of the License, or (at
32
; your option) any later version.
33
;
34
; This program is distributed in the hope that it will be useful, but WITHOUT
35
; ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
36
; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
37
; for more details.
38
;
39
; License:      GPL, v3, as defined and found on www.gnu.org,
40
;               http://www.gnu.org/licenses/gpl.html
41
;
42
;
43
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
44
;
45 41 dgisselq
// Under Verilator:
46 69 dgisselq
//      DMIPS:          30.3    100 MHz (sim)   0.29    // Initial baseline
47
//      DMIPS:          37.5    100 MHz (sim)   0.38    // 20151017
48
//      DMIPS:          38.0    100 MHz (sim)   0.38    // 20151211 (new ISA)
49
//      DMIPS:          40.5    100 MHz (sim)   0.41    // 20151212 (H/W DIV)
50
//      DMIPS:           8.2    100 MHz (sim)   0.08    // 20151104--!pipelined
51
//      DMIPS:          60.1    100 MHz (sim)   0.60    // 20151215 (New PF)
52 74 dgisselq
//      DMIPS:          60.0    100 MHz (sim)   0.60    // 20151226 (BugFix)
53 152 dgisselq
//      DMIPS:                  100 MHz (sim)   0.67    // 20160406 (??)
54
//      DMIPS:                  100 MHz (sim)   0.58    // 20160409 (BugFix)
55 69 dgisselq
// On real hardware:
56
//      DMIPS:          24.7    100 MHz (basys) 0.25    // Initial baseline
57
//      DMIPS:          30.6    100 MHz (basys) 0.31    // 20151017
58 74 dgisselq
//      DMIPS:          48.4    100 MHz (basys) 0.48    // 20151227 (New pf/ISA)
59 57 dgisselq
//
60 69 dgisselq
// (And, under Verilator, if the cache holds the entire 4kW program: 55.1 DMIPS)
61 57 dgisselq
//
62 69 dgisselq
//
63 57 dgisselq
//   with no loop unrolling nor function inlining
64
//      DMIPS:          24.3    100 MHz (sim)   0.24
65
//   with packed strings
66
//      DMIPS:          35.6    100 MHz (sim)   0.36
67
//
68 41 dgisselq
// For comparison:
69 69 dgisselq
//      uBlaze:         230     177 MHz         1.3
70 41 dgisselq
//      LEON3                                   1.4
71
//      NiOS II:        218     185 MHz         1.16
72
//      OpenRisk        250     250 MHz         1.00
73
//      LM32                                    1.14
74
//      ZPU             2.6      50 MHz         0.05
75
//
76
 
77 57 dgisselq
// Some #def's to control compilation.
78
//
79
// SKIP_SHORT_CIRCUITS determines whether or not we do internal testing and
80
// jump to a BUSY instruction on failure for the debugger to pick up.  Skip
81 69 dgisselq
// this for valid testing.  Enable it and see whether or not zipdhry dies mid
82
// process--if it down, you got there--so fix it.
83 57 dgisselq
//
84 69 dgisselq
#define SKIP_SHORT_CIRCUITS
85 57 dgisselq
//
86 69 dgisselq
//
87
//
88 57 dgisselq
// NO_INLINE controls whether or not we inline certain functions.  If you
89
// define this, nothing will be inlined.
90 69 dgisselq
//
91
// I recommend not setting this define.
92
//
93 57 dgisselq
// #define      NO_INLINE
94
//
95 69 dgisselq
//
96
//
97 57 dgisselq
// NO_LOOP_UNROLLING controls loop unrolling.  The default is to unroll loops
98 69 dgisselq
// by a factor of 4x.  By defining this, all loop unrolling is removed.  (Well,
99
// except the pipelined strcpy and strcmp below--those loops are automatically
100
// unrolled as part of being piped.  Undefine those as well and all loops will
101
// be effectively unrolled.
102
//
103
// I recommend not setting this define.
104
//
105 41 dgisselq
// #define      NO_LOOP_UNROLLING
106 57 dgisselq
//
107
//
108 69 dgisselq
//
109
// After building this whole thing and putting it together, I discovered another
110
// means I could use of generating a return statement.  In this case, instead
111
// of LOD -1(SP),PC, I would load the return PC from the stack as part of the
112
// pipelined memory operations, adjust the stack pointer, and jump to the
113
// register address.  It saves clocks because it uses the pipelined memory
114
// operation, but other than that it suffers the same number of stalls.
115
//
116
// Fast returns used to be controlled by a #define.  This has been removed,
117
// and all returns are "fast" by default.
118
//
119
//
120
//
121
//
122
//
123
// SKIP_DIVIDE controlls whether or not we want to calculate the speed of
124
// our processor assuming we had a divide instruction.  If you skip the
125
// divide, it will be as though you had such an instruction.  Otherwise,
126
// leave it in and the test bench will measure how long it takes to run
127
// while including the divide emulation.
128
//
129
// I recommend leaving this undefined, for a more accurate measure.
130
//
131
// #define      SKIP_DIVIDE     // 0xace17/0x50f37 vs 0xbd817/0x57d37
132
//
133
// Thus a divide instruction might raise our score from 37.5 to 41.1, or
134
// from 81 to 87.8--depending on whether or not the cache is loaded or not.
135
//
136
//
137
//
138
//
139
// HARDWARE_DIVIDE is appropriate when the hardware has a divide instruction,
140
// as it will use this divide instruction for the one time a divide is needed.
141
//
142
// I recommended setting this value ... IF the hardware has the divide
143
// instruction built in.
144
//
145
#define HARDWARE_DIVIDE
146
//
147
//
148
// PIPELINED_STRCPY and PIPELINED_STRCMP both have to do with whether or not
149
// the memory accesses of each of these "library" functions are pipelined.
150
// As you may recall, the Zip CPU allows you to pipeline memory accesses
151
// that are all done with the same condition, and that all reference either
152
// the same or increasing addresses.  These one-clock memory access instructions
153
// are ridiculously fast (when available), and we would be foolish not to use
154
// them.  These two defines modify the library functions to use this mode
155
// and to capitalize upon it as much as possible.
156
//
157
// I recommend setting these.
158
//
159
#define PIPELINED_STRCPY
160
#define PIPELINED_STRCMP
161
//
162
//
163 74 dgisselq
        dev.scope.cpu   equ     0x0120
164 41 dgisselq
        sys.ctr.mtask   equ     0xc0000008
165
// int main(int argc, char **argv) {
166
//      dhrystone();
167
// }
168 74 dgisselq
// #define      LOAD_ADDRESS    entry+PC
169
#define LOAD_ADDRESS    lcl_strcpy+PC
170 41 dgisselq
entry:
171 86 dgisselq
        ; LDI   0x0c000010,R0
172
        ; LDI   dev.scope.cpu,R1
173
        ; STO   R0,(R1)
174 74 dgisselq
        ;
175 41 dgisselq
        MOV     top_of_stack(PC),uSP
176
        MOV     entry(PC),uR12
177
        ; Store  our tick counter in R1
178
        LDI     sys.ctr.mtask,R1
179
        ; And start with our counter cleared at zero
180
        CLR     R0
181
        STO     R0,(R1)
182
#ifdef  SUPERVISOR_TASK
183 69 dgisselq
        MOV     __HERE__+2(PC),R0
184 41 dgisselq
        BRA     dhrystone
185
#else
186
        MOV     dhrystone(PC),uPC
187
        RTU
188
#endif
189
        ; Read the tick counter back out
190
        LOD     (R1),R0
191
        HALT    ; Stop the CPU--We're done!!!!!!!
192
 
193 74 dgisselq
//
194 41 dgisselq
// typedef      enum { Ident_1, Ident_2, Ident_3, Ident_4, Ident_5 } test_enum;
195
// typedef      enum { false, true } bool;
196
 
197
// typedef      int     Arr_1_Dim[50];
198
// typedef      int     Arr_2_Dim[50][50];
199
#define RECSIZE 35
200
#define NUMBER_OF_RUNS  (512)
201
        ptr_comp                        equ     0
202
        discr                           equ     1
203
        variant.var_1.enum_comp         equ     2
204
        variant.var_1.int_comp          equ     3
205
        variant.var_1.str_comp          equ     4
206
 
207 69 dgisselq
 
208 41 dgisselq
//char  *lcl_strcpy(char *d, char *s) {
209
//      char    *cpd = d, ch;
210
//
211
//      do{
212
//              *cpd++ = ch = *s++;
213
//      } while(ch);
214
//
215
//}
216
//
217 69 dgisselq
 
218
#ifdef  PIPELINED_STRCPY
219
; On entry,
220
;       R0 = dst
221
;       R1 = src
222
;       R2 = return address
223 41 dgisselq
lcl_strcpy:
224 69 dgisselq
        SUB     4,SP
225
        STO     R2,(SP)
226
        STO     R3,1(SP)
227
        STO     R4,2(SP)
228
        STO     R5,3(SP)
229
 
230
copy_next_char:
231 41 dgisselq
        ; R0 = d
232
        ; R1 = s
233
        ; R3 = ch
234 69 dgisselq
        LOD     (R1),R2
235
        LOD     1(R1),R3
236
        LOD     2(R1),R4
237
        LOD     3(R1),R5
238
 
239
        CMP     0,R2
240
        CMP.NZ  0,R3
241
        CMP.NZ  0,R4
242
        CMP.NZ  0,R5
243
        BZ      end_strcpy
244
 
245
        STO     R2,(R0)
246
        STO     R3,1(R0)
247
        STO     R4,2(R0)
248
        STO     R5,3(R0)
249
 
250
        ADD     4,R1
251
        ADD     4,R0
252
        BRA copy_next_char
253
 
254
end_strcpy:
255
        CMP     0,R2
256
        STO.NZ  R2,(R0)
257
        CMP.NZ  0,R3
258
        STO.NZ  R3,1(R0)
259
        CMP.NZ  0,R4
260 74 dgisselq
        STO.NZ  R4,2(R0)
261 69 dgisselq
        CMP.NZ  0,R5
262 74 dgisselq
        STO.NZ  R5,3(R0)
263 69 dgisselq
 
264
        LOD     (SP),R2
265
        LOD     1(SP),R3
266
        LOD     2(SP),R4
267
        LOD     3(SP),R5
268
        ADD     4,SP
269 74 dgisselq
#ifndef SKIP_SHORT_CIRCUITS
270
        CMP     LOAD_ADDRESS,R2
271
        HALT.LT
272
#endif
273 69 dgisselq
        JMP     R2
274
 
275
#else
276
lcl_strcpy:
277
        ; R0 = d
278
        ; R1 = s
279
        ; R3 = ch
280 57 dgisselq
copy_next_char:
281 69 dgisselq
        SUB     1,SP
282
        STO     R2,(SP)
283 41 dgisselq
#ifdef  NO_LOOP_UNROLLING
284
        LOD     (R1),R2
285
        STO     R2,(R0)
286 57 dgisselq
        CMP     0,R2
287 69 dgisselq
        BZ      lcl_strcpy_end_of_loop
288 41 dgisselq
        ADD     1,R0
289
        ADD     1,R1
290 57 dgisselq
        BRA     copy_next_char
291
 
292 41 dgisselq
#else
293
        LOD     (R1),R2
294 57 dgisselq
        STO     R2,(R0)
295 41 dgisselq
        CMP     0,R2
296 69 dgisselq
        BZ      lcl_strcpy_end_of_loop
297 41 dgisselq
        LOD     1(R1),R2
298 57 dgisselq
        STO     R2,1(R0)
299 41 dgisselq
        CMP     0,R2
300 69 dgisselq
        BZ      lcl_strcpy_end_of_loop
301 41 dgisselq
        LOD     2(R1),R2
302 57 dgisselq
        STO     R2,2(R0)
303 41 dgisselq
        CMP     0,R2
304 69 dgisselq
        BZ      lcl_strcpy_end_of_loop
305 41 dgisselq
        LOD     3(R1),R2
306 57 dgisselq
        STO     R2,3(R0)
307 41 dgisselq
        CMP     0,R2
308 69 dgisselq
        BZ      lcl_strcpy_end_of_loop
309 41 dgisselq
        ADD     4,R0
310
        ADD     4,R1
311 57 dgisselq
        BRA     copy_next_char
312 41 dgisselq
#endif
313 69 dgisselq
lcl_strcpy_end_of_loop:
314
        LOD     (SP),R2
315
        ADD     1,SP
316 74 dgisselq
#ifndef SKIP_SHORT_CIRCUITS
317
        CMP     LOAD_ADDRESS,R2
318
        BUSY.LT
319
#endif
320 69 dgisselq
        JMP     R2
321
#endif
322 41 dgisselq
 
323
//int   lcl_strcmp(char *s1, char *s2) {
324
//      char    a, b;
325
//      do {
326
//              a = *s1++; b = *s2++;
327
//      } while((a)&&(a==b));
328
//
329
//      return a-b;
330
//}
331
 
332 69 dgisselq
#ifdef  PIPELINED_STRCMP
333 41 dgisselq
lcl_strcmp:
334 69 dgisselq
        SUB     8,SP
335
        STO     R2,(SP)
336 41 dgisselq
        STO     R3,1(SP)
337 69 dgisselq
        STO     R4,2(SP)
338
        STO     R5,3(SP)
339
        STO     R6,4(SP)
340
        STO     R7,5(SP)
341
        STO     R8,6(SP)
342
        STO     R9,7(SP)
343 41 dgisselq
 
344
strcmp_top_of_loop:
345 69 dgisselq
        LOD     (R0),R2
346
        LOD     1(R0),R3
347
        LOD     2(R0),R4
348
        LOD     3(R0),R5
349
        ;
350
        LOD     (R1),R6
351
        LOD     1(R1),R7
352
        LOD     2(R1),R8
353
        LOD     3(R1),R9
354
        ;
355 74 dgisselq
        ;
356 69 dgisselq
        CMP     0,R2
357
        CMP.NZ  0,R3
358
        CMP.NZ  0,R4
359
        CMP.NZ  0,R5
360
        BZ      strcmp_end_loop
361
 
362
        CMP     R2,R6
363
        CMP.Z   R3,R7
364
        CMP.Z   R4,R8
365
        CMP.Z   R5,R9
366
        BNZ     strcmp_end_loop
367
 
368
        ADD     4,R0
369
        ADD     4,R1
370
        BRA     strcmp_top_of_loop
371
 
372
strcmp_end_loop:
373
        CMP     0,R2
374
        BZ      final_str_compare
375
        CMP     R2,R6
376
        BNZ     final_str_compare
377
 
378
        MOV     R3,R2
379
        MOV     R7,R6
380
        CMP     0,R2
381
        BZ      final_str_compare
382
        CMP     R2,R6
383
        BNZ     final_str_compare
384
 
385
        MOV     R4,R2
386
        MOV     R8,R6
387
        CMP     0,R2
388
        BZ      final_str_compare
389
        CMP     R2,R6
390
        BNZ     final_str_compare
391
 
392
        MOV     R5,R2
393
        MOV     R9,R6
394
 
395
final_str_compare:
396
        SUB     R6,R2
397
        MOV     R2,R0
398
 
399
        LOD     (SP),R2
400
        LOD     1(SP),R3
401
        LOD     2(SP),R4
402
        LOD     3(SP),R5
403
        LOD     4(SP),R6
404
        LOD     5(SP),R7
405
        LOD     6(SP),R8
406
        LOD     7(SP),R9
407
        ADD     8,SP
408 74 dgisselq
#ifndef SKIP_SHORT_CIRCUITS
409
        CMP     LOAD_ADDRESS,R2
410
        BUSY.LT
411
#endif
412 69 dgisselq
        JMP     R2
413
 
414
#else
415
lcl_strcmp:
416
        SUB     2,SP
417
        STO     R2,(SP)
418
        STO     R3,1(SP)
419
 
420
strcmp_top_of_loop:
421 41 dgisselq
#ifdef  NO_LOOP_UNROLLING
422 57 dgisselq
        ; LOD   (R0),R2
423
        ; LOD   (R1),R3                 ; Alternate approach:
424 41 dgisselq
        ; CMP   R2,R3                   ;       CMP     0,R2
425
        ; BNZ   strcmp_end_loop         ;       BZ      strcmp_end_loop
426
        ; CMP   0,R2                    ;       CMP     R2,R3
427
        ; BZ    strcmp_end_loop         ;       BZ      strcmp_top_of_loop
428
        ; CMP   0,R3                    ;
429
        ; BZ    strcmp_end_loop         ;
430
        ; ADD   1,R0
431
        ; ADD   1,R1
432
        ; BRA   strcmp_top_of_loop
433
        LOD     (R0),R2
434
        LOD     (R1),R3
435
        CMP     0,R2
436
        BZ      strcmp_end_loop
437 57 dgisselq
        ADD     1,R0
438
        ADD     1,R1
439 41 dgisselq
        CMP     R2,R3
440
        BZ      strcmp_top_of_loop
441
#else
442
        LOD     (R0),R2
443
        LOD     (R1),R3
444
        CMP     0,R2
445
        BZ      strcmp_end_loop
446
        CMP     R2,R3
447
        BNZ     strcmp_end_loop
448
        LOD     1(R0),R2
449
        LOD     1(R1),R3
450
        CMP     0,R2
451
        BZ      strcmp_end_loop
452
        CMP     R2,R3
453
        BNZ     strcmp_end_loop
454
        LOD     2(R0),R2
455
        LOD     2(R1),R3
456
        CMP     0,R2
457
        BZ      strcmp_end_loop
458
        CMP     R2,R3
459
        BNZ     strcmp_end_loop
460
        LOD     3(R0),R2
461
        LOD     3(R1),R3
462
        CMP     0,R2
463
        BZ      strcmp_end_loop
464
        CMP     R2,R3
465
        BNZ     strcmp_end_loop
466
        ADD     4,R0
467
        ADD     4,R1
468
        BRA     strcmp_top_of_loop
469
#endif
470
 
471
strcmp_end_loop:
472
        SUB     R3,R2
473
        MOV     R2,R0
474
 
475 69 dgisselq
        LOD     (SP),R2
476 41 dgisselq
        LOD     1(SP),R3
477 69 dgisselq
        ADD     2,SP
478 74 dgisselq
#ifndef SKIP_SHORT_CIRCUITS
479
        CMP     LOAD_ADDRESS,R2
480
        BUSY.LT
481
#endif
482 69 dgisselq
        JMP     R2
483
#endif
484 41 dgisselq
 
485
 
486
//test_enum     func_1(char ch_1, char ch_2) {
487
//      char    lcl_ch_1, lcl_ch_2;
488
//
489
//      lcl_ch_1 = ch_1;
490
//      lcl_ch_2 = lcl_ch_1;
491
//      if (lcl_ch_2 != ch_2)
492
//              return 0;
493
//      else {
494
//              gbl_ch = lcl_ch_1;
495
//              return 1;
496
//      }
497
 
498
#ifdef  NO_INLINE
499
func_1:
500
        ; On input,
501
        ; R0 = ch_1
502
        ; R1 = ch_2
503
        ; R2 = available
504
        ; On output, R0 is our return value
505
 
506 69 dgisselq
        SUB     1,SP
507
        STO     R2,(SP)
508 41 dgisselq
        MOV     R0,R2
509
        CMP     R2,R1
510
        CLR.NZ  R0
511
        STO.Z   R2,gbl_ch(R12)
512
        LDILO.Z 1,R0
513 69 dgisselq
        LOD     (SP),R2
514
        ADD     1,SP
515 74 dgisselq
#ifndef SKIP_SHORT_CIRCUITS
516
        CMP     LOAD_ADDRESS,R2
517
        BUSY.LT
518
#endif
519 69 dgisselq
        JMP     R2
520 41 dgisselq
#endif
521
 
522
//bool  func_2(char *str_1, char *str_2) {
523
//      int     lcl_int;
524
//      char    lcl_ch;
525
//
526
//      lcl_int = 2;
527
//      while(lcl_int <= 2) {
528
//              if (func_1(str_1[lcl_int], str_2[lcl_int+1])==0) {
529
//                      lcl_ch = 'A';
530
//                      lcl_int ++;
531
//              }
532
//      }
533
//
534
//      if ((lcl_ch >= 'W')&&(lcl_ch < 'Z'))
535
//              lcl_int = 7;
536
//      if (lcl_ch == 'R')
537
//              return true;
538
//      else {
539
//              if (lcl_strcmp(str_1, str_2)>0) {
540
//                      lcl_int += 7;
541
//                      gbl_int = lcl_int;
542
//              } else
543
//                      return false;
544
//      }
545
//}
546
func_2:
547
        ;
548
        SUB     6,SP
549 74 dgisselq
#ifndef SKIP_SHORT_CIRCUITS
550
        CMP     LOAD_ADDRESS,R2
551
        BUSY.LT
552
#endif
553
        STO     R2,(SP)         ; SP = 0x08daf
554 69 dgisselq
        STO     R3,1(SP)
555
        STO     R4,2(SP)
556
        STO     R5,3(SP)
557
        STO     R6,4(SP)
558
        STO     R7,5(SP)
559 41 dgisselq
 
560
        MOV     R0,R3   ; R3 = str_1
561
        MOV     R1,R4   ; R4 = str_2
562
        LDI     2,R5    ; R5 = lcl_int
563
        LDI     'A',R7  ; R7 = lcl_ch
564
func_2_while_loop:
565
        CMP     2,R5
566
        BGT     func_2_end_while_loop
567
func_2_top_while_loop:
568
        MOV     R3,R6
569
        ADD     R5,R6
570
 
571
#ifdef  NO_INLINE
572
        LOD     (R6),R0
573
        MOV     R4,R6
574
        ADD     R5,R6
575
        LOD     1(R6),R1
576
 
577 69 dgisselq
        MOV     __HERE__+2(PC),R2
578 41 dgisselq
        BRA     func_1
579
 
580
        CMP     0,R0
581
        ADD.Z   1,R5
582 57 dgisselq
#ifndef SKIP_SHORT_CIRCUITS
583
        BUSY.NZ
584
#endif
585 41 dgisselq
#else
586
        LOD     (R6),R2
587
        MOV     R4,R6
588
        ADD     R5,R6
589
        LOD     1(R6),R1
590
 
591
        CMP     R2,R1
592
        STO.Z   R2,gbl_ch(R12)
593
        LDILO.Z 1,R0
594
 
595
        ADD.NZ  1,R5
596 57 dgisselq
#ifndef SKIP_SHORT_CIRCUITS
597
        BUSY.Z
598 41 dgisselq
#endif
599 57 dgisselq
#endif
600 41 dgisselq
 
601
        CMP     3,R5
602
#ifndef SKIP_SHORT_CIRCUITS
603
        BUSY.LT
604
#endif
605
        BLT     func_2_top_while_loop
606
 
607
func_2_end_while_loop:
608
 
609
        // CMP  'W',R7                  // BUT! We know lcl_ch='A'
610
        // BLT  skip_if                 // So we can skip this
611
        // CMP  'Z',R7                  // entire  section
612
        // LDI.LT       7,R5
613
        // CMP  'R',R7
614
        // BNZ alt_if_case
615
        // LLO.Z        1,R0
616
        // BRA  func_2_return_and_cleanup
617
        //
618
        MOV     R3,R0
619
        MOV     R4,R1
620 69 dgisselq
        MOV     __HERE__+2(PC),R2
621 41 dgisselq
        BRA     lcl_strcmp
622
        CMP     0,R0
623
        BGT     func_2_final_then
624
        CLR     R0
625
        BRA     func_2_return_and_cleanup
626
func_2_final_then:
627
        // ADD  7,R5            ; Never read, so useless code
628
        LDI     1,R0
629
#ifndef SKIP_SHORT_CIRCUITS
630
        BUSY
631
#endif
632
func_2_return_and_cleanup:
633
 
634 69 dgisselq
        LOD     (SP),R2
635
        LOD     1(SP),R3
636
        LOD     2(SP),R4
637
        LOD     3(SP),R5
638
        LOD     4(SP),R6
639
        LOD     5(SP),R7
640 41 dgisselq
        ADD     6,SP
641 74 dgisselq
#ifndef SKIP_SHORT_CIRCUITS
642
        CMP     LOAD_ADDRESS,R2
643
        BUSY.LT
644
#endif
645 69 dgisselq
        JMP     R2
646 41 dgisselq
 
647
//bool  func_3(test_enum a) {
648
//      test_enum       lcl_enum;
649
//
650
//      lcl_enum = a;
651
//      if (lcl_enum == Ident_3)
652
//              return true;
653
//      else
654
//              return false;
655
//}
656
 
657
#ifdef  NO_INLINE
658
func_3:
659
        ; On entry,
660
        ;  R0 = a
661
        ;  R1 - available
662
        CMP     2,R0
663 69 dgisselq
        CLR     R0      ; CLR Doesn't set flags
664
        LDILO.Z 1,R0
665 74 dgisselq
#ifndef SKIP_SHORT_CIRCUITS
666
        CMP     LOAD_ADDRESS,R1
667
        BUSY.LT
668
#endif
669 69 dgisselq
        JMP     R1
670 41 dgisselq
#endif
671
 
672
 
673
// void proc_6(test_enum ev, test_enum *ep) {
674
//      *ep = ev;
675
//      if (!func_3(ev))
676
//              *ep = 3;
677
//      switch(ev) {
678
//              case 0: *ep = 0; break;
679
//              case 1:
680
//                      if (gbl_int > 100)
681
//                              *ep = 0;
682
//                      else
683
//                              *ep = 3;
684
//                      break;
685
//              case 2:
686
//                      *ep = 1;
687
//                      break;
688
//              case 3:
689
//                      break;
690
//              case 4:
691
//                      *ep = 2;
692
//      }
693
//}
694
 
695
proc_6:
696
        ; On entry:
697
        ;       R0 = ev
698
        ;       R1 = ep
699 69 dgisselq
        ;       R2 = link address
700 41 dgisselq
        ; Since we call func_3, we have to reserve R0 and R1
701
        ; for other purposes.  Thus
702
        ;       R2 = ev
703
        ;       R3 = ep
704
        SUB     2,SP
705 69 dgisselq
        STO     R2,(SP)
706
        STO     R3,1(SP)
707 41 dgisselq
 
708
        MOV     R1,R3
709
        MOV     R0,R2
710
        ; *ep = ev
711
        STO     R0,(R1)
712
#ifndef SKIP_SHORT_CIRCUITS
713
        CMP     2,R0
714
        BUSY.NZ
715
#endif
716
 
717
#ifdef  NO_INLINE
718
        ; !func_3(ev)
719 69 dgisselq
        MOV     __HERE__+2(PC),R1
720 41 dgisselq
        BRA     func_3
721
 
722
        TST     -1,R0
723
        LDI     3,R1
724 69 dgisselq
#ifndef SKIP_SHORT_CIRCUITS
725
        BUSY.Z
726
#endif
727 41 dgisselq
        STO.Z   R1,(R3)
728
#else
729 69 dgisselq
        CMP     2,R0
730 41 dgisselq
        LDI     3,R1
731 74 dgisselq
#ifndef SKIP_SHORT_CIRCUITS
732 69 dgisselq
        BUSY.NZ
733 41 dgisselq
#endif
734 69 dgisselq
        STO.NZ  R1,(R3)
735 41 dgisselq
#endif
736
 
737
#ifndef SKIP_SHORT_CIRCUITS
738
        CMP     2,R2
739
        BUSY.NZ
740
#endif
741
        CMP     0,R2
742
        BNZ     proc_6_case_not_zero
743
#ifndef SKIP_SHORT_CIRCUITS
744
        BUSY
745
#endif
746
        LDI     0,R1
747
        STO     R1,(R3)
748
        BRA     proc_6_end_of_case
749
proc_6_case_not_zero:
750
        CMP     1,R2
751
        BNZ     proc_6_case_not_one
752
#ifndef SKIP_SHORT_CIRCUITS
753
        BUSY
754
#endif
755
        LDI     3,R0
756
        LOD     gbl_int(R12),R1
757
        CMP     100,R1
758
        CLR.GT  R0
759
        STO     R0,(R3)
760
        BRA     proc_6_end_of_case
761
proc_6_case_not_one:
762
        CMP     2,R2
763
        BNZ     proc_6_case_not_two
764
        LDI     1,R1                            // Executed, if done properly
765
        STO     R1,(R3)
766
        BRA     proc_6_end_of_case
767
proc_6_case_not_two:
768
#ifndef SKIP_SHORT_CIRCUITS
769 74 dgisselq
        NOOP                            ;;;;;;;; TODO This fails--needs the NOOP
770
        BUSY                            ;;;;;;;; TODO so as not to do the BUSY
771 41 dgisselq
#endif
772
        CMP     4,R2
773
        BNZ     proc_6_case_not_four
774
        LDI     2,R1
775
        STO     R1,(R3)
776
        // BRA  proc_6_end_of_case
777
proc_6_case_not_four:
778
proc_6_end_of_case:
779 69 dgisselq
        LOD     (SP),R2
780
        LOD     1(SP),R3
781 74 dgisselq
#ifndef SKIP_SHORT_CIRCUITS
782
        CMP     LOAD_ADDRESS,R2         ; TODO This fails, even when the address
783
        BUSY.LT
784
#endif
785 41 dgisselq
        ADD     2,SP
786 69 dgisselq
        JMP     R2
787 41 dgisselq
 
788
// void proc_7(int a, int b, int *c) {
789
//      int     lcl;
790
//
791
//      lcl = a + 2;
792
//      *c = b + a;
793
//}
794
 
795
#ifdef  NO_INLINE
796
proc_7:
797
        ADD 2+R0,R1
798
        STO R1,(R2)
799
 
800 74 dgisselq
#ifndef SKIP_SHORT_CIRCUITS
801
        CMP     LOAD_ADDRESS,R3
802
        BUSY.LT
803
#endif
804 69 dgisselq
        JMP     R3
805 41 dgisselq
#endif
806
 
807
//      int     a[50];
808
//      int     b[50][50];
809
//
810
// void proc_8(Arr_1_Dim a, Arr_2_Dim b, int c, int d) {
811
//      int     idx, loc;
812
//
813
//      loc = c+5;
814
//      a[loc] = d;
815
//      a[loc+1] = a[loc];
816
//      a[loc+30] = loc;
817
//      for(idx=loc; idx<= loc+1; idx++)
818
//              b[loc][idx] = loc;
819
//      b[loc][loc-1] += 1;
820
//      b[loc+20][loc] = a[loc];
821
//      gbl_int = 5;
822
//}
823
proc_8:
824
        ; R0 = a
825
        ; R1 = b
826
        ; R2 = c
827
        ; R3 = d
828
        ; R4 - unassigned
829
        ; Makes no function/procedure calls, so these can keep
830
        ; R2 = loc = c+5, replaces c
831
        ; R4 = idx
832 69 dgisselq
        SUB     3,SP
833
        STO     R4,(SP)
834 41 dgisselq
        STO     R5,1(SP)
835
        STO     R6,2(SP)
836
 
837
        ADD     5,R2    ; loc = c+5
838
        MOV     R0,R5
839
        ADD     R2,R5
840
        STO     R3,(R5)
841
        STO     R3,1(R5)
842
        STO     R2,30(R5)
843
        MOV     R2,R5
844 152 dgisselq
        MPY     50,R5   ; R5 = 50 * R2 = 50 * loc
845 41 dgisselq
        ADD     R1,R5   ; R5 = &b[loc][0]
846
        MOV     R5,R6   ; R6 = &b[loc][0]
847
        ADD     R2,R5   ; R5 = &b[loc][loc]
848
        MOV     R2,R4   ; R4 = loc = index
849
proc_8_top_of_loop:
850
        CMP     1(R2),R4
851
        BGT     proc_8_end_of_loop
852
proc_8_loop_after_condition:
853
        STO     R2,(R5)
854
        ADD     1,R5
855
        ADD     1,R4
856
        CMP     2(R2),R4
857
        BLT     proc_8_loop_after_condition
858
proc_8_end_of_loop:
859
 
860
        ; b[loc][loc-1] += 1
861
        ADD     R2,R6           ; R6 = &b[loc][loc]
862
        LOD     -1(R6),R5
863
        ADD     1,R5
864
        STO     R5,-1(R6)
865
        ; b[loc+20][loc] = a[loc]
866
        MOV     R0,R4
867
        ADD     R2,R4
868
        LOD     (R4),R3
869
        STO     R3,20*50(R6)
870
        LDI     5,R3
871
        STO     R3,gbl_int(R12)
872
 
873