1
0
vt100-games/Blocks/mescc/mescc.h
2020-03-10 16:11:38 +01:00

945 lines
10 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @file mescc.h
* @brief Runtime library.
* @author Miguel I. Garcia Lopez / FloppySoftware
*
* Runtime library for MESCC (Mike's Enhanced
* Small C Compiler for Z80 & CP/M).
*
* This library file must be included first!
*
* Need following EQU's (generated by the compiler):
* - ccSTACKSIZE : Stack size in bytes.
*
* Supports following #defs:
* - #define CC_STDIO Support for stdin, stdout & stderr.
* - #define CC_REDIR Support for stdin & stdout redirection
* in command line (needs CC_STDIO).
* - #define CC_NO_MUL To exclude MULTIPLICATION code.
* - #define CC_NO_DIV To exclude DIVISION & MODULUS code.
* - #define CC_NO_SWITCH To exclude SWITCH code.
* - #define CC_NO_ARGS To exclude ARGC & ARGV code.
* - #define CC_NO_ORG To exclude ORG 0100H code.
*
* Sets the following #defines:
*
* - BYTE
* - WORD
* - BOOL
* - NULL
* - TRUE
* - FALSE
* - SIZEOF_CHAR
* - SIZEOF_INT
* - SIZEOF_PTR
*
* Revisions:
* - 16 Jan 2001 : Last revision.
* - 23 Mar 2007 : Expand ccladr1 and ccladr2 for more speed.
* - 16 Apr 2007 : GPL'd.
* - 26 Aug 2012 : Added standard defs.
* - 08 Dec 2014 : Minor changes.
* - 09 Dec 2014 : Added support for stdin, stdout & stderr with CC_STDIO.
* - 12 Dec 2014 : Added support for stdin & stdout redirection in command line with CC_REDIR.
* - 16 Jan 2015 : Added SIZEOF_??? definitions.
* - 16 Feb 2015 : Modified / added code in cctmpw, ccxpb2, ccxpb, ccxpb3, ccxpw2
* ccxpw, ccxpw3, ccladr2sv, ccladr2, ccladr1sv, ccladr1,
* to avoid use of IX register.
* - 20 Mar 2015 : Added support for CC_NO_MUL, CC_NO_DIV, CC_NO_SWITCH, CC_NO_ARGS.
* - 12 Apr 2015 : Removed ccDEFARGS code.
* - 14 Jul 2015 : Modified code for << and >>, because a shift of 0 positions,
* resulted in a wrong value (they assumed a shift > 0) - ie: 128 >> 0 resulted in 0.
* - 19 Oct 2015 : Improved multiplication algorithm (ccmul & ccumul).
* - 05 Nov 2015 : Modified ccsxt.
* - 30 Nov 2015 : Added support for atexit().
* - 24 Jan 2016 : Added support for CC_NO_ORG.
* - 10 Dec 2016 : Documented. GPL v3.
*
* Copyright (c) 1999-2016 Miguel I. Garcia Lopez / FloppySoftware.
*
* Licensed under the GNU General Public License v3.
*
* http://www.floppysoftware.es
* floppysoftware@gmail.com
*/
/* STANDARD DEFs
-------------
*/
#define BYTE unsigned char
#define WORD unsigned int
#define BOOL char
#define NULL 0
#define TRUE 1
#define FALSE 0
#define SIZEOF_CHAR 1 /* [unsigned] char */
#define SIZEOF_INT 2 /* [unsigned] int */
#define SIZEOF_PTR 2 /* pointer */
/* RUNTIME CODE
------------
*/
#ifndef CC_NO_ORG
#asm
; Start at TPA
ORG 0100H
#endasm
#endif
#asm
; Runtime address
ccrtadr:
; Set stack under BDOS (xx00h)
LD HL,(6)
LD L,0
LD SP,HL
; Leave space for stack and init. variables
LD DE,ccSTACKSIZE
OR A
SBC HL,DE
DEC HL
LD (ccfreelast),HL
LD DE,ccfreemem
LD (ccfreefirst),DE
OR A
SBC HL,DE
INC HL
LD (ccfreebytes),HL
JR NC,ccargs
; Error, no memory for stack
LD C,9
LD DE,ccerrstack
CALL 5
JP 0
ccerrstack
DEFB 'Runtime Error - No stack$'
; Setup command line arguments
ccargs
#endasm
#ifndef CC_NO_ARGS
#asm
; Copy command line
LD HL,81H
LD DE,ccmdbuf
LD BC,127
LDIR
LD A,(80H)
LD B,0
LD C,A
LD HL,ccmdbuf
ADD HL,BC
LD (HL),0
; Init. argc & argv
LD DE,cchptr
LD HL,ccmdbuf - 1
LD BC,1
ccspc
INC HL
LD A,(HL)
OR A
JR Z,ccarg
CP ' '
JR Z,ccspc
LD A,L
LD (DE),A
LD A,H
INC DE
LD (DE),A
INC DE
INC C
ccpar
INC HL
LD A,(HL)
OR A
JR Z,ccarg
CP ' '
JR NZ,ccpar
LD (HL),0
JR ccspc
ccarg
LD HL,cchptr - 2
PUSH BC ;argc
PUSH HL ;argv
#endasm
#endif
#ifdef CC_REDIR
#asm
CALL redir ;FIXME - Check errors
POP DE
POP BC
PUSH HL ;argc
PUSH DE ;argv
#endasm
#endif
#asm
; Execute program
CALL main
#endasm
/**
* @fn void exit(int code)
* @brief Exit to CP/M.
*
* FixMe: Return code is lost!
*/
#asm
; Exit to CP/M
exit
NOP ; Patch for atexit() -- 3 bytes.
NOP
NOP
#endasm
#ifdef CC_STDIO
BYTE *stdin, *stdout, *stderr; /* Sorry, no available FILE here */
#asm
LD HL,(stdin)
CALL ccflush
LD HL,(stdout)
CALL ccflush
JP 0
ccflush
LD A,H
OR L
RET Z
PUSH HL
CALL fclose
POP BC
RET
#endasm
#else
#asm
JP 0
#endasm
#endif
#asm
; Variables for memory functions
ccfreefirst
DEFW 0 ;Adr. first free byte
ccfreelast
DEFW 0 ;Adr. last free byte
ccfreebytes
DEFW 0 ;Number of free bytes
#endasm
#ifndef CC_NO_ARGS
#asm
; Variables for command line arguments
ccmdbuf
DEFS 128 ;Command line buffer
DEFW ccNULL ;Pointers table for argv
cchptr
DEFW ccNULL,ccNULL,ccNULL,ccNULL,ccNULL
DEFW ccNULL,ccNULL,ccNULL,ccNULL,ccNULL
DEFW ccNULL,ccNULL,ccNULL,ccNULL,ccNULL
DEFW ccNULL,ccNULL,ccNULL,ccNULL,ccNULL
DEFW ccNULL,ccNULL,ccNULL,ccNULL,ccNULL
ccNULL
DEFB 0 ;Null pointer
#endasm
#endif
#asm
; Basic routines
; Call formats to access locals:
;
; Format 1: CALL routine
; DEFB SpOffset
;
; Format 2: CALL routine
; DEFW SpOffset
; HL = unsigned char from local (format 2)
ccxgb2
CALL ccladr2
JR ccxgb3
; HL = unsigned char from local (format 1)
ccxgb
CALL ccladr1
ccxgb3
LD L,(HL)
LD H,0
RET
; HL = signed char from local (format 2)
ccxgc2
CALL ccladr2
JR ccgc
; HL = signed char from local (format 1)
ccxgc
CALL ccladr1
; HL = signed char from (HL)
ccgc
LD A,(HL)
; HL = signed char from A
ccsxt
LD L,A
RLCA
SBC A
LD H,A
RET
; LD H,0
; LD L,A
; AND 128
; RET Z
; DEC H
; RET
; HL = word from local (format 2)
ccxgw2
CALL ccladr2
JR ccgw
; HL = word from local (format 1)
ccxgw
CALL ccladr1
; HL = word from (HL)
ccgw
LD A,(HL)
INC HL
LD H,(HL)
LD L,A
RET
; char local = HL (format 2)
ccxpb2
CALL ccladr2sv
JR ccxpb3
; char local = HL (format 1)
ccxpb
CALL ccladr1sv
ccxpb3
LD DE,(cctmpw)
LD (HL),E
EX DE,HL
RET
; int/ptr local = HL (format 2)
ccxpw2
CALL ccladr2sv
JR ccxpw3
; int/ptr local = HL (format 1)
ccxpw
CALL ccladr1sv
ccxpw3
LD DE,(cctmpw)
LD (HL),E
INC HL
LD (HL),D
EX DE,HL
RET
; Copy 1 word from HL to (DE)
ccpw
LD A,L
LD (DE),A
INC DE
LD A,H
LD (DE),A
RET
; Calc. local adress
cctmpw DEFW 0
ccladr2sv
LD (cctmpw),HL
ccladr2
POP DE
POP HL
LD C,(HL)
INC HL
LD B,(HL)
INC HL
PUSH HL
PUSH DE
LD HL,4
ADD HL,BC
ADD HL,SP
RET
ccladr1sv
LD (cctmpw),HL
ccladr1
POP DE
POP HL
LD B,0
LD C,(HL)
INC HL
PUSH HL
PUSH DE
LD HL,4
ADD HL,BC
ADD HL,SP
RET
; OR HL = HL | DE
ccor
LD A,L
OR E
LD L,A
LD A,H
OR D
LD H,A
RET
; XOR HL = HL ^ DE
ccxor
LD A,L
XOR E
LD L,A
LD A,H
XOR D
LD H,A
RET
; AND HL = HL & DE
ccand
LD A,L
AND E
LD L,A
LD A,H
AND D
LD H,A
RET
; LOGIC OR HL = DE || HL
cclgor
LD A,H
OR L
OR D
OR E
LD L,A
RET
;LD A,H
;OR L
;RET NZ
;LD A,D
;OR E
;RET Z
;INC L
;RET
; LOGIC AND HL = DE && HL
cclgand
LD A,H
OR L
RET Z
LD A,D
OR E
RET NZ
JP ccfalse
; HL = HL == DE
cceq
OR A
SBC HL,DE
; LOGIC NOT HL = !HL
cclgnot
LD A,H
OR L
JP NZ,ccfalse
INC L
RET
; HL = HL != DE
ccne
OR A
SBC HL,DE
RET
; HL = DE > HL (SIGNED)
ccgt
EX DE,HL
; HL = DE < HL (SIGNED)
cclt
CALL cccmp
RET C
DEC L
RET
; HL = DE <= HL (SIGNED)
ccle
CALL cccmp
RET Z
RET C
DEC L
RET
; HL = DE >= HL (SIGNED)
ccge
CALL cccmp
RET NC
DEC L
RET
; Compare DE with HL, and return: (SIGNED)
;
; CARRY if DE < HL
; ZERO if DE == HL
; HL = 1
cccmp
LD A,E
SUB L
LD E,A
LD A,D
SBC H
LD HL,1
JP M,cccmp1
OR E
RET
cccmp1
OR E
SCF
RET
; HL = DE <= HL (UNSIGNED)
ccule
CALL ccucmp
RET Z
RET C
DEC L
RET
; HL = DE >= HL (UNSIGNED)
ccuge
CALL ccucmp
RET NC
DEC L
RET
; HL = DE > HL (UNSIGNED)
ccugt
EX DE,HL
; HL = DE < HL (UNSIGNED)
ccult
CALL ccucmp
RET C
DEC L
RET
; Compare DE with HL, and return: (UNSIGNED)
;
; CARRY if DE < HL
; ZERO if DE == HL
; HL = 1
ccucmp
LD A,D
CP H
JR NZ,ccucmp1
LD A,E
CP L
ccucmp1
LD HL,1
RET
; HL = DE >> HL (UNSIGNED)
ccuasr
EX DE,HL
LD A,E
ccuasr1
OR A
RET Z
DEC A
SRL H
RR L
JR ccuasr1
; HL = DE >> HL (ARITMETIC)
ccasr
EX DE,HL
LD A,E
ccasr1
OR A
RET Z
DEC A
SRA H
RR L
JR ccasr1
; HL = DE << HL (UNSIGNED)
ccuasl
; HL = DE << HL (ARITMETIC)
ccasl
EX DE,HL
LD A,E
ccasl1
OR A
RET Z
DEC A
ADD HL,HL
JR ccasl1
; HL = DE - HL
ccsub
EX DE,HL
OR A
SBC HL,DE
RET
; HL = ~HL (1 COMPLEMENT)
cccom
LD A,H
CPL
LD H,A
LD A,L
CPL
LD L,A
RET
; HL = -HL (2 COMPLEMENT)
ccneg
LD A,H
CPL
LD H,A
LD A,L
CPL
LD L,A
INC HL
RET
#endasm
#ifndef CC_NO_MUL
#asm
; HL = DE * HL (UNSIGNED)
ccumul
; HL = DE * HL (SIGNED)
ccmul
LD A,H
LD C,L
LD HL,0
LD B,16
ccmul0
ADD HL,HL
SLA C
RL A
JR NC,ccmul1
ADD HL,DE
ccmul1
DJNZ ccmul0
RET
#endasm
#endif
#ifndef CC_NO_DIV
#asm
; HL = DE % HL (SIGNED)
ccmod
CALL ccdiv
EX DE,HL
RET
; HL = DE / HL (SIGNED)
; DE = DE % HL (SIGNED)
ccdiv
LD B,H
LD C,L
LD A,D
XOR B
PUSH AF
LD A,D
OR A
CALL M,ccdivdeneg
LD A,B
OR A
JP P,ccdiv0
LD A,B
CPL
LD B,A
LD A,C
CPL
LD C,A
INC BC
ccdiv0
EX DE,HL
LD DE,0
LD A,16
ccdiv1
PUSH AF
ADD HL,HL
RL E
RL D
LD A,D
OR E
JR Z,ccdiv2
LD A,E
SUB C
LD A,D
SBC B
JP M,ccdiv2
LD A,L
OR 1
LD L,A
LD A,E
SUB C
LD E,A
LD A,D
SBC B
LD D,A
ccdiv2
POP AF
DEC A
JR NZ,ccdiv1
POP AF
RET P
CALL ccneg
ccdivdeneg
LD A,D
CPL
LD D,A
LD A,E
CPL
LD E,A
INC DE
RET
; HL = DE % HL (UNSIGNED)
ccumod
CALL ccudiv
EX DE,HL
RET
; HL = DE / HL (UNSIGNED)
; DE = DE % HL (UNSIGNED)
ccudiv
LD (ccudiv_tmp),HL
LD HL,ccudiv_cnt
LD (HL),17
LD BC,0
PUSH BC
XOR A
ccudiv0
RL E
RL D
DEC (HL)
POP HL
JR Z,ccudiv2
LD A,0
ADC 0
ADD HL,HL
LD B,H
ADD L
LD HL,(ccudiv_tmp)
SUB L
LD C,A
LD A,B
SBC H
LD B,A
PUSH BC
JR NC,ccudiv1
ADD HL,BC
EX (SP),HL
ccudiv1
LD HL,ccudiv_cnt
CCF
JR ccudiv0
ccudiv2
EX DE,HL
RET
ccudiv_tmp
DEFW 0
ccudiv_cnt
DEFB 0
#endasm
#endif
#ifndef CC_NO_SWITCH
#asm
; Switch, on entry:
;
; DE = Table address
; HL = Where to go if value was not found in table
; B = Number of entries in table
ccswtch
EX (SP),HL
EX DE,HL
ccswch1
LD A,E
CP (HL)
INC HL
JR NZ,ccswch2
LD A,D
CP (HL)
JR NZ,ccswch2
INC HL
LD E,(HL)
INC HL
LD D,(HL)
EX DE,HL
POP BC
JP (HL)
ccswch2
INC HL
INC HL
INC HL
DJNZ ccswch1
EX (SP),HL
POP BC
JP (HL)
#endasm
#endif
#asm
; HL = TRUE
cctrue
LD L,1
RET
; HL = FALSE
ccfalse
LD HL,0
RET
#endasm