URL
https://opencores.org/ocsvn/light8080/light8080/trunk
Subversion Repositories light8080
[/] [light8080/] [trunk/] [c/] [hello.asm] - Rev 66
Go to most recent revision | Compare with Previous | Blame | View Log
; <><><> Small-C V1.2 DOS--CP/M Cross Compiler <><><>; <><><><><> CP/M Large String Space Version <><><><><>; <><><><><><><><><><> By Ron Cain <><><><><><><><><><>;codeorg #0000ld hl,3072ld sp,hlcall __main;//---------------------------------------------------------------------------------------;// Project: light8080 SOC WiCores Solutions;//;// File name: hello.c (February 04, 2012);//;// Writer: Moti Litochevski;//;// Description:;// This file contains a simple program written in Small-C that sends a string to;// the UART and then switches to echo received bytes.;// This example also include a simple interrupt example which will work with the;// verilog testbench. the testbench;//;// Revision History:;//;// Rev <revnumber> <Date> <owner>;// <comment>;//---------------------------------------------------------------------------------------;// define interrupt vectors;// note that this file must be edited to enable interrupt used;#include intr_vec.h;//---------------------------------------------------------------------------------------;// Project: light8080 SOC WiCores Solutions;//;// File name: intr_vec.h (March 03, 2012);//;// Writer: Moti Litochevski;//;// Description:;// This file contains a simple example of calling interrupt service routine. this;// file defines the interrupt vector for external interrupt 0 located at address;// 0x0008. the interrupts vectors addresses are set in the verilog interrupt;// controller "intr_ctrl.v" file.;// Code is generated for all 4 supported external interrupts but non used interrupt;// are not called.;// On execution of an interrupt the CPU will automatically clear the interrupt;// enable flag set by the EI instruction. the interrupt vectors in this example;// enable the interrupts again after interrupt service routine execution. to enable;// nested interrupts just move the EI instruction to the code executed before the;// call instruction to the service routine (see comments below).;// Note that this code is not optimized in any way. this is just an example to;// verify the interrupt mechanism of the light8080 CPU and show a simple example.;//;// Revision History:;//;// Rev <revnumber> <Date> <owner>;// <comment>;//---------------------------------------------------------------------------------------;// to support interrupt enable the respective interrupt vector is defined here at the;// beginning of the output assembly file. only the interrupt vector for used interrupts;// should call a valid interrupt service routine name defined in the C source file. the;// C function name should be prefixed by "__".;#asm;Preserve space for interrupt routines;interrupt 0 vectororg #0008push afpush bcpush depush hl; ei ; to enable nested interrupts uncomment this instructioncall __int0_isrpop hlpop depop bcpop afei ; interrupt are not enabled during the execution os the isrret;interrupt 1 vectororg #0018push afpush bcpush depush hl; call __int1_isr ; interrupt not usedpop hlpop depop bcpop afeiret;interrupt 2 vectororg #0028push afpush bcpush depush hl; call __int2_isr ; interrupt not usedpop hlpop depop bcpop afeiret;interrupt 3 vectororg #0038push afpush bcpush depush hl; call __int3_isr ; interrupt not usedpop hlpop depop bcpop afeiret;//---------------------------------------------------------------------------------------;// Th.. Th.. Th.. Thats all folks !!!;//---------------------------------------------------------------------------------------;// insert c80 assmbly library to the output file;#include ..\tools\c80\c80.lib;#asm;;------------------------------------------------------------------; Small-C Run-time Librray;; V4d As of July 16, 1980 (gtf); Added EXIT() function;------------------------------------------------------------------;;Fetch a single byte from the address in HL and sign extend into HLccgchar:ld a,(hl)ccsxt:ld l,arlcasbc ald h,aret;Fetch a full 16-bit integer from the address in HLccgint:ld a,(hl)inc hlld h,(hl)ld l,aret;Store a single byte from HL at the address in DEccpchar:ld a,lld (de),aret;Store a 16-bit integer in HL at the address in DEccpint:ld a,lld (de),ainc deld a,hld (de),aret;Inclusive "or" HL and DE into HLccor:ld a,lor eld l,ald a,hor dld h,aret;Exclusive "or" HL and DE into HLccxor:ld a,lxor eld l,ald a,hxor dld h,aret;"And" HL and DE into HLccand:ld a,land eld l,ald a,hand dld h,aret;Test if HL = DE and set HL = 1 if true else 0cceq:call cccmpret zdec hlret;Test if DE ~= HLccne:call cccmpret nzdec hlret;Test if DE > HL (signed)ccgt:ex de,hlcall cccmpret cdec hlret;Test if DE <= HL (signed)ccle:call cccmpret zret cdec hlret;Test if DE >= HL (signed)ccge:call cccmpret ncdec hlret;Test if DE < HL (signed)cclt:call cccmpret cdec hlret; Signed compare of DE and HL; Performs DE - HL and sets the conditions:; Carry reflects sign of difference (set means DE < HL); Zero/non-zero set according to equality.cccmp:ld a,esub lld e,ald a,dsbc hld hl,1jp m,cccmp1or e ;"OR" resets carryretcccmp1:or escf ;set carry to signal minusret;Test if DE >= HL (unsigned)ccuge:call ccucmpret ncdec hlret;Test if DE < HL (unsigned)ccult:call ccucmpret cdec hlret;Test if DE > HL (unsigned)ccugt:ex de,hlcall ccucmpret cdec hlret;Test if DE <= HL (unsigned)ccule:call ccucmpret zret cdec hlret;Routine to perform unsigned compare;carry set if DE < HL;zero/nonzero set accordinglyccucmp:ld a,dcp hjp nz,$+5ld a,ecp lld hl,1ret;Shift DE arithmetically right by HL and return in HLccasr:ex de,hlld a,hrlald a,hrrald h,ald a,lrrald l,adec ejp nz,ccasr+1ret;Shift DE arithmetically left by HL and return in HLccasl:ex de,hladd hl,hldec ejp nz,ccasl+1ret;Subtract HL from DE and return in HLccsub:ld a,esub lld l,ald a,dsbc hld h,aret;Form the two's complement of HLccneg:call cccominc hlret;Form the one's complement of HLcccom:ld a,hcplld h,ald a,lcplld l,aret;Multiply DE by HL and return in HLccmult:ld b,hld c,lld hl,0ccmult1:ld a,crrcajp nc,$+4add hl,dexor ald a,brrald b,ald a,crrald c,aor bret zxor ald a,erlald e,ald a,drlald d,aor eret zjp ccmult1;Divide DE by HL and return quotient in HL, remainder in DEccdiv:ld b,hld c,lld a,dxor bpush afld a,dor acall m,ccdenegld a,bor acall m,ccbcnegld a,16push afex de,hlld de,0ccdiv1:add hl,hlcall ccrdeljp z,ccdiv2call cccmpbcdejp m,ccdiv2ld a,lor 1ld l,ald a,esub cld e,ald a,dsbc bld d,accdiv2:pop afdec ajp z,ccdiv3push afjp ccdiv1ccdiv3:pop afret pcall ccdenegex de,hlcall ccdenegex de,hlretccdeneg:ld a,dcplld d,ald a,ecplld e,ainc deretccbcneg:ld a,bcplld b,ald a,ccplld c,ainc bcretccrdel:ld a,erlald e,ald a,drlald d,aor eretcccmpbcde:ld a,esub cld a,dsbc bret;// UART IO registers;port (128) UDATA; // uart data register used for both transmit and receive;port (129) UBAUDL; // low byte of baud rate register;port (130) UBAUDH; // low byte of baud rate register;port (131) USTAT; // uart status register;// digital IO ports registers;port (132) P1DATA; // port 1 data register;port (133) P1DIR; // port 1 direction register control;port (134) P2DATA; // port 2 data register;port (135) P2DIR; // port 2 direction register control;// interrupt controller register;port (136) INTRENA; // interrupts enable register;// simulation end register;// writing any value to this port will end the verilog simulation when using tb_l80soc;// test bench.;port (255) SIMEND;;// registers bit fields definition;// uart status register decoding;#define UTXBUSY 1;#define URXFULL 16;// globals;char rxbyte; // byte received from the uart;int tstary[2] = {1234, 5678};;//---------------------------------------------------------------------------------------;// send a single byte to the UART;sendbyte(by)__sendbyte:;char by;;{; while (USTAT & UTXBUSY);cc2:in a,(131)call ccsxtpush hlld hl,1pop decall ccandld a,hor ljp z,cc3jp cc2cc3:; UDATA = by;ld hl,2add hl,spcall ccgcharld a,lout (128),a;}ret;// check if a byte was received by the uart;getbyte()__getbyte:;{; if (USTAT & URXFULL) {in a,(131)call ccsxtpush hlld hl,16pop decall ccandld a,hor ljp z,cc4; rxbyte = UDATA;in a,(128)call ccsxtld a,lld (__rxbyte),a; return 1;ld hl,1ret; }; elsejp cc5cc4:; return 0;ld hl,0retcc5:;}ret;// send new line to the UART;nl()__nl:;{; sendbyte(13);ld hl,13push hlcall __sendbytepop bc; sendbyte(10);ld hl,10push hlcall __sendbytepop bc;}ret;// sends a string to the UART;printstr(sptr)__printstr:;char *sptr;;{; while (*sptr != 0)cc6:ld hl,2add hl,spcall ccgintcall ccgcharpush hlld hl,0pop decall ccneld a,hor ljp z,cc7; sendbyte(*sptr++);ld hl,2add hl,sppush hlcall ccgintinc hlpop decall ccpintdec hlcall ccgcharpush hlcall __sendbytepop bcjp cc6cc7:;}ret;// sends a decimal value to the UART;printdec(dval)__printdec:;int dval;;{; if (dval<0) {ld hl,2add hl,spcall ccgintpush hlld hl,0pop decall ccltld a,hor ljp z,cc8; sendbyte('-');ld hl,45push hlcall __sendbytepop bc; dval = -dval;ld hl,2add hl,sppush hlld hl,4add hl,spcall ccgintcall ccnegpop decall ccpint; }; outint(dval);cc8:ld hl,2add hl,spcall ccgintpush hlcall __outintpop bc;}ret;// function copied from c80dos.c;outint(n)__outint:;int n;;{;int q;push bc; q = n/10;ld hl,0add hl,sppush hlld hl,6add hl,spcall ccgintpush hlld hl,10pop decall ccdivpop decall ccpint; if (q) outint(q);ld hl,0add hl,spcall ccgintld a,hor ljp z,cc9ld hl,0add hl,spcall ccgintpush hlcall __outintpop bc; sendbyte('0'+(n-q*10));cc9:ld hl,48push hlld hl,6add hl,spcall ccgintpush hlld hl,4add hl,spcall ccgintpush hlld hl,10pop decall ccmultpop decall ccsubpop deadd hl,depush hlcall __sendbytepop bc;}pop bcret;// sends a hexadecimal value to the UART;printhex(hval)__printhex:;int hval;;{;int q;push bc; q = hval/16;ld hl,0add hl,sppush hlld hl,6add hl,spcall ccgintpush hlld hl,16pop decall ccdivpop decall ccpint; if (q) printhex(q);ld hl,0add hl,spcall ccgintld a,hor ljp z,cc10ld hl,0add hl,spcall ccgintpush hlcall __printhexpop bc; q = hval-q*16;cc10:ld hl,0add hl,sppush hlld hl,6add hl,spcall ccgintpush hlld hl,4add hl,spcall ccgintpush hlld hl,16pop decall ccmultpop decall ccsubpop decall ccpint; if (q > 9)ld hl,0add hl,spcall ccgintpush hlld hl,9pop decall ccgtld a,hor ljp z,cc11; sendbyte('A'+q-10);ld hl,65push hlld hl,2add hl,spcall ccgintpop deadd hl,depush hlld hl,10pop decall ccsubpush hlcall __sendbytepop bc; elsejp cc12cc11:; sendbyte('0'+q);ld hl,48push hlld hl,2add hl,spcall ccgintpop deadd hl,depush hlcall __sendbytepop bccc12:;}pop bcret;// external interrupt 0 service routine;int0_isr()__int0_isr:;{; printstr("Interrupt 0 was asserted."); nl();ld hl,cc1+0push hlcall __printstrpop bccall __nl;}ret;// program main routine;main()__main:;{; // configure UART baud rate - set to 9600 for 30MHz clock; // BAUD = round(<clock>/<baud rate>/16) = round(30e6/9600/16) = 195;//MOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTI;//MOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTI;// UBAUDL = 195;; UBAUDL = 1;ld hl,1ld a,lout (129),a;//MOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTI;//MOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTIMOTI; UBAUDH = 0;ld hl,0ld a,lout (130),a; // configure both ports to output and digital outputs as zeros; P1DATA = 0x00;ld hl,0ld a,lout (132),a; P1DIR = 0xff;ld hl,255ld a,lout (133),a; P2DATA = 0x00;ld hl,0ld a,lout (134),a; P2DIR = 0xff;ld hl,255ld a,lout (135),a; // enable interrupt 0 only; INTRENA = 0x01;ld hl,1ld a,lout (136),a; // enable CPU interrupt;#asmei;; // print message; printstr("Hello World!!!"); nl();ld hl,cc1+26push hlcall __printstrpop bccall __nl; printstr("Dec value: "); printdec(tstary[1]); nl();ld hl,cc1+41push hlcall __printstrpop bcld hl,__tstarypush hlld hl,1add hl,hlpop deadd hl,decall ccgintpush hlcall __printdecpop bccall __nl; printstr("Hex value: 0x"); printhex(tstary[0]); nl();ld hl,cc1+53push hlcall __printstrpop bcld hl,__tstarypush hlld hl,0add hl,hlpop deadd hl,decall ccgintpush hlcall __printhexpop bccall __nl; // assert bit 0 of port 1 to test external interrupt 0; P1DATA = 0x01;ld hl,1ld a,lout (132),a;; printstr("Echoing received bytes: "); nl();ld hl,cc1+67push hlcall __printstrpop bccall __nl; // loop forever; while (1) {cc13:ld hl,1ld a,hor ljp z,cc14; // check if a new byte was received; if (getbyte())call __getbyteld a,hor ljp z,cc15; // echo the received byte to the UART; sendbyte(rxbyte);ld a,(__rxbyte)call ccsxtpush hlcall __sendbytepop bc; }cc15:jp cc13cc14:;}ret;//---------------------------------------------------------------------------------------;// Th.. Th.. Th.. Thats all folks !!!;//---------------------------------------------------------------------------------------cc1:db 73,110,116,101,114,114,117,112,116,32db 48,32,119,97,115,32,97,115,115,101db 114,116,101,100,46,0,72,101,108,108db 111,32,87,111,114,108,100,33,33,33db 0,68,101,99,32,118,97,108,117,101db 58,32,0,72,101,120,32,118,97,108db 117,101,58,32,48,120,0,69,99,104db 111,105,110,103,32,114,101,99,101,105db 118,101,100,32,98,121,116,101,115,58db 32,0__rxbyte:ds 1__tstary:db -46,4,46,22; --- End of Compilation ---
Go to most recent revision | Compare with Previous | Blame | View Log
