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

Subversion Repositories light8080

[/] [light8080/] [trunk/] [c/] [hello.asm] - Blame information for rev 67

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 65 motilito
; <><><>   Small-C  V1.2  DOS--CP/M Cross Compiler   <><><>
2
; <><><><><>   CP/M Large String Space Version   <><><><><>
3
; <><><><><><><><><><>   By Ron Cain   <><><><><><><><><><>
4
;
5
        code
6
        org #0000
7
        ld hl,3072
8
        ld sp,hl
9
        call __main
10
;//---------------------------------------------------------------------------------------
11
;//     Project:                        light8080 SOC           WiCores Solutions
12
;//
13
;//     File name:                      hello.c                                 (February 04, 2012)
14
;//
15
;//     Writer:                         Moti Litochevski
16
;//
17
;//     Description:
18
;//             This file contains a simple program written in Small-C that sends a string to
19
;//             the UART and then switches to echo received bytes.
20 66 motilito
;//             This example also include a simple interrupt example which will work with the
21
;//             verilog testbench. the testbench
22 65 motilito
;//
23
;//     Revision History:
24
;//
25
;//     Rev                                             
26
;//             
27
;//---------------------------------------------------------------------------------------
28 66 motilito
;// define interrupt vectors
29
;// note that this file must be edited to enable interrupt used
30
;#include intr_vec.h
31
;//---------------------------------------------------------------------------------------
32
;//     Project:                        light8080 SOC           WiCores Solutions
33
;//
34
;//     File name:                      intr_vec.h                      (March 03, 2012)
35
;//
36
;//     Writer:                         Moti Litochevski
37
;//
38
;//     Description:
39
;//             This file contains a simple example of calling interrupt service routine. this
40
;//             file defines the interrupt vector for external interrupt 0 located at address
41
;//             0x0008. the interrupts vectors addresses are set in the verilog interrupt
42
;//             controller "intr_ctrl.v" file.
43
;//             Code is generated for all 4 supported external interrupts but non used interrupt
44
;//             are not called.
45
;//             On execution of an interrupt the CPU will automatically clear the interrupt
46
;//             enable flag set by the EI instruction. the interrupt vectors in this example
47
;//             enable the interrupts again after interrupt service routine execution. to enable
48
;//             nested interrupts just move the EI instruction to the code executed before the
49
;//             call instruction to the service routine (see comments below).
50
;//             Note that this code is not optimized in any way. this is just an example to
51
;//             verify the interrupt mechanism of the light8080 CPU and show a simple example.
52
;//
53
;//     Revision History:
54
;//
55
;//     Rev                                             
56
;//             
57
;//---------------------------------------------------------------------------------------
58
;// to support interrupt enable the respective interrupt vector is defined here at the
59
;// beginning of the output assembly file. only the interrupt vector for used interrupts
60
;// should call a valid interrupt service routine name defined in the C source file. the
61
;// C function name should be prefixed by "__".
62
;#asm
63
;Preserve space for interrupt routines
64
;interrupt 0 vector
65
        org #0008
66
        push af
67
        push bc
68
        push de
69
        push hl
70
;       ei                                      ; to enable nested interrupts uncomment this instruction
71
        call __int0_isr
72
        pop hl
73
        pop de
74
        pop bc
75
        pop af
76
        ei                                      ; interrupt are not enabled during the execution os the isr
77
        ret
78
;interrupt 1 vector
79
        org #0018
80
        push af
81
        push bc
82
        push de
83
        push hl
84
;       call __int1_isr         ; interrupt not used
85
        pop hl
86
        pop de
87
        pop bc
88
        pop af
89
        ei
90
        ret
91
;interrupt 2 vector
92
        org #0028
93
        push af
94
        push bc
95
        push de
96
        push hl
97
;       call __int2_isr         ; interrupt not used
98
        pop hl
99
        pop de
100
        pop bc
101
        pop af
102
        ei
103
        ret
104
;interrupt 3 vector
105
        org #0038
106
        push af
107
        push bc
108
        push de
109
        push hl
110
;       call __int3_isr         ; interrupt not used
111
        pop hl
112
        pop de
113
        pop bc
114
        pop af
115
        ei
116
        ret
117
;//---------------------------------------------------------------------------------------
118
;//                                             Th.. Th.. Th.. Thats all folks !!!
119
;//---------------------------------------------------------------------------------------
120
;// insert c80 assmbly library to the output file
121 65 motilito
;#include ..\tools\c80\c80.lib
122
;#asm
123
;
124
;------------------------------------------------------------------
125
;       Small-C  Run-time Librray
126
;
127
;       V4d     As of July 16, 1980 (gtf)
128
;                  Added EXIT() function
129
;------------------------------------------------------------------
130
;
131
;Fetch a single byte from the address in HL and sign extend into HL
132
ccgchar:
133
        ld a,(hl)
134
ccsxt:
135
        ld l,a
136
        rlca
137
        sbc     a
138
        ld      h,a
139
        ret
140
;Fetch a full 16-bit integer from the address in HL
141
ccgint:
142
        ld a,(hl)
143
        inc     hl
144
        ld      h,(hl)
145
        ld l,a
146
        ret
147
;Store a single byte from HL at the address in DE
148
ccpchar:
149
        ld      a,l
150
        ld      (de),a
151
        ret
152
;Store a 16-bit integer in HL at the address in DE
153
ccpint:
154
        ld      a,l
155
        ld      (de),a
156
        inc     de
157
        ld      a,h
158
        ld      (de),a
159
        ret
160
;Inclusive "or" HL and DE into HL
161
ccor:
162
        ld      a,l
163
        or      e
164
        ld l,a
165
        ld      a,h
166
        or      d
167
        ld      h,a
168
        ret
169
;Exclusive "or" HL and DE into HL
170
ccxor:
171
        ld      a,l
172
        xor     e
173
        ld l,a
174
        ld      a,h
175
        xor     d
176
        ld      h,a
177
        ret
178
;"And" HL and DE into HL
179
ccand:
180
        ld      a,l
181
        and     e
182
        ld l,a
183
        ld      a,h
184
        and     d
185
        ld      h,a
186
        ret
187
;Test if HL = DE and set HL = 1 if true else 0
188
cceq:
189
        call cccmp
190
        ret z
191
        dec     hl
192
        ret
193
;Test if DE ~= HL
194
ccne:
195
        call cccmp
196
        ret nz
197
        dec     hl
198
        ret
199
;Test if DE > HL (signed)
200
ccgt:
201
        ex de,hl
202
        call cccmp
203
        ret c
204
        dec     hl
205
        ret
206
;Test if DE <= HL (signed)
207
ccle:
208
        call cccmp
209
        ret z
210
        ret c
211
        dec hl
212
        ret
213
;Test if DE >= HL (signed)
214
ccge:
215
        call cccmp
216
        ret nc
217
        dec hl
218
        ret
219
;Test if DE < HL (signed)
220
cclt:
221
        call cccmp
222
        ret c
223
        dec hl
224
        ret
225
; Signed compare of DE and HL
226
; Performs DE - HL and sets the conditions:
227
;       Carry reflects sign of difference (set means DE < HL)
228
;       Zero/non-zero set according to equality.
229
cccmp:
230
        ld      a,e
231
        sub     l
232
        ld      e,a
233
        ld      a,d
234
        sbc     h
235
        ld      hl,1
236
        jp      m,cccmp1
237
        or      e       ;"OR" resets carry
238
        ret
239
cccmp1:
240
        or      e
241
        scf             ;set carry to signal minus
242
        ret
243
;Test if DE >= HL (unsigned)
244
ccuge:
245
        call ccucmp
246
        ret nc
247
        dec hl
248
        ret
249
;Test if DE < HL (unsigned)
250
ccult:
251
        call ccucmp
252
        ret c
253
        dec hl
254
        ret
255
;Test if DE > HL (unsigned)
256
ccugt:
257
        ex de,hl
258
        call ccucmp
259
        ret c
260
        dec hl
261
        ret
262
;Test if DE <= HL (unsigned)
263
ccule:
264
        call ccucmp
265
        ret z
266
        ret c
267
        dec hl
268
        ret
269
;Routine to perform unsigned compare
270
;carry set if DE < HL
271
;zero/nonzero set accordingly
272
ccucmp:
273
        ld      a,d
274
        cp      h
275
        jp      nz,$+5
276
        ld      a,e
277
        cp      l
278
        ld      hl,1
279
        ret
280
;Shift DE arithmetically right by HL and return in HL
281
ccasr:
282
        ex      de,hl
283
        ld      a,h
284
        rla
285
        ld      a,h
286
        rra
287
        ld      h,a
288
        ld      a,l
289
        rra
290
        ld      l,a
291
        dec     e
292
        jp      nz,ccasr+1
293
        ret
294
;Shift DE arithmetically left by HL and return in HL
295
ccasl:
296
        ex      de,hl
297
        add     hl,hl
298
        dec     e
299
        jp      nz,ccasl+1
300
        ret
301
;Subtract HL from DE and return in HL
302
ccsub:
303
        ld      a,e
304
        sub     l
305
        ld l,a
306
        ld      a,d
307
        sbc     h
308
        ld      h,a
309
        ret
310
;Form the two's complement of HL
311
ccneg:
312
        call cccom
313
        inc     hl
314
        ret
315
;Form the one's complement of HL
316
cccom:
317
        ld      a,h
318
        cpl
319
        ld      h,a
320
        ld      a,l
321
        cpl
322
        ld l,a
323
        ret
324
;Multiply DE by HL and return in HL
325
ccmult:
326
        ld      b,h
327
        ld      c,l
328
        ld      hl,0
329
ccmult1:
330
        ld      a,c
331
        rrca
332
        jp      nc,$+4
333
        add     hl,de
334
        xor     a
335
        ld      a,b
336
        rra
337
        ld      b,a
338
        ld      a,c
339
        rra
340
        ld      c,a
341
        or      b
342
        ret z
343
        xor     a
344
        ld      a,e
345
        rla
346
        ld      e,a
347
        ld      a,d
348
        rla
349
        ld      d,a
350
        or      e
351
        ret z
352
        jp      ccmult1
353
;Divide DE by HL and return quotient in HL, remainder in DE
354
ccdiv:
355
        ld      b,h
356
        ld      c,l
357
        ld      a,d
358
        xor     b
359
        push af
360
        ld      a,d
361
        or      a
362
        call m,ccdeneg
363
        ld      a,b
364
        or      a
365
        call m,ccbcneg
366
        ld      a,16
367
        push af
368
        ex      de,hl
369
        ld      de,0
370
ccdiv1:
371
        add hl,hl
372
        call ccrdel
373
        jp      z,ccdiv2
374
        call cccmpbcde
375
        jp      m,ccdiv2
376
        ld      a,l
377
        or      1
378
        ld l,a
379
        ld      a,e
380
        sub     c
381
        ld      e,a
382
        ld      a,d
383
        sbc     b
384
        ld      d,a
385
ccdiv2:
386
        pop af
387
        dec     a
388
        jp      z,ccdiv3
389
        push af
390
        jp      ccdiv1
391
ccdiv3:
392
        pop af
393
        ret     p
394
        call ccdeneg
395
        ex de,hl
396
        call ccdeneg
397
        ex de,hl
398
        ret
399
ccdeneg:
400
        ld      a,d
401
        cpl
402
        ld      d,a
403
        ld      a,e
404
        cpl
405
        ld      e,a
406
        inc     de
407
        ret
408
ccbcneg:
409
        ld      a,b
410
        cpl
411
        ld      b,a
412
        ld      a,c
413
        cpl
414
        ld      c,a
415
        inc     bc
416
        ret
417
ccrdel:
418
        ld      a,e
419
        rla
420
        ld      e,a
421
        ld      a,d
422
        rla
423
        ld      d,a
424
        or      e
425
        ret
426
cccmpbcde:
427
        ld      a,e
428
        sub     c
429
        ld      a,d
430
        sbc     b
431
        ret
432
;// UART IO registers
433
;port (128) UDATA;              // uart data register used for both transmit and receive
434
;port (129) UBAUDL;             // low byte of baud rate register
435
;port (130) UBAUDH;             // low byte of baud rate register
436
;port (131) USTAT;              // uart status register
437
;// digital IO ports registers
438 66 motilito
;port (132) P1DATA;             // port 1 data register
439
;port (133) P1DIR;              // port 1 direction register control
440
;port (134) P2DATA;             // port 2 data register
441
;port (135) P2DIR;              // port 2 direction register control
442
;// interrupt controller register
443
;port (136) INTRENA;            // interrupts enable register
444 65 motilito
;// simulation end register
445
;// writing any value to this port will end the verilog simulation when using tb_l80soc
446
;// test bench.
447
;port (255) SIMEND;
448
;// registers bit fields definition
449
;// uart status register decoding
450
;#define UTXBUSY                1
451
;#define URXFULL                16
452
;// globals
453
;char rxbyte;           // byte received from the uart
454
;int tstary[2] = {1234, 5678};
455
;//---------------------------------------------------------------------------------------
456
;// send a single byte to the UART
457
;sendbyte(by)
458
__sendbyte:
459
;char by;
460
;{
461
;       while (USTAT & UTXBUSY);
462
cc2:
463
        in a,(131)
464
        call ccsxt
465
        push hl
466
        ld hl,1
467
        pop de
468
        call ccand
469
        ld a,h
470
        or l
471
        jp z,cc3
472
        jp cc2
473
cc3:
474
;       UDATA = by;
475
        ld hl,2
476
        add hl,sp
477
        call ccgchar
478
        ld a,l
479
        out (128),a
480
 
481
;}
482
        ret
483
;// check if a byte was received by the uart
484
;getbyte()
485
__getbyte:
486
;{
487
;       if (USTAT & URXFULL) {
488
        in a,(131)
489
        call ccsxt
490
        push hl
491
        ld hl,16
492
        pop de
493
        call ccand
494
        ld a,h
495
        or l
496
        jp z,cc4
497
;               rxbyte = UDATA;
498
        in a,(128)
499
        call ccsxt
500
        ld a,l
501
        ld (__rxbyte),a
502
;               return 1;
503
        ld hl,1
504
        ret
505
;       }
506
;       else
507
        jp cc5
508
cc4:
509
;               return 0;
510
        ld hl,0
511
        ret
512
cc5:
513
;}
514
        ret
515
;// send new line to the UART
516
;nl()
517
__nl:
518
;{
519
;       sendbyte(13);
520
        ld hl,13
521
        push hl
522
        call __sendbyte
523
        pop bc
524
;       sendbyte(10);
525
        ld hl,10
526
        push hl
527
        call __sendbyte
528
        pop bc
529
;}
530
        ret
531
;// sends a string to the UART
532
;printstr(sptr)
533
__printstr:
534
;char *sptr;
535
;{
536
;       while (*sptr != 0)
537
cc6:
538
        ld hl,2
539
        add hl,sp
540
        call ccgint
541
        call ccgchar
542
        push hl
543
        ld hl,0
544
        pop de
545
        call ccne
546
        ld a,h
547
        or l
548
        jp z,cc7
549
;               sendbyte(*sptr++);
550
        ld hl,2
551
        add hl,sp
552
        push hl
553
        call ccgint
554
        inc hl
555
        pop de
556
        call ccpint
557
        dec hl
558
        call ccgchar
559
        push hl
560
        call __sendbyte
561
        pop bc
562
        jp cc6
563
cc7:
564
;}
565
        ret
566
;// sends a decimal value to the UART
567
;printdec(dval)
568
__printdec:
569
;int dval;
570
;{
571
;       if (dval<0) {
572
        ld hl,2
573
        add hl,sp
574
        call ccgint
575
        push hl
576
        ld hl,0
577
        pop de
578
        call cclt
579
        ld a,h
580
        or l
581
        jp z,cc8
582
;               sendbyte('-');
583
        ld hl,45
584
        push hl
585
        call __sendbyte
586
        pop bc
587
;               dval = -dval;
588
        ld hl,2
589
        add hl,sp
590
        push hl
591
        ld hl,4
592
        add hl,sp
593
        call ccgint
594
        call ccneg
595
        pop de
596
        call ccpint
597
;       }
598
;       outint(dval);
599
cc8:
600
        ld hl,2
601
        add hl,sp
602
        call ccgint
603
        push hl
604
        call __outint
605
        pop bc
606
;}
607
        ret
608
;// function copied from c80dos.c
609
;outint(n)
610
__outint:
611
;int n;
612
;{
613
;int q;
614
        push bc
615
;       q = n/10;
616
        ld hl,0
617
        add hl,sp
618
        push hl
619
        ld hl,6
620
        add hl,sp
621
        call ccgint
622
        push hl
623
        ld hl,10
624
        pop de
625
        call ccdiv
626
        pop de
627
        call ccpint
628
;       if (q) outint(q);
629
        ld hl,0
630
        add hl,sp
631
        call ccgint
632
        ld a,h
633
        or l
634
        jp z,cc9
635
        ld hl,0
636
        add hl,sp
637
        call ccgint
638
        push hl
639
        call __outint
640
        pop bc
641
;       sendbyte('0'+(n-q*10));
642
cc9:
643
        ld hl,48
644
        push hl
645
        ld hl,6
646
        add hl,sp
647
        call ccgint
648
        push hl
649
        ld hl,4
650
        add hl,sp
651
        call ccgint
652
        push hl
653
        ld hl,10
654
        pop de
655
        call ccmult
656
        pop de
657
        call ccsub
658
        pop de
659
        add hl,de
660
        push hl
661
        call __sendbyte
662
        pop bc
663
;}
664
        pop bc
665
        ret
666
;// sends a hexadecimal value to the UART
667
;printhex(hval)
668
__printhex:
669
;int hval;
670
;{
671
;int q;
672
        push bc
673
;       q = hval/16;
674
        ld hl,0
675
        add hl,sp
676
        push hl
677
        ld hl,6
678
        add hl,sp
679
        call ccgint
680
        push hl
681
        ld hl,16
682
        pop de
683
        call ccdiv
684
        pop de
685
        call ccpint
686
;       if (q) printhex(q);
687
        ld hl,0
688
        add hl,sp
689
        call ccgint
690
        ld a,h
691
        or l
692
        jp z,cc10
693
        ld hl,0
694
        add hl,sp
695
        call ccgint
696
        push hl
697
        call __printhex
698
        pop bc
699
;       q = hval-q*16;
700
cc10:
701
        ld hl,0
702
        add hl,sp
703
        push hl
704
        ld hl,6
705
        add hl,sp
706
        call ccgint
707
        push hl
708
        ld hl,4
709
        add hl,sp
710
        call ccgint
711
        push hl
712
        ld hl,16
713
        pop de
714
        call ccmult
715
        pop de
716
        call ccsub
717
        pop de
718
        call ccpint
719
;       if (q > 9)
720
        ld hl,0
721
        add hl,sp
722
        call ccgint
723
        push hl
724
        ld hl,9
725
        pop de
726
        call ccgt
727
        ld a,h
728
        or l
729
        jp z,cc11
730
;               sendbyte('A'+q-10);
731
        ld hl,65
732
        push hl
733
        ld hl,2
734
        add hl,sp
735
        call ccgint
736
        pop de
737
        add hl,de
738
        push hl
739
        ld hl,10
740
        pop de
741
        call ccsub
742
        push hl
743
        call __sendbyte
744
        pop bc
745
;       else
746
        jp cc12
747
cc11:
748
;               sendbyte('0'+q);
749
        ld hl,48
750
        push hl
751
        ld hl,2
752
        add hl,sp
753
        call ccgint
754
        pop de
755
        add hl,de
756
        push hl
757
        call __sendbyte
758
        pop bc
759
cc12:
760
;}
761
        pop bc
762
        ret
763 66 motilito
;// external interrupt 0 service routine
764
;int0_isr()
765
__int0_isr:
766
;{
767
;       printstr("Interrupt 0 was asserted."); nl();
768
        ld hl,cc1+0
769
        push hl
770
        call __printstr
771
        pop bc
772
        call __nl
773
;}
774
        ret
775 65 motilito
;// program main routine
776
;main()
777
__main:
778
;{
779
;       // configure UART baud rate - set to 9600 for 30MHz clock
780
;       // BAUD = round(//16) = round(30e6/9600/16) = 195
781 67 motilito
;       // Note: Usage of a minimum divider value of 1 will accelerate the RTL simulation.
782
;       UBAUDL = 195;
783
        ld hl,195
784 65 motilito
        ld a,l
785
        out (129),a
786
 
787
;       UBAUDH = 0;
788
        ld hl,0
789
        ld a,l
790
        out (130),a
791
 
792 66 motilito
;       // configure both ports to output and digital outputs as zeros
793
;       P1DATA = 0x00;
794
        ld hl,0
795
        ld a,l
796
        out (132),a
797
 
798
;       P1DIR = 0xff;
799
        ld hl,255
800
        ld a,l
801
        out (133),a
802
 
803
;       P2DATA = 0x00;
804
        ld hl,0
805
        ld a,l
806
        out (134),a
807
 
808
;       P2DIR = 0xff;
809
        ld hl,255
810
        ld a,l
811
        out (135),a
812
 
813
;       // enable interrupt 0 only
814
;       INTRENA = 0x01;
815
        ld hl,1
816
        ld a,l
817
        out (136),a
818
 
819
;       // enable CPU interrupt
820
;#asm
821
        ei
822 65 motilito
;       // print message
823
;       printstr("Hello World!!!"); nl();
824 66 motilito
        ld hl,cc1+26
825 65 motilito
        push hl
826
        call __printstr
827
        pop bc
828
        call __nl
829
;       printstr("Dec value: "); printdec(tstary[1]); nl();
830 66 motilito
        ld hl,cc1+41
831 65 motilito
        push hl
832
        call __printstr
833
        pop bc
834
        ld hl,__tstary
835
        push hl
836
        ld hl,1
837
        add hl,hl
838
        pop de
839
        add hl,de
840
        call ccgint
841
        push hl
842
        call __printdec
843
        pop bc
844
        call __nl
845
;       printstr("Hex value: 0x"); printhex(tstary[0]); nl();
846 66 motilito
        ld hl,cc1+53
847 65 motilito
        push hl
848
        call __printstr
849
        pop bc
850
        ld hl,__tstary
851
        push hl
852
        ld hl,0
853
        add hl,hl
854
        pop de
855
        add hl,de
856
        call ccgint
857
        push hl
858
        call __printhex
859
        pop bc
860
        call __nl
861 66 motilito
;       // assert bit 0 of port 1 to test external interrupt 0
862
;       P1DATA = 0x01;
863
        ld hl,1
864
        ld a,l
865
        out (132),a
866
 
867
;
868 65 motilito
;       printstr("Echoing received bytes: "); nl();
869 66 motilito
        ld hl,cc1+67
870 65 motilito
        push hl
871
        call __printstr
872
        pop bc
873
        call __nl
874
;       // loop forever
875
;       while (1) {
876
cc13:
877
        ld hl,1
878
        ld a,h
879
        or l
880
        jp z,cc14
881
;               // check if a new byte was received
882
;               if (getbyte())
883
        call __getbyte
884
        ld a,h
885
        or l
886
        jp z,cc15
887
;                       // echo the received byte to the UART
888
;                       sendbyte(rxbyte);
889
        ld a,(__rxbyte)
890
        call ccsxt
891
        push hl
892
        call __sendbyte
893
        pop bc
894
;       }
895
cc15:
896
        jp cc13
897
cc14:
898
;}
899
        ret
900
;//---------------------------------------------------------------------------------------
901
;//                                             Th.. Th.. Th.. Thats all folks !!!
902
;//---------------------------------------------------------------------------------------
903
cc1:
904 66 motilito
        db 73,110,116,101,114,114,117,112,116,32
905
        db 48,32,119,97,115,32,97,115,115,101
906
        db 114,116,101,100,46,0,72,101,108,108
907
        db 111,32,87,111,114,108,100,33,33,33
908
        db 0,68,101,99,32,118,97,108,117,101
909
        db 58,32,0,72,101,120,32,118,97,108
910
        db 117,101,58,32,48,120,0,69,99,104
911
        db 111,105,110,103,32,114,101,99,101,105
912
        db 118,101,100,32,98,121,116,101,115,58
913
        db 32,0
914 65 motilito
__rxbyte:
915
        ds 1
916
__tstary:
917
        db -46,4,46,22
918
 
919
; --- End of Compilation ---

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.